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