| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: var.c,v 1.323 2020/07/26 18:11:12 rillig Exp $ */ | | 1 | /* $NetBSD: var.c,v 1.324 2020/07/26 18:47:02 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.323 2020/07/26 18:11:12 rillig Exp $"; | | 72 | static char rcsid[] = "$NetBSD: var.c,v 1.324 2020/07/26 18:47:02 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.323 2020/07/26 18:11:12 rillig Exp $"); | | 79 | __RCSID("$NetBSD: var.c,v 1.324 2020/07/26 18:47:02 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. | | 91 | * yet exist. |
92 | * | | 92 | * |
| @@ -1776,64 +1776,67 @@ VarRange(const char *str, int ac) | | | @@ -1776,64 +1776,67 @@ VarRange(const char *str, int ac) |
1776 | Buf_AddByte(&buf, ' '); | | 1776 | Buf_AddByte(&buf, ' '); |
1777 | Buf_AddInt(&buf, 1 + i); | | 1777 | Buf_AddInt(&buf, 1 + i); |
1778 | } | | 1778 | } |
1779 | | | 1779 | |
1780 | free(as); | | 1780 | free(as); |
1781 | free(av); | | 1781 | free(av); |
1782 | | | 1782 | |
1783 | return Buf_Destroy(&buf, FALSE); | | 1783 | return Buf_Destroy(&buf, FALSE); |
1784 | } | | 1784 | } |
1785 | | | 1785 | |
1786 | | | 1786 | |
1787 | /*- | | 1787 | /*- |
1788 | * Parse a text part of a modifier such as the "from" and "to" in :S/from/to/ | | 1788 | * Parse a text part of a modifier such as the "from" and "to" in :S/from/to/ |
1789 | * or the :@ modifier. Nested variables in the text are expanded unless | | 1789 | * or the :@ modifier, until the next unescaped delimiter. The delimiter, as |
1790 | * VARE_NOSUBST is set. | | 1790 | * well as the backslash or the dollar, can be escaped with a backslash. |
1791 | * | | 1791 | * |
1792 | * The text part is parsed until the next delimiter. To escape the delimiter, | | 1792 | * Return the parsed (and possibly expanded) string, or NULL if no delimiter |
1793 | * a backslash or a dollar, put a backslash before it. | | 1793 | * was found. |
1794 | * | | 1794 | * |
1795 | * Return the expanded string or NULL if the delimiter was missing. | | 1795 | * Nested variables in the text are expanded unless VARE_NOSUBST is set. |
1796 | * | | 1796 | * |
1797 | * If pattern is specified, handle escaped ampersands and replace unescaped | | 1797 | * If out_length is specified, store the length of the returned string, just |
1798 | * ampersands with the lhs of the pattern (for the :S modifier). | | 1798 | * to save another strlen call. |
1799 | * | | | |
1800 | * If out_length is specified, return the string length of the buffer | | | |
1801 | * (except on parse errors). | | | |
1802 | * | | 1799 | * |
1803 | * If out_pflags is specified and the last character of the pattern is a $, | | 1800 | * If out_pflags is specified and the last character of the pattern is a $, |
1804 | * set the VARP_ANCHOR_END bit of mpflags. | | 1801 | * set the VARP_ANCHOR_END bit of mpflags (for the first part of the :S |
| | | 1802 | * modifier). |
| | | 1803 | * |
| | | 1804 | * If subst is specified, handle escaped ampersands and replace unescaped |
| | | 1805 | * ampersands with the lhs of the pattern (for the second part of the :S |
| | | 1806 | * modifier). |
1805 | */ | | 1807 | */ |
1806 | static char * | | 1808 | static char * |
1807 | ParseModifierPart(GNode *ctxt, const char **tstr, int delim, | | 1809 | ParseModifierPart(const char **tstr, int delim, VarEvalFlags eflags, |
1808 | VarEvalFlags eflags, VarPatternFlags *out_pflags, | | 1810 | GNode *ctxt, size_t *out_length, |
1809 | size_t *out_length, ModifyWord_SubstArgs *subst) | | 1811 | VarPatternFlags *out_pflags, ModifyWord_SubstArgs *subst) |
1810 | { | | 1812 | { |
1811 | const char *cp; | | 1813 | const char *cp; |
1812 | char *rstr; | | 1814 | char *rstr; |
1813 | Buffer buf; | | 1815 | Buffer buf; |
1814 | VarEvalFlags errnum = eflags & VARE_UNDEFERR; | | 1816 | VarEvalFlags errnum = eflags & VARE_UNDEFERR; |
1815 | | | 1817 | |
1816 | Buf_Init(&buf, 0); | | 1818 | Buf_Init(&buf, 0); |
1817 | | | 1819 | |
1818 | /* | | 1820 | /* |
1819 | * Skim through until the matching delimiter is found; | | 1821 | * Skim through until the matching delimiter is found; |
1820 | * pick up variable substitutions on the way. Also allow | | 1822 | * pick up variable substitutions on the way. Also allow |
1821 | * backslashes to quote the delimiter, $, and \, but don't | | 1823 | * backslashes to quote the delimiter, $, and \, but don't |
1822 | * touch other backslashes. | | 1824 | * touch other backslashes. |
1823 | */ | | 1825 | */ |
1824 | for (cp = *tstr; *cp != '\0' && *cp != delim; cp++) { | | 1826 | for (cp = *tstr; *cp != '\0' && *cp != delim; cp++) { |
1825 | Boolean is_escaped = cp[0] == '\\' && (cp[1] == delim || | | 1827 | Boolean is_escaped = cp[0] == '\\' && ( |
1826 | cp[1] == '\\' || cp[1] == '$' || (subst != NULL && cp[1] == '&')); | | 1828 | cp[1] == delim || cp[1] == '\\' || cp[1] == '$' || |
| | | 1829 | (cp[1] == '&' && subst != NULL)); |
1827 | if (is_escaped) { | | 1830 | if (is_escaped) { |
1828 | Buf_AddByte(&buf, cp[1]); | | 1831 | Buf_AddByte(&buf, cp[1]); |
1829 | cp++; | | 1832 | cp++; |
1830 | } else if (*cp == '$') { | | 1833 | } else if (*cp == '$') { |
1831 | if (cp[1] == delim) { /* Unescaped $ at end of pattern */ | | 1834 | if (cp[1] == delim) { /* Unescaped $ at end of pattern */ |
1832 | if (out_pflags != NULL) | | 1835 | if (out_pflags != NULL) |
1833 | *out_pflags |= VARP_ANCHOR_END; | | 1836 | *out_pflags |= VARP_ANCHOR_END; |
1834 | else | | 1837 | else |
1835 | Buf_AddByte(&buf, *cp); | | 1838 | Buf_AddByte(&buf, *cp); |
1836 | } else { | | 1839 | } else { |
1837 | if (eflags & VARE_WANTRES) { | | 1840 | if (eflags & VARE_WANTRES) { |
1838 | char *cp2; | | 1841 | char *cp2; |
1839 | int len; | | 1842 | int len; |
| @@ -2064,37 +2067,35 @@ typedef struct { | | | @@ -2064,37 +2067,35 @@ typedef struct { |
2064 | #define STRMOD_MATCHX(s, want, n) \ | | 2067 | #define STRMOD_MATCHX(s, want, n) \ |
2065 | (strncmp(s, want, n) == 0 && \ | | 2068 | (strncmp(s, want, n) == 0 && \ |
2066 | (s[n] == st->endc || s[n] == ':' || s[n] == '=')) | | 2069 | (s[n] == st->endc || s[n] == ':' || s[n] == '=')) |
2067 | #define CHARMOD_MATCH(c) (c == st->endc || c == ':') | | 2070 | #define CHARMOD_MATCH(c) (c == st->endc || c == ':') |
2068 | | | 2071 | |
2069 | /* :@var@...${var}...@ */ | | 2072 | /* :@var@...${var}...@ */ |
2070 | static Boolean | | 2073 | static Boolean |
2071 | ApplyModifier_Loop(const char *mod, ApplyModifiersState *st) { | | 2074 | ApplyModifier_Loop(const char *mod, ApplyModifiersState *st) { |
2072 | ModifyWord_LoopArgs args; | | 2075 | ModifyWord_LoopArgs args; |
2073 | | | 2076 | |
2074 | args.ctx = st->ctxt; | | 2077 | args.ctx = st->ctxt; |
2075 | st->cp = mod + 1; | | 2078 | st->cp = mod + 1; |
2076 | char delim = '@'; | | 2079 | char delim = '@'; |
2077 | args.tvar = ParseModifierPart(st->ctxt, &st->cp, delim, | | 2080 | args.tvar = ParseModifierPart(&st->cp, delim, st->eflags & ~VARE_WANTRES, |
2078 | st->eflags & ~VARE_WANTRES, | | 2081 | st->ctxt, NULL, NULL, NULL); |
2079 | NULL, NULL, NULL); | | | |
2080 | if (args.tvar == NULL) { | | 2082 | if (args.tvar == NULL) { |
2081 | st->missing_delim = delim; | | 2083 | st->missing_delim = delim; |
2082 | return FALSE; | | 2084 | return FALSE; |
2083 | } | | 2085 | } |
2084 | | | 2086 | |
2085 | args.str = ParseModifierPart(st->ctxt, &st->cp, delim, | | 2087 | args.str = ParseModifierPart(&st->cp, delim, st->eflags & ~VARE_WANTRES, |
2086 | st->eflags & ~VARE_WANTRES, | | 2088 | st->ctxt, NULL, NULL, NULL); |
2087 | NULL, NULL, NULL); | | | |
2088 | if (args.str == NULL) { | | 2089 | if (args.str == NULL) { |
2089 | st->missing_delim = delim; | | 2090 | st->missing_delim = delim; |
2090 | return FALSE; | | 2091 | return FALSE; |
2091 | } | | 2092 | } |
2092 | | | 2093 | |
2093 | st->termc = *st->cp; | | 2094 | st->termc = *st->cp; |
2094 | | | 2095 | |
2095 | args.eflags = st->eflags & (VARE_UNDEFERR | VARE_WANTRES); | | 2096 | args.eflags = st->eflags & (VARE_UNDEFERR | VARE_WANTRES); |
2096 | int prev_sep = st->sep; | | 2097 | int prev_sep = st->sep; |
2097 | st->sep = ' '; /* XXX: this is inconsistent */ | | 2098 | st->sep = ' '; /* XXX: this is inconsistent */ |
2098 | st->newStr = ModifyWords(st->ctxt, st->sep, st->oneBigWord, st->nstr, | | 2099 | st->newStr = ModifyWords(st->ctxt, st->sep, st->oneBigWord, st->nstr, |
2099 | ModifyWord_Loop, &args); | | 2100 | ModifyWord_Loop, &args); |
2100 | st->sep = prev_sep; | | 2101 | st->sep = prev_sep; |
| @@ -2243,27 +2244,27 @@ ApplyModifier_Path(const char *mod, Appl | | | @@ -2243,27 +2244,27 @@ ApplyModifier_Path(const char *mod, Appl |
2243 | } | | 2244 | } |
2244 | if (!st->newStr) | | 2245 | if (!st->newStr) |
2245 | st->newStr = bmake_strdup(st->v->name); | | 2246 | st->newStr = bmake_strdup(st->v->name); |
2246 | st->cp = mod + 1; | | 2247 | st->cp = mod + 1; |
2247 | st->termc = *st->cp; | | 2248 | st->termc = *st->cp; |
2248 | } | | 2249 | } |
2249 | | | 2250 | |
2250 | /* :!cmd! */ | | 2251 | /* :!cmd! */ |
2251 | static Boolean | | 2252 | static Boolean |
2252 | ApplyModifier_Exclam(const char *mod, ApplyModifiersState *st) | | 2253 | ApplyModifier_Exclam(const char *mod, ApplyModifiersState *st) |
2253 | { | | 2254 | { |
2254 | st->cp = mod + 1; | | 2255 | st->cp = mod + 1; |
2255 | char delim = '!'; | | 2256 | char delim = '!'; |
2256 | char *cmd = ParseModifierPart(st->ctxt, &st->cp, delim, st->eflags, | | 2257 | char *cmd = ParseModifierPart(&st->cp, delim, st->eflags, st->ctxt, |
2257 | NULL, NULL, NULL); | | 2258 | NULL, NULL, NULL); |
2258 | if (cmd == NULL) { | | 2259 | if (cmd == NULL) { |
2259 | st->missing_delim = delim; | | 2260 | st->missing_delim = delim; |
2260 | return FALSE; | | 2261 | return FALSE; |
2261 | } | | 2262 | } |
2262 | | | 2263 | |
2263 | const char *emsg = NULL; | | 2264 | const char *emsg = NULL; |
2264 | if (st->eflags & VARE_WANTRES) | | 2265 | if (st->eflags & VARE_WANTRES) |
2265 | st->newStr = Cmd_Exec(cmd, &emsg); | | 2266 | st->newStr = Cmd_Exec(cmd, &emsg); |
2266 | else | | 2267 | else |
2267 | st->newStr = varNoError; | | 2268 | st->newStr = varNoError; |
2268 | free(cmd); | | 2269 | free(cmd); |
2269 | | | 2270 | |
| @@ -2389,36 +2390,36 @@ ApplyModifier_Subst(const char * const m | | | @@ -2389,36 +2390,36 @@ ApplyModifier_Subst(const char * const m |
2389 | | | 2390 | |
2390 | st->cp = mod + 2; | | 2391 | st->cp = mod + 2; |
2391 | | | 2392 | |
2392 | /* | | 2393 | /* |
2393 | * If pattern begins with '^', it is anchored to the | | 2394 | * If pattern begins with '^', it is anchored to the |
2394 | * start of the word -- skip over it and flag pattern. | | 2395 | * start of the word -- skip over it and flag pattern. |
2395 | */ | | 2396 | */ |
2396 | args.pflags = 0; | | 2397 | args.pflags = 0; |
2397 | if (*st->cp == '^') { | | 2398 | if (*st->cp == '^') { |
2398 | args.pflags |= VARP_ANCHOR_START; | | 2399 | args.pflags |= VARP_ANCHOR_START; |
2399 | st->cp++; | | 2400 | st->cp++; |
2400 | } | | 2401 | } |
2401 | | | 2402 | |
2402 | char *lhs = ParseModifierPart(st->ctxt, &st->cp, delim, st->eflags, | | 2403 | char *lhs = ParseModifierPart(&st->cp, delim, st->eflags, st->ctxt, |
2403 | &args.pflags, &args.lhsLen, NULL); | | 2404 | &args.lhsLen, &args.pflags, NULL); |
2404 | if (lhs == NULL) { | | 2405 | if (lhs == NULL) { |
2405 | st->missing_delim = delim; | | 2406 | st->missing_delim = delim; |
2406 | return FALSE; | | 2407 | return FALSE; |
2407 | } | | 2408 | } |
2408 | args.lhs = lhs; | | 2409 | args.lhs = lhs; |
2409 | | | 2410 | |
2410 | char *rhs = ParseModifierPart(st->ctxt, &st->cp, delim, st->eflags, | | 2411 | char *rhs = ParseModifierPart(&st->cp, delim, st->eflags, st->ctxt, |
2411 | NULL, &args.rhsLen, &args); | | 2412 | &args.rhsLen, NULL, &args); |
2412 | if (rhs == NULL) { | | 2413 | if (rhs == NULL) { |
2413 | st->missing_delim = delim; | | 2414 | st->missing_delim = delim; |
2414 | return FALSE; | | 2415 | return FALSE; |
2415 | } | | 2416 | } |
2416 | args.rhs = rhs; | | 2417 | args.rhs = rhs; |
2417 | | | 2418 | |
2418 | /* | | 2419 | /* |
2419 | * Check for global substitution. If 'g' after the final | | 2420 | * Check for global substitution. If 'g' after the final |
2420 | * delimiter, substitution is global and is marked that | | 2421 | * delimiter, substitution is global and is marked that |
2421 | * way. | | 2422 | * way. |
2422 | */ | | 2423 | */ |
2423 | for (;; st->cp++) { | | 2424 | for (;; st->cp++) { |
2424 | switch (*st->cp) { | | 2425 | switch (*st->cp) { |
| @@ -2448,35 +2449,35 @@ ApplyModifier_Subst(const char * const m | | | @@ -2448,35 +2449,35 @@ ApplyModifier_Subst(const char * const m |
2448 | | | 2449 | |
2449 | /* :C,from,to, */ | | 2450 | /* :C,from,to, */ |
2450 | static Boolean | | 2451 | static Boolean |
2451 | ApplyModifier_Regex(const char *mod, ApplyModifiersState *st) | | 2452 | ApplyModifier_Regex(const char *mod, ApplyModifiersState *st) |
2452 | { | | 2453 | { |
2453 | ModifyWord_SubstRegexArgs args; | | 2454 | ModifyWord_SubstRegexArgs args; |
2454 | | | 2455 | |
2455 | args.pflags = 0; | | 2456 | args.pflags = 0; |
2456 | Boolean oneBigWord = st->oneBigWord; | | 2457 | Boolean oneBigWord = st->oneBigWord; |
2457 | char delim = mod[1]; | | 2458 | char delim = mod[1]; |
2458 | | | 2459 | |
2459 | st->cp = mod + 2; | | 2460 | st->cp = mod + 2; |
2460 | | | 2461 | |
2461 | char *re = ParseModifierPart(st->ctxt, &st->cp, delim, | | 2462 | char *re = ParseModifierPart(&st->cp, delim, st->eflags, st->ctxt, |
2462 | st->eflags, NULL, NULL, NULL); | | 2463 | NULL, NULL, NULL); |
2463 | if (re == NULL) { | | 2464 | if (re == NULL) { |
2464 | st->missing_delim = delim; | | 2465 | st->missing_delim = delim; |
2465 | return FALSE; | | 2466 | return FALSE; |
2466 | } | | 2467 | } |
2467 | | | 2468 | |
2468 | args.replace = ParseModifierPart(st->ctxt, &st->cp, delim, | | 2469 | args.replace = ParseModifierPart(&st->cp, delim, st->eflags, st->ctxt, |
2469 | st->eflags, NULL, NULL, NULL); | | 2470 | NULL, NULL, NULL); |
2470 | if (args.replace == NULL) { | | 2471 | if (args.replace == NULL) { |
2471 | free(re); | | 2472 | free(re); |
2472 | st->missing_delim = delim; | | 2473 | st->missing_delim = delim; |
2473 | return FALSE; | | 2474 | return FALSE; |
2474 | } | | 2475 | } |
2475 | | | 2476 | |
2476 | for (;; st->cp++) { | | 2477 | for (;; st->cp++) { |
2477 | switch (*st->cp) { | | 2478 | switch (*st->cp) { |
2478 | case 'g': | | 2479 | case 'g': |
2479 | args.pflags |= VARP_SUB_GLOBAL; | | 2480 | args.pflags |= VARP_SUB_GLOBAL; |
2480 | continue; | | 2481 | continue; |
2481 | case '1': | | 2482 | case '1': |
2482 | args.pflags |= VARP_SUB_ONE; | | 2483 | args.pflags |= VARP_SUB_ONE; |
| @@ -2610,29 +2611,29 @@ ApplyModifier_To(const char *mod, ApplyM | | | @@ -2610,29 +2611,29 @@ ApplyModifier_To(const char *mod, ApplyM |
2610 | st->cp = mod + 2; | | 2611 | st->cp = mod + 2; |
2611 | st->termc = *st->cp; | | 2612 | st->termc = *st->cp; |
2612 | } else { | | 2613 | } else { |
2613 | /* Found ":t<unrecognised>:" or ":t<unrecognised><endc>". */ | | 2614 | /* Found ":t<unrecognised>:" or ":t<unrecognised><endc>". */ |
2614 | return FALSE; | | 2615 | return FALSE; |
2615 | } | | 2616 | } |
2616 | return TRUE; | | 2617 | return TRUE; |
2617 | } | | 2618 | } |
2618 | | | 2619 | |
2619 | /* :[#], :[1], etc. */ | | 2620 | /* :[#], :[1], etc. */ |
2620 | static int | | 2621 | static int |
2621 | ApplyModifier_Words(const char *mod, ApplyModifiersState *st) | | 2622 | ApplyModifier_Words(const char *mod, ApplyModifiersState *st) |
2622 | { | | 2623 | { |
2623 | st->cp = mod + 1; /* point to char after '[' */ | | 2624 | st->cp = mod + 1; /* point to char after '[' */ |
2624 | char delim = ']'; /* look for closing ']' */ | | 2625 | char delim = ']'; /* look for closing ']' */ |
2625 | char *estr = ParseModifierPart(st->ctxt, &st->cp, delim, st->eflags, | | 2626 | char *estr = ParseModifierPart(&st->cp, delim, st->eflags, st->ctxt, |
2626 | NULL, NULL, NULL); | | 2627 | NULL, NULL, NULL); |
2627 | if (estr == NULL) { | | 2628 | if (estr == NULL) { |
2628 | st->missing_delim = delim; | | 2629 | st->missing_delim = delim; |
2629 | return 'c'; | | 2630 | return 'c'; |
2630 | } | | 2631 | } |
2631 | | | 2632 | |
2632 | /* now st->cp points just after the closing ']' */ | | 2633 | /* now st->cp points just after the closing ']' */ |
2633 | if (st->cp[0] != ':' && st->cp[0] != st->endc) | | 2634 | if (st->cp[0] != ':' && st->cp[0] != st->endc) |
2634 | goto bad_modifier; /* Found junk after ']' */ | | 2635 | goto bad_modifier; /* Found junk after ']' */ |
2635 | | | 2636 | |
2636 | if (estr[0] == '\0') | | 2637 | if (estr[0] == '\0') |
2637 | goto bad_modifier; /* empty square brackets in ":[]". */ | | 2638 | goto bad_modifier; /* empty square brackets in ":[]". */ |
2638 | | | 2639 | |
| @@ -2750,36 +2751,36 @@ ApplyModifier_IfElse(const char *mod, Ap | | | @@ -2750,36 +2751,36 @@ ApplyModifier_IfElse(const char *mod, Ap |
2750 | VarEvalFlags then_eflags = st->eflags & ~VARE_WANTRES; | | 2751 | VarEvalFlags then_eflags = st->eflags & ~VARE_WANTRES; |
2751 | VarEvalFlags else_eflags = st->eflags & ~VARE_WANTRES; | | 2752 | VarEvalFlags else_eflags = st->eflags & ~VARE_WANTRES; |
2752 | | | 2753 | |
2753 | if (st->eflags & VARE_WANTRES) { | | 2754 | if (st->eflags & VARE_WANTRES) { |
2754 | cond_rc = Cond_EvalExpression(NULL, st->v->name, &value, 0, FALSE); | | 2755 | cond_rc = Cond_EvalExpression(NULL, st->v->name, &value, 0, FALSE); |
2755 | if (cond_rc != COND_INVALID && value) | | 2756 | if (cond_rc != COND_INVALID && value) |
2756 | then_eflags |= VARE_WANTRES; | | 2757 | then_eflags |= VARE_WANTRES; |
2757 | if (cond_rc != COND_INVALID && !value) | | 2758 | if (cond_rc != COND_INVALID && !value) |
2758 | else_eflags |= VARE_WANTRES; | | 2759 | else_eflags |= VARE_WANTRES; |
2759 | } | | 2760 | } |
2760 | | | 2761 | |
2761 | st->cp = mod + 1; | | 2762 | st->cp = mod + 1; |
2762 | char delim = ':'; | | 2763 | char delim = ':'; |
2763 | char *then_expr = ParseModifierPart( | | 2764 | char *then_expr = ParseModifierPart(&st->cp, delim, then_eflags, st->ctxt, |
2764 | st->ctxt, &st->cp, delim, then_eflags, NULL, NULL, NULL); | | 2765 | NULL, NULL, NULL); |
2765 | if (then_expr == NULL) { | | 2766 | if (then_expr == NULL) { |
2766 | st->missing_delim = delim; | | 2767 | st->missing_delim = delim; |
2767 | return FALSE; | | 2768 | return FALSE; |
2768 | } | | 2769 | } |
2769 | | | 2770 | |
2770 | delim = st->endc; /* BRCLOSE or PRCLOSE */ | | 2771 | delim = st->endc; /* BRCLOSE or PRCLOSE */ |
2771 | char *else_expr = ParseModifierPart( | | 2772 | char *else_expr = ParseModifierPart(&st->cp, delim, else_eflags, st->ctxt, |
2772 | st->ctxt, &st->cp, delim, else_eflags, NULL, NULL, NULL); | | 2773 | NULL, NULL, NULL); |
2773 | if (else_expr == NULL) { | | 2774 | if (else_expr == NULL) { |
2774 | st->missing_delim = delim; | | 2775 | st->missing_delim = delim; |
2775 | return FALSE; | | 2776 | return FALSE; |
2776 | } | | 2777 | } |
2777 | | | 2778 | |
2778 | st->termc = *--st->cp; | | 2779 | st->termc = *--st->cp; |
2779 | if (cond_rc == COND_INVALID) { | | 2780 | if (cond_rc == COND_INVALID) { |
2780 | Error("Bad conditional expression `%s' in %s?%s:%s", | | 2781 | Error("Bad conditional expression `%s' in %s?%s:%s", |
2781 | st->v->name, st->v->name, then_expr, else_expr); | | 2782 | st->v->name, st->v->name, then_expr, else_expr); |
2782 | return FALSE; | | 2783 | return FALSE; |
2783 | } | | 2784 | } |
2784 | | | 2785 | |
2785 | if (value) { | | 2786 | if (value) { |
| @@ -2847,28 +2848,28 @@ ApplyModifier_Assign(const char *mod, Ap | | | @@ -2847,28 +2848,28 @@ ApplyModifier_Assign(const char *mod, Ap |
2847 | | | 2848 | |
2848 | switch (op[0]) { | | 2849 | switch (op[0]) { |
2849 | case '+': | | 2850 | case '+': |
2850 | case '?': | | 2851 | case '?': |
2851 | case '!': | | 2852 | case '!': |
2852 | st->cp = mod + 3; | | 2853 | st->cp = mod + 3; |
2853 | break; | | 2854 | break; |
2854 | default: | | 2855 | default: |
2855 | st->cp = mod + 2; | | 2856 | st->cp = mod + 2; |
2856 | break; | | 2857 | break; |
2857 | } | | 2858 | } |
2858 | | | 2859 | |
2859 | char delim = st->startc == PROPEN ? PRCLOSE : BRCLOSE; | | 2860 | char delim = st->startc == PROPEN ? PRCLOSE : BRCLOSE; |
2860 | char *val = ParseModifierPart(st->ctxt, &st->cp, delim, | | 2861 | char *val = ParseModifierPart(&st->cp, delim, st->eflags, st->ctxt, |
2861 | st->eflags, NULL, NULL, NULL); | | 2862 | NULL, NULL, NULL); |
2862 | if (st->v->flags & VAR_JUNK) { | | 2863 | if (st->v->flags & VAR_JUNK) { |
2863 | /* restore original name */ | | 2864 | /* restore original name */ |
2864 | free(st->v->name); | | 2865 | free(st->v->name); |
2865 | st->v->name = sv_name; | | 2866 | st->v->name = sv_name; |
2866 | } | | 2867 | } |
2867 | if (val == NULL) { | | 2868 | if (val == NULL) { |
2868 | st->missing_delim = delim; | | 2869 | st->missing_delim = delim; |
2869 | return 'c'; | | 2870 | return 'c'; |
2870 | } | | 2871 | } |
2871 | | | 2872 | |
2872 | st->termc = *--st->cp; | | 2873 | st->termc = *--st->cp; |
2873 | | | 2874 | |
2874 | if (st->eflags & VARE_WANTRES) { | | 2875 | if (st->eflags & VARE_WANTRES) { |
| @@ -2947,35 +2948,35 @@ ApplyModifier_SysV(const char *mod, Appl | | | @@ -2947,35 +2948,35 @@ ApplyModifier_SysV(const char *mod, Appl |
2947 | /* continue looking for st->endc */ | | 2948 | /* continue looking for st->endc */ |
2948 | } else if (*st->cp == st->endc) | | 2949 | } else if (*st->cp == st->endc) |
2949 | nest--; | | 2950 | nest--; |
2950 | else if (*st->cp == st->startc) | | 2951 | else if (*st->cp == st->startc) |
2951 | nest++; | | 2952 | nest++; |
2952 | if (nest > 0) | | 2953 | if (nest > 0) |
2953 | st->cp++; | | 2954 | st->cp++; |
2954 | } | | 2955 | } |
2955 | if (*st->cp != st->endc || !eqFound) | | 2956 | if (*st->cp != st->endc || !eqFound) |
2956 | return 0; | | 2957 | return 0; |
2957 | | | 2958 | |
2958 | char delim = '='; | | 2959 | char delim = '='; |
2959 | st->cp = mod; | | 2960 | st->cp = mod; |
2960 | char *lhs = ParseModifierPart(st->ctxt, &st->cp, delim, st->eflags, | | 2961 | char *lhs = ParseModifierPart(&st->cp, delim, st->eflags, st->ctxt, |
2961 | NULL, NULL, NULL); | | 2962 | NULL, NULL, NULL); |
2962 | if (lhs == NULL) { | | 2963 | if (lhs == NULL) { |
2963 | st->missing_delim = delim; | | 2964 | st->missing_delim = delim; |
2964 | return 'c'; | | 2965 | return 'c'; |
2965 | } | | 2966 | } |
2966 | | | 2967 | |
2967 | delim = st->endc; | | 2968 | delim = st->endc; |
2968 | char *rhs = ParseModifierPart(st->ctxt, &st->cp, delim, st->eflags, | | 2969 | char *rhs = ParseModifierPart(&st->cp, delim, st->eflags, st->ctxt, |
2969 | NULL, NULL, NULL); | | 2970 | NULL, NULL, NULL); |
2970 | if (rhs == NULL) { | | 2971 | if (rhs == NULL) { |
2971 | st->missing_delim = delim; | | 2972 | st->missing_delim = delim; |
2972 | return 'c'; | | 2973 | return 'c'; |
2973 | } | | 2974 | } |
2974 | | | 2975 | |
2975 | /* | | 2976 | /* |
2976 | * SYSV modifications happen through the whole | | 2977 | * SYSV modifications happen through the whole |
2977 | * string. Note the pattern is anchored at the end. | | 2978 | * string. Note the pattern is anchored at the end. |
2978 | */ | | 2979 | */ |
2979 | st->termc = *--st->cp; | | 2980 | st->termc = *--st->cp; |
2980 | if (lhs[0] == '\0' && *st->nstr == '\0') { | | 2981 | if (lhs[0] == '\0' && *st->nstr == '\0') { |
2981 | st->newStr = st->nstr; /* special case */ | | 2982 | st->newStr = st->nstr; /* special case */ |