xref: /titanic_54/usr/src/contrib/ast/src/lib/libpp/ppcontrol.c (revision 906afcb89d0412cc073b95c2d701a804a8cdb62c)
1*906afcb8SAndy Fiddaman /***********************************************************************
2*906afcb8SAndy Fiddaman *                                                                      *
3*906afcb8SAndy Fiddaman *               This software is part of the ast package               *
4*906afcb8SAndy Fiddaman *          Copyright (c) 1986-2011 AT&T Intellectual Property          *
5*906afcb8SAndy Fiddaman *                      and is licensed under the                       *
6*906afcb8SAndy Fiddaman *                 Eclipse Public License, Version 1.0                  *
7*906afcb8SAndy Fiddaman *                    by AT&T Intellectual Property                     *
8*906afcb8SAndy Fiddaman *                                                                      *
9*906afcb8SAndy Fiddaman *                A copy of the License is available at                 *
10*906afcb8SAndy Fiddaman *          http://www.eclipse.org/org/documents/epl-v10.html           *
11*906afcb8SAndy Fiddaman *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
12*906afcb8SAndy Fiddaman *                                                                      *
13*906afcb8SAndy Fiddaman *              Information and Software Systems Research               *
14*906afcb8SAndy Fiddaman *                            AT&T Research                             *
15*906afcb8SAndy Fiddaman *                           Florham Park NJ                            *
16*906afcb8SAndy Fiddaman *                                                                      *
17*906afcb8SAndy Fiddaman *                 Glenn Fowler <gsf@research.att.com>                  *
18*906afcb8SAndy Fiddaman *                                                                      *
19*906afcb8SAndy Fiddaman ***********************************************************************/
20*906afcb8SAndy Fiddaman #pragma prototyped
21*906afcb8SAndy Fiddaman /*
22*906afcb8SAndy Fiddaman  * Glenn Fowler
23*906afcb8SAndy Fiddaman  * AT&T Research
24*906afcb8SAndy Fiddaman  *
25*906afcb8SAndy Fiddaman  * preprocessor control directive support
26*906afcb8SAndy Fiddaman  */
27*906afcb8SAndy Fiddaman 
28*906afcb8SAndy Fiddaman #include "pplib.h"
29*906afcb8SAndy Fiddaman 
30*906afcb8SAndy Fiddaman #include <regex.h>
31*906afcb8SAndy Fiddaman 
32*906afcb8SAndy Fiddaman #define TOKOP_DUP	(1<<0)
33*906afcb8SAndy Fiddaman #define TOKOP_STRING	(1<<1)
34*906afcb8SAndy Fiddaman #define TOKOP_UNSET	(1<<2)
35*906afcb8SAndy Fiddaman 
36*906afcb8SAndy Fiddaman struct edit
37*906afcb8SAndy Fiddaman {
38*906afcb8SAndy Fiddaman 	struct edit*	next;
39*906afcb8SAndy Fiddaman 	regex_t		re;
40*906afcb8SAndy Fiddaman };
41*906afcb8SAndy Fiddaman 
42*906afcb8SAndy Fiddaman struct map
43*906afcb8SAndy Fiddaman {
44*906afcb8SAndy Fiddaman 	struct map*	next;
45*906afcb8SAndy Fiddaman 	regex_t		re;
46*906afcb8SAndy Fiddaman 	struct edit*	edit;
47*906afcb8SAndy Fiddaman };
48*906afcb8SAndy Fiddaman 
49*906afcb8SAndy Fiddaman #define RESTORE		(COLLECTING|CONDITIONAL|DEFINITION|DIRECTIVE|DISABLE|EOF2NL|HEADER|NOSPACE|NOVERTICAL|PASSEOF|STRIP)
50*906afcb8SAndy Fiddaman 
51*906afcb8SAndy Fiddaman /*
52*906afcb8SAndy Fiddaman  * common predicate assertion operations
53*906afcb8SAndy Fiddaman  * op is DEFINE or UNDEF
54*906afcb8SAndy Fiddaman  */
55*906afcb8SAndy Fiddaman 
56*906afcb8SAndy Fiddaman static void
assert(int op,char * pred,char * args)57*906afcb8SAndy Fiddaman assert(int op, char* pred, char* args)
58*906afcb8SAndy Fiddaman {
59*906afcb8SAndy Fiddaman 	register struct pplist*		a;
60*906afcb8SAndy Fiddaman 	register struct ppsymbol*	sym;
61*906afcb8SAndy Fiddaman 	register struct pplist*		p;
62*906afcb8SAndy Fiddaman 	register struct pplist*		q;
63*906afcb8SAndy Fiddaman 
64*906afcb8SAndy Fiddaman 	if (!args) switch (op)
65*906afcb8SAndy Fiddaman 	{
66*906afcb8SAndy Fiddaman 	case DEFINE:
67*906afcb8SAndy Fiddaman 		goto mark;
68*906afcb8SAndy Fiddaman 	case UNDEF:
69*906afcb8SAndy Fiddaman 		a = 0;
70*906afcb8SAndy Fiddaman 		goto unmark;
71*906afcb8SAndy Fiddaman 	}
72*906afcb8SAndy Fiddaman 	if (a = (struct pplist*)hashget(pp.prdtab, pred))
73*906afcb8SAndy Fiddaman 	{
74*906afcb8SAndy Fiddaman 		p = 0;
75*906afcb8SAndy Fiddaman 		q = a;
76*906afcb8SAndy Fiddaman 		while (q)
77*906afcb8SAndy Fiddaman 		{
78*906afcb8SAndy Fiddaman 			if (streq(q->value, args))
79*906afcb8SAndy Fiddaman 			{
80*906afcb8SAndy Fiddaman 				if (op == DEFINE) return;
81*906afcb8SAndy Fiddaman 				q = q->next;
82*906afcb8SAndy Fiddaman 				if (p) p->next = q;
83*906afcb8SAndy Fiddaman 				else a = q;
84*906afcb8SAndy Fiddaman 			}
85*906afcb8SAndy Fiddaman 			else
86*906afcb8SAndy Fiddaman 			{
87*906afcb8SAndy Fiddaman 				p = q;
88*906afcb8SAndy Fiddaman 				q = q->next;
89*906afcb8SAndy Fiddaman 			}
90*906afcb8SAndy Fiddaman 		}
91*906afcb8SAndy Fiddaman 		if (op == UNDEF)
92*906afcb8SAndy Fiddaman 		{
93*906afcb8SAndy Fiddaman 		unmark:
94*906afcb8SAndy Fiddaman 			hashput(pp.prdtab, pred, a);
95*906afcb8SAndy Fiddaman 			if (sym = ppsymref(pp.symtab, pred))
96*906afcb8SAndy Fiddaman 				sym->flags &= ~SYM_PREDICATE;
97*906afcb8SAndy Fiddaman 			return;
98*906afcb8SAndy Fiddaman 		}
99*906afcb8SAndy Fiddaman 	}
100*906afcb8SAndy Fiddaman 	if (op == DEFINE)
101*906afcb8SAndy Fiddaman 	{
102*906afcb8SAndy Fiddaman 		p = newof(0, struct pplist, 1, 0);
103*906afcb8SAndy Fiddaman 		p->next = a;
104*906afcb8SAndy Fiddaman 		p->value = strdup(args);
105*906afcb8SAndy Fiddaman 		hashput(pp.prdtab, NiL, p);
106*906afcb8SAndy Fiddaman 	mark:
107*906afcb8SAndy Fiddaman 		if ((pp.state & COMPILE) && pp.truncate) return;
108*906afcb8SAndy Fiddaman 		if (sym = ppsymset(pp.symtab, pred))
109*906afcb8SAndy Fiddaman 			sym->flags |= SYM_PREDICATE;
110*906afcb8SAndy Fiddaman 	}
111*906afcb8SAndy Fiddaman }
112*906afcb8SAndy Fiddaman 
113*906afcb8SAndy Fiddaman /*
114*906afcb8SAndy Fiddaman  * tokenize string ppop()
115*906afcb8SAndy Fiddaman  *
116*906afcb8SAndy Fiddaman  *	op	PP_* op
117*906afcb8SAndy Fiddaman  *	name	option name
118*906afcb8SAndy Fiddaman  *	s	string of option values
119*906afcb8SAndy Fiddaman  *	n	option sense
120*906afcb8SAndy Fiddaman  *	flags	TOKOP_* flags
121*906afcb8SAndy Fiddaman  */
122*906afcb8SAndy Fiddaman 
123*906afcb8SAndy Fiddaman static void
tokop(int op,char * name,register char * s,register int n,int flags)124*906afcb8SAndy Fiddaman tokop(int op, char* name, register char* s, register int n, int flags)
125*906afcb8SAndy Fiddaman {
126*906afcb8SAndy Fiddaman 	register int	c;
127*906afcb8SAndy Fiddaman 	register char*	t;
128*906afcb8SAndy Fiddaman 
129*906afcb8SAndy Fiddaman 	if (!(flags & TOKOP_UNSET) && !n) error(2, "%s: option cannot be unset", name);
130*906afcb8SAndy Fiddaman 	else if (!s) ppop(op, s, n);
131*906afcb8SAndy Fiddaman 	else if (flags & TOKOP_STRING)
132*906afcb8SAndy Fiddaman 	{
133*906afcb8SAndy Fiddaman 		PUSH_LINE(s);
134*906afcb8SAndy Fiddaman 		for (;;)
135*906afcb8SAndy Fiddaman 		{
136*906afcb8SAndy Fiddaman 			pp.state &= ~NOSPACE;
137*906afcb8SAndy Fiddaman 			c = pplex();
138*906afcb8SAndy Fiddaman 			pp.state |= NOSPACE;
139*906afcb8SAndy Fiddaman 			if (!c) break;
140*906afcb8SAndy Fiddaman 			if (c != ' ')
141*906afcb8SAndy Fiddaman 				ppop(op, (flags & TOKOP_DUP) ? strdup(pp.token) : pp.token, n);
142*906afcb8SAndy Fiddaman 		}
143*906afcb8SAndy Fiddaman 		POP_LINE();
144*906afcb8SAndy Fiddaman 	}
145*906afcb8SAndy Fiddaman 	else do
146*906afcb8SAndy Fiddaman 	{
147*906afcb8SAndy Fiddaman 		while (*s == ' ') s++;
148*906afcb8SAndy Fiddaman 		for (t = s; *t && *t != ' '; t++);
149*906afcb8SAndy Fiddaman 		if (*t) *t++ = 0;
150*906afcb8SAndy Fiddaman 		else t = 0;
151*906afcb8SAndy Fiddaman 		if (*s) ppop(op, (flags & TOKOP_DUP) ? strdup(s) : s, n);
152*906afcb8SAndy Fiddaman 	} while (s = t);
153*906afcb8SAndy Fiddaman }
154*906afcb8SAndy Fiddaman 
155*906afcb8SAndy Fiddaman /*
156*906afcb8SAndy Fiddaman  * return symbol pointer for next token macro (re)definition
157*906afcb8SAndy Fiddaman  */
158*906afcb8SAndy Fiddaman 
159*906afcb8SAndy Fiddaman static struct ppsymbol*
macsym(int tok)160*906afcb8SAndy Fiddaman macsym(int tok)
161*906afcb8SAndy Fiddaman {
162*906afcb8SAndy Fiddaman 	register struct ppsymbol*	sym;
163*906afcb8SAndy Fiddaman 
164*906afcb8SAndy Fiddaman 	if (tok != T_ID)
165*906afcb8SAndy Fiddaman 	{
166*906afcb8SAndy Fiddaman 		error(2, "%s: invalid macro name", pptokstr(pp.token, 0));
167*906afcb8SAndy Fiddaman 		return 0;
168*906afcb8SAndy Fiddaman 	}
169*906afcb8SAndy Fiddaman 	sym = pprefmac(pp.token, REF_CREATE);
170*906afcb8SAndy Fiddaman 	if ((sym->flags & SYM_FINAL) && (pp.mode & HOSTED)) return 0;
171*906afcb8SAndy Fiddaman 	if (sym->flags & (SYM_ACTIVE|SYM_READONLY))
172*906afcb8SAndy Fiddaman 	{
173*906afcb8SAndy Fiddaman 		if (!(pp.option & ALLPOSSIBLE))
174*906afcb8SAndy Fiddaman 			error(2, "%s: macro is %s", sym->name, (sym->flags & SYM_READONLY) ? "readonly" : "active");
175*906afcb8SAndy Fiddaman 		return 0;
176*906afcb8SAndy Fiddaman 	}
177*906afcb8SAndy Fiddaman 	if (!sym->macro) sym->macro = newof(0, struct ppmacro, 1, 0);
178*906afcb8SAndy Fiddaman 	return sym;
179*906afcb8SAndy Fiddaman }
180*906afcb8SAndy Fiddaman 
181*906afcb8SAndy Fiddaman /*
182*906afcb8SAndy Fiddaman  * get one space canonical pplex() line, sans '\n', and place in p
183*906afcb8SAndy Fiddaman  * x is max+1 pos in p
184*906afcb8SAndy Fiddaman  * 0 returned if line too large
185*906afcb8SAndy Fiddaman  * otherwise end of p ('\0') returned
186*906afcb8SAndy Fiddaman  */
187*906afcb8SAndy Fiddaman 
188*906afcb8SAndy Fiddaman static char*
getline(register char * p,char * x,int disable)189*906afcb8SAndy Fiddaman getline(register char* p, char* x, int disable)
190*906afcb8SAndy Fiddaman {
191*906afcb8SAndy Fiddaman 	register int	c;
192*906afcb8SAndy Fiddaman 	register char*	s;
193*906afcb8SAndy Fiddaman 	char*		b;
194*906afcb8SAndy Fiddaman 	long		restore;
195*906afcb8SAndy Fiddaman 
196*906afcb8SAndy Fiddaman 	restore = pp.state & (NOSPACE|STRIP);
197*906afcb8SAndy Fiddaman 	pp.state &= ~(NEWLINE|NOSPACE|STRIP);
198*906afcb8SAndy Fiddaman 	pp.state |= EOF2NL;
199*906afcb8SAndy Fiddaman 	b = p;
200*906afcb8SAndy Fiddaman 	while ((c = pplex()) != '\n')
201*906afcb8SAndy Fiddaman 	{
202*906afcb8SAndy Fiddaman 		if (disable)
203*906afcb8SAndy Fiddaman 		{
204*906afcb8SAndy Fiddaman 			if (c == ' ')
205*906afcb8SAndy Fiddaman 				/*ignore*/;
206*906afcb8SAndy Fiddaman 			else if (disable == 1)
207*906afcb8SAndy Fiddaman 				disable = (c == T_ID && streq(pp.token, pp.pass)) ? 2 : 0;
208*906afcb8SAndy Fiddaman 			else
209*906afcb8SAndy Fiddaman 			{
210*906afcb8SAndy Fiddaman 				disable = 0;
211*906afcb8SAndy Fiddaman 				if (c == ':')
212*906afcb8SAndy Fiddaman 					pp.state |= DISABLE;
213*906afcb8SAndy Fiddaman 			}
214*906afcb8SAndy Fiddaman 		}
215*906afcb8SAndy Fiddaman 		s = pp.token;
216*906afcb8SAndy Fiddaman 		while (*p = *s++)
217*906afcb8SAndy Fiddaman 			if (++p >= x)
218*906afcb8SAndy Fiddaman 			{
219*906afcb8SAndy Fiddaman 				p = 0;
220*906afcb8SAndy Fiddaman 				goto done;
221*906afcb8SAndy Fiddaman 			}
222*906afcb8SAndy Fiddaman 	}
223*906afcb8SAndy Fiddaman 	if (p > b && *(p - 1) == ' ')
224*906afcb8SAndy Fiddaman 		p--;
225*906afcb8SAndy Fiddaman 	if (p >= x)
226*906afcb8SAndy Fiddaman 		p = 0;
227*906afcb8SAndy Fiddaman 	else
228*906afcb8SAndy Fiddaman 		*p = 0;
229*906afcb8SAndy Fiddaman  done:
230*906afcb8SAndy Fiddaman 	pp.state &= ~(NOSPACE|STRIP);
231*906afcb8SAndy Fiddaman 	pp.state |= restore;
232*906afcb8SAndy Fiddaman 	return p;
233*906afcb8SAndy Fiddaman }
234*906afcb8SAndy Fiddaman 
235*906afcb8SAndy Fiddaman /*
236*906afcb8SAndy Fiddaman  * regex error handler
237*906afcb8SAndy Fiddaman  */
238*906afcb8SAndy Fiddaman 
239*906afcb8SAndy Fiddaman void
regfatal(regex_t * p,int level,int code)240*906afcb8SAndy Fiddaman regfatal(regex_t* p, int level, int code)
241*906afcb8SAndy Fiddaman {
242*906afcb8SAndy Fiddaman 	char	buf[128];
243*906afcb8SAndy Fiddaman 
244*906afcb8SAndy Fiddaman 	regerror(code, p, buf, sizeof(buf));
245*906afcb8SAndy Fiddaman 	regfree(p);
246*906afcb8SAndy Fiddaman 	error(level, "regular expression: %s", buf);
247*906afcb8SAndy Fiddaman }
248*906afcb8SAndy Fiddaman 
249*906afcb8SAndy Fiddaman /*
250*906afcb8SAndy Fiddaman  * process a single directive line
251*906afcb8SAndy Fiddaman  */
252*906afcb8SAndy Fiddaman 
253*906afcb8SAndy Fiddaman int
ppcontrol(void)254*906afcb8SAndy Fiddaman ppcontrol(void)
255*906afcb8SAndy Fiddaman {
256*906afcb8SAndy Fiddaman 	register char*			p;
257*906afcb8SAndy Fiddaman 	register int			c;
258*906afcb8SAndy Fiddaman 	register int			n;
259*906afcb8SAndy Fiddaman 	register char*			s;
260*906afcb8SAndy Fiddaman 	register struct ppmacro*	mac;
261*906afcb8SAndy Fiddaman 	register struct ppsymbol*	sym;
262*906afcb8SAndy Fiddaman 	struct edit*			edit;
263*906afcb8SAndy Fiddaman 	struct map*			map;
264*906afcb8SAndy Fiddaman 	struct ppfile*			fp;
265*906afcb8SAndy Fiddaman 	int				o;
266*906afcb8SAndy Fiddaman 	int				directive;
267*906afcb8SAndy Fiddaman 	long				restore;
268*906afcb8SAndy Fiddaman 	struct pptuple*			rp;
269*906afcb8SAndy Fiddaman 	struct pptuple*			tp;
270*906afcb8SAndy Fiddaman 	char*				v;
271*906afcb8SAndy Fiddaman 	int				emitted;
272*906afcb8SAndy Fiddaman 
273*906afcb8SAndy Fiddaman 	union
274*906afcb8SAndy Fiddaman 	{
275*906afcb8SAndy Fiddaman 		struct map*		best;
276*906afcb8SAndy Fiddaman 		struct ppinstk*		inp;
277*906afcb8SAndy Fiddaman 		struct pplist*		list;
278*906afcb8SAndy Fiddaman 		char*			string;
279*906afcb8SAndy Fiddaman 		struct ppsymbol*	symbol;
280*906afcb8SAndy Fiddaman 		int			type;
281*906afcb8SAndy Fiddaman 		PPLINESYNC		linesync;
282*906afcb8SAndy Fiddaman 	}				var;
283*906afcb8SAndy Fiddaman 
284*906afcb8SAndy Fiddaman 	static char			__va_args__[] = "__VA_ARGS__";
285*906afcb8SAndy Fiddaman 	static int			i0;
286*906afcb8SAndy Fiddaman 	static int			i1;
287*906afcb8SAndy Fiddaman 	static int			i2;
288*906afcb8SAndy Fiddaman 	static int			i3;
289*906afcb8SAndy Fiddaman 	static int			i4;
290*906afcb8SAndy Fiddaman 
291*906afcb8SAndy Fiddaman 	static long			n1;
292*906afcb8SAndy Fiddaman 	static long			n2;
293*906afcb8SAndy Fiddaman 	static long			n3;
294*906afcb8SAndy Fiddaman 
295*906afcb8SAndy Fiddaman 	static char*			p0;
296*906afcb8SAndy Fiddaman 	static char*			p1;
297*906afcb8SAndy Fiddaman 	static char*			p2;
298*906afcb8SAndy Fiddaman 	static char*			p3;
299*906afcb8SAndy Fiddaman 	static char*			p4;
300*906afcb8SAndy Fiddaman 	static char*			p5;
301*906afcb8SAndy Fiddaman 	static char*			p6;
302*906afcb8SAndy Fiddaman 
303*906afcb8SAndy Fiddaman 	static struct ppmacro		old;
304*906afcb8SAndy Fiddaman 	static char*			formargs[MAXFORMALS];
305*906afcb8SAndy Fiddaman #if MACKEYARGS
306*906afcb8SAndy Fiddaman 	static char*			formvals[MAXFORMALS];
307*906afcb8SAndy Fiddaman #endif
308*906afcb8SAndy Fiddaman 
309*906afcb8SAndy Fiddaman 	emitted = 0;
310*906afcb8SAndy Fiddaman 	if (pp.state & SKIPCONTROL) pp.level--;
311*906afcb8SAndy Fiddaman 	restore = (pp.state & RESTORE)|NEWLINE;
312*906afcb8SAndy Fiddaman 	if (pp.state & PASSTHROUGH) restore |= DISABLE;
313*906afcb8SAndy Fiddaman 	else restore &= ~DISABLE;
314*906afcb8SAndy Fiddaman 	pp.state &= ~(NEWLINE|RESTORE|SKIPCONTROL);
315*906afcb8SAndy Fiddaman 	pp.state |= DIRECTIVE|DISABLE|EOF2NL|NOSPACE|NOVERTICAL;
316*906afcb8SAndy Fiddaman #if COMPATIBLE
317*906afcb8SAndy Fiddaman 	if ((pp.state & (COMPATIBILITY|STRICT)) == COMPATIBILITY || (pp.mode & HOSTED)) pp.state &= ~NOVERTICAL;
318*906afcb8SAndy Fiddaman #else
319*906afcb8SAndy Fiddaman 	if (pp.mode & HOSTED) pp.state &= ~NOVERTICAL;
320*906afcb8SAndy Fiddaman #endif
321*906afcb8SAndy Fiddaman 	switch (c = pplex())
322*906afcb8SAndy Fiddaman 	{
323*906afcb8SAndy Fiddaman 	case T_DECIMAL:
324*906afcb8SAndy Fiddaman 	case T_OCTAL:
325*906afcb8SAndy Fiddaman 		if ((pp.state & STRICT) && !(pp.mode & (HOSTED|RELAX)))
326*906afcb8SAndy Fiddaman 			error(1, "# <line> [ \"<file>\" [ <type> ] ]: non-standard directive");
327*906afcb8SAndy Fiddaman 		directive = INCLUDE;
328*906afcb8SAndy Fiddaman 		goto linesync;
329*906afcb8SAndy Fiddaman 	case T_ID:
330*906afcb8SAndy Fiddaman 		switch (directive = (int)hashref(pp.dirtab, pp.token))
331*906afcb8SAndy Fiddaman 		{
332*906afcb8SAndy Fiddaman 		case ELIF:
333*906afcb8SAndy Fiddaman 		else_if:
334*906afcb8SAndy Fiddaman 			if ((pp.option & ALLPOSSIBLE) && !pp.in->prev->prev)
335*906afcb8SAndy Fiddaman 				goto eatdirective;
336*906afcb8SAndy Fiddaman 			if (pp.control <= pp.in->control)
337*906afcb8SAndy Fiddaman 			{
338*906afcb8SAndy Fiddaman 				error(2, "no matching #%s for #%s", dirname(IF), dirname(ELIF));
339*906afcb8SAndy Fiddaman 				goto eatdirective;
340*906afcb8SAndy Fiddaman 			}
341*906afcb8SAndy Fiddaman 			if (pp.control == (pp.in->control + 1)) pp.in->flags |= IN_noguard;
342*906afcb8SAndy Fiddaman 			if (*pp.control & HADELSE)
343*906afcb8SAndy Fiddaman 			{
344*906afcb8SAndy Fiddaman 				error(2, "invalid #%s after #%s", dirname(ELIF), dirname(ELSE));
345*906afcb8SAndy Fiddaman 				*pp.control |= SKIP;
346*906afcb8SAndy Fiddaman 				goto eatdirective;
347*906afcb8SAndy Fiddaman 			}
348*906afcb8SAndy Fiddaman 			if (*pp.control & KEPT)
349*906afcb8SAndy Fiddaman 			{
350*906afcb8SAndy Fiddaman 				*pp.control |= SKIP;
351*906afcb8SAndy Fiddaman 				goto eatdirective;
352*906afcb8SAndy Fiddaman 			}
353*906afcb8SAndy Fiddaman 			if (directive == IFDEF || directive == IFNDEF)
354*906afcb8SAndy Fiddaman 			{
355*906afcb8SAndy Fiddaman 				*pp.control &= ~SKIP;
356*906afcb8SAndy Fiddaman 				goto else_ifdef;
357*906afcb8SAndy Fiddaman 			}
358*906afcb8SAndy Fiddaman 		conditional:
359*906afcb8SAndy Fiddaman 			if (ppexpr(&i1))
360*906afcb8SAndy Fiddaman 			{
361*906afcb8SAndy Fiddaman 				*pp.control &= ~SKIP;
362*906afcb8SAndy Fiddaman 				*pp.control |= KEPT;
363*906afcb8SAndy Fiddaman 			}
364*906afcb8SAndy Fiddaman 			else *pp.control |= SKIP;
365*906afcb8SAndy Fiddaman 			c = (pp.state & NEWLINE) ? '\n' : ' ';
366*906afcb8SAndy Fiddaman 			goto eatdirective;
367*906afcb8SAndy Fiddaman 		case ELSE:
368*906afcb8SAndy Fiddaman 			if ((pp.option & ALLPOSSIBLE) && !pp.in->prev->prev)
369*906afcb8SAndy Fiddaman 				goto eatdirective;
370*906afcb8SAndy Fiddaman 			if ((pp.option & ELSEIF) && (c = pplex()) == T_ID && ((n = (int)hashref(pp.dirtab, pp.token)) == IF || n == IFDEF || n == IFNDEF))
371*906afcb8SAndy Fiddaman 			{
372*906afcb8SAndy Fiddaman 				error(1, "#%s %s is non-standard -- use #%s", dirname(directive), dirname(n), dirname(ELIF));
373*906afcb8SAndy Fiddaman 				directive = n;
374*906afcb8SAndy Fiddaman 				goto else_if;
375*906afcb8SAndy Fiddaman 			}
376*906afcb8SAndy Fiddaman 			if (pp.control <= pp.in->control) error(2, "no matching #%s for #%s", dirname(IF), dirname(ELSE));
377*906afcb8SAndy Fiddaman 			else
378*906afcb8SAndy Fiddaman 			{
379*906afcb8SAndy Fiddaman 				if (pp.control == (pp.in->control + 1)) pp.in->flags |= IN_noguard;
380*906afcb8SAndy Fiddaman 				if (!(*pp.control & KEPT))
381*906afcb8SAndy Fiddaman 				{
382*906afcb8SAndy Fiddaman 					*pp.control &= ~SKIP;
383*906afcb8SAndy Fiddaman 					*pp.control |= HADELSE|KEPT;
384*906afcb8SAndy Fiddaman 				}
385*906afcb8SAndy Fiddaman 				else
386*906afcb8SAndy Fiddaman 				{
387*906afcb8SAndy Fiddaman 					if (*pp.control & HADELSE) error(2, "more than one #%s for #%s", dirname(ELSE), dirname(IF));
388*906afcb8SAndy Fiddaman 					*pp.control |= HADELSE|SKIP;
389*906afcb8SAndy Fiddaman 				}
390*906afcb8SAndy Fiddaman 			}
391*906afcb8SAndy Fiddaman 			goto enddirective;
392*906afcb8SAndy Fiddaman 		case ENDIF:
393*906afcb8SAndy Fiddaman 			if ((pp.option & ALLPOSSIBLE) && !pp.in->prev->prev)
394*906afcb8SAndy Fiddaman 				goto eatdirective;
395*906afcb8SAndy Fiddaman 			if (pp.control <= pp.in->control) error(2, "no matching #%s for #%s", dirname(IF), dirname(ENDIF));
396*906afcb8SAndy Fiddaman 			else if (--pp.control == pp.in->control && pp.in->symbol)
397*906afcb8SAndy Fiddaman 			{
398*906afcb8SAndy Fiddaman 				if (pp.in->flags & IN_endguard) pp.in->flags |= IN_noguard;
399*906afcb8SAndy Fiddaman 				else
400*906afcb8SAndy Fiddaman 				{
401*906afcb8SAndy Fiddaman 					pp.in->flags &= ~IN_tokens;
402*906afcb8SAndy Fiddaman 					pp.in->flags |= IN_endguard;
403*906afcb8SAndy Fiddaman 				}
404*906afcb8SAndy Fiddaman 			}
405*906afcb8SAndy Fiddaman 			goto enddirective;
406*906afcb8SAndy Fiddaman 		case IF:
407*906afcb8SAndy Fiddaman 		case IFDEF:
408*906afcb8SAndy Fiddaman 		case IFNDEF:
409*906afcb8SAndy Fiddaman 			if ((pp.option & ALLPOSSIBLE) && !pp.in->prev->prev)
410*906afcb8SAndy Fiddaman 				goto eatdirective;
411*906afcb8SAndy Fiddaman 			pushcontrol();
412*906afcb8SAndy Fiddaman 			SETIFBLOCK(pp.control);
413*906afcb8SAndy Fiddaman 			if (*pp.control & SKIP)
414*906afcb8SAndy Fiddaman 			{
415*906afcb8SAndy Fiddaman 				*pp.control |= KEPT;
416*906afcb8SAndy Fiddaman 				goto eatdirective;
417*906afcb8SAndy Fiddaman 			}
418*906afcb8SAndy Fiddaman 			if (directive == IF) goto conditional;
419*906afcb8SAndy Fiddaman 		else_ifdef:
420*906afcb8SAndy Fiddaman 			if ((c = pplex()) == T_ID)
421*906afcb8SAndy Fiddaman 			{
422*906afcb8SAndy Fiddaman 				sym = pprefmac(pp.token, REF_IF);
423*906afcb8SAndy Fiddaman 				if (directive == IFNDEF && pp.control == pp.in->control + 1)
424*906afcb8SAndy Fiddaman 				{
425*906afcb8SAndy Fiddaman 					if (pp.in->flags & (IN_defguard|IN_endguard))
426*906afcb8SAndy Fiddaman 						pp.in->flags |= IN_noguard;
427*906afcb8SAndy Fiddaman 					else
428*906afcb8SAndy Fiddaman 					{
429*906afcb8SAndy Fiddaman 						pp.in->flags |= IN_defguard;
430*906afcb8SAndy Fiddaman 						if (!(pp.in->flags & IN_tokens))
431*906afcb8SAndy Fiddaman 							pp.in->symbol = sym ? sym : pprefmac(pp.token, REF_CREATE);
432*906afcb8SAndy Fiddaman 					}
433*906afcb8SAndy Fiddaman 				}
434*906afcb8SAndy Fiddaman 			}
435*906afcb8SAndy Fiddaman 			else
436*906afcb8SAndy Fiddaman 			{
437*906afcb8SAndy Fiddaman 				sym = 0;
438*906afcb8SAndy Fiddaman 				if (!(pp.mode & HOSTED))
439*906afcb8SAndy Fiddaman 					error(1, "%s: invalid macro name", pptokstr(pp.token, 0));
440*906afcb8SAndy Fiddaman 			}
441*906afcb8SAndy Fiddaman 			*pp.control |= ((sym != 0) == (directive == IFDEF)) ? KEPT : SKIP;
442*906afcb8SAndy Fiddaman 			goto enddirective;
443*906afcb8SAndy Fiddaman 		case INCLUDE:
444*906afcb8SAndy Fiddaman 			if (*pp.control & SKIP)
445*906afcb8SAndy Fiddaman 			{
446*906afcb8SAndy Fiddaman 				pp.state |= HEADER;
447*906afcb8SAndy Fiddaman 				c = pplex();
448*906afcb8SAndy Fiddaman 				pp.state &= ~HEADER;
449*906afcb8SAndy Fiddaman 				goto eatdirective;
450*906afcb8SAndy Fiddaman 			}
451*906afcb8SAndy Fiddaman 			pp.state &= ~DISABLE;
452*906afcb8SAndy Fiddaman 			pp.state |= HEADER|STRIP;
453*906afcb8SAndy Fiddaman 			pp.in->flags |= IN_noguard;
454*906afcb8SAndy Fiddaman 			switch (c = pplex())
455*906afcb8SAndy Fiddaman 			{
456*906afcb8SAndy Fiddaman 			case T_STRING:
457*906afcb8SAndy Fiddaman 				p = pp.token;
458*906afcb8SAndy Fiddaman 				do pp.token = pp.toknxt; while ((c = pplex()) == T_STRING);
459*906afcb8SAndy Fiddaman 				*pp.token = 0;
460*906afcb8SAndy Fiddaman 				pp.token = p;
461*906afcb8SAndy Fiddaman 				/*FALLTHROUGH*/
462*906afcb8SAndy Fiddaman 			case T_HEADER:
463*906afcb8SAndy Fiddaman 			header:
464*906afcb8SAndy Fiddaman 				if (!*pp.token)
465*906afcb8SAndy Fiddaman 				{
466*906afcb8SAndy Fiddaman 					error(2, "#%s: null file name", dirname(INCLUDE));
467*906afcb8SAndy Fiddaman 					break;
468*906afcb8SAndy Fiddaman 				}
469*906afcb8SAndy Fiddaman 				if (*pp.token == '/' && !(pp.mode & (HOSTED|RELAX)))
470*906afcb8SAndy Fiddaman 					error(1, "#%s: reference to %s is not portable", dirname(INCLUDE), pp.token);
471*906afcb8SAndy Fiddaman 				n = ppsearch(pp.token, c, SEARCH_INCLUDE);
472*906afcb8SAndy Fiddaman 				break;
473*906afcb8SAndy Fiddaman 			case '<':
474*906afcb8SAndy Fiddaman 				/*
475*906afcb8SAndy Fiddaman 				 * HEADEREXPAND|HEADEREXPANDALL gets us here
476*906afcb8SAndy Fiddaman 				 */
477*906afcb8SAndy Fiddaman 
478*906afcb8SAndy Fiddaman 				if (!(p = pp.hdrbuf) && !(p = pp.hdrbuf = newof(0, char, MAXTOKEN, 0)))
479*906afcb8SAndy Fiddaman 					error(3, "out of space");
480*906afcb8SAndy Fiddaman 				pp.state &= ~NOSPACE;
481*906afcb8SAndy Fiddaman 				while ((c = pplex()) && c != '>')
482*906afcb8SAndy Fiddaman 				{
483*906afcb8SAndy Fiddaman 					v = p + 1;
484*906afcb8SAndy Fiddaman 					STRCOPY(p, pp.token, s);
485*906afcb8SAndy Fiddaman 					if (p == v && *(p - 1) == ' ' && pp.in->type != IN_MACRO)
486*906afcb8SAndy Fiddaman 						p--;
487*906afcb8SAndy Fiddaman 				}
488*906afcb8SAndy Fiddaman 				pp.state |= NOSPACE;
489*906afcb8SAndy Fiddaman 				*p++ = 0;
490*906afcb8SAndy Fiddaman 				memcpy(pp.token, pp.hdrbuf, p - pp.hdrbuf);
491*906afcb8SAndy Fiddaman 				c = T_HEADER;
492*906afcb8SAndy Fiddaman 				goto header;
493*906afcb8SAndy Fiddaman 			default:
494*906afcb8SAndy Fiddaman 				error(2, "#%s: \"...\" or <...> argument expected", dirname(INCLUDE));
495*906afcb8SAndy Fiddaman 				goto eatdirective;
496*906afcb8SAndy Fiddaman 			}
497*906afcb8SAndy Fiddaman 			goto enddirective;
498*906afcb8SAndy Fiddaman 		case 0:
499*906afcb8SAndy Fiddaman 			{
500*906afcb8SAndy Fiddaman 				regmatch_t	match[10];
501*906afcb8SAndy Fiddaman 
502*906afcb8SAndy Fiddaman 				/*UNDENT*/
503*906afcb8SAndy Fiddaman 	p = pp.valbuf;
504*906afcb8SAndy Fiddaman 	*p++ = '#';
505*906afcb8SAndy Fiddaman 	STRCOPY(p, pp.token, s);
506*906afcb8SAndy Fiddaman 	p0 = p;
507*906afcb8SAndy Fiddaman 	pp.mode |= EXPOSE;
508*906afcb8SAndy Fiddaman 	pp.state |= HEADER;
509*906afcb8SAndy Fiddaman 	p6 = getline(p, &pp.valbuf[MAXTOKEN], 0);
510*906afcb8SAndy Fiddaman 	pp.state &= ~HEADER;
511*906afcb8SAndy Fiddaman 	pp.mode &= ~EXPOSE;
512*906afcb8SAndy Fiddaman 	if (!p6)
513*906afcb8SAndy Fiddaman 	{
514*906afcb8SAndy Fiddaman 		*p0 = 0;
515*906afcb8SAndy Fiddaman 		error(2, "%s: directive too long", pp.valbuf);
516*906afcb8SAndy Fiddaman 		c = 0;
517*906afcb8SAndy Fiddaman 		goto eatdirective;
518*906afcb8SAndy Fiddaman 	}
519*906afcb8SAndy Fiddaman 	p1 = p2 = p3 = p4 = 0;
520*906afcb8SAndy Fiddaman 	p5 = *p ? p + 1 : 0;
521*906afcb8SAndy Fiddaman  checkmap:
522*906afcb8SAndy Fiddaman 	i0 = *p0;
523*906afcb8SAndy Fiddaman 	p = pp.valbuf;
524*906afcb8SAndy Fiddaman 	var.best = 0;
525*906afcb8SAndy Fiddaman 	n = 0;
526*906afcb8SAndy Fiddaman 	for (map = (struct map*)pp.maps; map; map = map->next)
527*906afcb8SAndy Fiddaman 		if (!(i1 = regexec(&map->re, p, elementsof(match), match, 0)))
528*906afcb8SAndy Fiddaman 		{
529*906afcb8SAndy Fiddaman 			if ((c = match[0].rm_eo - match[0].rm_so) > n)
530*906afcb8SAndy Fiddaman 			{
531*906afcb8SAndy Fiddaman 				n = c;
532*906afcb8SAndy Fiddaman 				var.best = map;
533*906afcb8SAndy Fiddaman 			}
534*906afcb8SAndy Fiddaman 		}
535*906afcb8SAndy Fiddaman 		else if (i1 != REG_NOMATCH)
536*906afcb8SAndy Fiddaman 			regfatal(&map->re, 4, i1);
537*906afcb8SAndy Fiddaman 	c = '\n';
538*906afcb8SAndy Fiddaman 	if (map = var.best)
539*906afcb8SAndy Fiddaman 	{
540*906afcb8SAndy Fiddaman 		if ((pp.state & (STRICT|WARN)) && !(pp.mode & (HOSTED|RELAX)))
541*906afcb8SAndy Fiddaman 		{
542*906afcb8SAndy Fiddaman 			*p0 = 0;
543*906afcb8SAndy Fiddaman 			if (!(pp.state & WARN) || strcmp(p + 1, dirname(PRAGMA)))
544*906afcb8SAndy Fiddaman 				error(1, "%s: non-standard directive", p);
545*906afcb8SAndy Fiddaman 			*p0 = i0;
546*906afcb8SAndy Fiddaman 		}
547*906afcb8SAndy Fiddaman 		if (!(*pp.control & SKIP))
548*906afcb8SAndy Fiddaman 		{
549*906afcb8SAndy Fiddaman 			n = 0;
550*906afcb8SAndy Fiddaman 			for (edit = map->edit; edit; edit = edit->next)
551*906afcb8SAndy Fiddaman 				if (!(i0 = regexec(&edit->re, p, elementsof(match), match, 0)))
552*906afcb8SAndy Fiddaman 				{
553*906afcb8SAndy Fiddaman 					n++;
554*906afcb8SAndy Fiddaman 					if (i0 = regsubexec(&edit->re, p, elementsof(match), match))
555*906afcb8SAndy Fiddaman 						regfatal(&edit->re, 4, i0);
556*906afcb8SAndy Fiddaman 					p = edit->re.re_sub->re_buf;
557*906afcb8SAndy Fiddaman 					if (edit->re.re_sub->re_flags & REG_SUB_STOP)
558*906afcb8SAndy Fiddaman 						break;
559*906afcb8SAndy Fiddaman 				}
560*906afcb8SAndy Fiddaman 				else if (i0 != REG_NOMATCH)
561*906afcb8SAndy Fiddaman 					regfatal(&edit->re, 4, i0);
562*906afcb8SAndy Fiddaman 			if (n && *p)
563*906afcb8SAndy Fiddaman 			{
564*906afcb8SAndy Fiddaman 				p1 = s = oldof(0, char, 0, strlen(p) + 32);
565*906afcb8SAndy Fiddaman 				while (*s = *p++) s++;
566*906afcb8SAndy Fiddaman 				debug((-4, "map: %s", p1));
567*906afcb8SAndy Fiddaman 				*s++ = '\n';
568*906afcb8SAndy Fiddaman 				*s = 0;
569*906afcb8SAndy Fiddaman 				error_info.line++;
570*906afcb8SAndy Fiddaman 				PUSH_RESCAN(p1);
571*906afcb8SAndy Fiddaman 				error_info.line--;
572*906afcb8SAndy Fiddaman 				directive = LINE;
573*906afcb8SAndy Fiddaman 			}
574*906afcb8SAndy Fiddaman 		}
575*906afcb8SAndy Fiddaman 		goto donedirective;
576*906afcb8SAndy Fiddaman 	}
577*906afcb8SAndy Fiddaman 	if (directive != PRAGMA && (!(*pp.control & SKIP) || !(pp.mode & (HOSTED|RELAX))))
578*906afcb8SAndy Fiddaman 	{
579*906afcb8SAndy Fiddaman 		*p0 = 0;
580*906afcb8SAndy Fiddaman 		error(1, "%s: unknown directive", pptokstr(pp.valbuf, 0));
581*906afcb8SAndy Fiddaman 		*p0 = i0;
582*906afcb8SAndy Fiddaman 	}
583*906afcb8SAndy Fiddaman  pass:
584*906afcb8SAndy Fiddaman 	if (!(*pp.control & SKIP) && pp.pragma && !(pp.state & NOTEXT) && (directive == PRAGMA || !(pp.mode & INIT)))
585*906afcb8SAndy Fiddaman 	{
586*906afcb8SAndy Fiddaman 		*p0 = 0;
587*906afcb8SAndy Fiddaman 		if (p2) *p2 = 0;
588*906afcb8SAndy Fiddaman 		if (p4)
589*906afcb8SAndy Fiddaman 		{
590*906afcb8SAndy Fiddaman 			if (p4 == p5)
591*906afcb8SAndy Fiddaman 			{
592*906afcb8SAndy Fiddaman 				p5 = strcpy(pp.tmpbuf, p5);
593*906afcb8SAndy Fiddaman 				if (p = strchr(p5, MARK))
594*906afcb8SAndy Fiddaman 				{
595*906afcb8SAndy Fiddaman 					s = p;
596*906afcb8SAndy Fiddaman 					while (*p)
597*906afcb8SAndy Fiddaman 						if ((*s++ = *p++) == MARK && *p == MARK) p++;
598*906afcb8SAndy Fiddaman 					*s = 0;
599*906afcb8SAndy Fiddaman 				}
600*906afcb8SAndy Fiddaman 			}
601*906afcb8SAndy Fiddaman 			*p4 = 0;
602*906afcb8SAndy Fiddaman 		}
603*906afcb8SAndy Fiddaman 		if (p = (char*)memchr(pp.valbuf + 1, MARK, p6 - pp.valbuf - 1))
604*906afcb8SAndy Fiddaman 		{
605*906afcb8SAndy Fiddaman 			s = p;
606*906afcb8SAndy Fiddaman 			while (p < p6) switch (*s++ = *p++)
607*906afcb8SAndy Fiddaman 			{
608*906afcb8SAndy Fiddaman 			case 0:
609*906afcb8SAndy Fiddaman 				s = p;
610*906afcb8SAndy Fiddaman 				break;
611*906afcb8SAndy Fiddaman 			case MARK:
612*906afcb8SAndy Fiddaman 				p++;
613*906afcb8SAndy Fiddaman 				break;
614*906afcb8SAndy Fiddaman 			}
615*906afcb8SAndy Fiddaman 			*s = 0;
616*906afcb8SAndy Fiddaman 		}
617*906afcb8SAndy Fiddaman 		(*pp.pragma)(pp.valbuf + 1, p1, p3, p5, (pp.state & COMPILE) || (pp.mode & INIT) != 0);
618*906afcb8SAndy Fiddaman 		emitted = 1;
619*906afcb8SAndy Fiddaman 	}
620*906afcb8SAndy Fiddaman 	goto donedirective;
621*906afcb8SAndy Fiddaman 
622*906afcb8SAndy Fiddaman 				/*INDENT*/
623*906afcb8SAndy Fiddaman 			}
624*906afcb8SAndy Fiddaman 		}
625*906afcb8SAndy Fiddaman 		if (*pp.control & SKIP) goto eatdirective;
626*906afcb8SAndy Fiddaman 		switch (directive)
627*906afcb8SAndy Fiddaman 		{
628*906afcb8SAndy Fiddaman #if MACDEF
629*906afcb8SAndy Fiddaman 		case ENDMAC:
630*906afcb8SAndy Fiddaman 			c = pplex();
631*906afcb8SAndy Fiddaman 			error(2, "no matching #%s for #%s", dirname(MACDEF), dirname(ENDMAC));
632*906afcb8SAndy Fiddaman 			goto enddirective;
633*906afcb8SAndy Fiddaman #endif
634*906afcb8SAndy Fiddaman #if MACDEF
635*906afcb8SAndy Fiddaman 		case MACDEF:
636*906afcb8SAndy Fiddaman 			if ((pp.state & STRICT) && !(pp.mode & (HOSTED|RELAX)))
637*906afcb8SAndy Fiddaman 				error(1, "#%s: non-standard directive", pp.token);
638*906afcb8SAndy Fiddaman #endif
639*906afcb8SAndy Fiddaman 			/* FALLTHROUGH */
640*906afcb8SAndy Fiddaman 		case DEFINE:
641*906afcb8SAndy Fiddaman 			n2 = error_info.line;
642*906afcb8SAndy Fiddaman 			if ((c = pplex()) == '#' && directive == DEFINE)
643*906afcb8SAndy Fiddaman 				goto assertion;
644*906afcb8SAndy Fiddaman 			if (c == '<')
645*906afcb8SAndy Fiddaman 			{
646*906afcb8SAndy Fiddaman 				n = 1;
647*906afcb8SAndy Fiddaman 				c = pplex();
648*906afcb8SAndy Fiddaman 			}
649*906afcb8SAndy Fiddaman 			else
650*906afcb8SAndy Fiddaman 				n = 0;
651*906afcb8SAndy Fiddaman 			if (!(sym = macsym(c)))
652*906afcb8SAndy Fiddaman 				goto eatdirective;
653*906afcb8SAndy Fiddaman 			if (pp.truncate)
654*906afcb8SAndy Fiddaman 				ppfsm(FSM_MACRO, pp.token);
655*906afcb8SAndy Fiddaman 			mac = sym->macro;
656*906afcb8SAndy Fiddaman 			if ((pp.option & ALLPOSSIBLE) && !pp.in->prev->prev && mac->value)
657*906afcb8SAndy Fiddaman 				goto eatdirective;
658*906afcb8SAndy Fiddaman 			if (n)
659*906afcb8SAndy Fiddaman 				goto tuple;
660*906afcb8SAndy Fiddaman 			old = *mac;
661*906afcb8SAndy Fiddaman 			i0 = sym->flags;
662*906afcb8SAndy Fiddaman 			sym->flags &= ~(SYM_BUILTIN|SYM_EMPTY|SYM_FINAL|SYM_FUNCTION|SYM_INIT|SYM_INITIAL|SYM_MULTILINE|SYM_NOEXPAND|SYM_PREDEFINED|SYM_REDEFINE|SYM_VARIADIC);
663*906afcb8SAndy Fiddaman #if MACDEF
664*906afcb8SAndy Fiddaman 			if (directive == MACDEF)
665*906afcb8SAndy Fiddaman 				sym->flags |= SYM_MULTILINE;
666*906afcb8SAndy Fiddaman #endif
667*906afcb8SAndy Fiddaman 			mac->arity = 0;
668*906afcb8SAndy Fiddaman 			mac->formals = 0;
669*906afcb8SAndy Fiddaman 			mac->value = 0;
670*906afcb8SAndy Fiddaman 			pp.state &= ~NOSPACE;
671*906afcb8SAndy Fiddaman 			pp.state |= DEFINITION|NOEXPAND;
672*906afcb8SAndy Fiddaman 			switch (c = pplex())
673*906afcb8SAndy Fiddaman 			{
674*906afcb8SAndy Fiddaman 			case '(':
675*906afcb8SAndy Fiddaman 				sym->flags |= SYM_FUNCTION;
676*906afcb8SAndy Fiddaman 				pp.state |= NOSPACE;
677*906afcb8SAndy Fiddaman #if MACKEYARGS
678*906afcb8SAndy Fiddaman 				if (pp.option & KEYARGS)
679*906afcb8SAndy Fiddaman 				{
680*906afcb8SAndy Fiddaman 					n = 2 * MAXTOKEN;
681*906afcb8SAndy Fiddaman 					p = mac->formals = oldof(0, char, 0, n);
682*906afcb8SAndy Fiddaman 					if ((c = pplex()) == T_ID) for (;;)
683*906afcb8SAndy Fiddaman 					{
684*906afcb8SAndy Fiddaman 						if (mac->arity < MAXFORMALS)
685*906afcb8SAndy Fiddaman 						{
686*906afcb8SAndy Fiddaman 							if (mac->arity) p++;
687*906afcb8SAndy Fiddaman 							formargs[mac->arity] = p;
688*906afcb8SAndy Fiddaman 							STRAPP(p, pp.token, s);
689*906afcb8SAndy Fiddaman 							formvals[mac->arity++] = p1 = p;
690*906afcb8SAndy Fiddaman 							if (mac->arity == 1) *p++ = ' ';
691*906afcb8SAndy Fiddaman 							*p++ = ' ';
692*906afcb8SAndy Fiddaman 							*p = 0;
693*906afcb8SAndy Fiddaman 						}
694*906afcb8SAndy Fiddaman 						else error(2, "%s: formal argument %s ignored", sym->name, pp.token);
695*906afcb8SAndy Fiddaman 						switch (c = pplex())
696*906afcb8SAndy Fiddaman 						{
697*906afcb8SAndy Fiddaman 						case '=':
698*906afcb8SAndy Fiddaman 							c = pplex();
699*906afcb8SAndy Fiddaman 							break;
700*906afcb8SAndy Fiddaman 						case ',':
701*906afcb8SAndy Fiddaman 							break;
702*906afcb8SAndy Fiddaman 						default:
703*906afcb8SAndy Fiddaman 							goto endformals;
704*906afcb8SAndy Fiddaman 						}
705*906afcb8SAndy Fiddaman 						pp.state &= ~NOSPACE;
706*906afcb8SAndy Fiddaman 						p0 = 0;
707*906afcb8SAndy Fiddaman 						for (;;)
708*906afcb8SAndy Fiddaman 						{
709*906afcb8SAndy Fiddaman 							switch (c)
710*906afcb8SAndy Fiddaman 							{
711*906afcb8SAndy Fiddaman 							case '\n':
712*906afcb8SAndy Fiddaman 								goto endformals;
713*906afcb8SAndy Fiddaman 							case '(':
714*906afcb8SAndy Fiddaman 								p0++;
715*906afcb8SAndy Fiddaman 								break;
716*906afcb8SAndy Fiddaman 							case ')':
717*906afcb8SAndy Fiddaman 								if (!p0--)
718*906afcb8SAndy Fiddaman 								{
719*906afcb8SAndy Fiddaman 									if (p > formvals[mac->arity - 1] && *(p - 1) == ' ') *--p = 0;
720*906afcb8SAndy Fiddaman 									goto endformals;
721*906afcb8SAndy Fiddaman 								}
722*906afcb8SAndy Fiddaman 								break;
723*906afcb8SAndy Fiddaman 							case ',':
724*906afcb8SAndy Fiddaman 								if (!p0)
725*906afcb8SAndy Fiddaman 								{
726*906afcb8SAndy Fiddaman 									if (p > formvals[mac->arity - 1] && *(p - 1) == ' ') *--p = 0;
727*906afcb8SAndy Fiddaman 									goto nextformal;
728*906afcb8SAndy Fiddaman 								}
729*906afcb8SAndy Fiddaman 								break;
730*906afcb8SAndy Fiddaman 							case ' ':
731*906afcb8SAndy Fiddaman 								if (p > formvals[mac->arity - 1] && *(p - 1) == ' ') continue;
732*906afcb8SAndy Fiddaman 								break;
733*906afcb8SAndy Fiddaman 							}
734*906afcb8SAndy Fiddaman 							STRCOPY(p, pp.token, s);
735*906afcb8SAndy Fiddaman 							if (p > &mac->formals[n - MAXTOKEN] && (s = newof(mac->formals, char, n += MAXTOKEN, 0)) != mac->formals)
736*906afcb8SAndy Fiddaman 							{
737*906afcb8SAndy Fiddaman 								n1 = s - mac->formals;
738*906afcb8SAndy Fiddaman 								for (n = 0; n < mac->arity; n++)
739*906afcb8SAndy Fiddaman 								{
740*906afcb8SAndy Fiddaman 									formargs[n] += n1;
741*906afcb8SAndy Fiddaman 									formvals[n] += n1;
742*906afcb8SAndy Fiddaman 								}
743*906afcb8SAndy Fiddaman 								c = p - mac->formals;
744*906afcb8SAndy Fiddaman 								mac->formals = s;
745*906afcb8SAndy Fiddaman 								p = mac->formals + c;
746*906afcb8SAndy Fiddaman 							}
747*906afcb8SAndy Fiddaman 							c = pplex();
748*906afcb8SAndy Fiddaman 						}
749*906afcb8SAndy Fiddaman 					nextformal:
750*906afcb8SAndy Fiddaman 						pp.state |= NOSPACE;
751*906afcb8SAndy Fiddaman 						if ((c = pplex()) != T_ID)
752*906afcb8SAndy Fiddaman 						{
753*906afcb8SAndy Fiddaman 							c = ',';
754*906afcb8SAndy Fiddaman 							break;
755*906afcb8SAndy Fiddaman 						}
756*906afcb8SAndy Fiddaman 					}
757*906afcb8SAndy Fiddaman 				endformals: /*NOP*/;
758*906afcb8SAndy Fiddaman 				}
759*906afcb8SAndy Fiddaman 				else
760*906afcb8SAndy Fiddaman #endif
761*906afcb8SAndy Fiddaman 				{
762*906afcb8SAndy Fiddaman 					p = mac->formals = oldof(0, char, 0, MAXFORMALS * (MAXID + 1));
763*906afcb8SAndy Fiddaman 					c = pplex();
764*906afcb8SAndy Fiddaman #if COMPATIBLE
765*906afcb8SAndy Fiddaman 					if ((pp.state & COMPATIBILITY) && c == ',')
766*906afcb8SAndy Fiddaman 					{
767*906afcb8SAndy Fiddaman 						if ((pp.state & WARN) && !(pp.mode & HOSTED))
768*906afcb8SAndy Fiddaman 							error(1, "%s: macro formal argument expected", sym->name);
769*906afcb8SAndy Fiddaman 						while ((c = pplex()) == ',');
770*906afcb8SAndy Fiddaman 					}
771*906afcb8SAndy Fiddaman #endif
772*906afcb8SAndy Fiddaman 					for (;;)
773*906afcb8SAndy Fiddaman 					{
774*906afcb8SAndy Fiddaman 						if (c == T_VARIADIC)
775*906afcb8SAndy Fiddaman 						{
776*906afcb8SAndy Fiddaman 							if (sym->flags & SYM_VARIADIC)
777*906afcb8SAndy Fiddaman 								error(2, "%s: %s: duplicate macro formal argument", sym->name, pp.token);
778*906afcb8SAndy Fiddaman 							sym->flags |= SYM_VARIADIC;
779*906afcb8SAndy Fiddaman 							v = __va_args__;
780*906afcb8SAndy Fiddaman 						}
781*906afcb8SAndy Fiddaman 						else if (c == T_ID)
782*906afcb8SAndy Fiddaman 						{
783*906afcb8SAndy Fiddaman 							v = pp.token;
784*906afcb8SAndy Fiddaman 							if (sym->flags & SYM_VARIADIC)
785*906afcb8SAndy Fiddaman 								error(2, "%s: %s: macro formal argument cannot follow ...", sym->name, v);
786*906afcb8SAndy Fiddaman 							else if (streq(v, __va_args__))
787*906afcb8SAndy Fiddaman 								error(2, "%s: %s: invalid macro formal argument", sym->name, v);
788*906afcb8SAndy Fiddaman 						}
789*906afcb8SAndy Fiddaman 						else
790*906afcb8SAndy Fiddaman 							break;
791*906afcb8SAndy Fiddaman 						if (mac->arity < MAXFORMALS)
792*906afcb8SAndy Fiddaman 						{
793*906afcb8SAndy Fiddaman 							for (n = 0; n < mac->arity; n++)
794*906afcb8SAndy Fiddaman 								if (streq(formargs[n], v))
795*906afcb8SAndy Fiddaman 									error(2, "%s: %s: duplicate macro formal argument", sym->name, v);
796*906afcb8SAndy Fiddaman 							formargs[mac->arity++] = p;
797*906afcb8SAndy Fiddaman 							STRAPP(p, v, s);
798*906afcb8SAndy Fiddaman 						}
799*906afcb8SAndy Fiddaman 						else
800*906afcb8SAndy Fiddaman 							error(2, "%s: %s: macro formal argument ignored", sym->name, v);
801*906afcb8SAndy Fiddaman 						if ((c = pplex()) == ',')
802*906afcb8SAndy Fiddaman 						{
803*906afcb8SAndy Fiddaman 							c = pplex();
804*906afcb8SAndy Fiddaman #if COMPATIBLE
805*906afcb8SAndy Fiddaman 							if ((pp.state & COMPATIBILITY) && c == ',')
806*906afcb8SAndy Fiddaman 							{
807*906afcb8SAndy Fiddaman 								if ((pp.state & WARN) && !(pp.mode & HOSTED))
808*906afcb8SAndy Fiddaman 									error(1, "%s: macro formal argument expected", sym->name);
809*906afcb8SAndy Fiddaman 								while ((c = pplex()) == ',');
810*906afcb8SAndy Fiddaman 							}
811*906afcb8SAndy Fiddaman #endif
812*906afcb8SAndy Fiddaman 						}
813*906afcb8SAndy Fiddaman 						else if (c != T_VARIADIC)
814*906afcb8SAndy Fiddaman 							break;
815*906afcb8SAndy Fiddaman 						else
816*906afcb8SAndy Fiddaman 						{
817*906afcb8SAndy Fiddaman 							if (sym->flags & SYM_VARIADIC)
818*906afcb8SAndy Fiddaman 								error(2, "%s: %s: duplicate macro formal argument", sym->name, pp.token);
819*906afcb8SAndy Fiddaman 							sym->flags |= SYM_VARIADIC;
820*906afcb8SAndy Fiddaman 							c = pplex();
821*906afcb8SAndy Fiddaman 							break;
822*906afcb8SAndy Fiddaman 						}
823*906afcb8SAndy Fiddaman 					}
824*906afcb8SAndy Fiddaman 					if (mac->arity && (s = newof(mac->formals, char, p - mac->formals, 0)) != mac->formals)
825*906afcb8SAndy Fiddaman 					{
826*906afcb8SAndy Fiddaman 						n1 = s - mac->formals;
827*906afcb8SAndy Fiddaman 						for (n = 0; n < mac->arity; n++)
828*906afcb8SAndy Fiddaman 							formargs[n] += n1;
829*906afcb8SAndy Fiddaman 						mac->formals = s;
830*906afcb8SAndy Fiddaman 					}
831*906afcb8SAndy Fiddaman 				}
832*906afcb8SAndy Fiddaman 				if (!mac->arity)
833*906afcb8SAndy Fiddaman 				{
834*906afcb8SAndy Fiddaman 					free(mac->formals);
835*906afcb8SAndy Fiddaman 					mac->formals = 0;
836*906afcb8SAndy Fiddaman 				}
837*906afcb8SAndy Fiddaman 				switch (c)
838*906afcb8SAndy Fiddaman 				{
839*906afcb8SAndy Fiddaman 				case ')':
840*906afcb8SAndy Fiddaman #if MACKEYARGS
841*906afcb8SAndy Fiddaman 					pp.state |= NOEXPAND|NOSPACE;
842*906afcb8SAndy Fiddaman #else
843*906afcb8SAndy Fiddaman 					pp.state |= NOEXPAND;
844*906afcb8SAndy Fiddaman #endif
845*906afcb8SAndy Fiddaman 					c = pplex();
846*906afcb8SAndy Fiddaman 					break;
847*906afcb8SAndy Fiddaman 				default:
848*906afcb8SAndy Fiddaman 					error(2, "%s: invalid macro formal argument list", sym->name);
849*906afcb8SAndy Fiddaman 					if (mac->formals)
850*906afcb8SAndy Fiddaman 					{
851*906afcb8SAndy Fiddaman 						free(mac->formals);
852*906afcb8SAndy Fiddaman 						mac->formals = 0;
853*906afcb8SAndy Fiddaman 						mac->arity = 0;
854*906afcb8SAndy Fiddaman 					}
855*906afcb8SAndy Fiddaman 					free(mac);
856*906afcb8SAndy Fiddaman 					sym->macro = 0;
857*906afcb8SAndy Fiddaman 					goto eatdirective;
858*906afcb8SAndy Fiddaman 				}
859*906afcb8SAndy Fiddaman 				pp.state &= ~NOSPACE;
860*906afcb8SAndy Fiddaman 				break;
861*906afcb8SAndy Fiddaman 			case ' ':
862*906afcb8SAndy Fiddaman 			case '\t':
863*906afcb8SAndy Fiddaman 				c = pplex();
864*906afcb8SAndy Fiddaman 				break;
865*906afcb8SAndy Fiddaman 			}
866*906afcb8SAndy Fiddaman 			n = 2 * MAXTOKEN;
867*906afcb8SAndy Fiddaman #if MACKEYARGS
868*906afcb8SAndy Fiddaman 			p1 = p;
869*906afcb8SAndy Fiddaman #endif
870*906afcb8SAndy Fiddaman 			p = mac->value = oldof(0, char, 0, n);
871*906afcb8SAndy Fiddaman 			var.type = 0;
872*906afcb8SAndy Fiddaman 			n1 = 0;
873*906afcb8SAndy Fiddaman #if MACDEF
874*906afcb8SAndy Fiddaman 			i2 = i3 = 0;
875*906afcb8SAndy Fiddaman 			n3 = pp.state;
876*906afcb8SAndy Fiddaman #endif
877*906afcb8SAndy Fiddaman 			if ((pp.option & PLUSPLUS) && (pp.state & (COMPATIBILITY|TRANSITION)) != COMPATIBILITY)
878*906afcb8SAndy Fiddaman 				switch (c)
879*906afcb8SAndy Fiddaman 				{
880*906afcb8SAndy Fiddaman 				case '+':
881*906afcb8SAndy Fiddaman 				case '-':
882*906afcb8SAndy Fiddaman 				case '&':
883*906afcb8SAndy Fiddaman 				case '|':
884*906afcb8SAndy Fiddaman 				case '<':
885*906afcb8SAndy Fiddaman 				case '>':
886*906afcb8SAndy Fiddaman 				case ':':
887*906afcb8SAndy Fiddaman 				case '=':
888*906afcb8SAndy Fiddaman 					*p++ = ' ';
889*906afcb8SAndy Fiddaman 					break;
890*906afcb8SAndy Fiddaman 				}
891*906afcb8SAndy Fiddaman 			o = 0;
892*906afcb8SAndy Fiddaman 			for (;;)
893*906afcb8SAndy Fiddaman 			{
894*906afcb8SAndy Fiddaman 				switch (c)
895*906afcb8SAndy Fiddaman 				{
896*906afcb8SAndy Fiddaman 				case T_ID:
897*906afcb8SAndy Fiddaman 					for (c = 0; c < mac->arity; c++)
898*906afcb8SAndy Fiddaman 						if (streq(formargs[c], pp.token))
899*906afcb8SAndy Fiddaman 						{
900*906afcb8SAndy Fiddaman #if COMPATIBLE
901*906afcb8SAndy Fiddaman 							if (!(pp.state & COMPATIBILITY))
902*906afcb8SAndy Fiddaman #endif
903*906afcb8SAndy Fiddaman 							if (var.type != TOK_TOKCAT && p > mac->value && *(p - 1) != ' ' && !(pp.option & PRESERVE)) *p++ = ' ';
904*906afcb8SAndy Fiddaman 							*p++ = MARK;
905*906afcb8SAndy Fiddaman #if COMPATIBLE
906*906afcb8SAndy Fiddaman 							if ((pp.state & (COMPATIBILITY|TRANSITION)) == COMPATIBILITY) *p++ = 'C';
907*906afcb8SAndy Fiddaman 							else
908*906afcb8SAndy Fiddaman #endif
909*906afcb8SAndy Fiddaman 							*p++ = (n1 || var.type == TOK_TOKCAT) ? 'C' : 'A';
910*906afcb8SAndy Fiddaman 							*p++ = c + ARGOFFSET;
911*906afcb8SAndy Fiddaman 							if ((pp.state & WARN) && !(pp.mode & (HOSTED|RELAX)) && var.type != TOK_TOKCAT && !(var.type & TOK_ID))
912*906afcb8SAndy Fiddaman 							{
913*906afcb8SAndy Fiddaman 								s = pp.in->nextchr;
914*906afcb8SAndy Fiddaman 								while ((c = *s++) && (c == ' ' || c == '\t'));
915*906afcb8SAndy Fiddaman 								if (c == '\n')
916*906afcb8SAndy Fiddaman 									c = 0;
917*906afcb8SAndy Fiddaman 								else if (c == '*' && *s == ')')
918*906afcb8SAndy Fiddaman 									c = ')';
919*906afcb8SAndy Fiddaman 								else if (c == '=' || ppisidig(c) || c == *s || *s == '=')
920*906afcb8SAndy Fiddaman 									c = 0;
921*906afcb8SAndy Fiddaman 								if (o != '.' && o != T_PTRMEM)
922*906afcb8SAndy Fiddaman 								{
923*906afcb8SAndy Fiddaman 									if ((var.type & TOK_ID) || o == ' ' || ppisseparate(o))
924*906afcb8SAndy Fiddaman 										o = 0;
925*906afcb8SAndy Fiddaman 									if (!((o == 0 || o == '(' || o == ')' || o == '[' || o == ']' || o == ',' || o == '|' || o == ';' || o == '{' || o == '}') && (c == '(' || c == ')' || c == '[' || c == ']' || c == ',' || c == '|' || c == ';' || c == '}' || c == 0)) && !(o == '*' && c == ')'))
926*906afcb8SAndy Fiddaman 										error(1, "%s: %s: formal should be parenthesized in macro value (t=%x o=%#c c=%#c)", sym->name, pp.token, var.type, o, c);
927*906afcb8SAndy Fiddaman 								}
928*906afcb8SAndy Fiddaman 							}
929*906afcb8SAndy Fiddaman 							var.type = TOK_FORMAL|TOK_ID;
930*906afcb8SAndy Fiddaman 							c = '>';
931*906afcb8SAndy Fiddaman 							goto checkvalue;
932*906afcb8SAndy Fiddaman 						}
933*906afcb8SAndy Fiddaman 					if (var.type == TOK_BUILTIN) switch ((int)hashget(pp.strtab, pp.token))
934*906afcb8SAndy Fiddaman 					{
935*906afcb8SAndy Fiddaman 					case V_DEFAULT:
936*906afcb8SAndy Fiddaman 					case V_EMPTY:
937*906afcb8SAndy Fiddaman 						sym->flags |= SYM_EMPTY;
938*906afcb8SAndy Fiddaman 						break;
939*906afcb8SAndy Fiddaman 					}
940*906afcb8SAndy Fiddaman 					else if (pp.hiding && (var.symbol = ppsymref(pp.symtab, pp.token)) && var.symbol->hidden)
941*906afcb8SAndy Fiddaman 					{
942*906afcb8SAndy Fiddaman 						for (var.inp = pp.in; var.inp->type != IN_FILE && var.inp->prev; var.inp = var.inp->prev);
943*906afcb8SAndy Fiddaman 						p += sfsprintf(p, MAXTOKEN, "_%d_%s_hIDe", var.inp->hide, pp.token);
944*906afcb8SAndy Fiddaman 						var.type = TOK_ID;
945*906afcb8SAndy Fiddaman 						goto checkvalue;
946*906afcb8SAndy Fiddaman 					}
947*906afcb8SAndy Fiddaman 					var.type = TOK_ID;
948*906afcb8SAndy Fiddaman 					break;
949*906afcb8SAndy Fiddaman 				case '#':
950*906afcb8SAndy Fiddaman 					var.type = 0;
951*906afcb8SAndy Fiddaman #if MACDEF
952*906afcb8SAndy Fiddaman 					if (!(sym->flags & (SYM_FUNCTION|SYM_MULTILINE))) break;
953*906afcb8SAndy Fiddaman #else
954*906afcb8SAndy Fiddaman 					if (!(sym->flags & SYM_FUNCTION)) break;
955*906afcb8SAndy Fiddaman #endif
956*906afcb8SAndy Fiddaman 					pp.state |= NOSPACE;
957*906afcb8SAndy Fiddaman 					c = pplex();
958*906afcb8SAndy Fiddaman 					if (c == '@')
959*906afcb8SAndy Fiddaman 					{
960*906afcb8SAndy Fiddaman 						c = pplex();
961*906afcb8SAndy Fiddaman 						i4 = 'S';
962*906afcb8SAndy Fiddaman 					}
963*906afcb8SAndy Fiddaman 					else i4 = 'Q';
964*906afcb8SAndy Fiddaman 					pp.state &= ~NOSPACE;
965*906afcb8SAndy Fiddaman 					if (c != T_ID) c = mac->arity;
966*906afcb8SAndy Fiddaman 					else for (c = 0; c < mac->arity; c++)
967*906afcb8SAndy Fiddaman 						if (streq(formargs[c], pp.token))
968*906afcb8SAndy Fiddaman 							break;
969*906afcb8SAndy Fiddaman 					if (c >= mac->arity)
970*906afcb8SAndy Fiddaman 					{
971*906afcb8SAndy Fiddaman #if MACDEF
972*906afcb8SAndy Fiddaman 						if (sym->flags & SYM_MULTILINE)
973*906afcb8SAndy Fiddaman 						{
974*906afcb8SAndy Fiddaman 							if (n3 & NEWLINE)
975*906afcb8SAndy Fiddaman 							{
976*906afcb8SAndy Fiddaman 								pp.state &= ~NOEXPAND;
977*906afcb8SAndy Fiddaman 								switch ((int)hashref(pp.dirtab, pp.token))
978*906afcb8SAndy Fiddaman 								{
979*906afcb8SAndy Fiddaman 								case ENDMAC:
980*906afcb8SAndy Fiddaman 									if (!i2--) goto gotdefinition;
981*906afcb8SAndy Fiddaman 									break;
982*906afcb8SAndy Fiddaman 								case INCLUDE:
983*906afcb8SAndy Fiddaman 									/* PARSE HEADER constant */
984*906afcb8SAndy Fiddaman 									break;
985*906afcb8SAndy Fiddaman 								case MACDEF:
986*906afcb8SAndy Fiddaman 									i2++;
987*906afcb8SAndy Fiddaman 									break;
988*906afcb8SAndy Fiddaman 								}
989*906afcb8SAndy Fiddaman 								*p++ = '#';
990*906afcb8SAndy Fiddaman 							}
991*906afcb8SAndy Fiddaman 						}
992*906afcb8SAndy Fiddaman 						else
993*906afcb8SAndy Fiddaman #endif
994*906afcb8SAndy Fiddaman #if COMPATIBLE
995*906afcb8SAndy Fiddaman 						if (pp.state & COMPATIBILITY) *p++ = '#';
996*906afcb8SAndy Fiddaman 						else
997*906afcb8SAndy Fiddaman #endif
998*906afcb8SAndy Fiddaman 						error(2, "# must precede a formal parameter");
999*906afcb8SAndy Fiddaman 					}
1000*906afcb8SAndy Fiddaman 					else
1001*906afcb8SAndy Fiddaman 					{
1002*906afcb8SAndy Fiddaman 						if (p > mac->value && ppisidig(*(p - 1)) && !(pp.option & PRESERVE)) *p++ = ' ';
1003*906afcb8SAndy Fiddaman 						*p++ = MARK;
1004*906afcb8SAndy Fiddaman 						*p++ = i4;
1005*906afcb8SAndy Fiddaman 						*p++ = c + ARGOFFSET;
1006*906afcb8SAndy Fiddaman 						goto checkvalue;
1007*906afcb8SAndy Fiddaman 					}
1008*906afcb8SAndy Fiddaman 					break;
1009*906afcb8SAndy Fiddaman 				case T_TOKCAT:
1010*906afcb8SAndy Fiddaman 					if (p <= mac->value) error(2, "%s lhs operand omitted", pp.token);
1011*906afcb8SAndy Fiddaman 					else
1012*906afcb8SAndy Fiddaman 					{
1013*906afcb8SAndy Fiddaman 						if (*(p - 1) == ' ') p--;
1014*906afcb8SAndy Fiddaman 						if (var.type == (TOK_FORMAL|TOK_ID)) *(p - 2) = 'C';
1015*906afcb8SAndy Fiddaman 					}
1016*906afcb8SAndy Fiddaman 					pp.state |= NOSPACE;
1017*906afcb8SAndy Fiddaman 					c = pplex();
1018*906afcb8SAndy Fiddaman 					pp.state &= ~NOSPACE;
1019*906afcb8SAndy Fiddaman 					if (c == '\n') error(2, "%s rhs operand omitted", pptokchr(T_TOKCAT));
1020*906afcb8SAndy Fiddaman 					var.type = TOK_TOKCAT;
1021*906afcb8SAndy Fiddaman 					continue;
1022*906afcb8SAndy Fiddaman 				case '(':
1023*906afcb8SAndy Fiddaman 					if (*pp.token == '#')
1024*906afcb8SAndy Fiddaman 					{
1025*906afcb8SAndy Fiddaman 						var.type = TOK_BUILTIN;
1026*906afcb8SAndy Fiddaman 						n1++;
1027*906afcb8SAndy Fiddaman 					}
1028*906afcb8SAndy Fiddaman 					else
1029*906afcb8SAndy Fiddaman 					{
1030*906afcb8SAndy Fiddaman 						var.type = 0;
1031*906afcb8SAndy Fiddaman 						if (n1) n1++;
1032*906afcb8SAndy Fiddaman 					}
1033*906afcb8SAndy Fiddaman 					break;
1034*906afcb8SAndy Fiddaman 				case ')':
1035*906afcb8SAndy Fiddaman 					var.type = 0;
1036*906afcb8SAndy Fiddaman 					if (n1) n1--;
1037*906afcb8SAndy Fiddaman 					break;
1038*906afcb8SAndy Fiddaman 				case T_STRING:
1039*906afcb8SAndy Fiddaman 				case T_CHARCONST:
1040*906afcb8SAndy Fiddaman 					pp.state &= ~NOEXPAND;
1041*906afcb8SAndy Fiddaman 					var.type = 0;
1042*906afcb8SAndy Fiddaman 					if (strchr(pp.token, MARK)) pp.state &= ~NOEXPAND;
1043*906afcb8SAndy Fiddaman #if COMPATIBLE
1044*906afcb8SAndy Fiddaman 					/*UNDENT*/
1045*906afcb8SAndy Fiddaman 
1046*906afcb8SAndy Fiddaman 	if ((sym->flags & SYM_FUNCTION) && (pp.state & (COMPATIBILITY|TRANSITION)))
1047*906afcb8SAndy Fiddaman 	{
1048*906afcb8SAndy Fiddaman 		char*	v;
1049*906afcb8SAndy Fiddaman 
1050*906afcb8SAndy Fiddaman 		s = pp.token;
1051*906afcb8SAndy Fiddaman 		for (;;)
1052*906afcb8SAndy Fiddaman 		{
1053*906afcb8SAndy Fiddaman 			if (!*s) goto checkvalue;
1054*906afcb8SAndy Fiddaman 			if (ppisid(*s))
1055*906afcb8SAndy Fiddaman 			{
1056*906afcb8SAndy Fiddaman 				v = s;
1057*906afcb8SAndy Fiddaman 				while (ppisid(*++s));
1058*906afcb8SAndy Fiddaman 				i1 = *s;
1059*906afcb8SAndy Fiddaman 				*s = 0;
1060*906afcb8SAndy Fiddaman 				for (c = 0; c < mac->arity; c++)
1061*906afcb8SAndy Fiddaman 					if (streq(formargs[c], v))
1062*906afcb8SAndy Fiddaman 					{
1063*906afcb8SAndy Fiddaman 						*p++ = MARK;
1064*906afcb8SAndy Fiddaman 						*p++ = 'C';
1065*906afcb8SAndy Fiddaman 						*p++ = c + ARGOFFSET;
1066*906afcb8SAndy Fiddaman 						if (!(pp.mode & HOSTED) && (!(pp.state & COMPATIBILITY) || (pp.state & WARN))) switch (*pp.token)
1067*906afcb8SAndy Fiddaman 						{
1068*906afcb8SAndy Fiddaman 						case '"':
1069*906afcb8SAndy Fiddaman 							error(1, "use the # operator to \"...\" quote macro arguments");
1070*906afcb8SAndy Fiddaman 							break;
1071*906afcb8SAndy Fiddaman 						case '\'':
1072*906afcb8SAndy Fiddaman 							error(1, "macro arguments should be '...' quoted before substitution");
1073*906afcb8SAndy Fiddaman 							break;
1074*906afcb8SAndy Fiddaman 						}
1075*906afcb8SAndy Fiddaman 						goto quotearg;
1076*906afcb8SAndy Fiddaman 					}
1077*906afcb8SAndy Fiddaman 				STRCOPY2(p, v);
1078*906afcb8SAndy Fiddaman 			quotearg:
1079*906afcb8SAndy Fiddaman 				*s = i1;
1080*906afcb8SAndy Fiddaman 			}
1081*906afcb8SAndy Fiddaman 			else *p++ = *s++;
1082*906afcb8SAndy Fiddaman 		}
1083*906afcb8SAndy Fiddaman 	}
1084*906afcb8SAndy Fiddaman 					/*INDENT*/
1085*906afcb8SAndy Fiddaman #endif
1086*906afcb8SAndy Fiddaman 					break;
1087*906afcb8SAndy Fiddaman 				case '\n':
1088*906afcb8SAndy Fiddaman #if MACDEF
1089*906afcb8SAndy Fiddaman 					if (sym->flags & SYM_MULTILINE)
1090*906afcb8SAndy Fiddaman 					{
1091*906afcb8SAndy Fiddaman 						if (pp.state & EOF2NL)
1092*906afcb8SAndy Fiddaman 						{
1093*906afcb8SAndy Fiddaman 							error_info.line++;
1094*906afcb8SAndy Fiddaman 							pp.state |= HIDDEN;
1095*906afcb8SAndy Fiddaman 							pp.hidden++;
1096*906afcb8SAndy Fiddaman 							var.type = 0;
1097*906afcb8SAndy Fiddaman 							if (!i3++)
1098*906afcb8SAndy Fiddaman 								goto checkvalue;
1099*906afcb8SAndy Fiddaman 							break;
1100*906afcb8SAndy Fiddaman 						}
1101*906afcb8SAndy Fiddaman 						pp.state |= EOF2NL;
1102*906afcb8SAndy Fiddaman 						error(2, "%s: missing #%s", sym->name, dirname(ENDMAC));
1103*906afcb8SAndy Fiddaman 					}
1104*906afcb8SAndy Fiddaman #endif
1105*906afcb8SAndy Fiddaman 					goto gotdefinition;
1106*906afcb8SAndy Fiddaman 				case 0:
1107*906afcb8SAndy Fiddaman 					c = '\n';
1108*906afcb8SAndy Fiddaman 					goto gotdefinition;
1109*906afcb8SAndy Fiddaman #if COMPATIBLE
1110*906afcb8SAndy Fiddaman 				case ' ':
1111*906afcb8SAndy Fiddaman 					if (pp.state & COMPATIBILITY) var.type = 0;
1112*906afcb8SAndy Fiddaman 					if (pp.option & PRESERVE) break;
1113*906afcb8SAndy Fiddaman 					if (p > mac->value && *(p - 1) != ' ') *p++ = ' ';
1114*906afcb8SAndy Fiddaman 					goto checkvalue;
1115*906afcb8SAndy Fiddaman 				case '\t':
1116*906afcb8SAndy Fiddaman 					if (var.type & TOK_ID)
1117*906afcb8SAndy Fiddaman 					{
1118*906afcb8SAndy Fiddaman 						while ((c = pplex()) == '\t');
1119*906afcb8SAndy Fiddaman 						if (c == T_ID)
1120*906afcb8SAndy Fiddaman 						{
1121*906afcb8SAndy Fiddaman 							if (var.type == (TOK_FORMAL|TOK_ID)) *(p - 2) = 'C';
1122*906afcb8SAndy Fiddaman 							var.type = TOK_TOKCAT;
1123*906afcb8SAndy Fiddaman 							if (pp.state & WARN) error(1, "use the ## operator to concatenate macro arguments");
1124*906afcb8SAndy Fiddaman 						}
1125*906afcb8SAndy Fiddaman 						else var.type = 0;
1126*906afcb8SAndy Fiddaman 						continue;
1127*906afcb8SAndy Fiddaman 					}
1128*906afcb8SAndy Fiddaman 					var.type = 0;
1129*906afcb8SAndy Fiddaman 					if (pp.option & PRESERVE) break;
1130*906afcb8SAndy Fiddaman 					if (p > mac->value && *(p - 1) != ' ') *p++ = ' ';
1131*906afcb8SAndy Fiddaman 					goto checkvalue;
1132*906afcb8SAndy Fiddaman #endif
1133*906afcb8SAndy Fiddaman 				case MARK:
1134*906afcb8SAndy Fiddaman 					pp.state &= ~NOEXPAND;
1135*906afcb8SAndy Fiddaman 					/*FALLTHROUGH*/
1136*906afcb8SAndy Fiddaman 
1137*906afcb8SAndy Fiddaman 				default:
1138*906afcb8SAndy Fiddaman 					var.type = 0;
1139*906afcb8SAndy Fiddaman 					break;
1140*906afcb8SAndy Fiddaman 				}
1141*906afcb8SAndy Fiddaman 				STRCOPY(p, pp.token, s);
1142*906afcb8SAndy Fiddaman 			checkvalue:
1143*906afcb8SAndy Fiddaman 				o = c;
1144*906afcb8SAndy Fiddaman 				if (p > &mac->value[n - MAXTOKEN] && (s = newof(mac->value, char, n += MAXTOKEN, 0)) != mac->value)
1145*906afcb8SAndy Fiddaman 				{
1146*906afcb8SAndy Fiddaman 					c = p - mac->value;
1147*906afcb8SAndy Fiddaman 					mac->value = s;
1148*906afcb8SAndy Fiddaman 					p = mac->value + c;
1149*906afcb8SAndy Fiddaman 				}
1150*906afcb8SAndy Fiddaman #if MACDEF
1151*906afcb8SAndy Fiddaman 				n3 = pp.state;
1152*906afcb8SAndy Fiddaman #endif
1153*906afcb8SAndy Fiddaman 				c = pplex();
1154*906afcb8SAndy Fiddaman 			}
1155*906afcb8SAndy Fiddaman 		gotdefinition:
1156*906afcb8SAndy Fiddaman 			while (p > mac->value && *(p - 1) == ' ') p--;
1157*906afcb8SAndy Fiddaman 			if (p > mac->value && (pp.option & PLUSPLUS) && (pp.state & (COMPATIBILITY|TRANSITION)) != COMPATIBILITY)
1158*906afcb8SAndy Fiddaman 				switch (o)
1159*906afcb8SAndy Fiddaman 				{
1160*906afcb8SAndy Fiddaman 				case '+':
1161*906afcb8SAndy Fiddaman 				case '-':
1162*906afcb8SAndy Fiddaman 				case '&':
1163*906afcb8SAndy Fiddaman 				case '|':
1164*906afcb8SAndy Fiddaman 				case '<':
1165*906afcb8SAndy Fiddaman 				case '>':
1166*906afcb8SAndy Fiddaman 				case ':':
1167*906afcb8SAndy Fiddaman 				case '=':
1168*906afcb8SAndy Fiddaman 					*p++ = ' ';
1169*906afcb8SAndy Fiddaman 					break;
1170*906afcb8SAndy Fiddaman 				}
1171*906afcb8SAndy Fiddaman 			*p = 0;
1172*906afcb8SAndy Fiddaman #if MACKEYARGS
1173*906afcb8SAndy Fiddaman 			if (!mac->arity) /* ok */;
1174*906afcb8SAndy Fiddaman 			else if (pp.option & KEYARGS)
1175*906afcb8SAndy Fiddaman 			{
1176*906afcb8SAndy Fiddaman 				p0 = mac->formals;
1177*906afcb8SAndy Fiddaman 				mac->formkeys = newof(0, struct ppkeyarg, n, p1 - p0 + 1);
1178*906afcb8SAndy Fiddaman 				s = (char*)&mac->formkeys[mac->arity];
1179*906afcb8SAndy Fiddaman 				(void)memcpy(s, p0, p1 - p0 + 1);
1180*906afcb8SAndy Fiddaman 				free(p0);
1181*906afcb8SAndy Fiddaman 				for (n = 0; n < mac->arity; n++)
1182*906afcb8SAndy Fiddaman 				{
1183*906afcb8SAndy Fiddaman 					mac->formkeys[n].name = s + (formargs[n] - p0);
1184*906afcb8SAndy Fiddaman 					mac->formkeys[n].value = s + (formvals[n] - p0);
1185*906afcb8SAndy Fiddaman 				}
1186*906afcb8SAndy Fiddaman 			}
1187*906afcb8SAndy Fiddaman 			else
1188*906afcb8SAndy Fiddaman #endif
1189*906afcb8SAndy Fiddaman 			for (n = 1; n < mac->arity; n++)
1190*906afcb8SAndy Fiddaman 				*(formargs[n] - 1) = ',';
1191*906afcb8SAndy Fiddaman 			if (old.value)
1192*906afcb8SAndy Fiddaman 			{
1193*906afcb8SAndy Fiddaman 				if ((i0 & SYM_FUNCTION) != (sym->flags & SYM_FUNCTION) || old.arity != mac->arity || !streq(old.value, mac->value)) goto redefined;
1194*906afcb8SAndy Fiddaman 				if (!old.formals)
1195*906afcb8SAndy Fiddaman 				{
1196*906afcb8SAndy Fiddaman 					if (mac->formals) goto redefined;
1197*906afcb8SAndy Fiddaman 				}
1198*906afcb8SAndy Fiddaman 				else if (mac->formals)
1199*906afcb8SAndy Fiddaman 				{
1200*906afcb8SAndy Fiddaman #if MACKEYARGS
1201*906afcb8SAndy Fiddaman 					if (pp.option & KEYARGS)
1202*906afcb8SAndy Fiddaman 					{
1203*906afcb8SAndy Fiddaman 						for (n = 0; n < mac->arity; n++)
1204*906afcb8SAndy Fiddaman 							if (!streq(mac->formkeys[n].name, old.formkeys[n].name) || !streq(mac->formkeys[n].value, old.formkeys[n].value))
1205*906afcb8SAndy Fiddaman 								goto redefined;
1206*906afcb8SAndy Fiddaman 					}
1207*906afcb8SAndy Fiddaman 					else
1208*906afcb8SAndy Fiddaman #endif
1209*906afcb8SAndy Fiddaman 					if (!streq(mac->formals, old.formals)) goto redefined;
1210*906afcb8SAndy Fiddaman 				}
1211*906afcb8SAndy Fiddaman #if MACKEYARGS
1212*906afcb8SAndy Fiddaman 				if (pp.option & KEYARGS)
1213*906afcb8SAndy Fiddaman 				{
1214*906afcb8SAndy Fiddaman 					if (mac->formkeys) free(mac->formkeys);
1215*906afcb8SAndy Fiddaman 					mac->formkeys = old.formkeys;
1216*906afcb8SAndy Fiddaman 				}
1217*906afcb8SAndy Fiddaman 				else
1218*906afcb8SAndy Fiddaman #endif
1219*906afcb8SAndy Fiddaman 				{
1220*906afcb8SAndy Fiddaman 					if (mac->formals) free(mac->formals);
1221*906afcb8SAndy Fiddaman 					mac->formals = old.formals;
1222*906afcb8SAndy Fiddaman 				}
1223*906afcb8SAndy Fiddaman 				free(mac->value);
1224*906afcb8SAndy Fiddaman 				mac->value = old.value;
1225*906afcb8SAndy Fiddaman 				goto benign;
1226*906afcb8SAndy Fiddaman 			redefined:
1227*906afcb8SAndy Fiddaman 				if (!(pp.mode & HOSTED) || !(i0 & SYM_INITIAL))
1228*906afcb8SAndy Fiddaman 					error(1, "%s redefined", sym->name);
1229*906afcb8SAndy Fiddaman #if MACKEYARGS
1230*906afcb8SAndy Fiddaman 				if ((pp.option & KEYARGS) && mac->formkeys)
1231*906afcb8SAndy Fiddaman 					free(mac->formkeys);
1232*906afcb8SAndy Fiddaman #endif
1233*906afcb8SAndy Fiddaman #if MACKEYARGS
1234*906afcb8SAndy Fiddaman 				if (!(pp.option & KEYARGS))
1235*906afcb8SAndy Fiddaman #endif
1236*906afcb8SAndy Fiddaman 				if (old.formals) free(old.formals);
1237*906afcb8SAndy Fiddaman 				free(old.value);
1238*906afcb8SAndy Fiddaman 			}
1239*906afcb8SAndy Fiddaman 			else if (!pp.truncate) ppfsm(FSM_MACRO, sym->name);
1240*906afcb8SAndy Fiddaman 			mac->value = newof(mac->value, char, (mac->size = p - mac->value) + 1, 0);
1241*906afcb8SAndy Fiddaman 			if ((pp.option & (DEFINITIONS|PREDEFINITIONS|REGUARD)) && !sym->hidden && !(sym->flags & SYM_MULTILINE) && ((pp.option & PREDEFINITIONS) || !(pp.mode & INIT)) && ((pp.option & (DEFINITIONS|PREDEFINITIONS)) || !(pp.state & NOTEXT)))
1242*906afcb8SAndy Fiddaman 			{
1243*906afcb8SAndy Fiddaman 				ppsync();
1244*906afcb8SAndy Fiddaman 				ppprintf("#%s %s", dirname(DEFINE), sym->name);
1245*906afcb8SAndy Fiddaman 				if (sym->flags & SYM_FUNCTION)
1246*906afcb8SAndy Fiddaman 				{
1247*906afcb8SAndy Fiddaman 					ppputchar('(');
1248*906afcb8SAndy Fiddaman 					if (mac->formals)
1249*906afcb8SAndy Fiddaman 						ppprintf("%s", mac->formals);
1250*906afcb8SAndy Fiddaman 					ppputchar(')');
1251*906afcb8SAndy Fiddaman 				}
1252*906afcb8SAndy Fiddaman 				if ((p = mac->value) && *p)
1253*906afcb8SAndy Fiddaman 				{
1254*906afcb8SAndy Fiddaman 					ppputchar(' ');
1255*906afcb8SAndy Fiddaman 					i0 = 0;
1256*906afcb8SAndy Fiddaman 					while (n = *p++)
1257*906afcb8SAndy Fiddaman 					{
1258*906afcb8SAndy Fiddaman 						if (n != MARK || (n = *p++) == MARK)
1259*906afcb8SAndy Fiddaman 						{
1260*906afcb8SAndy Fiddaman 							ppputchar(n);
1261*906afcb8SAndy Fiddaman 							i0 = ppisid(n);
1262*906afcb8SAndy Fiddaman 						}
1263*906afcb8SAndy Fiddaman 						else
1264*906afcb8SAndy Fiddaman 						{
1265*906afcb8SAndy Fiddaman 							if (n == 'Q')
1266*906afcb8SAndy Fiddaman 								ppputchar('#');
1267*906afcb8SAndy Fiddaman 							else if (i0)
1268*906afcb8SAndy Fiddaman 							{
1269*906afcb8SAndy Fiddaman 								ppputchar('#');
1270*906afcb8SAndy Fiddaman 								ppputchar('#');
1271*906afcb8SAndy Fiddaman 							}
1272*906afcb8SAndy Fiddaman 							s = formargs[*p++ - ARGOFFSET];
1273*906afcb8SAndy Fiddaman 							while ((n = *s++) && n != ',')
1274*906afcb8SAndy Fiddaman 								ppputchar(n);
1275*906afcb8SAndy Fiddaman 							if (ppisid(*p) || *p == MARK)
1276*906afcb8SAndy Fiddaman 							{
1277*906afcb8SAndy Fiddaman 								ppputchar('#');
1278*906afcb8SAndy Fiddaman 								ppputchar('#');
1279*906afcb8SAndy Fiddaman 							}
1280*906afcb8SAndy Fiddaman 							i0 = 0;
1281*906afcb8SAndy Fiddaman 						}
1282*906afcb8SAndy Fiddaman 						ppcheckout();
1283*906afcb8SAndy Fiddaman 					}
1284*906afcb8SAndy Fiddaman 				}
1285*906afcb8SAndy Fiddaman 				emitted = 1;
1286*906afcb8SAndy Fiddaman 			}
1287*906afcb8SAndy Fiddaman 		benign:
1288*906afcb8SAndy Fiddaman 			if (pp.mode & BUILTIN) sym->flags |= SYM_BUILTIN;
1289*906afcb8SAndy Fiddaman 			if (pp.option & FINAL) sym->flags |= SYM_FINAL;
1290*906afcb8SAndy Fiddaman 			if (pp.mode & INIT) sym->flags |= SYM_INIT;
1291*906afcb8SAndy Fiddaman 			if (pp.option & INITIAL) sym->flags |= SYM_INITIAL;
1292*906afcb8SAndy Fiddaman 			if (pp.state & NOEXPAND)  sym->flags |= SYM_NOEXPAND;
1293*906afcb8SAndy Fiddaman 			if (pp.option & PREDEFINED) sym->flags |= SYM_PREDEFINED;
1294*906afcb8SAndy Fiddaman 			if (pp.mode & READONLY) sym->flags |= SYM_READONLY;
1295*906afcb8SAndy Fiddaman 			if (pp.macref) (*pp.macref)(sym, error_info.file, n2, mac ? error_info.line - n2 + 1 : REF_UNDEF, mac ? strsum(mac->value, (long)mac->arity) : 0L);
1296*906afcb8SAndy Fiddaman 			break;
1297*906afcb8SAndy Fiddaman 		assertion:
1298*906afcb8SAndy Fiddaman 			c = pplex();
1299*906afcb8SAndy Fiddaman 			if ((pp.state & STRICT) && !(pp.mode & (HOSTED|RELAX)))
1300*906afcb8SAndy Fiddaman 				error(1, "#%s #%s: assertions are non-standard", dirname(directive), pptokstr(pp.token, 0));
1301*906afcb8SAndy Fiddaman 			if (c != T_ID)
1302*906afcb8SAndy Fiddaman 			{
1303*906afcb8SAndy Fiddaman 				error(2, "%s: invalid predicate name", pptokstr(pp.token, 0));
1304*906afcb8SAndy Fiddaman 				goto eatdirective;
1305*906afcb8SAndy Fiddaman 			}
1306*906afcb8SAndy Fiddaman 			switch ((int)hashref(pp.strtab, pp.token))
1307*906afcb8SAndy Fiddaman 			{
1308*906afcb8SAndy Fiddaman 			case X_DEFINED:
1309*906afcb8SAndy Fiddaman 			case X_EXISTS:
1310*906afcb8SAndy Fiddaman 			case X_STRCMP:
1311*906afcb8SAndy Fiddaman 				error(2, "%s is a builtin predicate", pp.token);
1312*906afcb8SAndy Fiddaman 				goto eatdirective;
1313*906afcb8SAndy Fiddaman 			case X_SIZEOF:
1314*906afcb8SAndy Fiddaman 				error(2, "%s cannot be a predicate", pp.token);
1315*906afcb8SAndy Fiddaman 				goto eatdirective;
1316*906afcb8SAndy Fiddaman 			}
1317*906afcb8SAndy Fiddaman 			strcpy(pp.tmpbuf, pp.token);
1318*906afcb8SAndy Fiddaman 			switch (pppredargs())
1319*906afcb8SAndy Fiddaman 			{
1320*906afcb8SAndy Fiddaman 			case T_ID:
1321*906afcb8SAndy Fiddaman 			case T_STRING:
1322*906afcb8SAndy Fiddaman 				assert(directive, pp.tmpbuf, pp.args);
1323*906afcb8SAndy Fiddaman 				break;
1324*906afcb8SAndy Fiddaman 			case 0:
1325*906afcb8SAndy Fiddaman 				assert(directive, pp.tmpbuf, NiL);
1326*906afcb8SAndy Fiddaman 				break;
1327*906afcb8SAndy Fiddaman 			default:
1328*906afcb8SAndy Fiddaman 				error(2, "invalid predicate argument list");
1329*906afcb8SAndy Fiddaman 				goto eatdirective;
1330*906afcb8SAndy Fiddaman 			}
1331*906afcb8SAndy Fiddaman 			break;
1332*906afcb8SAndy Fiddaman 		tuple:
1333*906afcb8SAndy Fiddaman 			pp.state |= DEFINITION|NOEXPAND|NOSPACE;
1334*906afcb8SAndy Fiddaman 			rp = 0;
1335*906afcb8SAndy Fiddaman 			tp = mac->tuple;
1336*906afcb8SAndy Fiddaman 			if (!tp && !mac->value)
1337*906afcb8SAndy Fiddaman 				ppfsm(FSM_MACRO, sym->name);
1338*906afcb8SAndy Fiddaman 			while ((c = pplex()) && c != '>' && c != '\n')
1339*906afcb8SAndy Fiddaman 			{
1340*906afcb8SAndy Fiddaman 				for (; tp; tp = tp->nomatch)
1341*906afcb8SAndy Fiddaman 					if (streq(tp->token, pp.token))
1342*906afcb8SAndy Fiddaman 						break;
1343*906afcb8SAndy Fiddaman 				if (!tp)
1344*906afcb8SAndy Fiddaman 				{
1345*906afcb8SAndy Fiddaman 					if (!(tp = newof(0, struct pptuple, 1, strlen(pp.token))))
1346*906afcb8SAndy Fiddaman 						error(3, "out of space");
1347*906afcb8SAndy Fiddaman 					strcpy(tp->token, pp.token);
1348*906afcb8SAndy Fiddaman 					if (rp)
1349*906afcb8SAndy Fiddaman 					{
1350*906afcb8SAndy Fiddaman 						tp->nomatch = rp;
1351*906afcb8SAndy Fiddaman 						rp->nomatch = tp;
1352*906afcb8SAndy Fiddaman 					}
1353*906afcb8SAndy Fiddaman 					else
1354*906afcb8SAndy Fiddaman 					{
1355*906afcb8SAndy Fiddaman 						tp->nomatch = mac->tuple;
1356*906afcb8SAndy Fiddaman 						mac->tuple = tp;
1357*906afcb8SAndy Fiddaman 					}
1358*906afcb8SAndy Fiddaman 				}
1359*906afcb8SAndy Fiddaman 				rp = tp;
1360*906afcb8SAndy Fiddaman 				tp = tp->match;
1361*906afcb8SAndy Fiddaman 			}
1362*906afcb8SAndy Fiddaman 			pp.state &= ~NOSPACE;
1363*906afcb8SAndy Fiddaman 			if (!rp || c != '>')
1364*906afcb8SAndy Fiddaman 				error(2, "%s: > omitted in tuple macro definition", sym->name);
1365*906afcb8SAndy Fiddaman 			else
1366*906afcb8SAndy Fiddaman 			{
1367*906afcb8SAndy Fiddaman 				n = 2 * MAXTOKEN;
1368*906afcb8SAndy Fiddaman 				p = v = oldof(0, char, 0, n);
1369*906afcb8SAndy Fiddaman 				while ((c = pplex()) && c != '\n')
1370*906afcb8SAndy Fiddaman 					if (p > v || c != ' ')
1371*906afcb8SAndy Fiddaman 					{
1372*906afcb8SAndy Fiddaman 						STRCOPY(p, pp.token, s);
1373*906afcb8SAndy Fiddaman 						if (p > &v[n - MAXTOKEN] && (s = newof(v, char, n += MAXTOKEN, 0)) != v)
1374*906afcb8SAndy Fiddaman 						{
1375*906afcb8SAndy Fiddaman 							c = p - v;
1376*906afcb8SAndy Fiddaman 							v = s;
1377*906afcb8SAndy Fiddaman 							p = v + c;
1378*906afcb8SAndy Fiddaman 						}
1379*906afcb8SAndy Fiddaman 					}
1380*906afcb8SAndy Fiddaman 				while (p > v && *(p - 1) == ' ')
1381*906afcb8SAndy Fiddaman 					p--;
1382*906afcb8SAndy Fiddaman 				n = p - v;
1383*906afcb8SAndy Fiddaman 				tp = newof(0, struct pptuple, 1, n);
1384*906afcb8SAndy Fiddaman 				strcpy(tp->token, v);
1385*906afcb8SAndy Fiddaman 				tp->match = rp->match;
1386*906afcb8SAndy Fiddaman 				rp->match = tp;
1387*906afcb8SAndy Fiddaman 			}
1388*906afcb8SAndy Fiddaman 			goto benign;
1389*906afcb8SAndy Fiddaman 		case WARNING:
1390*906afcb8SAndy Fiddaman 			if ((pp.state & STRICT) && !(pp.mode & (HOSTED|RELAX)))
1391*906afcb8SAndy Fiddaman 				error(1, "#%s: non-standard directive", pp.token);
1392*906afcb8SAndy Fiddaman 			/*FALLTHROUGH*/
1393*906afcb8SAndy Fiddaman 		case ERROR:
1394*906afcb8SAndy Fiddaman 			pp.state &= ~DISABLE;
1395*906afcb8SAndy Fiddaman 			p = pp.tmpbuf;
1396*906afcb8SAndy Fiddaman 			while ((c = pplex()) != '\n')
1397*906afcb8SAndy Fiddaman 				if (p + strlen(pp.token) < &pp.tmpbuf[MAXTOKEN])
1398*906afcb8SAndy Fiddaman 				{
1399*906afcb8SAndy Fiddaman 					STRCOPY(p, pp.token, s);
1400*906afcb8SAndy Fiddaman 					pp.state &= ~NOSPACE;
1401*906afcb8SAndy Fiddaman 				}
1402*906afcb8SAndy Fiddaman 			*p = 0;
1403*906afcb8SAndy Fiddaman 			p = *pp.tmpbuf ? pp.tmpbuf : ((directive == WARNING) ? "user warning" : "user error");
1404*906afcb8SAndy Fiddaman 			n = (directive == WARNING) ? 1 : 3;
1405*906afcb8SAndy Fiddaman 			error(n, "%s", p);
1406*906afcb8SAndy Fiddaman 			break;
1407*906afcb8SAndy Fiddaman 		case LET:
1408*906afcb8SAndy Fiddaman 			n2 = error_info.line;
1409*906afcb8SAndy Fiddaman 			if ((pp.state & STRICT) && !(pp.mode & (HOSTED|RELAX)))
1410*906afcb8SAndy Fiddaman 				error(1, "#%s: non-standard directive", pp.token);
1411*906afcb8SAndy Fiddaman 			if (!(sym = macsym(c = pplex()))) goto eatdirective;
1412*906afcb8SAndy Fiddaman 			if ((c = pplex()) != '=')
1413*906afcb8SAndy Fiddaman 			{
1414*906afcb8SAndy Fiddaman 				error(2, "%s: = expected", sym->name);
1415*906afcb8SAndy Fiddaman 				goto eatdirective;
1416*906afcb8SAndy Fiddaman 			}
1417*906afcb8SAndy Fiddaman 			sym->flags &= ~(SYM_BUILTIN|SYM_FUNCTION|SYM_MULTILINE|SYM_PREDEFINED|SYM_VARIADIC);
1418*906afcb8SAndy Fiddaman 			mac = sym->macro;
1419*906afcb8SAndy Fiddaman 			mac->arity = 0;
1420*906afcb8SAndy Fiddaman 			if (mac->value)
1421*906afcb8SAndy Fiddaman 			{
1422*906afcb8SAndy Fiddaman 				if (!(sym->flags & SYM_REDEFINE) && !sym->hidden)
1423*906afcb8SAndy Fiddaman 					error(1, "%s: redefined", sym->name);
1424*906afcb8SAndy Fiddaman #if MACKEYARGS
1425*906afcb8SAndy Fiddaman 				if ((pp.option & KEYARGS) && mac->formkeys) free(mac->formkeys);
1426*906afcb8SAndy Fiddaman 				else
1427*906afcb8SAndy Fiddaman #endif
1428*906afcb8SAndy Fiddaman 				free(mac->formals);
1429*906afcb8SAndy Fiddaman 				mac->formals = 0;
1430*906afcb8SAndy Fiddaman 				n = strlen(mac->value) + 1;
1431*906afcb8SAndy Fiddaman 			}
1432*906afcb8SAndy Fiddaman 			else
1433*906afcb8SAndy Fiddaman 			{
1434*906afcb8SAndy Fiddaman 				ppfsm(FSM_MACRO, sym->name);
1435*906afcb8SAndy Fiddaman 				n = 0;
1436*906afcb8SAndy Fiddaman 			}
1437*906afcb8SAndy Fiddaman 			n1 = ppexpr(&i1);
1438*906afcb8SAndy Fiddaman 			if (i1) c = sfsprintf(pp.tmpbuf, MAXTOKEN, "%luU", n1);
1439*906afcb8SAndy Fiddaman 			else c = sfsprintf(pp.tmpbuf, MAXTOKEN, "%ld", n1);
1440*906afcb8SAndy Fiddaman 			if (n < ++c)
1441*906afcb8SAndy Fiddaman 			{
1442*906afcb8SAndy Fiddaman 				if (mac->value) free(mac->value);
1443*906afcb8SAndy Fiddaman 				mac->value = oldof(0, char, 0, c);
1444*906afcb8SAndy Fiddaman 			}
1445*906afcb8SAndy Fiddaman 			strcpy(mac->value, pp.tmpbuf);
1446*906afcb8SAndy Fiddaman 			sym->flags |= SYM_REDEFINE;
1447*906afcb8SAndy Fiddaman 			c = (pp.state & NEWLINE) ? '\n' : ' ';
1448*906afcb8SAndy Fiddaman 			goto benign;
1449*906afcb8SAndy Fiddaman 		case LINE:
1450*906afcb8SAndy Fiddaman 			pp.state &= ~DISABLE;
1451*906afcb8SAndy Fiddaman 			if ((c = pplex()) == '#')
1452*906afcb8SAndy Fiddaman 			{
1453*906afcb8SAndy Fiddaman 				c = pplex();
1454*906afcb8SAndy Fiddaman 				directive = INCLUDE;
1455*906afcb8SAndy Fiddaman 			}
1456*906afcb8SAndy Fiddaman 			if (c != T_DECIMAL && c != T_OCTAL)
1457*906afcb8SAndy Fiddaman 			{
1458*906afcb8SAndy Fiddaman 				error(1, "#%s: line number expected", dirname(LINE));
1459*906afcb8SAndy Fiddaman 				goto eatdirective;
1460*906afcb8SAndy Fiddaman 			}
1461*906afcb8SAndy Fiddaman 		linesync:
1462*906afcb8SAndy Fiddaman 			n = error_info.line;
1463*906afcb8SAndy Fiddaman 			error_info.line = strtol(pp.token, NiL, 0);
1464*906afcb8SAndy Fiddaman 			if (error_info.line == 0 && directive == LINE && (pp.state & STRICT) && !(pp.mode & HOSTED))
1465*906afcb8SAndy Fiddaman 				error(1, "#%s: line number should be > 0", dirname(LINE));
1466*906afcb8SAndy Fiddaman 			pp.state &= ~DISABLE;
1467*906afcb8SAndy Fiddaman 			pp.state |= STRIP;
1468*906afcb8SAndy Fiddaman 			switch (c = pplex())
1469*906afcb8SAndy Fiddaman 			{
1470*906afcb8SAndy Fiddaman 			case T_STRING:
1471*906afcb8SAndy Fiddaman 				s = error_info.file;
1472*906afcb8SAndy Fiddaman 				if (*(p = pp.token))
1473*906afcb8SAndy Fiddaman 					pathcanon(p, 0, 0);
1474*906afcb8SAndy Fiddaman 				fp = ppsetfile(p);
1475*906afcb8SAndy Fiddaman 				error_info.file = fp->name;
1476*906afcb8SAndy Fiddaman 				if (error_info.line == 1)
1477*906afcb8SAndy Fiddaman 					ppmultiple(fp, INC_IGNORE);
1478*906afcb8SAndy Fiddaman 				switch (c = pplex())
1479*906afcb8SAndy Fiddaman 				{
1480*906afcb8SAndy Fiddaman 				case '\n':
1481*906afcb8SAndy Fiddaman 					break;
1482*906afcb8SAndy Fiddaman 				case T_DECIMAL:
1483*906afcb8SAndy Fiddaman 				case T_OCTAL:
1484*906afcb8SAndy Fiddaman 					if (directive == LINE && (pp.state & STRICT) && !(pp.mode & (HOSTED|RELAX)))
1485*906afcb8SAndy Fiddaman 						error(1, "#%s: integer file type argument is non-standard", dirname(LINE));
1486*906afcb8SAndy Fiddaman 					break;
1487*906afcb8SAndy Fiddaman 				default:
1488*906afcb8SAndy Fiddaman 					error(1, "#%s: integer file type argument expected", dirname(LINE));
1489*906afcb8SAndy Fiddaman 					break;
1490*906afcb8SAndy Fiddaman 				}
1491*906afcb8SAndy Fiddaman 				if (directive == LINE) pp.in->flags &= ~IN_ignoreline;
1492*906afcb8SAndy Fiddaman 				else if (pp.incref)
1493*906afcb8SAndy Fiddaman 				{
1494*906afcb8SAndy Fiddaman 					if (error_info.file != s)
1495*906afcb8SAndy Fiddaman 					{
1496*906afcb8SAndy Fiddaman 						switch (*pp.token)
1497*906afcb8SAndy Fiddaman 						{
1498*906afcb8SAndy Fiddaman 						case PP_sync_push:
1499*906afcb8SAndy Fiddaman 							if (pp.insert) (*pp.incref)(s, error_info.file, n, PP_SYNC_INSERT);
1500*906afcb8SAndy Fiddaman 							else (*pp.incref)(s, error_info.file, n, PP_SYNC_PUSH);
1501*906afcb8SAndy Fiddaman 							break;
1502*906afcb8SAndy Fiddaman 						case PP_sync_pop:
1503*906afcb8SAndy Fiddaman 							if (pp.insert) (*pp.incref)(s, error_info.file, n, PP_SYNC_INSERT);
1504*906afcb8SAndy Fiddaman 							else (*pp.incref)(s, error_info.file, n - 1, PP_SYNC_POP);
1505*906afcb8SAndy Fiddaman 							break;
1506*906afcb8SAndy Fiddaman 						case PP_sync_ignore:
1507*906afcb8SAndy Fiddaman 							if (pp.insert) (*pp.incref)(s, error_info.file, n, PP_SYNC_INSERT);
1508*906afcb8SAndy Fiddaman 							else
1509*906afcb8SAndy Fiddaman 							{
1510*906afcb8SAndy Fiddaman 								(*pp.incref)(s, error_info.file, n, PP_SYNC_IGNORE);
1511*906afcb8SAndy Fiddaman 								error_info.file = s;
1512*906afcb8SAndy Fiddaman 							}
1513*906afcb8SAndy Fiddaman 							break;
1514*906afcb8SAndy Fiddaman 						default:
1515*906afcb8SAndy Fiddaman 							if (*s)
1516*906afcb8SAndy Fiddaman 							{
1517*906afcb8SAndy Fiddaman 								if (fp == pp.insert)
1518*906afcb8SAndy Fiddaman 									pp.insert = 0;
1519*906afcb8SAndy Fiddaman 								else if (error_info.line == 1 && !pp.insert)
1520*906afcb8SAndy Fiddaman 									(*pp.incref)(s, error_info.file, n, PP_SYNC_PUSH);
1521*906afcb8SAndy Fiddaman 								else
1522*906afcb8SAndy Fiddaman 								{
1523*906afcb8SAndy Fiddaman 									if (!pp.insert) pp.insert = ppgetfile(s);
1524*906afcb8SAndy Fiddaman 									(*pp.incref)(s, error_info.file, n, PP_SYNC_INSERT);
1525*906afcb8SAndy Fiddaman 								}
1526*906afcb8SAndy Fiddaman 							}
1527*906afcb8SAndy Fiddaman 							break;
1528*906afcb8SAndy Fiddaman 						}
1529*906afcb8SAndy Fiddaman 					}
1530*906afcb8SAndy Fiddaman 				}
1531*906afcb8SAndy Fiddaman 				break;
1532*906afcb8SAndy Fiddaman 			case '\n':
1533*906afcb8SAndy Fiddaman 				break;
1534*906afcb8SAndy Fiddaman 			default:
1535*906afcb8SAndy Fiddaman 				error(1, "#%s: \"file-name\" expected", dirname(LINE));
1536*906afcb8SAndy Fiddaman 				break;
1537*906afcb8SAndy Fiddaman 			}
1538*906afcb8SAndy Fiddaman 			if (directive == LINE && (pp.in->flags & IN_ignoreline))
1539*906afcb8SAndy Fiddaman 				error_info.line = n + 1;
1540*906afcb8SAndy Fiddaman 			else
1541*906afcb8SAndy Fiddaman 			{
1542*906afcb8SAndy Fiddaman 				pp.hidden = 0;
1543*906afcb8SAndy Fiddaman 				pp.state &= ~HIDDEN;
1544*906afcb8SAndy Fiddaman 				if (pp.linesync)
1545*906afcb8SAndy Fiddaman 				{
1546*906afcb8SAndy Fiddaman #if CATSTRINGS
1547*906afcb8SAndy Fiddaman 					if (pp.state & JOINING) pp.state |= HIDDEN|SYNCLINE;
1548*906afcb8SAndy Fiddaman 					else
1549*906afcb8SAndy Fiddaman #endif
1550*906afcb8SAndy Fiddaman 					{
1551*906afcb8SAndy Fiddaman 						s = pp.lineid;
1552*906afcb8SAndy Fiddaman 						n = pp.flags;
1553*906afcb8SAndy Fiddaman 						if (directive == LINE)
1554*906afcb8SAndy Fiddaman 						{
1555*906afcb8SAndy Fiddaman 							pp.flags &= ~PP_linetype;
1556*906afcb8SAndy Fiddaman 							if (pp.macref) pp.lineid = dirname(LINE);
1557*906afcb8SAndy Fiddaman 						}
1558*906afcb8SAndy Fiddaman 						(*pp.linesync)(error_info.line, error_info.file);
1559*906afcb8SAndy Fiddaman 						pp.flags = n;
1560*906afcb8SAndy Fiddaman 						pp.lineid = s;
1561*906afcb8SAndy Fiddaman 					}
1562*906afcb8SAndy Fiddaman 				}
1563*906afcb8SAndy Fiddaman 			}
1564*906afcb8SAndy Fiddaman 			directive = LINE;
1565*906afcb8SAndy Fiddaman 			break;
1566*906afcb8SAndy Fiddaman 		case PRAGMA:
1567*906afcb8SAndy Fiddaman 			/*
1568*906afcb8SAndy Fiddaman 			 * #pragma [STDC] [pass:] [no]option [arg ...]
1569*906afcb8SAndy Fiddaman 			 *
1570*906afcb8SAndy Fiddaman 			 * pragma args are not expanded by default
1571*906afcb8SAndy Fiddaman 			 *
1572*906afcb8SAndy Fiddaman 			 * if STDC is present then it is silently passed on
1573*906afcb8SAndy Fiddaman 			 *
1574*906afcb8SAndy Fiddaman 			 * if pass is pp.pass then the option is used
1575*906afcb8SAndy Fiddaman 			 * and verified but is not passed on
1576*906afcb8SAndy Fiddaman 			 *
1577*906afcb8SAndy Fiddaman 			 * if pass is omitted then the option is passed on
1578*906afcb8SAndy Fiddaman 			 *
1579*906afcb8SAndy Fiddaman 			 * otherwise if pass is non-null and not pp.pass then
1580*906afcb8SAndy Fiddaman 			 * the option is passed on but not used
1581*906afcb8SAndy Fiddaman 			 *
1582*906afcb8SAndy Fiddaman 			 * if the line does not match this form then
1583*906afcb8SAndy Fiddaman 			 * it is passed on unchanged
1584*906afcb8SAndy Fiddaman 			 *
1585*906afcb8SAndy Fiddaman 			 *	#directive   pass:  option  [...]
1586*906afcb8SAndy Fiddaman 			 *	^         ^  ^   ^  ^     ^  ^   ^
1587*906afcb8SAndy Fiddaman 			 *	pp.valbuf p0 p1  p2 p3    p4 p5  p6
1588*906afcb8SAndy Fiddaman 			 *
1589*906afcb8SAndy Fiddaman 			 * p?	0 if component omitted
1590*906afcb8SAndy Fiddaman 			 * i0	0 if ``no''option
1591*906afcb8SAndy Fiddaman 			 */
1592*906afcb8SAndy Fiddaman 
1593*906afcb8SAndy Fiddaman 			p = pp.valbuf;
1594*906afcb8SAndy Fiddaman 			*p++ = '#';
1595*906afcb8SAndy Fiddaman 			STRCOPY(p, pp.token, s);
1596*906afcb8SAndy Fiddaman 			p0 = p;
1597*906afcb8SAndy Fiddaman 			if (pp.option & PRAGMAEXPAND)
1598*906afcb8SAndy Fiddaman 				pp.state &= ~DISABLE;
1599*906afcb8SAndy Fiddaman 			if (!(p6 = getline(p, &pp.valbuf[MAXTOKEN], !!(pp.option & PRAGMAEXPAND))))
1600*906afcb8SAndy Fiddaman 			{
1601*906afcb8SAndy Fiddaman 				*p0 = 0;
1602*906afcb8SAndy Fiddaman 				error(2, "%s: directive too long", pp.valbuf);
1603*906afcb8SAndy Fiddaman 				c = 0;
1604*906afcb8SAndy Fiddaman 				goto eatdirective;
1605*906afcb8SAndy Fiddaman 			}
1606*906afcb8SAndy Fiddaman 			p1 = ++p;
1607*906afcb8SAndy Fiddaman 			while (ppisid(*p))
1608*906afcb8SAndy Fiddaman 				p++;
1609*906afcb8SAndy Fiddaman 			if (p == p1)
1610*906afcb8SAndy Fiddaman 			{
1611*906afcb8SAndy Fiddaman 				p5 = p;
1612*906afcb8SAndy Fiddaman 				p4 = 0;
1613*906afcb8SAndy Fiddaman 				p3 = 0;
1614*906afcb8SAndy Fiddaman 				p2 = 0;
1615*906afcb8SAndy Fiddaman 				p1 = 0;
1616*906afcb8SAndy Fiddaman 			}
1617*906afcb8SAndy Fiddaman 			else if (*p != ':')
1618*906afcb8SAndy Fiddaman 			{
1619*906afcb8SAndy Fiddaman 				p5 = *p ? p + (*p == ' ') : 0;
1620*906afcb8SAndy Fiddaman 				p4 = p;
1621*906afcb8SAndy Fiddaman 				p3 = p1;
1622*906afcb8SAndy Fiddaman 				p2 = 0;
1623*906afcb8SAndy Fiddaman 				p1 = 0;
1624*906afcb8SAndy Fiddaman 			}
1625*906afcb8SAndy Fiddaman 			else
1626*906afcb8SAndy Fiddaman 			{
1627*906afcb8SAndy Fiddaman 				p2 = p++;
1628*906afcb8SAndy Fiddaman 				p3 = p;
1629*906afcb8SAndy Fiddaman 				while (ppisid(*p))
1630*906afcb8SAndy Fiddaman 					p++;
1631*906afcb8SAndy Fiddaman 				if (p == p3)
1632*906afcb8SAndy Fiddaman 				{
1633*906afcb8SAndy Fiddaman 					p4 = p1;
1634*906afcb8SAndy Fiddaman 					p3 = 0;
1635*906afcb8SAndy Fiddaman 					p2 = 0;
1636*906afcb8SAndy Fiddaman 					p1 = 0;
1637*906afcb8SAndy Fiddaman 				}
1638*906afcb8SAndy Fiddaman 				else
1639*906afcb8SAndy Fiddaman 					p4 = p;
1640*906afcb8SAndy Fiddaman 				p5 = *p4 ? p4 + (*p4 == ' ') : 0;
1641*906afcb8SAndy Fiddaman 			}
1642*906afcb8SAndy Fiddaman 			if (!p1 && p3 && (p4 - p3) == 4 && strneq(p3, "STDC", 4))
1643*906afcb8SAndy Fiddaman 				goto pass;
1644*906afcb8SAndy Fiddaman 			if ((pp.state & WARN) && (pp.mode & (HOSTED|RELAX|PEDANTIC)) == PEDANTIC)
1645*906afcb8SAndy Fiddaman 				error(1, "#%s: non-standard directive", dirname(PRAGMA));
1646*906afcb8SAndy Fiddaman 			i0 = !p3 || *p3 != 'n' || *(p3 + 1) != 'o';
1647*906afcb8SAndy Fiddaman 			if (!p3)
1648*906afcb8SAndy Fiddaman 				goto checkmap;
1649*906afcb8SAndy Fiddaman 			if (p1)
1650*906afcb8SAndy Fiddaman 			{
1651*906afcb8SAndy Fiddaman 				*p2 = 0;
1652*906afcb8SAndy Fiddaman 				n = streq(p1, pp.pass);
1653*906afcb8SAndy Fiddaman 				*p2 = ':';
1654*906afcb8SAndy Fiddaman 				if (!n)
1655*906afcb8SAndy Fiddaman 					goto checkmap;
1656*906afcb8SAndy Fiddaman 			}
1657*906afcb8SAndy Fiddaman 			else
1658*906afcb8SAndy Fiddaman 				n = 0;
1659*906afcb8SAndy Fiddaman 			i2 = *p4;
1660*906afcb8SAndy Fiddaman 			*p4 = 0;
1661*906afcb8SAndy Fiddaman 			if (((i1 = (int)hashref(pp.strtab, p3 + (i0 ? 0 : 2))) < 1 || i1 > X_last_option) && (i0 || (i1 = (int)hashref(pp.strtab, p3)) > X_last_option))
1662*906afcb8SAndy Fiddaman 				i1 = 0;
1663*906afcb8SAndy Fiddaman 			if ((pp.state & (COMPATIBILITY|STRICT)) == STRICT && !(pp.mode & (HOSTED|RELAX)))
1664*906afcb8SAndy Fiddaman 			{
1665*906afcb8SAndy Fiddaman 				if (pp.optflags[i1] & OPT_GLOBAL)
1666*906afcb8SAndy Fiddaman 					goto donedirective;
1667*906afcb8SAndy Fiddaman 				if (n || (pp.mode & WARN))
1668*906afcb8SAndy Fiddaman 				{
1669*906afcb8SAndy Fiddaman 					n = 0;
1670*906afcb8SAndy Fiddaman 					error(1, "#%s: non-standard directive ignored", dirname(PRAGMA));
1671*906afcb8SAndy Fiddaman 				}
1672*906afcb8SAndy Fiddaman 				i1 = 0;
1673*906afcb8SAndy Fiddaman 			}
1674*906afcb8SAndy Fiddaman 			if (!n)
1675*906afcb8SAndy Fiddaman 			{
1676*906afcb8SAndy Fiddaman 				if (!(pp.optflags[i1] & OPT_GLOBAL))
1677*906afcb8SAndy Fiddaman 				{
1678*906afcb8SAndy Fiddaman 					*p4 = i2;
1679*906afcb8SAndy Fiddaman 					goto checkmap;
1680*906afcb8SAndy Fiddaman 				}
1681*906afcb8SAndy Fiddaman 				if (!(pp.optflags[i1] & OPT_PASS))
1682*906afcb8SAndy Fiddaman 					n = 1;
1683*906afcb8SAndy Fiddaman 			}
1684*906afcb8SAndy Fiddaman 			else if (!i1)
1685*906afcb8SAndy Fiddaman 				error(2, "%s: unknown option", p1);
1686*906afcb8SAndy Fiddaman 			else if ((pp.state & STRICT) && !(pp.mode & (HOSTED|RELAX)))
1687*906afcb8SAndy Fiddaman 				error(1, "%s: non-standard option", p1);
1688*906afcb8SAndy Fiddaman 			p = p5;
1689*906afcb8SAndy Fiddaman 			switch (i1)
1690*906afcb8SAndy Fiddaman 			{
1691*906afcb8SAndy Fiddaman 			case X_ALLMULTIPLE:
1692*906afcb8SAndy Fiddaman 				ppop(PP_MULTIPLE, i0);
1693*906afcb8SAndy Fiddaman 				break;
1694*906afcb8SAndy Fiddaman 			case X_ALLPOSSIBLE:
1695*906afcb8SAndy Fiddaman 				setoption(ALLPOSSIBLE, i0);
1696*906afcb8SAndy Fiddaman 				break;
1697*906afcb8SAndy Fiddaman 			case X_BUILTIN:
1698*906afcb8SAndy Fiddaman 				setmode(BUILTIN, i0);
1699*906afcb8SAndy Fiddaman 				break;
1700*906afcb8SAndy Fiddaman 			case X_CATLITERAL:
1701*906afcb8SAndy Fiddaman 				setmode(CATLITERAL, i0);
1702*906afcb8SAndy Fiddaman 				if (pp.mode & CATLITERAL)
1703*906afcb8SAndy Fiddaman 					setoption(STRINGSPLIT, 0);
1704*906afcb8SAndy Fiddaman 				break;
1705*906afcb8SAndy Fiddaman 			case X_CDIR:
1706*906afcb8SAndy Fiddaman 				tokop(PP_CDIR, p3, p, i0, TOKOP_UNSET|TOKOP_STRING|TOKOP_DUP);
1707*906afcb8SAndy Fiddaman 				break;
1708*906afcb8SAndy Fiddaman 			case X_CHECKPOINT:
1709*906afcb8SAndy Fiddaman #if CHECKPOINT
1710*906afcb8SAndy Fiddaman 				ppload(p);
1711*906afcb8SAndy Fiddaman #else
1712*906afcb8SAndy Fiddaman 				error(3, "%s: preprocessor not compiled with checkpoint enabled", p3);
1713*906afcb8SAndy Fiddaman #endif
1714*906afcb8SAndy Fiddaman 				break;
1715*906afcb8SAndy Fiddaman 			case X_CHOP:
1716*906afcb8SAndy Fiddaman 				tokop(PP_CHOP, p3, p, i0, TOKOP_UNSET|TOKOP_STRING);
1717*906afcb8SAndy Fiddaman 				break;
1718*906afcb8SAndy Fiddaman 			case X_COMPATIBILITY:
1719*906afcb8SAndy Fiddaman 				ppop(PP_COMPATIBILITY, i0);
1720*906afcb8SAndy Fiddaman 				break;
1721*906afcb8SAndy Fiddaman 			case X_DEBUG:
1722*906afcb8SAndy Fiddaman 				error_info.trace = i0 ? (p ? -strtol(p, NiL, 0) : -1) : 0;
1723*906afcb8SAndy Fiddaman 				break;
1724*906afcb8SAndy Fiddaman 			case X_ELSEIF:
1725*906afcb8SAndy Fiddaman 				setoption(ELSEIF, i0);
1726*906afcb8SAndy Fiddaman 				break;
1727*906afcb8SAndy Fiddaman 			case X_EXTERNALIZE:
1728*906afcb8SAndy Fiddaman 				setmode(EXTERNALIZE, i0);
1729*906afcb8SAndy Fiddaman 				break;
1730*906afcb8SAndy Fiddaman 			case X_FINAL:
1731*906afcb8SAndy Fiddaman 				setoption(FINAL, i0);
1732*906afcb8SAndy Fiddaman 				break;
1733*906afcb8SAndy Fiddaman 			case X_HEADEREXPAND:
1734*906afcb8SAndy Fiddaman 				setoption(HEADEREXPAND, i0);
1735*906afcb8SAndy Fiddaman 				break;
1736*906afcb8SAndy Fiddaman 			case X_HEADEREXPANDALL:
1737*906afcb8SAndy Fiddaman 				setoption(HEADEREXPANDALL, i0);
1738*906afcb8SAndy Fiddaman 				break;
1739*906afcb8SAndy Fiddaman 			case X_HIDE:
1740*906afcb8SAndy Fiddaman 			case X_NOTE:
1741*906afcb8SAndy Fiddaman 				PUSH_LINE(p);
1742*906afcb8SAndy Fiddaman 				/* UNDENT...*/
1743*906afcb8SAndy Fiddaman 	while (c = pplex())
1744*906afcb8SAndy Fiddaman 	{
1745*906afcb8SAndy Fiddaman 		if (c != T_ID) error(1, "%s: %s: identifier expected", p3, pp.token);
1746*906afcb8SAndy Fiddaman 		else if (sym = ppsymset(pp.symtab, pp.token))
1747*906afcb8SAndy Fiddaman 		{
1748*906afcb8SAndy Fiddaman 			if (i1 == X_NOTE)
1749*906afcb8SAndy Fiddaman 			{
1750*906afcb8SAndy Fiddaman 				sym->flags &= ~SYM_NOTICED;
1751*906afcb8SAndy Fiddaman 				ppfsm(FSM_MACRO, sym->name);
1752*906afcb8SAndy Fiddaman 			}
1753*906afcb8SAndy Fiddaman 			else if (i0)
1754*906afcb8SAndy Fiddaman 			{
1755*906afcb8SAndy Fiddaman 				if (!sym->hidden && !(sym->hidden = newof(0, struct pphide, 1, 0)))
1756*906afcb8SAndy Fiddaman 					error(3, "out of space");
1757*906afcb8SAndy Fiddaman 				if (!sym->macro)
1758*906afcb8SAndy Fiddaman 					ppfsm(FSM_MACRO, sym->name);
1759*906afcb8SAndy Fiddaman 				if (!sym->hidden->level++)
1760*906afcb8SAndy Fiddaman 				{
1761*906afcb8SAndy Fiddaman 					pp.hiding++;
1762*906afcb8SAndy Fiddaman 					if (sym->macro && !(sym->flags & (SYM_ACTIVE|SYM_READONLY)))
1763*906afcb8SAndy Fiddaman 					{
1764*906afcb8SAndy Fiddaman 						sym->hidden->macro = sym->macro;
1765*906afcb8SAndy Fiddaman 						sym->macro = 0;
1766*906afcb8SAndy Fiddaman 						sym->hidden->flags = sym->flags;
1767*906afcb8SAndy Fiddaman 						sym->flags &= ~(SYM_BUILTIN|SYM_FUNCTION|SYM_INIT|SYM_MULTILINE|SYM_PREDEFINED|SYM_REDEFINE|SYM_VARIADIC);
1768*906afcb8SAndy Fiddaman 					}
1769*906afcb8SAndy Fiddaman 				}
1770*906afcb8SAndy Fiddaman 			}
1771*906afcb8SAndy Fiddaman 			else if (sym->hidden)
1772*906afcb8SAndy Fiddaman 			{
1773*906afcb8SAndy Fiddaman 				if ((mac = sym->macro) && !(sym->flags & (SYM_ACTIVE|SYM_READONLY)))
1774*906afcb8SAndy Fiddaman 				{
1775*906afcb8SAndy Fiddaman 					if (mac->formals) free(mac->formals);
1776*906afcb8SAndy Fiddaman 					free(mac->value);
1777*906afcb8SAndy Fiddaman 					free(mac);
1778*906afcb8SAndy Fiddaman 					sym->macro = 0;
1779*906afcb8SAndy Fiddaman 					sym->flags &= ~(SYM_BUILTIN|SYM_FUNCTION|SYM_INIT|SYM_MULTILINE|SYM_PREDEFINED|SYM_REDEFINE|SYM_VARIADIC);
1780*906afcb8SAndy Fiddaman 				}
1781*906afcb8SAndy Fiddaman 				if (!--sym->hidden->level)
1782*906afcb8SAndy Fiddaman 				{
1783*906afcb8SAndy Fiddaman 					pp.hiding--;
1784*906afcb8SAndy Fiddaman 					if (sym->hidden->macro)
1785*906afcb8SAndy Fiddaman 					{
1786*906afcb8SAndy Fiddaman 						sym->macro = sym->hidden->macro;
1787*906afcb8SAndy Fiddaman 						sym->flags = sym->hidden->flags;
1788*906afcb8SAndy Fiddaman 					}
1789*906afcb8SAndy Fiddaman 					free(sym->hidden);
1790*906afcb8SAndy Fiddaman 					sym->hidden = 0;
1791*906afcb8SAndy Fiddaman 				}
1792*906afcb8SAndy Fiddaman 			}
1793*906afcb8SAndy Fiddaman 		}
1794*906afcb8SAndy Fiddaman 	}
1795*906afcb8SAndy Fiddaman 				/*...INDENT*/
1796*906afcb8SAndy Fiddaman 				POP_LINE();
1797*906afcb8SAndy Fiddaman 				break;
1798*906afcb8SAndy Fiddaman 			case X_HOSTDIR:
1799*906afcb8SAndy Fiddaman 				tokop(PP_HOSTDIR, p3, p, i0, TOKOP_UNSET|TOKOP_STRING|TOKOP_DUP);
1800*906afcb8SAndy Fiddaman 				break;
1801*906afcb8SAndy Fiddaman 			case X_HOSTED:
1802*906afcb8SAndy Fiddaman 				setmode(HOSTED, i0);
1803*906afcb8SAndy Fiddaman 				break;
1804*906afcb8SAndy Fiddaman 			case X_HOSTEDTRANSITION:
1805*906afcb8SAndy Fiddaman 				setmode(HOSTEDTRANSITION, i0);
1806*906afcb8SAndy Fiddaman 				break;
1807*906afcb8SAndy Fiddaman 			case X_ID:
1808*906afcb8SAndy Fiddaman 				tokop(PP_ID, p3, p, i0, TOKOP_UNSET|TOKOP_STRING);
1809*906afcb8SAndy Fiddaman 				break;
1810*906afcb8SAndy Fiddaman 			case X_IGNORE:
1811*906afcb8SAndy Fiddaman 				tokop(PP_IGNORE, p3, p, i0, TOKOP_UNSET|TOKOP_STRING);
1812*906afcb8SAndy Fiddaman 				break;
1813*906afcb8SAndy Fiddaman 			case X_INCLUDE:
1814*906afcb8SAndy Fiddaman 				tokop(PP_INCLUDE, p3, p, i0, TOKOP_STRING|TOKOP_DUP);
1815*906afcb8SAndy Fiddaman 				break;
1816*906afcb8SAndy Fiddaman 			case X_INITIAL:
1817*906afcb8SAndy Fiddaman 				setoption(INITIAL, i0);
1818*906afcb8SAndy Fiddaman 				break;
1819*906afcb8SAndy Fiddaman 			case X_KEYARGS:
1820*906afcb8SAndy Fiddaman 				ppop(PP_KEYARGS, i0);
1821*906afcb8SAndy Fiddaman 				break;
1822*906afcb8SAndy Fiddaman 			case X_LINE:
1823*906afcb8SAndy Fiddaman 				if (pp.linesync) pp.olinesync = pp.linesync;
1824*906afcb8SAndy Fiddaman 				pp.linesync = i0 ? pp.olinesync : (PPLINESYNC)0;
1825*906afcb8SAndy Fiddaman 				break;
1826*906afcb8SAndy Fiddaman 			case X_LINEBASE:
1827*906afcb8SAndy Fiddaman 				ppop(PP_LINEBASE, i0);
1828*906afcb8SAndy Fiddaman 				break;
1829*906afcb8SAndy Fiddaman 			case X_LINEFILE:
1830*906afcb8SAndy Fiddaman 				ppop(PP_LINEFILE, i0);
1831*906afcb8SAndy Fiddaman 				break;
1832*906afcb8SAndy Fiddaman 			case X_LINEID:
1833*906afcb8SAndy Fiddaman 				ppop(PP_LINEID, i0 ? p : (char*)0);
1834*906afcb8SAndy Fiddaman 				break;
1835*906afcb8SAndy Fiddaman 			case X_LINETYPE:
1836*906afcb8SAndy Fiddaman 				ppop(PP_LINETYPE, i0 ? (p ? strtol(p, NiL, 0) : 1) : 0);
1837*906afcb8SAndy Fiddaman 				break;
1838*906afcb8SAndy Fiddaman 			case X_MACREF:
1839*906afcb8SAndy Fiddaman 				if (!p)
1840*906afcb8SAndy Fiddaman 				{
1841*906afcb8SAndy Fiddaman 					if (i0 && !pp.macref)
1842*906afcb8SAndy Fiddaman 					{
1843*906afcb8SAndy Fiddaman 						ppop(PP_LINETYPE, 1);
1844*906afcb8SAndy Fiddaman 						ppop(PP_MACREF, ppmacref);
1845*906afcb8SAndy Fiddaman 					}
1846*906afcb8SAndy Fiddaman 					else error(2, "%s: option cannot be unset", p3);
1847*906afcb8SAndy Fiddaman 				}
1848*906afcb8SAndy Fiddaman 				else if (s = strchr(p, ' '))
1849*906afcb8SAndy Fiddaman 				{
1850*906afcb8SAndy Fiddaman 					if (pp.macref && (s = strchr(p, ' ')))
1851*906afcb8SAndy Fiddaman 					{
1852*906afcb8SAndy Fiddaman 						*s++ = 0;
1853*906afcb8SAndy Fiddaman 						c = strtol(s, NiL, 0);
1854*906afcb8SAndy Fiddaman 						var.type = pp.truncate;
1855*906afcb8SAndy Fiddaman 						pp.truncate = PPTOKSIZ;
1856*906afcb8SAndy Fiddaman 						(*pp.macref)(pprefmac(p, REF_CREATE), error_info.file, error_info.line - (c == REF_NORMAL ? 2 : 1), c, (s = strchr(s, ' ')) ? strtol(s, NiL, 0) : 0L);
1857*906afcb8SAndy Fiddaman 						pp.truncate = var.type;
1858*906afcb8SAndy Fiddaman 					}
1859*906afcb8SAndy Fiddaman 					error_info.line -= 2;
1860*906afcb8SAndy Fiddaman 				}
1861*906afcb8SAndy Fiddaman 				break;
1862*906afcb8SAndy Fiddaman 			case X_MAP:
1863*906afcb8SAndy Fiddaman 				/*UNDENT*/
1864*906afcb8SAndy Fiddaman 	/*
1865*906afcb8SAndy Fiddaman 	 * #pragma pp:map [id ...] "/from/[,/to/]" [ "/old/new/[glnu]" ... ]
1866*906afcb8SAndy Fiddaman 	 */
1867*906afcb8SAndy Fiddaman 
1868*906afcb8SAndy Fiddaman 	if (!i0)
1869*906afcb8SAndy Fiddaman 	{
1870*906afcb8SAndy Fiddaman 		error(2, "%s: option cannot be unset", p3);
1871*906afcb8SAndy Fiddaman 		goto donedirective;
1872*906afcb8SAndy Fiddaman 	}
1873*906afcb8SAndy Fiddaman 	if (!p5)
1874*906afcb8SAndy Fiddaman 	{
1875*906afcb8SAndy Fiddaman 		error(2, "%s: address argument expected", p3);
1876*906afcb8SAndy Fiddaman 		goto donedirective;
1877*906afcb8SAndy Fiddaman 	}
1878*906afcb8SAndy Fiddaman 	PUSH_LINE(p5);
1879*906afcb8SAndy Fiddaman 	while ((c = pplex()) == T_ID)
1880*906afcb8SAndy Fiddaman 	{
1881*906afcb8SAndy Fiddaman 		sfsprintf(pp.tmpbuf, MAXTOKEN, "__%s__", s = pp.token);
1882*906afcb8SAndy Fiddaman 		if (c = (int)hashget(pp.dirtab, s))
1883*906afcb8SAndy Fiddaman 		{
1884*906afcb8SAndy Fiddaman 			hashput(pp.dirtab, 0, 0);
1885*906afcb8SAndy Fiddaman 			hashput(pp.dirtab, pp.tmpbuf, c);
1886*906afcb8SAndy Fiddaman 		}
1887*906afcb8SAndy Fiddaman 		if (c = (int)hashget(pp.strtab, s))
1888*906afcb8SAndy Fiddaman 		{
1889*906afcb8SAndy Fiddaman 			hashput(pp.strtab, 0, 0);
1890*906afcb8SAndy Fiddaman 			hashput(pp.strtab, pp.tmpbuf, c);
1891*906afcb8SAndy Fiddaman 		}
1892*906afcb8SAndy Fiddaman 	}
1893*906afcb8SAndy Fiddaman 	if (c != T_STRING || !*(s = pp.token))
1894*906afcb8SAndy Fiddaman 	{
1895*906afcb8SAndy Fiddaman 		if (c)
1896*906afcb8SAndy Fiddaman 			error(2, "%s: %s: address argument expected", p3, pptokstr(pp.token, 0));
1897*906afcb8SAndy Fiddaman 		goto eatmap;
1898*906afcb8SAndy Fiddaman 	}
1899*906afcb8SAndy Fiddaman 	map = newof(0, struct map, 1, 0);
1900*906afcb8SAndy Fiddaman 
1901*906afcb8SAndy Fiddaman 	/*
1902*906afcb8SAndy Fiddaman 	 * /from/
1903*906afcb8SAndy Fiddaman 	 */
1904*906afcb8SAndy Fiddaman 
1905*906afcb8SAndy Fiddaman 	if (i0 = regcomp(&map->re, s, REG_AUGMENTED|REG_DELIMITED|REG_LENIENT|REG_NULL))
1906*906afcb8SAndy Fiddaman 		regfatal(&map->re, 4, i0);
1907*906afcb8SAndy Fiddaman 	if (*(s += map->re.re_npat))
1908*906afcb8SAndy Fiddaman 	{
1909*906afcb8SAndy Fiddaman 		error(2, "%s: invalid characters after pattern: %s ", p3, s);
1910*906afcb8SAndy Fiddaman 		goto eatmap;
1911*906afcb8SAndy Fiddaman 	}
1912*906afcb8SAndy Fiddaman 
1913*906afcb8SAndy Fiddaman 	/*
1914*906afcb8SAndy Fiddaman 	 * /old/new/[flags]
1915*906afcb8SAndy Fiddaman 	 */
1916*906afcb8SAndy Fiddaman 
1917*906afcb8SAndy Fiddaman 	edit = 0;
1918*906afcb8SAndy Fiddaman 	while ((c = pplex()) == T_STRING)
1919*906afcb8SAndy Fiddaman 	{
1920*906afcb8SAndy Fiddaman 		if (!*(s = pp.token))
1921*906afcb8SAndy Fiddaman 		{
1922*906afcb8SAndy Fiddaman 			error(2, "%s: substitution argument expected", p3);
1923*906afcb8SAndy Fiddaman 			goto eatmap;
1924*906afcb8SAndy Fiddaman 		}
1925*906afcb8SAndy Fiddaman 		if (edit)
1926*906afcb8SAndy Fiddaman 			edit = edit->next = newof(0, struct edit, 1, 0);
1927*906afcb8SAndy Fiddaman 		else
1928*906afcb8SAndy Fiddaman 			edit = map->edit = newof(0, struct edit, 1, 0);
1929*906afcb8SAndy Fiddaman 		if (!(i0 = regcomp(&edit->re, s, REG_AUGMENTED|REG_DELIMITED|REG_LENIENT|REG_NULL)) && !(i0 = regsubcomp(&edit->re, s += edit->re.re_npat, NiL, 0, 0)))
1930*906afcb8SAndy Fiddaman 			s += edit->re.re_npat;
1931*906afcb8SAndy Fiddaman 		if (i0)
1932*906afcb8SAndy Fiddaman 			regfatal(&edit->re, 4, i0);
1933*906afcb8SAndy Fiddaman 		if (*s)
1934*906afcb8SAndy Fiddaman 		{
1935*906afcb8SAndy Fiddaman 			error(2, "%s: invalid characters after substitution: %s ", p3, s);
1936*906afcb8SAndy Fiddaman 			goto eatmap;
1937*906afcb8SAndy Fiddaman 		}
1938*906afcb8SAndy Fiddaman 	}
1939*906afcb8SAndy Fiddaman 	if (c)
1940*906afcb8SAndy Fiddaman 	{
1941*906afcb8SAndy Fiddaman 		error(2, "%s: %s: substitution argument expected", p3, pptokstr(pp.token, 0));
1942*906afcb8SAndy Fiddaman 		goto eatmap;
1943*906afcb8SAndy Fiddaman 	}
1944*906afcb8SAndy Fiddaman 	map->next = (struct map*)pp.maps;
1945*906afcb8SAndy Fiddaman 	pp.maps = (char*)map;
1946*906afcb8SAndy Fiddaman  eatmap:
1947*906afcb8SAndy Fiddaman 	POP_LINE();
1948*906afcb8SAndy Fiddaman 				/*INDENT*/
1949*906afcb8SAndy Fiddaman 				break;
1950*906afcb8SAndy Fiddaman 			case X_MAPINCLUDE:
1951*906afcb8SAndy Fiddaman 				ppmapinclude(NiL, p5);
1952*906afcb8SAndy Fiddaman 				break;
1953*906afcb8SAndy Fiddaman 			case X_MODERN:
1954*906afcb8SAndy Fiddaman 				setoption(MODERN, i0);
1955*906afcb8SAndy Fiddaman 				break;
1956*906afcb8SAndy Fiddaman 			case X_MULTIPLE:
1957*906afcb8SAndy Fiddaman 				n = 1;
1958*906afcb8SAndy Fiddaman 				if (pp.in->type == IN_FILE || pp.in->type == IN_RESCAN)
1959*906afcb8SAndy Fiddaman 					ppmultiple(ppsetfile(error_info.file), i0 ? INC_CLEAR : INC_IGNORE);
1960*906afcb8SAndy Fiddaman 				break;
1961*906afcb8SAndy Fiddaman 			case X_NATIVE:
1962*906afcb8SAndy Fiddaman 				setoption(NATIVE, i0);
1963*906afcb8SAndy Fiddaman 				break;
1964*906afcb8SAndy Fiddaman 			case X_OPSPACE:
1965*906afcb8SAndy Fiddaman 				ppfsm(FSM_OPSPACE, i0 ? p4 : (char*)0);
1966*906afcb8SAndy Fiddaman 				break;
1967*906afcb8SAndy Fiddaman 			case X_PASSTHROUGH:
1968*906afcb8SAndy Fiddaman 				ppop(PP_PASSTHROUGH, i0);
1969*906afcb8SAndy Fiddaman 				break;
1970*906afcb8SAndy Fiddaman 			case X_PEDANTIC:
1971*906afcb8SAndy Fiddaman 				ppop(PP_PEDANTIC, i0);
1972*906afcb8SAndy Fiddaman 				break;
1973*906afcb8SAndy Fiddaman 			case X_PLUSCOMMENT:
1974*906afcb8SAndy Fiddaman 				ppop(PP_PLUSCOMMENT, i0);
1975*906afcb8SAndy Fiddaman 				break;
1976*906afcb8SAndy Fiddaman 			case X_PLUSPLUS:
1977*906afcb8SAndy Fiddaman 				ppop(PP_PLUSPLUS, i0);
1978*906afcb8SAndy Fiddaman 				break;
1979*906afcb8SAndy Fiddaman 			case X_PLUSSPLICE:
1980*906afcb8SAndy Fiddaman 				setoption(PLUSSPLICE, i0);
1981*906afcb8SAndy Fiddaman 				break;
1982*906afcb8SAndy Fiddaman 			case X_PRAGMAEXPAND:
1983*906afcb8SAndy Fiddaman 				setoption(PRAGMAEXPAND, i0);
1984*906afcb8SAndy Fiddaman 				break;
1985*906afcb8SAndy Fiddaman 			case X_PRAGMAFLAGS:
1986*906afcb8SAndy Fiddaman 				tokop(PP_PRAGMAFLAGS, p3, p, i0, 0);
1987*906afcb8SAndy Fiddaman 				break;
1988*906afcb8SAndy Fiddaman 			case X_PREDEFINED:
1989*906afcb8SAndy Fiddaman 				setoption(PREDEFINED, i0);
1990*906afcb8SAndy Fiddaman 				break;
1991*906afcb8SAndy Fiddaman 			case X_PREFIX:
1992*906afcb8SAndy Fiddaman 				setoption(PREFIX, i0);
1993*906afcb8SAndy Fiddaman 				break;
1994*906afcb8SAndy Fiddaman 			case X_PRESERVE:
1995*906afcb8SAndy Fiddaman 				setoption(PRESERVE, i0);
1996*906afcb8SAndy Fiddaman 				if (pp.option & PRESERVE)
1997*906afcb8SAndy Fiddaman 				{
1998*906afcb8SAndy Fiddaman 					setmode(CATLITERAL, 0);
1999*906afcb8SAndy Fiddaman 					ppop(PP_COMPATIBILITY, 1);
2000*906afcb8SAndy Fiddaman 					ppop(PP_TRANSITION, 0);
2001*906afcb8SAndy Fiddaman 					ppop(PP_PLUSCOMMENT, 1);
2002*906afcb8SAndy Fiddaman 					ppop(PP_SPACEOUT, 1);
2003*906afcb8SAndy Fiddaman 					setoption(STRINGSPAN, 1);
2004*906afcb8SAndy Fiddaman 					setoption(STRINGSPLIT, 0);
2005*906afcb8SAndy Fiddaman 					ppop(PP_HOSTDIR, "-", 1);
2006*906afcb8SAndy Fiddaman 				}
2007*906afcb8SAndy Fiddaman 				break;
2008*906afcb8SAndy Fiddaman 			case X_PROTOTYPED:
2009*906afcb8SAndy Fiddaman 				/*
2010*906afcb8SAndy Fiddaman 				 * this option doesn't bump the token count
2011*906afcb8SAndy Fiddaman 				 */
2012*906afcb8SAndy Fiddaman 
2013*906afcb8SAndy Fiddaman 				n = 1;
2014*906afcb8SAndy Fiddaman 				directive = ENDIF;
2015*906afcb8SAndy Fiddaman #if PROTOTYPE
2016*906afcb8SAndy Fiddaman 				setoption(PROTOTYPED, i0);
2017*906afcb8SAndy Fiddaman #else
2018*906afcb8SAndy Fiddaman 				error(1, "preprocessor not compiled with prototype conversion enabled");
2019*906afcb8SAndy Fiddaman #endif
2020*906afcb8SAndy Fiddaman 				break;
2021*906afcb8SAndy Fiddaman 			case X_PROTO:
2022*906afcb8SAndy Fiddaman 				setoption(NOPROTO, !i0);
2023*906afcb8SAndy Fiddaman 				break;
2024*906afcb8SAndy Fiddaman 			case X_QUOTE:
2025*906afcb8SAndy Fiddaman 				tokop(PP_QUOTE, p3, p, i0, TOKOP_UNSET|TOKOP_STRING);
2026*906afcb8SAndy Fiddaman 				break;
2027*906afcb8SAndy Fiddaman 			case X_READONLY:
2028*906afcb8SAndy Fiddaman 				setmode(READONLY, i0);
2029*906afcb8SAndy Fiddaman 				break;
2030*906afcb8SAndy Fiddaman 			case X_REGUARD:
2031*906afcb8SAndy Fiddaman 				setoption(REGUARD, i0);
2032*906afcb8SAndy Fiddaman 				break;
2033*906afcb8SAndy Fiddaman 			case X_RESERVED:
2034*906afcb8SAndy Fiddaman 				tokop(PP_RESERVED, p3, p, i0, 0);
2035*906afcb8SAndy Fiddaman 				break;
2036*906afcb8SAndy Fiddaman 			case X_SPACEOUT:
2037*906afcb8SAndy Fiddaman 				if (!(pp.state & (COMPATIBILITY|COMPILE)))
2038*906afcb8SAndy Fiddaman 					ppop(PP_SPACEOUT, i0);
2039*906afcb8SAndy Fiddaman 				break;
2040*906afcb8SAndy Fiddaman 			case X_SPLICECAT:
2041*906afcb8SAndy Fiddaman 				setoption(SPLICECAT, i0);
2042*906afcb8SAndy Fiddaman 				break;
2043*906afcb8SAndy Fiddaman 			case X_SPLICESPACE:
2044*906afcb8SAndy Fiddaman 				setoption(SPLICESPACE, i0);
2045*906afcb8SAndy Fiddaman 				break;
2046*906afcb8SAndy Fiddaman 			case X_STANDARD:
2047*906afcb8SAndy Fiddaman 				tokop(PP_STANDARD, p3, p, i0, TOKOP_UNSET|TOKOP_STRING|TOKOP_DUP);
2048*906afcb8SAndy Fiddaman 				break;
2049*906afcb8SAndy Fiddaman 			case X_STRICT:
2050*906afcb8SAndy Fiddaman 				ppop(PP_STRICT, i0);
2051*906afcb8SAndy Fiddaman 				break;
2052*906afcb8SAndy Fiddaman 			case X_STRINGSPAN:
2053*906afcb8SAndy Fiddaman 				setoption(STRINGSPAN, i0);
2054*906afcb8SAndy Fiddaman 				break;
2055*906afcb8SAndy Fiddaman 			case X_STRINGSPLIT:
2056*906afcb8SAndy Fiddaman 				setoption(STRINGSPLIT, i0);
2057*906afcb8SAndy Fiddaman 				if (pp.option & STRINGSPLIT)
2058*906afcb8SAndy Fiddaman 					setmode(CATLITERAL, 0);
2059*906afcb8SAndy Fiddaman 				break;
2060*906afcb8SAndy Fiddaman 			case X_SYSTEM_HEADER:
2061*906afcb8SAndy Fiddaman 				if (i0)
2062*906afcb8SAndy Fiddaman 				{
2063*906afcb8SAndy Fiddaman 					pp.mode |= HOSTED;
2064*906afcb8SAndy Fiddaman 					pp.flags |= PP_hosted;
2065*906afcb8SAndy Fiddaman 					pp.in->flags |= IN_hosted;
2066*906afcb8SAndy Fiddaman 				}
2067*906afcb8SAndy Fiddaman 				else
2068*906afcb8SAndy Fiddaman 				{
2069*906afcb8SAndy Fiddaman 					pp.mode &= ~HOSTED;
2070*906afcb8SAndy Fiddaman 					pp.flags &= ~PP_hosted;
2071*906afcb8SAndy Fiddaman 					pp.in->flags &= ~PP_hosted;
2072*906afcb8SAndy Fiddaman 				}
2073*906afcb8SAndy Fiddaman 				break;
2074*906afcb8SAndy Fiddaman 			case X_TEST:
2075*906afcb8SAndy Fiddaman 				ppop(PP_TEST, p);
2076*906afcb8SAndy Fiddaman 				break;
2077*906afcb8SAndy Fiddaman 			case X_TEXT:
2078*906afcb8SAndy Fiddaman 				if (!(pp.option & KEEPNOTEXT))
2079*906afcb8SAndy Fiddaman 					setstate(NOTEXT, !i0);
2080*906afcb8SAndy Fiddaman 				break;
2081*906afcb8SAndy Fiddaman 			case X_TRANSITION:
2082*906afcb8SAndy Fiddaman 				ppop(PP_TRANSITION, i0);
2083*906afcb8SAndy Fiddaman 				if (pp.state & TRANSITION) ppop(PP_COMPATIBILITY, i0);
2084*906afcb8SAndy Fiddaman 				break;
2085*906afcb8SAndy Fiddaman 			case X_TRUNCATE:
2086*906afcb8SAndy Fiddaman 				ppop(PP_TRUNCATE, i0 ? (p ? strtol(p, NiL, 0) : TRUNCLENGTH) : 0);
2087*906afcb8SAndy Fiddaman 				break;
2088*906afcb8SAndy Fiddaman 			case X_VENDOR:
2089*906afcb8SAndy Fiddaman 				tokop(PP_VENDOR, p3, p, i0, TOKOP_UNSET|TOKOP_STRING|TOKOP_DUP);
2090*906afcb8SAndy Fiddaman 				break;
2091*906afcb8SAndy Fiddaman 			case X_VERSION:
2092*906afcb8SAndy Fiddaman 				if (!(*pp.control & SKIP) && pp.pragma && !(pp.state & NOTEXT))
2093*906afcb8SAndy Fiddaman 				{
2094*906afcb8SAndy Fiddaman 					sfsprintf(pp.tmpbuf, MAXTOKEN, "\"%s\"", pp.version);
2095*906afcb8SAndy Fiddaman 					(*pp.pragma)(dirname(PRAGMA), pp.pass, p3, pp.tmpbuf, !n);
2096*906afcb8SAndy Fiddaman 					if (pp.linesync && !n)
2097*906afcb8SAndy Fiddaman 						(*pp.linesync)(error_info.line, error_info.file);
2098*906afcb8SAndy Fiddaman 					emitted = 1;
2099*906afcb8SAndy Fiddaman 				}
2100*906afcb8SAndy Fiddaman 				break;
2101*906afcb8SAndy Fiddaman 			case X_WARN:
2102*906afcb8SAndy Fiddaman 				ppop(PP_WARN, i0);
2103*906afcb8SAndy Fiddaman 				break;
2104*906afcb8SAndy Fiddaman 			case X_ZEOF:
2105*906afcb8SAndy Fiddaman 				setoption(ZEOF, i0);
2106*906afcb8SAndy Fiddaman 				break;
2107*906afcb8SAndy Fiddaman #if DEBUG
2108*906afcb8SAndy Fiddaman 			case 0:
2109*906afcb8SAndy Fiddaman 			case X_INCLUDED:
2110*906afcb8SAndy Fiddaman 			case X_NOTICED:
2111*906afcb8SAndy Fiddaman 			case X_OPTION:
2112*906afcb8SAndy Fiddaman 			case X_STATEMENT:
2113*906afcb8SAndy Fiddaman 				break;
2114*906afcb8SAndy Fiddaman 			default:
2115*906afcb8SAndy Fiddaman 				error(PANIC, "%s: option recognized but not implemented", pp.valbuf);
2116*906afcb8SAndy Fiddaman 				break;
2117*906afcb8SAndy Fiddaman #endif
2118*906afcb8SAndy Fiddaman 			}
2119*906afcb8SAndy Fiddaman 			*p4 = i2;
2120*906afcb8SAndy Fiddaman 			if (!n)
2121*906afcb8SAndy Fiddaman 				goto checkmap;
2122*906afcb8SAndy Fiddaman 			goto donedirective;
2123*906afcb8SAndy Fiddaman 		case RENAME:
2124*906afcb8SAndy Fiddaman 			if ((pp.state & STRICT) && !(pp.mode & (HOSTED|RELAX)))
2125*906afcb8SAndy Fiddaman 				error(1, "#%s: non-standard directive", pp.token);
2126*906afcb8SAndy Fiddaman 			if ((c = pplex()) != T_ID)
2127*906afcb8SAndy Fiddaman 			{
2128*906afcb8SAndy Fiddaman 				error(1, "%s: invalid macro name", pptokstr(pp.token, 0));
2129*906afcb8SAndy Fiddaman 				goto eatdirective;
2130*906afcb8SAndy Fiddaman 			}
2131*906afcb8SAndy Fiddaman 			if (!(sym = pprefmac(pp.token, REF_DELETE)) || !sym->macro)
2132*906afcb8SAndy Fiddaman 				goto eatdirective;
2133*906afcb8SAndy Fiddaman 			if (sym->flags & (SYM_ACTIVE|SYM_READONLY))
2134*906afcb8SAndy Fiddaman 			{
2135*906afcb8SAndy Fiddaman 				if (!(pp.option & ALLPOSSIBLE))
2136*906afcb8SAndy Fiddaman 					error(2, "%s: macro is %s", sym->name, (sym->flags & SYM_READONLY) ? "readonly" : "active");
2137*906afcb8SAndy Fiddaman 				goto eatdirective;
2138*906afcb8SAndy Fiddaman 			}
2139*906afcb8SAndy Fiddaman 			if ((c = pplex()) != T_ID)
2140*906afcb8SAndy Fiddaman 			{
2141*906afcb8SAndy Fiddaman 				error(1, "%s: invalid macro name", pptokstr(pp.token, 0));
2142*906afcb8SAndy Fiddaman 				goto eatdirective;
2143*906afcb8SAndy Fiddaman 			}
2144*906afcb8SAndy Fiddaman 			var.symbol = pprefmac(pp.token, REF_CREATE);
2145*906afcb8SAndy Fiddaman 			if (mac = var.symbol->macro)
2146*906afcb8SAndy Fiddaman 			{
2147*906afcb8SAndy Fiddaman 				if (var.symbol->flags & (SYM_ACTIVE|SYM_READONLY))
2148*906afcb8SAndy Fiddaman 				{
2149*906afcb8SAndy Fiddaman 					if (!(pp.option & ALLPOSSIBLE))
2150*906afcb8SAndy Fiddaman 						error(2, "%s: macro is %s", var.symbol->name, (var.symbol->flags & SYM_READONLY) ? "readonly" : "active");
2151*906afcb8SAndy Fiddaman 					goto eatdirective;
2152*906afcb8SAndy Fiddaman 				}
2153*906afcb8SAndy Fiddaman 				if (!(pp.mode & HOSTED) || !(var.symbol->flags & SYM_INITIAL))
2154*906afcb8SAndy Fiddaman 					error(1, "%s redefined", var.symbol->name);
2155*906afcb8SAndy Fiddaman 				if (mac->formals) free(mac->formals);
2156*906afcb8SAndy Fiddaman 				free(mac->value);
2157*906afcb8SAndy Fiddaman 				free(mac);
2158*906afcb8SAndy Fiddaman 			}
2159*906afcb8SAndy Fiddaman 			ppfsm(FSM_MACRO, var.symbol->name);
2160*906afcb8SAndy Fiddaman 			var.symbol->flags = sym->flags;
2161*906afcb8SAndy Fiddaman 			sym->flags &= ~(SYM_BUILTIN|SYM_FUNCTION|SYM_INIT|SYM_MULTILINE|SYM_PREDEFINED|SYM_REDEFINE|SYM_VARIADIC);
2162*906afcb8SAndy Fiddaman 			var.symbol->macro = sym->macro;
2163*906afcb8SAndy Fiddaman 			sym->macro = 0;
2164*906afcb8SAndy Fiddaman 			break;
2165*906afcb8SAndy Fiddaman 		case UNDEF:
2166*906afcb8SAndy Fiddaman 			if ((c = pplex()) != T_ID)
2167*906afcb8SAndy Fiddaman 			{
2168*906afcb8SAndy Fiddaman 				error(1, "%s: invalid macro name", pptokstr(pp.token, 0));
2169*906afcb8SAndy Fiddaman 				goto eatdirective;
2170*906afcb8SAndy Fiddaman 			}
2171*906afcb8SAndy Fiddaman 			if (sym = pprefmac(pp.token, REF_DELETE))
2172*906afcb8SAndy Fiddaman 			{
2173*906afcb8SAndy Fiddaman 				if (mac = sym->macro)
2174*906afcb8SAndy Fiddaman 				{
2175*906afcb8SAndy Fiddaman 					if (sym->flags & (SYM_ACTIVE|SYM_READONLY))
2176*906afcb8SAndy Fiddaman 					{
2177*906afcb8SAndy Fiddaman 						if (!(pp.option & ALLPOSSIBLE))
2178*906afcb8SAndy Fiddaman 							error(2, "%s: macro is %s", sym->name, (sym->flags & SYM_READONLY) ? "readonly" : "active");
2179*906afcb8SAndy Fiddaman 						goto eatdirective;
2180*906afcb8SAndy Fiddaman 					}
2181*906afcb8SAndy Fiddaman 					if (mac->formals) free(mac->formals);
2182*906afcb8SAndy Fiddaman 					free(mac->value);
2183*906afcb8SAndy Fiddaman 					free(mac);
2184*906afcb8SAndy Fiddaman 					mac = sym->macro = 0;
2185*906afcb8SAndy Fiddaman 				}
2186*906afcb8SAndy Fiddaman 				if ((pp.option & (DEFINITIONS|PREDEFINITIONS|REGUARD)) && !sym->hidden && !(sym->flags & SYM_MULTILINE) && ((pp.option & PREDEFINITIONS) || !(pp.mode & INIT)) && ((pp.option & (DEFINITIONS|PREDEFINITIONS)) || !(pp.state & NOTEXT)))
2187*906afcb8SAndy Fiddaman 				{
2188*906afcb8SAndy Fiddaman 					ppsync();
2189*906afcb8SAndy Fiddaman 					ppprintf("#%s %s", dirname(UNDEF), sym->name);
2190*906afcb8SAndy Fiddaman 					emitted = 1;
2191*906afcb8SAndy Fiddaman 				}
2192*906afcb8SAndy Fiddaman 				sym->flags &= ~(SYM_BUILTIN|SYM_FUNCTION|SYM_INIT|SYM_MULTILINE|SYM_PREDEFINED|SYM_REDEFINE|SYM_VARIADIC);
2193*906afcb8SAndy Fiddaman 				n2 = error_info.line;
2194*906afcb8SAndy Fiddaman 				goto benign;
2195*906afcb8SAndy Fiddaman 			}
2196*906afcb8SAndy Fiddaman 			else pprefmac(pp.token, REF_UNDEF);
2197*906afcb8SAndy Fiddaman 			break;
2198*906afcb8SAndy Fiddaman #if DEBUG
2199*906afcb8SAndy Fiddaman 		default:
2200*906afcb8SAndy Fiddaman 			error(PANIC, "#%s: directive recognized but not implemented", pp.token);
2201*906afcb8SAndy Fiddaman 			goto eatdirective;
2202*906afcb8SAndy Fiddaman #endif
2203*906afcb8SAndy Fiddaman 		}
2204*906afcb8SAndy Fiddaman 		break;
2205*906afcb8SAndy Fiddaman 	case '\n':
2206*906afcb8SAndy Fiddaman 		break;
2207*906afcb8SAndy Fiddaman 	default:
2208*906afcb8SAndy Fiddaman 		error(1, "%s: invalid directive name", pptokstr(pp.token, 0));
2209*906afcb8SAndy Fiddaman 		goto eatdirective;
2210*906afcb8SAndy Fiddaman 	}
2211*906afcb8SAndy Fiddaman  enddirective:
2212*906afcb8SAndy Fiddaman #if COMPATIBLE
2213*906afcb8SAndy Fiddaman 	if (c != '\n' && !(pp.state & COMPATIBILITY))
2214*906afcb8SAndy Fiddaman #else
2215*906afcb8SAndy Fiddaman 	if (c != '\n')
2216*906afcb8SAndy Fiddaman #endif
2217*906afcb8SAndy Fiddaman 	{
2218*906afcb8SAndy Fiddaman 		pp.state |= DISABLE|NOSPACE;
2219*906afcb8SAndy Fiddaman 		if ((c = pplex()) != '\n' && (pp.mode & (HOSTED|PEDANTIC)) == PEDANTIC)
2220*906afcb8SAndy Fiddaman 			error(1, "%s: invalid characters after directive", pptokstr(pp.token, 0));
2221*906afcb8SAndy Fiddaman 	}
2222*906afcb8SAndy Fiddaman  eatdirective:
2223*906afcb8SAndy Fiddaman 	if (c != '\n')
2224*906afcb8SAndy Fiddaman 	{
2225*906afcb8SAndy Fiddaman 		pp.state |= DISABLE;
2226*906afcb8SAndy Fiddaman 		while (pplex() != '\n');
2227*906afcb8SAndy Fiddaman 	}
2228*906afcb8SAndy Fiddaman  donedirective:
2229*906afcb8SAndy Fiddaman #if _HUH_2002_05_09
2230*906afcb8SAndy Fiddaman 	if (!(pp.state & EOF2NL))
2231*906afcb8SAndy Fiddaman 		error(2, "%s in directive", pptokchr(0));
2232*906afcb8SAndy Fiddaman #endif
2233*906afcb8SAndy Fiddaman 	pp.state &= ~RESTORE;
2234*906afcb8SAndy Fiddaman 	pp.mode &= ~RELAX;
2235*906afcb8SAndy Fiddaman 	if (!(*pp.control & SKIP))
2236*906afcb8SAndy Fiddaman 	{
2237*906afcb8SAndy Fiddaman 		pp.state |= restore;
2238*906afcb8SAndy Fiddaman 		switch (directive)
2239*906afcb8SAndy Fiddaman 		{
2240*906afcb8SAndy Fiddaman 		case LINE:
2241*906afcb8SAndy Fiddaman 			return 0;
2242*906afcb8SAndy Fiddaman 		case INCLUDE:
2243*906afcb8SAndy Fiddaman 			if (pp.include)
2244*906afcb8SAndy Fiddaman 			{
2245*906afcb8SAndy Fiddaman 				error_info.line++;
2246*906afcb8SAndy Fiddaman 				PUSH_FILE(pp.include, n);
2247*906afcb8SAndy Fiddaman 				if (!pp.vendor && (pp.found->type & TYPE_VENDOR))
2248*906afcb8SAndy Fiddaman 					pp.vendor = 1;
2249*906afcb8SAndy Fiddaman 				pp.include = 0;
2250*906afcb8SAndy Fiddaman 				return 0;
2251*906afcb8SAndy Fiddaman 			}
2252*906afcb8SAndy Fiddaman 			if (pp.incref)
2253*906afcb8SAndy Fiddaman 				(*pp.incref)(error_info.file, ppgetfile(pp.path)->name, error_info.line, PP_SYNC_IGNORE);
2254*906afcb8SAndy Fiddaman 			else if (pp.linesync && pp.macref)
2255*906afcb8SAndy Fiddaman 			{
2256*906afcb8SAndy Fiddaman 				pp.flags |= PP_lineignore;
2257*906afcb8SAndy Fiddaman 				(*pp.linesync)(error_info.line, ppgetfile(pp.path)->name);
2258*906afcb8SAndy Fiddaman 			}
2259*906afcb8SAndy Fiddaman 			/*FALLTHROUGH*/
2260*906afcb8SAndy Fiddaman 		default:
2261*906afcb8SAndy Fiddaman 			pp.in->flags |= IN_tokens;
2262*906afcb8SAndy Fiddaman 			/*FALLTHROUGH*/
2263*906afcb8SAndy Fiddaman 		case ENDIF:
2264*906afcb8SAndy Fiddaman 			error_info.line++;
2265*906afcb8SAndy Fiddaman 			if (emitted)
2266*906afcb8SAndy Fiddaman 			{
2267*906afcb8SAndy Fiddaman 				ppputchar('\n');
2268*906afcb8SAndy Fiddaman 				ppcheckout();
2269*906afcb8SAndy Fiddaman 			}
2270*906afcb8SAndy Fiddaman 			else
2271*906afcb8SAndy Fiddaman 			{
2272*906afcb8SAndy Fiddaman 				pp.state |= HIDDEN;
2273*906afcb8SAndy Fiddaman 				pp.hidden++;
2274*906afcb8SAndy Fiddaman 			}
2275*906afcb8SAndy Fiddaman 			return 0;
2276*906afcb8SAndy Fiddaman 		}
2277*906afcb8SAndy Fiddaman 	}
2278*906afcb8SAndy Fiddaman 	pp.state |= restore|HIDDEN|SKIPCONTROL;
2279*906afcb8SAndy Fiddaman 	pp.hidden++;
2280*906afcb8SAndy Fiddaman 	pp.level++;
2281*906afcb8SAndy Fiddaman 	error_info.line++;
2282*906afcb8SAndy Fiddaman 	return 0;
2283*906afcb8SAndy Fiddaman }
2284*906afcb8SAndy Fiddaman 
2285*906afcb8SAndy Fiddaman /*
2286*906afcb8SAndy Fiddaman  * grow the pp nesting control stack
2287*906afcb8SAndy Fiddaman  */
2288*906afcb8SAndy Fiddaman 
2289*906afcb8SAndy Fiddaman void
ppnest(void)2290*906afcb8SAndy Fiddaman ppnest(void)
2291*906afcb8SAndy Fiddaman {
2292*906afcb8SAndy Fiddaman 	register struct ppinstk*	ip;
2293*906afcb8SAndy Fiddaman 	int				oz;
2294*906afcb8SAndy Fiddaman 	int				nz;
2295*906afcb8SAndy Fiddaman 	long				adjust;
2296*906afcb8SAndy Fiddaman 	long*				op;
2297*906afcb8SAndy Fiddaman 	long*				np;
2298*906afcb8SAndy Fiddaman 
2299*906afcb8SAndy Fiddaman 	oz = pp.constack;
2300*906afcb8SAndy Fiddaman 	op = pp.maxcon - oz + 1;
2301*906afcb8SAndy Fiddaman 	nz = oz * 2;
2302*906afcb8SAndy Fiddaman 	np = newof(op, long, nz, 0);
2303*906afcb8SAndy Fiddaman 	if (adjust = (np - op))
2304*906afcb8SAndy Fiddaman 	{
2305*906afcb8SAndy Fiddaman 		ip = pp.in;
2306*906afcb8SAndy Fiddaman 		do
2307*906afcb8SAndy Fiddaman 		{
2308*906afcb8SAndy Fiddaman 			if (ip->control)
2309*906afcb8SAndy Fiddaman 				ip->control += adjust;
2310*906afcb8SAndy Fiddaman 		} while (ip = ip->prev);
2311*906afcb8SAndy Fiddaman 	}
2312*906afcb8SAndy Fiddaman 	pp.control = np + oz;
2313*906afcb8SAndy Fiddaman 	pp.constack = nz;
2314*906afcb8SAndy Fiddaman 	pp.maxcon = np + nz - 1;
2315*906afcb8SAndy Fiddaman }
2316