/***********************************************************************
* *
* This software is part of the ast package *
* Copyright (c) 1984-2012 AT&T Intellectual Property *
* and is licensed under the *
* Eclipse Public License, Version 1.0 *
* by AT&T Intellectual Property *
* *
* A copy of the License is available at *
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
* *
* Information and Software Systems Research *
* AT&T Research *
* Florham Park NJ *
* *
* Glenn Fowler <gsf@research.att.com> *
* *
***********************************************************************/
#pragma prototyped
/*
* Glenn Fowler
* AT&T Research
*
* make variable routines
*/
#include "make.h"
#include "options.h"
/*
* generator for genprereqs()
* sp!=0 is the first pass that sets M_generate
* sp==0 is the second pass that clears M_generate
*/
static int
{
register int i;
register List_t* p;
register Rule_t* x;
Rule_t* y;
Rule_t* z;
List_t t;
i = 0;
top = -1;
else
top = 1;
if (top)
{
}
{
t.next = 0;
prereqs[i++] = &t;
}
while (--i >= 0)
{
x = p->rule;
do
{
z = 0;
break;
if (x->mark & M_generate)
{
if (!sp)
{
x->mark &= ~M_generate;
if (top >= 0)
}
}
else if (sp && (all || ((x->property & P_state) || x->scan || (y = staterule(PREREQS, x, NiL, 0)) && y->scan || !r->scan) && !(x->property & (P_use|P_virtual)) && (!(x->property & P_ignore) || (x->property & P_parameter)) && (!(x->property & P_dontcare) || x->time)))
{
x->mark |= M_generate;
{
if (sep)
else
sep = 1;
sfputr(sp, (op & VAL_UNBOUND) ? unbound(x) : state.localview ? localview(x) : ((x->dynamic & D_alias) ? x->uname : x->name), -1);
}
if (top >= 0)
}
} while (x = z);
}
return sep;
}
/*
* generate the list of source|explicit prerequisites in sp
* if sep!=0 then ' ' separation needed
* new value of sep is returned
*/
static int
{
return sep;
}
/*
* return the value of a variable given its name
* the internal automatic variables are (lazily) expanded here
* op: VAL_PRIMARY|VAL_AUXILIARY|VAL_UNBOUND
*/
char*
{
register List_t* p;
register Rule_t* r;
Rule_t* x;
Rule_t* z;
Var_t* v;
Var_t* a;
char* t;
char* o;
char* val;
char* next;
int c;
int n;
int var;
int tokens;
int pop;
int sep;
Time_t e;
char** ap;
if (!*s)
return null;
else if (isstatevar(s))
{
if (!(r = getrule(s)))
return null;
}
{
sep = 0;
/*
* some internal vars have no associated rule
*/
switch (var = *s)
{
#if __OBSOLETE__ < 20100101
case '+': /* 20051122 restore for backwards compatibility -- shoulda thunk it */
#if __OBSOLETE__ > 20070101
#endif
s--;
/*FALLTHROUGH*/
#endif
case '-': /* option settings suitable for command line */
/*
* -name option value if set
* --name option name and value for subsequent set
* -+name option value
* - non-default settings
* -+ non-default internal settings
* -- all settings
* -? := default settings
* -[^:alnum:] defined by genop()/listops()
*/
if (c = *++s)
{
if (isalnum(c))
c = 0;
else
s++;
}
if (*s)
{
}
if (state.mam.statix && (state.never || state.frame->target && !(state.frame->target->property & P_always)))
return "${NMAKEFLAGS}";
if (c == '-')
case '=': /* command line script args and export vars */
{
if (sep)
else
sep = 1;
}
{
if (sep)
else
sep = 1;
}
{
if (sep)
else
sep = 1;
}
}
next = 0;
tokens = 0;
for (;;)
{
while (*s == ' ')
s++;
if (!*s)
{
if (tokens)
goto done;
}
else
{
{
*next = 0;
if (!tokens++)
}
if (*s == MARK_CONTEXT)
{
if (!(t = next))
t = s + strlen(s);
if (*--t == MARK_CONTEXT)
{
*t = 0;
s++;
}
else
t = 0;
}
else
t = 0;
if (!(r = getrule(s)))
switch (var)
{
case '!':
case '&':
case '?':
r = makerule(s);
break;
}
if (t)
*t = MARK_CONTEXT;
if (!r)
goto done;
s = r->name;
r = source(r);
}
for (n = pop; n > 0; n--)
{
if (!r->active)
goto done;
}
switch (c = var)
{
case '#': /* local arg count */
val = 0;
argcount();
break;
case ';': /* target data */
if (r->property & P_statevar)
r = bind(r);
break;
case '<': /* target name */
{
break;
}
c = '~';
/*FALLTHROUGH*/
case '>': /* updated target file prerequisites */
case '*': /* all target file prerequisites */
case '~': /* all target prerequisites */
n = 0;
{
x = makerule(t);
if (c == '>')
{
val = t;
break;
}
n = 1;
}
else
{
x = 0;
n = 0;
}
val = 0;
e = (c == '>' && !(state.questionable & 0x01000000) && (z = staterule(RULE, r, NiL, -1))) ? z->time : r->time;
{
if (p->rule != x && (c == '~' && (!(op & VAL_FILE) || !notfile(p->rule) || (op & VAL_BRACE) && (*p->rule->name == '{' || *p->rule->name == '}') && !*(p->rule->name + 1)) || !notfile(p->rule) &&
(!(r->property & P_archive) && (p->rule->time >= state.start || p->rule->time > e || !(z = staterule(RULE, p->rule, NiL, -1)) || !z->time || !(state.questionable & 0x01000000) && z->time > e) ||
{
if (n)
else
{
if (!p->next)
{
val = t;
break;
}
else
n = 1;
if (sep)
else
sep = 1;
}
}
}
break;
case '@': /* target action */
if (r->action)
break;
case '%': /* target stem or functional args */
{
val = t + 1;
}
else
break;
case '!': /* explicit and generated file prerequisites */
case '&': /* explicit and generated state prerequisites */
case '?': /* all explicit and generated prerequisites */
val = 0;
break;
case '^': /* original bound name */
if (!r->active)
break;
{
break;
}
{
if (sep)
else
sep = 1;
}
val = 0;
break;
default:
#if DEBUG
#endif
return null;
}
done:
if (tokens)
{
{
if (sep)
else
sep = 1;
}
if (!next)
{
}
*next++ = ' ';
s = next;
}
else if (val)
return val;
else
}
}
{
if (v)
{
t = 0;
r = 0;
}
else
{
/*
* functional var with args
*/
*t = 0;
{
if (!r || !(r->property & P_functional))
{
*t++ = ' ';
return null;
}
v->property |= V_functional;
else
}
*t++ = ' ';
}
if (v->builtin)
{
if (t)
{
for (;;)
{
while (isspace(*t))
t++;
if (!*t)
break;
*ap++ = t;
break;
while (*t && !isspace(*t))
t++;
if (*t == '"' || *t == '\'')
{
o = t;
n = *t++;
while (*t && (n || !isspace(*t)))
{
if (*t == n)
n = 0;
else if (!n && (*t == '"' || *t == '\''))
n = *t;
else
*o++ = *t;
t++;
}
*o = 0;
}
if (!*t)
break;
*t++ = 0;
}
}
*ap = 0;
}
if (r)
{
v->property &= ~V_compiled;
}
{
}
if ((v->property & V_auxiliary) && (op & VAL_AUXILIARY) && (a = auxiliary(v->name, 0)) && *a->value)
{
if (!*t)
return a->value;
}
return t;
}
return null;
}
/*
* reset variable p value to v
* append!=0 if v is from append
*/
static void
{
register int n;
n = strlen(v);
{
if (append)
n = (n + 1023) & ~1023;
if (n < MINVALUE)
n = MINVALUE;
{
p->value = 0;
}
p->length = n;
}
}
/*
* set the value of a variable
*/
{
register char* t;
register Var_t* p;
register int n;
int isid;
int undefined;
if (!v)
v = null;
/*
* the name determines the variable type
*/
if (n & NAME_statevar)
{
return 0;
}
if (!(isid = !!(n & NAME_identifier)) && !(n & (NAME_variable|NAME_intvar)) && !istype(*s, C_VARIABLE1|C_ID1|C_ID2) && *s != '(')
{
return 0;
}
/*
* check for a previous definition
*/
{
newvar(p);
{
p->value = 0;
}
else if (p->value)
*p->value = 0;
p->builtin = 0;
}
/*
* check the variable attributes for precedence
*/
if (flags & V_auxiliary)
{
if (!p->value)
{
}
p->property |= V_auxiliary;
p = auxiliary(s, 1);
}
if (state.user || state.readonly || undefined || !(p->property & V_readonly) && (!state.pushed && !(p->property & V_import) || state.global != 1 || (flags & V_import) || state.base && !state.init))
{
{
{
}
p->value = v;
}
else
{
t = v;
{
{
if (*v)
{
}
else
t = p->value;
}
}
resetvar(p, t, n);
}
else
{
p->property |= V_readonly;
}
p->property |= V_compiled;
else
p->property &= ~V_compiled;
{
{
}
else
}
}
{
if (p->property & V_readonly)
{
/*
* save old value for makefile compiler
*/
t = v;
{
if (s && *s)
{
if (*v)
{
}
else
t = s;
}
}
p->property |= V_oldvalue;
{
}
}
{
}
}
if (!p->value)
{
}
return p;
}
/*
* translate ':' in s's expanded value to del in sp for list generators
* 0 returned if s empty
*/
char*
{
register char* p;
Var_t* v;
if (exp)
{
if (!(v = getvar(s)))
return 0;
s = v->value;
}
if (!*(s = p))
return 0;
for (;;)
switch (*p++)
{
case ':':
if (*(p - 1) = del)
break;
/*FALLTHROUGH*/
case 0:
return s;
}
}
/*
* copy variable reference into sp
*/
void
{
register char* s;
register int c;
char* prefix;
char* t;
Var_t* x;
{
if (*(s = value))
{
{
/*
* this quoting allows simple parameterization
*/
while (c = *s++)
{
switch (c)
{
case '$':
{
c = *t;
*t = 0;
x = getvar(s);
*t = c;
c = '$';
if (x)
break;
}
else if (*s == '{')
break;
/*FALLTHROUGH*/
case '\\':
case '"':
case '`':
break;
}
}
}
}
}
if (sp)
}
/*
* read the environment and set internal variables with setvar()
* complicated by those who pollute the environment
*/
void
readenv(void)
{
register char** e;
register char* t;
for (e = environ; t = *e; e++)
{
if (*t++ == '=')
else
}
}