Sun Mar 14 18:23:44 2021 UTC ()
make: don't evaluate several simple modifiers in parse-only mode

This affects the modifiers ':E', ':H', ':P', ':Q', ':R', ':T', ':hash',
':q', ':range', ':tl', ':ts', ':tu', and ':u'.  All these modifiers are
side-effect free.

Skipping the evaluation for these modifiers is purely for code
consistency and performance.

No functional change.


(rillig)
diff -r1.872 -r1.873 src/usr.bin/make/var.c

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

--- src/usr.bin/make/var.c 2021/03/14 18:10:57 1.872
+++ src/usr.bin/make/var.c 2021/03/14 18:23:44 1.873
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: var.c,v 1.872 2021/03/14 18:10:57 rillig Exp $ */ 1/* $NetBSD: var.c,v 1.873 2021/03/14 18:23:44 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.
@@ -130,27 +130,27 @@ @@ -130,27 +130,27 @@
130#include <regex.h> 130#include <regex.h>
131#endif 131#endif
132#include <errno.h> 132#include <errno.h>
133#include <inttypes.h> 133#include <inttypes.h>
134#include <limits.h> 134#include <limits.h>
135#include <time.h> 135#include <time.h>
136 136
137#include "make.h" 137#include "make.h"
138#include "dir.h" 138#include "dir.h"
139#include "job.h" 139#include "job.h"
140#include "metachar.h" 140#include "metachar.h"
141 141
142/* "@(#)var.c 8.3 (Berkeley) 3/19/94" */ 142/* "@(#)var.c 8.3 (Berkeley) 3/19/94" */
143MAKE_RCSID("$NetBSD: var.c,v 1.872 2021/03/14 18:10:57 rillig Exp $"); 143MAKE_RCSID("$NetBSD: var.c,v 1.873 2021/03/14 18:23:44 rillig Exp $");
144 144
145typedef enum VarFlags { 145typedef enum VarFlags {
146 VFL_NONE = 0, 146 VFL_NONE = 0,
147 147
148 /* 148 /*
149 * The variable's value is currently being used by Var_Parse or 149 * The variable's value is currently being used by Var_Parse or
150 * Var_Subst. This marker is used to avoid endless recursion. 150 * Var_Subst. This marker is used to avoid endless recursion.
151 */ 151 */
152 VFL_IN_USE = 1 << 0, 152 VFL_IN_USE = 1 << 0,
153 153
154 /* 154 /*
155 * The variable comes from the environment. 155 * The variable comes from the environment.
156 * These variables are not registered in any GNode, therefore they 156 * These variables are not registered in any GNode, therefore they
@@ -2601,41 +2601,45 @@ ApplyModifier_Localtime(const char **pp, @@ -2601,41 +2601,45 @@ ApplyModifier_Localtime(const char **pp,
2601 VarStrftime(st->expr->value.str, FALSE, utc)); 2601 VarStrftime(st->expr->value.str, FALSE, utc));
2602 2602
2603 return AMR_OK; 2603 return AMR_OK;
2604} 2604}
2605 2605
2606/* :hash */ 2606/* :hash */
2607static ApplyModifierResult 2607static ApplyModifierResult
2608ApplyModifier_Hash(const char **pp, ApplyModifiersState *st) 2608ApplyModifier_Hash(const char **pp, ApplyModifiersState *st)
2609{ 2609{
2610 if (!ModMatch(*pp, "hash", st)) 2610 if (!ModMatch(*pp, "hash", st))
2611 return AMR_UNKNOWN; 2611 return AMR_UNKNOWN;
2612 *pp += 4; 2612 *pp += 4;
2613 2613
2614 Expr_SetValueOwn(st->expr, VarHash(st->expr->value.str)); 2614 if (st->expr->eflags & VARE_WANTRES)
 2615 Expr_SetValueOwn(st->expr, VarHash(st->expr->value.str));
2615 2616
2616 return AMR_OK; 2617 return AMR_OK;
2617} 2618}
2618 2619
2619/* :P */ 2620/* :P */
2620static ApplyModifierResult 2621static ApplyModifierResult
2621ApplyModifier_Path(const char **pp, ApplyModifiersState *st) 2622ApplyModifier_Path(const char **pp, ApplyModifiersState *st)
2622{ 2623{
2623 Expr *expr = st->expr; 2624 Expr *expr = st->expr;
2624 GNode *gn; 2625 GNode *gn;
2625 char *path; 2626 char *path;
2626 2627
2627 (*pp)++; 2628 (*pp)++;
2628 2629
 2630 if (!(st->expr->eflags & VARE_WANTRES))
 2631 return AMR_OK;
 2632
2629 Expr_Define(expr); 2633 Expr_Define(expr);
2630 2634
2631 gn = Targ_FindNode(expr->var->name.str); 2635 gn = Targ_FindNode(expr->var->name.str);
2632 if (gn == NULL || gn->type & OP_NOPATH) { 2636 if (gn == NULL || gn->type & OP_NOPATH) {
2633 path = NULL; 2637 path = NULL;
2634 } else if (gn->path != NULL) { 2638 } else if (gn->path != NULL) {
2635 path = bmake_strdup(gn->path); 2639 path = bmake_strdup(gn->path);
2636 } else { 2640 } else {
2637 SearchPath *searchPath = Suff_FindPath(gn); 2641 SearchPath *searchPath = Suff_FindPath(gn);
2638 path = Dir_FindFile(expr->var->name.str, searchPath); 2642 path = Dir_FindFile(expr->var->name.str, searchPath);
2639 } 2643 }
2640 if (path == NULL) 2644 if (path == NULL)
2641 path = bmake_strdup(expr->var->name.str); 2645 path = bmake_strdup(expr->var->name.str);
@@ -2690,26 +2694,29 @@ ApplyModifier_Range(const char **pp, App @@ -2690,26 +2694,29 @@ ApplyModifier_Range(const char **pp, App
2690 const char *p = mod + 6; 2694 const char *p = mod + 6;
2691 if (!TryParseSize(&p, &n)) { 2695 if (!TryParseSize(&p, &n)) {
2692 Parse_Error(PARSE_FATAL, 2696 Parse_Error(PARSE_FATAL,
2693 "Invalid number \"%s\" for ':range' modifier", 2697 "Invalid number \"%s\" for ':range' modifier",
2694 mod + 6); 2698 mod + 6);
2695 return AMR_CLEANUP; 2699 return AMR_CLEANUP;
2696 } 2700 }
2697 *pp = p; 2701 *pp = p;
2698 } else { 2702 } else {
2699 n = 0; 2703 n = 0;
2700 *pp = mod + 5; 2704 *pp = mod + 5;
2701 } 2705 }
2702 2706
 2707 if (!(st->expr->eflags & VARE_WANTRES))
 2708 return AMR_OK;
 2709
2703 if (n == 0) { 2710 if (n == 0) {
2704 Words words = Str_Words(st->expr->value.str, FALSE); 2711 Words words = Str_Words(st->expr->value.str, FALSE);
2705 n = words.len; 2712 n = words.len;
2706 Words_Free(words); 2713 Words_Free(words);
2707 } 2714 }
2708 2715
2709 Buf_Init(&buf); 2716 Buf_Init(&buf);
2710 2717
2711 for (i = 0; i < n; i++) { 2718 for (i = 0; i < n; i++) {
2712 if (i != 0) { 2719 if (i != 0) {
2713 /* XXX: Use st->sep instead of ' ', for consistency. */ 2720 /* XXX: Use st->sep instead of ' ', for consistency. */
2714 Buf_AddByte(&buf, ' '); 2721 Buf_AddByte(&buf, ' ');
2715 } 2722 }
@@ -2939,44 +2946,53 @@ ApplyModifier_Regex(const char **pp, App @@ -2939,44 +2946,53 @@ ApplyModifier_Regex(const char **pp, App
2939} 2946}
2940 2947
2941#endif 2948#endif
2942 2949
2943/* :Q, :q */ 2950/* :Q, :q */
2944static ApplyModifierResult 2951static ApplyModifierResult
2945ApplyModifier_Quote(const char **pp, ApplyModifiersState *st) 2952ApplyModifier_Quote(const char **pp, ApplyModifiersState *st)
2946{ 2953{
2947 Boolean quoteDollar = **pp == 'q'; 2954 Boolean quoteDollar = **pp == 'q';
2948 if (!IsDelimiter((*pp)[1], st)) 2955 if (!IsDelimiter((*pp)[1], st))
2949 return AMR_UNKNOWN; 2956 return AMR_UNKNOWN;
2950 (*pp)++; 2957 (*pp)++;
2951 2958
2952 Expr_SetValueOwn(st->expr, VarQuote(st->expr->value.str, quoteDollar)); 2959 if (st->expr->eflags & VARE_WANTRES)
 2960 Expr_SetValueOwn(st->expr,
 2961 VarQuote(st->expr->value.str, quoteDollar));
2953 2962
2954 return AMR_OK; 2963 return AMR_OK;
2955} 2964}
2956 2965
2957/*ARGSUSED*/ 2966/*ARGSUSED*/
2958static void 2967static void
2959ModifyWord_Copy(const char *word, SepBuf *buf, void *data MAKE_ATTR_UNUSED) 2968ModifyWord_Copy(const char *word, SepBuf *buf, void *data MAKE_ATTR_UNUSED)
2960{ 2969{
2961 SepBuf_AddStr(buf, word); 2970 SepBuf_AddStr(buf, word);
2962} 2971}
2963 2972
2964/* :ts<separator> */ 2973/* :ts<separator> */
2965static ApplyModifierResult 2974static ApplyModifierResult
2966ApplyModifier_ToSep(const char **pp, ApplyModifiersState *st) 2975ApplyModifier_ToSep(const char **pp, ApplyModifiersState *st)
2967{ 2976{
2968 const char *sep = *pp + 2; 2977 const char *sep = *pp + 2;
2969 2978
 2979 /*
 2980 * Even if VARE_WANTRES is not set, proceed as normal since there is
 2981 * neither any observable side effect nor a performance penalty.
 2982 * Checking for VARE_WANTRES for every single piece of code in here
 2983 * would make the code in this function too hard to read.
 2984 */
 2985
2970 /* ":ts<any><endc>" or ":ts<any>:" */ 2986 /* ":ts<any><endc>" or ":ts<any>:" */
2971 if (sep[0] != st->endc && IsDelimiter(sep[1], st)) { 2987 if (sep[0] != st->endc && IsDelimiter(sep[1], st)) {
2972 *pp = sep + 1; 2988 *pp = sep + 1;
2973 st->sep = sep[0]; 2989 st->sep = sep[0];
2974 goto ok; 2990 goto ok;
2975 } 2991 }
2976 2992
2977 /* ":ts<endc>" or ":ts:" */ 2993 /* ":ts<endc>" or ":ts:" */
2978 if (IsDelimiter(sep[0], st)) { 2994 if (IsDelimiter(sep[0], st)) {
2979 *pp = sep; 2995 *pp = sep;
2980 st->sep = '\0'; /* no separator */ 2996 st->sep = '\0'; /* no separator */
2981 goto ok; 2997 goto ok;
2982 } 2998 }
@@ -3079,33 +3095,35 @@ ApplyModifier_To(const char **pp, ApplyM @@ -3079,33 +3095,35 @@ ApplyModifier_To(const char **pp, ApplyM
3079 if (!IsDelimiter(mod[2], st)) { /* :t<unrecognized> */ 3095 if (!IsDelimiter(mod[2], st)) { /* :t<unrecognized> */
3080 *pp = mod + 1; 3096 *pp = mod + 1;
3081 return AMR_BAD; 3097 return AMR_BAD;
3082 } 3098 }
3083 3099
3084 if (mod[1] == 'A') { /* :tA */ 3100 if (mod[1] == 'A') { /* :tA */
3085 *pp = mod + 2; 3101 *pp = mod + 2;
3086 ModifyWords(st, ModifyWord_Realpath, NULL, st->oneBigWord); 3102 ModifyWords(st, ModifyWord_Realpath, NULL, st->oneBigWord);
3087 return AMR_OK; 3103 return AMR_OK;
3088 } 3104 }
3089 3105
3090 if (mod[1] == 'u') { /* :tu */ 3106 if (mod[1] == 'u') { /* :tu */
3091 *pp = mod + 2; 3107 *pp = mod + 2;
3092 Expr_SetValueOwn(expr, str_toupper(expr->value.str)); 3108 if (st->expr->eflags & VARE_WANTRES)
 3109 Expr_SetValueOwn(expr, str_toupper(expr->value.str));
3093 return AMR_OK; 3110 return AMR_OK;
3094 } 3111 }
3095 3112
3096 if (mod[1] == 'l') { /* :tl */ 3113 if (mod[1] == 'l') { /* :tl */
3097 *pp = mod + 2; 3114 *pp = mod + 2;
3098 Expr_SetValueOwn(expr, str_tolower(expr->value.str)); 3115 if (st->expr->eflags & VARE_WANTRES)
 3116 Expr_SetValueOwn(expr, str_tolower(expr->value.str));
3099 return AMR_OK; 3117 return AMR_OK;
3100 } 3118 }
3101 3119
3102 if (mod[1] == 'W' || mod[1] == 'w') { /* :tW, :tw */ 3120 if (mod[1] == 'W' || mod[1] == 'w') { /* :tW, :tw */
3103 *pp = mod + 2; 3121 *pp = mod + 2;
3104 st->oneBigWord = mod[1] == 'W'; 3122 st->oneBigWord = mod[1] == 'W';
3105 return AMR_OK; 3123 return AMR_OK;
3106 } 3124 }
3107 3125
3108 /* Found ":t<unrecognised>:" or ":t<unrecognised><endc>". */ 3126 /* Found ":t<unrecognised>:" or ":t<unrecognised><endc>". */
3109 *pp = mod + 1; /* XXX: unnecessary but observable */ 3127 *pp = mod + 1; /* XXX: unnecessary but observable */
3110 return AMR_BAD; 3128 return AMR_BAD;
3111} 3129}
@@ -3454,39 +3472,41 @@ ApplyModifier_Remember(const char **pp,  @@ -3454,39 +3472,41 @@ ApplyModifier_Remember(const char **pp,
3454 3472
3455/* 3473/*
3456 * Apply the given function to each word of the variable value, 3474 * Apply the given function to each word of the variable value,
3457 * for a single-letter modifier such as :H, :T. 3475 * for a single-letter modifier such as :H, :T.
3458 */ 3476 */
3459static ApplyModifierResult 3477static ApplyModifierResult
3460ApplyModifier_WordFunc(const char **pp, ApplyModifiersState *st, 3478ApplyModifier_WordFunc(const char **pp, ApplyModifiersState *st,
3461 ModifyWordProc modifyWord) 3479 ModifyWordProc modifyWord)
3462{ 3480{
3463 if (!IsDelimiter((*pp)[1], st)) 3481 if (!IsDelimiter((*pp)[1], st))
3464 return AMR_UNKNOWN; 3482 return AMR_UNKNOWN;
3465 (*pp)++; 3483 (*pp)++;
3466 3484
3467 ModifyWords(st, modifyWord, NULL, st->oneBigWord); 3485 if (st->expr->eflags & VARE_WANTRES)
 3486 ModifyWords(st, modifyWord, NULL, st->oneBigWord);
3468 3487
3469 return AMR_OK; 3488 return AMR_OK;
3470} 3489}
3471 3490
3472static ApplyModifierResult 3491static ApplyModifierResult
3473ApplyModifier_Unique(const char **pp, ApplyModifiersState *st) 3492ApplyModifier_Unique(const char **pp, ApplyModifiersState *st)
3474{ 3493{
3475 if (!IsDelimiter((*pp)[1], st)) 3494 if (!IsDelimiter((*pp)[1], st))
3476 return AMR_UNKNOWN; 3495 return AMR_UNKNOWN;
3477 (*pp)++; 3496 (*pp)++;
3478 3497
3479 Expr_SetValueOwn(st->expr, VarUniq(st->expr->value.str)); 3498 if (st->expr->eflags & VARE_WANTRES)
 3499 Expr_SetValueOwn(st->expr, VarUniq(st->expr->value.str));
3480 3500
3481 return AMR_OK; 3501 return AMR_OK;
3482} 3502}
3483 3503
3484#ifdef SYSVVARSUB 3504#ifdef SYSVVARSUB
3485/* :from=to */ 3505/* :from=to */
3486static ApplyModifierResult 3506static ApplyModifierResult
3487ApplyModifier_SysV(const char **pp, ApplyModifiersState *st) 3507ApplyModifier_SysV(const char **pp, ApplyModifiersState *st)
3488{ 3508{
3489 Expr *expr = st->expr; 3509 Expr *expr = st->expr;
3490 char *lhs, *rhs; 3510 char *lhs, *rhs;
3491 VarParseResult res; 3511 VarParseResult res;
3492 3512