1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin *                                                                      *
3da2e3ebdSchin *               This software is part of the ast package               *
4*b30d1939SAndy Fiddaman *          Copyright (c) 1986-2011 AT&T Intellectual Property          *
5da2e3ebdSchin *                      and is licensed under the                       *
6*b30d1939SAndy Fiddaman *                 Eclipse Public License, Version 1.0                  *
77c2fbfb3SApril Chin *                    by AT&T Intellectual Property                     *
8da2e3ebdSchin *                                                                      *
9da2e3ebdSchin *                A copy of the License is available at                 *
10*b30d1939SAndy Fiddaman *          http://www.eclipse.org/org/documents/epl-v10.html           *
11*b30d1939SAndy Fiddaman *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
12da2e3ebdSchin *                                                                      *
13da2e3ebdSchin *              Information and Software Systems Research               *
14da2e3ebdSchin *                            AT&T Research                             *
15da2e3ebdSchin *                           Florham Park NJ                            *
16da2e3ebdSchin *                                                                      *
17da2e3ebdSchin *                 Glenn Fowler <gsf@research.att.com>                  *
18da2e3ebdSchin *                                                                      *
19da2e3ebdSchin ***********************************************************************/
20da2e3ebdSchin #pragma prototyped
21da2e3ebdSchin /*
22da2e3ebdSchin  * Glenn Fowler
23da2e3ebdSchin  * AT&T Research
24da2e3ebdSchin  *
25da2e3ebdSchin  * 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
11297c2fbfb3SApril Chin 			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 #endif
1186*b30d1939SAndy Fiddaman 			/*FALLTHROUGH*/
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 #endif
1211*b30d1939SAndy Fiddaman 					/*FALLTHROUGH*/
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