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