Annotation of src/usr.bin/make/var.c, Revision 1.50
1.50 ! espie 1: /* $OpenBSD: var.c,v 1.49 2000/10/13 08:29:21 espie Exp $ */
1.6 millert 2: /* $NetBSD: var.c,v 1.18 1997/03/18 19:24:46 christos Exp $ */
1.1 deraadt 3:
4: /*
1.17 espie 5: * Copyright (c) 1999 Marc Espie.
6: *
7: * Extensive code modifications for the OpenBSD project.
8: *
9: * Redistribution and use in source and binary forms, with or without
10: * modification, are permitted provided that the following conditions
11: * are met:
12: * 1. Redistributions of source code must retain the above copyright
13: * notice, this list of conditions and the following disclaimer.
14: * 2. Redistributions in binary form must reproduce the above copyright
15: * notice, this list of conditions and the following disclaimer in the
16: * documentation and/or other materials provided with the distribution.
17: *
18: * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT AND CONTRIBUTORS
19: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OPENBSD
22: * PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29: */
30:
31: /*
1.5 millert 32: * Copyright (c) 1988, 1989, 1990, 1993
33: * The Regents of the University of California. All rights reserved.
1.1 deraadt 34: * Copyright (c) 1989 by Berkeley Softworks
35: * All rights reserved.
36: *
37: * This code is derived from software contributed to Berkeley by
38: * Adam de Boor.
39: *
40: * Redistribution and use in source and binary forms, with or without
41: * modification, are permitted provided that the following conditions
42: * are met:
43: * 1. Redistributions of source code must retain the above copyright
44: * notice, this list of conditions and the following disclaimer.
45: * 2. Redistributions in binary form must reproduce the above copyright
46: * notice, this list of conditions and the following disclaimer in the
47: * documentation and/or other materials provided with the distribution.
48: * 3. All advertising materials mentioning features or use of this software
49: * must display the following acknowledgement:
50: * This product includes software developed by the University of
51: * California, Berkeley and its contributors.
52: * 4. Neither the name of the University nor the names of its contributors
53: * may be used to endorse or promote products derived from this software
54: * without specific prior written permission.
55: *
56: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
57: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
58: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
59: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
60: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
61: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
62: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
63: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
64: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
65: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
66: * SUCH DAMAGE.
67: */
68:
69: /*-
70: * var.c --
71: * Variable-handling functions
72: *
73: * Interface:
74: * Var_Set Set the value of a variable in the given
75: * context. The variable is created if it doesn't
76: * yet exist. The value and variable name need not
77: * be preserved.
78: *
79: * Var_Append Append more characters to an existing variable
80: * in the given context. The variable needn't
81: * exist already -- it will be created if it doesn't.
82: * A space is placed between the old value and the
83: * new one.
84: *
85: * Var_Exists See if a variable exists.
86: *
87: * Var_Value Return the value of a variable in a context or
88: * NULL if the variable is undefined.
89: *
90: * Var_Subst Substitute named variable, or all variables if
91: * NULL in a string using
92: * the given context as the top-most one. If the
93: * third argument is non-zero, Parse_Error is
94: * called if any variables are undefined.
95: *
1.50 ! espie 96: * Var_SubstVar Substitute a named variable in a string using
! 97: * the given context as the top-most one,
! 98: * accumulating the result into a user-supplied
! 99: * buffer.
! 100: *
1.1 deraadt 101: * Var_Parse Parse a variable expansion from a string and
102: * return the result and the number of characters
103: * consumed.
104: *
105: * Var_Delete Delete a variable in a context.
106: *
107: * Var_Init Initialize this module.
108: *
109: * Debugging:
110: * Var_Dump Print out all variables defined in the given
111: * context.
112: *
113: * XXX: There's a lot of duplication in these functions.
114: */
115:
116: #include <ctype.h>
1.6 millert 117: #ifndef MAKE_BOOTSTRAP
1.9 deraadt 118: #include <sys/types.h>
1.6 millert 119: #include <regex.h>
120: #endif
121: #include <stdlib.h>
1.35 espie 122: #include <stddef.h>
1.1 deraadt 123: #include "make.h"
124: #include "buf.h"
1.38 espie 125: #include "ohash.h"
126: #include "hashconsts.h"
1.43 espie 127: #include "varmodifiers.h"
1.34 espie 128:
1.48 espie 129: #ifndef lint
130: #if 0
131: static char sccsid[] = "@(#)var.c 8.3 (Berkeley) 3/19/94";
132: #else
133: UNUSED
1.50 ! espie 134: static char rcsid[] = "$OpenBSD: var.c,v 1.49 2000/10/13 08:29:21 espie Exp $";
1.48 espie 135: #endif
136: #endif /* not lint */
137:
1.37 espie 138: static SymTable *CTXT_GLOBAL, *CTXT_CMD, *CTXT_ENV;
139:
1.34 espie 140: static char *varnames[] = {
141: TARGET,
142: OODATE,
143: ALLSRC,
144: IMPSRC,
145: PREFIX,
146: ARCHIVE,
147: MEMBER };
148:
1.1 deraadt 149: /*
150: * This is a harmless return value for Var_Parse that can be used by Var_Subst
151: * to determine if there was an error in parsing -- easier than returning
152: * a flag, as things outside this module don't give a hoot.
153: */
154: char var_Error[] = "";
155:
156: /*
157: * Similar to var_Error, but returned when the 'err' flag for Var_Parse is
158: * set false. Why not just use a constant? Well, gcc likes to condense
159: * identical string instances...
160: */
161: static char varNoError[] = "";
162:
163: /*
164: * Internally, variables are contained in four different contexts.
165: * 1) the environment. They may not be changed. If an environment
166: * variable is appended-to, the result is placed in the global
167: * context.
168: * 2) the global context. Variables set in the Makefile are located in
169: * the global context. It is the penultimate context searched when
170: * substituting.
171: * 3) the command-line context. All variables set on the command line
172: * are placed in this context. They are UNALTERABLE once placed here.
173: * 4) the local context. Each target has associated with it a context
174: * list. On this list are located the structures describing such
175: * local variables as $(@) and $(*)
176: * The four contexts are searched in the reverse order from which they are
177: * listed.
178: */
1.37 espie 179: GSymT *VAR_GLOBAL; /* variables from the makefile */
180: GSymT *VAR_CMD; /* variables defined on the command-line */
181: static GSymT *VAR_ENV; /* variables read from env */
1.1 deraadt 182:
1.39 espie 183: #define FIND_MINE 0x1 /* look in CTXT_CMD and CTXT_GLOBAL */
184: #define FIND_ENV 0x2 /* look in the environment */
1.1 deraadt 185:
1.37 espie 186: typedef struct Var_ {
1.23 espie 187: BUFFER val; /* its value */
1.1 deraadt 188: int flags; /* miscellaneous status flags */
189: #define VAR_IN_USE 1 /* Variable's value currently being used.
190: * Used to avoid recursion */
191: #define VAR_JUNK 4 /* Variable is a junk variable that
192: * should be destroyed when done with
193: * it. Used by Var_Parse for undefined,
194: * modified variables */
1.38 espie 195: char name[1]; /* the variable's name */
1.1 deraadt 196: } Var;
197:
1.38 espie 198: static struct hash_info var_info = {
199: offsetof(Var, name),
200: NULL, hash_alloc, hash_free, element_alloc };
201: static int quick_lookup __P((const char *, const char **, u_int32_t *));
1.23 espie 202: #define VarValue(v) Buf_Retrieve(&((v)->val))
1.39 espie 203: static Var *varfind __P((const char *, const char *, SymTable *, int, int, u_int32_t));
204: static Var *VarFind_interval __P((const char *, const char *, SymTable *, int));
205: #define VarFind(n, ctxt, flags) VarFind_interval(n, NULL, ctxt, flags)
206: static Var *VarAdd __P((const char *, const char *, GSymT *));
1.32 espie 207: static void VarDelete __P((void *));
208: static void VarPrintVar __P((void *));
1.38 espie 209: static const char *context_name __P((GSymT *));
1.39 espie 210: static Var *new_var __P((const char *, const char *));
211: static Var *getvar __P((GSymT *, const char *, const char *, u_int32_t));
1.45 espie 212: static Var *var_name_with_dollar __P((char *, char **, SymTable *, Boolean, char));
1.37 espie 213:
214: void
215: SymTable_Init(ctxt)
216: SymTable *ctxt;
217: {
218: static SymTable sym_template;
219: memcpy(ctxt, &sym_template, sizeof(*ctxt));
220: }
221:
222: void
223: SymTable_Destroy(ctxt)
224: SymTable *ctxt;
225: {
226: int i;
227:
228: for (i = 0; i < LOCAL_SIZE; i++)
229: if (ctxt->locals[i] != NULL)
230: VarDelete(ctxt->locals[i]);
231: }
232:
1.38 espie 233: static int
234: quick_lookup(name, end, pk)
235: const char *name;
236: const char **end;
237: u_int32_t *pk;
238: {
239: size_t len;
240:
241: *pk = hash_interval(name, end);
242: len = *end - name;
243: /* substitute short version for long local name */
244: switch (*pk % MAGICSLOTS) { /* MAGICSLOTS should be the */
245: case K_LONGALLSRC % MAGICSLOTS: /* smallest constant yielding */
246: /* distinct case values */
247: if (*pk == K_LONGALLSRC && strncmp(name, LONGALLSRC, len) == 0 &&
248: len == strlen(LONGALLSRC))
249: return ALLSRC_INDEX;
250: break;
251: case K_LONGARCHIVE % MAGICSLOTS:
252: if (*pk == K_LONGARCHIVE && strncmp(name, LONGARCHIVE, len) == 0 &&
253: len == strlen(LONGARCHIVE))
254: return ARCHIVE_INDEX;
255: break;
256: case K_LONGIMPSRC % MAGICSLOTS:
257: if (*pk == K_LONGIMPSRC && strncmp(name, LONGIMPSRC, len) == 0 &&
258: len == strlen(LONGIMPSRC))
259: return IMPSRC_INDEX;
260: break;
261: case K_LONGMEMBER % MAGICSLOTS:
262: if (*pk == K_LONGMEMBER && strncmp(name, LONGMEMBER, len) == 0 &&
263: len == strlen(LONGMEMBER))
264: return MEMBER_INDEX;
265: break;
266: case K_LONGOODATE % MAGICSLOTS:
267: if (*pk == K_LONGOODATE && strncmp(name, LONGOODATE, len) == 0 &&
268: len == strlen(LONGOODATE))
269: return OODATE_INDEX;
270: break;
271: case K_LONGPREFIX % MAGICSLOTS:
272: if (*pk == K_LONGPREFIX && strncmp(name, LONGPREFIX, len) == 0 &&
273: len == strlen(LONGPREFIX))
274: return PREFIX_INDEX;
275: break;
276: case K_LONGTARGET % MAGICSLOTS:
277: if (*pk == K_LONGTARGET && strncmp(name, LONGTARGET, len) == 0 &&
278: len == strlen(LONGTARGET))
279: return TARGET_INDEX;
280: break;
281: case K_TARGET % MAGICSLOTS:
282: if (name[0] == TARGET[0] && len == 1)
283: return TARGET_INDEX;
284: break;
285: case K_OODATE % MAGICSLOTS:
286: if (name[0] == OODATE[0] && len == 1)
287: return OODATE_INDEX;
288: break;
289: case K_ALLSRC % MAGICSLOTS:
290: if (name[0] == ALLSRC[0] && len == 1)
291: return ALLSRC_INDEX;
292: break;
293: case K_IMPSRC % MAGICSLOTS:
294: if (name[0] == IMPSRC[0] && len == 1)
295: return IMPSRC_INDEX;
296: break;
297: case K_PREFIX % MAGICSLOTS:
298: if (name[0] == PREFIX[0] && len == 1)
299: return PREFIX_INDEX;
300: break;
301: case K_ARCHIVE % MAGICSLOTS:
302: if (name[0] == ARCHIVE[0] && len == 1)
303: return ARCHIVE_INDEX;
304: break;
305: case K_MEMBER % MAGICSLOTS:
306: if (name[0] == MEMBER[0] && len == 1)
307: return MEMBER_INDEX;
308: break;
309: default:
310: break;
311: }
312: return -1;
313: }
1.37 espie 314:
315: void
316: Varq_Set(idx, val, gn)
317: int idx;
1.48 espie 318: const char *val;
1.37 espie 319: GNode *gn;
320: {
1.38 espie 321: /* We only look for a variable in the given context since anything set
322: * here will override anything in a lower context, so there's not much
323: * point in searching them all just to save a bit of memory... */
1.37 espie 324: Var *v = gn->context.locals[idx];
325:
326: if (v == NULL) {
327: v = new_var(varnames[idx], val);
328: v->flags = 0;
329: gn->context.locals[idx] = v;
330: } else {
331: Buf_Reset(&(v->val));
332: Buf_AddString(&(v->val), val);
333: }
334: if (DEBUG(VAR))
335: printf("%s:%s = %s\n", gn->name, varnames[idx], val);
336: }
337:
338: void
339: Varq_Append(idx, val, gn)
340: int idx;
1.48 espie 341: const char *val;
1.37 espie 342: GNode *gn;
343: {
1.48 espie 344: Var *v = gn->context.locals[idx];
1.37 espie 345:
346: if (v == NULL) {
347: v = new_var(varnames[idx], val);
348: v->flags = 0;
349: gn->context.locals[idx] = v;
350: } else {
351: Buf_AddSpace(&(v->val));
352: Buf_AddString(&(v->val), val);
353: }
354: if (DEBUG(VAR))
355: printf("%s:%s = %s\n", gn->name, varnames[idx], VarValue(v));
356: }
357:
358: char *
359: Varq_Value(idx, gn)
360: int idx;
361: GNode *gn;
362: {
363: Var *v = gn->context.locals[idx];
364:
365: if (v != NULL)
366: return VarValue(v);
367: else
368: return NULL;
369: }
370:
371: Boolean
372: Varq_Exists(idx, gn)
373: int idx;
374: GNode *gn;
375: {
376: return gn->context.locals[idx] != NULL;
377: }
1.1 deraadt 378:
1.35 espie 379:
1.38 espie 380: static const char *
1.35 espie 381: context_name(ctxt)
1.37 espie 382: GSymT *ctxt;
1.35 espie 383: {
384: if (ctxt == VAR_GLOBAL)
385: return "Global";
1.37 espie 386: else if (ctxt == VAR_CMD)
1.35 espie 387: return "Command";
1.37 espie 388: else
1.35 espie 389: return "Environment";
390: }
391:
1.37 espie 392: /* Create a variable, to pass to VarAdd. */
393: static Var *
394: new_var(name, val)
1.39 espie 395: const char *name;
396: const char *val;
1.37 espie 397: {
398: Var *v;
1.38 espie 399: const char *end = NULL;
1.37 espie 400:
1.38 espie 401: v = hash_create_entry(&var_info, name, &end);
1.37 espie 402:
403: if (val != NULL) {
404: size_t len = strlen(val);
405: Buf_Init(&(v->val), len+1);
406: Buf_AddChars(&(v->val), len, val);
407: } else
408: Buf_Init(&(v->val), 1);
409:
410: return v;
411: }
412:
1.38 espie 413: static Var *
414: getvar(ctxt, name, end, k)
415: GSymT *ctxt;
1.39 espie 416: const char *name;
1.38 espie 417: const char *end;
418: u_int32_t k;
1.1 deraadt 419: {
1.38 espie 420: return hash_find(ctxt, hash_lookup_interval(ctxt, name, end, k));
1.37 espie 421: }
422:
1.1 deraadt 423: /*-
424: *-----------------------------------------------------------------------
1.39 espie 425: * VarFind_interval --
1.1 deraadt 426: * Find the given variable in the given context and any other contexts
1.39 espie 427: * indicated. if end is NULL, name is a string, otherwise, only
428: * the interval name - end is concerned.
1.1 deraadt 429: *
430: * Results:
431: * A pointer to the structure describing the desired variable or
1.26 espie 432: * NULL if the variable does not exist.
1.1 deraadt 433: *
434: * Side Effects:
1.17 espie 435: * Caches env variables in the VAR_ENV context.
1.1 deraadt 436: *-----------------------------------------------------------------------
437: */
438: static Var *
1.39 espie 439: VarFind_interval(name, end, ctxt, flags)
440: const char *name; /* name to find */
441: const char *end; /* end of name */
1.35 espie 442: SymTable *ctxt; /* context in which to find it */
1.39 espie 443: int flags; /* FIND_MINE set means to look in the
444: * CTXT_GLOBAL and CTXT_CMD contexts also.
1.1 deraadt 445: * FIND_ENV set means to look in the
1.39 espie 446: * environment */
1.1 deraadt 447: {
1.38 espie 448: int idx;
449: u_int32_t k;
450:
451: idx = quick_lookup(name, &end, &k);
1.39 espie 452: return varfind(name, end, ctxt, flags, idx, k);
453: }
454:
455: static Var *
456: varfind(name, end, ctxt, flags, idx, k)
457: const char *name;
458: const char *end;
459: SymTable *ctxt;
460: int flags;
461: int idx;
462: u_int32_t k;
463: {
464: Var *v;
1.1 deraadt 465:
466: /*
467: * First look for the variable in the given context. If it's not there,
468: * look for it in VAR_CMD, VAR_GLOBAL and the environment, in that order,
469: * depending on the FIND_* flags in 'flags'
470: */
1.37 espie 471: if (ctxt == NULL)
472: v = NULL;
473: else if (ctxt == CTXT_GLOBAL || ctxt == CTXT_CMD || ctxt == CTXT_ENV)
1.38 espie 474: v = getvar((GSymT *)ctxt, name, end, k);
1.37 espie 475: else {
1.38 espie 476: if (idx == -1)
477: v = NULL;
478: else
479: v = ctxt->locals[idx];
1.37 espie 480: }
481: if (v != NULL)
482: return v;
483:
1.39 espie 484: if ((flags & FIND_MINE) && ctxt != CTXT_CMD)
1.38 espie 485: v = getvar(VAR_CMD, name, end, k);
1.37 espie 486: if (v != NULL)
487: return v;
488:
1.39 espie 489: if (!checkEnvFirst && (flags & FIND_MINE) && ctxt != CTXT_GLOBAL)
1.38 espie 490: v = getvar(VAR_GLOBAL, name, end, k);
1.37 espie 491: if (v != NULL)
492: return v;
493:
494: if ((flags & FIND_ENV)) {
495: char *env;
1.42 espie 496: char *n;
1.37 espie 497:
1.38 espie 498: v = getvar(VAR_ENV, name, end, k);
1.37 espie 499: if (v != NULL)
500: return v;
1.1 deraadt 501:
1.42 espie 502: /* getenv requires a null-terminated name */
503: n = interval_dup(name, end);
504: env = getenv(n);
505: free(n);
506: if (env != NULL)
1.37 espie 507: return VarAdd(name, env, VAR_ENV);
508: }
1.17 espie 509:
1.39 espie 510: if (checkEnvFirst && (flags & FIND_MINE) && ctxt != CTXT_GLOBAL)
1.38 espie 511: v = getvar(VAR_GLOBAL, name, end, k);
1.37 espie 512: return v;
1.1 deraadt 513: }
514:
515: /*-
516: *-----------------------------------------------------------------------
517: * VarAdd --
518: * Add a new variable of name name and value val to the given context
519: *
520: * Results:
1.17 espie 521: * The added variable
1.1 deraadt 522: *
523: * Side Effects:
1.48 espie 524: * The new variable is placed in the given context.
1.1 deraadt 525: * The name and val arguments are duplicated so they may
526: * safely be freed.
527: *-----------------------------------------------------------------------
528: */
1.17 espie 529: static Var *
530: VarAdd(name, val, ctxt)
1.39 espie 531: const char *name; /* name of variable to add */
532: const char *val; /* value to set it to */
1.37 espie 533: GSymT *ctxt; /* context in which to set it */
1.1 deraadt 534: {
1.38 espie 535: Var *v;
536: const char *end = NULL;
537: int idx;
538: u_int32_t k;
1.1 deraadt 539:
1.37 espie 540: v = new_var(name, val);
1.1 deraadt 541:
542: v->flags = 0;
543:
1.38 espie 544: idx = quick_lookup(name, &end, &k);
545:
1.48 espie 546: if (idx != -1)
1.38 espie 547: Parse_Error(PARSE_FATAL, "Trying to set dynamic variable %s",
548: v->name);
1.48 espie 549: else
1.38 espie 550: hash_insert(ctxt, hash_lookup_interval(ctxt, name, end, k), v);
1.17 espie 551: return v;
1.1 deraadt 552: }
553:
554:
555: /*-
556: *-----------------------------------------------------------------------
557: * VarDelete --
558: * Delete a variable and all the space associated with it.
559: *-----------------------------------------------------------------------
560: */
561: static void
562: VarDelete(vp)
1.48 espie 563: void *vp;
1.1 deraadt 564: {
1.48 espie 565: Var *v = (Var *) vp;
566:
1.23 espie 567: Buf_Destroy(&(v->val));
568: free(v);
1.1 deraadt 569: }
570:
571:
572:
573: /*-
574: *-----------------------------------------------------------------------
575: * Var_Delete --
576: * Remove a variable from a context.
577: *
578: * Side Effects:
579: * The Var structure is removed and freed.
580: *-----------------------------------------------------------------------
581: */
582: void
583: Var_Delete(name, ctxt)
1.48 espie 584: const char *name;
585: GSymT *ctxt;
1.1 deraadt 586: {
1.48 espie 587: Var *v;
588: u_int32_t k;
589: const char *end = NULL;
1.1 deraadt 590:
1.37 espie 591: if (DEBUG(VAR))
1.35 espie 592: printf("%s:delete %s\n", context_name(ctxt), name);
1.38 espie 593: (void)quick_lookup(name, &end, &k);
594: v = hash_remove(ctxt, hash_lookup_interval(ctxt, name, end, k));
1.37 espie 595:
1.38 espie 596: if (v != NULL)
1.30 espie 597: VarDelete(v);
1.1 deraadt 598: }
599:
600: /*-
601: *-----------------------------------------------------------------------
602: * Var_Set --
603: * Set the variable name to the value val in the given context.
604: *
605: * Side Effects:
606: * If the variable doesn't yet exist, a new record is created for it.
607: * Else the old value is freed and the new one stuck in its place
608: *
609: * Notes:
610: * The variable is searched for only in its context before being
611: * created in that context. I.e. if the context is VAR_GLOBAL,
612: * only VAR_GLOBAL->context is searched. Likewise if it is VAR_CMD, only
613: * VAR_CMD->context is searched. This is done to avoid the literally
614: * thousands of unnecessary strcmp's that used to be done to
615: * set, say, $(@) or $(<).
616: *-----------------------------------------------------------------------
617: */
618: void
1.35 espie 619: Var_Set(name, val, ctxt)
1.48 espie 620: const char *name; /* name of variable to set */
621: const char *val; /* value to give to the variable */
1.37 espie 622: GSymT *ctxt; /* context in which to set it */
1.1 deraadt 623: {
1.48 espie 624: Var *v;
1.1 deraadt 625:
626: /*
627: * We only look for a variable in the given context since anything set
628: * here will override anything in a lower context, so there's not much
629: * point in searching them all just to save a bit of memory...
630: */
1.37 espie 631: v = VarFind(name, (SymTable *)ctxt, 0);
1.38 espie 632: if (v == NULL)
1.17 espie 633: (void)VarAdd(name, val, ctxt);
1.38 espie 634: else {
1.23 espie 635: Buf_Reset(&(v->val));
636: Buf_AddString(&(v->val), val);
1.1 deraadt 637: }
1.37 espie 638: if (DEBUG(VAR))
639: printf("%s:%s = %s\n", context_name(ctxt), name, val);
1.1 deraadt 640: /*
641: * Any variables given on the command line are automatically exported
1.17 espie 642: * to the environment (as per POSIX standard).
643: * We put them into the env cache directly.
644: * (Note that additions to VAR_CMD occur very early, so VAR_ENV is
645: * actually empty at this point).
1.1 deraadt 646: */
647: if (ctxt == VAR_CMD) {
1.49 espie 648: esetenv(name, val);
1.17 espie 649: (void)VarAdd(name, val, VAR_ENV);
1.1 deraadt 650: }
651: }
652:
653: /*-
654: *-----------------------------------------------------------------------
655: * Var_Append --
656: * The variable of the given name has the given value appended to it in
657: * the given context.
658: *
659: * Side Effects:
660: * If the variable doesn't exist, it is created. Else the strings
661: * are concatenated (with a space in between).
662: *
663: * Notes:
664: * Only if the variable is being sought in the global context is the
665: * environment searched.
666: * XXX: Knows its calling circumstances in that if called with ctxt
667: * an actual target, it will only search that context since only
668: * a local variable could be being appended to. This is actually
669: * a big win and must be tolerated.
670: *-----------------------------------------------------------------------
671: */
672: void
1.35 espie 673: Var_Append(name, val, ctxt)
1.48 espie 674: const char *name; /* Name of variable to modify */
675: const char *val; /* String to append to it */
1.37 espie 676: GSymT *ctxt; /* Context in which this should occur */
1.1 deraadt 677: {
1.48 espie 678: Var *v;
1.1 deraadt 679:
1.37 espie 680: v = VarFind(name, (SymTable *)ctxt, (ctxt == VAR_GLOBAL) ? FIND_ENV : 0);
1.1 deraadt 681:
1.26 espie 682: if (v == NULL) {
1.47 espie 683: v = VarAdd(name, val, ctxt);
1.1 deraadt 684: } else {
1.23 espie 685: Buf_AddSpace(&(v->val));
686: Buf_AddString(&(v->val), val);
1.1 deraadt 687: }
1.37 espie 688: if (DEBUG(VAR))
689: printf("%s:%s = %s\n", context_name(ctxt), name, VarValue(v));
1.1 deraadt 690: }
691:
692: /*-
693: *-----------------------------------------------------------------------
694: * Var_Exists --
695: * See if the given variable exists.
696: *
697: * Results:
698: * TRUE if it does, FALSE if it doesn't
699: *-----------------------------------------------------------------------
700: */
701: Boolean
702: Var_Exists(name, ctxt)
1.48 espie 703: const char *name; /* Variable to find */
1.37 espie 704: GSymT *ctxt; /* Context in which to start search */
1.1 deraadt 705: {
1.48 espie 706: Var *v;
1.1 deraadt 707:
1.39 espie 708: v = VarFind(name, (SymTable *)ctxt, FIND_MINE|FIND_ENV);
1.1 deraadt 709:
1.26 espie 710: if (v == NULL)
1.17 espie 711: return FALSE;
712: else
713: return TRUE;
1.1 deraadt 714: }
715:
716: /*-
717: *-----------------------------------------------------------------------
718: * Var_Value --
719: * Return the value of the named variable in the given context
720: *
721: * Results:
722: * The value if the variable exists, NULL if it doesn't
723: *-----------------------------------------------------------------------
724: */
725: char *
1.18 espie 726: Var_Value(name, ctxt)
1.48 espie 727: const char *name; /* name to find */
1.37 espie 728: GSymT *ctxt; /* context in which to search for it */
1.1 deraadt 729: {
1.48 espie 730: Var *v;
1.1 deraadt 731:
1.39 espie 732: v = VarFind(name, (SymTable *)ctxt, FIND_ENV | FIND_MINE);
1.26 espie 733: if (v != NULL)
1.23 espie 734: return VarValue(v);
1.21 espie 735: else
1.17 espie 736: return NULL;
1.1 deraadt 737: }
738:
1.45 espie 739: /*
740: *-----------------------------------------------------------------------
741: * v = var_name_with_dollar(str, &pos, ctxt, err, endc)
742: * handle variable name that contains a dollar
743: * str points to the first letter of the variable name,
744: * &pos to the current position in the name (first dollar at invocation,
745: * end of name specification at return).
746: * returns the corresponding variable.
747: *-----------------------------------------------------------------------
748: */
749: static Var *
750: var_name_with_dollar(str, pos, ctxt, err, endc)
1.48 espie 751: char *str; /* First dollar in variable name */
752: char **pos; /* Current position in variable spec */
1.45 espie 753: SymTable *ctxt; /* The context for the variable */
754: Boolean err; /* TRUE if undefined variables are an error */
755: char endc; /* End character for spec */
756: {
1.48 espie 757: BUFFER buf; /* Store the variable name */
758: size_t sublen; /* Deal with recursive expansions */
759: Boolean subfree;
760: char *n; /* Sub name */
761: Var *v;
1.45 espie 762:
763: Buf_Init(&buf, MAKE_BSIZE);
764:
1.48 espie 765: for (;;) {
1.45 espie 766: Buf_AddInterval(&buf, str, *pos);
767: n = Var_Parse(*pos, ctxt, err, &sublen, &subfree);
768: if (n != NULL)
769: Buf_AddString(&buf, n);
770: if (subfree)
771: free(n);
772: *pos += sublen;
773: str = *pos;
774: for (; **pos != '$'; (*pos)++) {
775: if (**pos == '\0' || **pos == endc || **pos == ':') {
776: v = VarFind(Buf_Retrieve(&buf), ctxt, FIND_ENV | FIND_MINE);
777: Buf_Destroy(&buf);
778: return v;
779: }
780: }
781: }
782: }
783:
1.1 deraadt 784: /*-
785: *-----------------------------------------------------------------------
786: * Var_Parse --
787: * Given the start of a variable invocation, extract the variable
788: * name and find its value, then modify it according to the
789: * specification.
790: *
791: * Results:
792: * The (possibly-modified) value of the variable or var_Error if the
793: * specification is invalid. The length of the specification is
794: * placed in *lengthPtr (for invalid specifications, this is just
795: * 2...?).
796: * A Boolean in *freePtr telling whether the returned string should
797: * be freed by the caller.
798: *-----------------------------------------------------------------------
799: */
800: char *
1.35 espie 801: Var_Parse(str, ctxt, err, lengthPtr, freePtr)
1.44 espie 802: char *str; /* The string to parse */
803: SymTable *ctxt; /* The context for the variable */
804: Boolean err; /* TRUE if undefined variables are an error */
805: size_t *lengthPtr; /* OUT: The length of the specification */
806: Boolean *freePtr; /* OUT: TRUE if caller should free result */
807: {
808: char *tstr; /* Pointer into str */
809: Var *v; /* Variable in invocation */
810: char endc; /* Ending character when variable in parens
1.1 deraadt 811: * or braces */
1.44 espie 812: char *start;
813: char *val; /* Variable value */
814: u_int32_t k;
815: int idx;
1.5 millert 816:
1.1 deraadt 817: *freePtr = FALSE;
1.44 espie 818: start = str++;
1.5 millert 819:
1.44 espie 820: val = NULL;
1.45 espie 821: v = NULL;
822: idx = 0;
1.44 espie 823:
824: if (*str != '(' && *str != '{') {
825: tstr = str + 1;
826: *lengthPtr = 2;
827: endc = '\0';
1.1 deraadt 828: } else {
1.44 espie 829: endc = *str == '(' ? ')' : '}';
830: str++;
1.5 millert 831:
1.44 espie 832: /* Find eventual modifiers in the variable */
1.45 espie 833: for (tstr = str; *tstr != ':'; tstr++) {
834: if (*tstr == '$') {
835: v = var_name_with_dollar(str, &tstr, ctxt, err, endc);
836: if (*tstr == '\0' || *tstr == endc)
837: endc = '\0';
838: break;
839: } else if (*tstr == '\0' || *tstr == endc) {
1.44 espie 840: endc = '\0';
841: break;
1.1 deraadt 842: }
1.45 espie 843: }
1.44 espie 844: *lengthPtr = tstr+1 - start;
845: }
1.5 millert 846:
1.45 espie 847: if (v == NULL) {
848: idx = quick_lookup(str, &tstr, &k);
849: v = varfind(str, tstr, ctxt, FIND_ENV | FIND_MINE, idx, k);
850: }
1.44 espie 851: if (v == NULL) {
852: /* Find out about D and F forms of local variables. */
853: if (idx == -1 && tstr == str+2 && (str[1] == 'D' || str[1] == 'F')) {
854: switch (*str) {
855: case '@':
856: idx = TARGET_INDEX;
857: break;
858: case '!':
859: idx = ARCHIVE_INDEX;
860: break;
861: case '*':
862: idx = PREFIX_INDEX;
863: break;
864: case '%':
865: idx = MEMBER_INDEX;
866: break;
867: default:
868: break;
1.1 deraadt 869: }
1.44 espie 870: /* This is a DF form, check if we can expand it now. */
871: if (idx != -1 && ctxt != NULL && ctxt != CTXT_GLOBAL) {
872: v = varfind(str, str+1, ctxt, 0, idx, 0);
873: /* No need for nested expansion or anything, as we're
874: * the only one who sets these things and we sure don't
875: * do nested invocations in them... */
876: if (v != NULL) {
877: val = VarValue(v);
878: if (str[1] == 'D')
879: val = Var_GetHead(val);
880: else
881: val = Var_GetTail(val);
1.1 deraadt 882: *freePtr = TRUE;
1.44 espie 883: }
1.1 deraadt 884: }
885: }
1.44 espie 886: } else {
887: if (v->flags & VAR_IN_USE)
888: Fatal("Variable %s is recursive.", v->name);
889: /*NOTREACHED*/
890: else
891: v->flags |= VAR_IN_USE;
892: /* Before doing any modification, we have to make sure the value
893: * has been fully expanded. If it looks like recursion might be
894: * necessary (there's a dollar sign somewhere in the variable's value)
895: * we just call Var_Subst to do any other substitutions that are
896: * necessary. Note that the value returned by Var_Subst will have
897: * been dynamically-allocated, so it will need freeing when we
898: * return. */
899: val = VarValue(v);
900: if (strchr(val, '$') != NULL) {
901: val = Var_Subst(val, ctxt, err);
902: *freePtr = TRUE;
903: }
904:
905: v->flags &= ~VAR_IN_USE;
1.1 deraadt 906: }
1.44 espie 907: if (endc != '\0')
908: val = VarModifiers_Apply(val, ctxt, err, freePtr, tstr+1, endc,
1.42 espie 909: lengthPtr);
1.44 espie 910: if (val == NULL) {
911: /* Dynamic source that can't be expanded for now: copy the var
912: * specification instead. */
913: if (idx != -1 && (ctxt == NULL || ctxt == CTXT_GLOBAL)) {
1.42 espie 914: *freePtr = TRUE;
1.44 espie 915: val = interval_dup(start, start+ *lengthPtr);
916: } else
917: val = err ? var_Error : varNoError;
1.42 espie 918: }
1.44 espie 919:
920: return val;
1.42 espie 921: }
922:
1.1 deraadt 923: /*-
924: *-----------------------------------------------------------------------
925: * Var_Subst --
1.24 espie 926: * Substitute for all variables in a string in a context
1.1 deraadt 927: * If undefErr is TRUE, Parse_Error will be called when an undefined
928: * variable is encountered.
929: *
930: * Results:
931: * The resulting string.
932: *
933: * Side Effects:
934: * None. The old string must be freed by the caller
935: *-----------------------------------------------------------------------
936: */
937: char *
1.24 espie 938: Var_Subst(str, ctxt, undefErr)
1.1 deraadt 939: char *str; /* the string in which to substitute */
1.35 espie 940: SymTable *ctxt; /* the context wherein to find variables */
1.1 deraadt 941: Boolean undefErr; /* TRUE if undefineds are an error */
942: {
1.24 espie 943: BUFFER buf; /* Buffer for forming things */
1.1 deraadt 944: static Boolean errorReported; /* Set true if an error has already
945: * been reported to prevent a plethora
946: * of messages when recursing */
947:
1.23 espie 948: Buf_Init(&buf, MAKE_BSIZE);
1.1 deraadt 949: errorReported = FALSE;
950:
1.24 espie 951: for (;;) {
952: char *val; /* Value to substitute for a variable */
953: size_t length; /* Length of the variable invocation */
954: Boolean doFree; /* Set true if val should be freed */
955: const char *cp;
956:
957: /* copy uninteresting stuff */
958: for (cp = str; *str != '\0' && *str != '$'; str++)
959: ;
960: Buf_AddInterval(&buf, cp, str);
961: if (*str == '\0')
962: break;
963: if (str[1] == '$') {
964: /* A dollar sign may be escaped with another dollar sign. */
965: Buf_AddChar(&buf, '$');
966: str += 2;
967: continue;
968: }
969: val = Var_Parse(str, ctxt, undefErr, &length, &doFree);
970: /* When we come down here, val should either point to the
971: * value of this variable, suitably modified, or be NULL.
972: * Length should be the total length of the potential
973: * variable invocation (from $ to end character...) */
974: if (val == var_Error || val == varNoError) {
975: /* If performing old-time variable substitution, skip over
976: * the variable and continue with the substitution. Otherwise,
977: * store the dollar sign and advance str so we continue with
978: * the string... */
979: if (oldVars) {
980: str += length;
981: } else if (undefErr) {
982: /* If variable is undefined, complain and skip the
983: * variable. The complaint will stop us from doing anything
984: * when the file is parsed. */
985: if (!errorReported) {
986: Parse_Error(PARSE_FATAL,
987: "Undefined variable \"%.*s\"",length,str);
988: }
989: str += length;
990: errorReported = TRUE;
991: } else {
992: Buf_AddChar(&buf, *str);
993: str += 1;
994: }
995: } else {
996: /* We've now got a variable structure to store in. But first,
997: * advance the string pointer. */
998: str += length;
999:
1000: /* Copy all the characters from the variable value straight
1001: * into the new string. */
1002: Buf_AddString(&buf, val);
1003: if (doFree)
1004: free(val);
1005: }
1006: }
1007: return Buf_Retrieve(&buf);
1008: }
1.1 deraadt 1009:
1.24 espie 1010: /*-
1011: *-----------------------------------------------------------------------
1012: * Var_SubstVar --
1013: * Substitute for one variable in the given string in the given context
1014: * If undefErr is TRUE, Parse_Error will be called when an undefined
1.50 ! espie 1015: * variable is encountered. Returns the string with substitutions.
1.24 espie 1016: *-----------------------------------------------------------------------
1017: */
1.50 ! espie 1018: char *
! 1019: Var_SubstVar(str, var, val, estimate)
! 1020: const char *str; /* The string in which to substitute */
1.24 espie 1021: const char *var; /* Named variable */
1.50 ! espie 1022: const char *val; /* Its value */
! 1023: size_t estimate; /* Size estimate for the result buffer */
1.24 espie 1024: {
1.50 ! espie 1025: BUFFER buf; /* Where to store the result */
1.24 espie 1026:
1.50 ! espie 1027: Buf_Init(&buf, estimate);
1.24 espie 1028: for (;;) {
1.50 ! espie 1029: const char *start;
! 1030: /* Copy uninteresting stuff */
! 1031: for (start = str; *str != '\0' && *str != '$'; str++)
1.24 espie 1032: ;
1.50 ! espie 1033: Buf_AddInterval(&buf, start, str);
! 1034:
! 1035: start = str;
! 1036: if (*str++ == '\0')
1.24 espie 1037: break;
1.50 ! espie 1038: str++;
! 1039: /* and escaped dollars */
! 1040: if (start[1] == '$') {
! 1041: Buf_AddInterval(&buf, start, start+2);
1.24 espie 1042: continue;
1043: }
1.50 ! espie 1044: /* Simple variable, if it's not us, copy. */
! 1045: if (start[1] != '(' && start[1] != '{') {
! 1046: if (start[1] != *var || var[1] != '\0') {
! 1047: Buf_AddChars(&buf, 2, start);
1.1 deraadt 1048: continue;
1.24 espie 1049: }
1.1 deraadt 1050: } else {
1.50 ! espie 1051: const char *p;
1.24 espie 1052: char endc;
1.1 deraadt 1053:
1.50 ! espie 1054: if (start[1] == '(')
1.24 espie 1055: endc = ')';
1.50 ! espie 1056: else
1.24 espie 1057: endc = '}';
1058:
1059: /* Find the end of the variable specification. */
1.50 ! espie 1060: p = str;
1.24 espie 1061: while (*p != '\0' && *p != ':' && *p != endc && *p != '$')
1062: p++;
1063: /* A variable inside the variable. We don't know how to
1064: * expand the external variable at this point, so we try
1065: * again with the nested variable. */
1066: if (*p == '$') {
1.50 ! espie 1067: Buf_AddInterval(&buf, start, p);
1.24 espie 1068: str = p;
1069: continue;
1.1 deraadt 1070: }
1.5 millert 1071:
1.50 ! espie 1072: if (strncmp(var, str, p - str) != 0 ||
! 1073: var[p - str] != '\0') {
1.24 espie 1074: /* Not the variable we want to expand. */
1.50 ! espie 1075: Buf_AddInterval(&buf, start, p);
1.24 espie 1076: str = p;
1077: continue;
1078: }
1.50 ! espie 1079: if (*p == ':') {
! 1080: size_t length; /* Length of the variable invocation */
! 1081: Boolean doFree; /* Set true if val should be freed */
! 1082: char *newval; /* Value substituted for a variable */
! 1083:
! 1084: length = p - str + 1;
! 1085: doFree = FALSE;
! 1086:
! 1087: /* val won't be freed since doFree == FALSE, but
! 1088: * VarModifiers_Apply doesn't know that, hence the cast. */
! 1089: newval = VarModifiers_Apply((char *)val, NULL, FALSE,
! 1090: &doFree, p+1, endc, &length);
! 1091: Buf_AddString(&buf, newval);
! 1092: if (doFree)
! 1093: free(newval);
! 1094: str += length;
! 1095: continue;
! 1096: } else
! 1097: str = p+1;
1.1 deraadt 1098: }
1.50 ! espie 1099: Buf_AddString(&buf, val);
1.1 deraadt 1100: }
1.50 ! espie 1101: return Buf_Retrieve(&buf);
1.1 deraadt 1102: }
1103:
1104: /*-
1105: *-----------------------------------------------------------------------
1106: * Var_Init --
1107: * Initialize the module
1108: *
1109: * Side Effects:
1.5 millert 1110: * The VAR_CMD and VAR_GLOBAL contexts are created
1.1 deraadt 1111: *-----------------------------------------------------------------------
1112: */
1113: void
1.33 espie 1114: Var_Init()
1.1 deraadt 1115: {
1.37 espie 1116: static GSymT global_vars, cmd_vars, env_vars;
1.35 espie 1117:
1118: VAR_GLOBAL = &global_vars;
1119: VAR_CMD = &cmd_vars;
1120: VAR_ENV = &env_vars;
1.38 espie 1121: hash_init(VAR_GLOBAL, 10, &var_info);
1122: hash_init(VAR_CMD, 5, &var_info);
1123: hash_init(VAR_ENV, 5, &var_info);
1.37 espie 1124: CTXT_GLOBAL = (SymTable *)VAR_GLOBAL;
1125: CTXT_CMD = (SymTable *)VAR_CMD;
1126: CTXT_ENV = (SymTable *)VAR_ENV;
1.1 deraadt 1127: }
1128:
1129:
1130: void
1.33 espie 1131: Var_End()
1.1 deraadt 1132: {
1.37 espie 1133: #ifdef CLEANUP
1.38 espie 1134: Var *v;
1135: unsigned int i;
1136:
1137: for (v = hash_first(VAR_GLOBAL, &i); v != NULL;
1138: v = hash_next(VAR_GLOBAL, &i))
1139: VarDelete(v);
1140: for (v = hash_first(VAR_CMD, &i); v != NULL;
1141: v = hash_next(VAR_CMD, &i))
1142: VarDelete(v);
1143: for (v = hash_first(VAR_ENV, &i); v != NULL;
1144: v = hash_next(VAR_ENV, &i))
1145: VarDelete(v);
1.37 espie 1146: #endif
1.1 deraadt 1147: }
1.5 millert 1148:
1.1 deraadt 1149:
1150: /****************** PRINT DEBUGGING INFO *****************/
1.31 espie 1151: static void
1152: VarPrintVar(vp)
1.32 espie 1153: void *vp;
1.1 deraadt 1154: {
1.31 espie 1155: Var *v = (Var *)vp;
1156:
1.23 espie 1157: printf("%-16s = %s\n", v->name, VarValue(v));
1.1 deraadt 1158: }
1159:
1160: /*-
1161: *-----------------------------------------------------------------------
1162: * Var_Dump --
1163: * print all variables in a context
1164: *-----------------------------------------------------------------------
1165: */
1166: void
1.35 espie 1167: Var_Dump(ctxt)
1.37 espie 1168: GSymT *ctxt;
1.1 deraadt 1169: {
1.38 espie 1170: Var *v;
1171: unsigned int i;
1172:
1173: for (v = hash_first(ctxt, &i); v != NULL;
1174: v = hash_next(ctxt, &i))
1175: VarPrintVar(v);
1.1 deraadt 1176: }
1.37 espie 1177:
1.46 espie 1178:
1179: #ifdef POSIX
1180:
1181: static const char *quotable = " \t\n\\'\"";
1182:
1183: /* In POSIX mode, variable assignments passed on the command line are
1184: * propagated to sub makes through MAKEFLAGS.
1185: */
1186: void
1187: Var_AddCmdline(name)
1188: const char *name;
1189: {
1190: Var *v;
1191: unsigned int i;
1192: BUFFER buf;
1193: char *s;
1194:
1195: Buf_Init(&buf, MAKE_BSIZE);
1196:
1197: for (v = hash_first(VAR_CMD, &i); v != NULL;
1198: v = hash_next(VAR_CMD, &i)) {
1199: /* We assume variable names don't need quoting */
1200: Buf_AddString(&buf, v->name);
1201: Buf_AddChar(&buf, '=');
1202: for (s = VarValue(v); *s != '\0'; s++) {
1203: if (strchr(quotable, *s))
1204: Buf_AddChar(&buf, '\\');
1205: Buf_AddChar(&buf, *s);
1206: }
1207: Buf_AddSpace(&buf);
1208: }
1209: Var_Append(name, Buf_Retrieve(&buf), VAR_GLOBAL);
1210: Buf_Destroy(&buf);
1211: }
1212: #endif