14887Schin /***********************************************************************
24887Schin * *
34887Schin * This software is part of the ast package *
4*10898Sroland.mainz@nrubsig.org * Copyright (c) 1986-2009 AT&T Intellectual Property *
54887Schin * and is licensed under the *
64887Schin * Common Public License, Version 1.0 *
78462SApril.Chin@Sun.COM * by AT&T Intellectual Property *
84887Schin * *
94887Schin * A copy of the License is available at *
104887Schin * http://www.opensource.org/licenses/cpl1.0.txt *
114887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
124887Schin * *
134887Schin * Information and Software Systems Research *
144887Schin * AT&T Research *
154887Schin * Florham Park NJ *
164887Schin * *
174887Schin * Glenn Fowler <gsf@research.att.com> *
184887Schin * *
194887Schin ***********************************************************************/
204887Schin #pragma prototyped
214887Schin /*
224887Schin * Glenn Fowler
234887Schin * AT&T Research
244887Schin *
254887Schin * miscellaneous preprocessor support
264887Schin */
274887Schin
284887Schin #include "pplib.h"
294887Schin
304887Schin /*
314887Schin * macro symbol def|ref
324887Schin */
334887Schin
344887Schin struct ppsymbol*
pprefmac(char * name,int ref)354887Schin pprefmac(char* name, int ref)
364887Schin {
374887Schin register struct ppsymbol* sym;
384887Schin
394887Schin if (!(sym = ppsymget(pp.symtab, name)) && (ref <= REF_NORMAL && pp.macref || ref == REF_CREATE || ref == REF_DELETE && (pp.mode & (INIT|READONLY))))
404887Schin {
414887Schin if ((pp.state & COMPILE) && pp.truncate && strlen(name) > pp.truncate)
424887Schin name[pp.truncate] = 0;
434887Schin sym = ppsymset(pp.symtab, NiL);
444887Schin }
454887Schin if (sym && ref <= REF_NORMAL)
464887Schin {
474887Schin if (pp.macref) (*pp.macref)(sym, error_info.file, error_info.line, ref == REF_NORMAL && (pp.state & CONDITIONAL) ? REF_IF : ref, 0L);
484887Schin if (!sym->macro) sym = 0;
494887Schin }
504887Schin #if COMPATIBLE
514887Schin if (!(pp.state & COMPATIBILITY))
524887Schin #endif
534887Schin if (ref == REF_IF && sym && (sym->flags & SYM_PREDEFINED) && *name != '_' && !(pp.mode & (HOSTED|INACTIVE)))
544887Schin {
554887Schin if (pp.state & STRICT)
564887Schin {
574887Schin error(1, "%s: obsolete predefined symbol reference disabled", name);
584887Schin return(0);
594887Schin }
604887Schin error(1, "%s: obsolete predefined symbol referenced", name);
614887Schin }
624887Schin return(sym);
634887Schin }
644887Schin
654887Schin /*
664887Schin * common predicate assertion operations
674887Schin * op is DEFINE or UNDEF
684887Schin */
694887Schin
704887Schin void
ppassert(int op,char * pred,char * args)714887Schin ppassert(int op, char* pred, char* args)
724887Schin {
734887Schin register struct pplist* a;
744887Schin register struct ppsymbol* sym;
754887Schin register struct pplist* p;
764887Schin register struct pplist* q;
774887Schin
784887Schin if (!args) switch (op)
794887Schin {
804887Schin case DEFINE:
814887Schin goto mark;
824887Schin case UNDEF:
834887Schin a = 0;
844887Schin goto unmark;
854887Schin }
864887Schin if (a = (struct pplist*)hashget(pp.prdtab, pred))
874887Schin {
884887Schin p = 0;
894887Schin q = a;
904887Schin while (q)
914887Schin {
924887Schin if (streq(q->value, args))
934887Schin {
944887Schin if (op == DEFINE) return;
954887Schin q = q->next;
964887Schin if (p) p->next = q;
974887Schin else a = q;
984887Schin }
994887Schin else
1004887Schin {
1014887Schin p = q;
1024887Schin q = q->next;
1034887Schin }
1044887Schin }
1054887Schin if (op == UNDEF)
1064887Schin {
1074887Schin unmark:
1084887Schin hashput(pp.prdtab, pred, a);
1094887Schin if (sym = ppsymref(pp.symtab, pred))
1104887Schin sym->flags &= ~SYM_PREDICATE;
1114887Schin return;
1124887Schin }
1134887Schin }
1144887Schin if (op == DEFINE)
1154887Schin {
1164887Schin p = newof(0, struct pplist, 1, 0);
1174887Schin p->next = a;
1184887Schin p->value = strdup(args);
1194887Schin hashput(pp.prdtab, NiL, p);
1204887Schin mark:
1214887Schin if ((pp.state & COMPILE) && pp.truncate) return;
1224887Schin if (sym = ppsymset(pp.symtab, pred))
1234887Schin sym->flags |= SYM_PREDICATE;
1244887Schin }
1254887Schin }
1264887Schin
1274887Schin /*
1284887Schin * parse a predicate argument list
1294887Schin * the args are placed in pp.args
1304887Schin * the first non-space/paren argument token type is returned
1314887Schin * forms:
1324887Schin *
1334887Schin * predicate <identifier> type=T_ID
1344887Schin * predicate ( <identifier> ) type=T_ID
1354887Schin * predicate ( ) type=0
1364887Schin * predicate ( <balanced-paren-list> ) type=T_STRING
1374887Schin * otherwise type=<other>
1384887Schin */
1394887Schin
1404887Schin int
pppredargs(void)1414887Schin pppredargs(void)
1424887Schin {
1434887Schin register int c;
1444887Schin register int n;
1454887Schin register int type;
1464887Schin char* pptoken;
1474887Schin
1484887Schin pptoken = pp.token;
1494887Schin pp.token = pp.args;
1504887Schin switch (type = pplex())
1514887Schin {
1524887Schin case '(':
1534887Schin type = 0;
1544887Schin n = 1;
1554887Schin pp.state |= HEADER;
1564887Schin pp.state &= ~STRIP;
1574887Schin c = pplex();
1584887Schin pp.state &= ~NOSPACE;
1594887Schin for (;;)
1604887Schin {
1614887Schin switch (c)
1624887Schin {
1634887Schin case '(':
1644887Schin n++;
1654887Schin break;
1664887Schin case '\n':
1674887Schin ungetchr(c);
1684887Schin error(2, "missing %d )%s in predicate argument list", n, n == 1 ? "" : "'s");
1694887Schin type = 0;
1704887Schin goto done;
1714887Schin case ')':
1724887Schin if (!--n) goto done;
1734887Schin break;
1744887Schin }
1754887Schin pp.token = pp.toknxt;
1764887Schin if (c != ' ')
1774887Schin {
1784887Schin if (type) type = T_STRING;
1794887Schin else type = (c == T_ID) ? T_ID : T_STRING;
1804887Schin }
1814887Schin c = pplex();
1824887Schin }
1834887Schin done:
1844887Schin pp.state &= ~HEADER;
1854887Schin pp.state |= NOSPACE|STRIP;
1864887Schin if (pp.token > pp.args && *(pp.token - 1) == ' ') pp.token--;
1874887Schin *pp.token = 0;
1884887Schin break;
1894887Schin case '\n':
1904887Schin ungetchr('\n');
1914887Schin type = 0;
1924887Schin break;
1934887Schin }
1944887Schin pp.token = pptoken;
1954887Schin return(type);
1964887Schin }
1974887Schin
1984887Schin /*
1994887Schin * sync output line number
2004887Schin */
2014887Schin
2024887Schin int
ppsync(void)2034887Schin ppsync(void)
2044887Schin {
2054887Schin long m;
2064887Schin
2074887Schin if ((pp.state & (ADD|HIDDEN)))
2084887Schin {
2094887Schin if (pp.state & ADD)
2104887Schin {
2114887Schin pp.state &= ~ADD;
2124887Schin m = pp.addp - pp.addbuf;
2134887Schin pp.addp = pp.addbuf;
2144887Schin ppprintf("%-.*s", m, pp.addbuf);
2154887Schin }
2164887Schin if (pp.linesync)
2174887Schin {
2184887Schin if ((pp.state & SYNCLINE) || pp.hidden >= MAXHIDDEN)
2194887Schin {
2204887Schin pp.hidden = 0;
2214887Schin pp.state &= ~(HIDDEN|SYNCLINE);
2224887Schin if (error_info.line)
2234887Schin (*pp.linesync)(error_info.line, error_info.file);
2244887Schin }
2254887Schin else
2264887Schin {
2274887Schin m = pp.hidden;
2284887Schin pp.hidden = 0;
2294887Schin pp.state &= ~HIDDEN;
2304887Schin while (m-- > 0)
2314887Schin ppputchar('\n');
2324887Schin }
2334887Schin }
2344887Schin else
2354887Schin {
2364887Schin pp.hidden = 0;
2374887Schin pp.state &= ~HIDDEN;
2384887Schin ppputchar('\n');
2394887Schin }
2404887Schin }
2414887Schin return 0;
2424887Schin }
243