| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: var.c,v 1.652 2020/11/02 21:34:40 rillig Exp $ */ | | 1 | /* $NetBSD: var.c,v 1.653 2020/11/04 02:26:21 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. |
| @@ -120,58 +120,53 @@ | | | @@ -120,58 +120,53 @@ |
120 | #include <regex.h> | | 120 | #include <regex.h> |
121 | #endif | | 121 | #endif |
122 | #include <errno.h> | | 122 | #include <errno.h> |
123 | #include <inttypes.h> | | 123 | #include <inttypes.h> |
124 | #include <limits.h> | | 124 | #include <limits.h> |
125 | #include <time.h> | | 125 | #include <time.h> |
126 | | | 126 | |
127 | #include "make.h" | | 127 | #include "make.h" |
128 | #include "dir.h" | | 128 | #include "dir.h" |
129 | #include "job.h" | | 129 | #include "job.h" |
130 | #include "metachar.h" | | 130 | #include "metachar.h" |
131 | | | 131 | |
132 | /* "@(#)var.c 8.3 (Berkeley) 3/19/94" */ | | 132 | /* "@(#)var.c 8.3 (Berkeley) 3/19/94" */ |
133 | MAKE_RCSID("$NetBSD: var.c,v 1.652 2020/11/02 21:34:40 rillig Exp $"); | | 133 | MAKE_RCSID("$NetBSD: var.c,v 1.653 2020/11/04 02:26:21 rillig Exp $"); |
134 | | | 134 | |
135 | #define VAR_DEBUG1(fmt, arg1) DEBUG1(VAR, fmt, arg1) | | 135 | #define VAR_DEBUG1(fmt, arg1) DEBUG1(VAR, fmt, arg1) |
136 | #define VAR_DEBUG2(fmt, arg1, arg2) DEBUG2(VAR, fmt, arg1, arg2) | | 136 | #define VAR_DEBUG2(fmt, arg1, arg2) DEBUG2(VAR, fmt, arg1, arg2) |
137 | #define VAR_DEBUG3(fmt, arg1, arg2, arg3) DEBUG3(VAR, fmt, arg1, arg2, arg3) | | 137 | #define VAR_DEBUG3(fmt, arg1, arg2, arg3) DEBUG3(VAR, fmt, arg1, arg2, arg3) |
138 | #define VAR_DEBUG4(fmt, arg1, arg2, arg3, arg4) DEBUG4(VAR, fmt, arg1, arg2, arg3, arg4) | | 138 | #define VAR_DEBUG4(fmt, arg1, arg2, arg3, arg4) DEBUG4(VAR, fmt, arg1, arg2, arg3, arg4) |
139 | | | 139 | |
140 | ENUM_FLAGS_RTTI_3(VarEvalFlags, | | 140 | ENUM_FLAGS_RTTI_3(VarEvalFlags, |
141 | VARE_UNDEFERR, VARE_WANTRES, VARE_ASSIGN); | | 141 | VARE_UNDEFERR, VARE_WANTRES, VARE_ASSIGN); |
142 | | | 142 | |
143 | /* | | 143 | /* |
144 | * This lets us tell if we have replaced the original environ | | 144 | * This lets us tell if we have replaced the original environ |
145 | * (which we cannot free). | | 145 | * (which we cannot free). |
146 | */ | | 146 | */ |
147 | char **savedEnv = NULL; | | 147 | char **savedEnv = NULL; |
148 | | | 148 | |
149 | /* Special return value for Var_Parse, indicating a parse error. It may be | | 149 | /* Special return value for Var_Parse, indicating a parse error. It may be |
150 | * caused by an undefined variable, a syntax error in a modifier or | | 150 | * caused by an undefined variable, a syntax error in a modifier or |
151 | * something entirely different. */ | | 151 | * something entirely different. */ |
152 | char var_Error[] = ""; | | 152 | char var_Error[] = ""; |
153 | | | 153 | |
154 | /* Special return value for Var_Parse, indicating an undefined variable in | | 154 | /* Special return value for Var_Parse, indicating an undefined variable in |
155 | * a case where VARE_UNDEFERR is not set. This undefined variable is | | 155 | * a case where VARE_UNDEFERR is not set. This undefined variable is |
156 | * typically a dynamic variable such as ${.TARGET}, whose expansion needs to | | 156 | * typically a dynamic variable such as ${.TARGET}, whose expansion needs to |
157 | * be deferred until it is defined in an actual target. */ | | 157 | * be deferred until it is defined in an actual target. */ |
158 | static char varUndefined[] = ""; | | 158 | static char varUndefined[] = ""; |
159 | | | 159 | |
160 | /* Special return value for Var_Parse, just to avoid allocating empty strings. | | | |
161 | * In contrast to var_Error and varUndefined, this is not an error marker but | | | |
162 | * just an ordinary successful return value. */ | | | |
163 | static char emptyString[] = ""; | | | |
164 | | | | |
165 | /* | | 160 | /* |
166 | * Traditionally this make consumed $$ during := like any other expansion. | | 161 | * Traditionally this make consumed $$ during := like any other expansion. |
167 | * Other make's do not, and this make follows straight since 2016-01-09. | | 162 | * Other make's do not, and this make follows straight since 2016-01-09. |
168 | * | | 163 | * |
169 | * This knob allows controlling the behavior. | | 164 | * This knob allows controlling the behavior. |
170 | * FALSE to consume $$ during := assignment. | | 165 | * FALSE to consume $$ during := assignment. |
171 | * TRUE to preserve $$ during := assignment. | | 166 | * TRUE to preserve $$ during := assignment. |
172 | */ | | 167 | */ |
173 | #define MAKE_SAVE_DOLLARS ".MAKE.SAVE_DOLLARS" | | 168 | #define MAKE_SAVE_DOLLARS ".MAKE.SAVE_DOLLARS" |
174 | static Boolean save_dollars = TRUE; | | 169 | static Boolean save_dollars = TRUE; |
175 | | | 170 | |
176 | /* | | 171 | /* |
177 | * Internally, variables are contained in four different contexts. | | 172 | * Internally, variables are contained in four different contexts. |
| @@ -2289,27 +2284,27 @@ ApplyModifier_ShellCommand(const char ** | | | @@ -2289,27 +2284,27 @@ ApplyModifier_ShellCommand(const char ** |
2289 | const char *errfmt; | | 2284 | const char *errfmt; |
2290 | VarParseResult res; | | 2285 | VarParseResult res; |
2291 | | | 2286 | |
2292 | (*pp)++; | | 2287 | (*pp)++; |
2293 | res = ParseModifierPart(pp, '!', st->eflags, st, | | 2288 | res = ParseModifierPart(pp, '!', st->eflags, st, |
2294 | &cmd, NULL, NULL, NULL); | | 2289 | &cmd, NULL, NULL, NULL); |
2295 | if (res != VPR_OK) | | 2290 | if (res != VPR_OK) |
2296 | return AMR_CLEANUP; | | 2291 | return AMR_CLEANUP; |
2297 | | | 2292 | |
2298 | errfmt = NULL; | | 2293 | errfmt = NULL; |
2299 | if (st->eflags & VARE_WANTRES) | | 2294 | if (st->eflags & VARE_WANTRES) |
2300 | st->newVal = Cmd_Exec(cmd, &errfmt); | | 2295 | st->newVal = Cmd_Exec(cmd, &errfmt); |
2301 | else | | 2296 | else |
2302 | st->newVal = emptyString; | | 2297 | st->newVal = bmake_strdup(""); |
2303 | free(cmd); | | 2298 | free(cmd); |
2304 | | | 2299 | |
2305 | if (errfmt != NULL) | | 2300 | if (errfmt != NULL) |
2306 | Error(errfmt, st->val); /* XXX: why still return AMR_OK? */ | | 2301 | Error(errfmt, st->val); /* XXX: why still return AMR_OK? */ |
2307 | | | 2302 | |
2308 | ApplyModifiersState_Define(st); | | 2303 | ApplyModifiersState_Define(st); |
2309 | return AMR_OK; | | 2304 | return AMR_OK; |
2310 | } | | 2305 | } |
2311 | | | 2306 | |
2312 | /* The :range modifier generates an integer sequence as long as the words. | | 2307 | /* The :range modifier generates an integer sequence as long as the words. |
2313 | * The :range=7 modifier generates an integer sequence from 1 to 7. */ | | 2308 | * The :range=7 modifier generates an integer sequence from 1 to 7. */ |
2314 | static ApplyModifierResult | | 2309 | static ApplyModifierResult |
2315 | ApplyModifier_Range(const char **pp, ApplyModifiersState *st) | | 2310 | ApplyModifier_Range(const char **pp, ApplyModifiersState *st) |
| @@ -3004,27 +2999,27 @@ ok: | | | @@ -3004,27 +2999,27 @@ ok: |
3004 | free(cmd_output); | | 2999 | free(cmd_output); |
3005 | break; | | 3000 | break; |
3006 | } | | 3001 | } |
3007 | case '?': | | 3002 | case '?': |
3008 | if (!(st->exprFlags & VEF_UNDEF)) | | 3003 | if (!(st->exprFlags & VEF_UNDEF)) |
3009 | break; | | 3004 | break; |
3010 | /* FALLTHROUGH */ | | 3005 | /* FALLTHROUGH */ |
3011 | default: | | 3006 | default: |
3012 | Var_Set(st->v->name, val, v_ctxt); | | 3007 | Var_Set(st->v->name, val, v_ctxt); |
3013 | break; | | 3008 | break; |
3014 | } | | 3009 | } |
3015 | } | | 3010 | } |
3016 | free(val); | | 3011 | free(val); |
3017 | st->newVal = emptyString; | | 3012 | st->newVal = bmake_strdup(""); |
3018 | return AMR_OK; | | 3013 | return AMR_OK; |
3019 | } | | 3014 | } |
3020 | | | 3015 | |
3021 | /* :_=... | | 3016 | /* :_=... |
3022 | * remember current value */ | | 3017 | * remember current value */ |
3023 | static ApplyModifierResult | | 3018 | static ApplyModifierResult |
3024 | ApplyModifier_Remember(const char **pp, ApplyModifiersState *st) | | 3019 | ApplyModifier_Remember(const char **pp, ApplyModifiersState *st) |
3025 | { | | 3020 | { |
3026 | const char *mod = *pp; | | 3021 | const char *mod = *pp; |
3027 | if (!ModMatchEq(mod, "_", st->endc)) | | 3022 | if (!ModMatchEq(mod, "_", st->endc)) |
3028 | return AMR_UNKNOWN; | | 3023 | return AMR_UNKNOWN; |
3029 | | | 3024 | |
3030 | if (mod[1] == '=') { | | 3025 | if (mod[1] == '=') { |
| @@ -3128,27 +3123,27 @@ ApplyModifier_SysV(const char **pp, Appl | | | @@ -3128,27 +3123,27 @@ ApplyModifier_SysV(const char **pp, Appl |
3128 | #ifdef SUNSHCMD | | 3123 | #ifdef SUNSHCMD |
3129 | /* :sh */ | | 3124 | /* :sh */ |
3130 | static ApplyModifierResult | | 3125 | static ApplyModifierResult |
3131 | ApplyModifier_SunShell(const char **pp, ApplyModifiersState *st) | | 3126 | ApplyModifier_SunShell(const char **pp, ApplyModifiersState *st) |
3132 | { | | 3127 | { |
3133 | const char *p = *pp; | | 3128 | const char *p = *pp; |
3134 | if (p[1] == 'h' && (p[2] == st->endc || p[2] == ':')) { | | 3129 | if (p[1] == 'h' && (p[2] == st->endc || p[2] == ':')) { |
3135 | if (st->eflags & VARE_WANTRES) { | | 3130 | if (st->eflags & VARE_WANTRES) { |
3136 | const char *errfmt; | | 3131 | const char *errfmt; |
3137 | st->newVal = Cmd_Exec(st->val, &errfmt); | | 3132 | st->newVal = Cmd_Exec(st->val, &errfmt); |
3138 | if (errfmt) | | 3133 | if (errfmt) |
3139 | Error(errfmt, st->val); | | 3134 | Error(errfmt, st->val); |
3140 | } else | | 3135 | } else |
3141 | st->newVal = emptyString; | | 3136 | st->newVal = bmake_strdup(""); |
3142 | *pp = p + 2; | | 3137 | *pp = p + 2; |
3143 | return AMR_OK; | | 3138 | return AMR_OK; |
3144 | } else | | 3139 | } else |
3145 | return AMR_UNKNOWN; | | 3140 | return AMR_UNKNOWN; |
3146 | } | | 3141 | } |
3147 | #endif | | 3142 | #endif |
3148 | | | 3143 | |
3149 | static void | | 3144 | static void |
3150 | LogBeforeApply(const ApplyModifiersState *st, const char *mod, const char endc) | | 3145 | LogBeforeApply(const ApplyModifiersState *st, const char *mod, const char endc) |
3151 | { | | 3146 | { |
3152 | char eflags_str[VarEvalFlags_ToStringSize]; | | 3147 | char eflags_str[VarEvalFlags_ToStringSize]; |
3153 | char vflags_str[VarFlags_ToStringSize]; | | 3148 | char vflags_str[VarFlags_ToStringSize]; |
3154 | char exprflags_str[VarExprFlags_ToStringSize]; | | 3149 | char exprflags_str[VarExprFlags_ToStringSize]; |
| @@ -3402,30 +3397,28 @@ ApplyModifiers( | | | @@ -3402,30 +3397,28 @@ ApplyModifiers( |
3402 | goto cleanup; | | 3397 | goto cleanup; |
3403 | if (res == AMR_BAD) | | 3398 | if (res == AMR_BAD) |
3404 | goto bad_modifier; | | 3399 | goto bad_modifier; |
3405 | | | 3400 | |
3406 | if (DEBUG(VAR)) | | 3401 | if (DEBUG(VAR)) |
3407 | LogAfterApply(&st, p, mod); | | 3402 | LogAfterApply(&st, p, mod); |
3408 | | | 3403 | |
3409 | if (st.newVal != st.val) { | | 3404 | if (st.newVal != st.val) { |
3410 | if (*out_freeIt) { | | 3405 | if (*out_freeIt) { |
3411 | free(st.val); | | 3406 | free(st.val); |
3412 | *out_freeIt = NULL; | | 3407 | *out_freeIt = NULL; |
3413 | } | | 3408 | } |
3414 | st.val = st.newVal; | | 3409 | st.val = st.newVal; |
3415 | if (st.val != var_Error && st.val != varUndefined && | | 3410 | if (st.val != var_Error && st.val != varUndefined) |
3416 | st.val != emptyString) { | | | |
3417 | *out_freeIt = st.val; | | 3411 | *out_freeIt = st.val; |
3418 | } | | | |
3419 | } | | 3412 | } |
3420 | if (*p == '\0' && st.endc != '\0') { | | 3413 | if (*p == '\0' && st.endc != '\0') { |
3421 | Error("Unclosed variable specification (expecting '%c') " | | 3414 | Error("Unclosed variable specification (expecting '%c') " |
3422 | "for \"%s\" (value \"%s\") modifier %c", | | 3415 | "for \"%s\" (value \"%s\") modifier %c", |
3423 | st.endc, st.v->name, st.val, *mod); | | 3416 | st.endc, st.v->name, st.val, *mod); |
3424 | } else if (*p == ':') { | | 3417 | } else if (*p == ':') { |
3425 | p++; | | 3418 | p++; |
3426 | } else if (DEBUG(LINT) && *p != '\0' && *p != endc) { | | 3419 | } else if (DEBUG(LINT) && *p != '\0' && *p != endc) { |
3427 | Parse_Error(PARSE_FATAL, | | 3420 | Parse_Error(PARSE_FATAL, |
3428 | "Missing delimiter ':' after modifier \"%.*s\"", | | 3421 | "Missing delimiter ':' after modifier \"%.*s\"", |
3429 | (int)(p - mod), mod); | | 3422 | (int)(p - mod), mod); |
3430 | /* TODO: propagate parse error to the enclosing expression */ | | 3423 | /* TODO: propagate parse error to the enclosing expression */ |
3431 | } | | 3424 | } |