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