Annotation of src/usr.bin/make/var.c, Revision 1.69
1.53 espie 1: /* $OpenPackages$ */
1.65 espie 2: /* $OpenBSD: var.c,v 1.64 2007/07/08 17:53:15 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.62 espie 6: * Copyright (c) 1999,2000,2007 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 <assert.h>
66: #include <stddef.h>
67: #include <stdio.h>
1.60 espie 68: #include <stdint.h>
1.55 espie 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"
1.62 espie 77: #include "pathnames.h"
1.55 espie 78: #include "varmodifiers.h"
79: #include "var.h"
80: #include "varname.h"
81: #include "error.h"
82: #include "str.h"
83: #include "var_int.h"
84: #include "memory.h"
85: #include "symtable.h"
86: #include "gnode.h"
87:
1.1 deraadt 88: /*
89: * This is a harmless return value for Var_Parse that can be used by Var_Subst
90: * to determine if there was an error in parsing -- easier than returning
91: * a flag, as things outside this module don't give a hoot.
92: */
1.53 espie 93: char var_Error[] = "";
1.1 deraadt 94:
95: /*
96: * Similar to var_Error, but returned when the 'err' flag for Var_Parse is
97: * set false. Why not just use a constant? Well, gcc likes to condense
98: * identical string instances...
99: */
100: static char varNoError[] = "";
1.66 espie 101: bool errorIsOkay;
102: static bool checkEnvFirst; /* true if environment should be searched for
103: * variables before the global context */
1.62 espie 104:
105: void
106: Var_setCheckEnvFirst(bool yes)
107: {
108: checkEnvFirst = yes;
109: }
1.1 deraadt 110:
111: /*
1.66 espie 112: * The rules for variable look-up are complicated.
113: *
114: * - Dynamic variables like $@ and $* are special. They always pertain to
115: * a given variable. In this implementation of make, it is an error to
116: * try to affect them manually. They are stored in a local symtable directly
117: * inside the gnode.
118: *
119: * Global variables can be obtained:
120: * - from the command line
121: * - from the environment
122: * - from the Makefile proper.
123: * All of these are stored in a hash global_variables.
124: *
125: * Variables set on the command line override Makefile contents, are
126: * passed to submakes (see Var_AddCmdLine), and are also exported to the
127: * environment.
128: *
129: * Without -e (!checkEnvFirst), make will see variables set in the
130: * Makefile, and default to the environment otherwise.
131: *
132: * With -e (checkEnvFirst), make will see the environment first, and that
133: * will override anything that's set in the Makefile (but not set on
134: * the command line).
135: *
136: * The SHELL variable is very special: it is never obtained from the
137: * environment, and never passed to the environment.
1.1 deraadt 138: */
1.53 espie 139:
1.66 espie 140: /* definitions pertaining to dynamic variables */
141:
142: /* full names of dynamic variables */
1.53 espie 143: static char *varnames[] = {
1.66 espie 144: TARGET,
145: PREFIX,
146: ARCHIVE,
147: MEMBER,
148: OODATE,
149: ALLSRC,
150: IMPSRC,
151: FTARGET,
152: DTARGET,
153: FPREFIX,
154: DPREFIX,
155: FARCHIVE,
156: DARCHIVE,
157: FMEMBER,
158: DMEMBER
159: };
1.53 espie 160:
1.66 espie 161: /* hashed names of dynamic variables */
1.65 espie 162: #include "varhashconsts.h"
163:
164: /* extended indices for System V stuff */
165: #define FTARGET_INDEX 7
166: #define DTARGET_INDEX 8
167: #define FPREFIX_INDEX 9
168: #define DPREFIX_INDEX 10
169: #define FARCHIVE_INDEX 11
170: #define DARCHIVE_INDEX 12
171: #define FMEMBER_INDEX 13
172: #define DMEMBER_INDEX 14
173:
1.66 espie 174: #define GLOBAL_INDEX -1
175:
1.65 espie 176: #define EXTENDED2SIMPLE(i) (((i)-LOCAL_SIZE)/2)
177: #define IS_EXTENDED_F(i) ((i)%2 == 1)
178:
1.66 espie 179:
1.65 espie 180: static struct ohash global_variables;
1.1 deraadt 181:
1.66 espie 182:
1.37 espie 183: typedef struct Var_ {
1.66 espie 184: BUFFER val; /* the variable value */
185: unsigned int flags; /* miscellaneous status flags */
1.62 espie 186: #define VAR_IN_USE 1 /* Variable's value currently being used. */
1.66 espie 187: /* (Used to avoid recursion) */
188: #define VAR_DUMMY 2 /* Variable is currently just a name */
189: /* In particular: BUFFER is invalid */
190: #define VAR_FROM_CMD 4 /* Special source: command line */
191: #define VAR_FROM_ENV 8 /* Special source: environment */
192: #define VAR_SEEN_ENV 16 /* No need to go look up environment again */
193: #define VAR_SHELL 32 /* Magic behavior */
194:
1.62 espie 195: #define POISONS (POISON_NORMAL | POISON_EMPTY | POISON_NOT_DEFINED)
1.66 espie 196: /* Defined in var.h */
197: char name[1]; /* the variable's name */
1.1 deraadt 198: } Var;
199:
1.53 espie 200:
201: static struct ohash_info var_info = {
202: offsetof(Var, name),
1.66 espie 203: NULL,
204: hash_alloc, hash_free, element_alloc
205: };
206:
207: static int classify_var(const char *, const char **, uint32_t *);
208: static Var *find_any_var(const char *, const char *, SymTable *, int, uint32_t);
1.62 espie 209: static Var *find_global_var(const char *, const char *, uint32_t);
1.66 espie 210: static Var *find_global_var_without_env(const char *, const char *, uint32_t);
1.62 espie 211: static void fill_from_env(Var *);
1.53 espie 212: static Var *create_var(const char *, const char *);
1.66 espie 213: static void var_set_initial_value(Var *, const char *);
214: static void var_set_value(Var *, const char *);
215: #define var_get_value(v) Buf_Retrieve(&((v)->val))
216: static void var_append_value(Var *, const char *);
217: static void poison_check(Var *);
1.62 espie 218: static void varq_set_append(int, const char *, GNode *, bool);
219: static void var_set_append(const char *, const char *, const char *, int, bool);
220: static void set_magic_shell_variable(void);
1.66 espie 221:
222: static void delete_var(Var *);
223: static void print_var(Var *);
224:
225:
1.53 espie 226: static const char *find_rparen(const char *);
227: static const char *find_ket(const char *);
228: typedef const char * (*find_t)(const char *);
229: static find_t find_pos(int);
1.69 ! espie 230: static void push_used(Var *);
! 231: static void pop_used(Var *);
! 232: static char *get_expanded_value(Var *, int, SymTable *, bool, bool *);
1.53 espie 233:
1.66 espie 234:
235:
236: /* Variable lookup function: return idx for dynamic variable, or
237: * GLOBAL_INDEX if name is not dynamic. Set up *pk for further use.
238: */
1.38 espie 239: static int
1.66 espie 240: classify_var(const char *name, const char **enamePtr, uint32_t *pk)
1.38 espie 241: {
1.66 espie 242: size_t len;
1.38 espie 243:
1.66 espie 244: *pk = ohash_interval(name, enamePtr);
245: len = *enamePtr - name;
246: /* substitute short version for long local name */
247: switch (*pk % MAGICSLOTS1) { /* MAGICSLOTS should be the */
248: case K_LONGALLSRC % MAGICSLOTS1:/* smallest constant yielding */
249: /* distinct case values */
250: if (*pk == K_LONGALLSRC && len == strlen(LONGALLSRC) &&
251: strncmp(name, LONGALLSRC, len) == 0)
252: return ALLSRC_INDEX;
253: break;
254: case K_LONGARCHIVE % MAGICSLOTS1:
255: if (*pk == K_LONGARCHIVE && len == strlen(LONGARCHIVE) &&
256: strncmp(name, LONGARCHIVE, len) == 0)
257: return ARCHIVE_INDEX;
258: break;
259: case K_LONGIMPSRC % MAGICSLOTS1:
260: if (*pk == K_LONGIMPSRC && len == strlen(LONGIMPSRC) &&
261: strncmp(name, LONGIMPSRC, len) == 0)
262: return IMPSRC_INDEX;
263: break;
264: case K_LONGMEMBER % MAGICSLOTS1:
265: if (*pk == K_LONGMEMBER && len == strlen(LONGMEMBER) &&
266: strncmp(name, LONGMEMBER, len) == 0)
267: return MEMBER_INDEX;
268: break;
269: case K_LONGOODATE % MAGICSLOTS1:
270: if (*pk == K_LONGOODATE && len == strlen(LONGOODATE) &&
271: strncmp(name, LONGOODATE, len) == 0)
272: return OODATE_INDEX;
273: break;
274: case K_LONGPREFIX % MAGICSLOTS1:
275: if (*pk == K_LONGPREFIX && len == strlen(LONGPREFIX) &&
276: strncmp(name, LONGPREFIX, len) == 0)
277: return PREFIX_INDEX;
278: break;
279: case K_LONGTARGET % MAGICSLOTS1:
280: if (*pk == K_LONGTARGET && len == strlen(LONGTARGET) &&
281: strncmp(name, LONGTARGET, len) == 0)
282: return TARGET_INDEX;
283: break;
284: case K_TARGET % MAGICSLOTS1:
285: if (name[0] == TARGET[0] && len == 1)
286: return TARGET_INDEX;
287: break;
288: case K_OODATE % MAGICSLOTS1:
289: if (name[0] == OODATE[0] && len == 1)
290: return OODATE_INDEX;
291: break;
292: case K_ALLSRC % MAGICSLOTS1:
293: if (name[0] == ALLSRC[0] && len == 1)
294: return ALLSRC_INDEX;
295: break;
296: case K_IMPSRC % MAGICSLOTS1:
297: if (name[0] == IMPSRC[0] && len == 1)
298: return IMPSRC_INDEX;
299: break;
300: case K_PREFIX % MAGICSLOTS1:
301: if (name[0] == PREFIX[0] && len == 1)
302: return PREFIX_INDEX;
303: break;
304: case K_ARCHIVE % MAGICSLOTS1:
305: if (name[0] == ARCHIVE[0] && len == 1)
306: return ARCHIVE_INDEX;
307: break;
308: case K_MEMBER % MAGICSLOTS1:
309: if (name[0] == MEMBER[0] && len == 1)
310: return MEMBER_INDEX;
311: break;
312: case K_FTARGET % MAGICSLOTS1:
313: if (name[0] == FTARGET[0] && name[1] == FTARGET[1] && len == 2)
314: return FTARGET_INDEX;
315: break;
316: case K_DTARGET % MAGICSLOTS1:
317: if (name[0] == DTARGET[0] && name[1] == DTARGET[1] && len == 2)
318: return DTARGET_INDEX;
319: break;
320: case K_FPREFIX % MAGICSLOTS1:
321: if (name[0] == FPREFIX[0] && name[1] == FPREFIX[1] && len == 2)
322: return FPREFIX_INDEX;
323: break;
324: case K_DPREFIX % MAGICSLOTS1:
325: if (name[0] == DPREFIX[0] && name[1] == DPREFIX[1] && len == 2)
326: return DPREFIX_INDEX;
327: break;
328: case K_FARCHIVE % MAGICSLOTS1:
329: if (name[0] == FARCHIVE[0] && name[1] == FARCHIVE[1] &&
330: len == 2)
331: return FARCHIVE_INDEX;
332: break;
333: case K_DARCHIVE % MAGICSLOTS1:
334: if (name[0] == DARCHIVE[0] && name[1] == DARCHIVE[1] &&
335: len == 2)
336: return DARCHIVE_INDEX;
337: break;
338: case K_FMEMBER % MAGICSLOTS1:
339: if (name[0] == FMEMBER[0] && name[1] == FMEMBER[1] && len == 2)
340: return FMEMBER_INDEX;
341: break;
342: case K_DMEMBER % MAGICSLOTS1:
343: if (name[0] == DMEMBER[0] && name[1] == DMEMBER[1] && len == 2)
344: return DMEMBER_INDEX;
345: break;
346: default:
347: break;
348: }
349: return GLOBAL_INDEX;
1.38 espie 350: }
1.37 espie 351:
1.66 espie 352:
353: /***
354: *** Internal handling of variables.
355: ***/
356:
357:
358: /* Create a new variable, does not initialize anything except the name.
359: * in particular, buffer is invalid, and flag value is invalid. Accordingly,
360: * must either:
361: * - set flags to VAR_DUMMY
362: * - set flags to !VAR_DUMMY, and initialize buffer, for instance with
363: * var_set_initial_value().
364: */
1.65 espie 365: static Var *
366: create_var(const char *name, const char *ename)
367: {
1.66 espie 368: return ohash_create_entry(&var_info, name, &ename);
1.65 espie 369: }
370:
1.66 espie 371: /* Initial version of var_set_value(), to be called after create_var().
372: */
1.65 espie 373: static void
1.66 espie 374: var_set_initial_value(Var *v, const char *val)
1.65 espie 375: {
1.66 espie 376: size_t len;
1.65 espie 377:
1.66 espie 378: len = strlen(val);
379: Buf_Init(&(v->val), len+1);
380: Buf_AddChars(&(v->val), len, val);
1.65 espie 381: }
382:
1.66 espie 383: /* Normal version of var_set_value(), to be called after variable is fully
384: * initialized.
385: */
1.65 espie 386: static void
1.66 espie 387: var_set_value(Var *v, const char *val)
1.65 espie 388: {
1.66 espie 389: if ((v->flags & VAR_DUMMY) == 0) {
390: Buf_Reset(&(v->val));
391: Buf_AddString(&(v->val), val);
392: } else {
393: var_set_initial_value(v, val);
394: v->flags &= ~VAR_DUMMY;
395: }
1.65 espie 396: }
397:
1.66 espie 398: /* Add to a variable, insert a separating space if the variable was already
399: * defined.
400: */
1.65 espie 401: static void
1.66 espie 402: var_append_value(Var *v, const char *val)
1.65 espie 403: {
1.66 espie 404: if ((v->flags & VAR_DUMMY) == 0) {
405: Buf_AddSpace(&(v->val));
406: Buf_AddString(&(v->val), val);
407: } else {
408: var_set_initial_value(v, val);
409: v->flags &= ~VAR_DUMMY;
410: }
411: }
412:
413:
414: /* Delete a variable and all the space associated with it.
1.65 espie 415: */
416: static void
1.66 espie 417: delete_var(Var *v)
1.65 espie 418: {
1.66 espie 419: if ((v->flags & VAR_DUMMY) == 0)
420: Buf_Destroy(&(v->val));
421: free(v);
1.65 espie 422: }
423:
424:
425:
1.66 espie 426:
427: /***
428: *** Dynamic variable handling.
429: ***/
430:
431:
432:
433: /* create empty symtable.
434: * XXX: to save space, dynamic variables may be NULL pointers.
435: */
1.65 espie 436: void
437: SymTable_Init(SymTable *ctxt)
438: {
1.66 espie 439: static SymTable sym_template;
440: memcpy(ctxt, &sym_template, sizeof(*ctxt));
1.65 espie 441: }
442:
1.66 espie 443: /* free symtable.
444: */
1.65 espie 445: #ifdef CLEANUP
446: void
447: SymTable_Destroy(SymTable *ctxt)
448: {
1.66 espie 449: int i;
1.65 espie 450:
1.66 espie 451: for (i = 0; i < LOCAL_SIZE; i++)
452: if (ctxt->locals[i] != NULL)
453: delete_var(ctxt->locals[i]);
1.65 espie 454: }
455: #endif
456:
1.66 espie 457: /* set or append to dynamic variable.
458: */
1.62 espie 459: static void
460: varq_set_append(int idx, const char *val, GNode *gn, bool append)
1.37 espie 461: {
1.66 espie 462: Var *v = gn->context.locals[idx];
1.37 espie 463:
1.66 espie 464: if (v == NULL) {
465: v = create_var(varnames[idx], NULL);
1.62 espie 466: #ifdef STATS_VAR_LOOKUP
1.66 espie 467: STAT_VAR_CREATION++;
1.62 espie 468: #endif
1.66 espie 469: if (val != NULL)
470: var_set_initial_value(v, val);
471: else
472: Buf_Init(&(v->val), 1);
473: v->flags = 0;
474: gn->context.locals[idx] = v;
475: } else {
476: if (append)
477: Buf_AddSpace(&(v->val));
478: else
479: Buf_Reset(&(v->val));
480: Buf_AddString(&(v->val), val);
481: }
482: if (DEBUG(VAR))
483: printf("%s:%s = %s\n", gn->name, varnames[idx],
484: var_get_value(v));
1.62 espie 485: }
486:
487: void
488: Varq_Set(int idx, const char *val, GNode *gn)
489: {
1.66 espie 490: varq_set_append(idx, val, gn, false);
1.37 espie 491: }
492:
1.53 espie 493: void
1.59 espie 494: Varq_Append(int idx, const char *val, GNode *gn)
1.37 espie 495: {
1.66 espie 496: varq_set_append(idx, val, gn, true);
1.37 espie 497: }
498:
499: char *
1.59 espie 500: Varq_Value(int idx, GNode *gn)
1.37 espie 501: {
1.66 espie 502: Var *v = gn->context.locals[idx];
1.37 espie 503:
1.66 espie 504: if (v == NULL)
505: return NULL;
506: else
507: return var_get_value(v);
1.53 espie 508: }
509:
1.66 espie 510: /***
511: *** Global variable handling.
512: ***/
513:
514: /* Create a new global var if necessary, and set it up correctly.
515: * Do not take environment into account.
516: */
1.53 espie 517: static Var *
1.66 espie 518: find_global_var_without_env(const char *name, const char *ename, uint32_t k)
1.37 espie 519: {
1.65 espie 520: unsigned int slot;
521: Var *v;
1.1 deraadt 522:
1.65 espie 523: slot = ohash_lookup_interval(&global_variables, name, ename, k);
524: v = ohash_find(&global_variables, slot);
525: if (v == NULL) {
526: v = create_var(name, ename);
527: v->flags = VAR_DUMMY;
528: ohash_insert(&global_variables, slot, v);
529: }
530: return v;
1.35 espie 531: }
1.53 espie 532:
1.66 espie 533: /* Helper for find_global_var(): grab environment value if needed.
534: */
1.62 espie 535: static void
536: fill_from_env(Var *v)
1.37 espie 537: {
1.66 espie 538: char *env;
1.37 espie 539:
1.66 espie 540: env = getenv(v->name);
541: if (env == NULL)
542: v->flags |= VAR_SEEN_ENV;
543: else {
544: var_set_value(v, env);
545: v->flags |= VAR_FROM_ENV | VAR_SEEN_ENV;
546: }
1.37 espie 547:
1.53 espie 548: #ifdef STATS_VAR_LOOKUP
1.66 espie 549: STAT_VAR_FROM_ENV++;
1.53 espie 550: #endif
1.62 espie 551: }
1.37 espie 552:
1.66 espie 553: /* Find global var, and obtain its value from the environment if needed.
554: */
1.62 espie 555: static Var *
1.65 espie 556: find_global_var(const char *name, const char *ename, uint32_t k)
557: {
1.66 espie 558: Var *v;
1.65 espie 559:
1.66 espie 560: v = find_global_var_without_env(name, ename, k);
1.65 espie 561:
1.66 espie 562: if ((v->flags & VAR_SEEN_ENV) == 0 &&
563: (checkEnvFirst && (v->flags & VAR_FROM_CMD) == 0 ||
564: (v->flags & VAR_DUMMY) != 0))
565: fill_from_env(v);
1.65 espie 566:
1.66 espie 567: return v;
1.65 espie 568: }
569:
1.66 espie 570: /* mark variable as poisoned, in a given setup.
571: */
1.65 espie 572: void
573: Var_MarkPoisoned(const char *name, const char *ename, unsigned int type)
1.62 espie 574: {
1.65 espie 575: Var *v;
576: uint32_t k;
577: int idx;
1.66 espie 578: idx = classify_var(name, &ename, &k);
1.65 espie 579:
1.66 espie 580: if (idx != GLOBAL_INDEX) {
581: Parse_Error(PARSE_FATAL,
1.65 espie 582: "Trying to poison dynamic variable $%s",
583: varnames[idx]);
584: return;
585: }
1.62 espie 586:
1.65 espie 587: v = find_global_var(name, ename, k);
588: v->flags |= type;
1.66 espie 589: /* POISON_NORMAL is not lazy: if the variable already exists in
590: * the Makefile, then it's a mistake.
591: */
1.65 espie 592: if (v->flags & POISON_NORMAL) {
593: if (v->flags & VAR_DUMMY)
594: return;
595: if (v->flags & VAR_FROM_ENV)
596: return;
597: Parse_Error(PARSE_FATAL,
598: "Poisoned variable %s is already set\n", v->name);
1.62 espie 599: }
1.37 espie 600: }
601:
1.66 espie 602: /* Check if there's any reason not to use the variable in this context.
603: */
1.62 espie 604: static void
605: poison_check(Var *v)
1.1 deraadt 606: {
1.62 espie 607: if (v->flags & POISON_NORMAL) {
1.66 espie 608: Parse_Error(PARSE_FATAL,
1.62 espie 609: "Poisoned variable %s has been referenced\n", v->name);
610: return;
611: }
612: if (v->flags & VAR_DUMMY) {
613: Parse_Error(PARSE_FATAL,
614: "Poisoned variable %s is not defined\n", v->name);
615: return;
616: }
617: if (v->flags & POISON_EMPTY)
1.66 espie 618: if (strcmp(var_get_value(v), "") == 0)
619: Parse_Error(PARSE_FATAL,
1.62 espie 620: "Poisoned variable %s is empty\n", v->name);
1.37 espie 621: }
622:
1.66 espie 623: /* Delete global variable.
624: */
1.1 deraadt 625: void
1.66 espie 626: Var_Deletei(const char *name, const char *ename)
1.1 deraadt 627: {
1.66 espie 628: Var *v;
629: uint32_t k;
1.62 espie 630: unsigned int slot;
1.66 espie 631: int idx;
1.62 espie 632:
1.66 espie 633: idx = classify_var(name, &ename, &k);
634: if (idx != GLOBAL_INDEX) {
635: Parse_Error(PARSE_FATAL,
636: "Trying to delete dynamic variable $%s", varnames[idx]);
637: return;
638: }
1.62 espie 639: slot = ohash_lookup_interval(&global_variables, name, ename, k);
640: v = ohash_find(&global_variables, slot);
641:
642: if (v == NULL)
643: return;
1.66 espie 644:
1.62 espie 645: if (checkEnvFirst && (v->flags & VAR_FROM_ENV))
646: return;
1.1 deraadt 647:
1.62 espie 648: if (v->flags & VAR_FROM_CMD)
649: return;
1.37 espie 650:
1.62 espie 651: ohash_remove(&global_variables, slot);
1.66 espie 652: delete_var(v);
1.1 deraadt 653: }
654:
1.66 espie 655: /* Set or add a global variable, in VAR_CMD or VAR_GLOBAL context.
656: */
1.62 espie 657: static void
658: var_set_append(const char *name, const char *ename, const char *val, int ctxt,
659: bool append)
1.1 deraadt 660: {
1.66 espie 661: Var *v;
662: uint32_t k;
663: int idx;
1.53 espie 664:
1.66 espie 665: idx = classify_var(name, &ename, &k);
666: if (idx != GLOBAL_INDEX) {
1.62 espie 667: Parse_Error(PARSE_FATAL, "Trying to %s dynamic variable $%s",
668: append ? "append to" : "set", varnames[idx]);
669: return;
670: }
1.53 espie 671:
1.62 espie 672: v = find_global_var(name, ename, k);
673: if (v->flags & POISON_NORMAL)
674: Parse_Error(PARSE_FATAL, "Trying to %s poisoned variable %s\n",
675: append ? "append to" : "set", v->name);
676: /* so can we write to it ? */
1.66 espie 677: if (ctxt == VAR_CMD) { /* always for command line */
678: (append ? var_append_value : var_set_value)(v, val);
1.62 espie 679: v->flags |= VAR_FROM_CMD;
680: if ((v->flags & VAR_SHELL) == 0) {
1.66 espie 681: /* Any variables given on the command line are
1.62 espie 682: * automatically exported to the environment,
1.66 espie 683: * except for SHELL (as per POSIX standard).
1.62 espie 684: */
685: esetenv(v->name, val);
1.66 espie 686: }
1.62 espie 687: if (DEBUG(VAR))
1.66 espie 688: printf("command:%s = %s\n", v->name, var_get_value(v));
1.62 espie 689: } else if ((v->flags & VAR_FROM_CMD) == 0 &&
690: (!checkEnvFirst || (v->flags & VAR_FROM_ENV) == 0)) {
1.66 espie 691: (append ? var_append_value : var_set_value)(v, val);
1.62 espie 692: if (DEBUG(VAR))
1.66 espie 693: printf("global:%s = %s\n", v->name, var_get_value(v));
1.62 espie 694: } else if (DEBUG(VAR))
1.66 espie 695: printf("overriden:%s = %s\n", v->name, var_get_value(v));
1.1 deraadt 696: }
697:
698: void
1.62 espie 699: Var_Seti(const char *name, const char *ename, const char *val, int ctxt)
1.1 deraadt 700: {
1.62 espie 701: var_set_append(name, ename, val, ctxt, false);
702: }
1.53 espie 703:
1.62 espie 704: void
705: Var_Appendi(const char *name, const char *ename, const char *val, int ctxt)
706: {
707: var_set_append(name, ename, val, ctxt, true);
708: }
1.53 espie 709:
1.66 espie 710: /* XXX different semantics for Var_Valuei() and Var_Definedi():
711: * references to poisoned value variables will error out in Var_Valuei(),
712: * but not in Var_Definedi(), so the following construct works:
713: * .poison BINDIR
714: * BINDIR ?= /usr/bin
715: */
1.53 espie 716: char *
1.59 espie 717: Var_Valuei(const char *name, const char *ename)
1.53 espie 718: {
1.66 espie 719: Var *v;
720: uint32_t k;
721: int idx;
1.62 espie 722:
1.66 espie 723: idx = classify_var(name, &ename, &k);
724: if (idx != GLOBAL_INDEX) {
725: Parse_Error(PARSE_FATAL,
726: "Trying to get value of dynamic variable $%s",
727: varnames[idx]);
728: return NULL;
1.62 espie 729: }
1.66 espie 730: v = find_global_var(name, ename, k);
731: if (v->flags & POISONS)
732: poison_check(v);
733: if ((v->flags & VAR_DUMMY) == 0)
734: return var_get_value(v);
735: else
736: return NULL;
1.53 espie 737: }
738:
1.62 espie 739: bool
740: Var_Definedi(const char *name, const char *ename)
741: {
1.66 espie 742: Var *v;
743: uint32_t k;
744: int idx;
1.62 espie 745:
1.66 espie 746: idx = classify_var(name, &ename, &k);
747: /* We don't bother writing an error message for dynamic variables,
748: * these will be caught when getting set later, usually.
749: */
750: if (idx == GLOBAL_INDEX) {
1.62 espie 751: v = find_global_var(name, ename, k);
752: if (v->flags & POISON_NORMAL)
1.66 espie 753: poison_check(v);
1.62 espie 754: if ((v->flags & VAR_DUMMY) == 0)
755: return true;
756: }
757: return false;
1.65 espie 758: }
759:
1.66 espie 760:
761: /***
762: *** Substitution functions, handling both global and dynamic variables.
763: ***/
764:
765:
766: /* XXX contrary to find_global_var(), find_any_var() can return NULL pointers.
767: */
1.65 espie 768: static Var *
1.66 espie 769: find_any_var(const char *name, const char *ename, SymTable *ctxt,
1.65 espie 770: int idx, uint32_t k)
771: {
1.66 espie 772: /* Handle local variables first */
773: if (idx != GLOBAL_INDEX) {
774: if (ctxt != NULL) {
775: if (idx < LOCAL_SIZE)
776: return ctxt->locals[idx];
777: else
778: return ctxt->locals[EXTENDED2SIMPLE(idx)];
779: } else
780: return NULL;
781: } else {
782: return find_global_var(name, ename, k);
783: }
1.62 espie 784: }
785:
1.66 espie 786: /* All the scanning functions needed to account for all the forms of
787: * variable names that exist:
788: * $A, ${AB}, $(ABC), ${A:mod}, $(A:mod)
789: */
1.53 espie 790:
791: static const char *
1.59 espie 792: find_rparen(const char *p)
1.53 espie 793: {
794: while (*p != '$' && *p != '\0' && *p != ')' && *p != ':')
795: p++;
796: return p;
797: }
1.1 deraadt 798:
1.53 espie 799: static const char *
1.59 espie 800: find_ket(const char *p)
1.53 espie 801: {
802: while (*p != '$' && *p != '\0' && *p != '}' && *p != ':')
803: p++;
804: return p;
805: }
1.1 deraadt 806:
1.66 espie 807: /* Figure out what kind of name we're looking for from a start character.
808: */
1.53 espie 809: static find_t
1.59 espie 810: find_pos(int c)
1.53 espie 811: {
812: switch(c) {
1.66 espie 813: case '(':
1.53 espie 814: return find_rparen;
1.66 espie 815: case '{':
1.53 espie 816: return find_ket;
817: default:
1.66 espie 818: Parse_Error(PARSE_FATAL,
819: "Wrong character in variable spec %c (can't happen)");
820: return find_rparen;
1.53 espie 821: }
1.1 deraadt 822: }
823:
1.68 espie 824: bool
825: Var_ParseSkip(const char **pstr, SymTable *ctxt)
1.1 deraadt 826: {
1.68 espie 827: const char *tstr;
828: Var *v;
829: char paren;
830: const char *str = *pstr;
1.66 espie 831: const char *start;
832: size_t length;
833: struct Name name;
1.68 espie 834: bool result;
1.66 espie 835:
836: v = NULL;
837: start = str;
1.53 espie 838: str++;
839:
1.66 espie 840: if (*str != '(' && *str != '{') {
841: name.tofree = false;
842: tstr = str + 1;
843: length = 2;
844: paren = '\0';
845: } else {
846: paren = *str;
847: str++;
848:
849: /* Find eventual modifiers in the variable */
850: tstr = VarName_Get(str, &name, ctxt, false, find_pos(paren));
851: VarName_Free(&name);
852: length = tstr - start;
853: if (*tstr != 0)
854: length++;
855: }
856:
1.68 espie 857: result = true;
1.66 espie 858: if (*tstr == ':' && paren != '\0')
859: if (VarModifiers_Apply(NULL, NULL, ctxt, true, NULL, tstr,
860: paren, &length) == var_Error)
1.68 espie 861: result = false;
862: *pstr += length;
863: return result;
1.1 deraadt 864: }
865:
1.55 espie 866: /* As of now, Var_ParseBuffer is just a wrapper around Var_Parse. For
867: * speed, it may be better to revisit the implementation to do things
868: * directly. */
869: bool
1.66 espie 870: Var_ParseBuffer(Buffer buf, const char *str, SymTable *ctxt, bool err,
1.59 espie 871: size_t *lengthPtr)
1.53 espie 872: {
1.66 espie 873: char *result;
874: bool freeIt;
1.45 espie 875:
1.66 espie 876: result = Var_Parse(str, ctxt, err, lengthPtr, &freeIt);
877: if (result == var_Error)
878: return false;
879:
880: Buf_AddString(buf, result);
881: if (freeIt)
882: free(result);
883: return true;
1.45 espie 884: }
885:
1.69 ! espie 886: /* Helper function for Var_Parse: still recursive, but we tag what variables
! 887: * we expand for better error messages.
! 888: */
! 889: #define MAX_DEPTH 350
! 890: static Var *call_trace[MAX_DEPTH];
! 891: static int current_depth = 0;
! 892:
! 893: static void
! 894: push_used(Var *v)
! 895: {
! 896: if (v->flags & VAR_IN_USE) {
! 897: int i;
! 898: fprintf(stderr, "Problem with variable expansion chain: ");
! 899: for (i = 0;
! 900: i < (current_depth > MAX_DEPTH ? MAX_DEPTH : current_depth);
! 901: i++)
! 902: fprintf(stderr, "%s -> ", call_trace[i]->name);
! 903: fprintf(stderr, "%s\n", v->name);
! 904: Fatal("\tVariable %s is recursive.", v->name);
! 905: /*NOTREACHED*/
! 906: }
! 907:
! 908: v->flags |= VAR_IN_USE;
! 909: if (current_depth < MAX_DEPTH)
! 910: call_trace[current_depth] = v;
! 911: current_depth++;
! 912: }
! 913:
! 914: static void
! 915: pop_used(Var *v)
! 916: {
! 917: v->flags &= ~VAR_IN_USE;
! 918: current_depth--;
! 919: }
! 920:
! 921: static char *
! 922: get_expanded_value(Var *v, int idx, SymTable *ctxt, bool err, bool *freePtr)
! 923: {
! 924: char *val;
! 925:
! 926: if (v == NULL)
! 927: return NULL;
! 928:
! 929: if ((v->flags & POISONS) != 0)
! 930: poison_check(v);
! 931: if ((v->flags & VAR_DUMMY) != 0)
! 932: return NULL;
! 933:
! 934: /* Before doing any modification, we have to make sure the
! 935: * value has been fully expanded. If it looks like recursion
! 936: * might be necessary (there's a dollar sign somewhere in
! 937: * the variable's value) we just call Var_Subst to do any
! 938: * other substitutions that are necessary. Note that the
! 939: * value returned by Var_Subst will have been dynamically
! 940: * allocated, so it will need freeing when we return.
! 941: */
! 942: val = var_get_value(v);
! 943: if (idx == GLOBAL_INDEX) {
! 944: if (strchr(val, '$') != NULL) {
! 945: push_used(v);
! 946: val = Var_Subst(val, ctxt, err);
! 947: pop_used(v);
! 948: *freePtr = true;
! 949: }
! 950: } else if (idx >= LOCAL_SIZE) {
! 951: if (IS_EXTENDED_F(idx))
! 952: val = Var_GetTail(val);
! 953: else
! 954: val = Var_GetHead(val);
! 955: *freePtr = true;
! 956: }
! 957: return val;
! 958: }
! 959:
1.1 deraadt 960: char *
1.66 espie 961: Var_Parse(const char *str, /* The string to parse */
962: SymTable *ctxt, /* The context for the variable */
963: bool err, /* true if undefined variables are an error */
964: size_t *lengthPtr, /* OUT: The length of the specification */
1.59 espie 965: bool *freePtr) /* OUT: true if caller should free result */
1.44 espie 966: {
1.66 espie 967: const char *tstr; /* Pointer into str */
968: Var *v; /* Variable in invocation */
969: char paren; /* Parenthesis or brace or nothing */
970: struct Name name;
971: const char *start;
972: char *val; /* Variable value */
973: uint32_t k;
974: int idx;
975:
976: *freePtr = false;
977: start = str++;
978:
979: val = NULL;
980: v = NULL;
981: idx = GLOBAL_INDEX;
982:
983: if (*str != '(' && *str != '{') {
984: name.s = str;
985: name.e = str+1;
986: name.tofree = false;
987: tstr = str + 1;
988: *lengthPtr = 2;
989: paren = '\0';
990: } else {
991: paren = *str;
992: str++;
993:
994: /* Find eventual modifiers in the variable */
995: tstr = VarName_Get(str, &name, ctxt, false, find_pos(paren));
996: *lengthPtr = tstr - start;
997: if (*tstr != '\0')
998: (*lengthPtr)++;
999: }
1.5 millert 1000:
1.66 espie 1001: idx = classify_var(name.s, &name.e, &k);
1002: v = find_any_var(name.s, name.e, ctxt, idx, k);
1.69 ! espie 1003: val = get_expanded_value(v, idx, ctxt, err, freePtr);
1.66 espie 1004: if (*tstr == ':' && paren != '\0')
1005: val = VarModifiers_Apply(val, &name, ctxt, err, freePtr,
1006: tstr, paren, lengthPtr);
1007: if (val == NULL) {
1008: val = err ? var_Error : varNoError;
1009: /* Dynamic source */
1010: if (idx != GLOBAL_INDEX) {
1011: /* can't be expanded for now: copy the spec instead. */
1012: if (ctxt == NULL) {
1013: *freePtr = true;
1014: val = Str_dupi(start, start+ *lengthPtr);
1015: } else {
1016: /* somehow, this should have been expanded already. */
1017: GNode *n;
1018:
1019: /* XXX */
1020: n = (GNode *)(((char *)ctxt) -
1021: offsetof(GNode, context));
1022: if (idx >= LOCAL_SIZE)
1023: idx = EXTENDED2SIMPLE(idx);
1024: switch(idx) {
1025: case IMPSRC_INDEX:
1026: Fatal(
1027: "Using $< in a non-suffix rule context is a GNUmake idiom (line %lu of %s)",
1028: n->lineno, n->fname);
1029: default:
1030: Error(
1031: "Using undefined dynamic variable $%s (line %lu of %s)",
1032: varnames[idx], n->lineno, n->fname);
1033: break;
1034: }
1035: }
1.53 espie 1036: }
1037: }
1.66 espie 1038: VarName_Free(&name);
1039: return val;
1.42 espie 1040: }
1041:
1.66 espie 1042:
1.1 deraadt 1043: char *
1.66 espie 1044: Var_Subst(const char *str, /* the string in which to substitute */
1045: SymTable *ctxt, /* the context wherein to find variables */
1.59 espie 1046: bool undefErr) /* true if undefineds are an error */
1047: {
1.66 espie 1048: BUFFER buf; /* Buffer for forming things */
1049: static bool errorReported;
1050:
1051: Buf_Init(&buf, MAKE_BSIZE);
1052: errorReported = false;
1053:
1054: for (;;) {
1055: char *val; /* Value to substitute for a variable */
1056: size_t length; /* Length of the variable invocation */
1057: bool doFree; /* Set true if val should be freed */
1058: const char *cp;
1059:
1060: /* copy uninteresting stuff */
1061: for (cp = str; *str != '\0' && *str != '$'; str++)
1062: ;
1063: Buf_Addi(&buf, cp, str);
1064: if (*str == '\0')
1065: break;
1066: if (str[1] == '$') {
1067: /* A $ may be escaped with another $. */
1068: Buf_AddChar(&buf, '$');
1069: str += 2;
1070: continue;
1071: }
1072: val = Var_Parse(str, ctxt, undefErr, &length, &doFree);
1073: /* When we come down here, val should either point to the
1074: * value of this variable, suitably modified, or be NULL.
1075: * Length should be the total length of the potential
1076: * variable invocation (from $ to end character...) */
1077: if (val == var_Error || val == varNoError) {
1078: /* If errors are not an issue, skip over the variable
1079: * and continue with the substitution. Otherwise, store
1080: * the dollar sign and advance str so we continue with
1081: * the string... */
1082: if (errorIsOkay)
1083: str += length;
1084: else if (undefErr) {
1085: /* If variable is undefined, complain and
1086: * skip the variable name. The complaint
1087: * will stop us from doing anything when
1088: * the file is parsed. */
1089: if (!errorReported)
1090: Parse_Error(PARSE_FATAL,
1091: "Undefined variable \"%.*s\"",
1092: length, str);
1093: str += length;
1094: errorReported = true;
1095: } else {
1096: Buf_AddChar(&buf, *str);
1097: str++;
1098: }
1099: } else {
1100: /* We've now got a variable structure to store in.
1101: * But first, advance the string pointer. */
1102: str += length;
1103:
1104: /* Copy all the characters from the variable value
1105: * straight into the new string. */
1106: Buf_AddString(&buf, val);
1107: if (doFree)
1108: free(val);
1109: }
1.24 espie 1110: }
1.66 espie 1111: return Buf_Retrieve(&buf);
1112: }
1113:
1114:
1115: /***
1116: *** Supplementary support for .for loops.
1117: ***/
1118:
1119:
1120:
1121: struct LoopVar
1122: {
1123: Var old; /* keep old variable value (before the loop) */
1124: Var *me; /* the variable we're dealing with */
1125: };
1126:
1127:
1128: struct LoopVar *
1129: Var_NewLoopVar(const char *name, const char *ename)
1130: {
1131: struct LoopVar *l;
1132: uint32_t k;
1133:
1134: l = emalloc(sizeof(struct LoopVar));
1135:
1136: /* we obtain a new variable quickly, make a snapshot of its old
1137: * value, and make sure the environment cannot touch us.
1138: */
1139: /* XXX: should we avoid dynamic variables ? */
1140: k = ohash_interval(name, &ename);
1141:
1142: l->me = find_global_var_without_env(name, ename, k);
1143: l->old = *(l->me);
1.67 espie 1144: l->me->flags = VAR_SEEN_ENV | VAR_DUMMY;
1.66 espie 1145: return l;
1146: }
1147:
1148: void
1149: Var_DeleteLoopVar(struct LoopVar *l)
1150: {
1.67 espie 1151: if ((l->me->flags & VAR_DUMMY) == 0)
1152: Buf_Destroy(&(l->me->val));
1.66 espie 1153: *(l->me) = l->old;
1154: free(l);
1.24 espie 1155: }
1.1 deraadt 1156:
1.53 espie 1157: void
1.66 espie 1158: Var_SubstVar(Buffer buf, /* To store result */
1159: const char *str, /* The string in which to substitute */
1160: struct LoopVar *l, /* Handle */
1.59 espie 1161: const char *val) /* Its value */
1.24 espie 1162: {
1.66 espie 1163: const char *var = l->me->name;
1.24 espie 1164:
1.66 espie 1165: var_set_value(l->me, val);
1.53 espie 1166:
1.66 espie 1167: for (;;) {
1168: const char *start;
1169: /* Copy uninteresting stuff */
1170: for (start = str; *str != '\0' && *str != '$'; str++)
1171: ;
1172: Buf_Addi(buf, start, str);
1173:
1174: start = str;
1175: if (*str++ == '\0')
1176: break;
1177: str++;
1178: /* and escaped dollars */
1179: if (start[1] == '$') {
1180: Buf_Addi(buf, start, start+2);
1181: continue;
1182: }
1183: /* Simple variable, if it's not us, copy. */
1184: if (start[1] != '(' && start[1] != '{') {
1185: if (start[1] != *var || var[1] != '\0') {
1186: Buf_AddChars(buf, 2, start);
1187: continue;
1188: }
1189: } else {
1190: const char *p;
1191: char paren = start[1];
1192:
1193:
1194: /* Find the end of the variable specification. */
1195: p = find_pos(paren)(str);
1196: /* A variable inside the variable. We don't know how to
1197: * expand the external variable at this point, so we
1198: * try again with the nested variable. */
1199: if (*p == '$') {
1200: Buf_Addi(buf, start, p);
1201: str = p;
1202: continue;
1203: }
1204:
1205: if (strncmp(var, str, p - str) != 0 ||
1206: var[p - str] != '\0') {
1207: /* Not the variable we want to expand. */
1208: Buf_Addi(buf, start, p);
1209: str = p;
1210: continue;
1211: }
1212: if (*p == ':') {
1213: size_t length; /* Length of variable name */
1214: bool doFree; /* should val be freed ? */
1215: char *newval;
1216: struct Name name;
1217:
1218: length = p - str + 1;
1219: doFree = false;
1220: name.s = var;
1221: name.e = var + (p-str);
1222:
1223: /* val won't be freed since !doFree, but
1224: * VarModifiers_Apply doesn't know that,
1225: * hence the cast. */
1226: newval = VarModifiers_Apply((char *)val, &name,
1227: NULL, false, &doFree, p, paren, &length);
1228: Buf_AddString(buf, newval);
1229: if (doFree)
1230: free(newval);
1231: str += length;
1232: continue;
1233: } else
1234: str = p+1;
1235: }
1236: Buf_AddString(buf, val);
1237: }
1238: }
1.1 deraadt 1239:
1.66 espie 1240: /***
1241: *** Odds and ends
1242: ***/
1.1 deraadt 1243:
1.62 espie 1244: static void
1245: set_magic_shell_variable()
1246: {
1.66 espie 1247: const char *name = "SHELL";
1248: const char *ename = NULL;
1249: uint32_t k;
1250: Var *v;
1251:
1252: k = ohash_interval(name, &ename);
1253: v = find_global_var_without_env(name, ename, k);
1254: var_set_value(v, _PATH_BSHELL);
1255: /* XXX the environment shall never affect it */
1256: v->flags = VAR_SHELL | VAR_SEEN_ENV;
1257: }
1258:
1259: /*
1260: * Var_Init
1.1 deraadt 1261: * Initialize the module
1262: */
1263: void
1.59 espie 1264: Var_Init(void)
1.1 deraadt 1265: {
1.66 espie 1266: ohash_init(&global_variables, 10, &var_info);
1267: set_magic_shell_variable();
1.35 espie 1268:
1.62 espie 1269:
1.66 espie 1270: errorIsOkay = true;
1271: Var_setCheckEnvFirst(false);
1.53 espie 1272:
1.66 espie 1273: VarModifiers_Init();
1.1 deraadt 1274: }
1275:
1276:
1.55 espie 1277: #ifdef CLEANUP
1.1 deraadt 1278: void
1.59 espie 1279: Var_End(void)
1.1 deraadt 1280: {
1.66 espie 1281: Var *v;
1282: unsigned int i;
1.38 espie 1283:
1.66 espie 1284: for (v = ohash_first(&global_variables, &i); v != NULL;
1285: v = ohash_next(&global_variables, &i))
1286: delete_var(v);
1.55 espie 1287: }
1.37 espie 1288: #endif
1.5 millert 1289:
1.53 espie 1290: static const char *interpret(int);
1291:
1292: static const char *
1.59 espie 1293: interpret(int f)
1.53 espie 1294: {
1.66 espie 1295: if (f & VAR_DUMMY)
1296: return "(D)";
1297: return "";
1.53 espie 1298: }
1299:
1.1 deraadt 1300:
1.31 espie 1301: static void
1.66 espie 1302: print_var(Var *v)
1.1 deraadt 1303: {
1.66 espie 1304: printf("%-16s%s = %s\n", v->name, interpret(v->flags),
1305: (v->flags & VAR_DUMMY) == 0 ? var_get_value(v) : "(none)");
1.1 deraadt 1306: }
1307:
1308: void
1.59 espie 1309: Var_Dump(void)
1.1 deraadt 1310: {
1.66 espie 1311: Var *v;
1312: unsigned int i;
1.53 espie 1313:
1.66 espie 1314: printf("#*** Global Variables:\n");
1.37 espie 1315:
1.66 espie 1316: for (v = ohash_first(&global_variables, &i); v != NULL;
1317: v = ohash_next(&global_variables, &i))
1318: print_var(v);
1.53 espie 1319: }
1.46 espie 1320:
1321: static const char *quotable = " \t\n\\'\"";
1322:
1.66 espie 1323: /* POSIX says that variable assignments passed on the command line should be
1.46 espie 1324: * propagated to sub makes through MAKEFLAGS.
1325: */
1326: void
1.59 espie 1327: Var_AddCmdline(const char *name)
1.46 espie 1328: {
1.66 espie 1329: Var *v;
1330: unsigned int i;
1331: BUFFER buf;
1332: char *s;
1333:
1334: Buf_Init(&buf, MAKE_BSIZE);
1335:
1336: for (v = ohash_first(&global_variables, &i); v != NULL;
1337: v = ohash_next(&global_variables, &i)) {
1338: /* This is not as expensive as it looks: this function is
1339: * called before parsing Makefiles, so there are just a
1340: * few non cmdling variables in there.
1341: */
1.62 espie 1342: if (!(v->flags & VAR_FROM_CMD)) {
1343: continue;
1344: }
1.46 espie 1345: /* We assume variable names don't need quoting */
1346: Buf_AddString(&buf, v->name);
1347: Buf_AddChar(&buf, '=');
1.66 espie 1348: for (s = var_get_value(v); *s != '\0'; s++) {
1.46 espie 1349: if (strchr(quotable, *s))
1350: Buf_AddChar(&buf, '\\');
1351: Buf_AddChar(&buf, *s);
1352: }
1353: Buf_AddSpace(&buf);
1.66 espie 1354: }
1355: Var_Append(name, Buf_Retrieve(&buf), VAR_GLOBAL);
1356: Buf_Destroy(&buf);
1.46 espie 1357: }