| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: var.c,v 1.265 2020/07/19 16:08:24 rillig Exp $ */ | | 1 | /* $NetBSD: var.c,v 1.266 2020/07/19 16:22:44 rillig Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 1988, 1989, 1990, 1993 | | 4 | * Copyright (c) 1988, 1989, 1990, 1993 |
5 | * The Regents of the University of California. All rights reserved. | | 5 | * The Regents of the University of California. All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to Berkeley by | | 7 | * This code is derived from software contributed to Berkeley by |
8 | * Adam de Boor. | | 8 | * Adam de Boor. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
| @@ -59,34 +59,34 @@ | | | @@ -59,34 +59,34 @@ |
59 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | | 59 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
60 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | 60 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
61 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | | 61 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
62 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 62 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
63 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 63 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
64 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 64 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
65 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 65 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
66 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 66 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
67 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 67 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
68 | * SUCH DAMAGE. | | 68 | * SUCH DAMAGE. |
69 | */ | | 69 | */ |
70 | | | 70 | |
71 | #ifndef MAKE_NATIVE | | 71 | #ifndef MAKE_NATIVE |
72 | static char rcsid[] = "$NetBSD: var.c,v 1.265 2020/07/19 16:08:24 rillig Exp $"; | | 72 | static char rcsid[] = "$NetBSD: var.c,v 1.266 2020/07/19 16:22:44 rillig Exp $"; |
73 | #else | | 73 | #else |
74 | #include <sys/cdefs.h> | | 74 | #include <sys/cdefs.h> |
75 | #ifndef lint | | 75 | #ifndef lint |
76 | #if 0 | | 76 | #if 0 |
77 | static char sccsid[] = "@(#)var.c 8.3 (Berkeley) 3/19/94"; | | 77 | static char sccsid[] = "@(#)var.c 8.3 (Berkeley) 3/19/94"; |
78 | #else | | 78 | #else |
79 | __RCSID("$NetBSD: var.c,v 1.265 2020/07/19 16:08:24 rillig Exp $"); | | 79 | __RCSID("$NetBSD: var.c,v 1.266 2020/07/19 16:22:44 rillig Exp $"); |
80 | #endif | | 80 | #endif |
81 | #endif /* not lint */ | | 81 | #endif /* not lint */ |
82 | #endif | | 82 | #endif |
83 | | | 83 | |
84 | /*- | | 84 | /*- |
85 | * var.c -- | | 85 | * var.c -- |
86 | * Variable-handling functions | | 86 | * Variable-handling functions |
87 | * | | 87 | * |
88 | * Interface: | | 88 | * Interface: |
89 | * Var_Set Set the value of a variable in the given | | 89 | * Var_Set Set the value of a variable in the given |
90 | * context. The variable is created if it doesn't | | 90 | * context. The variable is created if it doesn't |
91 | * yet exist. The value and variable name need not | | 91 | * yet exist. The value and variable name need not |
92 | * be preserved. | | 92 | * be preserved. |
| @@ -2029,29 +2029,29 @@ VarRange(const char *str, int ac) | | | @@ -2029,29 +2029,29 @@ VarRange(const char *str, int ac) |
2029 | * | | 2029 | * |
2030 | * The text part is parsed until the next delimiter. To escape the delimiter, | | 2030 | * The text part is parsed until the next delimiter. To escape the delimiter, |
2031 | * a backslash or a dollar, put a backslash before it. | | 2031 | * a backslash or a dollar, put a backslash before it. |
2032 | * | | 2032 | * |
2033 | * Return the expanded string or NULL if the delimiter was missing. | | 2033 | * Return the expanded string or NULL if the delimiter was missing. |
2034 | * If pattern is specified, handle escaped ampersands and replace unescaped | | 2034 | * If pattern is specified, handle escaped ampersands and replace unescaped |
2035 | * ampersands with the lhs of the pattern (for the :S and :C modifiers). | | 2035 | * ampersands with the lhs of the pattern (for the :S and :C modifiers). |
2036 | * | | 2036 | * |
2037 | * If length is specified, return the string length of the buffer. | | 2037 | * If length is specified, return the string length of the buffer. |
2038 | * If mpflags is specified and the last character of the pattern is a $, | | 2038 | * If mpflags is specified and the last character of the pattern is a $, |
2039 | * set the VARP_MATCH_END bit of mpflags. | | 2039 | * set the VARP_MATCH_END bit of mpflags. |
2040 | */ | | 2040 | */ |
2041 | static char * | | 2041 | static char * |
2042 | ParseModifierPart(GNode *ctxt, Var_Parse_State *vpstate MAKE_ATTR_UNUSED, | | 2042 | ParseModifierPart(GNode *ctxt, const char **tstr, int delim, |
2043 | VarEvalFlags eflags, const char **tstr, int delim, | | 2043 | VarEvalFlags eflags, VarPatternFlags *mpflags, |
2044 | VarPatternFlags *mpflags, int *length, VarPattern *pattern) | | 2044 | int *length, VarPattern *pattern) |
2045 | { | | 2045 | { |
2046 | const char *cp; | | 2046 | const char *cp; |
2047 | char *rstr; | | 2047 | char *rstr; |
2048 | Buffer buf; | | 2048 | Buffer buf; |
2049 | int junk; | | 2049 | int junk; |
2050 | VarEvalFlags errnum = eflags & VARE_UNDEFERR; | | 2050 | VarEvalFlags errnum = eflags & VARE_UNDEFERR; |
2051 | | | 2051 | |
2052 | Buf_Init(&buf, 0); | | 2052 | Buf_Init(&buf, 0); |
2053 | if (length == NULL) | | 2053 | if (length == NULL) |
2054 | length = &junk; | | 2054 | length = &junk; |
2055 | | | 2055 | |
2056 | /* | | 2056 | /* |
2057 | * Skim through until the matching delimiter is found; | | 2057 | * Skim through until the matching delimiter is found; |
| @@ -2308,33 +2308,33 @@ typedef struct { | | | @@ -2308,33 +2308,33 @@ typedef struct { |
2308 | (strncmp(s, want, n) == 0 && \ | | 2308 | (strncmp(s, want, n) == 0 && \ |
2309 | (s[n] == st->endc || s[n] == ':' || s[n] == '=')) | | 2309 | (s[n] == st->endc || s[n] == ':' || s[n] == '=')) |
2310 | #define CHARMOD_MATCH(c) (c == st->endc || c == ':') | | 2310 | #define CHARMOD_MATCH(c) (c == st->endc || c == ':') |
2311 | | | 2311 | |
2312 | /* :@var@...${var}...@ */ | | 2312 | /* :@var@...${var}...@ */ |
2313 | static Boolean | | 2313 | static Boolean |
2314 | ApplyModifier_At(ApplyModifiersState *st) { | | 2314 | ApplyModifier_At(ApplyModifiersState *st) { |
2315 | VarLoop loop; | | 2315 | VarLoop loop; |
2316 | VarPatternFlags pflags = VAR_NOSUBST; /* FIXME: mismatch between pflags and VAR_NOSUBST */ | | 2316 | VarPatternFlags pflags = VAR_NOSUBST; /* FIXME: mismatch between pflags and VAR_NOSUBST */ |
2317 | | | 2317 | |
2318 | st->cp = ++st->tstr; | | 2318 | st->cp = ++st->tstr; |
2319 | st->delim = '@'; | | 2319 | st->delim = '@'; |
2320 | loop.tvar = ParseModifierPart( | | 2320 | loop.tvar = ParseModifierPart( |
2321 | st->ctxt, &st->parsestate, st->flags, &st->cp, st->delim, | | 2321 | st->ctxt, &st->cp, st->delim, st->flags, |
2322 | &pflags, &loop.tvarLen, NULL); | | 2322 | &pflags, &loop.tvarLen, NULL); |
2323 | if (loop.tvar == NULL) | | 2323 | if (loop.tvar == NULL) |
2324 | return FALSE; | | 2324 | return FALSE; |
2325 | | | 2325 | |
2326 | loop.str = ParseModifierPart( | | 2326 | loop.str = ParseModifierPart( |
2327 | st->ctxt, &st->parsestate, st->flags, &st->cp, st->delim, | | 2327 | st->ctxt, &st->cp, st->delim, st->flags, |
2328 | &pflags, &loop.strLen, NULL); | | 2328 | &pflags, &loop.strLen, NULL); |
2329 | if (loop.str == NULL) | | 2329 | if (loop.str == NULL) |
2330 | return FALSE; | | 2330 | return FALSE; |
2331 | | | 2331 | |
2332 | st->termc = *st->cp; | | 2332 | st->termc = *st->cp; |
2333 | st->delim = '\0'; | | 2333 | st->delim = '\0'; |
2334 | | | 2334 | |
2335 | loop.flags = st->flags & (VARE_UNDEFERR | VARE_WANTRES); | | 2335 | loop.flags = st->flags & (VARE_UNDEFERR | VARE_WANTRES); |
2336 | loop.ctxt = st->ctxt; | | 2336 | loop.ctxt = st->ctxt; |
2337 | st->newStr = VarModify( | | 2337 | st->newStr = VarModify( |
2338 | st->ctxt, &st->parsestate, st->nstr, VarLoopExpand, &loop); | | 2338 | st->ctxt, &st->parsestate, st->nstr, VarLoopExpand, &loop); |
2339 | Var_Delete(loop.tvar, st->ctxt); | | 2339 | Var_Delete(loop.tvar, st->ctxt); |
2340 | free(loop.tvar); | | 2340 | free(loop.tvar); |
| @@ -2490,27 +2490,27 @@ ApplyModifier_Path(ApplyModifiersState * | | | @@ -2490,27 +2490,27 @@ ApplyModifier_Path(ApplyModifiersState * |
2490 | /* :!cmd! */ | | 2490 | /* :!cmd! */ |
2491 | static Boolean | | 2491 | static Boolean |
2492 | ApplyModifier_Exclam(ApplyModifiersState *st) | | 2492 | ApplyModifier_Exclam(ApplyModifiersState *st) |
2493 | { | | 2493 | { |
2494 | const char *emsg; | | 2494 | const char *emsg; |
2495 | VarPattern pattern; | | 2495 | VarPattern pattern; |
2496 | | | 2496 | |
2497 | pattern.pflags = 0; | | 2497 | pattern.pflags = 0; |
2498 | | | 2498 | |
2499 | st->delim = '!'; | | 2499 | st->delim = '!'; |
2500 | emsg = NULL; | | 2500 | emsg = NULL; |
2501 | st->cp = ++st->tstr; | | 2501 | st->cp = ++st->tstr; |
2502 | pattern.rhs = ParseModifierPart( | | 2502 | pattern.rhs = ParseModifierPart( |
2503 | st->ctxt, &st->parsestate, st->flags, &st->cp, st->delim, | | 2503 | st->ctxt, &st->cp, st->delim, st->flags, |
2504 | NULL, &pattern.rightLen, NULL); | | 2504 | NULL, &pattern.rightLen, NULL); |
2505 | if (pattern.rhs == NULL) | | 2505 | if (pattern.rhs == NULL) |
2506 | return FALSE; | | 2506 | return FALSE; |
2507 | if (st->flags & VARE_WANTRES) | | 2507 | if (st->flags & VARE_WANTRES) |
2508 | st->newStr = Cmd_Exec(pattern.rhs, &emsg); | | 2508 | st->newStr = Cmd_Exec(pattern.rhs, &emsg); |
2509 | else | | 2509 | else |
2510 | st->newStr = varNoError; | | 2510 | st->newStr = varNoError; |
2511 | free(UNCONST(pattern.rhs)); | | 2511 | free(UNCONST(pattern.rhs)); |
2512 | if (emsg) | | 2512 | if (emsg) |
2513 | Error(emsg, st->nstr); | | 2513 | Error(emsg, st->nstr); |
2514 | st->termc = *st->cp; | | 2514 | st->termc = *st->cp; |
2515 | st->delim = '\0'; | | 2515 | st->delim = '\0'; |
2516 | if (st->v->flags & VAR_JUNK) | | 2516 | if (st->v->flags & VAR_JUNK) |
| @@ -2642,33 +2642,33 @@ ApplyModifier_Subst(ApplyModifiersState | | | @@ -2642,33 +2642,33 @@ ApplyModifier_Subst(ApplyModifiersState |
2642 | st->tstr += 2; | | 2642 | st->tstr += 2; |
2643 | | | 2643 | |
2644 | /* | | 2644 | /* |
2645 | * If pattern begins with '^', it is anchored to the | | 2645 | * If pattern begins with '^', it is anchored to the |
2646 | * start of the word -- skip over it and flag pattern. | | 2646 | * start of the word -- skip over it and flag pattern. |
2647 | */ | | 2647 | */ |
2648 | if (*st->tstr == '^') { | | 2648 | if (*st->tstr == '^') { |
2649 | pattern.pflags |= VARP_MATCH_START; | | 2649 | pattern.pflags |= VARP_MATCH_START; |
2650 | st->tstr++; | | 2650 | st->tstr++; |
2651 | } | | 2651 | } |
2652 | | | 2652 | |
2653 | st->cp = st->tstr; | | 2653 | st->cp = st->tstr; |
2654 | pattern.lhs = ParseModifierPart( | | 2654 | pattern.lhs = ParseModifierPart( |
2655 | st->ctxt, &st->parsestate, st->flags, &st->cp, st->delim, | | 2655 | st->ctxt, &st->cp, st->delim, st->flags, |
2656 | &pattern.pflags, &pattern.leftLen, NULL); | | 2656 | &pattern.pflags, &pattern.leftLen, NULL); |
2657 | if (pattern.lhs == NULL) | | 2657 | if (pattern.lhs == NULL) |
2658 | return FALSE; | | 2658 | return FALSE; |
2659 | | | 2659 | |
2660 | pattern.rhs = ParseModifierPart( | | 2660 | pattern.rhs = ParseModifierPart( |
2661 | st->ctxt, &st->parsestate, st->flags, &st->cp, st->delim, | | 2661 | st->ctxt, &st->cp, st->delim, st->flags, |
2662 | NULL, &pattern.rightLen, &pattern); | | 2662 | NULL, &pattern.rightLen, &pattern); |
2663 | if (pattern.rhs == NULL) | | 2663 | if (pattern.rhs == NULL) |
2664 | return FALSE; | | 2664 | return FALSE; |
2665 | | | 2665 | |
2666 | /* | | 2666 | /* |
2667 | * Check for global substitution. If 'g' after the final | | 2667 | * Check for global substitution. If 'g' after the final |
2668 | * delimiter, substitution is global and is marked that | | 2668 | * delimiter, substitution is global and is marked that |
2669 | * way. | | 2669 | * way. |
2670 | */ | | 2670 | */ |
2671 | for (;; st->cp++) { | | 2671 | for (;; st->cp++) { |
2672 | switch (*st->cp) { | | 2672 | switch (*st->cp) { |
2673 | case 'g': | | 2673 | case 'g': |
2674 | pattern.pflags |= VARP_SUB_GLOBAL; | | 2674 | pattern.pflags |= VARP_SUB_GLOBAL; |
| @@ -2701,35 +2701,33 @@ ApplyModifier_Regex(ApplyModifiersState | | | @@ -2701,35 +2701,33 @@ ApplyModifier_Regex(ApplyModifiersState |
2701 | { | | 2701 | { |
2702 | VarREPattern pattern; | | 2702 | VarREPattern pattern; |
2703 | char *re; | | 2703 | char *re; |
2704 | int error; | | 2704 | int error; |
2705 | Var_Parse_State tmpparsestate; | | 2705 | Var_Parse_State tmpparsestate; |
2706 | | | 2706 | |
2707 | pattern.pflags = 0; | | 2707 | pattern.pflags = 0; |
2708 | tmpparsestate = st->parsestate; | | 2708 | tmpparsestate = st->parsestate; |
2709 | st->delim = st->tstr[1]; | | 2709 | st->delim = st->tstr[1]; |
2710 | st->tstr += 2; | | 2710 | st->tstr += 2; |
2711 | | | 2711 | |
2712 | st->cp = st->tstr; | | 2712 | st->cp = st->tstr; |
2713 | | | 2713 | |
2714 | re = ParseModifierPart( | | 2714 | re = ParseModifierPart(st->ctxt, &st->cp, st->delim, st->flags, |
2715 | st->ctxt, &st->parsestate, st->flags, &st->cp, st->delim, | | 2715 | NULL, NULL, NULL); |
2716 | NULL, NULL, NULL); | | | |
2717 | if (re == NULL) | | 2716 | if (re == NULL) |
2718 | return FALSE; | | 2717 | return FALSE; |
2719 | | | 2718 | |
2720 | pattern.replace = ParseModifierPart( | | 2719 | pattern.replace = ParseModifierPart(st->ctxt, &st->cp, st->delim, |
2721 | st->ctxt, &st->parsestate, st->flags, &st->cp, st->delim, | | 2720 | st->flags, NULL, NULL, NULL); |
2722 | NULL, NULL, NULL); | | | |
2723 | if (pattern.replace == NULL) { | | 2721 | if (pattern.replace == NULL) { |
2724 | free(re); | | 2722 | free(re); |
2725 | return FALSE; | | 2723 | return FALSE; |
2726 | } | | 2724 | } |
2727 | | | 2725 | |
2728 | for (;; st->cp++) { | | 2726 | for (;; st->cp++) { |
2729 | switch (*st->cp) { | | 2727 | switch (*st->cp) { |
2730 | case 'g': | | 2728 | case 'g': |
2731 | pattern.pflags |= VARP_SUB_GLOBAL; | | 2729 | pattern.pflags |= VARP_SUB_GLOBAL; |
2732 | continue; | | 2730 | continue; |
2733 | case '1': | | 2731 | case '1': |
2734 | pattern.pflags |= VARP_SUB_ONE; | | 2732 | pattern.pflags |= VARP_SUB_ONE; |
2735 | continue; | | 2733 | continue; |
| @@ -2872,40 +2870,30 @@ ApplyModifier_To(ApplyModifiersState *st | | | @@ -2872,40 +2870,30 @@ ApplyModifier_To(ApplyModifiersState *st |
2872 | return FALSE; | | 2870 | return FALSE; |
2873 | } | | 2871 | } |
2874 | } else { | | 2872 | } else { |
2875 | /* Found ":t<endc>" or ":t:". */ | | 2873 | /* Found ":t<endc>" or ":t:". */ |
2876 | return FALSE; | | 2874 | return FALSE; |
2877 | } | | 2875 | } |
2878 | return TRUE; | | 2876 | return TRUE; |
2879 | } | | 2877 | } |
2880 | | | 2878 | |
2881 | /* :[#], :[1], etc. */ | | 2879 | /* :[#], :[1], etc. */ |
2882 | static int | | 2880 | static int |
2883 | ApplyModifier_Words(ApplyModifiersState *st) | | 2881 | ApplyModifier_Words(ApplyModifiersState *st) |
2884 | { | | 2882 | { |
2885 | /* | | | |
2886 | * Look for the closing ']', recursively | | | |
2887 | * expanding any embedded variables. | | | |
2888 | * | | | |
2889 | * estr is a pointer to the expanded result, | | | |
2890 | * which we must free(). | | | |
2891 | */ | | | |
2892 | char *estr; | | | |
2893 | | | | |
2894 | st->cp = st->tstr + 1; /* point to char after '[' */ | | 2883 | st->cp = st->tstr + 1; /* point to char after '[' */ |
2895 | st->delim = ']'; /* look for closing ']' */ | | 2884 | st->delim = ']'; /* look for closing ']' */ |
2896 | estr = ParseModifierPart( | | 2885 | char *estr = ParseModifierPart(st->ctxt, &st->cp, st->delim, st->flags, |
2897 | st->ctxt, &st->parsestate, st->flags, &st->cp, st->delim, | | 2886 | NULL, NULL, NULL); |
2898 | NULL, NULL, NULL); | | | |
2899 | if (estr == NULL) | | 2887 | if (estr == NULL) |
2900 | return 'c'; /* report missing ']' */ | | 2888 | return 'c'; /* report missing ']' */ |
2901 | /* now st->cp points just after the closing ']' */ | | 2889 | /* now st->cp points just after the closing ']' */ |
2902 | st->delim = '\0'; | | 2890 | st->delim = '\0'; |
2903 | if (st->cp[0] != ':' && st->cp[0] != st->endc) { | | 2891 | if (st->cp[0] != ':' && st->cp[0] != st->endc) { |
2904 | /* Found junk after ']' */ | | 2892 | /* Found junk after ']' */ |
2905 | free(estr); | | 2893 | free(estr); |
2906 | return 'b'; | | 2894 | return 'b'; |
2907 | } | | 2895 | } |
2908 | if (estr[0] == '\0') { | | 2896 | if (estr[0] == '\0') { |
2909 | /* Found empty square brackets in ":[]". */ | | 2897 | /* Found empty square brackets in ":[]". */ |
2910 | free(estr); | | 2898 | free(estr); |
2911 | return 'b'; | | 2899 | return 'b'; |
| @@ -3047,36 +3035,34 @@ ApplyModifier_IfElse(ApplyModifiersState | | | @@ -3047,36 +3035,34 @@ ApplyModifier_IfElse(ApplyModifiersState |
3047 | if (st->flags & VARE_WANTRES) { | | 3035 | if (st->flags & VARE_WANTRES) { |
3048 | cond_rc = Cond_EvalExpression(NULL, st->v->name, &value, 0, FALSE); | | 3036 | cond_rc = Cond_EvalExpression(NULL, st->v->name, &value, 0, FALSE); |
3049 | then_flags = cond_rc != COND_INVALID && value ? 0 : VAR_NOSUBST; | | 3037 | then_flags = cond_rc != COND_INVALID && value ? 0 : VAR_NOSUBST; |
3050 | else_flags = cond_rc != COND_INVALID && !value ? 0 : VAR_NOSUBST; | | 3038 | else_flags = cond_rc != COND_INVALID && !value ? 0 : VAR_NOSUBST; |
3051 | } else { | | 3039 | } else { |
3052 | /* we are just consuming and discarding */ | | 3040 | /* we are just consuming and discarding */ |
3053 | cond_rc = value = 0; | | 3041 | cond_rc = value = 0; |
3054 | then_flags = else_flags = VAR_NOSUBST; | | 3042 | then_flags = else_flags = VAR_NOSUBST; |
3055 | } | | 3043 | } |
3056 | | | 3044 | |
3057 | st->cp = ++st->tstr; | | 3045 | st->cp = ++st->tstr; |
3058 | st->delim = ':'; | | 3046 | st->delim = ':'; |
3059 | char *then_expr = ParseModifierPart( | | 3047 | char *then_expr = ParseModifierPart( |
3060 | st->ctxt, &st->parsestate, st->flags, &st->cp, st->delim, | | 3048 | st->ctxt, &st->cp, st->delim, st->flags, &then_flags, NULL, NULL); |
3061 | &then_flags, NULL, NULL); | | | |
3062 | if (then_expr == NULL) | | 3049 | if (then_expr == NULL) |
3063 | return FALSE; | | 3050 | return FALSE; |
3064 | | | 3051 | |
3065 | /* BROPEN or PROPEN */ | | 3052 | /* BROPEN or PROPEN */ |
3066 | st->delim = st->endc; | | 3053 | st->delim = st->endc; |
3067 | char *else_expr = ParseModifierPart( | | 3054 | char *else_expr = ParseModifierPart( |
3068 | st->ctxt, &st->parsestate, st->flags, &st->cp, st->delim, | | 3055 | st->ctxt, &st->cp, st->delim, st->flags, &else_flags, NULL, NULL); |
3069 | &else_flags, NULL, NULL); | | | |
3070 | if (else_expr == NULL) | | 3056 | if (else_expr == NULL) |
3071 | return FALSE; | | 3057 | return FALSE; |
3072 | | | 3058 | |
3073 | st->termc = *--st->cp; | | 3059 | st->termc = *--st->cp; |
3074 | st->delim = '\0'; | | 3060 | st->delim = '\0'; |
3075 | if (cond_rc == COND_INVALID) { | | 3061 | if (cond_rc == COND_INVALID) { |
3076 | Error("Bad conditional expression `%s' in %s?%s:%s", | | 3062 | Error("Bad conditional expression `%s' in %s?%s:%s", |
3077 | st->v->name, st->v->name, then_expr, else_expr); | | 3063 | st->v->name, st->v->name, then_expr, else_expr); |
3078 | return FALSE; | | 3064 | return FALSE; |
3079 | } | | 3065 | } |
3080 | | | 3066 | |
3081 | if (value) { | | 3067 | if (value) { |
3082 | st->newStr = then_expr; | | 3068 | st->newStr = then_expr; |
| @@ -3131,27 +3117,27 @@ ApplyModifier_Assign(ApplyModifiersState | | | @@ -3131,27 +3117,27 @@ ApplyModifier_Assign(ApplyModifiersState |
3131 | case '?': | | 3117 | case '?': |
3132 | case '!': | | 3118 | case '!': |
3133 | st->cp = &st->tstr[2]; | | 3119 | st->cp = &st->tstr[2]; |
3134 | break; | | 3120 | break; |
3135 | default: | | 3121 | default: |
3136 | st->cp = ++st->tstr; | | 3122 | st->cp = ++st->tstr; |
3137 | break; | | 3123 | break; |
3138 | } | | 3124 | } |
3139 | st->delim = st->startc == PROPEN ? PRCLOSE : BRCLOSE; | | 3125 | st->delim = st->startc == PROPEN ? PRCLOSE : BRCLOSE; |
3140 | pattern.pflags = 0; | | 3126 | pattern.pflags = 0; |
3141 | | | 3127 | |
3142 | pflags = (st->flags & VARE_WANTRES) ? 0 : VAR_NOSUBST; | | 3128 | pflags = (st->flags & VARE_WANTRES) ? 0 : VAR_NOSUBST; |
3143 | pattern.rhs = ParseModifierPart( | | 3129 | pattern.rhs = ParseModifierPart( |
3144 | st->ctxt, &st->parsestate, st->flags, &st->cp, st->delim, | | 3130 | st->ctxt, &st->cp, st->delim, st->flags, |
3145 | &pflags, &pattern.rightLen, NULL); | | 3131 | &pflags, &pattern.rightLen, NULL); |
3146 | if (st->v->flags & VAR_JUNK) { | | 3132 | if (st->v->flags & VAR_JUNK) { |
3147 | /* restore original name */ | | 3133 | /* restore original name */ |
3148 | free(st->v->name); | | 3134 | free(st->v->name); |
3149 | st->v->name = sv_name; | | 3135 | st->v->name = sv_name; |
3150 | } | | 3136 | } |
3151 | if (pattern.rhs == NULL) | | 3137 | if (pattern.rhs == NULL) |
3152 | return 'c'; | | 3138 | return 'c'; |
3153 | | | 3139 | |
3154 | st->termc = *--st->cp; | | 3140 | st->termc = *--st->cp; |
3155 | st->delim = '\0'; | | 3141 | st->delim = '\0'; |
3156 | | | 3142 | |
3157 | if (st->flags & VARE_WANTRES) { | | 3143 | if (st->flags & VARE_WANTRES) { |
| @@ -3242,34 +3228,34 @@ ApplyModifier_SysV(ApplyModifiersState * | | | @@ -3242,34 +3228,34 @@ ApplyModifier_SysV(ApplyModifiersState * |
3242 | nest++; | | 3228 | nest++; |
3243 | if (nest > 0) | | 3229 | if (nest > 0) |
3244 | st->cp++; | | 3230 | st->cp++; |
3245 | } | | 3231 | } |
3246 | if (*st->cp != st->endc || !eqFound) | | 3232 | if (*st->cp != st->endc || !eqFound) |
3247 | return 0; | | 3233 | return 0; |
3248 | | | 3234 | |
3249 | st->delim = '='; | | 3235 | st->delim = '='; |
3250 | st->cp = st->tstr; | | 3236 | st->cp = st->tstr; |
3251 | /* FIXME: There's no point in having a single $ at the end of a | | 3237 | /* FIXME: There's no point in having a single $ at the end of a |
3252 | * SysV substitution since that will not be interpreted as an | | 3238 | * SysV substitution since that will not be interpreted as an |
3253 | * anchor anyway. */ | | 3239 | * anchor anyway. */ |
3254 | pattern.lhs = ParseModifierPart( | | 3240 | pattern.lhs = ParseModifierPart( |
3255 | st->ctxt, &st->parsestate, st->flags, &st->cp, st->delim, | | 3241 | st->ctxt, &st->cp, st->delim, st->flags, |
3256 | &pattern.pflags, &pattern.leftLen, NULL); | | 3242 | &pattern.pflags, &pattern.leftLen, NULL); |
3257 | if (pattern.lhs == NULL) | | 3243 | if (pattern.lhs == NULL) |
3258 | return 'c'; | | 3244 | return 'c'; |
3259 | | | 3245 | |
3260 | st->delim = st->endc; | | 3246 | st->delim = st->endc; |
3261 | pattern.rhs = ParseModifierPart( | | 3247 | pattern.rhs = ParseModifierPart( |
3262 | st->ctxt, &st->parsestate, st->flags, &st->cp, st->delim, | | 3248 | st->ctxt, &st->cp, st->delim, st->flags, |
3263 | NULL, &pattern.rightLen, &pattern); | | 3249 | NULL, &pattern.rightLen, &pattern); |
3264 | if (pattern.rhs == NULL) | | 3250 | if (pattern.rhs == NULL) |
3265 | return 'c'; | | 3251 | return 'c'; |
3266 | | | 3252 | |
3267 | /* | | 3253 | /* |
3268 | * SYSV modifications happen through the whole | | 3254 | * SYSV modifications happen through the whole |
3269 | * string. Note the pattern is anchored at the end. | | 3255 | * string. Note the pattern is anchored at the end. |
3270 | */ | | 3256 | */ |
3271 | st->termc = *--st->cp; | | 3257 | st->termc = *--st->cp; |
3272 | st->delim = '\0'; | | 3258 | st->delim = '\0'; |
3273 | if (pattern.leftLen == 0 && *st->nstr == '\0') { | | 3259 | if (pattern.leftLen == 0 && *st->nstr == '\0') { |
3274 | st->newStr = st->nstr; /* special case */ | | 3260 | st->newStr = st->nstr; /* special case */ |
3275 | } else { | | 3261 | } else { |