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