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