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