Wed Nov 4 02:26:21 2020 UTC ()
make(1): replace emptyString with allocated empty string

Special-casing this variable only made the code more complicated.
Furthermore, it is not related to error handling in any way and
therefore distracted the reader from this topic.


(rillig)
diff -r1.652 -r1.653 src/usr.bin/make/var.c

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

--- src/usr.bin/make/var.c 2020/11/02 21:34:40 1.652
+++ src/usr.bin/make/var.c 2020/11/04 02:26:21 1.653
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: var.c,v 1.652 2020/11/02 21:34:40 rillig Exp $ */ 1/* $NetBSD: var.c,v 1.653 2020/11/04 02:26:21 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.
@@ -120,58 +120,53 @@ @@ -120,58 +120,53 @@
120#include <regex.h> 120#include <regex.h>
121#endif 121#endif
122#include <errno.h> 122#include <errno.h>
123#include <inttypes.h> 123#include <inttypes.h>
124#include <limits.h> 124#include <limits.h>
125#include <time.h> 125#include <time.h>
126 126
127#include "make.h" 127#include "make.h"
128#include "dir.h" 128#include "dir.h"
129#include "job.h" 129#include "job.h"
130#include "metachar.h" 130#include "metachar.h"
131 131
132/* "@(#)var.c 8.3 (Berkeley) 3/19/94" */ 132/* "@(#)var.c 8.3 (Berkeley) 3/19/94" */
133MAKE_RCSID("$NetBSD: var.c,v 1.652 2020/11/02 21:34:40 rillig Exp $"); 133MAKE_RCSID("$NetBSD: var.c,v 1.653 2020/11/04 02:26:21 rillig Exp $");
134 134
135#define VAR_DEBUG1(fmt, arg1) DEBUG1(VAR, fmt, arg1) 135#define VAR_DEBUG1(fmt, arg1) DEBUG1(VAR, fmt, arg1)
136#define VAR_DEBUG2(fmt, arg1, arg2) DEBUG2(VAR, fmt, arg1, arg2) 136#define VAR_DEBUG2(fmt, arg1, arg2) DEBUG2(VAR, fmt, arg1, arg2)
137#define VAR_DEBUG3(fmt, arg1, arg2, arg3) DEBUG3(VAR, fmt, arg1, arg2, arg3) 137#define VAR_DEBUG3(fmt, arg1, arg2, arg3) DEBUG3(VAR, fmt, arg1, arg2, arg3)
138#define VAR_DEBUG4(fmt, arg1, arg2, arg3, arg4) DEBUG4(VAR, fmt, arg1, arg2, arg3, arg4) 138#define VAR_DEBUG4(fmt, arg1, arg2, arg3, arg4) DEBUG4(VAR, fmt, arg1, arg2, arg3, arg4)
139 139
140ENUM_FLAGS_RTTI_3(VarEvalFlags, 140ENUM_FLAGS_RTTI_3(VarEvalFlags,
141 VARE_UNDEFERR, VARE_WANTRES, VARE_ASSIGN); 141 VARE_UNDEFERR, VARE_WANTRES, VARE_ASSIGN);
142 142
143/* 143/*
144 * This lets us tell if we have replaced the original environ 144 * This lets us tell if we have replaced the original environ
145 * (which we cannot free). 145 * (which we cannot free).
146 */ 146 */
147char **savedEnv = NULL; 147char **savedEnv = NULL;
148 148
149/* Special return value for Var_Parse, indicating a parse error. It may be 149/* Special return value for Var_Parse, indicating a parse error. It may be
150 * caused by an undefined variable, a syntax error in a modifier or 150 * caused by an undefined variable, a syntax error in a modifier or
151 * something entirely different. */ 151 * something entirely different. */
152char var_Error[] = ""; 152char var_Error[] = "";
153 153
154/* Special return value for Var_Parse, indicating an undefined variable in 154/* Special return value for Var_Parse, indicating an undefined variable in
155 * a case where VARE_UNDEFERR is not set. This undefined variable is 155 * a case where VARE_UNDEFERR is not set. This undefined variable is
156 * typically a dynamic variable such as ${.TARGET}, whose expansion needs to 156 * typically a dynamic variable such as ${.TARGET}, whose expansion needs to
157 * be deferred until it is defined in an actual target. */ 157 * be deferred until it is defined in an actual target. */
158static char varUndefined[] = ""; 158static char varUndefined[] = "";
159 159
160/* Special return value for Var_Parse, just to avoid allocating empty strings. 
161 * In contrast to var_Error and varUndefined, this is not an error marker but 
162 * just an ordinary successful return value. */ 
163static char emptyString[] = ""; 
164 
165/* 160/*
166 * Traditionally this make consumed $$ during := like any other expansion. 161 * Traditionally this make consumed $$ during := like any other expansion.
167 * Other make's do not, and this make follows straight since 2016-01-09. 162 * Other make's do not, and this make follows straight since 2016-01-09.
168 * 163 *
169 * This knob allows controlling the behavior. 164 * This knob allows controlling the behavior.
170 * FALSE to consume $$ during := assignment. 165 * FALSE to consume $$ during := assignment.
171 * TRUE to preserve $$ during := assignment. 166 * TRUE to preserve $$ during := assignment.
172 */ 167 */
173#define MAKE_SAVE_DOLLARS ".MAKE.SAVE_DOLLARS" 168#define MAKE_SAVE_DOLLARS ".MAKE.SAVE_DOLLARS"
174static Boolean save_dollars = TRUE; 169static Boolean save_dollars = TRUE;
175 170
176/* 171/*
177 * Internally, variables are contained in four different contexts. 172 * Internally, variables are contained in four different contexts.
@@ -2289,27 +2284,27 @@ ApplyModifier_ShellCommand(const char ** @@ -2289,27 +2284,27 @@ ApplyModifier_ShellCommand(const char **
2289 const char *errfmt; 2284 const char *errfmt;
2290 VarParseResult res; 2285 VarParseResult res;
2291 2286
2292 (*pp)++; 2287 (*pp)++;
2293 res = ParseModifierPart(pp, '!', st->eflags, st, 2288 res = ParseModifierPart(pp, '!', st->eflags, st,
2294 &cmd, NULL, NULL, NULL); 2289 &cmd, NULL, NULL, NULL);
2295 if (res != VPR_OK) 2290 if (res != VPR_OK)
2296 return AMR_CLEANUP; 2291 return AMR_CLEANUP;
2297 2292
2298 errfmt = NULL; 2293 errfmt = NULL;
2299 if (st->eflags & VARE_WANTRES) 2294 if (st->eflags & VARE_WANTRES)
2300 st->newVal = Cmd_Exec(cmd, &errfmt); 2295 st->newVal = Cmd_Exec(cmd, &errfmt);
2301 else 2296 else
2302 st->newVal = emptyString; 2297 st->newVal = bmake_strdup("");
2303 free(cmd); 2298 free(cmd);
2304 2299
2305 if (errfmt != NULL) 2300 if (errfmt != NULL)
2306 Error(errfmt, st->val); /* XXX: why still return AMR_OK? */ 2301 Error(errfmt, st->val); /* XXX: why still return AMR_OK? */
2307 2302
2308 ApplyModifiersState_Define(st); 2303 ApplyModifiersState_Define(st);
2309 return AMR_OK; 2304 return AMR_OK;
2310} 2305}
2311 2306
2312/* The :range modifier generates an integer sequence as long as the words. 2307/* The :range modifier generates an integer sequence as long as the words.
2313 * The :range=7 modifier generates an integer sequence from 1 to 7. */ 2308 * The :range=7 modifier generates an integer sequence from 1 to 7. */
2314static ApplyModifierResult 2309static ApplyModifierResult
2315ApplyModifier_Range(const char **pp, ApplyModifiersState *st) 2310ApplyModifier_Range(const char **pp, ApplyModifiersState *st)
@@ -3004,27 +2999,27 @@ ok: @@ -3004,27 +2999,27 @@ ok:
3004 free(cmd_output); 2999 free(cmd_output);
3005 break; 3000 break;
3006 } 3001 }
3007 case '?': 3002 case '?':
3008 if (!(st->exprFlags & VEF_UNDEF)) 3003 if (!(st->exprFlags & VEF_UNDEF))
3009 break; 3004 break;
3010 /* FALLTHROUGH */ 3005 /* FALLTHROUGH */
3011 default: 3006 default:
3012 Var_Set(st->v->name, val, v_ctxt); 3007 Var_Set(st->v->name, val, v_ctxt);
3013 break; 3008 break;
3014 } 3009 }
3015 } 3010 }
3016 free(val); 3011 free(val);
3017 st->newVal = emptyString; 3012 st->newVal = bmake_strdup("");
3018 return AMR_OK; 3013 return AMR_OK;
3019} 3014}
3020 3015
3021/* :_=... 3016/* :_=...
3022 * remember current value */ 3017 * remember current value */
3023static ApplyModifierResult 3018static ApplyModifierResult
3024ApplyModifier_Remember(const char **pp, ApplyModifiersState *st) 3019ApplyModifier_Remember(const char **pp, ApplyModifiersState *st)
3025{ 3020{
3026 const char *mod = *pp; 3021 const char *mod = *pp;
3027 if (!ModMatchEq(mod, "_", st->endc)) 3022 if (!ModMatchEq(mod, "_", st->endc))
3028 return AMR_UNKNOWN; 3023 return AMR_UNKNOWN;
3029 3024
3030 if (mod[1] == '=') { 3025 if (mod[1] == '=') {
@@ -3128,27 +3123,27 @@ ApplyModifier_SysV(const char **pp, Appl @@ -3128,27 +3123,27 @@ ApplyModifier_SysV(const char **pp, Appl
3128#ifdef SUNSHCMD 3123#ifdef SUNSHCMD
3129/* :sh */ 3124/* :sh */
3130static ApplyModifierResult 3125static ApplyModifierResult
3131ApplyModifier_SunShell(const char **pp, ApplyModifiersState *st) 3126ApplyModifier_SunShell(const char **pp, ApplyModifiersState *st)
3132{ 3127{
3133 const char *p = *pp; 3128 const char *p = *pp;
3134 if (p[1] == 'h' && (p[2] == st->endc || p[2] == ':')) { 3129 if (p[1] == 'h' && (p[2] == st->endc || p[2] == ':')) {
3135 if (st->eflags & VARE_WANTRES) { 3130 if (st->eflags & VARE_WANTRES) {
3136 const char *errfmt; 3131 const char *errfmt;
3137 st->newVal = Cmd_Exec(st->val, &errfmt); 3132 st->newVal = Cmd_Exec(st->val, &errfmt);
3138 if (errfmt) 3133 if (errfmt)
3139 Error(errfmt, st->val); 3134 Error(errfmt, st->val);
3140 } else 3135 } else
3141 st->newVal = emptyString; 3136 st->newVal = bmake_strdup("");
3142 *pp = p + 2; 3137 *pp = p + 2;
3143 return AMR_OK; 3138 return AMR_OK;
3144 } else 3139 } else
3145 return AMR_UNKNOWN; 3140 return AMR_UNKNOWN;
3146} 3141}
3147#endif 3142#endif
3148 3143
3149static void 3144static void
3150LogBeforeApply(const ApplyModifiersState *st, const char *mod, const char endc) 3145LogBeforeApply(const ApplyModifiersState *st, const char *mod, const char endc)
3151{ 3146{
3152 char eflags_str[VarEvalFlags_ToStringSize]; 3147 char eflags_str[VarEvalFlags_ToStringSize];
3153 char vflags_str[VarFlags_ToStringSize]; 3148 char vflags_str[VarFlags_ToStringSize];
3154 char exprflags_str[VarExprFlags_ToStringSize]; 3149 char exprflags_str[VarExprFlags_ToStringSize];
@@ -3402,30 +3397,28 @@ ApplyModifiers( @@ -3402,30 +3397,28 @@ ApplyModifiers(
3402 goto cleanup; 3397 goto cleanup;
3403 if (res == AMR_BAD) 3398 if (res == AMR_BAD)
3404 goto bad_modifier; 3399 goto bad_modifier;
3405 3400
3406 if (DEBUG(VAR)) 3401 if (DEBUG(VAR))
3407 LogAfterApply(&st, p, mod); 3402 LogAfterApply(&st, p, mod);
3408 3403
3409 if (st.newVal != st.val) { 3404 if (st.newVal != st.val) {
3410 if (*out_freeIt) { 3405 if (*out_freeIt) {
3411 free(st.val); 3406 free(st.val);
3412 *out_freeIt = NULL; 3407 *out_freeIt = NULL;
3413 } 3408 }
3414 st.val = st.newVal; 3409 st.val = st.newVal;
3415 if (st.val != var_Error && st.val != varUndefined && 3410 if (st.val != var_Error && st.val != varUndefined)
3416 st.val != emptyString) { 
3417 *out_freeIt = st.val; 3411 *out_freeIt = st.val;
3418 } 
3419 } 3412 }
3420 if (*p == '\0' && st.endc != '\0') { 3413 if (*p == '\0' && st.endc != '\0') {
3421 Error("Unclosed variable specification (expecting '%c') " 3414 Error("Unclosed variable specification (expecting '%c') "
3422 "for \"%s\" (value \"%s\") modifier %c", 3415 "for \"%s\" (value \"%s\") modifier %c",
3423 st.endc, st.v->name, st.val, *mod); 3416 st.endc, st.v->name, st.val, *mod);
3424 } else if (*p == ':') { 3417 } else if (*p == ':') {
3425 p++; 3418 p++;
3426 } else if (DEBUG(LINT) && *p != '\0' && *p != endc) { 3419 } else if (DEBUG(LINT) && *p != '\0' && *p != endc) {
3427 Parse_Error(PARSE_FATAL, 3420 Parse_Error(PARSE_FATAL,
3428 "Missing delimiter ':' after modifier \"%.*s\"", 3421 "Missing delimiter ':' after modifier \"%.*s\"",
3429 (int)(p - mod), mod); 3422 (int)(p - mod), mod);
3430 /* TODO: propagate parse error to the enclosing expression */ 3423 /* TODO: propagate parse error to the enclosing expression */
3431 } 3424 }