Home | History | Annotate | Line # | Download | only in make
      1  1.1172       sjg /*	$NetBSD: var.c,v 1.1172 2025/09/16 15:15:47 sjg Exp $	*/
      2    1.11  christos 
      3     1.1       cgd /*
      4    1.15  christos  * Copyright (c) 1988, 1989, 1990, 1993
      5    1.15  christos  *	The Regents of the University of California.  All rights reserved.
      6    1.80       agc  *
      7    1.80       agc  * This code is derived from software contributed to Berkeley by
      8    1.80       agc  * Adam de Boor.
      9    1.80       agc  *
     10    1.80       agc  * Redistribution and use in source and binary forms, with or without
     11    1.80       agc  * modification, are permitted provided that the following conditions
     12    1.80       agc  * are met:
     13    1.80       agc  * 1. Redistributions of source code must retain the above copyright
     14    1.80       agc  *    notice, this list of conditions and the following disclaimer.
     15    1.80       agc  * 2. Redistributions in binary form must reproduce the above copyright
     16    1.80       agc  *    notice, this list of conditions and the following disclaimer in the
     17    1.80       agc  *    documentation and/or other materials provided with the distribution.
     18    1.80       agc  * 3. Neither the name of the University nor the names of its contributors
     19    1.80       agc  *    may be used to endorse or promote products derived from this software
     20    1.80       agc  *    without specific prior written permission.
     21    1.80       agc  *
     22    1.80       agc  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     23    1.80       agc  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     24    1.80       agc  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     25    1.80       agc  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     26    1.80       agc  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     27    1.80       agc  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     28    1.80       agc  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     29    1.80       agc  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     30    1.80       agc  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     31    1.80       agc  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     32    1.80       agc  * SUCH DAMAGE.
     33    1.80       agc  */
     34    1.80       agc 
     35    1.80       agc /*
     36     1.1       cgd  * Copyright (c) 1989 by Berkeley Softworks
     37     1.1       cgd  * All rights reserved.
     38     1.1       cgd  *
     39     1.1       cgd  * This code is derived from software contributed to Berkeley by
     40     1.1       cgd  * Adam de Boor.
     41     1.1       cgd  *
     42     1.1       cgd  * Redistribution and use in source and binary forms, with or without
     43     1.1       cgd  * modification, are permitted provided that the following conditions
     44     1.1       cgd  * are met:
     45     1.1       cgd  * 1. Redistributions of source code must retain the above copyright
     46     1.1       cgd  *    notice, this list of conditions and the following disclaimer.
     47     1.1       cgd  * 2. Redistributions in binary form must reproduce the above copyright
     48     1.1       cgd  *    notice, this list of conditions and the following disclaimer in the
     49     1.1       cgd  *    documentation and/or other materials provided with the distribution.
     50     1.1       cgd  * 3. All advertising materials mentioning features or use of this software
     51     1.1       cgd  *    must display the following acknowledgement:
     52     1.1       cgd  *	This product includes software developed by the University of
     53     1.1       cgd  *	California, Berkeley and its contributors.
     54     1.1       cgd  * 4. Neither the name of the University nor the names of its contributors
     55     1.1       cgd  *    may be used to endorse or promote products derived from this software
     56     1.1       cgd  *    without specific prior written permission.
     57     1.1       cgd  *
     58     1.1       cgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     59     1.1       cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     60     1.1       cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     61     1.1       cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     62     1.1       cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     63     1.1       cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     64     1.1       cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     65     1.1       cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     66     1.1       cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     67     1.1       cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     68     1.1       cgd  * SUCH DAMAGE.
     69     1.1       cgd  */
     70     1.1       cgd 
     71   1.592    rillig /*
     72   1.592    rillig  * Handling of variables and the expressions formed from them.
     73   1.592    rillig  *
     74   1.592    rillig  * Variables are set using lines of the form VAR=value.  Both the variable
     75   1.592    rillig  * name and the value can contain references to other variables, by using
     76   1.592    rillig  * expressions like ${VAR}, ${VAR:Modifiers}, ${${VARNAME}} or ${VAR:${MODS}}.
     77     1.1       cgd  *
     78     1.1       cgd  * Interface:
     79   1.798    rillig  *	Var_Set
     80  1.1105    rillig  *	Var_SetExpand	Set the value of the variable, creating it if
     81   1.592    rillig  *			necessary.
     82   1.592    rillig  *
     83   1.794    rillig  *	Var_Append
     84   1.794    rillig  *	Var_AppendExpand
     85   1.794    rillig  *			Append more characters to the variable, creating it if
     86   1.592    rillig  *			necessary. A space is placed between the old value and
     87   1.592    rillig  *			the new one.
     88     1.1       cgd  *
     89   1.796    rillig  *	Var_Exists
     90   1.796    rillig  *	Var_ExistsExpand
     91   1.796    rillig  *			See if a variable exists.
     92     1.1       cgd  *
     93   1.592    rillig  *	Var_Value	Return the unexpanded value of a variable, or NULL if
     94   1.592    rillig  *			the variable is undefined.
     95   1.592    rillig  *
     96  1.1075    rillig  *	Var_Subst	Substitute all expressions in a string.
     97   1.592    rillig  *
     98  1.1075    rillig  *	Var_Parse	Parse an expression such as ${VAR:Mpattern}.
     99     1.1       cgd  *
    100  1.1105    rillig  *	Var_Delete	Delete a variable.
    101     1.1       cgd  *
    102   1.725    rillig  *	Var_ReexportVars
    103   1.725    rillig  *			Export some or even all variables to the environment
    104   1.592    rillig  *			of this process and its child processes.
    105     1.1       cgd  *
    106   1.592    rillig  *	Var_Export	Export the variable to the environment of this process
    107   1.592    rillig  *			and its child processes.
    108     1.1       cgd  *
    109   1.592    rillig  *	Var_UnExport	Don't export the variable anymore.
    110     1.1       cgd  *
    111     1.1       cgd  * Debugging:
    112   1.592    rillig  *	Var_Stats	Print out hashing statistics if in -dh mode.
    113   1.592    rillig  *
    114   1.802    rillig  *	Var_Dump	Print out all variables defined in the given scope.
    115     1.1       cgd  */
    116     1.1       cgd 
    117   1.630    rillig #include <sys/stat.h>
    118   1.630    rillig #include <sys/types.h>
    119   1.630    rillig #include <regex.h>
    120   1.631    rillig #include <errno.h>
    121   1.630    rillig #include <inttypes.h>
    122   1.630    rillig #include <limits.h>
    123   1.630    rillig #include <time.h>
    124   1.630    rillig 
    125   1.630    rillig #include "make.h"
    126   1.630    rillig #include "dir.h"
    127   1.630    rillig #include "job.h"
    128   1.630    rillig #include "metachar.h"
    129     1.1       cgd 
    130   1.512    rillig /*	"@(#)var.c	8.3 (Berkeley) 3/19/94" */
    131  1.1172       sjg MAKE_RCSID("$NetBSD: var.c,v 1.1172 2025/09/16 15:15:47 sjg Exp $");
    132   1.228    rillig 
    133   1.778    rillig /*
    134   1.778    rillig  * Variables are defined using one of the VAR=value assignments.  Their
    135   1.570    rillig  * value can be queried by expressions such as $V, ${VAR}, or with modifiers
    136   1.570    rillig  * such as ${VAR:S,from,to,g:Q}.
    137   1.570    rillig  *
    138   1.802    rillig  * There are 3 kinds of variables: scope variables, environment variables,
    139   1.570    rillig  * undefined variables.
    140   1.570    rillig  *
    141  1.1105    rillig  * Scope variables are stored in GNode.vars.  The only way to undefine
    142   1.802    rillig  * a scope variable is using the .undef directive.  In particular, it must
    143   1.570    rillig  * not be possible to undefine a variable during the evaluation of an
    144   1.996    rillig  * expression, or Var.name might point nowhere.  (There is another,
    145   1.996    rillig  * unintended way to undefine a scope variable, see varmod-loop-delete.mk.)
    146   1.570    rillig  *
    147   1.977    rillig  * Environment variables are short-lived.  They are returned by VarFind, and
    148   1.977    rillig  * after using them, they must be freed using VarFreeShortLived.
    149   1.570    rillig  *
    150  1.1075    rillig  * Undefined variables occur during evaluation of expressions such
    151   1.570    rillig  * as ${UNDEF:Ufallback} in Var_Parse and ApplyModifiers.
    152   1.570    rillig  */
    153     1.1       cgd typedef struct Var {
    154   1.703    rillig 	/*
    155   1.703    rillig 	 * The name of the variable, once set, doesn't change anymore.
    156   1.802    rillig 	 * For scope variables, it aliases the corresponding HashEntry name.
    157   1.703    rillig 	 * For environment and undefined variables, it is allocated.
    158   1.703    rillig 	 */
    159   1.711    rillig 	FStr name;
    160   1.570    rillig 
    161   1.703    rillig 	/* The unexpanded value of the variable. */
    162   1.703    rillig 	Buffer val;
    163   1.902    rillig 
    164   1.902    rillig 	/* The variable came from the command line. */
    165   1.987    rillig 	bool fromCmd:1;
    166   1.902    rillig 
    167   1.902    rillig 	/*
    168   1.978    rillig 	 * The variable is short-lived.
    169   1.978    rillig 	 * These variables are not registered in any GNode, therefore they
    170   1.978    rillig 	 * must be freed after use.
    171   1.978    rillig 	 */
    172   1.987    rillig 	bool shortLived:1;
    173   1.978    rillig 
    174   1.978    rillig 	/*
    175   1.902    rillig 	 * The variable comes from the environment.
    176  1.1105    rillig 	 * Appending to its value depends on the scope, see var-op-append.mk.
    177   1.902    rillig 	 */
    178   1.987    rillig 	bool fromEnvironment:1;
    179   1.902    rillig 
    180   1.902    rillig 	/*
    181   1.902    rillig 	 * The variable value cannot be changed anymore, and the variable
    182   1.902    rillig 	 * cannot be deleted.  Any attempts to do so are silently ignored,
    183   1.902    rillig 	 * they are logged with -dv though.
    184  1.1038       sjg 	 * Use .[NO]READONLY: to adjust.
    185   1.902    rillig 	 *
    186   1.902    rillig 	 * See VAR_SET_READONLY.
    187   1.902    rillig 	 */
    188   1.987    rillig 	bool readOnly:1;
    189   1.902    rillig 
    190   1.902    rillig 	/*
    191  1.1121    rillig 	 * The variable is read-only and immune to the .NOREADONLY special
    192  1.1121    rillig 	 * target.  Any attempt to modify it results in an error.
    193  1.1121    rillig 	 */
    194  1.1121    rillig 	bool readOnlyLoud:1;
    195  1.1121    rillig 
    196  1.1121    rillig 	/*
    197  1.1035    rillig 	 * The variable is currently being accessed by Var_Parse or Var_Subst.
    198  1.1035    rillig 	 * This temporary marker is used to avoid endless recursion.
    199  1.1035    rillig 	 */
    200   1.987    rillig 	bool inUse:1;
    201   1.902    rillig 
    202   1.902    rillig 	/*
    203   1.902    rillig 	 * The variable is exported to the environment, to be used by child
    204   1.902    rillig 	 * processes.
    205   1.902    rillig 	 */
    206   1.987    rillig 	bool exported:1;
    207   1.902    rillig 
    208   1.902    rillig 	/*
    209   1.902    rillig 	 * At the point where this variable was exported, it contained an
    210   1.902    rillig 	 * unresolved reference to another variable.  Before any child
    211  1.1066    rillig 	 * process is started, it needs to be actually exported, resolving
    212  1.1066    rillig 	 * the referenced variable just in time.
    213   1.902    rillig 	 */
    214   1.987    rillig 	bool reexport:1;
    215   1.417    rillig } Var;
    216     1.1       cgd 
    217   1.710    rillig /*
    218   1.830    rillig  * Exporting variables is expensive and may leak memory, so skip it if we
    219   1.830    rillig  * can.
    220   1.710    rillig  */
    221   1.710    rillig typedef enum VarExportedMode {
    222   1.710    rillig 	VAR_EXPORTED_NONE,
    223   1.710    rillig 	VAR_EXPORTED_SOME,
    224   1.710    rillig 	VAR_EXPORTED_ALL
    225   1.710    rillig } VarExportedMode;
    226   1.710    rillig 
    227   1.713    rillig typedef enum UnexportWhat {
    228   1.830    rillig 	/* Unexport the variables given by name. */
    229   1.713    rillig 	UNEXPORT_NAMED,
    230   1.830    rillig 	/*
    231   1.830    rillig 	 * Unexport all globals previously exported, but keep the environment
    232   1.830    rillig 	 * inherited from the parent.
    233   1.830    rillig 	 */
    234   1.713    rillig 	UNEXPORT_ALL,
    235   1.830    rillig 	/*
    236   1.830    rillig 	 * Unexport all globals previously exported and clear the environment
    237   1.830    rillig 	 * inherited from the parent.
    238   1.830    rillig 	 */
    239   1.713    rillig 	UNEXPORT_ENV
    240   1.713    rillig } UnexportWhat;
    241   1.713    rillig 
    242   1.261    rillig /* Flags for pattern matching in the :S and :C modifiers */
    243   1.927    rillig typedef struct PatternFlags {
    244   1.987    rillig 	bool subGlobal:1;	/* 'g': replace as often as possible */
    245   1.987    rillig 	bool subOnce:1;		/* '1': replace only once */
    246   1.987    rillig 	bool anchorStart:1;	/* '^': match only at start of word */
    247   1.987    rillig 	bool anchorEnd:1;	/* '$': match only at end of word */
    248   1.927    rillig } PatternFlags;
    249    1.16  christos 
    250   1.830    rillig /* SepBuf builds a string from words interleaved with separators. */
    251   1.710    rillig typedef struct SepBuf {
    252   1.710    rillig 	Buffer buf;
    253   1.895    rillig 	bool needSep;
    254   1.710    rillig 	/* Usually ' ', but see the ':ts' modifier. */
    255   1.710    rillig 	char sep;
    256   1.710    rillig } SepBuf;
    257   1.710    rillig 
    258  1.1120    rillig typedef enum {
    259  1.1163    rillig 	VSK_MAKEFLAGS,
    260  1.1120    rillig 	VSK_TARGET,
    261  1.1146    rillig 	VSK_COMMAND,
    262  1.1120    rillig 	VSK_VARNAME,
    263  1.1147    rillig 	VSK_INDIRECT_MODIFIERS,
    264  1.1124    rillig 	VSK_COND,
    265  1.1124    rillig 	VSK_COND_THEN,
    266  1.1124    rillig 	VSK_COND_ELSE,
    267  1.1133    rillig 	VSK_EXPR,
    268  1.1133    rillig 	VSK_EXPR_PARSE
    269  1.1120    rillig } EvalStackElementKind;
    270  1.1120    rillig 
    271  1.1102    rillig typedef struct {
    272  1.1120    rillig 	EvalStackElementKind kind;
    273  1.1120    rillig 	const char *str;
    274  1.1128    rillig 	const FStr *value;
    275  1.1102    rillig } EvalStackElement;
    276  1.1102    rillig 
    277  1.1102    rillig typedef struct {
    278  1.1102    rillig 	EvalStackElement *elems;
    279  1.1102    rillig 	size_t len;
    280  1.1102    rillig 	size_t cap;
    281  1.1102    rillig } EvalStack;
    282   1.710    rillig 
    283  1.1088    rillig /* Whether we have replaced the original environ (which we cannot free). */
    284   1.710    rillig char **savedEnv = NULL;
    285   1.710    rillig 
    286   1.778    rillig /*
    287   1.778    rillig  * Special return value for Var_Parse, indicating a parse error.  It may be
    288   1.710    rillig  * caused by an undefined variable, a syntax error in a modifier or
    289   1.778    rillig  * something entirely different.
    290   1.778    rillig  */
    291   1.710    rillig char var_Error[] = "";
    292   1.710    rillig 
    293   1.778    rillig /*
    294   1.778    rillig  * Special return value for Var_Parse, indicating an undefined variable in
    295  1.1119    rillig  * a case where VARE_EVAL_DEFINED is not set.  This undefined variable is
    296   1.710    rillig  * typically a dynamic variable such as ${.TARGET}, whose expansion needs to
    297   1.778    rillig  * be deferred until it is defined in an actual target.
    298   1.830    rillig  *
    299  1.1119    rillig  * See VARE_EVAL_KEEP_UNDEFINED.
    300   1.778    rillig  */
    301   1.710    rillig static char varUndefined[] = "";
    302   1.710    rillig 
    303   1.710    rillig /*
    304   1.710    rillig  * Traditionally this make consumed $$ during := like any other expansion.
    305   1.710    rillig  * Other make's do not, and this make follows straight since 2016-01-09.
    306   1.710    rillig  *
    307   1.895    rillig  * This knob allows controlling the behavior:
    308   1.895    rillig  *	false to consume $$ during := assignment.
    309   1.895    rillig  *	true to preserve $$ during := assignment.
    310   1.710    rillig  */
    311   1.710    rillig #define MAKE_SAVE_DOLLARS ".MAKE.SAVE_DOLLARS"
    312   1.895    rillig static bool save_dollars = true;
    313   1.710    rillig 
    314   1.710    rillig /*
    315   1.807    rillig  * A scope collects variable names and their values.
    316   1.807    rillig  *
    317   1.807    rillig  * The main scope is SCOPE_GLOBAL, which contains the variables that are set
    318   1.807    rillig  * in the makefiles.  SCOPE_INTERNAL acts as a fallback for SCOPE_GLOBAL and
    319   1.807    rillig  * contains some internal make variables.  These internal variables can thus
    320   1.807    rillig  * be overridden, they can also be restored by undefining the overriding
    321   1.807    rillig  * variable.
    322   1.807    rillig  *
    323   1.807    rillig  * SCOPE_CMDLINE contains variables from the command line arguments.  These
    324   1.807    rillig  * override variables from SCOPE_GLOBAL.
    325   1.807    rillig  *
    326   1.807    rillig  * There is no scope for environment variables, these are generated on-the-fly
    327  1.1088    rillig  * whenever they are referenced.
    328   1.807    rillig  *
    329   1.807    rillig  * Each target has its own scope, containing the 7 target-local variables
    330  1.1006       sjg  * .TARGET, .ALLSRC, etc.  Variables set on dependency lines also go in
    331  1.1006       sjg  * this scope.
    332   1.807    rillig  */
    333   1.807    rillig 
    334   1.807    rillig GNode *SCOPE_CMDLINE;
    335   1.807    rillig GNode *SCOPE_GLOBAL;
    336   1.807    rillig GNode *SCOPE_INTERNAL;
    337   1.710    rillig 
    338   1.710    rillig static VarExportedMode var_exportedVars = VAR_EXPORTED_NONE;
    339   1.710    rillig 
    340   1.951    rillig static const char VarEvalMode_Name[][32] = {
    341  1.1119    rillig 	"parse",
    342  1.1047    rillig 	"parse-balanced",
    343   1.906    rillig 	"eval",
    344  1.1144    rillig 	"eval-defined-loud",
    345   1.906    rillig 	"eval-defined",
    346   1.906    rillig 	"eval-keep-undefined",
    347   1.906    rillig 	"eval-keep-dollar-and-undefined",
    348   1.906    rillig };
    349   1.711    rillig 
    350  1.1102    rillig static EvalStack evalStack;
    351  1.1102    rillig 
    352  1.1102    rillig 
    353  1.1120    rillig static void
    354  1.1128    rillig EvalStack_Push(EvalStackElementKind kind, const char *str, const FStr *value)
    355  1.1102    rillig {
    356  1.1102    rillig 	if (evalStack.len >= evalStack.cap) {
    357  1.1102    rillig 		evalStack.cap = 16 + 2 * evalStack.cap;
    358  1.1102    rillig 		evalStack.elems = bmake_realloc(evalStack.elems,
    359  1.1102    rillig 		    evalStack.cap * sizeof(*evalStack.elems));
    360  1.1102    rillig 	}
    361  1.1120    rillig 	evalStack.elems[evalStack.len].kind = kind;
    362  1.1120    rillig 	evalStack.elems[evalStack.len].str = str;
    363  1.1128    rillig 	evalStack.elems[evalStack.len].value = value;
    364  1.1102    rillig 	evalStack.len++;
    365  1.1102    rillig }
    366  1.1102    rillig 
    367  1.1163    rillig void
    368  1.1163    rillig EvalStack_PushMakeflags(const char *makeflags)
    369  1.1163    rillig {
    370  1.1163    rillig 	EvalStack_Push(VSK_MAKEFLAGS, makeflags, NULL);
    371  1.1163    rillig }
    372  1.1163    rillig 
    373  1.1163    rillig void
    374  1.1102    rillig EvalStack_Pop(void)
    375  1.1102    rillig {
    376  1.1102    rillig 	assert(evalStack.len > 0);
    377  1.1102    rillig 	evalStack.len--;
    378  1.1102    rillig }
    379  1.1102    rillig 
    380  1.1152    rillig bool
    381  1.1164    rillig EvalStack_Details(Buffer *buf)
    382  1.1102    rillig {
    383  1.1102    rillig 	size_t i;
    384  1.1102    rillig 
    385  1.1139    rillig 	for (i = evalStack.len; i > 0; i--) {
    386  1.1124    rillig 		static const char descr[][42] = {
    387  1.1163    rillig 			"while evaluating MAKEFLAGS",
    388  1.1124    rillig 			"in target",
    389  1.1146    rillig 			"in command",
    390  1.1124    rillig 			"while evaluating variable",
    391  1.1147    rillig 			"while evaluating indirect modifiers",
    392  1.1124    rillig 			"while evaluating condition",
    393  1.1124    rillig 			"while evaluating then-branch of condition",
    394  1.1124    rillig 			"while evaluating else-branch of condition",
    395  1.1124    rillig 			"while evaluating",
    396  1.1133    rillig 			"while parsing",
    397  1.1124    rillig 		};
    398  1.1139    rillig 		EvalStackElement *elem = evalStack.elems + i - 1;
    399  1.1132    rillig 		EvalStackElementKind kind = elem->kind;
    400  1.1140    rillig 		const char* value = elem->value != NULL
    401  1.1140    rillig 		    && (kind == VSK_VARNAME || kind == VSK_EXPR)
    402  1.1140    rillig 		    ? elem->value->str : NULL;
    403  1.1140    rillig 
    404  1.1164    rillig 		Buf_AddStr(buf, "\t");
    405  1.1164    rillig 		Buf_AddStr(buf, descr[kind]);
    406  1.1164    rillig 		Buf_AddStr(buf, " \"");
    407  1.1164    rillig 		Buf_AddStr(buf, elem->str);
    408  1.1164    rillig 		if (value != NULL) {
    409  1.1164    rillig 			Buf_AddStr(buf, "\" with value \"");
    410  1.1164    rillig 			Buf_AddStr(buf, value);
    411  1.1164    rillig 		}
    412  1.1164    rillig 		Buf_AddStr(buf, "\"\n");
    413  1.1102    rillig 	}
    414  1.1152    rillig 	return evalStack.len > 0;
    415  1.1102    rillig }
    416   1.904    rillig 
    417   1.569    rillig static Var *
    418   1.978    rillig VarNew(FStr name, const char *value,
    419   1.978    rillig        bool shortLived, bool fromEnvironment, bool readOnly)
    420   1.569    rillig {
    421   1.703    rillig 	size_t value_len = strlen(value);
    422   1.703    rillig 	Var *var = bmake_malloc(sizeof *var);
    423   1.744    rillig 	var->name = name;
    424   1.703    rillig 	Buf_InitSize(&var->val, value_len + 1);
    425   1.703    rillig 	Buf_AddBytes(&var->val, value, value_len);
    426   1.902    rillig 	var->fromCmd = false;
    427   1.978    rillig 	var->shortLived = shortLived;
    428   1.978    rillig 	var->fromEnvironment = fromEnvironment;
    429   1.902    rillig 	var->readOnly = readOnly;
    430  1.1121    rillig 	var->readOnlyLoud = false;
    431   1.902    rillig 	var->inUse = false;
    432   1.902    rillig 	var->exported = false;
    433   1.902    rillig 	var->reexport = false;
    434   1.703    rillig 	return var;
    435   1.569    rillig }
    436   1.569    rillig 
    437   1.916    rillig static Substring
    438   1.916    rillig CanonicalVarname(Substring name)
    439     1.1       cgd {
    440  1.1169    rillig 	if (Substring_Equals(name, "^"))
    441  1.1169    rillig 		return Substring_InitStr(ALLSRC);
    442   1.916    rillig 
    443   1.916    rillig 	if (!(Substring_Length(name) > 0 && name.start[0] == '.'))
    444   1.916    rillig 		return name;
    445   1.916    rillig 
    446   1.916    rillig 	if (Substring_Equals(name, ".ALLSRC"))
    447   1.916    rillig 		return Substring_InitStr(ALLSRC);
    448   1.916    rillig 	if (Substring_Equals(name, ".ARCHIVE"))
    449   1.916    rillig 		return Substring_InitStr(ARCHIVE);
    450   1.916    rillig 	if (Substring_Equals(name, ".IMPSRC"))
    451   1.916    rillig 		return Substring_InitStr(IMPSRC);
    452   1.916    rillig 	if (Substring_Equals(name, ".MEMBER"))
    453   1.916    rillig 		return Substring_InitStr(MEMBER);
    454   1.916    rillig 	if (Substring_Equals(name, ".OODATE"))
    455   1.916    rillig 		return Substring_InitStr(OODATE);
    456   1.916    rillig 	if (Substring_Equals(name, ".PREFIX"))
    457   1.916    rillig 		return Substring_InitStr(PREFIX);
    458   1.916    rillig 	if (Substring_Equals(name, ".TARGET"))
    459   1.916    rillig 		return Substring_InitStr(TARGET);
    460   1.916    rillig 
    461   1.916    rillig 	if (Substring_Equals(name, ".SHELL") && shellPath == NULL)
    462   1.916    rillig 		Shell_Init();
    463   1.242    rillig 
    464   1.703    rillig 	return name;
    465   1.580    rillig }
    466   1.580    rillig 
    467   1.587    rillig static Var *
    468  1.1160    rillig GNode_FindVar(GNode *scope, Substring varname, unsigned hash)
    469   1.587    rillig {
    470   1.916    rillig 	return HashTable_FindValueBySubstringHash(&scope->vars, varname, hash);
    471   1.587    rillig }
    472   1.587    rillig 
    473   1.778    rillig /*
    474   1.802    rillig  * Find the variable in the scope, and maybe in other scopes as well.
    475   1.580    rillig  *
    476   1.580    rillig  * Input:
    477   1.607    rillig  *	name		name to find, is not expanded any further
    478   1.802    rillig  *	scope		scope in which to look first
    479   1.895    rillig  *	elsewhere	true to look in other scopes as well
    480   1.580    rillig  *
    481   1.580    rillig  * Results:
    482   1.605    rillig  *	The found variable, or NULL if the variable does not exist.
    483   1.977    rillig  *	If the variable is short-lived (such as environment variables), it
    484   1.977    rillig  *	must be freed using VarFreeShortLived after use.
    485   1.580    rillig  */
    486   1.580    rillig static Var *
    487   1.916    rillig VarFindSubstring(Substring name, GNode *scope, bool elsewhere)
    488   1.580    rillig {
    489   1.703    rillig 	Var *var;
    490  1.1160    rillig 	unsigned nameHash;
    491   1.703    rillig 
    492   1.830    rillig 	/* Replace '.TARGET' with '@', likewise for other local variables. */
    493   1.703    rillig 	name = CanonicalVarname(name);
    494   1.916    rillig 	nameHash = Hash_Substring(name);
    495   1.580    rillig 
    496   1.802    rillig 	var = GNode_FindVar(scope, name, nameHash);
    497   1.703    rillig 	if (!elsewhere)
    498   1.703    rillig 		return var;
    499   1.160  christos 
    500   1.802    rillig 	if (var == NULL && scope != SCOPE_CMDLINE)
    501   1.801    rillig 		var = GNode_FindVar(SCOPE_CMDLINE, name, nameHash);
    502     1.1       cgd 
    503   1.802    rillig 	if (!opts.checkEnvFirst && var == NULL && scope != SCOPE_GLOBAL) {
    504   1.801    rillig 		var = GNode_FindVar(SCOPE_GLOBAL, name, nameHash);
    505   1.802    rillig 		if (var == NULL && scope != SCOPE_INTERNAL) {
    506   1.801    rillig 			/* SCOPE_INTERNAL is subordinate to SCOPE_GLOBAL */
    507   1.801    rillig 			var = GNode_FindVar(SCOPE_INTERNAL, name, nameHash);
    508   1.703    rillig 		}
    509   1.184       sjg 	}
    510   1.399    rillig 
    511   1.703    rillig 	if (var == NULL) {
    512  1.1105    rillig 		FStr envName = Substring_Str(name);
    513  1.1105    rillig 		const char *envValue = getenv(envName.str);
    514   1.916    rillig 		if (envValue != NULL)
    515   1.978    rillig 			return VarNew(envName, envValue, true, true, false);
    516   1.916    rillig 		FStr_Done(&envName);
    517     1.1       cgd 
    518   1.802    rillig 		if (opts.checkEnvFirst && scope != SCOPE_GLOBAL) {
    519   1.801    rillig 			var = GNode_FindVar(SCOPE_GLOBAL, name, nameHash);
    520   1.802    rillig 			if (var == NULL && scope != SCOPE_INTERNAL)
    521   1.801    rillig 				var = GNode_FindVar(SCOPE_INTERNAL, name,
    522   1.703    rillig 				    nameHash);
    523   1.703    rillig 			return var;
    524   1.703    rillig 		}
    525   1.399    rillig 
    526   1.703    rillig 		return NULL;
    527     1.1       cgd 	}
    528   1.399    rillig 
    529   1.703    rillig 	return var;
    530     1.1       cgd }
    531     1.1       cgd 
    532   1.916    rillig static Var *
    533   1.916    rillig VarFind(const char *name, GNode *scope, bool elsewhere)
    534   1.916    rillig {
    535   1.916    rillig 	return VarFindSubstring(Substring_InitStr(name), scope, elsewhere);
    536   1.916    rillig }
    537   1.916    rillig 
    538   1.977    rillig /* If the variable is short-lived, free it, including its value. */
    539   1.837    rillig static void
    540   1.977    rillig VarFreeShortLived(Var *v)
    541   1.105  christos {
    542   1.978    rillig 	if (!v->shortLived)
    543   1.837    rillig 		return;
    544   1.605    rillig 
    545   1.711    rillig 	FStr_Done(&v->name);
    546   1.837    rillig 	Buf_Done(&v->val);
    547   1.703    rillig 	free(v);
    548   1.105  christos }
    549   1.105  christos 
    550  1.1018    rillig static const char *
    551  1.1018    rillig ValueDescription(const char *value)
    552  1.1018    rillig {
    553  1.1018    rillig 	if (value[0] == '\0')
    554  1.1018    rillig 		return "# (empty)";
    555  1.1019    rillig 	if (ch_isspace(value[strlen(value) - 1]))
    556  1.1018    rillig 		return "# (ends with space)";
    557  1.1018    rillig 	return "";
    558  1.1018    rillig }
    559  1.1018    rillig 
    560   1.831    rillig /* Add a new variable of the given name and value to the given scope. */
    561   1.833    rillig static Var *
    562   1.831    rillig VarAdd(const char *name, const char *value, GNode *scope, VarSetFlags flags)
    563     1.1       cgd {
    564   1.802    rillig 	HashEntry *he = HashTable_CreateEntry(&scope->vars, name, NULL);
    565   1.831    rillig 	Var *v = VarNew(FStr_InitRefer(/* aliased to */ he->key), value,
    566   1.978    rillig 	    false, false, (flags & VAR_SET_READONLY) != 0);
    567   1.703    rillig 	HashEntry_Set(he, v);
    568  1.1018    rillig 	DEBUG4(VAR, "%s: %s = %s%s\n",
    569  1.1018    rillig 	    scope->name, name, value, ValueDescription(value));
    570   1.833    rillig 	return v;
    571     1.1       cgd }
    572     1.1       cgd 
    573   1.736    rillig /*
    574   1.802    rillig  * Remove a variable from a scope, freeing all related memory as well.
    575   1.736    rillig  * The variable name is kept as-is, it is not expanded.
    576   1.736    rillig  */
    577   1.736    rillig void
    578   1.805    rillig Var_Delete(GNode *scope, const char *varname)
    579   1.736    rillig {
    580   1.802    rillig 	HashEntry *he = HashTable_FindEntry(&scope->vars, varname);
    581   1.736    rillig 	Var *v;
    582   1.736    rillig 
    583   1.736    rillig 	if (he == NULL) {
    584  1.1085    rillig 		DEBUG2(VAR, "%s: ignoring delete '%s' as it is not found\n",
    585  1.1017    rillig 		    scope->name, varname);
    586   1.736    rillig 		return;
    587   1.736    rillig 	}
    588   1.736    rillig 
    589   1.831    rillig 	v = he->value;
    590  1.1121    rillig 	if (v->readOnlyLoud) {
    591  1.1121    rillig 		Parse_Error(PARSE_FATAL,
    592  1.1121    rillig 		    "Cannot delete \"%s\" as it is read-only",
    593  1.1121    rillig 		    v->name.str);
    594  1.1121    rillig 		return;
    595  1.1121    rillig 	}
    596  1.1056       sjg 	if (v->readOnly) {
    597  1.1085    rillig 		DEBUG2(VAR, "%s: ignoring delete '%s' as it is read-only\n",
    598  1.1056       sjg 		    scope->name, varname);
    599  1.1056       sjg 		return;
    600  1.1056       sjg 	}
    601   1.963    rillig 	if (v->inUse) {
    602   1.963    rillig 		Parse_Error(PARSE_FATAL,
    603   1.969    rillig 		    "Cannot delete variable \"%s\" while it is used",
    604   1.963    rillig 		    v->name.str);
    605   1.963    rillig 		return;
    606   1.963    rillig 	}
    607  1.1017    rillig 
    608  1.1085    rillig 	DEBUG2(VAR, "%s: delete %s\n", scope->name, varname);
    609   1.902    rillig 	if (v->exported)
    610   1.736    rillig 		unsetenv(v->name.str);
    611  1.1045    rillig 	if (strcmp(v->name.str, ".MAKE.EXPORTED") == 0)
    612   1.736    rillig 		var_exportedVars = VAR_EXPORTED_NONE;
    613  1.1017    rillig 
    614   1.736    rillig 	assert(v->name.freeIt == NULL);
    615   1.802    rillig 	HashTable_DeleteEntry(&scope->vars, he);
    616   1.784    rillig 	Buf_Done(&v->val);
    617   1.736    rillig 	free(v);
    618   1.736    rillig }
    619   1.736    rillig 
    620  1.1111    rillig #ifdef CLEANUP
    621  1.1111    rillig void
    622  1.1111    rillig Var_DeleteAll(GNode *scope)
    623  1.1111    rillig {
    624  1.1113    rillig 	HashIter hi;
    625  1.1113    rillig 	HashIter_Init(&hi, &scope->vars);
    626  1.1114    rillig 	while (HashIter_Next(&hi)) {
    627  1.1113    rillig 		Var *v = hi.entry->value;
    628  1.1113    rillig 		Buf_Done(&v->val);
    629  1.1113    rillig 		free(v);
    630  1.1111    rillig 	}
    631  1.1111    rillig }
    632  1.1111    rillig #endif
    633  1.1111    rillig 
    634   1.778    rillig /*
    635   1.762    rillig  * Undefine one or more variables from the global scope.
    636   1.762    rillig  * The argument is expanded exactly once and then split into words.
    637   1.737    rillig  */
    638   1.735    rillig void
    639   1.762    rillig Var_Undef(const char *arg)
    640   1.735    rillig {
    641   1.762    rillig 	char *expanded;
    642   1.762    rillig 	Words varnames;
    643   1.762    rillig 	size_t i;
    644   1.762    rillig 
    645   1.762    rillig 	if (arg[0] == '\0') {
    646   1.762    rillig 		Parse_Error(PARSE_FATAL,
    647   1.762    rillig 		    "The .undef directive requires an argument");
    648   1.762    rillig 		return;
    649   1.762    rillig 	}
    650   1.735    rillig 
    651  1.1119    rillig 	expanded = Var_Subst(arg, SCOPE_GLOBAL, VARE_EVAL);
    652  1.1043    rillig 	if (expanded == var_Error) {
    653  1.1043    rillig 		/* TODO: Make this part of the code reachable. */
    654   1.737    rillig 		Parse_Error(PARSE_FATAL,
    655   1.762    rillig 		    "Error in variable names to be undefined");
    656   1.762    rillig 		return;
    657   1.762    rillig 	}
    658   1.762    rillig 
    659   1.895    rillig 	varnames = Str_Words(expanded, false);
    660   1.762    rillig 	if (varnames.len == 1 && varnames.words[0][0] == '\0')
    661   1.762    rillig 		varnames.len = 0;
    662   1.762    rillig 
    663   1.762    rillig 	for (i = 0; i < varnames.len; i++) {
    664   1.762    rillig 		const char *varname = varnames.words[i];
    665   1.804    rillig 		Global_Delete(varname);
    666   1.737    rillig 	}
    667   1.735    rillig 
    668   1.762    rillig 	Words_Free(varnames);
    669   1.763    rillig 	free(expanded);
    670   1.735    rillig }
    671   1.735    rillig 
    672   1.895    rillig static bool
    673   1.598    rillig MayExport(const char *name)
    674   1.118       sjg {
    675   1.703    rillig 	if (name[0] == '.')
    676   1.895    rillig 		return false;	/* skip internals */
    677   1.703    rillig 	if (name[0] == '-')
    678   1.895    rillig 		return false;	/* skip misnamed variables */
    679   1.703    rillig 	if (name[1] == '\0') {
    680   1.703    rillig 		/*
    681   1.703    rillig 		 * A single char.
    682   1.802    rillig 		 * If it is one of the variables that should only appear in
    683   1.802    rillig 		 * local scope, skip it, else we can get Var_Subst
    684   1.703    rillig 		 * into a loop.
    685   1.703    rillig 		 */
    686   1.703    rillig 		switch (name[0]) {
    687   1.703    rillig 		case '@':
    688   1.703    rillig 		case '%':
    689   1.703    rillig 		case '*':
    690   1.703    rillig 		case '!':
    691   1.895    rillig 			return false;
    692   1.703    rillig 		}
    693   1.118       sjg 	}
    694   1.895    rillig 	return true;
    695   1.598    rillig }
    696   1.598    rillig 
    697   1.895    rillig static bool
    698  1.1100       sjg ExportVarEnv(Var *v, GNode *scope)
    699   1.776    rillig {
    700   1.776    rillig 	const char *name = v->name.str;
    701   1.777    rillig 	char *val = v->val.data;
    702   1.777    rillig 	char *expr;
    703   1.776    rillig 
    704   1.902    rillig 	if (v->exported && !v->reexport)
    705   1.895    rillig 		return false;	/* nothing to do */
    706   1.776    rillig 
    707   1.777    rillig 	if (strchr(val, '$') == NULL) {
    708   1.902    rillig 		if (!v->exported)
    709   1.776    rillig 			setenv(name, val, 1);
    710   1.895    rillig 		return true;
    711   1.776    rillig 	}
    712   1.776    rillig 
    713  1.1070    rillig 	if (v->inUse)
    714  1.1070    rillig 		return false;	/* see EMPTY_SHELL in directive-export.mk */
    715   1.776    rillig 
    716   1.777    rillig 	/* XXX: name is injected without escaping it */
    717   1.777    rillig 	expr = str_concat3("${", name, "}");
    718  1.1119    rillig 	val = Var_Subst(expr, scope, VARE_EVAL);
    719  1.1100       sjg 	if (scope != SCOPE_GLOBAL) {
    720  1.1101    rillig 		/* we will need to re-export the global version */
    721  1.1100       sjg 		v = VarFind(name, SCOPE_GLOBAL, false);
    722  1.1101    rillig 		if (v != NULL)
    723  1.1100       sjg 			v->exported = false;
    724  1.1100       sjg 	}
    725   1.777    rillig 	/* TODO: handle errors */
    726   1.777    rillig 	setenv(name, val, 1);
    727   1.777    rillig 	free(val);
    728   1.777    rillig 	free(expr);
    729   1.895    rillig 	return true;
    730   1.776    rillig }
    731   1.776    rillig 
    732   1.895    rillig static bool
    733   1.776    rillig ExportVarPlain(Var *v)
    734   1.598    rillig {
    735   1.777    rillig 	if (strchr(v->val.data, '$') == NULL) {
    736   1.777    rillig 		setenv(v->name.str, v->val.data, 1);
    737   1.902    rillig 		v->exported = true;
    738   1.902    rillig 		v->reexport = false;
    739   1.895    rillig 		return true;
    740   1.776    rillig 	}
    741   1.776    rillig 
    742   1.777    rillig 	/*
    743   1.777    rillig 	 * Flag the variable as something we need to re-export.
    744   1.777    rillig 	 * No point actually exporting it now though,
    745   1.777    rillig 	 * the child process can do it at the last minute.
    746   1.830    rillig 	 * Avoid calling setenv more often than necessary since it can leak.
    747   1.777    rillig 	 */
    748   1.902    rillig 	v->exported = true;
    749   1.902    rillig 	v->reexport = true;
    750   1.895    rillig 	return true;
    751   1.776    rillig }
    752   1.401    rillig 
    753   1.895    rillig static bool
    754   1.776    rillig ExportVarLiteral(Var *v)
    755   1.776    rillig {
    756   1.902    rillig 	if (v->exported && !v->reexport)
    757   1.895    rillig 		return false;
    758   1.401    rillig 
    759   1.902    rillig 	if (!v->exported)
    760   1.777    rillig 		setenv(v->name.str, v->val.data, 1);
    761   1.605    rillig 
    762   1.895    rillig 	return true;
    763   1.118       sjg }
    764   1.118       sjg 
    765   1.118       sjg /*
    766   1.830    rillig  * Mark a single variable to be exported later for subprocesses.
    767   1.776    rillig  *
    768  1.1088    rillig  * Internal variables are not exported.
    769   1.776    rillig  */
    770   1.895    rillig static bool
    771  1.1100       sjg ExportVar(const char *name, GNode *scope, VarExportMode mode)
    772   1.776    rillig {
    773   1.776    rillig 	Var *v;
    774   1.776    rillig 
    775   1.776    rillig 	if (!MayExport(name))
    776   1.895    rillig 		return false;
    777   1.776    rillig 
    778  1.1100       sjg 	v = VarFind(name, scope, false);
    779  1.1100       sjg 	if (v == NULL && scope != SCOPE_GLOBAL)
    780  1.1100       sjg 		v = VarFind(name, SCOPE_GLOBAL, false);
    781   1.776    rillig 	if (v == NULL)
    782   1.895    rillig 		return false;
    783   1.776    rillig 
    784   1.776    rillig 	if (mode == VEM_ENV)
    785  1.1100       sjg 		return ExportVarEnv(v, scope);
    786   1.776    rillig 	else if (mode == VEM_PLAIN)
    787   1.776    rillig 		return ExportVarPlain(v);
    788   1.776    rillig 	else
    789   1.776    rillig 		return ExportVarLiteral(v);
    790   1.776    rillig }
    791   1.776    rillig 
    792   1.776    rillig /*
    793   1.765    rillig  * Actually export the variables that have been marked as needing to be
    794   1.765    rillig  * re-exported.
    795   1.118       sjg  */
    796   1.118       sjg void
    797  1.1100       sjg Var_ReexportVars(GNode *scope)
    798   1.118       sjg {
    799   1.775    rillig 	char *xvarnames;
    800   1.412    rillig 
    801   1.703    rillig 	/*
    802   1.703    rillig 	 * Several make implementations support this sort of mechanism for
    803   1.703    rillig 	 * tracking recursion - but each uses a different name.
    804   1.703    rillig 	 * We allow the makefiles to update MAKELEVEL and ensure
    805   1.703    rillig 	 * children see a correctly incremented value.
    806   1.703    rillig 	 */
    807  1.1067    rillig 	char level_buf[21];
    808  1.1067    rillig 	snprintf(level_buf, sizeof level_buf, "%d", makelevel + 1);
    809  1.1067    rillig 	setenv(MAKE_LEVEL_ENV, level_buf, 1);
    810   1.182  christos 
    811   1.703    rillig 	if (var_exportedVars == VAR_EXPORTED_NONE)
    812   1.703    rillig 		return;
    813   1.118       sjg 
    814   1.703    rillig 	if (var_exportedVars == VAR_EXPORTED_ALL) {
    815   1.703    rillig 		HashIter hi;
    816   1.575    rillig 
    817   1.831    rillig 		/* Ouch! Exporting all variables at once is crazy. */
    818   1.801    rillig 		HashIter_Init(&hi, &SCOPE_GLOBAL->vars);
    819  1.1114    rillig 		while (HashIter_Next(&hi)) {
    820   1.703    rillig 			Var *var = hi.entry->value;
    821  1.1100       sjg 			ExportVar(var->name.str, scope, VEM_ENV);
    822   1.703    rillig 		}
    823   1.703    rillig 		return;
    824   1.575    rillig 	}
    825   1.369    rillig 
    826  1.1045    rillig 	xvarnames = Var_Subst("${.MAKE.EXPORTED:O:u}", SCOPE_GLOBAL,
    827  1.1119    rillig 	    VARE_EVAL);
    828   1.703    rillig 	/* TODO: handle errors */
    829   1.775    rillig 	if (xvarnames[0] != '\0') {
    830   1.895    rillig 		Words varnames = Str_Words(xvarnames, false);
    831   1.703    rillig 		size_t i;
    832   1.703    rillig 
    833   1.775    rillig 		for (i = 0; i < varnames.len; i++)
    834  1.1100       sjg 			ExportVar(varnames.words[i], scope, VEM_ENV);
    835   1.775    rillig 		Words_Free(varnames);
    836   1.703    rillig 	}
    837   1.775    rillig 	free(xvarnames);
    838   1.118       sjg }
    839   1.118       sjg 
    840   1.726    rillig static void
    841   1.895    rillig ExportVars(const char *varnames, bool isExport, VarExportMode mode)
    842   1.831    rillig /* TODO: try to combine the parameters 'isExport' and 'mode'. */
    843   1.726    rillig {
    844   1.895    rillig 	Words words = Str_Words(varnames, false);
    845   1.727    rillig 	size_t i;
    846   1.727    rillig 
    847   1.727    rillig 	if (words.len == 1 && words.words[0][0] == '\0')
    848   1.727    rillig 		words.len = 0;
    849   1.727    rillig 
    850   1.727    rillig 	for (i = 0; i < words.len; i++) {
    851   1.727    rillig 		const char *varname = words.words[i];
    852  1.1100       sjg 		if (!ExportVar(varname, SCOPE_GLOBAL, mode))
    853   1.727    rillig 			continue;
    854   1.727    rillig 
    855   1.727    rillig 		if (var_exportedVars == VAR_EXPORTED_NONE)
    856   1.727    rillig 			var_exportedVars = VAR_EXPORTED_SOME;
    857   1.726    rillig 
    858   1.765    rillig 		if (isExport && mode == VEM_PLAIN)
    859  1.1045    rillig 			Global_Append(".MAKE.EXPORTED", varname);
    860   1.726    rillig 	}
    861   1.727    rillig 	Words_Free(words);
    862   1.726    rillig }
    863   1.726    rillig 
    864   1.728    rillig static void
    865   1.895    rillig ExportVarsExpand(const char *uvarnames, bool isExport, VarExportMode mode)
    866   1.728    rillig {
    867  1.1119    rillig 	char *xvarnames = Var_Subst(uvarnames, SCOPE_GLOBAL, VARE_EVAL);
    868   1.728    rillig 	/* TODO: handle errors */
    869   1.730    rillig 	ExportVars(xvarnames, isExport, mode);
    870   1.728    rillig 	free(xvarnames);
    871   1.728    rillig }
    872   1.728    rillig 
    873   1.731    rillig /* Export the named variables, or all variables. */
    874   1.118       sjg void
    875   1.731    rillig Var_Export(VarExportMode mode, const char *varnames)
    876   1.118       sjg {
    877  1.1117       sjg 	if (mode == VEM_ALL) {
    878   1.703    rillig 		var_exportedVars = VAR_EXPORTED_ALL; /* use with caution! */
    879   1.703    rillig 		return;
    880  1.1117       sjg 	} else if (mode == VEM_PLAIN && varnames[0] == '\0') {
    881  1.1117       sjg 		Parse_Error(PARSE_WARNING, ".export requires an argument.");
    882  1.1117       sjg 		return;
    883   1.703    rillig 	}
    884   1.118       sjg 
    885   1.895    rillig 	ExportVarsExpand(varnames, true, mode);
    886   1.729    rillig }
    887   1.729    rillig 
    888   1.729    rillig void
    889   1.729    rillig Var_ExportVars(const char *varnames)
    890   1.729    rillig {
    891   1.895    rillig 	ExportVarsExpand(varnames, false, VEM_PLAIN);
    892   1.118       sjg }
    893   1.118       sjg 
    894   1.155       sjg 
    895   1.700    rillig static void
    896   1.714    rillig ClearEnv(void)
    897   1.701    rillig {
    898  1.1083    rillig 	const char *level;
    899   1.701    rillig 	char **newenv;
    900   1.701    rillig 
    901  1.1083    rillig 	level = getenv(MAKE_LEVEL_ENV);	/* we should preserve this */
    902   1.701    rillig 	if (environ == savedEnv) {
    903   1.701    rillig 		/* we have been here before! */
    904   1.701    rillig 		newenv = bmake_realloc(environ, 2 * sizeof(char *));
    905   1.701    rillig 	} else {
    906   1.701    rillig 		if (savedEnv != NULL) {
    907   1.701    rillig 			free(savedEnv);
    908   1.701    rillig 			savedEnv = NULL;
    909   1.701    rillig 		}
    910   1.701    rillig 		newenv = bmake_malloc(2 * sizeof(char *));
    911   1.701    rillig 	}
    912   1.701    rillig 
    913   1.701    rillig 	/* Note: we cannot safely free() the original environ. */
    914   1.701    rillig 	environ = savedEnv = newenv;
    915   1.701    rillig 	newenv[0] = NULL;
    916   1.701    rillig 	newenv[1] = NULL;
    917  1.1083    rillig 	if (level != NULL && *level != '\0')
    918  1.1083    rillig 		setenv(MAKE_LEVEL_ENV, level, 1);
    919   1.701    rillig }
    920   1.701    rillig 
    921   1.701    rillig static void
    922   1.895    rillig GetVarnamesToUnexport(bool isEnv, const char *arg,
    923   1.715    rillig 		      FStr *out_varnames, UnexportWhat *out_what)
    924   1.714    rillig {
    925   1.714    rillig 	UnexportWhat what;
    926   1.739    rillig 	FStr varnames = FStr_InitRefer("");
    927   1.714    rillig 
    928   1.732    rillig 	if (isEnv) {
    929   1.732    rillig 		if (arg[0] != '\0') {
    930   1.723    rillig 			Parse_Error(PARSE_FATAL,
    931   1.723    rillig 			    "The directive .unexport-env does not take "
    932   1.723    rillig 			    "arguments");
    933   1.830    rillig 			/* continue anyway */
    934   1.723    rillig 		}
    935   1.714    rillig 		what = UNEXPORT_ENV;
    936   1.723    rillig 
    937   1.732    rillig 	} else {
    938   1.732    rillig 		what = arg[0] != '\0' ? UNEXPORT_NAMED : UNEXPORT_ALL;
    939   1.714    rillig 		if (what == UNEXPORT_NAMED)
    940   1.739    rillig 			varnames = FStr_InitRefer(arg);
    941   1.714    rillig 	}
    942   1.714    rillig 
    943   1.714    rillig 	if (what != UNEXPORT_NAMED) {
    944  1.1045    rillig 		char *expanded = Var_Subst("${.MAKE.EXPORTED:O:u}",
    945  1.1119    rillig 		    SCOPE_GLOBAL, VARE_EVAL);
    946   1.714    rillig 		/* TODO: handle errors */
    947   1.739    rillig 		varnames = FStr_InitOwn(expanded);
    948   1.714    rillig 	}
    949   1.714    rillig 
    950   1.714    rillig 	*out_varnames = varnames;
    951   1.714    rillig 	*out_what = what;
    952   1.714    rillig }
    953   1.714    rillig 
    954   1.714    rillig static void
    955   1.959    rillig UnexportVar(Substring varname, UnexportWhat what)
    956   1.700    rillig {
    957   1.959    rillig 	Var *v = VarFindSubstring(varname, SCOPE_GLOBAL, false);
    958   1.700    rillig 	if (v == NULL) {
    959   1.959    rillig 		DEBUG2(VAR, "Not unexporting \"%.*s\" (not found)\n",
    960   1.959    rillig 		    (int)Substring_Length(varname), varname.start);
    961   1.700    rillig 		return;
    962   1.700    rillig 	}
    963   1.700    rillig 
    964   1.959    rillig 	DEBUG2(VAR, "Unexporting \"%.*s\"\n",
    965   1.959    rillig 	    (int)Substring_Length(varname), varname.start);
    966   1.902    rillig 	if (what != UNEXPORT_ENV && v->exported && !v->reexport)
    967   1.711    rillig 		unsetenv(v->name.str);
    968   1.902    rillig 	v->exported = false;
    969   1.902    rillig 	v->reexport = false;
    970   1.700    rillig 
    971   1.713    rillig 	if (what == UNEXPORT_NAMED) {
    972   1.713    rillig 		/* Remove the variable names from .MAKE.EXPORTED. */
    973   1.700    rillig 		/* XXX: v->name is injected without escaping it */
    974  1.1083    rillig 		char *expr = str_concat3(
    975  1.1083    rillig 		    "${.MAKE.EXPORTED:N", v->name.str, "}");
    976  1.1119    rillig 		char *filtered = Var_Subst(expr, SCOPE_GLOBAL, VARE_EVAL);
    977   1.700    rillig 		/* TODO: handle errors */
    978  1.1083    rillig 		Global_Set(".MAKE.EXPORTED", filtered);
    979  1.1083    rillig 		free(filtered);
    980   1.700    rillig 		free(expr);
    981   1.700    rillig 	}
    982   1.700    rillig }
    983   1.700    rillig 
    984   1.716    rillig static void
    985  1.1142    rillig UnexportVars(const char *varnames, UnexportWhat what)
    986   1.716    rillig {
    987   1.716    rillig 	size_t i;
    988   1.959    rillig 	SubstringWords words;
    989   1.717    rillig 
    990   1.717    rillig 	if (what == UNEXPORT_ENV)
    991   1.717    rillig 		ClearEnv();
    992   1.716    rillig 
    993  1.1142    rillig 	words = Substring_Words(varnames, false);
    994   1.959    rillig 	for (i = 0; i < words.len; i++)
    995   1.959    rillig 		UnexportVar(words.words[i], what);
    996   1.959    rillig 	SubstringWords_Free(words);
    997   1.716    rillig 
    998   1.716    rillig 	if (what != UNEXPORT_NAMED)
    999  1.1045    rillig 		Global_Delete(".MAKE.EXPORTED");
   1000   1.716    rillig }
   1001   1.716    rillig 
   1002  1.1088    rillig /* Handle the .unexport and .unexport-env directives. */
   1003   1.155       sjg void
   1004   1.895    rillig Var_UnExport(bool isEnv, const char *arg)
   1005   1.155       sjg {
   1006   1.713    rillig 	UnexportWhat what;
   1007   1.714    rillig 	FStr varnames;
   1008   1.155       sjg 
   1009   1.732    rillig 	GetVarnamesToUnexport(isEnv, arg, &varnames, &what);
   1010  1.1142    rillig 	UnexportVars(varnames.str, what);
   1011   1.712    rillig 	FStr_Done(&varnames);
   1012   1.155       sjg }
   1013   1.155       sjg 
   1014   1.747    rillig /* Set the variable to the value; the name is not expanded. */
   1015   1.800    rillig void
   1016   1.805    rillig Var_SetWithFlags(GNode *scope, const char *name, const char *val,
   1017   1.800    rillig 		 VarSetFlags flags)
   1018     1.1       cgd {
   1019   1.704    rillig 	Var *v;
   1020   1.142       dsl 
   1021   1.793    rillig 	assert(val != NULL);
   1022   1.793    rillig 	if (name[0] == '\0') {
   1023  1.1086    rillig 		DEBUG3(VAR,
   1024  1.1086    rillig 		    "%s: ignoring '%s = %s' as the variable name is empty\n",
   1025  1.1086    rillig 		    scope->name, name, val);
   1026   1.793    rillig 		return;
   1027   1.793    rillig 	}
   1028   1.793    rillig 
   1029  1.1089    rillig 	if (scope == SCOPE_GLOBAL
   1030  1.1089    rillig 	    && VarFind(name, SCOPE_CMDLINE, false) != NULL) {
   1031  1.1089    rillig 		/*
   1032  1.1089    rillig 		 * The global variable would not be visible anywhere.
   1033  1.1089    rillig 		 * Therefore, there is no point in setting it at all.
   1034  1.1089    rillig 		 */
   1035  1.1082    rillig 		DEBUG3(VAR,
   1036  1.1086    rillig 		    "%s: ignoring '%s = %s' "
   1037  1.1082    rillig 		    "due to a command line variable of the same name\n",
   1038  1.1086    rillig 		    scope->name, name, val);
   1039   1.834    rillig 		return;
   1040  1.1080    rillig 	}
   1041   1.400    rillig 
   1042   1.704    rillig 	/*
   1043   1.802    rillig 	 * Only look for a variable in the given scope since anything set
   1044   1.802    rillig 	 * here will override anything in a lower scope, so there's not much
   1045   1.830    rillig 	 * point in searching them all.
   1046   1.704    rillig 	 */
   1047   1.895    rillig 	v = VarFind(name, scope, false);
   1048   1.704    rillig 	if (v == NULL) {
   1049   1.802    rillig 		if (scope == SCOPE_CMDLINE && !(flags & VAR_SET_NO_EXPORT)) {
   1050   1.704    rillig 			/*
   1051  1.1105    rillig 			 * This variable would normally prevent the same name
   1052  1.1105    rillig 			 * being added to SCOPE_GLOBAL, so delete it from
   1053  1.1105    rillig 			 * there if needed. Otherwise -V name may show the
   1054  1.1105    rillig 			 * wrong value.
   1055   1.832    rillig 			 *
   1056   1.835    rillig 			 * See ExistsInCmdline.
   1057   1.704    rillig 			 */
   1058  1.1141    rillig 			Var *gl = VarFind(name, SCOPE_GLOBAL, false);
   1059  1.1145    rillig 			if (gl != NULL && strcmp(gl->val.data, val) == 0) {
   1060  1.1145    rillig 				DEBUG3(VAR,
   1061  1.1145    rillig 				    "%s: ignoring to override the global "
   1062  1.1145    rillig 				    "'%s = %s' from a command line variable "
   1063  1.1145    rillig 				    "as the value wouldn't change\n",
   1064  1.1145    rillig 				    scope->name, name, val);
   1065  1.1145    rillig 			} else if (gl != NULL && gl->readOnlyLoud)
   1066  1.1141    rillig 				Parse_Error(PARSE_FATAL,
   1067  1.1141    rillig 				    "Cannot override "
   1068  1.1141    rillig 				    "read-only global variable \"%s\" "
   1069  1.1141    rillig 				    "with a command line variable", name);
   1070  1.1141    rillig 			else
   1071  1.1141    rillig 				Var_Delete(SCOPE_GLOBAL, name);
   1072   1.704    rillig 		}
   1073   1.973       sjg 		if (strcmp(name, ".SUFFIXES") == 0) {
   1074  1.1079    rillig 			/* special: treat as read-only */
   1075  1.1086    rillig 			DEBUG3(VAR,
   1076  1.1086    rillig 			    "%s: ignoring '%s = %s' as it is read-only\n",
   1077   1.973       sjg 			    scope->name, name, val);
   1078   1.973       sjg 			return;
   1079   1.973       sjg 		}
   1080   1.833    rillig 		v = VarAdd(name, val, scope, flags);
   1081   1.704    rillig 	} else {
   1082  1.1121    rillig 		if (v->readOnlyLoud) {
   1083  1.1121    rillig 			Parse_Error(PARSE_FATAL,
   1084  1.1121    rillig 			    "Cannot overwrite \"%s\" as it is read-only",
   1085  1.1121    rillig 			    name);
   1086  1.1121    rillig 			return;
   1087  1.1121    rillig 		}
   1088   1.902    rillig 		if (v->readOnly && !(flags & VAR_SET_READONLY)) {
   1089  1.1086    rillig 			DEBUG3(VAR,
   1090  1.1086    rillig 			    "%s: ignoring '%s = %s' as it is read-only\n",
   1091   1.802    rillig 			    scope->name, name, val);
   1092   1.747    rillig 			return;
   1093   1.704    rillig 		}
   1094   1.998    rillig 		Buf_Clear(&v->val);
   1095   1.704    rillig 		Buf_AddStr(&v->val, val);
   1096   1.704    rillig 
   1097  1.1018    rillig 		DEBUG4(VAR, "%s: %s = %s%s\n",
   1098  1.1018    rillig 		    scope->name, name, val, ValueDescription(val));
   1099   1.902    rillig 		if (v->exported)
   1100  1.1100       sjg 			ExportVar(name, scope, VEM_PLAIN);
   1101   1.183       sjg 	}
   1102   1.833    rillig 
   1103  1.1076       sjg 	if (scope == SCOPE_CMDLINE) {
   1104   1.902    rillig 		v->fromCmd = true;
   1105  1.1079    rillig 
   1106  1.1079    rillig 		/*
   1107  1.1079    rillig 		 * Any variables given on the command line are automatically
   1108  1.1079    rillig 		 * exported to the environment (as per POSIX standard), except
   1109  1.1079    rillig 		 * for internals.
   1110  1.1079    rillig 		 */
   1111  1.1109       sjg 		if (!(flags & VAR_SET_NO_EXPORT)) {
   1112   1.704    rillig 
   1113  1.1076       sjg 			/*
   1114  1.1076       sjg 			 * If requested, don't export these in the
   1115  1.1076       sjg 			 * environment individually.  We still put
   1116  1.1076       sjg 			 * them in .MAKEOVERRIDES so that the
   1117  1.1077    rillig 			 * command-line settings continue to override
   1118  1.1076       sjg 			 * Makefile settings.
   1119  1.1076       sjg 			 */
   1120  1.1109       sjg 			if (!opts.varNoExportEnv && name[0] != '.')
   1121  1.1076       sjg 				setenv(name, val, 1);
   1122  1.1109       sjg 
   1123  1.1109       sjg 			if (!(flags & VAR_SET_INTERNAL))
   1124  1.1109       sjg 				Global_Append(".MAKEOVERRIDES", name);
   1125  1.1076       sjg 		}
   1126   1.704    rillig 	}
   1127   1.833    rillig 
   1128   1.704    rillig 	if (name[0] == '.' && strcmp(name, MAKE_SAVE_DOLLARS) == 0)
   1129   1.704    rillig 		save_dollars = ParseBoolean(val, save_dollars);
   1130   1.205       sjg 
   1131   1.704    rillig 	if (v != NULL)
   1132   1.977    rillig 		VarFreeShortLived(v);
   1133     1.1       cgd }
   1134     1.1       cgd 
   1135   1.798    rillig void
   1136   1.805    rillig Var_Set(GNode *scope, const char *name, const char *val)
   1137   1.798    rillig {
   1138   1.805    rillig 	Var_SetWithFlags(scope, name, val, VAR_SET_NONE);
   1139   1.798    rillig }
   1140   1.798    rillig 
   1141   1.718    rillig /*
   1142  1.1079    rillig  * In the scope, expand the variable name once, then create the variable or
   1143  1.1079    rillig  * replace its value.
   1144   1.230    rillig  */
   1145   1.230    rillig void
   1146   1.805    rillig Var_SetExpand(GNode *scope, const char *name, const char *val)
   1147   1.230    rillig {
   1148  1.1007    rillig 	FStr varname = FStr_InitRefer(name);
   1149  1.1007    rillig 
   1150  1.1007    rillig 	assert(val != NULL);
   1151  1.1007    rillig 
   1152  1.1119    rillig 	Var_Expand(&varname, scope, VARE_EVAL);
   1153  1.1007    rillig 
   1154  1.1007    rillig 	if (varname.str[0] == '\0') {
   1155  1.1086    rillig 		DEBUG4(VAR,
   1156  1.1086    rillig 		    "%s: ignoring '%s = %s' "
   1157  1.1086    rillig 		    "as the variable name '%s' expands to empty\n",
   1158  1.1089    rillig 		    scope->name, varname.str, val, name);
   1159  1.1007    rillig 	} else
   1160  1.1007    rillig 		Var_SetWithFlags(scope, varname.str, val, VAR_SET_NONE);
   1161  1.1007    rillig 
   1162  1.1007    rillig 	FStr_Done(&varname);
   1163   1.230    rillig }
   1164   1.230    rillig 
   1165   1.791    rillig void
   1166   1.792    rillig Global_Set(const char *name, const char *value)
   1167   1.792    rillig {
   1168   1.805    rillig 	Var_Set(SCOPE_GLOBAL, name, value);
   1169   1.792    rillig }
   1170   1.792    rillig 
   1171   1.792    rillig void
   1172   1.804    rillig Global_Delete(const char *name)
   1173   1.804    rillig {
   1174   1.805    rillig 	Var_Delete(SCOPE_GLOBAL, name);
   1175   1.804    rillig }
   1176   1.804    rillig 
   1177  1.1039       sjg void
   1178  1.1039       sjg Global_Set_ReadOnly(const char *name, const char *value)
   1179  1.1039       sjg {
   1180  1.1121    rillig 	Var_SetWithFlags(SCOPE_GLOBAL, name, value, VAR_SET_NONE);
   1181  1.1121    rillig 	VarFind(name, SCOPE_GLOBAL, false)->readOnlyLoud = true;
   1182  1.1039       sjg }
   1183  1.1039       sjg 
   1184   1.718    rillig /*
   1185   1.794    rillig  * Append the value to the named variable.
   1186   1.794    rillig  *
   1187   1.794    rillig  * If the variable doesn't exist, it is created.  Otherwise a single space
   1188   1.794    rillig  * and the given value are appended.
   1189   1.794    rillig  */
   1190   1.794    rillig void
   1191   1.805    rillig Var_Append(GNode *scope, const char *name, const char *val)
   1192   1.794    rillig {
   1193   1.794    rillig 	Var *v;
   1194   1.794    rillig 
   1195   1.802    rillig 	v = VarFind(name, scope, scope == SCOPE_GLOBAL);
   1196   1.794    rillig 
   1197   1.794    rillig 	if (v == NULL) {
   1198   1.805    rillig 		Var_SetWithFlags(scope, name, val, VAR_SET_NONE);
   1199  1.1121    rillig 	} else if (v->readOnlyLoud) {
   1200  1.1121    rillig 		Parse_Error(PARSE_FATAL,
   1201  1.1121    rillig 		    "Cannot append to \"%s\" as it is read-only", name);
   1202  1.1121    rillig 		return;
   1203   1.902    rillig 	} else if (v->readOnly) {
   1204  1.1086    rillig 		DEBUG3(VAR, "%s: ignoring '%s += %s' as it is read-only\n",
   1205  1.1086    rillig 		    scope->name, name, val);
   1206   1.902    rillig 	} else if (scope == SCOPE_CMDLINE || !v->fromCmd) {
   1207   1.794    rillig 		Buf_AddByte(&v->val, ' ');
   1208   1.794    rillig 		Buf_AddStr(&v->val, val);
   1209   1.794    rillig 
   1210   1.911    rillig 		DEBUG3(VAR, "%s: %s = %s\n", scope->name, name, v->val.data);
   1211   1.794    rillig 
   1212   1.978    rillig 		if (v->fromEnvironment) {
   1213  1.1014    rillig 			/* See VarAdd. */
   1214  1.1014    rillig 			HashEntry *he =
   1215  1.1014    rillig 			    HashTable_CreateEntry(&scope->vars, name, NULL);
   1216  1.1014    rillig 			HashEntry_Set(he, v);
   1217  1.1014    rillig 			FStr_Done(&v->name);
   1218  1.1014    rillig 			v->name = FStr_InitRefer(/* aliased to */ he->key);
   1219  1.1014    rillig 			v->shortLived = false;
   1220   1.978    rillig 			v->fromEnvironment = false;
   1221   1.794    rillig 		}
   1222   1.794    rillig 	}
   1223   1.794    rillig }
   1224   1.794    rillig 
   1225   1.794    rillig /*
   1226  1.1088    rillig  * In the scope, expand the variable name once.  If the variable exists in the
   1227  1.1088    rillig  * scope, add a space and the value, otherwise set the variable to the value.
   1228   1.483    rillig  *
   1229  1.1088    rillig  * Appending to an environment variable only works in the global scope, that
   1230  1.1088    rillig  * is, for variable assignments in makefiles, but not inside conditions or the
   1231  1.1088    rillig  * commands of a target.
   1232     1.1       cgd  */
   1233     1.1       cgd void
   1234   1.805    rillig Var_AppendExpand(GNode *scope, const char *name, const char *val)
   1235     1.1       cgd {
   1236   1.838    rillig 	FStr xname = FStr_InitRefer(name);
   1237     1.1       cgd 
   1238   1.704    rillig 	assert(val != NULL);
   1239   1.460    rillig 
   1240  1.1119    rillig 	Var_Expand(&xname, scope, VARE_EVAL);
   1241  1.1001    rillig 	if (xname.str != name && xname.str[0] == '\0')
   1242  1.1086    rillig 		DEBUG4(VAR,
   1243  1.1086    rillig 		    "%s: ignoring '%s += %s' "
   1244  1.1086    rillig 		    "as the variable name '%s' expands to empty\n",
   1245  1.1086    rillig 		    scope->name, xname.str, val, name);
   1246  1.1001    rillig 	else
   1247  1.1001    rillig 		Var_Append(scope, xname.str, val);
   1248     1.1       cgd 
   1249   1.838    rillig 	FStr_Done(&xname);
   1250     1.1       cgd }
   1251     1.1       cgd 
   1252   1.791    rillig void
   1253   1.795    rillig Global_Append(const char *name, const char *value)
   1254   1.791    rillig {
   1255   1.805    rillig 	Var_Append(SCOPE_GLOBAL, name, value);
   1256   1.791    rillig }
   1257   1.791    rillig 
   1258   1.895    rillig bool
   1259   1.805    rillig Var_Exists(GNode *scope, const char *name)
   1260   1.796    rillig {
   1261   1.895    rillig 	Var *v = VarFind(name, scope, true);
   1262   1.796    rillig 	if (v == NULL)
   1263   1.895    rillig 		return false;
   1264   1.796    rillig 
   1265   1.977    rillig 	VarFreeShortLived(v);
   1266   1.895    rillig 	return true;
   1267   1.796    rillig }
   1268   1.796    rillig 
   1269   1.778    rillig /*
   1270   1.802    rillig  * See if the given variable exists, in the given scope or in other
   1271   1.802    rillig  * fallback scopes.
   1272     1.1       cgd  *
   1273    1.70       wiz  * Input:
   1274   1.953    rillig  *	scope		scope in which to start search
   1275   1.953    rillig  *	name		name of the variable to find, is expanded once
   1276     1.1       cgd  */
   1277   1.895    rillig bool
   1278   1.805    rillig Var_ExistsExpand(GNode *scope, const char *name)
   1279     1.1       cgd {
   1280   1.747    rillig 	FStr varname = FStr_InitRefer(name);
   1281   1.895    rillig 	bool exists;
   1282   1.412    rillig 
   1283  1.1119    rillig 	Var_Expand(&varname, scope, VARE_EVAL);
   1284   1.805    rillig 	exists = Var_Exists(scope, varname.str);
   1285   1.747    rillig 	FStr_Done(&varname);
   1286   1.796    rillig 	return exists;
   1287     1.1       cgd }
   1288     1.1       cgd 
   1289   1.718    rillig /*
   1290   1.802    rillig  * Return the unexpanded value of the given variable in the given scope,
   1291  1.1066    rillig  * falling back to the command, global and environment scopes, in this order,
   1292  1.1066    rillig  * but see the -e option.
   1293     1.1       cgd  *
   1294    1.70       wiz  * Input:
   1295  1.1066    rillig  *	name		the name to find, is not expanded any further
   1296    1.70       wiz  *
   1297     1.1       cgd  * Results:
   1298   1.337    rillig  *	The value if the variable exists, NULL if it doesn't.
   1299   1.830    rillig  *	The value is valid until the next modification to any variable.
   1300     1.1       cgd  */
   1301   1.745    rillig FStr
   1302   1.805    rillig Var_Value(GNode *scope, const char *name)
   1303     1.1       cgd {
   1304   1.895    rillig 	Var *v = VarFind(name, scope, true);
   1305   1.703    rillig 	char *value;
   1306   1.703    rillig 
   1307   1.703    rillig 	if (v == NULL)
   1308   1.745    rillig 		return FStr_InitRefer(NULL);
   1309   1.412    rillig 
   1310   1.978    rillig 	if (!v->shortLived)
   1311   1.837    rillig 		return FStr_InitRefer(v->val.data);
   1312   1.837    rillig 
   1313   1.978    rillig 	value = v->val.data;
   1314   1.978    rillig 	v->val.data = NULL;
   1315   1.978    rillig 	VarFreeShortLived(v);
   1316   1.978    rillig 
   1317   1.837    rillig 	return FStr_InitOwn(value);
   1318     1.1       cgd }
   1319     1.1       cgd 
   1320  1.1088    rillig /* Set or clear the read-only attribute of the variable if it exists. */
   1321  1.1037       sjg void
   1322  1.1037       sjg Var_ReadOnly(const char *name, bool bf)
   1323  1.1037       sjg {
   1324  1.1037       sjg 	Var *v;
   1325  1.1037       sjg 
   1326  1.1037       sjg 	v = VarFind(name, SCOPE_GLOBAL, false);
   1327  1.1037       sjg 	if (v == NULL) {
   1328  1.1037       sjg 		DEBUG1(VAR, "Var_ReadOnly: %s not found\n", name);
   1329  1.1037       sjg 		return;
   1330  1.1037       sjg 	}
   1331  1.1037       sjg 	v->readOnly = bf;
   1332  1.1038       sjg 	DEBUG2(VAR, "Var_ReadOnly: %s %s\n", name, bf ? "true" : "false");
   1333  1.1037       sjg }
   1334  1.1037       sjg 
   1335  1.1037       sjg /*
   1336   1.778    rillig  * Return the unexpanded variable value from this node, without trying to look
   1337   1.802    rillig  * up the variable in any other scope.
   1338   1.778    rillig  */
   1339   1.616    rillig const char *
   1340   1.803    rillig GNode_ValueDirect(GNode *gn, const char *name)
   1341   1.616    rillig {
   1342   1.895    rillig 	Var *v = VarFind(name, gn, false);
   1343   1.785    rillig 	return v != NULL ? v->val.data : NULL;
   1344   1.616    rillig }
   1345   1.616    rillig 
   1346   1.906    rillig static VarEvalMode
   1347   1.906    rillig VarEvalMode_WithoutKeepDollar(VarEvalMode emode)
   1348   1.906    rillig {
   1349  1.1119    rillig 	return emode == VARE_EVAL_KEEP_DOLLAR_AND_UNDEFINED
   1350  1.1119    rillig 	    ? VARE_EVAL_KEEP_UNDEFINED : emode;
   1351   1.906    rillig }
   1352   1.906    rillig 
   1353   1.905    rillig static bool
   1354   1.906    rillig VarEvalMode_ShouldEval(VarEvalMode emode)
   1355   1.905    rillig {
   1356  1.1119    rillig 	return emode != VARE_PARSE;
   1357   1.906    rillig }
   1358   1.906    rillig 
   1359   1.906    rillig static bool
   1360   1.906    rillig VarEvalMode_ShouldKeepUndef(VarEvalMode emode)
   1361   1.906    rillig {
   1362  1.1119    rillig 	return emode == VARE_EVAL_KEEP_UNDEFINED ||
   1363  1.1119    rillig 	       emode == VARE_EVAL_KEEP_DOLLAR_AND_UNDEFINED;
   1364   1.906    rillig }
   1365   1.906    rillig 
   1366   1.906    rillig static bool
   1367   1.906    rillig VarEvalMode_ShouldKeepDollar(VarEvalMode emode)
   1368   1.906    rillig {
   1369  1.1119    rillig 	return emode == VARE_EVAL_KEEP_DOLLAR_AND_UNDEFINED;
   1370   1.905    rillig }
   1371   1.905    rillig 
   1372   1.905    rillig 
   1373   1.278    rillig static void
   1374   1.278    rillig SepBuf_Init(SepBuf *buf, char sep)
   1375   1.278    rillig {
   1376   1.703    rillig 	Buf_InitSize(&buf->buf, 32);
   1377   1.895    rillig 	buf->needSep = false;
   1378   1.703    rillig 	buf->sep = sep;
   1379   1.278    rillig }
   1380   1.278    rillig 
   1381   1.278    rillig static void
   1382   1.278    rillig SepBuf_Sep(SepBuf *buf)
   1383   1.278    rillig {
   1384   1.895    rillig 	buf->needSep = true;
   1385   1.278    rillig }
   1386   1.278    rillig 
   1387   1.278    rillig static void
   1388   1.314    rillig SepBuf_AddBytes(SepBuf *buf, const char *mem, size_t mem_size)
   1389   1.278    rillig {
   1390   1.703    rillig 	if (mem_size == 0)
   1391   1.703    rillig 		return;
   1392   1.703    rillig 	if (buf->needSep && buf->sep != '\0') {
   1393   1.703    rillig 		Buf_AddByte(&buf->buf, buf->sep);
   1394   1.895    rillig 		buf->needSep = false;
   1395   1.703    rillig 	}
   1396   1.703    rillig 	Buf_AddBytes(&buf->buf, mem, mem_size);
   1397   1.278    rillig }
   1398   1.278    rillig 
   1399   1.314    rillig static void
   1400  1.1055    rillig SepBuf_AddRange(SepBuf *buf, const char *start, const char *end)
   1401   1.314    rillig {
   1402   1.703    rillig 	SepBuf_AddBytes(buf, start, (size_t)(end - start));
   1403   1.314    rillig }
   1404   1.314    rillig 
   1405   1.314    rillig static void
   1406   1.314    rillig SepBuf_AddStr(SepBuf *buf, const char *str)
   1407   1.314    rillig {
   1408   1.703    rillig 	SepBuf_AddBytes(buf, str, strlen(str));
   1409   1.314    rillig }
   1410   1.314    rillig 
   1411   1.919    rillig static void
   1412   1.919    rillig SepBuf_AddSubstring(SepBuf *buf, Substring sub)
   1413   1.919    rillig {
   1414  1.1055    rillig 	SepBuf_AddRange(buf, sub.start, sub.end);
   1415   1.919    rillig }
   1416   1.919    rillig 
   1417   1.278    rillig static char *
   1418   1.784    rillig SepBuf_DoneData(SepBuf *buf)
   1419   1.278    rillig {
   1420   1.784    rillig 	return Buf_DoneData(&buf->buf);
   1421   1.278    rillig }
   1422   1.278    rillig 
   1423   1.278    rillig 
   1424   1.778    rillig /*
   1425  1.1075    rillig  * This callback for ModifyWords gets a single word from an expression
   1426   1.609    rillig  * and typically adds a modification of this word to the buffer. It may also
   1427   1.609    rillig  * do nothing or add several words.
   1428   1.609    rillig  *
   1429   1.822    rillig  * For example, when evaluating the modifier ':M*b' in ${:Ua b c:M*b}, the
   1430   1.822    rillig  * callback is called 3 times, once for "a", "b" and "c".
   1431   1.919    rillig  *
   1432   1.919    rillig  * Some ModifyWord functions assume that they are always passed a
   1433   1.919    rillig  * null-terminated substring, which is currently guaranteed but may change in
   1434   1.919    rillig  * the future.
   1435   1.778    rillig  */
   1436   1.919    rillig typedef void (*ModifyWordProc)(Substring word, SepBuf *buf, void *data);
   1437   1.244    rillig 
   1438   1.244    rillig 
   1439   1.278    rillig static void
   1440   1.919    rillig ModifyWord_Head(Substring word, SepBuf *buf, void *dummy MAKE_ATTR_UNUSED)
   1441     1.1       cgd {
   1442   1.919    rillig 	SepBuf_AddSubstring(buf, Substring_Dirname(word));
   1443     1.1       cgd }
   1444     1.1       cgd 
   1445   1.278    rillig static void
   1446   1.919    rillig ModifyWord_Tail(Substring word, SepBuf *buf, void *dummy MAKE_ATTR_UNUSED)
   1447     1.1       cgd {
   1448   1.919    rillig 	SepBuf_AddSubstring(buf, Substring_Basename(word));
   1449     1.1       cgd }
   1450     1.1       cgd 
   1451   1.278    rillig static void
   1452   1.919    rillig ModifyWord_Suffix(Substring word, SepBuf *buf, void *dummy MAKE_ATTR_UNUSED)
   1453     1.1       cgd {
   1454  1.1092    rillig 	const char *lastDot = Substring_FindLast(word, '.');
   1455   1.703    rillig 	if (lastDot != NULL)
   1456  1.1055    rillig 		SepBuf_AddRange(buf, lastDot + 1, word.end);
   1457     1.1       cgd }
   1458     1.1       cgd 
   1459   1.278    rillig static void
   1460   1.919    rillig ModifyWord_Root(Substring word, SepBuf *buf, void *dummy MAKE_ATTR_UNUSED)
   1461     1.1       cgd {
   1462   1.919    rillig 	const char *lastDot, *end;
   1463   1.919    rillig 
   1464  1.1092    rillig 	lastDot = Substring_FindLast(word, '.');
   1465   1.919    rillig 	end = lastDot != NULL ? lastDot : word.end;
   1466  1.1055    rillig 	SepBuf_AddRange(buf, word.start, end);
   1467     1.1       cgd }
   1468     1.1       cgd 
   1469   1.926    rillig struct ModifyWord_SysVSubstArgs {
   1470   1.806    rillig 	GNode *scope;
   1471   1.925    rillig 	Substring lhsPrefix;
   1472   1.925    rillig 	bool lhsPercent;
   1473   1.925    rillig 	Substring lhsSuffix;
   1474   1.703    rillig 	const char *rhs;
   1475   1.541    rillig };
   1476   1.276    rillig 
   1477   1.278    rillig static void
   1478   1.926    rillig ModifyWord_SysVSubst(Substring word, SepBuf *buf, void *data)
   1479     1.5       cgd {
   1480   1.926    rillig 	const struct ModifyWord_SysVSubstArgs *args = data;
   1481   1.925    rillig 	FStr rhs;
   1482   1.703    rillig 	const char *percent;
   1483   1.919    rillig 
   1484   1.925    rillig 	if (Substring_IsEmpty(word))
   1485   1.703    rillig 		return;
   1486   1.925    rillig 
   1487  1.1011    rillig 	if (!Substring_HasPrefix(word, args->lhsPrefix) ||
   1488  1.1011    rillig 	    !Substring_HasSuffix(word, args->lhsSuffix)) {
   1489  1.1011    rillig 		SepBuf_AddSubstring(buf, word);
   1490  1.1011    rillig 		return;
   1491  1.1011    rillig 	}
   1492   1.925    rillig 
   1493   1.925    rillig 	rhs = FStr_InitRefer(args->rhs);
   1494  1.1119    rillig 	Var_Expand(&rhs, args->scope, VARE_EVAL);
   1495   1.379    rillig 
   1496   1.925    rillig 	percent = args->lhsPercent ? strchr(rhs.str, '%') : NULL;
   1497   1.379    rillig 
   1498   1.925    rillig 	if (percent != NULL)
   1499  1.1055    rillig 		SepBuf_AddRange(buf, rhs.str, percent);
   1500   1.925    rillig 	if (percent != NULL || !args->lhsPercent)
   1501  1.1055    rillig 		SepBuf_AddRange(buf,
   1502   1.925    rillig 		    word.start + Substring_Length(args->lhsPrefix),
   1503   1.925    rillig 		    word.end - Substring_Length(args->lhsSuffix));
   1504   1.925    rillig 	SepBuf_AddStr(buf, percent != NULL ? percent + 1 : rhs.str);
   1505   1.379    rillig 
   1506   1.925    rillig 	FStr_Done(&rhs);
   1507     1.5       cgd }
   1508     1.5       cgd 
   1509   1.918    rillig static const char *
   1510   1.918    rillig Substring_Find(Substring haystack, Substring needle)
   1511   1.918    rillig {
   1512   1.918    rillig 	size_t len, needleLen, i;
   1513   1.918    rillig 
   1514   1.918    rillig 	len = Substring_Length(haystack);
   1515   1.918    rillig 	needleLen = Substring_Length(needle);
   1516   1.918    rillig 	for (i = 0; i + needleLen <= len; i++)
   1517   1.918    rillig 		if (memcmp(haystack.start + i, needle.start, needleLen) == 0)
   1518   1.918    rillig 			return haystack.start + i;
   1519   1.918    rillig 	return NULL;
   1520   1.918    rillig }
   1521   1.918    rillig 
   1522  1.1079    rillig struct ModifyWord_SubstArgs {
   1523  1.1079    rillig 	Substring lhs;
   1524  1.1079    rillig 	Substring rhs;
   1525  1.1079    rillig 	PatternFlags pflags;
   1526  1.1079    rillig 	bool matched;
   1527  1.1079    rillig };
   1528  1.1079    rillig 
   1529   1.278    rillig static void
   1530   1.919    rillig ModifyWord_Subst(Substring word, SepBuf *buf, void *data)
   1531     1.1       cgd {
   1532   1.703    rillig 	struct ModifyWord_SubstArgs *args = data;
   1533   1.918    rillig 	size_t wordLen, lhsLen;
   1534  1.1089    rillig 	const char *match;
   1535   1.703    rillig 
   1536   1.919    rillig 	wordLen = Substring_Length(word);
   1537   1.788    rillig 	if (args->pflags.subOnce && args->matched)
   1538   1.703    rillig 		goto nosub;
   1539   1.703    rillig 
   1540   1.918    rillig 	lhsLen = Substring_Length(args->lhs);
   1541   1.788    rillig 	if (args->pflags.anchorStart) {
   1542   1.918    rillig 		if (wordLen < lhsLen ||
   1543   1.919    rillig 		    memcmp(word.start, args->lhs.start, lhsLen) != 0)
   1544   1.703    rillig 			goto nosub;
   1545   1.703    rillig 
   1546   1.918    rillig 		if (args->pflags.anchorEnd && wordLen != lhsLen)
   1547   1.703    rillig 			goto nosub;
   1548   1.703    rillig 
   1549   1.703    rillig 		/* :S,^prefix,replacement, or :S,^whole$,replacement, */
   1550   1.919    rillig 		SepBuf_AddSubstring(buf, args->rhs);
   1551  1.1089    rillig 		SepBuf_AddRange(buf, word.start + lhsLen, word.end);
   1552   1.895    rillig 		args->matched = true;
   1553   1.703    rillig 		return;
   1554   1.703    rillig 	}
   1555     1.1       cgd 
   1556   1.788    rillig 	if (args->pflags.anchorEnd) {
   1557   1.918    rillig 		if (wordLen < lhsLen)
   1558   1.703    rillig 			goto nosub;
   1559  1.1089    rillig 		if (memcmp(word.end - lhsLen, args->lhs.start, lhsLen) != 0)
   1560   1.703    rillig 			goto nosub;
   1561   1.703    rillig 
   1562   1.703    rillig 		/* :S,suffix$,replacement, */
   1563  1.1089    rillig 		SepBuf_AddRange(buf, word.start, word.end - lhsLen);
   1564   1.919    rillig 		SepBuf_AddSubstring(buf, args->rhs);
   1565   1.895    rillig 		args->matched = true;
   1566   1.703    rillig 		return;
   1567   1.703    rillig 	}
   1568   1.315    rillig 
   1569   1.921    rillig 	if (Substring_IsEmpty(args->lhs))
   1570   1.703    rillig 		goto nosub;
   1571   1.279    rillig 
   1572   1.703    rillig 	/* unanchored case, may match more than once */
   1573   1.919    rillig 	while ((match = Substring_Find(word, args->lhs)) != NULL) {
   1574  1.1055    rillig 		SepBuf_AddRange(buf, word.start, match);
   1575   1.919    rillig 		SepBuf_AddSubstring(buf, args->rhs);
   1576   1.895    rillig 		args->matched = true;
   1577   1.921    rillig 		word.start = match + lhsLen;
   1578   1.919    rillig 		if (Substring_IsEmpty(word) || !args->pflags.subGlobal)
   1579   1.703    rillig 			break;
   1580   1.703    rillig 	}
   1581   1.242    rillig nosub:
   1582   1.919    rillig 	SepBuf_AddSubstring(buf, word);
   1583     1.1       cgd }
   1584     1.1       cgd 
   1585   1.400    rillig /* Print the error caused by a regcomp or regexec call. */
   1586    1.16  christos static void
   1587  1.1059    rillig RegexError(int reerr, const regex_t *pat, const char *str)
   1588    1.16  christos {
   1589   1.703    rillig 	size_t errlen = regerror(reerr, pat, NULL, 0);
   1590   1.703    rillig 	char *errbuf = bmake_malloc(errlen);
   1591   1.703    rillig 	regerror(reerr, pat, errbuf, errlen);
   1592  1.1125    rillig 	Parse_Error(PARSE_FATAL, "%s: %s", str, errbuf);
   1593   1.703    rillig 	free(errbuf);
   1594    1.16  christos }
   1595    1.16  christos 
   1596   1.981    rillig /* In the modifier ':C', replace a backreference from \0 to \9. */
   1597   1.981    rillig static void
   1598   1.981    rillig RegexReplaceBackref(char ref, SepBuf *buf, const char *wp,
   1599   1.981    rillig 		    const regmatch_t *m, size_t nsub)
   1600   1.981    rillig {
   1601  1.1160    rillig 	unsigned n = (unsigned)ref - '0';
   1602   1.981    rillig 
   1603   1.981    rillig 	if (n >= nsub)
   1604  1.1125    rillig 		Parse_Error(PARSE_FATAL, "No subexpression \\%u", n);
   1605   1.981    rillig 	else if (m[n].rm_so == -1) {
   1606   1.981    rillig 		if (opts.strict)
   1607   1.981    rillig 			Error("No match for subexpression \\%u", n);
   1608   1.981    rillig 	} else {
   1609  1.1055    rillig 		SepBuf_AddRange(buf,
   1610   1.981    rillig 		    wp + (size_t)m[n].rm_so,
   1611   1.981    rillig 		    wp + (size_t)m[n].rm_eo);
   1612   1.981    rillig 	}
   1613   1.981    rillig }
   1614   1.981    rillig 
   1615   1.937    rillig /*
   1616   1.983    rillig  * The regular expression matches the word; now add the replacement to the
   1617   1.983    rillig  * buffer, taking back-references from 'wp'.
   1618   1.937    rillig  */
   1619   1.937    rillig static void
   1620   1.984    rillig RegexReplace(Substring replace, SepBuf *buf, const char *wp,
   1621   1.937    rillig 	     const regmatch_t *m, size_t nsub)
   1622   1.937    rillig {
   1623   1.937    rillig 	const char *rp;
   1624   1.937    rillig 
   1625   1.984    rillig 	for (rp = replace.start; rp != replace.end; rp++) {
   1626   1.984    rillig 		if (*rp == '\\' && rp + 1 != replace.end &&
   1627   1.984    rillig 		    (rp[1] == '&' || rp[1] == '\\'))
   1628   1.983    rillig 			SepBuf_AddBytes(buf, ++rp, 1);
   1629   1.984    rillig 		else if (*rp == '\\' && rp + 1 != replace.end &&
   1630   1.984    rillig 			 ch_isdigit(rp[1]))
   1631   1.983    rillig 			RegexReplaceBackref(*++rp, buf, wp, m, nsub);
   1632   1.983    rillig 		else if (*rp == '&') {
   1633  1.1055    rillig 			SepBuf_AddRange(buf,
   1634   1.948    rillig 			    wp + (size_t)m[0].rm_so,
   1635   1.948    rillig 			    wp + (size_t)m[0].rm_eo);
   1636   1.983    rillig 		} else
   1637   1.937    rillig 			SepBuf_AddBytes(buf, rp, 1);
   1638   1.937    rillig 	}
   1639   1.937    rillig }
   1640   1.937    rillig 
   1641   1.541    rillig struct ModifyWord_SubstRegexArgs {
   1642   1.703    rillig 	regex_t re;
   1643   1.703    rillig 	size_t nsub;
   1644   1.984    rillig 	Substring replace;
   1645   1.927    rillig 	PatternFlags pflags;
   1646   1.895    rillig 	bool matched;
   1647   1.541    rillig };
   1648   1.291    rillig 
   1649   1.278    rillig static void
   1650   1.919    rillig ModifyWord_SubstRegex(Substring word, SepBuf *buf, void *data)
   1651    1.16  christos {
   1652   1.704    rillig 	struct ModifyWord_SubstRegexArgs *args = data;
   1653   1.704    rillig 	int xrv;
   1654   1.919    rillig 	const char *wp;
   1655   1.704    rillig 	int flags = 0;
   1656   1.704    rillig 	regmatch_t m[10];
   1657    1.16  christos 
   1658   1.919    rillig 	assert(word.end[0] == '\0');	/* assume null-terminated word */
   1659   1.919    rillig 	wp = word.start;
   1660   1.936    rillig 	if (args->pflags.subOnce && args->matched)
   1661   1.936    rillig 		goto no_match;
   1662   1.307    rillig 
   1663   1.935    rillig again:
   1664   1.704    rillig 	xrv = regexec(&args->re, wp, args->nsub, m, flags);
   1665   1.935    rillig 	if (xrv == 0)
   1666   1.935    rillig 		goto ok;
   1667   1.935    rillig 	if (xrv != REG_NOMATCH)
   1668  1.1059    rillig 		RegexError(xrv, &args->re, "Unexpected regex error");
   1669   1.936    rillig no_match:
   1670  1.1055    rillig 	SepBuf_AddRange(buf, wp, word.end);
   1671   1.936    rillig 	return;
   1672    1.16  christos 
   1673   1.935    rillig ok:
   1674   1.935    rillig 	args->matched = true;
   1675   1.935    rillig 	SepBuf_AddBytes(buf, wp, (size_t)m[0].rm_so);
   1676   1.704    rillig 
   1677   1.937    rillig 	RegexReplace(args->replace, buf, wp, m, args->nsub);
   1678   1.445    rillig 
   1679   1.948    rillig 	wp += (size_t)m[0].rm_eo;
   1680   1.935    rillig 	if (args->pflags.subGlobal) {
   1681   1.935    rillig 		flags |= REG_NOTBOL;
   1682  1.1077    rillig 		if (m[0].rm_so == 0 && m[0].rm_eo == 0 && *wp != '\0') {
   1683   1.935    rillig 			SepBuf_AddBytes(buf, wp, 1);
   1684   1.935    rillig 			wp++;
   1685   1.704    rillig 		}
   1686   1.704    rillig 		if (*wp != '\0')
   1687   1.935    rillig 			goto again;
   1688   1.935    rillig 	}
   1689   1.935    rillig 	if (*wp != '\0')
   1690   1.704    rillig 		SepBuf_AddStr(buf, wp);
   1691    1.16  christos }
   1692    1.16  christos 
   1693    1.16  christos 
   1694   1.541    rillig struct ModifyWord_LoopArgs {
   1695   1.806    rillig 	GNode *scope;
   1696   1.928    rillig 	const char *var;	/* name of the temporary variable */
   1697   1.928    rillig 	const char *body;	/* string to expand */
   1698   1.906    rillig 	VarEvalMode emode;
   1699   1.541    rillig };
   1700   1.291    rillig 
   1701   1.278    rillig static void
   1702   1.919    rillig ModifyWord_Loop(Substring word, SepBuf *buf, void *data)
   1703    1.40       sjg {
   1704   1.703    rillig 	const struct ModifyWord_LoopArgs *args;
   1705   1.703    rillig 	char *s;
   1706   1.412    rillig 
   1707   1.919    rillig 	if (Substring_IsEmpty(word))
   1708   1.703    rillig 		return;
   1709   1.278    rillig 
   1710   1.703    rillig 	args = data;
   1711   1.919    rillig 	assert(word.end[0] == '\0');	/* assume null-terminated word */
   1712   1.928    rillig 	Var_SetWithFlags(args->scope, args->var, word.start,
   1713   1.919    rillig 	    VAR_SET_NO_EXPORT);
   1714  1.1043    rillig 	s = Var_Subst(args->body, args->scope, args->emode);
   1715   1.703    rillig 	/* TODO: handle errors */
   1716    1.64       sjg 
   1717  1.1090    rillig 	DEBUG2(VAR, "ModifyWord_Loop: expand \"%s\" to \"%s\"\n",
   1718  1.1090    rillig 	    args->body, s);
   1719   1.703    rillig 
   1720   1.703    rillig 	if (s[0] == '\n' || Buf_EndsWith(&buf->buf, '\n'))
   1721   1.895    rillig 		buf->needSep = false;
   1722   1.703    rillig 	SepBuf_AddStr(buf, s);
   1723   1.703    rillig 	free(s);
   1724    1.40       sjg }
   1725    1.40       sjg 
   1726    1.81       sjg 
   1727   1.778    rillig /*
   1728   1.778    rillig  * The :[first..last] modifier selects words from the expression.
   1729   1.778    rillig  * It can also reverse the words.
   1730   1.778    rillig  */
   1731    1.81       sjg static char *
   1732   1.840    rillig VarSelectWords(const char *str, int first, int last,
   1733   1.895    rillig 	       char sep, bool oneBigWord)
   1734    1.81       sjg {
   1735   1.960    rillig 	SubstringWords words;
   1736   1.703    rillig 	int len, start, end, step;
   1737   1.703    rillig 	int i;
   1738   1.703    rillig 
   1739   1.703    rillig 	SepBuf buf;
   1740   1.703    rillig 	SepBuf_Init(&buf, sep);
   1741   1.703    rillig 
   1742   1.703    rillig 	if (oneBigWord) {
   1743   1.960    rillig 		/* fake what Substring_Words() would do */
   1744   1.703    rillig 		words.len = 1;
   1745   1.960    rillig 		words.words = bmake_malloc(sizeof(words.words[0]));
   1746   1.960    rillig 		words.freeIt = NULL;
   1747   1.960    rillig 		words.words[0] = Substring_InitStr(str); /* no need to copy */
   1748   1.703    rillig 	} else {
   1749   1.960    rillig 		words = Substring_Words(str, false);
   1750   1.703    rillig 	}
   1751    1.81       sjg 
   1752  1.1088    rillig 	/* Convert -1 to len, -2 to (len - 1), etc. */
   1753   1.703    rillig 	len = (int)words.len;
   1754   1.703    rillig 	if (first < 0)
   1755   1.703    rillig 		first += len + 1;
   1756   1.703    rillig 	if (last < 0)
   1757   1.703    rillig 		last += len + 1;
   1758   1.703    rillig 
   1759   1.703    rillig 	if (first > last) {
   1760   1.703    rillig 		start = (first > len ? len : first) - 1;
   1761   1.703    rillig 		end = last < 1 ? 0 : last - 1;
   1762   1.703    rillig 		step = -1;
   1763   1.703    rillig 	} else {
   1764   1.703    rillig 		start = first < 1 ? 0 : first - 1;
   1765   1.703    rillig 		end = last > len ? len : last;
   1766   1.703    rillig 		step = 1;
   1767   1.703    rillig 	}
   1768    1.81       sjg 
   1769   1.703    rillig 	for (i = start; (step < 0) == (i >= end); i += step) {
   1770   1.960    rillig 		SepBuf_AddSubstring(&buf, words.words[i]);
   1771   1.703    rillig 		SepBuf_Sep(&buf);
   1772   1.703    rillig 	}
   1773    1.81       sjg 
   1774   1.960    rillig 	SubstringWords_Free(words);
   1775    1.81       sjg 
   1776   1.784    rillig 	return SepBuf_DoneData(&buf);
   1777    1.81       sjg }
   1778    1.81       sjg 
   1779   1.156       sjg 
   1780   1.278    rillig static void
   1781   1.919    rillig ModifyWord_Realpath(Substring word, SepBuf *buf, void *data MAKE_ATTR_UNUSED)
   1782   1.156       sjg {
   1783   1.703    rillig 	struct stat st;
   1784   1.703    rillig 	char rbuf[MAXPATHLEN];
   1785   1.919    rillig 	const char *rp;
   1786   1.231    rillig 
   1787   1.919    rillig 	assert(word.end[0] == '\0');	/* assume null-terminated word */
   1788   1.919    rillig 	rp = cached_realpath(word.start, rbuf);
   1789   1.703    rillig 	if (rp != NULL && *rp == '/' && stat(rp, &st) == 0)
   1790   1.919    rillig 		SepBuf_AddStr(buf, rp);
   1791   1.919    rillig 	else
   1792   1.919    rillig 		SepBuf_AddSubstring(buf, word);
   1793   1.156       sjg }
   1794   1.156       sjg 
   1795    1.35  christos 
   1796   1.403    rillig static char *
   1797   1.962    rillig SubstringWords_JoinFree(SubstringWords words)
   1798   1.403    rillig {
   1799   1.703    rillig 	Buffer buf;
   1800   1.703    rillig 	size_t i;
   1801   1.412    rillig 
   1802   1.703    rillig 	Buf_Init(&buf);
   1803   1.403    rillig 
   1804   1.703    rillig 	for (i = 0; i < words.len; i++) {
   1805   1.703    rillig 		if (i != 0) {
   1806   1.988    rillig 			/*
   1807   1.988    rillig 			 * XXX: Use ch->sep instead of ' ', for consistency.
   1808   1.988    rillig 			 */
   1809   1.703    rillig 			Buf_AddByte(&buf, ' ');
   1810   1.703    rillig 		}
   1811  1.1055    rillig 		Buf_AddRange(&buf, words.words[i].start, words.words[i].end);
   1812   1.703    rillig 	}
   1813   1.403    rillig 
   1814   1.962    rillig 	SubstringWords_Free(words);
   1815   1.403    rillig 
   1816   1.784    rillig 	return Buf_DoneData(&buf);
   1817   1.403    rillig }
   1818   1.403    rillig 
   1819    1.55  christos 
   1820   1.778    rillig /*
   1821   1.778    rillig  * Quote shell meta-characters and space characters in the string.
   1822   1.778    rillig  * If quoteDollar is set, also quote and double any '$' characters.
   1823   1.778    rillig  */
   1824   1.924    rillig static void
   1825  1.1059    rillig QuoteShell(const char *str, bool quoteDollar, LazyBuf *buf)
   1826    1.16  christos {
   1827   1.924    rillig 	const char *p;
   1828   1.193  christos 
   1829   1.924    rillig 	LazyBuf_Init(buf, str);
   1830   1.924    rillig 	for (p = str; *p != '\0'; p++) {
   1831   1.924    rillig 		if (*p == '\n') {
   1832   1.703    rillig 			const char *newline = Shell_GetNewline();
   1833   1.703    rillig 			if (newline == NULL)
   1834   1.703    rillig 				newline = "\\\n";
   1835   1.924    rillig 			LazyBuf_AddStr(buf, newline);
   1836   1.703    rillig 			continue;
   1837   1.703    rillig 		}
   1838   1.997    rillig 		if (ch_isspace(*p) || ch_is_shell_meta(*p))
   1839   1.924    rillig 			LazyBuf_Add(buf, '\\');
   1840   1.924    rillig 		LazyBuf_Add(buf, *p);
   1841   1.924    rillig 		if (quoteDollar && *p == '$')
   1842   1.924    rillig 			LazyBuf_AddStr(buf, "\\$");
   1843   1.193  christos 	}
   1844    1.16  christos }
   1845    1.16  christos 
   1846   1.778    rillig /*
   1847   1.778    rillig  * Compute the 32-bit hash of the given string, using the MurmurHash3
   1848   1.778    rillig  * algorithm. Output is encoded as 8 hex digits, in Little Endian order.
   1849   1.778    rillig  */
   1850   1.163     joerg static char *
   1851  1.1059    rillig Hash(const char *str)
   1852   1.163     joerg {
   1853  1.1172       sjg 	static const char hexdigits[] = "0123456789abcdef";
   1854   1.703    rillig 	const unsigned char *ustr = (const unsigned char *)str;
   1855   1.703    rillig 
   1856   1.703    rillig 	uint32_t h = 0x971e137bU;
   1857   1.703    rillig 	uint32_t c1 = 0x95543787U;
   1858   1.703    rillig 	uint32_t c2 = 0x2ad7eb25U;
   1859   1.703    rillig 	size_t len2 = strlen(str);
   1860   1.163     joerg 
   1861   1.703    rillig 	char *buf;
   1862   1.703    rillig 	size_t i;
   1863   1.703    rillig 
   1864   1.703    rillig 	size_t len;
   1865   1.781    rillig 	for (len = len2; len != 0;) {
   1866   1.703    rillig 		uint32_t k = 0;
   1867   1.703    rillig 		switch (len) {
   1868   1.703    rillig 		default:
   1869   1.703    rillig 			k = ((uint32_t)ustr[3] << 24) |
   1870   1.703    rillig 			    ((uint32_t)ustr[2] << 16) |
   1871   1.703    rillig 			    ((uint32_t)ustr[1] << 8) |
   1872   1.703    rillig 			    (uint32_t)ustr[0];
   1873   1.703    rillig 			len -= 4;
   1874   1.703    rillig 			ustr += 4;
   1875   1.703    rillig 			break;
   1876   1.703    rillig 		case 3:
   1877   1.703    rillig 			k |= (uint32_t)ustr[2] << 16;
   1878   1.703    rillig 			/* FALLTHROUGH */
   1879   1.703    rillig 		case 2:
   1880   1.703    rillig 			k |= (uint32_t)ustr[1] << 8;
   1881   1.703    rillig 			/* FALLTHROUGH */
   1882   1.703    rillig 		case 1:
   1883   1.703    rillig 			k |= (uint32_t)ustr[0];
   1884   1.703    rillig 			len = 0;
   1885   1.703    rillig 		}
   1886   1.703    rillig 		c1 = c1 * 5 + 0x7b7d159cU;
   1887   1.703    rillig 		c2 = c2 * 5 + 0x6bce6396U;
   1888   1.703    rillig 		k *= c1;
   1889   1.703    rillig 		k = (k << 11) ^ (k >> 21);
   1890   1.703    rillig 		k *= c2;
   1891   1.703    rillig 		h = (h << 13) ^ (h >> 19);
   1892   1.703    rillig 		h = h * 5 + 0x52dce729U;
   1893   1.703    rillig 		h ^= k;
   1894   1.703    rillig 	}
   1895   1.703    rillig 	h ^= (uint32_t)len2;
   1896   1.703    rillig 	h *= 0x85ebca6b;
   1897   1.703    rillig 	h ^= h >> 13;
   1898   1.703    rillig 	h *= 0xc2b2ae35;
   1899   1.703    rillig 	h ^= h >> 16;
   1900   1.703    rillig 
   1901   1.703    rillig 	buf = bmake_malloc(9);
   1902   1.703    rillig 	for (i = 0; i < 8; i++) {
   1903   1.703    rillig 		buf[i] = hexdigits[h & 0x0f];
   1904   1.703    rillig 		h >>= 4;
   1905   1.703    rillig 	}
   1906   1.703    rillig 	buf[8] = '\0';
   1907   1.703    rillig 	return buf;
   1908   1.163     joerg }
   1909   1.163     joerg 
   1910   1.164       sjg static char *
   1911  1.1059    rillig FormatTime(const char *fmt, time_t t, bool gmt)
   1912   1.164       sjg {
   1913   1.703    rillig 	char buf[BUFSIZ];
   1914   1.164       sjg 
   1915   1.993    rillig 	if (t == 0)
   1916   1.993    rillig 		time(&t);
   1917   1.703    rillig 	if (*fmt == '\0')
   1918   1.703    rillig 		fmt = "%c";
   1919  1.1064    rillig 	if (gmt && strchr(fmt, 's') != NULL) {
   1920  1.1064    rillig 		/* strftime "%s" only works with localtime, not with gmtime. */
   1921  1.1062    rillig 		const char *prev_tz_env = getenv("TZ");
   1922  1.1062    rillig 		char *prev_tz = prev_tz_env != NULL
   1923  1.1062    rillig 		    ? bmake_strdup(prev_tz_env) : NULL;
   1924  1.1062    rillig 		setenv("TZ", "UTC", 1);
   1925  1.1062    rillig 		strftime(buf, sizeof buf, fmt, localtime(&t));
   1926  1.1062    rillig 		if (prev_tz != NULL) {
   1927  1.1062    rillig 			setenv("TZ", prev_tz, 1);
   1928  1.1062    rillig 			free(prev_tz);
   1929  1.1062    rillig 		} else
   1930  1.1062    rillig 			unsetenv("TZ");
   1931  1.1062    rillig 	} else
   1932  1.1064    rillig 		strftime(buf, sizeof buf, fmt, (gmt ? gmtime : localtime)(&t));
   1933   1.235    rillig 
   1934   1.703    rillig 	buf[sizeof buf - 1] = '\0';
   1935   1.703    rillig 	return bmake_strdup(buf);
   1936   1.164       sjg }
   1937   1.164       sjg 
   1938   1.687    rillig /*
   1939   1.687    rillig  * The ApplyModifier functions take an expression that is being evaluated.
   1940   1.830    rillig  * Their task is to apply a single modifier to the expression.  This involves
   1941   1.830    rillig  * parsing the modifier, evaluating it and finally updating the value of the
   1942   1.830    rillig  * expression.
   1943   1.467    rillig  *
   1944   1.467    rillig  * Parsing the modifier
   1945   1.467    rillig  *
   1946   1.467    rillig  * If parsing succeeds, the parsing position *pp is updated to point to the
   1947   1.467    rillig  * first character following the modifier, which typically is either ':' or
   1948   1.891    rillig  * ch->endc.  The modifier doesn't have to check for this delimiter character,
   1949   1.687    rillig  * this is done by ApplyModifiers.
   1950   1.687    rillig  *
   1951   1.687    rillig  * XXX: As of 2020-11-15, some modifiers such as :S, :C, :P, :L do not
   1952   1.687    rillig  * need to be followed by a ':' or endc; this was an unintended mistake.
   1953   1.467    rillig  *
   1954  1.1079    rillig  * If parsing fails because of a missing delimiter after a modifier part (as
   1955  1.1079    rillig  * in the :S, :C or :@ modifiers), return AMR_CLEANUP.
   1956   1.467    rillig  *
   1957   1.467    rillig  * If parsing fails because the modifier is unknown, return AMR_UNKNOWN to
   1958  1.1088    rillig  * try the SysV modifier ':from=to' as fallback.  This should only be
   1959   1.467    rillig  * done as long as there have been no side effects from evaluating nested
   1960   1.467    rillig  * variables, to avoid evaluating them more than once.  In this case, the
   1961   1.687    rillig  * parsing position may or may not be updated.  (XXX: Why not? The original
   1962   1.687    rillig  * parsing position is well-known in ApplyModifiers.)
   1963   1.467    rillig  *
   1964   1.467    rillig  * If parsing fails and the SysV modifier ${VAR:from=to} should not be used
   1965  1.1066    rillig  * as a fallback, issue an error message using Parse_Error (preferred over
   1966  1.1088    rillig  * Error) and then return AMR_CLEANUP, which stops processing the expression.
   1967  1.1088    rillig  * (XXX: As of 2020-08-23, evaluation of the string continues nevertheless
   1968  1.1088    rillig  * after skipping a few bytes, which results in garbage.)
   1969   1.467    rillig  *
   1970   1.467    rillig  * Evaluating the modifier
   1971   1.467    rillig  *
   1972   1.467    rillig  * After parsing, the modifier is evaluated.  The side effects from evaluating
   1973  1.1075    rillig  * nested expressions in the modifier text often already happen
   1974   1.830    rillig  * during parsing though.  For most modifiers this doesn't matter since their
   1975   1.949    rillig  * only noticeable effect is that they update the value of the expression.
   1976   1.830    rillig  * Some modifiers such as ':sh' or '::=' have noticeable side effects though.
   1977   1.467    rillig  *
   1978  1.1075    rillig  * Evaluating the modifier usually takes the current value of the
   1979  1.1094    rillig  * expression from ch->expr->value, or the variable name from ch->var->name,
   1980  1.1066    rillig  * and stores the result back in ch->expr->value via Expr_SetValueOwn or
   1981   1.821    rillig  * Expr_SetValueRefer.
   1982   1.467    rillig  *
   1983   1.528    rillig  * Some modifiers such as :D and :U turn undefined expressions into defined
   1984  1.1066    rillig  * expressions using Expr_Define.
   1985   1.350    rillig  */
   1986   1.409    rillig 
   1987   1.825    rillig typedef enum ExprDefined {
   1988  1.1075    rillig 	/* The expression is based on a regular, defined variable. */
   1989   1.825    rillig 	DEF_REGULAR,
   1990  1.1075    rillig 	/* The expression is based on an undefined variable. */
   1991   1.825    rillig 	DEF_UNDEF,
   1992   1.703    rillig 	/*
   1993  1.1075    rillig 	 * The expression started as an undefined expression, but one
   1994   1.825    rillig 	 * of the modifiers (such as ':D' or ':U') has turned the expression
   1995   1.825    rillig 	 * from undefined to defined.
   1996   1.703    rillig 	 */
   1997   1.825    rillig 	DEF_DEFINED
   1998   1.825    rillig } ExprDefined;
   1999   1.527    rillig 
   2000   1.951    rillig static const char ExprDefined_Name[][10] = {
   2001   1.826    rillig 	"regular",
   2002   1.826    rillig 	"undefined",
   2003   1.826    rillig 	"defined"
   2004   1.789    rillig };
   2005   1.527    rillig 
   2006   1.897    rillig #if __STDC_VERSION__ >= 199901L
   2007   1.989    rillig #define const_member		const
   2008   1.897    rillig #else
   2009   1.989    rillig #define const_member		/* no const possible */
   2010   1.897    rillig #endif
   2011   1.897    rillig 
   2012   1.966    rillig /* An expression based on a variable, such as $@ or ${VAR:Mpattern:Q}. */
   2013   1.823    rillig typedef struct Expr {
   2014   1.898    rillig 	const char *name;
   2015   1.823    rillig 	FStr value;
   2016   1.906    rillig 	VarEvalMode const_member emode;
   2017   1.897    rillig 	GNode *const_member scope;
   2018   1.825    rillig 	ExprDefined defined;
   2019   1.823    rillig } Expr;
   2020   1.823    rillig 
   2021   1.823    rillig /*
   2022   1.890    rillig  * The status of applying a chain of modifiers to an expression.
   2023   1.823    rillig  *
   2024   1.890    rillig  * The modifiers of an expression are broken into chains of modifiers,
   2025   1.892    rillig  * starting a new nested chain whenever an indirect modifier starts.  There
   2026   1.892    rillig  * are at most 2 nesting levels: the outer one for the direct modifiers, and
   2027   1.892    rillig  * the inner one for the indirect modifiers.
   2028   1.890    rillig  *
   2029   1.892    rillig  * For example, the expression ${VAR:M*:${IND1}:${IND2}:O:u} has 3 chains of
   2030   1.889    rillig  * modifiers:
   2031   1.889    rillig  *
   2032   1.892    rillig  *	Chain 1 starts with the single modifier ':M*'.
   2033   1.892    rillig  *	  Chain 2 starts with all modifiers from ${IND1}.
   2034   1.892    rillig  *	  Chain 2 ends at the ':' between ${IND1} and ${IND2}.
   2035   1.893    rillig  *	  Chain 3 starts with all modifiers from ${IND2}.
   2036   1.893    rillig  *	  Chain 3 ends at the ':' after ${IND2}.
   2037   1.942    rillig  *	Chain 1 continues with the 2 modifiers ':O' and ':u'.
   2038   1.892    rillig  *	Chain 1 ends at the final '}' of the expression.
   2039   1.890    rillig  *
   2040   1.892    rillig  * After such a chain ends, its properties no longer have any effect.
   2041   1.889    rillig  *
   2042   1.823    rillig  * See varmod-indirect.mk.
   2043   1.823    rillig  */
   2044   1.891    rillig typedef struct ModChain {
   2045   1.823    rillig 	Expr *expr;
   2046   1.703    rillig 	/* '\0' or '{' or '(' */
   2047   1.897    rillig 	char const_member startc;
   2048   1.703    rillig 	/* '\0' or '}' or ')' */
   2049   1.897    rillig 	char const_member endc;
   2050  1.1094    rillig 	/* Separator when joining words (see the :ts modifier). */
   2051   1.703    rillig 	char sep;
   2052   1.703    rillig 	/*
   2053  1.1066    rillig 	 * Whether some modifiers that otherwise split the variable value
   2054   1.703    rillig 	 * into words, like :S and :C, treat the variable value as a single
   2055   1.703    rillig 	 * big word, possibly containing spaces.
   2056   1.703    rillig 	 */
   2057   1.895    rillig 	bool oneBigWord;
   2058   1.891    rillig } ModChain;
   2059   1.236    rillig 
   2060   1.525    rillig static void
   2061   1.812    rillig Expr_Define(Expr *expr)
   2062   1.525    rillig {
   2063   1.825    rillig 	if (expr->defined == DEF_UNDEF)
   2064   1.825    rillig 		expr->defined = DEF_DEFINED;
   2065   1.525    rillig }
   2066   1.525    rillig 
   2067   1.965    rillig static const char *
   2068   1.965    rillig Expr_Str(const Expr *expr)
   2069   1.965    rillig {
   2070   1.965    rillig 	return expr->value.str;
   2071   1.965    rillig }
   2072   1.965    rillig 
   2073   1.967    rillig static SubstringWords
   2074   1.967    rillig Expr_Words(const Expr *expr)
   2075   1.967    rillig {
   2076   1.967    rillig 	return Substring_Words(Expr_Str(expr), false);
   2077   1.967    rillig }
   2078   1.967    rillig 
   2079   1.813    rillig static void
   2080   1.921    rillig Expr_SetValue(Expr *expr, FStr value)
   2081   1.921    rillig {
   2082   1.921    rillig 	FStr_Done(&expr->value);
   2083   1.921    rillig 	expr->value = value;
   2084   1.921    rillig }
   2085   1.921    rillig 
   2086   1.921    rillig static void
   2087   1.813    rillig Expr_SetValueOwn(Expr *expr, char *value)
   2088   1.813    rillig {
   2089   1.921    rillig 	Expr_SetValue(expr, FStr_InitOwn(value));
   2090   1.813    rillig }
   2091   1.813    rillig 
   2092   1.813    rillig static void
   2093   1.813    rillig Expr_SetValueRefer(Expr *expr, const char *value)
   2094   1.813    rillig {
   2095   1.921    rillig 	Expr_SetValue(expr, FStr_InitRefer(value));
   2096   1.813    rillig }
   2097   1.813    rillig 
   2098   1.905    rillig static bool
   2099   1.905    rillig Expr_ShouldEval(const Expr *expr)
   2100   1.905    rillig {
   2101   1.906    rillig 	return VarEvalMode_ShouldEval(expr->emode);
   2102   1.905    rillig }
   2103   1.905    rillig 
   2104   1.905    rillig static bool
   2105   1.905    rillig ModChain_ShouldEval(const ModChain *ch)
   2106   1.905    rillig {
   2107   1.905    rillig 	return Expr_ShouldEval(ch->expr);
   2108   1.905    rillig }
   2109   1.905    rillig 
   2110   1.905    rillig 
   2111   1.578    rillig typedef enum ApplyModifierResult {
   2112   1.703    rillig 	/* Continue parsing */
   2113   1.703    rillig 	AMR_OK,
   2114  1.1093    rillig 	/* Not a match, try the ':from=to' modifier as well. */
   2115   1.703    rillig 	AMR_UNKNOWN,
   2116  1.1155    rillig 	/* Error out without further error message. */
   2117   1.703    rillig 	AMR_CLEANUP
   2118   1.356    rillig } ApplyModifierResult;
   2119   1.356    rillig 
   2120   1.703    rillig /*
   2121  1.1171    rillig  * Allow backslashes to escape the delimiters, $, and \, but don't touch other
   2122   1.703    rillig  * backslashes.
   2123   1.703    rillig  */
   2124   1.895    rillig static bool
   2125  1.1171    rillig IsEscapedModifierPart(const char *p, char end1, char end2,
   2126   1.620    rillig 		      struct ModifyWord_SubstArgs *subst)
   2127   1.620    rillig {
   2128  1.1118    rillig 	if (p[0] != '\\' || p[1] == '\0')
   2129   1.895    rillig 		return false;
   2130  1.1171    rillig 	if (p[1] == end1 || p[1] == end2 || p[1] == '\\' || p[1] == '$')
   2131   1.895    rillig 		return true;
   2132   1.703    rillig 	return p[1] == '&' && subst != NULL;
   2133   1.620    rillig }
   2134   1.620    rillig 
   2135   1.956    rillig /*
   2136   1.957    rillig  * In a part of a modifier, parse a subexpression and evaluate it.
   2137   1.957    rillig  */
   2138   1.957    rillig static void
   2139   1.957    rillig ParseModifierPartExpr(const char **pp, LazyBuf *part, const ModChain *ch,
   2140   1.957    rillig 		      VarEvalMode emode)
   2141   1.957    rillig {
   2142   1.957    rillig 	const char *p = *pp;
   2143  1.1042    rillig 	FStr nested_val = Var_Parse(&p, ch->expr->scope,
   2144  1.1042    rillig 	    VarEvalMode_WithoutKeepDollar(emode));
   2145   1.957    rillig 	/* TODO: handle errors */
   2146  1.1047    rillig 	if (VarEvalMode_ShouldEval(emode))
   2147  1.1047    rillig 		LazyBuf_AddStr(part, nested_val.str);
   2148  1.1047    rillig 	else
   2149  1.1047    rillig 		LazyBuf_AddSubstring(part, Substring_Init(*pp, p));
   2150   1.957    rillig 	FStr_Done(&nested_val);
   2151   1.957    rillig 	*pp = p;
   2152   1.957    rillig }
   2153   1.957    rillig 
   2154  1.1029    rillig /*
   2155  1.1047    rillig  * In a part of a modifier, parse some text that looks like a subexpression.
   2156  1.1047    rillig  * If the text starts with '$(', any '(' and ')' must be balanced.
   2157  1.1047    rillig  * If the text starts with '${', any '{' and '}' must be balanced.
   2158  1.1066    rillig  * If the text starts with '$', that '$' is copied verbatim, it is not parsed
   2159  1.1075    rillig  * as a short-name expression.
   2160  1.1029    rillig  */
   2161   1.956    rillig static void
   2162  1.1047    rillig ParseModifierPartBalanced(const char **pp, LazyBuf *part)
   2163   1.956    rillig {
   2164   1.956    rillig 	const char *p = *pp;
   2165   1.956    rillig 
   2166   1.956    rillig 	if (p[1] == '(' || p[1] == '{') {
   2167  1.1029    rillig 		char startc = p[1];
   2168  1.1029    rillig 		int endc = startc == '(' ? ')' : '}';
   2169  1.1029    rillig 		int depth = 1;
   2170  1.1029    rillig 
   2171  1.1029    rillig 		for (p += 2; *p != '\0' && depth > 0; p++) {
   2172  1.1029    rillig 			if (p[-1] != '\\') {
   2173  1.1029    rillig 				if (*p == startc)
   2174  1.1029    rillig 					depth++;
   2175  1.1029    rillig 				if (*p == endc)
   2176  1.1029    rillig 					depth--;
   2177  1.1029    rillig 			}
   2178  1.1029    rillig 		}
   2179  1.1089    rillig 		LazyBuf_AddSubstring(part, Substring_Init(*pp, p));
   2180  1.1029    rillig 		*pp = p;
   2181   1.956    rillig 	} else {
   2182  1.1089    rillig 		LazyBuf_Add(part, *p);
   2183  1.1029    rillig 		*pp = p + 1;
   2184   1.956    rillig 	}
   2185   1.956    rillig }
   2186   1.956    rillig 
   2187  1.1115    rillig /*
   2188  1.1115    rillig  * Parse a part of a modifier such as the "from" and "to" in :S/from/to/ or
   2189  1.1115    rillig  * the "var" or "replacement ${var}" in :@var@replacement ${var}@, up to and
   2190  1.1115    rillig  * including the next unescaped delimiter.  The delimiter, as well as the
   2191  1.1115    rillig  * backslash or the dollar, can be escaped with a backslash.
   2192  1.1115    rillig  *
   2193  1.1115    rillig  * Return true if parsing succeeded, together with the parsed (and possibly
   2194  1.1115    rillig  * expanded) part.  In that case, pp points right after the delimiter.  The
   2195  1.1115    rillig  * delimiter is not included in the part though.
   2196  1.1115    rillig  */
   2197  1.1044    rillig static bool
   2198  1.1115    rillig ParseModifierPart(
   2199  1.1115    rillig     /* The parsing position, updated upon return */
   2200   1.703    rillig     const char **pp,
   2201  1.1115    rillig     char end1,
   2202  1.1115    rillig     char end2,
   2203  1.1115    rillig     /* Mode for evaluating nested expressions. */
   2204   1.906    rillig     VarEvalMode emode,
   2205   1.891    rillig     ModChain *ch,
   2206   1.921    rillig     LazyBuf *part,
   2207   1.988    rillig     /*
   2208  1.1066    rillig      * For the first part of the ':S' modifier, set anchorEnd if the last
   2209   1.988    rillig      * character of the pattern is a $.
   2210   1.988    rillig      */
   2211   1.927    rillig     PatternFlags *out_pflags,
   2212   1.988    rillig     /*
   2213  1.1066    rillig      * For the second part of the ':S' modifier, allow ampersands to be
   2214  1.1066    rillig      * escaped and replace unescaped ampersands with subst->lhs.
   2215   1.988    rillig      */
   2216   1.541    rillig     struct ModifyWord_SubstArgs *subst
   2217   1.704    rillig )
   2218   1.704    rillig {
   2219  1.1115    rillig 	const char *p = *pp;
   2220   1.704    rillig 
   2221   1.923    rillig 	LazyBuf_Init(part, p);
   2222  1.1050    rillig 	while (*p != '\0' && *p != end1 && *p != end2) {
   2223  1.1171    rillig 		if (IsEscapedModifierPart(p, end1, end2, subst)) {
   2224   1.921    rillig 			LazyBuf_Add(part, p[1]);
   2225   1.704    rillig 			p += 2;
   2226   1.958    rillig 		} else if (*p != '$') {	/* Unescaped, simple text */
   2227   1.704    rillig 			if (subst != NULL && *p == '&')
   2228   1.921    rillig 				LazyBuf_AddSubstring(part, subst->lhs);
   2229   1.704    rillig 			else
   2230   1.921    rillig 				LazyBuf_Add(part, *p);
   2231   1.704    rillig 			p++;
   2232  1.1115    rillig 		} else if (p[1] == end2) {	/* Unescaped '$' at end */
   2233   1.704    rillig 			if (out_pflags != NULL)
   2234   1.895    rillig 				out_pflags->anchorEnd = true;
   2235   1.704    rillig 			else
   2236   1.921    rillig 				LazyBuf_Add(part, *p);
   2237   1.704    rillig 			p++;
   2238  1.1047    rillig 		} else if (emode == VARE_PARSE_BALANCED)
   2239  1.1047    rillig 			ParseModifierPartBalanced(&p, part);
   2240  1.1047    rillig 		else
   2241   1.957    rillig 			ParseModifierPartExpr(&p, part, ch, emode);
   2242   1.529    rillig 	}
   2243   1.529    rillig 
   2244  1.1050    rillig 	if (*p != end1 && *p != end2) {
   2245  1.1125    rillig 		Parse_Error(PARSE_FATAL,
   2246  1.1148    rillig 		    "Unfinished modifier after \"%.*s\", expecting \"%c\"",
   2247  1.1148    rillig 		    (int)(p - *pp), *pp, end2);
   2248   1.921    rillig 		LazyBuf_Done(part);
   2249  1.1148    rillig 		*pp = p;
   2250  1.1044    rillig 		return false;
   2251   1.704    rillig 	}
   2252  1.1148    rillig 	*pp = p;
   2253  1.1115    rillig 	if (end1 == end2)
   2254  1.1050    rillig 		(*pp)++;
   2255   1.529    rillig 
   2256   1.921    rillig 	{
   2257   1.921    rillig 		Substring sub = LazyBuf_Get(part);
   2258   1.921    rillig 		DEBUG2(VAR, "Modifier part: \"%.*s\"\n",
   2259   1.921    rillig 		    (int)Substring_Length(sub), sub.start);
   2260   1.921    rillig 	}
   2261   1.921    rillig 
   2262  1.1044    rillig 	return true;
   2263   1.529    rillig }
   2264   1.529    rillig 
   2265   1.895    rillig MAKE_INLINE bool
   2266   1.891    rillig IsDelimiter(char c, const ModChain *ch)
   2267   1.859    rillig {
   2268  1.1032    rillig 	return c == ':' || c == ch->endc || c == '\0';
   2269   1.859    rillig }
   2270   1.859    rillig 
   2271   1.400    rillig /* Test whether mod starts with modname, followed by a delimiter. */
   2272   1.895    rillig MAKE_INLINE bool
   2273   1.891    rillig ModMatch(const char *mod, const char *modname, const ModChain *ch)
   2274   1.340    rillig {
   2275   1.703    rillig 	size_t n = strlen(modname);
   2276   1.891    rillig 	return strncmp(mod, modname, n) == 0 && IsDelimiter(mod[n], ch);
   2277   1.340    rillig }
   2278   1.340    rillig 
   2279   1.400    rillig /* Test whether mod starts with modname, followed by a delimiter or '='. */
   2280   1.895    rillig MAKE_INLINE bool
   2281   1.891    rillig ModMatchEq(const char *mod, const char *modname, const ModChain *ch)
   2282   1.340    rillig {
   2283   1.703    rillig 	size_t n = strlen(modname);
   2284   1.703    rillig 	return strncmp(mod, modname, n) == 0 &&
   2285   1.891    rillig 	       (IsDelimiter(mod[n], ch) || mod[n] == '=');
   2286   1.340    rillig }
   2287   1.236    rillig 
   2288   1.895    rillig static bool
   2289   1.635    rillig TryParseIntBase0(const char **pp, int *out_num)
   2290   1.635    rillig {
   2291   1.703    rillig 	char *end;
   2292   1.703    rillig 	long n;
   2293   1.635    rillig 
   2294   1.703    rillig 	errno = 0;
   2295   1.703    rillig 	n = strtol(*pp, &end, 0);
   2296   1.865    rillig 
   2297   1.865    rillig 	if (end == *pp)
   2298   1.895    rillig 		return false;
   2299   1.703    rillig 	if ((n == LONG_MIN || n == LONG_MAX) && errno == ERANGE)
   2300   1.895    rillig 		return false;
   2301   1.703    rillig 	if (n < INT_MIN || n > INT_MAX)
   2302   1.895    rillig 		return false;
   2303   1.635    rillig 
   2304   1.703    rillig 	*pp = end;
   2305   1.703    rillig 	*out_num = (int)n;
   2306   1.895    rillig 	return true;
   2307   1.635    rillig }
   2308   1.635    rillig 
   2309   1.895    rillig static bool
   2310   1.635    rillig TryParseSize(const char **pp, size_t *out_num)
   2311   1.635    rillig {
   2312   1.703    rillig 	char *end;
   2313   1.703    rillig 	unsigned long n;
   2314   1.635    rillig 
   2315   1.703    rillig 	if (!ch_isdigit(**pp))
   2316   1.895    rillig 		return false;
   2317   1.635    rillig 
   2318   1.703    rillig 	errno = 0;
   2319   1.703    rillig 	n = strtoul(*pp, &end, 10);
   2320   1.703    rillig 	if (n == ULONG_MAX && errno == ERANGE)
   2321   1.895    rillig 		return false;
   2322   1.703    rillig 	if (n > SIZE_MAX)
   2323   1.895    rillig 		return false;
   2324   1.635    rillig 
   2325   1.703    rillig 	*pp = end;
   2326   1.703    rillig 	*out_num = (size_t)n;
   2327   1.895    rillig 	return true;
   2328   1.635    rillig }
   2329   1.635    rillig 
   2330   1.895    rillig static bool
   2331   1.635    rillig TryParseChar(const char **pp, int base, char *out_ch)
   2332   1.635    rillig {
   2333   1.703    rillig 	char *end;
   2334   1.703    rillig 	unsigned long n;
   2335   1.635    rillig 
   2336   1.703    rillig 	if (!ch_isalnum(**pp))
   2337   1.895    rillig 		return false;
   2338   1.635    rillig 
   2339   1.703    rillig 	errno = 0;
   2340   1.703    rillig 	n = strtoul(*pp, &end, base);
   2341   1.703    rillig 	if (n == ULONG_MAX && errno == ERANGE)
   2342   1.895    rillig 		return false;
   2343   1.703    rillig 	if (n > UCHAR_MAX)
   2344   1.895    rillig 		return false;
   2345   1.635    rillig 
   2346   1.703    rillig 	*pp = end;
   2347   1.703    rillig 	*out_ch = (char)n;
   2348   1.895    rillig 	return true;
   2349   1.635    rillig }
   2350   1.635    rillig 
   2351   1.820    rillig /*
   2352   1.822    rillig  * Modify each word of the expression using the given function and place the
   2353   1.822    rillig  * result back in the expression.
   2354   1.820    rillig  */
   2355   1.820    rillig static void
   2356   1.891    rillig ModifyWords(ModChain *ch,
   2357   1.822    rillig 	    ModifyWordProc modifyWord, void *modifyWord_args,
   2358   1.895    rillig 	    bool oneBigWord)
   2359   1.820    rillig {
   2360   1.891    rillig 	Expr *expr = ch->expr;
   2361   1.965    rillig 	const char *val = Expr_Str(expr);
   2362   1.820    rillig 	SepBuf result;
   2363   1.920    rillig 	SubstringWords words;
   2364   1.820    rillig 	size_t i;
   2365   1.919    rillig 	Substring word;
   2366   1.820    rillig 
   2367  1.1097    rillig 	if (!ModChain_ShouldEval(ch))
   2368  1.1097    rillig 		return;
   2369  1.1097    rillig 
   2370   1.820    rillig 	if (oneBigWord) {
   2371   1.891    rillig 		SepBuf_Init(&result, ch->sep);
   2372   1.919    rillig 		/* XXX: performance: Substring_InitStr calls strlen */
   2373   1.919    rillig 		word = Substring_InitStr(val);
   2374   1.919    rillig 		modifyWord(word, &result, modifyWord_args);
   2375   1.820    rillig 		goto done;
   2376   1.820    rillig 	}
   2377   1.820    rillig 
   2378   1.920    rillig 	words = Substring_Words(val, false);
   2379   1.820    rillig 
   2380   1.954    rillig 	DEBUG3(VAR, "ModifyWords: split \"%s\" into %u %s\n",
   2381   1.954    rillig 	    val, (unsigned)words.len, words.len != 1 ? "words" : "word");
   2382   1.820    rillig 
   2383   1.891    rillig 	SepBuf_Init(&result, ch->sep);
   2384   1.820    rillig 	for (i = 0; i < words.len; i++) {
   2385   1.920    rillig 		modifyWord(words.words[i], &result, modifyWord_args);
   2386   1.820    rillig 		if (result.buf.len > 0)
   2387   1.820    rillig 			SepBuf_Sep(&result);
   2388   1.820    rillig 	}
   2389   1.820    rillig 
   2390   1.920    rillig 	SubstringWords_Free(words);
   2391   1.820    rillig 
   2392   1.820    rillig done:
   2393   1.823    rillig 	Expr_SetValueOwn(expr, SepBuf_DoneData(&result));
   2394   1.820    rillig }
   2395   1.820    rillig 
   2396   1.236    rillig /* :@var (at) ...${var}...@ */
   2397   1.356    rillig static ApplyModifierResult
   2398   1.891    rillig ApplyModifier_Loop(const char **pp, ModChain *ch)
   2399   1.417    rillig {
   2400   1.891    rillig 	Expr *expr = ch->expr;
   2401   1.703    rillig 	struct ModifyWord_LoopArgs args;
   2402   1.703    rillig 	char prev_sep;
   2403   1.921    rillig 	LazyBuf tvarBuf, strBuf;
   2404   1.921    rillig 	FStr tvar, str;
   2405   1.703    rillig 
   2406   1.823    rillig 	args.scope = expr->scope;
   2407   1.703    rillig 
   2408   1.703    rillig 	(*pp)++;		/* Skip the first '@' */
   2409  1.1119    rillig 	if (!ParseModifierPart(pp, '@', '@', VARE_PARSE,
   2410  1.1115    rillig 	    ch, &tvarBuf, NULL, NULL))
   2411   1.703    rillig 		return AMR_CLEANUP;
   2412   1.921    rillig 	tvar = LazyBuf_DoneGet(&tvarBuf);
   2413   1.928    rillig 	args.var = tvar.str;
   2414   1.928    rillig 	if (strchr(args.var, '$') != NULL) {
   2415   1.703    rillig 		Parse_Error(PARSE_FATAL,
   2416  1.1102    rillig 		    "In the :@ modifier, the variable name \"%s\" "
   2417   1.969    rillig 		    "must not contain a dollar",
   2418  1.1102    rillig 		    args.var);
   2419  1.1112    rillig 		goto cleanup_tvar;
   2420   1.703    rillig 	}
   2421   1.236    rillig 
   2422  1.1115    rillig 	if (!ParseModifierPart(pp, '@', '@', VARE_PARSE_BALANCED,
   2423  1.1115    rillig 	    ch, &strBuf, NULL, NULL))
   2424  1.1112    rillig 		goto cleanup_tvar;
   2425   1.921    rillig 	str = LazyBuf_DoneGet(&strBuf);
   2426   1.928    rillig 	args.body = str.str;
   2427   1.703    rillig 
   2428   1.906    rillig 	if (!Expr_ShouldEval(expr))
   2429   1.870    rillig 		goto done;
   2430   1.870    rillig 
   2431   1.906    rillig 	args.emode = VarEvalMode_WithoutKeepDollar(expr->emode);
   2432   1.891    rillig 	prev_sep = ch->sep;
   2433   1.891    rillig 	ch->sep = ' ';		/* XXX: should be ch->sep for consistency */
   2434   1.891    rillig 	ModifyWords(ch, ModifyWord_Loop, &args, ch->oneBigWord);
   2435   1.891    rillig 	ch->sep = prev_sep;
   2436   1.928    rillig 	/* XXX: Consider restoring the previous value instead of deleting. */
   2437   1.928    rillig 	Var_Delete(expr->scope, args.var);
   2438   1.870    rillig 
   2439   1.870    rillig done:
   2440   1.921    rillig 	FStr_Done(&tvar);
   2441   1.921    rillig 	FStr_Done(&str);
   2442   1.703    rillig 	return AMR_OK;
   2443  1.1112    rillig 
   2444  1.1112    rillig cleanup_tvar:
   2445  1.1112    rillig 	FStr_Done(&tvar);
   2446  1.1112    rillig 	return AMR_CLEANUP;
   2447   1.236    rillig }
   2448   1.236    rillig 
   2449  1.1026    rillig static void
   2450  1.1027    rillig ParseModifier_Defined(const char **pp, ModChain *ch, bool shouldEval,
   2451  1.1026    rillig 		      LazyBuf *buf)
   2452   1.236    rillig {
   2453   1.703    rillig 	const char *p;
   2454   1.412    rillig 
   2455   1.703    rillig 	p = *pp + 1;
   2456  1.1026    rillig 	LazyBuf_Init(buf, p);
   2457  1.1032    rillig 	while (!IsDelimiter(*p, ch)) {
   2458   1.703    rillig 
   2459   1.988    rillig 		/*
   2460   1.988    rillig 		 * XXX: This code is similar to the one in Var_Parse. See if
   2461  1.1065    rillig 		 * the code can be merged. See also ParseModifier_Match and
   2462   1.988    rillig 		 * ParseModifierPart.
   2463   1.988    rillig 		 */
   2464   1.703    rillig 
   2465  1.1066    rillig 		/* See Buf_AddEscaped in for.c for the counterpart. */
   2466   1.703    rillig 		if (*p == '\\') {
   2467   1.703    rillig 			char c = p[1];
   2468  1.1030    rillig 			if ((IsDelimiter(c, ch) && c != '\0') ||
   2469  1.1030    rillig 			    c == '$' || c == '\\') {
   2470  1.1027    rillig 				if (shouldEval)
   2471  1.1027    rillig 					LazyBuf_Add(buf, c);
   2472   1.703    rillig 				p += 2;
   2473   1.703    rillig 				continue;
   2474   1.703    rillig 			}
   2475   1.703    rillig 		}
   2476   1.236    rillig 
   2477   1.703    rillig 		if (*p == '$') {
   2478  1.1042    rillig 			FStr val = Var_Parse(&p, ch->expr->scope,
   2479  1.1119    rillig 			    shouldEval ? ch->expr->emode : VARE_PARSE);
   2480   1.703    rillig 			/* TODO: handle errors */
   2481  1.1027    rillig 			if (shouldEval)
   2482  1.1027    rillig 				LazyBuf_AddStr(buf, val.str);
   2483  1.1027    rillig 			FStr_Done(&val);
   2484   1.703    rillig 			continue;
   2485   1.703    rillig 		}
   2486   1.687    rillig 
   2487  1.1027    rillig 		if (shouldEval)
   2488  1.1027    rillig 			LazyBuf_Add(buf, *p);
   2489   1.703    rillig 		p++;
   2490   1.466    rillig 	}
   2491   1.703    rillig 	*pp = p;
   2492  1.1026    rillig }
   2493  1.1026    rillig 
   2494  1.1026    rillig /* :Ddefined or :Uundefined */
   2495  1.1026    rillig static ApplyModifierResult
   2496  1.1026    rillig ApplyModifier_Defined(const char **pp, ModChain *ch)
   2497  1.1026    rillig {
   2498  1.1026    rillig 	Expr *expr = ch->expr;
   2499  1.1026    rillig 	LazyBuf buf;
   2500  1.1027    rillig 	bool shouldEval =
   2501  1.1027    rillig 	    Expr_ShouldEval(expr) &&
   2502  1.1027    rillig 	    (**pp == 'D') == (expr->defined == DEF_REGULAR);
   2503  1.1026    rillig 
   2504  1.1027    rillig 	ParseModifier_Defined(pp, ch, shouldEval, &buf);
   2505   1.466    rillig 
   2506   1.823    rillig 	Expr_Define(expr);
   2507  1.1027    rillig 	if (shouldEval)
   2508   1.929    rillig 		Expr_SetValue(expr, Substring_Str(LazyBuf_Get(&buf)));
   2509  1.1111    rillig 	LazyBuf_Done(&buf);
   2510   1.821    rillig 
   2511   1.703    rillig 	return AMR_OK;
   2512   1.236    rillig }
   2513   1.236    rillig 
   2514   1.567    rillig /* :L */
   2515   1.567    rillig static ApplyModifierResult
   2516   1.891    rillig ApplyModifier_Literal(const char **pp, ModChain *ch)
   2517   1.567    rillig {
   2518   1.891    rillig 	Expr *expr = ch->expr;
   2519   1.864    rillig 
   2520   1.864    rillig 	(*pp)++;
   2521   1.864    rillig 
   2522   1.905    rillig 	if (Expr_ShouldEval(expr)) {
   2523   1.872    rillig 		Expr_Define(expr);
   2524   1.898    rillig 		Expr_SetValueOwn(expr, bmake_strdup(expr->name));
   2525   1.872    rillig 	}
   2526   1.864    rillig 
   2527   1.703    rillig 	return AMR_OK;
   2528   1.567    rillig }
   2529   1.567    rillig 
   2530   1.895    rillig static bool
   2531   1.633    rillig TryParseTime(const char **pp, time_t *out_time)
   2532   1.631    rillig {
   2533   1.703    rillig 	char *end;
   2534   1.703    rillig 	unsigned long n;
   2535   1.631    rillig 
   2536   1.703    rillig 	if (!ch_isdigit(**pp))
   2537   1.895    rillig 		return false;
   2538   1.631    rillig 
   2539   1.703    rillig 	errno = 0;
   2540   1.703    rillig 	n = strtoul(*pp, &end, 10);
   2541   1.703    rillig 	if (n == ULONG_MAX && errno == ERANGE)
   2542   1.895    rillig 		return false;
   2543   1.631    rillig 
   2544   1.703    rillig 	*pp = end;
   2545   1.703    rillig 	*out_time = (time_t)n;	/* ignore possible truncation for now */
   2546   1.895    rillig 	return true;
   2547   1.631    rillig }
   2548   1.631    rillig 
   2549   1.994    rillig /* :gmtime and :localtime */
   2550   1.356    rillig static ApplyModifierResult
   2551   1.995    rillig ApplyModifier_Time(const char **pp, ModChain *ch)
   2552   1.236    rillig {
   2553   1.950    rillig 	Expr *expr;
   2554   1.993    rillig 	time_t t;
   2555   1.994    rillig 	const char *args;
   2556   1.995    rillig 	const char *mod = *pp;
   2557   1.995    rillig 	bool gmt = mod[0] == 'g';
   2558   1.412    rillig 
   2559   1.994    rillig 	if (!ModMatchEq(mod, gmt ? "gmtime" : "localtime", ch))
   2560   1.703    rillig 		return AMR_UNKNOWN;
   2561   1.994    rillig 	args = mod + (gmt ? 6 : 9);
   2562   1.703    rillig 
   2563   1.994    rillig 	if (args[0] == '=') {
   2564   1.994    rillig 		const char *p = args + 1;
   2565  1.1050    rillig 		LazyBuf buf;
   2566  1.1104    rillig 		FStr arg;
   2567  1.1115    rillig 		if (!ParseModifierPart(&p, ':', ch->endc, ch->expr->emode,
   2568  1.1050    rillig 		    ch, &buf, NULL, NULL))
   2569   1.703    rillig 			return AMR_CLEANUP;
   2570  1.1104    rillig 		arg = LazyBuf_DoneGet(&buf);
   2571  1.1050    rillig 		if (ModChain_ShouldEval(ch)) {
   2572  1.1104    rillig 			const char *arg_p = arg.str;
   2573  1.1104    rillig 			if (!TryParseTime(&arg_p, &t) || *arg_p != '\0') {
   2574  1.1050    rillig 				Parse_Error(PARSE_FATAL,
   2575  1.1104    rillig 				    "Invalid time value \"%s\"", arg.str);
   2576  1.1104    rillig 				FStr_Done(&arg);
   2577  1.1050    rillig 				return AMR_CLEANUP;
   2578  1.1050    rillig 			}
   2579  1.1050    rillig 		} else
   2580  1.1050    rillig 			t = 0;
   2581  1.1104    rillig 		FStr_Done(&arg);
   2582   1.843    rillig 		*pp = p;
   2583   1.703    rillig 	} else {
   2584   1.993    rillig 		t = 0;
   2585   1.994    rillig 		*pp = args;
   2586   1.631    rillig 	}
   2587   1.864    rillig 
   2588   1.950    rillig 	expr = ch->expr;
   2589   1.950    rillig 	if (Expr_ShouldEval(expr))
   2590  1.1059    rillig 		Expr_SetValueOwn(expr, FormatTime(Expr_Str(expr), t, gmt));
   2591   1.864    rillig 
   2592   1.703    rillig 	return AMR_OK;
   2593   1.236    rillig }
   2594   1.236    rillig 
   2595   1.236    rillig /* :hash */
   2596   1.356    rillig static ApplyModifierResult
   2597   1.891    rillig ApplyModifier_Hash(const char **pp, ModChain *ch)
   2598   1.236    rillig {
   2599   1.891    rillig 	if (!ModMatch(*pp, "hash", ch))
   2600   1.703    rillig 		return AMR_UNKNOWN;
   2601   1.864    rillig 	*pp += 4;
   2602   1.340    rillig 
   2603   1.905    rillig 	if (ModChain_ShouldEval(ch))
   2604  1.1059    rillig 		Expr_SetValueOwn(ch->expr, Hash(Expr_Str(ch->expr)));
   2605   1.864    rillig 
   2606   1.703    rillig 	return AMR_OK;
   2607   1.236    rillig }
   2608   1.236    rillig 
   2609   1.236    rillig /* :P */
   2610   1.356    rillig static ApplyModifierResult
   2611   1.891    rillig ApplyModifier_Path(const char **pp, ModChain *ch)
   2612   1.236    rillig {
   2613   1.891    rillig 	Expr *expr = ch->expr;
   2614   1.703    rillig 	GNode *gn;
   2615   1.703    rillig 	char *path;
   2616   1.412    rillig 
   2617   1.864    rillig 	(*pp)++;
   2618   1.864    rillig 
   2619   1.950    rillig 	if (!Expr_ShouldEval(expr))
   2620   1.873    rillig 		return AMR_OK;
   2621   1.873    rillig 
   2622   1.823    rillig 	Expr_Define(expr);
   2623   1.409    rillig 
   2624   1.898    rillig 	gn = Targ_FindNode(expr->name);
   2625  1.1067    rillig 	if (gn == NULL || gn->type & OP_NOPATH)
   2626   1.703    rillig 		path = NULL;
   2627  1.1067    rillig 	else if (gn->path != NULL)
   2628   1.703    rillig 		path = bmake_strdup(gn->path);
   2629  1.1067    rillig 	else {
   2630   1.703    rillig 		SearchPath *searchPath = Suff_FindPath(gn);
   2631   1.898    rillig 		path = Dir_FindFile(expr->name, searchPath);
   2632   1.703    rillig 	}
   2633   1.703    rillig 	if (path == NULL)
   2634   1.898    rillig 		path = bmake_strdup(expr->name);
   2635   1.823    rillig 	Expr_SetValueOwn(expr, path);
   2636   1.409    rillig 
   2637   1.703    rillig 	return AMR_OK;
   2638   1.236    rillig }
   2639   1.236    rillig 
   2640   1.236    rillig /* :!cmd! */
   2641   1.356    rillig static ApplyModifierResult
   2642   1.891    rillig ApplyModifier_ShellCommand(const char **pp, ModChain *ch)
   2643   1.236    rillig {
   2644   1.891    rillig 	Expr *expr = ch->expr;
   2645   1.921    rillig 	LazyBuf cmdBuf;
   2646   1.921    rillig 	FStr cmd;
   2647   1.703    rillig 
   2648   1.703    rillig 	(*pp)++;
   2649  1.1115    rillig 	if (!ParseModifierPart(pp, '!', '!', expr->emode,
   2650  1.1115    rillig 	    ch, &cmdBuf, NULL, NULL))
   2651   1.703    rillig 		return AMR_CLEANUP;
   2652   1.921    rillig 	cmd = LazyBuf_DoneGet(&cmdBuf);
   2653   1.921    rillig 
   2654  1.1000    rillig 	if (Expr_ShouldEval(expr)) {
   2655  1.1000    rillig 		char *output, *error;
   2656  1.1000    rillig 		output = Cmd_Exec(cmd.str, &error);
   2657  1.1000    rillig 		Expr_SetValueOwn(expr, output);
   2658  1.1000    rillig 		if (error != NULL) {
   2659  1.1122    rillig 			Parse_Error(PARSE_WARNING, "%s", error);
   2660  1.1000    rillig 			free(error);
   2661  1.1000    rillig 		}
   2662  1.1000    rillig 	} else
   2663  1.1000    rillig 		Expr_SetValueRefer(expr, "");
   2664   1.703    rillig 
   2665   1.921    rillig 	FStr_Done(&cmd);
   2666   1.864    rillig 	Expr_Define(expr);
   2667   1.274    rillig 
   2668   1.703    rillig 	return AMR_OK;
   2669   1.236    rillig }
   2670   1.236    rillig 
   2671   1.778    rillig /*
   2672   1.778    rillig  * The :range modifier generates an integer sequence as long as the words.
   2673   1.778    rillig  * The :range=7 modifier generates an integer sequence from 1 to 7.
   2674   1.778    rillig  */
   2675   1.356    rillig static ApplyModifierResult
   2676   1.891    rillig ApplyModifier_Range(const char **pp, ModChain *ch)
   2677   1.236    rillig {
   2678   1.703    rillig 	size_t n;
   2679   1.703    rillig 	Buffer buf;
   2680   1.703    rillig 	size_t i;
   2681   1.412    rillig 
   2682   1.703    rillig 	const char *mod = *pp;
   2683   1.891    rillig 	if (!ModMatchEq(mod, "range", ch))
   2684   1.703    rillig 		return AMR_UNKNOWN;
   2685   1.703    rillig 
   2686   1.703    rillig 	if (mod[5] == '=') {
   2687   1.703    rillig 		const char *p = mod + 6;
   2688   1.703    rillig 		if (!TryParseSize(&p, &n)) {
   2689   1.703    rillig 			Parse_Error(PARSE_FATAL,
   2690  1.1170    rillig 			    "Invalid number \"%s\" for modifier \":range\"",
   2691   1.844    rillig 			    mod + 6);
   2692   1.703    rillig 			return AMR_CLEANUP;
   2693   1.703    rillig 		}
   2694   1.703    rillig 		*pp = p;
   2695   1.703    rillig 	} else {
   2696   1.703    rillig 		n = 0;
   2697   1.703    rillig 		*pp = mod + 5;
   2698   1.635    rillig 	}
   2699   1.386    rillig 
   2700   1.905    rillig 	if (!ModChain_ShouldEval(ch))
   2701   1.873    rillig 		return AMR_OK;
   2702   1.873    rillig 
   2703   1.703    rillig 	if (n == 0) {
   2704   1.967    rillig 		SubstringWords words = Expr_Words(ch->expr);
   2705   1.703    rillig 		n = words.len;
   2706   1.961    rillig 		SubstringWords_Free(words);
   2707   1.703    rillig 	}
   2708   1.386    rillig 
   2709   1.703    rillig 	Buf_Init(&buf);
   2710   1.386    rillig 
   2711   1.703    rillig 	for (i = 0; i < n; i++) {
   2712   1.703    rillig 		if (i != 0) {
   2713   1.988    rillig 			/*
   2714   1.988    rillig 			 * XXX: Use ch->sep instead of ' ', for consistency.
   2715   1.988    rillig 			 */
   2716   1.703    rillig 			Buf_AddByte(&buf, ' ');
   2717   1.703    rillig 		}
   2718   1.703    rillig 		Buf_AddInt(&buf, 1 + (int)i);
   2719   1.703    rillig 	}
   2720   1.386    rillig 
   2721   1.891    rillig 	Expr_SetValueOwn(ch->expr, Buf_DoneData(&buf));
   2722   1.703    rillig 	return AMR_OK;
   2723   1.236    rillig }
   2724   1.236    rillig 
   2725   1.845    rillig /* Parse a ':M' or ':N' modifier. */
   2726  1.1013    rillig static char *
   2727  1.1013    rillig ParseModifier_Match(const char **pp, const ModChain *ch)
   2728   1.236    rillig {
   2729   1.845    rillig 	const char *mod = *pp;
   2730   1.891    rillig 	Expr *expr = ch->expr;
   2731   1.895    rillig 	bool copy = false;	/* pattern should be, or has been, copied */
   2732   1.895    rillig 	bool needSubst = false;
   2733   1.703    rillig 	const char *endpat;
   2734   1.703    rillig 	char *pattern;
   2735   1.412    rillig 
   2736   1.703    rillig 	/*
   2737   1.703    rillig 	 * In the loop below, ignore ':' unless we are at (or back to) the
   2738   1.703    rillig 	 * original brace level.
   2739   1.703    rillig 	 * XXX: This will likely not work right if $() and ${} are intermixed.
   2740   1.703    rillig 	 */
   2741   1.845    rillig 	/*
   2742   1.845    rillig 	 * XXX: This code is similar to the one in Var_Parse.
   2743   1.703    rillig 	 * See if the code can be merged.
   2744   1.845    rillig 	 * See also ApplyModifier_Defined.
   2745   1.845    rillig 	 */
   2746  1.1083    rillig 	int depth = 0;
   2747   1.703    rillig 	const char *p;
   2748  1.1083    rillig 	for (p = mod + 1; *p != '\0' && !(*p == ':' && depth == 0); p++) {
   2749  1.1031    rillig 		if (*p == '\\' && p[1] != '\0' &&
   2750   1.891    rillig 		    (IsDelimiter(p[1], ch) || p[1] == ch->startc)) {
   2751   1.703    rillig 			if (!needSubst)
   2752   1.895    rillig 				copy = true;
   2753   1.703    rillig 			p++;
   2754   1.703    rillig 			continue;
   2755   1.703    rillig 		}
   2756   1.703    rillig 		if (*p == '$')
   2757   1.895    rillig 			needSubst = true;
   2758   1.703    rillig 		if (*p == '(' || *p == '{')
   2759  1.1083    rillig 			depth++;
   2760   1.703    rillig 		if (*p == ')' || *p == '}') {
   2761  1.1083    rillig 			depth--;
   2762  1.1083    rillig 			if (depth < 0)
   2763   1.703    rillig 				break;
   2764   1.703    rillig 		}
   2765   1.236    rillig 	}
   2766   1.703    rillig 	*pp = p;
   2767   1.703    rillig 	endpat = p;
   2768   1.703    rillig 
   2769   1.703    rillig 	if (copy) {
   2770   1.703    rillig 		char *dst;
   2771   1.703    rillig 		const char *src;
   2772   1.703    rillig 
   2773   1.703    rillig 		/* Compress the \:'s out of the pattern. */
   2774   1.703    rillig 		pattern = bmake_malloc((size_t)(endpat - (mod + 1)) + 1);
   2775   1.703    rillig 		dst = pattern;
   2776   1.703    rillig 		src = mod + 1;
   2777   1.703    rillig 		for (; src < endpat; src++, dst++) {
   2778   1.703    rillig 			if (src[0] == '\\' && src + 1 < endpat &&
   2779   1.891    rillig 			    /* XXX: ch->startc is missing here; see above */
   2780   1.891    rillig 			    IsDelimiter(src[1], ch))
   2781   1.703    rillig 				src++;
   2782   1.703    rillig 			*dst = *src;
   2783   1.703    rillig 		}
   2784   1.703    rillig 		*dst = '\0';
   2785   1.703    rillig 	} else {
   2786   1.703    rillig 		pattern = bmake_strsedup(mod + 1, endpat);
   2787   1.236    rillig 	}
   2788   1.288    rillig 
   2789   1.703    rillig 	if (needSubst) {
   2790   1.703    rillig 		char *old_pattern = pattern;
   2791  1.1013    rillig 		/*
   2792  1.1013    rillig 		 * XXX: Contrary to ParseModifierPart, a dollar in a ':M' or
   2793  1.1013    rillig 		 * ':N' modifier must be escaped as '$$', not as '\$'.
   2794  1.1013    rillig 		 */
   2795  1.1043    rillig 		pattern = Var_Subst(pattern, expr->scope, expr->emode);
   2796   1.703    rillig 		/* TODO: handle errors */
   2797   1.703    rillig 		free(old_pattern);
   2798   1.236    rillig 	}
   2799   1.346    rillig 
   2800   1.908    rillig 	DEBUG2(VAR, "Pattern for ':%c' is \"%s\"\n", mod[0], pattern);
   2801   1.346    rillig 
   2802  1.1013    rillig 	return pattern;
   2803   1.845    rillig }
   2804   1.845    rillig 
   2805  1.1057    rillig struct ModifyWord_MatchArgs {
   2806  1.1057    rillig 	const char *pattern;
   2807  1.1057    rillig 	bool neg;
   2808  1.1058    rillig 	bool error_reported;
   2809  1.1057    rillig };
   2810  1.1057    rillig 
   2811  1.1057    rillig static void
   2812  1.1057    rillig ModifyWord_Match(Substring word, SepBuf *buf, void *data)
   2813  1.1057    rillig {
   2814  1.1057    rillig 	struct ModifyWord_MatchArgs *args = data;
   2815  1.1058    rillig 	StrMatchResult res;
   2816  1.1057    rillig 	assert(word.end[0] == '\0');	/* assume null-terminated word */
   2817  1.1058    rillig 	res = Str_Match(word.start, args->pattern);
   2818  1.1058    rillig 	if (res.error != NULL && !args->error_reported) {
   2819  1.1058    rillig 		args->error_reported = true;
   2820  1.1135    rillig 		Parse_Error(PARSE_FATAL,
   2821  1.1170    rillig 		    "%s in pattern \"%s\" of modifier \"%s\"",
   2822  1.1058    rillig 		    res.error, args->pattern, args->neg ? ":N" : ":M");
   2823  1.1058    rillig 	}
   2824  1.1058    rillig 	if (res.matched != args->neg)
   2825  1.1057    rillig 		SepBuf_AddSubstring(buf, word);
   2826  1.1057    rillig }
   2827  1.1057    rillig 
   2828   1.845    rillig /* :Mpattern or :Npattern */
   2829   1.845    rillig static ApplyModifierResult
   2830   1.891    rillig ApplyModifier_Match(const char **pp, ModChain *ch)
   2831   1.845    rillig {
   2832   1.996    rillig 	char mod = **pp;
   2833   1.845    rillig 	char *pattern;
   2834   1.845    rillig 
   2835  1.1013    rillig 	pattern = ParseModifier_Match(pp, ch);
   2836   1.845    rillig 
   2837   1.905    rillig 	if (ModChain_ShouldEval(ch)) {
   2838  1.1057    rillig 		struct ModifyWord_MatchArgs args;
   2839  1.1057    rillig 		args.pattern = pattern;
   2840  1.1057    rillig 		args.neg = mod == 'N';
   2841  1.1058    rillig 		args.error_reported = false;
   2842  1.1057    rillig 		ModifyWords(ch, ModifyWord_Match, &args, ch->oneBigWord);
   2843   1.876    rillig 	}
   2844   1.876    rillig 
   2845   1.703    rillig 	free(pattern);
   2846   1.703    rillig 	return AMR_OK;
   2847   1.236    rillig }
   2848   1.236    rillig 
   2849  1.1054       sjg struct ModifyWord_MtimeArgs {
   2850  1.1054       sjg 	bool error;
   2851  1.1060    rillig 	bool use_fallback;
   2852  1.1054       sjg 	ApplyModifierResult rc;
   2853  1.1060    rillig 	time_t fallback;
   2854  1.1054       sjg };
   2855  1.1054       sjg 
   2856  1.1054       sjg static void
   2857  1.1054       sjg ModifyWord_Mtime(Substring word, SepBuf *buf, void *data)
   2858  1.1054       sjg {
   2859  1.1060    rillig 	struct ModifyWord_MtimeArgs *args = data;
   2860  1.1054       sjg 	struct stat st;
   2861  1.1060    rillig 	char tbuf[21];
   2862  1.1054       sjg 
   2863  1.1054       sjg 	if (Substring_IsEmpty(word))
   2864  1.1054       sjg 		return;
   2865  1.1054       sjg 	assert(word.end[0] == '\0');	/* assume null-terminated word */
   2866  1.1054       sjg 	if (stat(word.start, &st) < 0) {
   2867  1.1054       sjg 		if (args->error) {
   2868  1.1054       sjg 			Parse_Error(PARSE_FATAL,
   2869  1.1166    rillig 			    "Cannot determine mtime for \"%s\": %s",
   2870  1.1054       sjg 			    word.start, strerror(errno));
   2871  1.1054       sjg 			args->rc = AMR_CLEANUP;
   2872  1.1054       sjg 			return;
   2873  1.1054       sjg 		}
   2874  1.1060    rillig 		if (args->use_fallback)
   2875  1.1060    rillig 			st.st_mtime = args->fallback;
   2876  1.1054       sjg 		else
   2877  1.1054       sjg 			time(&st.st_mtime);
   2878  1.1054       sjg 	}
   2879  1.1054       sjg 	snprintf(tbuf, sizeof(tbuf), "%u", (unsigned)st.st_mtime);
   2880  1.1054       sjg 	SepBuf_AddStr(buf, tbuf);
   2881  1.1054       sjg }
   2882  1.1054       sjg 
   2883  1.1051       sjg /* :mtime */
   2884  1.1051       sjg static ApplyModifierResult
   2885  1.1051       sjg ApplyModifier_Mtime(const char **pp, ModChain *ch)
   2886  1.1051       sjg {
   2887  1.1054       sjg 	const char *p, *mod = *pp;
   2888  1.1054       sjg 	struct ModifyWord_MtimeArgs args;
   2889  1.1051       sjg 
   2890  1.1051       sjg 	if (!ModMatchEq(mod, "mtime", ch))
   2891  1.1051       sjg 		return AMR_UNKNOWN;
   2892  1.1051       sjg 	*pp += 5;
   2893  1.1054       sjg 	p = *pp;
   2894  1.1060    rillig 	args.error = false;
   2895  1.1060    rillig 	args.use_fallback = p[0] == '=';
   2896  1.1054       sjg 	args.rc = AMR_OK;
   2897  1.1060    rillig 	if (args.use_fallback) {
   2898  1.1054       sjg 		p++;
   2899  1.1060    rillig 		if (TryParseTime(&p, &args.fallback)) {
   2900  1.1072    rillig 		} else if (strncmp(p, "error", 5) == 0) {
   2901  1.1060    rillig 			p += 5;
   2902  1.1060    rillig 			args.error = true;
   2903  1.1072    rillig 		} else
   2904  1.1072    rillig 			goto invalid_argument;
   2905  1.1072    rillig 		if (!IsDelimiter(*p, ch))
   2906  1.1072    rillig 			goto invalid_argument;
   2907  1.1054       sjg 		*pp = p;
   2908  1.1051       sjg 	}
   2909  1.1097    rillig 	ModifyWords(ch, ModifyWord_Mtime, &args, ch->oneBigWord);
   2910  1.1054       sjg 	return args.rc;
   2911  1.1072    rillig 
   2912  1.1072    rillig invalid_argument:
   2913  1.1072    rillig 	Parse_Error(PARSE_FATAL,
   2914  1.1170    rillig 	    "Invalid argument \"%.*s\" for modifier \":mtime\"",
   2915  1.1072    rillig 	    (int)strcspn(*pp + 1, ":{}()"), *pp + 1);
   2916  1.1072    rillig 	return AMR_CLEANUP;
   2917  1.1051       sjg }
   2918  1.1051       sjg 
   2919   1.860    rillig static void
   2920   1.927    rillig ParsePatternFlags(const char **pp, PatternFlags *pflags, bool *oneBigWord)
   2921   1.860    rillig {
   2922   1.860    rillig 	for (;; (*pp)++) {
   2923   1.860    rillig 		if (**pp == 'g')
   2924   1.895    rillig 			pflags->subGlobal = true;
   2925   1.860    rillig 		else if (**pp == '1')
   2926   1.895    rillig 			pflags->subOnce = true;
   2927   1.860    rillig 		else if (**pp == 'W')
   2928   1.895    rillig 			*oneBigWord = true;
   2929   1.860    rillig 		else
   2930   1.860    rillig 			break;
   2931   1.860    rillig 	}
   2932   1.860    rillig }
   2933   1.860    rillig 
   2934   1.927    rillig MAKE_INLINE PatternFlags
   2935   1.927    rillig PatternFlags_None(void)
   2936   1.897    rillig {
   2937   1.927    rillig 	PatternFlags pflags = { false, false, false, false };
   2938   1.897    rillig 	return pflags;
   2939   1.897    rillig }
   2940   1.897    rillig 
   2941   1.236    rillig /* :S,from,to, */
   2942   1.356    rillig static ApplyModifierResult
   2943   1.891    rillig ApplyModifier_Subst(const char **pp, ModChain *ch)
   2944   1.236    rillig {
   2945   1.703    rillig 	struct ModifyWord_SubstArgs args;
   2946   1.895    rillig 	bool oneBigWord;
   2947   1.921    rillig 	LazyBuf lhsBuf, rhsBuf;
   2948   1.299    rillig 
   2949   1.703    rillig 	char delim = (*pp)[1];
   2950   1.703    rillig 	if (delim == '\0') {
   2951  1.1125    rillig 		Parse_Error(PARSE_FATAL,
   2952  1.1170    rillig 		    "Missing delimiter for modifier \":S\"");
   2953   1.703    rillig 		(*pp)++;
   2954   1.703    rillig 		return AMR_CLEANUP;
   2955   1.703    rillig 	}
   2956   1.236    rillig 
   2957   1.703    rillig 	*pp += 2;
   2958   1.236    rillig 
   2959   1.927    rillig 	args.pflags = PatternFlags_None();
   2960   1.895    rillig 	args.matched = false;
   2961   1.236    rillig 
   2962   1.703    rillig 	if (**pp == '^') {
   2963   1.895    rillig 		args.pflags.anchorStart = true;
   2964   1.703    rillig 		(*pp)++;
   2965   1.703    rillig 	}
   2966   1.703    rillig 
   2967  1.1115    rillig 	if (!ParseModifierPart(pp, delim, delim, ch->expr->emode,
   2968  1.1115    rillig 	    ch, &lhsBuf, &args.pflags, NULL))
   2969   1.703    rillig 		return AMR_CLEANUP;
   2970   1.921    rillig 	args.lhs = LazyBuf_Get(&lhsBuf);
   2971   1.703    rillig 
   2972  1.1115    rillig 	if (!ParseModifierPart(pp, delim, delim, ch->expr->emode,
   2973  1.1115    rillig 	    ch, &rhsBuf, NULL, &args)) {
   2974   1.921    rillig 		LazyBuf_Done(&lhsBuf);
   2975   1.703    rillig 		return AMR_CLEANUP;
   2976   1.921    rillig 	}
   2977   1.921    rillig 	args.rhs = LazyBuf_Get(&rhsBuf);
   2978   1.703    rillig 
   2979   1.891    rillig 	oneBigWord = ch->oneBigWord;
   2980   1.860    rillig 	ParsePatternFlags(pp, &args.pflags, &oneBigWord);
   2981   1.236    rillig 
   2982   1.891    rillig 	ModifyWords(ch, ModifyWord_Subst, &args, oneBigWord);
   2983   1.236    rillig 
   2984   1.921    rillig 	LazyBuf_Done(&lhsBuf);
   2985   1.921    rillig 	LazyBuf_Done(&rhsBuf);
   2986   1.703    rillig 	return AMR_OK;
   2987   1.236    rillig }
   2988   1.236    rillig 
   2989   1.236    rillig /* :C,from,to, */
   2990   1.356    rillig static ApplyModifierResult
   2991   1.891    rillig ApplyModifier_Regex(const char **pp, ModChain *ch)
   2992   1.236    rillig {
   2993   1.703    rillig 	struct ModifyWord_SubstRegexArgs args;
   2994   1.895    rillig 	bool oneBigWord;
   2995   1.703    rillig 	int error;
   2996   1.921    rillig 	LazyBuf reBuf, replaceBuf;
   2997   1.984    rillig 	FStr re;
   2998   1.703    rillig 
   2999   1.703    rillig 	char delim = (*pp)[1];
   3000   1.703    rillig 	if (delim == '\0') {
   3001  1.1125    rillig 		Parse_Error(PARSE_FATAL,
   3002  1.1170    rillig 		    "Missing delimiter for modifier \":C\"");
   3003   1.703    rillig 		(*pp)++;
   3004   1.703    rillig 		return AMR_CLEANUP;
   3005   1.703    rillig 	}
   3006   1.703    rillig 
   3007   1.703    rillig 	*pp += 2;
   3008   1.236    rillig 
   3009  1.1115    rillig 	if (!ParseModifierPart(pp, delim, delim, ch->expr->emode,
   3010  1.1115    rillig 	    ch, &reBuf, NULL, NULL))
   3011   1.703    rillig 		return AMR_CLEANUP;
   3012   1.921    rillig 	re = LazyBuf_DoneGet(&reBuf);
   3013   1.703    rillig 
   3014  1.1115    rillig 	if (!ParseModifierPart(pp, delim, delim, ch->expr->emode,
   3015  1.1115    rillig 	    ch, &replaceBuf, NULL, NULL)) {
   3016   1.921    rillig 		FStr_Done(&re);
   3017   1.703    rillig 		return AMR_CLEANUP;
   3018   1.703    rillig 	}
   3019   1.984    rillig 	args.replace = LazyBuf_Get(&replaceBuf);
   3020   1.703    rillig 
   3021   1.927    rillig 	args.pflags = PatternFlags_None();
   3022   1.895    rillig 	args.matched = false;
   3023   1.891    rillig 	oneBigWord = ch->oneBigWord;
   3024   1.860    rillig 	ParsePatternFlags(pp, &args.pflags, &oneBigWord);
   3025   1.236    rillig 
   3026  1.1034    rillig 	if (!ModChain_ShouldEval(ch))
   3027  1.1034    rillig 		goto done;
   3028   1.856    rillig 
   3029   1.921    rillig 	error = regcomp(&args.re, re.str, REG_EXTENDED);
   3030   1.703    rillig 	if (error != 0) {
   3031  1.1059    rillig 		RegexError(error, &args.re, "Regex compilation error");
   3032   1.984    rillig 		LazyBuf_Done(&replaceBuf);
   3033   1.921    rillig 		FStr_Done(&re);
   3034   1.703    rillig 		return AMR_CLEANUP;
   3035   1.236    rillig 	}
   3036   1.236    rillig 
   3037   1.703    rillig 	args.nsub = args.re.re_nsub + 1;
   3038   1.703    rillig 	if (args.nsub > 10)
   3039   1.703    rillig 		args.nsub = 10;
   3040   1.820    rillig 
   3041   1.891    rillig 	ModifyWords(ch, ModifyWord_SubstRegex, &args, oneBigWord);
   3042   1.820    rillig 
   3043   1.703    rillig 	regfree(&args.re);
   3044  1.1034    rillig done:
   3045   1.984    rillig 	LazyBuf_Done(&replaceBuf);
   3046   1.921    rillig 	FStr_Done(&re);
   3047   1.703    rillig 	return AMR_OK;
   3048   1.703    rillig }
   3049   1.236    rillig 
   3050   1.555    rillig /* :Q, :q */
   3051   1.555    rillig static ApplyModifierResult
   3052   1.891    rillig ApplyModifier_Quote(const char **pp, ModChain *ch)
   3053   1.555    rillig {
   3054   1.924    rillig 	LazyBuf buf;
   3055   1.924    rillig 	bool quoteDollar;
   3056   1.924    rillig 
   3057   1.924    rillig 	quoteDollar = **pp == 'q';
   3058   1.891    rillig 	if (!IsDelimiter((*pp)[1], ch))
   3059   1.703    rillig 		return AMR_UNKNOWN;
   3060   1.861    rillig 	(*pp)++;
   3061   1.861    rillig 
   3062   1.924    rillig 	if (!ModChain_ShouldEval(ch))
   3063   1.924    rillig 		return AMR_OK;
   3064   1.924    rillig 
   3065  1.1059    rillig 	QuoteShell(Expr_Str(ch->expr), quoteDollar, &buf);
   3066   1.924    rillig 	if (buf.data != NULL)
   3067   1.924    rillig 		Expr_SetValue(ch->expr, LazyBuf_DoneGet(&buf));
   3068   1.924    rillig 	else
   3069   1.924    rillig 		LazyBuf_Done(&buf);
   3070   1.861    rillig 
   3071   1.861    rillig 	return AMR_OK;
   3072   1.555    rillig }
   3073   1.555    rillig 
   3074   1.278    rillig static void
   3075   1.919    rillig ModifyWord_Copy(Substring word, SepBuf *buf, void *data MAKE_ATTR_UNUSED)
   3076   1.278    rillig {
   3077   1.919    rillig 	SepBuf_AddSubstring(buf, word);
   3078   1.275    rillig }
   3079   1.275    rillig 
   3080   1.289    rillig /* :ts<separator> */
   3081   1.356    rillig static ApplyModifierResult
   3082   1.891    rillig ApplyModifier_ToSep(const char **pp, ModChain *ch)
   3083   1.289    rillig {
   3084   1.703    rillig 	const char *sep = *pp + 2;
   3085   1.703    rillig 
   3086   1.873    rillig 	/*
   3087  1.1079    rillig 	 * Even in parse-only mode, apply the side effects, since the side
   3088  1.1079    rillig 	 * effects are neither observable nor is there a performance penalty.
   3089  1.1119    rillig 	 * Checking for VARE_EVAL for every single piece of code in here
   3090   1.873    rillig 	 * would make the code in this function too hard to read.
   3091   1.873    rillig 	 */
   3092   1.873    rillig 
   3093   1.703    rillig 	/* ":ts<any><endc>" or ":ts<any>:" */
   3094   1.891    rillig 	if (sep[0] != ch->endc && IsDelimiter(sep[1], ch)) {
   3095   1.864    rillig 		*pp = sep + 1;
   3096   1.891    rillig 		ch->sep = sep[0];
   3097   1.703    rillig 		goto ok;
   3098   1.703    rillig 	}
   3099   1.468    rillig 
   3100   1.703    rillig 	/* ":ts<endc>" or ":ts:" */
   3101   1.891    rillig 	if (IsDelimiter(sep[0], ch)) {
   3102   1.864    rillig 		*pp = sep;
   3103   1.891    rillig 		ch->sep = '\0';	/* no separator */
   3104   1.703    rillig 		goto ok;
   3105   1.703    rillig 	}
   3106   1.468    rillig 
   3107  1.1154    rillig 	if (sep[0] != '\\')
   3108  1.1154    rillig 		return AMR_UNKNOWN;
   3109   1.468    rillig 
   3110   1.703    rillig 	/* ":ts\n" */
   3111   1.703    rillig 	if (sep[1] == 'n') {
   3112   1.864    rillig 		*pp = sep + 2;
   3113   1.891    rillig 		ch->sep = '\n';
   3114   1.703    rillig 		goto ok;
   3115   1.703    rillig 	}
   3116   1.468    rillig 
   3117   1.703    rillig 	/* ":ts\t" */
   3118   1.703    rillig 	if (sep[1] == 't') {
   3119   1.864    rillig 		*pp = sep + 2;
   3120   1.891    rillig 		ch->sep = '\t';
   3121   1.703    rillig 		goto ok;
   3122   1.703    rillig 	}
   3123   1.468    rillig 
   3124   1.703    rillig 	/* ":ts\x40" or ":ts\100" */
   3125   1.703    rillig 	{
   3126   1.703    rillig 		const char *p = sep + 1;
   3127   1.703    rillig 		int base = 8;	/* assume octal */
   3128   1.468    rillig 
   3129   1.703    rillig 		if (sep[1] == 'x') {
   3130   1.703    rillig 			base = 16;
   3131   1.703    rillig 			p++;
   3132  1.1154    rillig 		} else if (!ch_isdigit(sep[1]))
   3133  1.1154    rillig 			return AMR_UNKNOWN;	/* ":ts\..." */
   3134   1.289    rillig 
   3135   1.891    rillig 		if (!TryParseChar(&p, base, &ch->sep)) {
   3136   1.703    rillig 			Parse_Error(PARSE_FATAL,
   3137   1.970    rillig 			    "Invalid character number at \"%s\"", p);
   3138   1.703    rillig 			return AMR_CLEANUP;
   3139   1.703    rillig 		}
   3140  1.1154    rillig 		if (!IsDelimiter(*p, ch))
   3141  1.1154    rillig 			return AMR_UNKNOWN;
   3142   1.468    rillig 
   3143   1.703    rillig 		*pp = p;
   3144   1.556    rillig 	}
   3145   1.635    rillig 
   3146   1.468    rillig ok:
   3147   1.891    rillig 	ModifyWords(ch, ModifyWord_Copy, NULL, ch->oneBigWord);
   3148   1.703    rillig 	return AMR_OK;
   3149   1.289    rillig }
   3150   1.289    rillig 
   3151   1.738    rillig static char *
   3152  1.1126       sjg str_totitle(const char *str)
   3153  1.1126       sjg {
   3154  1.1126       sjg 	size_t i, n = strlen(str) + 1;
   3155  1.1126       sjg 	char *res = bmake_malloc(n);
   3156  1.1126       sjg 	for (i = 0; i < n; i++) {
   3157  1.1126       sjg 		if (i == 0 || ch_isspace(res[i - 1]))
   3158  1.1126       sjg 			res[i] = ch_toupper(str[i]);
   3159  1.1126       sjg 		else
   3160  1.1126       sjg 			res[i] = ch_tolower(str[i]);
   3161  1.1126       sjg 	}
   3162  1.1126       sjg 	return res;
   3163  1.1126       sjg }
   3164  1.1126       sjg 
   3165  1.1126       sjg 
   3166  1.1126       sjg static char *
   3167   1.738    rillig str_toupper(const char *str)
   3168   1.738    rillig {
   3169  1.1106    rillig 	size_t i, n = strlen(str) + 1;
   3170  1.1106    rillig 	char *res = bmake_malloc(n);
   3171  1.1106    rillig 	for (i = 0; i < n; i++)
   3172   1.738    rillig 		res[i] = ch_toupper(str[i]);
   3173   1.738    rillig 	return res;
   3174   1.738    rillig }
   3175   1.738    rillig 
   3176   1.738    rillig static char *
   3177   1.738    rillig str_tolower(const char *str)
   3178   1.738    rillig {
   3179  1.1106    rillig 	size_t i, n = strlen(str) + 1;
   3180  1.1106    rillig 	char *res = bmake_malloc(n);
   3181  1.1106    rillig 	for (i = 0; i < n; i++)
   3182   1.738    rillig 		res[i] = ch_tolower(str[i]);
   3183   1.738    rillig 	return res;
   3184   1.738    rillig }
   3185   1.738    rillig 
   3186   1.289    rillig /* :tA, :tu, :tl, :ts<separator>, etc. */
   3187   1.356    rillig static ApplyModifierResult
   3188   1.891    rillig ApplyModifier_To(const char **pp, ModChain *ch)
   3189   1.236    rillig {
   3190   1.891    rillig 	Expr *expr = ch->expr;
   3191   1.703    rillig 	const char *mod = *pp;
   3192   1.703    rillig 	assert(mod[0] == 't');
   3193   1.363    rillig 
   3194  1.1154    rillig 	if (IsDelimiter(mod[1], ch))
   3195  1.1154    rillig 		return AMR_UNKNOWN;		/* ":t<endc>" or ":t:" */
   3196   1.289    rillig 
   3197   1.703    rillig 	if (mod[1] == 's')
   3198   1.891    rillig 		return ApplyModifier_ToSep(pp, ch);
   3199   1.289    rillig 
   3200  1.1154    rillig 	if (!IsDelimiter(mod[2], ch))
   3201  1.1154    rillig 		return AMR_UNKNOWN;
   3202   1.236    rillig 
   3203   1.810    rillig 	if (mod[1] == 'A') {				/* :tA */
   3204   1.864    rillig 		*pp = mod + 2;
   3205   1.891    rillig 		ModifyWords(ch, ModifyWord_Realpath, NULL, ch->oneBigWord);
   3206   1.703    rillig 		return AMR_OK;
   3207   1.703    rillig 	}
   3208   1.475    rillig 
   3209  1.1126       sjg 	if (mod[1] == 't') {				/* :tt */
   3210  1.1126       sjg 		*pp = mod + 2;
   3211  1.1126       sjg 		if (Expr_ShouldEval(expr))
   3212  1.1126       sjg 			Expr_SetValueOwn(expr, str_totitle(Expr_Str(expr)));
   3213  1.1126       sjg 		return AMR_OK;
   3214  1.1126       sjg 	}
   3215  1.1127    rillig 
   3216   1.810    rillig 	if (mod[1] == 'u') {				/* :tu */
   3217   1.864    rillig 		*pp = mod + 2;
   3218   1.950    rillig 		if (Expr_ShouldEval(expr))
   3219   1.965    rillig 			Expr_SetValueOwn(expr, str_toupper(Expr_Str(expr)));
   3220   1.703    rillig 		return AMR_OK;
   3221   1.703    rillig 	}
   3222   1.475    rillig 
   3223   1.810    rillig 	if (mod[1] == 'l') {				/* :tl */
   3224   1.864    rillig 		*pp = mod + 2;
   3225   1.950    rillig 		if (Expr_ShouldEval(expr))
   3226   1.965    rillig 			Expr_SetValueOwn(expr, str_tolower(Expr_Str(expr)));
   3227   1.703    rillig 		return AMR_OK;
   3228   1.703    rillig 	}
   3229   1.475    rillig 
   3230   1.810    rillig 	if (mod[1] == 'W' || mod[1] == 'w') {		/* :tW, :tw */
   3231   1.864    rillig 		*pp = mod + 2;
   3232   1.891    rillig 		ch->oneBigWord = mod[1] == 'W';
   3233   1.703    rillig 		return AMR_OK;
   3234   1.703    rillig 	}
   3235   1.475    rillig 
   3236  1.1154    rillig 	return AMR_UNKNOWN;		/* ":t<any>:" or ":t<any><endc>" */
   3237   1.236    rillig }
   3238   1.236    rillig 
   3239   1.634    rillig /* :[#], :[1], :[-1..1], etc. */
   3240   1.356    rillig static ApplyModifierResult
   3241   1.891    rillig ApplyModifier_Words(const char **pp, ModChain *ch)
   3242   1.236    rillig {
   3243   1.891    rillig 	Expr *expr = ch->expr;
   3244   1.703    rillig 	int first, last;
   3245  1.1157    rillig 	const char *p;
   3246  1.1079    rillig 	LazyBuf argBuf;
   3247  1.1079    rillig 	FStr arg;
   3248   1.412    rillig 
   3249   1.703    rillig 	(*pp)++;		/* skip the '[' */
   3250  1.1115    rillig 	if (!ParseModifierPart(pp, ']', ']', expr->emode,
   3251  1.1115    rillig 	    ch, &argBuf, NULL, NULL))
   3252   1.703    rillig 		return AMR_CLEANUP;
   3253  1.1079    rillig 	arg = LazyBuf_DoneGet(&argBuf);
   3254  1.1079    rillig 	p = arg.str;
   3255   1.703    rillig 
   3256  1.1157    rillig 	if (!IsDelimiter(**pp, ch)) {
   3257  1.1157    rillig 		Parse_Error(PARSE_FATAL,
   3258  1.1157    rillig 		    "Extra text after \"[%s]\"", arg.str);
   3259  1.1157    rillig 		FStr_Done(&arg);
   3260  1.1157    rillig 		return AMR_CLEANUP;
   3261  1.1157    rillig 	}
   3262   1.703    rillig 
   3263   1.905    rillig 	if (!ModChain_ShouldEval(ch))
   3264   1.877    rillig 		goto ok;
   3265   1.877    rillig 
   3266  1.1069    rillig 	if (p[0] == '\0')
   3267  1.1069    rillig 		goto bad_modifier;		/* Found ":[]". */
   3268   1.703    rillig 
   3269  1.1069    rillig 	if (strcmp(p, "#") == 0) {		/* Found ":[#]" */
   3270  1.1069    rillig 		if (ch->oneBigWord)
   3271   1.823    rillig 			Expr_SetValueRefer(expr, "1");
   3272  1.1069    rillig 		else {
   3273   1.703    rillig 			Buffer buf;
   3274   1.412    rillig 
   3275   1.967    rillig 			SubstringWords words = Expr_Words(expr);
   3276   1.703    rillig 			size_t ac = words.len;
   3277   1.961    rillig 			SubstringWords_Free(words);
   3278   1.703    rillig 
   3279  1.1087    rillig 			Buf_Init(&buf);
   3280   1.703    rillig 			Buf_AddInt(&buf, (int)ac);
   3281   1.823    rillig 			Expr_SetValueOwn(expr, Buf_DoneData(&buf));
   3282   1.703    rillig 		}
   3283   1.703    rillig 		goto ok;
   3284   1.703    rillig 	}
   3285   1.494    rillig 
   3286  1.1069    rillig 	if (strcmp(p, "*") == 0) {		/* ":[*]" */
   3287   1.895    rillig 		ch->oneBigWord = true;
   3288   1.703    rillig 		goto ok;
   3289   1.236    rillig 	}
   3290   1.288    rillig 
   3291  1.1069    rillig 	if (strcmp(p, "@") == 0) {		/* ":[@]" */
   3292   1.895    rillig 		ch->oneBigWord = false;
   3293   1.703    rillig 		goto ok;
   3294   1.703    rillig 	}
   3295   1.288    rillig 
   3296  1.1069    rillig 	/* Expect ":[N]" or ":[start..end]" */
   3297   1.703    rillig 	if (!TryParseIntBase0(&p, &first))
   3298  1.1069    rillig 		goto bad_modifier;
   3299   1.703    rillig 
   3300  1.1069    rillig 	if (p[0] == '\0')			/* ":[N]" */
   3301   1.703    rillig 		last = first;
   3302  1.1069    rillig 	else if (strncmp(p, "..", 2) == 0) {
   3303   1.703    rillig 		p += 2;
   3304   1.703    rillig 		if (!TryParseIntBase0(&p, &last) || *p != '\0')
   3305  1.1069    rillig 			goto bad_modifier;
   3306   1.703    rillig 	} else
   3307  1.1069    rillig 		goto bad_modifier;
   3308   1.288    rillig 
   3309  1.1069    rillig 	if (first == 0 && last == 0) {		/* ":[0]" or ":[0..0]" */
   3310   1.895    rillig 		ch->oneBigWord = true;
   3311   1.703    rillig 		goto ok;
   3312   1.703    rillig 	}
   3313   1.288    rillig 
   3314  1.1069    rillig 	if (first == 0 || last == 0)		/* ":[0..N]" or ":[N..0]" */
   3315   1.703    rillig 		goto bad_modifier;
   3316   1.703    rillig 
   3317   1.823    rillig 	Expr_SetValueOwn(expr,
   3318   1.965    rillig 	    VarSelectWords(Expr_Str(expr), first, last,
   3319  1.1019    rillig 		ch->sep, ch->oneBigWord));
   3320   1.288    rillig 
   3321   1.288    rillig ok:
   3322  1.1079    rillig 	FStr_Done(&arg);
   3323   1.703    rillig 	return AMR_OK;
   3324   1.288    rillig 
   3325   1.288    rillig bad_modifier:
   3326  1.1157    rillig 	Parse_Error(PARSE_FATAL, "Invalid modifier \":[%s]\"", arg.str);
   3327  1.1079    rillig 	FStr_Done(&arg);
   3328  1.1155    rillig 	return AMR_CLEANUP;
   3329   1.236    rillig }
   3330   1.236    rillig 
   3331  1.1016    rillig #if __STDC_VERSION__ >= 199901L
   3332   1.939       sjg # define NUM_TYPE long long
   3333  1.1009    rillig # define PARSE_NUM_TYPE strtoll
   3334  1.1009    rillig #else
   3335  1.1009    rillig # define NUM_TYPE long
   3336  1.1009    rillig # define PARSE_NUM_TYPE strtol
   3337   1.939       sjg #endif
   3338   1.939       sjg 
   3339   1.939       sjg static NUM_TYPE
   3340   1.964    rillig num_val(Substring s)
   3341   1.939       sjg {
   3342   1.939       sjg 	NUM_TYPE val;
   3343   1.939       sjg 	char *ep;
   3344   1.939       sjg 
   3345  1.1009    rillig 	val = PARSE_NUM_TYPE(s.start, &ep, 0);
   3346   1.964    rillig 	if (ep != s.start) {
   3347   1.939       sjg 		switch (*ep) {
   3348   1.939       sjg 		case 'K':
   3349   1.939       sjg 		case 'k':
   3350   1.939       sjg 			val <<= 10;
   3351   1.939       sjg 			break;
   3352   1.939       sjg 		case 'M':
   3353   1.939       sjg 		case 'm':
   3354   1.939       sjg 			val <<= 20;
   3355   1.939       sjg 			break;
   3356   1.939       sjg 		case 'G':
   3357   1.939       sjg 		case 'g':
   3358   1.939       sjg 			val <<= 30;
   3359   1.939       sjg 			break;
   3360   1.939       sjg 		}
   3361   1.939       sjg 	}
   3362   1.939       sjg 	return val;
   3363   1.939       sjg }
   3364   1.939       sjg 
   3365   1.939       sjg static int
   3366   1.964    rillig SubNumAsc(const void *sa, const void *sb)
   3367   1.939       sjg {
   3368   1.939       sjg 	NUM_TYPE a, b;
   3369   1.939       sjg 
   3370   1.964    rillig 	a = num_val(*((const Substring *)sa));
   3371   1.964    rillig 	b = num_val(*((const Substring *)sb));
   3372  1.1067    rillig 	return a > b ? 1 : b > a ? -1 : 0;
   3373   1.939       sjg }
   3374   1.940    rillig 
   3375   1.939       sjg static int
   3376   1.964    rillig SubNumDesc(const void *sa, const void *sb)
   3377   1.939       sjg {
   3378   1.964    rillig 	return SubNumAsc(sb, sa);
   3379   1.939       sjg }
   3380   1.940    rillig 
   3381   1.404    rillig static int
   3382  1.1068    rillig Substring_Cmp(Substring a, Substring b)
   3383  1.1068    rillig {
   3384  1.1068    rillig 	for (; a.start < a.end && b.start < b.end; a.start++, b.start++)
   3385  1.1068    rillig 		if (a.start[0] != b.start[0])
   3386  1.1068    rillig 			return (unsigned char)a.start[0]
   3387  1.1068    rillig 			    - (unsigned char)b.start[0];
   3388  1.1068    rillig 	return (int)((a.end - a.start) - (b.end - b.start));
   3389  1.1068    rillig }
   3390  1.1068    rillig 
   3391  1.1068    rillig static int
   3392   1.964    rillig SubStrAsc(const void *sa, const void *sb)
   3393   1.404    rillig {
   3394  1.1068    rillig 	return Substring_Cmp(*(const Substring *)sa, *(const Substring *)sb);
   3395   1.404    rillig }
   3396   1.404    rillig 
   3397   1.404    rillig static int
   3398   1.964    rillig SubStrDesc(const void *sa, const void *sb)
   3399   1.404    rillig {
   3400   1.964    rillig 	return SubStrAsc(sb, sa);
   3401   1.404    rillig }
   3402   1.404    rillig 
   3403   1.705    rillig static void
   3404   1.962    rillig ShuffleSubstrings(Substring *strs, size_t n)
   3405   1.705    rillig {
   3406   1.705    rillig 	size_t i;
   3407   1.705    rillig 
   3408   1.705    rillig 	for (i = n - 1; i > 0; i--) {
   3409   1.705    rillig 		size_t rndidx = (size_t)random() % (i + 1);
   3410   1.962    rillig 		Substring t = strs[i];
   3411   1.705    rillig 		strs[i] = strs[rndidx];
   3412   1.705    rillig 		strs[rndidx] = t;
   3413   1.705    rillig 	}
   3414   1.705    rillig }
   3415   1.705    rillig 
   3416   1.943    rillig /*
   3417   1.943    rillig  * :O		order ascending
   3418   1.943    rillig  * :Or		order descending
   3419   1.943    rillig  * :Ox		shuffle
   3420   1.943    rillig  * :On		numeric ascending
   3421   1.943    rillig  * :Onr, :Orn	numeric descending
   3422   1.939       sjg  */
   3423   1.356    rillig static ApplyModifierResult
   3424   1.891    rillig ApplyModifier_Order(const char **pp, ModChain *ch)
   3425   1.236    rillig {
   3426   1.942    rillig 	const char *mod = *pp;
   3427   1.962    rillig 	SubstringWords words;
   3428   1.946    rillig 	int (*cmp)(const void *, const void *);
   3429   1.401    rillig 
   3430  1.1032    rillig 	if (IsDelimiter(mod[1], ch)) {
   3431   1.964    rillig 		cmp = SubStrAsc;
   3432   1.939       sjg 		(*pp)++;
   3433  1.1032    rillig 	} else if (IsDelimiter(mod[2], ch)) {
   3434   1.942    rillig 		if (mod[1] == 'n')
   3435   1.964    rillig 			cmp = SubNumAsc;
   3436   1.942    rillig 		else if (mod[1] == 'r')
   3437   1.964    rillig 			cmp = SubStrDesc;
   3438   1.942    rillig 		else if (mod[1] == 'x')
   3439   1.944    rillig 			cmp = NULL;
   3440   1.942    rillig 		else
   3441  1.1153    rillig 			return AMR_UNKNOWN;
   3442   1.942    rillig 		*pp += 2;
   3443  1.1032    rillig 	} else if (IsDelimiter(mod[3], ch)) {
   3444   1.942    rillig 		if ((mod[1] == 'n' && mod[2] == 'r') ||
   3445   1.944    rillig 		    (mod[1] == 'r' && mod[2] == 'n'))
   3446   1.964    rillig 			cmp = SubNumDesc;
   3447   1.944    rillig 		else
   3448  1.1153    rillig 			return AMR_UNKNOWN;
   3449   1.942    rillig 		*pp += 3;
   3450   1.996    rillig 	} else
   3451  1.1153    rillig 		return AMR_UNKNOWN;
   3452   1.402    rillig 
   3453   1.905    rillig 	if (!ModChain_ShouldEval(ch))
   3454   1.879    rillig 		return AMR_OK;
   3455   1.879    rillig 
   3456   1.967    rillig 	words = Expr_Words(ch->expr);
   3457   1.944    rillig 	if (cmp == NULL)
   3458   1.962    rillig 		ShuffleSubstrings(words.words, words.len);
   3459   1.964    rillig 	else {
   3460   1.964    rillig 		assert(words.words[0].end[0] == '\0');
   3461   1.944    rillig 		qsort(words.words, words.len, sizeof(words.words[0]), cmp);
   3462   1.964    rillig 	}
   3463   1.962    rillig 	Expr_SetValueOwn(ch->expr, SubstringWords_JoinFree(words));
   3464   1.878    rillig 
   3465   1.705    rillig 	return AMR_OK;
   3466   1.236    rillig }
   3467   1.236    rillig 
   3468   1.236    rillig /* :? then : else */
   3469   1.356    rillig static ApplyModifierResult
   3470   1.891    rillig ApplyModifier_IfElse(const char **pp, ModChain *ch)
   3471   1.236    rillig {
   3472   1.891    rillig 	Expr *expr = ch->expr;
   3473   1.985    rillig 	LazyBuf thenBuf;
   3474   1.985    rillig 	LazyBuf elseBuf;
   3475   1.412    rillig 
   3476  1.1119    rillig 	VarEvalMode then_emode = VARE_PARSE;
   3477  1.1119    rillig 	VarEvalMode else_emode = VARE_PARSE;
   3478  1.1161    rillig 	int parseErrorsBefore = parseErrors;
   3479   1.236    rillig 
   3480  1.1143    rillig 	CondResult cond_rc = CR_TRUE;	/* anything other than CR_ERROR */
   3481   1.905    rillig 	if (Expr_ShouldEval(expr)) {
   3482  1.1124    rillig 		evalStack.elems[evalStack.len - 1].kind = VSK_COND;
   3483   1.990    rillig 		cond_rc = Cond_EvalCondition(expr->name);
   3484   1.990    rillig 		if (cond_rc == CR_TRUE)
   3485   1.906    rillig 			then_emode = expr->emode;
   3486  1.1161    rillig 		else if (cond_rc == CR_FALSE)
   3487   1.906    rillig 			else_emode = expr->emode;
   3488  1.1161    rillig 		else if (parseErrors == parseErrorsBefore)
   3489  1.1161    rillig 			Parse_Error(PARSE_FATAL, "Bad condition");
   3490   1.703    rillig 	}
   3491   1.703    rillig 
   3492  1.1124    rillig 	evalStack.elems[evalStack.len - 1].kind = VSK_COND_THEN;
   3493   1.988    rillig 	(*pp)++;		/* skip past the '?' */
   3494  1.1115    rillig 	if (!ParseModifierPart(pp, ':', ':', then_emode,
   3495  1.1115    rillig 	    ch, &thenBuf, NULL, NULL))
   3496   1.703    rillig 		return AMR_CLEANUP;
   3497   1.703    rillig 
   3498  1.1124    rillig 	evalStack.elems[evalStack.len - 1].kind = VSK_COND_ELSE;
   3499  1.1115    rillig 	if (!ParseModifierPart(pp, ch->endc, ch->endc, else_emode,
   3500  1.1115    rillig 	    ch, &elseBuf, NULL, NULL)) {
   3501   1.985    rillig 		LazyBuf_Done(&thenBuf);
   3502   1.703    rillig 		return AMR_CLEANUP;
   3503   1.921    rillig 	}
   3504   1.703    rillig 
   3505   1.891    rillig 	(*pp)--;		/* Go back to the ch->endc. */
   3506   1.809    rillig 
   3507   1.990    rillig 	if (cond_rc == CR_ERROR) {
   3508   1.985    rillig 		LazyBuf_Done(&thenBuf);
   3509   1.985    rillig 		LazyBuf_Done(&elseBuf);
   3510   1.703    rillig 		return AMR_CLEANUP;
   3511   1.703    rillig 	}
   3512   1.703    rillig 
   3513   1.950    rillig 	if (!Expr_ShouldEval(expr)) {
   3514   1.985    rillig 		LazyBuf_Done(&thenBuf);
   3515   1.985    rillig 		LazyBuf_Done(&elseBuf);
   3516   1.990    rillig 	} else if (cond_rc == CR_TRUE) {
   3517   1.985    rillig 		Expr_SetValue(expr, LazyBuf_DoneGet(&thenBuf));
   3518   1.985    rillig 		LazyBuf_Done(&elseBuf);
   3519   1.703    rillig 	} else {
   3520   1.985    rillig 		LazyBuf_Done(&thenBuf);
   3521   1.985    rillig 		Expr_SetValue(expr, LazyBuf_DoneGet(&elseBuf));
   3522   1.703    rillig 	}
   3523   1.823    rillig 	Expr_Define(expr);
   3524   1.703    rillig 	return AMR_OK;
   3525   1.236    rillig }
   3526   1.236    rillig 
   3527   1.283    rillig /*
   3528   1.808    rillig  * The ::= modifiers are special in that they do not read the variable value
   3529   1.808    rillig  * but instead assign to that variable.  They always expand to an empty
   3530   1.808    rillig  * string.
   3531   1.808    rillig  *
   3532   1.808    rillig  * Their main purpose is in supporting .for loops that generate shell commands
   3533   1.808    rillig  * since an ordinary variable assignment at that point would terminate the
   3534   1.808    rillig  * dependency group for these targets.  For example:
   3535   1.283    rillig  *
   3536   1.808    rillig  * list-targets: .USE
   3537   1.283    rillig  * .for i in ${.TARGET} ${.TARGET:R}.gz
   3538   1.808    rillig  *	@${t::=$i}
   3539   1.808    rillig  *	@echo 'The target is ${t:T}.'
   3540   1.283    rillig  * .endfor
   3541   1.283    rillig  *
   3542   1.283    rillig  *	  ::=<str>	Assigns <str> as the new value of variable.
   3543   1.283    rillig  *	  ::?=<str>	Assigns <str> as value of variable if
   3544   1.283    rillig  *			it was not already set.
   3545   1.283    rillig  *	  ::+=<str>	Appends <str> to variable.
   3546   1.283    rillig  *	  ::!=<cmd>	Assigns output of <cmd> as the new value of
   3547   1.283    rillig  *			variable.
   3548   1.283    rillig  */
   3549   1.356    rillig static ApplyModifierResult
   3550   1.891    rillig ApplyModifier_Assign(const char **pp, ModChain *ch)
   3551   1.236    rillig {
   3552   1.891    rillig 	Expr *expr = ch->expr;
   3553   1.802    rillig 	GNode *scope;
   3554   1.921    rillig 	FStr val;
   3555   1.921    rillig 	LazyBuf buf;
   3556   1.272    rillig 
   3557   1.703    rillig 	const char *mod = *pp;
   3558   1.703    rillig 	const char *op = mod + 1;
   3559   1.272    rillig 
   3560   1.703    rillig 	if (op[0] == '=')
   3561   1.992    rillig 		goto found_op;
   3562   1.992    rillig 	if ((op[0] == '+' || op[0] == '?' || op[0] == '!') && op[1] == '=')
   3563   1.992    rillig 		goto found_op;
   3564  1.1066    rillig 	return AMR_UNKNOWN;	/* "::<unrecognized>" */
   3565   1.862    rillig 
   3566   1.992    rillig found_op:
   3567   1.898    rillig 	if (expr->name[0] == '\0') {
   3568  1.1156    rillig 		const char *value = op[0] == '=' ? op + 1 : op + 2;
   3569   1.703    rillig 		*pp = mod + 1;
   3570  1.1155    rillig 		/* Take a guess at where the modifier ends. */
   3571  1.1156    rillig 		Parse_Error(PARSE_FATAL,
   3572  1.1156    rillig 		    "Invalid attempt to assign \"%.*s\" to variable \"\" "
   3573  1.1162    rillig 		    "via modifier \":%.*s\"",
   3574  1.1156    rillig 		    (int)strcspn(value, ":)}"), value,
   3575  1.1162    rillig 		    (int)(value - mod), mod);
   3576  1.1155    rillig 		return AMR_CLEANUP;
   3577   1.703    rillig 	}
   3578   1.272    rillig 
   3579  1.1089    rillig 	*pp = mod + (op[0] != '=' ? 3 : 2);
   3580   1.703    rillig 
   3581  1.1115    rillig 	if (!ParseModifierPart(pp, ch->endc, ch->endc, expr->emode,
   3582  1.1115    rillig 	    ch, &buf, NULL, NULL))
   3583   1.703    rillig 		return AMR_CLEANUP;
   3584   1.921    rillig 	val = LazyBuf_DoneGet(&buf);
   3585   1.703    rillig 
   3586   1.891    rillig 	(*pp)--;		/* Go back to the ch->endc. */
   3587   1.703    rillig 
   3588   1.905    rillig 	if (!Expr_ShouldEval(expr))
   3589   1.882    rillig 		goto done;
   3590   1.882    rillig 
   3591   1.881    rillig 	scope = expr->scope;	/* scope where v belongs */
   3592  1.1089    rillig 	if (expr->defined == DEF_REGULAR && expr->scope != SCOPE_GLOBAL
   3593  1.1089    rillig 	    && VarFind(expr->name, expr->scope, false) == NULL)
   3594  1.1089    rillig 		scope = SCOPE_GLOBAL;
   3595   1.881    rillig 
   3596   1.999    rillig 	if (op[0] == '+')
   3597   1.921    rillig 		Var_Append(scope, expr->name, val.str);
   3598   1.999    rillig 	else if (op[0] == '!') {
   3599  1.1000    rillig 		char *output, *error;
   3600  1.1000    rillig 		output = Cmd_Exec(val.str, &error);
   3601  1.1000    rillig 		if (error != NULL) {
   3602  1.1123    rillig 			Parse_Error(PARSE_WARNING, "%s", error);
   3603  1.1000    rillig 			free(error);
   3604  1.1000    rillig 		} else
   3605  1.1000    rillig 			Var_Set(scope, expr->name, output);
   3606  1.1000    rillig 		free(output);
   3607   1.999    rillig 	} else if (op[0] == '?' && expr->defined == DEF_REGULAR) {
   3608   1.999    rillig 		/* Do nothing. */
   3609   1.999    rillig 	} else
   3610   1.921    rillig 		Var_Set(scope, expr->name, val.str);
   3611   1.999    rillig 
   3612   1.882    rillig 	Expr_SetValueRefer(expr, "");
   3613   1.882    rillig 
   3614   1.882    rillig done:
   3615   1.921    rillig 	FStr_Done(&val);
   3616   1.703    rillig 	return AMR_OK;
   3617   1.236    rillig }
   3618   1.236    rillig 
   3619   1.778    rillig /*
   3620   1.778    rillig  * :_=...
   3621   1.778    rillig  * remember current value
   3622   1.778    rillig  */
   3623   1.356    rillig static ApplyModifierResult
   3624   1.891    rillig ApplyModifier_Remember(const char **pp, ModChain *ch)
   3625   1.236    rillig {
   3626   1.891    rillig 	Expr *expr = ch->expr;
   3627   1.703    rillig 	const char *mod = *pp;
   3628   1.868    rillig 	FStr name;
   3629   1.866    rillig 
   3630   1.891    rillig 	if (!ModMatchEq(mod, "_", ch))
   3631   1.703    rillig 		return AMR_UNKNOWN;
   3632   1.703    rillig 
   3633   1.868    rillig 	name = FStr_InitRefer("_");
   3634   1.703    rillig 	if (mod[1] == '=') {
   3635   1.847    rillig 		/*
   3636   1.847    rillig 		 * XXX: This ad-hoc call to strcspn deviates from the usual
   3637   1.847    rillig 		 * behavior defined in ParseModifierPart.  This creates an
   3638  1.1066    rillig 		 * unnecessary and undocumented inconsistency in make.
   3639   1.847    rillig 		 */
   3640   1.869    rillig 		const char *arg = mod + 2;
   3641   1.869    rillig 		size_t argLen = strcspn(arg, ":)}");
   3642   1.869    rillig 		*pp = arg + argLen;
   3643   1.869    rillig 		name = FStr_InitOwn(bmake_strldup(arg, argLen));
   3644   1.868    rillig 	} else
   3645   1.868    rillig 		*pp = mod + 1;
   3646   1.864    rillig 
   3647   1.905    rillig 	if (Expr_ShouldEval(expr))
   3648  1.1040       sjg 		Var_Set(SCOPE_GLOBAL, name.str, Expr_Str(expr));
   3649   1.868    rillig 	FStr_Done(&name);
   3650   1.864    rillig 
   3651   1.703    rillig 	return AMR_OK;
   3652   1.236    rillig }
   3653   1.236    rillig 
   3654   1.778    rillig /*
   3655   1.778    rillig  * Apply the given function to each word of the variable value,
   3656   1.778    rillig  * for a single-letter modifier such as :H, :T.
   3657   1.778    rillig  */
   3658   1.434    rillig static ApplyModifierResult
   3659   1.891    rillig ApplyModifier_WordFunc(const char **pp, ModChain *ch,
   3660   1.822    rillig 		       ModifyWordProc modifyWord)
   3661   1.434    rillig {
   3662   1.891    rillig 	if (!IsDelimiter((*pp)[1], ch))
   3663   1.703    rillig 		return AMR_UNKNOWN;
   3664   1.864    rillig 	(*pp)++;
   3665   1.703    rillig 
   3666  1.1097    rillig 	ModifyWords(ch, modifyWord, NULL, ch->oneBigWord);
   3667   1.864    rillig 
   3668   1.703    rillig 	return AMR_OK;
   3669   1.434    rillig }
   3670   1.434    rillig 
   3671   1.931    rillig /* Remove adjacent duplicate words. */
   3672   1.567    rillig static ApplyModifierResult
   3673   1.891    rillig ApplyModifier_Unique(const char **pp, ModChain *ch)
   3674   1.567    rillig {
   3675   1.962    rillig 	SubstringWords words;
   3676   1.931    rillig 
   3677   1.891    rillig 	if (!IsDelimiter((*pp)[1], ch))
   3678   1.703    rillig 		return AMR_UNKNOWN;
   3679   1.862    rillig 	(*pp)++;
   3680   1.862    rillig 
   3681   1.931    rillig 	if (!ModChain_ShouldEval(ch))
   3682   1.931    rillig 		return AMR_OK;
   3683   1.931    rillig 
   3684   1.967    rillig 	words = Expr_Words(ch->expr);
   3685   1.931    rillig 
   3686   1.931    rillig 	if (words.len > 1) {
   3687  1.1067    rillig 		size_t di, si;
   3688  1.1162    rillig 		for (di = 0, si = 1; si < words.len; si++)
   3689  1.1162    rillig 			if (!Substring_Eq(words.words[di], words.words[si]))
   3690  1.1162    rillig 				words.words[++di] = words.words[si];
   3691   1.932    rillig 		words.len = di + 1;
   3692   1.931    rillig 	}
   3693   1.931    rillig 
   3694   1.962    rillig 	Expr_SetValueOwn(ch->expr, SubstringWords_JoinFree(words));
   3695   1.862    rillig 
   3696   1.862    rillig 	return AMR_OK;
   3697   1.567    rillig }
   3698   1.567    rillig 
   3699  1.1071    rillig /* Test whether the modifier has the form '<lhs>=<rhs>'. */
   3700  1.1071    rillig static bool
   3701  1.1071    rillig IsSysVModifier(const char *p, char startc, char endc)
   3702  1.1071    rillig {
   3703  1.1071    rillig 	bool eqFound = false;
   3704  1.1071    rillig 
   3705  1.1071    rillig 	int depth = 1;
   3706  1.1149    rillig 	while (*p != '\0') {
   3707  1.1071    rillig 		if (*p == '=')	/* XXX: should also test depth == 1 */
   3708  1.1071    rillig 			eqFound = true;
   3709  1.1149    rillig 		else if (*p == endc) {
   3710  1.1149    rillig 			if (--depth == 0)
   3711  1.1149    rillig 				break;
   3712  1.1149    rillig 		} else if (*p == startc)
   3713  1.1071    rillig 			depth++;
   3714  1.1149    rillig 		p++;
   3715  1.1071    rillig 	}
   3716  1.1149    rillig 	return eqFound;
   3717  1.1071    rillig }
   3718  1.1071    rillig 
   3719   1.236    rillig /* :from=to */
   3720   1.356    rillig static ApplyModifierResult
   3721   1.891    rillig ApplyModifier_SysV(const char **pp, ModChain *ch)
   3722   1.236    rillig {
   3723   1.891    rillig 	Expr *expr = ch->expr;
   3724   1.925    rillig 	LazyBuf lhsBuf, rhsBuf;
   3725   1.925    rillig 	FStr rhs;
   3726   1.926    rillig 	struct ModifyWord_SysVSubstArgs args;
   3727   1.925    rillig 	Substring lhs;
   3728   1.925    rillig 	const char *lhsSuffix;
   3729   1.412    rillig 
   3730   1.703    rillig 	const char *mod = *pp;
   3731   1.245    rillig 
   3732  1.1071    rillig 	if (!IsSysVModifier(mod, ch->startc, ch->endc))
   3733   1.703    rillig 		return AMR_UNKNOWN;
   3734   1.236    rillig 
   3735  1.1115    rillig 	if (!ParseModifierPart(pp, '=', '=', expr->emode,
   3736  1.1115    rillig 	    ch, &lhsBuf, NULL, NULL))
   3737   1.703    rillig 		return AMR_CLEANUP;
   3738   1.703    rillig 
   3739  1.1115    rillig 	if (!ParseModifierPart(pp, ch->endc, ch->endc, expr->emode,
   3740  1.1115    rillig 	    ch, &rhsBuf, NULL, NULL)) {
   3741   1.925    rillig 		LazyBuf_Done(&lhsBuf);
   3742   1.703    rillig 		return AMR_CLEANUP;
   3743   1.921    rillig 	}
   3744   1.925    rillig 	rhs = LazyBuf_DoneGet(&rhsBuf);
   3745   1.703    rillig 
   3746   1.891    rillig 	(*pp)--;		/* Go back to the ch->endc. */
   3747   1.809    rillig 
   3748   1.925    rillig 	/* Do not turn an empty expression into non-empty. */
   3749   1.965    rillig 	if (lhsBuf.len == 0 && Expr_Str(expr)[0] == '\0')
   3750   1.925    rillig 		goto done;
   3751   1.925    rillig 
   3752   1.925    rillig 	lhs = LazyBuf_Get(&lhsBuf);
   3753   1.925    rillig 	lhsSuffix = Substring_SkipFirst(lhs, '%');
   3754   1.925    rillig 
   3755   1.925    rillig 	args.scope = expr->scope;
   3756   1.925    rillig 	args.lhsPrefix = Substring_Init(lhs.start,
   3757   1.925    rillig 	    lhsSuffix != lhs.start ? lhsSuffix - 1 : lhs.start);
   3758   1.925    rillig 	args.lhsPercent = lhsSuffix != lhs.start;
   3759   1.925    rillig 	args.lhsSuffix = Substring_Init(lhsSuffix, lhs.end);
   3760   1.925    rillig 	args.rhs = rhs.str;
   3761   1.925    rillig 
   3762   1.926    rillig 	ModifyWords(ch, ModifyWord_SysVSubst, &args, ch->oneBigWord);
   3763   1.897    rillig 
   3764   1.925    rillig done:
   3765   1.925    rillig 	LazyBuf_Done(&lhsBuf);
   3766  1.1048    rillig 	FStr_Done(&rhs);
   3767   1.703    rillig 	return AMR_OK;
   3768   1.236    rillig }
   3769   1.236    rillig 
   3770   1.548    rillig /* :sh */
   3771   1.548    rillig static ApplyModifierResult
   3772   1.891    rillig ApplyModifier_SunShell(const char **pp, ModChain *ch)
   3773   1.548    rillig {
   3774   1.891    rillig 	Expr *expr = ch->expr;
   3775   1.703    rillig 	const char *p = *pp;
   3776   1.891    rillig 	if (!(p[1] == 'h' && IsDelimiter(p[2], ch)))
   3777   1.703    rillig 		return AMR_UNKNOWN;
   3778   1.864    rillig 	*pp = p + 2;
   3779   1.863    rillig 
   3780   1.905    rillig 	if (Expr_ShouldEval(expr)) {
   3781  1.1000    rillig 		char *output, *error;
   3782  1.1000    rillig 		output = Cmd_Exec(Expr_Str(expr), &error);
   3783  1.1000    rillig 		if (error != NULL) {
   3784  1.1122    rillig 			Parse_Error(PARSE_WARNING, "%s", error);
   3785  1.1000    rillig 			free(error);
   3786  1.1000    rillig 		}
   3787   1.863    rillig 		Expr_SetValueOwn(expr, output);
   3788   1.863    rillig 	}
   3789   1.864    rillig 
   3790   1.863    rillig 	return AMR_OK;
   3791   1.548    rillig }
   3792   1.548    rillig 
   3793  1.1041    rillig /*
   3794  1.1041    rillig  * In cases where the evaluation mode and the definedness are the "standard"
   3795  1.1041    rillig  * ones, don't log them, to keep the logs readable.
   3796  1.1041    rillig  */
   3797  1.1041    rillig static bool
   3798  1.1041    rillig ShouldLogInSimpleFormat(const Expr *expr)
   3799  1.1041    rillig {
   3800  1.1144    rillig 	return (expr->emode == VARE_EVAL
   3801  1.1144    rillig 		|| expr->emode == VARE_EVAL_DEFINED
   3802  1.1144    rillig 		|| expr->emode == VARE_EVAL_DEFINED_LOUD)
   3803  1.1119    rillig 	    && expr->defined == DEF_REGULAR;
   3804  1.1041    rillig }
   3805  1.1041    rillig 
   3806   1.549    rillig static void
   3807   1.891    rillig LogBeforeApply(const ModChain *ch, const char *mod)
   3808   1.549    rillig {
   3809   1.891    rillig 	const Expr *expr = ch->expr;
   3810   1.895    rillig 	bool is_single_char = mod[0] != '\0' && IsDelimiter(mod[1], ch);
   3811   1.703    rillig 
   3812   1.909    rillig 	/*
   3813   1.909    rillig 	 * At this point, only the first character of the modifier can
   3814   1.909    rillig 	 * be used since the end of the modifier is not yet known.
   3815   1.909    rillig 	 */
   3816   1.909    rillig 
   3817   1.909    rillig 	if (!Expr_ShouldEval(expr)) {
   3818   1.909    rillig 		debug_printf("Parsing modifier ${%s:%c%s}\n",
   3819   1.909    rillig 		    expr->name, mod[0], is_single_char ? "" : "...");
   3820   1.909    rillig 		return;
   3821   1.909    rillig 	}
   3822   1.909    rillig 
   3823  1.1041    rillig 	if (ShouldLogInSimpleFormat(expr)) {
   3824   1.910    rillig 		debug_printf(
   3825   1.910    rillig 		    "Evaluating modifier ${%s:%c%s} on value \"%s\"\n",
   3826   1.910    rillig 		    expr->name, mod[0], is_single_char ? "" : "...",
   3827   1.965    rillig 		    Expr_Str(expr));
   3828   1.910    rillig 		return;
   3829   1.910    rillig 	}
   3830   1.910    rillig 
   3831   1.909    rillig 	debug_printf(
   3832   1.909    rillig 	    "Evaluating modifier ${%s:%c%s} on value \"%s\" (%s, %s)\n",
   3833   1.965    rillig 	    expr->name, mod[0], is_single_char ? "" : "...", Expr_Str(expr),
   3834   1.910    rillig 	    VarEvalMode_Name[expr->emode], ExprDefined_Name[expr->defined]);
   3835   1.549    rillig }
   3836   1.549    rillig 
   3837   1.549    rillig static void
   3838   1.891    rillig LogAfterApply(const ModChain *ch, const char *p, const char *mod)
   3839   1.549    rillig {
   3840   1.891    rillig 	const Expr *expr = ch->expr;
   3841   1.965    rillig 	const char *value = Expr_Str(expr);
   3842   1.703    rillig 
   3843  1.1041    rillig 	if (ShouldLogInSimpleFormat(expr)) {
   3844  1.1150    rillig 		debug_printf("Result of ${%s:%.*s} is \"%s\"\n",
   3845  1.1150    rillig 		    expr->name, (int)(p - mod), mod, value);
   3846   1.912    rillig 		return;
   3847   1.912    rillig 	}
   3848   1.912    rillig 
   3849  1.1150    rillig 	debug_printf("Result of ${%s:%.*s} is \"%s\" (%s, %s)\n",
   3850  1.1150    rillig 	    expr->name, (int)(p - mod), mod, value,
   3851   1.906    rillig 	    VarEvalMode_Name[expr->emode],
   3852   1.825    rillig 	    ExprDefined_Name[expr->defined]);
   3853   1.549    rillig }
   3854   1.549    rillig 
   3855   1.551    rillig static ApplyModifierResult
   3856   1.891    rillig ApplyModifier(const char **pp, ModChain *ch)
   3857   1.551    rillig {
   3858   1.703    rillig 	switch (**pp) {
   3859   1.857    rillig 	case '!':
   3860   1.891    rillig 		return ApplyModifier_ShellCommand(pp, ch);
   3861   1.703    rillig 	case ':':
   3862   1.891    rillig 		return ApplyModifier_Assign(pp, ch);
   3863   1.857    rillig 	case '?':
   3864   1.891    rillig 		return ApplyModifier_IfElse(pp, ch);
   3865   1.703    rillig 	case '@':
   3866   1.891    rillig 		return ApplyModifier_Loop(pp, ch);
   3867   1.857    rillig 	case '[':
   3868   1.891    rillig 		return ApplyModifier_Words(pp, ch);
   3869   1.703    rillig 	case '_':
   3870   1.891    rillig 		return ApplyModifier_Remember(pp, ch);
   3871   1.857    rillig 	case 'C':
   3872   1.891    rillig 		return ApplyModifier_Regex(pp, ch);
   3873   1.703    rillig 	case 'D':
   3874   1.968    rillig 	case 'U':
   3875   1.891    rillig 		return ApplyModifier_Defined(pp, ch);
   3876   1.857    rillig 	case 'E':
   3877   1.891    rillig 		return ApplyModifier_WordFunc(pp, ch, ModifyWord_Suffix);
   3878   1.703    rillig 	case 'g':
   3879   1.995    rillig 	case 'l':
   3880   1.995    rillig 		return ApplyModifier_Time(pp, ch);
   3881   1.857    rillig 	case 'H':
   3882   1.891    rillig 		return ApplyModifier_WordFunc(pp, ch, ModifyWord_Head);
   3883   1.703    rillig 	case 'h':
   3884   1.891    rillig 		return ApplyModifier_Hash(pp, ch);
   3885   1.857    rillig 	case 'L':
   3886   1.891    rillig 		return ApplyModifier_Literal(pp, ch);
   3887   1.857    rillig 	case 'M':
   3888   1.703    rillig 	case 'N':
   3889   1.891    rillig 		return ApplyModifier_Match(pp, ch);
   3890  1.1051       sjg 	case 'm':
   3891  1.1051       sjg 		return ApplyModifier_Mtime(pp, ch);
   3892   1.857    rillig 	case 'O':
   3893   1.891    rillig 		return ApplyModifier_Order(pp, ch);
   3894   1.857    rillig 	case 'P':
   3895   1.891    rillig 		return ApplyModifier_Path(pp, ch);
   3896   1.857    rillig 	case 'Q':
   3897   1.703    rillig 	case 'q':
   3898   1.891    rillig 		return ApplyModifier_Quote(pp, ch);
   3899   1.703    rillig 	case 'R':
   3900   1.891    rillig 		return ApplyModifier_WordFunc(pp, ch, ModifyWord_Root);
   3901   1.703    rillig 	case 'r':
   3902   1.891    rillig 		return ApplyModifier_Range(pp, ch);
   3903   1.857    rillig 	case 'S':
   3904   1.891    rillig 		return ApplyModifier_Subst(pp, ch);
   3905   1.703    rillig 	case 's':
   3906   1.891    rillig 		return ApplyModifier_SunShell(pp, ch);
   3907   1.857    rillig 	case 'T':
   3908   1.891    rillig 		return ApplyModifier_WordFunc(pp, ch, ModifyWord_Tail);
   3909   1.857    rillig 	case 't':
   3910   1.891    rillig 		return ApplyModifier_To(pp, ch);
   3911   1.857    rillig 	case 'u':
   3912   1.891    rillig 		return ApplyModifier_Unique(pp, ch);
   3913   1.703    rillig 	default:
   3914   1.703    rillig 		return AMR_UNKNOWN;
   3915   1.703    rillig 	}
   3916   1.551    rillig }
   3917   1.551    rillig 
   3918   1.823    rillig static void ApplyModifiers(Expr *, const char **, char, char);
   3919   1.641    rillig 
   3920   1.641    rillig typedef enum ApplyModifiersIndirectResult {
   3921   1.752    rillig 	/* The indirect modifiers have been applied successfully. */
   3922   1.703    rillig 	AMIR_CONTINUE,
   3923   1.752    rillig 	/* Fall back to the SysV modifier. */
   3924   1.849    rillig 	AMIR_SYSV,
   3925   1.752    rillig 	/* Error out. */
   3926   1.703    rillig 	AMIR_OUT
   3927   1.641    rillig } ApplyModifiersIndirectResult;
   3928   1.641    rillig 
   3929   1.752    rillig /*
   3930  1.1075    rillig  * While expanding an expression, expand and apply indirect modifiers,
   3931   1.752    rillig  * such as in ${VAR:${M_indirect}}.
   3932   1.752    rillig  *
   3933  1.1075    rillig  * All indirect modifiers of a group must come from a single
   3934   1.752    rillig  * expression.  ${VAR:${M1}} is valid but ${VAR:${M1}${M2}} is not.
   3935   1.752    rillig  *
   3936   1.752    rillig  * Multiple groups of indirect modifiers can be chained by separating them
   3937   1.752    rillig  * with colons.  ${VAR:${M1}:${M2}} contains 2 indirect modifiers.
   3938   1.752    rillig  *
   3939  1.1075    rillig  * If the expression is not followed by ch->endc or ':', fall
   3940   1.752    rillig  * back to trying the SysV modifier, such as in ${VAR:${FROM}=${TO}}.
   3941   1.752    rillig  */
   3942   1.641    rillig static ApplyModifiersIndirectResult
   3943   1.891    rillig ApplyModifiersIndirect(ModChain *ch, const char **pp)
   3944   1.703    rillig {
   3945   1.891    rillig 	Expr *expr = ch->expr;
   3946   1.721    rillig 	const char *p = *pp;
   3947  1.1042    rillig 	FStr mods = Var_Parse(&p, expr->scope, expr->emode);
   3948   1.703    rillig 	/* TODO: handle errors */
   3949   1.641    rillig 
   3950  1.1032    rillig 	if (mods.str[0] != '\0' && !IsDelimiter(*p, ch)) {
   3951   1.743    rillig 		FStr_Done(&mods);
   3952   1.849    rillig 		return AMIR_SYSV;
   3953   1.703    rillig 	}
   3954   1.703    rillig 
   3955   1.708    rillig 	DEBUG3(VAR, "Indirect modifier \"%s\" from \"%.*s\"\n",
   3956   1.743    rillig 	    mods.str, (int)(p - *pp), *pp);
   3957   1.703    rillig 
   3958  1.1098    rillig 	if (ModChain_ShouldEval(ch) && mods.str[0] != '\0') {
   3959   1.743    rillig 		const char *modsp = mods.str;
   3960  1.1147    rillig 		EvalStack_Push(VSK_INDIRECT_MODIFIERS, mods.str, NULL);
   3961   1.823    rillig 		ApplyModifiers(expr, &modsp, '\0', '\0');
   3962  1.1147    rillig 		EvalStack_Pop();
   3963   1.965    rillig 		if (Expr_Str(expr) == var_Error || *modsp != '\0') {
   3964   1.743    rillig 			FStr_Done(&mods);
   3965   1.721    rillig 			*pp = p;
   3966   1.703    rillig 			return AMIR_OUT;	/* error already reported */
   3967   1.703    rillig 		}
   3968   1.703    rillig 	}
   3969   1.743    rillig 	FStr_Done(&mods);
   3970   1.641    rillig 
   3971   1.703    rillig 	if (*p == ':')
   3972   1.703    rillig 		p++;
   3973   1.891    rillig 	else if (*p == '\0' && ch->endc != '\0') {
   3974  1.1131    rillig 		Parse_Error(PARSE_FATAL,
   3975  1.1131    rillig 		    "Unclosed expression after indirect modifier, "
   3976  1.1170    rillig 		    "expecting \"%c\"",
   3977  1.1131    rillig 		    ch->endc);
   3978   1.721    rillig 		*pp = p;
   3979   1.703    rillig 		return AMIR_OUT;
   3980   1.641    rillig 	}
   3981   1.641    rillig 
   3982   1.721    rillig 	*pp = p;
   3983   1.703    rillig 	return AMIR_CONTINUE;
   3984   1.641    rillig }
   3985   1.641    rillig 
   3986   1.750    rillig static ApplyModifierResult
   3987   1.891    rillig ApplySingleModifier(const char **pp, ModChain *ch)
   3988   1.750    rillig {
   3989   1.750    rillig 	ApplyModifierResult res;
   3990   1.850    rillig 	const char *mod = *pp;
   3991   1.750    rillig 	const char *p = *pp;
   3992   1.750    rillig 
   3993   1.750    rillig 	if (DEBUG(VAR))
   3994   1.891    rillig 		LogBeforeApply(ch, mod);
   3995   1.750    rillig 
   3996  1.1158       sjg 	if (posix_state == PS_SET)
   3997  1.1158       sjg 		res = ApplyModifier_SysV(&p, ch);
   3998  1.1158       sjg 	else
   3999  1.1158       sjg 		res = AMR_UNKNOWN;
   4000  1.1158       sjg 	if (res == AMR_UNKNOWN)
   4001  1.1158       sjg 		res = ApplyModifier(&p, ch);
   4002   1.750    rillig 
   4003  1.1158       sjg 	if (res == AMR_UNKNOWN && posix_state != PS_SET) {
   4004   1.750    rillig 		assert(p == mod);
   4005   1.891    rillig 		res = ApplyModifier_SysV(&p, ch);
   4006   1.750    rillig 	}
   4007   1.750    rillig 
   4008   1.750    rillig 	if (res == AMR_UNKNOWN) {
   4009   1.750    rillig 		/*
   4010   1.750    rillig 		 * Guess the end of the current modifier.
   4011   1.750    rillig 		 * XXX: Skipping the rest of the modifier hides
   4012   1.750    rillig 		 * errors and leads to wrong results.
   4013   1.750    rillig 		 * Parsing should rather stop here.
   4014   1.750    rillig 		 */
   4015  1.1032    rillig 		for (p++; !IsDelimiter(*p, ch); p++)
   4016   1.750    rillig 			continue;
   4017  1.1151    rillig 		Parse_Error(PARSE_FATAL, "Unknown modifier \":%.*s\"",
   4018   1.851    rillig 		    (int)(p - mod), mod);
   4019   1.891    rillig 		Expr_SetValueRefer(ch->expr, var_Error);
   4020  1.1150    rillig 		res = AMR_CLEANUP;
   4021   1.750    rillig 	}
   4022  1.1150    rillig 	if (res != AMR_OK) {
   4023   1.750    rillig 		*pp = p;
   4024   1.750    rillig 		return res;
   4025   1.750    rillig 	}
   4026   1.750    rillig 
   4027   1.750    rillig 	if (DEBUG(VAR))
   4028   1.891    rillig 		LogAfterApply(ch, p, mod);
   4029   1.750    rillig 
   4030   1.891    rillig 	if (*p == '\0' && ch->endc != '\0') {
   4031  1.1131    rillig 		Parse_Error(PARSE_FATAL,
   4032  1.1170    rillig 		    "Unclosed expression, expecting \"%c\" for "
   4033  1.1131    rillig 		    "modifier \"%.*s\"",
   4034  1.1131    rillig 		    ch->endc, (int)(p - mod), mod);
   4035   1.750    rillig 	} else if (*p == ':') {
   4036   1.750    rillig 		p++;
   4037   1.891    rillig 	} else if (opts.strict && *p != '\0' && *p != ch->endc) {
   4038   1.750    rillig 		Parse_Error(PARSE_FATAL,
   4039  1.1170    rillig 		    "Missing delimiter \":\" after modifier \"%.*s\"",
   4040   1.750    rillig 		    (int)(p - mod), mod);
   4041   1.750    rillig 		/*
   4042   1.750    rillig 		 * TODO: propagate parse error to the enclosing
   4043   1.750    rillig 		 * expression
   4044   1.750    rillig 		 */
   4045   1.750    rillig 	}
   4046   1.750    rillig 	*pp = p;
   4047   1.750    rillig 	return AMR_OK;
   4048   1.750    rillig }
   4049   1.750    rillig 
   4050   1.897    rillig #if __STDC_VERSION__ >= 199901L
   4051  1.1079    rillig #define ModChain_Init(expr, startc, endc, sep, oneBigWord) \
   4052   1.897    rillig 	(ModChain) { expr, startc, endc, sep, oneBigWord }
   4053   1.897    rillig #else
   4054   1.897    rillig MAKE_INLINE ModChain
   4055  1.1079    rillig ModChain_Init(Expr *expr, char startc, char endc, char sep, bool oneBigWord)
   4056   1.897    rillig {
   4057   1.897    rillig 	ModChain ch;
   4058   1.897    rillig 	ch.expr = expr;
   4059   1.897    rillig 	ch.startc = startc;
   4060   1.897    rillig 	ch.endc = endc;
   4061   1.897    rillig 	ch.sep = sep;
   4062   1.897    rillig 	ch.oneBigWord = oneBigWord;
   4063   1.897    rillig 	return ch;
   4064   1.897    rillig }
   4065   1.897    rillig #endif
   4066   1.897    rillig 
   4067   1.419    rillig /* Apply any modifiers (such as :Mpattern or :@var@loop@ or :Q or ::=value). */
   4068   1.823    rillig static void
   4069   1.357    rillig ApplyModifiers(
   4070   1.823    rillig     Expr *expr,
   4071   1.821    rillig     const char **pp,	/* the parsing position, updated upon return */
   4072   1.821    rillig     char startc,	/* '(' or '{'; or '\0' for indirect modifiers */
   4073   1.823    rillig     char endc		/* ')' or '}'; or '\0' for indirect modifiers */
   4074   1.703    rillig )
   4075   1.703    rillig {
   4076  1.1079    rillig 	ModChain ch = ModChain_Init(expr, startc, endc, ' ', false);
   4077   1.703    rillig 	const char *p;
   4078   1.703    rillig 
   4079   1.703    rillig 	assert(startc == '(' || startc == '{' || startc == '\0');
   4080   1.703    rillig 	assert(endc == ')' || endc == '}' || endc == '\0');
   4081   1.965    rillig 	assert(Expr_Str(expr) != NULL);
   4082   1.703    rillig 
   4083   1.703    rillig 	p = *pp;
   4084   1.703    rillig 
   4085   1.703    rillig 	if (*p == '\0' && endc != '\0') {
   4086  1.1131    rillig 		Parse_Error(PARSE_FATAL,
   4087  1.1170    rillig 		    "Unclosed expression, expecting \"%c\"", ch.endc);
   4088   1.703    rillig 		goto cleanup;
   4089   1.703    rillig 	}
   4090   1.703    rillig 
   4091   1.703    rillig 	while (*p != '\0' && *p != endc) {
   4092   1.750    rillig 		ApplyModifierResult res;
   4093   1.703    rillig 
   4094   1.703    rillig 		if (*p == '$') {
   4095  1.1079    rillig 			/*
   4096  1.1079    rillig 			 * TODO: Only evaluate the expression once, no matter
   4097  1.1079    rillig 			 * whether it's an indirect modifier or the initial
   4098  1.1079    rillig 			 * part of a SysV modifier.
   4099  1.1079    rillig 			 */
   4100   1.849    rillig 			ApplyModifiersIndirectResult amir =
   4101   1.891    rillig 			    ApplyModifiersIndirect(&ch, &p);
   4102   1.703    rillig 			if (amir == AMIR_CONTINUE)
   4103   1.703    rillig 				continue;
   4104   1.703    rillig 			if (amir == AMIR_OUT)
   4105   1.752    rillig 				break;
   4106   1.703    rillig 		}
   4107   1.752    rillig 
   4108   1.891    rillig 		res = ApplySingleModifier(&p, &ch);
   4109   1.703    rillig 		if (res == AMR_CLEANUP)
   4110   1.703    rillig 			goto cleanup;
   4111   1.356    rillig 	}
   4112   1.752    rillig 
   4113   1.703    rillig 	*pp = p;
   4114   1.988    rillig 	assert(Expr_Str(expr) != NULL);	/* Use var_Error or varUndefined. */
   4115   1.823    rillig 	return;
   4116    1.25  christos 
   4117   1.240    rillig cleanup:
   4118   1.858    rillig 	/*
   4119   1.858    rillig 	 * TODO: Use p + strlen(p) instead, to stop parsing immediately.
   4120   1.858    rillig 	 *
   4121  1.1015    rillig 	 * In the unit tests, this generates a few shell commands with
   4122  1.1015    rillig 	 * unbalanced quotes.  Instead of producing these incomplete strings,
   4123  1.1015    rillig 	 * commands with evaluation errors should not be run at all.
   4124   1.858    rillig 	 *
   4125   1.858    rillig 	 * To make that happen, Var_Subst must report the actual errors
   4126  1.1044    rillig 	 * instead of returning the resulting string unconditionally.
   4127   1.858    rillig 	 */
   4128   1.703    rillig 	*pp = p;
   4129   1.823    rillig 	Expr_SetValueRefer(expr, var_Error);
   4130   1.108       sjg }
   4131    1.25  christos 
   4132   1.778    rillig /*
   4133  1.1015    rillig  * Only 4 of the 7 built-in local variables are treated specially as they are
   4134  1.1015    rillig  * the only ones that will be set when dynamic sources are expanded.
   4135   1.778    rillig  */
   4136   1.895    rillig static bool
   4137   1.916    rillig VarnameIsDynamic(Substring varname)
   4138   1.335    rillig {
   4139   1.916    rillig 	const char *name;
   4140   1.916    rillig 	size_t len;
   4141   1.916    rillig 
   4142   1.916    rillig 	name = varname.start;
   4143   1.916    rillig 	len = Substring_Length(varname);
   4144   1.703    rillig 	if (len == 1 || (len == 2 && (name[1] == 'F' || name[1] == 'D'))) {
   4145   1.703    rillig 		switch (name[0]) {
   4146   1.703    rillig 		case '@':
   4147   1.703    rillig 		case '%':
   4148   1.703    rillig 		case '*':
   4149   1.703    rillig 		case '!':
   4150   1.895    rillig 			return true;
   4151   1.703    rillig 		}
   4152   1.895    rillig 		return false;
   4153   1.335    rillig 	}
   4154   1.335    rillig 
   4155   1.703    rillig 	if ((len == 7 || len == 8) && name[0] == '.' && ch_isupper(name[1])) {
   4156   1.916    rillig 		return Substring_Equals(varname, ".TARGET") ||
   4157   1.916    rillig 		       Substring_Equals(varname, ".ARCHIVE") ||
   4158   1.916    rillig 		       Substring_Equals(varname, ".PREFIX") ||
   4159   1.916    rillig 		       Substring_Equals(varname, ".MEMBER");
   4160   1.703    rillig 	}
   4161   1.335    rillig 
   4162   1.895    rillig 	return false;
   4163   1.335    rillig }
   4164   1.335    rillig 
   4165   1.502    rillig static const char *
   4166   1.802    rillig UndefinedShortVarValue(char varname, const GNode *scope)
   4167   1.502    rillig {
   4168   1.802    rillig 	if (scope == SCOPE_CMDLINE || scope == SCOPE_GLOBAL) {
   4169   1.703    rillig 		/*
   4170   1.802    rillig 		 * If substituting a local variable in a non-local scope,
   4171   1.703    rillig 		 * assume it's for dynamic source stuff. We have to handle
   4172   1.703    rillig 		 * this specially and return the longhand for the variable
   4173   1.703    rillig 		 * with the dollar sign escaped so it makes it back to the
   4174   1.703    rillig 		 * caller. Only four of the local variables are treated
   4175   1.703    rillig 		 * specially as they are the only four that will be set
   4176   1.703    rillig 		 * when dynamic sources are expanded.
   4177   1.703    rillig 		 */
   4178   1.703    rillig 		switch (varname) {
   4179   1.703    rillig 		case '@':
   4180   1.703    rillig 			return "$(.TARGET)";
   4181   1.703    rillig 		case '%':
   4182   1.703    rillig 			return "$(.MEMBER)";
   4183   1.703    rillig 		case '*':
   4184   1.703    rillig 			return "$(.PREFIX)";
   4185   1.703    rillig 		case '!':
   4186   1.703    rillig 			return "$(.ARCHIVE)";
   4187   1.703    rillig 		}
   4188   1.502    rillig 	}
   4189   1.769    rillig 	return NULL;
   4190   1.502    rillig }
   4191   1.502    rillig 
   4192   1.778    rillig /*
   4193   1.778    rillig  * Parse a variable name, until the end character or a colon, whichever
   4194   1.778    rillig  * comes first.
   4195   1.778    rillig  */
   4196   1.916    rillig static void
   4197   1.501    rillig ParseVarname(const char **pp, char startc, char endc,
   4198   1.906    rillig 	     GNode *scope, VarEvalMode emode,
   4199   1.916    rillig 	     LazyBuf *buf)
   4200   1.501    rillig {
   4201   1.703    rillig 	const char *p = *pp;
   4202  1.1066    rillig 	int depth = 0;
   4203   1.703    rillig 
   4204   1.923    rillig 	LazyBuf_Init(buf, p);
   4205   1.703    rillig 
   4206   1.703    rillig 	while (*p != '\0') {
   4207   1.854    rillig 		if ((*p == endc || *p == ':') && depth == 0)
   4208   1.854    rillig 			break;
   4209   1.703    rillig 		if (*p == startc)
   4210   1.703    rillig 			depth++;
   4211   1.854    rillig 		if (*p == endc)
   4212   1.854    rillig 			depth--;
   4213   1.501    rillig 
   4214   1.703    rillig 		if (*p == '$') {
   4215  1.1042    rillig 			FStr nested_val = Var_Parse(&p, scope, emode);
   4216   1.703    rillig 			/* TODO: handle errors */
   4217   1.916    rillig 			LazyBuf_AddStr(buf, nested_val.str);
   4218   1.743    rillig 			FStr_Done(&nested_val);
   4219   1.703    rillig 		} else {
   4220   1.916    rillig 			LazyBuf_Add(buf, *p);
   4221   1.703    rillig 			p++;
   4222   1.703    rillig 		}
   4223   1.501    rillig 	}
   4224   1.703    rillig 	*pp = p;
   4225   1.501    rillig }
   4226   1.501    rillig 
   4227  1.1023    rillig static bool
   4228  1.1023    rillig IsShortVarnameValid(char varname, const char *start)
   4229   1.507    rillig {
   4230   1.818    rillig 	if (varname != '$' && varname != ':' && varname != '}' &&
   4231   1.818    rillig 	    varname != ')' && varname != '\0')
   4232  1.1023    rillig 		return true;
   4233   1.507    rillig 
   4234   1.771    rillig 	if (!opts.strict)
   4235  1.1023    rillig 		return false;	/* XXX: Missing error message */
   4236   1.507    rillig 
   4237  1.1096       sjg 	if (varname == '$' && save_dollars)
   4238   1.703    rillig 		Parse_Error(PARSE_FATAL,
   4239   1.507    rillig 		    "To escape a dollar, use \\$, not $$, at \"%s\"", start);
   4240   1.703    rillig 	else if (varname == '\0')
   4241   1.703    rillig 		Parse_Error(PARSE_FATAL, "Dollar followed by nothing");
   4242  1.1096       sjg 	else if (save_dollars)
   4243   1.703    rillig 		Parse_Error(PARSE_FATAL,
   4244  1.1170    rillig 		    "Invalid variable name \"%c\", at \"%s\"", varname, start);
   4245   1.507    rillig 
   4246  1.1023    rillig 	return false;
   4247   1.507    rillig }
   4248   1.507    rillig 
   4249   1.778    rillig /*
   4250   1.817    rillig  * Parse a single-character variable name such as in $V or $@.
   4251   1.778    rillig  * Return whether to continue parsing.
   4252   1.778    rillig  */
   4253   1.895    rillig static bool
   4254   1.817    rillig ParseVarnameShort(char varname, const char **pp, GNode *scope,
   4255   1.906    rillig 		  VarEvalMode emode,
   4256  1.1042    rillig 		  const char **out_false_val,
   4257   1.896    rillig 		  Var **out_true_var)
   4258   1.667    rillig {
   4259   1.703    rillig 	char name[2];
   4260   1.703    rillig 	Var *v;
   4261  1.1024    rillig 	const char *val;
   4262   1.622    rillig 
   4263  1.1023    rillig 	if (!IsShortVarnameValid(varname, *pp)) {
   4264  1.1025    rillig 		(*pp)++;	/* only skip the '$' */
   4265   1.896    rillig 		*out_false_val = var_Error;
   4266   1.895    rillig 		return false;
   4267   1.703    rillig 	}
   4268   1.622    rillig 
   4269   1.817    rillig 	name[0] = varname;
   4270   1.703    rillig 	name[1] = '\0';
   4271   1.895    rillig 	v = VarFind(name, scope, true);
   4272  1.1024    rillig 	if (v != NULL) {
   4273  1.1025    rillig 		/* No need to advance *pp, the calling code handles this. */
   4274  1.1024    rillig 		*out_true_var = v;
   4275  1.1024    rillig 		return true;
   4276  1.1024    rillig 	}
   4277   1.622    rillig 
   4278  1.1024    rillig 	*pp += 2;
   4279   1.769    rillig 
   4280  1.1024    rillig 	val = UndefinedShortVarValue(varname, scope);
   4281  1.1024    rillig 	if (val == NULL)
   4282  1.1144    rillig 		val = emode == VARE_EVAL_DEFINED
   4283  1.1144    rillig 		    || emode == VARE_EVAL_DEFINED_LOUD
   4284  1.1144    rillig 		    ? var_Error : varUndefined;
   4285   1.767    rillig 
   4286  1.1144    rillig 	if ((opts.strict || emode == VARE_EVAL_DEFINED_LOUD)
   4287  1.1144    rillig 	    && val == var_Error) {
   4288  1.1024    rillig 		Parse_Error(PARSE_FATAL,
   4289  1.1024    rillig 		    "Variable \"%s\" is undefined", name);
   4290   1.622    rillig 	}
   4291   1.622    rillig 
   4292  1.1024    rillig 	*out_false_val = val;
   4293  1.1024    rillig 	return false;
   4294   1.622    rillig }
   4295   1.622    rillig 
   4296   1.662    rillig /* Find variables like @F or <D. */
   4297   1.662    rillig static Var *
   4298   1.916    rillig FindLocalLegacyVar(Substring varname, GNode *scope,
   4299   1.662    rillig 		   const char **out_extraModifiers)
   4300   1.662    rillig {
   4301   1.916    rillig 	Var *v;
   4302   1.916    rillig 
   4303   1.802    rillig 	/* Only resolve these variables if scope is a "real" target. */
   4304   1.802    rillig 	if (scope == SCOPE_CMDLINE || scope == SCOPE_GLOBAL)
   4305   1.703    rillig 		return NULL;
   4306   1.703    rillig 
   4307   1.916    rillig 	if (Substring_Length(varname) != 2)
   4308   1.703    rillig 		return NULL;
   4309   1.916    rillig 	if (varname.start[1] != 'F' && varname.start[1] != 'D')
   4310   1.703    rillig 		return NULL;
   4311  1.1169    rillig 	if (strchr("@%?*!<>^", varname.start[0]) == NULL)
   4312   1.703    rillig 		return NULL;
   4313   1.703    rillig 
   4314  1.1091    rillig 	v = VarFindSubstring(Substring_Init(varname.start, varname.start + 1),
   4315  1.1091    rillig 	    scope, false);
   4316   1.916    rillig 	if (v == NULL)
   4317   1.916    rillig 		return NULL;
   4318   1.897    rillig 
   4319   1.916    rillig 	*out_extraModifiers = varname.start[1] == 'D' ? "H:" : "T:";
   4320   1.916    rillig 	return v;
   4321   1.662    rillig }
   4322   1.662    rillig 
   4323  1.1044    rillig static FStr
   4324   1.916    rillig EvalUndefined(bool dynamic, const char *start, const char *p,
   4325  1.1159    rillig 	      Substring varname, VarEvalMode emode, int parseErrorsBefore)
   4326   1.667    rillig {
   4327  1.1044    rillig 	if (dynamic)
   4328  1.1044    rillig 		return FStr_InitOwn(bmake_strsedup(start, p));
   4329   1.703    rillig 
   4330  1.1144    rillig 	if (emode == VARE_EVAL_DEFINED_LOUD
   4331  1.1144    rillig 	    || (emode == VARE_EVAL_DEFINED && opts.strict)) {
   4332  1.1159    rillig 		if (parseErrors == parseErrorsBefore) {
   4333  1.1159    rillig 			Parse_Error(PARSE_FATAL,
   4334  1.1159    rillig 			    "Variable \"%.*s\" is undefined",
   4335  1.1159    rillig 			    (int) Substring_Length(varname), varname.start);
   4336  1.1159    rillig 		}
   4337  1.1044    rillig 		return FStr_InitRefer(var_Error);
   4338   1.703    rillig 	}
   4339   1.703    rillig 
   4340  1.1044    rillig 	return FStr_InitRefer(
   4341  1.1144    rillig 	    emode == VARE_EVAL_DEFINED_LOUD || emode == VARE_EVAL_DEFINED
   4342  1.1144    rillig 		? var_Error : varUndefined);
   4343   1.663    rillig }
   4344   1.663    rillig 
   4345  1.1165       sjg static void
   4346  1.1165       sjg CheckVarname(Substring name)
   4347  1.1165       sjg {
   4348  1.1165       sjg 	const char *p;
   4349  1.1165       sjg 
   4350  1.1165       sjg 	for (p = name.start; p < name.end; p++) {
   4351  1.1165       sjg 		if (ch_isspace(*p))
   4352  1.1165       sjg 			break;
   4353  1.1165       sjg 	}
   4354  1.1165       sjg 	if (p < name.end) {
   4355  1.1165       sjg 		Parse_Error(PARSE_WARNING,
   4356  1.1165       sjg 		    ch_isprint(*p)
   4357  1.1165       sjg 		    ? "Invalid character \"%c\" in variable name \"%.*s\""
   4358  1.1165       sjg 		    : "Invalid character \"\\x%02x\" in variable name \"%.*s\"",
   4359  1.1165       sjg 		    (int)(*p),
   4360  1.1165       sjg 		    (int)Substring_Length(name), name.start);
   4361  1.1165       sjg 	}
   4362  1.1165       sjg }
   4363  1.1165       sjg 
   4364   1.778    rillig /*
   4365   1.778    rillig  * Parse a long variable name enclosed in braces or parentheses such as $(VAR)
   4366   1.623    rillig  * or ${VAR}, up to the closing brace or parenthesis, or in the case of
   4367   1.623    rillig  * ${VAR:Modifiers}, up to the ':' that starts the modifiers.
   4368   1.778    rillig  * Return whether to continue parsing.
   4369   1.778    rillig  */
   4370   1.895    rillig static bool
   4371   1.623    rillig ParseVarnameLong(
   4372   1.922    rillig 	const char **pp,
   4373   1.624    rillig 	char startc,
   4374   1.802    rillig 	GNode *scope,
   4375   1.906    rillig 	VarEvalMode emode,
   4376  1.1144    rillig 	VarEvalMode nested_emode,
   4377  1.1159    rillig 	int parseErrorsBefore,
   4378   1.624    rillig 
   4379   1.896    rillig 	const char **out_false_pp,
   4380   1.896    rillig 	FStr *out_false_val,
   4381   1.896    rillig 
   4382   1.896    rillig 	char *out_true_endc,
   4383   1.896    rillig 	Var **out_true_v,
   4384   1.896    rillig 	bool *out_true_haveModifier,
   4385   1.896    rillig 	const char **out_true_extraModifiers,
   4386   1.896    rillig 	bool *out_true_dynamic,
   4387   1.896    rillig 	ExprDefined *out_true_exprDefined
   4388   1.703    rillig )
   4389   1.703    rillig {
   4390   1.916    rillig 	LazyBuf varname;
   4391   1.972       sjg 	Substring name;
   4392   1.703    rillig 	Var *v;
   4393   1.895    rillig 	bool haveModifier;
   4394   1.895    rillig 	bool dynamic = false;
   4395   1.703    rillig 
   4396   1.922    rillig 	const char *p = *pp;
   4397  1.1095    rillig 	const char *start = p;
   4398   1.703    rillig 	char endc = startc == '(' ? ')' : '}';
   4399   1.703    rillig 
   4400   1.703    rillig 	p += 2;			/* skip "${" or "$(" or "y(" */
   4401  1.1144    rillig 	ParseVarname(&p, startc, endc, scope, nested_emode, &varname);
   4402   1.972       sjg 	name = LazyBuf_Get(&varname);
   4403   1.703    rillig 
   4404  1.1093    rillig 	if (*p == ':')
   4405   1.895    rillig 		haveModifier = true;
   4406  1.1093    rillig 	else if (*p == endc)
   4407   1.895    rillig 		haveModifier = false;
   4408  1.1093    rillig 	else {
   4409   1.916    rillig 		Parse_Error(PARSE_FATAL, "Unclosed variable \"%.*s\"",
   4410   1.916    rillig 		    (int)Substring_Length(name), name.start);
   4411   1.916    rillig 		LazyBuf_Done(&varname);
   4412   1.896    rillig 		*out_false_pp = p;
   4413   1.896    rillig 		*out_false_val = FStr_InitRefer(var_Error);
   4414   1.895    rillig 		return false;
   4415   1.703    rillig 	}
   4416   1.623    rillig 
   4417   1.972       sjg 	v = VarFindSubstring(name, scope, true);
   4418   1.623    rillig 
   4419   1.988    rillig 	/*
   4420   1.988    rillig 	 * At this point, p points just after the variable name, either at
   4421   1.988    rillig 	 * ':' or at endc.
   4422   1.988    rillig 	 */
   4423   1.623    rillig 
   4424   1.974    rillig 	if (v == NULL && Substring_Equals(name, ".SUFFIXES")) {
   4425   1.974    rillig 		char *suffixes = Suff_NamesStr();
   4426   1.975    rillig 		v = VarNew(FStr_InitRefer(".SUFFIXES"), suffixes,
   4427   1.979    rillig 		    true, false, true);
   4428   1.974    rillig 		free(suffixes);
   4429   1.974    rillig 	} else if (v == NULL)
   4430   1.974    rillig 		v = FindLocalLegacyVar(name, scope, out_true_extraModifiers);
   4431   1.623    rillig 
   4432   1.703    rillig 	if (v == NULL) {
   4433   1.703    rillig 		/*
   4434   1.703    rillig 		 * Defer expansion of dynamic variables if they appear in
   4435   1.802    rillig 		 * non-local scope since they are not defined there.
   4436   1.703    rillig 		 */
   4437   1.972       sjg 		dynamic = VarnameIsDynamic(name) &&
   4438   1.802    rillig 			  (scope == SCOPE_CMDLINE || scope == SCOPE_GLOBAL);
   4439   1.703    rillig 
   4440   1.703    rillig 		if (!haveModifier) {
   4441  1.1165       sjg 			CheckVarname(name);
   4442   1.703    rillig 			p++;	/* skip endc */
   4443   1.896    rillig 			*out_false_pp = p;
   4444  1.1044    rillig 			*out_false_val = EvalUndefined(dynamic, start, p,
   4445  1.1159    rillig 			    name, emode, parseErrorsBefore);
   4446   1.986    rillig 			LazyBuf_Done(&varname);
   4447   1.895    rillig 			return false;
   4448   1.703    rillig 		}
   4449   1.623    rillig 
   4450   1.703    rillig 		/*
   4451  1.1075    rillig 		 * The expression is based on an undefined variable.
   4452   1.703    rillig 		 * Nevertheless it needs a Var, for modifiers that access the
   4453   1.703    rillig 		 * variable name, such as :L or :?.
   4454   1.703    rillig 		 *
   4455   1.703    rillig 		 * Most modifiers leave this expression in the "undefined"
   4456  1.1079    rillig 		 * state (DEF_UNDEF), only a few modifiers like :D, :U, :L,
   4457   1.703    rillig 		 * :P turn this undefined expression into a defined
   4458  1.1079    rillig 		 * expression (DEF_DEFINED).
   4459   1.703    rillig 		 *
   4460   1.830    rillig 		 * In the end, after applying all modifiers, if the expression
   4461   1.703    rillig 		 * is still undefined, Var_Parse will return an empty string
   4462   1.703    rillig 		 * instead of the actually computed value.
   4463   1.703    rillig 		 */
   4464   1.978    rillig 		v = VarNew(LazyBuf_DoneGet(&varname), "",
   4465   1.980    rillig 		    true, false, false);
   4466   1.896    rillig 		*out_true_exprDefined = DEF_UNDEF;
   4467   1.703    rillig 	} else
   4468   1.916    rillig 		LazyBuf_Done(&varname);
   4469   1.623    rillig 
   4470   1.922    rillig 	*pp = p;
   4471   1.896    rillig 	*out_true_endc = endc;
   4472   1.896    rillig 	*out_true_v = v;
   4473   1.896    rillig 	*out_true_haveModifier = haveModifier;
   4474   1.896    rillig 	*out_true_dynamic = dynamic;
   4475   1.895    rillig 	return true;
   4476   1.623    rillig }
   4477   1.623    rillig 
   4478   1.897    rillig #if __STDC_VERSION__ >= 199901L
   4479  1.1079    rillig #define Expr_Init(name, value, emode, scope, defined) \
   4480  1.1079    rillig 	(Expr) { name, value, emode, scope, defined }
   4481   1.897    rillig #else
   4482   1.897    rillig MAKE_INLINE Expr
   4483  1.1079    rillig Expr_Init(const char *name, FStr value,
   4484  1.1079    rillig 	  VarEvalMode emode, GNode *scope, ExprDefined defined)
   4485   1.897    rillig {
   4486   1.897    rillig 	Expr expr;
   4487   1.897    rillig 
   4488   1.898    rillig 	expr.name = name;
   4489   1.897    rillig 	expr.value = value;
   4490   1.917    rillig 	expr.emode = emode;
   4491   1.897    rillig 	expr.scope = scope;
   4492   1.897    rillig 	expr.defined = defined;
   4493   1.897    rillig 	return expr;
   4494   1.897    rillig }
   4495   1.897    rillig #endif
   4496   1.897    rillig 
   4497   1.666    rillig /*
   4498   1.913    rillig  * Expressions of the form ${:U...} with a trivial value are often generated
   4499  1.1079    rillig  * by .for loops and are boring, so evaluate them without debug logging.
   4500   1.913    rillig  */
   4501   1.913    rillig static bool
   4502  1.1106    rillig Var_Parse_U(const char **pp, VarEvalMode emode, FStr *out_value)
   4503   1.913    rillig {
   4504   1.913    rillig 	const char *p;
   4505   1.913    rillig 
   4506   1.913    rillig 	p = *pp;
   4507   1.913    rillig 	if (!(p[0] == '$' && p[1] == '{' && p[2] == ':' && p[3] == 'U'))
   4508   1.913    rillig 		return false;
   4509   1.913    rillig 
   4510   1.913    rillig 	p += 4;
   4511   1.915    rillig 	while (*p != '$' && *p != '{' && *p != ':' && *p != '\\' &&
   4512   1.915    rillig 	       *p != '}' && *p != '\0')
   4513   1.913    rillig 		p++;
   4514   1.913    rillig 	if (*p != '}')
   4515   1.913    rillig 		return false;
   4516   1.913    rillig 
   4517  1.1119    rillig 	*out_value = emode == VARE_PARSE
   4518  1.1093    rillig 	    ? FStr_InitRefer("")
   4519  1.1093    rillig 	    : FStr_InitOwn(bmake_strsedup(*pp + 4, p));
   4520   1.913    rillig 	*pp = p + 1;
   4521   1.913    rillig 	return true;
   4522   1.913    rillig }
   4523   1.913    rillig 
   4524   1.913    rillig /*
   4525  1.1079    rillig  * Given the start of an expression (such as $v, $(VAR), ${VAR:Mpattern}),
   4526  1.1079    rillig  * extract the variable name and the modifiers, if any.  While parsing, apply
   4527  1.1079    rillig  * the modifiers to the value of the expression.
   4528   1.579    rillig  *
   4529   1.108       sjg  * Input:
   4530   1.666    rillig  *	*pp		The string to parse.
   4531  1.1021    rillig  *			When called from CondParser_FuncCallEmpty, it can
   4532  1.1021    rillig  *			also point to the "y" of "empty(VARNAME:Modifiers)".
   4533  1.1079    rillig  *	scope		The scope for finding variables.
   4534  1.1079    rillig  *	emode		Controls the exact details of parsing and evaluation.
   4535   1.666    rillig  *
   4536   1.666    rillig  * Output:
   4537   1.666    rillig  *	*pp		The position where to continue parsing.
   4538   1.666    rillig  *			TODO: After a parse error, the value of *pp is
   4539   1.666    rillig  *			unspecified.  It may not have been updated at all,
   4540   1.666    rillig  *			point to some random character in the string, to the
   4541   1.666    rillig  *			location of the parse error, or at the end of the
   4542   1.666    rillig  *			string.
   4543  1.1075    rillig  *	return		The value of the expression, never NULL.
   4544  1.1042    rillig  *	return		var_Error if there was a parse error.
   4545  1.1042    rillig  *	return		var_Error if the base variable of the expression was
   4546  1.1119    rillig  *			undefined, emode is VARE_EVAL_DEFINED, and none of
   4547   1.666    rillig  *			the modifiers turned the undefined expression into a
   4548   1.666    rillig  *			defined expression.
   4549   1.666    rillig  *			XXX: It is not guaranteed that an error message has
   4550   1.666    rillig  *			been printed.
   4551  1.1042    rillig  *	return		varUndefined if the base variable of the expression
   4552  1.1119    rillig  *			was undefined, emode was not VARE_EVAL_DEFINED,
   4553   1.666    rillig  *			and none of the modifiers turned the undefined
   4554   1.666    rillig  *			expression into a defined expression.
   4555   1.108       sjg  */
   4556  1.1042    rillig FStr
   4557  1.1042    rillig Var_Parse(const char **pp, GNode *scope, VarEvalMode emode)
   4558   1.108       sjg {
   4559  1.1106    rillig 	const char *start, *p;
   4560  1.1021    rillig 	bool haveModifier;	/* true for ${VAR:...}, false for ${VAR} */
   4561  1.1021    rillig 	char startc;		/* the actual '{' or '(' or '\0' */
   4562  1.1021    rillig 	char endc;		/* the expected '}' or ')' or '\0' */
   4563   1.703    rillig 	/*
   4564  1.1021    rillig 	 * true if the expression is based on one of the 7 predefined
   4565  1.1021    rillig 	 * variables that are local to a target, and the expression is
   4566  1.1021    rillig 	 * expanded in a non-local scope.  The result is the text of the
   4567  1.1021    rillig 	 * expression, unaltered.  This is needed to support dynamic sources.
   4568   1.703    rillig 	 */
   4569   1.895    rillig 	bool dynamic;
   4570   1.703    rillig 	const char *extramodifiers;
   4571   1.703    rillig 	Var *v;
   4572  1.1144    rillig 	Expr expr = Expr_Init(NULL, FStr_InitRefer(NULL),
   4573  1.1144    rillig 	    emode == VARE_EVAL_DEFINED || emode == VARE_EVAL_DEFINED_LOUD
   4574  1.1144    rillig 		? VARE_EVAL : emode,
   4575   1.898    rillig 	    scope, DEF_REGULAR);
   4576  1.1042    rillig 	FStr val;
   4577  1.1159    rillig 	int parseErrorsBefore = parseErrors;
   4578   1.703    rillig 
   4579  1.1106    rillig 	if (Var_Parse_U(pp, emode, &val))
   4580  1.1042    rillig 		return val;
   4581   1.913    rillig 
   4582  1.1106    rillig 	p = *pp;
   4583  1.1106    rillig 	start = p;
   4584   1.906    rillig 	DEBUG2(VAR, "Var_Parse: %s (%s)\n", start, VarEvalMode_Name[emode]);
   4585   1.703    rillig 
   4586  1.1042    rillig 	val = FStr_InitRefer(NULL);
   4587   1.703    rillig 	extramodifiers = NULL;	/* extra modifiers to apply first */
   4588   1.895    rillig 	dynamic = false;
   4589   1.473    rillig 
   4590  1.1021    rillig 	endc = '\0';		/* Appease GCC. */
   4591   1.108       sjg 
   4592   1.703    rillig 	startc = p[1];
   4593   1.703    rillig 	if (startc != '(' && startc != '{') {
   4594  1.1042    rillig 		if (!ParseVarnameShort(startc, pp, scope, emode, &val.str, &v))
   4595  1.1042    rillig 			return val;
   4596   1.895    rillig 		haveModifier = false;
   4597   1.703    rillig 		p++;
   4598   1.703    rillig 	} else {
   4599  1.1144    rillig 		if (!ParseVarnameLong(&p, startc, scope, emode, expr.emode,
   4600  1.1159    rillig 		    parseErrorsBefore,
   4601  1.1044    rillig 		    pp, &val,
   4602   1.922    rillig 		    &endc, &v, &haveModifier, &extramodifiers,
   4603   1.825    rillig 		    &dynamic, &expr.defined))
   4604  1.1042    rillig 			return val;
   4605   1.703    rillig 	}
   4606   1.401    rillig 
   4607   1.898    rillig 	expr.name = v->name.str;
   4608  1.1028    rillig 	if (v->inUse && VarEvalMode_ShouldEval(emode)) {
   4609  1.1137    rillig 		Parse_Error(PARSE_FATAL, "Variable %s is recursive.",
   4610  1.1137    rillig 		    v->name.str);
   4611  1.1138    rillig 		FStr_Done(&val);
   4612  1.1138    rillig 		if (*p != '\0')
   4613  1.1138    rillig 			p++;
   4614  1.1138    rillig 		*pp = p;
   4615  1.1138    rillig 		return FStr_InitRefer(var_Error);
   4616  1.1008    rillig 	}
   4617   1.187  christos 
   4618   1.703    rillig 	/*
   4619  1.1078    rillig 	 * FIXME: This assignment creates an alias to the current value of the
   4620   1.703    rillig 	 * variable.  This means that as long as the value of the expression
   4621  1.1078    rillig 	 * stays the same, the value of the variable must not change, and the
   4622  1.1078    rillig 	 * variable must not be deleted.  Using the ':@' modifier, it is
   4623  1.1084    rillig 	 * possible (since var.c 1.212 from 2017-02-01) to delete the variable
   4624  1.1078    rillig 	 * while its value is still being used:
   4625  1.1078    rillig 	 *
   4626  1.1078    rillig 	 *	VAR=	value
   4627  1.1107    rillig 	 *	_:=	${VAR:${:U:@VAR@@}:S,^,prefix,}
   4628  1.1078    rillig 	 *
   4629  1.1078    rillig 	 * The same effect might be achievable using the '::=' or the ':_'
   4630  1.1078    rillig 	 * modifiers.
   4631  1.1021    rillig 	 *
   4632   1.703    rillig 	 * At the bottom of this function, the resulting value is compared to
   4633   1.703    rillig 	 * the then-current value of the variable.  This might also invoke
   4634   1.703    rillig 	 * undefined behavior.
   4635   1.703    rillig 	 */
   4636   1.823    rillig 	expr.value = FStr_InitRefer(v->val.data);
   4637   1.108       sjg 
   4638  1.1133    rillig 	if (!VarEvalMode_ShouldEval(emode))
   4639  1.1133    rillig 		EvalStack_Push(VSK_EXPR_PARSE, start, NULL);
   4640  1.1133    rillig 	else if (expr.name[0] != '\0')
   4641  1.1128    rillig 		EvalStack_Push(VSK_VARNAME, expr.name, &expr.value);
   4642  1.1102    rillig 	else
   4643  1.1132    rillig 		EvalStack_Push(VSK_EXPR, start, &expr.value);
   4644  1.1102    rillig 
   4645   1.703    rillig 	/*
   4646   1.703    rillig 	 * Before applying any modifiers, expand any nested expressions from
   4647   1.703    rillig 	 * the variable value.
   4648   1.703    rillig 	 */
   4649  1.1003    rillig 	if (VarEvalMode_ShouldEval(emode) &&
   4650  1.1003    rillig 	    strchr(Expr_Str(&expr), '$') != NULL) {
   4651   1.743    rillig 		char *expanded;
   4652   1.902    rillig 		v->inUse = true;
   4653  1.1144    rillig 		expanded = Var_Subst(Expr_Str(&expr), scope, expr.emode);
   4654   1.902    rillig 		v->inUse = false;
   4655   1.703    rillig 		/* TODO: handle errors */
   4656   1.823    rillig 		Expr_SetValueOwn(&expr, expanded);
   4657   1.191  dholland 	}
   4658   1.191  dholland 
   4659   1.855    rillig 	if (extramodifiers != NULL) {
   4660   1.855    rillig 		const char *em = extramodifiers;
   4661   1.855    rillig 		ApplyModifiers(&expr, &em, '\0', '\0');
   4662   1.855    rillig 	}
   4663   1.191  dholland 
   4664   1.855    rillig 	if (haveModifier) {
   4665   1.988    rillig 		p++;		/* Skip initial colon. */
   4666   1.855    rillig 		ApplyModifiers(&expr, &p, startc, endc);
   4667   1.191  dholland 	}
   4668   1.438    rillig 
   4669   1.703    rillig 	if (*p != '\0')		/* Skip past endc if possible. */
   4670   1.703    rillig 		p++;
   4671   1.519    rillig 
   4672   1.703    rillig 	*pp = p;
   4673    1.15  christos 
   4674   1.980    rillig 	if (expr.defined == DEF_UNDEF) {
   4675  1.1159    rillig 		Substring varname = Substring_InitStr(expr.name);
   4676  1.1159    rillig 		FStr value = EvalUndefined(dynamic, start, p, varname, emode,
   4677  1.1159    rillig 		    parseErrorsBefore);
   4678  1.1159    rillig 		Expr_SetValue(&expr, value);
   4679   1.980    rillig 	}
   4680   1.980    rillig 
   4681  1.1161    rillig 	EvalStack_Pop();
   4682  1.1161    rillig 
   4683   1.978    rillig 	if (v->shortLived) {
   4684   1.980    rillig 		if (expr.value.str == v->val.data) {
   4685   1.980    rillig 			/* move ownership */
   4686   1.980    rillig 			expr.value.freeIt = v->val.data;
   4687   1.980    rillig 			v->val.data = NULL;
   4688   1.703    rillig 		}
   4689   1.980    rillig 		VarFreeShortLived(v);
   4690    1.34  christos 	}
   4691   1.980    rillig 
   4692  1.1042    rillig 	return expr.value;
   4693     1.1       cgd }
   4694     1.1       cgd 
   4695   1.678    rillig static void
   4696   1.906    rillig VarSubstDollarDollar(const char **pp, Buffer *res, VarEvalMode emode)
   4697   1.768    rillig {
   4698   1.830    rillig 	/* A dollar sign may be escaped with another dollar sign. */
   4699   1.906    rillig 	if (save_dollars && VarEvalMode_ShouldKeepDollar(emode))
   4700   1.768    rillig 		Buf_AddByte(res, '$');
   4701   1.768    rillig 	Buf_AddByte(res, '$');
   4702   1.768    rillig 	*pp += 2;
   4703   1.768    rillig }
   4704   1.768    rillig 
   4705   1.768    rillig static void
   4706  1.1136    rillig VarSubstExpr(const char **pp, Buffer *buf, GNode *scope, VarEvalMode emode)
   4707   1.678    rillig {
   4708   1.703    rillig 	const char *p = *pp;
   4709   1.703    rillig 	const char *nested_p = p;
   4710  1.1042    rillig 	FStr val = Var_Parse(&nested_p, scope, emode);
   4711   1.703    rillig 	/* TODO: handle errors */
   4712   1.678    rillig 
   4713   1.743    rillig 	if (val.str == var_Error || val.str == varUndefined) {
   4714  1.1136    rillig 		if (!VarEvalMode_ShouldKeepUndef(emode)
   4715  1.1136    rillig 		    || val.str == var_Error) {
   4716   1.703    rillig 			p = nested_p;
   4717   1.703    rillig 		} else {
   4718   1.988    rillig 			/*
   4719   1.988    rillig 			 * Copy the initial '$' of the undefined expression,
   4720   1.703    rillig 			 * thereby deferring expansion of the expression, but
   4721   1.988    rillig 			 * expand nested expressions if already possible. See
   4722   1.988    rillig 			 * unit-tests/varparse-undef-partial.mk.
   4723   1.988    rillig 			 */
   4724   1.703    rillig 			Buf_AddByte(buf, *p);
   4725   1.703    rillig 			p++;
   4726   1.703    rillig 		}
   4727   1.678    rillig 	} else {
   4728   1.703    rillig 		p = nested_p;
   4729   1.743    rillig 		Buf_AddStr(buf, val.str);
   4730   1.678    rillig 	}
   4731   1.678    rillig 
   4732   1.743    rillig 	FStr_Done(&val);
   4733   1.678    rillig 
   4734   1.703    rillig 	*pp = p;
   4735   1.678    rillig }
   4736   1.678    rillig 
   4737   1.768    rillig /*
   4738  1.1075    rillig  * Skip as many characters as possible -- either to the end of the string,
   4739  1.1075    rillig  * or to the next dollar sign, which may start an expression.
   4740   1.768    rillig  */
   4741   1.768    rillig static void
   4742   1.768    rillig VarSubstPlain(const char **pp, Buffer *res)
   4743   1.768    rillig {
   4744   1.768    rillig 	const char *p = *pp;
   4745   1.768    rillig 	const char *start = p;
   4746   1.768    rillig 
   4747   1.768    rillig 	for (p++; *p != '$' && *p != '\0'; p++)
   4748   1.768    rillig 		continue;
   4749  1.1055    rillig 	Buf_AddRange(res, start, p);
   4750   1.768    rillig 	*pp = p;
   4751   1.768    rillig }
   4752   1.768    rillig 
   4753   1.778    rillig /*
   4754  1.1075    rillig  * Expand all expressions like $V, ${VAR}, $(VAR:Modifiers) in the
   4755   1.660    rillig  * given string.
   4756     1.1       cgd  *
   4757    1.70       wiz  * Input:
   4758  1.1105    rillig  *	str		The string in which the expressions are expanded.
   4759  1.1105    rillig  *	scope		The scope in which to start searching for variables.
   4760  1.1105    rillig  *			The other scopes are searched as well.
   4761   1.917    rillig  *	emode		The mode for parsing or evaluating subexpressions.
   4762     1.1       cgd  */
   4763  1.1043    rillig char *
   4764  1.1043    rillig Var_Subst(const char *str, GNode *scope, VarEvalMode emode)
   4765     1.1       cgd {
   4766   1.703    rillig 	const char *p = str;
   4767   1.703    rillig 	Buffer res;
   4768     1.1       cgd 
   4769   1.703    rillig 	Buf_Init(&res);
   4770   1.703    rillig 
   4771   1.703    rillig 	while (*p != '\0') {
   4772   1.768    rillig 		if (p[0] == '$' && p[1] == '$')
   4773   1.906    rillig 			VarSubstDollarDollar(&p, &res, emode);
   4774   1.768    rillig 		else if (p[0] == '$')
   4775  1.1136    rillig 			VarSubstExpr(&p, &res, scope, emode);
   4776   1.768    rillig 		else
   4777   1.768    rillig 			VarSubstPlain(&p, &res);
   4778     1.1       cgd 	}
   4779    1.15  christos 
   4780  1.1108    rillig 	return Buf_DoneData(&res);
   4781     1.1       cgd }
   4782     1.1       cgd 
   4783  1.1120    rillig char *
   4784  1.1120    rillig Var_SubstInTarget(const char *str, GNode *scope)
   4785  1.1120    rillig {
   4786  1.1120    rillig 	char *res;
   4787  1.1128    rillig 	EvalStack_Push(VSK_TARGET, scope->name, NULL);
   4788  1.1146    rillig 	EvalStack_Push(VSK_COMMAND, str, NULL);
   4789  1.1120    rillig 	res = Var_Subst(str, scope, VARE_EVAL);
   4790  1.1120    rillig 	EvalStack_Pop();
   4791  1.1146    rillig 	EvalStack_Pop();
   4792  1.1120    rillig 	return res;
   4793  1.1120    rillig }
   4794  1.1120    rillig 
   4795  1.1001    rillig void
   4796  1.1167    rillig Var_ExportStackTrace(const char *target, const char *cmd)
   4797  1.1167    rillig {
   4798  1.1167    rillig 	char *stackTrace;
   4799  1.1167    rillig 
   4800  1.1168    rillig 	if (GetParentStackTrace() == NULL)
   4801  1.1167    rillig 		return;
   4802  1.1167    rillig 
   4803  1.1167    rillig 	if (target != NULL)
   4804  1.1167    rillig 		EvalStack_Push(VSK_TARGET, target, NULL);
   4805  1.1167    rillig 	if (cmd != NULL)
   4806  1.1167    rillig 		EvalStack_Push(VSK_COMMAND, cmd, NULL);
   4807  1.1167    rillig 
   4808  1.1167    rillig 	stackTrace = GetStackTrace(true);
   4809  1.1167    rillig 	(void)setenv("MAKE_STACK_TRACE", stackTrace, 1);
   4810  1.1167    rillig 	free(stackTrace);
   4811  1.1167    rillig 
   4812  1.1167    rillig 	if (cmd != NULL)
   4813  1.1167    rillig 		EvalStack_Pop();
   4814  1.1167    rillig 	if (target != NULL)
   4815  1.1167    rillig 		EvalStack_Pop();
   4816  1.1167    rillig }
   4817  1.1167    rillig 
   4818  1.1167    rillig void
   4819  1.1001    rillig Var_Expand(FStr *str, GNode *scope, VarEvalMode emode)
   4820  1.1001    rillig {
   4821  1.1001    rillig 	char *expanded;
   4822  1.1001    rillig 
   4823  1.1001    rillig 	if (strchr(str->str, '$') == NULL)
   4824  1.1001    rillig 		return;
   4825  1.1043    rillig 	expanded = Var_Subst(str->str, scope, emode);
   4826  1.1001    rillig 	/* TODO: handle errors */
   4827  1.1001    rillig 	FStr_Done(str);
   4828  1.1001    rillig 	*str = FStr_InitOwn(expanded);
   4829  1.1001    rillig }
   4830  1.1001    rillig 
   4831   1.286       sjg void
   4832   1.286       sjg Var_Stats(void)
   4833   1.286       sjg {
   4834   1.802    rillig 	HashTable_DebugStats(&SCOPE_GLOBAL->vars, "Global variables");
   4835     1.1       cgd }
   4836    1.15  christos 
   4837   1.964    rillig static int
   4838   1.964    rillig StrAsc(const void *sa, const void *sb)
   4839   1.964    rillig {
   4840   1.964    rillig 	return strcmp(
   4841   1.964    rillig 	    *((const char *const *)sa), *((const char *const *)sb));
   4842   1.964    rillig }
   4843   1.964    rillig 
   4844   1.964    rillig 
   4845   1.802    rillig /* Print all variables in a scope, sorted by name. */
   4846     1.5       cgd void
   4847   1.802    rillig Var_Dump(GNode *scope)
   4848     1.1       cgd {
   4849   1.703    rillig 	Vector /* of const char * */ vec;
   4850   1.703    rillig 	HashIter hi;
   4851   1.703    rillig 	size_t i;
   4852   1.703    rillig 	const char **varnames;
   4853   1.703    rillig 
   4854   1.703    rillig 	Vector_Init(&vec, sizeof(const char *));
   4855   1.703    rillig 
   4856   1.802    rillig 	HashIter_Init(&hi, &scope->vars);
   4857  1.1114    rillig 	while (HashIter_Next(&hi))
   4858   1.703    rillig 		*(const char **)Vector_Push(&vec) = hi.entry->key;
   4859   1.703    rillig 	varnames = vec.items;
   4860   1.703    rillig 
   4861   1.964    rillig 	qsort(varnames, vec.len, sizeof varnames[0], StrAsc);
   4862   1.703    rillig 
   4863   1.703    rillig 	for (i = 0; i < vec.len; i++) {
   4864   1.703    rillig 		const char *varname = varnames[i];
   4865  1.1035    rillig 		const Var *var = HashTable_FindValue(&scope->vars, varname);
   4866  1.1018    rillig 		debug_printf("%-16s = %s%s\n", varname,
   4867  1.1018    rillig 		    var->val.data, ValueDescription(var->val.data));
   4868   1.703    rillig 	}
   4869   1.573    rillig 
   4870   1.703    rillig 	Vector_Done(&vec);
   4871     1.1       cgd }
   4872