Annotation of src/usr.bin/make/var.c, Revision 1.54
1.53 espie 1: /* $OpenPackages$ */
1.54 ! espie 2: /* $OpenBSD: var.c,v 1.53 2001/05/03 13:41:13 espie Exp $ */
1.6 millert 3: /* $NetBSD: var.c,v 1.18 1997/03/18 19:24:46 christos Exp $ */
1.1 deraadt 4:
5: /*
1.53 espie 6: * Copyright (c) 1999,2000 Marc Espie.
1.17 espie 7: *
8: * Extensive code modifications for the OpenBSD project.
9: *
10: * Redistribution and use in source and binary forms, with or without
11: * modification, are permitted provided that the following conditions
12: * are met:
13: * 1. Redistributions of source code must retain the above copyright
14: * notice, this list of conditions and the following disclaimer.
15: * 2. Redistributions in binary form must reproduce the above copyright
16: * notice, this list of conditions and the following disclaimer in the
17: * documentation and/or other materials provided with the distribution.
18: *
19: * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT AND CONTRIBUTORS
20: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OPENBSD
23: * PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
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: *
1.53 espie 73: * Basic 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.
1.1 deraadt 78: *
79: * Var_Append Append more characters to an existing variable
1.53 espie 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_Value Return the value of a variable in a context or
86: * NULL if the variable is undefined.
1.1 deraadt 87: *
88: * Var_Delete Delete a variable in a context.
89: *
1.53 espie 90: * Var_Init Initialize this module.
91: *
92: * Fast interface:
93: * Varq_Set, Varq_Append, Varq_Value:
94: * Use index form of local variables
95: *
96: * Higher level functions:
97: * Var_Subst Substitute variables in a string using
98: * the given context as the top-most one. If the
99: * third argument is non-zero, Parse_Error is
100: * called if any variables are undefined.
101: *
102: * Var_SubstVar Substitute a named variable in a string using
103: * the given context as the top-most one,
104: * accumulating the result into a user-supplied
105: * buffer.
106: *
107: * Var_Parse Parse a variable expansion from a string and
108: * return the result and the number of characters
109: * consumed.
1.1 deraadt 110: *
111: * Debugging:
1.53 espie 112: * Var_Dump Print out all global variables.
1.1 deraadt 113: */
114:
1.53 espie 115: #include <assert.h>
1.1 deraadt 116: #include <ctype.h>
1.6 millert 117: #include <stdlib.h>
1.35 espie 118: #include <stddef.h>
1.53 espie 119: #include <string.h>
1.1 deraadt 120: #include "make.h"
121: #include "buf.h"
1.53 espie 122: #include "stats.h"
1.38 espie 123: #include "ohash.h"
1.43 espie 124: #include "varmodifiers.h"
1.34 espie 125:
1.48 espie 126: #ifndef lint
127: #if 0
128: static char sccsid[] = "@(#)var.c 8.3 (Berkeley) 3/19/94";
129: #else
130: UNUSED
1.54 ! espie 131: static char rcsid[] = "$OpenBSD: var.c,v 1.53 2001/05/03 13:41:13 espie Exp $";
1.48 espie 132: #endif
133: #endif /* not lint */
134:
1.34 espie 135:
1.1 deraadt 136: /*
137: * This is a harmless return value for Var_Parse that can be used by Var_Subst
138: * to determine if there was an error in parsing -- easier than returning
139: * a flag, as things outside this module don't give a hoot.
140: */
1.53 espie 141: char var_Error[] = "";
1.1 deraadt 142:
143: /*
144: * Similar to var_Error, but returned when the 'err' flag for Var_Parse is
145: * set false. Why not just use a constant? Well, gcc likes to condense
146: * identical string instances...
147: */
148: static char varNoError[] = "";
149:
150: /*
1.53 espie 151: * Variable values are obtained from four different contexts:
152: * 1) the process environment. The process environment itself
153: * may not be changed, but these variables may be modified,
154: * unless make is invoked with -e, in which case those variables
155: * are unmodifiable and supersede the global context.
1.1 deraadt 156: * 2) the global context. Variables set in the Makefile are located in
157: * the global context. It is the penultimate context searched when
158: * substituting.
159: * 3) the command-line context. All variables set on the command line
160: * are placed in this context. They are UNALTERABLE once placed here.
161: * 4) the local context. Each target has associated with it a context
162: * list. On this list are located the structures describing such
163: * local variables as $(@) and $(*)
164: * The four contexts are searched in the reverse order from which they are
165: * listed.
166: */
1.37 espie 167: GSymT *VAR_GLOBAL; /* variables from the makefile */
168: GSymT *VAR_CMD; /* variables defined on the command-line */
1.53 espie 169:
170: static SymTable *CTXT_GLOBAL, *CTXT_CMD;
171:
172:
173: static char *varnames[] = {
174: TARGET,
175: PREFIX,
176: ARCHIVE,
177: MEMBER,
178: OODATE,
179: ALLSRC,
180: IMPSRC,
181: FTARGET,
182: DTARGET,
183: FPREFIX,
184: DPREFIX,
185: FARCHIVE,
186: DARCHIVE,
187: FMEMBER,
188: DMEMBER
189: };
190:
1.1 deraadt 191:
1.39 espie 192: #define FIND_MINE 0x1 /* look in CTXT_CMD and CTXT_GLOBAL */
1.53 espie 193: #define FIND_ENV 0x2 /* look in the environment */
1.1 deraadt 194:
1.37 espie 195: typedef struct Var_ {
1.53 espie 196: BUFFER val; /* its value */
197: unsigned int flags; /* miscellaneous status flags */
198: #define VAR_IN_USE 1 /* Variable's value currently being used.
199: * Used to avoid recursion */
200: #define VAR_READ_ONLY 2 /* Environment variable not modifiable */
201: #define VAR_FROM_ENV 4 /* Var was read from env */
202: #define VAR_DUMMY 8 /* Var does not exist, actually */
203: char name[1]; /* the variable's name */
1.1 deraadt 204: } Var;
205:
1.53 espie 206:
207: static struct ohash_info var_info = {
208: offsetof(Var, name),
1.38 espie 209: NULL, hash_alloc, hash_free, element_alloc };
1.53 espie 210: static int quick_lookup(const char *, const char **, u_int32_t *);
1.23 espie 211: #define VarValue(v) Buf_Retrieve(&((v)->val))
1.53 espie 212: static Var *varfind(const char *, const char *, SymTable *, int, int, u_int32_t);
213: static Var *VarFind_interval(const char *, const char *, SymTable *, int);
214: static Var *VarAdd(const char *, const char *, u_int32_t, const char *, GSymT *);
215: static void VarDelete(void *);
216: static void VarPrintVar(Var *);
217: static const char *context_name(GSymT *);
218: static Var *new_var(const char *, const char *, const char *);
219: static Var *getvar(GSymT *, const char *, const char *, u_int32_t);
220: static Var *create_var(const char *, const char *);
221: static Var *var_from_env(const char *, const char *, u_int32_t);
222: static void var_init_string(Var *, const char *);
223:
224: static const char *find_0(const char *);
225: static const char *find_rparen(const char *);
226: static const char *find_ket(const char *);
227: typedef const char * (*find_t)(const char *);
228: static find_t find_pos(int);
229:
230: /* retrieve the hashed values for well-known variables. */
231: #include "varhashconsts.h"
232:
233: /* Parse a variable name for embedded $, to handle recursive variables */
234: const char *
235: Var_Name_Get(start, name, ctxt, err, cont)
236: const char *start; /* start of variable spec */
237: struct Name *name; /* result, might be a copy or not */
238: SymTable *ctxt; /* context in which to expand */
239: Boolean err; /* whether to error out for undefined sub */
240: const char *(*cont)(const char *);
241: /* hook: find the next interesting character */
242: {
243: const char *p;
244: size_t len;
245:
246: p = cont(start);
247: /* If we don't want recursive variables, we skip over '$' */
248: if (!FEATURES(FEATURE_RECVARS)) {
249: while (*p == '$')
250: p = cont(p);
251: }
252: if (*p != '$') {
253: name->s = start;
254: name->e = p;
255: name->tofree = FALSE;
256: return p;
257: } else {
258: BUFFER buf;
259: Buf_Init(&buf, MAKE_BSIZE);
260: for (;;) {
261: Buf_AddInterval(&buf, start, p);
262: if (*p != '$') {
263: name->s = (const char *)Buf_Retrieve(&buf);
264: name->e = name->s + Buf_Size(&buf);
265: name->tofree = TRUE;
266: return p;
267: }
268: start = p;
269: Var_ParseBuffer(&buf, start, ctxt, err, &len);
270: start += len;
271: p = cont(start);
272: }
273: }
274: }
275:
276: void
277: Var_Name_Free(name)
278: struct Name *name;
279: {
280: if (name->tofree)
281: free((char *)name->s);
282: }
1.37 espie 283:
284: void
285: SymTable_Init(ctxt)
286: SymTable *ctxt;
287: {
1.53 espie 288: static SymTable sym_template;
1.37 espie 289: memcpy(ctxt, &sym_template, sizeof(*ctxt));
290: }
291:
1.53 espie 292: #ifdef CLEANUP
1.37 espie 293: void
294: SymTable_Destroy(ctxt)
295: SymTable *ctxt;
296: {
297: int i;
298:
299: for (i = 0; i < LOCAL_SIZE; i++)
300: if (ctxt->locals[i] != NULL)
301: VarDelete(ctxt->locals[i]);
302: }
1.53 espie 303: #endif
1.37 espie 304:
1.38 espie 305: static int
306: quick_lookup(name, end, pk)
307: const char *name;
308: const char **end;
309: u_int32_t *pk;
310: {
311: size_t len;
312:
1.52 espie 313: *pk = ohash_interval(name, end);
1.38 espie 314: len = *end - name;
315: /* substitute short version for long local name */
1.53 espie 316: switch (*pk % MAGICSLOTS1) { /* MAGICSLOTS should be the */
317: case K_LONGALLSRC % MAGICSLOTS1: /* smallest constant yielding */
318: /* distinct case values */
1.38 espie 319: if (*pk == K_LONGALLSRC && strncmp(name, LONGALLSRC, len) == 0 &&
320: len == strlen(LONGALLSRC))
321: return ALLSRC_INDEX;
322: break;
1.53 espie 323: case K_LONGARCHIVE % MAGICSLOTS1:
1.38 espie 324: if (*pk == K_LONGARCHIVE && strncmp(name, LONGARCHIVE, len) == 0 &&
325: len == strlen(LONGARCHIVE))
326: return ARCHIVE_INDEX;
327: break;
1.53 espie 328: case K_LONGIMPSRC % MAGICSLOTS1:
1.38 espie 329: if (*pk == K_LONGIMPSRC && strncmp(name, LONGIMPSRC, len) == 0 &&
330: len == strlen(LONGIMPSRC))
331: return IMPSRC_INDEX;
332: break;
1.53 espie 333: case K_LONGMEMBER % MAGICSLOTS1:
1.38 espie 334: if (*pk == K_LONGMEMBER && strncmp(name, LONGMEMBER, len) == 0 &&
335: len == strlen(LONGMEMBER))
336: return MEMBER_INDEX;
337: break;
1.53 espie 338: case K_LONGOODATE % MAGICSLOTS1:
1.38 espie 339: if (*pk == K_LONGOODATE && strncmp(name, LONGOODATE, len) == 0 &&
340: len == strlen(LONGOODATE))
341: return OODATE_INDEX;
342: break;
1.53 espie 343: case K_LONGPREFIX % MAGICSLOTS1:
1.38 espie 344: if (*pk == K_LONGPREFIX && strncmp(name, LONGPREFIX, len) == 0 &&
345: len == strlen(LONGPREFIX))
346: return PREFIX_INDEX;
347: break;
1.53 espie 348: case K_LONGTARGET % MAGICSLOTS1:
1.38 espie 349: if (*pk == K_LONGTARGET && strncmp(name, LONGTARGET, len) == 0 &&
350: len == strlen(LONGTARGET))
351: return TARGET_INDEX;
352: break;
1.53 espie 353: case K_TARGET % MAGICSLOTS1:
1.38 espie 354: if (name[0] == TARGET[0] && len == 1)
355: return TARGET_INDEX;
356: break;
1.53 espie 357: case K_OODATE % MAGICSLOTS1:
1.38 espie 358: if (name[0] == OODATE[0] && len == 1)
359: return OODATE_INDEX;
360: break;
1.53 espie 361: case K_ALLSRC % MAGICSLOTS1:
1.38 espie 362: if (name[0] == ALLSRC[0] && len == 1)
363: return ALLSRC_INDEX;
364: break;
1.53 espie 365: case K_IMPSRC % MAGICSLOTS1:
1.38 espie 366: if (name[0] == IMPSRC[0] && len == 1)
367: return IMPSRC_INDEX;
368: break;
1.53 espie 369: case K_PREFIX % MAGICSLOTS1:
1.38 espie 370: if (name[0] == PREFIX[0] && len == 1)
371: return PREFIX_INDEX;
372: break;
1.53 espie 373: case K_ARCHIVE % MAGICSLOTS1:
1.38 espie 374: if (name[0] == ARCHIVE[0] && len == 1)
375: return ARCHIVE_INDEX;
376: break;
1.53 espie 377: case K_MEMBER % MAGICSLOTS1:
1.38 espie 378: if (name[0] == MEMBER[0] && len == 1)
379: return MEMBER_INDEX;
380: break;
1.53 espie 381: case K_FTARGET % MAGICSLOTS1:
382: if (name[0] == FTARGET[0] && name[1] == FTARGET[1] && len == 2)
383: return FTARGET_INDEX;
384: break;
385: case K_DTARGET % MAGICSLOTS1:
386: if (name[0] == DTARGET[0] && name[1] == DTARGET[1] && len == 2)
387: return DTARGET_INDEX;
388: break;
389: case K_FPREFIX % MAGICSLOTS1:
390: if (name[0] == FPREFIX[0] && name[1] == FPREFIX[1] && len == 2)
391: return FPREFIX_INDEX;
392: break;
393: case K_DPREFIX % MAGICSLOTS1:
394: if (name[0] == DPREFIX[0] && name[1] == DPREFIX[1] && len == 2)
395: return DPREFIX_INDEX;
396: break;
397: case K_FARCHIVE % MAGICSLOTS1:
398: if (name[0] == FARCHIVE[0] && name[1] == FARCHIVE[1] && len == 2)
399: return FARCHIVE_INDEX;
400: break;
401: case K_DARCHIVE % MAGICSLOTS1:
402: if (name[0] == DARCHIVE[0] && name[1] == DARCHIVE[1] && len == 2)
403: return DARCHIVE_INDEX;
404: break;
405: case K_FMEMBER % MAGICSLOTS1:
406: if (name[0] == FMEMBER[0] && name[1] == FMEMBER[1] && len == 2)
407: return FMEMBER_INDEX;
408: break;
409: case K_DMEMBER % MAGICSLOTS1:
410: if (name[0] == DMEMBER[0] && name[1] == DMEMBER[1] && len == 2)
411: return DMEMBER_INDEX;
412: break;
1.38 espie 413: default:
414: break;
415: }
416: return -1;
417: }
1.37 espie 418:
1.53 espie 419: void
1.37 espie 420: Varq_Set(idx, val, gn)
421: int idx;
1.53 espie 422: const char *val;
423: GNode *gn;
1.37 espie 424: {
1.38 espie 425: /* We only look for a variable in the given context since anything set
426: * here will override anything in a lower context, so there's not much
427: * point in searching them all just to save a bit of memory... */
1.37 espie 428: Var *v = gn->context.locals[idx];
429:
430: if (v == NULL) {
1.53 espie 431: v = new_var(varnames[idx], NULL, val);
1.37 espie 432: v->flags = 0;
433: gn->context.locals[idx] = v;
434: } else {
435: Buf_Reset(&(v->val));
436: Buf_AddString(&(v->val), val);
1.53 espie 437:
1.37 espie 438: }
439: if (DEBUG(VAR))
440: printf("%s:%s = %s\n", gn->name, varnames[idx], val);
441: }
442:
1.53 espie 443: void
1.37 espie 444: Varq_Append(idx, val, gn)
1.53 espie 445: int idx;
1.48 espie 446: const char *val;
1.37 espie 447: GNode *gn;
448: {
1.53 espie 449: Var *v = gn->context.locals[idx];
1.37 espie 450:
451: if (v == NULL) {
1.53 espie 452: v = new_var(varnames[idx], NULL, val);
1.37 espie 453: v->flags = 0;
454: gn->context.locals[idx] = v;
455: } else {
456: Buf_AddSpace(&(v->val));
457: Buf_AddString(&(v->val), val);
458: }
459: if (DEBUG(VAR))
460: printf("%s:%s = %s\n", gn->name, varnames[idx], VarValue(v));
461: }
462:
463: char *
464: Varq_Value(idx, gn)
1.53 espie 465: int idx;
1.37 espie 466: GNode *gn;
467: {
468: Var *v = gn->context.locals[idx];
469:
1.53 espie 470: if (v == NULL)
471: return NULL;
1.37 espie 472: else
1.53 espie 473: return VarValue(v);
474: }
475:
476: static const char *
477: context_name(ctxt)
478: GSymT *ctxt;
479: {
480: if (ctxt == VAR_GLOBAL)
481: return "Global";
482: if (ctxt == VAR_CMD)
483: return "Command";
484: return "Error";
1.37 espie 485: }
486:
1.53 espie 487: /* We separate var creation proper from setting of initial value:
488: * VAR_DUMMY corresponds to `lazy' setup, e.g., always create global
489: * variable at first lookup, and then fill it up when value is wanted.
490: * This avoids looking through the environment several times.
491: */
492: static Var *
493: create_var(name, end)
494: const char *name;
495: const char *end;
1.37 espie 496: {
1.53 espie 497: return ohash_create_entry(&var_info, name, &end);
1.37 espie 498: }
1.1 deraadt 499:
1.53 espie 500: /* Set the initial value a var should have */
501: static void
502: var_init_string(v, val)
503: Var *v;
504: const char *val;
505: {
506: size_t len;
507:
508: len = strlen(val);
509: Buf_Init(&(v->val), len+1);
510: Buf_AddChars(&(v->val), len, val);
511: }
1.35 espie 512:
1.53 espie 513: static Var *
514: new_var(name, end, val)
515: const char *name;
516: const char *end;
517: const char *val;
1.35 espie 518: {
1.53 espie 519: Var *v;
520:
521: v = create_var(name, end);
522: #ifdef STATS_VAR_LOOKUP
523: STAT_VAR_CREATION++;
524: #endif
525: if (val != NULL)
526: var_init_string(v, val);
1.37 espie 527: else
1.53 espie 528: Buf_Init(&(v->val), 1);
529:
530: return v;
1.35 espie 531: }
1.53 espie 532:
1.37 espie 533: static Var *
1.53 espie 534: var_from_env(name, end, k)
535: const char *name;
536: const char *end;
537: u_int32_t k;
1.37 espie 538: {
1.53 espie 539: char *env;
540: Var *v;
1.37 espie 541:
1.53 espie 542: /* getenv requires a null-terminated name, so we create the var
543: * structure first. */
544: v = create_var(name, end);
545: env = getenv(v->name);
546: if (env == NULL)
547: v->flags = VAR_DUMMY;
548: else {
549: var_init_string(v, env);
550: if (checkEnvFirst)
551: v->flags = VAR_READ_ONLY | VAR_FROM_ENV;
552: else
553: v->flags = VAR_FROM_ENV;
554: }
1.37 espie 555:
1.53 espie 556: #ifdef STATS_VAR_LOOKUP
557: STAT_VAR_FROM_ENV++;
558: #endif
1.37 espie 559:
1.53 espie 560: ohash_insert(VAR_GLOBAL, ohash_lookup_interval(VAR_GLOBAL, name, end, k), v);
1.37 espie 561: return v;
562: }
563:
1.38 espie 564: static Var *
565: getvar(ctxt, name, end, k)
566: GSymT *ctxt;
1.53 espie 567: const char *name;
1.38 espie 568: const char *end;
569: u_int32_t k;
1.1 deraadt 570: {
1.52 espie 571: return ohash_find(ctxt, ohash_lookup_interval(ctxt, name, end, k));
1.37 espie 572: }
573:
1.1 deraadt 574: /*-
575: *-----------------------------------------------------------------------
1.39 espie 576: * VarFind_interval --
1.1 deraadt 577: * Find the given variable in the given context and any other contexts
1.39 espie 578: * indicated. if end is NULL, name is a string, otherwise, only
1.53 espie 579: * the interval name - end is concerned.
1.1 deraadt 580: *
581: * Results:
582: * A pointer to the structure describing the desired variable or
1.26 espie 583: * NULL if the variable does not exist.
1.1 deraadt 584: *-----------------------------------------------------------------------
585: */
586: static Var *
1.39 espie 587: VarFind_interval(name, end, ctxt, flags)
1.53 espie 588: const char *name; /* name to find */
1.39 espie 589: const char *end; /* end of name */
1.53 espie 590: SymTable *ctxt; /* context in which to find it */
591: int flags; /* FIND_MINE set means to look in the
1.39 espie 592: * CTXT_GLOBAL and CTXT_CMD contexts also.
1.1 deraadt 593: * FIND_ENV set means to look in the
1.39 espie 594: * environment */
1.1 deraadt 595: {
1.53 espie 596: u_int32_t k;
1.38 espie 597: int idx;
1.53 espie 598:
599: #ifdef STATS_VAR_LOOKUP
600: STAT_VAR_FIND++;
601: #endif
1.38 espie 602:
603: idx = quick_lookup(name, &end, &k);
1.39 espie 604: return varfind(name, end, ctxt, flags, idx, k);
605: }
606:
607: static Var *
608: varfind(name, end, ctxt, flags, idx, k)
609: const char *name;
610: const char *end;
611: SymTable *ctxt;
1.53 espie 612: int flags;
613: int idx;
1.39 espie 614: u_int32_t k;
615: {
1.53 espie 616: Var *v;
1.1 deraadt 617:
1.53 espie 618: /* Handle local variables first */
619: if (idx != -1) {
620: if (ctxt != NULL && ctxt != CTXT_CMD && ctxt != CTXT_GLOBAL) {
621: if (idx < LOCAL_SIZE)
622: return ctxt->locals[idx];
623: else
624: return ctxt->locals[EXTENDED2SIMPLE(idx)];
625: } else
626: return NULL;
627: }
628: /* First look for the variable in the given context. If it's not there,
629: look for it in CTXT_CMD, CTXT_GLOBAL and the environment,
630: depending on the FIND_* flags in 'flags' */
631: if (ctxt == CTXT_CMD || ctxt == CTXT_GLOBAL)
632: v = getvar((GSymT *)ctxt, name, end, k);
633: else
1.37 espie 634: v = NULL;
1.17 espie 635:
1.53 espie 636: if (v == NULL)
637: switch (flags) {
638: case 0:
639: break;
640: case FIND_MINE:
641: if (ctxt != CTXT_CMD)
642: v = getvar(VAR_CMD, name, end, k);
643: if (v == NULL && ctxt != CTXT_GLOBAL)
644: v = getvar(VAR_GLOBAL, name, end, k);
645: break;
646: case FIND_ENV:
647: v = var_from_env(name, end, k);
648: break;
649: case FIND_ENV | FIND_MINE:
650: if (ctxt != CTXT_CMD)
651: v = getvar(VAR_CMD, name, end, k);
652: if (v == NULL) {
653: if (ctxt != CTXT_GLOBAL)
654: v = getvar(VAR_GLOBAL, name, end, k);
655: if (v == NULL)
656: v = var_from_env(name, end, k);
657: else if (checkEnvFirst && (v->flags & VAR_FROM_ENV) == 0) {
658: char *env;
659:
660: env = getenv(v->name);
661: if (env != NULL) {
662: Buf_Reset(&(v->val));
663: Buf_AddString(&(v->val), env);
664: }
665: /* XXX even if no such env variable, fake it, to avoid
666: * further lookup */
667: v->flags |= VAR_FROM_ENV;
668: }
669: }
670: break;
671: }
1.37 espie 672: return v;
1.1 deraadt 673: }
674:
675: /*-
676: *-----------------------------------------------------------------------
677: * VarAdd --
678: * Add a new variable of name name and value val to the given context
679: *
680: * Results:
1.53 espie 681: * The added variable.
1.1 deraadt 682: *
683: * Side Effects:
1.48 espie 684: * The new variable is placed in the given context.
1.1 deraadt 685: * The name and val arguments are duplicated so they may
686: * safely be freed.
687: *-----------------------------------------------------------------------
688: */
1.17 espie 689: static Var *
1.53 espie 690: VarAdd(name, end, k, val, ctxt)
1.39 espie 691: const char *name; /* name of variable to add */
1.53 espie 692: const char *end;
693: u_int32_t k;
1.39 espie 694: const char *val; /* value to set it to */
1.37 espie 695: GSymT *ctxt; /* context in which to set it */
1.1 deraadt 696: {
1.53 espie 697: Var *v;
1.1 deraadt 698:
1.53 espie 699: v = new_var(name, end, val);
1.1 deraadt 700:
701: v->flags = 0;
702:
1.53 espie 703: ohash_insert(ctxt, ohash_lookup_interval(ctxt, name, end, k), v);
704: if (DEBUG(VAR))
705: printf("%s:%s = %s\n", context_name(ctxt), v->name, val);
1.17 espie 706: return v;
1.1 deraadt 707: }
708:
709: /*-
710: *-----------------------------------------------------------------------
711: * VarDelete --
712: * Delete a variable and all the space associated with it.
713: *-----------------------------------------------------------------------
714: */
715: static void
716: VarDelete(vp)
1.53 espie 717: void *vp;
1.1 deraadt 718: {
1.53 espie 719: Var *v = (Var *)vp;
1.48 espie 720:
1.53 espie 721: if ((v->flags & VAR_DUMMY) == 0)
722: Buf_Destroy(&(v->val));
1.23 espie 723: free(v);
1.1 deraadt 724: }
725:
726:
727:
728: /*-
729: *-----------------------------------------------------------------------
730: * Var_Delete --
1.53 espie 731: * Remove a global variable.
1.1 deraadt 732: *
733: * Side Effects:
734: * The Var structure is removed and freed.
735: *-----------------------------------------------------------------------
736: */
737: void
1.53 espie 738: Var_Delete(name)
739: const char *name;
1.1 deraadt 740: {
1.48 espie 741: Var *v;
742: u_int32_t k;
1.53 espie 743: unsigned int slot;
1.48 espie 744: const char *end = NULL;
1.53 espie 745: int idx;
746:
1.1 deraadt 747:
1.37 espie 748: if (DEBUG(VAR))
1.53 espie 749: printf("delete %s\n", name);
1.37 espie 750:
1.53 espie 751: idx = quick_lookup(name, &end, &k);
752: if (idx != -1)
753: Parse_Error(PARSE_FATAL, "Trying to delete dynamic variable");
754: slot = ohash_lookup_interval(VAR_GLOBAL, name, end, k);
755: v = ohash_find(VAR_GLOBAL, slot);
756: if (v != NULL && (v->flags & VAR_READ_ONLY) == 0) {
757: ohash_remove(VAR_GLOBAL, slot);
1.30 espie 758: VarDelete(v);
1.53 espie 759: }
1.1 deraadt 760: }
761:
762: /*-
763: *-----------------------------------------------------------------------
764: * Var_Set --
765: * Set the variable name to the value val in the given context.
766: *
767: * Side Effects:
768: * If the variable doesn't yet exist, a new record is created for it.
769: * Else the old value is freed and the new one stuck in its place
770: *
771: * Notes:
772: * The variable is searched for only in its context before being
1.53 espie 773: * created in that context. I.e. if the context is CTXT_GLOBAL,
774: * only CTXT_GLOBAL is searched. Likewise if it is CTXT_CMD, only
775: * CTXT_CMD is searched.
1.1 deraadt 776: *-----------------------------------------------------------------------
777: */
778: void
1.53 espie 779: Var_Set_interval(name, end, val, ctxt)
1.48 espie 780: const char *name; /* name of variable to set */
1.53 espie 781: const char *end;
1.48 espie 782: const char *val; /* value to give to the variable */
1.53 espie 783: GSymT *ctxt; /* context in which to set it */
1.1 deraadt 784: {
1.48 espie 785: Var *v;
1.53 espie 786: u_int32_t k;
787: int idx;
788:
789: idx = quick_lookup(name, &end, &k);
790: if (idx != -1)
791: Parse_Error(PARSE_FATAL, "Trying to set dynamic variable $%s",
792: varnames[idx]);
1.1 deraadt 793:
1.53 espie 794: /* We only look for a variable in the given context since anything set
1.1 deraadt 795: * here will override anything in a lower context, so there's not much
1.53 espie 796: * point in searching them all just to save a bit of memory... */
797: v = varfind(name, end, (SymTable *)ctxt, 0, idx, k);
1.38 espie 798: if (v == NULL)
1.53 espie 799: v = VarAdd(name, end, k, val, ctxt);
1.38 espie 800: else {
1.53 espie 801: if ((v->flags & VAR_READ_ONLY) == 0) {
802: if ((v->flags & VAR_DUMMY) == 0) {
803: Buf_Reset(&(v->val));
804: Buf_AddString(&(v->val), val);
805: } else {
806: var_init_string(v, val);
807: v->flags &= ~VAR_DUMMY;
808: }
809:
810: }
1.1 deraadt 811: }
1.37 espie 812: if (DEBUG(VAR))
1.53 espie 813: printf("%s:%s = %s\n", context_name(ctxt), v->name, val);
814: /* Any variables given on the command line are automatically exported
815: * to the environment (as per POSIX standard). */
816: if (ctxt == VAR_CMD)
817: esetenv(v->name, val);
1.1 deraadt 818: }
819:
820: /*-
821: *-----------------------------------------------------------------------
822: * Var_Append --
823: * The variable of the given name has the given value appended to it in
824: * the given context.
825: *
826: * Side Effects:
827: * If the variable doesn't exist, it is created. Else the strings
828: * are concatenated (with a space in between).
829: *
830: *-----------------------------------------------------------------------
831: */
832: void
1.53 espie 833: Var_Append_interval(name, end, val, ctxt)
1.48 espie 834: const char *name; /* Name of variable to modify */
1.53 espie 835: const char *end;
1.48 espie 836: const char *val; /* String to append to it */
1.37 espie 837: GSymT *ctxt; /* Context in which this should occur */
1.1 deraadt 838: {
1.53 espie 839: Var *v;
840: u_int32_t k;
841: int idx;
842:
843: assert(ctxt == VAR_GLOBAL || ctxt == VAR_CMD);
844:
845: idx = quick_lookup(name, &end, &k);
846: if (idx != -1)
847: Parse_Error(PARSE_FATAL, "Trying to append to dynamic variable $%s",
848: varnames[idx]);
1.1 deraadt 849:
1.53 espie 850: v = varfind(name, end, (SymTable *)ctxt, FIND_ENV, idx, k);
851:
852: if ((v->flags & VAR_READ_ONLY) == 0) {
853: if ((v->flags & VAR_DUMMY) == 0) {
854: Buf_AddSpace(&(v->val));
855: Buf_AddString(&(v->val), val);
856: } else {
857: var_init_string(v, val);
858: v->flags &= ~VAR_DUMMY;
859: }
1.1 deraadt 860:
861: }
1.37 espie 862: if (DEBUG(VAR))
1.53 espie 863: printf("%s:%s = %s\n", context_name(ctxt), v->name, VarValue(v));
1.1 deraadt 864: }
865:
866: /*-
867: *-----------------------------------------------------------------------
1.53 espie 868: * Var_Value --
869: * Return the value of a global named variable
1.1 deraadt 870: *
871: * Results:
1.53 espie 872: * The value if the variable exists, NULL if it doesn't
1.1 deraadt 873: *-----------------------------------------------------------------------
874: */
1.53 espie 875: char *
876: Var_Value_interval(name, end)
877: const char *name; /* name to find */
878: const char *end;
879: {
880: Var *v;
881:
882: v = VarFind_interval(name, end, NULL, FIND_ENV | FIND_MINE);
883: if (v != NULL && (v->flags & VAR_DUMMY) == 0)
884: return VarValue(v);
885: else
886: return NULL;
887: }
888:
889: static const char *
890: find_0(p)
891: const char *p;
1.1 deraadt 892: {
1.53 espie 893: while (*p != '$' && *p != '\0' && *p != ':')
894: p++;
895: return p;
896: }
897:
898: static const char *
899: find_rparen(p)
900: const char *p;
901: {
902: while (*p != '$' && *p != '\0' && *p != ')' && *p != ':')
903: p++;
904: return p;
905: }
1.1 deraadt 906:
1.53 espie 907: static const char *
908: find_ket(p)
909: const char *p;
910: {
911: while (*p != '$' && *p != '\0' && *p != '}' && *p != ':')
912: p++;
913: return p;
914: }
1.1 deraadt 915:
1.53 espie 916: static find_t
917: find_pos(c)
918: int c;
919: {
920: switch(c) {
921: case '\0':
922: return find_0;
923: case ')':
924: return find_rparen;
925: case '}':
926: return find_ket;
927: default:
928: return 0;
929: }
1.1 deraadt 930: }
931:
932: /*-
933: *-----------------------------------------------------------------------
1.53 espie 934: * Var_ParseSkip --
935: * Do whatever is needed to skip over a var specification. Since the
936: * result is not needed at this point, some shortcuts may be taken.
1.1 deraadt 937: *
1.53 espie 938: * Return value: the amount to skip
1.1 deraadt 939: *-----------------------------------------------------------------------
940: */
1.53 espie 941: size_t
942: Var_ParseSkip(str, ctxt, result)
943: const char *str;
944: SymTable *ctxt;
945: ReturnStatus *result;
1.1 deraadt 946: {
1.53 espie 947: const char *tstr; /* Pointer into str */
948: Var *v; /* Variable in invocation */
949: char endc; /* Ending character when variable in parens
950: * or braces */
951: const char *start;
952: size_t length;
953: struct Name name;
1.1 deraadt 954:
1.53 espie 955: v = NULL;
956: start = str;
957: str++;
958:
959: if (*str != '(' && *str != '{') {
960: name.tofree = FALSE;
961: tstr = str + 1;
962: length = 2;
963: endc = '\0';
964: } else {
965: endc = *str == '(' ? ')' : '}';
966: str++;
967:
968: /* Find eventual modifiers in the variable */
969: tstr = Var_Name_Get(str, &name, ctxt, FALSE, find_pos(endc));
970: Var_Name_Free(&name);
1.54 ! espie 971: length = tstr - start;
! 972: /* Terminated correctly */
! 973: if (*tstr != '\0')
! 974: length++;
1.53 espie 975: }
976:
977: if (result != NULL)
978: *result = SUCCESS;
979: if (*tstr == ':' && endc != '\0')
980: if (VarModifiers_Apply(NULL, NULL, ctxt, TRUE, NULL, tstr, endc,
981: &length) == var_Error)
982: *result = FAILURE;
983: return length;
1.1 deraadt 984: }
985:
1.53 espie 986: /*-
1.45 espie 987: *-----------------------------------------------------------------------
1.53 espie 988: * Var_ParseBuffer --
989: * Given the start of a variable invocation, extract the variable
990: * name and find its value, then modify it according to the
991: * specification, and add the result to the buffer.
992: *
993: * Results:
994: * FAILURE for invalid specifications.
995: *
996: * Side-effects:
997: * The length of the specification is placed in *lengthPtr
998: * (for invalid specifications, this is just 2...?).
1.45 espie 999: *-----------------------------------------------------------------------
1000: */
1.53 espie 1001: ReturnStatus
1002: Var_ParseBuffer(buf, str, ctxt, err, lengthPtr)
1003: Buffer buf;
1004: const char *str;
1005: SymTable *ctxt;
1006: Boolean err;
1007: size_t *lengthPtr;
1008: {
1009: char *result;
1010: Boolean freeIt;
1.45 espie 1011:
1.53 espie 1012: result = Var_Parse(str, ctxt, err, lengthPtr, &freeIt);
1013: if (result == var_Error)
1014: return FAILURE;
1015:
1016: Buf_AddString(buf, result);
1017: if (freeIt)
1018: free(result);
1019: return SUCCESS;
1.45 espie 1020: }
1021:
1.1 deraadt 1022: /*-
1023: *-----------------------------------------------------------------------
1024: * Var_Parse --
1025: * Given the start of a variable invocation, extract the variable
1026: * name and find its value, then modify it according to the
1027: * specification.
1028: *
1029: * Results:
1030: * The (possibly-modified) value of the variable or var_Error if the
1031: * specification is invalid. The length of the specification is
1032: * placed in *lengthPtr (for invalid specifications, this is just
1033: * 2...?).
1034: * A Boolean in *freePtr telling whether the returned string should
1035: * be freed by the caller.
1036: *-----------------------------------------------------------------------
1037: */
1038: char *
1.35 espie 1039: Var_Parse(str, ctxt, err, lengthPtr, freePtr)
1.53 espie 1040: const char *str; /* The string to parse */
1041: SymTable *ctxt; /* The context for the variable */
1042: Boolean err; /* TRUE if undefined variables are an error */
1.44 espie 1043: size_t *lengthPtr; /* OUT: The length of the specification */
1.53 espie 1044: Boolean *freePtr; /* OUT: TRUE if caller should free result */
1.44 espie 1045: {
1.53 espie 1046: const char *tstr; /* Pointer into str */
1047: Var *v; /* Variable in invocation */
1048: char endc; /* Ending character when variable in parens
1.1 deraadt 1049: * or braces */
1.53 espie 1050: struct Name name;
1051: const char *start;
1.44 espie 1052: char *val; /* Variable value */
1053: u_int32_t k;
1.53 espie 1054: int idx;
1.5 millert 1055:
1.1 deraadt 1056: *freePtr = FALSE;
1.44 espie 1057: start = str++;
1.5 millert 1058:
1.44 espie 1059: val = NULL;
1.45 espie 1060: v = NULL;
1.53 espie 1061: idx = -1;
1.44 espie 1062:
1063: if (*str != '(' && *str != '{') {
1.53 espie 1064: name.s = str;
1065: name.e = str+1;
1066: name.tofree = FALSE;
1067: tstr = str + 1;
1.44 espie 1068: *lengthPtr = 2;
1069: endc = '\0';
1.1 deraadt 1070: } else {
1.44 espie 1071: endc = *str == '(' ? ')' : '}';
1.53 espie 1072: str++;
1.5 millert 1073:
1.44 espie 1074: /* Find eventual modifiers in the variable */
1.53 espie 1075: tstr = Var_Name_Get(str, &name, ctxt, FALSE, find_pos(endc));
1.54 ! espie 1076: *lengthPtr = tstr - start;
! 1077: if (*tstr != '\0')
! 1078: (*lengthPtr)++;
1.44 espie 1079: }
1.5 millert 1080:
1.53 espie 1081: idx = quick_lookup(name.s, &name.e, &k);
1082: v = varfind(name.s, name.e, ctxt, FIND_ENV | FIND_MINE, idx, k);
1083: if (v != NULL && (v->flags & VAR_DUMMY) == 0) {
1.44 espie 1084: if (v->flags & VAR_IN_USE)
1085: Fatal("Variable %s is recursive.", v->name);
1086: /*NOTREACHED*/
1087: else
1088: v->flags |= VAR_IN_USE;
1.53 espie 1089:
1.44 espie 1090: /* Before doing any modification, we have to make sure the value
1091: * has been fully expanded. If it looks like recursion might be
1092: * necessary (there's a dollar sign somewhere in the variable's value)
1093: * we just call Var_Subst to do any other substitutions that are
1094: * necessary. Note that the value returned by Var_Subst will have
1095: * been dynamically-allocated, so it will need freeing when we
1096: * return. */
1097: val = VarValue(v);
1.53 espie 1098: if (idx == -1) {
1099: if (strchr(val, '$') != NULL) {
1100: val = Var_Subst(val, ctxt, err);
1101: *freePtr = TRUE;
1102: }
1103: } else if (idx >= LOCAL_SIZE) {
1104: if (IS_EXTENDED_F(idx))
1105: val = Var_GetTail(val);
1106: else
1107: val = Var_GetHead(val);
1.44 espie 1108: *freePtr = TRUE;
1109: }
1110: v->flags &= ~VAR_IN_USE;
1.1 deraadt 1111: }
1.53 espie 1112: if (*tstr == ':' && endc != '\0')
1113: val = VarModifiers_Apply(val, &name, ctxt, err, freePtr, tstr, endc,
1.42 espie 1114: lengthPtr);
1.44 espie 1115: if (val == NULL) {
1.53 espie 1116: val = err ? var_Error : varNoError;
1117: /* Dynamic source */
1118: if (idx != -1) {
1119: /* can't be expanded for now: copy the var spec instead. */
1120: if (ctxt == NULL || ctxt == CTXT_GLOBAL || ctxt == CTXT_CMD) {
1121: *freePtr = TRUE;
1122: val = interval_dup(start, start+ *lengthPtr);
1123: } else {
1124: /* somehow, this should have been expanded already. */
1125: GNode *n;
1126:
1127: n = (GNode *)(((char *)ctxt) - offsetof(GNode, context));
1128: if (idx >= LOCAL_SIZE)
1129: idx = EXTENDED2SIMPLE(idx);
1130: switch(idx) {
1131: case IMPSRC_INDEX:
1132: Fatal("Using $< in a non-suffix rule context is a GNUmake idiom (line %lu of %s)",
1133: n->lineno, n->fname);
1134: default:
1135: Error("Using undefined dynamic variable $%s (line %lu of %s)",
1136: varnames[idx], n->lineno, n->fname);
1137: break;
1138: }
1139: }
1140: }
1.42 espie 1141: }
1.53 espie 1142: Var_Name_Free(&name);
1.44 espie 1143: return val;
1.42 espie 1144: }
1145:
1.1 deraadt 1146: /*-
1147: *-----------------------------------------------------------------------
1148: * Var_Subst --
1.24 espie 1149: * Substitute for all variables in a string in a context
1.1 deraadt 1150: * If undefErr is TRUE, Parse_Error will be called when an undefined
1151: * variable is encountered.
1152: *
1153: * Results:
1154: * The resulting string.
1155: *
1156: * Side Effects:
1.53 espie 1157: * The new string must be freed by the caller
1.1 deraadt 1158: *-----------------------------------------------------------------------
1159: */
1160: char *
1.24 espie 1161: Var_Subst(str, ctxt, undefErr)
1.53 espie 1162: const char *str; /* the string in which to substitute */
1163: SymTable *ctxt; /* the context wherein to find variables */
1164: Boolean undefErr; /* TRUE if undefineds are an error */
1.1 deraadt 1165: {
1.53 espie 1166: BUFFER buf; /* Buffer for forming things */
1.1 deraadt 1167: static Boolean errorReported; /* Set true if an error has already
1168: * been reported to prevent a plethora
1169: * of messages when recursing */
1170:
1.23 espie 1171: Buf_Init(&buf, MAKE_BSIZE);
1.1 deraadt 1172: errorReported = FALSE;
1173:
1.24 espie 1174: for (;;) {
1175: char *val; /* Value to substitute for a variable */
1.53 espie 1176: size_t length; /* Length of the variable invocation */
1177: Boolean doFree; /* Set true if val should be freed */
1.24 espie 1178: const char *cp;
1179:
1180: /* copy uninteresting stuff */
1181: for (cp = str; *str != '\0' && *str != '$'; str++)
1182: ;
1183: Buf_AddInterval(&buf, cp, str);
1184: if (*str == '\0')
1185: break;
1186: if (str[1] == '$') {
1187: /* A dollar sign may be escaped with another dollar sign. */
1188: Buf_AddChar(&buf, '$');
1189: str += 2;
1190: continue;
1191: }
1192: val = Var_Parse(str, ctxt, undefErr, &length, &doFree);
1193: /* When we come down here, val should either point to the
1194: * value of this variable, suitably modified, or be NULL.
1195: * Length should be the total length of the potential
1196: * variable invocation (from $ to end character...) */
1197: if (val == var_Error || val == varNoError) {
1198: /* If performing old-time variable substitution, skip over
1199: * the variable and continue with the substitution. Otherwise,
1200: * store the dollar sign and advance str so we continue with
1201: * the string... */
1.53 espie 1202: if (oldVars)
1.24 espie 1203: str += length;
1.53 espie 1204: else if (undefErr) {
1.24 espie 1205: /* If variable is undefined, complain and skip the
1206: * variable. The complaint will stop us from doing anything
1207: * when the file is parsed. */
1.53 espie 1208: if (!errorReported)
1.24 espie 1209: Parse_Error(PARSE_FATAL,
1210: "Undefined variable \"%.*s\"",length,str);
1211: str += length;
1212: errorReported = TRUE;
1213: } else {
1214: Buf_AddChar(&buf, *str);
1.53 espie 1215: str++;
1.24 espie 1216: }
1217: } else {
1218: /* We've now got a variable structure to store in. But first,
1219: * advance the string pointer. */
1220: str += length;
1221:
1222: /* Copy all the characters from the variable value straight
1223: * into the new string. */
1224: Buf_AddString(&buf, val);
1225: if (doFree)
1226: free(val);
1227: }
1228: }
1229: return Buf_Retrieve(&buf);
1230: }
1.1 deraadt 1231:
1.24 espie 1232: /*-
1233: *-----------------------------------------------------------------------
1234: * Var_SubstVar --
1235: * Substitute for one variable in the given string in the given context
1236: * If undefErr is TRUE, Parse_Error will be called when an undefined
1.53 espie 1237: * variable is encountered. Add the substituted string to buffer.
1.24 espie 1238: *-----------------------------------------------------------------------
1239: */
1.53 espie 1240: void
1241: Var_SubstVar(buf, str, var, val)
1242: Buffer buf;
1243: const char *str; /* The string in which to substitute */
1.24 espie 1244: const char *var; /* Named variable */
1.50 espie 1245: const char *val; /* Its value */
1.24 espie 1246: {
1247:
1.53 espie 1248: assert(*var != '\0');
1249:
1.24 espie 1250: for (;;) {
1.50 espie 1251: const char *start;
1252: /* Copy uninteresting stuff */
1253: for (start = str; *str != '\0' && *str != '$'; str++)
1.24 espie 1254: ;
1.53 espie 1255: Buf_AddInterval(buf, start, str);
1.50 espie 1256:
1257: start = str;
1258: if (*str++ == '\0')
1.24 espie 1259: break;
1.50 espie 1260: str++;
1261: /* and escaped dollars */
1262: if (start[1] == '$') {
1.53 espie 1263: Buf_AddInterval(buf, start, start+2);
1.24 espie 1264: continue;
1265: }
1.50 espie 1266: /* Simple variable, if it's not us, copy. */
1267: if (start[1] != '(' && start[1] != '{') {
1268: if (start[1] != *var || var[1] != '\0') {
1.53 espie 1269: Buf_AddChars(buf, 2, start);
1.1 deraadt 1270: continue;
1.24 espie 1271: }
1.1 deraadt 1272: } else {
1.50 espie 1273: const char *p;
1.24 espie 1274: char endc;
1.1 deraadt 1275:
1.50 espie 1276: if (start[1] == '(')
1.24 espie 1277: endc = ')';
1.53 espie 1278: else
1.24 espie 1279: endc = '}';
1280:
1281: /* Find the end of the variable specification. */
1.50 espie 1282: p = str;
1.24 espie 1283: while (*p != '\0' && *p != ':' && *p != endc && *p != '$')
1284: p++;
1.53 espie 1285: /* A variable inside the variable. We don't know how to
1286: * expand the external variable at this point, so we try
1287: * again with the nested variable. */
1.24 espie 1288: if (*p == '$') {
1.53 espie 1289: Buf_AddInterval(buf, start, p);
1.24 espie 1290: str = p;
1291: continue;
1.1 deraadt 1292: }
1.5 millert 1293:
1.50 espie 1294: if (strncmp(var, str, p - str) != 0 ||
1295: var[p - str] != '\0') {
1.53 espie 1296: /* Not the variable we want to expand. */
1297: Buf_AddInterval(buf, start, p);
1.24 espie 1298: str = p;
1299: continue;
1.53 espie 1300: }
1.50 espie 1301: if (*p == ':') {
1.53 espie 1302: size_t length; /* Length of the variable invocation */
1303: Boolean doFree; /* Set true if val should be freed */
1.50 espie 1304: char *newval; /* Value substituted for a variable */
1.53 espie 1305: struct Name name;
1.50 espie 1306:
1.53 espie 1307: length = p - str + 1;
1.50 espie 1308: doFree = FALSE;
1.53 espie 1309: name.s = var;
1310: name.e = var + (p-str);
1.50 espie 1311:
1312: /* val won't be freed since doFree == FALSE, but
1313: * VarModifiers_Apply doesn't know that, hence the cast. */
1.53 espie 1314: newval = VarModifiers_Apply((char *)val, &name, NULL, FALSE,
1315: &doFree, p, endc, &length);
1316: Buf_AddString(buf, newval);
1.50 espie 1317: if (doFree)
1318: free(newval);
1319: str += length;
1320: continue;
1321: } else
1.53 espie 1322: str = p+1;
1.1 deraadt 1323: }
1.53 espie 1324: Buf_AddString(buf, val);
1.1 deraadt 1325: }
1326: }
1327:
1328: /*-
1329: *-----------------------------------------------------------------------
1330: * Var_Init --
1331: * Initialize the module
1332: *
1333: * Side Effects:
1.53 espie 1334: * The CTXT_CMD and CTXT_GLOBAL contexts are initialized
1.1 deraadt 1335: *-----------------------------------------------------------------------
1336: */
1337: void
1.33 espie 1338: Var_Init()
1.1 deraadt 1339: {
1.53 espie 1340: static GSymT global_vars, cmd_vars;
1.35 espie 1341:
1342: VAR_GLOBAL = &global_vars;
1343: VAR_CMD = &cmd_vars;
1.52 espie 1344: ohash_init(VAR_GLOBAL, 10, &var_info);
1345: ohash_init(VAR_CMD, 5, &var_info);
1.37 espie 1346: CTXT_GLOBAL = (SymTable *)VAR_GLOBAL;
1347: CTXT_CMD = (SymTable *)VAR_CMD;
1.53 espie 1348:
1349: VarModifiers_Init();
1.1 deraadt 1350: }
1351:
1352:
1353: void
1.33 espie 1354: Var_End()
1.1 deraadt 1355: {
1.37 espie 1356: #ifdef CLEANUP
1.38 espie 1357: Var *v;
1358: unsigned int i;
1359:
1.53 espie 1360: for (v = ohash_first(VAR_GLOBAL, &i); v != NULL;
1.52 espie 1361: v = ohash_next(VAR_GLOBAL, &i))
1.38 espie 1362: VarDelete(v);
1.53 espie 1363: for (v = ohash_first(VAR_CMD, &i); v != NULL;
1.52 espie 1364: v = ohash_next(VAR_CMD, &i))
1.38 espie 1365: VarDelete(v);
1.37 espie 1366: #endif
1.1 deraadt 1367: }
1.5 millert 1368:
1.53 espie 1369: static const char *interpret(int);
1370:
1371: static const char *
1372: interpret(f)
1373: int f;
1374: {
1375: if (f & VAR_DUMMY)
1376: return "(D)";
1377: return "";
1378: }
1379:
1.1 deraadt 1380:
1381: /****************** PRINT DEBUGGING INFO *****************/
1.31 espie 1382: static void
1.53 espie 1383: VarPrintVar(v)
1384: Var *v;
1.1 deraadt 1385: {
1.53 espie 1386: printf("%-16s%s = %s\n", v->name, interpret(v->flags),
1387: (v->flags & VAR_DUMMY) == 0 ? VarValue(v) : "(none)");
1.1 deraadt 1388: }
1389:
1390: /*-
1391: *-----------------------------------------------------------------------
1392: * Var_Dump --
1.53 espie 1393: * print all variables
1.1 deraadt 1394: *-----------------------------------------------------------------------
1395: */
1396: void
1.53 espie 1397: Var_Dump()
1.1 deraadt 1398: {
1.53 espie 1399: Var *v;
1400: unsigned int i;
1401:
1402: printf("#*** Global Variables:\n");
1.38 espie 1403:
1.53 espie 1404: for (v = ohash_first(VAR_GLOBAL, &i); v != NULL;
1405: v = ohash_next(VAR_GLOBAL, &i))
1406: VarPrintVar(v);
1.37 espie 1407:
1.53 espie 1408: printf("#*** Command-line Variables:\n");
1.46 espie 1409:
1.53 espie 1410: for (v = ohash_first(VAR_CMD, &i); v != NULL; v = ohash_next(VAR_CMD, &i))
1411: VarPrintVar(v);
1412: }
1.46 espie 1413:
1414: static const char *quotable = " \t\n\\'\"";
1415:
1416: /* In POSIX mode, variable assignments passed on the command line are
1417: * propagated to sub makes through MAKEFLAGS.
1418: */
1419: void
1420: Var_AddCmdline(name)
1421: const char *name;
1422: {
1423: Var *v;
1424: unsigned int i;
1425: BUFFER buf;
1426: char *s;
1427:
1428: Buf_Init(&buf, MAKE_BSIZE);
1429:
1.53 espie 1430: for (v = ohash_first(VAR_CMD, &i); v != NULL;
1431: v = ohash_next(VAR_CMD, &i)) {
1.46 espie 1432: /* We assume variable names don't need quoting */
1433: Buf_AddString(&buf, v->name);
1434: Buf_AddChar(&buf, '=');
1435: for (s = VarValue(v); *s != '\0'; s++) {
1436: if (strchr(quotable, *s))
1437: Buf_AddChar(&buf, '\\');
1438: Buf_AddChar(&buf, *s);
1439: }
1440: Buf_AddSpace(&buf);
1441: }
1442: Var_Append(name, Buf_Retrieve(&buf), VAR_GLOBAL);
1443: Buf_Destroy(&buf);
1444: }