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