| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: var.c,v 1.334 2020/07/26 22:19:11 rillig Exp $ */ | | 1 | /* $NetBSD: var.c,v 1.335 2020/07/26 22:43:16 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.334 2020/07/26 22:19:11 rillig Exp $"; | | 72 | static char rcsid[] = "$NetBSD: var.c,v 1.335 2020/07/26 22:43:16 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.334 2020/07/26 22:19:11 rillig Exp $"); | | 79 | __RCSID("$NetBSD: var.c,v 1.335 2020/07/26 22:43:16 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 | * |
| @@ -3348,26 +3348,65 @@ bad_modifier: | | | @@ -3348,26 +3348,65 @@ bad_modifier: |
3348 | Error("Bad modifier `:%.*s' for %s", | | 3348 | Error("Bad modifier `:%.*s' for %s", |
3349 | (int)strcspn(p, ":)}"), p, st.v->name); | | 3349 | (int)strcspn(p, ":)}"), p, st.v->name); |
3350 | | | 3350 | |
3351 | cleanup: | | 3351 | cleanup: |
3352 | *st.lengthPtr = st.cp - st.start; | | 3352 | *st.lengthPtr = st.cp - st.start; |
3353 | if (st.missing_delim != '\0') | | 3353 | if (st.missing_delim != '\0') |
3354 | Error("Unclosed substitution for %s (%c missing)", | | 3354 | Error("Unclosed substitution for %s (%c missing)", |
3355 | st.v->name, st.missing_delim); | | 3355 | st.v->name, st.missing_delim); |
3356 | free(*st.freePtr); | | 3356 | free(*st.freePtr); |
3357 | *st.freePtr = NULL; | | 3357 | *st.freePtr = NULL; |
3358 | return var_Error; | | 3358 | return var_Error; |
3359 | } | | 3359 | } |
3360 | | | 3360 | |
| | | 3361 | static Boolean |
| | | 3362 | VarIsDynamic(GNode *ctxt, const char *varname, size_t namelen) |
| | | 3363 | { |
| | | 3364 | if ((namelen == 1 || |
| | | 3365 | (namelen == 2 && (varname[1] == 'F' || varname[1] == 'D'))) && |
| | | 3366 | (ctxt == VAR_CMD || ctxt == VAR_GLOBAL)) |
| | | 3367 | { |
| | | 3368 | /* |
| | | 3369 | * If substituting a local variable in a non-local context, |
| | | 3370 | * assume it's for dynamic source stuff. We have to handle |
| | | 3371 | * this specially and return the longhand for the variable |
| | | 3372 | * with the dollar sign escaped so it makes it back to the |
| | | 3373 | * caller. Only four of the local variables are treated |
| | | 3374 | * specially as they are the only four that will be set |
| | | 3375 | * when dynamic sources are expanded. |
| | | 3376 | */ |
| | | 3377 | switch (varname[0]) { |
| | | 3378 | case '@': |
| | | 3379 | case '%': |
| | | 3380 | case '*': |
| | | 3381 | case '!': |
| | | 3382 | return TRUE; |
| | | 3383 | } |
| | | 3384 | return FALSE; |
| | | 3385 | } |
| | | 3386 | |
| | | 3387 | if (namelen > 2 && varname[0] == '.' && |
| | | 3388 | isupper((unsigned char) varname[1]) && |
| | | 3389 | (ctxt == VAR_CMD || ctxt == VAR_GLOBAL)) |
| | | 3390 | { |
| | | 3391 | return strcmp(varname, ".TARGET") == 0 || |
| | | 3392 | strcmp(varname, ".ARCHIVE") == 0 || |
| | | 3393 | strcmp(varname, ".PREFIX") == 0 || |
| | | 3394 | strcmp(varname, ".MEMBER") == 0; |
| | | 3395 | } |
| | | 3396 | |
| | | 3397 | return FALSE; |
| | | 3398 | } |
| | | 3399 | |
3361 | /*- | | 3400 | /*- |
3362 | *----------------------------------------------------------------------- | | 3401 | *----------------------------------------------------------------------- |
3363 | * Var_Parse -- | | 3402 | * Var_Parse -- |
3364 | * Given the start of a variable invocation (such as $v, $(VAR), | | 3403 | * Given the start of a variable invocation (such as $v, $(VAR), |
3365 | * ${VAR:Mpattern}), extract the variable name, possibly some | | 3404 | * ${VAR:Mpattern}), extract the variable name, possibly some |
3366 | * modifiers and find its value by applying the modifiers to the | | 3405 | * modifiers and find its value by applying the modifiers to the |
3367 | * original value. | | 3406 | * original value. |
3368 | * | | 3407 | * |
3369 | * Input: | | 3408 | * Input: |
3370 | * str The string to parse | | 3409 | * str The string to parse |
3371 | * ctxt The context for the variable | | 3410 | * ctxt The context for the variable |
3372 | * flags VARE_UNDEFERR if undefineds are an error | | 3411 | * flags VARE_UNDEFERR if undefineds are an error |
3373 | * VARE_WANTRES if we actually want the result | | 3412 | * VARE_WANTRES if we actually want the result |
| @@ -3532,59 +3571,27 @@ Var_Parse(const char * const str, GNode | | | @@ -3532,59 +3571,27 @@ Var_Parse(const char * const str, GNode |
3532 | char name[] = {varname[0], '\0' }; | | 3571 | char name[] = {varname[0], '\0' }; |
3533 | v = VarFind(name, ctxt, 0); | | 3572 | v = VarFind(name, ctxt, 0); |
3534 | | | 3573 | |
3535 | if (v != NULL) { | | 3574 | if (v != NULL) { |
3536 | if (varname[1] == 'D') { | | 3575 | if (varname[1] == 'D') { |
3537 | extramodifiers = "H:"; | | 3576 | extramodifiers = "H:"; |
3538 | } else { /* F */ | | 3577 | } else { /* F */ |
3539 | extramodifiers = "T:"; | | 3578 | extramodifiers = "T:"; |
3540 | } | | 3579 | } |
3541 | } | | 3580 | } |
3542 | } | | 3581 | } |
3543 | | | 3582 | |
3544 | if (v == NULL) { | | 3583 | if (v == NULL) { |
3545 | if ((namelen == 1 || | | 3584 | dynamic = VarIsDynamic(ctxt, varname, namelen); |
3546 | (namelen == 2 && (varname[1] == 'F' || varname[1] == 'D'))) && | | | |
3547 | (ctxt == VAR_CMD || ctxt == VAR_GLOBAL)) | | | |
3548 | { | | | |
3549 | /* | | | |
3550 | * If substituting a local variable in a non-local context, | | | |
3551 | * assume it's for dynamic source stuff. We have to handle | | | |
3552 | * this specially and return the longhand for the variable | | | |
3553 | * with the dollar sign escaped so it makes it back to the | | | |
3554 | * caller. Only four of the local variables are treated | | | |
3555 | * specially as they are the only four that will be set | | | |
3556 | * when dynamic sources are expanded. | | | |
3557 | */ | | | |
3558 | switch (varname[0]) { | | | |
3559 | case '@': | | | |
3560 | case '%': | | | |
3561 | case '*': | | | |
3562 | case '!': | | | |
3563 | dynamic = TRUE; | | | |
3564 | break; | | | |
3565 | } | | | |
3566 | } else if (namelen > 2 && varname[0] == '.' && | | | |
3567 | isupper((unsigned char) varname[1]) && | | | |
3568 | (ctxt == VAR_CMD || ctxt == VAR_GLOBAL)) | | | |
3569 | { | | | |
3570 | if ((strcmp(varname, ".TARGET") == 0) || | | | |
3571 | (strcmp(varname, ".ARCHIVE") == 0) || | | | |
3572 | (strcmp(varname, ".PREFIX") == 0) || | | | |
3573 | (strcmp(varname, ".MEMBER") == 0)) | | | |
3574 | { | | | |
3575 | dynamic = TRUE; | | | |
3576 | } | | | |
3577 | } | | | |
3578 | | | 3585 | |
3579 | if (!haveModifier) { | | 3586 | if (!haveModifier) { |
3580 | /* | | 3587 | /* |
3581 | * No modifiers -- have specification length so we can return | | 3588 | * No modifiers -- have specification length so we can return |
3582 | * now. | | 3589 | * now. |
3583 | */ | | 3590 | */ |
3584 | *lengthPtr = tstr - str + 1; | | 3591 | *lengthPtr = tstr - str + 1; |
3585 | if (dynamic) { | | 3592 | if (dynamic) { |
3586 | char *pstr = bmake_strndup(str, *lengthPtr); | | 3593 | char *pstr = bmake_strndup(str, *lengthPtr); |
3587 | *freePtr = pstr; | | 3594 | *freePtr = pstr; |
3588 | Buf_Destroy(&namebuf, TRUE); | | 3595 | Buf_Destroy(&namebuf, TRUE); |
3589 | return pstr; | | 3596 | return pstr; |
3590 | } else { | | 3597 | } else { |