Sun Nov 1 23:17:40 2020 UTC ()
make(1): extract ApplyModifiersIndirect from ApplyModifiers


(rillig)
diff -r1.640 -r1.641 src/usr.bin/make/var.c

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

--- src/usr.bin/make/var.c 2020/11/01 22:48:41 1.640
+++ src/usr.bin/make/var.c 2020/11/01 23:17:40 1.641
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: var.c,v 1.640 2020/11/01 22:48:41 rillig Exp $ */ 1/* $NetBSD: var.c,v 1.641 2020/11/01 23:17:40 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,27 +120,27 @@ @@ -120,27 +120,27 @@
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.640 2020/11/01 22:48:41 rillig Exp $"); 133MAKE_RCSID("$NetBSD: var.c,v 1.641 2020/11/01 23:17:40 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 */
@@ -3244,26 +3244,103 @@ ApplyModifier(const char **pp, ApplyModi @@ -3244,26 +3244,103 @@ ApplyModifier(const char **pp, ApplyModi
3244 case 'O': 3244 case 'O':
3245 return ApplyModifier_Order(pp, st); 3245 return ApplyModifier_Order(pp, st);
3246 case 'u': 3246 case 'u':
3247 return ApplyModifier_Unique(pp, st); 3247 return ApplyModifier_Unique(pp, st);
3248#ifdef SUNSHCMD 3248#ifdef SUNSHCMD
3249 case 's': 3249 case 's':
3250 return ApplyModifier_SunShell(pp, st); 3250 return ApplyModifier_SunShell(pp, st);
3251#endif 3251#endif
3252 default: 3252 default:
3253 return AMR_UNKNOWN; 3253 return AMR_UNKNOWN;
3254 } 3254 }
3255} 3255}
3256 3256
 3257static char *ApplyModifiers(const char **, char *, char, char, Var *,
 3258 VarExprFlags *, GNode *, VarEvalFlags, void **);
 3259
 3260typedef enum ApplyModifiersIndirectResult {
 3261 AMIR_CONTINUE,
 3262 AMIR_APPLY_MODS,
 3263 AMIR_OUT
 3264} ApplyModifiersIndirectResult;
 3265
 3266/* While expanding a variable expression, expand and apply indirect
 3267 * modifiers. */
 3268static ApplyModifiersIndirectResult
 3269ApplyModifiersIndirect(
 3270 ApplyModifiersState *const st,
 3271 const char **inout_p,
 3272 void **const out_freeIt
 3273) {
 3274 const char *p = *inout_p;
 3275 const char *nested_p = p;
 3276 void *freeIt;
 3277 const char *rval;
 3278 char c;
 3279
 3280 (void)Var_Parse(&nested_p, st->ctxt, st->eflags, &rval, &freeIt);
 3281 /* TODO: handle errors */
 3282
 3283 /*
 3284 * If we have not parsed up to st->endc or ':', we are not
 3285 * interested. This means the expression ${VAR:${M_1}${M_2}}
 3286 * is not accepted, but ${VAR:${M_1}:${M_2}} is.
 3287 */
 3288 if (rval[0] != '\0' &&
 3289 (c = *nested_p) != '\0' && c != ':' && c != st->endc) {
 3290 if (DEBUG(LINT))
 3291 Parse_Error(PARSE_FATAL,
 3292 "Missing delimiter ':' after indirect modifier \"%.*s\"",
 3293 (int)(nested_p - p), p);
 3294
 3295 free(freeIt);
 3296 /* XXX: apply_mods doesn't sound like "not interested". */
 3297 /* XXX: Why is the indirect modifier parsed again by
 3298 * apply_mods? If any, p should be advanced to nested_p. */
 3299 return AMIR_APPLY_MODS;
 3300 }
 3301
 3302 VAR_DEBUG3("Indirect modifier \"%s\" from \"%.*s\"\n",
 3303 rval, (int)(size_t)(nested_p - p), p);
 3304
 3305 p = nested_p;
 3306
 3307 if (rval[0] != '\0') {
 3308 const char *rval_pp = rval;
 3309 st->val = ApplyModifiers(&rval_pp, st->val, '\0', '\0', st->v,
 3310 &st->exprFlags, st->ctxt, st->eflags, out_freeIt);
 3311 if (st->val == var_Error
 3312 || (st->val == varUndefined && !(st->eflags & VARE_UNDEFERR))
 3313 || *rval_pp != '\0') {
 3314 free(freeIt);
 3315 *inout_p = p;
 3316 return AMIR_OUT; /* error already reported */
 3317 }
 3318 }
 3319 free(freeIt);
 3320
 3321 if (*p == ':')
 3322 p++;
 3323 else if (*p == '\0' && st->endc != '\0') {
 3324 Error("Unclosed variable specification after complex "
 3325 "modifier (expecting '%c') for %s", st->endc, st->v->name);
 3326 *inout_p = p;
 3327 return AMIR_OUT;
 3328 }
 3329
 3330 *inout_p = p;
 3331 return AMIR_CONTINUE;
 3332}
 3333
