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