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