Sat Oct 31 15:23:52 2020 UTC ()
make(1): rewrite VarIsDynamic to VarnameIsDynamic

The condition for the context is the same for both short and long names,
therefore move that condition to the only caller.

Clean up the comment and move its parts to the appropriate places.  The
"with the dollar sign escaped" part had been wrong already in 1993, and
it didn't get better over time.


(rillig)
diff -r1.625 -r1.626 src/usr.bin/make/var.c

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

--- src/usr.bin/make/var.c 2020/10/31 14:55:33 1.625
+++ src/usr.bin/make/var.c 2020/10/31 15:23:52 1.626
@@ -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" */
132MAKE_RCSID("$NetBSD: var.c,v 1.625 2020/10/31 14:55:33 rillig Exp $"); 132MAKE_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
139ENUM_FLAGS_RTTI_3(VarEvalFlags, 139ENUM_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
3317bad_modifier: 3317bad_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
3321cleanup: 3321cleanup:
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. */
3329static Boolean 3331static Boolean
3330VarIsDynamic(GNode *ctxt, const char *varname, size_t namelen) 3332VarnameIsDynamic(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
3367static const char * 3355static const char *
3368UndefinedShortVarValue(char varname, const GNode *ctxt, VarEvalFlags eflags) 3356UndefinedShortVarValue(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 != '{') {