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