1 /* $NetBSD: var.c,v 1.522 2020/09/14 21:55:53 rillig 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 * var.c -- 73 * Variable-handling functions 74 * 75 * Interface: 76 * Var_Set Set the value of a variable in the given 77 * context. The variable is created if it doesn't 78 * yet exist. 79 * 80 * Var_Append Append more characters to an existing variable 81 * in the given context. The variable needn't 82 * exist already -- it will be created if it doesn't. 83 * A space is placed between the old value and the 84 * new one. 85 * 86 * Var_Exists See if a variable exists. 87 * 88 * Var_Value Return the unexpanded value of a variable in a 89 * context or NULL if the variable is undefined. 90 * 91 * Var_Subst Substitute either a single variable or all 92 * variables in a string, using the given context. 93 * 94 * Var_Parse Parse a variable expansion from a string and 95 * return the result and the number of characters 96 * consumed. 97 * 98 * Var_Delete Delete a variable in a context. 99 * 100 * Var_Init Initialize this module. 101 * 102 * Debugging: 103 * Var_Dump Print out all variables defined in the given 104 * context. 105 * 106 * XXX: There's a lot of duplication in these functions. 107 */ 108 109 #include <sys/stat.h> 110 #ifndef NO_REGEX 111 #include <sys/types.h> 112 #include <regex.h> 113 #endif 114 #include <inttypes.h> 115 #include <limits.h> 116 #include <time.h> 117 118 #include "make.h" 119 #include "dir.h" 120 #include "job.h" 121 #include "metachar.h" 122 123 /* "@(#)var.c 8.3 (Berkeley) 3/19/94" */ 124 MAKE_RCSID("$NetBSD: var.c,v 1.522 2020/09/14 21:55:53 rillig Exp $"); 125 126 #define VAR_DEBUG_IF(cond, fmt, ...) \ 127 if (!(DEBUG(VAR) && (cond))) \ 128 (void) 0; \ 129 else \ 130 fprintf(debug_file, fmt, __VA_ARGS__) 131 132 #define VAR_DEBUG(fmt, ...) VAR_DEBUG_IF(TRUE, fmt, __VA_ARGS__) 133 134 ENUM_FLAGS_RTTI_3(VarEvalFlags, 135 VARE_UNDEFERR, VARE_WANTRES, VARE_ASSIGN); 136 137 /* 138 * This lets us tell if we have replaced the original environ 139 * (which we cannot free). 140 */ 141 char **savedEnv = NULL; 142 143 /* 144 * This is a harmless return value for Var_Parse that can be used by Var_Subst 145 * to determine if there was an error in parsing -- easier than returning 146 * a flag, as things outside this module don't give a hoot. 147 */ 148 char var_Error[] = ""; 149 150 /* 151 * Similar to var_Error, but returned when the 'VARE_UNDEFERR' flag for 152 * Var_Parse is not set. 153 * 154 * Why not just use a constant? Well, GCC likes to condense identical string 155 * instances... 156 */ 157 static char varNoError[] = ""; 158 159 /* 160 * Traditionally we consume $$ during := like any other expansion. 161 * Other make's do not. 162 * This knob allows controlling the behavior. 163 * FALSE to consume $$ during := assignment. 164 * TRUE to preserve $$ during := assignment. 165 */ 166 #define SAVE_DOLLARS ".MAKE.SAVE_DOLLARS" 167 static Boolean save_dollars = TRUE; 168 169 /* 170 * Internally, variables are contained in four different contexts. 171 * 1) the environment. They cannot be changed. If an environment 172 * variable is appended to, the result is placed in the global 173 * context. 174 * 2) the global context. Variables set in the Makefile are located in 175 * the global context. 176 * 3) the command-line context. All variables set on the command line 177 * are placed in this context. They are UNALTERABLE once placed here. 178 * 4) the local context. Each target has associated with it a context 179 * list. On this list are located the structures describing such 180 * local variables as $(@) and $(*) 181 * The four contexts are searched in the reverse order from which they are 182 * listed (but see checkEnvFirst). 183 */ 184 GNode *VAR_INTERNAL; /* variables from make itself */ 185 GNode *VAR_GLOBAL; /* variables from the makefile */ 186 GNode *VAR_CMD; /* variables defined on the command-line */ 187 188 typedef enum { 189 FIND_CMD = 0x01, /* look in VAR_CMD when searching */ 190 FIND_GLOBAL = 0x02, /* look in VAR_GLOBAL as well */ 191 FIND_ENV = 0x04 /* look in the environment also */ 192 } VarFindFlags; 193 194 typedef enum { 195 /* The variable's value is currently being used by Var_Parse or Var_Subst. 196 * This marker is used to avoid endless recursion. */ 197 VAR_IN_USE = 0x01, 198 /* The variable comes from the environment. 199 * These variables are not registered in any GNode, therefore they must 200 * be freed as soon as they are not used anymore. */ 201 VAR_FROM_ENV = 0x02, 202 /* The variable is a junk variable that should be destroyed when done with 203 * it. Used by Var_Parse for undefined, modified variables. */ 204 VAR_JUNK = 0x04, 205 /* Variable is VAR_JUNK, but we found a use for it in some modifier and 206 * the value is therefore valid. */ 207 VAR_KEEP = 0x08, 208 /* The variable is exported to the environment, to be used by child 209 * processes. */ 210 VAR_EXPORTED = 0x10, 211 /* At the point where this variable was exported, it contained an 212 * unresolved reference to another variable. Before any child process is 213 * started, it needs to be exported again, in the hope that the referenced 214 * variable can then be resolved. */ 215 VAR_REEXPORT = 0x20, 216 /* The variable came from command line. */ 217 VAR_FROM_CMD = 0x40, 218 VAR_READONLY = 0x80 219 } VarFlags; 220 221 ENUM_FLAGS_RTTI_8(VarFlags, 222 VAR_IN_USE, VAR_FROM_ENV, VAR_JUNK, VAR_KEEP, 223 VAR_EXPORTED, VAR_REEXPORT, VAR_FROM_CMD, VAR_READONLY); 224 225 typedef struct Var { 226 char *name; /* the variable's name; it is allocated for 227 * environment variables and aliased to the 228 * Hash_Entry name for all other variables, 229 * and thus must not be modified */ 230 Buffer val; /* its value */ 231 VarFlags flags; /* miscellaneous status flags */ 232 } Var; 233 234 /* 235 * Exporting vars is expensive so skip it if we can 236 */ 237 typedef enum { 238 VAR_EXPORTED_NONE, 239 VAR_EXPORTED_YES, 240 VAR_EXPORTED_ALL 241 } VarExportedMode; 242 243 static VarExportedMode var_exportedVars = VAR_EXPORTED_NONE; 244 245 typedef enum { 246 /* 247 * We pass this to Var_Export when doing the initial export 248 * or after updating an exported var. 249 */ 250 VAR_EXPORT_PARENT = 0x01, 251 /* 252 * We pass this to Var_Export1 to tell it to leave the value alone. 253 */ 254 VAR_EXPORT_LITERAL = 0x02 255 } VarExportFlags; 256 257 /* Flags for pattern matching in the :S and :C modifiers */ 258 typedef enum { 259 VARP_SUB_GLOBAL = 0x01, /* Apply substitution globally */ 260 VARP_SUB_ONE = 0x02, /* Apply substitution to one word */ 261 VARP_ANCHOR_START = 0x04, /* Match at start of word */ 262 VARP_ANCHOR_END = 0x08 /* Match at end of word */ 263 } VarPatternFlags; 264 265 /*- 266 *----------------------------------------------------------------------- 267 * VarFind -- 268 * Find the given variable in the given context and any other contexts 269 * indicated. 270 * 271 * Input: 272 * name name to find 273 * ctxt context in which to find it 274 * flags FIND_GLOBAL look in VAR_GLOBAL as well 275 * FIND_CMD look in VAR_CMD as well 276 * FIND_ENV look in the environment as well 277 * 278 * Results: 279 * A pointer to the structure describing the desired variable or 280 * NULL if the variable does not exist. 281 *----------------------------------------------------------------------- 282 */ 283 static Var * 284 VarFind(const char *name, GNode *ctxt, VarFindFlags flags) 285 { 286 Hash_Entry *var; 287 288 /* 289 * If the variable name begins with a '.', it could very well be one of 290 * the local ones. We check the name against all the local variables 291 * and substitute the short version in for 'name' if it matches one of 292 * them. 293 */ 294 if (*name == '.' && ch_isupper(name[1])) { 295 switch (name[1]) { 296 case 'A': 297 if (strcmp(name, ".ALLSRC") == 0) 298 name = ALLSRC; 299 if (strcmp(name, ".ARCHIVE") == 0) 300 name = ARCHIVE; 301 break; 302 case 'I': 303 if (strcmp(name, ".IMPSRC") == 0) 304 name = IMPSRC; 305 break; 306 case 'M': 307 if (strcmp(name, ".MEMBER") == 0) 308 name = MEMBER; 309 break; 310 case 'O': 311 if (strcmp(name, ".OODATE") == 0) 312 name = OODATE; 313 break; 314 case 'P': 315 if (strcmp(name, ".PREFIX") == 0) 316 name = PREFIX; 317 break; 318 case 'S': 319 if (strcmp(name, ".SHELL") == 0 ) { 320 if (!shellPath) 321 Shell_Init(); 322 } 323 break; 324 case 'T': 325 if (strcmp(name, ".TARGET") == 0) 326 name = TARGET; 327 break; 328 } 329 } 330 331 #ifdef notyet 332 /* for compatibility with gmake */ 333 if (name[0] == '^' && name[1] == '\0') 334 name = ALLSRC; 335 #endif 336 337 /* 338 * First look for the variable in the given context. If it's not there, 339 * look for it in VAR_CMD, VAR_GLOBAL and the environment, in that order, 340 * depending on the FIND_* flags in 'flags' 341 */ 342 var = Hash_FindEntry(&ctxt->context, name); 343 344 if (var == NULL && (flags & FIND_CMD) && ctxt != VAR_CMD) 345 var = Hash_FindEntry(&VAR_CMD->context, name); 346 347 if (!checkEnvFirst && var == NULL && (flags & FIND_GLOBAL) && 348 ctxt != VAR_GLOBAL) 349 { 350 var = Hash_FindEntry(&VAR_GLOBAL->context, name); 351 if (var == NULL && ctxt != VAR_INTERNAL) { 352 /* VAR_INTERNAL is subordinate to VAR_GLOBAL */ 353 var = Hash_FindEntry(&VAR_INTERNAL->context, name); 354 } 355 } 356 357 if (var == NULL && (flags & FIND_ENV)) { 358 char *env; 359 360 if ((env = getenv(name)) != NULL) { 361 Var *v = bmake_malloc(sizeof(Var)); 362 size_t len; 363 v->name = bmake_strdup(name); 364 365 len = strlen(env); 366 Buf_Init(&v->val, len + 1); 367 Buf_AddBytes(&v->val, env, len); 368 369 v->flags = VAR_FROM_ENV; 370 return v; 371 } 372 373 if (checkEnvFirst && (flags & FIND_GLOBAL) && ctxt != VAR_GLOBAL) { 374 var = Hash_FindEntry(&VAR_GLOBAL->context, name); 375 if (var == NULL && ctxt != VAR_INTERNAL) 376 var = Hash_FindEntry(&VAR_INTERNAL->context, name); 377 if (var == NULL) 378 return NULL; 379 else 380 return (Var *)Hash_GetValue(var); 381 } 382 383 return NULL; 384 } 385 386 if (var == NULL) 387 return NULL; 388 else 389 return (Var *)Hash_GetValue(var); 390 } 391 392 /*- 393 *----------------------------------------------------------------------- 394 * VarFreeEnv -- 395 * If the variable is an environment variable, free it 396 * 397 * Input: 398 * v the variable 399 * destroy true if the value buffer should be destroyed. 400 * 401 * Results: 402 * TRUE if it is an environment variable, FALSE otherwise. 403 *----------------------------------------------------------------------- 404 */ 405 static Boolean 406 VarFreeEnv(Var *v, Boolean destroy) 407 { 408 if (!(v->flags & VAR_FROM_ENV)) 409 return FALSE; 410 free(v->name); 411 Buf_Destroy(&v->val, destroy); 412 free(v); 413 return TRUE; 414 } 415 416 /* Add a new variable of the given name and value to the given context. 417 * The name and val arguments are duplicated so they may safely be freed. */ 418 static void 419 VarAdd(const char *name, const char *val, GNode *ctxt, VarSet_Flags flags) 420 { 421 Var *v = bmake_malloc(sizeof(Var)); 422 size_t len = strlen(val); 423 Hash_Entry *he; 424 425 Buf_Init(&v->val, len + 1); 426 Buf_AddBytes(&v->val, val, len); 427 428 v->flags = 0; 429 if (flags & VAR_SET_READONLY) 430 v->flags |= VAR_READONLY; 431 432 he = Hash_CreateEntry(&ctxt->context, name, NULL); 433 Hash_SetValue(he, v); 434 v->name = he->name; 435 VAR_DEBUG_IF(!(ctxt->flags & INTERNAL), 436 "%s:%s = %s\n", ctxt->name, name, val); 437 } 438 439 /* Remove a variable from a context, freeing the Var structure as well. */ 440 void 441 Var_Delete(const char *name, GNode *ctxt) 442 { 443 char *name_freeIt = NULL; 444 Hash_Entry *he; 445 446 if (strchr(name, '$') != NULL) 447 name = name_freeIt = Var_Subst(name, VAR_GLOBAL, VARE_WANTRES); 448 he = Hash_FindEntry(&ctxt->context, name); 449 VAR_DEBUG("%s:delete %s%s\n", 450 ctxt->name, name, he != NULL ? "" : " (not found)"); 451 free(name_freeIt); 452 453 if (he != NULL) { 454 Var *v = (Var *)Hash_GetValue(he); 455 if (v->flags & VAR_EXPORTED) 456 unsetenv(v->name); 457 if (strcmp(v->name, MAKE_EXPORTED) == 0) 458 var_exportedVars = VAR_EXPORTED_NONE; 459 if (v->name != he->name) 460 free(v->name); 461 Hash_DeleteEntry(&ctxt->context, he); 462 Buf_Destroy(&v->val, TRUE); 463 free(v); 464 } 465 } 466 467 468 /* 469 * Export a single variable. 470 * We ignore make internal variables (those which start with '.'). 471 * Also we jump through some hoops to avoid calling setenv 472 * more than necessary since it can leak. 473 * We only manipulate flags of vars if 'parent' is set. 474 */ 475 static Boolean 476 Var_Export1(const char *name, VarExportFlags flags) 477 { 478 VarExportFlags parent = flags & VAR_EXPORT_PARENT; 479 Var *v; 480 char *val; 481 482 if (name[0] == '.') 483 return FALSE; /* skip internals */ 484 if (name[1] == '\0') { 485 /* 486 * A single char. 487 * If it is one of the vars that should only appear in 488 * local context, skip it, else we can get Var_Subst 489 * into a loop. 490 */ 491 switch (name[0]) { 492 case '@': 493 case '%': 494 case '*': 495 case '!': 496 return FALSE; 497 } 498 } 499 500 v = VarFind(name, VAR_GLOBAL, 0); 501 if (v == NULL) 502 return FALSE; 503 504 if (!parent && (v->flags & VAR_EXPORTED) && !(v->flags & VAR_REEXPORT)) 505 return FALSE; /* nothing to do */ 506 507 val = Buf_GetAll(&v->val, NULL); 508 if (!(flags & VAR_EXPORT_LITERAL) && strchr(val, '$') != NULL) { 509 char *expr; 510 511 if (parent) { 512 /* 513 * Flag this as something we need to re-export. 514 * No point actually exporting it now though, 515 * the child can do it at the last minute. 516 */ 517 v->flags |= VAR_EXPORTED | VAR_REEXPORT; 518 return TRUE; 519 } 520 if (v->flags & VAR_IN_USE) { 521 /* 522 * We recursed while exporting in a child. 523 * This isn't going to end well, just skip it. 524 */ 525 return FALSE; 526 } 527 528 expr = str_concat3("${", name, "}"); 529 val = Var_Subst(expr, VAR_GLOBAL, VARE_WANTRES); 530 setenv(name, val, 1); 531 free(val); 532 free(expr); 533 } else { 534 if (parent) 535 v->flags &= ~(unsigned)VAR_REEXPORT; /* once will do */ 536 if (parent || !(v->flags & VAR_EXPORTED)) 537 setenv(name, val, 1); 538 } 539 /* 540 * This is so Var_Set knows to call Var_Export again... 541 */ 542 if (parent) { 543 v->flags |= VAR_EXPORTED; 544 } 545 return TRUE; 546 } 547 548 static void 549 Var_ExportVars_callback(void *entry, void *unused MAKE_ATTR_UNUSED) 550 { 551 Var *var = entry; 552 Var_Export1(var->name, 0); 553 } 554 555 /* 556 * This gets called from our children. 557 */ 558 void 559 Var_ExportVars(void) 560 { 561 char *val; 562 563 /* 564 * Several make's support this sort of mechanism for tracking 565 * recursion - but each uses a different name. 566 * We allow the makefiles to update MAKELEVEL and ensure 567 * children see a correctly incremented value. 568 */ 569 char tmp[BUFSIZ]; 570 snprintf(tmp, sizeof(tmp), "%d", makelevel + 1); 571 setenv(MAKE_LEVEL_ENV, tmp, 1); 572 573 if (var_exportedVars == VAR_EXPORTED_NONE) 574 return; 575 576 if (var_exportedVars == VAR_EXPORTED_ALL) { 577 /* Ouch! This is crazy... */ 578 Hash_ForEach(&VAR_GLOBAL->context, Var_ExportVars_callback, NULL); 579 return; 580 } 581 582 val = Var_Subst("${" MAKE_EXPORTED ":O:u}", VAR_GLOBAL, VARE_WANTRES); 583 if (*val) { 584 Words words = Str_Words(val, FALSE); 585 size_t i; 586 587 for (i = 0; i < words.len; i++) 588 Var_Export1(words.words[i], 0); 589 Words_Free(words); 590 } 591 free(val); 592 } 593 594 /* 595 * This is called when .export is seen or .MAKE.EXPORTED is modified. 596 * 597 * It is also called when any exported variable is modified. 598 * XXX: Is it really? 599 * 600 * str has the format "[-env|-literal] varname...". 601 */ 602 void 603 Var_Export(const char *str, Boolean isExport) 604 { 605 VarExportFlags flags; 606 char *val; 607 608 if (isExport && str[0] == '\0') { 609 var_exportedVars = VAR_EXPORTED_ALL; /* use with caution! */ 610 return; 611 } 612 613 flags = 0; 614 if (strncmp(str, "-env", 4) == 0) { 615 str += 4; 616 } else if (strncmp(str, "-literal", 8) == 0) { 617 str += 8; 618 flags |= VAR_EXPORT_LITERAL; 619 } else { 620 flags |= VAR_EXPORT_PARENT; 621 } 622 623 val = Var_Subst(str, VAR_GLOBAL, VARE_WANTRES); 624 if (val[0] != '\0') { 625 Words words = Str_Words(val, FALSE); 626 627 size_t i; 628 for (i = 0; i < words.len; i++) { 629 const char *name = words.words[i]; 630 if (Var_Export1(name, flags)) { 631 if (var_exportedVars != VAR_EXPORTED_ALL) 632 var_exportedVars = VAR_EXPORTED_YES; 633 if (isExport && (flags & VAR_EXPORT_PARENT)) { 634 Var_Append(MAKE_EXPORTED, name, VAR_GLOBAL); 635 } 636 } 637 } 638 Words_Free(words); 639 } 640 free(val); 641 } 642 643 644 extern char **environ; 645 646 /* 647 * This is called when .unexport[-env] is seen. 648 * 649 * str must have the form "unexport[-env] varname...". 650 */ 651 void 652 Var_UnExport(const char *str) 653 { 654 const char *varnames; 655 char *varnames_freeIt; 656 Boolean unexport_env; 657 658 varnames = NULL; 659 varnames_freeIt = NULL; 660 661 str += strlen("unexport"); 662 unexport_env = strncmp(str, "-env", 4) == 0; 663 if (unexport_env) { 664 const char *cp; 665 char **newenv; 666 667 cp = getenv(MAKE_LEVEL_ENV); /* we should preserve this */ 668 if (environ == savedEnv) { 669 /* we have been here before! */ 670 newenv = bmake_realloc(environ, 2 * sizeof(char *)); 671 } else { 672 if (savedEnv) { 673 free(savedEnv); 674 savedEnv = NULL; 675 } 676 newenv = bmake_malloc(2 * sizeof(char *)); 677 } 678 679 /* Note: we cannot safely free() the original environ. */ 680 environ = savedEnv = newenv; 681 newenv[0] = NULL; 682 newenv[1] = NULL; 683 if (cp && *cp) 684 setenv(MAKE_LEVEL_ENV, cp, 1); 685 } else { 686 for (; ch_isspace(*str); str++) 687 continue; 688 if (str[0] != '\0') 689 varnames = str; 690 } 691 692 if (varnames == NULL) { 693 /* Using .MAKE.EXPORTED */ 694 varnames = varnames_freeIt = Var_Subst("${" MAKE_EXPORTED ":O:u}", 695 VAR_GLOBAL, VARE_WANTRES); 696 } 697 698 { 699 Var *v; 700 size_t i; 701 702 Words words = Str_Words(varnames, FALSE); 703 for (i = 0; i < words.len; i++) { 704 const char *varname = words.words[i]; 705 v = VarFind(varname, VAR_GLOBAL, 0); 706 if (v == NULL) { 707 VAR_DEBUG("Not unexporting \"%s\" (not found)\n", varname); 708 continue; 709 } 710 711 VAR_DEBUG("Unexporting \"%s\"\n", varname); 712 if (!unexport_env && (v->flags & VAR_EXPORTED) && 713 !(v->flags & VAR_REEXPORT)) 714 unsetenv(v->name); 715 v->flags &= ~(unsigned)(VAR_EXPORTED | VAR_REEXPORT); 716 717 /* 718 * If we are unexporting a list, 719 * remove each one from .MAKE.EXPORTED. 720 * If we are removing them all, 721 * just delete .MAKE.EXPORTED below. 722 */ 723 if (varnames == str) { 724 char *expr = str_concat3("${" MAKE_EXPORTED ":N", v->name, "}"); 725 char *cp = Var_Subst(expr, VAR_GLOBAL, VARE_WANTRES); 726 Var_Set(MAKE_EXPORTED, cp, VAR_GLOBAL); 727 free(cp); 728 free(expr); 729 } 730 } 731 Words_Free(words); 732 if (varnames != str) { 733 Var_Delete(MAKE_EXPORTED, VAR_GLOBAL); 734 free(varnames_freeIt); 735 } 736 } 737 } 738 739 /* See Var_Set for documentation. */ 740 void 741 Var_Set_with_flags(const char *name, const char *val, GNode *ctxt, 742 VarSet_Flags flags) 743 { 744 const char *unexpanded_name = name; 745 char *name_freeIt = NULL; 746 Var *v; 747 748 assert(val != NULL); 749 750 /* 751 * We only look for a variable in the given context since anything set 752 * here will override anything in a lower context, so there's not much 753 * point in searching them all just to save a bit of memory... 754 */ 755 if (strchr(name, '$') != NULL) 756 name = name_freeIt = Var_Subst(name, ctxt, VARE_WANTRES); 757 758 if (name[0] == '\0') { 759 VAR_DEBUG("Var_Set(\"%s\", \"%s\", ...) " 760 "name expands to empty string - ignored\n", 761 unexpanded_name, val); 762 free(name_freeIt); 763 return; 764 } 765 766 if (ctxt == VAR_GLOBAL) { 767 v = VarFind(name, VAR_CMD, 0); 768 if (v != NULL) { 769 if (v->flags & VAR_FROM_CMD) { 770 VAR_DEBUG("%s:%s = %s ignored!\n", ctxt->name, name, val); 771 goto out; 772 } 773 VarFreeEnv(v, TRUE); 774 } 775 } 776 777 v = VarFind(name, ctxt, 0); 778 if (v == NULL) { 779 if (ctxt == VAR_CMD && !(flags & VAR_NO_EXPORT)) { 780 /* 781 * This var would normally prevent the same name being added 782 * to VAR_GLOBAL, so delete it from there if needed. 783 * Otherwise -V name may show the wrong value. 784 */ 785 Var_Delete(name, VAR_GLOBAL); 786 } 787 VarAdd(name, val, ctxt, flags); 788 } else { 789 if ((v->flags & VAR_READONLY) && !(flags & VAR_SET_READONLY)) { 790 VAR_DEBUG("%s:%s = %s ignored (read-only)\n", 791 ctxt->name, name, val); 792 goto out; 793 } 794 Buf_Empty(&v->val); 795 if (val) 796 Buf_AddStr(&v->val, val); 797 798 VAR_DEBUG("%s:%s = %s\n", ctxt->name, name, val); 799 if (v->flags & VAR_EXPORTED) { 800 Var_Export1(name, VAR_EXPORT_PARENT); 801 } 802 } 803 /* 804 * Any variables given on the command line are automatically exported 805 * to the environment (as per POSIX standard) 806 * Other than internals. 807 */ 808 if (ctxt == VAR_CMD && !(flags & VAR_NO_EXPORT) && name[0] != '.') { 809 if (v == NULL) { 810 /* we just added it */ 811 v = VarFind(name, ctxt, 0); 812 } 813 if (v != NULL) 814 v->flags |= VAR_FROM_CMD; 815 /* 816 * If requested, don't export these in the environment 817 * individually. We still put them in MAKEOVERRIDES so 818 * that the command-line settings continue to override 819 * Makefile settings. 820 */ 821 if (!varNoExportEnv) 822 setenv(name, val ? val : "", 1); 823 824 Var_Append(MAKEOVERRIDES, name, VAR_GLOBAL); 825 } 826 if (name[0] == '.' && strcmp(name, SAVE_DOLLARS) == 0) 827 save_dollars = s2Boolean(val, save_dollars); 828 829 out: 830 free(name_freeIt); 831 if (v != NULL) 832 VarFreeEnv(v, TRUE); 833 } 834 835 /*- 836 *----------------------------------------------------------------------- 837 * Var_Set -- 838 * Set the variable name to the value val in the given context. 839 * 840 * If the variable doesn't yet exist, it is created. 841 * Otherwise the new value overwrites and replaces the old value. 842 * 843 * Input: 844 * name name of variable to set 845 * val value to give to the variable 846 * ctxt context in which to set it 847 * 848 * Notes: 849 * The variable is searched for only in its context before being 850 * created in that context. I.e. if the context is VAR_GLOBAL, 851 * only VAR_GLOBAL->context is searched. Likewise if it is VAR_CMD, only 852 * VAR_CMD->context is searched. This is done to avoid the literally 853 * thousands of unnecessary strcmp's that used to be done to 854 * set, say, $(@) or $(<). 855 * If the context is VAR_GLOBAL though, we check if the variable 856 * was set in VAR_CMD from the command line and skip it if so. 857 *----------------------------------------------------------------------- 858 */ 859 void 860 Var_Set(const char *name, const char *val, GNode *ctxt) 861 { 862 Var_Set_with_flags(name, val, ctxt, 0); 863 } 864 865 /*- 866 *----------------------------------------------------------------------- 867 * Var_Append -- 868 * The variable of the given name has the given value appended to it in 869 * the given context. 870 * 871 * If the variable doesn't exist, it is created. Otherwise the strings 872 * are concatenated, with a space in between. 873 * 874 * Input: 875 * name name of variable to modify 876 * val string to append to it 877 * ctxt context in which this should occur 878 * 879 * Notes: 880 * Only if the variable is being sought in the global context is the 881 * environment searched. 882 * XXX: Knows its calling circumstances in that if called with ctxt 883 * an actual target, it will only search that context since only 884 * a local variable could be being appended to. This is actually 885 * a big win and must be tolerated. 886 *----------------------------------------------------------------------- 887 */ 888 void 889 Var_Append(const char *name, const char *val, GNode *ctxt) 890 { 891 char *name_freeIt = NULL; 892 Var *v; 893 894 assert(val != NULL); 895 896 if (strchr(name, '$') != NULL) { 897 const char *unexpanded_name = name; 898 name = name_freeIt = Var_Subst(name, ctxt, VARE_WANTRES); 899 if (name[0] == '\0') { 900 VAR_DEBUG("Var_Append(\"%s\", \"%s\", ...) " 901 "name expands to empty string - ignored\n", 902 unexpanded_name, val); 903 free(name_freeIt); 904 return; 905 } 906 } 907 908 v = VarFind(name, ctxt, ctxt == VAR_GLOBAL ? (FIND_CMD | FIND_ENV) : 0); 909 910 if (v == NULL) { 911 Var_Set(name, val, ctxt); 912 } else if (ctxt == VAR_CMD || !(v->flags & VAR_FROM_CMD)) { 913 Buf_AddByte(&v->val, ' '); 914 Buf_AddStr(&v->val, val); 915 916 VAR_DEBUG("%s:%s = %s\n", ctxt->name, name, 917 Buf_GetAll(&v->val, NULL)); 918 919 if (v->flags & VAR_FROM_ENV) { 920 Hash_Entry *h; 921 922 /* 923 * If the original variable came from the environment, we 924 * have to install it in the global context (we could place 925 * it in the environment, but then we should provide a way to 926 * export other variables...) 927 */ 928 v->flags &= ~(unsigned)VAR_FROM_ENV; 929 h = Hash_CreateEntry(&ctxt->context, name, NULL); 930 Hash_SetValue(h, v); 931 } 932 } 933 free(name_freeIt); 934 } 935 936 /* See if the given variable exists, in the given context or in other 937 * fallback contexts. 938 * 939 * Input: 940 * name Variable to find 941 * ctxt Context in which to start search 942 */ 943 Boolean 944 Var_Exists(const char *name, GNode *ctxt) 945 { 946 char *name_freeIt = NULL; 947 Var *v; 948 949 if (strchr(name, '$') != NULL) 950 name = name_freeIt = Var_Subst(name, ctxt, VARE_WANTRES); 951 952 v = VarFind(name, ctxt, FIND_CMD | FIND_GLOBAL | FIND_ENV); 953 free(name_freeIt); 954 if (v == NULL) 955 return FALSE; 956 957 (void)VarFreeEnv(v, TRUE); 958 return TRUE; 959 } 960 961 /*- 962 *----------------------------------------------------------------------- 963 * Var_Value -- 964 * Return the unexpanded value of the given variable in the given 965 * context, or the usual contexts. 966 * 967 * Input: 968 * name name to find 969 * ctxt context in which to search for it 970 * 971 * Results: 972 * The value if the variable exists, NULL if it doesn't. 973 * If the returned value is not NULL, the caller must free *freeIt 974 * as soon as the returned value is no longer needed. 975 *----------------------------------------------------------------------- 976 */ 977 const char * 978 Var_Value(const char *name, GNode *ctxt, char **freeIt) 979 { 980 Var *v = VarFind(name, ctxt, FIND_ENV | FIND_GLOBAL | FIND_CMD); 981 char *p; 982 983 *freeIt = NULL; 984 if (v == NULL) 985 return NULL; 986 987 p = Buf_GetAll(&v->val, NULL); 988 if (VarFreeEnv(v, FALSE)) 989 *freeIt = p; 990 return p; 991 } 992 993 994 /* SepBuf is a string being built from "words", interleaved with separators. */ 995 typedef struct { 996 Buffer buf; 997 Boolean needSep; 998 char sep; /* usually ' ', but see the :ts modifier */ 999 } SepBuf; 1000 1001 static void 1002 SepBuf_Init(SepBuf *buf, char sep) 1003 { 1004 Buf_Init(&buf->buf, 32 /* bytes */); 1005 buf->needSep = FALSE; 1006 buf->sep = sep; 1007 } 1008 1009 static void 1010 SepBuf_Sep(SepBuf *buf) 1011 { 1012 buf->needSep = TRUE; 1013 } 1014 1015 static void 1016 SepBuf_AddBytes(SepBuf *buf, const char *mem, size_t mem_size) 1017 { 1018 if (mem_size == 0) 1019 return; 1020 if (buf->needSep && buf->sep != '\0') { 1021 Buf_AddByte(&buf->buf, buf->sep); 1022 buf->needSep = FALSE; 1023 } 1024 Buf_AddBytes(&buf->buf, mem, mem_size); 1025 } 1026 1027 static void 1028 SepBuf_AddBytesBetween(SepBuf *buf, const char *start, const char *end) 1029 { 1030 SepBuf_AddBytes(buf, start, (size_t)(end - start)); 1031 } 1032 1033 static void 1034 SepBuf_AddStr(SepBuf *buf, const char *str) 1035 { 1036 SepBuf_AddBytes(buf, str, strlen(str)); 1037 } 1038 1039 static char * 1040 SepBuf_Destroy(SepBuf *buf, Boolean free_buf) 1041 { 1042 return Buf_Destroy(&buf->buf, free_buf); 1043 } 1044 1045 1046 /* This callback for ModifyWords gets a single word from an expression and 1047 * typically adds a modification of this word to the buffer. It may also do 1048 * nothing or add several words. */ 1049 typedef void (*ModifyWordsCallback)(const char *word, SepBuf *buf, void *data); 1050 1051 1052 /* Callback for ModifyWords to implement the :H modifier. 1053 * Add the dirname of the given word to the buffer. */ 1054 static void 1055 ModifyWord_Head(const char *word, SepBuf *buf, void *dummy MAKE_ATTR_UNUSED) 1056 { 1057 const char *slash = strrchr(word, '/'); 1058 if (slash != NULL) 1059 SepBuf_AddBytesBetween(buf, word, slash); 1060 else 1061 SepBuf_AddStr(buf, "."); 1062 } 1063 1064 /* Callback for ModifyWords to implement the :T modifier. 1065 * Add the basename of the given word to the buffer. */ 1066 static void 1067 ModifyWord_Tail(const char *word, SepBuf *buf, void *dummy MAKE_ATTR_UNUSED) 1068 { 1069 const char *slash = strrchr(word, '/'); 1070 const char *base = slash != NULL ? slash + 1 : word; 1071 SepBuf_AddStr(buf, base); 1072 } 1073 1074 /* Callback for ModifyWords to implement the :E modifier. 1075 * Add the filename suffix of the given word to the buffer, if it exists. */ 1076 static void 1077 ModifyWord_Suffix(const char *word, SepBuf *buf, void *dummy MAKE_ATTR_UNUSED) 1078 { 1079 const char *dot = strrchr(word, '.'); 1080 if (dot != NULL) 1081 SepBuf_AddStr(buf, dot + 1); 1082 } 1083 1084 /* Callback for ModifyWords to implement the :R modifier. 1085 * Add the basename of the given word to the buffer. */ 1086 static void 1087 ModifyWord_Root(const char *word, SepBuf *buf, void *dummy MAKE_ATTR_UNUSED) 1088 { 1089 const char *dot = strrchr(word, '.'); 1090 size_t len = dot != NULL ? (size_t)(dot - word) : strlen(word); 1091 SepBuf_AddBytes(buf, word, len); 1092 } 1093 1094 /* Callback for ModifyWords to implement the :M modifier. 1095 * Place the word in the buffer if it matches the given pattern. */ 1096 static void 1097 ModifyWord_Match(const char *word, SepBuf *buf, void *data) 1098 { 1099 const char *pattern = data; 1100 VAR_DEBUG("VarMatch [%s] [%s]\n", word, pattern); 1101 if (Str_Match(word, pattern)) 1102 SepBuf_AddStr(buf, word); 1103 } 1104 1105 /* Callback for ModifyWords to implement the :N modifier. 1106 * Place the word in the buffer if it doesn't match the given pattern. */ 1107 static void 1108 ModifyWord_NoMatch(const char *word, SepBuf *buf, void *data) 1109 { 1110 const char *pattern = data; 1111 if (!Str_Match(word, pattern)) 1112 SepBuf_AddStr(buf, word); 1113 } 1114 1115 #ifdef SYSVVARSUB 1116 /*- 1117 *----------------------------------------------------------------------- 1118 * Str_SYSVMatch -- 1119 * Check word against pattern for a match (% is wild), 1120 * 1121 * Input: 1122 * word Word to examine 1123 * pattern Pattern to examine against 1124 * 1125 * Results: 1126 * Returns the start of the match, or NULL. 1127 * *match_len returns the length of the match, if any. 1128 * *hasPercent returns whether the pattern contains a percent. 1129 *----------------------------------------------------------------------- 1130 */ 1131 static const char * 1132 Str_SYSVMatch(const char *word, const char *pattern, size_t *match_len, 1133 Boolean *hasPercent) 1134 { 1135 const char *p = pattern; 1136 const char *w = word; 1137 const char *percent; 1138 size_t w_len; 1139 size_t p_len; 1140 const char *w_tail; 1141 1142 *hasPercent = FALSE; 1143 if (*p == '\0') { /* ${VAR:=suffix} */ 1144 *match_len = strlen(w); /* Null pattern is the whole string */ 1145 return w; 1146 } 1147 1148 percent = strchr(p, '%'); 1149 if (percent != NULL) { /* ${VAR:...%...=...} */ 1150 *hasPercent = TRUE; 1151 if (*w == '\0') 1152 return NULL; /* empty word does not match pattern */ 1153 1154 /* check that the prefix matches */ 1155 for (; p != percent && *w != '\0' && *w == *p; w++, p++) 1156 continue; 1157 if (p != percent) 1158 return NULL; /* No match */ 1159 1160 p++; /* Skip the percent */ 1161 if (*p == '\0') { 1162 /* No more pattern, return the rest of the string */ 1163 *match_len = strlen(w); 1164 return w; 1165 } 1166 } 1167 1168 /* Test whether the tail matches */ 1169 w_len = strlen(w); 1170 p_len = strlen(p); 1171 if (w_len < p_len) 1172 return NULL; 1173 1174 w_tail = w + w_len - p_len; 1175 if (memcmp(p, w_tail, p_len) != 0) 1176 return NULL; 1177 1178 *match_len = (size_t)(w_tail - w); 1179 return w; 1180 } 1181 1182 typedef struct { 1183 GNode *ctx; 1184 const char *lhs; 1185 const char *rhs; 1186 } ModifyWord_SYSVSubstArgs; 1187 1188 /* Callback for ModifyWords to implement the :%.from=%.to modifier. */ 1189 static void 1190 ModifyWord_SYSVSubst(const char *word, SepBuf *buf, void *data) 1191 { 1192 const ModifyWord_SYSVSubstArgs *args = data; 1193 char *rhs_expanded; 1194 const char *rhs; 1195 const char *percent; 1196 1197 size_t match_len; 1198 Boolean lhsPercent; 1199 const char *match = Str_SYSVMatch(word, args->lhs, &match_len, &lhsPercent); 1200 if (match == NULL) { 1201 SepBuf_AddStr(buf, word); 1202 return; 1203 } 1204 1205 /* Append rhs to the buffer, substituting the first '%' with the 1206 * match, but only if the lhs had a '%' as well. */ 1207 1208 rhs_expanded = Var_Subst(args->rhs, args->ctx, VARE_WANTRES); 1209 1210 rhs = rhs_expanded; 1211 percent = strchr(rhs, '%'); 1212 1213 if (percent != NULL && lhsPercent) { 1214 /* Copy the prefix of the replacement pattern */ 1215 SepBuf_AddBytesBetween(buf, rhs, percent); 1216 rhs = percent + 1; 1217 } 1218 if (percent != NULL || !lhsPercent) 1219 SepBuf_AddBytes(buf, match, match_len); 1220 1221 /* Append the suffix of the replacement pattern */ 1222 SepBuf_AddStr(buf, rhs); 1223 1224 free(rhs_expanded); 1225 } 1226 #endif 1227 1228 1229 typedef struct { 1230 const char *lhs; 1231 size_t lhsLen; 1232 const char *rhs; 1233 size_t rhsLen; 1234 VarPatternFlags pflags; 1235 Boolean matched; 1236 } ModifyWord_SubstArgs; 1237 1238 /* Callback for ModifyWords to implement the :S,from,to, modifier. 1239 * Perform a string substitution on the given word. */ 1240 static void 1241 ModifyWord_Subst(const char *word, SepBuf *buf, void *data) 1242 { 1243 size_t wordLen = strlen(word); 1244 ModifyWord_SubstArgs *args = data; 1245 const char *match; 1246 1247 if ((args->pflags & VARP_SUB_ONE) && args->matched) 1248 goto nosub; 1249 1250 if (args->pflags & VARP_ANCHOR_START) { 1251 if (wordLen < args->lhsLen || 1252 memcmp(word, args->lhs, args->lhsLen) != 0) 1253 goto nosub; 1254 1255 if (args->pflags & VARP_ANCHOR_END) { 1256 if (wordLen != args->lhsLen) 1257 goto nosub; 1258 1259 /* :S,^whole$,replacement, */ 1260 SepBuf_AddBytes(buf, args->rhs, args->rhsLen); 1261 args->matched = TRUE; 1262 } else { 1263 /* :S,^prefix,replacement, */ 1264 SepBuf_AddBytes(buf, args->rhs, args->rhsLen); 1265 SepBuf_AddBytes(buf, word + args->lhsLen, wordLen - args->lhsLen); 1266 args->matched = TRUE; 1267 } 1268 return; 1269 } 1270 1271 if (args->pflags & VARP_ANCHOR_END) { 1272 const char *start; 1273 1274 if (wordLen < args->lhsLen) 1275 goto nosub; 1276 1277 start = word + (wordLen - args->lhsLen); 1278 if (memcmp(start, args->lhs, args->lhsLen) != 0) 1279 goto nosub; 1280 1281 /* :S,suffix$,replacement, */ 1282 SepBuf_AddBytesBetween(buf, word, start); 1283 SepBuf_AddBytes(buf, args->rhs, args->rhsLen); 1284 args->matched = TRUE; 1285 return; 1286 } 1287 1288 /* unanchored case, may match more than once */ 1289 while ((match = Str_FindSubstring(word, args->lhs)) != NULL) { 1290 SepBuf_AddBytesBetween(buf, word, match); 1291 SepBuf_AddBytes(buf, args->rhs, args->rhsLen); 1292 args->matched = TRUE; 1293 wordLen -= (size_t)(match - word) + args->lhsLen; 1294 word += (size_t)(match - word) + args->lhsLen; 1295 if (wordLen == 0 || !(args->pflags & VARP_SUB_GLOBAL)) 1296 break; 1297 } 1298 nosub: 1299 SepBuf_AddBytes(buf, word, wordLen); 1300 } 1301 1302 #ifndef NO_REGEX 1303 /* Print the error caused by a regcomp or regexec call. */ 1304 static void 1305 VarREError(int reerr, regex_t *pat, const char *str) 1306 { 1307 size_t errlen = regerror(reerr, pat, 0, 0); 1308 char *errbuf = bmake_malloc(errlen); 1309 regerror(reerr, pat, errbuf, errlen); 1310 Error("%s: %s", str, errbuf); 1311 free(errbuf); 1312 } 1313 1314 typedef struct { 1315 regex_t re; 1316 size_t nsub; 1317 char *replace; 1318 VarPatternFlags pflags; 1319 Boolean matched; 1320 } ModifyWord_SubstRegexArgs; 1321 1322 /* Callback for ModifyWords to implement the :C/from/to/ modifier. 1323 * Perform a regex substitution on the given word. */ 1324 static void 1325 ModifyWord_SubstRegex(const char *word, SepBuf *buf, void *data) 1326 { 1327 ModifyWord_SubstRegexArgs *args = data; 1328 int xrv; 1329 const char *wp = word; 1330 char *rp; 1331 int flags = 0; 1332 regmatch_t m[10]; 1333 1334 if ((args->pflags & VARP_SUB_ONE) && args->matched) 1335 goto nosub; 1336 1337 tryagain: 1338 xrv = regexec(&args->re, wp, args->nsub, m, flags); 1339 1340 switch (xrv) { 1341 case 0: 1342 args->matched = TRUE; 1343 SepBuf_AddBytes(buf, wp, (size_t)m[0].rm_so); 1344 1345 for (rp = args->replace; *rp; rp++) { 1346 if (*rp == '\\' && (rp[1] == '&' || rp[1] == '\\')) { 1347 SepBuf_AddBytes(buf, rp + 1, 1); 1348 rp++; 1349 continue; 1350 } 1351 1352 if (*rp == '&') { 1353 SepBuf_AddBytesBetween(buf, wp + m[0].rm_so, wp + m[0].rm_eo); 1354 continue; 1355 } 1356 1357 if (*rp != '\\' || !ch_isdigit(rp[1])) { 1358 SepBuf_AddBytes(buf, rp, 1); 1359 continue; 1360 } 1361 1362 { /* \0 to \9 backreference */ 1363 size_t n = (size_t)(rp[1] - '0'); 1364 rp++; 1365 1366 if (n >= args->nsub) { 1367 Error("No subexpression \\%zu", n); 1368 } else if (m[n].rm_so == -1 && m[n].rm_eo == -1) { 1369 Error("No match for subexpression \\%zu", n); 1370 } else { 1371 SepBuf_AddBytesBetween(buf, wp + m[n].rm_so, 1372 wp + m[n].rm_eo); 1373 } 1374 } 1375 } 1376 1377 wp += m[0].rm_eo; 1378 if (args->pflags & VARP_SUB_GLOBAL) { 1379 flags |= REG_NOTBOL; 1380 if (m[0].rm_so == 0 && m[0].rm_eo == 0) { 1381 SepBuf_AddBytes(buf, wp, 1); 1382 wp++; 1383 } 1384 if (*wp) 1385 goto tryagain; 1386 } 1387 if (*wp) { 1388 SepBuf_AddStr(buf, wp); 1389 } 1390 break; 1391 default: 1392 VarREError(xrv, &args->re, "Unexpected regex error"); 1393 /* fall through */ 1394 case REG_NOMATCH: 1395 nosub: 1396 SepBuf_AddStr(buf, wp); 1397 break; 1398 } 1399 } 1400 #endif 1401 1402 1403 typedef struct { 1404 GNode *ctx; 1405 char *tvar; /* name of temporary variable */ 1406 char *str; /* string to expand */ 1407 VarEvalFlags eflags; 1408 } ModifyWord_LoopArgs; 1409 1410 /* Callback for ModifyWords to implement the :@var@...@ modifier of ODE make. */ 1411 static void 1412 ModifyWord_Loop(const char *word, SepBuf *buf, void *data) 1413 { 1414 const ModifyWord_LoopArgs *args; 1415 char *s; 1416 1417 if (word[0] == '\0') 1418 return; 1419 1420 args = data; 1421 Var_Set_with_flags(args->tvar, word, args->ctx, VAR_NO_EXPORT); 1422 s = Var_Subst(args->str, args->ctx, args->eflags); 1423 1424 VAR_DEBUG("ModifyWord_Loop: in \"%s\", replace \"%s\" with \"%s\" " 1425 "to \"%s\"\n", 1426 word, args->tvar, args->str, s); 1427 1428 if (s[0] == '\n' || (buf->buf.count > 0 && 1429 buf->buf.buffer[buf->buf.count - 1] == '\n')) 1430 buf->needSep = FALSE; 1431 SepBuf_AddStr(buf, s); 1432 free(s); 1433 } 1434 1435 1436 /*- 1437 * Implements the :[first..last] modifier. 1438 * This is a special case of ModifyWords since we want to be able 1439 * to scan the list backwards if first > last. 1440 */ 1441 static char * 1442 VarSelectWords(char sep, Boolean oneBigWord, const char *str, int first, 1443 int last) 1444 { 1445 Words words; 1446 int start, end, step; 1447 int i; 1448 1449 SepBuf buf; 1450 SepBuf_Init(&buf, sep); 1451 1452 if (oneBigWord) { 1453 /* fake what Str_Words() would do if there were only one word */ 1454 words.len = 1; 1455 words.words = bmake_malloc((words.len + 1) * sizeof(char *)); 1456 words.freeIt = bmake_strdup(str); 1457 words.words[0] = words.freeIt; 1458 words.words[1] = NULL; 1459 } else { 1460 words = Str_Words(str, FALSE); 1461 } 1462 1463 /* 1464 * Now sanitize the given range. 1465 * If first or last are negative, convert them to the positive equivalents 1466 * (-1 gets converted to ac, -2 gets converted to (ac - 1), etc.). 1467 */ 1468 if (first < 0) 1469 first += (int)words.len + 1; 1470 if (last < 0) 1471 last += (int)words.len + 1; 1472 1473 /* 1474 * We avoid scanning more of the list than we need to. 1475 */ 1476 if (first > last) { 1477 start = MIN((int)words.len, first) - 1; 1478 end = MAX(0, last - 1); 1479 step = -1; 1480 } else { 1481 start = MAX(0, first - 1); 1482 end = MIN((int)words.len, last); 1483 step = 1; 1484 } 1485 1486 for (i = start; (step < 0) == (i >= end); i += step) { 1487 SepBuf_AddStr(&buf, words.words[i]); 1488 SepBuf_Sep(&buf); 1489 } 1490 1491 Words_Free(words); 1492 1493 return SepBuf_Destroy(&buf, FALSE); 1494 } 1495 1496 1497 /* Callback for ModifyWords to implement the :tA modifier. 1498 * Replace each word with the result of realpath() if successful. */ 1499 static void 1500 ModifyWord_Realpath(const char *word, SepBuf *buf, void *data MAKE_ATTR_UNUSED) 1501 { 1502 struct stat st; 1503 char rbuf[MAXPATHLEN]; 1504 1505 const char *rp = cached_realpath(word, rbuf); 1506 if (rp != NULL && *rp == '/' && stat(rp, &st) == 0) 1507 word = rp; 1508 1509 SepBuf_AddStr(buf, word); 1510 } 1511 1512 /*- 1513 *----------------------------------------------------------------------- 1514 * Modify each of the words of the passed string using the given function. 1515 * 1516 * Input: 1517 * str String whose words should be modified 1518 * modifyWord Function that modifies a single word 1519 * modifyWord_args Custom arguments for modifyWord 1520 * 1521 * Results: 1522 * A string of all the words modified appropriately. 1523 *----------------------------------------------------------------------- 1524 */ 1525 static char * 1526 ModifyWords(GNode *ctx, char sep, Boolean oneBigWord, const char *str, 1527 ModifyWordsCallback modifyWord, void *modifyWord_args) 1528 { 1529 SepBuf result; 1530 Words words; 1531 size_t i; 1532 1533 if (oneBigWord) { 1534 SepBuf_Init(&result, sep); 1535 modifyWord(str, &result, modifyWord_args); 1536 return SepBuf_Destroy(&result, FALSE); 1537 } 1538 1539 SepBuf_Init(&result, sep); 1540 1541 words = Str_Words(str, FALSE); 1542 1543 VAR_DEBUG("ModifyWords: split \"%s\" into %zu words\n", str, words.len); 1544 1545 for (i = 0; i < words.len; i++) { 1546 modifyWord(words.words[i], &result, modifyWord_args); 1547 if (result.buf.count > 0) 1548 SepBuf_Sep(&result); 1549 } 1550 1551 Words_Free(words); 1552 1553 return SepBuf_Destroy(&result, FALSE); 1554 } 1555 1556 1557 static char * 1558 Words_JoinFree(Words words) 1559 { 1560 Buffer buf; 1561 size_t i; 1562 1563 Buf_Init(&buf, 0); 1564 1565 for (i = 0; i < words.len; i++) { 1566 if (i != 0) 1567 Buf_AddByte(&buf, ' '); /* XXX: st->sep, for consistency */ 1568 Buf_AddStr(&buf, words.words[i]); 1569 } 1570 1571 Words_Free(words); 1572 1573 return Buf_Destroy(&buf, FALSE); 1574 } 1575 1576 /* Remove adjacent duplicate words. */ 1577 static char * 1578 VarUniq(const char *str) 1579 { 1580 Words words = Str_Words(str, FALSE); 1581 1582 if (words.len > 1) { 1583 size_t i, j; 1584 for (j = 0, i = 1; i < words.len; i++) 1585 if (strcmp(words.words[i], words.words[j]) != 0 && (++j != i)) 1586 words.words[j] = words.words[i]; 1587 words.len = j + 1; 1588 } 1589 1590 return Words_JoinFree(words); 1591 } 1592 1593 1594 /*- 1595 * Parse a part of a modifier such as the "from" and "to" in :S/from/to/ 1596 * or the "var" or "replacement" in :@var@replacement+${var}@, up to and 1597 * including the next unescaped delimiter. The delimiter, as well as the 1598 * backslash or the dollar, can be escaped with a backslash. 1599 * 1600 * Return the parsed (and possibly expanded) string, or NULL if no delimiter 1601 * was found. On successful return, the parsing position pp points right 1602 * after the delimiter. The delimiter is not included in the returned 1603 * value though. 1604 */ 1605 static char * 1606 ParseModifierPart( 1607 const char **pp, /* The parsing position, updated upon return */ 1608 int delim, /* Parsing stops at this delimiter */ 1609 VarEvalFlags eflags, /* Flags for evaluating nested variables; 1610 * if VARE_WANTRES is not set, the text is 1611 * only parsed */ 1612 GNode *ctxt, /* For looking up nested variables */ 1613 size_t *out_length, /* Optionally stores the length of the returned 1614 * string, just to save another strlen call. */ 1615 VarPatternFlags *out_pflags,/* For the first part of the :S modifier, 1616 * sets the VARP_ANCHOR_END flag if the last 1617 * character of the pattern is a $. */ 1618 ModifyWord_SubstArgs *subst /* For the second part of the :S modifier, 1619 * allow ampersands to be escaped and replace 1620 * unescaped ampersands with subst->lhs. */ 1621 ) { 1622 Buffer buf; 1623 const char *p; 1624 char *rstr; 1625 1626 Buf_Init(&buf, 0); 1627 1628 /* 1629 * Skim through until the matching delimiter is found; 1630 * pick up variable substitutions on the way. Also allow 1631 * backslashes to quote the delimiter, $, and \, but don't 1632 * touch other backslashes. 1633 */ 1634 p = *pp; 1635 while (*p != '\0' && *p != delim) { 1636 const char *varstart; 1637 1638 Boolean is_escaped = p[0] == '\\' && ( 1639 p[1] == delim || p[1] == '\\' || p[1] == '$' || 1640 (p[1] == '&' && subst != NULL)); 1641 if (is_escaped) { 1642 Buf_AddByte(&buf, p[1]); 1643 p += 2; 1644 continue; 1645 } 1646 1647 if (*p != '$') { /* Unescaped, simple text */ 1648 if (subst != NULL && *p == '&') 1649 Buf_AddBytes(&buf, subst->lhs, subst->lhsLen); 1650 else 1651 Buf_AddByte(&buf, *p); 1652 p++; 1653 continue; 1654 } 1655 1656 if (p[1] == delim) { /* Unescaped $ at end of pattern */ 1657 if (out_pflags != NULL) 1658 *out_pflags |= VARP_ANCHOR_END; 1659 else 1660 Buf_AddByte(&buf, *p); 1661 p++; 1662 continue; 1663 } 1664 1665 if (eflags & VARE_WANTRES) { /* Nested variable, evaluated */ 1666 const char *nested_p = p; 1667 const char *nested_val; 1668 void *nested_val_freeIt; 1669 VarEvalFlags nested_eflags = eflags & ~(unsigned)VARE_ASSIGN; 1670 1671 (void)Var_Parse(&nested_p, ctxt, nested_eflags, 1672 &nested_val, &nested_val_freeIt); 1673 /* TODO: handle errors */ 1674 Buf_AddStr(&buf, nested_val); 1675 free(nested_val_freeIt); 1676 p += nested_p - p; 1677 continue; 1678 } 1679 1680 /* XXX: This whole block is very similar to Var_Parse without 1681 * VARE_WANTRES. There may be subtle edge cases though that are 1682 * not yet covered in the unit tests and that are parsed differently, 1683 * depending on whether they are evaluated or not. 1684 * 1685 * This subtle difference is not documented in the manual page, 1686 * neither is the difference between parsing :D and :M documented. 1687 * No code should ever depend on these details, but who knows. */ 1688 1689 varstart = p; /* Nested variable, only parsed */ 1690 if (p[1] == '(' || p[1] == '{') { 1691 /* 1692 * Find the end of this variable reference 1693 * and suck it in without further ado. 1694 * It will be interpreted later. 1695 */ 1696 int have = p[1]; 1697 int want = have == '(' ? ')' : '}'; 1698 int depth = 1; 1699 1700 for (p += 2; *p != '\0' && depth > 0; p++) { 1701 if (p[-1] != '\\') { 1702 if (*p == have) 1703 depth++; 1704 if (*p == want) 1705 depth--; 1706 } 1707 } 1708 Buf_AddBytesBetween(&buf, varstart, p); 1709 } else { 1710 Buf_AddByte(&buf, *varstart); 1711 p++; 1712 } 1713 } 1714 1715 if (*p != delim) { 1716 *pp = p; 1717 return NULL; 1718 } 1719 1720 *pp = ++p; 1721 if (out_length != NULL) 1722 *out_length = Buf_Size(&buf); 1723 1724 rstr = Buf_Destroy(&buf, FALSE); 1725 VAR_DEBUG("Modifier part: \"%s\"\n", rstr); 1726 return rstr; 1727 } 1728 1729 /* Quote shell meta-characters and space characters in the string. 1730 * If quoteDollar is set, also quote and double any '$' characters. */ 1731 static char * 1732 VarQuote(const char *str, Boolean quoteDollar) 1733 { 1734 char *res; 1735 Buffer buf; 1736 Buf_Init(&buf, 0); 1737 1738 for (; *str != '\0'; str++) { 1739 if (*str == '\n') { 1740 const char *newline = Shell_GetNewline(); 1741 if (newline == NULL) 1742 newline = "\\\n"; 1743 Buf_AddStr(&buf, newline); 1744 continue; 1745 } 1746 if (ch_isspace(*str) || ismeta((unsigned char)*str)) 1747 Buf_AddByte(&buf, '\\'); 1748 Buf_AddByte(&buf, *str); 1749 if (quoteDollar && *str == '$') 1750 Buf_AddStr(&buf, "\\$"); 1751 } 1752 1753 res = Buf_Destroy(&buf, FALSE); 1754 VAR_DEBUG("QuoteMeta: [%s]\n", res); 1755 return res; 1756 } 1757 1758 /* Compute the 32-bit hash of the given string, using the MurmurHash3 1759 * algorithm. Output is encoded as 8 hex digits, in Little Endian order. */ 1760 static char * 1761 VarHash(const char *str) 1762 { 1763 static const char hexdigits[16] = "0123456789abcdef"; 1764 const unsigned char *ustr = (const unsigned char *)str; 1765 1766 uint32_t h = 0x971e137bU; 1767 uint32_t c1 = 0x95543787U; 1768 uint32_t c2 = 0x2ad7eb25U; 1769 size_t len2 = strlen(str); 1770 1771 char *buf; 1772 size_t i; 1773 1774 size_t len; 1775 for (len = len2; len; ) { 1776 uint32_t k = 0; 1777 switch (len) { 1778 default: 1779 k = ((uint32_t)ustr[3] << 24) | 1780 ((uint32_t)ustr[2] << 16) | 1781 ((uint32_t)ustr[1] << 8) | 1782 (uint32_t)ustr[0]; 1783 len -= 4; 1784 ustr += 4; 1785 break; 1786 case 3: 1787 k |= (uint32_t)ustr[2] << 16; 1788 /* FALLTHROUGH */ 1789 case 2: 1790 k |= (uint32_t)ustr[1] << 8; 1791 /* FALLTHROUGH */ 1792 case 1: 1793 k |= (uint32_t)ustr[0]; 1794 len = 0; 1795 } 1796 c1 = c1 * 5 + 0x7b7d159cU; 1797 c2 = c2 * 5 + 0x6bce6396U; 1798 k *= c1; 1799 k = (k << 11) ^ (k >> 21); 1800 k *= c2; 1801 h = (h << 13) ^ (h >> 19); 1802 h = h * 5 + 0x52dce729U; 1803 h ^= k; 1804 } 1805 h ^= (uint32_t)len2; 1806 h *= 0x85ebca6b; 1807 h ^= h >> 13; 1808 h *= 0xc2b2ae35; 1809 h ^= h >> 16; 1810 1811 buf = bmake_malloc(9); 1812 for (i = 0; i < 8; i++) { 1813 buf[i] = hexdigits[h & 0x0f]; 1814 h >>= 4; 1815 } 1816 buf[8] = '\0'; 1817 return buf; 1818 } 1819 1820 static char * 1821 VarStrftime(const char *fmt, Boolean zulu, time_t tim) 1822 { 1823 char buf[BUFSIZ]; 1824 1825 if (!tim) 1826 time(&tim); 1827 if (!*fmt) 1828 fmt = "%c"; 1829 strftime(buf, sizeof(buf), fmt, zulu ? gmtime(&tim) : localtime(&tim)); 1830 1831 buf[sizeof(buf) - 1] = '\0'; 1832 return bmake_strdup(buf); 1833 } 1834 1835 /* The ApplyModifier functions all work in the same way. They get the 1836 * current parsing position (pp) and parse the modifier from there. The 1837 * modifier typically lasts until the next ':', or a closing '}' or ')' 1838 * (taken from st->endc), or the end of the string (parse error). 1839 * 1840 * The high-level behavior of these functions is: 1841 * 1842 * 1. parse the modifier 1843 * 2. evaluate the modifier 1844 * 3. housekeeping 1845 * 1846 * Parsing the modifier 1847 * 1848 * If parsing succeeds, the parsing position *pp is updated to point to the 1849 * first character following the modifier, which typically is either ':' or 1850 * st->endc. 1851 * 1852 * If parsing fails because of a missing delimiter (as in the :S, :C or :@ 1853 * modifiers), set st->missing_delim and return AMR_CLEANUP. 1854 * 1855 * If parsing fails because the modifier is unknown, return AMR_UNKNOWN to 1856 * try the SysV modifier ${VAR:from=to} as fallback. This should only be 1857 * done as long as there have been no side effects from evaluating nested 1858 * variables, to avoid evaluating them more than once. In this case, the 1859 * parsing position must not be updated. (XXX: Why not? The original parsing 1860 * position is well-known in ApplyModifiers.) 1861 * 1862 * If parsing fails and the SysV modifier ${VAR:from=to} should not be used 1863 * as a fallback, either issue an error message using Error or Parse_Error 1864 * and then return AMR_CLEANUP, or return AMR_BAD for the default error 1865 * message. Both of these return values will stop processing the variable 1866 * expression. (XXX: As of 2020-08-23, evaluation of the whole string 1867 * continues nevertheless after skipping a few bytes, which essentially is 1868 * undefined behavior. Not in the sense of C, but still it's impossible to 1869 * predict what happens in the parser.) 1870 * 1871 * Evaluating the modifier 1872 * 1873 * After parsing, the modifier is evaluated. The side effects from evaluating 1874 * nested variable expressions in the modifier text often already happen 1875 * during parsing though. 1876 * 1877 * Evaluating the modifier usually takes the current value of the variable 1878 * expression from st->val, or the variable name from st->v->name and stores 1879 * the result in st->newVal. 1880 * 1881 * If evaluating fails (as of 2020-08-23), an error message is printed using 1882 * Error. This function has no side-effects, it really just prints the error 1883 * message. Processing the expression continues as if everything were ok. 1884 * XXX: This should be fixed by adding proper error handling to Var_Subst, 1885 * Var_Parse, ApplyModifiers and ModifyWords. 1886 * 1887 * Housekeeping 1888 * 1889 * Some modifiers such as :D and :U turn undefined variables into useful 1890 * variables (VAR_JUNK, VAR_KEEP). 1891 * 1892 * Some modifiers need to free some memory. 1893 */ 1894 1895 typedef struct { 1896 const char startc; /* '\0' or '{' or '(' */ 1897 const char endc; /* '\0' or '}' or ')' */ 1898 Var * const v; 1899 GNode * const ctxt; 1900 const VarEvalFlags eflags; 1901 1902 char *val; /* The old value of the expression, 1903 * before applying the modifier, never NULL */ 1904 char *newVal; /* The new value of the expression, 1905 * after applying the modifier, never NULL */ 1906 char missing_delim; /* For error reporting */ 1907 1908 char sep; /* Word separator in expansions 1909 * (see the :ts modifier) */ 1910 Boolean oneBigWord; /* TRUE if some modifiers that otherwise split 1911 * the variable value into words, like :S and 1912 * :C, treat the variable value as a single big 1913 * word, possibly containing spaces. */ 1914 } ApplyModifiersState; 1915 1916 typedef enum { 1917 AMR_OK, /* Continue parsing */ 1918 AMR_UNKNOWN, /* Not a match, try other modifiers as well */ 1919 AMR_BAD, /* Error out with "Bad modifier" message */ 1920 AMR_CLEANUP /* Error out, with "Unfinished modifier" 1921 * if st->missing_delim is set. */ 1922 } ApplyModifierResult; 1923 1924 /* Test whether mod starts with modname, followed by a delimiter. */ 1925 static Boolean 1926 ModMatch(const char *mod, const char *modname, char endc) 1927 { 1928 size_t n = strlen(modname); 1929 return strncmp(mod, modname, n) == 0 && 1930 (mod[n] == endc || mod[n] == ':'); 1931 } 1932 1933 /* Test whether mod starts with modname, followed by a delimiter or '='. */ 1934 static inline Boolean 1935 ModMatchEq(const char *mod, const char *modname, char endc) 1936 { 1937 size_t n = strlen(modname); 1938 return strncmp(mod, modname, n) == 0 && 1939 (mod[n] == endc || mod[n] == ':' || mod[n] == '='); 1940 } 1941 1942 /* :@var@...${var}...@ */ 1943 static ApplyModifierResult 1944 ApplyModifier_Loop(const char **pp, ApplyModifiersState *st) 1945 { 1946 ModifyWord_LoopArgs args; 1947 char delim; 1948 char prev_sep; 1949 VarEvalFlags eflags = st->eflags & ~(unsigned)VARE_WANTRES; 1950 1951 args.ctx = st->ctxt; 1952 1953 (*pp)++; /* Skip the first '@' */ 1954 delim = '@'; 1955 args.tvar = ParseModifierPart(pp, delim, eflags, 1956 st->ctxt, NULL, NULL, NULL); 1957 if (args.tvar == NULL) { 1958 st->missing_delim = delim; 1959 return AMR_CLEANUP; 1960 } 1961 if (DEBUG(LINT) && strchr(args.tvar, '$') != NULL) { 1962 Parse_Error(PARSE_FATAL, 1963 "In the :@ modifier of \"%s\", the variable name \"%s\" " 1964 "must not contain a dollar.", 1965 st->v->name, args.tvar); 1966 return AMR_CLEANUP; 1967 } 1968 1969 args.str = ParseModifierPart(pp, delim, eflags, 1970 st->ctxt, NULL, NULL, NULL); 1971 if (args.str == NULL) { 1972 st->missing_delim = delim; 1973 return AMR_CLEANUP; 1974 } 1975 1976 args.eflags = st->eflags & (VARE_UNDEFERR | VARE_WANTRES); 1977 prev_sep = st->sep; 1978 st->sep = ' '; /* XXX: should be st->sep for consistency */ 1979 st->newVal = ModifyWords(st->ctxt, st->sep, st->oneBigWord, st->val, 1980 ModifyWord_Loop, &args); 1981 st->sep = prev_sep; 1982 Var_Delete(args.tvar, st->ctxt); 1983 free(args.tvar); 1984 free(args.str); 1985 return AMR_OK; 1986 } 1987 1988 /* :Ddefined or :Uundefined */ 1989 static ApplyModifierResult 1990 ApplyModifier_Defined(const char **pp, ApplyModifiersState *st) 1991 { 1992 Buffer buf; 1993 const char *p; 1994 1995 VarEvalFlags eflags = st->eflags & ~(unsigned)VARE_WANTRES; 1996 if (st->eflags & VARE_WANTRES) { 1997 if ((**pp == 'D') == !(st->v->flags & VAR_JUNK)) 1998 eflags |= VARE_WANTRES; 1999 } 2000 2001 Buf_Init(&buf, 0); 2002 p = *pp + 1; 2003 while (*p != st->endc && *p != ':' && *p != '\0') { 2004 2005 /* Escaped delimiter or other special character */ 2006 if (*p == '\\') { 2007 char c = p[1]; 2008 if (c == st->endc || c == ':' || c == '$' || c == '\\') { 2009 Buf_AddByte(&buf, c); 2010 p += 2; 2011 continue; 2012 } 2013 } 2014 2015 /* Nested variable expression */ 2016 if (*p == '$') { 2017 const char *nested_val; 2018 void *nested_val_freeIt; 2019 2020 (void)Var_Parse(&p, st->ctxt, eflags, 2021 &nested_val, &nested_val_freeIt); 2022 /* TODO: handle errors */ 2023 Buf_AddStr(&buf, nested_val); 2024 free(nested_val_freeIt); 2025 continue; 2026 } 2027 2028 /* Ordinary text */ 2029 Buf_AddByte(&buf, *p); 2030 p++; 2031 } 2032 *pp = p; 2033 2034 if (st->v->flags & VAR_JUNK) 2035 st->v->flags |= VAR_KEEP; 2036 if (eflags & VARE_WANTRES) { 2037 st->newVal = Buf_Destroy(&buf, FALSE); 2038 } else { 2039 st->newVal = st->val; 2040 Buf_Destroy(&buf, TRUE); 2041 } 2042 return AMR_OK; 2043 } 2044 2045 /* :gmtime */ 2046 static ApplyModifierResult 2047 ApplyModifier_Gmtime(const char **pp, ApplyModifiersState *st) 2048 { 2049 time_t utc; 2050 2051 const char *mod = *pp; 2052 if (!ModMatchEq(mod, "gmtime", st->endc)) 2053 return AMR_UNKNOWN; 2054 2055 if (mod[6] == '=') { 2056 char *ep; 2057 utc = (time_t)strtoul(mod + 7, &ep, 10); 2058 *pp = ep; 2059 } else { 2060 utc = 0; 2061 *pp = mod + 6; 2062 } 2063 st->newVal = VarStrftime(st->val, TRUE, utc); 2064 return AMR_OK; 2065 } 2066 2067 /* :localtime */ 2068 static ApplyModifierResult 2069 ApplyModifier_Localtime(const char **pp, ApplyModifiersState *st) 2070 { 2071 time_t utc; 2072 2073 const char *mod = *pp; 2074 if (!ModMatchEq(mod, "localtime", st->endc)) 2075 return AMR_UNKNOWN; 2076 2077 if (mod[9] == '=') { 2078 char *ep; 2079 utc = (time_t)strtoul(mod + 10, &ep, 10); 2080 *pp = ep; 2081 } else { 2082 utc = 0; 2083 *pp = mod + 9; 2084 } 2085 st->newVal = VarStrftime(st->val, FALSE, utc); 2086 return AMR_OK; 2087 } 2088 2089 /* :hash */ 2090 static ApplyModifierResult 2091 ApplyModifier_Hash(const char **pp, ApplyModifiersState *st) 2092 { 2093 if (!ModMatch(*pp, "hash", st->endc)) 2094 return AMR_UNKNOWN; 2095 2096 st->newVal = VarHash(st->val); 2097 *pp += 4; 2098 return AMR_OK; 2099 } 2100 2101 /* :P */ 2102 static ApplyModifierResult 2103 ApplyModifier_Path(const char **pp, ApplyModifiersState *st) 2104 { 2105 GNode *gn; 2106 char *path; 2107 2108 if (st->v->flags & VAR_JUNK) 2109 st->v->flags |= VAR_KEEP; 2110 2111 gn = Targ_FindNode(st->v->name, TARG_NOCREATE); 2112 if (gn == NULL || gn->type & OP_NOPATH) { 2113 path = NULL; 2114 } else if (gn->path) { 2115 path = bmake_strdup(gn->path); 2116 } else { 2117 Lst searchPath = Suff_FindPath(gn); 2118 path = Dir_FindFile(st->v->name, searchPath); 2119 } 2120 if (path == NULL) 2121 path = bmake_strdup(st->v->name); 2122 st->newVal = path; 2123 2124 (*pp)++; 2125 return AMR_OK; 2126 } 2127 2128 /* :!cmd! */ 2129 static ApplyModifierResult 2130 ApplyModifier_ShellCommand(const char **pp, ApplyModifiersState *st) 2131 { 2132 char delim; 2133 char *cmd; 2134 const char *errfmt; 2135 2136 (*pp)++; 2137 delim = '!'; 2138 cmd = ParseModifierPart(pp, delim, st->eflags, st->ctxt, 2139 NULL, NULL, NULL); 2140 if (cmd == NULL) { 2141 st->missing_delim = delim; 2142 return AMR_CLEANUP; 2143 } 2144 2145 errfmt = NULL; 2146 if (st->eflags & VARE_WANTRES) 2147 st->newVal = Cmd_Exec(cmd, &errfmt); 2148 else 2149 st->newVal = varNoError; 2150 free(cmd); 2151 2152 if (errfmt != NULL) 2153 Error(errfmt, st->val); /* XXX: why still return AMR_OK? */ 2154 2155 if (st->v->flags & VAR_JUNK) 2156 st->v->flags |= VAR_KEEP; 2157 return AMR_OK; 2158 } 2159 2160 /* The :range modifier generates an integer sequence as long as the words. 2161 * The :range=7 modifier generates an integer sequence from 1 to 7. */ 2162 static ApplyModifierResult 2163 ApplyModifier_Range(const char **pp, ApplyModifiersState *st) 2164 { 2165 size_t n; 2166 Buffer buf; 2167 size_t i; 2168 2169 const char *mod = *pp; 2170 if (!ModMatchEq(mod, "range", st->endc)) 2171 return AMR_UNKNOWN; 2172 2173 if (mod[5] == '=') { 2174 char *ep; 2175 n = (size_t)strtoul(mod + 6, &ep, 10); 2176 *pp = ep; 2177 } else { 2178 n = 0; 2179 *pp = mod + 5; 2180 } 2181 2182 if (n == 0) { 2183 Words words = Str_Words(st->val, FALSE); 2184 n = words.len; 2185 Words_Free(words); 2186 } 2187 2188 Buf_Init(&buf, 0); 2189 2190 for (i = 0; i < n; i++) { 2191 if (i != 0) 2192 Buf_AddByte(&buf, ' '); /* XXX: st->sep, for consistency */ 2193 Buf_AddInt(&buf, 1 + (int)i); 2194 } 2195 2196 st->newVal = Buf_Destroy(&buf, FALSE); 2197 return AMR_OK; 2198 } 2199 2200 /* :Mpattern or :Npattern */ 2201 static ApplyModifierResult 2202 ApplyModifier_Match(const char **pp, ApplyModifiersState *st) 2203 { 2204 const char *mod = *pp; 2205 Boolean copy = FALSE; /* pattern should be, or has been, copied */ 2206 Boolean needSubst = FALSE; 2207 const char *endpat; 2208 char *pattern; 2209 ModifyWordsCallback callback; 2210 2211 /* 2212 * In the loop below, ignore ':' unless we are at (or back to) the 2213 * original brace level. 2214 * XXX This will likely not work right if $() and ${} are intermixed. 2215 */ 2216 int nest = 0; 2217 const char *p; 2218 for (p = mod + 1; *p != '\0' && !(*p == ':' && nest == 0); p++) { 2219 if (*p == '\\' && 2220 (p[1] == ':' || p[1] == st->endc || p[1] == st->startc)) { 2221 if (!needSubst) 2222 copy = TRUE; 2223 p++; 2224 continue; 2225 } 2226 if (*p == '$') 2227 needSubst = TRUE; 2228 if (*p == '(' || *p == '{') 2229 nest++; 2230 if (*p == ')' || *p == '}') { 2231 nest--; 2232 if (nest < 0) 2233 break; 2234 } 2235 } 2236 *pp = p; 2237 endpat = p; 2238 2239 if (copy) { 2240 char *dst; 2241 const char *src; 2242 2243 /* Compress the \:'s out of the pattern. */ 2244 pattern = bmake_malloc((size_t)(endpat - (mod + 1)) + 1); 2245 dst = pattern; 2246 src = mod + 1; 2247 for (; src < endpat; src++, dst++) { 2248 if (src[0] == '\\' && src + 1 < endpat && 2249 /* XXX: st->startc is missing here; see above */ 2250 (src[1] == ':' || src[1] == st->endc)) 2251 src++; 2252 *dst = *src; 2253 } 2254 *dst = '\0'; 2255 endpat = dst; 2256 } else { 2257 pattern = bmake_strsedup(mod + 1, endpat); 2258 } 2259 2260 if (needSubst) { 2261 /* pattern contains embedded '$', so use Var_Subst to expand it. */ 2262 char *old_pattern = pattern; 2263 pattern = Var_Subst(pattern, st->ctxt, st->eflags); 2264 free(old_pattern); 2265 } 2266 2267 VAR_DEBUG("Pattern[%s] for [%s] is [%s]\n", st->v->name, st->val, pattern); 2268 2269 callback = mod[0] == 'M' ? ModifyWord_Match : ModifyWord_NoMatch; 2270 st->newVal = ModifyWords(st->ctxt, st->sep, st->oneBigWord, st->val, 2271 callback, pattern); 2272 free(pattern); 2273 return AMR_OK; 2274 } 2275 2276 /* :S,from,to, */ 2277 static ApplyModifierResult 2278 ApplyModifier_Subst(const char **pp, ApplyModifiersState *st) 2279 { 2280 ModifyWord_SubstArgs args; 2281 char *lhs, *rhs; 2282 Boolean oneBigWord; 2283 2284 char delim = (*pp)[1]; 2285 if (delim == '\0') { 2286 Error("Missing delimiter for :S modifier"); 2287 (*pp)++; 2288 return AMR_CLEANUP; 2289 } 2290 2291 *pp += 2; 2292 2293 args.pflags = 0; 2294 args.matched = FALSE; 2295 2296 /* 2297 * If pattern begins with '^', it is anchored to the 2298 * start of the word -- skip over it and flag pattern. 2299 */ 2300 if (**pp == '^') { 2301 args.pflags |= VARP_ANCHOR_START; 2302 (*pp)++; 2303 } 2304 2305 lhs = ParseModifierPart(pp, delim, st->eflags, st->ctxt, 2306 &args.lhsLen, &args.pflags, NULL); 2307 if (lhs == NULL) { 2308 st->missing_delim = delim; 2309 return AMR_CLEANUP; 2310 } 2311 args.lhs = lhs; 2312 2313 rhs = ParseModifierPart(pp, delim, st->eflags, st->ctxt, 2314 &args.rhsLen, NULL, &args); 2315 if (rhs == NULL) { 2316 st->missing_delim = delim; 2317 return AMR_CLEANUP; 2318 } 2319 args.rhs = rhs; 2320 2321 oneBigWord = st->oneBigWord; 2322 for (;; (*pp)++) { 2323 switch (**pp) { 2324 case 'g': 2325 args.pflags |= VARP_SUB_GLOBAL; 2326 continue; 2327 case '1': 2328 args.pflags |= VARP_SUB_ONE; 2329 continue; 2330 case 'W': 2331 oneBigWord = TRUE; 2332 continue; 2333 } 2334 break; 2335 } 2336 2337 st->newVal = ModifyWords(st->ctxt, st->sep, oneBigWord, st->val, 2338 ModifyWord_Subst, &args); 2339 2340 free(lhs); 2341 free(rhs); 2342 return AMR_OK; 2343 } 2344 2345 #ifndef NO_REGEX 2346 2347 /* :C,from,to, */ 2348 static ApplyModifierResult 2349 ApplyModifier_Regex(const char **pp, ApplyModifiersState *st) 2350 { 2351 char *re; 2352 ModifyWord_SubstRegexArgs args; 2353 Boolean oneBigWord; 2354 int error; 2355 2356 char delim = (*pp)[1]; 2357 if (delim == '\0') { 2358 Error("Missing delimiter for :C modifier"); 2359 (*pp)++; 2360 return AMR_CLEANUP; 2361 } 2362 2363 *pp += 2; 2364 2365 re = ParseModifierPart(pp, delim, st->eflags, st->ctxt, NULL, NULL, NULL); 2366 if (re == NULL) { 2367 st->missing_delim = delim; 2368 return AMR_CLEANUP; 2369 } 2370 2371 args.replace = ParseModifierPart(pp, delim, st->eflags, st->ctxt, 2372 NULL, NULL, NULL); 2373 if (args.replace == NULL) { 2374 free(re); 2375 st->missing_delim = delim; 2376 return AMR_CLEANUP; 2377 } 2378 2379 args.pflags = 0; 2380 args.matched = FALSE; 2381 oneBigWord = st->oneBigWord; 2382 for (;; (*pp)++) { 2383 switch (**pp) { 2384 case 'g': 2385 args.pflags |= VARP_SUB_GLOBAL; 2386 continue; 2387 case '1': 2388 args.pflags |= VARP_SUB_ONE; 2389 continue; 2390 case 'W': 2391 oneBigWord = TRUE; 2392 continue; 2393 } 2394 break; 2395 } 2396 2397 error = regcomp(&args.re, re, REG_EXTENDED); 2398 free(re); 2399 if (error) { 2400 VarREError(error, &args.re, "Regex compilation error"); 2401 free(args.replace); 2402 return AMR_CLEANUP; 2403 } 2404 2405 args.nsub = args.re.re_nsub + 1; 2406 if (args.nsub > 10) 2407 args.nsub = 10; 2408 st->newVal = ModifyWords(st->ctxt, st->sep, oneBigWord, st->val, 2409 ModifyWord_SubstRegex, &args); 2410 regfree(&args.re); 2411 free(args.replace); 2412 return AMR_OK; 2413 } 2414 #endif 2415 2416 static void 2417 ModifyWord_Copy(const char *word, SepBuf *buf, void *data MAKE_ATTR_UNUSED) 2418 { 2419 SepBuf_AddStr(buf, word); 2420 } 2421 2422 /* :ts<separator> */ 2423 static ApplyModifierResult 2424 ApplyModifier_ToSep(const char **pp, ApplyModifiersState *st) 2425 { 2426 /* XXX: pp points to the 's', for historic reasons only. 2427 * Changing this will influence the error messages. */ 2428 const char *sep = *pp + 1; 2429 2430 /* ":ts<any><endc>" or ":ts<any>:" */ 2431 if (sep[0] != st->endc && (sep[1] == st->endc || sep[1] == ':')) { 2432 st->sep = sep[0]; 2433 *pp = sep + 1; 2434 goto ok; 2435 } 2436 2437 /* ":ts<endc>" or ":ts:" */ 2438 if (sep[0] == st->endc || sep[0] == ':') { 2439 st->sep = '\0'; /* no separator */ 2440 *pp = sep; 2441 goto ok; 2442 } 2443 2444 /* ":ts<unrecognised><unrecognised>". */ 2445 if (sep[0] != '\\') 2446 return AMR_BAD; 2447 2448 /* ":ts\n" */ 2449 if (sep[1] == 'n') { 2450 st->sep = '\n'; 2451 *pp = sep + 2; 2452 goto ok; 2453 } 2454 2455 /* ":ts\t" */ 2456 if (sep[1] == 't') { 2457 st->sep = '\t'; 2458 *pp = sep + 2; 2459 goto ok; 2460 } 2461 2462 /* ":ts\x40" or ":ts\100" */ 2463 { 2464 const char *numStart = sep + 1; 2465 int base = 8; /* assume octal */ 2466 char *end; 2467 2468 if (sep[1] == 'x') { 2469 base = 16; 2470 numStart++; 2471 } else if (!ch_isdigit(sep[1])) 2472 return AMR_BAD; /* ":ts<backslash><unrecognised>". */ 2473 2474 st->sep = (char)strtoul(numStart, &end, base); 2475 if (*end != ':' && *end != st->endc) 2476 return AMR_BAD; 2477 *pp = end; 2478 } 2479 2480 ok: 2481 st->newVal = ModifyWords(st->ctxt, st->sep, st->oneBigWord, st->val, 2482 ModifyWord_Copy, NULL); 2483 return AMR_OK; 2484 } 2485 2486 /* :tA, :tu, :tl, :ts<separator>, etc. */ 2487 static ApplyModifierResult 2488 ApplyModifier_To(const char **pp, ApplyModifiersState *st) 2489 { 2490 const char *mod = *pp; 2491 assert(mod[0] == 't'); 2492 2493 *pp = mod + 1; /* make sure it is set */ 2494 if (mod[1] == st->endc || mod[1] == ':' || mod[1] == '\0') 2495 return AMR_BAD; /* Found ":t<endc>" or ":t:". */ 2496 2497 if (mod[1] == 's') 2498 return ApplyModifier_ToSep(pp, st); 2499 2500 if (mod[2] != st->endc && mod[2] != ':') 2501 return AMR_BAD; /* Found ":t<unrecognised><unrecognised>". */ 2502 2503 /* Check for two-character options: ":tu", ":tl" */ 2504 if (mod[1] == 'A') { /* absolute path */ 2505 st->newVal = ModifyWords(st->ctxt, st->sep, st->oneBigWord, st->val, 2506 ModifyWord_Realpath, NULL); 2507 *pp = mod + 2; 2508 return AMR_OK; 2509 } 2510 2511 if (mod[1] == 'u') { 2512 size_t i; 2513 size_t len = strlen(st->val); 2514 st->newVal = bmake_malloc(len + 1); 2515 for (i = 0; i < len + 1; i++) 2516 st->newVal[i] = ch_toupper(st->val[i]); 2517 *pp = mod + 2; 2518 return AMR_OK; 2519 } 2520 2521 if (mod[1] == 'l') { 2522 size_t i; 2523 size_t len = strlen(st->val); 2524 st->newVal = bmake_malloc(len + 1); 2525 for (i = 0; i < len + 1; i++) 2526 st->newVal[i] = ch_tolower(st->val[i]); 2527 *pp = mod + 2; 2528 return AMR_OK; 2529 } 2530 2531 if (mod[1] == 'W' || mod[1] == 'w') { 2532 st->oneBigWord = mod[1] == 'W'; 2533 st->newVal = st->val; 2534 *pp = mod + 2; 2535 return AMR_OK; 2536 } 2537 2538 /* Found ":t<unrecognised>:" or ":t<unrecognised><endc>". */ 2539 return AMR_BAD; 2540 } 2541 2542 /* :[#], :[1], etc. */ 2543 static ApplyModifierResult 2544 ApplyModifier_Words(const char **pp, ApplyModifiersState *st) 2545 { 2546 char delim; 2547 char *estr; 2548 char *ep; 2549 int first, last; 2550 2551 (*pp)++; /* skip the '[' */ 2552 delim = ']'; /* look for closing ']' */ 2553 estr = ParseModifierPart(pp, delim, st->eflags, st->ctxt, 2554 NULL, NULL, NULL); 2555 if (estr == NULL) { 2556 st->missing_delim = delim; 2557 return AMR_CLEANUP; 2558 } 2559 2560 /* now *pp points just after the closing ']' */ 2561 if (**pp != ':' && **pp != st->endc) 2562 goto bad_modifier; /* Found junk after ']' */ 2563 2564 if (estr[0] == '\0') 2565 goto bad_modifier; /* empty square brackets in ":[]". */ 2566 2567 if (estr[0] == '#' && estr[1] == '\0') { /* Found ":[#]" */ 2568 if (st->oneBigWord) { 2569 st->newVal = bmake_strdup("1"); 2570 } else { 2571 Buffer buf; 2572 2573 Words words = Str_Words(st->val, FALSE); 2574 size_t ac = words.len; 2575 Words_Free(words); 2576 2577 Buf_Init(&buf, 4); /* 3 digits + '\0' is usually enough */ 2578 Buf_AddInt(&buf, (int)ac); 2579 st->newVal = Buf_Destroy(&buf, FALSE); 2580 } 2581 goto ok; 2582 } 2583 2584 if (estr[0] == '*' && estr[1] == '\0') { 2585 /* Found ":[*]" */ 2586 st->oneBigWord = TRUE; 2587 st->newVal = st->val; 2588 goto ok; 2589 } 2590 2591 if (estr[0] == '@' && estr[1] == '\0') { 2592 /* Found ":[@]" */ 2593 st->oneBigWord = FALSE; 2594 st->newVal = st->val; 2595 goto ok; 2596 } 2597 2598 /* 2599 * We expect estr to contain a single integer for :[N], or two integers 2600 * separated by ".." for :[start..end]. 2601 */ 2602 first = (int)strtol(estr, &ep, 0); 2603 if (ep == estr) /* Found junk instead of a number */ 2604 goto bad_modifier; 2605 2606 if (ep[0] == '\0') { /* Found only one integer in :[N] */ 2607 last = first; 2608 } else if (ep[0] == '.' && ep[1] == '.' && ep[2] != '\0') { 2609 /* Expecting another integer after ".." */ 2610 ep += 2; 2611 last = (int)strtol(ep, &ep, 0); 2612 if (ep[0] != '\0') /* Found junk after ".." */ 2613 goto bad_modifier; 2614 } else 2615 goto bad_modifier; /* Found junk instead of ".." */ 2616 2617 /* 2618 * Now seldata is properly filled in, but we still have to check for 0 as 2619 * a special case. 2620 */ 2621 if (first == 0 && last == 0) { 2622 /* ":[0]" or perhaps ":[0..0]" */ 2623 st->oneBigWord = TRUE; 2624 st->newVal = st->val; 2625 goto ok; 2626 } 2627 2628 /* ":[0..N]" or ":[N..0]" */ 2629 if (first == 0 || last == 0) 2630 goto bad_modifier; 2631 2632 /* Normal case: select the words described by seldata. */ 2633 st->newVal = VarSelectWords(st->sep, st->oneBigWord, st->val, first, last); 2634 2635 ok: 2636 free(estr); 2637 return AMR_OK; 2638 2639 bad_modifier: 2640 free(estr); 2641 return AMR_BAD; 2642 } 2643 2644 static int 2645 str_cmp_asc(const void *a, const void *b) 2646 { 2647 return strcmp(*(const char * const *)a, *(const char * const *)b); 2648 } 2649 2650 static int 2651 str_cmp_desc(const void *a, const void *b) 2652 { 2653 return strcmp(*(const char * const *)b, *(const char * const *)a); 2654 } 2655 2656 /* :O (order ascending) or :Or (order descending) or :Ox (shuffle) */ 2657 static ApplyModifierResult 2658 ApplyModifier_Order(const char **pp, ApplyModifiersState *st) 2659 { 2660 const char *mod = (*pp)++; /* skip past the 'O' in any case */ 2661 2662 Words words = Str_Words(st->val, FALSE); 2663 2664 if (mod[1] == st->endc || mod[1] == ':') { 2665 /* :O sorts ascending */ 2666 qsort(words.words, words.len, sizeof(char *), str_cmp_asc); 2667 2668 } else if ((mod[1] == 'r' || mod[1] == 'x') && 2669 (mod[2] == st->endc || mod[2] == ':')) { 2670 (*pp)++; 2671 2672 if (mod[1] == 'r') { 2673 /* :Or sorts descending */ 2674 qsort(words.words, words.len, sizeof(char *), str_cmp_desc); 2675 2676 } else { 2677 /* :Ox shuffles 2678 * 2679 * We will use [ac..2] range for mod factors. This will produce 2680 * random numbers in [(ac-1)..0] interval, and minimal 2681 * reasonable value for mod factor is 2 (the mod 1 will produce 2682 * 0 with probability 1). 2683 */ 2684 size_t i; 2685 for (i = words.len - 1; i > 0; i--) { 2686 size_t rndidx = (size_t)random() % (i + 1); 2687 char *t = words.words[i]; 2688 words.words[i] = words.words[rndidx]; 2689 words.words[rndidx] = t; 2690 } 2691 } 2692 } else { 2693 Words_Free(words); 2694 return AMR_BAD; 2695 } 2696 2697 st->newVal = Words_JoinFree(words); 2698 return AMR_OK; 2699 } 2700 2701 /* :? then : else */ 2702 static ApplyModifierResult 2703 ApplyModifier_IfElse(const char **pp, ApplyModifiersState *st) 2704 { 2705 char delim; 2706 char *then_expr, *else_expr; 2707 2708 Boolean value = FALSE; 2709 VarEvalFlags then_eflags = st->eflags & ~(unsigned)VARE_WANTRES; 2710 VarEvalFlags else_eflags = st->eflags & ~(unsigned)VARE_WANTRES; 2711 2712 int cond_rc = COND_PARSE; /* anything other than COND_INVALID */ 2713 if (st->eflags & VARE_WANTRES) { 2714 cond_rc = Cond_EvalCondition(st->v->name, &value); 2715 if (cond_rc != COND_INVALID && value) 2716 then_eflags |= VARE_WANTRES; 2717 if (cond_rc != COND_INVALID && !value) 2718 else_eflags |= VARE_WANTRES; 2719 } 2720 2721 (*pp)++; /* skip past the '?' */ 2722 delim = ':'; 2723 then_expr = ParseModifierPart(pp, delim, then_eflags, st->ctxt, 2724 NULL, NULL, NULL); 2725 if (then_expr == NULL) { 2726 st->missing_delim = delim; 2727 return AMR_CLEANUP; 2728 } 2729 2730 delim = st->endc; /* BRCLOSE or PRCLOSE */ 2731 else_expr = ParseModifierPart(pp, delim, else_eflags, st->ctxt, 2732 NULL, NULL, NULL); 2733 if (else_expr == NULL) { 2734 st->missing_delim = delim; 2735 return AMR_CLEANUP; 2736 } 2737 2738 (*pp)--; 2739 if (cond_rc == COND_INVALID) { 2740 Error("Bad conditional expression `%s' in %s?%s:%s", 2741 st->v->name, st->v->name, then_expr, else_expr); 2742 return AMR_CLEANUP; 2743 } 2744 2745 if (value) { 2746 st->newVal = then_expr; 2747 free(else_expr); 2748 } else { 2749 st->newVal = else_expr; 2750 free(then_expr); 2751 } 2752 if (st->v->flags & VAR_JUNK) 2753 st->v->flags |= VAR_KEEP; 2754 return AMR_OK; 2755 } 2756 2757 /* 2758 * The ::= modifiers actually assign a value to the variable. 2759 * Their main purpose is in supporting modifiers of .for loop 2760 * iterators and other obscure uses. They always expand to 2761 * nothing. In a target rule that would otherwise expand to an 2762 * empty line they can be preceded with @: to keep make happy. 2763 * Eg. 2764 * 2765 * foo: .USE 2766 * .for i in ${.TARGET} ${.TARGET:R}.gz 2767 * @: ${t::=$i} 2768 * @echo blah ${t:T} 2769 * .endfor 2770 * 2771 * ::=<str> Assigns <str> as the new value of variable. 2772 * ::?=<str> Assigns <str> as value of variable if 2773 * it was not already set. 2774 * ::+=<str> Appends <str> to variable. 2775 * ::!=<cmd> Assigns output of <cmd> as the new value of 2776 * variable. 2777 */ 2778 static ApplyModifierResult 2779 ApplyModifier_Assign(const char **pp, ApplyModifiersState *st) 2780 { 2781 GNode *v_ctxt; 2782 char *sv_name; 2783 char delim; 2784 char *val; 2785 2786 const char *mod = *pp; 2787 const char *op = mod + 1; 2788 if (!(op[0] == '=' || 2789 (op[1] == '=' && 2790 (op[0] == '!' || op[0] == '+' || op[0] == '?')))) 2791 return AMR_UNKNOWN; /* "::<unrecognised>" */ 2792 2793 2794 if (st->v->name[0] == 0) { 2795 *pp = mod + 1; 2796 return AMR_BAD; 2797 } 2798 2799 v_ctxt = st->ctxt; /* context where v belongs */ 2800 sv_name = NULL; 2801 if (st->v->flags & VAR_JUNK) { 2802 /* 2803 * We need to bmake_strdup() it in case ParseModifierPart() recurses. 2804 */ 2805 sv_name = st->v->name; 2806 st->v->name = bmake_strdup(st->v->name); 2807 } else if (st->ctxt != VAR_GLOBAL) { 2808 Var *gv = VarFind(st->v->name, st->ctxt, 0); 2809 if (gv == NULL) 2810 v_ctxt = VAR_GLOBAL; 2811 else 2812 VarFreeEnv(gv, TRUE); 2813 } 2814 2815 switch (op[0]) { 2816 case '+': 2817 case '?': 2818 case '!': 2819 *pp = mod + 3; 2820 break; 2821 default: 2822 *pp = mod + 2; 2823 break; 2824 } 2825 2826 delim = st->startc == '(' ? ')' : '}'; 2827 val = ParseModifierPart(pp, delim, st->eflags, st->ctxt, NULL, NULL, NULL); 2828 if (st->v->flags & VAR_JUNK) { 2829 /* restore original name */ 2830 free(st->v->name); 2831 st->v->name = sv_name; 2832 } 2833 if (val == NULL) { 2834 st->missing_delim = delim; 2835 return AMR_CLEANUP; 2836 } 2837 2838 (*pp)--; 2839 2840 if (st->eflags & VARE_WANTRES) { 2841 switch (op[0]) { 2842 case '+': 2843 Var_Append(st->v->name, val, v_ctxt); 2844 break; 2845 case '!': { 2846 const char *errfmt; 2847 char *cmd_output = Cmd_Exec(val, &errfmt); 2848 if (errfmt) 2849 Error(errfmt, val); 2850 else 2851 Var_Set(st->v->name, cmd_output, v_ctxt); 2852 free(cmd_output); 2853 break; 2854 } 2855 case '?': 2856 if (!(st->v->flags & VAR_JUNK)) 2857 break; 2858 /* FALLTHROUGH */ 2859 default: 2860 Var_Set(st->v->name, val, v_ctxt); 2861 break; 2862 } 2863 } 2864 free(val); 2865 st->newVal = varNoError; /* XXX: varNoError is kind of an error, 2866 * the intention here is to just return 2867 * an empty string. */ 2868 return AMR_OK; 2869 } 2870 2871 /* remember current value */ 2872 static ApplyModifierResult 2873 ApplyModifier_Remember(const char **pp, ApplyModifiersState *st) 2874 { 2875 const char *mod = *pp; 2876 if (!ModMatchEq(mod, "_", st->endc)) 2877 return AMR_UNKNOWN; 2878 2879 if (mod[1] == '=') { 2880 size_t n = strcspn(mod + 2, ":)}"); 2881 char *name = bmake_strldup(mod + 2, n); 2882 Var_Set(name, st->val, st->ctxt); 2883 free(name); 2884 *pp = mod + 2 + n; 2885 } else { 2886 Var_Set("_", st->val, st->ctxt); 2887 *pp = mod + 1; 2888 } 2889 st->newVal = st->val; 2890 return AMR_OK; 2891 } 2892 2893 /* Apply the given function to each word of the variable value. */ 2894 static ApplyModifierResult 2895 ApplyModifier_WordFunc(const char **pp, ApplyModifiersState *st, 2896 ModifyWordsCallback modifyWord) 2897 { 2898 char delim = (*pp)[1]; 2899 if (delim != st->endc && delim != ':') 2900 return AMR_UNKNOWN; 2901 2902 st->newVal = ModifyWords(st->ctxt, st->sep, st->oneBigWord, 2903 st->val, modifyWord, NULL); 2904 (*pp)++; 2905 return AMR_OK; 2906 } 2907 2908 #ifdef SYSVVARSUB 2909 /* :from=to */ 2910 static ApplyModifierResult 2911 ApplyModifier_SysV(const char **pp, ApplyModifiersState *st) 2912 { 2913 char delim; 2914 char *lhs, *rhs; 2915 2916 const char *mod = *pp; 2917 Boolean eqFound = FALSE; 2918 2919 /* 2920 * First we make a pass through the string trying 2921 * to verify it is a SYSV-make-style translation: 2922 * it must be: <string1>=<string2>) 2923 */ 2924 int nest = 1; 2925 const char *next = mod; 2926 while (*next != '\0' && nest > 0) { 2927 if (*next == '=') { 2928 eqFound = TRUE; 2929 /* continue looking for st->endc */ 2930 } else if (*next == st->endc) 2931 nest--; 2932 else if (*next == st->startc) 2933 nest++; 2934 if (nest > 0) 2935 next++; 2936 } 2937 if (*next != st->endc || !eqFound) 2938 return AMR_UNKNOWN; 2939 2940 delim = '='; 2941 *pp = mod; 2942 lhs = ParseModifierPart(pp, delim, st->eflags, st->ctxt, NULL, NULL, NULL); 2943 if (lhs == NULL) { 2944 st->missing_delim = delim; 2945 return AMR_CLEANUP; 2946 } 2947 2948 delim = st->endc; 2949 rhs = ParseModifierPart(pp, delim, st->eflags, st->ctxt, NULL, NULL, NULL); 2950 if (rhs == NULL) { 2951 st->missing_delim = delim; 2952 return AMR_CLEANUP; 2953 } 2954 2955 /* 2956 * SYSV modifications happen through the whole 2957 * string. Note the pattern is anchored at the end. 2958 */ 2959 (*pp)--; 2960 if (lhs[0] == '\0' && st->val[0] == '\0') { 2961 st->newVal = st->val; /* special case */ 2962 } else { 2963 ModifyWord_SYSVSubstArgs args = {st->ctxt, lhs, rhs}; 2964 st->newVal = ModifyWords(st->ctxt, st->sep, st->oneBigWord, st->val, 2965 ModifyWord_SYSVSubst, &args); 2966 } 2967 free(lhs); 2968 free(rhs); 2969 return AMR_OK; 2970 } 2971 #endif 2972 2973 /* Apply any modifiers (such as :Mpattern or :@var@loop@ or :Q or ::=value). */ 2974 static char * 2975 ApplyModifiers( 2976 const char **pp, /* the parsing position, updated upon return */ 2977 char *val, /* the current value of the variable */ 2978 char const startc, /* '(' or '{', or '\0' for indirect modifiers */ 2979 char const endc, /* ')' or '}', or '\0' for indirect modifiers */ 2980 Var * const v, /* the variable may have its flags changed */ 2981 GNode * const ctxt, /* for looking up and modifying variables */ 2982 VarEvalFlags const eflags, 2983 void ** const freePtr /* free this after using the return value */ 2984 ) { 2985 ApplyModifiersState st = { 2986 startc, endc, v, ctxt, eflags, val, 2987 var_Error, /* .newVal */ 2988 '\0', /* .missing_delim */ 2989 ' ', /* .sep */ 2990 FALSE /* .oneBigWord */ 2991 }; 2992 const char *p; 2993 const char *mod; 2994 ApplyModifierResult res; 2995 2996 assert(startc == '(' || startc == '{' || startc == '\0'); 2997 assert(endc == ')' || endc == '}' || endc == '\0'); 2998 assert(val != NULL); 2999 3000 p = *pp; 3001 while (*p != '\0' && *p != endc) { 3002 3003 if (*p == '$') { 3004 /* 3005 * We may have some complex modifiers in a variable. 3006 */ 3007 const char *nested_p = p; 3008 void *freeIt; 3009 const char *rval; 3010 int c; 3011 3012 (void)Var_Parse(&nested_p, st.ctxt, st.eflags, &rval, &freeIt); 3013 /* TODO: handle errors */ 3014 3015 /* 3016 * If we have not parsed up to st.endc or ':', 3017 * we are not interested. 3018 */ 3019 if (rval[0] != '\0' && 3020 (c = *nested_p) != '\0' && c != ':' && c != st.endc) { 3021 free(freeIt); 3022 /* XXX: apply_mods doesn't sound like "not interested". */ 3023 goto apply_mods; 3024 } 3025 3026 VAR_DEBUG("Indirect modifier \"%s\" from \"%.*s\"\n", 3027 rval, (int)(size_t)(nested_p - p), p); 3028 3029 p = nested_p; 3030 3031 if (rval[0] != '\0') { 3032 const char *rval_pp = rval; 3033 st.val = ApplyModifiers(&rval_pp, st.val, '\0', '\0', v, 3034 ctxt, eflags, freePtr); 3035 if (st.val == var_Error 3036 || (st.val == varNoError && !(st.eflags & VARE_UNDEFERR)) 3037 || *rval_pp != '\0') { 3038 free(freeIt); 3039 goto out; /* error already reported */ 3040 } 3041 } 3042 free(freeIt); 3043 if (*p == ':') 3044 p++; 3045 else if (*p == '\0' && endc != '\0') { 3046 Error("Unclosed variable specification after complex " 3047 "modifier (expecting '%c') for %s", st.endc, st.v->name); 3048 goto out; 3049 } 3050 continue; 3051 } 3052 apply_mods: 3053 st.newVal = var_Error; /* default value, in case of errors */ 3054 res = AMR_BAD; /* just a safe fallback */ 3055 mod = p; 3056 3057 if (DEBUG(VAR)) { 3058 char eflags_str[VarEvalFlags_ToStringSize]; 3059 char vflags_str[VarFlags_ToStringSize]; 3060 Boolean is_single_char = mod[0] != '\0' && 3061 (mod[1] == endc || mod[1] == ':'); 3062 3063 /* At this point, only the first character of the modifier can 3064 * be used since the end of the modifier is not yet known. */ 3065 VAR_DEBUG("Applying ${%s:%c%s} to \"%s\" (%s, %s)\n", 3066 st.v->name, mod[0], is_single_char ? "" : "...", st.val, 3067 Enum_FlagsToString(eflags_str, sizeof eflags_str, 3068 st.eflags, VarEvalFlags_ToStringSpecs), 3069 Enum_FlagsToString(vflags_str, sizeof vflags_str, 3070 st.v->flags, VarFlags_ToStringSpecs)); 3071 } 3072 3073 switch (*mod) { 3074 case ':': 3075 res = ApplyModifier_Assign(&p, &st); 3076 break; 3077 case '@': 3078 res = ApplyModifier_Loop(&p, &st); 3079 break; 3080 case '_': 3081 res = ApplyModifier_Remember(&p, &st); 3082 break; 3083 case 'D': 3084 case 'U': 3085 res = ApplyModifier_Defined(&p, &st); 3086 break; 3087 case 'L': 3088 if (st.v->flags & VAR_JUNK) 3089 st.v->flags |= VAR_KEEP; 3090 st.newVal = bmake_strdup(st.v->name); 3091 p++; 3092 res = AMR_OK; 3093 break; 3094 case 'P': 3095 res = ApplyModifier_Path(&p, &st); 3096 break; 3097 case '!': 3098 res = ApplyModifier_ShellCommand(&p, &st); 3099 break; 3100 case '[': 3101 res = ApplyModifier_Words(&p, &st); 3102 break; 3103 case 'g': 3104 res = ApplyModifier_Gmtime(&p, &st); 3105 break; 3106 case 'h': 3107 res = ApplyModifier_Hash(&p, &st); 3108 break; 3109 case 'l': 3110 res = ApplyModifier_Localtime(&p, &st); 3111 break; 3112 case 't': 3113 res = ApplyModifier_To(&p, &st); 3114 break; 3115 case 'N': 3116 case 'M': 3117 res = ApplyModifier_Match(&p, &st); 3118 break; 3119 case 'S': 3120 res = ApplyModifier_Subst(&p, &st); 3121 break; 3122 case '?': 3123 res = ApplyModifier_IfElse(&p, &st); 3124 break; 3125 #ifndef NO_REGEX 3126 case 'C': 3127 res = ApplyModifier_Regex(&p, &st); 3128 break; 3129 #endif 3130 case 'q': 3131 case 'Q': 3132 if (p[1] == st.endc || p[1] == ':') { 3133 st.newVal = VarQuote(st.val, *mod == 'q'); 3134 p++; 3135 res = AMR_OK; 3136 } else 3137 res = AMR_UNKNOWN; 3138 break; 3139 case 'T': 3140 res = ApplyModifier_WordFunc(&p, &st, ModifyWord_Tail); 3141 break; 3142 case 'H': 3143 res = ApplyModifier_WordFunc(&p, &st, ModifyWord_Head); 3144 break; 3145 case 'E': 3146 res = ApplyModifier_WordFunc(&p, &st, ModifyWord_Suffix); 3147 break; 3148 case 'R': 3149 res = ApplyModifier_WordFunc(&p, &st, ModifyWord_Root); 3150 break; 3151 case 'r': 3152 res = ApplyModifier_Range(&p, &st); 3153 break; 3154 case 'O': 3155 res = ApplyModifier_Order(&p, &st); 3156 break; 3157 case 'u': 3158 if (p[1] == st.endc || p[1] == ':') { 3159 st.newVal = VarUniq(st.val); 3160 p++; 3161 res = AMR_OK; 3162 } else 3163 res = AMR_UNKNOWN; 3164 break; 3165 #ifdef SUNSHCMD 3166 case 's': 3167 if (p[1] == 'h' && (p[2] == st.endc || p[2] == ':')) { 3168 if (st.eflags & VARE_WANTRES) { 3169 const char *errfmt; 3170 st.newVal = Cmd_Exec(st.val, &errfmt); 3171 if (errfmt) 3172 Error(errfmt, st.val); 3173 } else 3174 st.newVal = varNoError; 3175 p += 2; 3176 res = AMR_OK; 3177 } else 3178 res = AMR_UNKNOWN; 3179 break; 3180 #endif 3181 default: 3182 res = AMR_UNKNOWN; 3183 } 3184 3185 #ifdef SYSVVARSUB 3186 if (res == AMR_UNKNOWN) { 3187 assert(p == mod); 3188 res = ApplyModifier_SysV(&p, &st); 3189 } 3190 #endif 3191 3192 if (res == AMR_UNKNOWN) { 3193 Error("Unknown modifier '%c'", *mod); 3194 for (p++; *p != ':' && *p != st.endc && *p != '\0'; p++) 3195 continue; 3196 st.newVal = var_Error; 3197 } 3198 if (res == AMR_CLEANUP) 3199 goto cleanup; 3200 if (res == AMR_BAD) 3201 goto bad_modifier; 3202 3203 if (DEBUG(VAR)) { 3204 char eflags_str[VarEvalFlags_ToStringSize]; 3205 char vflags_str[VarFlags_ToStringSize]; 3206 const char *quot = st.newVal == var_Error ? "" : "\""; 3207 const char *newVal = st.newVal == var_Error ? "error" : st.newVal; 3208 3209 VAR_DEBUG("Result of ${%s:%.*s} is %s%s%s (%s, %s)\n", 3210 st.v->name, (int)(p - mod), mod, quot, newVal, quot, 3211 Enum_FlagsToString(eflags_str, sizeof eflags_str, 3212 st.eflags, VarEvalFlags_ToStringSpecs), 3213 Enum_FlagsToString(vflags_str, sizeof vflags_str, 3214 st.v->flags, VarFlags_ToStringSpecs)); 3215 } 3216 3217 if (st.newVal != st.val) { 3218 if (*freePtr) { 3219 free(st.val); 3220 *freePtr = NULL; 3221 } 3222 st.val = st.newVal; 3223 if (st.val != var_Error && st.val != varNoError) { 3224 *freePtr = st.val; 3225 } 3226 } 3227 if (*p == '\0' && st.endc != '\0') { 3228 Error("Unclosed variable specification (expecting '%c') " 3229 "for \"%s\" (value \"%s\") modifier %c", 3230 st.endc, st.v->name, st.val, *mod); 3231 } else if (*p == ':') { 3232 p++; 3233 } 3234 mod = p; 3235 } 3236 out: 3237 *pp = p; 3238 assert(st.val != NULL); /* Use var_Error or varNoError instead. */ 3239 return st.val; 3240 3241 bad_modifier: 3242 Error("Bad modifier `:%.*s' for %s", 3243 (int)strcspn(mod, ":)}"), mod, st.v->name); 3244 3245 cleanup: 3246 *pp = p; 3247 if (st.missing_delim != '\0') 3248 Error("Unfinished modifier for %s ('%c' missing)", 3249 st.v->name, st.missing_delim); 3250 free(*freePtr); 3251 *freePtr = NULL; 3252 return var_Error; 3253 } 3254 3255 static Boolean 3256 VarIsDynamic(GNode *ctxt, const char *varname, size_t namelen) 3257 { 3258 if ((namelen == 1 || 3259 (namelen == 2 && (varname[1] == 'F' || varname[1] == 'D'))) && 3260 (ctxt == VAR_CMD || ctxt == VAR_GLOBAL)) 3261 { 3262 /* 3263 * If substituting a local variable in a non-local context, 3264 * assume it's for dynamic source stuff. We have to handle 3265 * this specially and return the longhand for the variable 3266 * with the dollar sign escaped so it makes it back to the 3267 * caller. Only four of the local variables are treated 3268 * specially as they are the only four that will be set 3269 * when dynamic sources are expanded. 3270 */ 3271 switch (varname[0]) { 3272 case '@': 3273 case '%': 3274 case '*': 3275 case '!': 3276 return TRUE; 3277 } 3278 return FALSE; 3279 } 3280 3281 if ((namelen == 7 || namelen == 8) && varname[0] == '.' && 3282 ch_isupper(varname[1]) && (ctxt == VAR_CMD || ctxt == VAR_GLOBAL)) 3283 { 3284 return strcmp(varname, ".TARGET") == 0 || 3285 strcmp(varname, ".ARCHIVE") == 0 || 3286 strcmp(varname, ".PREFIX") == 0 || 3287 strcmp(varname, ".MEMBER") == 0; 3288 } 3289 3290 return FALSE; 3291 } 3292 3293 static const char * 3294 ShortVarValue(char varname, const GNode *ctxt, VarEvalFlags eflags) 3295 { 3296 if (ctxt == VAR_CMD || ctxt == VAR_GLOBAL) { 3297 /* 3298 * If substituting a local variable in a non-local context, 3299 * assume it's for dynamic source stuff. We have to handle 3300 * this specially and return the longhand for the variable 3301 * with the dollar sign escaped so it makes it back to the 3302 * caller. Only four of the local variables are treated 3303 * specially as they are the only four that will be set 3304 * when dynamic sources are expanded. 3305 */ 3306 switch (varname) { 3307 case '@': 3308 return "$(.TARGET)"; 3309 case '%': 3310 return "$(.MEMBER)"; 3311 case '*': 3312 return "$(.PREFIX)"; 3313 case '!': 3314 return "$(.ARCHIVE)"; 3315 } 3316 } 3317 return eflags & VARE_UNDEFERR ? var_Error : varNoError; 3318 } 3319 3320 /* Parse a variable name, until the end character or a colon, whichever 3321 * comes first. */ 3322 static char * 3323 ParseVarname(const char **pp, char startc, char endc, 3324 GNode *ctxt, VarEvalFlags eflags, 3325 size_t *out_varname_len) 3326 { 3327 Buffer buf; 3328 const char *p = *pp; 3329 int depth = 1; 3330 3331 Buf_Init(&buf, 0); 3332 3333 while (*p != '\0') { 3334 /* Track depth so we can spot parse errors. */ 3335 if (*p == startc) 3336 depth++; 3337 if (*p == endc) { 3338 if (--depth == 0) 3339 break; 3340 } 3341 if (*p == ':' && depth == 1) 3342 break; 3343 3344 /* A variable inside a variable, expand. */ 3345 if (*p == '$') { 3346 void *freeIt; 3347 const char *rval; 3348 (void)Var_Parse(&p, ctxt, eflags, &rval, &freeIt); 3349 /* TODO: handle errors */ 3350 Buf_AddStr(&buf, rval); 3351 free(freeIt); 3352 } else { 3353 Buf_AddByte(&buf, *p); 3354 p++; 3355 } 3356 } 3357 *pp = p; 3358 *out_varname_len = Buf_Size(&buf); 3359 return Buf_Destroy(&buf, FALSE); 3360 } 3361 3362 static Boolean 3363 ValidShortVarname(char varname, const char *start) 3364 { 3365 switch (varname) { 3366 case '\0': 3367 case ')': 3368 case '}': 3369 case ':': 3370 case '$': 3371 break; 3372 default: 3373 return TRUE; 3374 } 3375 3376 if (!DEBUG(LINT)) 3377 return FALSE; 3378 3379 if (varname == '$') 3380 Parse_Error(PARSE_FATAL, 3381 "To escape a dollar, use \\$, not $$, at \"%s\"", start); 3382 else if (varname == '\0') 3383 Parse_Error(PARSE_FATAL, "Dollar followed by nothing"); 3384 else 3385 Parse_Error(PARSE_FATAL, 3386 "Invalid variable name '%c', at \"%s\"", varname, start); 3387 3388 return FALSE; 3389 } 3390 3391 /*- 3392 *----------------------------------------------------------------------- 3393 * Var_Parse -- 3394 * Given the start of a variable expression (such as $v, $(VAR), 3395 * ${VAR:Mpattern}), extract the variable name, possibly some 3396 * modifiers and find its value by applying the modifiers to the 3397 * original value. 3398 * 3399 * Input: 3400 * str The string to parse 3401 * ctxt The context for the variable 3402 * flags VARE_UNDEFERR if undefineds are an error 3403 * VARE_WANTRES if we actually want the result 3404 * VARE_ASSIGN if we are in a := assignment 3405 * lengthPtr OUT: The length of the specification 3406 * freePtr OUT: Non-NULL if caller should free *freePtr 3407 * 3408 * Results: 3409 * Returns the value of the variable expression, never NULL. 3410 * var_Error if there was a parse error and VARE_UNDEFERR was set. 3411 * varNoError if there was a parse error and VARE_UNDEFERR was not set. 3412 * 3413 * Parsing should continue at str + *lengthPtr. 3414 * TODO: Document the value of *lengthPtr on parse errors. It might be 3415 * 0, or +1, or the index of the parse error, or the guessed end of the 3416 * variable expression. 3417 * 3418 * If var_Error is returned, a diagnostic may or may not have been 3419 * printed. XXX: This is inconsistent. 3420 * 3421 * If varNoError is returned, a diagnostic may or may not have been 3422 * printed. XXX: This is inconsistent, and as of 2020-09-08, returning 3423 * varNoError is even used to return a regular, non-error empty string. 3424 * 3425 * After using the returned value, *freePtr must be freed, preferably 3426 * using bmake_free since it is NULL in most cases. 3427 * 3428 * Side Effects: 3429 * Any effects from the modifiers, such as :!cmd! or ::=value. 3430 *----------------------------------------------------------------------- 3431 */ 3432 /* coverity[+alloc : arg-*4] */ 3433 VarParseErrors 3434 Var_Parse(const char **pp, GNode *ctxt, VarEvalFlags eflags, 3435 const char **out_val, void **freePtr) 3436 { 3437 const char *const start = *pp; 3438 const char *p; 3439 Boolean haveModifier; /* TRUE if have modifiers for the variable */ 3440 char startc; /* Starting character if variable in parens 3441 * or braces */ 3442 char endc; /* Ending character if variable in parens 3443 * or braces */ 3444 Boolean dynamic; /* TRUE if the variable is local and we're 3445 * expanding it in a non-local context. This 3446 * is done to support dynamic sources. The 3447 * result is just the expression, unaltered */ 3448 const char *extramodifiers; 3449 Var *v; 3450 char *nstr; 3451 char eflags_str[VarEvalFlags_ToStringSize]; 3452 3453 VAR_DEBUG("%s: %s with %s\n", __func__, start, 3454 Enum_FlagsToString(eflags_str, sizeof eflags_str, eflags, 3455 VarEvalFlags_ToStringSpecs)); 3456 3457 *freePtr = NULL; 3458 extramodifiers = NULL; /* extra modifiers to apply first */ 3459 dynamic = FALSE; 3460 3461 /* Appease GCC, which thinks that the variable might not be 3462 * initialized. */ 3463 endc = '\0'; 3464 3465 startc = start[1]; 3466 if (startc != '(' && startc != '{') { 3467 char name[2]; 3468 3469 /* 3470 * If it's not bounded by braces of some sort, life is much simpler. 3471 * We just need to check for the first character and return the 3472 * value if it exists. 3473 */ 3474 3475 if (!ValidShortVarname(startc, start)) { 3476 (*pp)++; 3477 *out_val = var_Error; 3478 return VPE_PARSE_MSG; 3479 } 3480 3481 name[0] = startc; 3482 name[1] = '\0'; 3483 v = VarFind(name, ctxt, FIND_ENV | FIND_GLOBAL | FIND_CMD); 3484 if (v == NULL) { 3485 *pp += 2; 3486 3487 *out_val = ShortVarValue(startc, ctxt, eflags); 3488 if (DEBUG(LINT) && *out_val == var_Error) { 3489 Parse_Error(PARSE_FATAL, "Variable \"%s\" is undefined", name); 3490 return VPE_UNDEF_MSG; 3491 } 3492 return eflags & VARE_UNDEFERR ? VPE_UNDEF_SILENT : VPE_OK; 3493 } else { 3494 haveModifier = FALSE; 3495 p = start + 1; 3496 } 3497 } else { 3498 size_t namelen; 3499 char *varname; 3500 3501 endc = startc == '(' ? ')' : '}'; 3502 3503 p = start + 2; 3504 varname = ParseVarname(&p, startc, endc, ctxt, eflags, &namelen); 3505 3506 if (*p == ':') { 3507 haveModifier = TRUE; 3508 } else if (*p == endc) { 3509 haveModifier = FALSE; 3510 } else { 3511 Parse_Error(PARSE_FATAL, "Unclosed variable \"%s\"", varname); 3512 *pp = p; 3513 free(varname); 3514 *out_val = var_Error; 3515 return VPE_PARSE_MSG; 3516 } 3517 3518 v = VarFind(varname, ctxt, FIND_ENV | FIND_GLOBAL | FIND_CMD); 3519 3520 /* At this point, p points just after the variable name, 3521 * either at ':' or at endc. */ 3522 3523 /* 3524 * Check also for bogus D and F forms of local variables since we're 3525 * in a local context and the name is the right length. 3526 */ 3527 if (v == NULL && ctxt != VAR_CMD && ctxt != VAR_GLOBAL && 3528 namelen == 2 && (varname[1] == 'F' || varname[1] == 'D') && 3529 strchr("@%?*!<>", varname[0]) != NULL) 3530 { 3531 /* 3532 * Well, it's local -- go look for it. 3533 */ 3534 char name[] = { varname[0], '\0' }; 3535 v = VarFind(name, ctxt, 0); 3536 3537 if (v != NULL) { 3538 if (varname[1] == 'D') { 3539 extramodifiers = "H:"; 3540 } else { /* F */ 3541 extramodifiers = "T:"; 3542 } 3543 } 3544 } 3545 3546 if (v == NULL) { 3547 dynamic = VarIsDynamic(ctxt, varname, namelen); 3548 3549 if (!haveModifier) { 3550 p++; /* skip endc */ 3551 *pp = p; 3552 if (dynamic) { 3553 char *pstr = bmake_strsedup(start, p); 3554 *freePtr = pstr; 3555 free(varname); 3556 *out_val = pstr; 3557 return VPE_OK; 3558 } 3559 3560 if ((eflags & VARE_UNDEFERR) && (eflags & VARE_WANTRES) && 3561 DEBUG(LINT)) 3562 { 3563 Parse_Error(PARSE_FATAL, "Variable \"%s\" is undefined", 3564 varname); 3565 free(varname); 3566 *out_val = var_Error; 3567 return VPE_UNDEF_MSG; 3568 } 3569 3570 if (eflags & VARE_UNDEFERR) { 3571 free(varname); 3572 *out_val = var_Error; 3573 return VPE_UNDEF_SILENT; 3574 } 3575 3576 free(varname); 3577 *out_val = varNoError; 3578 return VPE_OK; 3579 } 3580 3581 /* The variable expression is based on an undefined variable. 3582 * Nevertheless it needs a Var, for modifiers that access the 3583 * variable name, such as :L or :?, and for modifiers that access 3584 * the variable flags (VAR_JUNK, VAR_KEEP). 3585 * 3586 * Most modifiers leave this expression in the "undefined" state 3587 * (VAR_JUNK), only a few modifiers like :D, :U, :L, :P turn this 3588 * undefined expression into a defined expression (VAR_KEEP). 3589 * 3590 * At the end, after applying all modifiers, if the expression 3591 * is still !VAR_KEEP, Var_Parse will return var_Error. */ 3592 v = bmake_malloc(sizeof(Var)); 3593 v->name = varname; 3594 Buf_Init(&v->val, 1); 3595 v->flags = VAR_JUNK; 3596 } else 3597 free(varname); 3598 } 3599 3600 if (v->flags & VAR_IN_USE) { 3601 Fatal("Variable %s is recursive.", v->name); 3602 /*NOTREACHED*/ 3603 } else { 3604 v->flags |= VAR_IN_USE; 3605 } 3606 3607 /* 3608 * Before doing any modification, we have to make sure the value 3609 * has been fully expanded. If it looks like recursion might be 3610 * necessary (there's a dollar sign somewhere in the variable's value) 3611 * we just call Var_Subst to do any other substitutions that are 3612 * necessary. Note that the value returned by Var_Subst will have 3613 * been dynamically-allocated, so it will need freeing when we 3614 * return. 3615 */ 3616 nstr = Buf_GetAll(&v->val, NULL); 3617 if (strchr(nstr, '$') != NULL && (eflags & VARE_WANTRES)) { 3618 VarEvalFlags nested_eflags = eflags; 3619 if (DEBUG(LINT)) 3620 nested_eflags &= ~(unsigned)VARE_UNDEFERR; 3621 nstr = Var_Subst(nstr, ctxt, nested_eflags); 3622 *freePtr = nstr; 3623 } 3624 3625 v->flags &= ~(unsigned)VAR_IN_USE; 3626 3627 if (haveModifier || extramodifiers != NULL) { 3628 void *extraFree; 3629 3630 extraFree = NULL; 3631 if (extramodifiers != NULL) { 3632 const char *em = extramodifiers; 3633 nstr = ApplyModifiers(&em, nstr, '(', ')', 3634 v, ctxt, eflags, &extraFree); 3635 } 3636 3637 if (haveModifier) { 3638 /* Skip initial colon. */ 3639 p++; 3640 3641 nstr = ApplyModifiers(&p, nstr, startc, endc, 3642 v, ctxt, eflags, freePtr); 3643 free(extraFree); 3644 } else { 3645 *freePtr = extraFree; 3646 } 3647 } 3648 3649 if (*p != '\0') /* Skip past endc if possible. */ 3650 p++; 3651 3652 *pp = p; 3653 3654 if (v->flags & VAR_FROM_ENV) { 3655 /* Free the environment variable now since we own it, 3656 * but don't free the variable value if it will be returned. */ 3657 Boolean keepValue = nstr == Buf_GetAll(&v->val, NULL); 3658 if (keepValue) 3659 *freePtr = nstr; 3660 (void)VarFreeEnv(v, !keepValue); 3661 3662 } else if (v->flags & VAR_JUNK) { 3663 /* 3664 * Perform any freeing needed and set *freePtr to NULL so the caller 3665 * doesn't try to free a static pointer. 3666 * If VAR_KEEP is also set then we want to keep str(?) as is. 3667 */ 3668 if (!(v->flags & VAR_KEEP)) { 3669 if (*freePtr != NULL) { 3670 free(*freePtr); 3671 *freePtr = NULL; 3672 } 3673 if (dynamic) { 3674 nstr = bmake_strsedup(start, p); 3675 *freePtr = nstr; 3676 } else { 3677 nstr = (eflags & VARE_UNDEFERR) ? var_Error : varNoError; 3678 } 3679 } 3680 if (nstr != Buf_GetAll(&v->val, NULL)) 3681 Buf_Destroy(&v->val, TRUE); 3682 free(v->name); 3683 free(v); 3684 } 3685 *out_val = nstr; 3686 return VPE_OK; /* TODO: may also be errors */ 3687 } 3688 3689 /* Substitute for all variables in the given string in the given context. 3690 * 3691 * If eflags & VARE_UNDEFERR, Parse_Error will be called when an undefined 3692 * variable is encountered. 3693 * 3694 * If eflags & VARE_WANTRES, any effects from the modifiers, such as ::=, 3695 * :sh or !cmd! take place. 3696 * 3697 * Input: 3698 * str the string which to substitute 3699 * ctxt the context wherein to find variables 3700 * eflags VARE_UNDEFERR if undefineds are an error 3701 * VARE_WANTRES if we actually want the result 3702 * VARE_ASSIGN if we are in a := assignment 3703 * 3704 * Results: 3705 * The resulting string. 3706 */ 3707 char * 3708 Var_Subst(const char *str, GNode *ctxt, VarEvalFlags eflags) 3709 { 3710 Buffer buf; /* Buffer for forming things */ 3711 Boolean trailingBackslash; 3712 3713 /* Set true if an error has already been reported, 3714 * to prevent a plethora of messages when recursing */ 3715 static Boolean errorReported; 3716 3717 Buf_Init(&buf, 0); 3718 errorReported = FALSE; 3719 trailingBackslash = FALSE; /* variable ends in \ */ 3720 3721 while (*str) { 3722 if (*str == '\n' && trailingBackslash) 3723 Buf_AddByte(&buf, ' '); 3724 3725 if (*str == '$' && str[1] == '$') { 3726 /* 3727 * A dollar sign may be escaped with another dollar sign. 3728 * In such a case, we skip over the escape character and store the 3729 * dollar sign into the buffer directly. 3730 */ 3731 if (save_dollars && (eflags & VARE_ASSIGN)) 3732 Buf_AddByte(&buf, '$'); 3733 Buf_AddByte(&buf, '$'); 3734 str += 2; 3735 } else if (*str != '$') { 3736 /* 3737 * Skip as many characters as possible -- either to the end of 3738 * the string or to the next dollar sign (variable expression). 3739 */ 3740 const char *cp; 3741 3742 for (cp = str++; *str != '$' && *str != '\0'; str++) 3743 continue; 3744 Buf_AddBytesBetween(&buf, cp, str); 3745 } else { 3746 const char *nested_str = str; 3747 void *freeIt; 3748 const char *val; 3749 (void)Var_Parse(&nested_str, ctxt, eflags, &val, &freeIt); 3750 /* TODO: handle errors */ 3751 3752 if (val == var_Error || val == varNoError) { 3753 /* 3754 * If performing old-time variable substitution, skip over 3755 * the variable and continue with the substitution. Otherwise, 3756 * store the dollar sign and advance str so we continue with 3757 * the string... 3758 */ 3759 if (oldVars) { 3760 str = nested_str; 3761 } else if ((eflags & VARE_UNDEFERR) || val == var_Error) { 3762 /* 3763 * If variable is undefined, complain and skip the 3764 * variable. The complaint will stop us from doing anything 3765 * when the file is parsed. 3766 */ 3767 if (!errorReported) { 3768 Parse_Error(PARSE_FATAL, "Undefined variable \"%.*s\"", 3769 (int)(size_t)(nested_str - str), str); 3770 } 3771 str = nested_str; 3772 errorReported = TRUE; 3773 } else { 3774 Buf_AddByte(&buf, *str); 3775 str++; 3776 } 3777 } else { 3778 size_t val_len; 3779 3780 str = nested_str; 3781 3782 val_len = strlen(val); 3783 Buf_AddBytes(&buf, val, val_len); 3784 trailingBackslash = val_len > 0 && val[val_len - 1] == '\\'; 3785 } 3786 free(freeIt); 3787 freeIt = NULL; 3788 } 3789 } 3790 3791 return Buf_DestroyCompact(&buf); 3792 } 3793 3794 /* Initialize the module. */ 3795 void 3796 Var_Init(void) 3797 { 3798 VAR_INTERNAL = Targ_NewGN("Internal"); 3799 VAR_GLOBAL = Targ_NewGN("Global"); 3800 VAR_CMD = Targ_NewGN("Command"); 3801 } 3802 3803 3804 void 3805 Var_End(void) 3806 { 3807 Var_Stats(); 3808 } 3809 3810 void 3811 Var_Stats(void) 3812 { 3813 Hash_DebugStats(&VAR_GLOBAL->context, "VAR_GLOBAL"); 3814 } 3815 3816 3817 /****************** PRINT DEBUGGING INFO *****************/ 3818 static void 3819 VarPrintVar(void *vp, void *data MAKE_ATTR_UNUSED) 3820 { 3821 Var *v = (Var *)vp; 3822 fprintf(debug_file, "%-16s = %s\n", v->name, Buf_GetAll(&v->val, NULL)); 3823 } 3824 3825 /* Print all variables in a context, unordered. */ 3826 void 3827 Var_Dump(GNode *ctxt) 3828 { 3829 Hash_ForEach(&ctxt->context, VarPrintVar, NULL); 3830 } 3831