| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: var.c,v 1.625 2020/10/31 14:55:33 rillig Exp $ */ | | 1 | /* $NetBSD: var.c,v 1.626 2020/10/31 15:23:52 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. |
| @@ -119,27 +119,27 @@ | | | @@ -119,27 +119,27 @@ |
119 | #include <sys/types.h> | | 119 | #include <sys/types.h> |
120 | #include <regex.h> | | 120 | #include <regex.h> |
121 | #endif | | 121 | #endif |
122 | #include <inttypes.h> | | 122 | #include <inttypes.h> |
123 | #include <limits.h> | | 123 | #include <limits.h> |
124 | #include <time.h> | | 124 | #include <time.h> |
125 | | | 125 | |
126 | #include "make.h" | | 126 | #include "make.h" |
127 | #include "dir.h" | | 127 | #include "dir.h" |
128 | #include "job.h" | | 128 | #include "job.h" |
129 | #include "metachar.h" | | 129 | #include "metachar.h" |
130 | | | 130 | |
131 | /* "@(#)var.c 8.3 (Berkeley) 3/19/94" */ | | 131 | /* "@(#)var.c 8.3 (Berkeley) 3/19/94" */ |
132 | MAKE_RCSID("$NetBSD: var.c,v 1.625 2020/10/31 14:55:33 rillig Exp $"); | | 132 | MAKE_RCSID("$NetBSD: var.c,v 1.626 2020/10/31 15:23:52 rillig Exp $"); |
133 | | | 133 | |
134 | #define VAR_DEBUG1(fmt, arg1) DEBUG1(VAR, fmt, arg1) | | 134 | #define VAR_DEBUG1(fmt, arg1) DEBUG1(VAR, fmt, arg1) |
135 | #define VAR_DEBUG2(fmt, arg1, arg2) DEBUG2(VAR, fmt, arg1, arg2) | | 135 | #define VAR_DEBUG2(fmt, arg1, arg2) DEBUG2(VAR, fmt, arg1, arg2) |
136 | #define VAR_DEBUG3(fmt, arg1, arg2, arg3) DEBUG3(VAR, fmt, arg1, arg2, arg3) | | 136 | #define VAR_DEBUG3(fmt, arg1, arg2, arg3) DEBUG3(VAR, fmt, arg1, arg2, arg3) |
137 | #define VAR_DEBUG4(fmt, arg1, arg2, arg3, arg4) DEBUG4(VAR, fmt, arg1, arg2, arg3, arg4) | | 137 | #define VAR_DEBUG4(fmt, arg1, arg2, arg3, arg4) DEBUG4(VAR, fmt, arg1, arg2, arg3, arg4) |
138 | | | 138 | |
139 | ENUM_FLAGS_RTTI_3(VarEvalFlags, | | 139 | ENUM_FLAGS_RTTI_3(VarEvalFlags, |
140 | VARE_UNDEFERR, VARE_WANTRES, VARE_ASSIGN); | | 140 | VARE_UNDEFERR, VARE_WANTRES, VARE_ASSIGN); |
141 | | | 141 | |
142 | /* | | 142 | /* |
143 | * This lets us tell if we have replaced the original environ | | 143 | * This lets us tell if we have replaced the original environ |
144 | * (which we cannot free). | | 144 | * (which we cannot free). |
145 | */ | | 145 | */ |
| @@ -3316,59 +3316,47 @@ out: | | | @@ -3316,59 +3316,47 @@ out: |
3316 | | | 3316 | |
3317 | bad_modifier: | | 3317 | bad_modifier: |
3318 | Error("Bad modifier `:%.*s' for %s", | | 3318 | Error("Bad modifier `:%.*s' for %s", |
3319 | (int)strcspn(mod, ":)}"), mod, st.v->name); | | 3319 | (int)strcspn(mod, ":)}"), mod, st.v->name); |
3320 | | | 3320 | |
3321 | cleanup: | | 3321 | cleanup: |
3322 | *pp = p; | | 3322 | *pp = p; |
3323 | free(*freePtr); | | 3323 | free(*freePtr); |
3324 | *freePtr = NULL; | | 3324 | *freePtr = NULL; |
3325 | *exprFlags = st.exprFlags; | | 3325 | *exprFlags = st.exprFlags; |
3326 | return var_Error; | | 3326 | return var_Error; |
3327 | } | | 3327 | } |
3328 | | | 3328 | |
| | | 3329 | /* Only four of the local variables are treated specially as they are the |
| | | 3330 | * only four that will be set when dynamic sources are expanded. */ |
3329 | static Boolean | | 3331 | static Boolean |
3330 | VarIsDynamic(GNode *ctxt, const char *varname, size_t namelen) | | 3332 | VarnameIsDynamic(const char *name, size_t len) |
3331 | { | | 3333 | { |
3332 | if ((namelen == 1 || | | 3334 | if (len == 1 || (len == 2 && (name[1] == 'F' || name[1] == 'D'))) { |
3333 | (namelen == 2 && (varname[1] == 'F' || varname[1] == 'D'))) && | | 3335 | switch (name[0]) { |
3334 | (ctxt == VAR_CMDLINE || ctxt == VAR_GLOBAL)) | | | |
3335 | { | | | |
3336 | /* | | | |
3337 | * If substituting a local variable in a non-local context, | | | |
3338 | * assume it's for dynamic source stuff. We have to handle | | | |
3339 | * this specially and return the longhand for the variable | | | |
3340 | * with the dollar sign escaped so it makes it back to the | | | |
3341 | * caller. Only four of the local variables are treated | | | |
3342 | * specially as they are the only four that will be set | | | |
3343 | * when dynamic sources are expanded. | | | |
3344 | */ | | | |
3345 | switch (varname[0]) { | | | |
3346 | case '@': | | 3336 | case '@': |
3347 | case '%': | | 3337 | case '%': |
3348 | case '*': | | 3338 | case '*': |
3349 | case '!': | | 3339 | case '!': |
3350 | return TRUE; | | 3340 | return TRUE; |
3351 | } | | 3341 | } |
3352 | return FALSE; | | 3342 | return FALSE; |
3353 | } | | 3343 | } |
3354 | | | 3344 | |
3355 | if ((namelen == 7 || namelen == 8) && varname[0] == '.' && | | 3345 | if ((len == 7 || len == 8) && name[0] == '.' && ch_isupper(name[1])) { |
3356 | ch_isupper(varname[1]) && (ctxt == VAR_CMDLINE || ctxt == VAR_GLOBAL)) | | 3346 | return strcmp(name, ".TARGET") == 0 || |
3357 | { | | 3347 | strcmp(name, ".ARCHIVE") == 0 || |
3358 | return strcmp(varname, ".TARGET") == 0 || | | 3348 | strcmp(name, ".PREFIX") == 0 || |
3359 | strcmp(varname, ".ARCHIVE") == 0 || | | 3349 | strcmp(name, ".MEMBER") == 0; |
3360 | strcmp(varname, ".PREFIX") == 0 || | | | |
3361 | strcmp(varname, ".MEMBER") == 0; | | | |
3362 | } | | 3350 | } |
3363 | | | 3351 | |
3364 | return FALSE; | | 3352 | return FALSE; |
3365 | } | | 3353 | } |
3366 | | | 3354 | |
3367 | static const char * | | 3355 | static const char * |
3368 | UndefinedShortVarValue(char varname, const GNode *ctxt, VarEvalFlags eflags) | | 3356 | UndefinedShortVarValue(char varname, const GNode *ctxt, VarEvalFlags eflags) |
3369 | { | | 3357 | { |
3370 | if (ctxt == VAR_CMDLINE || ctxt == VAR_GLOBAL) { | | 3358 | if (ctxt == VAR_CMDLINE || ctxt == VAR_GLOBAL) { |
3371 | /* | | 3359 | /* |
3372 | * If substituting a local variable in a non-local context, | | 3360 | * If substituting a local variable in a non-local context, |
3373 | * assume it's for dynamic source stuff. We have to handle | | 3361 | * assume it's for dynamic source stuff. We have to handle |
3374 | * this specially and return the longhand for the variable | | 3362 | * this specially and return the longhand for the variable |
| @@ -3577,27 +3565,30 @@ ParseVarnameLong( | | | @@ -3577,27 +3565,30 @@ ParseVarnameLong( |
3577 | char name[] = { varname[0], '\0' }; | | 3565 | char name[] = { varname[0], '\0' }; |
3578 | v = VarFind(name, ctxt, 0); | | 3566 | v = VarFind(name, ctxt, 0); |
3579 | | | 3567 | |
3580 | if (v != NULL) { | | 3568 | if (v != NULL) { |
3581 | if (varname[1] == 'D') { | | 3569 | if (varname[1] == 'D') { |
3582 | *out_TRUE_extraModifiers = "H:"; | | 3570 | *out_TRUE_extraModifiers = "H:"; |
3583 | } else { /* F */ | | 3571 | } else { /* F */ |
3584 | *out_TRUE_extraModifiers = "T:"; | | 3572 | *out_TRUE_extraModifiers = "T:"; |
3585 | } | | 3573 | } |
3586 | } | | 3574 | } |
3587 | } | | 3575 | } |
3588 | | | 3576 | |
3589 | if (v == NULL) { | | 3577 | if (v == NULL) { |
3590 | dynamic = VarIsDynamic(ctxt, varname, namelen); | | 3578 | /* Defer expansion of dynamic variables if they appear in non-local |
| | | 3579 | * context since they are not defined there. */ |
| | | 3580 | dynamic = VarnameIsDynamic(varname, namelen) && |
| | | 3581 | (ctxt == VAR_CMDLINE || ctxt == VAR_GLOBAL); |
3591 | | | 3582 | |
3592 | if (!haveModifier) { | | 3583 | if (!haveModifier) { |
3593 | p++; /* skip endc */ | | 3584 | p++; /* skip endc */ |
3594 | *pp = p; | | 3585 | *pp = p; |
3595 | if (dynamic) { | | 3586 | if (dynamic) { |
3596 | char *pstr = bmake_strsedup(start, p); | | 3587 | char *pstr = bmake_strsedup(start, p); |
3597 | free(varname); | | 3588 | free(varname); |
3598 | *out_FALSE_res = VPR_OK; | | 3589 | *out_FALSE_res = VPR_OK; |
3599 | *out_FALSE_freePtr = pstr; | | 3590 | *out_FALSE_freePtr = pstr; |
3600 | *out_FALSE_val = pstr; | | 3591 | *out_FALSE_val = pstr; |
3601 | return FALSE; | | 3592 | return FALSE; |
3602 | } | | 3593 | } |
3603 | | | 3594 | |
| @@ -3704,27 +3695,27 @@ Var_Parse(const char **pp, GNode *ctxt, | | | @@ -3704,27 +3695,27 @@ Var_Parse(const char **pp, GNode *ctxt, |
3704 | * or braces */ | | 3695 | * or braces */ |
3705 | char endc; /* Ending character if variable in parens | | 3696 | char endc; /* Ending character if variable in parens |
3706 | * or braces */ | | 3697 | * or braces */ |
3707 | Boolean dynamic; /* TRUE if the variable is local and we're | | 3698 | Boolean dynamic; /* TRUE if the variable is local and we're |
3708 | * expanding it in a non-local context. This | | 3699 | * expanding it in a non-local context. This |
3709 | * is done to support dynamic sources. The | | 3700 | * is done to support dynamic sources. The |
3710 | * result is just the expression, unaltered */ | | 3701 | * result is just the expression, unaltered */ |
3711 | const char *extramodifiers; | | 3702 | const char *extramodifiers; |
3712 | Var *v; | | 3703 | Var *v; |
3713 | char *nstr; | | 3704 | char *nstr; |
3714 | char eflags_str[VarEvalFlags_ToStringSize]; | | 3705 | char eflags_str[VarEvalFlags_ToStringSize]; |
3715 | VarExprFlags exprFlags = 0; | | 3706 | VarExprFlags exprFlags = 0; |
3716 | | | 3707 | |
3717 | VAR_DEBUG3("%s: %s with %s\n", __func__, start, | | 3708 | VAR_DEBUG2("Var_Parse: %s with %s\n", start, |
3718 | Enum_FlagsToString(eflags_str, sizeof eflags_str, eflags, | | 3709 | Enum_FlagsToString(eflags_str, sizeof eflags_str, eflags, |
3719 | VarEvalFlags_ToStringSpecs)); | | 3710 | VarEvalFlags_ToStringSpecs)); |
3720 | | | 3711 | |
3721 | *out_val_freeIt = NULL; | | 3712 | *out_val_freeIt = NULL; |
3722 | extramodifiers = NULL; /* extra modifiers to apply first */ | | 3713 | extramodifiers = NULL; /* extra modifiers to apply first */ |
3723 | dynamic = FALSE; | | 3714 | dynamic = FALSE; |
3724 | | | 3715 | |
3725 | /* Appease GCC, which thinks that the variable might not be | | 3716 | /* Appease GCC, which thinks that the variable might not be |
3726 | * initialized. */ | | 3717 | * initialized. */ |
3727 | endc = '\0'; | | 3718 | endc = '\0'; |
3728 | | | 3719 | |
3729 | startc = start[1]; | | 3720 | startc = start[1]; |
3730 | if (startc != '(' && startc != '{') { | | 3721 | if (startc != '(' && startc != '{') { |