| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: var.c,v 1.342 2020/07/27 22:21:29 rillig Exp $ */ | | 1 | /* $NetBSD: var.c,v 1.343 2020/07/27 22:24:03 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.342 2020/07/27 22:21:29 rillig Exp $"; | | 72 | static char rcsid[] = "$NetBSD: var.c,v 1.343 2020/07/27 22:24:03 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.342 2020/07/27 22:21:29 rillig Exp $"); | | 79 | __RCSID("$NetBSD: var.c,v 1.343 2020/07/27 22:24:03 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 | * |
| @@ -2038,27 +2038,26 @@ VarStrftime(const char *fmt, int zulu, t | | | @@ -2038,27 +2038,26 @@ VarStrftime(const char *fmt, int zulu, t |
2038 | | | 2038 | |
2039 | typedef struct { | | 2039 | typedef struct { |
2040 | /* const parameters */ | | 2040 | /* const parameters */ |
2041 | int startc; /* '\0' or '{' or '(' */ | | 2041 | int startc; /* '\0' or '{' or '(' */ |
2042 | int endc; | | 2042 | int endc; |
2043 | Var *v; | | 2043 | Var *v; |
2044 | GNode *ctxt; | | 2044 | GNode *ctxt; |
2045 | VarEvalFlags eflags; | | 2045 | VarEvalFlags eflags; |
2046 | int *lengthPtr; | | 2046 | int *lengthPtr; |
2047 | void **freePtr; | | 2047 | void **freePtr; |
2048 | | | 2048 | |
2049 | /* read-write */ | | 2049 | /* read-write */ |
2050 | char *nstr; | | 2050 | char *nstr; |
2051 | const char *start; | | | |
2052 | const char *cp; /* The position where parsing continues | | 2051 | const char *cp; /* The position where parsing continues |
2053 | * after the current modifier. */ | | 2052 | * after the current modifier. */ |
2054 | char termc; /* Character which terminated scan */ | | 2053 | char termc; /* Character which terminated scan */ |
2055 | char missing_delim; /* For error reporting */ | | 2054 | char missing_delim; /* For error reporting */ |
2056 | | | 2055 | |
2057 | Byte sep; /* Word separator in expansions */ | | 2056 | Byte sep; /* Word separator in expansions */ |
2058 | Boolean oneBigWord; /* TRUE if we will treat the variable as a | | 2057 | Boolean oneBigWord; /* TRUE if we will treat the variable as a |
2059 | * single big word, even if it contains | | 2058 | * single big word, even if it contains |
2060 | * embedded spaces (as opposed to the | | 2059 | * embedded spaces (as opposed to the |
2061 | * usual behaviour of treating it as | | 2060 | * usual behaviour of treating it as |
2062 | * several space-separated words). */ | | 2061 | * several space-separated words). */ |
2063 | | | 2062 | |
2064 | /* result */ | | 2063 | /* result */ |
| @@ -3060,35 +3059,34 @@ ApplyModifier_SysV(const char *mod, Appl | | | @@ -3060,35 +3059,34 @@ ApplyModifier_SysV(const char *mod, Appl |
3060 | * :U<newval> Use <newval> as value if variable undefined | | 3059 | * :U<newval> Use <newval> as value if variable undefined |
3061 | * :L Use the name of the variable as the value. | | 3060 | * :L Use the name of the variable as the value. |
3062 | * :P Use the path of the node that has the same | | 3061 | * :P Use the path of the node that has the same |
3063 | * name as the variable as the value. This | | 3062 | * name as the variable as the value. This |
3064 | * basically includes an implied :L so that | | 3063 | * basically includes an implied :L so that |
3065 | * the common method of refering to the path | | 3064 | * the common method of refering to the path |
3066 | * of your dependent 'x' in a rule is to use | | 3065 | * of your dependent 'x' in a rule is to use |
3067 | * the form '${x:P}'. | | 3066 | * the form '${x:P}'. |
3068 | * :!<cmd>! Run cmd much the same as :sh run's the | | 3067 | * :!<cmd>! Run cmd much the same as :sh run's the |
3069 | * current value of the variable. | | 3068 | * current value of the variable. |
3070 | * Assignment operators (see ApplyModifier_Assign). | | 3069 | * Assignment operators (see ApplyModifier_Assign). |
3071 | */ | | 3070 | */ |
3072 | static char * | | 3071 | static char * |
3073 | ApplyModifiers(char *nstr, const char *tstr, | | 3072 | ApplyModifiers(char *nstr, const char * const tstr, |
3074 | int const startc, int const endc, | | 3073 | int const startc, int const endc, |
3075 | Var * const v, GNode * const ctxt, VarEvalFlags const eflags, | | 3074 | Var * const v, GNode * const ctxt, VarEvalFlags const eflags, |
3076 | int * const lengthPtr, void ** const freePtr) | | 3075 | int * const lengthPtr, void ** const freePtr) |
3077 | { | | 3076 | { |
3078 | ApplyModifiersState st = { | | 3077 | ApplyModifiersState st = { |
3079 | startc, endc, v, ctxt, eflags, lengthPtr, freePtr, | | 3078 | startc, endc, v, ctxt, eflags, lengthPtr, freePtr, |
3080 | nstr, tstr, tstr, | | 3079 | nstr, tstr, '\0', '\0', ' ', FALSE, NULL |
3081 | '\0', '\0', ' ', FALSE, NULL | | | |
3082 | }; | | 3080 | }; |
3083 | | | 3081 | |
3084 | const char *p = tstr; | | 3082 | const char *p = tstr; |
3085 | while (*p != '\0' && *p != endc) { | | 3083 | while (*p != '\0' && *p != endc) { |
3086 | | | 3084 | |
3087 | if (*p == '$') { | | 3085 | if (*p == '$') { |
3088 | /* | | 3086 | /* |
3089 | * We may have some complex modifiers in a variable. | | 3087 | * We may have some complex modifiers in a variable. |
3090 | */ | | 3088 | */ |
3091 | void *freeIt; | | 3089 | void *freeIt; |
3092 | const char *rval; | | 3090 | const char *rval; |
3093 | int rlen; | | 3091 | int rlen; |
3094 | int c; | | 3092 | int c; |
| @@ -3338,35 +3336,35 @@ ApplyModifiers(char *nstr, const char *t | | | @@ -3338,35 +3336,35 @@ ApplyModifiers(char *nstr, const char *t |
3338 | *st.freePtr = st.nstr; | | 3336 | *st.freePtr = st.nstr; |
3339 | } | | 3337 | } |
3340 | } | | 3338 | } |
3341 | if (st.termc == '\0' && st.endc != '\0') { | | 3339 | if (st.termc == '\0' && st.endc != '\0') { |
3342 | Error("Unclosed variable specification (expecting '%c') " | | 3340 | Error("Unclosed variable specification (expecting '%c') " |
3343 | "for \"%s\" (value \"%s\") modifier %c", | | 3341 | "for \"%s\" (value \"%s\") modifier %c", |
3344 | st.endc, st.v->name, st.nstr, modifier); | | 3342 | st.endc, st.v->name, st.nstr, modifier); |
3345 | } else if (st.termc == ':') { | | 3343 | } else if (st.termc == ':') { |
3346 | st.cp++; | | 3344 | st.cp++; |
3347 | } | | 3345 | } |
3348 | p = st.cp; | | 3346 | p = st.cp; |
3349 | } | | 3347 | } |
3350 | out: | | 3348 | out: |
3351 | *st.lengthPtr = p - st.start; | | 3349 | *st.lengthPtr = p - tstr; |
3352 | return st.nstr; | | 3350 | return st.nstr; |
3353 | | | 3351 | |
3354 | bad_modifier: | | 3352 | bad_modifier: |
3355 | Error("Bad modifier `:%.*s' for %s", | | 3353 | Error("Bad modifier `:%.*s' for %s", |
3356 | (int)strcspn(p, ":)}"), p, st.v->name); | | 3354 | (int)strcspn(p, ":)}"), p, st.v->name); |
3357 | | | 3355 | |
3358 | cleanup: | | 3356 | cleanup: |
3359 | *st.lengthPtr = st.cp - st.start; | | 3357 | *st.lengthPtr = st.cp - tstr; |
3360 | if (st.missing_delim != '\0') | | 3358 | if (st.missing_delim != '\0') |
3361 | Error("Unclosed substitution for %s (%c missing)", | | 3359 | Error("Unclosed substitution for %s (%c missing)", |
3362 | st.v->name, st.missing_delim); | | 3360 | st.v->name, st.missing_delim); |
3363 | free(*st.freePtr); | | 3361 | free(*st.freePtr); |
3364 | *st.freePtr = NULL; | | 3362 | *st.freePtr = NULL; |
3365 | return var_Error; | | 3363 | return var_Error; |
3366 | } | | 3364 | } |
3367 | | | 3365 | |
3368 | static Boolean | | 3366 | static Boolean |
3369 | VarIsDynamic(GNode *ctxt, const char *varname, size_t namelen) | | 3367 | VarIsDynamic(GNode *ctxt, const char *varname, size_t namelen) |
3370 | { | | 3368 | { |
3371 | if ((namelen == 1 || | | 3369 | if ((namelen == 1 || |
3372 | (namelen == 2 && (varname[1] == 'F' || varname[1] == 'D'))) && | | 3370 | (namelen == 2 && (varname[1] == 'F' || varname[1] == 'D'))) && |