14887Schin /***********************************************************************
24887Schin *                                                                      *
34887Schin *               This software is part of the ast package               *
4*8462SApril.Chin@Sun.COM *          Copyright (c) 1986-2008 AT&T Intellectual Property          *
54887Schin *                      and is licensed under the                       *
64887Schin *                  Common Public License, Version 1.0                  *
7*8462SApril.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*
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
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
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
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