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