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