/***********************************************************************
* *
* This software is part of the ast package *
* Copyright (c) 1984-2011 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 language dependent scan support
*/
#include "make.h"
#include <tm.h>
typedef unsigned short Scanstate_t;
{
struct
{
struct
{
} Action_t;
{
};
{
} Scan_t;
/*
* default scan strategies
*/
{
".IGNORE", SCAN_IGNORE,
".NULL", SCAN_NULL,
".STATE", SCAN_STATE,
};
/*
* initialize the scan atoms
*/
void
{
register int i;
register Rule_t* r;
if (!repeat)
for (i = 0; i < elementsof(scantab); i++)
{
r->property |= P_attribute;
}
}
/*
* scan pattern sort -- strcmp(3) convention
*/
static int
scansort(register const char* a, register const char* b)
{
register const char* s;
while (*++a == *++b)
if (!*a)
return 0;
for (s = "* %@"; *s; s++)
if (*a == *s)
return 1;
else if (*b == *s)
return -1;
return *a - *b;
}
/*
* compile a branch of the expression tree
* next state pointer returned
*/
static Scanstate_t*
{
register Action_t* a;
Action_t* b;
Action_t* m;
Scanstate_t* v;
{
if (a->pattern)
{
while (a->pattern[i])
{
v = u + 1;
m = a;
for (b = a + 1; b <= last; b++)
{
{
*u++ = m->pattern[i];
*u++ = 0;
m = b;
}
}
if (m != a)
{
*u++ = m->pattern[i];
*u++ = 0;
*u++ = 0;
*u++ = 0;
m = a;
for (b = a + 1; b <= last; b++)
{
{
if ((*v = (u - v)) != (u - v))
v += 2;
m = b;
}
}
if ((*v = (u - v)) != (u - v))
}
switch (*u++ = a->pattern[i++])
{
case DIG:
case NAM:
case REP:
case SPC:
case TOK:
*u++ = 1;
break;
default:
*u++ = 3;
*u++ = 0;
*u++ = 0;
break;
}
}
*u++ = 0;
*u++ = a - action;
a->pattern = 0;
}
}
return u;
}
/*
* parse scan action for a in s
* s points to the first delimiter
*/
static void
{
register int c;
register int t;
register char* v;
register char* n;
Rule_t* u;
unsigned long m;
if (c = *s++)
do
{
v = n = s;
while (t = *s++)
{
if (t == c)
break;
if (t == '\\' && !(t = *s++))
break;
*n++ = t;
}
*n = 0;
if (!*v)
break;
switch (*v++)
{
case 'A':
n = tokopen(v, 1);
while (v = tokread(n))
{
{
*v = ATTRNAME;
u = getrule(v);
*v = t;
if (!u)
u = getrule(v + 1);
}
else
u = getrule(v);
if (!u || !(u->property & P_attribute))
if (u->scan)
{
if (!a->scan)
}
{
a->attrprop = 1;
if (t == '-')
else
}
else if (m = u->property & (P_accept|P_after|P_always|P_archive|P_before|P_command|P_dontcare|P_force|P_foreground|P_functional|P_ignore|P_implicit|P_local|P_make|P_multiple|P_parameter|P_repeat|P_terminal|P_virtual))
{
a->attrprop = 1;
if (t == '-')
else
}
}
tokclose(n);
break;
case 'M':
if (a->map)
{
}
break;
case 'O':
for (;;)
{
switch (*v++)
{
case 0:
break;
case 'X':
a->flags |= SCAN_nopropagate;
continue;
default:
continue;
}
break;
}
break;
case 'R':
if (a->script)
{
}
break;
default:
break;
}
} while (t);
}
/*
* compile scan description in r and return scan pointer
*/
static Scan_t*
{
register char* s;
register Quote_t* q;
register int c;
int i;
int t;
int z;
int line;
char* file;
char* n;
char* v;
char* y;
char* x[128];
char** p;
Action_t* a;
z = 0;
p = x;
error_info.line = 0;
do
{
error_info.line++;
if (n = strchr(s, '\n'))
*n++ = 0;
switch (*s++)
{
case 0:
break;
case 'C':
break;
case 'D':
break;
/*FALLTHROUGH*/
case 'A':
case 'B':
case 'E':
case 'I':
case 'T':
if (*s)
{
if (p >= &x[elementsof(x) - 1])
*p++ = s - 1;
z += n ? (n - s) : strlen(s);
}
break;
case 'F':
break;
case 'O':
c = isalnum(*s) ? 0 : *s++;
for (;;)
{
switch (*s++)
{
case 0:
break;
case 'M':
continue;
case 'O':
continue;
case 'S':
continue;
default:
if (*(s - 1) == c)
break;
continue;
}
break;
}
break;
case 'Q':
if (c = *s++)
{
z = 0;
do
{
v = y = s;
while (t = *s++)
{
if (t == c || t == '\\' && !(t = *s++))
break;
*y++ = t;
}
*y = 0;
switch (z++)
{
case 0:
break;
case 1:
q->flags |= QUOTE_newline;
break;
case 2:
q->escape = *v;
break;
case 3:
for (;;)
{
switch (*v++)
{
case 0:
break;
case 'C':
q->flags |= QUOTE_comment;
continue;
case 'L':
q->flags |= QUOTE_newline;
continue;
case 'N':
q->flags |= QUOTE_nested;
continue;
case 'Q':
q->flags |= QUOTE_quote;
continue;
case 'S':
q->flags |= QUOTE_single;
continue;
case 'W':
q->flags |= QUOTE_space;
continue;
default:
continue;
}
break;
}
break;
case 4:
break;
default:
break;
}
} while (t);
}
break;
case 'S':
break;
case 'X':
if (*s)
s++;
{
}
break;
default:
break;
}
} while (s = n);
if (p > x)
{
z = p - x;
*p = 0;
p = x;
while (s = *p++)
{
a++;
a->type = *s++;
c = *s++;
i = 0;
a->pattern = n = s;
while (t = *s++)
{
if (t == c)
break;
if (t == '\\')
{
if (!(t = *s++))
break;
switch (t)
{
case 'D':
t = DIG;
break;
case 'T':
t = TOK;
break;
case 'V':
t = NAM;
break;
}
if (n > a->pattern && *(n - 1) == t)
continue;
}
else if (isspace(t))
{
t = SPC;
if (n > a->pattern && *(n - 1) == t)
continue;
}
else if (t == '%')
{
i++;
t = ARG;
}
else if (t == '*')
t = ANY;
else if (t == '@')
t = REP;
*n++ = t;
}
scanaction(a, s - 1);
*n = 0;
switch (a->type)
{
case 'A':
case 'I':
if (!i)
if (i > SCANARGS)
break;
}
}
}
if (r->dynamic & D_triggered)
{
}
return ss;
}
/*
* skip quotes in q
*/
static unsigned char*
scanquote(int fd, unsigned char* buf, unsigned char** p, register unsigned char* g, Quote_t* q, int flags)
{
register int c;
register unsigned char* t;
unsigned char* x;
unsigned char* y;
unsigned char* z;
int e;
for (x = g; q; q = q->next)
if ((flags & q->flags) && (t = (unsigned char*)q->begin) && *(g - 1) == *t++ && (!(q->flags & QUOTE_space) || (g - 1) == *p || *(g - 2) == ' ' || *(g - 2) == '\t'))
{
for (;;)
{
while (!(c = *g++))
{
if (*p >= buf + SCANBUFFER)
{
c = g - *p - 1;
*p = buf + SCANBUFFER - c;
}
{
g[0] = 0;
return g;
}
g[c] = 0;
}
if (!*t)
{
if (q->flags & QUOTE_single)
goto accept;
e = *q->end;
y = g;
for (;;)
{
{
g--;
goto accept;
}
if (c == e && *(g - 2) != q->escape)
{
z = g;
t = (unsigned char*)q->end + 1;
/*UNDENT*/
for (;;)
{
if (!*t)
{
if (c == '\n')
g--;
goto accept;
}
while (!(c = *g++))
{
if (q->flags & QUOTE_comment)
{
c = g - z;
z = buf + SCANBUFFER - c;
}
else
{
c = g - *p - 1;
}
*p = buf + SCANBUFFER - c;
{
g[0] = 0;
return g;
}
g[c] = 0;
}
if (c != *t++)
{
g = z;
break;
}
}
/*INDENT*/
}
while (!(c = *g++))
{
if (*p >= buf + SCANBUFFER)
{
c = g - *p - 1;
*p = buf + SCANBUFFER - c;
}
{
g[0] = 0;
return g;
}
g[c] = 0;
}
}
}
if (c != *t++)
{
g = x;
break;
}
}
}
return g;
for (x--; x < g; *x++ = ' ');
return g;
}
/*
* parameter definition
*/
static List_t*
{
register char* t;
char* b;
char* z;
int c;
Rule_t* u;
Var_t* v;
while (isspace(*s))
s++;
t = s;
s++;
if (s > t)
{
c = *s;
*s = 0;
if (!(v = getvar(t)))
*s = c;
b = t = s;
for (;;)
{
while (isspace(*s))
s++;
while (*s && !isspace(*s))
*t++ = *s++;
if (!*s)
break;
*t++ = ' ';
}
for (z = t; z < s; *z++ = ' ');
*t = 0;
if (*v->value)
{
}
else
{
u->property |= P_parameter;
p = cons(u, p);
}
if (t < s)
*t = ' ';
}
return p;
}
/*
* macro scan -- only partial parameterization
*
* include(<SP>*<FILE><SP>*)
* sinclude(<SP>*<FILE><SP>*)
* INCLUDE(<SP>*<FILE>[,<FILE>]*<SP>*)
* define(<SP>*<VARIABLE><SP>*,<DEFINITION><SP>*)
* ifelse(c,t,f)
* # comment
*
* attribute and property from first I pattern propagated to prereq files
*/
/*ARGSUSED*/
static List_t*
{
register int c;
register int inquote;
register char* w;
int n;
int dontcare;
int ifparen;
int paren;
int h;
int t;
Rule_t* u;
Var_t* v;
{
return p;
}
switch (c)
{
case ')':
if (!inquote)
{
ifparen = 0;
}
break;
case '"':
case '#':
case '\n':
if (inquote == c)
{
inquote = 0;
}
else if (!inquote && c != '\n')
break;
case '\\':
break;
default:
if (!inquote)
{
{
if (c == '(')
paren++;
{
h = 1;
t = C_VARPOS1;
}
{
h = 0;
}
}
else
{
{
if (t == C_VARPOS8)
else
t <<= 1;
}
if (istype(c, t))
{
{
{
p = cons(u, p);
}
}
if (c == '(')
{
paren++;
/*UNDENT*/
if (*w == 's')
{
dontcare = 1;
w++;
}
else
if (*w == 'i')
{
if (!strcmp(w, "include"))
{
if (!isspace(c))
{
if (dontcare)
u->property |= P_dontcare;
u->property &= ~P_dontcare;
{
}
p = cons(u, p);
}
}
}
{
do
{
if (!isspace(c))
{
if (dontcare)
u->property |= P_dontcare;
u->property &= ~P_dontcare;
{
}
p = cons(u, p);
}
} while (c == ',');
}
{
if (!isspace(c))
if (c == '`')
inquote = '\'';
else
n = 1;
{
if (!inquote)
{
if (c == '(')
n++;
else if (c == ')' && !n--)
break;
}
else if (c == '#')
{
continue;
}
}
inquote = 0;
}
/*INDENT*/
}
}
else
{
h = 0;
}
}
}
break;
}
return p;
}
/*
* do scan match action a on r with matched string s
* b is beginning of the original line
*/
static List_t*
{
int n;
char* t;
char* o;
Rule_t* u;
Rule_t* x;
if (strchr(s, ' '))
return p;
{
if (a->script)
{
}
if (a->map)
{
}
}
if (*s)
{
if (split)
t = tokopen(s, 1);
do
{
break;
if (o = strchr(s, ' '))
{
do
{
} while (o = strchr(o, ' '));
o = s;
}
if (!*s || *s == '-' && !*(s + 1))
break;
#if _WINIX
{
*(s + 1) = *s;
*s = '/';
}
#endif
u = makerule(s);
{
{
oldname(u);
u = makerule(s);
}
else
{
error(1, "%s : %s: implicit reference before action completed", sfstruse(internal.tmp), unbound(u));
}
}
{
p = cons(u, p);
if (iflev || o)
u->property |= P_dontcare;
u->property &= ~P_dontcare;
if (a->attrprop)
{
if (x)
{
}
}
{
if (!(n = a->scan))
n = r->scan;
else if (n == SCAN_NULL)
n = 0;
{
if (u->scan)
{
char* os;
char* ns;
List_t* q;
}
u->scan = n;
if (x)
x->scan = n;
}
}
}
} while (split);
if (split)
tokclose(t);
}
else
{
if (a->attrprop)
{
if (x)
{
}
}
}
if (tmp)
return p;
}
#if DEBUG
static char*
{
int i;
switch (*s)
{
case ANY:
return "ANY";
case ARG:
return "ARG";
case DIG:
return "DIG";
case NAM:
return "NAM";
case REP:
return "REP";
case SPC:
return "SPC";
case TOK:
return "TOK";
case 0:
return "END";
}
i = 0;
buf[i++] = '\'';
buf[i++] = *s++;
buf[i++] = '\'';
buf[i] = 0;
return buf;
}
#endif
/*
* scan fd on file r for patterns compiled in ss
* cons prereqs on p
*/
static List_t*
{
register int c;
register unsigned char* g;
register Scanstate_t* s;
Scanstate_t* m;
unsigned char* pb;
unsigned char* x;
unsigned char* b;
char* a;
int d;
int e;
int hit;
int n;
int collect;
int iflev;
int h;
int t;
int typ;
Rule_t* u;
Var_t* v;
struct
{
int arg;
unsigned char* buffer;
struct
{
int begin;
int end;
int replace;
{
return p;
}
{
}
g[0] = 0;
m = 0;
collect = 0;
for (;;)
{
n = 0;
pb = 0;
hit = 0;
b = g;
{
for (x = g; *x && *x != '\n'; x++);
if (x > g)
}
{
next:
while (!(c = *g++))
{
c = g - b - 1;
g = buf + SCANBUFFER;
if (c && b >= g)
{
memcpy(g - c, b, c);
c += b - g;
b -= c;
if (pb)
pb -= c;
}
else
b = g;
goto done;
g[c] = 0;
{
for (x = g; *x && *x != '\n'; x++);
}
}
for (;;)
{
#if DEBUG
{
for (x = g - 1; *x && *x != '\n'; x++);
}
#endif
/*UNDENT*/
{
h = g == (b + 1);
if (typ == DIG || typ == SPC || typ == NAM && istype(c, C_VARIABLE1) || typ == TOK && istype(c, C_VARIABLE1|C_VARIABLE2))
for (;;)
{
{
if (m)
{
m = 0;
if (collect)
{
collect = 0;
}
}
#if DEBUG
h = 1;
#endif
if (c == '\n')
break;
h = 1;
}
else if (!c)
{
if (b >= buf + SCANBUFFER)
{
c = g - b - 1;
b = buf + SCANBUFFER - c;
}
goto done;
g[c] = 0;
}
else if (!m)
break;
c = *g++;
}
s += *(s + 1) + 1;
{
#if DEBUG
#endif
m = 0;
collect = 0;
break;
}
}
{
{
pop++;
}
s += *(s + 1) + 1;
}
{
m = s += *(s + 1) + 1;
if (n < elementsof(arg))
{
collect = 1;
}
}
{
if (rep)
{
{
while (x < g)
{
while (x < g && isspace(*x))
x++;
else
{
if (*x != *per)
break;
x++;
}
}
if (x >= g)
break;
}
goto rephit;
}
else
}
else if (typ == 0)
{
if (m)
{
if (c != '\n')
{
s = m;
goto next;
}
m = 0;
if (collect)
{
collect = 0;
}
}
if (c == '\n')
{
g++;
else
rep = 0;
}
{
if (rep)
hit += n;
if (n < elementsof(arg))
{
n++;
}
for (c = 0; c < n; c++)
for (c = 0; c < n; c++)
while (c < elementsof(arg))
#if DEBUG
error(2, "scanexec: HIT %s: %c n=%d \"%s\" \"%s\"", r->name, ss->action[*s].type, n - 1, b + arg[0].begin, b + arg[1].begin);
#endif
a = null;
{
case 'A':
{
else
}
else
break;
case 'B':
iflev++;
break;
case 'D':
if (r->property & P_parameter)
break;
case 'E':
iflev--;
break;
case 'I':
case 'T':
break;
}
p = scanmatch(p, &ss->action[*s], r, (char*)b, a, iflev, c == 'T' ? -1 : a != null && a > (char*)b && (c = *(a - 1)) != '"' && c != '\'' && (c != '<' || arg[0].replace != '>'));
for (c = 0; c < n; c++)
pop--;
}
else
{
#if DEBUG
#endif
if (hit)
rep = 0;
{
pop--;
if (c != '\n')
{
#if DEBUG
#endif
goto next;
}
}
}
if (rep)
{
s = rep;
if ((b = --g) == pb)
goto done;
pb = b;
n = 0;
goto next;
}
break;
}
else if (c == *s++)
{
if (m)
{
m = 0;
if (collect)
{
collect = 0;
}
}
s += *s;
goto next;
}
else
s++;
/*INDENT*/
}
g = b;
}
while ((c = *g++) != '\n')
{
if (!c)
{
goto done;
g[c] = 0;
}
else if (x[c] & (QUOTE_comment|QUOTE_quote))
{
if (g - 2 >= b)
b = g - 2;
}
{
{
h = 1;
t = C_VARPOS1;
}
else
{
h = 0;
}
b = g - 1;
for (;;)
{
while (!(c = *g++))
{
if (b >= buf + SCANBUFFER)
{
c = g - b - 1;
b = buf + SCANBUFFER - c;
}
goto done;
g[c] = 0;
}
{
if (t == C_VARPOS8)
else
t <<= 1;
}
if (!istype(c, t))
{
break;
h = 0;
}
}
g--;
if (h)
{
*g = 0;
{
{
p = cons(u, p);
}
}
*g = c;
}
}
{
d = e = 0;
h = 0;
b = g - 1;
for (;;)
{
while (!(c = *g++))
{
if (b >= buf + SCANBUFFER)
{
c = g - b - 1;
b = buf + SCANBUFFER - c;
}
goto done;
g[c] = 0;
}
{
if (e && d > 1)
{
h = e;
break;
}
if (!isspace(c))
{
h = 0;
break;
}
if (!h)
h = g - b - 1;
}
else if (c == '.')
{
d++;
e = g - b - 1;
}
else if (h)
break;
}
g--;
if (h)
{
c = b[h];
b[h] = 0;
b[h] = c;
}
break;
}
}
}
done:
{
{
}
}
return p;
}
/*
* return list of r's implicit prerequisites
* r must be bound to a file which is then scanned
*/
{
register Rule_t* s;
List_t* p;
int fd;
if (tm)
*tm = 0;
return 0;
{
alt = s;
s->property |= P_implicit;
}
{
alt = 0;
}
{
ss = 0;
if (alt)
s->prereqs = 0;
}
else
{
{
{
break;
}
if (!p)
}
}
return s->prereqs;
if (ss)
{
if (!(r->property & P_accept) && !state.accept && !((s->property | (alt ? alt->property : 0L)) & P_force) && r->scan == s->scan)
ss = 0;
{
return 0;
}
else
{
s->prereqs = scanexec(fd, r, ss, ss->before ? scanmatch(NiL, ss->before, r, null, null, 0, 1) : (List_t*)0);
}
}
if (alt)
{
{
}
}
else
if (ss)
{
{
{
}
}
{
}
}
return s->prereqs;
}