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