Module Name: src Committed By: rillig Date: Mon Mar 15 20:00:51 UTC 2021
Modified Files: src/usr.bin/make: var.c src/usr.bin/make/unit-tests: varmod-indirect.mk Log Message: make: rename ApplyModifiersState to ModChain The new name accurately describes the structural element that holds such properties as the separator character and whether the expression value is considered a single word. The old name ApplyModifiersState was too long and was meant as a placeholder anyway, when I introduced it in var.c 1.236 from 2020-07-03. To generate a diff of this commit: cvs rdiff -u -r1.890 -r1.891 src/usr.bin/make/var.c cvs rdiff -u -r1.8 -r1.9 src/usr.bin/make/unit-tests/varmod-indirect.mk Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/usr.bin/make/var.c diff -u src/usr.bin/make/var.c:1.890 src/usr.bin/make/var.c:1.891 --- src/usr.bin/make/var.c:1.890 Mon Mar 15 19:15:04 2021 +++ src/usr.bin/make/var.c Mon Mar 15 20:00:50 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: var.c,v 1.890 2021/03/15 19:15:04 rillig Exp $ */ +/* $NetBSD: var.c,v 1.891 2021/03/15 20:00:50 rillig Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1993 @@ -140,7 +140,7 @@ #include "metachar.h" /* "@(#)var.c 8.3 (Berkeley) 3/19/94" */ -MAKE_RCSID("$NetBSD: var.c,v 1.890 2021/03/15 19:15:04 rillig Exp $"); +MAKE_RCSID("$NetBSD: var.c,v 1.891 2021/03/15 20:00:50 rillig Exp $"); typedef enum VarFlags { VFL_NONE = 0, @@ -1831,7 +1831,7 @@ Words_JoinFree(Words words) for (i = 0; i < words.len; i++) { if (i != 0) { - /* XXX: Use st->sep instead of ' ', for consistency. */ + /* XXX: Use ch->sep instead of ' ', for consistency. */ Buf_AddByte(&buf, ' '); } Buf_AddStr(&buf, words.words[i]); @@ -1978,7 +1978,7 @@ VarStrftime(const char *fmt, Boolean zul * * If parsing succeeds, the parsing position *pp is updated to point to the * first character following the modifier, which typically is either ':' or - * st->endc. The modifier doesn't have to check for this delimiter character, + * ch->endc. The modifier doesn't have to check for this delimiter character, * this is done by ApplyModifiers. * * XXX: As of 2020-11-15, some modifiers such as :S, :C, :P, :L do not @@ -2012,7 +2012,7 @@ VarStrftime(const char *fmt, Boolean zul * Some modifiers such as ':sh' or '::=' have noticeable side effects though. * * Evaluating the modifier usually takes the current value of the variable - * expression from st->expr->value, or the variable name from st->var->name + * expression from ch->expr->value, or the variable name from ch->var->name * and stores the result back in expr->value via Expr_SetValueOwn or * Expr_SetValueRefer. * @@ -2079,7 +2079,7 @@ typedef struct Expr { * * See varmod-indirect.mk. */ -typedef struct ApplyModifiersState { +typedef struct ModChain { Expr *expr; /* '\0' or '{' or '(' */ const char startc; @@ -2093,7 +2093,7 @@ typedef struct ApplyModifiersState { * big word, possibly containing spaces. */ Boolean oneBigWord; -} ApplyModifiersState; +} ModChain; static void Expr_Define(Expr *expr) @@ -2148,7 +2148,7 @@ ParseModifierPartSubst( const char **pp, char delim, VarEvalFlags eflags, - ApplyModifiersState *st, + ModChain *ch, char **out_part, /* Optionally stores the length of the returned string, just to save * another strlen call. */ @@ -2204,7 +2204,7 @@ ParseModifierPartSubst( VarEvalFlags nested_eflags = eflags; nested_eflags.keepDollar = FALSE; - (void)Var_Parse(&nested_p, st->expr->scope, + (void)Var_Parse(&nested_p, ch->expr->scope, nested_eflags, &nested_val); /* TODO: handle errors */ Buf_AddStr(&buf, nested_val.str); @@ -2255,7 +2255,7 @@ ParseModifierPartSubst( if (*p != delim) { *pp = p; Error("Unfinished modifier for \"%s\" ('%c' missing)", - st->expr->var->name.str, delim); + ch->expr->var->name.str, delim); *out_part = NULL; return VPR_ERR; } @@ -2288,35 +2288,35 @@ ParseModifierPart( char delim, /* Flags for evaluating nested variables. */ VarEvalFlags eflags, - ApplyModifiersState *st, + ModChain *ch, char **out_part ) { - return ParseModifierPartSubst(pp, delim, eflags, st, out_part, + return ParseModifierPartSubst(pp, delim, eflags, ch, out_part, NULL, NULL, NULL); } MAKE_INLINE Boolean -IsDelimiter(char ch, const ApplyModifiersState *st) +IsDelimiter(char c, const ModChain *ch) { - return ch == ':' || ch == st->endc; + return c == ':' || c == ch->endc; } /* Test whether mod starts with modname, followed by a delimiter. */ MAKE_INLINE Boolean -ModMatch(const char *mod, const char *modname, const ApplyModifiersState *st) +ModMatch(const char *mod, const char *modname, const ModChain *ch) { size_t n = strlen(modname); - return strncmp(mod, modname, n) == 0 && IsDelimiter(mod[n], st); + return strncmp(mod, modname, n) == 0 && IsDelimiter(mod[n], ch); } /* Test whether mod starts with modname, followed by a delimiter or '='. */ MAKE_INLINE Boolean -ModMatchEq(const char *mod, const char *modname, const ApplyModifiersState *st) +ModMatchEq(const char *mod, const char *modname, const ModChain *ch) { size_t n = strlen(modname); return strncmp(mod, modname, n) == 0 && - (IsDelimiter(mod[n], st) || mod[n] == '='); + (IsDelimiter(mod[n], ch) || mod[n] == '='); } static Boolean @@ -2387,18 +2387,18 @@ TryParseChar(const char **pp, int base, * result back in the expression. */ static void -ModifyWords(ApplyModifiersState *st, +ModifyWords(ModChain *ch, ModifyWordProc modifyWord, void *modifyWord_args, Boolean oneBigWord) { - Expr *expr = st->expr; + Expr *expr = ch->expr; const char *val = expr->value.str; SepBuf result; Words words; size_t i; if (oneBigWord) { - SepBuf_Init(&result, st->sep); + SepBuf_Init(&result, ch->sep); modifyWord(val, &result, modifyWord_args); goto done; } @@ -2408,7 +2408,7 @@ ModifyWords(ApplyModifiersState *st, DEBUG2(VAR, "ModifyWords: split \"%s\" into %u words\n", val, (unsigned)words.len); - SepBuf_Init(&result, st->sep); + SepBuf_Init(&result, ch->sep); for (i = 0; i < words.len; i++) { modifyWord(words.words[i], &result, modifyWord_args); if (result.buf.len > 0) @@ -2423,9 +2423,9 @@ done: /* :@var@...${var}...@ */ static ApplyModifierResult -ApplyModifier_Loop(const char **pp, ApplyModifiersState *st) +ApplyModifier_Loop(const char **pp, ModChain *ch) { - Expr *expr = st->expr; + Expr *expr = ch->expr; struct ModifyWord_LoopArgs args; char prev_sep; VarParseResult res; @@ -2433,7 +2433,7 @@ ApplyModifier_Loop(const char **pp, Appl args.scope = expr->scope; (*pp)++; /* Skip the first '@' */ - res = ParseModifierPart(pp, '@', VARE_PARSE_ONLY, st, &args.tvar); + res = ParseModifierPart(pp, '@', VARE_PARSE_ONLY, ch, &args.tvar); if (res != VPR_OK) return AMR_CLEANUP; if (opts.strict && strchr(args.tvar, '$') != NULL) { @@ -2444,7 +2444,7 @@ ApplyModifier_Loop(const char **pp, Appl return AMR_CLEANUP; } - res = ParseModifierPart(pp, '@', VARE_PARSE_ONLY, st, &args.str); + res = ParseModifierPart(pp, '@', VARE_PARSE_ONLY, ch, &args.str); if (res != VPR_OK) return AMR_CLEANUP; @@ -2453,10 +2453,10 @@ ApplyModifier_Loop(const char **pp, Appl args.eflags = expr->eflags; args.eflags.keepDollar = FALSE; - prev_sep = st->sep; - st->sep = ' '; /* XXX: should be st->sep for consistency */ - ModifyWords(st, ModifyWord_Loop, &args, st->oneBigWord); - st->sep = prev_sep; + prev_sep = ch->sep; + ch->sep = ' '; /* XXX: should be ch->sep for consistency */ + ModifyWords(ch, ModifyWord_Loop, &args, ch->oneBigWord); + ch->sep = prev_sep; /* XXX: Consider restoring the previous variable instead of deleting. */ /* * XXX: The variable name should not be expanded here, see @@ -2472,9 +2472,9 @@ done: /* :Ddefined or :Uundefined */ static ApplyModifierResult -ApplyModifier_Defined(const char **pp, ApplyModifiersState *st) +ApplyModifier_Defined(const char **pp, ModChain *ch) { - Expr *expr = st->expr; + Expr *expr = ch->expr; Buffer buf; const char *p; @@ -2485,7 +2485,7 @@ ApplyModifier_Defined(const char **pp, A Buf_Init(&buf); p = *pp + 1; - while (!IsDelimiter(*p, st) && *p != '\0') { + while (!IsDelimiter(*p, ch) && *p != '\0') { /* XXX: This code is similar to the one in Var_Parse. * See if the code can be merged. @@ -2495,7 +2495,7 @@ ApplyModifier_Defined(const char **pp, A /* See Buf_AddEscaped in for.c. */ if (*p == '\\') { char c = p[1]; - if (IsDelimiter(c, st) || c == '$' || c == '\\') { + if (IsDelimiter(c, ch) || c == '$' || c == '\\') { Buf_AddByte(&buf, c); p += 2; continue; @@ -2532,9 +2532,9 @@ ApplyModifier_Defined(const char **pp, A /* :L */ static ApplyModifierResult -ApplyModifier_Literal(const char **pp, ApplyModifiersState *st) +ApplyModifier_Literal(const char **pp, ModChain *ch) { - Expr *expr = st->expr; + Expr *expr = ch->expr; (*pp)++; @@ -2567,12 +2567,12 @@ TryParseTime(const char **pp, time_t *ou /* :gmtime */ static ApplyModifierResult -ApplyModifier_Gmtime(const char **pp, ApplyModifiersState *st) +ApplyModifier_Gmtime(const char **pp, ModChain *ch) { time_t utc; const char *mod = *pp; - if (!ModMatchEq(mod, "gmtime", st)) + if (!ModMatchEq(mod, "gmtime", ch)) return AMR_UNKNOWN; if (mod[6] == '=') { @@ -2588,21 +2588,21 @@ ApplyModifier_Gmtime(const char **pp, Ap *pp = mod + 6; } - if (st->expr->eflags.wantRes) - Expr_SetValueOwn(st->expr, - VarStrftime(st->expr->value.str, TRUE, utc)); + if (ch->expr->eflags.wantRes) + Expr_SetValueOwn(ch->expr, + VarStrftime(ch->expr->value.str, TRUE, utc)); return AMR_OK; } /* :localtime */ static ApplyModifierResult -ApplyModifier_Localtime(const char **pp, ApplyModifiersState *st) +ApplyModifier_Localtime(const char **pp, ModChain *ch) { time_t utc; const char *mod = *pp; - if (!ModMatchEq(mod, "localtime", st)) + if (!ModMatchEq(mod, "localtime", ch)) return AMR_UNKNOWN; if (mod[9] == '=') { @@ -2618,38 +2618,38 @@ ApplyModifier_Localtime(const char **pp, *pp = mod + 9; } - if (st->expr->eflags.wantRes) - Expr_SetValueOwn(st->expr, - VarStrftime(st->expr->value.str, FALSE, utc)); + if (ch->expr->eflags.wantRes) + Expr_SetValueOwn(ch->expr, + VarStrftime(ch->expr->value.str, FALSE, utc)); return AMR_OK; } /* :hash */ static ApplyModifierResult -ApplyModifier_Hash(const char **pp, ApplyModifiersState *st) +ApplyModifier_Hash(const char **pp, ModChain *ch) { - if (!ModMatch(*pp, "hash", st)) + if (!ModMatch(*pp, "hash", ch)) return AMR_UNKNOWN; *pp += 4; - if (st->expr->eflags.wantRes) - Expr_SetValueOwn(st->expr, VarHash(st->expr->value.str)); + if (ch->expr->eflags.wantRes) + Expr_SetValueOwn(ch->expr, VarHash(ch->expr->value.str)); return AMR_OK; } /* :P */ static ApplyModifierResult -ApplyModifier_Path(const char **pp, ApplyModifiersState *st) +ApplyModifier_Path(const char **pp, ModChain *ch) { - Expr *expr = st->expr; + Expr *expr = ch->expr; GNode *gn; char *path; (*pp)++; - if (!st->expr->eflags.wantRes) + if (!ch->expr->eflags.wantRes) return AMR_OK; Expr_Define(expr); @@ -2672,15 +2672,15 @@ ApplyModifier_Path(const char **pp, Appl /* :!cmd! */ static ApplyModifierResult -ApplyModifier_ShellCommand(const char **pp, ApplyModifiersState *st) +ApplyModifier_ShellCommand(const char **pp, ModChain *ch) { - Expr *expr = st->expr; + Expr *expr = ch->expr; char *cmd; const char *errfmt; VarParseResult res; (*pp)++; - res = ParseModifierPart(pp, '!', expr->eflags, st, &cmd); + res = ParseModifierPart(pp, '!', expr->eflags, ch, &cmd); if (res != VPR_OK) return AMR_CLEANUP; @@ -2702,14 +2702,14 @@ ApplyModifier_ShellCommand(const char ** * The :range=7 modifier generates an integer sequence from 1 to 7. */ static ApplyModifierResult -ApplyModifier_Range(const char **pp, ApplyModifiersState *st) +ApplyModifier_Range(const char **pp, ModChain *ch) { size_t n; Buffer buf; size_t i; const char *mod = *pp; - if (!ModMatchEq(mod, "range", st)) + if (!ModMatchEq(mod, "range", ch)) return AMR_UNKNOWN; if (mod[5] == '=') { @@ -2726,11 +2726,11 @@ ApplyModifier_Range(const char **pp, App *pp = mod + 5; } - if (!st->expr->eflags.wantRes) + if (!ch->expr->eflags.wantRes) return AMR_OK; if (n == 0) { - Words words = Str_Words(st->expr->value.str, FALSE); + Words words = Str_Words(ch->expr->value.str, FALSE); n = words.len; Words_Free(words); } @@ -2739,23 +2739,23 @@ ApplyModifier_Range(const char **pp, App for (i = 0; i < n; i++) { if (i != 0) { - /* XXX: Use st->sep instead of ' ', for consistency. */ + /* XXX: Use ch->sep instead of ' ', for consistency. */ Buf_AddByte(&buf, ' '); } Buf_AddInt(&buf, 1 + (int)i); } - Expr_SetValueOwn(st->expr, Buf_DoneData(&buf)); + Expr_SetValueOwn(ch->expr, Buf_DoneData(&buf)); return AMR_OK; } /* Parse a ':M' or ':N' modifier. */ static void -ParseModifier_Match(const char **pp, const ApplyModifiersState *st, +ParseModifier_Match(const char **pp, const ModChain *ch, char **out_pattern) { const char *mod = *pp; - Expr *expr = st->expr; + Expr *expr = ch->expr; Boolean copy = FALSE; /* pattern should be, or has been, copied */ Boolean needSubst = FALSE; const char *endpat; @@ -2775,7 +2775,7 @@ ParseModifier_Match(const char **pp, con const char *p; for (p = mod + 1; *p != '\0' && !(*p == ':' && nest == 0); p++) { if (*p == '\\' && - (IsDelimiter(p[1], st) || p[1] == st->startc)) { + (IsDelimiter(p[1], ch) || p[1] == ch->startc)) { if (!needSubst) copy = TRUE; p++; @@ -2804,8 +2804,8 @@ ParseModifier_Match(const char **pp, con src = mod + 1; for (; src < endpat; src++, dst++) { if (src[0] == '\\' && src + 1 < endpat && - /* XXX: st->startc is missing here; see above */ - IsDelimiter(src[1], st)) + /* XXX: ch->startc is missing here; see above */ + IsDelimiter(src[1], ch)) src++; *dst = *src; } @@ -2829,17 +2829,17 @@ ParseModifier_Match(const char **pp, con /* :Mpattern or :Npattern */ static ApplyModifierResult -ApplyModifier_Match(const char **pp, ApplyModifiersState *st) +ApplyModifier_Match(const char **pp, ModChain *ch) { const char mod = **pp; char *pattern; - ParseModifier_Match(pp, st, &pattern); + ParseModifier_Match(pp, ch, &pattern); - if (st->expr->eflags.wantRes) { + if (ch->expr->eflags.wantRes) { ModifyWordProc modifyWord = mod == 'M' ? ModifyWord_Match : ModifyWord_NoMatch; - ModifyWords(st, modifyWord, pattern, st->oneBigWord); + ModifyWords(ch, modifyWord, pattern, ch->oneBigWord); } free(pattern); @@ -2863,7 +2863,7 @@ ParsePatternFlags(const char **pp, VarPa /* :S,from,to, */ static ApplyModifierResult -ApplyModifier_Subst(const char **pp, ApplyModifiersState *st) +ApplyModifier_Subst(const char **pp, ModChain *ch) { struct ModifyWord_SubstArgs args; char *lhs, *rhs; @@ -2887,22 +2887,22 @@ ApplyModifier_Subst(const char **pp, App (*pp)++; } - res = ParseModifierPartSubst(pp, delim, st->expr->eflags, st, &lhs, + res = ParseModifierPartSubst(pp, delim, ch->expr->eflags, ch, &lhs, &args.lhsLen, &args.pflags, NULL); if (res != VPR_OK) return AMR_CLEANUP; args.lhs = lhs; - res = ParseModifierPartSubst(pp, delim, st->expr->eflags, st, &rhs, + res = ParseModifierPartSubst(pp, delim, ch->expr->eflags, ch, &rhs, &args.rhsLen, NULL, &args); if (res != VPR_OK) return AMR_CLEANUP; args.rhs = rhs; - oneBigWord = st->oneBigWord; + oneBigWord = ch->oneBigWord; ParsePatternFlags(pp, &args.pflags, &oneBigWord); - ModifyWords(st, ModifyWord_Subst, &args, oneBigWord); + ModifyWords(ch, ModifyWord_Subst, &args, oneBigWord); free(lhs); free(rhs); @@ -2913,7 +2913,7 @@ ApplyModifier_Subst(const char **pp, App /* :C,from,to, */ static ApplyModifierResult -ApplyModifier_Regex(const char **pp, ApplyModifiersState *st) +ApplyModifier_Regex(const char **pp, ModChain *ch) { char *re; struct ModifyWord_SubstRegexArgs args; @@ -2930,11 +2930,11 @@ ApplyModifier_Regex(const char **pp, App *pp += 2; - res = ParseModifierPart(pp, delim, st->expr->eflags, st, &re); + res = ParseModifierPart(pp, delim, ch->expr->eflags, ch, &re); if (res != VPR_OK) return AMR_CLEANUP; - res = ParseModifierPart(pp, delim, st->expr->eflags, st, &args.replace); + res = ParseModifierPart(pp, delim, ch->expr->eflags, ch, &args.replace); if (args.replace == NULL) { free(re); return AMR_CLEANUP; @@ -2942,10 +2942,10 @@ ApplyModifier_Regex(const char **pp, App args.pflags = (VarPatternFlags){ FALSE, FALSE, FALSE, FALSE }; args.matched = FALSE; - oneBigWord = st->oneBigWord; + oneBigWord = ch->oneBigWord; ParsePatternFlags(pp, &args.pflags, &oneBigWord); - if (!(st->expr->eflags.wantRes)) { + if (!(ch->expr->eflags.wantRes)) { free(args.replace); free(re); return AMR_OK; @@ -2963,7 +2963,7 @@ ApplyModifier_Regex(const char **pp, App if (args.nsub > 10) args.nsub = 10; - ModifyWords(st, ModifyWord_SubstRegex, &args, oneBigWord); + ModifyWords(ch, ModifyWord_SubstRegex, &args, oneBigWord); regfree(&args.re); free(args.replace); @@ -2974,16 +2974,16 @@ ApplyModifier_Regex(const char **pp, App /* :Q, :q */ static ApplyModifierResult -ApplyModifier_Quote(const char **pp, ApplyModifiersState *st) +ApplyModifier_Quote(const char **pp, ModChain *ch) { Boolean quoteDollar = **pp == 'q'; - if (!IsDelimiter((*pp)[1], st)) + if (!IsDelimiter((*pp)[1], ch)) return AMR_UNKNOWN; (*pp)++; - if (st->expr->eflags.wantRes) - Expr_SetValueOwn(st->expr, - VarQuote(st->expr->value.str, quoteDollar)); + if (ch->expr->eflags.wantRes) + Expr_SetValueOwn(ch->expr, + VarQuote(ch->expr->value.str, quoteDollar)); return AMR_OK; } @@ -2997,7 +2997,7 @@ ModifyWord_Copy(const char *word, SepBuf /* :ts<separator> */ static ApplyModifierResult -ApplyModifier_ToSep(const char **pp, ApplyModifiersState *st) +ApplyModifier_ToSep(const char **pp, ModChain *ch) { const char *sep = *pp + 2; @@ -3009,16 +3009,16 @@ ApplyModifier_ToSep(const char **pp, App */ /* ":ts<any><endc>" or ":ts<any>:" */ - if (sep[0] != st->endc && IsDelimiter(sep[1], st)) { + if (sep[0] != ch->endc && IsDelimiter(sep[1], ch)) { *pp = sep + 1; - st->sep = sep[0]; + ch->sep = sep[0]; goto ok; } /* ":ts<endc>" or ":ts:" */ - if (IsDelimiter(sep[0], st)) { + if (IsDelimiter(sep[0], ch)) { *pp = sep; - st->sep = '\0'; /* no separator */ + ch->sep = '\0'; /* no separator */ goto ok; } @@ -3031,14 +3031,14 @@ ApplyModifier_ToSep(const char **pp, App /* ":ts\n" */ if (sep[1] == 'n') { *pp = sep + 2; - st->sep = '\n'; + ch->sep = '\n'; goto ok; } /* ":ts\t" */ if (sep[1] == 't') { *pp = sep + 2; - st->sep = '\t'; + ch->sep = '\t'; goto ok; } @@ -3055,12 +3055,12 @@ ApplyModifier_ToSep(const char **pp, App return AMR_BAD; /* ":ts<backslash><unrecognised>". */ } - if (!TryParseChar(&p, base, &st->sep)) { + if (!TryParseChar(&p, base, &ch->sep)) { Parse_Error(PARSE_FATAL, "Invalid character number: %s", p); return AMR_CLEANUP; } - if (!IsDelimiter(*p, st)) { + if (!IsDelimiter(*p, ch)) { (*pp)++; /* just for backwards compatibility */ return AMR_BAD; } @@ -3069,7 +3069,7 @@ ApplyModifier_ToSep(const char **pp, App } ok: - ModifyWords(st, ModifyWord_Copy, NULL, st->oneBigWord); + ModifyWords(ch, ModifyWord_Copy, NULL, ch->oneBigWord); return AMR_OK; } @@ -3103,48 +3103,48 @@ str_tolower(const char *str) /* :tA, :tu, :tl, :ts<separator>, etc. */ static ApplyModifierResult -ApplyModifier_To(const char **pp, ApplyModifiersState *st) +ApplyModifier_To(const char **pp, ModChain *ch) { - Expr *expr = st->expr; + Expr *expr = ch->expr; const char *mod = *pp; assert(mod[0] == 't'); - if (IsDelimiter(mod[1], st) || mod[1] == '\0') { + if (IsDelimiter(mod[1], ch) || mod[1] == '\0') { *pp = mod + 1; return AMR_BAD; /* Found ":t<endc>" or ":t:". */ } if (mod[1] == 's') - return ApplyModifier_ToSep(pp, st); + return ApplyModifier_ToSep(pp, ch); - if (!IsDelimiter(mod[2], st)) { /* :t<unrecognized> */ + if (!IsDelimiter(mod[2], ch)) { /* :t<unrecognized> */ *pp = mod + 1; return AMR_BAD; } if (mod[1] == 'A') { /* :tA */ *pp = mod + 2; - ModifyWords(st, ModifyWord_Realpath, NULL, st->oneBigWord); + ModifyWords(ch, ModifyWord_Realpath, NULL, ch->oneBigWord); return AMR_OK; } if (mod[1] == 'u') { /* :tu */ *pp = mod + 2; - if (st->expr->eflags.wantRes) + if (ch->expr->eflags.wantRes) Expr_SetValueOwn(expr, str_toupper(expr->value.str)); return AMR_OK; } if (mod[1] == 'l') { /* :tl */ *pp = mod + 2; - if (st->expr->eflags.wantRes) + if (ch->expr->eflags.wantRes) Expr_SetValueOwn(expr, str_tolower(expr->value.str)); return AMR_OK; } if (mod[1] == 'W' || mod[1] == 'w') { /* :tW, :tw */ *pp = mod + 2; - st->oneBigWord = mod[1] == 'W'; + ch->oneBigWord = mod[1] == 'W'; return AMR_OK; } @@ -3155,20 +3155,20 @@ ApplyModifier_To(const char **pp, ApplyM /* :[#], :[1], :[-1..1], etc. */ static ApplyModifierResult -ApplyModifier_Words(const char **pp, ApplyModifiersState *st) +ApplyModifier_Words(const char **pp, ModChain *ch) { - Expr *expr = st->expr; + Expr *expr = ch->expr; char *estr; int first, last; VarParseResult res; const char *p; (*pp)++; /* skip the '[' */ - res = ParseModifierPart(pp, ']', expr->eflags, st, &estr); + res = ParseModifierPart(pp, ']', expr->eflags, ch, &estr); if (res != VPR_OK) return AMR_CLEANUP; - if (!IsDelimiter(**pp, st)) + if (!IsDelimiter(**pp, ch)) goto bad_modifier; /* Found junk after ']' */ if (!(expr->eflags.wantRes)) @@ -3178,7 +3178,7 @@ ApplyModifier_Words(const char **pp, App goto bad_modifier; /* Found ":[]". */ if (estr[0] == '#' && estr[1] == '\0') { /* Found ":[#]" */ - if (st->oneBigWord) { + if (ch->oneBigWord) { Expr_SetValueRefer(expr, "1"); } else { Buffer buf; @@ -3196,12 +3196,12 @@ ApplyModifier_Words(const char **pp, App } if (estr[0] == '*' && estr[1] == '\0') { /* Found ":[*]" */ - st->oneBigWord = TRUE; + ch->oneBigWord = TRUE; goto ok; } if (estr[0] == '@' && estr[1] == '\0') { /* Found ":[@]" */ - st->oneBigWord = FALSE; + ch->oneBigWord = FALSE; goto ok; } @@ -3229,7 +3229,7 @@ ApplyModifier_Words(const char **pp, App */ if (first == 0 && last == 0) { /* ":[0]" or perhaps ":[0..0]" */ - st->oneBigWord = TRUE; + ch->oneBigWord = TRUE; goto ok; } @@ -3240,7 +3240,7 @@ ApplyModifier_Words(const char **pp, App /* Normal case: select the words described by first and last. */ Expr_SetValueOwn(expr, VarSelectWords(expr->value.str, first, last, - st->sep, st->oneBigWord)); + ch->sep, ch->oneBigWord)); ok: free(estr); @@ -3278,7 +3278,7 @@ ShuffleStrings(char **strs, size_t n) /* :O (order ascending) or :Or (order descending) or :Ox (shuffle) */ static ApplyModifierResult -ApplyModifier_Order(const char **pp, ApplyModifiersState *st) +ApplyModifier_Order(const char **pp, ModChain *ch) { const char *mod = (*pp)++; /* skip past the 'O' in any case */ Words words; @@ -3286,34 +3286,34 @@ ApplyModifier_Order(const char **pp, App ASC, DESC, SHUFFLE } mode; - if (IsDelimiter(mod[1], st)) { + if (IsDelimiter(mod[1], ch)) { mode = ASC; } else if ((mod[1] == 'r' || mod[1] == 'x') && - IsDelimiter(mod[2], st)) { + IsDelimiter(mod[2], ch)) { (*pp)++; mode = mod[1] == 'r' ? DESC : SHUFFLE; } else return AMR_BAD; - if (!st->expr->eflags.wantRes) + if (!ch->expr->eflags.wantRes) return AMR_OK; - words = Str_Words(st->expr->value.str, FALSE); + words = Str_Words(ch->expr->value.str, FALSE); if (mode == SHUFFLE) ShuffleStrings(words.words, words.len); else qsort(words.words, words.len, sizeof words.words[0], mode == ASC ? str_cmp_asc : str_cmp_desc); - Expr_SetValueOwn(st->expr, Words_JoinFree(words)); + Expr_SetValueOwn(ch->expr, Words_JoinFree(words)); return AMR_OK; } /* :? then : else */ static ApplyModifierResult -ApplyModifier_IfElse(const char **pp, ApplyModifiersState *st) +ApplyModifier_IfElse(const char **pp, ModChain *ch) { - Expr *expr = st->expr; + Expr *expr = ch->expr; char *then_expr, *else_expr; VarParseResult res; @@ -3331,15 +3331,15 @@ ApplyModifier_IfElse(const char **pp, Ap } (*pp)++; /* skip past the '?' */ - res = ParseModifierPart(pp, ':', then_eflags, st, &then_expr); + res = ParseModifierPart(pp, ':', then_eflags, ch, &then_expr); if (res != VPR_OK) return AMR_CLEANUP; - res = ParseModifierPart(pp, st->endc, else_eflags, st, &else_expr); + res = ParseModifierPart(pp, ch->endc, else_eflags, ch, &else_expr); if (res != VPR_OK) return AMR_CLEANUP; - (*pp)--; /* Go back to the st->endc. */ + (*pp)--; /* Go back to the ch->endc. */ if (cond_rc == COND_INVALID) { Error("Bad conditional expression `%s' in %s?%s:%s", @@ -3385,9 +3385,9 @@ ApplyModifier_IfElse(const char **pp, Ap * variable. */ static ApplyModifierResult -ApplyModifier_Assign(const char **pp, ApplyModifiersState *st) +ApplyModifier_Assign(const char **pp, ModChain *ch) { - Expr *expr = st->expr; + Expr *expr = ch->expr; GNode *scope; char *val; VarParseResult res; @@ -3418,11 +3418,11 @@ ok: break; } - res = ParseModifierPart(pp, st->endc, expr->eflags, st, &val); + res = ParseModifierPart(pp, ch->endc, expr->eflags, ch, &val); if (res != VPR_OK) return AMR_CLEANUP; - (*pp)--; /* Go back to the st->endc. */ + (*pp)--; /* Go back to the ch->endc. */ if (!expr->eflags.wantRes) goto done; @@ -3470,13 +3470,13 @@ done: * remember current value */ static ApplyModifierResult -ApplyModifier_Remember(const char **pp, ApplyModifiersState *st) +ApplyModifier_Remember(const char **pp, ModChain *ch) { - Expr *expr = st->expr; + Expr *expr = ch->expr; const char *mod = *pp; FStr name; - if (!ModMatchEq(mod, "_", st)) + if (!ModMatchEq(mod, "_", ch)) return AMR_UNKNOWN; name = FStr_InitRefer("_"); @@ -3505,28 +3505,28 @@ ApplyModifier_Remember(const char **pp, * for a single-letter modifier such as :H, :T. */ static ApplyModifierResult -ApplyModifier_WordFunc(const char **pp, ApplyModifiersState *st, +ApplyModifier_WordFunc(const char **pp, ModChain *ch, ModifyWordProc modifyWord) { - if (!IsDelimiter((*pp)[1], st)) + if (!IsDelimiter((*pp)[1], ch)) return AMR_UNKNOWN; (*pp)++; - if (st->expr->eflags.wantRes) - ModifyWords(st, modifyWord, NULL, st->oneBigWord); + if (ch->expr->eflags.wantRes) + ModifyWords(ch, modifyWord, NULL, ch->oneBigWord); return AMR_OK; } static ApplyModifierResult -ApplyModifier_Unique(const char **pp, ApplyModifiersState *st) +ApplyModifier_Unique(const char **pp, ModChain *ch) { - if (!IsDelimiter((*pp)[1], st)) + if (!IsDelimiter((*pp)[1], ch)) return AMR_UNKNOWN; (*pp)++; - if (st->expr->eflags.wantRes) - Expr_SetValueOwn(st->expr, VarUniq(st->expr->value.str)); + if (ch->expr->eflags.wantRes) + Expr_SetValueOwn(ch->expr, VarUniq(ch->expr->value.str)); return AMR_OK; } @@ -3534,9 +3534,9 @@ ApplyModifier_Unique(const char **pp, Ap #ifdef SYSVVARSUB /* :from=to */ static ApplyModifierResult -ApplyModifier_SysV(const char **pp, ApplyModifiersState *st) +ApplyModifier_SysV(const char **pp, ModChain *ch) { - Expr *expr = st->expr; + Expr *expr = ch->expr; char *lhs, *rhs; VarParseResult res; @@ -3552,27 +3552,27 @@ ApplyModifier_SysV(const char **pp, Appl while (*p != '\0' && depth > 0) { if (*p == '=') { /* XXX: should also test depth == 1 */ eqFound = TRUE; - /* continue looking for st->endc */ - } else if (*p == st->endc) + /* continue looking for ch->endc */ + } else if (*p == ch->endc) depth--; - else if (*p == st->startc) + else if (*p == ch->startc) depth++; if (depth > 0) p++; } - if (*p != st->endc || !eqFound) + if (*p != ch->endc || !eqFound) return AMR_UNKNOWN; - res = ParseModifierPart(pp, '=', expr->eflags, st, &lhs); + res = ParseModifierPart(pp, '=', expr->eflags, ch, &lhs); if (res != VPR_OK) return AMR_CLEANUP; /* The SysV modifier lasts until the end of the variable expression. */ - res = ParseModifierPart(pp, st->endc, expr->eflags, st, &rhs); + res = ParseModifierPart(pp, ch->endc, expr->eflags, ch, &rhs); if (res != VPR_OK) return AMR_CLEANUP; - (*pp)--; /* Go back to the st->endc. */ + (*pp)--; /* Go back to the ch->endc. */ if (lhs[0] == '\0' && expr->value.str[0] == '\0') { /* Do not turn an empty expression into non-empty. */ @@ -3580,7 +3580,7 @@ ApplyModifier_SysV(const char **pp, Appl struct ModifyWord_SYSVSubstArgs args = { expr->scope, lhs, rhs }; - ModifyWords(st, ModifyWord_SYSVSubst, &args, st->oneBigWord); + ModifyWords(ch, ModifyWord_SYSVSubst, &args, ch->oneBigWord); } free(lhs); free(rhs); @@ -3591,11 +3591,11 @@ ApplyModifier_SysV(const char **pp, Appl #ifdef SUNSHCMD /* :sh */ static ApplyModifierResult -ApplyModifier_SunShell(const char **pp, ApplyModifiersState *st) +ApplyModifier_SunShell(const char **pp, ModChain *ch) { - Expr *expr = st->expr; + Expr *expr = ch->expr; const char *p = *pp; - if (!(p[1] == 'h' && IsDelimiter(p[2], st))) + if (!(p[1] == 'h' && IsDelimiter(p[2], ch))) return AMR_UNKNOWN; *pp = p + 2; @@ -3612,11 +3612,11 @@ ApplyModifier_SunShell(const char **pp, #endif static void -LogBeforeApply(const ApplyModifiersState *st, const char *mod) +LogBeforeApply(const ModChain *ch, const char *mod) { - const Expr *expr = st->expr; + const Expr *expr = ch->expr; char vflags_str[VarFlags_ToStringSize]; - Boolean is_single_char = mod[0] != '\0' && IsDelimiter(mod[1], st); + Boolean is_single_char = mod[0] != '\0' && IsDelimiter(mod[1], ch); /* At this point, only the first character of the modifier can * be used since the end of the modifier is not yet known. */ @@ -3629,9 +3629,9 @@ LogBeforeApply(const ApplyModifiersState } static void -LogAfterApply(const ApplyModifiersState *st, const char *p, const char *mod) +LogAfterApply(const ModChain *ch, const char *p, const char *mod) { - const Expr *expr = st->expr; + const Expr *expr = ch->expr; const char *value = expr->value.str; char vflags_str[VarFlags_ToStringSize]; const char *quot = value == var_Error ? "" : "\""; @@ -3645,67 +3645,67 @@ LogAfterApply(const ApplyModifiersState } static ApplyModifierResult -ApplyModifier(const char **pp, ApplyModifiersState *st) +ApplyModifier(const char **pp, ModChain *ch) { switch (**pp) { case '!': - return ApplyModifier_ShellCommand(pp, st); + return ApplyModifier_ShellCommand(pp, ch); case ':': - return ApplyModifier_Assign(pp, st); + return ApplyModifier_Assign(pp, ch); case '?': - return ApplyModifier_IfElse(pp, st); + return ApplyModifier_IfElse(pp, ch); case '@': - return ApplyModifier_Loop(pp, st); + return ApplyModifier_Loop(pp, ch); case '[': - return ApplyModifier_Words(pp, st); + return ApplyModifier_Words(pp, ch); case '_': - return ApplyModifier_Remember(pp, st); + return ApplyModifier_Remember(pp, ch); #ifndef NO_REGEX case 'C': - return ApplyModifier_Regex(pp, st); + return ApplyModifier_Regex(pp, ch); #endif case 'D': - return ApplyModifier_Defined(pp, st); + return ApplyModifier_Defined(pp, ch); case 'E': - return ApplyModifier_WordFunc(pp, st, ModifyWord_Suffix); + return ApplyModifier_WordFunc(pp, ch, ModifyWord_Suffix); case 'g': - return ApplyModifier_Gmtime(pp, st); + return ApplyModifier_Gmtime(pp, ch); case 'H': - return ApplyModifier_WordFunc(pp, st, ModifyWord_Head); + return ApplyModifier_WordFunc(pp, ch, ModifyWord_Head); case 'h': - return ApplyModifier_Hash(pp, st); + return ApplyModifier_Hash(pp, ch); case 'L': - return ApplyModifier_Literal(pp, st); + return ApplyModifier_Literal(pp, ch); case 'l': - return ApplyModifier_Localtime(pp, st); + return ApplyModifier_Localtime(pp, ch); case 'M': case 'N': - return ApplyModifier_Match(pp, st); + return ApplyModifier_Match(pp, ch); case 'O': - return ApplyModifier_Order(pp, st); + return ApplyModifier_Order(pp, ch); case 'P': - return ApplyModifier_Path(pp, st); + return ApplyModifier_Path(pp, ch); case 'Q': case 'q': - return ApplyModifier_Quote(pp, st); + return ApplyModifier_Quote(pp, ch); case 'R': - return ApplyModifier_WordFunc(pp, st, ModifyWord_Root); + return ApplyModifier_WordFunc(pp, ch, ModifyWord_Root); case 'r': - return ApplyModifier_Range(pp, st); + return ApplyModifier_Range(pp, ch); case 'S': - return ApplyModifier_Subst(pp, st); + return ApplyModifier_Subst(pp, ch); #ifdef SUNSHCMD case 's': - return ApplyModifier_SunShell(pp, st); + return ApplyModifier_SunShell(pp, ch); #endif case 'T': - return ApplyModifier_WordFunc(pp, st, ModifyWord_Tail); + return ApplyModifier_WordFunc(pp, ch, ModifyWord_Tail); case 't': - return ApplyModifier_To(pp, st); + return ApplyModifier_To(pp, ch); case 'U': - return ApplyModifier_Defined(pp, st); + return ApplyModifier_Defined(pp, ch); case 'u': - return ApplyModifier_Unique(pp, st); + return ApplyModifier_Unique(pp, ch); default: return AMR_UNKNOWN; } @@ -3732,20 +3732,20 @@ typedef enum ApplyModifiersIndirectResul * Multiple groups of indirect modifiers can be chained by separating them * with colons. ${VAR:${M1}:${M2}} contains 2 indirect modifiers. * - * If the variable expression is not followed by st->endc or ':', fall + * If the variable expression is not followed by ch->endc or ':', fall * back to trying the SysV modifier, such as in ${VAR:${FROM}=${TO}}. */ static ApplyModifiersIndirectResult -ApplyModifiersIndirect(ApplyModifiersState *st, const char **pp) +ApplyModifiersIndirect(ModChain *ch, const char **pp) { - Expr *expr = st->expr; + Expr *expr = ch->expr; const char *p = *pp; FStr mods; (void)Var_Parse(&p, expr->scope, expr->eflags, &mods); /* TODO: handle errors */ - if (mods.str[0] != '\0' && *p != '\0' && !IsDelimiter(*p, st)) { + if (mods.str[0] != '\0' && *p != '\0' && !IsDelimiter(*p, ch)) { FStr_Done(&mods); return AMIR_SYSV; } @@ -3766,10 +3766,10 @@ ApplyModifiersIndirect(ApplyModifiersSta if (*p == ':') p++; - else if (*p == '\0' && st->endc != '\0') { + else if (*p == '\0' && ch->endc != '\0') { Error("Unclosed variable expression after indirect " "modifier, expecting '%c' for variable \"%s\"", - st->endc, expr->var->name.str); + ch->endc, expr->var->name.str); *pp = p; return AMIR_OUT; } @@ -3779,21 +3779,21 @@ ApplyModifiersIndirect(ApplyModifiersSta } static ApplyModifierResult -ApplySingleModifier(const char **pp, ApplyModifiersState *st) +ApplySingleModifier(const char **pp, ModChain *ch) { ApplyModifierResult res; const char *mod = *pp; const char *p = *pp; if (DEBUG(VAR)) - LogBeforeApply(st, mod); + LogBeforeApply(ch, mod); - res = ApplyModifier(&p, st); + res = ApplyModifier(&p, ch); #ifdef SYSVVARSUB if (res == AMR_UNKNOWN) { assert(p == mod); - res = ApplyModifier_SysV(&p, st); + res = ApplyModifier_SysV(&p, ch); } #endif @@ -3804,11 +3804,11 @@ ApplySingleModifier(const char **pp, App * errors and leads to wrong results. * Parsing should rather stop here. */ - for (p++; !IsDelimiter(*p, st) && *p != '\0'; p++) + for (p++; !IsDelimiter(*p, ch) && *p != '\0'; p++) continue; Parse_Error(PARSE_FATAL, "Unknown modifier \"%.*s\"", (int)(p - mod), mod); - Expr_SetValueRefer(st->expr, var_Error); + Expr_SetValueRefer(ch->expr, var_Error); } if (res == AMR_CLEANUP || res == AMR_BAD) { *pp = p; @@ -3816,18 +3816,18 @@ ApplySingleModifier(const char **pp, App } if (DEBUG(VAR)) - LogAfterApply(st, p, mod); + LogAfterApply(ch, p, mod); - if (*p == '\0' && st->endc != '\0') { + if (*p == '\0' && ch->endc != '\0') { Error( "Unclosed variable expression, expecting '%c' for " "modifier \"%.*s\" of variable \"%s\" with value \"%s\"", - st->endc, + ch->endc, (int)(p - mod), mod, - st->expr->var->name.str, st->expr->value.str); + ch->expr->var->name.str, ch->expr->value.str); } else if (*p == ':') { p++; - } else if (opts.strict && *p != '\0' && *p != st->endc) { + } else if (opts.strict && *p != '\0' && *p != ch->endc) { Parse_Error(PARSE_FATAL, "Missing delimiter ':' after modifier \"%.*s\"", (int)(p - mod), mod); @@ -3849,7 +3849,7 @@ ApplyModifiers( char endc /* ')' or '}'; or '\0' for indirect modifiers */ ) { - ApplyModifiersState st = { + ModChain ch = { expr, startc, endc, @@ -3868,7 +3868,7 @@ ApplyModifiers( if (*p == '\0' && endc != '\0') { Error( "Unclosed variable expression (expecting '%c') for \"%s\"", - st.endc, expr->var->name.str); + ch.endc, expr->var->name.str); goto cleanup; } @@ -3877,7 +3877,7 @@ ApplyModifiers( if (*p == '$') { ApplyModifiersIndirectResult amir = - ApplyModifiersIndirect(&st, &p); + ApplyModifiersIndirect(&ch, &p); if (amir == AMIR_CONTINUE) continue; if (amir == AMIR_OUT) @@ -3891,7 +3891,7 @@ ApplyModifiers( mod = p; - res = ApplySingleModifier(&p, &st); + res = ApplySingleModifier(&p, &ch); if (res == AMR_CLEANUP) goto cleanup; if (res == AMR_BAD) Index: src/usr.bin/make/unit-tests/varmod-indirect.mk diff -u src/usr.bin/make/unit-tests/varmod-indirect.mk:1.8 src/usr.bin/make/unit-tests/varmod-indirect.mk:1.9 --- src/usr.bin/make/unit-tests/varmod-indirect.mk:1.8 Sun Feb 14 17:47:33 2021 +++ src/usr.bin/make/unit-tests/varmod-indirect.mk Mon Mar 15 20:00:50 2021 @@ -1,4 +1,4 @@ -# $NetBSD: varmod-indirect.mk,v 1.8 2021/02/14 17:47:33 rillig Exp $ +# $NetBSD: varmod-indirect.mk,v 1.9 2021/03/15 20:00:50 rillig Exp $ # # Tests for indirect variable modifiers, such as in ${VAR:${M_modifiers}}. # These can be used for very basic purposes like converting a string to either @@ -221,7 +221,7 @@ _:= before ${UNDEF:${:UZ}} after # the ':M' since that is not part of the text from the indirect modifier. # # Implementation detail: when ApplyModifiersIndirect calls ApplyModifiers -# (which creates a new ApplyModifiersState containing a fresh separator), +# (which creates a new ModChain containing a fresh separator), # the outer separator character is not passed by reference to the inner # evaluation, therefore the scope of the inner separator ends after applying # the modifier ':ts*'.