1/* 2 * Copyright (c) 1988, 1989, 1990, 1993 3 * The Regents of the University of California. All rights reserved. 4 * Copyright (c) 1989 by Berkeley Softworks 5 * 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. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * @(#)var.c 8.3 (Berkeley) 3/19/94 39 */ 40 41#include <sys/cdefs.h>
| 1/* 2 * Copyright (c) 1988, 1989, 1990, 1993 3 * The Regents of the University of California. All rights reserved. 4 * Copyright (c) 1989 by Berkeley Softworks 5 * 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. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * @(#)var.c 8.3 (Berkeley) 3/19/94 39 */ 40 41#include <sys/cdefs.h>
|
42__FBSDID("$FreeBSD: head/usr.bin/make/var.c 105895 2002-10-24 20:37:58Z jmallett $");
| 42__FBSDID("$FreeBSD: head/usr.bin/make/var.c 106106 2002-10-28 23:33:57Z jmallett $");
|
43 44/*- 45 * var.c -- 46 * Variable-handling functions 47 * 48 * Interface: 49 * Var_Set Set the value of a variable in the given 50 * context. The variable is created if it doesn't 51 * yet exist. The value and variable name need not 52 * be preserved. 53 * 54 * Var_Append Append more characters to an existing variable 55 * in the given context. The variable needn't 56 * exist already -- it will be created if it doesn't. 57 * A space is placed between the old value and the 58 * new one. 59 * 60 * Var_Exists See if a variable exists. 61 * 62 * Var_Value Return the value of a variable in a context or 63 * NULL if the variable is undefined. 64 * 65 * Var_Subst Substitute named variable, or all variables if 66 * NULL in a string using 67 * the given context as the top-most one. If the 68 * third argument is non-zero, Parse_Error is 69 * called if any variables are undefined. 70 * 71 * Var_Parse Parse a variable expansion from a string and 72 * return the result and the number of characters 73 * consumed. 74 * 75 * Var_Delete Delete a variable in a context. 76 * 77 * Var_Init Initialize this module. 78 * 79 * Debugging: 80 * Var_Dump Print out all variables defined in the given 81 * context. 82 * 83 * XXX: There's a lot of duplication in these functions. 84 */ 85 86#include <ctype.h> 87#include <sys/types.h> 88#include <regex.h> 89#include <stdlib.h> 90#include "make.h" 91#include "buf.h"
| 43 44/*- 45 * var.c -- 46 * Variable-handling functions 47 * 48 * Interface: 49 * Var_Set Set the value of a variable in the given 50 * context. The variable is created if it doesn't 51 * yet exist. The value and variable name need not 52 * be preserved. 53 * 54 * Var_Append Append more characters to an existing variable 55 * in the given context. The variable needn't 56 * exist already -- it will be created if it doesn't. 57 * A space is placed between the old value and the 58 * new one. 59 * 60 * Var_Exists See if a variable exists. 61 * 62 * Var_Value Return the value of a variable in a context or 63 * NULL if the variable is undefined. 64 * 65 * Var_Subst Substitute named variable, or all variables if 66 * NULL in a string using 67 * the given context as the top-most one. If the 68 * third argument is non-zero, Parse_Error is 69 * called if any variables are undefined. 70 * 71 * Var_Parse Parse a variable expansion from a string and 72 * return the result and the number of characters 73 * consumed. 74 * 75 * Var_Delete Delete a variable in a context. 76 * 77 * Var_Init Initialize this module. 78 * 79 * Debugging: 80 * Var_Dump Print out all variables defined in the given 81 * context. 82 * 83 * XXX: There's a lot of duplication in these functions. 84 */ 85 86#include <ctype.h> 87#include <sys/types.h> 88#include <regex.h> 89#include <stdlib.h> 90#include "make.h" 91#include "buf.h"
|
| 92#include "var.h"
|
92 93/* 94 * This is a harmless return value for Var_Parse that can be used by Var_Subst 95 * to determine if there was an error in parsing -- easier than returning 96 * a flag, as things outside this module don't give a hoot. 97 */ 98char var_Error[] = ""; 99 100/* 101 * Similar to var_Error, but returned when the 'err' flag for Var_Parse is 102 * set false. Why not just use a constant? Well, gcc likes to condense 103 * identical string instances... 104 */ 105static char varNoError[] = ""; 106 107/* 108 * Internally, variables are contained in four different contexts. 109 * 1) the environment. They may not be changed. If an environment 110 * variable is appended-to, the result is placed in the global 111 * context. 112 * 2) the global context. Variables set in the Makefile are located in 113 * the global context. It is the penultimate context searched when 114 * substituting. 115 * 3) the command-line context. All variables set on the command line 116 * are placed in this context. They are UNALTERABLE once placed here. 117 * 4) the local context. Each target has associated with it a context 118 * list. On this list are located the structures describing such 119 * local variables as $(@) and $(*) 120 * The four contexts are searched in the reverse order from which they are 121 * listed. 122 */ 123GNode *VAR_GLOBAL; /* variables from the makefile */ 124GNode *VAR_CMD; /* variables defined on the command-line */ 125 126static Lst allVars; /* List of all variables */ 127 128#define FIND_CMD 0x1 /* look in VAR_CMD when searching */ 129#define FIND_GLOBAL 0x2 /* look in VAR_GLOBAL as well */ 130#define FIND_ENV 0x4 /* look in the environment also */ 131
| 93 94/* 95 * This is a harmless return value for Var_Parse that can be used by Var_Subst 96 * to determine if there was an error in parsing -- easier than returning 97 * a flag, as things outside this module don't give a hoot. 98 */ 99char var_Error[] = ""; 100 101/* 102 * Similar to var_Error, but returned when the 'err' flag for Var_Parse is 103 * set false. Why not just use a constant? Well, gcc likes to condense 104 * identical string instances... 105 */ 106static char varNoError[] = ""; 107 108/* 109 * Internally, variables are contained in four different contexts. 110 * 1) the environment. They may not be changed. If an environment 111 * variable is appended-to, the result is placed in the global 112 * context. 113 * 2) the global context. Variables set in the Makefile are located in 114 * the global context. It is the penultimate context searched when 115 * substituting. 116 * 3) the command-line context. All variables set on the command line 117 * are placed in this context. They are UNALTERABLE once placed here. 118 * 4) the local context. Each target has associated with it a context 119 * list. On this list are located the structures describing such 120 * local variables as $(@) and $(*) 121 * The four contexts are searched in the reverse order from which they are 122 * listed. 123 */ 124GNode *VAR_GLOBAL; /* variables from the makefile */ 125GNode *VAR_CMD; /* variables defined on the command-line */ 126 127static Lst allVars; /* List of all variables */ 128 129#define FIND_CMD 0x1 /* look in VAR_CMD when searching */ 130#define FIND_GLOBAL 0x2 /* look in VAR_GLOBAL as well */ 131#define FIND_ENV 0x4 /* look in the environment also */ 132
|
132typedef struct Var { 133 char *name; /* the variable's name */ 134 Buffer val; /* its value */ 135 int flags; /* miscellaneous status flags */ 136#define VAR_IN_USE 1 /* Variable's value currently being used. 137 * Used to avoid recursion */ 138#define VAR_FROM_ENV 2 /* Variable comes from the environment */ 139#define VAR_JUNK 4 /* Variable is a junk variable that 140 * should be destroyed when done with 141 * it. Used by Var_Parse for undefined, 142 * modified variables */ 143} Var; 144 145/* Var*Pattern flags */ 146#define VAR_SUB_GLOBAL 0x01 /* Apply substitution globally */ 147#define VAR_SUB_ONE 0x02 /* Apply substitution to one word */ 148#define VAR_SUB_MATCHED 0x04 /* There was a match */ 149#define VAR_MATCH_START 0x08 /* Match at start of word */ 150#define VAR_MATCH_END 0x10 /* Match at end of word */ 151#define VAR_NOSUBST 0x20 /* don't expand vars in VarGetPattern */ 152 153typedef struct { 154 char *lhs; /* String to match */ 155 int leftLen; /* Length of string */ 156 char *rhs; /* Replacement string (w/ &'s removed) */ 157 int rightLen; /* Length of replacement */ 158 int flags; 159} VarPattern; 160 161typedef struct { 162 regex_t re; 163 int nsub; 164 regmatch_t *matches; 165 char *replace; 166 int flags; 167} VarREPattern; 168
| |
169static int VarCmp(void *, void *); 170static void VarPossiblyExpand(char **, GNode *); 171static Var *VarFind(char *, GNode *, int); 172static void VarAdd(char *, char *, GNode *); 173static void VarDelete(void *);
| 133static int VarCmp(void *, void *); 134static void VarPossiblyExpand(char **, GNode *); 135static Var *VarFind(char *, GNode *, int); 136static void VarAdd(char *, char *, GNode *); 137static void VarDelete(void *);
|
174static Boolean VarHead(char *, Boolean, Buffer, void *); 175static Boolean VarTail(char *, Boolean, Buffer, void *); 176static Boolean VarSuffix(char *, Boolean, Buffer, void *); 177static Boolean VarRoot(char *, Boolean, Buffer, void *); 178static Boolean VarMatch(char *, Boolean, Buffer, void *); 179#ifdef SYSVVARSUB 180static Boolean VarSYSVMatch(char *, Boolean, Buffer, void *); 181#endif 182static Boolean VarNoMatch(char *, Boolean, Buffer, void *); 183static void VarREError(int, regex_t *, const char *); 184static Boolean VarRESubstitute(char *, Boolean, Buffer, void *); 185static Boolean VarSubstitute(char *, Boolean, Buffer, void *);
| |
186static char *VarGetPattern(GNode *, int, char **, int, int *, int *, 187 VarPattern *);
| 138static char *VarGetPattern(GNode *, int, char **, int, int *, int *, 139 VarPattern *);
|
188static char *VarQuote(char *); 189static char *VarModify(char *, Boolean (*)(char *, Boolean, Buffer, void *),
| 140static char *VarQuote(const char *); 141static char *VarModify(char *, 142 Boolean (*)(const char *, Boolean, Buffer, void *),
|
190 void *); 191static int VarPrintVar(void *, void *); 192 193/*- 194 *----------------------------------------------------------------------- 195 * VarCmp -- 196 * See if the given variable matches the named one. Called from 197 * Lst_Find when searching for a variable of a given name. 198 * 199 * Results: 200 * 0 if they match. non-zero otherwise. 201 * 202 * Side Effects: 203 * none 204 *----------------------------------------------------------------------- 205 */ 206static int 207VarCmp (void *v, void *name) 208{ 209 return (strcmp ((char *) name, ((Var *) v)->name)); 210} 211 212/*- 213 *----------------------------------------------------------------------- 214 * VarPossiblyExpand -- 215 * Expand a variable name's embedded variables in the given context. 216 * 217 * Results: 218 * The contents of name, possibly expanded. 219 * 220 * Side Effects: 221 * The caller must free the new contents or old contents of name. 222 *----------------------------------------------------------------------- 223 */ 224static void 225VarPossiblyExpand(char **name, GNode *ctxt) 226{ 227 if (strchr(*name, '$') != NULL) 228 *name = Var_Subst(NULL, *name, ctxt, 0); 229 else 230 *name = estrdup(*name); 231} 232 233/*- 234 *----------------------------------------------------------------------- 235 * VarFind -- 236 * Find the given variable in the given context and any other contexts 237 * indicated. 238 * 239 * Flags: 240 * FIND_GLOBAL set means look in the VAR_GLOBAL context too 241 * FIND_CMD set means to look in the VAR_CMD context too 242 * FIND_ENV set means to look in the environment 243 * 244 * Results: 245 * A pointer to the structure describing the desired variable or 246 * NULL if the variable does not exist. 247 * 248 * Side Effects: 249 * None 250 *----------------------------------------------------------------------- 251 */ 252static Var * 253VarFind (char *name, GNode *ctxt, int flags) 254{ 255 Boolean localCheckEnvFirst; 256 LstNode var; 257 Var *v; 258 259 /* 260 * If the variable name begins with a '.', it could very well be one of 261 * the local ones. We check the name against all the local variables 262 * and substitute the short version in for 'name' if it matches one of 263 * them. 264 */ 265 if (*name == '.' && isupper((unsigned char) name[1])) 266 switch (name[1]) { 267 case 'A': 268 if (!strcmp(name, ".ALLSRC")) 269 name = ALLSRC; 270 if (!strcmp(name, ".ARCHIVE")) 271 name = ARCHIVE; 272 break; 273 case 'I': 274 if (!strcmp(name, ".IMPSRC")) 275 name = IMPSRC; 276 break; 277 case 'M': 278 if (!strcmp(name, ".MEMBER")) 279 name = MEMBER; 280 break; 281 case 'O': 282 if (!strcmp(name, ".OODATE")) 283 name = OODATE; 284 break; 285 case 'P': 286 if (!strcmp(name, ".PREFIX")) 287 name = PREFIX; 288 break; 289 case 'T': 290 if (!strcmp(name, ".TARGET")) 291 name = TARGET; 292 break; 293 } 294 295 /* 296 * Note whether this is one of the specific variables we were told through 297 * the -E flag to use environment-variable-override for. 298 */ 299 if (Lst_Find (envFirstVars, (void *)name, 300 (int (*)(void *, void *)) strcmp) != NULL) 301 { 302 localCheckEnvFirst = TRUE; 303 } else { 304 localCheckEnvFirst = FALSE; 305 } 306 307 /* 308 * First look for the variable in the given context. If it's not there, 309 * look for it in VAR_CMD, VAR_GLOBAL and the environment, in that order, 310 * depending on the FIND_* flags in 'flags' 311 */ 312 var = Lst_Find (ctxt->context, (void *)name, VarCmp); 313 314 if ((var == NULL) && (flags & FIND_CMD) && (ctxt != VAR_CMD)) { 315 var = Lst_Find (VAR_CMD->context, (void *)name, VarCmp); 316 } 317 if ((var == NULL) && (flags & FIND_GLOBAL) && (ctxt != VAR_GLOBAL) && 318 !checkEnvFirst && !localCheckEnvFirst) 319 { 320 var = Lst_Find (VAR_GLOBAL->context, (void *)name, VarCmp); 321 } 322 if ((var == NULL) && (flags & FIND_ENV)) { 323 char *env; 324 325 if ((env = getenv (name)) != NULL) { 326 int len; 327 328 v = (Var *) emalloc(sizeof(Var)); 329 v->name = estrdup(name); 330 331 len = strlen(env); 332 333 v->val = Buf_Init(len); 334 Buf_AddBytes(v->val, len, (Byte *)env); 335 336 v->flags = VAR_FROM_ENV; 337 return (v); 338 } else if ((checkEnvFirst || localCheckEnvFirst) && 339 (flags & FIND_GLOBAL) && (ctxt != VAR_GLOBAL)) 340 { 341 var = Lst_Find (VAR_GLOBAL->context, (void *)name, VarCmp); 342 if (var == NULL) { 343 return ((Var *) NULL); 344 } else { 345 return ((Var *)Lst_Datum(var)); 346 } 347 } else { 348 return((Var *)NULL); 349 } 350 } else if (var == NULL) { 351 return ((Var *) NULL); 352 } else { 353 return ((Var *) Lst_Datum (var)); 354 } 355} 356 357/*- 358 *----------------------------------------------------------------------- 359 * VarAdd -- 360 * Add a new variable of name name and value val to the given context. 361 * 362 * Results: 363 * None 364 * 365 * Side Effects: 366 * The new variable is placed at the front of the given context 367 * The name and val arguments are duplicated so they may 368 * safely be freed. 369 *----------------------------------------------------------------------- 370 */ 371static void 372VarAdd (char *name, char *val, GNode *ctxt) 373{ 374 Var *v; 375 int len; 376 377 v = (Var *) emalloc (sizeof (Var)); 378 379 v->name = estrdup (name); 380 381 len = val ? strlen(val) : 0; 382 v->val = Buf_Init(len+1); 383 Buf_AddBytes(v->val, len, (Byte *)val); 384 385 v->flags = 0; 386 387 (void) Lst_AtFront (ctxt->context, (void *)v); 388 (void) Lst_AtEnd (allVars, (void *) v); 389 DEBUGF(VAR, ("%s:%s = %s\n", ctxt->name, name, val)); 390} 391 392 393/*- 394 *----------------------------------------------------------------------- 395 * VarDelete -- 396 * Delete a variable and all the space associated with it. 397 * 398 * Results: 399 * None 400 * 401 * Side Effects: 402 * None 403 *----------------------------------------------------------------------- 404 */ 405static void 406VarDelete(void *vp) 407{ 408 Var *v = (Var *) vp; 409 free(v->name); 410 Buf_Destroy(v->val, TRUE); 411 free(v); 412} 413 414 415 416/*- 417 *----------------------------------------------------------------------- 418 * Var_Delete -- 419 * Remove a variable from a context. 420 * 421 * Results: 422 * None. 423 * 424 * Side Effects: 425 * The Var structure is removed and freed. 426 * 427 *----------------------------------------------------------------------- 428 */ 429void 430Var_Delete(char *name, GNode *ctxt) 431{ 432 LstNode ln; 433 434 DEBUGF(VAR, ("%s:delete %s\n", ctxt->name, name)); 435 ln = Lst_Find(ctxt->context, (void *)name, VarCmp); 436 if (ln != NULL) { 437 Var *v; 438 439 v = (Var *)Lst_Datum(ln); 440 Lst_Remove(ctxt->context, ln); 441 ln = Lst_Member(allVars, v); 442 Lst_Remove(allVars, ln); 443 VarDelete((void *) v); 444 } 445} 446 447/*- 448 *----------------------------------------------------------------------- 449 * Var_Set -- 450 * Set the variable name to the value val in the given context. 451 * 452 * Results: 453 * None. 454 * 455 * Side Effects: 456 * If the variable doesn't yet exist, a new record is created for it. 457 * Else the old value is freed and the new one stuck in its place 458 * 459 * Notes: 460 * The variable is searched for only in its context before being 461 * created in that context. I.e. if the context is VAR_GLOBAL, 462 * only VAR_GLOBAL->context is searched. Likewise if it is VAR_CMD, only 463 * VAR_CMD->context is searched. This is done to avoid the literally 464 * thousands of unnecessary strcmp's that used to be done to 465 * set, say, $(@) or $(<). 466 *----------------------------------------------------------------------- 467 */ 468void 469Var_Set (char *name, char *val, GNode *ctxt) 470{ 471 Var *v; 472 473 /* 474 * We only look for a variable in the given context since anything set 475 * here will override anything in a lower context, so there's not much 476 * point in searching them all just to save a bit of memory... 477 */ 478 VarPossiblyExpand(&name, ctxt); 479 v = VarFind (name, ctxt, 0); 480 if (v == (Var *) NULL) { 481 VarAdd (name, val, ctxt); 482 } else { 483 Buf_Discard(v->val, Buf_Size(v->val)); 484 Buf_AddBytes(v->val, strlen(val), (Byte *)val); 485 486 DEBUGF(VAR, ("%s:%s = %s\n", ctxt->name, name, val)); 487 } 488 /* 489 * Any variables given on the command line are automatically exported 490 * to the environment (as per POSIX standard) 491 */ 492 if (ctxt == VAR_CMD) { 493 setenv(name, val, 1); 494 } 495 free(name); 496} 497 498/*- 499 *----------------------------------------------------------------------- 500 * Var_Append -- 501 * The variable of the given name has the given value appended to it in 502 * the given context. 503 * 504 * Results: 505 * None 506 * 507 * Side Effects: 508 * If the variable doesn't exist, it is created. Else the strings 509 * are concatenated (with a space in between). 510 * 511 * Notes: 512 * Only if the variable is being sought in the global context is the 513 * environment searched. 514 * XXX: Knows its calling circumstances in that if called with ctxt 515 * an actual target, it will only search that context since only 516 * a local variable could be being appended to. This is actually 517 * a big win and must be tolerated. 518 *----------------------------------------------------------------------- 519 */ 520void 521Var_Append (char *name, char *val, GNode *ctxt) 522{ 523 Var *v; 524 525 VarPossiblyExpand(&name, ctxt); 526 v = VarFind (name, ctxt, (ctxt == VAR_GLOBAL) ? FIND_ENV : 0); 527 528 if (v == (Var *) NULL) { 529 VarAdd (name, val, ctxt); 530 } else { 531 Buf_AddByte(v->val, (Byte)' '); 532 Buf_AddBytes(v->val, strlen(val), (Byte *)val); 533 534 DEBUGF(VAR, ("%s:%s = %s\n", ctxt->name, name, 535 (char *) Buf_GetAll(v->val, (int *)NULL))); 536 537 if (v->flags & VAR_FROM_ENV) { 538 /* 539 * If the original variable came from the environment, we 540 * have to install it in the global context (we could place 541 * it in the environment, but then we should provide a way to 542 * export other variables...) 543 */ 544 v->flags &= ~VAR_FROM_ENV; 545 Lst_AtFront(ctxt->context, (void *)v); 546 } 547 } 548 free(name); 549} 550 551/*- 552 *----------------------------------------------------------------------- 553 * Var_Exists -- 554 * See if the given variable exists. 555 * 556 * Results: 557 * TRUE if it does, FALSE if it doesn't 558 * 559 * Side Effects: 560 * None. 561 * 562 *----------------------------------------------------------------------- 563 */ 564Boolean 565Var_Exists(char *name, GNode *ctxt) 566{ 567 Var *v; 568 569 VarPossiblyExpand(&name, ctxt); 570 v = VarFind(name, ctxt, FIND_CMD|FIND_GLOBAL|FIND_ENV); 571 free(name); 572 573 if (v == (Var *)NULL) { 574 return(FALSE); 575 } else if (v->flags & VAR_FROM_ENV) { 576 free(v->name); 577 Buf_Destroy(v->val, TRUE); 578 free((char *)v); 579 } 580 return(TRUE); 581} 582 583/*- 584 *----------------------------------------------------------------------- 585 * Var_Value -- 586 * Return the value of the named variable in the given context 587 * 588 * Results: 589 * The value if the variable exists, NULL if it doesn't 590 * 591 * Side Effects: 592 * None 593 *----------------------------------------------------------------------- 594 */ 595char * 596Var_Value (char *name, GNode *ctxt, char **frp) 597{ 598 Var *v; 599 600 VarPossiblyExpand(&name, ctxt); 601 v = VarFind (name, ctxt, FIND_ENV | FIND_GLOBAL | FIND_CMD); 602 free(name); 603 *frp = NULL; 604 if (v != (Var *) NULL) { 605 char *p = ((char *)Buf_GetAll(v->val, (int *)NULL)); 606 if (v->flags & VAR_FROM_ENV) { 607 Buf_Destroy(v->val, FALSE); 608 free(v); 609 *frp = p; 610 } 611 return p; 612 } else { 613 return ((char *) NULL); 614 } 615} 616 617/*- 618 *-----------------------------------------------------------------------
| 143 void *); 144static int VarPrintVar(void *, void *); 145 146/*- 147 *----------------------------------------------------------------------- 148 * VarCmp -- 149 * See if the given variable matches the named one. Called from 150 * Lst_Find when searching for a variable of a given name. 151 * 152 * Results: 153 * 0 if they match. non-zero otherwise. 154 * 155 * Side Effects: 156 * none 157 *----------------------------------------------------------------------- 158 */ 159static int 160VarCmp (void *v, void *name) 161{ 162 return (strcmp ((char *) name, ((Var *) v)->name)); 163} 164 165/*- 166 *----------------------------------------------------------------------- 167 * VarPossiblyExpand -- 168 * Expand a variable name's embedded variables in the given context. 169 * 170 * Results: 171 * The contents of name, possibly expanded. 172 * 173 * Side Effects: 174 * The caller must free the new contents or old contents of name. 175 *----------------------------------------------------------------------- 176 */ 177static void 178VarPossiblyExpand(char **name, GNode *ctxt) 179{ 180 if (strchr(*name, '$') != NULL) 181 *name = Var_Subst(NULL, *name, ctxt, 0); 182 else 183 *name = estrdup(*name); 184} 185 186/*- 187 *----------------------------------------------------------------------- 188 * VarFind -- 189 * Find the given variable in the given context and any other contexts 190 * indicated. 191 * 192 * Flags: 193 * FIND_GLOBAL set means look in the VAR_GLOBAL context too 194 * FIND_CMD set means to look in the VAR_CMD context too 195 * FIND_ENV set means to look in the environment 196 * 197 * Results: 198 * A pointer to the structure describing the desired variable or 199 * NULL if the variable does not exist. 200 * 201 * Side Effects: 202 * None 203 *----------------------------------------------------------------------- 204 */ 205static Var * 206VarFind (char *name, GNode *ctxt, int flags) 207{ 208 Boolean localCheckEnvFirst; 209 LstNode var; 210 Var *v; 211 212 /* 213 * If the variable name begins with a '.', it could very well be one of 214 * the local ones. We check the name against all the local variables 215 * and substitute the short version in for 'name' if it matches one of 216 * them. 217 */ 218 if (*name == '.' && isupper((unsigned char) name[1])) 219 switch (name[1]) { 220 case 'A': 221 if (!strcmp(name, ".ALLSRC")) 222 name = ALLSRC; 223 if (!strcmp(name, ".ARCHIVE")) 224 name = ARCHIVE; 225 break; 226 case 'I': 227 if (!strcmp(name, ".IMPSRC")) 228 name = IMPSRC; 229 break; 230 case 'M': 231 if (!strcmp(name, ".MEMBER")) 232 name = MEMBER; 233 break; 234 case 'O': 235 if (!strcmp(name, ".OODATE")) 236 name = OODATE; 237 break; 238 case 'P': 239 if (!strcmp(name, ".PREFIX")) 240 name = PREFIX; 241 break; 242 case 'T': 243 if (!strcmp(name, ".TARGET")) 244 name = TARGET; 245 break; 246 } 247 248 /* 249 * Note whether this is one of the specific variables we were told through 250 * the -E flag to use environment-variable-override for. 251 */ 252 if (Lst_Find (envFirstVars, (void *)name, 253 (int (*)(void *, void *)) strcmp) != NULL) 254 { 255 localCheckEnvFirst = TRUE; 256 } else { 257 localCheckEnvFirst = FALSE; 258 } 259 260 /* 261 * First look for the variable in the given context. If it's not there, 262 * look for it in VAR_CMD, VAR_GLOBAL and the environment, in that order, 263 * depending on the FIND_* flags in 'flags' 264 */ 265 var = Lst_Find (ctxt->context, (void *)name, VarCmp); 266 267 if ((var == NULL) && (flags & FIND_CMD) && (ctxt != VAR_CMD)) { 268 var = Lst_Find (VAR_CMD->context, (void *)name, VarCmp); 269 } 270 if ((var == NULL) && (flags & FIND_GLOBAL) && (ctxt != VAR_GLOBAL) && 271 !checkEnvFirst && !localCheckEnvFirst) 272 { 273 var = Lst_Find (VAR_GLOBAL->context, (void *)name, VarCmp); 274 } 275 if ((var == NULL) && (flags & FIND_ENV)) { 276 char *env; 277 278 if ((env = getenv (name)) != NULL) { 279 int len; 280 281 v = (Var *) emalloc(sizeof(Var)); 282 v->name = estrdup(name); 283 284 len = strlen(env); 285 286 v->val = Buf_Init(len); 287 Buf_AddBytes(v->val, len, (Byte *)env); 288 289 v->flags = VAR_FROM_ENV; 290 return (v); 291 } else if ((checkEnvFirst || localCheckEnvFirst) && 292 (flags & FIND_GLOBAL) && (ctxt != VAR_GLOBAL)) 293 { 294 var = Lst_Find (VAR_GLOBAL->context, (void *)name, VarCmp); 295 if (var == NULL) { 296 return ((Var *) NULL); 297 } else { 298 return ((Var *)Lst_Datum(var)); 299 } 300 } else { 301 return((Var *)NULL); 302 } 303 } else if (var == NULL) { 304 return ((Var *) NULL); 305 } else { 306 return ((Var *) Lst_Datum (var)); 307 } 308} 309 310/*- 311 *----------------------------------------------------------------------- 312 * VarAdd -- 313 * Add a new variable of name name and value val to the given context. 314 * 315 * Results: 316 * None 317 * 318 * Side Effects: 319 * The new variable is placed at the front of the given context 320 * The name and val arguments are duplicated so they may 321 * safely be freed. 322 *----------------------------------------------------------------------- 323 */ 324static void 325VarAdd (char *name, char *val, GNode *ctxt) 326{ 327 Var *v; 328 int len; 329 330 v = (Var *) emalloc (sizeof (Var)); 331 332 v->name = estrdup (name); 333 334 len = val ? strlen(val) : 0; 335 v->val = Buf_Init(len+1); 336 Buf_AddBytes(v->val, len, (Byte *)val); 337 338 v->flags = 0; 339 340 (void) Lst_AtFront (ctxt->context, (void *)v); 341 (void) Lst_AtEnd (allVars, (void *) v); 342 DEBUGF(VAR, ("%s:%s = %s\n", ctxt->name, name, val)); 343} 344 345 346/*- 347 *----------------------------------------------------------------------- 348 * VarDelete -- 349 * Delete a variable and all the space associated with it. 350 * 351 * Results: 352 * None 353 * 354 * Side Effects: 355 * None 356 *----------------------------------------------------------------------- 357 */ 358static void 359VarDelete(void *vp) 360{ 361 Var *v = (Var *) vp; 362 free(v->name); 363 Buf_Destroy(v->val, TRUE); 364 free(v); 365} 366 367 368 369/*- 370 *----------------------------------------------------------------------- 371 * Var_Delete -- 372 * Remove a variable from a context. 373 * 374 * Results: 375 * None. 376 * 377 * Side Effects: 378 * The Var structure is removed and freed. 379 * 380 *----------------------------------------------------------------------- 381 */ 382void 383Var_Delete(char *name, GNode *ctxt) 384{ 385 LstNode ln; 386 387 DEBUGF(VAR, ("%s:delete %s\n", ctxt->name, name)); 388 ln = Lst_Find(ctxt->context, (void *)name, VarCmp); 389 if (ln != NULL) { 390 Var *v; 391 392 v = (Var *)Lst_Datum(ln); 393 Lst_Remove(ctxt->context, ln); 394 ln = Lst_Member(allVars, v); 395 Lst_Remove(allVars, ln); 396 VarDelete((void *) v); 397 } 398} 399 400/*- 401 *----------------------------------------------------------------------- 402 * Var_Set -- 403 * Set the variable name to the value val in the given context. 404 * 405 * Results: 406 * None. 407 * 408 * Side Effects: 409 * If the variable doesn't yet exist, a new record is created for it. 410 * Else the old value is freed and the new one stuck in its place 411 * 412 * Notes: 413 * The variable is searched for only in its context before being 414 * created in that context. I.e. if the context is VAR_GLOBAL, 415 * only VAR_GLOBAL->context is searched. Likewise if it is VAR_CMD, only 416 * VAR_CMD->context is searched. This is done to avoid the literally 417 * thousands of unnecessary strcmp's that used to be done to 418 * set, say, $(@) or $(<). 419 *----------------------------------------------------------------------- 420 */ 421void 422Var_Set (char *name, char *val, GNode *ctxt) 423{ 424 Var *v; 425 426 /* 427 * We only look for a variable in the given context since anything set 428 * here will override anything in a lower context, so there's not much 429 * point in searching them all just to save a bit of memory... 430 */ 431 VarPossiblyExpand(&name, ctxt); 432 v = VarFind (name, ctxt, 0); 433 if (v == (Var *) NULL) { 434 VarAdd (name, val, ctxt); 435 } else { 436 Buf_Discard(v->val, Buf_Size(v->val)); 437 Buf_AddBytes(v->val, strlen(val), (Byte *)val); 438 439 DEBUGF(VAR, ("%s:%s = %s\n", ctxt->name, name, val)); 440 } 441 /* 442 * Any variables given on the command line are automatically exported 443 * to the environment (as per POSIX standard) 444 */ 445 if (ctxt == VAR_CMD) { 446 setenv(name, val, 1); 447 } 448 free(name); 449} 450 451/*- 452 *----------------------------------------------------------------------- 453 * Var_Append -- 454 * The variable of the given name has the given value appended to it in 455 * the given context. 456 * 457 * Results: 458 * None 459 * 460 * Side Effects: 461 * If the variable doesn't exist, it is created. Else the strings 462 * are concatenated (with a space in between). 463 * 464 * Notes: 465 * Only if the variable is being sought in the global context is the 466 * environment searched. 467 * XXX: Knows its calling circumstances in that if called with ctxt 468 * an actual target, it will only search that context since only 469 * a local variable could be being appended to. This is actually 470 * a big win and must be tolerated. 471 *----------------------------------------------------------------------- 472 */ 473void 474Var_Append (char *name, char *val, GNode *ctxt) 475{ 476 Var *v; 477 478 VarPossiblyExpand(&name, ctxt); 479 v = VarFind (name, ctxt, (ctxt == VAR_GLOBAL) ? FIND_ENV : 0); 480 481 if (v == (Var *) NULL) { 482 VarAdd (name, val, ctxt); 483 } else { 484 Buf_AddByte(v->val, (Byte)' '); 485 Buf_AddBytes(v->val, strlen(val), (Byte *)val); 486 487 DEBUGF(VAR, ("%s:%s = %s\n", ctxt->name, name, 488 (char *) Buf_GetAll(v->val, (int *)NULL))); 489 490 if (v->flags & VAR_FROM_ENV) { 491 /* 492 * If the original variable came from the environment, we 493 * have to install it in the global context (we could place 494 * it in the environment, but then we should provide a way to 495 * export other variables...) 496 */ 497 v->flags &= ~VAR_FROM_ENV; 498 Lst_AtFront(ctxt->context, (void *)v); 499 } 500 } 501 free(name); 502} 503 504/*- 505 *----------------------------------------------------------------------- 506 * Var_Exists -- 507 * See if the given variable exists. 508 * 509 * Results: 510 * TRUE if it does, FALSE if it doesn't 511 * 512 * Side Effects: 513 * None. 514 * 515 *----------------------------------------------------------------------- 516 */ 517Boolean 518Var_Exists(char *name, GNode *ctxt) 519{ 520 Var *v; 521 522 VarPossiblyExpand(&name, ctxt); 523 v = VarFind(name, ctxt, FIND_CMD|FIND_GLOBAL|FIND_ENV); 524 free(name); 525 526 if (v == (Var *)NULL) { 527 return(FALSE); 528 } else if (v->flags & VAR_FROM_ENV) { 529 free(v->name); 530 Buf_Destroy(v->val, TRUE); 531 free((char *)v); 532 } 533 return(TRUE); 534} 535 536/*- 537 *----------------------------------------------------------------------- 538 * Var_Value -- 539 * Return the value of the named variable in the given context 540 * 541 * Results: 542 * The value if the variable exists, NULL if it doesn't 543 * 544 * Side Effects: 545 * None 546 *----------------------------------------------------------------------- 547 */ 548char * 549Var_Value (char *name, GNode *ctxt, char **frp) 550{ 551 Var *v; 552 553 VarPossiblyExpand(&name, ctxt); 554 v = VarFind (name, ctxt, FIND_ENV | FIND_GLOBAL | FIND_CMD); 555 free(name); 556 *frp = NULL; 557 if (v != (Var *) NULL) { 558 char *p = ((char *)Buf_GetAll(v->val, (int *)NULL)); 559 if (v->flags & VAR_FROM_ENV) { 560 Buf_Destroy(v->val, FALSE); 561 free(v); 562 *frp = p; 563 } 564 return p; 565 } else { 566 return ((char *) NULL); 567 } 568} 569 570/*- 571 *-----------------------------------------------------------------------
|
619 * VarHead -- 620 * Remove the tail of the given word and place the result in the given 621 * buffer. 622 * 623 * Results: 624 * TRUE if characters were added to the buffer (a space needs to be 625 * added to the buffer before the next word). 626 * 627 * Side Effects: 628 * The trimmed word is added to the buffer. 629 * 630 *----------------------------------------------------------------------- 631 */ 632static Boolean 633VarHead (char *word, Boolean addSpace, Buffer buf, void *dummy __unused) 634{ 635 char *slash; 636 637 slash = strrchr (word, '/'); 638 if (slash != (char *)NULL) { 639 if (addSpace) { 640 Buf_AddByte (buf, (Byte)' '); 641 } 642 *slash = '\0'; 643 Buf_AddBytes (buf, strlen (word), (Byte *)word); 644 *slash = '/'; 645 return (TRUE); 646 } else { 647 /* 648 * If no directory part, give . (q.v. the POSIX standard) 649 */ 650 if (addSpace) { 651 Buf_AddBytes(buf, 2, (Byte *)" ."); 652 } else { 653 Buf_AddByte(buf, (Byte)'.'); 654 } 655 } 656 return (TRUE); 657} 658 659/*- 660 *----------------------------------------------------------------------- 661 * VarTail -- 662 * Remove the head of the given word and place the result in the given 663 * buffer. 664 * 665 * Results: 666 * TRUE if characters were added to the buffer (a space needs to be 667 * added to the buffer before the next word). 668 * 669 * Side Effects: 670 * The trimmed word is added to the buffer. 671 * 672 *----------------------------------------------------------------------- 673 */ 674static Boolean 675VarTail (char *word, Boolean addSpace, Buffer buf, void *dummy __unused) 676{ 677 char *slash; 678 679 if (addSpace) { 680 Buf_AddByte (buf, (Byte)' '); 681 } 682 683 slash = strrchr (word, '/'); 684 if (slash != (char *)NULL) { 685 *slash++ = '\0'; 686 Buf_AddBytes (buf, strlen(slash), (Byte *)slash); 687 slash[-1] = '/'; 688 } else { 689 Buf_AddBytes (buf, strlen(word), (Byte *)word); 690 } 691 return (TRUE); 692} 693 694/*- 695 *----------------------------------------------------------------------- 696 * VarSuffix -- 697 * Place the suffix of the given word in the given buffer. 698 * 699 * Results: 700 * TRUE if characters were added to the buffer (a space needs to be 701 * added to the buffer before the next word). 702 * 703 * Side Effects: 704 * The suffix from the word is placed in the buffer. 705 * 706 *----------------------------------------------------------------------- 707 */ 708static Boolean 709VarSuffix (char *word, Boolean addSpace, Buffer buf, void *dummy __unused) 710{ 711 char *dot; 712 713 dot = strrchr (word, '.'); 714 if (dot != (char *)NULL) { 715 if (addSpace) { 716 Buf_AddByte (buf, (Byte)' '); 717 } 718 *dot++ = '\0'; 719 Buf_AddBytes (buf, strlen (dot), (Byte *)dot); 720 dot[-1] = '.'; 721 addSpace = TRUE; 722 } 723 return (addSpace); 724} 725 726/*- 727 *----------------------------------------------------------------------- 728 * VarRoot -- 729 * Remove the suffix of the given word and place the result in the 730 * buffer. 731 * 732 * Results: 733 * TRUE if characters were added to the buffer (a space needs to be 734 * added to the buffer before the next word). 735 * 736 * Side Effects: 737 * The trimmed word is added to the buffer. 738 * 739 *----------------------------------------------------------------------- 740 */ 741static Boolean 742VarRoot (char *word, Boolean addSpace, Buffer buf, void *dummy __unused) 743{ 744 char *dot; 745 746 if (addSpace) { 747 Buf_AddByte (buf, (Byte)' '); 748 } 749 750 dot = strrchr (word, '.'); 751 if (dot != (char *)NULL) { 752 *dot = '\0'; 753 Buf_AddBytes (buf, strlen (word), (Byte *)word); 754 *dot = '.'; 755 } else { 756 Buf_AddBytes (buf, strlen(word), (Byte *)word); 757 } 758 return (TRUE); 759} 760 761/*- 762 *----------------------------------------------------------------------- 763 * VarMatch -- 764 * Place the word in the buffer if it matches the given pattern. 765 * Callback function for VarModify to implement the :M modifier. 766 * A space will be added if requested. A pattern is supplied 767 * which the word must match. 768 * 769 * Results: 770 * TRUE if a space should be placed in the buffer before the next 771 * word. 772 * 773 * Side Effects: 774 * The word may be copied to the buffer. 775 * 776 *----------------------------------------------------------------------- 777 */ 778static Boolean 779VarMatch (char *word, Boolean addSpace, Buffer buf, void *pattern) 780{ 781 if (Str_Match(word, (char *) pattern)) { 782 if (addSpace) { 783 Buf_AddByte(buf, (Byte)' '); 784 } 785 addSpace = TRUE; 786 Buf_AddBytes(buf, strlen(word), (Byte *)word); 787 } 788 return(addSpace); 789} 790 791#ifdef SYSVVARSUB 792/*- 793 *----------------------------------------------------------------------- 794 * VarSYSVMatch -- 795 * Place the word in the buffer if it matches the given pattern. 796 * Callback function for VarModify to implement the System V % 797 * modifiers. A space is added if requested. 798 * 799 * Results: 800 * TRUE if a space should be placed in the buffer before the next 801 * word. 802 * 803 * Side Effects: 804 * The word may be copied to the buffer. 805 * 806 *----------------------------------------------------------------------- 807 */ 808static Boolean 809VarSYSVMatch (char *word, Boolean addSpace, Buffer buf, void *patp) 810{ 811 int len; 812 char *ptr; 813 VarPattern *pat = (VarPattern *) patp; 814 815 if (addSpace) 816 Buf_AddByte(buf, (Byte)' '); 817 818 addSpace = TRUE; 819 820 if ((ptr = Str_SYSVMatch(word, pat->lhs, &len)) != NULL) 821 Str_SYSVSubst(buf, pat->rhs, ptr, len); 822 else 823 Buf_AddBytes(buf, strlen(word), (Byte *) word); 824 825 return(addSpace); 826} 827#endif 828 829 830/*- 831 *----------------------------------------------------------------------- 832 * VarNoMatch -- 833 * Place the word in the buffer if it doesn't match the given pattern. 834 * Callback function for VarModify to implement the :N modifier. A 835 * space is added if requested. 836 * 837 * Results: 838 * TRUE if a space should be placed in the buffer before the next 839 * word. 840 * 841 * Side Effects: 842 * The word may be copied to the buffer. 843 * 844 *----------------------------------------------------------------------- 845 */ 846static Boolean 847VarNoMatch (char *word, Boolean addSpace, Buffer buf, void *pattern) 848{ 849 if (!Str_Match(word, (char *) pattern)) { 850 if (addSpace) { 851 Buf_AddByte(buf, (Byte)' '); 852 } 853 addSpace = TRUE; 854 Buf_AddBytes(buf, strlen(word), (Byte *)word); 855 } 856 return(addSpace); 857} 858 859 860/*- 861 *----------------------------------------------------------------------- 862 * VarSubstitute -- 863 * Perform a string-substitution on the given word, placing the 864 * result in the passed buffer. A space is added if requested. 865 * 866 * Results: 867 * TRUE if a space is needed before more characters are added. 868 * 869 * Side Effects: 870 * None. 871 * 872 *----------------------------------------------------------------------- 873 */ 874static Boolean 875VarSubstitute (char *word, Boolean addSpace, Buffer buf, void *patternp) 876{ 877 int wordLen; /* Length of word */ 878 char *cp; /* General pointer */ 879 VarPattern *pattern = (VarPattern *) patternp; 880 881 wordLen = strlen(word); 882 if (1) { /* substitute in each word of the variable */ 883 /* 884 * Break substitution down into simple anchored cases 885 * and if none of them fits, perform the general substitution case. 886 */ 887 if ((pattern->flags & VAR_MATCH_START) && 888 (strncmp(word, pattern->lhs, pattern->leftLen) == 0)) { 889 /* 890 * Anchored at start and beginning of word matches pattern 891 */ 892 if ((pattern->flags & VAR_MATCH_END) && 893 (wordLen == pattern->leftLen)) { 894 /* 895 * Also anchored at end and matches to the end (word 896 * is same length as pattern) add space and rhs only 897 * if rhs is non-null. 898 */ 899 if (pattern->rightLen != 0) { 900 if (addSpace) { 901 Buf_AddByte(buf, (Byte)' '); 902 } 903 addSpace = TRUE; 904 Buf_AddBytes(buf, pattern->rightLen, 905 (Byte *)pattern->rhs); 906 } 907 } else if (pattern->flags & VAR_MATCH_END) { 908 /* 909 * Doesn't match to end -- copy word wholesale 910 */ 911 goto nosub; 912 } else { 913 /* 914 * Matches at start but need to copy in trailing characters 915 */ 916 if ((pattern->rightLen + wordLen - pattern->leftLen) != 0){ 917 if (addSpace) { 918 Buf_AddByte(buf, (Byte)' '); 919 } 920 addSpace = TRUE; 921 } 922 Buf_AddBytes(buf, pattern->rightLen, (Byte *)pattern->rhs); 923 Buf_AddBytes(buf, wordLen - pattern->leftLen, 924 (Byte *)(word + pattern->leftLen)); 925 } 926 } else if (pattern->flags & VAR_MATCH_START) { 927 /* 928 * Had to match at start of word and didn't -- copy whole word. 929 */ 930 goto nosub; 931 } else if (pattern->flags & VAR_MATCH_END) { 932 /* 933 * Anchored at end, Find only place match could occur (leftLen 934 * characters from the end of the word) and see if it does. Note 935 * that because the $ will be left at the end of the lhs, we have 936 * to use strncmp. 937 */ 938 cp = word + (wordLen - pattern->leftLen); 939 if ((cp >= word) && 940 (strncmp(cp, pattern->lhs, pattern->leftLen) == 0)) { 941 /* 942 * Match found. If we will place characters in the buffer, 943 * add a space before hand as indicated by addSpace, then 944 * stuff in the initial, unmatched part of the word followed 945 * by the right-hand-side. 946 */ 947 if (((cp - word) + pattern->rightLen) != 0) { 948 if (addSpace) { 949 Buf_AddByte(buf, (Byte)' '); 950 } 951 addSpace = TRUE; 952 } 953 Buf_AddBytes(buf, cp - word, (Byte *)word); 954 Buf_AddBytes(buf, pattern->rightLen, (Byte *)pattern->rhs); 955 } else { 956 /* 957 * Had to match at end and didn't. Copy entire word. 958 */ 959 goto nosub; 960 } 961 } else { 962 /* 963 * Pattern is unanchored: search for the pattern in the word using 964 * String_FindSubstring, copying unmatched portions and the 965 * right-hand-side for each match found, handling non-global 966 * substitutions correctly, etc. When the loop is done, any 967 * remaining part of the word (word and wordLen are adjusted 968 * accordingly through the loop) is copied straight into the 969 * buffer. 970 * addSpace is set FALSE as soon as a space is added to the 971 * buffer. 972 */ 973 Boolean done; 974 int origSize; 975 976 done = FALSE; 977 origSize = Buf_Size(buf); 978 while (!done) { 979 cp = Str_FindSubstring(word, pattern->lhs); 980 if (cp != (char *)NULL) { 981 if (addSpace && (((cp - word) + pattern->rightLen) != 0)){ 982 Buf_AddByte(buf, (Byte)' '); 983 addSpace = FALSE; 984 } 985 Buf_AddBytes(buf, cp-word, (Byte *)word); 986 Buf_AddBytes(buf, pattern->rightLen, (Byte *)pattern->rhs); 987 wordLen -= (cp - word) + pattern->leftLen; 988 word = cp + pattern->leftLen; 989 if (wordLen == 0 || (pattern->flags & VAR_SUB_GLOBAL) == 0){ 990 done = TRUE; 991 } 992 } else { 993 done = TRUE; 994 } 995 } 996 if (wordLen != 0) { 997 if (addSpace) { 998 Buf_AddByte(buf, (Byte)' '); 999 } 1000 Buf_AddBytes(buf, wordLen, (Byte *)word); 1001 } 1002 /* 1003 * If added characters to the buffer, need to add a space 1004 * before we add any more. If we didn't add any, just return 1005 * the previous value of addSpace. 1006 */ 1007 return ((Buf_Size(buf) != origSize) || addSpace); 1008 } 1009 /* 1010 * Common code for anchored substitutions: 1011 * addSpace was set TRUE if characters were added to the buffer. 1012 */ 1013 return (addSpace); 1014 } 1015 nosub: 1016 if (addSpace) { 1017 Buf_AddByte(buf, (Byte)' '); 1018 } 1019 Buf_AddBytes(buf, wordLen, (Byte *)word); 1020 return(TRUE); 1021} 1022 1023/*- 1024 *----------------------------------------------------------------------- 1025 * VarREError -- 1026 * Print the error caused by a regcomp or regexec call. 1027 * 1028 * Results: 1029 * None. 1030 * 1031 * Side Effects: 1032 * An error gets printed. 1033 * 1034 *----------------------------------------------------------------------- 1035 */ 1036static void 1037VarREError(int err, regex_t *pat, const char *str) 1038{ 1039 char *errbuf; 1040 int errlen; 1041 1042 errlen = regerror(err, pat, 0, 0); 1043 errbuf = emalloc(errlen); 1044 regerror(err, pat, errbuf, errlen); 1045 Error("%s: %s", str, errbuf); 1046 free(errbuf); 1047} 1048 1049 1050/*- 1051 *----------------------------------------------------------------------- 1052 * VarRESubstitute -- 1053 * Perform a regex substitution on the given word, placing the 1054 * result in the passed buffer. A space is added if requested. 1055 * 1056 * Results: 1057 * TRUE if a space is needed before more characters are added. 1058 * 1059 * Side Effects: 1060 * None. 1061 * 1062 *----------------------------------------------------------------------- 1063 */ 1064static Boolean 1065VarRESubstitute(char *word, Boolean addSpace, Buffer buf, void *patternp) 1066{ 1067 VarREPattern *pat; 1068 int xrv; 1069 char *wp; 1070 char *rp; 1071 int added; 1072 int flags = 0; 1073 1074#define MAYBE_ADD_SPACE() \ 1075 if (addSpace && !added) \ 1076 Buf_AddByte(buf, ' '); \ 1077 added = 1 1078 1079 added = 0; 1080 wp = word; 1081 pat = patternp; 1082 1083 if ((pat->flags & (VAR_SUB_ONE|VAR_SUB_MATCHED)) == 1084 (VAR_SUB_ONE|VAR_SUB_MATCHED)) 1085 xrv = REG_NOMATCH; 1086 else { 1087 tryagain: 1088 xrv = regexec(&pat->re, wp, pat->nsub, pat->matches, flags); 1089 } 1090 1091 switch (xrv) { 1092 case 0: 1093 pat->flags |= VAR_SUB_MATCHED; 1094 if (pat->matches[0].rm_so > 0) { 1095 MAYBE_ADD_SPACE(); 1096 Buf_AddBytes(buf, pat->matches[0].rm_so, wp); 1097 } 1098 1099 for (rp = pat->replace; *rp; rp++) { 1100 if ((*rp == '\\') && ((rp[1] == '&') || (rp[1] == '\\'))) { 1101 MAYBE_ADD_SPACE(); 1102 Buf_AddByte(buf,rp[1]); 1103 rp++; 1104 } 1105 else if ((*rp == '&') || 1106 ((*rp == '\\') && isdigit((unsigned char)rp[1]))) { 1107 int n; 1108 char *subbuf; 1109 int sublen; 1110 char errstr[3]; 1111 1112 if (*rp == '&') { 1113 n = 0; 1114 errstr[0] = '&'; 1115 errstr[1] = '\0'; 1116 } else { 1117 n = rp[1] - '0'; 1118 errstr[0] = '\\'; 1119 errstr[1] = rp[1]; 1120 errstr[2] = '\0'; 1121 rp++; 1122 } 1123 1124 if (n > pat->nsub) { 1125 Error("No subexpression %s", &errstr[0]); 1126 subbuf = ""; 1127 sublen = 0; 1128 } else if ((pat->matches[n].rm_so == -1) && 1129 (pat->matches[n].rm_eo == -1)) { 1130 Error("No match for subexpression %s", &errstr[0]); 1131 subbuf = ""; 1132 sublen = 0; 1133 } else { 1134 subbuf = wp + pat->matches[n].rm_so; 1135 sublen = pat->matches[n].rm_eo - pat->matches[n].rm_so; 1136 } 1137 1138 if (sublen > 0) { 1139 MAYBE_ADD_SPACE(); 1140 Buf_AddBytes(buf, sublen, subbuf); 1141 } 1142 } else { 1143 MAYBE_ADD_SPACE(); 1144 Buf_AddByte(buf, *rp); 1145 } 1146 } 1147 wp += pat->matches[0].rm_eo; 1148 if (pat->flags & VAR_SUB_GLOBAL) { 1149 flags |= REG_NOTBOL; 1150 if (pat->matches[0].rm_so == 0 && pat->matches[0].rm_eo == 0) { 1151 MAYBE_ADD_SPACE(); 1152 Buf_AddByte(buf, *wp); 1153 wp++; 1154 1155 } 1156 if (*wp) 1157 goto tryagain; 1158 } 1159 if (*wp) { 1160 MAYBE_ADD_SPACE(); 1161 Buf_AddBytes(buf, strlen(wp), wp); 1162 } 1163 break; 1164 default: 1165 VarREError(xrv, &pat->re, "Unexpected regex error"); 1166 /* fall through */ 1167 case REG_NOMATCH: 1168 if (*wp) { 1169 MAYBE_ADD_SPACE(); 1170 Buf_AddBytes(buf,strlen(wp),wp); 1171 } 1172 break; 1173 } 1174 return(addSpace||added); 1175} 1176 1177 1178/*- 1179 *-----------------------------------------------------------------------
| |
1180 * VarModify -- 1181 * Modify each of the words of the passed string using the given 1182 * function. Used to implement all modifiers. 1183 * 1184 * Results: 1185 * A string of all the words modified appropriately. 1186 * 1187 * Side Effects: 1188 * None. 1189 * 1190 *----------------------------------------------------------------------- 1191 */ 1192static char *
| 572 * VarModify -- 573 * Modify each of the words of the passed string using the given 574 * function. Used to implement all modifiers. 575 * 576 * Results: 577 * A string of all the words modified appropriately. 578 * 579 * Side Effects: 580 * None. 581 * 582 *----------------------------------------------------------------------- 583 */ 584static char *
|
1193VarModify (char *str, Boolean (*modProc)(char *, Boolean, Buffer, void *),
| 585VarModify (char *str, Boolean (*modProc)(const char *, Boolean, Buffer, void *),
|
1194 void *datum) 1195{ 1196 Buffer buf; /* Buffer for the new string */ 1197 Boolean addSpace; /* TRUE if need to add a space to the 1198 * buffer before adding the trimmed 1199 * word */ 1200 char **av; /* word list [first word does not count] */ 1201 int ac, i; 1202 1203 buf = Buf_Init (0); 1204 addSpace = FALSE; 1205 1206 av = brk_string(str, &ac, FALSE); 1207 1208 for (i = 1; i < ac; i++) 1209 addSpace = (*modProc)(av[i], addSpace, buf, datum); 1210 1211 Buf_AddByte (buf, '\0'); 1212 str = (char *)Buf_GetAll (buf, (int *)NULL); 1213 Buf_Destroy (buf, FALSE); 1214 return (str); 1215} 1216 1217/*- 1218 *----------------------------------------------------------------------- 1219 * VarGetPattern -- 1220 * Pass through the tstr looking for 1) escaped delimiters, 1221 * '$'s and backslashes (place the escaped character in 1222 * uninterpreted) and 2) unescaped $'s that aren't before 1223 * the delimiter (expand the variable substitution unless flags 1224 * has VAR_NOSUBST set). 1225 * Return the expanded string or NULL if the delimiter was missing 1226 * If pattern is specified, handle escaped ampersands, and replace 1227 * unescaped ampersands with the lhs of the pattern. 1228 * 1229 * Results: 1230 * A string of all the words modified appropriately. 1231 * If length is specified, return the string length of the buffer 1232 * If flags is specified and the last character of the pattern is a 1233 * $ set the VAR_MATCH_END bit of flags. 1234 * 1235 * Side Effects: 1236 * None. 1237 *----------------------------------------------------------------------- 1238 */ 1239static char * 1240VarGetPattern(GNode *ctxt, int err, char **tstr, int delim, int *flags, 1241 int *length, VarPattern *pattern) 1242{ 1243 char *cp; 1244 Buffer buf = Buf_Init(0); 1245 int junk; 1246 if (length == NULL) 1247 length = &junk; 1248 1249#define IS_A_MATCH(cp, delim) \ 1250 ((cp[0] == '\\') && ((cp[1] == delim) || \ 1251 (cp[1] == '\\') || (cp[1] == '$') || (pattern && (cp[1] == '&')))) 1252 1253 /* 1254 * Skim through until the matching delimiter is found; 1255 * pick up variable substitutions on the way. Also allow 1256 * backslashes to quote the delimiter, $, and \, but don't 1257 * touch other backslashes. 1258 */ 1259 for (cp = *tstr; *cp && (*cp != delim); cp++) { 1260 if (IS_A_MATCH(cp, delim)) { 1261 Buf_AddByte(buf, (Byte) cp[1]); 1262 cp++; 1263 } else if (*cp == '$') { 1264 if (cp[1] == delim) { 1265 if (flags == NULL) 1266 Buf_AddByte(buf, (Byte) *cp); 1267 else 1268 /* 1269 * Unescaped $ at end of pattern => anchor 1270 * pattern at end. 1271 */ 1272 *flags |= VAR_MATCH_END; 1273 } else { 1274 if (flags == NULL || (*flags & VAR_NOSUBST) == 0) { 1275 char *cp2; 1276 int len; 1277 Boolean freeIt; 1278 1279 /* 1280 * If unescaped dollar sign not before the 1281 * delimiter, assume it's a variable 1282 * substitution and recurse. 1283 */ 1284 cp2 = Var_Parse(cp, ctxt, err, &len, &freeIt); 1285 Buf_AddBytes(buf, strlen(cp2), (Byte *) cp2); 1286 if (freeIt) 1287 free(cp2); 1288 cp += len - 1; 1289 } else { 1290 char *cp2 = &cp[1]; 1291 1292 if (*cp2 == '(' || *cp2 == '{') { 1293 /* 1294 * Find the end of this variable reference 1295 * and suck it in without further ado. 1296 * It will be interperated later. 1297 */ 1298 int have = *cp2; 1299 int want = (*cp2 == '(') ? ')' : '}'; 1300 int depth = 1; 1301 1302 for (++cp2; *cp2 != '\0' && depth > 0; ++cp2) { 1303 if (cp2[-1] != '\\') { 1304 if (*cp2 == have) 1305 ++depth; 1306 if (*cp2 == want) 1307 --depth; 1308 } 1309 } 1310 Buf_AddBytes(buf, cp2 - cp, (Byte *)cp); 1311 cp = --cp2; 1312 } else 1313 Buf_AddByte(buf, (Byte) *cp); 1314 } 1315 } 1316 } 1317 else if (pattern && *cp == '&') 1318 Buf_AddBytes(buf, pattern->leftLen, (Byte *)pattern->lhs); 1319 else 1320 Buf_AddByte(buf, (Byte) *cp); 1321 } 1322 1323 Buf_AddByte(buf, (Byte) '\0'); 1324 1325 if (*cp != delim) { 1326 *tstr = cp; 1327 *length = 0; 1328 return NULL; 1329 } 1330 else { 1331 *tstr = ++cp; 1332 cp = (char *) Buf_GetAll(buf, length); 1333 *length -= 1; /* Don't count the NULL */ 1334 Buf_Destroy(buf, FALSE); 1335 return cp; 1336 } 1337} 1338 1339 1340/*- 1341 *----------------------------------------------------------------------- 1342 * VarQuote -- 1343 * Quote shell meta-characters in the string 1344 * 1345 * Results: 1346 * The quoted string 1347 * 1348 * Side Effects: 1349 * None. 1350 * 1351 *----------------------------------------------------------------------- 1352 */ 1353static char *
| 586 void *datum) 587{ 588 Buffer buf; /* Buffer for the new string */ 589 Boolean addSpace; /* TRUE if need to add a space to the 590 * buffer before adding the trimmed 591 * word */ 592 char **av; /* word list [first word does not count] */ 593 int ac, i; 594 595 buf = Buf_Init (0); 596 addSpace = FALSE; 597 598 av = brk_string(str, &ac, FALSE); 599 600 for (i = 1; i < ac; i++) 601 addSpace = (*modProc)(av[i], addSpace, buf, datum); 602 603 Buf_AddByte (buf, '\0'); 604 str = (char *)Buf_GetAll (buf, (int *)NULL); 605 Buf_Destroy (buf, FALSE); 606 return (str); 607} 608 609/*- 610 *----------------------------------------------------------------------- 611 * VarGetPattern -- 612 * Pass through the tstr looking for 1) escaped delimiters, 613 * '$'s and backslashes (place the escaped character in 614 * uninterpreted) and 2) unescaped $'s that aren't before 615 * the delimiter (expand the variable substitution unless flags 616 * has VAR_NOSUBST set). 617 * Return the expanded string or NULL if the delimiter was missing 618 * If pattern is specified, handle escaped ampersands, and replace 619 * unescaped ampersands with the lhs of the pattern. 620 * 621 * Results: 622 * A string of all the words modified appropriately. 623 * If length is specified, return the string length of the buffer 624 * If flags is specified and the last character of the pattern is a 625 * $ set the VAR_MATCH_END bit of flags. 626 * 627 * Side Effects: 628 * None. 629 *----------------------------------------------------------------------- 630 */ 631static char * 632VarGetPattern(GNode *ctxt, int err, char **tstr, int delim, int *flags, 633 int *length, VarPattern *pattern) 634{ 635 char *cp; 636 Buffer buf = Buf_Init(0); 637 int junk; 638 if (length == NULL) 639 length = &junk; 640 641#define IS_A_MATCH(cp, delim) \ 642 ((cp[0] == '\\') && ((cp[1] == delim) || \ 643 (cp[1] == '\\') || (cp[1] == '$') || (pattern && (cp[1] == '&')))) 644 645 /* 646 * Skim through until the matching delimiter is found; 647 * pick up variable substitutions on the way. Also allow 648 * backslashes to quote the delimiter, $, and \, but don't 649 * touch other backslashes. 650 */ 651 for (cp = *tstr; *cp && (*cp != delim); cp++) { 652 if (IS_A_MATCH(cp, delim)) { 653 Buf_AddByte(buf, (Byte) cp[1]); 654 cp++; 655 } else if (*cp == '$') { 656 if (cp[1] == delim) { 657 if (flags == NULL) 658 Buf_AddByte(buf, (Byte) *cp); 659 else 660 /* 661 * Unescaped $ at end of pattern => anchor 662 * pattern at end. 663 */ 664 *flags |= VAR_MATCH_END; 665 } else { 666 if (flags == NULL || (*flags & VAR_NOSUBST) == 0) { 667 char *cp2; 668 int len; 669 Boolean freeIt; 670 671 /* 672 * If unescaped dollar sign not before the 673 * delimiter, assume it's a variable 674 * substitution and recurse. 675 */ 676 cp2 = Var_Parse(cp, ctxt, err, &len, &freeIt); 677 Buf_AddBytes(buf, strlen(cp2), (Byte *) cp2); 678 if (freeIt) 679 free(cp2); 680 cp += len - 1; 681 } else { 682 char *cp2 = &cp[1]; 683 684 if (*cp2 == '(' || *cp2 == '{') { 685 /* 686 * Find the end of this variable reference 687 * and suck it in without further ado. 688 * It will be interperated later. 689 */ 690 int have = *cp2; 691 int want = (*cp2 == '(') ? ')' : '}'; 692 int depth = 1; 693 694 for (++cp2; *cp2 != '\0' && depth > 0; ++cp2) { 695 if (cp2[-1] != '\\') { 696 if (*cp2 == have) 697 ++depth; 698 if (*cp2 == want) 699 --depth; 700 } 701 } 702 Buf_AddBytes(buf, cp2 - cp, (Byte *)cp); 703 cp = --cp2; 704 } else 705 Buf_AddByte(buf, (Byte) *cp); 706 } 707 } 708 } 709 else if (pattern && *cp == '&') 710 Buf_AddBytes(buf, pattern->leftLen, (Byte *)pattern->lhs); 711 else 712 Buf_AddByte(buf, (Byte) *cp); 713 } 714 715 Buf_AddByte(buf, (Byte) '\0'); 716 717 if (*cp != delim) { 718 *tstr = cp; 719 *length = 0; 720 return NULL; 721 } 722 else { 723 *tstr = ++cp; 724 cp = (char *) Buf_GetAll(buf, length); 725 *length -= 1; /* Don't count the NULL */ 726 Buf_Destroy(buf, FALSE); 727 return cp; 728 } 729} 730 731 732/*- 733 *----------------------------------------------------------------------- 734 * VarQuote -- 735 * Quote shell meta-characters in the string 736 * 737 * Results: 738 * The quoted string 739 * 740 * Side Effects: 741 * None. 742 * 743 *----------------------------------------------------------------------- 744 */ 745static char *
|
1354VarQuote(char *str)
| 746VarQuote(const char *str)
|
1355{ 1356 1357 Buffer buf; 1358 /* This should cover most shells :-( */ 1359 static char meta[] = "\n \t'`\";&<>()|*?{}[]\\$!#^~";
| 747{ 748 749 Buffer buf; 750 /* This should cover most shells :-( */ 751 static char meta[] = "\n \t'`\";&<>()|*?{}[]\\$!#^~";
|
| 752 char *ret;
|
1360 1361 buf = Buf_Init (MAKE_BSIZE); 1362 for (; *str; str++) { 1363 if (strchr(meta, *str) != NULL) 1364 Buf_AddByte(buf, (Byte)'\\'); 1365 Buf_AddByte(buf, (Byte)*str); 1366 } 1367 Buf_AddByte(buf, (Byte) '\0');
| 753 754 buf = Buf_Init (MAKE_BSIZE); 755 for (; *str; str++) { 756 if (strchr(meta, *str) != NULL) 757 Buf_AddByte(buf, (Byte)'\\'); 758 Buf_AddByte(buf, (Byte)*str); 759 } 760 Buf_AddByte(buf, (Byte) '\0');
|
1368 str = (char *)Buf_GetAll (buf, (int *)NULL);
| 761 ret = Buf_GetAll (buf, NULL);
|
1369 Buf_Destroy (buf, FALSE);
| 762 Buf_Destroy (buf, FALSE);
|
1370 return str;
| 763 return ret;
|
1371} 1372 1373/*- 1374 *-----------------------------------------------------------------------
| 764} 765 766/*- 767 *-----------------------------------------------------------------------
|
| 768 * VarREError -- 769 * Print the error caused by a regcomp or regexec call. 770 * 771 * Results: 772 * None. 773 * 774 * Side Effects: 775 * An error gets printed. 776 * 777 *----------------------------------------------------------------------- 778 */ 779void 780VarREError(int err, regex_t *pat, const char *str) 781{ 782 char *errbuf; 783 int errlen; 784 785 errlen = regerror(err, pat, 0, 0); 786 errbuf = emalloc(errlen); 787 regerror(err, pat, errbuf, errlen); 788 Error("%s: %s", str, errbuf); 789 free(errbuf); 790} 791 792 793/*- 794 *-----------------------------------------------------------------------
|
1375 * Var_Parse -- 1376 * Given the start of a variable invocation, extract the variable 1377 * name and find its value, then modify it according to the 1378 * specification. 1379 * 1380 * Results: 1381 * The (possibly-modified) value of the variable or var_Error if the 1382 * specification is invalid. The length of the specification is 1383 * placed in *lengthPtr (for invalid specifications, this is just 1384 * 2...?). 1385 * A Boolean in *freePtr telling whether the returned string should 1386 * be freed by the caller. 1387 * 1388 * Side Effects: 1389 * None. 1390 * 1391 *----------------------------------------------------------------------- 1392 */ 1393char * 1394Var_Parse(char *str, GNode *ctxt, Boolean err, int *lengthPtr, Boolean *freePtr) 1395{ 1396 char *tstr; /* Pointer into str */ 1397 Var *v; /* Variable in invocation */ 1398 char *cp; /* Secondary pointer into str (place marker 1399 * for tstr) */ 1400 Boolean haveModifier;/* TRUE if have modifiers for the variable */ 1401 char endc; /* Ending character when variable in parens 1402 * or braces */ 1403 char startc=0; /* Starting character when variable in parens 1404 * or braces */ 1405 int cnt; /* Used to count brace pairs when variable in 1406 * in parens or braces */ 1407 char *start; 1408 char delim; 1409 Boolean dynamic; /* TRUE if the variable is local and we're 1410 * expanding it in a non-local context. This 1411 * is done to support dynamic sources. The 1412 * result is just the invocation, unaltered */ 1413 int vlen; /* length of variable name, after embedded variable 1414 * expansion */ 1415 1416 *freePtr = FALSE; 1417 dynamic = FALSE; 1418 start = str; 1419 1420 if (str[1] != '(' && str[1] != '{') { 1421 /* 1422 * If it's not bounded by braces of some sort, life is much simpler. 1423 * We just need to check for the first character and return the 1424 * value if it exists. 1425 */ 1426 char name[2]; 1427 1428 name[0] = str[1]; 1429 name[1] = '\0'; 1430 1431 v = VarFind (name, ctxt, FIND_ENV | FIND_GLOBAL | FIND_CMD); 1432 if (v == (Var *)NULL) { 1433 *lengthPtr = 2; 1434 1435 if ((ctxt == VAR_CMD) || (ctxt == VAR_GLOBAL)) { 1436 /* 1437 * If substituting a local variable in a non-local context, 1438 * assume it's for dynamic source stuff. We have to handle 1439 * this specially and return the longhand for the variable 1440 * with the dollar sign escaped so it makes it back to the 1441 * caller. Only four of the local variables are treated 1442 * specially as they are the only four that will be set 1443 * when dynamic sources are expanded. 1444 */ 1445 /* XXX: It looks like $% and $! are reversed here */ 1446 switch (str[1]) { 1447 case '@': 1448 return("$(.TARGET)"); 1449 case '%': 1450 return("$(.ARCHIVE)"); 1451 case '*': 1452 return("$(.PREFIX)"); 1453 case '!': 1454 return("$(.MEMBER)"); 1455 default: 1456 break; 1457 } 1458 } 1459 /* 1460 * Error 1461 */ 1462 return (err ? var_Error : varNoError); 1463 } else { 1464 haveModifier = FALSE; 1465 tstr = &str[1]; 1466 endc = str[1]; 1467 } 1468 } else { 1469 /* build up expanded variable name in this buffer */ 1470 Buffer buf = Buf_Init(MAKE_BSIZE); 1471 1472 startc = str[1]; 1473 endc = startc == '(' ? ')' : '}'; 1474 1475 /* 1476 * Skip to the end character or a colon, whichever comes first, 1477 * replacing embedded variables as we go. 1478 */ 1479 for (tstr = str + 2; *tstr != '\0' && *tstr != endc && *tstr != ':'; tstr++) 1480 if (*tstr == '$') { 1481 int rlen; 1482 Boolean rfree; 1483 char* rval = Var_Parse(tstr, ctxt, err, &rlen, &rfree); 1484 1485 if (rval == var_Error) { 1486 Fatal("Error expanding embedded variable."); 1487 } else if (rval != NULL) { 1488 Buf_AddBytes(buf, strlen(rval), (Byte *) rval); 1489 if (rfree) 1490 free(rval); 1491 } 1492 tstr += rlen - 1; 1493 } else 1494 Buf_AddByte(buf, (Byte) *tstr); 1495 1496 if (*tstr == '\0') { 1497 /* 1498 * If we never did find the end character, return NULL 1499 * right now, setting the length to be the distance to 1500 * the end of the string, since that's what make does. 1501 */ 1502 *lengthPtr = tstr - str; 1503 return (var_Error); 1504 } 1505 1506 haveModifier = (*tstr == ':'); 1507 *tstr = '\0'; 1508 1509 Buf_AddByte(buf, (Byte) '\0'); 1510 str = Buf_GetAll(buf, NULL); 1511 vlen = strlen(str); 1512 1513 v = VarFind (str, ctxt, FIND_ENV | FIND_GLOBAL | FIND_CMD); 1514 if ((v == (Var *)NULL) && (ctxt != VAR_CMD) && (ctxt != VAR_GLOBAL) && 1515 (vlen == 2) && (str[1] == 'F' || str[1] == 'D')) 1516 { 1517 /* 1518 * Check for bogus D and F forms of local variables since we're 1519 * in a local context and the name is the right length. 1520 */ 1521 switch(str[0]) { 1522 case '@': 1523 case '%': 1524 case '*': 1525 case '!': 1526 case '>': 1527 case '<': 1528 { 1529 char vname[2]; 1530 char *val; 1531 1532 /* 1533 * Well, it's local -- go look for it. 1534 */ 1535 vname[0] = str[0]; 1536 vname[1] = '\0'; 1537 v = VarFind(vname, ctxt, 0); 1538 1539 if (v != (Var *)NULL && !haveModifier) { 1540 /* 1541 * No need for nested expansion or anything, as we're 1542 * the only one who sets these things and we sure don't 1543 * put nested invocations in them... 1544 */ 1545 val = (char *)Buf_GetAll(v->val, (int *)NULL); 1546 1547 if (str[1] == 'D') { 1548 val = VarModify(val, VarHead, (void *)0); 1549 } else { 1550 val = VarModify(val, VarTail, (void *)0); 1551 } 1552 /* 1553 * Resulting string is dynamically allocated, so 1554 * tell caller to free it. 1555 */ 1556 *freePtr = TRUE; 1557 *lengthPtr = tstr-start+1; 1558 *tstr = endc; 1559 Buf_Destroy(buf, TRUE); 1560 return(val); 1561 } 1562 break; 1563 default: 1564 break; 1565 } 1566 } 1567 } 1568 1569 if (v == (Var *)NULL) { 1570 if (((vlen == 1) || 1571 (((vlen == 2) && (str[1] == 'F' || 1572 str[1] == 'D')))) && 1573 ((ctxt == VAR_CMD) || (ctxt == VAR_GLOBAL))) 1574 { 1575 /* 1576 * If substituting a local variable in a non-local context, 1577 * assume it's for dynamic source stuff. We have to handle 1578 * this specially and return the longhand for the variable 1579 * with the dollar sign escaped so it makes it back to the 1580 * caller. Only four of the local variables are treated 1581 * specially as they are the only four that will be set 1582 * when dynamic sources are expanded. 1583 */ 1584 switch (str[0]) { 1585 case '@': 1586 case '%': 1587 case '*': 1588 case '!': 1589 dynamic = TRUE; 1590 break; 1591 default: 1592 break; 1593 } 1594 } else if ((vlen > 2) && (str[0] == '.') && 1595 isupper((unsigned char) str[1]) && 1596 ((ctxt == VAR_CMD) || (ctxt == VAR_GLOBAL))) 1597 { 1598 int len; 1599 1600 len = vlen - 1; 1601 if ((strncmp(str, ".TARGET", len) == 0) || 1602 (strncmp(str, ".ARCHIVE", len) == 0) || 1603 (strncmp(str, ".PREFIX", len) == 0) || 1604 (strncmp(str, ".MEMBER", len) == 0)) 1605 { 1606 dynamic = TRUE; 1607 } 1608 } 1609 1610 if (!haveModifier) { 1611 /* 1612 * No modifiers -- have specification length so we can return 1613 * now. 1614 */ 1615 *lengthPtr = tstr - start + 1; 1616 *tstr = endc; 1617 if (dynamic) { 1618 str = emalloc(*lengthPtr + 1); 1619 strncpy(str, start, *lengthPtr); 1620 str[*lengthPtr] = '\0'; 1621 *freePtr = TRUE; 1622 Buf_Destroy(buf, TRUE); 1623 return(str); 1624 } else { 1625 Buf_Destroy(buf, TRUE); 1626 return (err ? var_Error : varNoError); 1627 } 1628 } else { 1629 /* 1630 * Still need to get to the end of the variable specification, 1631 * so kludge up a Var structure for the modifications 1632 */ 1633 v = (Var *) emalloc(sizeof(Var)); 1634 v->name = estrdup(str); 1635 v->val = Buf_Init(1); 1636 v->flags = VAR_JUNK; 1637 } 1638 } 1639 Buf_Destroy(buf, TRUE); 1640 } 1641 1642 if (v->flags & VAR_IN_USE) { 1643 Fatal("Variable %s is recursive.", v->name); 1644 /*NOTREACHED*/ 1645 } else { 1646 v->flags |= VAR_IN_USE; 1647 } 1648 /* 1649 * Before doing any modification, we have to make sure the value 1650 * has been fully expanded. If it looks like recursion might be 1651 * necessary (there's a dollar sign somewhere in the variable's value) 1652 * we just call Var_Subst to do any other substitutions that are 1653 * necessary. Note that the value returned by Var_Subst will have 1654 * been dynamically-allocated, so it will need freeing when we 1655 * return. 1656 */ 1657 str = (char *)Buf_GetAll(v->val, (int *)NULL); 1658 if (strchr (str, '$') != (char *)NULL) { 1659 str = Var_Subst(NULL, str, ctxt, err); 1660 *freePtr = TRUE; 1661 } 1662 1663 v->flags &= ~VAR_IN_USE; 1664 1665 /* 1666 * Now we need to apply any modifiers the user wants applied. 1667 * These are: 1668 * :M<pattern> words which match the given <pattern>. 1669 * <pattern> is of the standard file 1670 * wildcarding form. 1671 * :S<d><pat1><d><pat2><d>[g] 1672 * Substitute <pat2> for <pat1> in the value 1673 * :C<d><pat1><d><pat2><d>[g] 1674 * Substitute <pat2> for regex <pat1> in the value 1675 * :H Substitute the head of each word 1676 * :T Substitute the tail of each word 1677 * :E Substitute the extension (minus '.') of 1678 * each word 1679 * :R Substitute the root of each word 1680 * (pathname minus the suffix). 1681 * :lhs=rhs Like :S, but the rhs goes to the end of 1682 * the invocation. 1683 * :U Converts variable to upper-case. 1684 * :L Converts variable to lower-case. 1685 */ 1686 if ((str != (char *)NULL) && haveModifier) { 1687 /* 1688 * Skip initial colon while putting it back. 1689 */ 1690 *tstr++ = ':'; 1691 while (*tstr != endc) { 1692 char *newStr; /* New value to return */ 1693 char termc; /* Character which terminated scan */ 1694 1695 DEBUGF(VAR, ("Applying :%c to \"%s\"\n", *tstr, str)); 1696 switch (*tstr) { 1697 case 'U': 1698 if (tstr[1] == endc || tstr[1] == ':') { 1699 Buffer buf; 1700 buf = Buf_Init(MAKE_BSIZE); 1701 for (cp = str; *cp ; cp++) 1702 Buf_AddByte(buf, (Byte) toupper(*cp)); 1703 1704 Buf_AddByte(buf, (Byte) '\0'); 1705 newStr = (char *) Buf_GetAll(buf, (int *) NULL); 1706 Buf_Destroy(buf, FALSE); 1707 1708 cp = tstr + 1; 1709 termc = *cp; 1710 break; 1711 } 1712 /* FALLTHROUGH */ 1713 case 'L': 1714 if (tstr[1] == endc || tstr[1] == ':') { 1715 Buffer buf; 1716 buf = Buf_Init(MAKE_BSIZE); 1717 for (cp = str; *cp ; cp++) 1718 Buf_AddByte(buf, (Byte) tolower(*cp)); 1719 1720 Buf_AddByte(buf, (Byte) '\0'); 1721 newStr = (char *) Buf_GetAll(buf, (int *) NULL); 1722 Buf_Destroy(buf, FALSE); 1723 1724 cp = tstr + 1; 1725 termc = *cp; 1726 break; 1727 } 1728 /* FALLTHROUGH */ 1729 case 'N': 1730 case 'M': 1731 { 1732 char *pattern; 1733 char *cp2; 1734 Boolean copy; 1735 1736 copy = FALSE; 1737 for (cp = tstr + 1; 1738 *cp != '\0' && *cp != ':' && *cp != endc; 1739 cp++) 1740 { 1741 if (*cp == '\\' && (cp[1] == ':' || cp[1] == endc)){ 1742 copy = TRUE; 1743 cp++; 1744 } 1745 } 1746 termc = *cp; 1747 *cp = '\0'; 1748 if (copy) { 1749 /* 1750 * Need to compress the \:'s out of the pattern, so 1751 * allocate enough room to hold the uncompressed 1752 * pattern (note that cp started at tstr+1, so 1753 * cp - tstr takes the null byte into account) and 1754 * compress the pattern into the space. 1755 */ 1756 pattern = emalloc(cp - tstr); 1757 for (cp2 = pattern, cp = tstr + 1; 1758 *cp != '\0'; 1759 cp++, cp2++) 1760 { 1761 if ((*cp == '\\') && 1762 (cp[1] == ':' || cp[1] == endc)) { 1763 cp++; 1764 } 1765 *cp2 = *cp; 1766 } 1767 *cp2 = '\0'; 1768 } else { 1769 pattern = &tstr[1]; 1770 } 1771 if (*tstr == 'M' || *tstr == 'm') { 1772 newStr = VarModify(str, VarMatch, (void *)pattern); 1773 } else { 1774 newStr = VarModify(str, VarNoMatch, 1775 (void *)pattern); 1776 } 1777 if (copy) { 1778 free(pattern); 1779 } 1780 break; 1781 } 1782 case 'S': 1783 { 1784 VarPattern pattern; 1785 char del; 1786 Buffer buf; /* Buffer for patterns */ 1787 1788 pattern.flags = 0; 1789 del = tstr[1]; 1790 tstr += 2; 1791 1792 /* 1793 * If pattern begins with '^', it is anchored to the 1794 * start of the word -- skip over it and flag pattern. 1795 */ 1796 if (*tstr == '^') { 1797 pattern.flags |= VAR_MATCH_START; 1798 tstr += 1; 1799 } 1800 1801 buf = Buf_Init(0); 1802 1803 /* 1804 * Pass through the lhs looking for 1) escaped delimiters, 1805 * '$'s and backslashes (place the escaped character in 1806 * uninterpreted) and 2) unescaped $'s that aren't before 1807 * the delimiter (expand the variable substitution). 1808 * The result is left in the Buffer buf. 1809 */ 1810 for (cp = tstr; *cp != '\0' && *cp != del; cp++) { 1811 if ((*cp == '\\') && 1812 ((cp[1] == del) || 1813 (cp[1] == '$') || 1814 (cp[1] == '\\'))) 1815 { 1816 Buf_AddByte(buf, (Byte)cp[1]); 1817 cp++; 1818 } else if (*cp == '$') { 1819 if (cp[1] != del) { 1820 /* 1821 * If unescaped dollar sign not before the 1822 * delimiter, assume it's a variable 1823 * substitution and recurse. 1824 */ 1825 char *cp2; 1826 int len; 1827 Boolean freeIt; 1828 1829 cp2 = Var_Parse(cp, ctxt, err, &len, &freeIt); 1830 Buf_AddBytes(buf, strlen(cp2), (Byte *)cp2); 1831 if (freeIt) { 1832 free(cp2); 1833 } 1834 cp += len - 1; 1835 } else { 1836 /* 1837 * Unescaped $ at end of pattern => anchor 1838 * pattern at end. 1839 */ 1840 pattern.flags |= VAR_MATCH_END; 1841 } 1842 } else { 1843 Buf_AddByte(buf, (Byte)*cp); 1844 } 1845 } 1846 1847 Buf_AddByte(buf, (Byte)'\0'); 1848 1849 /* 1850 * If lhs didn't end with the delimiter, complain and 1851 * return NULL 1852 */ 1853 if (*cp != del) { 1854 *lengthPtr = cp - start + 1; 1855 if (*freePtr) { 1856 free(str); 1857 } 1858 Buf_Destroy(buf, TRUE); 1859 Error("Unclosed substitution for %s (%c missing)", 1860 v->name, del); 1861 return (var_Error); 1862 } 1863 1864 /* 1865 * Fetch pattern and destroy buffer, but preserve the data 1866 * in it, since that's our lhs. Note that Buf_GetAll 1867 * will return the actual number of bytes, which includes 1868 * the null byte, so we have to decrement the length by 1869 * one. 1870 */ 1871 pattern.lhs = (char *)Buf_GetAll(buf, &pattern.leftLen); 1872 pattern.leftLen--; 1873 Buf_Destroy(buf, FALSE); 1874 1875 /* 1876 * Now comes the replacement string. Three things need to 1877 * be done here: 1) need to compress escaped delimiters and 1878 * ampersands and 2) need to replace unescaped ampersands 1879 * with the l.h.s. (since this isn't regexp, we can do 1880 * it right here) and 3) expand any variable substitutions. 1881 */ 1882 buf = Buf_Init(0); 1883 1884 tstr = cp + 1; 1885 for (cp = tstr; *cp != '\0' && *cp != del; cp++) { 1886 if ((*cp == '\\') && 1887 ((cp[1] == del) || 1888 (cp[1] == '&') || 1889 (cp[1] == '\\') || 1890 (cp[1] == '$'))) 1891 { 1892 Buf_AddByte(buf, (Byte)cp[1]); 1893 cp++; 1894 } else if ((*cp == '$') && (cp[1] != del)) { 1895 char *cp2; 1896 int len; 1897 Boolean freeIt; 1898 1899 cp2 = Var_Parse(cp, ctxt, err, &len, &freeIt); 1900 Buf_AddBytes(buf, strlen(cp2), (Byte *)cp2); 1901 cp += len - 1; 1902 if (freeIt) { 1903 free(cp2); 1904 } 1905 } else if (*cp == '&') { 1906 Buf_AddBytes(buf, pattern.leftLen, 1907 (Byte *)pattern.lhs); 1908 } else { 1909 Buf_AddByte(buf, (Byte)*cp); 1910 } 1911 } 1912 1913 Buf_AddByte(buf, (Byte)'\0'); 1914 1915 /* 1916 * If didn't end in delimiter character, complain 1917 */ 1918 if (*cp != del) { 1919 *lengthPtr = cp - start + 1; 1920 if (*freePtr) { 1921 free(str); 1922 } 1923 Buf_Destroy(buf, TRUE); 1924 Error("Unclosed substitution for %s (%c missing)", 1925 v->name, del); 1926 return (var_Error); 1927 } 1928 1929 pattern.rhs = (char *)Buf_GetAll(buf, &pattern.rightLen); 1930 pattern.rightLen--; 1931 Buf_Destroy(buf, FALSE); 1932 1933 /* 1934 * Check for global substitution. If 'g' after the final 1935 * delimiter, substitution is global and is marked that 1936 * way. 1937 */ 1938 cp++; 1939 if (*cp == 'g') { 1940 pattern.flags |= VAR_SUB_GLOBAL; 1941 cp++; 1942 } 1943 1944 termc = *cp; 1945 newStr = VarModify(str, VarSubstitute, 1946 (void *)&pattern); 1947 /* 1948 * Free the two strings. 1949 */ 1950 free(pattern.lhs); 1951 free(pattern.rhs); 1952 break; 1953 } 1954 case 'C': 1955 { 1956 VarREPattern pattern; 1957 char *re; 1958 int error; 1959 1960 pattern.flags = 0; 1961 delim = tstr[1]; 1962 tstr += 2; 1963 1964 cp = tstr; 1965 1966 if ((re = VarGetPattern(ctxt, err, &cp, delim, NULL, 1967 NULL, NULL)) == NULL) { 1968 /* was: goto cleanup */ 1969 *lengthPtr = cp - start + 1; 1970 if (*freePtr) 1971 free(str); 1972 if (delim != '\0') 1973 Error("Unclosed substitution for %s (%c missing)", 1974 v->name, delim); 1975 return (var_Error); 1976 } 1977 1978 if ((pattern.replace = VarGetPattern(ctxt, err, &cp, 1979 delim, NULL, NULL, NULL)) == NULL){ 1980 free(re); 1981 1982 /* was: goto cleanup */ 1983 *lengthPtr = cp - start + 1; 1984 if (*freePtr) 1985 free(str); 1986 if (delim != '\0') 1987 Error("Unclosed substitution for %s (%c missing)", 1988 v->name, delim); 1989 return (var_Error); 1990 } 1991 1992 for (;; cp++) { 1993 switch (*cp) { 1994 case 'g': 1995 pattern.flags |= VAR_SUB_GLOBAL; 1996 continue; 1997 case '1': 1998 pattern.flags |= VAR_SUB_ONE; 1999 continue; 2000 default: 2001 break; 2002 } 2003 break; 2004 } 2005 2006 termc = *cp; 2007 2008 error = regcomp(&pattern.re, re, REG_EXTENDED); 2009 free(re); 2010 if (error) { 2011 *lengthPtr = cp - start + 1; 2012 VarREError(error, &pattern.re, "RE substitution error"); 2013 free(pattern.replace); 2014 return (var_Error); 2015 } 2016 2017 pattern.nsub = pattern.re.re_nsub + 1; 2018 if (pattern.nsub < 1) 2019 pattern.nsub = 1; 2020 if (pattern.nsub > 10) 2021 pattern.nsub = 10; 2022 pattern.matches = emalloc(pattern.nsub * 2023 sizeof(regmatch_t)); 2024 newStr = VarModify(str, VarRESubstitute, 2025 (void *) &pattern); 2026 regfree(&pattern.re); 2027 free(pattern.replace); 2028 free(pattern.matches); 2029 break; 2030 } 2031 case 'Q': 2032 if (tstr[1] == endc || tstr[1] == ':') { 2033 newStr = VarQuote (str); 2034 cp = tstr + 1; 2035 termc = *cp; 2036 break; 2037 } 2038 /*FALLTHRU*/ 2039 case 'T': 2040 if (tstr[1] == endc || tstr[1] == ':') { 2041 newStr = VarModify (str, VarTail, (void *)0); 2042 cp = tstr + 1; 2043 termc = *cp; 2044 break; 2045 } 2046 /*FALLTHRU*/ 2047 case 'H': 2048 if (tstr[1] == endc || tstr[1] == ':') { 2049 newStr = VarModify (str, VarHead, (void *)0); 2050 cp = tstr + 1; 2051 termc = *cp; 2052 break; 2053 } 2054 /*FALLTHRU*/ 2055 case 'E': 2056 if (tstr[1] == endc || tstr[1] == ':') { 2057 newStr = VarModify (str, VarSuffix, (void *)0); 2058 cp = tstr + 1; 2059 termc = *cp; 2060 break; 2061 } 2062 /*FALLTHRU*/ 2063 case 'R': 2064 if (tstr[1] == endc || tstr[1] == ':') { 2065 newStr = VarModify (str, VarRoot, (void *)0); 2066 cp = tstr + 1; 2067 termc = *cp; 2068 break; 2069 } 2070 /*FALLTHRU*/ 2071#ifdef SUNSHCMD 2072 case 's': 2073 if (tstr[1] == 'h' && (tstr[2] == endc || tstr[2] == ':')) { 2074 char *error; 2075 newStr = Cmd_Exec (str, &error); 2076 if (error) 2077 Error (error, str); 2078 cp = tstr + 2; 2079 termc = *cp; 2080 break; 2081 } 2082 /*FALLTHRU*/ 2083#endif 2084 default: 2085 { 2086#ifdef SYSVVARSUB 2087 /* 2088 * This can either be a bogus modifier or a System-V 2089 * substitution command. 2090 */ 2091 VarPattern pattern; 2092 Boolean eqFound; 2093 2094 pattern.flags = 0; 2095 eqFound = FALSE; 2096 /* 2097 * First we make a pass through the string trying 2098 * to verify it is a SYSV-make-style translation: 2099 * it must be: <string1>=<string2>) 2100 */ 2101 cp = tstr; 2102 cnt = 1; 2103 while (*cp != '\0' && cnt) { 2104 if (*cp == '=') { 2105 eqFound = TRUE; 2106 /* continue looking for endc */ 2107 } 2108 else if (*cp == endc) 2109 cnt--; 2110 else if (*cp == startc) 2111 cnt++; 2112 if (cnt) 2113 cp++; 2114 } 2115 if (*cp == endc && eqFound) { 2116 2117 /* 2118 * Now we break this sucker into the lhs and 2119 * rhs. We must null terminate them of course. 2120 */ 2121 for (cp = tstr; *cp != '='; cp++) 2122 continue; 2123 pattern.lhs = tstr; 2124 pattern.leftLen = cp - tstr; 2125 *cp++ = '\0'; 2126 2127 pattern.rhs = cp; 2128 cnt = 1; 2129 while (cnt) { 2130 if (*cp == endc) 2131 cnt--; 2132 else if (*cp == startc) 2133 cnt++; 2134 if (cnt) 2135 cp++; 2136 } 2137 pattern.rightLen = cp - pattern.rhs; 2138 *cp = '\0'; 2139 2140 /* 2141 * SYSV modifications happen through the whole 2142 * string. Note the pattern is anchored at the end. 2143 */ 2144 newStr = VarModify(str, VarSYSVMatch, 2145 (void *)&pattern); 2146 2147 /* 2148 * Restore the nulled characters 2149 */ 2150 pattern.lhs[pattern.leftLen] = '='; 2151 pattern.rhs[pattern.rightLen] = endc; 2152 termc = endc; 2153 } else 2154#endif 2155 { 2156 Error ("Unknown modifier '%c'\n", *tstr); 2157 for (cp = tstr+1; 2158 *cp != ':' && *cp != endc && *cp != '\0'; 2159 cp++) 2160 continue; 2161 termc = *cp; 2162 newStr = var_Error; 2163 } 2164 } 2165 } 2166 DEBUGF(VAR, ("Result is \"%s\"\n", newStr)); 2167 2168 if (*freePtr) { 2169 free (str); 2170 } 2171 str = newStr; 2172 if (str != var_Error) { 2173 *freePtr = TRUE; 2174 } else { 2175 *freePtr = FALSE; 2176 } 2177 if (termc == '\0') { 2178 Error("Unclosed variable specification for %s", v->name); 2179 } else if (termc == ':') { 2180 *cp++ = termc; 2181 } else { 2182 *cp = termc; 2183 } 2184 tstr = cp; 2185 } 2186 *lengthPtr = tstr - start + 1; 2187 } else { 2188 *lengthPtr = tstr - start + 1; 2189 *tstr = endc; 2190 } 2191 2192 if (v->flags & VAR_FROM_ENV) { 2193 Boolean destroy = FALSE; 2194 2195 if (str != (char *)Buf_GetAll(v->val, (int *)NULL)) { 2196 destroy = TRUE; 2197 } else { 2198 /* 2199 * Returning the value unmodified, so tell the caller to free 2200 * the thing. 2201 */ 2202 *freePtr = TRUE; 2203 } 2204 free(v->name); 2205 Buf_Destroy(v->val, destroy); 2206 free(v); 2207 } else if (v->flags & VAR_JUNK) { 2208 /* 2209 * Perform any free'ing needed and set *freePtr to FALSE so the caller 2210 * doesn't try to free a static pointer. 2211 */ 2212 if (*freePtr) { 2213 free(str); 2214 } 2215 *freePtr = FALSE; 2216 free(v->name); 2217 Buf_Destroy(v->val, TRUE); 2218 free(v); 2219 if (dynamic) { 2220 str = emalloc(*lengthPtr + 1); 2221 strncpy(str, start, *lengthPtr); 2222 str[*lengthPtr] = '\0'; 2223 *freePtr = TRUE; 2224 } else { 2225 str = err ? var_Error : varNoError; 2226 } 2227 } 2228 return (str); 2229} 2230 2231/*- 2232 *----------------------------------------------------------------------- 2233 * Var_Subst -- 2234 * Substitute for all variables in the given string in the given context 2235 * If undefErr is TRUE, Parse_Error will be called when an undefined 2236 * variable is encountered. 2237 * 2238 * Results: 2239 * The resulting string. 2240 * 2241 * Side Effects: 2242 * None. The old string must be freed by the caller 2243 *----------------------------------------------------------------------- 2244 */ 2245char * 2246Var_Subst (char *var, char *str, GNode *ctxt, Boolean undefErr) 2247{ 2248 Buffer buf; /* Buffer for forming things */ 2249 char *val; /* Value to substitute for a variable */ 2250 int length; /* Length of the variable invocation */ 2251 Boolean doFree; /* Set true if val should be freed */ 2252 static Boolean errorReported; /* Set true if an error has already 2253 * been reported to prevent a plethora 2254 * of messages when recursing */ 2255 2256 buf = Buf_Init (MAKE_BSIZE); 2257 errorReported = FALSE; 2258 2259 while (*str) { 2260 if (var == NULL && (*str == '$') && (str[1] == '$')) { 2261 /* 2262 * A dollar sign may be escaped either with another dollar sign. 2263 * In such a case, we skip over the escape character and store the 2264 * dollar sign into the buffer directly. 2265 */ 2266 str++; 2267 Buf_AddByte(buf, (Byte)*str); 2268 str++; 2269 } else if (*str != '$') { 2270 /* 2271 * Skip as many characters as possible -- either to the end of 2272 * the string or to the next dollar sign (variable invocation). 2273 */ 2274 char *cp; 2275 2276 for (cp = str++; *str != '$' && *str != '\0'; str++) 2277 continue; 2278 Buf_AddBytes(buf, str - cp, (Byte *)cp); 2279 } else { 2280 if (var != NULL) { 2281 int expand; 2282 for (;;) { 2283 if (str[1] != '(' && str[1] != '{') { 2284 if (str[1] != *var || var[1] != '\0') { 2285 Buf_AddBytes(buf, 2, (Byte *) str); 2286 str += 2; 2287 expand = FALSE; 2288 } 2289 else 2290 expand = TRUE; 2291 break; 2292 } 2293 else { 2294 char *p; 2295 2296 /* 2297 * Scan up to the end of the variable name. 2298 */ 2299 for (p = &str[2]; *p && 2300 *p != ':' && *p != ')' && *p != '}'; p++) 2301 if (*p == '$') 2302 break; 2303 /* 2304 * A variable inside the variable. We cannot expand 2305 * the external variable yet, so we try again with 2306 * the nested one 2307 */ 2308 if (*p == '$') { 2309 Buf_AddBytes(buf, p - str, (Byte *) str); 2310 str = p; 2311 continue; 2312 } 2313 2314 if (strncmp(var, str + 2, p - str - 2) != 0 || 2315 var[p - str - 2] != '\0') { 2316 /* 2317 * Not the variable we want to expand, scan 2318 * until the next variable 2319 */ 2320 for (;*p != '$' && *p != '\0'; p++) 2321 continue; 2322 Buf_AddBytes(buf, p - str, (Byte *) str); 2323 str = p; 2324 expand = FALSE; 2325 } 2326 else 2327 expand = TRUE; 2328 break; 2329 } 2330 } 2331 if (!expand) 2332 continue; 2333 } 2334 2335 val = Var_Parse (str, ctxt, undefErr, &length, &doFree); 2336 2337 /* 2338 * When we come down here, val should either point to the 2339 * value of this variable, suitably modified, or be NULL. 2340 * Length should be the total length of the potential 2341 * variable invocation (from $ to end character...) 2342 */ 2343 if (val == var_Error || val == varNoError) { 2344 /* 2345 * If performing old-time variable substitution, skip over 2346 * the variable and continue with the substitution. Otherwise, 2347 * store the dollar sign and advance str so we continue with 2348 * the string... 2349 */ 2350 if (oldVars) { 2351 str += length; 2352 } else if (undefErr) { 2353 /* 2354 * If variable is undefined, complain and skip the 2355 * variable. The complaint will stop us from doing anything 2356 * when the file is parsed. 2357 */ 2358 if (!errorReported) { 2359 Parse_Error (PARSE_FATAL, 2360 "Undefined variable \"%.*s\"",length,str); 2361 } 2362 str += length; 2363 errorReported = TRUE; 2364 } else { 2365 Buf_AddByte (buf, (Byte)*str); 2366 str += 1; 2367 } 2368 } else { 2369 /* 2370 * We've now got a variable structure to store in. But first, 2371 * advance the string pointer. 2372 */ 2373 str += length; 2374 2375 /* 2376 * Copy all the characters from the variable value straight 2377 * into the new string. 2378 */ 2379 Buf_AddBytes (buf, strlen (val), (Byte *)val); 2380 if (doFree) { 2381 free (val); 2382 } 2383 } 2384 } 2385 } 2386 2387 Buf_AddByte (buf, '\0'); 2388 str = (char *)Buf_GetAll (buf, (int *)NULL); 2389 Buf_Destroy (buf, FALSE); 2390 return (str); 2391} 2392 2393/*- 2394 *----------------------------------------------------------------------- 2395 * Var_GetTail -- 2396 * Return the tail from each of a list of words. Used to set the 2397 * System V local variables. 2398 * 2399 * Results: 2400 * The resulting string. 2401 * 2402 * Side Effects: 2403 * None. 2404 * 2405 *----------------------------------------------------------------------- 2406 */ 2407char * 2408Var_GetTail(char *file) 2409{ 2410 return(VarModify(file, VarTail, (void *)0)); 2411} 2412 2413/*- 2414 *----------------------------------------------------------------------- 2415 * Var_GetHead -- 2416 * Find the leading components of a (list of) filename(s). 2417 * XXX: VarHead does not replace foo by ., as (sun) System V make 2418 * does. 2419 * 2420 * Results: 2421 * The leading components. 2422 * 2423 * Side Effects: 2424 * None. 2425 * 2426 *----------------------------------------------------------------------- 2427 */ 2428char * 2429Var_GetHead(char *file) 2430{ 2431 return(VarModify(file, VarHead, (void *)0)); 2432} 2433 2434/*- 2435 *----------------------------------------------------------------------- 2436 * Var_Init -- 2437 * Initialize the module 2438 * 2439 * Results: 2440 * None 2441 * 2442 * Side Effects: 2443 * The VAR_CMD and VAR_GLOBAL contexts are created 2444 *----------------------------------------------------------------------- 2445 */ 2446void 2447Var_Init (void) 2448{ 2449 VAR_GLOBAL = Targ_NewGN ("Global"); 2450 VAR_CMD = Targ_NewGN ("Command"); 2451 allVars = Lst_Init(FALSE); 2452 2453} 2454 2455 2456void 2457Var_End (void) 2458{ 2459 Lst_Destroy(allVars, VarDelete); 2460} 2461 2462 2463/****************** PRINT DEBUGGING INFO *****************/ 2464static int 2465VarPrintVar (void *vp, void *dummy __unused) 2466{ 2467 Var *v = (Var *) vp; 2468 printf ("%-16s = %s\n", v->name, (char *) Buf_GetAll(v->val, (int *)NULL)); 2469 return (0); 2470} 2471 2472/*- 2473 *----------------------------------------------------------------------- 2474 * Var_Dump -- 2475 * print all variables in a context 2476 *----------------------------------------------------------------------- 2477 */ 2478void 2479Var_Dump (GNode *ctxt) 2480{ 2481 Lst_ForEach (ctxt->context, VarPrintVar, (void *) 0); 2482}
| 795 * Var_Parse -- 796 * Given the start of a variable invocation, extract the variable 797 * name and find its value, then modify it according to the 798 * specification. 799 * 800 * Results: 801 * The (possibly-modified) value of the variable or var_Error if the 802 * specification is invalid. The length of the specification is 803 * placed in *lengthPtr (for invalid specifications, this is just 804 * 2...?). 805 * A Boolean in *freePtr telling whether the returned string should 806 * be freed by the caller. 807 * 808 * Side Effects: 809 * None. 810 * 811 *----------------------------------------------------------------------- 812 */ 813char * 814Var_Parse(char *str, GNode *ctxt, Boolean err, int *lengthPtr, Boolean *freePtr) 815{ 816 char *tstr; /* Pointer into str */ 817 Var *v; /* Variable in invocation */ 818 char *cp; /* Secondary pointer into str (place marker 819 * for tstr) */ 820 Boolean haveModifier;/* TRUE if have modifiers for the variable */ 821 char endc; /* Ending character when variable in parens 822 * or braces */ 823 char startc=0; /* Starting character when variable in parens 824 * or braces */ 825 int cnt; /* Used to count brace pairs when variable in 826 * in parens or braces */ 827 char *start; 828 char delim; 829 Boolean dynamic; /* TRUE if the variable is local and we're 830 * expanding it in a non-local context. This 831 * is done to support dynamic sources. The 832 * result is just the invocation, unaltered */ 833 int vlen; /* length of variable name, after embedded variable 834 * expansion */ 835 836 *freePtr = FALSE; 837 dynamic = FALSE; 838 start = str; 839 840 if (str[1] != '(' && str[1] != '{') { 841 /* 842 * If it's not bounded by braces of some sort, life is much simpler. 843 * We just need to check for the first character and return the 844 * value if it exists. 845 */ 846 char name[2]; 847 848 name[0] = str[1]; 849 name[1] = '\0'; 850 851 v = VarFind (name, ctxt, FIND_ENV | FIND_GLOBAL | FIND_CMD); 852 if (v == (Var *)NULL) { 853 *lengthPtr = 2; 854 855 if ((ctxt == VAR_CMD) || (ctxt == VAR_GLOBAL)) { 856 /* 857 * If substituting a local variable in a non-local context, 858 * assume it's for dynamic source stuff. We have to handle 859 * this specially and return the longhand for the variable 860 * with the dollar sign escaped so it makes it back to the 861 * caller. Only four of the local variables are treated 862 * specially as they are the only four that will be set 863 * when dynamic sources are expanded. 864 */ 865 /* XXX: It looks like $% and $! are reversed here */ 866 switch (str[1]) { 867 case '@': 868 return("$(.TARGET)"); 869 case '%': 870 return("$(.ARCHIVE)"); 871 case '*': 872 return("$(.PREFIX)"); 873 case '!': 874 return("$(.MEMBER)"); 875 default: 876 break; 877 } 878 } 879 /* 880 * Error 881 */ 882 return (err ? var_Error : varNoError); 883 } else { 884 haveModifier = FALSE; 885 tstr = &str[1]; 886 endc = str[1]; 887 } 888 } else { 889 /* build up expanded variable name in this buffer */ 890 Buffer buf = Buf_Init(MAKE_BSIZE); 891 892 startc = str[1]; 893 endc = startc == '(' ? ')' : '}'; 894 895 /* 896 * Skip to the end character or a colon, whichever comes first, 897 * replacing embedded variables as we go. 898 */ 899 for (tstr = str + 2; *tstr != '\0' && *tstr != endc && *tstr != ':'; tstr++) 900 if (*tstr == '$') { 901 int rlen; 902 Boolean rfree; 903 char* rval = Var_Parse(tstr, ctxt, err, &rlen, &rfree); 904 905 if (rval == var_Error) { 906 Fatal("Error expanding embedded variable."); 907 } else if (rval != NULL) { 908 Buf_AddBytes(buf, strlen(rval), (Byte *) rval); 909 if (rfree) 910 free(rval); 911 } 912 tstr += rlen - 1; 913 } else 914 Buf_AddByte(buf, (Byte) *tstr); 915 916 if (*tstr == '\0') { 917 /* 918 * If we never did find the end character, return NULL 919 * right now, setting the length to be the distance to 920 * the end of the string, since that's what make does. 921 */ 922 *lengthPtr = tstr - str; 923 return (var_Error); 924 } 925 926 haveModifier = (*tstr == ':'); 927 *tstr = '\0'; 928 929 Buf_AddByte(buf, (Byte) '\0'); 930 str = Buf_GetAll(buf, NULL); 931 vlen = strlen(str); 932 933 v = VarFind (str, ctxt, FIND_ENV | FIND_GLOBAL | FIND_CMD); 934 if ((v == (Var *)NULL) && (ctxt != VAR_CMD) && (ctxt != VAR_GLOBAL) && 935 (vlen == 2) && (str[1] == 'F' || str[1] == 'D')) 936 { 937 /* 938 * Check for bogus D and F forms of local variables since we're 939 * in a local context and the name is the right length. 940 */ 941 switch(str[0]) { 942 case '@': 943 case '%': 944 case '*': 945 case '!': 946 case '>': 947 case '<': 948 { 949 char vname[2]; 950 char *val; 951 952 /* 953 * Well, it's local -- go look for it. 954 */ 955 vname[0] = str[0]; 956 vname[1] = '\0'; 957 v = VarFind(vname, ctxt, 0); 958 959 if (v != (Var *)NULL && !haveModifier) { 960 /* 961 * No need for nested expansion or anything, as we're 962 * the only one who sets these things and we sure don't 963 * put nested invocations in them... 964 */ 965 val = (char *)Buf_GetAll(v->val, (int *)NULL); 966 967 if (str[1] == 'D') { 968 val = VarModify(val, VarHead, (void *)0); 969 } else { 970 val = VarModify(val, VarTail, (void *)0); 971 } 972 /* 973 * Resulting string is dynamically allocated, so 974 * tell caller to free it. 975 */ 976 *freePtr = TRUE; 977 *lengthPtr = tstr-start+1; 978 *tstr = endc; 979 Buf_Destroy(buf, TRUE); 980 return(val); 981 } 982 break; 983 default: 984 break; 985 } 986 } 987 } 988 989 if (v == (Var *)NULL) { 990 if (((vlen == 1) || 991 (((vlen == 2) && (str[1] == 'F' || 992 str[1] == 'D')))) && 993 ((ctxt == VAR_CMD) || (ctxt == VAR_GLOBAL))) 994 { 995 /* 996 * If substituting a local variable in a non-local context, 997 * assume it's for dynamic source stuff. We have to handle 998 * this specially and return the longhand for the variable 999 * with the dollar sign escaped so it makes it back to the 1000 * caller. Only four of the local variables are treated 1001 * specially as they are the only four that will be set 1002 * when dynamic sources are expanded. 1003 */ 1004 switch (str[0]) { 1005 case '@': 1006 case '%': 1007 case '*': 1008 case '!': 1009 dynamic = TRUE; 1010 break; 1011 default: 1012 break; 1013 } 1014 } else if ((vlen > 2) && (str[0] == '.') && 1015 isupper((unsigned char) str[1]) && 1016 ((ctxt == VAR_CMD) || (ctxt == VAR_GLOBAL))) 1017 { 1018 int len; 1019 1020 len = vlen - 1; 1021 if ((strncmp(str, ".TARGET", len) == 0) || 1022 (strncmp(str, ".ARCHIVE", len) == 0) || 1023 (strncmp(str, ".PREFIX", len) == 0) || 1024 (strncmp(str, ".MEMBER", len) == 0)) 1025 { 1026 dynamic = TRUE; 1027 } 1028 } 1029 1030 if (!haveModifier) { 1031 /* 1032 * No modifiers -- have specification length so we can return 1033 * now. 1034 */ 1035 *lengthPtr = tstr - start + 1; 1036 *tstr = endc; 1037 if (dynamic) { 1038 str = emalloc(*lengthPtr + 1); 1039 strncpy(str, start, *lengthPtr); 1040 str[*lengthPtr] = '\0'; 1041 *freePtr = TRUE; 1042 Buf_Destroy(buf, TRUE); 1043 return(str); 1044 } else { 1045 Buf_Destroy(buf, TRUE); 1046 return (err ? var_Error : varNoError); 1047 } 1048 } else { 1049 /* 1050 * Still need to get to the end of the variable specification, 1051 * so kludge up a Var structure for the modifications 1052 */ 1053 v = (Var *) emalloc(sizeof(Var)); 1054 v->name = estrdup(str); 1055 v->val = Buf_Init(1); 1056 v->flags = VAR_JUNK; 1057 } 1058 } 1059 Buf_Destroy(buf, TRUE); 1060 } 1061 1062 if (v->flags & VAR_IN_USE) { 1063 Fatal("Variable %s is recursive.", v->name); 1064 /*NOTREACHED*/ 1065 } else { 1066 v->flags |= VAR_IN_USE; 1067 } 1068 /* 1069 * Before doing any modification, we have to make sure the value 1070 * has been fully expanded. If it looks like recursion might be 1071 * necessary (there's a dollar sign somewhere in the variable's value) 1072 * we just call Var_Subst to do any other substitutions that are 1073 * necessary. Note that the value returned by Var_Subst will have 1074 * been dynamically-allocated, so it will need freeing when we 1075 * return. 1076 */ 1077 str = (char *)Buf_GetAll(v->val, (int *)NULL); 1078 if (strchr (str, '$') != (char *)NULL) { 1079 str = Var_Subst(NULL, str, ctxt, err); 1080 *freePtr = TRUE; 1081 } 1082 1083 v->flags &= ~VAR_IN_USE; 1084 1085 /* 1086 * Now we need to apply any modifiers the user wants applied. 1087 * These are: 1088 * :M<pattern> words which match the given <pattern>. 1089 * <pattern> is of the standard file 1090 * wildcarding form. 1091 * :S<d><pat1><d><pat2><d>[g] 1092 * Substitute <pat2> for <pat1> in the value 1093 * :C<d><pat1><d><pat2><d>[g] 1094 * Substitute <pat2> for regex <pat1> in the value 1095 * :H Substitute the head of each word 1096 * :T Substitute the tail of each word 1097 * :E Substitute the extension (minus '.') of 1098 * each word 1099 * :R Substitute the root of each word 1100 * (pathname minus the suffix). 1101 * :lhs=rhs Like :S, but the rhs goes to the end of 1102 * the invocation. 1103 * :U Converts variable to upper-case. 1104 * :L Converts variable to lower-case. 1105 */ 1106 if ((str != (char *)NULL) && haveModifier) { 1107 /* 1108 * Skip initial colon while putting it back. 1109 */ 1110 *tstr++ = ':'; 1111 while (*tstr != endc) { 1112 char *newStr; /* New value to return */ 1113 char termc; /* Character which terminated scan */ 1114 1115 DEBUGF(VAR, ("Applying :%c to \"%s\"\n", *tstr, str)); 1116 switch (*tstr) { 1117 case 'U': 1118 if (tstr[1] == endc || tstr[1] == ':') { 1119 Buffer buf; 1120 buf = Buf_Init(MAKE_BSIZE); 1121 for (cp = str; *cp ; cp++) 1122 Buf_AddByte(buf, (Byte) toupper(*cp)); 1123 1124 Buf_AddByte(buf, (Byte) '\0'); 1125 newStr = (char *) Buf_GetAll(buf, (int *) NULL); 1126 Buf_Destroy(buf, FALSE); 1127 1128 cp = tstr + 1; 1129 termc = *cp; 1130 break; 1131 } 1132 /* FALLTHROUGH */ 1133 case 'L': 1134 if (tstr[1] == endc || tstr[1] == ':') { 1135 Buffer buf; 1136 buf = Buf_Init(MAKE_BSIZE); 1137 for (cp = str; *cp ; cp++) 1138 Buf_AddByte(buf, (Byte) tolower(*cp)); 1139 1140 Buf_AddByte(buf, (Byte) '\0'); 1141 newStr = (char *) Buf_GetAll(buf, (int *) NULL); 1142 Buf_Destroy(buf, FALSE); 1143 1144 cp = tstr + 1; 1145 termc = *cp; 1146 break; 1147 } 1148 /* FALLTHROUGH */ 1149 case 'N': 1150 case 'M': 1151 { 1152 char *pattern; 1153 char *cp2; 1154 Boolean copy; 1155 1156 copy = FALSE; 1157 for (cp = tstr + 1; 1158 *cp != '\0' && *cp != ':' && *cp != endc; 1159 cp++) 1160 { 1161 if (*cp == '\\' && (cp[1] == ':' || cp[1] == endc)){ 1162 copy = TRUE; 1163 cp++; 1164 } 1165 } 1166 termc = *cp; 1167 *cp = '\0'; 1168 if (copy) { 1169 /* 1170 * Need to compress the \:'s out of the pattern, so 1171 * allocate enough room to hold the uncompressed 1172 * pattern (note that cp started at tstr+1, so 1173 * cp - tstr takes the null byte into account) and 1174 * compress the pattern into the space. 1175 */ 1176 pattern = emalloc(cp - tstr); 1177 for (cp2 = pattern, cp = tstr + 1; 1178 *cp != '\0'; 1179 cp++, cp2++) 1180 { 1181 if ((*cp == '\\') && 1182 (cp[1] == ':' || cp[1] == endc)) { 1183 cp++; 1184 } 1185 *cp2 = *cp; 1186 } 1187 *cp2 = '\0'; 1188 } else { 1189 pattern = &tstr[1]; 1190 } 1191 if (*tstr == 'M' || *tstr == 'm') { 1192 newStr = VarModify(str, VarMatch, (void *)pattern); 1193 } else { 1194 newStr = VarModify(str, VarNoMatch, 1195 (void *)pattern); 1196 } 1197 if (copy) { 1198 free(pattern); 1199 } 1200 break; 1201 } 1202 case 'S': 1203 { 1204 VarPattern pattern; 1205 char del; 1206 Buffer buf; /* Buffer for patterns */ 1207 1208 pattern.flags = 0; 1209 del = tstr[1]; 1210 tstr += 2; 1211 1212 /* 1213 * If pattern begins with '^', it is anchored to the 1214 * start of the word -- skip over it and flag pattern. 1215 */ 1216 if (*tstr == '^') { 1217 pattern.flags |= VAR_MATCH_START; 1218 tstr += 1; 1219 } 1220 1221 buf = Buf_Init(0); 1222 1223 /* 1224 * Pass through the lhs looking for 1) escaped delimiters, 1225 * '$'s and backslashes (place the escaped character in 1226 * uninterpreted) and 2) unescaped $'s that aren't before 1227 * the delimiter (expand the variable substitution). 1228 * The result is left in the Buffer buf. 1229 */ 1230 for (cp = tstr; *cp != '\0' && *cp != del; cp++) { 1231 if ((*cp == '\\') && 1232 ((cp[1] == del) || 1233 (cp[1] == '$') || 1234 (cp[1] == '\\'))) 1235 { 1236 Buf_AddByte(buf, (Byte)cp[1]); 1237 cp++; 1238 } else if (*cp == '$') { 1239 if (cp[1] != del) { 1240 /* 1241 * If unescaped dollar sign not before the 1242 * delimiter, assume it's a variable 1243 * substitution and recurse. 1244 */ 1245 char *cp2; 1246 int len; 1247 Boolean freeIt; 1248 1249 cp2 = Var_Parse(cp, ctxt, err, &len, &freeIt); 1250 Buf_AddBytes(buf, strlen(cp2), (Byte *)cp2); 1251 if (freeIt) { 1252 free(cp2); 1253 } 1254 cp += len - 1; 1255 } else { 1256 /* 1257 * Unescaped $ at end of pattern => anchor 1258 * pattern at end. 1259 */ 1260 pattern.flags |= VAR_MATCH_END; 1261 } 1262 } else { 1263 Buf_AddByte(buf, (Byte)*cp); 1264 } 1265 } 1266 1267 Buf_AddByte(buf, (Byte)'\0'); 1268 1269 /* 1270 * If lhs didn't end with the delimiter, complain and 1271 * return NULL 1272 */ 1273 if (*cp != del) { 1274 *lengthPtr = cp - start + 1; 1275 if (*freePtr) { 1276 free(str); 1277 } 1278 Buf_Destroy(buf, TRUE); 1279 Error("Unclosed substitution for %s (%c missing)", 1280 v->name, del); 1281 return (var_Error); 1282 } 1283 1284 /* 1285 * Fetch pattern and destroy buffer, but preserve the data 1286 * in it, since that's our lhs. Note that Buf_GetAll 1287 * will return the actual number of bytes, which includes 1288 * the null byte, so we have to decrement the length by 1289 * one. 1290 */ 1291 pattern.lhs = (char *)Buf_GetAll(buf, &pattern.leftLen); 1292 pattern.leftLen--; 1293 Buf_Destroy(buf, FALSE); 1294 1295 /* 1296 * Now comes the replacement string. Three things need to 1297 * be done here: 1) need to compress escaped delimiters and 1298 * ampersands and 2) need to replace unescaped ampersands 1299 * with the l.h.s. (since this isn't regexp, we can do 1300 * it right here) and 3) expand any variable substitutions. 1301 */ 1302 buf = Buf_Init(0); 1303 1304 tstr = cp + 1; 1305 for (cp = tstr; *cp != '\0' && *cp != del; cp++) { 1306 if ((*cp == '\\') && 1307 ((cp[1] == del) || 1308 (cp[1] == '&') || 1309 (cp[1] == '\\') || 1310 (cp[1] == '$'))) 1311 { 1312 Buf_AddByte(buf, (Byte)cp[1]); 1313 cp++; 1314 } else if ((*cp == '$') && (cp[1] != del)) { 1315 char *cp2; 1316 int len; 1317 Boolean freeIt; 1318 1319 cp2 = Var_Parse(cp, ctxt, err, &len, &freeIt); 1320 Buf_AddBytes(buf, strlen(cp2), (Byte *)cp2); 1321 cp += len - 1; 1322 if (freeIt) { 1323 free(cp2); 1324 } 1325 } else if (*cp == '&') { 1326 Buf_AddBytes(buf, pattern.leftLen, 1327 (Byte *)pattern.lhs); 1328 } else { 1329 Buf_AddByte(buf, (Byte)*cp); 1330 } 1331 } 1332 1333 Buf_AddByte(buf, (Byte)'\0'); 1334 1335 /* 1336 * If didn't end in delimiter character, complain 1337 */ 1338 if (*cp != del) { 1339 *lengthPtr = cp - start + 1; 1340 if (*freePtr) { 1341 free(str); 1342 } 1343 Buf_Destroy(buf, TRUE); 1344 Error("Unclosed substitution for %s (%c missing)", 1345 v->name, del); 1346 return (var_Error); 1347 } 1348 1349 pattern.rhs = (char *)Buf_GetAll(buf, &pattern.rightLen); 1350 pattern.rightLen--; 1351 Buf_Destroy(buf, FALSE); 1352 1353 /* 1354 * Check for global substitution. If 'g' after the final 1355 * delimiter, substitution is global and is marked that 1356 * way. 1357 */ 1358 cp++; 1359 if (*cp == 'g') { 1360 pattern.flags |= VAR_SUB_GLOBAL; 1361 cp++; 1362 } 1363 1364 termc = *cp; 1365 newStr = VarModify(str, VarSubstitute, 1366 (void *)&pattern); 1367 /* 1368 * Free the two strings. 1369 */ 1370 free(pattern.lhs); 1371 free(pattern.rhs); 1372 break; 1373 } 1374 case 'C': 1375 { 1376 VarREPattern pattern; 1377 char *re; 1378 int error; 1379 1380 pattern.flags = 0; 1381 delim = tstr[1]; 1382 tstr += 2; 1383 1384 cp = tstr; 1385 1386 if ((re = VarGetPattern(ctxt, err, &cp, delim, NULL, 1387 NULL, NULL)) == NULL) { 1388 /* was: goto cleanup */ 1389 *lengthPtr = cp - start + 1; 1390 if (*freePtr) 1391 free(str); 1392 if (delim != '\0') 1393 Error("Unclosed substitution for %s (%c missing)", 1394 v->name, delim); 1395 return (var_Error); 1396 } 1397 1398 if ((pattern.replace = VarGetPattern(ctxt, err, &cp, 1399 delim, NULL, NULL, NULL)) == NULL){ 1400 free(re); 1401 1402 /* was: goto cleanup */ 1403 *lengthPtr = cp - start + 1; 1404 if (*freePtr) 1405 free(str); 1406 if (delim != '\0') 1407 Error("Unclosed substitution for %s (%c missing)", 1408 v->name, delim); 1409 return (var_Error); 1410 } 1411 1412 for (;; cp++) { 1413 switch (*cp) { 1414 case 'g': 1415 pattern.flags |= VAR_SUB_GLOBAL; 1416 continue; 1417 case '1': 1418 pattern.flags |= VAR_SUB_ONE; 1419 continue; 1420 default: 1421 break; 1422 } 1423 break; 1424 } 1425 1426 termc = *cp; 1427 1428 error = regcomp(&pattern.re, re, REG_EXTENDED); 1429 free(re); 1430 if (error) { 1431 *lengthPtr = cp - start + 1; 1432 VarREError(error, &pattern.re, "RE substitution error"); 1433 free(pattern.replace); 1434 return (var_Error); 1435 } 1436 1437 pattern.nsub = pattern.re.re_nsub + 1; 1438 if (pattern.nsub < 1) 1439 pattern.nsub = 1; 1440 if (pattern.nsub > 10) 1441 pattern.nsub = 10; 1442 pattern.matches = emalloc(pattern.nsub * 1443 sizeof(regmatch_t)); 1444 newStr = VarModify(str, VarRESubstitute, 1445 (void *) &pattern); 1446 regfree(&pattern.re); 1447 free(pattern.replace); 1448 free(pattern.matches); 1449 break; 1450 } 1451 case 'Q': 1452 if (tstr[1] == endc || tstr[1] == ':') { 1453 newStr = VarQuote (str); 1454 cp = tstr + 1; 1455 termc = *cp; 1456 break; 1457 } 1458 /*FALLTHRU*/ 1459 case 'T': 1460 if (tstr[1] == endc || tstr[1] == ':') { 1461 newStr = VarModify (str, VarTail, (void *)0); 1462 cp = tstr + 1; 1463 termc = *cp; 1464 break; 1465 } 1466 /*FALLTHRU*/ 1467 case 'H': 1468 if (tstr[1] == endc || tstr[1] == ':') { 1469 newStr = VarModify (str, VarHead, (void *)0); 1470 cp = tstr + 1; 1471 termc = *cp; 1472 break; 1473 } 1474 /*FALLTHRU*/ 1475 case 'E': 1476 if (tstr[1] == endc || tstr[1] == ':') { 1477 newStr = VarModify (str, VarSuffix, (void *)0); 1478 cp = tstr + 1; 1479 termc = *cp; 1480 break; 1481 } 1482 /*FALLTHRU*/ 1483 case 'R': 1484 if (tstr[1] == endc || tstr[1] == ':') { 1485 newStr = VarModify (str, VarRoot, (void *)0); 1486 cp = tstr + 1; 1487 termc = *cp; 1488 break; 1489 } 1490 /*FALLTHRU*/ 1491#ifdef SUNSHCMD 1492 case 's': 1493 if (tstr[1] == 'h' && (tstr[2] == endc || tstr[2] == ':')) { 1494 char *error; 1495 newStr = Cmd_Exec (str, &error); 1496 if (error) 1497 Error (error, str); 1498 cp = tstr + 2; 1499 termc = *cp; 1500 break; 1501 } 1502 /*FALLTHRU*/ 1503#endif 1504 default: 1505 { 1506#ifdef SYSVVARSUB 1507 /* 1508 * This can either be a bogus modifier or a System-V 1509 * substitution command. 1510 */ 1511 VarPattern pattern; 1512 Boolean eqFound; 1513 1514 pattern.flags = 0; 1515 eqFound = FALSE; 1516 /* 1517 * First we make a pass through the string trying 1518 * to verify it is a SYSV-make-style translation: 1519 * it must be: <string1>=<string2>) 1520 */ 1521 cp = tstr; 1522 cnt = 1; 1523 while (*cp != '\0' && cnt) { 1524 if (*cp == '=') { 1525 eqFound = TRUE; 1526 /* continue looking for endc */ 1527 } 1528 else if (*cp == endc) 1529 cnt--; 1530 else if (*cp == startc) 1531 cnt++; 1532 if (cnt) 1533 cp++; 1534 } 1535 if (*cp == endc && eqFound) { 1536 1537 /* 1538 * Now we break this sucker into the lhs and 1539 * rhs. We must null terminate them of course. 1540 */ 1541 for (cp = tstr; *cp != '='; cp++) 1542 continue; 1543 pattern.lhs = tstr; 1544 pattern.leftLen = cp - tstr; 1545 *cp++ = '\0'; 1546 1547 pattern.rhs = cp; 1548 cnt = 1; 1549 while (cnt) { 1550 if (*cp == endc) 1551 cnt--; 1552 else if (*cp == startc) 1553 cnt++; 1554 if (cnt) 1555 cp++; 1556 } 1557 pattern.rightLen = cp - pattern.rhs; 1558 *cp = '\0'; 1559 1560 /* 1561 * SYSV modifications happen through the whole 1562 * string. Note the pattern is anchored at the end. 1563 */ 1564 newStr = VarModify(str, VarSYSVMatch, 1565 (void *)&pattern); 1566 1567 /* 1568 * Restore the nulled characters 1569 */ 1570 pattern.lhs[pattern.leftLen] = '='; 1571 pattern.rhs[pattern.rightLen] = endc; 1572 termc = endc; 1573 } else 1574#endif 1575 { 1576 Error ("Unknown modifier '%c'\n", *tstr); 1577 for (cp = tstr+1; 1578 *cp != ':' && *cp != endc && *cp != '\0'; 1579 cp++) 1580 continue; 1581 termc = *cp; 1582 newStr = var_Error; 1583 } 1584 } 1585 } 1586 DEBUGF(VAR, ("Result is \"%s\"\n", newStr)); 1587 1588 if (*freePtr) { 1589 free (str); 1590 } 1591 str = newStr; 1592 if (str != var_Error) { 1593 *freePtr = TRUE; 1594 } else { 1595 *freePtr = FALSE; 1596 } 1597 if (termc == '\0') { 1598 Error("Unclosed variable specification for %s", v->name); 1599 } else if (termc == ':') { 1600 *cp++ = termc; 1601 } else { 1602 *cp = termc; 1603 } 1604 tstr = cp; 1605 } 1606 *lengthPtr = tstr - start + 1; 1607 } else { 1608 *lengthPtr = tstr - start + 1; 1609 *tstr = endc; 1610 } 1611 1612 if (v->flags & VAR_FROM_ENV) { 1613 Boolean destroy = FALSE; 1614 1615 if (str != (char *)Buf_GetAll(v->val, (int *)NULL)) { 1616 destroy = TRUE; 1617 } else { 1618 /* 1619 * Returning the value unmodified, so tell the caller to free 1620 * the thing. 1621 */ 1622 *freePtr = TRUE; 1623 } 1624 free(v->name); 1625 Buf_Destroy(v->val, destroy); 1626 free(v); 1627 } else if (v->flags & VAR_JUNK) { 1628 /* 1629 * Perform any free'ing needed and set *freePtr to FALSE so the caller 1630 * doesn't try to free a static pointer. 1631 */ 1632 if (*freePtr) { 1633 free(str); 1634 } 1635 *freePtr = FALSE; 1636 free(v->name); 1637 Buf_Destroy(v->val, TRUE); 1638 free(v); 1639 if (dynamic) { 1640 str = emalloc(*lengthPtr + 1); 1641 strncpy(str, start, *lengthPtr); 1642 str[*lengthPtr] = '\0'; 1643 *freePtr = TRUE; 1644 } else { 1645 str = err ? var_Error : varNoError; 1646 } 1647 } 1648 return (str); 1649} 1650 1651/*- 1652 *----------------------------------------------------------------------- 1653 * Var_Subst -- 1654 * Substitute for all variables in the given string in the given context 1655 * If undefErr is TRUE, Parse_Error will be called when an undefined 1656 * variable is encountered. 1657 * 1658 * Results: 1659 * The resulting string. 1660 * 1661 * Side Effects: 1662 * None. The old string must be freed by the caller 1663 *----------------------------------------------------------------------- 1664 */ 1665char * 1666Var_Subst (char *var, char *str, GNode *ctxt, Boolean undefErr) 1667{ 1668 Buffer buf; /* Buffer for forming things */ 1669 char *val; /* Value to substitute for a variable */ 1670 int length; /* Length of the variable invocation */ 1671 Boolean doFree; /* Set true if val should be freed */ 1672 static Boolean errorReported; /* Set true if an error has already 1673 * been reported to prevent a plethora 1674 * of messages when recursing */ 1675 1676 buf = Buf_Init (MAKE_BSIZE); 1677 errorReported = FALSE; 1678 1679 while (*str) { 1680 if (var == NULL && (*str == '$') && (str[1] == '$')) { 1681 /* 1682 * A dollar sign may be escaped either with another dollar sign. 1683 * In such a case, we skip over the escape character and store the 1684 * dollar sign into the buffer directly. 1685 */ 1686 str++; 1687 Buf_AddByte(buf, (Byte)*str); 1688 str++; 1689 } else if (*str != '$') { 1690 /* 1691 * Skip as many characters as possible -- either to the end of 1692 * the string or to the next dollar sign (variable invocation). 1693 */ 1694 char *cp; 1695 1696 for (cp = str++; *str != '$' && *str != '\0'; str++) 1697 continue; 1698 Buf_AddBytes(buf, str - cp, (Byte *)cp); 1699 } else { 1700 if (var != NULL) { 1701 int expand; 1702 for (;;) { 1703 if (str[1] != '(' && str[1] != '{') { 1704 if (str[1] != *var || var[1] != '\0') { 1705 Buf_AddBytes(buf, 2, (Byte *) str); 1706 str += 2; 1707 expand = FALSE; 1708 } 1709 else 1710 expand = TRUE; 1711 break; 1712 } 1713 else { 1714 char *p; 1715 1716 /* 1717 * Scan up to the end of the variable name. 1718 */ 1719 for (p = &str[2]; *p && 1720 *p != ':' && *p != ')' && *p != '}'; p++) 1721 if (*p == '$') 1722 break; 1723 /* 1724 * A variable inside the variable. We cannot expand 1725 * the external variable yet, so we try again with 1726 * the nested one 1727 */ 1728 if (*p == '$') { 1729 Buf_AddBytes(buf, p - str, (Byte *) str); 1730 str = p; 1731 continue; 1732 } 1733 1734 if (strncmp(var, str + 2, p - str - 2) != 0 || 1735 var[p - str - 2] != '\0') { 1736 /* 1737 * Not the variable we want to expand, scan 1738 * until the next variable 1739 */ 1740 for (;*p != '$' && *p != '\0'; p++) 1741 continue; 1742 Buf_AddBytes(buf, p - str, (Byte *) str); 1743 str = p; 1744 expand = FALSE; 1745 } 1746 else 1747 expand = TRUE; 1748 break; 1749 } 1750 } 1751 if (!expand) 1752 continue; 1753 } 1754 1755 val = Var_Parse (str, ctxt, undefErr, &length, &doFree); 1756 1757 /* 1758 * When we come down here, val should either point to the 1759 * value of this variable, suitably modified, or be NULL. 1760 * Length should be the total length of the potential 1761 * variable invocation (from $ to end character...) 1762 */ 1763 if (val == var_Error || val == varNoError) { 1764 /* 1765 * If performing old-time variable substitution, skip over 1766 * the variable and continue with the substitution. Otherwise, 1767 * store the dollar sign and advance str so we continue with 1768 * the string... 1769 */ 1770 if (oldVars) { 1771 str += length; 1772 } else if (undefErr) { 1773 /* 1774 * If variable is undefined, complain and skip the 1775 * variable. The complaint will stop us from doing anything 1776 * when the file is parsed. 1777 */ 1778 if (!errorReported) { 1779 Parse_Error (PARSE_FATAL, 1780 "Undefined variable \"%.*s\"",length,str); 1781 } 1782 str += length; 1783 errorReported = TRUE; 1784 } else { 1785 Buf_AddByte (buf, (Byte)*str); 1786 str += 1; 1787 } 1788 } else { 1789 /* 1790 * We've now got a variable structure to store in. But first, 1791 * advance the string pointer. 1792 */ 1793 str += length; 1794 1795 /* 1796 * Copy all the characters from the variable value straight 1797 * into the new string. 1798 */ 1799 Buf_AddBytes (buf, strlen (val), (Byte *)val); 1800 if (doFree) { 1801 free (val); 1802 } 1803 } 1804 } 1805 } 1806 1807 Buf_AddByte (buf, '\0'); 1808 str = (char *)Buf_GetAll (buf, (int *)NULL); 1809 Buf_Destroy (buf, FALSE); 1810 return (str); 1811} 1812 1813/*- 1814 *----------------------------------------------------------------------- 1815 * Var_GetTail -- 1816 * Return the tail from each of a list of words. Used to set the 1817 * System V local variables. 1818 * 1819 * Results: 1820 * The resulting string. 1821 * 1822 * Side Effects: 1823 * None. 1824 * 1825 *----------------------------------------------------------------------- 1826 */ 1827char * 1828Var_GetTail(char *file) 1829{ 1830 return(VarModify(file, VarTail, (void *)0)); 1831} 1832 1833/*- 1834 *----------------------------------------------------------------------- 1835 * Var_GetHead -- 1836 * Find the leading components of a (list of) filename(s). 1837 * XXX: VarHead does not replace foo by ., as (sun) System V make 1838 * does. 1839 * 1840 * Results: 1841 * The leading components. 1842 * 1843 * Side Effects: 1844 * None. 1845 * 1846 *----------------------------------------------------------------------- 1847 */ 1848char * 1849Var_GetHead(char *file) 1850{ 1851 return(VarModify(file, VarHead, (void *)0)); 1852} 1853 1854/*- 1855 *----------------------------------------------------------------------- 1856 * Var_Init -- 1857 * Initialize the module 1858 * 1859 * Results: 1860 * None 1861 * 1862 * Side Effects: 1863 * The VAR_CMD and VAR_GLOBAL contexts are created 1864 *----------------------------------------------------------------------- 1865 */ 1866void 1867Var_Init (void) 1868{ 1869 VAR_GLOBAL = Targ_NewGN ("Global"); 1870 VAR_CMD = Targ_NewGN ("Command"); 1871 allVars = Lst_Init(FALSE); 1872 1873} 1874 1875 1876void 1877Var_End (void) 1878{ 1879 Lst_Destroy(allVars, VarDelete); 1880} 1881 1882 1883/****************** PRINT DEBUGGING INFO *****************/ 1884static int 1885VarPrintVar (void *vp, void *dummy __unused) 1886{ 1887 Var *v = (Var *) vp; 1888 printf ("%-16s = %s\n", v->name, (char *) Buf_GetAll(v->val, (int *)NULL)); 1889 return (0); 1890} 1891 1892/*- 1893 *----------------------------------------------------------------------- 1894 * Var_Dump -- 1895 * print all variables in a context 1896 *----------------------------------------------------------------------- 1897 */ 1898void 1899Var_Dump (GNode *ctxt) 1900{ 1901 Lst_ForEach (ctxt->context, VarPrintVar, (void *) 0); 1902}
|