xref: /titanic_51/usr/src/lib/libpp/common/pplex.c (revision 34f9b3eef6fdadbda0a846aa4d68691ac40eace5)
1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin *                                                                      *
3da2e3ebdSchin *               This software is part of the ast package               *
4*34f9b3eeSRoland Mainz *          Copyright (c) 1986-2009 AT&T Intellectual Property          *
5da2e3ebdSchin *                      and is licensed under the                       *
6da2e3ebdSchin *                  Common Public License, Version 1.0                  *
77c2fbfb3SApril Chin *                    by AT&T Intellectual Property                     *
8da2e3ebdSchin *                                                                      *
9da2e3ebdSchin *                A copy of the License is available at                 *
10da2e3ebdSchin *            http://www.opensource.org/licenses/cpl1.0.txt             *
11da2e3ebdSchin *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
12da2e3ebdSchin *                                                                      *
13da2e3ebdSchin *              Information and Software Systems Research               *
14da2e3ebdSchin *                            AT&T Research                             *
15da2e3ebdSchin *                           Florham Park NJ                            *
16da2e3ebdSchin *                                                                      *
17da2e3ebdSchin *                 Glenn Fowler <gsf@research.att.com>                  *
18da2e3ebdSchin *                                                                      *
19da2e3ebdSchin ***********************************************************************/
20da2e3ebdSchin #pragma prototyped
21da2e3ebdSchin /*
22da2e3ebdSchin  * Glenn Fowler
23da2e3ebdSchin  * AT&T Research
24da2e3ebdSchin  *
25da2e3ebdSchin  * preprocessor lexical analyzer
26da2e3ebdSchin  * standalone and tokenizing lexer combined in one source
27da2e3ebdSchin  * define CPP=1 for standalone
28da2e3ebdSchin  */
29da2e3ebdSchin 
30da2e3ebdSchin #include "pplib.h"
31da2e3ebdSchin #include "ppfsm.h"
32da2e3ebdSchin 
33da2e3ebdSchin #if CPP
34da2e3ebdSchin 
35da2e3ebdSchin /*
36da2e3ebdSchin  * standalone entry point
37da2e3ebdSchin  */
38da2e3ebdSchin 
39da2e3ebdSchin #define PPCPP_T		void
40da2e3ebdSchin 
41da2e3ebdSchin #define START		QUICK
42da2e3ebdSchin #define INMACRO(x)	INQMACRO(x)
43da2e3ebdSchin #define DOSTRIP()	(st&STRIP)
44da2e3ebdSchin 
45da2e3ebdSchin #if DEBUG & TRACE_debug
46da2e3ebdSchin static int		hit[LAST-TERMINAL+2];
47da2e3ebdSchin #endif
48da2e3ebdSchin 
49da2e3ebdSchin #define BACKIN()	(ip--)
50da2e3ebdSchin #define BACKOUT()	(op=tp)
51da2e3ebdSchin #define CACHE()		do{CACHEINX();CACHEOUTX();st=pp.state;if(!pp.hidden)spliced=0;}while(0)
52da2e3ebdSchin #define CACHEIN()	do{CACHEINX();st=pp.state;if(!pp.hidden)spliced=0;}while(0)
53da2e3ebdSchin #define CACHEINX()	do{ip=pp.in->nextchr;}while(0)
54da2e3ebdSchin #define CACHEOUT()	do{CACHEOUTX();st=pp.state;if(!pp.hidden)spliced=0;}while(0)
55da2e3ebdSchin #define CACHEOUTX()	do{tp=op=pp.outp;xp=pp.oute;if(sp)sp=op;}while(0)
56da2e3ebdSchin #define GETCHR()	(*(unsigned char*)ip++)
57da2e3ebdSchin #define LASTCHR()	(*(ip-1))
58da2e3ebdSchin #define LASTOUT()	((op>pp.outbuf)?*(op-1):pp.lastout)
59da2e3ebdSchin #define SKIPIN()	(ip++)
60da2e3ebdSchin #define PUTCHR(c)	(*op++=(c))
61da2e3ebdSchin #define SETCHR(c)	(*op=(c))
62da2e3ebdSchin #define SYNC()		do{SYNCINX();SYNCOUTX();pp.state=st;}while(0)
63da2e3ebdSchin #define SYNCIN()	do{SYNCINX();pp.state=st;}while(0)
64da2e3ebdSchin #define SYNCINX()	do{pp.in->nextchr=ip;}while(0)
65da2e3ebdSchin #define SYNCOUT()	do{SYNCOUTX();pp.state=st;}while(0)
66da2e3ebdSchin #define SYNCOUTX()	do{if(sp)op=tp=sp;pp.outp=op;}while(0)
67da2e3ebdSchin #define UNGETCHR(c)	(*--ip=(c))
68da2e3ebdSchin 
69da2e3ebdSchin #define PPCHECKOUT()	do{if(op>xp){{PPWRITE(PPBUFSIZ);if(pp.outbuf==pp.outb){pp.outbuf+=PPBUFSIZ;xp=pp.oute+=PPBUFSIZ;}else{pp.outbuf-=PPBUFSIZ;memcpy(pp.outbuf,xp,op-xp);xp=pp.oute-=PPBUFSIZ;op-=2*PPBUFSIZ;}}}}while(0)
70da2e3ebdSchin #define PPCHECKOUTSP()	do{if(op>xp){if(sp)op=sp;else{PPWRITE(PPBUFSIZ);if(pp.outbuf==pp.outb){pp.outbuf+=PPBUFSIZ;xp=pp.oute+=PPBUFSIZ;}else{pp.outbuf-=PPBUFSIZ;memcpy(pp.outbuf,xp,op-xp);xp=pp.oute-=PPBUFSIZ;op-=2*PPBUFSIZ;}}}}while(0)
71da2e3ebdSchin #define PPCHECKOUTTP()	do{if(op>xp){{PPWRITE(PPBUFSIZ);if(pp.outbuf==pp.outb){pp.outbuf+=PPBUFSIZ;xp=pp.oute+=PPBUFSIZ;}else{pp.outbuf-=PPBUFSIZ;memcpy(pp.outbuf,xp,op-xp);xp=pp.oute-=PPBUFSIZ;op-=2*PPBUFSIZ;}}tp=op;}}while(0)
72da2e3ebdSchin 
73da2e3ebdSchin #define PPSYNCLINE()	do { \
74da2e3ebdSchin 		if ((st & (ADD|HIDDEN)) && !(*pp.control & SKIP)) \
75da2e3ebdSchin 		{ \
76da2e3ebdSchin 		    if (spliced) \
77da2e3ebdSchin 		    { \
78da2e3ebdSchin 			error_info.line += spliced; \
79da2e3ebdSchin 			spliced = 0; \
80da2e3ebdSchin 		    } \
81da2e3ebdSchin 		    else \
82da2e3ebdSchin 		    { \
83da2e3ebdSchin 			if (st & ADD) \
84da2e3ebdSchin 			{ \
85da2e3ebdSchin 				st &= ~ADD; \
86da2e3ebdSchin 				m = pp.addp - pp.addbuf; \
87da2e3ebdSchin 				pp.addp = pp.addbuf; \
88da2e3ebdSchin 				memcpy(op, pp.addbuf, m); \
89da2e3ebdSchin 				op += m; \
90da2e3ebdSchin 				PPCHECKOUT(); \
91da2e3ebdSchin 			} \
92da2e3ebdSchin 			if (pp.linesync) \
93da2e3ebdSchin 			{ \
94da2e3ebdSchin 				if ((st & SYNCLINE) || pp.hidden >= MAXHIDDEN) \
95da2e3ebdSchin 				{ \
96da2e3ebdSchin 					pp.hidden = 0; \
97da2e3ebdSchin 					st &= ~(HIDDEN|SYNCLINE); \
98da2e3ebdSchin 					if (error_info.line) \
99da2e3ebdSchin 					{ \
100da2e3ebdSchin 						if (LASTOUT() != '\n') \
101da2e3ebdSchin 							PUTCHR('\n'); \
102da2e3ebdSchin 						SYNCOUT(); \
103da2e3ebdSchin 						(*pp.linesync)(error_info.line, error_info.file); \
104da2e3ebdSchin 						CACHEOUT(); \
105da2e3ebdSchin 					} \
106da2e3ebdSchin 				} \
107da2e3ebdSchin 				else \
108da2e3ebdSchin 				{ \
109da2e3ebdSchin 					m = pp.hidden; \
110da2e3ebdSchin 					pp.hidden = 0; \
111da2e3ebdSchin 					st &= ~HIDDEN; \
112da2e3ebdSchin 					while (m-- > 0) \
113da2e3ebdSchin 						PUTCHR('\n'); \
114da2e3ebdSchin 				} \
115da2e3ebdSchin 			} \
116da2e3ebdSchin 			else \
117da2e3ebdSchin 			{ \
118da2e3ebdSchin 				pp.hidden = 0; \
119da2e3ebdSchin 				st &= ~HIDDEN; \
120da2e3ebdSchin 				PUTCHR('\n'); \
121da2e3ebdSchin 			} \
122da2e3ebdSchin 		    } \
123da2e3ebdSchin 		} \
124da2e3ebdSchin 	} while (0)
125da2e3ebdSchin 
126da2e3ebdSchin #if POOL
127da2e3ebdSchin 
128da2e3ebdSchin /*
129da2e3ebdSchin  * <wait.h> is poison here so pool moved to the end
130da2e3ebdSchin  */
131da2e3ebdSchin 
132da2e3ebdSchin static void	poolstatus(void);
133da2e3ebdSchin static void	pool(void);
134da2e3ebdSchin 
135da2e3ebdSchin #endif
136da2e3ebdSchin 
137da2e3ebdSchin #else
138da2e3ebdSchin 
139da2e3ebdSchin /*
140da2e3ebdSchin  * return next pp token
141da2e3ebdSchin  *
142da2e3ebdSchin  * NOTE: pp.token points to at least MAXTOKEN*2 chars and is
143da2e3ebdSchin  *       truncated back to MAXTOKEN on EOB
144da2e3ebdSchin  */
145da2e3ebdSchin 
146da2e3ebdSchin #define PPCPP_T		int
147da2e3ebdSchin #define ppcpp		pplex
148da2e3ebdSchin 
149da2e3ebdSchin #define START		TOKEN
150da2e3ebdSchin #define INMACRO(x)	INTMACRO(x)
151da2e3ebdSchin #define DOSTRIP()	((st&STRIP)||pp.level==1&&(st&(COMPILE|JOINING))==COMPILE&&!(pp.option&PRESERVE))
152da2e3ebdSchin 
153da2e3ebdSchin #define st		pp.state
154da2e3ebdSchin #define tp		pp.token
155da2e3ebdSchin #define xp		&pp.token[MAXTOKEN]
156da2e3ebdSchin 
157da2e3ebdSchin #define BACKIN()	(ip--)
158da2e3ebdSchin #define BACKOUT()	(op=pp.token)
159da2e3ebdSchin #define CACHE()		do{CACHEIN();CACHEOUT();}while(0)
160da2e3ebdSchin #define CACHEIN()	(ip=pp.in->nextchr)
161da2e3ebdSchin #define CACHEOUT()	(op=pp.token)
162da2e3ebdSchin #define GETCHR()	(*(unsigned char*)ip++)
163da2e3ebdSchin #define LASTCHR()	(*(ip-1))
164da2e3ebdSchin #define PUTCHR(c)	(*op++=(c))
165da2e3ebdSchin #define SETCHR(c)	(*op=(c))
166da2e3ebdSchin #define SKIPIN()	(ip++)
167da2e3ebdSchin #define SYNC()		do{SYNCIN();SYNCOUT();}while(0)
168da2e3ebdSchin #define SYNCIN()	(pp.in->nextchr=ip)
169da2e3ebdSchin #define SYNCOUT()	(pp.toknxt=op)
170da2e3ebdSchin #define UNGETCHR(c)	(*--ip=(c))
171da2e3ebdSchin 
172da2e3ebdSchin #endif
173da2e3ebdSchin 
174da2e3ebdSchin PPCPP_T
ppcpp(void)175da2e3ebdSchin ppcpp(void)
176da2e3ebdSchin {
177da2e3ebdSchin 	register short*		rp;
178da2e3ebdSchin 	register char*		ip;
179da2e3ebdSchin 	register int		state;
180da2e3ebdSchin 	register int		c;
181da2e3ebdSchin 	register char*		op;
182da2e3ebdSchin 	char*			bp;
183da2e3ebdSchin 	int			n;
184da2e3ebdSchin 	int			m;
185da2e3ebdSchin 	int			quot;
186da2e3ebdSchin 	int			quotquot;
187da2e3ebdSchin 	int			comdelim = 0;
188da2e3ebdSchin 	int			comstart = 0;
189da2e3ebdSchin 	int			comwarn = 0;
190da2e3ebdSchin 	char*			s;
191da2e3ebdSchin 	struct ppsymbol*	sym;
192da2e3ebdSchin #if CPP
193da2e3ebdSchin 	register long		st;
194da2e3ebdSchin 	char*			tp;
195da2e3ebdSchin 	char*			xp;
196da2e3ebdSchin 	char*			sp = 0;
197da2e3ebdSchin 	int			qual = 0;
198da2e3ebdSchin 	int			spliced = 0;
199da2e3ebdSchin #else
200da2e3ebdSchin 	int			qual;
201da2e3ebdSchin #endif
202da2e3ebdSchin 
203da2e3ebdSchin #if CPP
204da2e3ebdSchin #if POOL
205da2e3ebdSchin  fsm_pool:
206da2e3ebdSchin #endif
207da2e3ebdSchin #else
208da2e3ebdSchin 	count(pplex);
209da2e3ebdSchin #endif
210da2e3ebdSchin 	error_info.indent++;
211da2e3ebdSchin 	pp.level++;
212da2e3ebdSchin 	CACHE();
213da2e3ebdSchin #if !CPP
214da2e3ebdSchin  fsm_top:
215da2e3ebdSchin 	qual = 0;
216da2e3ebdSchin #endif
217da2e3ebdSchin  fsm_start:
218da2e3ebdSchin #if CPP
219da2e3ebdSchin 	PPCHECKOUTSP();
220da2e3ebdSchin 	tp = op;
221da2e3ebdSchin #endif
222da2e3ebdSchin 	state = START;
223da2e3ebdSchin  fsm_begin:
224da2e3ebdSchin 	bp = ip;
225da2e3ebdSchin 	do
226da2e3ebdSchin 	{
227da2e3ebdSchin 		rp = fsm[state];
228da2e3ebdSchin  fsm_get:
229da2e3ebdSchin 		while (!(state = rp[c = GETCHR()]));
230da2e3ebdSchin  fsm_next:
231da2e3ebdSchin 		;
232da2e3ebdSchin 	} while (state > 0);
233da2e3ebdSchin 	if (((state = ~state) != S_COMMENT || pp.comment || c == '/' && !INCOMMENT(rp)) && (n = ip - bp - 1) > 0)
234da2e3ebdSchin 	{
235da2e3ebdSchin 		ip = bp;
236da2e3ebdSchin #if CPP
2377c2fbfb3SApril Chin 		if (op == tp && (st & (ADD|HIDDEN)) && !(st & PASSTHROUGH) && !(pp.option & PRESERVE))
238da2e3ebdSchin 			switch (TERM(state))
239da2e3ebdSchin 			{
240da2e3ebdSchin 			case S_SHARP:
241da2e3ebdSchin 				break;
242da2e3ebdSchin 			case S_CHRB:
243da2e3ebdSchin 			case S_NL:
244da2e3ebdSchin 				if (*ip == '\n')
245da2e3ebdSchin 					break;
246da2e3ebdSchin 				/*FALLTHROUGH*/
247da2e3ebdSchin 			default:
2487c2fbfb3SApril Chin 				if ((pp.option & PRESERVE) && !(st & NEWLINE) && c != '\n')
2497c2fbfb3SApril Chin 					break;
250da2e3ebdSchin 				PPSYNCLINE();
251da2e3ebdSchin 				tp = op;
252da2e3ebdSchin 				break;
253da2e3ebdSchin 			}
254da2e3ebdSchin #endif
255da2e3ebdSchin 		MEMCPY(op, ip, n);
256da2e3ebdSchin 		ip++;
257da2e3ebdSchin 	}
258da2e3ebdSchin 	count(terminal);
259da2e3ebdSchin #if CPP && (DEBUG & TRACE_debug)
260da2e3ebdSchin 	hit[(state & SPLICE) ? (elementsof(hit) - 1) : (TERM(state) - TERMINAL)]++;
261da2e3ebdSchin #endif
262da2e3ebdSchin  fsm_terminal:
263da2e3ebdSchin 	debug((-9, "TERM %s > %s%s%s |%-*.*s|%s|", pplexstr(INDEX(rp)), pplexstr(state), (st & NEWLINE) ? "|NEWLINE" : "", (st & SKIPCONTROL) ? "|SKIP" : "", op - tp, op - tp, tp, pptokchr(c)));
264da2e3ebdSchin 	switch (TERM(state))
265da2e3ebdSchin 	{
266da2e3ebdSchin 
267da2e3ebdSchin #if !CPP
268da2e3ebdSchin 	case S_CHR:
269da2e3ebdSchin 		PUTCHR(c);
270da2e3ebdSchin 		break;
271da2e3ebdSchin #endif
272da2e3ebdSchin 
273da2e3ebdSchin 	case S_CHRB:
274da2e3ebdSchin 		BACKIN();
275da2e3ebdSchin #if CPP
276da2e3ebdSchin 		st &= ~NEWLINE;
277da2e3ebdSchin 		pp.in->flags |= IN_tokens;
278da2e3ebdSchin 		count(token);
279da2e3ebdSchin 		goto fsm_start;
280da2e3ebdSchin #else
281da2e3ebdSchin 		c = *tp;
282da2e3ebdSchin 		break;
283da2e3ebdSchin #endif
284da2e3ebdSchin 
285da2e3ebdSchin 	case S_COMMENT:
286da2e3ebdSchin 		switch (c)
287da2e3ebdSchin 		{
288da2e3ebdSchin 		case '\n':
289da2e3ebdSchin 			if (!INCOMMENTXX(rp))
290da2e3ebdSchin 			{
291da2e3ebdSchin 				qual = 0;
292da2e3ebdSchin 				if (!comstart) comstart = comdelim = error_info.line;
293da2e3ebdSchin 				error_info.line++;
294da2e3ebdSchin 				if (pp.comment) PUTCHR(c);
295da2e3ebdSchin 				else BACKOUT();
296da2e3ebdSchin #if CPP
297da2e3ebdSchin 				rp = fsm[COM2];
298da2e3ebdSchin 				bp = ip;
299da2e3ebdSchin 				goto fsm_get;
300da2e3ebdSchin #else
301da2e3ebdSchin 				state = COM2;
302da2e3ebdSchin 				goto fsm_begin;
303da2e3ebdSchin #endif
304da2e3ebdSchin 			}
305da2e3ebdSchin 			else if (comwarn < 0 && !(pp.mode & HOSTED))
306da2e3ebdSchin 				error(1, "/* appears in // comment");
307da2e3ebdSchin 			break;
308da2e3ebdSchin 		case '*':
309da2e3ebdSchin 			if (!comwarn && !(pp.mode & HOSTED))
310da2e3ebdSchin 			{
311da2e3ebdSchin 				if (INCOMMENTXX(rp)) comwarn = -1;
312da2e3ebdSchin 				else if (comstart && comstart != error_info.line)
313da2e3ebdSchin 				{
314da2e3ebdSchin 					if (qual || comdelim < error_info.line - 1)
315da2e3ebdSchin 					{
316da2e3ebdSchin 						error(1, "/* appears in /* ... */ comment starting at line %d", comstart);
317da2e3ebdSchin 						comwarn = 1;
318da2e3ebdSchin 					}
319da2e3ebdSchin 					else comdelim = error_info.line;
320da2e3ebdSchin 				}
321da2e3ebdSchin 			}
322da2e3ebdSchin  fsm_comment:
323da2e3ebdSchin 			PUTCHR(c);
324da2e3ebdSchin #if CPP
325da2e3ebdSchin 			rp = fsm[INCOMMENTXX(rp) ? COM5 : COM3];
326da2e3ebdSchin 			bp = ip;
327da2e3ebdSchin 			goto fsm_get;
328da2e3ebdSchin #else
329da2e3ebdSchin 			state = INCOMMENTXX(rp) ? COM5 : COM3;
330da2e3ebdSchin 			goto fsm_begin;
331da2e3ebdSchin #endif
332da2e3ebdSchin 		case '/':
333da2e3ebdSchin 			if (!INCOMMENT(rp))
334da2e3ebdSchin 			{
335da2e3ebdSchin 				if (!(pp.mode & HOSTED))
336da2e3ebdSchin 					error(1, "*/ appears outside of comment");
337da2e3ebdSchin 				BACKIN();
338da2e3ebdSchin #if CPP
339da2e3ebdSchin 				st &= ~NEWLINE;
340da2e3ebdSchin 				pp.in->flags |= IN_tokens;
341da2e3ebdSchin 				count(token);
342da2e3ebdSchin 				goto fsm_start;
343da2e3ebdSchin #else
344da2e3ebdSchin 				c = '*';
345da2e3ebdSchin 				if (!pp.comment) PUTCHR(c);
346da2e3ebdSchin 				goto fsm_token;
347da2e3ebdSchin #endif
348da2e3ebdSchin 			}
349da2e3ebdSchin 			else if (INCOMMENTXX(rp))
350da2e3ebdSchin 			{
351da2e3ebdSchin 				if (!(pp.mode & HOSTED))
352da2e3ebdSchin 				{
353da2e3ebdSchin 					if (comwarn < 0) comwarn = 0;
354da2e3ebdSchin 					else if (!comwarn)
355da2e3ebdSchin 					{
356da2e3ebdSchin 						comwarn = 1;
357da2e3ebdSchin 						error(1, "*/ appears in // comment");
358da2e3ebdSchin 					}
359da2e3ebdSchin 				}
360da2e3ebdSchin 				goto fsm_comment;
361da2e3ebdSchin 			}
362da2e3ebdSchin 			break;
363da2e3ebdSchin 		case EOF:
364da2e3ebdSchin 			BACKIN();
365da2e3ebdSchin 			if (!(pp.mode & HOSTED))
366da2e3ebdSchin 			{
367da2e3ebdSchin 				if (comstart) error(2, "unterminated /* ... */ comment starting at line %d", comstart);
368da2e3ebdSchin 				else if (INCOMMENTXX(rp)) error(2, "unterminated // ... comment");
369da2e3ebdSchin 				else error(2, "unterminated /* ... */ comment");
370da2e3ebdSchin 			}
371da2e3ebdSchin 			break;
372da2e3ebdSchin 		}
373da2e3ebdSchin #if CPP
374da2e3ebdSchin 		if (!pp.comment || sp)
375da2e3ebdSchin 		{
376da2e3ebdSchin #if COMPATIBLE
377da2e3ebdSchin 			if (!(pp.state & COMPATIBILITY) || *bp == ' ' || *bp == '\t')
378da2e3ebdSchin #endif
379da2e3ebdSchin 			{
380da2e3ebdSchin 				BACKOUT();
381da2e3ebdSchin 				PUTCHR(' ');
382da2e3ebdSchin 				tp = op;
383da2e3ebdSchin 			}
384da2e3ebdSchin 		}
385da2e3ebdSchin 		else if (pp.in->type & IN_TOP)
386da2e3ebdSchin #else
387da2e3ebdSchin 		if (pp.comment && !(st & (COLLECTING|DIRECTIVE|JOINING)) && !(*pp.control & SKIP) && (pp.in->type & IN_TOP))
388da2e3ebdSchin #endif
389da2e3ebdSchin 		{
390da2e3ebdSchin 			st &= ~HIDDEN;
391da2e3ebdSchin 			pp.hidden = 0;
392da2e3ebdSchin 			*(op - (c != '\n')) = 0;
393da2e3ebdSchin 			m = (op - (c != '\n') - tp > MAXTOKEN - 6) ? (error_info.line - MAXHIDDEN) : 0;
394da2e3ebdSchin 			BACKOUT();
395da2e3ebdSchin 			SYNC();
396da2e3ebdSchin 			while (*tp != '/') tp++;
397da2e3ebdSchin 			(*pp.comment)(c == '\n' ? "//" : "/*", tp + 2, c == '\n' ? "" : (st & HEADER) ? "*/\n" : "*/", comstart ? comstart : error_info.line);
398da2e3ebdSchin 			CACHE();
399da2e3ebdSchin 			comstart = m;
400da2e3ebdSchin 		}
401da2e3ebdSchin 		if (comstart)
402da2e3ebdSchin 		{
403da2e3ebdSchin 			st |= HIDDEN;
404da2e3ebdSchin 			pp.hidden += error_info.line - comstart;
405da2e3ebdSchin 			comstart = 0;
406da2e3ebdSchin 		}
407da2e3ebdSchin 		qual = comwarn = comdelim = 0;
408da2e3ebdSchin 		BACKOUT();
409da2e3ebdSchin 		if (c == '\n') goto fsm_newline;
410da2e3ebdSchin 		if ((st & PASSTHROUGH) && ((st & (HIDDEN|NEWLINE)) || *ip == '\n'))
411da2e3ebdSchin 		{
412da2e3ebdSchin 			if (*ip == '\n')
413da2e3ebdSchin 				ip++;
414da2e3ebdSchin 			goto fsm_newline;
415da2e3ebdSchin 		}
416da2e3ebdSchin #if COMPATIBLE
417da2e3ebdSchin 		if ((st & (COMPATIBILITY|TRANSITION)) == COMPATIBILITY) st &= ~NEWLINE;
418da2e3ebdSchin #endif
419da2e3ebdSchin #if !CPP
420da2e3ebdSchin 		if (pp.level > 1 && !(st & (NOSPACE|SKIPCONTROL)))
421da2e3ebdSchin 		{
422da2e3ebdSchin #if COMPATIBLE
423da2e3ebdSchin 			c = ((st & (COMPATIBILITY|DEFINITION)) == ((COMPATIBILITY|DEFINITION))) ? '\t' : ' ';
424da2e3ebdSchin #else
425da2e3ebdSchin 			c = ' ';
426da2e3ebdSchin #endif
427da2e3ebdSchin 			goto fsm_return;
428da2e3ebdSchin 		}
429da2e3ebdSchin #endif
430da2e3ebdSchin 		goto fsm_start;
431da2e3ebdSchin 
432da2e3ebdSchin 	case S_EOB:
433da2e3ebdSchin 		if (c)
434da2e3ebdSchin 		{
435da2e3ebdSchin 			if (state = fsm[TERMINAL][INDEX(rp)+1])
436da2e3ebdSchin 				goto fsm_terminal;
437da2e3ebdSchin #if CPP
438da2e3ebdSchin #if POOL
439da2e3ebdSchin 			if (pp.pool.input)
440da2e3ebdSchin 			{
441da2e3ebdSchin 				BACKIN();
442da2e3ebdSchin 				SYNC();
443da2e3ebdSchin 				pool();
444da2e3ebdSchin 				CACHE();
445da2e3ebdSchin 				goto fsm_pool;
446da2e3ebdSchin 			}
447da2e3ebdSchin #endif
448da2e3ebdSchin 			SYNCOUT();
449da2e3ebdSchin 			return;
450da2e3ebdSchin #else
451da2e3ebdSchin 			BACKIN();
452da2e3ebdSchin 			c = 0;
453da2e3ebdSchin 			goto fsm_return;
454da2e3ebdSchin #endif
455da2e3ebdSchin 		}
456da2e3ebdSchin 		{
457da2e3ebdSchin 			register struct ppinstk*	cur = pp.in;
458da2e3ebdSchin 			register struct ppinstk*	prv = pp.in->prev;
459da2e3ebdSchin 
460da2e3ebdSchin #if CPP
461da2e3ebdSchin 			if (sp) op = sp;
462da2e3ebdSchin #endif
463da2e3ebdSchin 			switch (cur->type)
464da2e3ebdSchin 			{
465da2e3ebdSchin 			case IN_BUFFER:
466da2e3ebdSchin 			case IN_INIT:
467da2e3ebdSchin 			case IN_RESCAN:
468da2e3ebdSchin #if CPP
469da2e3ebdSchin 				if (prv)
470da2e3ebdSchin #else
471da2e3ebdSchin 				if (!(st & PASSEOF) && prv)
472da2e3ebdSchin #endif
473da2e3ebdSchin 				{
474da2e3ebdSchin 					if (cur->type == IN_RESCAN || cur->type == IN_BUFFER)
475da2e3ebdSchin 					{
476da2e3ebdSchin  fsm_pop:
477da2e3ebdSchin #if PROTOTYPE
478da2e3ebdSchin 						if (cur->flags & IN_prototype)
479da2e3ebdSchin 							pppclose(cur->buffer + PPBAKSIZ);
480da2e3ebdSchin 						else
481da2e3ebdSchin #endif
482da2e3ebdSchin 						if (!(cur->flags & IN_static))
483da2e3ebdSchin 							free(cur->buffer);
484da2e3ebdSchin 					}
485da2e3ebdSchin 					while (pp.control-- != cur->control)
486da2e3ebdSchin 						error(2, "#%s on line %d has no #%s", dirname(IF), GETIFLINE(pp.control+1), dirname(ENDIF));
487da2e3ebdSchin 					st |= NEWLINE;
488da2e3ebdSchin 					error_info.file = cur->file;
489da2e3ebdSchin 					error_info.line = cur->line;
490da2e3ebdSchin 					pp.hidden = 0;
491da2e3ebdSchin #if CPP
492da2e3ebdSchin 					spliced = 0;
493da2e3ebdSchin #endif
494da2e3ebdSchin 					if (cur->flags & IN_hosted)
495da2e3ebdSchin 					{
496da2e3ebdSchin 						pp.mode |= HOSTED;
497da2e3ebdSchin 						pp.flags |= PP_hosted;
498da2e3ebdSchin 					}
499da2e3ebdSchin 					else
500da2e3ebdSchin 					{
501da2e3ebdSchin 						pp.mode &= ~HOSTED;
502da2e3ebdSchin 						pp.flags &= ~PP_hosted;
503da2e3ebdSchin 					}
504da2e3ebdSchin #if !CPP && CATSTRINGS
505da2e3ebdSchin 					if (st & JOINING) st |= HIDDEN|SYNCLINE;
506da2e3ebdSchin 					else
507da2e3ebdSchin #endif
508da2e3ebdSchin 					{
509da2e3ebdSchin 						st &= ~(HIDDEN|SYNCLINE);
510da2e3ebdSchin 						switch (cur->type)
511da2e3ebdSchin 						{
512da2e3ebdSchin 						case IN_BUFFER:
513da2e3ebdSchin 						case IN_INIT:
514da2e3ebdSchin 							if (!prv->prev) break;
515da2e3ebdSchin 							/*FALLTHROUGH*/
516da2e3ebdSchin 						case IN_FILE:
517da2e3ebdSchin 						case IN_RESCAN:
518da2e3ebdSchin 							if (prv->type == IN_FILE || cur->type == IN_FILE && (prv->type == IN_RESCAN || prv->type == IN_MULTILINE))
519da2e3ebdSchin 							{
520da2e3ebdSchin 								if (pp.linesync && (cur->type != IN_RESCAN || (cur->flags & IN_sync)))
521da2e3ebdSchin 								{
522da2e3ebdSchin 									POP();
523da2e3ebdSchin 									SYNCOUT();
524da2e3ebdSchin 									(*pp.linesync)(error_info.line, error_info.file);
525da2e3ebdSchin 									CACHEOUT();
526da2e3ebdSchin 									prv = pp.in;
527da2e3ebdSchin 								}
528da2e3ebdSchin 							}
529da2e3ebdSchin #if DEBUG
530da2e3ebdSchin 							else if (!prv->prev)
531da2e3ebdSchin 							{
532da2e3ebdSchin 								/*UNDENT*/
533da2e3ebdSchin 	c = 0;
534da2e3ebdSchin #if DEBUG & TRACE_count
535da2e3ebdSchin 	if (pp.test & TEST_count)
536da2e3ebdSchin 	{
537da2e3ebdSchin 		c = 1;
538da2e3ebdSchin 		sfprintf(sfstderr, "\n");
539da2e3ebdSchin 		sfprintf(sfstderr, "%7d: pplex calls\n", pp.counter.pplex);
540da2e3ebdSchin 		sfprintf(sfstderr, "%7d: terminal states\n", pp.counter.terminal);
541da2e3ebdSchin 		sfprintf(sfstderr, "%7d: emitted tokens\n", pp.counter.token);
542da2e3ebdSchin 		sfprintf(sfstderr, "%7d: input stream pushes\n", pp.counter.push);
543da2e3ebdSchin 		sfprintf(sfstderr, "%7d: macro candidates\n", pp.counter.candidate);
544da2e3ebdSchin 		sfprintf(sfstderr, "%7d: macro expansions\n", pp.counter.macro);
545da2e3ebdSchin 		sfprintf(sfstderr, "%7d: function macros\n", pp.counter.function);
546da2e3ebdSchin 	}
547da2e3ebdSchin #endif
548da2e3ebdSchin #if CPP && (DEBUG & TRACE_debug)
549da2e3ebdSchin 	if (pp.test & TEST_hit)
550da2e3ebdSchin 	{
551da2e3ebdSchin 		c = 1;
552da2e3ebdSchin 		sfprintf(sfstderr, "\n");
553da2e3ebdSchin 		if (hit[elementsof(hit) - 1])
554da2e3ebdSchin 			sfprintf(sfstderr, "%7d: SPLICE\n", hit[elementsof(hit) - 1]);
555da2e3ebdSchin 		for (n = 0; n < elementsof(hit) - 1; n++)
556da2e3ebdSchin 			if (hit[n])
557da2e3ebdSchin 				sfprintf(sfstderr, "%7d: %s\n", hit[n], pplexstr(TERMINAL + n));
558da2e3ebdSchin 	}
559da2e3ebdSchin #endif
560da2e3ebdSchin 	if (pp.test & (TEST_hashcount|TEST_hashdump))
561da2e3ebdSchin 	{
562da2e3ebdSchin 		c = 1;
563da2e3ebdSchin 		sfprintf(sfstderr, "\n");
564da2e3ebdSchin 		hashdump(NiL, (pp.test & TEST_hashdump) ? HASH_BUCKET : 0);
565da2e3ebdSchin 	}
566da2e3ebdSchin 	if (c) sfprintf(sfstderr, "\n");
567da2e3ebdSchin 								/*INDENT*/
568da2e3ebdSchin 							}
569da2e3ebdSchin #endif
570da2e3ebdSchin 							break;
571da2e3ebdSchin 						}
572da2e3ebdSchin 					}
573da2e3ebdSchin #if CHECKPOINT
574da2e3ebdSchin 					if (cur->index)
575da2e3ebdSchin 					{
576da2e3ebdSchin 						SYNCOUT();
577da2e3ebdSchin 						cur->index->end = ppoffset();
578da2e3ebdSchin 						cur->index = 0;
579da2e3ebdSchin 						CACHEOUT();
580da2e3ebdSchin 					}
581da2e3ebdSchin #endif
582da2e3ebdSchin 					POP();
583da2e3ebdSchin 					bp = ip;
584da2e3ebdSchin 					tp = op;
585da2e3ebdSchin 					goto fsm_get;
586da2e3ebdSchin 				}
587da2e3ebdSchin 				c = EOF;
588da2e3ebdSchin 				break;
589da2e3ebdSchin 			case IN_COPY:
590da2e3ebdSchin 				if (prv)
591da2e3ebdSchin 				{
592da2e3ebdSchin 					error_info.line = cur->line;
593da2e3ebdSchin 					if (!(prv->symbol->flags & SYM_MULTILINE))
594da2e3ebdSchin 						prv->symbol->flags |= SYM_DISABLED;
595da2e3ebdSchin 					POP();
596da2e3ebdSchin 					bp = ip;
597da2e3ebdSchin 					goto fsm_get;
598da2e3ebdSchin 				}
599da2e3ebdSchin 				c = EOF;
600da2e3ebdSchin 				break;
601da2e3ebdSchin 			case IN_EXPAND:
602da2e3ebdSchin 				if (prv)
603da2e3ebdSchin 				{
604da2e3ebdSchin 					error_info.line = cur->line;
605da2e3ebdSchin 					free(cur->buffer);
606da2e3ebdSchin 					POP();
607da2e3ebdSchin 					bp = ip;
608da2e3ebdSchin 					goto fsm_get;
609da2e3ebdSchin 				}
610da2e3ebdSchin 				c = EOF;
611da2e3ebdSchin 				break;
612da2e3ebdSchin 			case IN_FILE:
613da2e3ebdSchin 				FGET(c, c, tp, xp);
614da2e3ebdSchin 				if (c == EOB)
615da2e3ebdSchin 				{
616da2e3ebdSchin #if CPP
617da2e3ebdSchin 					if ((st & (NOTEXT|HIDDEN)) == HIDDEN && LASTOUT() != '\n')
618da2e3ebdSchin 						PUTCHR('\n');
619da2e3ebdSchin 					if (prv)
620da2e3ebdSchin #else
621da2e3ebdSchin 					if (st & EOF2NL)
622da2e3ebdSchin 					{
623da2e3ebdSchin 						st &= ~EOF2NL;
624da2e3ebdSchin 						*(ip - 1) = c = '\n';
625da2e3ebdSchin 					}
626da2e3ebdSchin 					else if (!(st & (FILEPOP|PASSEOF)) && prv)
627da2e3ebdSchin #endif
628da2e3ebdSchin 					{
629da2e3ebdSchin 						if (!(cur->flags & IN_newline))
630da2e3ebdSchin 						{
631da2e3ebdSchin 							cur->flags |= IN_newline;
632da2e3ebdSchin 							if ((pp.mode & (HOSTED|PEDANTIC)) == PEDANTIC && LASTCHR() != '\f' && LASTCHR() != CC_sub)
633da2e3ebdSchin 								error(1, "file does not end with %s", pptokchr('\n'));
634da2e3ebdSchin 							*(ip - 1) = c = '\n';
635da2e3ebdSchin 						}
636da2e3ebdSchin 						else
637da2e3ebdSchin 						{
638da2e3ebdSchin 							if (!(cur->flags & (IN_noguard|IN_tokens)) && cur->symbol)
639da2e3ebdSchin 								ppmultiple(ppsetfile(error_info.file), cur->symbol);
640da2e3ebdSchin 							if (cur->fd >= 0)
641da2e3ebdSchin 								close(cur->fd);
642da2e3ebdSchin 							if (pp.incref && !(pp.mode & INIT))
643da2e3ebdSchin 							{
644da2e3ebdSchin 								SYNCOUT();
645da2e3ebdSchin 								(*pp.incref)(error_info.file, cur->file, error_info.line - 1, PP_SYNC_POP);
646da2e3ebdSchin 								CACHEOUT();
647da2e3ebdSchin 							}
648da2e3ebdSchin 							goto fsm_pop;
649da2e3ebdSchin 						}
650da2e3ebdSchin 					}
651da2e3ebdSchin 					else
652da2e3ebdSchin 						c = EOF;
653da2e3ebdSchin 				}
654da2e3ebdSchin 				break;
655da2e3ebdSchin 			case IN_MACRO:
656da2e3ebdSchin 			case IN_MULTILINE:
657da2e3ebdSchin #if !CPP
658da2e3ebdSchin 				if (!(st & PASSEOF))
659da2e3ebdSchin #endif
660da2e3ebdSchin #if COMPATIBLE
661da2e3ebdSchin 				if (prv && (!INMACRO(rp) || (st & (COMPATIBILITY|TRANSITION)) == COMPATIBILITY && ppismac(*prv->nextchr)))
662da2e3ebdSchin #else
663da2e3ebdSchin 				if (prv && !INMACRO(rp))
664da2e3ebdSchin #endif
665da2e3ebdSchin 				{
666da2e3ebdSchin 					if (cur->type == IN_MULTILINE)
667da2e3ebdSchin 					{
668da2e3ebdSchin 						while (pp.control-- != cur->control)
669da2e3ebdSchin 							error(2, "#%s on line %d has no #%s", dirname(IF), GETIFLINE(pp.control+1), dirname(ENDIF));
670da2e3ebdSchin 						free(cur->buffer);
671da2e3ebdSchin 						error_info.file = cur->file;
672da2e3ebdSchin 						error_info.line = cur->line;
673da2e3ebdSchin 						if (pp.linesync)
674da2e3ebdSchin 						{
675da2e3ebdSchin 							SYNCOUT();
676da2e3ebdSchin 							(*pp.linesync)(error_info.line, error_info.file);
677da2e3ebdSchin 							CACHEOUT();
678da2e3ebdSchin 						}
679da2e3ebdSchin 					}
680da2e3ebdSchin 					cur->symbol->flags &= ~SYM_DISABLED;
681da2e3ebdSchin 					if (cur->symbol->flags & SYM_FUNCTION)
682da2e3ebdSchin 						popframe(pp.macp);
683da2e3ebdSchin 					POP();
684da2e3ebdSchin #if CPP
685da2e3ebdSchin 					if (!(st & COMPATIBILITY) && ppisidig(*(op - 1)) && ppisidig(*ip)) UNGETCHR(' ');
686da2e3ebdSchin #endif
687da2e3ebdSchin 					bp = ip;
688da2e3ebdSchin 					goto fsm_get;
689da2e3ebdSchin 				}
690da2e3ebdSchin 				c = EOF;
691da2e3ebdSchin 				break;
692da2e3ebdSchin 			case IN_QUOTE:
693da2e3ebdSchin 				if (prv)
694da2e3ebdSchin 				{
695da2e3ebdSchin 					error_info.line = cur->line;
696da2e3ebdSchin 					st &= ~(ESCAPE|QUOTE);
697da2e3ebdSchin 					POP();
698da2e3ebdSchin 					c = '"';
699da2e3ebdSchin 				}
700da2e3ebdSchin 				else c = EOF;
701da2e3ebdSchin 				break;
702da2e3ebdSchin 			case IN_SQUOTE:
703da2e3ebdSchin 				if (prv)
704da2e3ebdSchin 				{
705da2e3ebdSchin 					error_info.line = cur->line;
706da2e3ebdSchin 					st &= ~(ESCAPE|SQUOTE);
707da2e3ebdSchin 					POP();
708da2e3ebdSchin 					c = '\'';
709da2e3ebdSchin 				}
710da2e3ebdSchin 				else c = EOF;
711da2e3ebdSchin 				break;
712da2e3ebdSchin 			case IN_STRING:
713da2e3ebdSchin #if CPP
714da2e3ebdSchin 				if (prv)
715da2e3ebdSchin #else
716da2e3ebdSchin 				if (!(st & PASSEOF) && !(cur->flags & IN_expand) && prv)
717da2e3ebdSchin #endif
718da2e3ebdSchin 				{
719da2e3ebdSchin 					if (cur->flags & IN_disable) st |= DISABLE;
720da2e3ebdSchin 					else st &= ~DISABLE;
721da2e3ebdSchin 					POP();
722da2e3ebdSchin 					bp = ip;
723da2e3ebdSchin 					goto fsm_get;
724da2e3ebdSchin 				}
725da2e3ebdSchin 				c = EOF;
726da2e3ebdSchin 				break;
727da2e3ebdSchin 			default:
728da2e3ebdSchin 				c = EOF;
729da2e3ebdSchin 				break;
730da2e3ebdSchin 			}
731da2e3ebdSchin 		}
732da2e3ebdSchin 		bp = ip - 1;
733da2e3ebdSchin 		if (state = rp[c]) goto fsm_next;
734da2e3ebdSchin 		goto fsm_get;
735da2e3ebdSchin 
736da2e3ebdSchin #if !CPP
737da2e3ebdSchin 	case S_HUH:
738da2e3ebdSchin 		if (INOPSPACE(rp))
739da2e3ebdSchin 		{
740da2e3ebdSchin 			if (c == '=')
741da2e3ebdSchin 			{
742da2e3ebdSchin #if PROTOTYPE
743da2e3ebdSchin 				if (pp.in->flags & IN_prototype) PUTCHR(c);
744da2e3ebdSchin 				else
745da2e3ebdSchin 				{
746da2e3ebdSchin #endif
747da2e3ebdSchin 					while (*(op - 1) == ' ' || *(op - 1) == '\t') op--;
748da2e3ebdSchin 					PUTCHR(c);
749da2e3ebdSchin 					if (st & (STRICT|WARN)) error(1, "%-*.*s: space ignored in operator", op - tp, op - tp, tp);
750da2e3ebdSchin #if PROTOTYPE
751da2e3ebdSchin 				}
752da2e3ebdSchin #endif
753da2e3ebdSchin 				switch (*tp)
754da2e3ebdSchin 				{
755da2e3ebdSchin 				case '/':
756da2e3ebdSchin 					c = T_DIVEQ;
757da2e3ebdSchin 					break;
758da2e3ebdSchin 				case '%':
759da2e3ebdSchin 					c = T_MODEQ;
760da2e3ebdSchin 					break;
761da2e3ebdSchin 				case '&':
762da2e3ebdSchin 					c = T_ANDEQ;
763da2e3ebdSchin 					break;
764da2e3ebdSchin 				case '*':
765da2e3ebdSchin 					c = T_MPYEQ;
766da2e3ebdSchin 					break;
767da2e3ebdSchin 				case '+':
768da2e3ebdSchin 					c = T_ADDEQ;
769da2e3ebdSchin 					break;
770da2e3ebdSchin 				case '-':
771da2e3ebdSchin 					c = T_SUBEQ;
772da2e3ebdSchin 					break;
773da2e3ebdSchin 				case '^':
774da2e3ebdSchin 					c = T_XOREQ;
775da2e3ebdSchin 					break;
776da2e3ebdSchin 				case '|':
777da2e3ebdSchin 					c = T_OREQ;
778da2e3ebdSchin 					break;
779da2e3ebdSchin 				case '<':
780da2e3ebdSchin 					c = T_LSHIFTEQ;
781da2e3ebdSchin 					break;
782da2e3ebdSchin 				case '>':
783da2e3ebdSchin 					c = T_RSHIFTEQ;
784da2e3ebdSchin 					break;
785da2e3ebdSchin 				}
786da2e3ebdSchin 			}
787da2e3ebdSchin 			else
788da2e3ebdSchin 			{
789da2e3ebdSchin 				BACKIN();
790da2e3ebdSchin 				switch (c = *tp)
791da2e3ebdSchin 				{
792da2e3ebdSchin 				case '<':
793da2e3ebdSchin 					c = T_LSHIFT;
794da2e3ebdSchin 					break;
795da2e3ebdSchin 				case '>':
796da2e3ebdSchin 					c = T_RSHIFT;
797da2e3ebdSchin 					break;
798da2e3ebdSchin 				}
799da2e3ebdSchin 			}
800da2e3ebdSchin 		}
801da2e3ebdSchin 		else if (pp.level > 1 || (pp.option & PRESERVE)) PUTCHR(c);
802da2e3ebdSchin 		else if (tp == op)
803da2e3ebdSchin 		{
804da2e3ebdSchin 			if (pp.in->type != IN_BUFFER)
805da2e3ebdSchin 			{
806da2e3ebdSchin 				if (!(pp.option & ALLPOSSIBLE))
807da2e3ebdSchin 					error(1, "%s: invalid character ignored", pptokchr(c));
808da2e3ebdSchin 				goto fsm_top;
809da2e3ebdSchin 			}
810da2e3ebdSchin 			PUTCHR(c);
811da2e3ebdSchin 		}
812da2e3ebdSchin 		else if (*tp == ':')
813da2e3ebdSchin 		{
814da2e3ebdSchin 			PUTCHR(c);
815da2e3ebdSchin 			if (c == '=') error(2, "real programmers use =");
816da2e3ebdSchin 			else c = '+';
817da2e3ebdSchin 		}
818da2e3ebdSchin 		else
819da2e3ebdSchin 		{
820da2e3ebdSchin 			BACKIN();
821da2e3ebdSchin 			c = *tp;
822da2e3ebdSchin 		}
823da2e3ebdSchin 		break;
824da2e3ebdSchin #endif
825da2e3ebdSchin 
826da2e3ebdSchin 	case S_QUAL:
827da2e3ebdSchin 		if ((state = NEXT(state)) != LIT1)
828da2e3ebdSchin 		{
829da2e3ebdSchin 			rp = fsm[state];
830da2e3ebdSchin 			bp = ip;
831da2e3ebdSchin #if CPP
832da2e3ebdSchin 			qual = 1;
833da2e3ebdSchin #if COMPATIBLE
834da2e3ebdSchin 			if (!(st & COMPATIBILITY) || c != 'u' && c != 'U')
835da2e3ebdSchin #endif
836da2e3ebdSchin 				PUTCHR(c);
837da2e3ebdSchin #else
838da2e3ebdSchin 			switch (c)
839da2e3ebdSchin 			{
840da2e3ebdSchin 			case 'f':
841da2e3ebdSchin 			case 'F':
842da2e3ebdSchin 				qual |= N_FLOAT;
843da2e3ebdSchin #if COMPATIBLE
844da2e3ebdSchin 				if (!(st & COMPATIBILITY))
845da2e3ebdSchin #endif
846da2e3ebdSchin 				PUTCHR(c);
847da2e3ebdSchin 				break;
848da2e3ebdSchin 			case 'l':
849da2e3ebdSchin 			case 'L':
850da2e3ebdSchin 				qual |= N_LONG;
851da2e3ebdSchin 				PUTCHR(c);
852da2e3ebdSchin 				break;
853da2e3ebdSchin 			case 'u':
854da2e3ebdSchin 			case 'U':
855da2e3ebdSchin 				qual |= N_UNSIGNED;
856da2e3ebdSchin #if COMPATIBLE
857da2e3ebdSchin 				if (!(st & COMPATIBILITY))
858da2e3ebdSchin #endif
859da2e3ebdSchin 				PUTCHR(c);
860da2e3ebdSchin 				break;
861da2e3ebdSchin 			default:
862da2e3ebdSchin 				PUTCHR(c);
863da2e3ebdSchin 				break;
864da2e3ebdSchin 			}
865da2e3ebdSchin #endif
866da2e3ebdSchin 			goto fsm_get;
867da2e3ebdSchin 		}
868da2e3ebdSchin #if !CPP
869da2e3ebdSchin 		qual |= N_WIDE;
870da2e3ebdSchin 		if (DOSTRIP()) BACKOUT();
871da2e3ebdSchin #endif
872da2e3ebdSchin 		/*FALLTHROUGH*/
873da2e3ebdSchin 
874da2e3ebdSchin 	case S_LITBEG:
875da2e3ebdSchin #if CPP
876da2e3ebdSchin 		quot = c;
877da2e3ebdSchin 		rp = fsm[LIT1];
878da2e3ebdSchin 		if (op == tp)
879da2e3ebdSchin 		{
880da2e3ebdSchin 			PPSYNCLINE();
881da2e3ebdSchin 			tp = op;
882da2e3ebdSchin 		}
883da2e3ebdSchin #else
884da2e3ebdSchin 		if ((quot = c) == '<')
885da2e3ebdSchin 		{
886da2e3ebdSchin 			if (!(st & HEADER) || (pp.option & (HEADEREXPAND|HEADEREXPANDALL)) && pp.in->type != IN_FILE && pp.in->type != IN_BUFFER && pp.in->type != IN_INIT && pp.in->type != IN_RESCAN)
887da2e3ebdSchin 			{
888da2e3ebdSchin 				PUTCHR(c);
889da2e3ebdSchin 				bp = ip;
890da2e3ebdSchin 				rp = fsm[LT1];
891da2e3ebdSchin 				goto fsm_get;
892da2e3ebdSchin 			}
893da2e3ebdSchin 			quot = '>';
894da2e3ebdSchin 			rp = fsm[HDR1];
895da2e3ebdSchin 		}
896da2e3ebdSchin 		else rp = fsm[LIT1];
897da2e3ebdSchin 		if (!DOSTRIP())
898da2e3ebdSchin #endif
899da2e3ebdSchin 		PUTCHR(c);
900da2e3ebdSchin 		bp = ip;
901da2e3ebdSchin 		goto fsm_get;
902da2e3ebdSchin 
903da2e3ebdSchin 	case S_LITEND:
904da2e3ebdSchin 		n = 1;
905da2e3ebdSchin 		if (c != quot)
906da2e3ebdSchin 		{
907da2e3ebdSchin 			if (c != '\n' && c != EOF)
908da2e3ebdSchin 			{
909da2e3ebdSchin 				if (st & (QUOTE|SQUOTE))
910da2e3ebdSchin 				{
911da2e3ebdSchin 					if (!(st & ESCAPE))
912da2e3ebdSchin 					{
913da2e3ebdSchin 						st |= ESCAPE;
914da2e3ebdSchin 						quotquot = c;
915da2e3ebdSchin 					}
916da2e3ebdSchin 					else if (c == quotquot) st &= ~ESCAPE;
917da2e3ebdSchin 				}
918da2e3ebdSchin 				PUTCHR(c);
919da2e3ebdSchin 				bp = ip;
920da2e3ebdSchin 				goto fsm_get;
921da2e3ebdSchin 			}
922da2e3ebdSchin #if CPP
9237c2fbfb3SApril Chin 			if ((st & PASSTHROUGH) || (pp.option & PRESERVE))
924da2e3ebdSchin 			{
925da2e3ebdSchin 				if (c == '\n') goto fsm_newline;
926da2e3ebdSchin 				bp = ip;
927da2e3ebdSchin 				goto fsm_start;
928da2e3ebdSchin 			}
929da2e3ebdSchin #endif
930da2e3ebdSchin 			m = (st & SKIPCONTROL) && (pp.mode & HOSTED) ? -1 : 1;
931da2e3ebdSchin 			if (c == '\n' && quot == '\'' && (pp.option & STRINGSPAN)) n = 0;
932da2e3ebdSchin 			else
933da2e3ebdSchin #if COMPATIBLE && !CPP
934da2e3ebdSchin 			if ((st & (COMPATIBILITY|DEFINITION)) != (COMPATIBILITY|DEFINITION))
935da2e3ebdSchin #endif
936da2e3ebdSchin 			{
937da2e3ebdSchin 				switch (quot)
938da2e3ebdSchin 				{
939da2e3ebdSchin 				case '"':
940da2e3ebdSchin 					if (c == '\n')
941da2e3ebdSchin 					{
942da2e3ebdSchin 						if (!(pp.option & STRINGSPAN) || (st & (COMPATIBILITY|STRICT)) == STRICT)
943da2e3ebdSchin 							error(m, "%s in string", pptokchr(c));
944da2e3ebdSchin 						error_info.line++;
945da2e3ebdSchin 						if (!(pp.option & STRINGSPAN))
946da2e3ebdSchin 						{
947da2e3ebdSchin 							PUTCHR('\\');
948da2e3ebdSchin 							c = 'n';
949da2e3ebdSchin 						}
950da2e3ebdSchin 						else if (pp.option & STRINGSPLIT)
951da2e3ebdSchin 						{
952da2e3ebdSchin 							PUTCHR('\\');
953da2e3ebdSchin 							PUTCHR('n');
954da2e3ebdSchin 							PUTCHR('"');
955da2e3ebdSchin 							PUTCHR('\n');
956da2e3ebdSchin 							c = '"';
957da2e3ebdSchin 						}
958da2e3ebdSchin 						PUTCHR(c);
959da2e3ebdSchin 						bp = ip;
960da2e3ebdSchin 						goto fsm_get;
961da2e3ebdSchin 					}
962da2e3ebdSchin 					error(m, "%s in string", pptokchr(c));
963da2e3ebdSchin 					c = '\n';
964da2e3ebdSchin 					break;
965da2e3ebdSchin 				case '\'':
966da2e3ebdSchin 					if (!(st & DIRECTIVE) || !(pp.mode & (HOSTED|RELAX)))
967da2e3ebdSchin 						error(m, "%s in character constant", pptokchr(c));
968da2e3ebdSchin 					break;
969da2e3ebdSchin 				case '>':
970da2e3ebdSchin 					error(m, "%s in header constant", pptokchr(c));
971da2e3ebdSchin 					break;
972da2e3ebdSchin 				default:
973da2e3ebdSchin 					error(m, "%s in %c quote", pptokchr(c), quot);
974da2e3ebdSchin 					break;
975da2e3ebdSchin 				}
976da2e3ebdSchin #if !CPP
977da2e3ebdSchin 				if (!DOSTRIP())
978da2e3ebdSchin #endif
979da2e3ebdSchin 				PUTCHR(quot);
980da2e3ebdSchin 			}
981da2e3ebdSchin 			if (c == '\n')
982da2e3ebdSchin 			{
983da2e3ebdSchin 				UNGETCHR(c);
984da2e3ebdSchin 				c = quot;
985da2e3ebdSchin 			}
986da2e3ebdSchin 		}
987da2e3ebdSchin 		else if (st & (SQUOTE|QUOTE))
988da2e3ebdSchin 		{
989da2e3ebdSchin 			if (!(st & ESCAPE))
990da2e3ebdSchin 			{
991da2e3ebdSchin 				st |= ESCAPE;
992da2e3ebdSchin 				quotquot = c;
993da2e3ebdSchin 			}
994da2e3ebdSchin 			else if (c == quotquot) st &= ~ESCAPE;
995da2e3ebdSchin 			PUTCHR('\\');
996da2e3ebdSchin 			PUTCHR(c);
997da2e3ebdSchin 			bp = ip;
998da2e3ebdSchin 			goto fsm_get;
999da2e3ebdSchin 		}
1000da2e3ebdSchin #if CPP
1001da2e3ebdSchin 		else PUTCHR(c);
1002da2e3ebdSchin #else
1003da2e3ebdSchin 		else if (!DOSTRIP()) PUTCHR(c);
1004da2e3ebdSchin #endif
1005da2e3ebdSchin #if CATSTRINGS
1006da2e3ebdSchin #if CPP
1007da2e3ebdSchin 		if (c == '"' && !(st & (COLLECTING|NOTEXT|PASSTHROUGH|SKIPCONTROL)) && (pp.mode & CATLITERAL))
1008da2e3ebdSchin #else
1009da2e3ebdSchin 		if (c == '"' && pp.level == 1 && !(st & (COLLECTING|JOINING|NOTEXT|SKIPCONTROL)) && (pp.mode & CATLITERAL))
1010da2e3ebdSchin #endif
1011da2e3ebdSchin 		{
1012da2e3ebdSchin 			char*	pptoken;
1013da2e3ebdSchin 			long	ppstate;
1014da2e3ebdSchin 
1015da2e3ebdSchin 			pptoken = pp.token;
1016da2e3ebdSchin 			pp.token = pp.catbuf;
1017da2e3ebdSchin 			*pp.token++ = 0;
1018da2e3ebdSchin 			ppstate = (st & STRIP);
1019da2e3ebdSchin 			if (DOSTRIP())
1020da2e3ebdSchin 				ppstate |= ADD|QUOTE;
1021da2e3ebdSchin 			st |= JOINING;
1022da2e3ebdSchin 			st &= ~(NEWLINE|STRIP);
1023da2e3ebdSchin 
1024da2e3ebdSchin 			/*
1025da2e3ebdSchin 			 * revert to the top level since string
1026da2e3ebdSchin 			 * concatenation crosses file boundaries
1027da2e3ebdSchin 			 * (allowing intervening directives)
1028da2e3ebdSchin 			 */
1029da2e3ebdSchin 
1030da2e3ebdSchin 			pp.level = 0;
1031da2e3ebdSchin 			SYNCIN();
1032da2e3ebdSchin 			m = n = 0;
1033da2e3ebdSchin 			for (;;)
1034da2e3ebdSchin 			{
1035da2e3ebdSchin 				switch (c = pplex())
1036da2e3ebdSchin 				{
1037da2e3ebdSchin 				case '\n':
1038da2e3ebdSchin 					m++;
1039da2e3ebdSchin 					continue;
1040da2e3ebdSchin 				case ' ':
1041da2e3ebdSchin 					*pp.catbuf = ' ';
1042da2e3ebdSchin 					continue;
1043da2e3ebdSchin 				case T_WSTRING:
1044da2e3ebdSchin #if !CPP
1045da2e3ebdSchin 					qual = N_WIDE;
1046da2e3ebdSchin #endif
1047da2e3ebdSchin 					if (ppstate & ADD)
1048da2e3ebdSchin 						ppstate &= ~ADD;
1049da2e3ebdSchin 					else if (m == n || !(st & SPACEOUT))
1050da2e3ebdSchin 						op--;
1051da2e3ebdSchin 					else
1052da2e3ebdSchin 					{
1053da2e3ebdSchin 						n = m;
1054da2e3ebdSchin 						*(op - 1) = '\\';
1055da2e3ebdSchin 						*op++ = '\n';
1056da2e3ebdSchin 					}
1057da2e3ebdSchin 					STRCOPY(op, pp.token + 2 + (*pp.token == ' '), s);
1058da2e3ebdSchin 					continue;
1059da2e3ebdSchin 				case T_STRING:
1060da2e3ebdSchin 					if (ppstate & ADD)
1061da2e3ebdSchin 						ppstate &= ~ADD;
1062da2e3ebdSchin 					else if (m == n || !(st & SPACEOUT))
1063da2e3ebdSchin 						op--;
1064da2e3ebdSchin 					else
1065da2e3ebdSchin 					{
1066da2e3ebdSchin 						n = m;
1067da2e3ebdSchin 						*(op - 1) = '\\';
1068da2e3ebdSchin 						*op++ = '\n';
1069da2e3ebdSchin 					}
1070da2e3ebdSchin 					STRCOPY(op, pp.token + 1 + (*pp.token == ' '), s);
1071da2e3ebdSchin 					continue;
1072da2e3ebdSchin 				case 0:
1073da2e3ebdSchin 					m = error_info.line ? (error_info.line - 1) : 0;
1074da2e3ebdSchin 					*pp.token = 0;
1075da2e3ebdSchin 					/*FALLTHROUGH*/
1076da2e3ebdSchin 				default:
1077da2e3ebdSchin 					if (m)
1078da2e3ebdSchin 					{
1079da2e3ebdSchin 						if (--m)
1080da2e3ebdSchin 						{
1081da2e3ebdSchin 							pp.state |= HIDDEN|SYNCLINE;
1082da2e3ebdSchin 							pp.hidden += m;
1083da2e3ebdSchin 						}
1084da2e3ebdSchin #if COMPATIBLE
1085da2e3ebdSchin 						if ((st & COMPATIBILITY) && c == '#' && *(pp.token - 1))
1086da2e3ebdSchin 						{
1087da2e3ebdSchin 							*(pp.token + 3) = *(pp.token + 2);
1088da2e3ebdSchin 							*(pp.token + 2) = *(pp.token + 1);
1089da2e3ebdSchin 							*(pp.token + 1) = *pp.token;
1090da2e3ebdSchin 							*pp.token = *(pp.token - 1);
1091da2e3ebdSchin 						}
1092da2e3ebdSchin 						error_info.line--;
1093da2e3ebdSchin 						*--pp.token = '\n';
1094da2e3ebdSchin #endif
1095da2e3ebdSchin 					}
1096da2e3ebdSchin 					else if (*(pp.token - 1))
1097da2e3ebdSchin 						pp.token--;
1098da2e3ebdSchin 					if (ppisidig(*pp.token))
1099da2e3ebdSchin 						*op++ = ' ';
1100da2e3ebdSchin 					if (pp.in->type == IN_MACRO && (s = strchr(pp.token, MARK)) && !*(s + 1))
1101da2e3ebdSchin 					{
1102da2e3ebdSchin 						*(s + 1) = MARK;
1103da2e3ebdSchin 						*(s + 2) = 0;
1104da2e3ebdSchin 					}
1105da2e3ebdSchin 					PUSH_STRING(pp.token);
1106da2e3ebdSchin 					pp.state &= ~(JOINING|NEWLINE);
1107da2e3ebdSchin 					pp.state |= ppstate & ~(ADD|QUOTE);
1108da2e3ebdSchin 					if ((ppstate & (ADD|QUOTE)) == QUOTE)
1109da2e3ebdSchin 						op--;
1110da2e3ebdSchin 					break;
1111da2e3ebdSchin 				}
1112da2e3ebdSchin 				break;
1113da2e3ebdSchin 			}
1114da2e3ebdSchin 			pp.token = pptoken;
1115da2e3ebdSchin 			CACHEIN();
1116da2e3ebdSchin 			pp.level = 1;
1117da2e3ebdSchin #if !CPP
1118da2e3ebdSchin 			c = T_STRING | qual;
1119da2e3ebdSchin 			break;
1120da2e3ebdSchin #endif
1121da2e3ebdSchin 		}
1122da2e3ebdSchin #endif
1123da2e3ebdSchin #if CPP
1124da2e3ebdSchin 		if (n && !(st & (PASSTHROUGH|SKIPCONTROL|NOTEXT)) && c == '\'' && (op - tp) <= 2 && !(pp.mode & (HOSTED|RELAX)))
1125da2e3ebdSchin 			error(1, "empty character constant");
11267c2fbfb3SApril Chin 		if (pp.option & PRESERVE)
11277c2fbfb3SApril Chin 			st &= ~ESCAPE;
11287c2fbfb3SApril Chin 		else
1129da2e3ebdSchin 			st &= ~(ESCAPE|NEWLINE);
1130da2e3ebdSchin 		pp.in->flags |= IN_tokens;
1131da2e3ebdSchin 		count(token);
1132da2e3ebdSchin 		goto fsm_start;
1133da2e3ebdSchin #else
1134da2e3ebdSchin 		st &= ~ESCAPE;
1135da2e3ebdSchin 		switch (quot)
1136da2e3ebdSchin 		{
1137da2e3ebdSchin 		case '\'':
1138da2e3ebdSchin 			if (n && !(st & NOTEXT) && (op - tp) <= (DOSTRIP() ? 0 : 2) && !(pp.mode & (HOSTED|RELAX)))
1139da2e3ebdSchin 				error(1, "empty character constant");
1140da2e3ebdSchin 			c = T_CHARCONST | qual;
1141da2e3ebdSchin 			break;
1142da2e3ebdSchin 		case '>':
1143da2e3ebdSchin 			c = T_HEADER;
1144da2e3ebdSchin 			break;
1145da2e3ebdSchin 		default:
1146da2e3ebdSchin 			if (c == quot)
1147da2e3ebdSchin 				c = T_STRING | qual;
1148da2e3ebdSchin 			break;
1149da2e3ebdSchin 		}
1150da2e3ebdSchin 		break;
1151da2e3ebdSchin #endif
1152da2e3ebdSchin 
1153da2e3ebdSchin 	case S_LITESC:
1154da2e3ebdSchin 		if (st & (COLLECTING|DIRECTIVE|QUOTE|SQUOTE))
1155da2e3ebdSchin 		{
1156da2e3ebdSchin 			if (st & ESCAPE)
1157da2e3ebdSchin 			{
1158da2e3ebdSchin 				PUTCHR('\\');
1159da2e3ebdSchin 				if (c == quot) PUTCHR('\\');
1160da2e3ebdSchin 			}
1161da2e3ebdSchin 			PUTCHR(c);
1162da2e3ebdSchin 		}
1163da2e3ebdSchin #if CPP
1164da2e3ebdSchin 		else if (st & PASSTHROUGH) PUTCHR(c);
1165da2e3ebdSchin #endif
1166da2e3ebdSchin 		else if (pp.option & PRESERVE) PUTCHR(c);
1167da2e3ebdSchin 		else switch (c)
1168da2e3ebdSchin 		{
1169da2e3ebdSchin 		case 'b':
1170da2e3ebdSchin 		case 'f':
1171da2e3ebdSchin 		case 'n':
1172da2e3ebdSchin 		case 'r':
1173da2e3ebdSchin 		case 't':
1174da2e3ebdSchin 		case '\\':
1175da2e3ebdSchin 		case '\'':
1176da2e3ebdSchin 		case '"':
1177da2e3ebdSchin 		case '?':
1178da2e3ebdSchin 			PUTCHR(c);
1179da2e3ebdSchin 			break;
1180da2e3ebdSchin #if COMPATIBLE
1181da2e3ebdSchin 		case '8':
1182da2e3ebdSchin 		case '9':
1183da2e3ebdSchin 			if (!(st & COMPATIBILITY)) goto unknown;
1184da2e3ebdSchin 			if (st & STRICT) error(1, "%c: invalid character in octal character escape", c);
1185da2e3ebdSchin 			/*FALLTHROUGH*/
1186da2e3ebdSchin #endif
1187da2e3ebdSchin 		case '0':
1188da2e3ebdSchin 		case '1':
1189da2e3ebdSchin 		case '2':
1190da2e3ebdSchin 		case '3':
1191da2e3ebdSchin 		case '4':
1192da2e3ebdSchin 		case '5':
1193da2e3ebdSchin 		case '6':
1194da2e3ebdSchin 		case '7':
1195da2e3ebdSchin 			n = c - '0';
1196da2e3ebdSchin 			for (m = 0; m < 2; m++)
1197da2e3ebdSchin 			{
1198da2e3ebdSchin 				GET(c, c, tp, xp);
1199da2e3ebdSchin 				switch (c)
1200da2e3ebdSchin 				{
1201da2e3ebdSchin #if COMPATIBLE
1202da2e3ebdSchin 				case '8':
1203da2e3ebdSchin 				case '9':
1204da2e3ebdSchin 					if (!(st & COMPATIBILITY))
1205da2e3ebdSchin 					{
1206da2e3ebdSchin 						UNGETCHR(c);
1207da2e3ebdSchin 						break;
1208da2e3ebdSchin 					}
1209da2e3ebdSchin 					if (st & STRICT) error(1, "%c: invalid character in octal character escape", c);
1210da2e3ebdSchin 					/*FALLTHROUGH*/
1211da2e3ebdSchin #endif
1212da2e3ebdSchin 				case '0':
1213da2e3ebdSchin 				case '1':
1214da2e3ebdSchin 				case '2':
1215da2e3ebdSchin 				case '3':
1216da2e3ebdSchin 				case '4':
1217da2e3ebdSchin 				case '5':
1218da2e3ebdSchin 				case '6':
1219da2e3ebdSchin 				case '7':
1220da2e3ebdSchin 					n = (n << 3) + c - '0';
1221da2e3ebdSchin 					continue;
1222da2e3ebdSchin 				default:
1223da2e3ebdSchin 					UNGETCHR(c);
1224da2e3ebdSchin 					break;
1225da2e3ebdSchin 				}
1226da2e3ebdSchin 				break;
1227da2e3ebdSchin 			}
1228da2e3ebdSchin 			if (n & ~0777) error(1, "octal character constant too large");
1229da2e3ebdSchin 			goto octal;
1230da2e3ebdSchin 		case 'a':
1231da2e3ebdSchin 			if (pp.option & MODERN)
1232da2e3ebdSchin 			{
1233da2e3ebdSchin 				PUTCHR(c);
1234da2e3ebdSchin 				break;
1235da2e3ebdSchin 			}
1236da2e3ebdSchin #if COMPATIBLE
1237da2e3ebdSchin 			if (st & COMPATIBILITY) goto unknown;
1238da2e3ebdSchin #endif
1239da2e3ebdSchin 			n = CC_bel;
1240da2e3ebdSchin 			goto octal;
1241da2e3ebdSchin 		case 'v':
1242da2e3ebdSchin 			if (pp.option & MODERN)
1243da2e3ebdSchin 			{
1244da2e3ebdSchin 				PUTCHR(c);
1245da2e3ebdSchin 				break;
1246da2e3ebdSchin 			}
1247da2e3ebdSchin 			n = CC_vt;
1248da2e3ebdSchin 			goto octal;
1249da2e3ebdSchin 		case 'E':
1250da2e3ebdSchin 			if (st & (COMPATIBILITY|STRICT)) goto unknown;
1251da2e3ebdSchin 			n = CC_esc;
1252da2e3ebdSchin 			goto octal;
1253da2e3ebdSchin 		case 'x':
1254da2e3ebdSchin #if COMPATIBLE
1255da2e3ebdSchin 			if (st & COMPATIBILITY) goto unknown;
1256da2e3ebdSchin #endif
1257da2e3ebdSchin 			n = 0;
1258da2e3ebdSchin 			for (m = 0; m < 3; m++)
1259da2e3ebdSchin 			{
1260da2e3ebdSchin 				GET(c, c, tp, xp);
1261da2e3ebdSchin 				switch (c)
1262da2e3ebdSchin 				{
1263da2e3ebdSchin 				case '0':
1264da2e3ebdSchin 				case '1':
1265da2e3ebdSchin 				case '2':
1266da2e3ebdSchin 				case '3':
1267da2e3ebdSchin 				case '4':
1268da2e3ebdSchin 				case '5':
1269da2e3ebdSchin 				case '6':
1270da2e3ebdSchin 				case '7':
1271da2e3ebdSchin 				case '8':
1272da2e3ebdSchin 				case '9':
1273da2e3ebdSchin 					n = (n << 4) + c - '0';
1274da2e3ebdSchin 					continue;
1275da2e3ebdSchin 				case 'a':
1276da2e3ebdSchin 				case 'b':
1277da2e3ebdSchin 				case 'c':
1278da2e3ebdSchin 				case 'd':
1279da2e3ebdSchin 				case 'e':
1280da2e3ebdSchin 				case 'f':
1281da2e3ebdSchin 					n = (n << 4) + c - 'a' + 10;
1282da2e3ebdSchin 					continue;
1283da2e3ebdSchin 				case 'A':
1284da2e3ebdSchin 				case 'B':
1285da2e3ebdSchin 				case 'C':
1286da2e3ebdSchin 				case 'D':
1287da2e3ebdSchin 				case 'E':
1288da2e3ebdSchin 				case 'F':
1289da2e3ebdSchin 					n = (n << 4) + c - 'A' + 10;
1290da2e3ebdSchin 					continue;
1291da2e3ebdSchin 				default:
1292da2e3ebdSchin 					if (!m) error(1, "\\x%c: invalid character in hexadecimal character constant", c);
1293da2e3ebdSchin 					UNGETCHR(c);
1294da2e3ebdSchin 					break;
1295da2e3ebdSchin 				}
1296da2e3ebdSchin 				break;
1297da2e3ebdSchin 			}
1298da2e3ebdSchin 			if (n & ~0777) error(1, "hexadecimal character constant too large");
1299da2e3ebdSchin 		octal:
1300da2e3ebdSchin 			PUTCHR(((n >> 6) & 07) + '0');
1301da2e3ebdSchin 			PUTCHR(((n >> 3) & 07) + '0');
1302da2e3ebdSchin 			PUTCHR((n & 07) + '0');
1303da2e3ebdSchin 			break;
1304da2e3ebdSchin 		default:
1305da2e3ebdSchin 		unknown:
1306da2e3ebdSchin 			if (st & (STRICT|WARN)) error(1, "\\%c: non-standard character constant", c);
1307da2e3ebdSchin 			PUTCHR(c);
1308da2e3ebdSchin 			break;
1309da2e3ebdSchin 		}
1310da2e3ebdSchin 		state = LIT1;
1311da2e3ebdSchin 		goto fsm_begin;
1312da2e3ebdSchin 
1313da2e3ebdSchin 	case S_MACRO:
1314da2e3ebdSchin 		BACKIN();
1315da2e3ebdSchin #if CPP
1316da2e3ebdSchin 		if (st & (DISABLE|SKIPCONTROL|SKIPMACRO))
1317da2e3ebdSchin 		{
1318da2e3ebdSchin 			if (st & SKIPMACRO)
1319da2e3ebdSchin 				pp.mode |= MARKMACRO;
1320da2e3ebdSchin 			st &= ~(NEWLINE|SKIPMACRO);
1321da2e3ebdSchin 			pp.in->flags |= IN_tokens;
1322da2e3ebdSchin 			count(token);
1323da2e3ebdSchin 			goto fsm_start;
1324da2e3ebdSchin 		}
1325da2e3ebdSchin 		count(candidate);
1326da2e3ebdSchin 		SETCHR(0);
1327da2e3ebdSchin 		switch (state = INDEX(rp))
1328da2e3ebdSchin 		{
1329da2e3ebdSchin 		case HIT0:
1330da2e3ebdSchin 			tp = op - 1;
1331da2e3ebdSchin 			break;
1332da2e3ebdSchin 		case HITN:
1333da2e3ebdSchin 			bp = tp;
1334da2e3ebdSchin 			tp = op - ((pp.truncate && pp.truncate < (HITN - HIT0)) ? (pp.truncate - 1) : (HITN - HIT0));
1335da2e3ebdSchin 			while (tp > bp && ppisidig(*(tp - 1))) tp--;
1336da2e3ebdSchin 			break;
1337da2e3ebdSchin 		default:
1338da2e3ebdSchin 			bp = tp;
1339da2e3ebdSchin 			if ((tp = op - (state - HIT0)) > bp && *(tp - 1) == 'L') tp--;
1340da2e3ebdSchin 			break;
1341da2e3ebdSchin 		}
1342da2e3ebdSchin 		if (sym = ppsymref(pp.symtab, tp))
1343da2e3ebdSchin 		{
1344da2e3ebdSchin 			SYNCIN();
1345da2e3ebdSchin 			n = ppcall(sym, 0);
1346da2e3ebdSchin 			CACHEIN();
1347da2e3ebdSchin 			if (n >= 0)
1348da2e3ebdSchin 			{
1349da2e3ebdSchin 				BACKOUT();
1350da2e3ebdSchin 				if (!n)
1351da2e3ebdSchin 				{
1352da2e3ebdSchin 					if (sp) op = sp;
1353da2e3ebdSchin 					else
1354da2e3ebdSchin 					{
1355da2e3ebdSchin 						s = ip;
1356da2e3ebdSchin 						ip = sym->macro->value;
1357da2e3ebdSchin 						c = sym->macro->size;
1358da2e3ebdSchin 						while (c > 0)
1359da2e3ebdSchin 						{
1360da2e3ebdSchin 							if (op + c < xp + PPBUFSIZ) n = c;
1361da2e3ebdSchin 							else n = xp + PPBUFSIZ - op;
1362da2e3ebdSchin 							MEMCPY(op, ip, n);
1363da2e3ebdSchin 							c -= n;
1364da2e3ebdSchin 							PPCHECKOUT();
1365da2e3ebdSchin 						}
1366da2e3ebdSchin 						ip = s;
1367da2e3ebdSchin 					}
1368da2e3ebdSchin 				}
1369da2e3ebdSchin 				else if ((sym->flags & SYM_MULTILINE) && pp.linesync)
1370da2e3ebdSchin 				{
1371da2e3ebdSchin 					SYNCOUT();
1372da2e3ebdSchin 					if (!(state & NEWLINE))
1373da2e3ebdSchin 						ppputchar('\n');
1374da2e3ebdSchin 					(*pp.linesync)(error_info.line, error_info.file);
1375da2e3ebdSchin 					CACHEOUT();
1376da2e3ebdSchin 				}
1377da2e3ebdSchin 			}
1378da2e3ebdSchin 		}
1379da2e3ebdSchin 		pp.in->flags |= IN_tokens;
1380da2e3ebdSchin 		goto fsm_start;
1381da2e3ebdSchin #else
1382da2e3ebdSchin 		if (st & (COLLECTING|DEFINITION|DISABLE|SKIPCONTROL|SKIPMACRO))
1383da2e3ebdSchin 		{
1384da2e3ebdSchin 			if (st & SKIPMACRO)
1385da2e3ebdSchin 				pp.mode |= MARKMACRO;
1386da2e3ebdSchin 			st &= ~(NEWLINE|NOEXPAND|SKIPMACRO);
1387da2e3ebdSchin 			c = T_ID;
1388da2e3ebdSchin 			if (pp.level == 1)
1389da2e3ebdSchin 			{
1390da2e3ebdSchin 				pp.in->flags |= IN_tokens;
1391da2e3ebdSchin 				if (st & NOTEXT)
1392da2e3ebdSchin 				{
1393da2e3ebdSchin 					BACKOUT();
1394da2e3ebdSchin 					goto fsm_top;
1395da2e3ebdSchin 				}
1396da2e3ebdSchin 				if (st & COMPILE)
1397da2e3ebdSchin 				{
1398da2e3ebdSchin 					SETCHR(0);
1399da2e3ebdSchin 					if (pp.truncate && (op - tp) > pp.truncate) tp[pp.truncate] = 0;
1400da2e3ebdSchin 					sym = (pp.option & NOHASH) ? ppsymref(pp.symtab, tp) : ppsymset(pp.symtab, tp);
1401da2e3ebdSchin  fsm_noise:
1402da2e3ebdSchin 					if (pp.symbol = sym)
1403da2e3ebdSchin 					{
1404da2e3ebdSchin 						if ((sym->flags & SYM_KEYWORD) && (!pp.truncate || (op - tp) <= pp.truncate || (tp[pp.truncate] = '_', tp[pp.truncate + 1] = 0, pp.symbol = sym = (pp.option & NOHASH) ? ppsymref(pp.symtab, tp) : ppsymset(pp.symtab, tp), 0)))
1405da2e3ebdSchin 						{
1406da2e3ebdSchin 							c = ((struct ppsymkey*)sym)->lex;
1407da2e3ebdSchin 							/*UNDENT*/
1408da2e3ebdSchin 
1409da2e3ebdSchin #define ADVANCE()	do{if(pp.toknxt<op)pp.token=pp.toknxt;}while(0)
1410da2e3ebdSchin 
1411da2e3ebdSchin #define NOISE_BRACE		01
1412da2e3ebdSchin #define NOISE_NOSPACEOUT	02
1413da2e3ebdSchin #define NOISE_PAREN		04
1414da2e3ebdSchin 
1415da2e3ebdSchin 	if ((pp.option & NOISE) && ppisnoise(c))
1416da2e3ebdSchin 	{
1417da2e3ebdSchin 		if (c != T_NOISE)
1418da2e3ebdSchin 		{
1419da2e3ebdSchin 			int		p;
1420da2e3ebdSchin 			int		f;
1421da2e3ebdSchin 			char*		pptoken;
1422da2e3ebdSchin 			PPCOMMENT	ppcomment;
1423da2e3ebdSchin 
1424da2e3ebdSchin 			SYNCIN();
1425da2e3ebdSchin 			pp.toknxt = op;
1426da2e3ebdSchin 			f = 0;
1427da2e3ebdSchin 			if (!(pp.state & SPACEOUT))
1428da2e3ebdSchin 			{
1429da2e3ebdSchin 				pp.state |= SPACEOUT;
1430da2e3ebdSchin 				f |= NOISE_NOSPACEOUT;
1431da2e3ebdSchin 			}
1432da2e3ebdSchin 			ppcomment = pp.comment;
1433da2e3ebdSchin 			pp.comment = 0;
1434da2e3ebdSchin 			op = (pptoken = tp) + MAXTOKEN;
1435da2e3ebdSchin 			switch (c)
1436da2e3ebdSchin 			{
1437da2e3ebdSchin 			case T_X_GROUP:
1438da2e3ebdSchin 				m = p = 0;
1439da2e3ebdSchin 				quot = 1;
1440da2e3ebdSchin 				for (;;)
1441da2e3ebdSchin 				{
1442da2e3ebdSchin 					ADVANCE();
1443da2e3ebdSchin 					switch (c = pplex())
1444da2e3ebdSchin 					{
1445da2e3ebdSchin 					case '(':
1446da2e3ebdSchin 					case '{':
1447da2e3ebdSchin 						if (!p)
1448da2e3ebdSchin 						{
1449da2e3ebdSchin 							if (c == '(')
1450da2e3ebdSchin 							{
1451da2e3ebdSchin 								if (f & NOISE_PAREN)
1452da2e3ebdSchin 								{
1453da2e3ebdSchin 									ungetchr(c);
1454da2e3ebdSchin 									*--pp.toknxt = 0;
1455da2e3ebdSchin 									break;
1456da2e3ebdSchin 								}
1457da2e3ebdSchin 								f |= NOISE_PAREN;
1458da2e3ebdSchin 								p = ')';
1459da2e3ebdSchin 							}
1460da2e3ebdSchin 							else
1461da2e3ebdSchin 							{
1462da2e3ebdSchin 								f |= NOISE_BRACE|NOISE_PAREN;
1463da2e3ebdSchin 								p = '}';
1464da2e3ebdSchin 							}
1465da2e3ebdSchin 							n = 1;
1466da2e3ebdSchin 							m = c;
1467da2e3ebdSchin 						}
1468da2e3ebdSchin 						else if (c == m) n++;
1469da2e3ebdSchin 						quot = 0;
1470da2e3ebdSchin 						continue;
1471da2e3ebdSchin 					case ')':
1472da2e3ebdSchin 					case '}':
1473da2e3ebdSchin 						if (c == p && --n <= 0)
1474da2e3ebdSchin 						{
1475da2e3ebdSchin 							if (c == '}') break;
1476da2e3ebdSchin 							m = '\n';
1477da2e3ebdSchin 							p = 0;
1478da2e3ebdSchin 						}
1479da2e3ebdSchin 						quot = 0;
1480da2e3ebdSchin 						continue;
1481da2e3ebdSchin 					case ' ':
1482da2e3ebdSchin 						continue;
1483da2e3ebdSchin 					case '\n':
1484da2e3ebdSchin 						error_info.line++;
1485da2e3ebdSchin 						if (!m) m = '\n';
1486da2e3ebdSchin 						continue;
1487da2e3ebdSchin 					case 0:
1488da2e3ebdSchin 						break;
1489da2e3ebdSchin 					case T_ID:
1490da2e3ebdSchin 						if (quot) continue;
1491da2e3ebdSchin 						/*FALLTHROUGH*/
1492da2e3ebdSchin 					default:
1493da2e3ebdSchin 						if (m == '\n')
1494da2e3ebdSchin 						{
1495da2e3ebdSchin 							/*
1496da2e3ebdSchin 							 * NOTE: token expanded again
1497da2e3ebdSchin 							 */
1498da2e3ebdSchin 
1499da2e3ebdSchin 							s = pp.toknxt;
1500da2e3ebdSchin 							while (s > pp.token) ungetchr(*--s);
1501da2e3ebdSchin 							*(pp.toknxt = s) = 0;
1502da2e3ebdSchin 							break;
1503da2e3ebdSchin 						}
1504da2e3ebdSchin 						continue;
1505da2e3ebdSchin 					}
1506da2e3ebdSchin 					break;
1507da2e3ebdSchin 				}
1508da2e3ebdSchin 				break;
1509da2e3ebdSchin 			case T_X_LINE:
1510da2e3ebdSchin 				for (;;)
1511da2e3ebdSchin 				{
1512da2e3ebdSchin 					ADVANCE();
1513da2e3ebdSchin 					switch (pplex())
1514da2e3ebdSchin 					{
1515da2e3ebdSchin 					case 0:
1516da2e3ebdSchin 						break;
1517da2e3ebdSchin 					case '\n':
1518da2e3ebdSchin 						error_info.line++;
1519da2e3ebdSchin 						break;
1520da2e3ebdSchin 					default:
1521da2e3ebdSchin 						continue;
1522da2e3ebdSchin 					}
1523da2e3ebdSchin 					break;
1524da2e3ebdSchin 				}
1525da2e3ebdSchin 				break;
1526da2e3ebdSchin 			case T_X_STATEMENT:
1527da2e3ebdSchin 				for (;;)
1528da2e3ebdSchin 				{
1529da2e3ebdSchin 					ADVANCE();
1530da2e3ebdSchin 					switch (pplex())
1531da2e3ebdSchin 					{
1532da2e3ebdSchin 					case 0:
1533da2e3ebdSchin 						break;
1534da2e3ebdSchin 					case ';':
1535da2e3ebdSchin 						ungetchr(';');
1536da2e3ebdSchin 						*(pp.toknxt = pp.token) = 0;
1537da2e3ebdSchin 						break;
1538da2e3ebdSchin 					default:
1539da2e3ebdSchin 						continue;
1540da2e3ebdSchin 					}
1541da2e3ebdSchin 					break;
1542da2e3ebdSchin 				}
1543da2e3ebdSchin 				break;
1544da2e3ebdSchin 			}
1545da2e3ebdSchin 			pp.comment = ppcomment;
1546da2e3ebdSchin 			if (f & NOISE_NOSPACEOUT)
1547da2e3ebdSchin 				pp.state &= ~SPACEOUT;
1548da2e3ebdSchin 			CACHEIN();
1549da2e3ebdSchin 			tp = pptoken;
1550da2e3ebdSchin 			op = pp.toknxt;
1551da2e3ebdSchin 			c = T_NOISES;
1552da2e3ebdSchin 		}
1553da2e3ebdSchin 		if (pp.option & NOISEFILTER)
1554da2e3ebdSchin 		{
1555da2e3ebdSchin 			BACKOUT();
1556da2e3ebdSchin 			goto fsm_top;
1557da2e3ebdSchin 		}
1558da2e3ebdSchin 	}
1559da2e3ebdSchin 
1560da2e3ebdSchin 							/*INDENT*/
1561da2e3ebdSchin 						}
1562da2e3ebdSchin 						else if ((pp.option & NOISE) && c == T_ID && strneq(tp, "__builtin_", 10))
1563da2e3ebdSchin 						{
1564da2e3ebdSchin 							hashlook(pp.symtab, tp, HASH_DELETE, NiL);
1565da2e3ebdSchin 							pp.symbol = sym = (struct ppsymbol*)ppkeyset(pp.symtab, tp);
1566da2e3ebdSchin 							sym->flags |= SYM_KEYWORD;
1567da2e3ebdSchin 							c = ((struct ppsymkey*)sym)->lex = T_BUILTIN;
1568da2e3ebdSchin 						}
1569da2e3ebdSchin 					}
1570da2e3ebdSchin 				}
1571da2e3ebdSchin 				goto fsm_symbol;
1572da2e3ebdSchin 			}
1573da2e3ebdSchin 			goto fsm_check;
1574da2e3ebdSchin 		}
1575da2e3ebdSchin 		if (pp.level == 1)
1576da2e3ebdSchin 		{
1577da2e3ebdSchin 			st &= ~(NEWLINE|PASSEOF);
1578da2e3ebdSchin 			pp.in->flags |= IN_tokens;
1579da2e3ebdSchin 		}
1580da2e3ebdSchin 		else st &= ~PASSEOF;
1581da2e3ebdSchin 		count(candidate);
1582da2e3ebdSchin 		SETCHR(0);
1583da2e3ebdSchin 		if (sym = ppsymref(pp.symtab, tp))
1584da2e3ebdSchin 		{
1585da2e3ebdSchin 			SYNCIN();
1586da2e3ebdSchin 			c = ppcall(sym, 1);
1587da2e3ebdSchin 			CACHEIN();
1588da2e3ebdSchin 			if (c >= 0)
1589da2e3ebdSchin 			{
1590da2e3ebdSchin 				BACKOUT();
1591da2e3ebdSchin 				if ((sym->flags & SYM_MULTILINE) && pp.linesync)
1592da2e3ebdSchin 				{
1593da2e3ebdSchin 					SYNCOUT();
1594da2e3ebdSchin 					(*pp.linesync)(error_info.line, error_info.file);
1595da2e3ebdSchin 					CACHEOUT();
1596da2e3ebdSchin 				}
1597da2e3ebdSchin 				goto fsm_top;
1598da2e3ebdSchin 			}
1599da2e3ebdSchin 		}
1600da2e3ebdSchin 		c = T_ID;
1601da2e3ebdSchin 		if (pp.level == 1)
1602da2e3ebdSchin 		{
1603da2e3ebdSchin 			if (st & NOTEXT)
1604da2e3ebdSchin 			{
1605da2e3ebdSchin 				BACKOUT();
1606da2e3ebdSchin 				goto fsm_top;
1607da2e3ebdSchin 			}
1608da2e3ebdSchin 			if (st & COMPILE)
1609da2e3ebdSchin 			{
1610da2e3ebdSchin 				if (pp.truncate && (op - tp) > pp.truncate)
1611da2e3ebdSchin 				{
1612da2e3ebdSchin 					tp[pp.truncate] = 0;
1613da2e3ebdSchin 					sym = 0;
1614da2e3ebdSchin 				}
1615da2e3ebdSchin 				if (!sym)
1616da2e3ebdSchin 				{
1617da2e3ebdSchin 					if (!(pp.option & NOHASH)) sym = ppsymset(pp.symtab, tp);
1618da2e3ebdSchin 					else if (!(sym = ppsymref(pp.symtab, tp))) goto fsm_symbol;
1619da2e3ebdSchin 				}
1620da2e3ebdSchin 				goto fsm_noise;
1621da2e3ebdSchin 			}
1622da2e3ebdSchin 			goto fsm_symbol;
1623da2e3ebdSchin 		}
1624da2e3ebdSchin 		goto fsm_check;
1625da2e3ebdSchin #endif
1626da2e3ebdSchin 
1627da2e3ebdSchin 	case S_SHARP:
1628da2e3ebdSchin 		if (c == '(')
1629da2e3ebdSchin 		{
1630da2e3ebdSchin 			pp.in->flags |= IN_tokens;
1631da2e3ebdSchin 			if ((st & STRICT) && pp.in->type != IN_MACRO && pp.in->type != IN_MULTILINE)
1632da2e3ebdSchin 			{
1633da2e3ebdSchin 				if (!(pp.mode & HOSTED)) error(1, "non-standard reference to #(...)");
1634da2e3ebdSchin 				if (st & STRICT)
1635da2e3ebdSchin 				{
1636da2e3ebdSchin 					PUTCHR(c);
1637da2e3ebdSchin #if CPP
1638da2e3ebdSchin 					st &= ~NEWLINE;
1639da2e3ebdSchin 					count(token);
1640da2e3ebdSchin 					goto fsm_start;
1641da2e3ebdSchin #else
1642da2e3ebdSchin 					break;
1643da2e3ebdSchin #endif
1644da2e3ebdSchin 				}
1645da2e3ebdSchin 			}
1646da2e3ebdSchin 			if (st & (COLLECTING|DEFINITION|DISABLE|SKIPCONTROL))
1647da2e3ebdSchin 			{
1648da2e3ebdSchin 				PUTCHR(c);
1649da2e3ebdSchin #if CPP
1650da2e3ebdSchin 				st &= ~NEWLINE;
1651da2e3ebdSchin 				count(token);
1652da2e3ebdSchin 				goto fsm_start;
1653da2e3ebdSchin #else
1654da2e3ebdSchin 				st &= ~NOEXPAND;
1655da2e3ebdSchin 				break;
1656da2e3ebdSchin #endif
1657da2e3ebdSchin 			}
1658da2e3ebdSchin 			op--;
1659da2e3ebdSchin 			SYNC();
1660da2e3ebdSchin 			ppbuiltin();
1661da2e3ebdSchin 			CACHE();
1662da2e3ebdSchin #if CPP
1663da2e3ebdSchin 			count(token);
1664da2e3ebdSchin 			goto fsm_start;
1665da2e3ebdSchin #else
1666da2e3ebdSchin 			goto fsm_top;
1667da2e3ebdSchin #endif
1668da2e3ebdSchin 		}
1669da2e3ebdSchin 		BACKIN();
1670da2e3ebdSchin #if CPP
1671da2e3ebdSchin 		if (!(st & NEWLINE) || !(pp.in->type & IN_TOP))
1672da2e3ebdSchin 		{
1673da2e3ebdSchin  fsm_nondirective:
1674da2e3ebdSchin 			st &= ~NEWLINE;
1675da2e3ebdSchin 			pp.in->flags |= IN_tokens;
1676da2e3ebdSchin 			count(token);
1677da2e3ebdSchin 			goto fsm_start;
1678da2e3ebdSchin 		}
1679da2e3ebdSchin 		if (*(s = tp) != '#')
1680da2e3ebdSchin 		{
1681da2e3ebdSchin #if COMPATIBLE
1682da2e3ebdSchin 			if ((st & (COMPATIBILITY|TRANSITION)) == COMPATIBILITY) goto fsm_nondirective;
1683da2e3ebdSchin #endif
1684da2e3ebdSchin 			while (*s == ' ' || *s == '\t') s++;
1685da2e3ebdSchin 			if (*s != '#') goto fsm_nondirective;
1686da2e3ebdSchin 		}
1687da2e3ebdSchin 		BACKOUT();
1688da2e3ebdSchin #else
1689da2e3ebdSchin 		if (!(st & NEWLINE) || (st & DEFINITION) || !(pp.in->type & IN_TOP))
1690da2e3ebdSchin 		{
1691da2e3ebdSchin 			if (c == '#')
1692da2e3ebdSchin 			{
1693da2e3ebdSchin 				SKIPIN();
1694da2e3ebdSchin 				if (!(st & DEFINITION))
1695da2e3ebdSchin 					PUTCHR(c);
1696da2e3ebdSchin 				c = T_TOKCAT;
1697da2e3ebdSchin 			}
1698da2e3ebdSchin 			else if (pp.level == 1 && !(st & (JOINING|SPACEOUT)) && !(pp.option & PRESERVE))
1699da2e3ebdSchin 			{
1700da2e3ebdSchin 				char*		pptoken;
1701da2e3ebdSchin 				char*		oop;
1702da2e3ebdSchin 				PPCOMMENT	ppcomment;
1703da2e3ebdSchin 
1704da2e3ebdSchin 				SYNCIN();
1705da2e3ebdSchin 				pp.toknxt = oop = op;
1706da2e3ebdSchin 				pp.state |= SPACEOUT;
1707da2e3ebdSchin 				ppcomment = pp.comment;
1708da2e3ebdSchin 				pp.comment = 0;
1709da2e3ebdSchin 				op = (pptoken = tp) + MAXTOKEN;
1710da2e3ebdSchin 				for (;;)
1711da2e3ebdSchin 				{
1712da2e3ebdSchin 					ADVANCE();
1713da2e3ebdSchin 					switch (pplex())
1714da2e3ebdSchin 					{
1715da2e3ebdSchin 					case 0:
1716da2e3ebdSchin 						break;
1717da2e3ebdSchin 					case '\n':
1718da2e3ebdSchin 						error_info.line++;
1719da2e3ebdSchin 						break;
1720da2e3ebdSchin 					default:
1721da2e3ebdSchin 						continue;
1722da2e3ebdSchin 					}
1723da2e3ebdSchin 					break;
1724da2e3ebdSchin 				}
1725da2e3ebdSchin 				pp.comment = ppcomment;
1726da2e3ebdSchin 				pp.state &= ~SPACEOUT;
1727da2e3ebdSchin 				CACHEIN();
1728da2e3ebdSchin 				tp = pptoken;
1729da2e3ebdSchin 				*--op = 0;
1730da2e3ebdSchin 				op = oop;
1731da2e3ebdSchin 				if (pp.pragma && !(st & NOTEXT))
1732da2e3ebdSchin 				{
1733da2e3ebdSchin 					*s = 0;
1734da2e3ebdSchin 					SYNC();
1735da2e3ebdSchin 					(*pp.pragma)(NiL, NiL, NiL, tp, 1);
1736da2e3ebdSchin 					CACHE();
1737da2e3ebdSchin 				}
1738da2e3ebdSchin 				if (!c) BACKIN();
1739da2e3ebdSchin 				goto fsm_top;
1740da2e3ebdSchin 			}
1741da2e3ebdSchin 			else c = '#';
1742da2e3ebdSchin 			break;
1743da2e3ebdSchin 		}
1744da2e3ebdSchin 		if ((st & (COLLECTING|STRICT)) == (COLLECTING|STRICT))
1745da2e3ebdSchin 			error(1, "directives in macro call arguments are not portable");
1746da2e3ebdSchin #endif
1747da2e3ebdSchin 		if (c == '#' && pp.in->type == IN_RESCAN)
1748da2e3ebdSchin 		{
1749da2e3ebdSchin 			/*
1750da2e3ebdSchin 			 * pass line to pp.pragma VERBATIM
1751da2e3ebdSchin 			 */
1752da2e3ebdSchin 
1753da2e3ebdSchin 			SKIPIN();
1754da2e3ebdSchin 			s = pp.valbuf;
1755da2e3ebdSchin 			while ((c = GETCHR()) && c != '\n')
1756da2e3ebdSchin 				if ((*s++ = c) == MARK) SKIPIN();
1757da2e3ebdSchin 			if (pp.pragma && !(st & NOTEXT))
1758da2e3ebdSchin 			{
1759da2e3ebdSchin 				*s = 0;
1760da2e3ebdSchin 				SYNC();
1761da2e3ebdSchin 				(*pp.pragma)(NiL, NiL, NiL, pp.valbuf, 1);
1762da2e3ebdSchin 				CACHE();
1763da2e3ebdSchin 			}
1764da2e3ebdSchin 			if (!c) BACKIN();
1765da2e3ebdSchin #if CPP
1766da2e3ebdSchin 			goto fsm_start;
1767da2e3ebdSchin #else
1768da2e3ebdSchin 			goto fsm_top;
1769da2e3ebdSchin #endif
1770da2e3ebdSchin 		}
1771da2e3ebdSchin 		SYNC();
1772da2e3ebdSchin 		ppcontrol();
1773da2e3ebdSchin 		CACHE();
1774da2e3ebdSchin #if CPP
1775da2e3ebdSchin 		if (st & (NOTEXT|SKIPCONTROL))
1776da2e3ebdSchin 		{
1777da2e3ebdSchin 			if (!sp)
1778da2e3ebdSchin 			{
1779da2e3ebdSchin 				PPCHECKOUTTP();
1780da2e3ebdSchin 				sp = tp;
1781da2e3ebdSchin 			}
1782da2e3ebdSchin 		}
1783da2e3ebdSchin 		else if (sp)
1784da2e3ebdSchin 		{
1785da2e3ebdSchin 			tp = op = sp;
1786da2e3ebdSchin 			sp = 0;
1787da2e3ebdSchin 		}
1788da2e3ebdSchin 		goto fsm_start;
1789da2e3ebdSchin #else
1790da2e3ebdSchin 		goto fsm_top;
1791da2e3ebdSchin #endif
1792da2e3ebdSchin 
1793da2e3ebdSchin 	case S_NL:
1794da2e3ebdSchin #if CPP
17957c2fbfb3SApril Chin 		if (op == tp && !(st & JOINING) && pp.in->type == IN_FILE && !(pp.option & PRESERVE))
1796da2e3ebdSchin 		{
1797da2e3ebdSchin 			st |= NEWLINE|HIDDEN;
1798da2e3ebdSchin 			pp.hidden++;
1799da2e3ebdSchin 			error_info.line++;
1800da2e3ebdSchin 			goto fsm_start;
1801da2e3ebdSchin 		}
1802da2e3ebdSchin #endif
1803da2e3ebdSchin  fsm_newline:
1804da2e3ebdSchin #if CPP
1805da2e3ebdSchin 		if (sp)
1806da2e3ebdSchin 			op = sp;
1807da2e3ebdSchin 		else if (!(pp.in->flags & IN_noguard))
1808da2e3ebdSchin 		{
1809da2e3ebdSchin 			while (tp < op)
1810da2e3ebdSchin 				if ((c = *tp++) != ' ' && c != '\t')
1811da2e3ebdSchin 				{
1812da2e3ebdSchin 					pp.in->flags |= IN_tokens;
1813da2e3ebdSchin 					break;
1814da2e3ebdSchin 				}
1815da2e3ebdSchin 			c = '\n';
1816da2e3ebdSchin 		}
1817da2e3ebdSchin 		st |= NEWLINE;
1818da2e3ebdSchin 		error_info.line++;
1819da2e3ebdSchin 		if (*ip == '\n' && *(ip + 1) != '\n' && !pp.macref && !(st & (ADD|HIDDEN)))
1820da2e3ebdSchin 		{
1821da2e3ebdSchin 			ip++;
1822da2e3ebdSchin 			PUTCHR('\n');
1823da2e3ebdSchin 			error_info.line++;
1824da2e3ebdSchin 		}
1825da2e3ebdSchin 		if ((st & NOTEXT) && ((pp.mode & FILEDEPS) || (pp.option & (DEFINITIONS|PREDEFINITIONS))))
1826da2e3ebdSchin 			BACKOUT();
1827da2e3ebdSchin 		else
1828da2e3ebdSchin 		{
1829da2e3ebdSchin 			debug((-5, "token[%d] %03o = %s [line=%d]", pp.level, c, pptokchr(c), error_info.line));
1830da2e3ebdSchin 			PUTCHR('\n');
1831da2e3ebdSchin 			PPSYNCLINE();
1832da2e3ebdSchin 			if (sp)
1833da2e3ebdSchin 			{
1834da2e3ebdSchin 				PPCHECKOUT();
1835da2e3ebdSchin 				sp = op;
1836da2e3ebdSchin 			}
1837da2e3ebdSchin 		}
1838da2e3ebdSchin 		goto fsm_start;
1839da2e3ebdSchin #else
1840da2e3ebdSchin 		st |= NEWLINE;
1841da2e3ebdSchin 		if (pp.level == 1)
1842da2e3ebdSchin 		{
1843da2e3ebdSchin 			error_info.line++;
1844da2e3ebdSchin 			if (!(st & (JOINING|SPACEOUT)))
1845da2e3ebdSchin 			{
1846da2e3ebdSchin 				debug((-5, "token[%d] %03o = %s [line=%d]", pp.level, c, pptokchr(c), error_info.line));
1847da2e3ebdSchin 				BACKOUT();
1848da2e3ebdSchin 				goto fsm_top;
1849da2e3ebdSchin 			}
1850da2e3ebdSchin 		}
1851da2e3ebdSchin 		BACKOUT();
1852da2e3ebdSchin 		if (st & SKIPCONTROL)
1853da2e3ebdSchin 		{
1854da2e3ebdSchin 			error_info.line++;
1855da2e3ebdSchin 			st |= HIDDEN;
1856da2e3ebdSchin 			pp.hidden++;
1857da2e3ebdSchin 			goto fsm_start;
1858da2e3ebdSchin 		}
1859da2e3ebdSchin 		PUTCHR(c = '\n');
1860da2e3ebdSchin 		goto fsm_return;
1861da2e3ebdSchin #endif
1862da2e3ebdSchin 
1863da2e3ebdSchin #if !CPP
1864da2e3ebdSchin 	case S_TOK:
1865da2e3ebdSchin 		PUTCHR(c);
1866da2e3ebdSchin 		c = TYPE(state) | qual;
1867da2e3ebdSchin 		break;
1868da2e3ebdSchin 
1869da2e3ebdSchin 	case S_TOKB:
1870da2e3ebdSchin 		BACKIN();
1871da2e3ebdSchin 		c = TYPE(state) | qual;
1872da2e3ebdSchin 		break;
1873da2e3ebdSchin #endif
1874da2e3ebdSchin 
1875da2e3ebdSchin 	case S_VS:
1876da2e3ebdSchin 		PUTCHR(c);
1877da2e3ebdSchin #if !CPP
1878da2e3ebdSchin 		if (st & NOVERTICAL)
1879da2e3ebdSchin 		{
1880da2e3ebdSchin 			error(1, "%s invalid in directives", pptokchr(c));
1881da2e3ebdSchin 			st &= ~NOVERTICAL;
1882da2e3ebdSchin 		}
1883da2e3ebdSchin #endif
1884da2e3ebdSchin #if COMPATIBLE
1885da2e3ebdSchin 		if (st & COMPATIBILITY) st |= NEWLINE;
1886da2e3ebdSchin #endif
1887da2e3ebdSchin #if CPP
1888da2e3ebdSchin 		if (!(pp.in->flags & IN_noguard))
1889da2e3ebdSchin 			while (tp < op)
1890da2e3ebdSchin 				if ((c = *tp++) != ' ' && c != '\t')
1891da2e3ebdSchin 				{
1892da2e3ebdSchin 					pp.in->flags |= IN_tokens;
1893da2e3ebdSchin 					break;
1894da2e3ebdSchin 				}
1895da2e3ebdSchin 		goto fsm_start;
1896da2e3ebdSchin #else
1897da2e3ebdSchin 		bp = ip;
1898da2e3ebdSchin 		rp = fsm[WS1];
1899da2e3ebdSchin 		goto fsm_get;
1900da2e3ebdSchin #endif
1901da2e3ebdSchin 
1902da2e3ebdSchin #if !CPP
1903da2e3ebdSchin 	case S_WS:
1904da2e3ebdSchin #if COMPATIBLE
1905da2e3ebdSchin 		if ((st & (COMPATIBILITY|TRANSITION)) == COMPATIBILITY) st &= ~NEWLINE;
1906da2e3ebdSchin #endif
1907da2e3ebdSchin 		if (pp.level == 1)
1908da2e3ebdSchin 		{
1909da2e3ebdSchin 			if ((st & (COMPATIBILITY|SPACEOUT)) && !(st & TRANSITION))
1910da2e3ebdSchin 			{
1911da2e3ebdSchin 				if (st & (COMPILE|NOTEXT))
1912da2e3ebdSchin 				{
1913da2e3ebdSchin #if CATSTRINGS
1914da2e3ebdSchin 					if ((st & (JOINING|NOTEXT|SPACEOUT)) != SPACEOUT)
1915da2e3ebdSchin #else
1916da2e3ebdSchin 					if ((st & (NOTEXT|SPACEOUT)) != SPACEOUT)
1917da2e3ebdSchin #endif
1918da2e3ebdSchin 					{
1919da2e3ebdSchin 						BACKOUT();
1920da2e3ebdSchin 						bp = ip - 1;
1921da2e3ebdSchin 						rp = fsm[START];
1922da2e3ebdSchin 						if (state = rp[c]) goto fsm_next;
1923da2e3ebdSchin 						goto fsm_get;
1924da2e3ebdSchin 					}
1925da2e3ebdSchin 				}
1926da2e3ebdSchin 				else
1927da2e3ebdSchin #if CATSTRINGS
1928da2e3ebdSchin 				if (!(st & JOINING))
1929da2e3ebdSchin #endif
1930da2e3ebdSchin 				{
1931da2e3ebdSchin 					tp = op;
1932da2e3ebdSchin 					bp = ip - 1;
1933da2e3ebdSchin 					rp = fsm[START];
1934da2e3ebdSchin 					if (state = rp[c]) goto fsm_next;
1935da2e3ebdSchin 					goto fsm_get;
1936da2e3ebdSchin 				}
1937da2e3ebdSchin 				BACKIN();
1938da2e3ebdSchin 				c = ' ';
1939da2e3ebdSchin 				goto fsm_return;
1940da2e3ebdSchin 			}
1941da2e3ebdSchin 			BACKOUT();
1942da2e3ebdSchin 			bp = ip - 1;
1943da2e3ebdSchin 			rp = fsm[START];
1944da2e3ebdSchin 			if (state = rp[c]) goto fsm_next;
1945da2e3ebdSchin 			goto fsm_get;
1946da2e3ebdSchin 		}
1947da2e3ebdSchin 		if (st & (NOSPACE|SKIPCONTROL))
1948da2e3ebdSchin 		{
1949da2e3ebdSchin 			BACKOUT();
1950da2e3ebdSchin 			bp = ip - 1;
1951da2e3ebdSchin 			rp = fsm[START];
1952da2e3ebdSchin 			if (state = rp[c]) goto fsm_next;
1953da2e3ebdSchin 			goto fsm_get;
1954da2e3ebdSchin 		}
1955da2e3ebdSchin 		if (c != '\n')
1956da2e3ebdSchin 		{
1957da2e3ebdSchin 			BACKIN();
1958da2e3ebdSchin 			c = ' ';
1959da2e3ebdSchin 		}
1960da2e3ebdSchin 		if (!(pp.option & PRESERVE))
1961da2e3ebdSchin 		{
1962da2e3ebdSchin 			BACKOUT();
1963da2e3ebdSchin 			PUTCHR(c);
1964da2e3ebdSchin 		}
1965da2e3ebdSchin 		goto fsm_return;
1966da2e3ebdSchin #endif
1967da2e3ebdSchin 
1968da2e3ebdSchin 	default:
1969da2e3ebdSchin 		if (state & SPLICE)
1970da2e3ebdSchin 		{
1971da2e3ebdSchin 			switch (c)
1972da2e3ebdSchin 			{
1973da2e3ebdSchin 			case MARK:
1974da2e3ebdSchin 				/*
1975da2e3ebdSchin 				 * internal mark
1976da2e3ebdSchin 				 */
1977da2e3ebdSchin 
1978da2e3ebdSchin 				switch (pp.in->type)
1979da2e3ebdSchin 				{
1980da2e3ebdSchin 				case IN_BUFFER:
1981da2e3ebdSchin 				case IN_FILE:
1982da2e3ebdSchin #if !CPP
1983da2e3ebdSchin 				case IN_INIT:
1984da2e3ebdSchin #if CATSTRINGS
1985da2e3ebdSchin 					if ((st & JOINING) && (!INQUOTE(rp) || quot != '"') || pp.level > 1 && (rp == fsm[START] || INQUOTE(rp)))
1986da2e3ebdSchin #else
1987da2e3ebdSchin 					if (pp.level > 1 && (rp == fsm[START] || INQUOTE(rp)))
1988da2e3ebdSchin #endif
1989da2e3ebdSchin 						PUTCHR(c);
1990da2e3ebdSchin #endif
1991da2e3ebdSchin 					break;
1992da2e3ebdSchin 				default:
1993da2e3ebdSchin 					switch (GETCHR())
1994da2e3ebdSchin 					{
1995da2e3ebdSchin 					case 'A':
1996da2e3ebdSchin 						if (!(st & (DEFINITION|DISABLE)))
1997da2e3ebdSchin 						{
1998da2e3ebdSchin 							c = GETCHR();
1999da2e3ebdSchin 							SYNCIN();
2000da2e3ebdSchin 							if (pp.macp->arg[c - ARGOFFSET][-1])
2001da2e3ebdSchin 								PUSH_EXPAND(pp.macp->arg[c - ARGOFFSET], pp.macp->line);
2002da2e3ebdSchin 							else
2003da2e3ebdSchin 								PUSH_COPY(pp.macp->arg[c - ARGOFFSET], pp.macp->line);
2004da2e3ebdSchin 							CACHEIN();
2005da2e3ebdSchin 							bp = ip;
2006da2e3ebdSchin 							goto fsm_get;
2007da2e3ebdSchin 						}
2008da2e3ebdSchin 						/*FALLTHROUGH*/
2009da2e3ebdSchin 					case 'C':
2010da2e3ebdSchin 						c = GETCHR() - ARGOFFSET;
2011da2e3ebdSchin 						if (!*(s = pp.macp->arg[c]) && (pp.in->symbol->flags & SYM_VARIADIC) && pp.in->symbol->macro->arity == (c + 1))
2012da2e3ebdSchin 						{
2013da2e3ebdSchin 							s = ip - 3;
2014da2e3ebdSchin 							while (--op > tp && --s > bp && ppisidig(*s));
2015da2e3ebdSchin 						}
2016da2e3ebdSchin 						else
2017da2e3ebdSchin 						{
2018da2e3ebdSchin 							SYNCIN();
2019da2e3ebdSchin 							PUSH_COPY(s, pp.macp->line);
2020da2e3ebdSchin 							CACHEIN();
2021da2e3ebdSchin 						}
2022da2e3ebdSchin 						bp = ip;
2023da2e3ebdSchin 						goto fsm_get;
2024da2e3ebdSchin 					case 'F':
2025da2e3ebdSchin 						error_info.file = (char*)strtoul(ip, &s, 16);
2026da2e3ebdSchin 						debug((-6, "actual sync: file = \"%s\"", error_info.file));
2027da2e3ebdSchin 						bp = ip = s + 1;
2028da2e3ebdSchin 						goto fsm_get;
2029da2e3ebdSchin 					case 'L':
2030da2e3ebdSchin 						error_info.line = strtoul(ip, &s, 16);
2031da2e3ebdSchin 						debug((-6, "actual sync: line = %d", error_info.line));
2032da2e3ebdSchin 						bp = ip = s + 1;
2033da2e3ebdSchin 						goto fsm_get;
2034da2e3ebdSchin 					case 'Q':
2035da2e3ebdSchin 						c = GETCHR();
2036da2e3ebdSchin 						SYNCIN();
2037da2e3ebdSchin 						PUSH_QUOTE(pp.macp->arg[c - ARGOFFSET], pp.macp->line);
2038da2e3ebdSchin 						CACHEIN();
2039*34f9b3eeSRoland Mainz 						*(bp = ip - 1) = '"';
2040da2e3ebdSchin 						if (st & (COLLECTING|EOF2NL|JOINING)) rp = fsm[START];
2041da2e3ebdSchin 						if (state = rp[c = '"']) goto fsm_next;
2042da2e3ebdSchin 						goto fsm_get;
2043da2e3ebdSchin 					case 'S':
2044da2e3ebdSchin 						c = GETCHR();
2045da2e3ebdSchin 						SYNCIN();
2046da2e3ebdSchin 						PUSH_SQUOTE(pp.macp->arg[c - ARGOFFSET], pp.macp->line);
2047da2e3ebdSchin 						CACHEIN();
2048da2e3ebdSchin 						bp = ip - 1;
2049da2e3ebdSchin 						if (st & COLLECTING) rp = fsm[START];
2050da2e3ebdSchin 						if (state = rp[c = '\'']) goto fsm_next;
2051da2e3ebdSchin 						goto fsm_get;
2052da2e3ebdSchin 					case 'X':
2053da2e3ebdSchin 						if (pp.in->type != IN_COPY)
2054da2e3ebdSchin 							st |= SKIPMACRO;
2055da2e3ebdSchin 						if (pp.level <= 1)
2056da2e3ebdSchin 						{
2057da2e3ebdSchin 							bp = ip;
2058da2e3ebdSchin 							goto fsm_get;
2059da2e3ebdSchin 						}
2060da2e3ebdSchin 						if (pp.in->type == IN_EXPAND)
2061da2e3ebdSchin 						{
2062da2e3ebdSchin 							st &= ~SKIPMACRO;
2063da2e3ebdSchin 							PUTCHR(c);
2064da2e3ebdSchin 							PUTCHR('X');
2065da2e3ebdSchin 						}
2066da2e3ebdSchin 						c = GETCHR();
2067da2e3ebdSchin 						break;
2068da2e3ebdSchin 					case 0:
2069da2e3ebdSchin 						if ((state &= ~SPLICE) >= TERMINAL) goto fsm_terminal;
2070da2e3ebdSchin 						goto fsm_begin;
2071da2e3ebdSchin 					default:
2072da2e3ebdSchin #if DEBUG
2073da2e3ebdSchin 						error(PANIC, "invalid mark op `%c'", LASTCHR());
2074da2e3ebdSchin 						/*FALLTHROUGH*/
2075da2e3ebdSchin 					case MARK:
2076da2e3ebdSchin #endif
2077da2e3ebdSchin #if CATSTRINGS
2078da2e3ebdSchin 						if ((st & (JOINING|QUOTE)) == JOINING)
2079da2e3ebdSchin 						{
2080da2e3ebdSchin 							if (!INQUOTE(rp))
2081da2e3ebdSchin 								PUTCHR(c);
2082da2e3ebdSchin 						}
2083da2e3ebdSchin 						else
2084da2e3ebdSchin #endif
2085da2e3ebdSchin #if CPP
2086da2e3ebdSchin 						if (rp != fsm[START] && !INQUOTE(rp))
2087da2e3ebdSchin 							UNGETCHR(c);
2088da2e3ebdSchin #else
2089da2e3ebdSchin 						if (rp != fsm[START] && !INQUOTE(rp))
2090da2e3ebdSchin 							UNGETCHR(c);
2091da2e3ebdSchin 						else if (pp.level > 1)
2092da2e3ebdSchin 							PUTCHR(c);
2093da2e3ebdSchin #endif
2094da2e3ebdSchin 						break;
2095da2e3ebdSchin 					}
2096da2e3ebdSchin 					break;
2097da2e3ebdSchin 				}
2098da2e3ebdSchin 				break;
2099da2e3ebdSchin 			case '?':
2100da2e3ebdSchin 				/*
2101da2e3ebdSchin 				 * trigraph
2102da2e3ebdSchin 				 */
2103da2e3ebdSchin 
2104da2e3ebdSchin 				if (pp.in->type == IN_FILE)
2105da2e3ebdSchin 				{
2106da2e3ebdSchin 					GET(c, n, tp, xp);
2107da2e3ebdSchin 					if (n == '?')
2108da2e3ebdSchin 					{
2109da2e3ebdSchin 						GET(c, n, tp, xp);
2110da2e3ebdSchin 						if (c = trigraph[n])
2111da2e3ebdSchin 						{
2112da2e3ebdSchin 							if ((st & WARN) && (st & (COMPATIBILITY|TRANSITION)) && !(pp.mode & HOSTED) && !INCOMMENT(rp))
2113da2e3ebdSchin 								error(1, "trigraph conversion %c%c%c -> %c%s", '?', '?', n, c, (st & TRANSITION) ? "" : " inhibited");
2114da2e3ebdSchin #if COMPATIBLE
2115da2e3ebdSchin 							if ((st & (COMPATIBILITY|TRANSITION)) != COMPATIBILITY)
2116da2e3ebdSchin 							{
2117da2e3ebdSchin #endif
2118da2e3ebdSchin 							*(bp = ip - 1) = c;
2119da2e3ebdSchin 							if (state = rp[c]) goto fsm_next;
2120da2e3ebdSchin 							goto fsm_get;
2121da2e3ebdSchin #if COMPATIBLE
2122da2e3ebdSchin 							}
2123da2e3ebdSchin #endif
2124da2e3ebdSchin 						}
2125da2e3ebdSchin 						if (n != EOB) BACKIN();
2126da2e3ebdSchin 						UNGETCHR(c = '?');
2127da2e3ebdSchin 					}
2128da2e3ebdSchin 					else if (n != EOB) BACKIN();
2129da2e3ebdSchin 				}
2130da2e3ebdSchin 				break;
2131da2e3ebdSchin 			case '%':
2132da2e3ebdSchin 			case '<':
2133da2e3ebdSchin 			case ':':
2134da2e3ebdSchin 				/*
2135da2e3ebdSchin 				 * digraph = --trigraph
2136da2e3ebdSchin 				 */
2137da2e3ebdSchin 
2138da2e3ebdSchin 				if (pp.in->type == IN_FILE && (pp.option & PLUSPLUS))
2139da2e3ebdSchin 				{
2140da2e3ebdSchin 					m = 0;
2141da2e3ebdSchin 					GET(c, n, tp, xp);
2142da2e3ebdSchin 					switch (n)
2143da2e3ebdSchin 					{
2144da2e3ebdSchin 					case '%':
2145da2e3ebdSchin 						if (c == '<') m = '{';
2146da2e3ebdSchin 						break;
2147da2e3ebdSchin 					case '>':
2148da2e3ebdSchin 						if (c == '%') m = '}';
2149da2e3ebdSchin 						else if (c == ':') m = ']';
2150da2e3ebdSchin 						break;
2151da2e3ebdSchin 					case ':':
2152da2e3ebdSchin 						if (c == '%') m = '#';
2153da2e3ebdSchin 						else if (c == '<') m = '[';
2154da2e3ebdSchin 						break;
2155da2e3ebdSchin 					}
2156da2e3ebdSchin 					if (m)
2157da2e3ebdSchin 					{
2158da2e3ebdSchin 						if ((st & WARN) && (st & (COMPATIBILITY|TRANSITION)) && !(pp.mode & HOSTED) && !INCOMMENT(rp))
2159da2e3ebdSchin 							error(1, "digraph conversion %c%c -> %c%s", c, n, m, (st & TRANSITION) ? "" : " inhibited");
2160da2e3ebdSchin #if COMPATIBLE
2161da2e3ebdSchin 						if ((st & (COMPATIBILITY|TRANSITION)) != COMPATIBILITY)
2162da2e3ebdSchin 						{
2163da2e3ebdSchin #endif
2164da2e3ebdSchin 						*(bp = ip - 1) = c = m;
2165da2e3ebdSchin 						if (state = rp[c]) goto fsm_next;
2166da2e3ebdSchin 						goto fsm_get;
2167da2e3ebdSchin #if COMPATIBLE
2168da2e3ebdSchin 						}
2169da2e3ebdSchin #endif
2170da2e3ebdSchin 					}
2171da2e3ebdSchin 					if (n != EOB) BACKIN();
2172da2e3ebdSchin 				}
2173da2e3ebdSchin 				break;
2174da2e3ebdSchin 			case '\\':
2175da2e3ebdSchin 				/*
2176da2e3ebdSchin 				 * line splice
2177da2e3ebdSchin 				 */
2178da2e3ebdSchin 
2179da2e3ebdSchin 				if (pp.in->type == IN_FILE && (!(pp.option & PLUSSPLICE) || !INCOMMENTXX(rp)))
2180da2e3ebdSchin 				{
2181da2e3ebdSchin 					m = 0;
2182da2e3ebdSchin 					GET(c, n, tp, xp);
2183da2e3ebdSchin 					if ((pp.option & SPLICESPACE) && !INQUOTE(rp))
2184da2e3ebdSchin 						while (n == ' ')
2185da2e3ebdSchin 						{
2186da2e3ebdSchin 							GET(c, n, tp, xp);
2187da2e3ebdSchin 							m = 1;
2188da2e3ebdSchin 						}
2189da2e3ebdSchin 					if (n == '\r')
2190da2e3ebdSchin 					{
2191da2e3ebdSchin 						GET(c, n, tp, xp);
2192da2e3ebdSchin 						if (n != '\n' && n != EOB)
2193da2e3ebdSchin 							BACKIN();
2194da2e3ebdSchin 					}
2195da2e3ebdSchin 					if (n == '\n')
2196da2e3ebdSchin 					{
2197da2e3ebdSchin #if CPP
2198da2e3ebdSchin 						if (INQUOTE(rp))
2199da2e3ebdSchin 						{
2200da2e3ebdSchin 							if ((pp.option & STRINGSPLIT) && quot == '"')
2201da2e3ebdSchin 							{
2202da2e3ebdSchin 								PUTCHR(quot);
2203da2e3ebdSchin 								PUTCHR(n);
2204da2e3ebdSchin 								PUTCHR(quot);
2205da2e3ebdSchin 							}
2206da2e3ebdSchin 							else if (*pp.lineid)
2207da2e3ebdSchin 							{
2208da2e3ebdSchin 								PUTCHR(c);
2209da2e3ebdSchin 								PUTCHR(n);
2210da2e3ebdSchin 							}
2211da2e3ebdSchin 							else
2212da2e3ebdSchin 							{
2213da2e3ebdSchin 								st |= HIDDEN;
2214da2e3ebdSchin 								pp.hidden++;
2215da2e3ebdSchin 							}
2216da2e3ebdSchin 						}
2217da2e3ebdSchin 						else
2218da2e3ebdSchin #else
2219da2e3ebdSchin #if COMPATIBLE
2220da2e3ebdSchin 						if (!INQUOTE(rp) && (st & (COMPATIBILITY|DEFINITION|TRANSITION)) == (COMPATIBILITY|DEFINITION))
2221da2e3ebdSchin 						{
2222da2e3ebdSchin 							if (op == tp)
2223da2e3ebdSchin 							{
2224da2e3ebdSchin 								st |= HIDDEN;
2225da2e3ebdSchin 								pp.hidden++;
2226da2e3ebdSchin 								error_info.line++;
2227da2e3ebdSchin 								if (st & SPACEOUT)
2228da2e3ebdSchin 									goto fsm_start;
2229da2e3ebdSchin 								c = (pp.option & SPLICECAT) ? '\t' : ' ';
2230da2e3ebdSchin 								PUTCHR(c);
2231da2e3ebdSchin 								goto fsm_check;
2232da2e3ebdSchin 							}
2233da2e3ebdSchin 							UNGETCHR(n);
2234da2e3ebdSchin 							state &= ~SPLICE;
2235da2e3ebdSchin 							goto fsm_terminal;
2236da2e3ebdSchin 						}
2237da2e3ebdSchin #endif
2238da2e3ebdSchin #endif
2239da2e3ebdSchin 						{
2240da2e3ebdSchin 							st |= HIDDEN;
2241da2e3ebdSchin 							pp.hidden++;
2242da2e3ebdSchin 						}
2243da2e3ebdSchin #if CPP
2244da2e3ebdSchin 						spliced++;
2245da2e3ebdSchin #else
2246da2e3ebdSchin 						error_info.line++;
2247da2e3ebdSchin #endif
2248da2e3ebdSchin 						bp = ip;
2249da2e3ebdSchin 						goto fsm_get;
2250da2e3ebdSchin 					}
2251da2e3ebdSchin 					else if ((n == 'u' || n == 'U') && !INQUOTE(rp))
2252da2e3ebdSchin 					{
2253da2e3ebdSchin 						PUTCHR(c);
2254da2e3ebdSchin 						PUTCHR(n);
2255da2e3ebdSchin 						bp = ip;
2256da2e3ebdSchin 						goto fsm_get;
2257da2e3ebdSchin 					}
2258da2e3ebdSchin #if COMPATIBLE
2259da2e3ebdSchin 					else if ((st & (COMPATIBILITY|TRANSITION)) == COMPATIBILITY && (n == '"' || n == '\'') && !INQUOTE(rp))
2260da2e3ebdSchin 					{
2261da2e3ebdSchin 						PUTCHR(c);
2262da2e3ebdSchin 						PUTCHR(n);
2263da2e3ebdSchin 						bp = ip;
2264da2e3ebdSchin 						goto fsm_get;
2265da2e3ebdSchin 					}
2266da2e3ebdSchin #endif
2267da2e3ebdSchin 					else if (n != EOB)
2268da2e3ebdSchin 						BACKIN();
2269da2e3ebdSchin 					if (m && INSPACE(rp))
2270da2e3ebdSchin 						UNGETCHR(c);
2271da2e3ebdSchin 				}
2272da2e3ebdSchin #if COMPATIBLE
2273da2e3ebdSchin 				else if ((st & (COMPATIBILITY|TRANSITION)) == COMPATIBILITY && !INQUOTE(rp))
2274da2e3ebdSchin 				{
2275da2e3ebdSchin 					GET(c, n, tp, xp);
2276da2e3ebdSchin 					if (n == '"' || n == '\'')
2277da2e3ebdSchin 					{
2278da2e3ebdSchin 						PUTCHR(c);
2279da2e3ebdSchin 						PUTCHR(n);
2280da2e3ebdSchin 						bp = ip;
2281da2e3ebdSchin 						goto fsm_get;
2282da2e3ebdSchin 					}
2283da2e3ebdSchin 					if (n != EOB)
2284da2e3ebdSchin 						BACKIN();
2285da2e3ebdSchin 				}
2286da2e3ebdSchin #endif
2287da2e3ebdSchin 				break;
2288da2e3ebdSchin 			case '\r':
2289da2e3ebdSchin 				/*
2290da2e3ebdSchin 				 * barf
2291da2e3ebdSchin 				 */
2292da2e3ebdSchin 
2293da2e3ebdSchin 				if (pp.in->type == IN_FILE)
2294da2e3ebdSchin 				{
2295da2e3ebdSchin 					GET(c, n, tp, xp);
2296da2e3ebdSchin 					if (n == '\n')
2297da2e3ebdSchin 					{
2298da2e3ebdSchin 						*(bp = ip - 1) = c = n;
2299da2e3ebdSchin 						if (state = rp[c]) goto fsm_next;
2300da2e3ebdSchin 						goto fsm_get;
2301da2e3ebdSchin 					}
2302da2e3ebdSchin 					if (n != EOB) BACKIN();
2303da2e3ebdSchin 				}
2304da2e3ebdSchin 				break;
2305da2e3ebdSchin 			case CC_sub:
2306da2e3ebdSchin 				/*
2307da2e3ebdSchin 				 * barf & puke
2308da2e3ebdSchin 				 */
2309da2e3ebdSchin 
2310da2e3ebdSchin 				if ((pp.option & ZEOF) && pp.in->type == IN_FILE)
2311da2e3ebdSchin 				{
2312da2e3ebdSchin 					pp.in->flags |= IN_eof;
2313da2e3ebdSchin 					c = 0;
2314da2e3ebdSchin 					state = S_EOB;
2315da2e3ebdSchin 					goto fsm_terminal;
2316da2e3ebdSchin 				}
2317da2e3ebdSchin 				break;
2318da2e3ebdSchin 			}
2319da2e3ebdSchin 			if ((state &= ~SPLICE) >= TERMINAL)
2320da2e3ebdSchin 				goto fsm_terminal;
2321da2e3ebdSchin 			PUTCHR(c);
2322da2e3ebdSchin 			goto fsm_begin;
2323da2e3ebdSchin 		}
2324da2e3ebdSchin #if CPP
2325da2e3ebdSchin 		if (INOPSPACE(rp))
2326da2e3ebdSchin 		{
2327da2e3ebdSchin 			BACKIN();
2328da2e3ebdSchin 			goto fsm_start;
2329da2e3ebdSchin 		}
2330da2e3ebdSchin #endif
2331da2e3ebdSchin 		PUTCHR(c);
2332da2e3ebdSchin 		bp = ip;
2333da2e3ebdSchin 		goto fsm_get;
2334da2e3ebdSchin 	}
2335da2e3ebdSchin #if !CPP
2336da2e3ebdSchin  fsm_token:
2337da2e3ebdSchin 	st &= ~NEWLINE;
2338da2e3ebdSchin 	if (pp.level == 1)
2339da2e3ebdSchin 	{
2340da2e3ebdSchin 		pp.in->flags |= IN_tokens;
2341da2e3ebdSchin 		if (st & NOTEXT)
2342da2e3ebdSchin 		{
2343da2e3ebdSchin 			BACKOUT();
2344da2e3ebdSchin 			goto fsm_top;
2345da2e3ebdSchin 		}
2346da2e3ebdSchin  fsm_symbol:
2347da2e3ebdSchin 		count(token);
2348da2e3ebdSchin 	}
2349da2e3ebdSchin  fsm_check:
2350da2e3ebdSchin 	if (st & SKIPCONTROL)
2351da2e3ebdSchin 	{
2352da2e3ebdSchin 		BACKOUT();
2353da2e3ebdSchin 		goto fsm_start;
2354da2e3ebdSchin 	}
2355da2e3ebdSchin  fsm_return:
2356da2e3ebdSchin #if CPP
2357da2e3ebdSchin 	error_info.line += spliced;
2358da2e3ebdSchin #endif
2359da2e3ebdSchin 	SETCHR(0);
2360da2e3ebdSchin 	debug((-5, "token[%d] %03o = %s", pp.level, c, pptokstr(tp, 0)));
2361da2e3ebdSchin 	SYNC();
2362da2e3ebdSchin 	pp.level--;
2363da2e3ebdSchin 	error_info.indent--;
2364da2e3ebdSchin 	return c;
2365da2e3ebdSchin #endif
2366da2e3ebdSchin }
2367da2e3ebdSchin 
2368da2e3ebdSchin #if CPP && POOL
2369da2e3ebdSchin 
2370da2e3ebdSchin #include <ls.h>
2371da2e3ebdSchin #include <wait.h>
2372da2e3ebdSchin 
2373da2e3ebdSchin /*
2374da2e3ebdSchin  * output pool status on exit
2375da2e3ebdSchin  */
2376da2e3ebdSchin 
2377da2e3ebdSchin static void
poolstatus(void)2378da2e3ebdSchin poolstatus(void)
2379da2e3ebdSchin {
2380da2e3ebdSchin 	error(ERROR_OUTPUT|0, pp.pool.output, "%d", error_info.errors != 0);
2381da2e3ebdSchin }
2382da2e3ebdSchin 
2383da2e3ebdSchin /*
2384da2e3ebdSchin  * loop on < input output >
2385da2e3ebdSchin  */
2386da2e3ebdSchin 
2387da2e3ebdSchin static void
pool(void)2388da2e3ebdSchin pool(void)
2389da2e3ebdSchin {
2390da2e3ebdSchin 	char*	ifile;
2391da2e3ebdSchin 	char*	ofile;
2392da2e3ebdSchin 
2393da2e3ebdSchin 	ppflushout();
2394da2e3ebdSchin 	if (!sfnew(sfstdin, NiL, SF_UNBOUND, pp.pool.input, SF_READ))
2395da2e3ebdSchin 		error(ERROR_SYSTEM|3, "cannot dup pool input");
2396da2e3ebdSchin 
2397da2e3ebdSchin 	/*
2398da2e3ebdSchin 	 * kick the -I cache
2399da2e3ebdSchin 	 */
2400da2e3ebdSchin 
2401da2e3ebdSchin 	ppsearch(".", T_STRING, SEARCH_EXISTS);
2402da2e3ebdSchin 
2403da2e3ebdSchin 	/*
2404da2e3ebdSchin 	 * loop on < input output >
2405da2e3ebdSchin 	 */
2406da2e3ebdSchin 
2407da2e3ebdSchin 	pp.pool.input = 0;
2408da2e3ebdSchin 	while (ifile = sfgetr(sfstdin, '\n', 1))
2409da2e3ebdSchin 	{
2410da2e3ebdSchin 		if (!(ofile = strchr(ifile, ' ')))
2411da2e3ebdSchin 			error(3, "%s: pool output file expected", ifile);
2412da2e3ebdSchin 		*ofile++ = 0;
2413da2e3ebdSchin 		waitpid(0, NiL, WNOHANG);
2414da2e3ebdSchin 		switch (fork())
2415da2e3ebdSchin 		{
2416da2e3ebdSchin 		case -1:
2417da2e3ebdSchin 			error(ERROR_SYSTEM|3, "cannot fork pool");
2418da2e3ebdSchin 		case 0:
2419da2e3ebdSchin 			atexit(poolstatus);
2420da2e3ebdSchin 			error_info.errors = 0;
2421da2e3ebdSchin 			error_info.warnings = 0;
2422da2e3ebdSchin 			close(0);
2423da2e3ebdSchin 			if (open(ifile, O_RDONLY))
2424da2e3ebdSchin 				error(ERROR_SYSTEM|3, "%s: cannot read", ifile);
2425da2e3ebdSchin 			close(1);
2426da2e3ebdSchin 			if (open(ofile, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) != 1)
2427da2e3ebdSchin 				error(ERROR_SYSTEM|3, "%s: cannot create", ofile);
2428da2e3ebdSchin 			pp.outfile = ofile;
2429da2e3ebdSchin 			pathcanon(ifile, 0);
2430da2e3ebdSchin 			ifile = ppsetfile(ifile)->name;
2431da2e3ebdSchin #if CHECKPOINT
2432da2e3ebdSchin 			if (pp.mode & DUMP)
2433da2e3ebdSchin 			{
2434da2e3ebdSchin 				if (!pp.pragma)
2435da2e3ebdSchin 					error(3, "#%s must be enabled for checkpoints", dirname(PRAGMA));
2436da2e3ebdSchin 				(*pp.pragma)(dirname(PRAGMA), pp.pass, keyname(X_CHECKPOINT), pp.checkpoint, 1);
2437da2e3ebdSchin 			}
2438da2e3ebdSchin #endif
2439da2e3ebdSchin 			PUSH_FILE(ifile, 0);
2440da2e3ebdSchin 			return;
2441da2e3ebdSchin 		}
2442da2e3ebdSchin 	}
2443da2e3ebdSchin 	while (wait(NiL) != -1);
2444da2e3ebdSchin }
2445da2e3ebdSchin 
2446da2e3ebdSchin #endif
2447