Sun Jul 26 19:11:06 2020 UTC ()
make(1): split local variable into two

Reusing a const char * parameter to store a char * and later free that
string was not a good idea. It made the pretty long code of Var_Parse
more difficult to understand.


(rillig)
diff -r1.324 -r1.325 src/usr.bin/make/var.c

cvs diff -r1.324 -r1.325 src/usr.bin/make/var.c (expand / switch to unified diff)

--- src/usr.bin/make/var.c 2020/07/26 18:47:02 1.324
+++ src/usr.bin/make/var.c 2020/07/26 19:11:06 1.325
@@ -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
72static char rcsid[] = "$NetBSD: var.c,v 1.324 2020/07/26 18:47:02 rillig Exp $"; 72static 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
77static char sccsid[] = "@(#)var.c 8.3 (Berkeley) 3/19/94"; 77static 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 }