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