xref: /onnv-gate/usr/src/lib/libpp/common/pplex.c (revision 10898:1883b621b3ea)
14887Schin /***********************************************************************
24887Schin *                                                                      *
34887Schin *               This software is part of the ast package               *
4*10898Sroland.mainz@nrubsig.org *          Copyright (c) 1986-2009 AT&T Intellectual Property          *
54887Schin *                      and is licensed under the                       *
64887Schin *                  Common Public License, Version 1.0                  *
78462SApril.Chin@Sun.COM *                    by AT&T Intellectual Property                     *
84887Schin *                                                                      *
94887Schin *                A copy of the License is available at                 *
104887Schin *            http://www.opensource.org/licenses/cpl1.0.txt             *
114887Schin *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
124887Schin *                                                                      *
134887Schin *              Information and Software Systems Research               *
144887Schin *                            AT&T Research                             *
154887Schin *                           Florham Park NJ                            *
164887Schin *                                                                      *
174887Schin *                 Glenn Fowler <gsf@research.att.com>                  *
184887Schin *                                                                      *
194887Schin ***********************************************************************/
204887Schin #pragma prototyped
214887Schin /*
224887Schin  * Glenn Fowler
234887Schin  * AT&T Research
244887Schin  *
254887Schin  * preprocessor lexical analyzer
264887Schin  * standalone and tokenizing lexer combined in one source
274887Schin  * define CPP=1 for standalone
284887Schin  */
294887Schin 
304887Schin #include "pplib.h"
314887Schin #include "ppfsm.h"
324887Schin 
334887Schin #if CPP
344887Schin 
354887Schin /*
364887Schin  * standalone entry point
374887Schin  */
384887Schin 
394887Schin #define PPCPP_T		void
404887Schin 
414887Schin #define START		QUICK
424887Schin #define INMACRO(x)	INQMACRO(x)
434887Schin #define DOSTRIP()	(st&STRIP)
444887Schin 
454887Schin #if DEBUG & TRACE_debug
464887Schin static int		hit[LAST-TERMINAL+2];
474887Schin #endif
484887Schin 
494887Schin #define BACKIN()	(ip--)
504887Schin #define BACKOUT()	(op=tp)
514887Schin #define CACHE()		do{CACHEINX();CACHEOUTX();st=pp.state;if(!pp.hidden)spliced=0;}while(0)
524887Schin #define CACHEIN()	do{CACHEINX();st=pp.state;if(!pp.hidden)spliced=0;}while(0)
534887Schin #define CACHEINX()	do{ip=pp.in->nextchr;}while(0)
544887Schin #define CACHEOUT()	do{CACHEOUTX();st=pp.state;if(!pp.hidden)spliced=0;}while(0)
554887Schin #define CACHEOUTX()	do{tp=op=pp.outp;xp=pp.oute;if(sp)sp=op;}while(0)
564887Schin #define GETCHR()	(*(unsigned char*)ip++)
574887Schin #define LASTCHR()	(*(ip-1))
584887Schin #define LASTOUT()	((op>pp.outbuf)?*(op-1):pp.lastout)
594887Schin #define SKIPIN()	(ip++)
604887Schin #define PUTCHR(c)	(*op++=(c))
614887Schin #define SETCHR(c)	(*op=(c))
624887Schin #define SYNC()		do{SYNCINX();SYNCOUTX();pp.state=st;}while(0)
634887Schin #define SYNCIN()	do{SYNCINX();pp.state=st;}while(0)
644887Schin #define SYNCINX()	do{pp.in->nextchr=ip;}while(0)
654887Schin #define SYNCOUT()	do{SYNCOUTX();pp.state=st;}while(0)
664887Schin #define SYNCOUTX()	do{if(sp)op=tp=sp;pp.outp=op;}while(0)
674887Schin #define UNGETCHR(c)	(*--ip=(c))
684887Schin 
694887Schin #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)
704887Schin #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)
714887Schin #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)
724887Schin 
734887Schin #define PPSYNCLINE()	do { \
744887Schin 		if ((st & (ADD|HIDDEN)) && !(*pp.control & SKIP)) \
754887Schin 		{ \
764887Schin 		    if (spliced) \
774887Schin 		    { \
784887Schin 			error_info.line += spliced; \
794887Schin 			spliced = 0; \
804887Schin 		    } \
814887Schin 		    else \
824887Schin 		    { \
834887Schin 			if (st & ADD) \
844887Schin 			{ \
854887Schin 				st &= ~ADD; \
864887Schin 				m = pp.addp - pp.addbuf; \
874887Schin 				pp.addp = pp.addbuf; \
884887Schin 				memcpy(op, pp.addbuf, m); \
894887Schin 				op += m; \
904887Schin 				PPCHECKOUT(); \
914887Schin 			} \
924887Schin 			if (pp.linesync) \
934887Schin 			{ \
944887Schin 				if ((st & SYNCLINE) || pp.hidden >= MAXHIDDEN) \
954887Schin 				{ \
964887Schin 					pp.hidden = 0; \
974887Schin 					st &= ~(HIDDEN|SYNCLINE); \
984887Schin 					if (error_info.line) \
994887Schin 					{ \
1004887Schin 						if (LASTOUT() != '\n') \
1014887Schin 							PUTCHR('\n'); \
1024887Schin 						SYNCOUT(); \
1034887Schin 						(*pp.linesync)(error_info.line, error_info.file); \
1044887Schin 						CACHEOUT(); \
1054887Schin 					} \
1064887Schin 				} \
1074887Schin 				else \
1084887Schin 				{ \
1094887Schin 					m = pp.hidden; \
1104887Schin 					pp.hidden = 0; \
1114887Schin 					st &= ~HIDDEN; \
1124887Schin 					while (m-- > 0) \
1134887Schin 						PUTCHR('\n'); \
1144887Schin 				} \
1154887Schin 			} \
1164887Schin 			else \
1174887Schin 			{ \
1184887Schin 				pp.hidden = 0; \
1194887Schin 				st &= ~HIDDEN; \
1204887Schin 				PUTCHR('\n'); \
1214887Schin 			} \
1224887Schin 		    } \
1234887Schin 		} \
1244887Schin 	} while (0)
1254887Schin 
1264887Schin #if POOL
1274887Schin 
1284887Schin /*
1294887Schin  * <wait.h> is poison here so pool moved to the end
1304887Schin  */
1314887Schin 
1324887Schin static void	poolstatus(void);
1334887Schin static void	pool(void);
1344887Schin 
1354887Schin #endif
1364887Schin 
1374887Schin #else
1384887Schin 
1394887Schin /*
1404887Schin  * return next pp token
1414887Schin  *
1424887Schin  * NOTE: pp.token points to at least MAXTOKEN*2 chars and is
1434887Schin  *       truncated back to MAXTOKEN on EOB
1444887Schin  */
1454887Schin 
1464887Schin #define PPCPP_T		int
1474887Schin #define ppcpp		pplex
1484887Schin 
1494887Schin #define START		TOKEN
1504887Schin #define INMACRO(x)	INTMACRO(x)
1514887Schin #define DOSTRIP()	((st&STRIP)||pp.level==1&&(st&(COMPILE|JOINING))==COMPILE&&!(pp.option&PRESERVE))
1524887Schin 
1534887Schin #define st		pp.state
1544887Schin #define tp		pp.token
1554887Schin #define xp		&pp.token[MAXTOKEN]
1564887Schin 
1574887Schin #define BACKIN()	(ip--)
1584887Schin #define BACKOUT()	(op=pp.token)
1594887Schin #define CACHE()		do{CACHEIN();CACHEOUT();}while(0)
1604887Schin #define CACHEIN()	(ip=pp.in->nextchr)
1614887Schin #define CACHEOUT()	(op=pp.token)
1624887Schin #define GETCHR()	(*(unsigned char*)ip++)
1634887Schin #define LASTCHR()	(*(ip-1))
1644887Schin #define PUTCHR(c)	(*op++=(c))
1654887Schin #define SETCHR(c)	(*op=(c))
1664887Schin #define SKIPIN()	(ip++)
1674887Schin #define SYNC()		do{SYNCIN();SYNCOUT();}while(0)
1684887Schin #define SYNCIN()	(pp.in->nextchr=ip)
1694887Schin #define SYNCOUT()	(pp.toknxt=op)
1704887Schin #define UNGETCHR(c)	(*--ip=(c))
1714887Schin 
1724887Schin #endif
1734887Schin 
1744887Schin PPCPP_T
ppcpp(void)1754887Schin ppcpp(void)
1764887Schin {
1774887Schin 	register short*		rp;
1784887Schin 	register char*		ip;
1794887Schin 	register int		state;
1804887Schin 	register int		c;
1814887Schin 	register char*		op;
1824887Schin 	char*			bp;
1834887Schin 	int			n;
1844887Schin 	int			m;
1854887Schin 	int			quot;
1864887Schin 	int			quotquot;
1874887Schin 	int			comdelim = 0;
1884887Schin 	int			comstart = 0;
1894887Schin 	int			comwarn = 0;
1904887Schin 	char*			s;
1914887Schin 	struct ppsymbol*	sym;
1924887Schin #if CPP
1934887Schin 	register long		st;
1944887Schin 	char*			tp;
1954887Schin 	char*			xp;
1964887Schin 	char*			sp = 0;
1974887Schin 	int			qual = 0;
1984887Schin 	int			spliced = 0;
1994887Schin #else
2004887Schin 	int			qual;
2014887Schin #endif
2024887Schin 
2034887Schin #if CPP
2044887Schin #if POOL
2054887Schin  fsm_pool:
2064887Schin #endif
2074887Schin #else
2084887Schin 	count(pplex);
2094887Schin #endif
2104887Schin 	error_info.indent++;
2114887Schin 	pp.level++;
2124887Schin 	CACHE();
2134887Schin #if !CPP
2144887Schin  fsm_top:
2154887Schin 	qual = 0;
2164887Schin #endif
2174887Schin  fsm_start:
2184887Schin #if CPP
2194887Schin 	PPCHECKOUTSP();
2204887Schin 	tp = op;
2214887Schin #endif
2224887Schin 	state = START;
2234887Schin  fsm_begin:
2244887Schin 	bp = ip;
2254887Schin 	do
2264887Schin 	{
2274887Schin 		rp = fsm[state];
2284887Schin  fsm_get:
2294887Schin 		while (!(state = rp[c = GETCHR()]));
2304887Schin  fsm_next:
2314887Schin 		;
2324887Schin 	} while (state > 0);
2334887Schin 	if (((state = ~state) != S_COMMENT || pp.comment || c == '/' && !INCOMMENT(rp)) && (n = ip - bp - 1) > 0)
2344887Schin 	{
2354887Schin 		ip = bp;
2364887Schin #if CPP
2378462SApril.Chin@Sun.COM 		if (op == tp && (st & (ADD|HIDDEN)) && !(st & PASSTHROUGH) && !(pp.option & PRESERVE))
2384887Schin 			switch (TERM(state))
2394887Schin 			{
2404887Schin 			case S_SHARP:
2414887Schin 				break;
2424887Schin 			case S_CHRB:
2434887Schin 			case S_NL:
2444887Schin 				if (*ip == '\n')
2454887Schin 					break;
2464887Schin 				/*FALLTHROUGH*/
2474887Schin 			default:
2488462SApril.Chin@Sun.COM 				if ((pp.option & PRESERVE) && !(st & NEWLINE) && c != '\n')
2498462SApril.Chin@Sun.COM 					break;
2504887Schin 				PPSYNCLINE();
2514887Schin 				tp = op;
2524887Schin 				break;
2534887Schin 			}
2544887Schin #endif
2554887Schin 		MEMCPY(op, ip, n);
2564887Schin 		ip++;
2574887Schin 	}
2584887Schin 	count(terminal);
2594887Schin #if CPP && (DEBUG & TRACE_debug)
2604887Schin 	hit[(state & SPLICE) ? (elementsof(hit) - 1) : (TERM(state) - TERMINAL)]++;
2614887Schin #endif
2624887Schin  fsm_terminal:
2634887Schin 	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)));
2644887Schin 	switch (TERM(state))
2654887Schin 	{
2664887Schin 
2674887Schin #if !CPP
2684887Schin 	case S_CHR:
2694887Schin 		PUTCHR(c);
2704887Schin 		break;
2714887Schin #endif
2724887Schin 
2734887Schin 	case S_CHRB:
2744887Schin 		BACKIN();
2754887Schin #if CPP
2764887Schin 		st &= ~NEWLINE;
2774887Schin 		pp.in->flags |= IN_tokens;
2784887Schin 		count(token);
2794887Schin 		goto fsm_start;
2804887Schin #else
2814887Schin 		c = *tp;
2824887Schin 		break;
2834887Schin #endif
2844887Schin 
2854887Schin 	case S_COMMENT:
2864887Schin 		switch (c)
2874887Schin 		{
2884887Schin 		case '\n':
2894887Schin 			if (!INCOMMENTXX(rp))
2904887Schin 			{
2914887Schin 				qual = 0;
2924887Schin 				if (!comstart) comstart = comdelim = error_info.line;
2934887Schin 				error_info.line++;
2944887Schin 				if (pp.comment) PUTCHR(c);
2954887Schin 				else BACKOUT();
2964887Schin #if CPP
2974887Schin 				rp = fsm[COM2];
2984887Schin 				bp = ip;
2994887Schin 				goto fsm_get;
3004887Schin #else
3014887Schin 				state = COM2;
3024887Schin 				goto fsm_begin;
3034887Schin #endif
3044887Schin 			}
3054887Schin 			else if (comwarn < 0 && !(pp.mode & HOSTED))
3064887Schin 				error(1, "/* appears in // comment");
3074887Schin 			break;
3084887Schin 		case '*':
3094887Schin 			if (!comwarn && !(pp.mode & HOSTED))
3104887Schin 			{
3114887Schin 				if (INCOMMENTXX(rp)) comwarn = -1;
3124887Schin 				else if (comstart && comstart != error_info.line)
3134887Schin 				{
3144887Schin 					if (qual || comdelim < error_info.line - 1)
3154887Schin 					{
3164887Schin 						error(1, "/* appears in /* ... */ comment starting at line %d", comstart);
3174887Schin 						comwarn = 1;
3184887Schin 					}
3194887Schin 					else comdelim = error_info.line;
3204887Schin 				}
3214887Schin 			}
3224887Schin  fsm_comment:
3234887Schin 			PUTCHR(c);
3244887Schin #if CPP
3254887Schin 			rp = fsm[INCOMMENTXX(rp) ? COM5 : COM3];
3264887Schin 			bp = ip;
3274887Schin 			goto fsm_get;
3284887Schin #else
3294887Schin 			state = INCOMMENTXX(rp) ? COM5 : COM3;
3304887Schin 			goto fsm_begin;
3314887Schin #endif
3324887Schin 		case '/':
3334887Schin 			if (!INCOMMENT(rp))
3344887Schin 			{
3354887Schin 				if (!(pp.mode & HOSTED))
3364887Schin 					error(1, "*/ appears outside of comment");
3374887Schin 				BACKIN();
3384887Schin #if CPP
3394887Schin 				st &= ~NEWLINE;
3404887Schin 				pp.in->flags |= IN_tokens;
3414887Schin 				count(token);
3424887Schin 				goto fsm_start;
3434887Schin #else
3444887Schin 				c = '*';
3454887Schin 				if (!pp.comment) PUTCHR(c);
3464887Schin 				goto fsm_token;
3474887Schin #endif
3484887Schin 			}
3494887Schin 			else if (INCOMMENTXX(rp))
3504887Schin 			{
3514887Schin 				if (!(pp.mode & HOSTED))
3524887Schin 				{
3534887Schin 					if (comwarn < 0) comwarn = 0;
3544887Schin 					else if (!comwarn)
3554887Schin 					{
3564887Schin 						comwarn = 1;
3574887Schin 						error(1, "*/ appears in // comment");
3584887Schin 					}
3594887Schin 				}
3604887Schin 				goto fsm_comment;
3614887Schin 			}
3624887Schin 			break;
3634887Schin 		case EOF:
3644887Schin 			BACKIN();
3654887Schin 			if (!(pp.mode & HOSTED))
3664887Schin 			{
3674887Schin 				if (comstart) error(2, "unterminated /* ... */ comment starting at line %d", comstart);
3684887Schin 				else if (INCOMMENTXX(rp)) error(2, "unterminated // ... comment");
3694887Schin 				else error(2, "unterminated /* ... */ comment");
3704887Schin 			}
3714887Schin 			break;
3724887Schin 		}
3734887Schin #if CPP
3744887Schin 		if (!pp.comment || sp)
3754887Schin 		{
3764887Schin #if COMPATIBLE
3774887Schin 			if (!(pp.state & COMPATIBILITY) || *bp == ' ' || *bp == '\t')
3784887Schin #endif
3794887Schin 			{
3804887Schin 				BACKOUT();
3814887Schin 				PUTCHR(' ');
3824887Schin 				tp = op;
3834887Schin 			}
3844887Schin 		}
3854887Schin 		else if (pp.in->type & IN_TOP)
3864887Schin #else
3874887Schin 		if (pp.comment && !(st & (COLLECTING|DIRECTIVE|JOINING)) && !(*pp.control & SKIP) && (pp.in->type & IN_TOP))
3884887Schin #endif
3894887Schin 		{
3904887Schin 			st &= ~HIDDEN;
3914887Schin 			pp.hidden = 0;
3924887Schin 			*(op - (c != '\n')) = 0;
3934887Schin 			m = (op - (c != '\n') - tp > MAXTOKEN - 6) ? (error_info.line - MAXHIDDEN) : 0;
3944887Schin 			BACKOUT();
3954887Schin 			SYNC();
3964887Schin 			while (*tp != '/') tp++;
3974887Schin 			(*pp.comment)(c == '\n' ? "//" : "/*", tp + 2, c == '\n' ? "" : (st & HEADER) ? "*/\n" : "*/", comstart ? comstart : error_info.line);
3984887Schin 			CACHE();
3994887Schin 			comstart = m;
4004887Schin 		}
4014887Schin 		if (comstart)
4024887Schin 		{
4034887Schin 			st |= HIDDEN;
4044887Schin 			pp.hidden += error_info.line - comstart;
4054887Schin 			comstart = 0;
4064887Schin 		}
4074887Schin 		qual = comwarn = comdelim = 0;
4084887Schin 		BACKOUT();
4094887Schin 		if (c == '\n') goto fsm_newline;
4104887Schin 		if ((st & PASSTHROUGH) && ((st & (HIDDEN|NEWLINE)) || *ip == '\n'))
4114887Schin 		{
4124887Schin 			if (*ip == '\n')
4134887Schin 				ip++;
4144887Schin 			goto fsm_newline;
4154887Schin 		}
4164887Schin #if COMPATIBLE
4174887Schin 		if ((st & (COMPATIBILITY|TRANSITION)) == COMPATIBILITY) st &= ~NEWLINE;
4184887Schin #endif
4194887Schin #if !CPP
4204887Schin 		if (pp.level > 1 && !(st & (NOSPACE|SKIPCONTROL)))
4214887Schin 		{
4224887Schin #if COMPATIBLE
4234887Schin 			c = ((st & (COMPATIBILITY|DEFINITION)) == ((COMPATIBILITY|DEFINITION))) ? '\t' : ' ';
4244887Schin #else
4254887Schin 			c = ' ';
4264887Schin #endif
4274887Schin 			goto fsm_return;
4284887Schin 		}
4294887Schin #endif
4304887Schin 		goto fsm_start;
4314887Schin 
4324887Schin 	case S_EOB:
4334887Schin 		if (c)
4344887Schin 		{
4354887Schin 			if (state = fsm[TERMINAL][INDEX(rp)+1])
4364887Schin 				goto fsm_terminal;
4374887Schin #if CPP
4384887Schin #if POOL
4394887Schin 			if (pp.pool.input)
4404887Schin 			{
4414887Schin 				BACKIN();
4424887Schin 				SYNC();
4434887Schin 				pool();
4444887Schin 				CACHE();
4454887Schin 				goto fsm_pool;
4464887Schin 			}
4474887Schin #endif
4484887Schin 			SYNCOUT();
4494887Schin 			return;
4504887Schin #else
4514887Schin 			BACKIN();
4524887Schin 			c = 0;
4534887Schin 			goto fsm_return;
4544887Schin #endif
4554887Schin 		}
4564887Schin 		{
4574887Schin 			register struct ppinstk*	cur = pp.in;
4584887Schin 			register struct ppinstk*	prv = pp.in->prev;
4594887Schin 
4604887Schin #if CPP
4614887Schin 			if (sp) op = sp;
4624887Schin #endif
4634887Schin 			switch (cur->type)
4644887Schin 			{
4654887Schin 			case IN_BUFFER:
4664887Schin 			case IN_INIT:
4674887Schin 			case IN_RESCAN:
4684887Schin #if CPP
4694887Schin 				if (prv)
4704887Schin #else
4714887Schin 				if (!(st & PASSEOF) && prv)
4724887Schin #endif
4734887Schin 				{
4744887Schin 					if (cur->type == IN_RESCAN || cur->type == IN_BUFFER)
4754887Schin 					{
4764887Schin  fsm_pop:
4774887Schin #if PROTOTYPE
4784887Schin 						if (cur->flags & IN_prototype)
4794887Schin 							pppclose(cur->buffer + PPBAKSIZ);
4804887Schin 						else
4814887Schin #endif
4824887Schin 						if (!(cur->flags & IN_static))
4834887Schin 							free(cur->buffer);
4844887Schin 					}
4854887Schin 					while (pp.control-- != cur->control)
4864887Schin 						error(2, "#%s on line %d has no #%s", dirname(IF), GETIFLINE(pp.control+1), dirname(ENDIF));
4874887Schin 					st |= NEWLINE;
4884887Schin 					error_info.file = cur->file;
4894887Schin 					error_info.line = cur->line;
4904887Schin 					pp.hidden = 0;
4914887Schin #if CPP
4924887Schin 					spliced = 0;
4934887Schin #endif
4944887Schin 					if (cur->flags & IN_hosted)
4954887Schin 					{
4964887Schin 						pp.mode |= HOSTED;
4974887Schin 						pp.flags |= PP_hosted;
4984887Schin 					}
4994887Schin 					else
5004887Schin 					{
5014887Schin 						pp.mode &= ~HOSTED;
5024887Schin 						pp.flags &= ~PP_hosted;
5034887Schin 					}
5044887Schin #if !CPP && CATSTRINGS
5054887Schin 					if (st & JOINING) st |= HIDDEN|SYNCLINE;
5064887Schin 					else
5074887Schin #endif
5084887Schin 					{
5094887Schin 						st &= ~(HIDDEN|SYNCLINE);
5104887Schin 						switch (cur->type)
5114887Schin 						{
5124887Schin 						case IN_BUFFER:
5134887Schin 						case IN_INIT:
5144887Schin 							if (!prv->prev) break;
5154887Schin 							/*FALLTHROUGH*/
5164887Schin 						case IN_FILE:
5174887Schin 						case IN_RESCAN:
5184887Schin 							if (prv->type == IN_FILE || cur->type == IN_FILE && (prv->type == IN_RESCAN || prv->type == IN_MULTILINE))
5194887Schin 							{
5204887Schin 								if (pp.linesync && (cur->type != IN_RESCAN || (cur->flags & IN_sync)))
5214887Schin 								{
5224887Schin 									POP();
5234887Schin 									SYNCOUT();
5244887Schin 									(*pp.linesync)(error_info.line, error_info.file);
5254887Schin 									CACHEOUT();
5264887Schin 									prv = pp.in;
5274887Schin 								}
5284887Schin 							}
5294887Schin #if DEBUG
5304887Schin 							else if (!prv->prev)
5314887Schin 							{
5324887Schin 								/*UNDENT*/
5334887Schin 	c = 0;
5344887Schin #if DEBUG & TRACE_count
5354887Schin 	if (pp.test & TEST_count)
5364887Schin 	{
5374887Schin 		c = 1;
5384887Schin 		sfprintf(sfstderr, "\n");
5394887Schin 		sfprintf(sfstderr, "%7d: pplex calls\n", pp.counter.pplex);
5404887Schin 		sfprintf(sfstderr, "%7d: terminal states\n", pp.counter.terminal);
5414887Schin 		sfprintf(sfstderr, "%7d: emitted tokens\n", pp.counter.token);
5424887Schin 		sfprintf(sfstderr, "%7d: input stream pushes\n", pp.counter.push);
5434887Schin 		sfprintf(sfstderr, "%7d: macro candidates\n", pp.counter.candidate);
5444887Schin 		sfprintf(sfstderr, "%7d: macro expansions\n", pp.counter.macro);
5454887Schin 		sfprintf(sfstderr, "%7d: function macros\n", pp.counter.function);
5464887Schin 	}
5474887Schin #endif
5484887Schin #if CPP && (DEBUG & TRACE_debug)
5494887Schin 	if (pp.test & TEST_hit)
5504887Schin 	{
5514887Schin 		c = 1;
5524887Schin 		sfprintf(sfstderr, "\n");
5534887Schin 		if (hit[elementsof(hit) - 1])
5544887Schin 			sfprintf(sfstderr, "%7d: SPLICE\n", hit[elementsof(hit) - 1]);
5554887Schin 		for (n = 0; n < elementsof(hit) - 1; n++)
5564887Schin 			if (hit[n])
5574887Schin 				sfprintf(sfstderr, "%7d: %s\n", hit[n], pplexstr(TERMINAL + n));
5584887Schin 	}
5594887Schin #endif
5604887Schin 	if (pp.test & (TEST_hashcount|TEST_hashdump))
5614887Schin 	{
5624887Schin 		c = 1;
5634887Schin 		sfprintf(sfstderr, "\n");
5644887Schin 		hashdump(NiL, (pp.test & TEST_hashdump) ? HASH_BUCKET : 0);
5654887Schin 	}
5664887Schin 	if (c) sfprintf(sfstderr, "\n");
5674887Schin 								/*INDENT*/
5684887Schin 							}
5694887Schin #endif
5704887Schin 							break;
5714887Schin 						}
5724887Schin 					}
5734887Schin #if CHECKPOINT
5744887Schin 					if (cur->index)
5754887Schin 					{
5764887Schin 						SYNCOUT();
5774887Schin 						cur->index->end = ppoffset();
5784887Schin 						cur->index = 0;
5794887Schin 						CACHEOUT();
5804887Schin 					}
5814887Schin #endif
5824887Schin 					POP();
5834887Schin 					bp = ip;
5844887Schin 					tp = op;
5854887Schin 					goto fsm_get;
5864887Schin 				}
5874887Schin 				c = EOF;
5884887Schin 				break;
5894887Schin 			case IN_COPY:
5904887Schin 				if (prv)
5914887Schin 				{
5924887Schin 					error_info.line = cur->line;
5934887Schin 					if (!(prv->symbol->flags & SYM_MULTILINE))
5944887Schin 						prv->symbol->flags |= SYM_DISABLED;
5954887Schin 					POP();
5964887Schin 					bp = ip;
5974887Schin 					goto fsm_get;
5984887Schin 				}
5994887Schin 				c = EOF;
6004887Schin 				break;
6014887Schin 			case IN_EXPAND:
6024887Schin 				if (prv)
6034887Schin 				{
6044887Schin 					error_info.line = cur->line;
6054887Schin 					free(cur->buffer);
6064887Schin 					POP();
6074887Schin 					bp = ip;
6084887Schin 					goto fsm_get;
6094887Schin 				}
6104887Schin 				c = EOF;
6114887Schin 				break;
6124887Schin 			case IN_FILE:
6134887Schin 				FGET(c, c, tp, xp);
6144887Schin 				if (c == EOB)
6154887Schin 				{
6164887Schin #if CPP
6174887Schin 					if ((st & (NOTEXT|HIDDEN)) == HIDDEN && LASTOUT() != '\n')
6184887Schin 						PUTCHR('\n');
6194887Schin 					if (prv)
6204887Schin #else
6214887Schin 					if (st & EOF2NL)
6224887Schin 					{
6234887Schin 						st &= ~EOF2NL;
6244887Schin 						*(ip - 1) = c = '\n';
6254887Schin 					}
6264887Schin 					else if (!(st & (FILEPOP|PASSEOF)) && prv)
6274887Schin #endif
6284887Schin 					{
6294887Schin 						if (!(cur->flags & IN_newline))
6304887Schin 						{
6314887Schin 							cur->flags |= IN_newline;
6324887Schin 							if ((pp.mode & (HOSTED|PEDANTIC)) == PEDANTIC && LASTCHR() != '\f' && LASTCHR() != CC_sub)
6334887Schin 								error(1, "file does not end with %s", pptokchr('\n'));
6344887Schin 							*(ip - 1) = c = '\n';
6354887Schin 						}
6364887Schin 						else
6374887Schin 						{
6384887Schin 							if (!(cur->flags & (IN_noguard|IN_tokens)) && cur->symbol)
6394887Schin 								ppmultiple(ppsetfile(error_info.file), cur->symbol);
6404887Schin 							if (cur->fd >= 0)
6414887Schin 								close(cur->fd);
6424887Schin 							if (pp.incref && !(pp.mode & INIT))
6434887Schin 							{
6444887Schin 								SYNCOUT();
6454887Schin 								(*pp.incref)(error_info.file, cur->file, error_info.line - 1, PP_SYNC_POP);
6464887Schin 								CACHEOUT();
6474887Schin 							}
6484887Schin 							goto fsm_pop;
6494887Schin 						}
6504887Schin 					}
6514887Schin 					else
6524887Schin 						c = EOF;
6534887Schin 				}
6544887Schin 				break;
6554887Schin 			case IN_MACRO:
6564887Schin 			case IN_MULTILINE:
6574887Schin #if !CPP
6584887Schin 				if (!(st & PASSEOF))
6594887Schin #endif
6604887Schin #if COMPATIBLE
6614887Schin 				if (prv && (!INMACRO(rp) || (st & (COMPATIBILITY|TRANSITION)) == COMPATIBILITY && ppismac(*prv->nextchr)))
6624887Schin #else
6634887Schin 				if (prv && !INMACRO(rp))
6644887Schin #endif
6654887Schin 				{
6664887Schin 					if (cur->type == IN_MULTILINE)
6674887Schin 					{
6684887Schin 						while (pp.control-- != cur->control)
6694887Schin 							error(2, "#%s on line %d has no #%s", dirname(IF), GETIFLINE(pp.control+1), dirname(ENDIF));
6704887Schin 						free(cur->buffer);
6714887Schin 						error_info.file = cur->file;
6724887Schin 						error_info.line = cur->line;
6734887Schin 						if (pp.linesync)
6744887Schin 						{
6754887Schin 							SYNCOUT();
6764887Schin 							(*pp.linesync)(error_info.line, error_info.file);
6774887Schin 							CACHEOUT();
6784887Schin 						}
6794887Schin 					}
6804887Schin 					cur->symbol->flags &= ~SYM_DISABLED;
6814887Schin 					if (cur->symbol->flags & SYM_FUNCTION)
6824887Schin 						popframe(pp.macp);
6834887Schin 					POP();
6844887Schin #if CPP
6854887Schin 					if (!(st & COMPATIBILITY) && ppisidig(*(op - 1)) && ppisidig(*ip)) UNGETCHR(' ');
6864887Schin #endif
6874887Schin 					bp = ip;
6884887Schin 					goto fsm_get;
6894887Schin 				}
6904887Schin 				c = EOF;
6914887Schin 				break;
6924887Schin 			case IN_QUOTE:
6934887Schin 				if (prv)
6944887Schin 				{
6954887Schin 					error_info.line = cur->line;
6964887Schin 					st &= ~(ESCAPE|QUOTE);
6974887Schin 					POP();
6984887Schin 					c = '"';
6994887Schin 				}
7004887Schin 				else c = EOF;
7014887Schin 				break;
7024887Schin 			case IN_SQUOTE:
7034887Schin 				if (prv)
7044887Schin 				{
7054887Schin 					error_info.line = cur->line;
7064887Schin 					st &= ~(ESCAPE|SQUOTE);
7074887Schin 					POP();
7084887Schin 					c = '\'';
7094887Schin 				}
7104887Schin 				else c = EOF;
7114887Schin 				break;
7124887Schin 			case IN_STRING:
7134887Schin #if CPP
7144887Schin 				if (prv)
7154887Schin #else
7164887Schin 				if (!(st & PASSEOF) && !(cur->flags & IN_expand) && prv)
7174887Schin #endif
7184887Schin 				{
7194887Schin 					if (cur->flags & IN_disable) st |= DISABLE;
7204887Schin 					else st &= ~DISABLE;
7214887Schin 					POP();
7224887Schin 					bp = ip;
7234887Schin 					goto fsm_get;
7244887Schin 				}
7254887Schin 				c = EOF;
7264887Schin 				break;
7274887Schin 			default:
7284887Schin 				c = EOF;
7294887Schin 				break;
7304887Schin 			}
7314887Schin 		}
7324887Schin 		bp = ip - 1;
7334887Schin 		if (state = rp[c]) goto fsm_next;
7344887Schin 		goto fsm_get;
7354887Schin 
7364887Schin #if !CPP
7374887Schin 	case S_HUH:
7384887Schin 		if (INOPSPACE(rp))
7394887Schin 		{
7404887Schin 			if (c == '=')
7414887Schin 			{
7424887Schin #if PROTOTYPE
7434887Schin 				if (pp.in->flags & IN_prototype) PUTCHR(c);
7444887Schin 				else
7454887Schin 				{
7464887Schin #endif
7474887Schin 					while (*(op - 1) == ' ' || *(op - 1) == '\t') op--;
7484887Schin 					PUTCHR(c);
7494887Schin 					if (st & (STRICT|WARN)) error(1, "%-*.*s: space ignored in operator", op - tp, op - tp, tp);
7504887Schin #if PROTOTYPE
7514887Schin 				}
7524887Schin #endif
7534887Schin 				switch (*tp)
7544887Schin 				{
7554887Schin 				case '/':
7564887Schin 					c = T_DIVEQ;
7574887Schin 					break;
7584887Schin 				case '%':
7594887Schin 					c = T_MODEQ;
7604887Schin 					break;
7614887Schin 				case '&':
7624887Schin 					c = T_ANDEQ;
7634887Schin 					break;
7644887Schin 				case '*':
7654887Schin 					c = T_MPYEQ;
7664887Schin 					break;
7674887Schin 				case '+':
7684887Schin 					c = T_ADDEQ;
7694887Schin 					break;
7704887Schin 				case '-':
7714887Schin 					c = T_SUBEQ;
7724887Schin 					break;
7734887Schin 				case '^':
7744887Schin 					c = T_XOREQ;
7754887Schin 					break;
7764887Schin 				case '|':
7774887Schin 					c = T_OREQ;
7784887Schin 					break;
7794887Schin 				case '<':
7804887Schin 					c = T_LSHIFTEQ;
7814887Schin 					break;
7824887Schin 				case '>':
7834887Schin 					c = T_RSHIFTEQ;
7844887Schin 					break;
7854887Schin 				}
7864887Schin 			}
7874887Schin 			else
7884887Schin 			{
7894887Schin 				BACKIN();
7904887Schin 				switch (c = *tp)
7914887Schin 				{
7924887Schin 				case '<':
7934887Schin 					c = T_LSHIFT;
7944887Schin 					break;
7954887Schin 				case '>':
7964887Schin 					c = T_RSHIFT;
7974887Schin 					break;
7984887Schin 				}
7994887Schin 			}
8004887Schin 		}
8014887Schin 		else if (pp.level > 1 || (pp.option & PRESERVE)) PUTCHR(c);
8024887Schin 		else if (tp == op)
8034887Schin 		{
8044887Schin 			if (pp.in->type != IN_BUFFER)
8054887Schin 			{
8064887Schin 				if (!(pp.option & ALLPOSSIBLE))
8074887Schin 					error(1, "%s: invalid character ignored", pptokchr(c));
8084887Schin 				goto fsm_top;
8094887Schin 			}
8104887Schin 			PUTCHR(c);
8114887Schin 		}
8124887Schin 		else if (*tp == ':')
8134887Schin 		{
8144887Schin 			PUTCHR(c);
8154887Schin 			if (c == '=') error(2, "real programmers use =");
8164887Schin 			else c = '+';
8174887Schin 		}
8184887Schin 		else
8194887Schin 		{
8204887Schin 			BACKIN();
8214887Schin 			c = *tp;
8224887Schin 		}
8234887Schin 		break;
8244887Schin #endif
8254887Schin 
8264887Schin 	case S_QUAL:
8274887Schin 		if ((state = NEXT(state)) != LIT1)
8284887Schin 		{
8294887Schin 			rp = fsm[state];
8304887Schin 			bp = ip;
8314887Schin #if CPP
8324887Schin 			qual = 1;
8334887Schin #if COMPATIBLE
8344887Schin 			if (!(st & COMPATIBILITY) || c != 'u' && c != 'U')
8354887Schin #endif
8364887Schin 				PUTCHR(c);
8374887Schin #else
8384887Schin 			switch (c)
8394887Schin 			{
8404887Schin 			case 'f':
8414887Schin 			case 'F':
8424887Schin 				qual |= N_FLOAT;
8434887Schin #if COMPATIBLE
8444887Schin 				if (!(st & COMPATIBILITY))
8454887Schin #endif
8464887Schin 				PUTCHR(c);
8474887Schin 				break;
8484887Schin 			case 'l':
8494887Schin 			case 'L':
8504887Schin 				qual |= N_LONG;
8514887Schin 				PUTCHR(c);
8524887Schin 				break;
8534887Schin 			case 'u':
8544887Schin 			case 'U':
8554887Schin 				qual |= N_UNSIGNED;
8564887Schin #if COMPATIBLE
8574887Schin 				if (!(st & COMPATIBILITY))
8584887Schin #endif
8594887Schin 				PUTCHR(c);
8604887Schin 				break;
8614887Schin 			default:
8624887Schin 				PUTCHR(c);
8634887Schin 				break;
8644887Schin 			}
8654887Schin #endif
8664887Schin 			goto fsm_get;
8674887Schin 		}
8684887Schin #if !CPP
8694887Schin 		qual |= N_WIDE;
8704887Schin 		if (DOSTRIP()) BACKOUT();
8714887Schin #endif
8724887Schin 		/*FALLTHROUGH*/
8734887Schin 
8744887Schin 	case S_LITBEG:
8754887Schin #if CPP
8764887Schin 		quot = c;
8774887Schin 		rp = fsm[LIT1];
8784887Schin 		if (op == tp)
8794887Schin 		{
8804887Schin 			PPSYNCLINE();
8814887Schin 			tp = op;
8824887Schin 		}
8834887Schin #else
8844887Schin 		if ((quot = c) == '<')
8854887Schin 		{
8864887Schin 			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)
8874887Schin 			{
8884887Schin 				PUTCHR(c);
8894887Schin 				bp = ip;
8904887Schin 				rp = fsm[LT1];
8914887Schin 				goto fsm_get;
8924887Schin 			}
8934887Schin 			quot = '>';
8944887Schin 			rp = fsm[HDR1];
8954887Schin 		}
8964887Schin 		else rp = fsm[LIT1];
8974887Schin 		if (!DOSTRIP())
8984887Schin #endif
8994887Schin 		PUTCHR(c);
9004887Schin 		bp = ip;
9014887Schin 		goto fsm_get;
9024887Schin 
9034887Schin 	case S_LITEND:
9044887Schin 		n = 1;
9054887Schin 		if (c != quot)
9064887Schin 		{
9074887Schin 			if (c != '\n' && c != EOF)
9084887Schin 			{
9094887Schin 				if (st & (QUOTE|SQUOTE))
9104887Schin 				{
9114887Schin 					if (!(st & ESCAPE))
9124887Schin 					{
9134887Schin 						st |= ESCAPE;
9144887Schin 						quotquot = c;
9154887Schin 					}
9164887Schin 					else if (c == quotquot) st &= ~ESCAPE;
9174887Schin 				}
9184887Schin 				PUTCHR(c);
9194887Schin 				bp = ip;
9204887Schin 				goto fsm_get;
9214887Schin 			}
9224887Schin #if CPP
9238462SApril.Chin@Sun.COM 			if ((st & PASSTHROUGH) || (pp.option & PRESERVE))
9244887Schin 			{
9254887Schin 				if (c == '\n') goto fsm_newline;
9264887Schin 				bp = ip;
9274887Schin 				goto fsm_start;
9284887Schin 			}
9294887Schin #endif
9304887Schin 			m = (st & SKIPCONTROL) && (pp.mode & HOSTED) ? -1 : 1;
9314887Schin 			if (c == '\n' && quot == '\'' && (pp.option & STRINGSPAN)) n = 0;
9324887Schin 			else
9334887Schin #if COMPATIBLE && !CPP
9344887Schin 			if ((st & (COMPATIBILITY|DEFINITION)) != (COMPATIBILITY|DEFINITION))
9354887Schin #endif
9364887Schin 			{
9374887Schin 				switch (quot)
9384887Schin 				{
9394887Schin 				case '"':
9404887Schin 					if (c == '\n')
9414887Schin 					{
9424887Schin 						if (!(pp.option & STRINGSPAN) || (st & (COMPATIBILITY|STRICT)) == STRICT)
9434887Schin 							error(m, "%s in string", pptokchr(c));
9444887Schin 						error_info.line++;
9454887Schin 						if (!(pp.option & STRINGSPAN))
9464887Schin 						{
9474887Schin 							PUTCHR('\\');
9484887Schin 							c = 'n';
9494887Schin 						}
9504887Schin 						else if (pp.option & STRINGSPLIT)
9514887Schin 						{
9524887Schin 							PUTCHR('\\');
9534887Schin 							PUTCHR('n');
9544887Schin 							PUTCHR('"');
9554887Schin 							PUTCHR('\n');
9564887Schin 							c = '"';
9574887Schin 						}
9584887Schin 						PUTCHR(c);
9594887Schin 						bp = ip;
9604887Schin 						goto fsm_get;
9614887Schin 					}
9624887Schin 					error(m, "%s in string", pptokchr(c));
9634887Schin 					c = '\n';
9644887Schin 					break;
9654887Schin 				case '\'':
9664887Schin 					if (!(st & DIRECTIVE) || !(pp.mode & (HOSTED|RELAX)))
9674887Schin 						error(m, "%s in character constant", pptokchr(c));
9684887Schin 					break;
9694887Schin 				case '>':
9704887Schin 					error(m, "%s in header constant", pptokchr(c));
9714887Schin 					break;
9724887Schin 				default:
9734887Schin 					error(m, "%s in %c quote", pptokchr(c), quot);
9744887Schin 					break;
9754887Schin 				}
9764887Schin #if !CPP
9774887Schin 				if (!DOSTRIP())
9784887Schin #endif
9794887Schin 				PUTCHR(quot);
9804887Schin 			}
9814887Schin 			if (c == '\n')
9824887Schin 			{
9834887Schin 				UNGETCHR(c);
9844887Schin 				c = quot;
9854887Schin 			}
9864887Schin 		}
9874887Schin 		else if (st & (SQUOTE|QUOTE))
9884887Schin 		{
9894887Schin 			if (!(st & ESCAPE))
9904887Schin 			{
9914887Schin 				st |= ESCAPE;
9924887Schin 				quotquot = c;
9934887Schin 			}
9944887Schin 			else if (c == quotquot) st &= ~ESCAPE;
9954887Schin 			PUTCHR('\\');
9964887Schin 			PUTCHR(c);
9974887Schin 			bp = ip;
9984887Schin 			goto fsm_get;
9994887Schin 		}
10004887Schin #if CPP
10014887Schin 		else PUTCHR(c);
10024887Schin #else
10034887Schin 		else if (!DOSTRIP()) PUTCHR(c);
10044887Schin #endif
10054887Schin #if CATSTRINGS
10064887Schin #if CPP
10074887Schin 		if (c == '"' && !(st & (COLLECTING|NOTEXT|PASSTHROUGH|SKIPCONTROL)) && (pp.mode & CATLITERAL))
10084887Schin #else
10094887Schin 		if (c == '"' && pp.level == 1 && !(st & (COLLECTING|JOINING|NOTEXT|SKIPCONTROL)) && (pp.mode & CATLITERAL))
10104887Schin #endif
10114887Schin 		{
10124887Schin 			char*	pptoken;
10134887Schin 			long	ppstate;
10144887Schin 
10154887Schin 			pptoken = pp.token;
10164887Schin 			pp.token = pp.catbuf;
10174887Schin 			*pp.token++ = 0;
10184887Schin 			ppstate = (st & STRIP);
10194887Schin 			if (DOSTRIP())
10204887Schin 				ppstate |= ADD|QUOTE;
10214887Schin 			st |= JOINING;
10224887Schin 			st &= ~(NEWLINE|STRIP);
10234887Schin 
10244887Schin 			/*
10254887Schin 			 * revert to the top level since string
10264887Schin 			 * concatenation crosses file boundaries
10274887Schin 			 * (allowing intervening directives)
10284887Schin 			 */
10294887Schin 
10304887Schin 			pp.level = 0;
10314887Schin 			SYNCIN();
10324887Schin 			m = n = 0;
10334887Schin 			for (;;)
10344887Schin 			{
10354887Schin 				switch (c = pplex())
10364887Schin 				{
10374887Schin 				case '\n':
10384887Schin 					m++;
10394887Schin 					continue;
10404887Schin 				case ' ':
10414887Schin 					*pp.catbuf = ' ';
10424887Schin 					continue;
10434887Schin 				case T_WSTRING:
10444887Schin #if !CPP
10454887Schin 					qual = N_WIDE;
10464887Schin #endif
10474887Schin 					if (ppstate & ADD)
10484887Schin 						ppstate &= ~ADD;
10494887Schin 					else if (m == n || !(st & SPACEOUT))
10504887Schin 						op--;
10514887Schin 					else
10524887Schin 					{
10534887Schin 						n = m;
10544887Schin 						*(op - 1) = '\\';
10554887Schin 						*op++ = '\n';
10564887Schin 					}
10574887Schin 					STRCOPY(op, pp.token + 2 + (*pp.token == ' '), s);
10584887Schin 					continue;
10594887Schin 				case T_STRING:
10604887Schin 					if (ppstate & ADD)
10614887Schin 						ppstate &= ~ADD;
10624887Schin 					else if (m == n || !(st & SPACEOUT))
10634887Schin 						op--;
10644887Schin 					else
10654887Schin 					{
10664887Schin 						n = m;
10674887Schin 						*(op - 1) = '\\';
10684887Schin 						*op++ = '\n';
10694887Schin 					}
10704887Schin 					STRCOPY(op, pp.token + 1 + (*pp.token == ' '), s);
10714887Schin 					continue;
10724887Schin 				case 0:
10734887Schin 					m = error_info.line ? (error_info.line - 1) : 0;
10744887Schin 					*pp.token = 0;
10754887Schin 					/*FALLTHROUGH*/
10764887Schin 				default:
10774887Schin 					if (m)
10784887Schin 					{
10794887Schin 						if (--m)
10804887Schin 						{
10814887Schin 							pp.state |= HIDDEN|SYNCLINE;
10824887Schin 							pp.hidden += m;
10834887Schin 						}
10844887Schin #if COMPATIBLE
10854887Schin 						if ((st & COMPATIBILITY) && c == '#' && *(pp.token - 1))
10864887Schin 						{
10874887Schin 							*(pp.token + 3) = *(pp.token + 2);
10884887Schin 							*(pp.token + 2) = *(pp.token + 1);
10894887Schin 							*(pp.token + 1) = *pp.token;
10904887Schin 							*pp.token = *(pp.token - 1);
10914887Schin 						}
10924887Schin 						error_info.line--;
10934887Schin 						*--pp.token = '\n';
10944887Schin #endif
10954887Schin 					}
10964887Schin 					else if (*(pp.token - 1))
10974887Schin 						pp.token--;
10984887Schin 					if (ppisidig(*pp.token))
10994887Schin 						*op++ = ' ';
11004887Schin 					if (pp.in->type == IN_MACRO && (s = strchr(pp.token, MARK)) && !*(s + 1))
11014887Schin 					{
11024887Schin 						*(s + 1) = MARK;
11034887Schin 						*(s + 2) = 0;
11044887Schin 					}
11054887Schin 					PUSH_STRING(pp.token);
11064887Schin 					pp.state &= ~(JOINING|NEWLINE);
11074887Schin 					pp.state |= ppstate & ~(ADD|QUOTE);
11084887Schin 					if ((ppstate & (ADD|QUOTE)) == QUOTE)
11094887Schin 						op--;
11104887Schin 					break;
11114887Schin 				}
11124887Schin 				break;
11134887Schin 			}
11144887Schin 			pp.token = pptoken;
11154887Schin 			CACHEIN();
11164887Schin 			pp.level = 1;
11174887Schin #if !CPP
11184887Schin 			c = T_STRING | qual;
11194887Schin 			break;
11204887Schin #endif
11214887Schin 		}
11224887Schin #endif
11234887Schin #if CPP
11244887Schin 		if (n && !(st & (PASSTHROUGH|SKIPCONTROL|NOTEXT)) && c == '\'' && (op - tp) <= 2 && !(pp.mode & (HOSTED|RELAX)))
11254887Schin 			error(1, "empty character constant");
11268462SApril.Chin@Sun.COM 		if (pp.option & PRESERVE)
11278462SApril.Chin@Sun.COM 			st &= ~ESCAPE;
11288462SApril.Chin@Sun.COM 		else
11298462SApril.Chin@Sun.COM 			st &= ~(ESCAPE|NEWLINE);
11304887Schin 		pp.in->flags |= IN_tokens;
11314887Schin 		count(token);
11324887Schin 		goto fsm_start;
11334887Schin #else
11344887Schin 		st &= ~ESCAPE;
11354887Schin 		switch (quot)
11364887Schin 		{
11374887Schin 		case '\'':
11384887Schin 			if (n && !(st & NOTEXT) && (op - tp) <= (DOSTRIP() ? 0 : 2) && !(pp.mode & (HOSTED|RELAX)))
11394887Schin 				error(1, "empty character constant");
11404887Schin 			c = T_CHARCONST | qual;
11414887Schin 			break;
11424887Schin 		case '>':
11434887Schin 			c = T_HEADER;
11444887Schin 			break;
11454887Schin 		default:
11464887Schin 			if (c == quot)
11474887Schin 				c = T_STRING | qual;
11484887Schin 			break;
11494887Schin 		}
11504887Schin 		break;
11514887Schin #endif
11524887Schin 
11534887Schin 	case S_LITESC:
11544887Schin 		if (st & (COLLECTING|DIRECTIVE|QUOTE|SQUOTE))
11554887Schin 		{
11564887Schin 			if (st & ESCAPE)
11574887Schin 			{
11584887Schin 				PUTCHR('\\');
11594887Schin 				if (c == quot) PUTCHR('\\');
11604887Schin 			}
11614887Schin 			PUTCHR(c);
11624887Schin 		}
11634887Schin #if CPP
11644887Schin 		else if (st & PASSTHROUGH) PUTCHR(c);
11654887Schin #endif
11664887Schin 		else if (pp.option & PRESERVE) PUTCHR(c);
11674887Schin 		else switch (c)
11684887Schin 		{
11694887Schin 		case 'b':
11704887Schin 		case 'f':
11714887Schin 		case 'n':
11724887Schin 		case 'r':
11734887Schin 		case 't':
11744887Schin 		case '\\':
11754887Schin 		case '\'':
11764887Schin 		case '"':
11774887Schin 		case '?':
11784887Schin 			PUTCHR(c);
11794887Schin 			break;
11804887Schin #if COMPATIBLE
11814887Schin 		case '8':
11824887Schin 		case '9':
11834887Schin 			if (!(st & COMPATIBILITY)) goto unknown;
11844887Schin 			if (st & STRICT) error(1, "%c: invalid character in octal character escape", c);
11854887Schin 			/*FALLTHROUGH*/
11864887Schin #endif
11874887Schin 		case '0':
11884887Schin 		case '1':
11894887Schin 		case '2':
11904887Schin 		case '3':
11914887Schin 		case '4':
11924887Schin 		case '5':
11934887Schin 		case '6':
11944887Schin 		case '7':
11954887Schin 			n = c - '0';
11964887Schin 			for (m = 0; m < 2; m++)
11974887Schin 			{
11984887Schin 				GET(c, c, tp, xp);
11994887Schin 				switch (c)
12004887Schin 				{
12014887Schin #if COMPATIBLE
12024887Schin 				case '8':
12034887Schin 				case '9':
12044887Schin 					if (!(st & COMPATIBILITY))
12054887Schin 					{
12064887Schin 						UNGETCHR(c);
12074887Schin 						break;
12084887Schin 					}
12094887Schin 					if (st & STRICT) error(1, "%c: invalid character in octal character escape", c);
12104887Schin 					/*FALLTHROUGH*/
12114887Schin #endif
12124887Schin 				case '0':
12134887Schin 				case '1':
12144887Schin 				case '2':
12154887Schin 				case '3':
12164887Schin 				case '4':
12174887Schin 				case '5':
12184887Schin 				case '6':
12194887Schin 				case '7':
12204887Schin 					n = (n << 3) + c - '0';
12214887Schin 					continue;
12224887Schin 				default:
12234887Schin 					UNGETCHR(c);
12244887Schin 					break;
12254887Schin 				}
12264887Schin 				break;
12274887Schin 			}
12284887Schin 			if (n & ~0777) error(1, "octal character constant too large");
12294887Schin 			goto octal;
12304887Schin 		case 'a':
12314887Schin 			if (pp.option & MODERN)
12324887Schin 			{
12334887Schin 				PUTCHR(c);
12344887Schin 				break;
12354887Schin 			}
12364887Schin #if COMPATIBLE
12374887Schin 			if (st & COMPATIBILITY) goto unknown;
12384887Schin #endif
12394887Schin 			n = CC_bel;
12404887Schin 			goto octal;
12414887Schin 		case 'v':
12424887Schin 			if (pp.option & MODERN)
12434887Schin 			{
12444887Schin 				PUTCHR(c);
12454887Schin 				break;
12464887Schin 			}
12474887Schin 			n = CC_vt;
12484887Schin 			goto octal;
12494887Schin 		case 'E':
12504887Schin 			if (st & (COMPATIBILITY|STRICT)) goto unknown;
12514887Schin 			n = CC_esc;
12524887Schin 			goto octal;
12534887Schin 		case 'x':
12544887Schin #if COMPATIBLE
12554887Schin 			if (st & COMPATIBILITY) goto unknown;
12564887Schin #endif
12574887Schin 			n = 0;
12584887Schin 			for (m = 0; m < 3; m++)
12594887Schin 			{
12604887Schin 				GET(c, c, tp, xp);
12614887Schin 				switch (c)
12624887Schin 				{
12634887Schin 				case '0':
12644887Schin 				case '1':
12654887Schin 				case '2':
12664887Schin 				case '3':
12674887Schin 				case '4':
12684887Schin 				case '5':
12694887Schin 				case '6':
12704887Schin 				case '7':
12714887Schin 				case '8':
12724887Schin 				case '9':
12734887Schin 					n = (n << 4) + c - '0';
12744887Schin 					continue;
12754887Schin 				case 'a':
12764887Schin 				case 'b':
12774887Schin 				case 'c':
12784887Schin 				case 'd':
12794887Schin 				case 'e':
12804887Schin 				case 'f':
12814887Schin 					n = (n << 4) + c - 'a' + 10;
12824887Schin 					continue;
12834887Schin 				case 'A':
12844887Schin 				case 'B':
12854887Schin 				case 'C':
12864887Schin 				case 'D':
12874887Schin 				case 'E':
12884887Schin 				case 'F':
12894887Schin 					n = (n << 4) + c - 'A' + 10;
12904887Schin 					continue;
12914887Schin 				default:
12924887Schin 					if (!m) error(1, "\\x%c: invalid character in hexadecimal character constant", c);
12934887Schin 					UNGETCHR(c);
12944887Schin 					break;
12954887Schin 				}
12964887Schin 				break;
12974887Schin 			}
12984887Schin 			if (n & ~0777) error(1, "hexadecimal character constant too large");
12994887Schin 		octal:
13004887Schin 			PUTCHR(((n >> 6) & 07) + '0');
13014887Schin 			PUTCHR(((n >> 3) & 07) + '0');
13024887Schin 			PUTCHR((n & 07) + '0');
13034887Schin 			break;
13044887Schin 		default:
13054887Schin 		unknown:
13064887Schin 			if (st & (STRICT|WARN)) error(1, "\\%c: non-standard character constant", c);
13074887Schin 			PUTCHR(c);
13084887Schin 			break;
13094887Schin 		}
13104887Schin 		state = LIT1;
13114887Schin 		goto fsm_begin;
13124887Schin 
13134887Schin 	case S_MACRO:
13144887Schin 		BACKIN();
13154887Schin #if CPP
13164887Schin 		if (st & (DISABLE|SKIPCONTROL|SKIPMACRO))
13174887Schin 		{
13184887Schin 			if (st & SKIPMACRO)
13194887Schin 				pp.mode |= MARKMACRO;
13204887Schin 			st &= ~(NEWLINE|SKIPMACRO);
13214887Schin 			pp.in->flags |= IN_tokens;
13224887Schin 			count(token);
13234887Schin 			goto fsm_start;
13244887Schin 		}
13254887Schin 		count(candidate);
13264887Schin 		SETCHR(0);
13274887Schin 		switch (state = INDEX(rp))
13284887Schin 		{
13294887Schin 		case HIT0:
13304887Schin 			tp = op - 1;
13314887Schin 			break;
13324887Schin 		case HITN:
13334887Schin 			bp = tp;
13344887Schin 			tp = op - ((pp.truncate && pp.truncate < (HITN - HIT0)) ? (pp.truncate - 1) : (HITN - HIT0));
13354887Schin 			while (tp > bp && ppisidig(*(tp - 1))) tp--;
13364887Schin 			break;
13374887Schin 		default:
13384887Schin 			bp = tp;
13394887Schin 			if ((tp = op - (state - HIT0)) > bp && *(tp - 1) == 'L') tp--;
13404887Schin 			break;
13414887Schin 		}
13424887Schin 		if (sym = ppsymref(pp.symtab, tp))
13434887Schin 		{
13444887Schin 			SYNCIN();
13454887Schin 			n = ppcall(sym, 0);
13464887Schin 			CACHEIN();
13474887Schin 			if (n >= 0)
13484887Schin 			{
13494887Schin 				BACKOUT();
13504887Schin 				if (!n)
13514887Schin 				{
13524887Schin 					if (sp) op = sp;
13534887Schin 					else
13544887Schin 					{
13554887Schin 						s = ip;
13564887Schin 						ip = sym->macro->value;
13574887Schin 						c = sym->macro->size;
13584887Schin 						while (c > 0)
13594887Schin 						{
13604887Schin 							if (op + c < xp + PPBUFSIZ) n = c;
13614887Schin 							else n = xp + PPBUFSIZ - op;
13624887Schin 							MEMCPY(op, ip, n);
13634887Schin 							c -= n;
13644887Schin 							PPCHECKOUT();
13654887Schin 						}
13664887Schin 						ip = s;
13674887Schin 					}
13684887Schin 				}
13694887Schin 				else if ((sym->flags & SYM_MULTILINE) && pp.linesync)
13704887Schin 				{
13714887Schin 					SYNCOUT();
13724887Schin 					if (!(state & NEWLINE))
13734887Schin 						ppputchar('\n');
13744887Schin 					(*pp.linesync)(error_info.line, error_info.file);
13754887Schin 					CACHEOUT();
13764887Schin 				}
13774887Schin 			}
13784887Schin 		}
13794887Schin 		pp.in->flags |= IN_tokens;
13804887Schin 		goto fsm_start;
13814887Schin #else
13824887Schin 		if (st & (COLLECTING|DEFINITION|DISABLE|SKIPCONTROL|SKIPMACRO))
13834887Schin 		{
13844887Schin 			if (st & SKIPMACRO)
13854887Schin 				pp.mode |= MARKMACRO;
13864887Schin 			st &= ~(NEWLINE|NOEXPAND|SKIPMACRO);
13874887Schin 			c = T_ID;
13884887Schin 			if (pp.level == 1)
13894887Schin 			{
13904887Schin 				pp.in->flags |= IN_tokens;
13914887Schin 				if (st & NOTEXT)
13924887Schin 				{
13934887Schin 					BACKOUT();
13944887Schin 					goto fsm_top;
13954887Schin 				}
13964887Schin 				if (st & COMPILE)
13974887Schin 				{
13984887Schin 					SETCHR(0);
13994887Schin 					if (pp.truncate && (op - tp) > pp.truncate) tp[pp.truncate] = 0;
14004887Schin 					sym = (pp.option & NOHASH) ? ppsymref(pp.symtab, tp) : ppsymset(pp.symtab, tp);
14014887Schin  fsm_noise:
14024887Schin 					if (pp.symbol = sym)
14034887Schin 					{
14044887Schin 						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)))
14054887Schin 						{
14064887Schin 							c = ((struct ppsymkey*)sym)->lex;
14074887Schin 							/*UNDENT*/
14084887Schin 
14094887Schin #define ADVANCE()	do{if(pp.toknxt<op)pp.token=pp.toknxt;}while(0)
14104887Schin 
14114887Schin #define NOISE_BRACE		01
14124887Schin #define NOISE_NOSPACEOUT	02
14134887Schin #define NOISE_PAREN		04
14144887Schin 
14154887Schin 	if ((pp.option & NOISE) && ppisnoise(c))
14164887Schin 	{
14174887Schin 		if (c != T_NOISE)
14184887Schin 		{
14194887Schin 			int		p;
14204887Schin 			int		f;
14214887Schin 			char*		pptoken;
14224887Schin 			PPCOMMENT	ppcomment;
14234887Schin 
14244887Schin 			SYNCIN();
14254887Schin 			pp.toknxt = op;
14264887Schin 			f = 0;
14274887Schin 			if (!(pp.state & SPACEOUT))
14284887Schin 			{
14294887Schin 				pp.state |= SPACEOUT;
14304887Schin 				f |= NOISE_NOSPACEOUT;
14314887Schin 			}
14324887Schin 			ppcomment = pp.comment;
14334887Schin 			pp.comment = 0;
14344887Schin 			op = (pptoken = tp) + MAXTOKEN;
14354887Schin 			switch (c)
14364887Schin 			{
14374887Schin 			case T_X_GROUP:
14384887Schin 				m = p = 0;
14394887Schin 				quot = 1;
14404887Schin 				for (;;)
14414887Schin 				{
14424887Schin 					ADVANCE();
14434887Schin 					switch (c = pplex())
14444887Schin 					{
14454887Schin 					case '(':
14464887Schin 					case '{':
14474887Schin 						if (!p)
14484887Schin 						{
14494887Schin 							if (c == '(')
14504887Schin 							{
14514887Schin 								if (f & NOISE_PAREN)
14524887Schin 								{
14534887Schin 									ungetchr(c);
14544887Schin 									*--pp.toknxt = 0;
14554887Schin 									break;
14564887Schin 								}
14574887Schin 								f |= NOISE_PAREN;
14584887Schin 								p = ')';
14594887Schin 							}
14604887Schin 							else
14614887Schin 							{
14624887Schin 								f |= NOISE_BRACE|NOISE_PAREN;
14634887Schin 								p = '}';
14644887Schin 							}
14654887Schin 							n = 1;
14664887Schin 							m = c;
14674887Schin 						}
14684887Schin 						else if (c == m) n++;
14694887Schin 						quot = 0;
14704887Schin 						continue;
14714887Schin 					case ')':
14724887Schin 					case '}':
14734887Schin 						if (c == p && --n <= 0)
14744887Schin 						{
14754887Schin 							if (c == '}') break;
14764887Schin 							m = '\n';
14774887Schin 							p = 0;
14784887Schin 						}
14794887Schin 						quot = 0;
14804887Schin 						continue;
14814887Schin 					case ' ':
14824887Schin 						continue;
14834887Schin 					case '\n':
14844887Schin 						error_info.line++;
14854887Schin 						if (!m) m = '\n';
14864887Schin 						continue;
14874887Schin 					case 0:
14884887Schin 						break;
14894887Schin 					case T_ID:
14904887Schin 						if (quot) continue;
14914887Schin 						/*FALLTHROUGH*/
14924887Schin 					default:
14934887Schin 						if (m == '\n')
14944887Schin 						{
14954887Schin 							/*
14964887Schin 							 * NOTE: token expanded again
14974887Schin 							 */
14984887Schin 
14994887Schin 							s = pp.toknxt;
15004887Schin 							while (s > pp.token) ungetchr(*--s);
15014887Schin 							*(pp.toknxt = s) = 0;
15024887Schin 							break;
15034887Schin 						}
15044887Schin 						continue;
15054887Schin 					}
15064887Schin 					break;
15074887Schin 				}
15084887Schin 				break;
15094887Schin 			case T_X_LINE:
15104887Schin 				for (;;)
15114887Schin 				{
15124887Schin 					ADVANCE();
15134887Schin 					switch (pplex())
15144887Schin 					{
15154887Schin 					case 0:
15164887Schin 						break;
15174887Schin 					case '\n':
15184887Schin 						error_info.line++;
15194887Schin 						break;
15204887Schin 					default:
15214887Schin 						continue;
15224887Schin 					}
15234887Schin 					break;
15244887Schin 				}
15254887Schin 				break;
15264887Schin 			case T_X_STATEMENT:
15274887Schin 				for (;;)
15284887Schin 				{
15294887Schin 					ADVANCE();
15304887Schin 					switch (pplex())
15314887Schin 					{
15324887Schin 					case 0:
15334887Schin 						break;
15344887Schin 					case ';':
15354887Schin 						ungetchr(';');
15364887Schin 						*(pp.toknxt = pp.token) = 0;
15374887Schin 						break;
15384887Schin 					default:
15394887Schin 						continue;
15404887Schin 					}
15414887Schin 					break;
15424887Schin 				}
15434887Schin 				break;
15444887Schin 			}
15454887Schin 			pp.comment = ppcomment;
15464887Schin 			if (f & NOISE_NOSPACEOUT)
15474887Schin 				pp.state &= ~SPACEOUT;
15484887Schin 			CACHEIN();
15494887Schin 			tp = pptoken;
15504887Schin 			op = pp.toknxt;
15514887Schin 			c = T_NOISES;
15524887Schin 		}
15534887Schin 		if (pp.option & NOISEFILTER)
15544887Schin 		{
15554887Schin 			BACKOUT();
15564887Schin 			goto fsm_top;
15574887Schin 		}
15584887Schin 	}
15594887Schin 
15604887Schin 							/*INDENT*/
15614887Schin 						}
15624887Schin 						else if ((pp.option & NOISE) && c == T_ID && strneq(tp, "__builtin_", 10))
15634887Schin 						{
15644887Schin 							hashlook(pp.symtab, tp, HASH_DELETE, NiL);
15654887Schin 							pp.symbol = sym = (struct ppsymbol*)ppkeyset(pp.symtab, tp);
15664887Schin 							sym->flags |= SYM_KEYWORD;
15674887Schin 							c = ((struct ppsymkey*)sym)->lex = T_BUILTIN;
15684887Schin 						}
15694887Schin 					}
15704887Schin 				}
15714887Schin 				goto fsm_symbol;
15724887Schin 			}
15734887Schin 			goto fsm_check;
15744887Schin 		}
15754887Schin 		if (pp.level == 1)
15764887Schin 		{
15774887Schin 			st &= ~(NEWLINE|PASSEOF);
15784887Schin 			pp.in->flags |= IN_tokens;
15794887Schin 		}
15804887Schin 		else st &= ~PASSEOF;
15814887Schin 		count(candidate);
15824887Schin 		SETCHR(0);
15834887Schin 		if (sym = ppsymref(pp.symtab, tp))
15844887Schin 		{
15854887Schin 			SYNCIN();
15864887Schin 			c = ppcall(sym, 1);
15874887Schin 			CACHEIN();
15884887Schin 			if (c >= 0)
15894887Schin 			{
15904887Schin 				BACKOUT();
15914887Schin 				if ((sym->flags & SYM_MULTILINE) && pp.linesync)
15924887Schin 				{
15934887Schin 					SYNCOUT();
15944887Schin 					(*pp.linesync)(error_info.line, error_info.file);
15954887Schin 					CACHEOUT();
15964887Schin 				}
15974887Schin 				goto fsm_top;
15984887Schin 			}
15994887Schin 		}
16004887Schin 		c = T_ID;
16014887Schin 		if (pp.level == 1)
16024887Schin 		{
16034887Schin 			if (st & NOTEXT)
16044887Schin 			{
16054887Schin 				BACKOUT();
16064887Schin 				goto fsm_top;
16074887Schin 			}
16084887Schin 			if (st & COMPILE)
16094887Schin 			{
16104887Schin 				if (pp.truncate && (op - tp) > pp.truncate)
16114887Schin 				{
16124887Schin 					tp[pp.truncate] = 0;
16134887Schin 					sym = 0;
16144887Schin 				}
16154887Schin 				if (!sym)
16164887Schin 				{
16174887Schin 					if (!(pp.option & NOHASH)) sym = ppsymset(pp.symtab, tp);
16184887Schin 					else if (!(sym = ppsymref(pp.symtab, tp))) goto fsm_symbol;
16194887Schin 				}
16204887Schin 				goto fsm_noise;
16214887Schin 			}
16224887Schin 			goto fsm_symbol;
16234887Schin 		}
16244887Schin 		goto fsm_check;
16254887Schin #endif
16264887Schin 
16274887Schin 	case S_SHARP:
16284887Schin 		if (c == '(')
16294887Schin 		{
16304887Schin 			pp.in->flags |= IN_tokens;
16314887Schin 			if ((st & STRICT) && pp.in->type != IN_MACRO && pp.in->type != IN_MULTILINE)
16324887Schin 			{
16334887Schin 				if (!(pp.mode & HOSTED)) error(1, "non-standard reference to #(...)");
16344887Schin 				if (st & STRICT)
16354887Schin 				{
16364887Schin 					PUTCHR(c);
16374887Schin #if CPP
16384887Schin 					st &= ~NEWLINE;
16394887Schin 					count(token);
16404887Schin 					goto fsm_start;
16414887Schin #else
16424887Schin 					break;
16434887Schin #endif
16444887Schin 				}
16454887Schin 			}
16464887Schin 			if (st & (COLLECTING|DEFINITION|DISABLE|SKIPCONTROL))
16474887Schin 			{
16484887Schin 				PUTCHR(c);
16494887Schin #if CPP
16504887Schin 				st &= ~NEWLINE;
16514887Schin 				count(token);
16524887Schin 				goto fsm_start;
16534887Schin #else
16544887Schin 				st &= ~NOEXPAND;
16554887Schin 				break;
16564887Schin #endif
16574887Schin 			}
16584887Schin 			op--;
16594887Schin 			SYNC();
16604887Schin 			ppbuiltin();
16614887Schin 			CACHE();
16624887Schin #if CPP
16634887Schin 			count(token);
16644887Schin 			goto fsm_start;
16654887Schin #else
16664887Schin 			goto fsm_top;
16674887Schin #endif
16684887Schin 		}
16694887Schin 		BACKIN();
16704887Schin #if CPP
16714887Schin 		if (!(st & NEWLINE) || !(pp.in->type & IN_TOP))
16724887Schin 		{
16734887Schin  fsm_nondirective:
16744887Schin 			st &= ~NEWLINE;
16754887Schin 			pp.in->flags |= IN_tokens;
16764887Schin 			count(token);
16774887Schin 			goto fsm_start;
16784887Schin 		}
16794887Schin 		if (*(s = tp) != '#')
16804887Schin 		{
16814887Schin #if COMPATIBLE
16824887Schin 			if ((st & (COMPATIBILITY|TRANSITION)) == COMPATIBILITY) goto fsm_nondirective;
16834887Schin #endif
16844887Schin 			while (*s == ' ' || *s == '\t') s++;
16854887Schin 			if (*s != '#') goto fsm_nondirective;
16864887Schin 		}
16874887Schin 		BACKOUT();
16884887Schin #else
16894887Schin 		if (!(st & NEWLINE) || (st & DEFINITION) || !(pp.in->type & IN_TOP))
16904887Schin 		{
16914887Schin 			if (c == '#')
16924887Schin 			{
16934887Schin 				SKIPIN();
16944887Schin 				if (!(st & DEFINITION))
16954887Schin 					PUTCHR(c);
16964887Schin 				c = T_TOKCAT;
16974887Schin 			}
16984887Schin 			else if (pp.level == 1 && !(st & (JOINING|SPACEOUT)) && !(pp.option & PRESERVE))
16994887Schin 			{
17004887Schin 				char*		pptoken;
17014887Schin 				char*		oop;
17024887Schin 				PPCOMMENT	ppcomment;
17034887Schin 
17044887Schin 				SYNCIN();
17054887Schin 				pp.toknxt = oop = op;
17064887Schin 				pp.state |= SPACEOUT;
17074887Schin 				ppcomment = pp.comment;
17084887Schin 				pp.comment = 0;
17094887Schin 				op = (pptoken = tp) + MAXTOKEN;
17104887Schin 				for (;;)
17114887Schin 				{
17124887Schin 					ADVANCE();
17134887Schin 					switch (pplex())
17144887Schin 					{
17154887Schin 					case 0:
17164887Schin 						break;
17174887Schin 					case '\n':
17184887Schin 						error_info.line++;
17194887Schin 						break;
17204887Schin 					default:
17214887Schin 						continue;
17224887Schin 					}
17234887Schin 					break;
17244887Schin 				}
17254887Schin 				pp.comment = ppcomment;
17264887Schin 				pp.state &= ~SPACEOUT;
17274887Schin 				CACHEIN();
17284887Schin 				tp = pptoken;
17294887Schin 				*--op = 0;
17304887Schin 				op = oop;
17314887Schin 				if (pp.pragma && !(st & NOTEXT))
17324887Schin 				{
17334887Schin 					*s = 0;
17344887Schin 					SYNC();
17354887Schin 					(*pp.pragma)(NiL, NiL, NiL, tp, 1);
17364887Schin 					CACHE();
17374887Schin 				}
17384887Schin 				if (!c) BACKIN();
17394887Schin 				goto fsm_top;
17404887Schin 			}
17414887Schin 			else c = '#';
17424887Schin 			break;
17434887Schin 		}
17444887Schin 		if ((st & (COLLECTING|STRICT)) == (COLLECTING|STRICT))
17454887Schin 			error(1, "directives in macro call arguments are not portable");
17464887Schin #endif
17474887Schin 		if (c == '#' && pp.in->type == IN_RESCAN)
17484887Schin 		{
17494887Schin 			/*
17504887Schin 			 * pass line to pp.pragma VERBATIM
17514887Schin 			 */
17524887Schin 
17534887Schin 			SKIPIN();
17544887Schin 			s = pp.valbuf;
17554887Schin 			while ((c = GETCHR()) && c != '\n')
17564887Schin 				if ((*s++ = c) == MARK) SKIPIN();
17574887Schin 			if (pp.pragma && !(st & NOTEXT))
17584887Schin 			{
17594887Schin 				*s = 0;
17604887Schin 				SYNC();
17614887Schin 				(*pp.pragma)(NiL, NiL, NiL, pp.valbuf, 1);
17624887Schin 				CACHE();
17634887Schin 			}
17644887Schin 			if (!c) BACKIN();
17654887Schin #if CPP
17664887Schin 			goto fsm_start;
17674887Schin #else
17684887Schin 			goto fsm_top;
17694887Schin #endif
17704887Schin 		}
17714887Schin 		SYNC();
17724887Schin 		ppcontrol();
17734887Schin 		CACHE();
17744887Schin #if CPP
17754887Schin 		if (st & (NOTEXT|SKIPCONTROL))
17764887Schin 		{
17774887Schin 			if (!sp)
17784887Schin 			{
17794887Schin 				PPCHECKOUTTP();
17804887Schin 				sp = tp;
17814887Schin 			}
17824887Schin 		}
17834887Schin 		else if (sp)
17844887Schin 		{
17854887Schin 			tp = op = sp;
17864887Schin 			sp = 0;
17874887Schin 		}
17884887Schin 		goto fsm_start;
17894887Schin #else
17904887Schin 		goto fsm_top;
17914887Schin #endif
17924887Schin 
17934887Schin 	case S_NL:
17944887Schin #if CPP
17958462SApril.Chin@Sun.COM 		if (op == tp && !(st & JOINING) && pp.in->type == IN_FILE && !(pp.option & PRESERVE))
17964887Schin 		{
17974887Schin 			st |= NEWLINE|HIDDEN;
17984887Schin 			pp.hidden++;
17994887Schin 			error_info.line++;
18004887Schin 			goto fsm_start;
18014887Schin 		}
18024887Schin #endif
18034887Schin  fsm_newline:
18044887Schin #if CPP
18054887Schin 		if (sp)
18064887Schin 			op = sp;
18074887Schin 		else if (!(pp.in->flags & IN_noguard))
18084887Schin 		{
18094887Schin 			while (tp < op)
18104887Schin 				if ((c = *tp++) != ' ' && c != '\t')
18114887Schin 				{
18124887Schin 					pp.in->flags |= IN_tokens;
18134887Schin 					break;
18144887Schin 				}
18154887Schin 			c = '\n';
18164887Schin 		}
18174887Schin 		st |= NEWLINE;
18184887Schin 		error_info.line++;
18194887Schin 		if (*ip == '\n' && *(ip + 1) != '\n' && !pp.macref && !(st & (ADD|HIDDEN)))
18204887Schin 		{
18214887Schin 			ip++;
18224887Schin 			PUTCHR('\n');
18234887Schin 			error_info.line++;
18244887Schin 		}
18254887Schin 		if ((st & NOTEXT) && ((pp.mode & FILEDEPS) || (pp.option & (DEFINITIONS|PREDEFINITIONS))))
18264887Schin 			BACKOUT();
18274887Schin 		else
18284887Schin 		{
18294887Schin 			debug((-5, "token[%d] %03o = %s [line=%d]", pp.level, c, pptokchr(c), error_info.line));
18304887Schin 			PUTCHR('\n');
18314887Schin 			PPSYNCLINE();
18324887Schin 			if (sp)
18334887Schin 			{
18344887Schin 				PPCHECKOUT();
18354887Schin 				sp = op;
18364887Schin 			}
18374887Schin 		}
18384887Schin 		goto fsm_start;
18394887Schin #else
18404887Schin 		st |= NEWLINE;
18414887Schin 		if (pp.level == 1)
18424887Schin 		{
18434887Schin 			error_info.line++;
18444887Schin 			if (!(st & (JOINING|SPACEOUT)))
18454887Schin 			{
18464887Schin 				debug((-5, "token[%d] %03o = %s [line=%d]", pp.level, c, pptokchr(c), error_info.line));
18474887Schin 				BACKOUT();
18484887Schin 				goto fsm_top;
18494887Schin 			}
18504887Schin 		}
18514887Schin 		BACKOUT();
18524887Schin 		if (st & SKIPCONTROL)
18534887Schin 		{
18544887Schin 			error_info.line++;
18554887Schin 			st |= HIDDEN;
18564887Schin 			pp.hidden++;
18574887Schin 			goto fsm_start;
18584887Schin 		}
18594887Schin 		PUTCHR(c = '\n');
18604887Schin 		goto fsm_return;
18614887Schin #endif
18624887Schin 
18634887Schin #if !CPP
18644887Schin 	case S_TOK:
18654887Schin 		PUTCHR(c);
18664887Schin 		c = TYPE(state) | qual;
18674887Schin 		break;
18684887Schin 
18694887Schin 	case S_TOKB:
18704887Schin 		BACKIN();
18714887Schin 		c = TYPE(state) | qual;
18724887Schin 		break;
18734887Schin #endif
18744887Schin 
18754887Schin 	case S_VS:
18764887Schin 		PUTCHR(c);
18774887Schin #if !CPP
18784887Schin 		if (st & NOVERTICAL)
18794887Schin 		{
18804887Schin 			error(1, "%s invalid in directives", pptokchr(c));
18814887Schin 			st &= ~NOVERTICAL;
18824887Schin 		}
18834887Schin #endif
18844887Schin #if COMPATIBLE
18854887Schin 		if (st & COMPATIBILITY) st |= NEWLINE;
18864887Schin #endif
18874887Schin #if CPP
18884887Schin 		if (!(pp.in->flags & IN_noguard))
18894887Schin 			while (tp < op)
18904887Schin 				if ((c = *tp++) != ' ' && c != '\t')
18914887Schin 				{
18924887Schin 					pp.in->flags |= IN_tokens;
18934887Schin 					break;
18944887Schin 				}
18954887Schin 		goto fsm_start;
18964887Schin #else
18974887Schin 		bp = ip;
18984887Schin 		rp = fsm[WS1];
18994887Schin 		goto fsm_get;
19004887Schin #endif
19014887Schin 
19024887Schin #if !CPP
19034887Schin 	case S_WS:
19044887Schin #if COMPATIBLE
19054887Schin 		if ((st & (COMPATIBILITY|TRANSITION)) == COMPATIBILITY) st &= ~NEWLINE;
19064887Schin #endif
19074887Schin 		if (pp.level == 1)
19084887Schin 		{
19094887Schin 			if ((st & (COMPATIBILITY|SPACEOUT)) && !(st & TRANSITION))
19104887Schin 			{
19114887Schin 				if (st & (COMPILE|NOTEXT))
19124887Schin 				{
19134887Schin #if CATSTRINGS
19144887Schin 					if ((st & (JOINING|NOTEXT|SPACEOUT)) != SPACEOUT)
19154887Schin #else
19164887Schin 					if ((st & (NOTEXT|SPACEOUT)) != SPACEOUT)
19174887Schin #endif
19184887Schin 					{
19194887Schin 						BACKOUT();
19204887Schin 						bp = ip - 1;
19214887Schin 						rp = fsm[START];
19224887Schin 						if (state = rp[c]) goto fsm_next;
19234887Schin 						goto fsm_get;
19244887Schin 					}
19254887Schin 				}
19264887Schin 				else
19274887Schin #if CATSTRINGS
19284887Schin 				if (!(st & JOINING))
19294887Schin #endif
19304887Schin 				{
19314887Schin 					tp = op;
19324887Schin 					bp = ip - 1;
19334887Schin 					rp = fsm[START];
19344887Schin 					if (state = rp[c]) goto fsm_next;
19354887Schin 					goto fsm_get;
19364887Schin 				}
19374887Schin 				BACKIN();
19384887Schin 				c = ' ';
19394887Schin 				goto fsm_return;
19404887Schin 			}
19414887Schin 			BACKOUT();
19424887Schin 			bp = ip - 1;
19434887Schin 			rp = fsm[START];
19444887Schin 			if (state = rp[c]) goto fsm_next;
19454887Schin 			goto fsm_get;
19464887Schin 		}
19474887Schin 		if (st & (NOSPACE|SKIPCONTROL))
19484887Schin 		{
19494887Schin 			BACKOUT();
19504887Schin 			bp = ip - 1;
19514887Schin 			rp = fsm[START];
19524887Schin 			if (state = rp[c]) goto fsm_next;
19534887Schin 			goto fsm_get;
19544887Schin 		}
19554887Schin 		if (c != '\n')
19564887Schin 		{
19574887Schin 			BACKIN();
19584887Schin 			c = ' ';
19594887Schin 		}
19604887Schin 		if (!(pp.option & PRESERVE))
19614887Schin 		{
19624887Schin 			BACKOUT();
19634887Schin 			PUTCHR(c);
19644887Schin 		}
19654887Schin 		goto fsm_return;
19664887Schin #endif
19674887Schin 
19684887Schin 	default:
19694887Schin 		if (state & SPLICE)
19704887Schin 		{
19714887Schin 			switch (c)
19724887Schin 			{
19734887Schin 			case MARK:
19744887Schin 				/*
19754887Schin 				 * internal mark
19764887Schin 				 */
19774887Schin 
19784887Schin 				switch (pp.in->type)
19794887Schin 				{
19804887Schin 				case IN_BUFFER:
19814887Schin 				case IN_FILE:
19824887Schin #if !CPP
19834887Schin 				case IN_INIT:
19844887Schin #if CATSTRINGS
19854887Schin 					if ((st & JOINING) && (!INQUOTE(rp) || quot != '"') || pp.level > 1 && (rp == fsm[START] || INQUOTE(rp)))
19864887Schin #else
19874887Schin 					if (pp.level > 1 && (rp == fsm[START] || INQUOTE(rp)))
19884887Schin #endif
19894887Schin 						PUTCHR(c);
19904887Schin #endif
19914887Schin 					break;
19924887Schin 				default:
19934887Schin 					switch (GETCHR())
19944887Schin 					{
19954887Schin 					case 'A':
19964887Schin 						if (!(st & (DEFINITION|DISABLE)))
19974887Schin 						{
19984887Schin 							c = GETCHR();
19994887Schin 							SYNCIN();
20004887Schin 							if (pp.macp->arg[c - ARGOFFSET][-1])
20014887Schin 								PUSH_EXPAND(pp.macp->arg[c - ARGOFFSET], pp.macp->line);
20024887Schin 							else
20034887Schin 								PUSH_COPY(pp.macp->arg[c - ARGOFFSET], pp.macp->line);
20044887Schin 							CACHEIN();
20054887Schin 							bp = ip;
20064887Schin 							goto fsm_get;
20074887Schin 						}
20084887Schin 						/*FALLTHROUGH*/
20094887Schin 					case 'C':
20104887Schin 						c = GETCHR() - ARGOFFSET;
20114887Schin 						if (!*(s = pp.macp->arg[c]) && (pp.in->symbol->flags & SYM_VARIADIC) && pp.in->symbol->macro->arity == (c + 1))
20124887Schin 						{
20134887Schin 							s = ip - 3;
20144887Schin 							while (--op > tp && --s > bp && ppisidig(*s));
20154887Schin 						}
20164887Schin 						else
20174887Schin 						{
20184887Schin 							SYNCIN();
20194887Schin 							PUSH_COPY(s, pp.macp->line);
20204887Schin 							CACHEIN();
20214887Schin 						}
20224887Schin 						bp = ip;
20234887Schin 						goto fsm_get;
20244887Schin 					case 'F':
20254887Schin 						error_info.file = (char*)strtoul(ip, &s, 16);
20264887Schin 						debug((-6, "actual sync: file = \"%s\"", error_info.file));
20274887Schin 						bp = ip = s + 1;
20284887Schin 						goto fsm_get;
20294887Schin 					case 'L':
20304887Schin 						error_info.line = strtoul(ip, &s, 16);
20314887Schin 						debug((-6, "actual sync: line = %d", error_info.line));
20324887Schin 						bp = ip = s + 1;
20334887Schin 						goto fsm_get;
20344887Schin 					case 'Q':
20354887Schin 						c = GETCHR();
20364887Schin 						SYNCIN();
20374887Schin 						PUSH_QUOTE(pp.macp->arg[c - ARGOFFSET], pp.macp->line);
20384887Schin 						CACHEIN();
2039*10898Sroland.mainz@nrubsig.org 						*(bp = ip - 1) = '"';
20404887Schin 						if (st & (COLLECTING|EOF2NL|JOINING)) rp = fsm[START];
20414887Schin 						if (state = rp[c = '"']) goto fsm_next;
20424887Schin 						goto fsm_get;
20434887Schin 					case 'S':
20444887Schin 						c = GETCHR();
20454887Schin 						SYNCIN();
20464887Schin 						PUSH_SQUOTE(pp.macp->arg[c - ARGOFFSET], pp.macp->line);
20474887Schin 						CACHEIN();
20484887Schin 						bp = ip - 1;
20494887Schin 						if (st & COLLECTING) rp = fsm[START];
20504887Schin 						if (state = rp[c = '\'']) goto fsm_next;
20514887Schin 						goto fsm_get;
20524887Schin 					case 'X':
20534887Schin 						if (pp.in->type != IN_COPY)
20544887Schin 							st |= SKIPMACRO;
20554887Schin 						if (pp.level <= 1)
20564887Schin 						{
20574887Schin 							bp = ip;
20584887Schin 							goto fsm_get;
20594887Schin 						}
20604887Schin 						if (pp.in->type == IN_EXPAND)
20614887Schin 						{
20624887Schin 							st &= ~SKIPMACRO;
20634887Schin 							PUTCHR(c);
20644887Schin 							PUTCHR('X');
20654887Schin 						}
20664887Schin 						c = GETCHR();
20674887Schin 						break;
20684887Schin 					case 0:
20694887Schin 						if ((state &= ~SPLICE) >= TERMINAL) goto fsm_terminal;
20704887Schin 						goto fsm_begin;
20714887Schin 					default:
20724887Schin #if DEBUG
20734887Schin 						error(PANIC, "invalid mark op `%c'", LASTCHR());
20744887Schin 						/*FALLTHROUGH*/
20754887Schin 					case MARK:
20764887Schin #endif
20774887Schin #if CATSTRINGS
20784887Schin 						if ((st & (JOINING|QUOTE)) == JOINING)
20794887Schin 						{
20804887Schin 							if (!INQUOTE(rp))
20814887Schin 								PUTCHR(c);
20824887Schin 						}
20834887Schin 						else
20844887Schin #endif
20854887Schin #if CPP
20864887Schin 						if (rp != fsm[START] && !INQUOTE(rp))
20874887Schin 							UNGETCHR(c);
20884887Schin #else
20894887Schin 						if (rp != fsm[START] && !INQUOTE(rp))
20904887Schin 							UNGETCHR(c);
20914887Schin 						else if (pp.level > 1)
20924887Schin 							PUTCHR(c);
20934887Schin #endif
20944887Schin 						break;
20954887Schin 					}
20964887Schin 					break;
20974887Schin 				}
20984887Schin 				break;
20994887Schin 			case '?':
21004887Schin 				/*
21014887Schin 				 * trigraph
21024887Schin 				 */
21034887Schin 
21044887Schin 				if (pp.in->type == IN_FILE)
21054887Schin 				{
21064887Schin 					GET(c, n, tp, xp);
21074887Schin 					if (n == '?')
21084887Schin 					{
21094887Schin 						GET(c, n, tp, xp);
21104887Schin 						if (c = trigraph[n])
21114887Schin 						{
21124887Schin 							if ((st & WARN) && (st & (COMPATIBILITY|TRANSITION)) && !(pp.mode & HOSTED) && !INCOMMENT(rp))
21134887Schin 								error(1, "trigraph conversion %c%c%c -> %c%s", '?', '?', n, c, (st & TRANSITION) ? "" : " inhibited");
21144887Schin #if COMPATIBLE
21154887Schin 							if ((st & (COMPATIBILITY|TRANSITION)) != COMPATIBILITY)
21164887Schin 							{
21174887Schin #endif
21184887Schin 							*(bp = ip - 1) = c;
21194887Schin 							if (state = rp[c]) goto fsm_next;
21204887Schin 							goto fsm_get;
21214887Schin #if COMPATIBLE
21224887Schin 							}
21234887Schin #endif
21244887Schin 						}
21254887Schin 						if (n != EOB) BACKIN();
21264887Schin 						UNGETCHR(c = '?');
21274887Schin 					}
21284887Schin 					else if (n != EOB) BACKIN();
21294887Schin 				}
21304887Schin 				break;
21314887Schin 			case '%':
21324887Schin 			case '<':
21334887Schin 			case ':':
21344887Schin 				/*
21354887Schin 				 * digraph = --trigraph
21364887Schin 				 */
21374887Schin 
21384887Schin 				if (pp.in->type == IN_FILE && (pp.option & PLUSPLUS))
21394887Schin 				{
21404887Schin 					m = 0;
21414887Schin 					GET(c, n, tp, xp);
21424887Schin 					switch (n)
21434887Schin 					{
21444887Schin 					case '%':
21454887Schin 						if (c == '<') m = '{';
21464887Schin 						break;
21474887Schin 					case '>':
21484887Schin 						if (c == '%') m = '}';
21494887Schin 						else if (c == ':') m = ']';
21504887Schin 						break;
21514887Schin 					case ':':
21524887Schin 						if (c == '%') m = '#';
21534887Schin 						else if (c == '<') m = '[';
21544887Schin 						break;
21554887Schin 					}
21564887Schin 					if (m)
21574887Schin 					{
21584887Schin 						if ((st & WARN) && (st & (COMPATIBILITY|TRANSITION)) && !(pp.mode & HOSTED) && !INCOMMENT(rp))
21594887Schin 							error(1, "digraph conversion %c%c -> %c%s", c, n, m, (st & TRANSITION) ? "" : " inhibited");
21604887Schin #if COMPATIBLE
21614887Schin 						if ((st & (COMPATIBILITY|TRANSITION)) != COMPATIBILITY)
21624887Schin 						{
21634887Schin #endif
21644887Schin 						*(bp = ip - 1) = c = m;
21654887Schin 						if (state = rp[c]) goto fsm_next;
21664887Schin 						goto fsm_get;
21674887Schin #if COMPATIBLE
21684887Schin 						}
21694887Schin #endif
21704887Schin 					}
21714887Schin 					if (n != EOB) BACKIN();
21724887Schin 				}
21734887Schin 				break;
21744887Schin 			case '\\':
21754887Schin 				/*
21764887Schin 				 * line splice
21774887Schin 				 */
21784887Schin 
21794887Schin 				if (pp.in->type == IN_FILE && (!(pp.option & PLUSSPLICE) || !INCOMMENTXX(rp)))
21804887Schin 				{
21814887Schin 					m = 0;
21824887Schin 					GET(c, n, tp, xp);
21834887Schin 					if ((pp.option & SPLICESPACE) && !INQUOTE(rp))
21844887Schin 						while (n == ' ')
21854887Schin 						{
21864887Schin 							GET(c, n, tp, xp);
21874887Schin 							m = 1;
21884887Schin 						}
21894887Schin 					if (n == '\r')
21904887Schin 					{
21914887Schin 						GET(c, n, tp, xp);
21924887Schin 						if (n != '\n' && n != EOB)
21934887Schin 							BACKIN();
21944887Schin 					}
21954887Schin 					if (n == '\n')
21964887Schin 					{
21974887Schin #if CPP
21984887Schin 						if (INQUOTE(rp))
21994887Schin 						{
22004887Schin 							if ((pp.option & STRINGSPLIT) && quot == '"')
22014887Schin 							{
22024887Schin 								PUTCHR(quot);
22034887Schin 								PUTCHR(n);
22044887Schin 								PUTCHR(quot);
22054887Schin 							}
22064887Schin 							else if (*pp.lineid)
22074887Schin 							{
22084887Schin 								PUTCHR(c);
22094887Schin 								PUTCHR(n);
22104887Schin 							}
22114887Schin 							else
22124887Schin 							{
22134887Schin 								st |= HIDDEN;
22144887Schin 								pp.hidden++;
22154887Schin 							}
22164887Schin 						}
22174887Schin 						else
22184887Schin #else
22194887Schin #if COMPATIBLE
22204887Schin 						if (!INQUOTE(rp) && (st & (COMPATIBILITY|DEFINITION|TRANSITION)) == (COMPATIBILITY|DEFINITION))
22214887Schin 						{
22224887Schin 							if (op == tp)
22234887Schin 							{
22244887Schin 								st |= HIDDEN;
22254887Schin 								pp.hidden++;
22264887Schin 								error_info.line++;
22274887Schin 								if (st & SPACEOUT)
22284887Schin 									goto fsm_start;
22294887Schin 								c = (pp.option & SPLICECAT) ? '\t' : ' ';
22304887Schin 								PUTCHR(c);
22314887Schin 								goto fsm_check;
22324887Schin 							}
22334887Schin 							UNGETCHR(n);
22344887Schin 							state &= ~SPLICE;
22354887Schin 							goto fsm_terminal;
22364887Schin 						}
22374887Schin #endif
22384887Schin #endif
22394887Schin 						{
22404887Schin 							st |= HIDDEN;
22414887Schin 							pp.hidden++;
22424887Schin 						}
22434887Schin #if CPP
22444887Schin 						spliced++;
22454887Schin #else
22464887Schin 						error_info.line++;
22474887Schin #endif
22484887Schin 						bp = ip;
22494887Schin 						goto fsm_get;
22504887Schin 					}
22514887Schin 					else if ((n == 'u' || n == 'U') && !INQUOTE(rp))
22524887Schin 					{
22534887Schin 						PUTCHR(c);
22544887Schin 						PUTCHR(n);
22554887Schin 						bp = ip;
22564887Schin 						goto fsm_get;
22574887Schin 					}
22584887Schin #if COMPATIBLE
22594887Schin 					else if ((st & (COMPATIBILITY|TRANSITION)) == COMPATIBILITY && (n == '"' || n == '\'') && !INQUOTE(rp))
22604887Schin 					{
22614887Schin 						PUTCHR(c);
22624887Schin 						PUTCHR(n);
22634887Schin 						bp = ip;
22644887Schin 						goto fsm_get;
22654887Schin 					}
22664887Schin #endif
22674887Schin 					else if (n != EOB)
22684887Schin 						BACKIN();
22694887Schin 					if (m && INSPACE(rp))
22704887Schin 						UNGETCHR(c);
22714887Schin 				}
22724887Schin #if COMPATIBLE
22734887Schin 				else if ((st & (COMPATIBILITY|TRANSITION)) == COMPATIBILITY && !INQUOTE(rp))
22744887Schin 				{
22754887Schin 					GET(c, n, tp, xp);
22764887Schin 					if (n == '"' || n == '\'')
22774887Schin 					{
22784887Schin 						PUTCHR(c);
22794887Schin 						PUTCHR(n);
22804887Schin 						bp = ip;
22814887Schin 						goto fsm_get;
22824887Schin 					}
22834887Schin 					if (n != EOB)
22844887Schin 						BACKIN();
22854887Schin 				}
22864887Schin #endif
22874887Schin 				break;
22884887Schin 			case '\r':
22894887Schin 				/*
22904887Schin 				 * barf
22914887Schin 				 */
22924887Schin 
22934887Schin 				if (pp.in->type == IN_FILE)
22944887Schin 				{
22954887Schin 					GET(c, n, tp, xp);
22964887Schin 					if (n == '\n')
22974887Schin 					{
22984887Schin 						*(bp = ip - 1) = c = n;
22994887Schin 						if (state = rp[c]) goto fsm_next;
23004887Schin 						goto fsm_get;
23014887Schin 					}
23024887Schin 					if (n != EOB) BACKIN();
23034887Schin 				}
23044887Schin 				break;
23054887Schin 			case CC_sub:
23064887Schin 				/*
23074887Schin 				 * barf & puke
23084887Schin 				 */
23094887Schin 
23104887Schin 				if ((pp.option & ZEOF) && pp.in->type == IN_FILE)
23114887Schin 				{
23124887Schin 					pp.in->flags |= IN_eof;
23134887Schin 					c = 0;
23144887Schin 					state = S_EOB;
23154887Schin 					goto fsm_terminal;
23164887Schin 				}
23174887Schin 				break;
23184887Schin 			}
23194887Schin 			if ((state &= ~SPLICE) >= TERMINAL)
23204887Schin 				goto fsm_terminal;
23214887Schin 			PUTCHR(c);
23224887Schin 			goto fsm_begin;
23234887Schin 		}
23244887Schin #if CPP
23254887Schin 		if (INOPSPACE(rp))
23264887Schin 		{
23274887Schin 			BACKIN();
23284887Schin 			goto fsm_start;
23294887Schin 		}
23304887Schin #endif
23314887Schin 		PUTCHR(c);
23324887Schin 		bp = ip;
23334887Schin 		goto fsm_get;
23344887Schin 	}
23354887Schin #if !CPP
23364887Schin  fsm_token:
23374887Schin 	st &= ~NEWLINE;
23384887Schin 	if (pp.level == 1)
23394887Schin 	{
23404887Schin 		pp.in->flags |= IN_tokens;
23414887Schin 		if (st & NOTEXT)
23424887Schin 		{
23434887Schin 			BACKOUT();
23444887Schin 			goto fsm_top;
23454887Schin 		}
23464887Schin  fsm_symbol:
23474887Schin 		count(token);
23484887Schin 	}
23494887Schin  fsm_check:
23504887Schin 	if (st & SKIPCONTROL)
23514887Schin 	{
23524887Schin 		BACKOUT();
23534887Schin 		goto fsm_start;
23544887Schin 	}
23554887Schin  fsm_return:
23564887Schin #if CPP
23574887Schin 	error_info.line += spliced;
23584887Schin #endif
23594887Schin 	SETCHR(0);
23604887Schin 	debug((-5, "token[%d] %03o = %s", pp.level, c, pptokstr(tp, 0)));
23614887Schin 	SYNC();
23624887Schin 	pp.level--;
23634887Schin 	error_info.indent--;
23644887Schin 	return c;
23654887Schin #endif
23664887Schin }
23674887Schin 
23684887Schin #if CPP && POOL
23694887Schin 
23704887Schin #include <ls.h>
23714887Schin #include <wait.h>
23724887Schin 
23734887Schin /*
23744887Schin  * output pool status on exit
23754887Schin  */
23764887Schin 
23774887Schin static void
poolstatus(void)23784887Schin poolstatus(void)
23794887Schin {
23804887Schin 	error(ERROR_OUTPUT|0, pp.pool.output, "%d", error_info.errors != 0);
23814887Schin }
23824887Schin 
23834887Schin /*
23844887Schin  * loop on < input output >
23854887Schin  */
23864887Schin 
23874887Schin static void
pool(void)23884887Schin pool(void)
23894887Schin {
23904887Schin 	char*	ifile;
23914887Schin 	char*	ofile;
23924887Schin 
23934887Schin 	ppflushout();
23944887Schin 	if (!sfnew(sfstdin, NiL, SF_UNBOUND, pp.pool.input, SF_READ))
23954887Schin 		error(ERROR_SYSTEM|3, "cannot dup pool input");
23964887Schin 
23974887Schin 	/*
23984887Schin 	 * kick the -I cache
23994887Schin 	 */
24004887Schin 
24014887Schin 	ppsearch(".", T_STRING, SEARCH_EXISTS);
24024887Schin 
24034887Schin 	/*
24044887Schin 	 * loop on < input output >
24054887Schin 	 */
24064887Schin 
24074887Schin 	pp.pool.input = 0;
24084887Schin 	while (ifile = sfgetr(sfstdin, '\n', 1))
24094887Schin 	{
24104887Schin 		if (!(ofile = strchr(ifile, ' ')))
24114887Schin 			error(3, "%s: pool output file expected", ifile);
24124887Schin 		*ofile++ = 0;
24134887Schin 		waitpid(0, NiL, WNOHANG);
24144887Schin 		switch (fork())
24154887Schin 		{
24164887Schin 		case -1:
24174887Schin 			error(ERROR_SYSTEM|3, "cannot fork pool");
24184887Schin 		case 0:
24194887Schin 			atexit(poolstatus);
24204887Schin 			error_info.errors = 0;
24214887Schin 			error_info.warnings = 0;
24224887Schin 			close(0);
24234887Schin 			if (open(ifile, O_RDONLY))
24244887Schin 				error(ERROR_SYSTEM|3, "%s: cannot read", ifile);
24254887Schin 			close(1);
24264887Schin 			if (open(ofile, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) != 1)
24274887Schin 				error(ERROR_SYSTEM|3, "%s: cannot create", ofile);
24284887Schin 			pp.outfile = ofile;
24294887Schin 			pathcanon(ifile, 0);
24304887Schin 			ifile = ppsetfile(ifile)->name;
24314887Schin #if CHECKPOINT
24324887Schin 			if (pp.mode & DUMP)
24334887Schin 			{
24344887Schin 				if (!pp.pragma)
24354887Schin 					error(3, "#%s must be enabled for checkpoints", dirname(PRAGMA));
24364887Schin 				(*pp.pragma)(dirname(PRAGMA), pp.pass, keyname(X_CHECKPOINT), pp.checkpoint, 1);
24374887Schin 			}
24384887Schin #endif
24394887Schin 			PUSH_FILE(ifile, 0);
24404887Schin 			return;
24414887Schin 		}
24424887Schin 	}
24434887Schin 	while (wait(NiL) != -1);
24444887Schin }
24454887Schin 
24464887Schin #endif
2447