| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: var.c,v 1.324 2020/07/26 18:47:02 rillig Exp $ */ | | 1 | /* $NetBSD: var.c,v 1.325 2020/07/26 19:11:06 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.324 2020/07/26 18:47:02 rillig Exp $"; | | 72 | static char rcsid[] = "$NetBSD: var.c,v 1.325 2020/07/26 19:11:06 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.324 2020/07/26 18:47:02 rillig Exp $"); | | 79 | __RCSID("$NetBSD: var.c,v 1.325 2020/07/26 19:11:06 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 | * |
| @@ -3442,27 +3442,27 @@ Var_Parse(const char *str, GNode *ctxt, | | | @@ -3442,27 +3442,27 @@ Var_Parse(const char *str, GNode *ctxt, |
3442 | case '@': | | 3442 | case '@': |
3443 | return UNCONST("$(.TARGET)"); | | 3443 | return UNCONST("$(.TARGET)"); |
3444 | case '%': | | 3444 | case '%': |
3445 | return UNCONST("$(.MEMBER)"); | | 3445 | return UNCONST("$(.MEMBER)"); |
3446 | case '*': | | 3446 | case '*': |
3447 | return UNCONST("$(.PREFIX)"); | | 3447 | return UNCONST("$(.PREFIX)"); |
3448 | case '!': | | 3448 | case '!': |
3449 | return UNCONST("$(.ARCHIVE)"); | | 3449 | return UNCONST("$(.ARCHIVE)"); |
3450 | } | | 3450 | } |
3451 | } | | 3451 | } |
3452 | return (flags & VARE_UNDEFERR) ? var_Error : varNoError; | | 3452 | return (flags & VARE_UNDEFERR) ? var_Error : varNoError; |
3453 | } else { | | 3453 | } else { |
3454 | haveModifier = FALSE; | | 3454 | haveModifier = FALSE; |
3455 | tstr = &str[1]; | | 3455 | tstr = str + 1; |
3456 | endc = str[1]; | | 3456 | endc = str[1]; |
3457 | } | | 3457 | } |
3458 | } else { | | 3458 | } else { |
3459 | Buffer buf; /* Holds the variable name */ | | 3459 | Buffer buf; /* Holds the variable name */ |
3460 | int depth = 1; | | 3460 | int depth = 1; |
3461 | | | 3461 | |
3462 | endc = startc == PROPEN ? PRCLOSE : BRCLOSE; | | 3462 | endc = startc == PROPEN ? PRCLOSE : BRCLOSE; |
3463 | Buf_Init(&buf, 0); | | 3463 | Buf_Init(&buf, 0); |
3464 | | | 3464 | |
3465 | /* | | 3465 | /* |
3466 | * Skip to the end character or a colon, whichever comes first. | | 3466 | * Skip to the end character or a colon, whichever comes first. |
3467 | */ | | 3467 | */ |
3468 | for (tstr = str + 2; *tstr != '\0'; tstr++) { | | 3468 | for (tstr = str + 2; *tstr != '\0'; tstr++) { |
| @@ -3491,121 +3491,122 @@ Var_Parse(const char *str, GNode *ctxt, | | | @@ -3491,121 +3491,122 @@ Var_Parse(const char *str, GNode *ctxt, |
3491 | haveModifier = TRUE; | | 3491 | haveModifier = TRUE; |
3492 | } else if (*tstr == endc) { | | 3492 | } else if (*tstr == endc) { |
3493 | haveModifier = FALSE; | | 3493 | haveModifier = FALSE; |
3494 | } else { | | 3494 | } else { |
3495 | /* | | 3495 | /* |
3496 | * If we never did find the end character, return NULL | | 3496 | * If we never did find the end character, return NULL |
3497 | * right now, setting the length to be the distance to | | 3497 | * right now, setting the length to be the distance to |
3498 | * the end of the string, since that's what make does. | | 3498 | * the end of the string, since that's what make does. |
3499 | */ | | 3499 | */ |
3500 | *lengthPtr = tstr - str; | | 3500 | *lengthPtr = tstr - str; |
3501 | Buf_Destroy(&buf, TRUE); | | 3501 | Buf_Destroy(&buf, TRUE); |
3502 | return var_Error; | | 3502 | return var_Error; |
3503 | } | | 3503 | } |
3504 | str = Buf_GetAll(&buf, &vlen); | | 3504 | |
| | | 3505 | char *varname = Buf_GetAll(&buf, &vlen); |
3505 | | | 3506 | |
3506 | /* | | 3507 | /* |
3507 | * At this point, str points into newly allocated memory from | | 3508 | * At this point, varname points into newly allocated memory from |
3508 | * buf, containing only the name of the variable. | | 3509 | * buf, containing only the name of the variable. |
3509 | * | | 3510 | * |
3510 | * start and tstr point into the const string that was pointed | | 3511 | * start and tstr point into the const string that was pointed |
3511 | * to by the original value of the str parameter. start points | | 3512 | * to by the original value of the str parameter. start points |
3512 | * to the '$' at the beginning of the string, while tstr points | | 3513 | * to the '$' at the beginning of the string, while tstr points |
3513 | * to the char just after the end of the variable name -- this | | 3514 | * to the char just after the end of the variable name -- this |
3514 | * will be '\0', ':', PRCLOSE, or BRCLOSE. | | 3515 | * will be '\0', ':', PRCLOSE, or BRCLOSE. |
3515 | */ | | 3516 | */ |
3516 | | | 3517 | |
3517 | v = VarFind(str, ctxt, FIND_ENV | FIND_GLOBAL | FIND_CMD); | | 3518 | v = VarFind(varname, ctxt, FIND_ENV | FIND_GLOBAL | FIND_CMD); |
3518 | /* | | 3519 | /* |
3519 | * Check also for bogus D and F forms of local variables since we're | | 3520 | * Check also for bogus D and F forms of local variables since we're |
3520 | * in a local context and the name is the right length. | | 3521 | * in a local context and the name is the right length. |
3521 | */ | | 3522 | */ |
3522 | if ((v == NULL) && (ctxt != VAR_CMD) && (ctxt != VAR_GLOBAL) && | | 3523 | if (v == NULL && ctxt != VAR_CMD && ctxt != VAR_GLOBAL && |
3523 | (vlen == 2) && (str[1] == 'F' || str[1] == 'D') && | | 3524 | vlen == 2 && (varname[1] == 'F' || varname[1] == 'D') && |
3524 | strchr("@%?*!<>", str[0]) != NULL) { | | 3525 | strchr("@%?*!<>", varname[0]) != NULL) { |
3525 | /* | | 3526 | /* |
3526 | * Well, it's local -- go look for it. | | 3527 | * Well, it's local -- go look for it. |
3527 | */ | | 3528 | */ |
3528 | name[0] = *str; | | 3529 | name[0] = varname[0]; |
3529 | name[1] = '\0'; | | 3530 | name[1] = '\0'; |
3530 | v = VarFind(name, ctxt, 0); | | 3531 | v = VarFind(name, ctxt, 0); |
3531 | | | 3532 | |
3532 | if (v != NULL) { | | 3533 | if (v != NULL) { |
3533 | if (str[1] == 'D') { | | 3534 | if (varname[1] == 'D') { |
3534 | extramodifiers = "H:"; | | 3535 | extramodifiers = "H:"; |
3535 | } else { /* F */ | | 3536 | } else { /* F */ |
3536 | extramodifiers = "T:"; | | 3537 | extramodifiers = "T:"; |
3537 | } | | 3538 | } |
3538 | } | | 3539 | } |
3539 | } | | 3540 | } |
3540 | | | 3541 | |
3541 | if (v == NULL) { | | 3542 | if (v == NULL) { |
3542 | if (((vlen == 1) || | | 3543 | if ((vlen == 1 || |
3543 | (((vlen == 2) && (str[1] == 'F' || str[1] == 'D')))) && | | 3544 | ((vlen == 2 && (varname[1] == 'F' || varname[1] == 'D')))) && |
3544 | ((ctxt == VAR_CMD) || (ctxt == VAR_GLOBAL))) | | 3545 | (ctxt == VAR_CMD || ctxt == VAR_GLOBAL)) |
3545 | { | | 3546 | { |
3546 | /* | | 3547 | /* |
3547 | * If substituting a local variable in a non-local context, | | 3548 | * If substituting a local variable in a non-local context, |
3548 | * assume it's for dynamic source stuff. We have to handle | | 3549 | * assume it's for dynamic source stuff. We have to handle |
3549 | * this specially and return the longhand for the variable | | 3550 | * this specially and return the longhand for the variable |
3550 | * with the dollar sign escaped so it makes it back to the | | 3551 | * with the dollar sign escaped so it makes it back to the |
3551 | * caller. Only four of the local variables are treated | | 3552 | * caller. Only four of the local variables are treated |
3552 | * specially as they are the only four that will be set | | 3553 | * specially as they are the only four that will be set |
3553 | * when dynamic sources are expanded. | | 3554 | * when dynamic sources are expanded. |
3554 | */ | | 3555 | */ |
3555 | switch (*str) { | | 3556 | switch (varname[0]) { |
3556 | case '@': | | 3557 | case '@': |
3557 | case '%': | | 3558 | case '%': |
3558 | case '*': | | 3559 | case '*': |
3559 | case '!': | | 3560 | case '!': |
3560 | dynamic = TRUE; | | 3561 | dynamic = TRUE; |
3561 | break; | | 3562 | break; |
3562 | } | | 3563 | } |
3563 | } else if (vlen > 2 && *str == '.' && | | 3564 | } else if (vlen > 2 && varname[0] == '.' && |
3564 | isupper((unsigned char) str[1]) && | | 3565 | isupper((unsigned char) varname[1]) && |
3565 | (ctxt == VAR_CMD || ctxt == VAR_GLOBAL)) | | 3566 | (ctxt == VAR_CMD || ctxt == VAR_GLOBAL)) |
3566 | { | | 3567 | { |
3567 | int len = vlen - 1; | | 3568 | int len = vlen - 1; |
3568 | if ((strncmp(str, ".TARGET", len) == 0) || | | 3569 | if ((strncmp(varname, ".TARGET", len) == 0) || |
3569 | (strncmp(str, ".ARCHIVE", len) == 0) || | | 3570 | (strncmp(varname, ".ARCHIVE", len) == 0) || |
3570 | (strncmp(str, ".PREFIX", len) == 0) || | | 3571 | (strncmp(varname, ".PREFIX", len) == 0) || |
3571 | (strncmp(str, ".MEMBER", len) == 0)) | | 3572 | (strncmp(varname, ".MEMBER", len) == 0)) |
3572 | { | | 3573 | { |
3573 | dynamic = TRUE; | | 3574 | dynamic = TRUE; |
3574 | } | | 3575 | } |
3575 | } | | 3576 | } |
3576 | | | 3577 | |
3577 | if (!haveModifier) { | | 3578 | if (!haveModifier) { |
3578 | /* | | 3579 | /* |
3579 | * No modifiers -- have specification length so we can return | | 3580 | * No modifiers -- have specification length so we can return |
3580 | * now. | | 3581 | * now. |
3581 | */ | | 3582 | */ |
3582 | *lengthPtr = tstr - start + 1; | | 3583 | *lengthPtr = tstr - start + 1; |
3583 | if (dynamic) { | | 3584 | if (dynamic) { |
3584 | char *pstr = bmake_strndup(start, *lengthPtr); | | 3585 | char *pstr = bmake_strndup(start, *lengthPtr); |
3585 | *freePtr = pstr; | | 3586 | *freePtr = pstr; |
3586 | Buf_Destroy(&buf, TRUE); | | 3587 | Buf_Destroy(&buf, TRUE); |
3587 | return pstr; | | 3588 | return pstr; |
3588 | } else { | | 3589 | } else { |
3589 | Buf_Destroy(&buf, TRUE); | | 3590 | Buf_Destroy(&buf, TRUE); |
3590 | return (flags & VARE_UNDEFERR) ? var_Error : varNoError; | | 3591 | return (flags & VARE_UNDEFERR) ? var_Error : varNoError; |
3591 | } | | 3592 | } |
3592 | } else { | | 3593 | } else { |
3593 | /* | | 3594 | /* |
3594 | * Still need to get to the end of the variable specification, | | 3595 | * Still need to get to the end of the variable specification, |
3595 | * so kludge up a Var structure for the modifications | | 3596 | * so kludge up a Var structure for the modifications |
3596 | */ | | 3597 | */ |
3597 | v = bmake_malloc(sizeof(Var)); | | 3598 | v = bmake_malloc(sizeof(Var)); |
3598 | v->name = UNCONST(str); | | 3599 | v->name = varname; |
3599 | Buf_Init(&v->val, 1); | | 3600 | Buf_Init(&v->val, 1); |
3600 | v->flags = VAR_JUNK; | | 3601 | v->flags = VAR_JUNK; |
3601 | Buf_Destroy(&buf, FALSE); | | 3602 | Buf_Destroy(&buf, FALSE); |
3602 | } | | 3603 | } |
3603 | } else | | 3604 | } else |
3604 | Buf_Destroy(&buf, TRUE); | | 3605 | Buf_Destroy(&buf, TRUE); |
3605 | } | | 3606 | } |
3606 | | | 3607 | |
3607 | if (v->flags & VAR_IN_USE) { | | 3608 | if (v->flags & VAR_IN_USE) { |
3608 | Fatal("Variable %s is recursive.", v->name); | | 3609 | Fatal("Variable %s is recursive.", v->name); |
3609 | /*NOTREACHED*/ | | 3610 | /*NOTREACHED*/ |
3610 | } else { | | 3611 | } else { |
3611 | v->flags |= VAR_IN_USE; | | 3612 | v->flags |= VAR_IN_USE; |
| @@ -3658,27 +3659,27 @@ Var_Parse(const char *str, GNode *ctxt, | | | @@ -3658,27 +3659,27 @@ Var_Parse(const char *str, GNode *ctxt, |
3658 | destroy = TRUE; | | 3659 | destroy = TRUE; |
3659 | } else { | | 3660 | } else { |
3660 | /* | | 3661 | /* |
3661 | * Returning the value unmodified, so tell the caller to free | | 3662 | * Returning the value unmodified, so tell the caller to free |
3662 | * the thing. | | 3663 | * the thing. |
3663 | */ | | 3664 | */ |
3664 | *freePtr = nstr; | | 3665 | *freePtr = nstr; |
3665 | } | | 3666 | } |
3666 | VarFreeEnv(v, destroy); | | 3667 | VarFreeEnv(v, destroy); |
3667 | } else if (v->flags & VAR_JUNK) { | | 3668 | } else if (v->flags & VAR_JUNK) { |
3668 | /* | | 3669 | /* |
3669 | * Perform any free'ing needed and set *freePtr to NULL so the caller | | 3670 | * Perform any free'ing needed and set *freePtr to NULL so the caller |
3670 | * doesn't try to free a static pointer. | | 3671 | * doesn't try to free a static pointer. |
3671 | * If VAR_KEEP is also set then we want to keep str as is. | | 3672 | * If VAR_KEEP is also set then we want to keep str(?) as is. |
3672 | */ | | 3673 | */ |
3673 | if (!(v->flags & VAR_KEEP)) { | | 3674 | if (!(v->flags & VAR_KEEP)) { |
3674 | if (*freePtr) { | | 3675 | if (*freePtr) { |
3675 | free(nstr); | | 3676 | free(nstr); |
3676 | *freePtr = NULL; | | 3677 | *freePtr = NULL; |
3677 | } | | 3678 | } |
3678 | if (dynamic) { | | 3679 | if (dynamic) { |
3679 | nstr = bmake_strndup(start, *lengthPtr); | | 3680 | nstr = bmake_strndup(start, *lengthPtr); |
3680 | *freePtr = nstr; | | 3681 | *freePtr = nstr; |
3681 | } else { | | 3682 | } else { |
3682 | nstr = (flags & VARE_UNDEFERR) ? var_Error : varNoError; | | 3683 | nstr = (flags & VARE_UNDEFERR) ? var_Error : varNoError; |
3683 | } | | 3684 | } |
3684 | } | | 3685 | } |