1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin *                                                                      *
3da2e3ebdSchin *               This software is part of the ast package               *
4*b30d1939SAndy Fiddaman *          Copyright (c) 1986-2011 AT&T Intellectual Property          *
5da2e3ebdSchin *                      and is licensed under the                       *
6*b30d1939SAndy Fiddaman *                 Eclipse Public License, Version 1.0                  *
77c2fbfb3SApril Chin *                    by AT&T Intellectual Property                     *
8da2e3ebdSchin *                                                                      *
9da2e3ebdSchin *                A copy of the License is available at                 *
10*b30d1939SAndy Fiddaman *          http://www.eclipse.org/org/documents/epl-v10.html           *
11*b30d1939SAndy Fiddaman *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
12da2e3ebdSchin *                                                                      *
13da2e3ebdSchin *              Information and Software Systems Research               *
14da2e3ebdSchin *                            AT&T Research                             *
15da2e3ebdSchin *                           Florham Park NJ                            *
16da2e3ebdSchin *                                                                      *
17da2e3ebdSchin *                 Glenn Fowler <gsf@research.att.com>                  *
18da2e3ebdSchin *                                                                      *
19da2e3ebdSchin ***********************************************************************/
20da2e3ebdSchin #pragma prototyped
21da2e3ebdSchin /*
22da2e3ebdSchin  * Glenn Fowler
23da2e3ebdSchin  * AT&T Research
24da2e3ebdSchin  *
25da2e3ebdSchin  * miscellaneous preprocessor support
26da2e3ebdSchin  */
27da2e3ebdSchin 
28da2e3ebdSchin #include "pplib.h"
29da2e3ebdSchin 
30da2e3ebdSchin /*
31da2e3ebdSchin  * macro symbol def|ref
32da2e3ebdSchin  */
33da2e3ebdSchin 
34da2e3ebdSchin struct ppsymbol*
pprefmac(char * name,int ref)35da2e3ebdSchin pprefmac(char* name, int ref)
36da2e3ebdSchin {
37da2e3ebdSchin 	register struct ppsymbol*	sym;
38da2e3ebdSchin 
39da2e3ebdSchin 	if (!(sym = ppsymget(pp.symtab, name)) && (ref <= REF_NORMAL && pp.macref || ref == REF_CREATE || ref == REF_DELETE && (pp.mode & (INIT|READONLY))))
40da2e3ebdSchin 	{
41da2e3ebdSchin 		if ((pp.state & COMPILE) && pp.truncate && strlen(name) > pp.truncate)
42da2e3ebdSchin 			name[pp.truncate] = 0;
43da2e3ebdSchin 		sym = ppsymset(pp.symtab, NiL);
44da2e3ebdSchin 	}
45da2e3ebdSchin 	if (sym && ref <= REF_NORMAL)
46da2e3ebdSchin 	{
47da2e3ebdSchin 		if (pp.macref) (*pp.macref)(sym, error_info.file, error_info.line, ref == REF_NORMAL && (pp.state & CONDITIONAL) ? REF_IF : ref, 0L);
48da2e3ebdSchin 		if (!sym->macro) sym = 0;
49da2e3ebdSchin 	}
50da2e3ebdSchin #if COMPATIBLE
51da2e3ebdSchin 	if (!(pp.state & COMPATIBILITY))
52da2e3ebdSchin #endif
53da2e3ebdSchin 	if (ref == REF_IF && sym && (sym->flags & SYM_PREDEFINED) && *name != '_' && !(pp.mode & (HOSTED|INACTIVE)))
54da2e3ebdSchin 	{
55da2e3ebdSchin 		if (pp.state & STRICT)
56da2e3ebdSchin 		{
57da2e3ebdSchin 			error(1, "%s: obsolete predefined symbol reference disabled", name);
58da2e3ebdSchin 			return(0);
59da2e3ebdSchin 		}
60da2e3ebdSchin 		error(1, "%s: obsolete predefined symbol referenced", name);
61da2e3ebdSchin 	}
62da2e3ebdSchin 	return(sym);
63da2e3ebdSchin }
64da2e3ebdSchin 
65da2e3ebdSchin /*
66da2e3ebdSchin  * common predicate assertion operations
67da2e3ebdSchin  * op is DEFINE or UNDEF
68da2e3ebdSchin  */
69da2e3ebdSchin 
70da2e3ebdSchin void
ppassert(int op,char * pred,char * args)71da2e3ebdSchin ppassert(int op, char* pred, char* args)
72da2e3ebdSchin {
73da2e3ebdSchin 	register struct pplist*		a;
74da2e3ebdSchin 	register struct ppsymbol*	sym;
75da2e3ebdSchin 	register struct pplist*		p;
76da2e3ebdSchin 	register struct pplist*		q;
77da2e3ebdSchin 
78da2e3ebdSchin 	if (!args) switch (op)
79da2e3ebdSchin 	{
80da2e3ebdSchin 	case DEFINE:
81da2e3ebdSchin 		goto mark;
82da2e3ebdSchin 	case UNDEF:
83da2e3ebdSchin 		a = 0;
84da2e3ebdSchin 		goto unmark;
85da2e3ebdSchin 	}
86da2e3ebdSchin 	if (a = (struct pplist*)hashget(pp.prdtab, pred))
87da2e3ebdSchin 	{
88da2e3ebdSchin 		p = 0;
89da2e3ebdSchin 		q = a;
90da2e3ebdSchin 		while (q)
91da2e3ebdSchin 		{
92da2e3ebdSchin 			if (streq(q->value, args))
93da2e3ebdSchin 			{
94da2e3ebdSchin 				if (op == DEFINE) return;
95da2e3ebdSchin 				q = q->next;
96da2e3ebdSchin 				if (p) p->next = q;
97da2e3ebdSchin 				else a = q;
98da2e3ebdSchin 			}
99da2e3ebdSchin 			else
100da2e3ebdSchin 			{
101da2e3ebdSchin 				p = q;
102da2e3ebdSchin 				q = q->next;
103da2e3ebdSchin 			}
104da2e3ebdSchin 		}
105da2e3ebdSchin 		if (op == UNDEF)
106da2e3ebdSchin 		{
107da2e3ebdSchin 		unmark:
108da2e3ebdSchin 			hashput(pp.prdtab, pred, a);
109da2e3ebdSchin 			if (sym = ppsymref(pp.symtab, pred))
110da2e3ebdSchin 				sym->flags &= ~SYM_PREDICATE;
111da2e3ebdSchin 			return;
112da2e3ebdSchin 		}
113da2e3ebdSchin 	}
114da2e3ebdSchin 	if (op == DEFINE)
115da2e3ebdSchin 	{
116da2e3ebdSchin 		p = newof(0, struct pplist, 1, 0);
117da2e3ebdSchin 		p->next = a;
118da2e3ebdSchin 		p->value = strdup(args);
119da2e3ebdSchin 		hashput(pp.prdtab, NiL, p);
120da2e3ebdSchin 	mark:
121da2e3ebdSchin 		if ((pp.state & COMPILE) && pp.truncate) return;
122da2e3ebdSchin 		if (sym = ppsymset(pp.symtab, pred))
123da2e3ebdSchin 			sym->flags |= SYM_PREDICATE;
124da2e3ebdSchin 	}
125da2e3ebdSchin }
126da2e3ebdSchin 
127da2e3ebdSchin /*
128da2e3ebdSchin  * parse a predicate argument list
129da2e3ebdSchin  * the args are placed in pp.args
130da2e3ebdSchin  * the first non-space/paren argument token type is returned
131da2e3ebdSchin  * forms:
132da2e3ebdSchin  *
133da2e3ebdSchin  *	predicate <identifier>			type=T_ID
134da2e3ebdSchin  *	predicate ( <identifier> )		type=T_ID
135da2e3ebdSchin  *	predicate ( )				type=0
136da2e3ebdSchin  *	predicate ( <balanced-paren-list> )	type=T_STRING
137da2e3ebdSchin  *	otherwise				type=<other>
138da2e3ebdSchin  */
139da2e3ebdSchin 
140da2e3ebdSchin int
pppredargs(void)141da2e3ebdSchin pppredargs(void)
142da2e3ebdSchin {
143da2e3ebdSchin 	register int	c;
144da2e3ebdSchin 	register int	n;
145da2e3ebdSchin 	register int	type;
146da2e3ebdSchin 	char*		pptoken;
147da2e3ebdSchin 
148da2e3ebdSchin 	pptoken = pp.token;
149da2e3ebdSchin 	pp.token = pp.args;
150da2e3ebdSchin 	switch (type = pplex())
151da2e3ebdSchin 	{
152da2e3ebdSchin 	case '(':
153da2e3ebdSchin 		type = 0;
154da2e3ebdSchin 		n = 1;
155da2e3ebdSchin 		pp.state |= HEADER;
156da2e3ebdSchin 		pp.state &= ~STRIP;
157da2e3ebdSchin 		c = pplex();
158da2e3ebdSchin 		pp.state &= ~NOSPACE;
159da2e3ebdSchin 		for (;;)
160da2e3ebdSchin 		{
161da2e3ebdSchin 			switch (c)
162da2e3ebdSchin 			{
163da2e3ebdSchin 			case '(':
164da2e3ebdSchin 				n++;
165da2e3ebdSchin 				break;
166da2e3ebdSchin 			case '\n':
167da2e3ebdSchin 				ungetchr(c);
168da2e3ebdSchin 				error(2, "missing %d )%s in predicate argument list", n, n == 1 ? "" : "'s");
169da2e3ebdSchin 				type = 0;
170da2e3ebdSchin 				goto done;
171da2e3ebdSchin 			case ')':
172da2e3ebdSchin 				if (!--n) goto done;
173da2e3ebdSchin 				break;
174da2e3ebdSchin 			}
175da2e3ebdSchin 			pp.token = pp.toknxt;
176da2e3ebdSchin 			if (c != ' ')
177da2e3ebdSchin 			{
178da2e3ebdSchin 				if (type) type = T_STRING;
179da2e3ebdSchin 				else type = (c == T_ID) ? T_ID : T_STRING;
180da2e3ebdSchin 			}
181da2e3ebdSchin 			c = pplex();
182da2e3ebdSchin 		}
183da2e3ebdSchin 	done:
184da2e3ebdSchin 		pp.state &= ~HEADER;
185da2e3ebdSchin 		pp.state |= NOSPACE|STRIP;
186da2e3ebdSchin 		if (pp.token > pp.args && *(pp.token - 1) == ' ') pp.token--;
187da2e3ebdSchin 		*pp.token = 0;
188da2e3ebdSchin 		break;
189da2e3ebdSchin 	case '\n':
190da2e3ebdSchin 		ungetchr('\n');
191da2e3ebdSchin 		type = 0;
192da2e3ebdSchin 		break;
193da2e3ebdSchin 	}
194da2e3ebdSchin 	pp.token = pptoken;
195da2e3ebdSchin 	return(type);
196da2e3ebdSchin }
197da2e3ebdSchin 
198da2e3ebdSchin /*
199da2e3ebdSchin  * sync output line number
200da2e3ebdSchin  */
201da2e3ebdSchin 
202da2e3ebdSchin int
ppsync(void)203da2e3ebdSchin ppsync(void)
204da2e3ebdSchin {
205da2e3ebdSchin 	long	m;
206da2e3ebdSchin 
207da2e3ebdSchin 	if ((pp.state & (ADD|HIDDEN)))
208da2e3ebdSchin 	{
209da2e3ebdSchin 		if (pp.state & ADD)
210da2e3ebdSchin 		{
211da2e3ebdSchin 			pp.state &= ~ADD;
212da2e3ebdSchin 			m = pp.addp - pp.addbuf;
213da2e3ebdSchin 			pp.addp = pp.addbuf;
214da2e3ebdSchin 			ppprintf("%-.*s", m, pp.addbuf);
215da2e3ebdSchin 		}
216da2e3ebdSchin 		if (pp.linesync)
217da2e3ebdSchin 		{
218da2e3ebdSchin 			if ((pp.state & SYNCLINE) || pp.hidden >= MAXHIDDEN)
219da2e3ebdSchin 			{
220da2e3ebdSchin 				pp.hidden = 0;
221da2e3ebdSchin 				pp.state &= ~(HIDDEN|SYNCLINE);
222da2e3ebdSchin 				if (error_info.line)
223da2e3ebdSchin 					(*pp.linesync)(error_info.line, error_info.file);
224da2e3ebdSchin 			}
225da2e3ebdSchin 			else
226da2e3ebdSchin 			{
227da2e3ebdSchin 				m = pp.hidden;
228da2e3ebdSchin 				pp.hidden = 0;
229da2e3ebdSchin 				pp.state &= ~HIDDEN;
230da2e3ebdSchin 				while (m-- > 0)
231da2e3ebdSchin 					ppputchar('\n');
232da2e3ebdSchin 			}
233da2e3ebdSchin 		}
234da2e3ebdSchin 		else
235da2e3ebdSchin 		{
236da2e3ebdSchin 			pp.hidden = 0;
237da2e3ebdSchin 			pp.state &= ~HIDDEN;
238da2e3ebdSchin 			ppputchar('\n');
239da2e3ebdSchin 		}
240da2e3ebdSchin 	}
241da2e3ebdSchin 	return 0;
242da2e3ebdSchin }
243