3257/* Apply any modifiers (such as :Mpattern or :@var@loop@ or :Q or ::=value). */ 3334/* Apply any modifiers (such as :Mpattern or :@var@loop@ or :Q or ::=value). */
3258static char * 3335static char *
3259ApplyModifiers( 3336ApplyModifiers(
3260 const char **pp, /* the parsing position, updated upon return */ 3337 const char **pp, /* the parsing position, updated upon return */
3261 char *const val, /* the current value of the expression */ 3338 char *const val, /* the current value of the expression */
3262 char const startc, /* '(' or '{', or '\0' for indirect modifiers */ 3339 char const startc, /* '(' or '{', or '\0' for indirect modifiers */
3263 char const endc, /* ')' or '}', or '\0' for indirect modifiers */ 3340 char const endc, /* ')' or '}', or '\0' for indirect modifiers */
3264 Var * const v, 3341 Var * const v,
3265 VarExprFlags *exprFlags, 3342 VarExprFlags *exprFlags,
3266 GNode * const ctxt, /* for looking up and modifying variables */ 3343 GNode * const ctxt, /* for looking up and modifying variables */
3267 VarEvalFlags const eflags, 3344 VarEvalFlags const eflags,
3268 void ** const out_freeIt /* free this after using the return value */ 3345 void ** const out_freeIt /* free this after using the return value */
3269) { 3346) {
@@ -3277,84 +3354,33 @@ ApplyModifiers( @@ -3277,84 +3354,33 @@ ApplyModifiers(
3277 }; 3354 };
3278 const char *p; 3355 const char *p;
3279 const char *mod; 3356 const char *mod;
3280 ApplyModifierResult res; 3357 ApplyModifierResult res;
3281 3358
3282 assert(startc == '(' || startc == '{' || startc == '\0'); 3359 assert(startc == '(' || startc == '{' || startc == '\0');
3283 assert(endc == ')' || endc == '}' || endc == '\0'); 3360 assert(endc == ')' || endc == '}' || endc == '\0');
3284 assert(val != NULL); 3361 assert(val != NULL);
3285 3362
3286 p = *pp; 3363 p = *pp;
3287 while (*p != '\0' && *p != endc) { 3364 while (*p != '\0' && *p != endc) {
3288 3365
3289 if (*p == '$') { 3366 if (*p == '$') {
3290 /* 3367 ApplyModifiersIndirectResult amir;
3291 * We may have some complex modifiers in a variable. 3368 amir = ApplyModifiersIndirect(&st, &p, out_freeIt);
3292 */ 3369 if (amir == AMIR_CONTINUE)
3293 const char *nested_p = p; 3370 continue;
3294 void *freeIt; 3371 if (amir == AMIR_OUT)
3295 const char *rval; 3372 goto out;
3296 char c; 
3297 
3298 (void)Var_Parse(&nested_p, st.ctxt, st.eflags, &rval, &freeIt); 
3299 /* TODO: handle errors */ 
3300 
3301 /* 
3302 * If we have not parsed up to st.endc or ':', we are not 
3303 * interested. This means the expression ${VAR:${M_1}${M_2}} 
3304 * is not accepted, but ${VAR:${M_1}:${M_2}} is. 
3305 */ 
3306 if (rval[0] != '\0' && 
3307 (c = *nested_p) != '\0' && c != ':' && c != st.endc) { 
3308 if (DEBUG(LINT)) 
3309 Parse_Error(PARSE_FATAL, 
3310 "Missing delimiter ':' after indirect modifier \"%.*s\"", 
3311 (int)(nested_p - p), p); 
3312 
3313 free(freeIt); 
3314 /* XXX: apply_mods doesn't sound like "not interested". */ 
3315 /* XXX: Why is the indirect modifier parsed again by 
3316 * apply_mods? If any, p should be advanced to nested_p. */ 
3317 goto apply_mods; 
3318 } 
3319 
3320 VAR_DEBUG3("Indirect modifier \"%s\" from \"%.*s\"\n", 
3321 rval, (int)(size_t)(nested_p - p), p); 
3322 
3323 p = nested_p; 
3324 
3325 if (rval[0] != '\0') { 
3326 const char *rval_pp = rval; 
3327 st.val = ApplyModifiers(&rval_pp, st.val, '\0', '\0', v, 
3328 &st.exprFlags, ctxt, eflags, out_freeIt); 
3329 if (st.val == var_Error 
3330 || (st.val == varUndefined && !(st.eflags & VARE_UNDEFERR)) 
3331 || *rval_pp != '\0') { 
3332 free(freeIt); 
3333 goto out; /* error already reported */ 
3334 } 
3335 } 
3336 free(freeIt); 
3337 
3338 if (*p == ':') 
3339 p++; 
3340 else if (*p == '\0' && endc != '\0') { 
3341 Error("Unclosed variable specification after complex " 
3342 "modifier (expecting '%c') for %s", st.endc, st.v->name); 
3343 goto out; 
3344 } 
3345 continue; 
3346 } 3373 }
3347 apply_mods: 
3348 st.newVal = var_Error; /* default value, in case of errors */ 3374 st.newVal = var_Error; /* default value, in case of errors */
3349 mod = p; 3375 mod = p;
3350 3376
3351 if (DEBUG(VAR)) 3377 if (DEBUG(VAR))
3352 LogBeforeApply(&st, mod, endc); 3378 LogBeforeApply(&st, mod, endc);
3353 3379
3354 res = ApplyModifier(&p, &st); 3380 res = ApplyModifier(&p, &st);
3355 3381
3356#ifdef SYSVVARSUB 3382#ifdef SYSVVARSUB
3357 if (res == AMR_UNKNOWN) { 3383 if (res == AMR_UNKNOWN) {
3358 assert(p == mod); 3384 assert(p == mod);
3359 res = ApplyModifier_SysV(&p, &st); 3385 res = ApplyModifier_SysV(&p, &st);
3360 } 3386 }