1N/A/***********************************************************************
1N/A* *
1N/A* This software is part of the ast package *
1N/A* Copyright (c) 1986-2010 AT&T Intellectual Property *
1N/A* and is licensed under the *
1N/A* Common Public License, Version 1.0 *
1N/A* by AT&T Intellectual Property *
1N/A* *
1N/A* A copy of the License is available at *
1N/A* http://www.opensource.org/licenses/cpl1.0.txt *
1N/A* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
1N/A* *
1N/A* Information and Software Systems Research *
1N/A* AT&T Research *
1N/A* Florham Park NJ *
1N/A* *
1N/A* Glenn Fowler <gsf@research.att.com> *
1N/A* *
1N/A***********************************************************************/
1N/A#pragma prototyped
1N/A/*
1N/A * Glenn Fowler
1N/A * AT&T Research
1N/A *
1N/A * preprocessor lexical analyzer
1N/A * standalone and tokenizing lexer combined in one source
1N/A * define CPP=1 for standalone
1N/A */
1N/A
1N/A#include "pplib.h"
1N/A#include "ppfsm.h"
1N/A
1N/A#if CPP
1N/A
1N/A/*
1N/A * standalone entry point
1N/A */
1N/A
1N/A#define PPCPP_T void
1N/A
1N/A#define START QUICK
1N/A#define INMACRO(x) INQMACRO(x)
1N/A#define DOSTRIP() (st&STRIP)
1N/A
1N/A#if DEBUG & TRACE_debug
1N/Astatic int hit[LAST-TERMINAL+2];
1N/A#endif
1N/A
1N/A#define BACKIN() (ip--)
1N/A#define BACKOUT() (op=tp)
1N/A#define CACHE() do{CACHEINX();CACHEOUTX();st=pp.state;if(!pp.hidden)spliced=0;}while(0)
1N/A#define CACHEIN() do{CACHEINX();st=pp.state;if(!pp.hidden)spliced=0;}while(0)
1N/A#define CACHEINX() do{ip=pp.in->nextchr;}while(0)
1N/A#define CACHEOUT() do{CACHEOUTX();st=pp.state;if(!pp.hidden)spliced=0;}while(0)
1N/A#define CACHEOUTX() do{tp=op=pp.outp;xp=pp.oute;if(sp)sp=op;}while(0)
1N/A#define GETCHR() (*(unsigned char*)ip++)
1N/A#define LASTCHR() (*(ip-1))
1N/A#define LASTOUT() ((op>pp.outbuf)?*(op-1):pp.lastout)
1N/A#define SKIPIN() (ip++)
1N/A#define PUTCHR(c) (*op++=(c))
1N/A#define SETCHR(c) (*op=(c))
1N/A#define SYNC() do{SYNCINX();SYNCOUTX();pp.state=st;}while(0)
1N/A#define SYNCIN() do{SYNCINX();pp.state=st;}while(0)
1N/A#define SYNCINX() do{pp.in->nextchr=ip;}while(0)
1N/A#define SYNCOUT() do{SYNCOUTX();pp.state=st;}while(0)
1N/A#define SYNCOUTX() do{if(sp)op=tp=sp;pp.outp=op;}while(0)
1N/A#define UNGETCHR(c) (*--ip=(c))
1N/A
1N/A#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)
1N/A#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)
1N/A#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)
1N/A
1N/A#define PPSYNCLINE() do { \
1N/A if ((st & (ADD|HIDDEN)) && !(*pp.control & SKIP)) \
1N/A { \
1N/A if (spliced) \
1N/A { \
1N/A error_info.line += spliced; \
1N/A spliced = 0; \
1N/A } \
1N/A else \
1N/A { \
1N/A if (st & ADD) \
1N/A { \
1N/A st &= ~ADD; \
1N/A m = pp.addp - pp.addbuf; \
1N/A pp.addp = pp.addbuf; \
1N/A memcpy(op, pp.addbuf, m); \
1N/A op += m; \
1N/A PPCHECKOUT(); \
1N/A } \
1N/A if (pp.linesync) \
1N/A { \
1N/A if ((st & SYNCLINE) || pp.hidden >= MAXHIDDEN) \
1N/A { \
1N/A pp.hidden = 0; \
1N/A st &= ~(HIDDEN|SYNCLINE); \
1N/A if (error_info.line) \
1N/A { \
1N/A if (LASTOUT() != '\n') \
1N/A PUTCHR('\n'); \
1N/A SYNCOUT(); \
1N/A (*pp.linesync)(error_info.line, error_info.file); \
1N/A CACHEOUT(); \
1N/A } \
1N/A } \
1N/A else \
1N/A { \
1N/A m = pp.hidden; \
1N/A pp.hidden = 0; \
1N/A st &= ~HIDDEN; \
1N/A while (m-- > 0) \
1N/A PUTCHR('\n'); \
1N/A } \
1N/A } \
1N/A else \
1N/A { \
1N/A pp.hidden = 0; \
1N/A st &= ~HIDDEN; \
1N/A PUTCHR('\n'); \
1N/A } \
1N/A } \
1N/A } \
1N/A } while (0)
1N/A
1N/A#if POOL
1N/A
1N/A/*
1N/A * <wait.h> is poison here so pool moved to the end
1N/A */
1N/A
1N/Astatic void poolstatus(void);
1N/Astatic void pool(void);
1N/A
1N/A#endif
1N/A
1N/A#else
1N/A
1N/A/*
1N/A * return next pp token
1N/A *
1N/A * NOTE: pp.token points to at least MAXTOKEN*2 chars and is
1N/A * truncated back to MAXTOKEN on EOB
1N/A */
1N/A
1N/A#define PPCPP_T int
1N/A#define ppcpp pplex
1N/A
1N/A#define START TOKEN
1N/A#define INMACRO(x) INTMACRO(x)
1N/A#define DOSTRIP() ((st&STRIP)||pp.level==1&&(st&(COMPILE|JOINING))==COMPILE&&!(pp.option&PRESERVE))
1N/A
1N/A#define st pp.state
1N/A#define tp pp.token
1N/A#define xp &pp.token[MAXTOKEN]
1N/A
1N/A#define BACKIN() (ip--)
1N/A#define BACKOUT() (op=pp.token)
1N/A#define CACHE() do{CACHEIN();CACHEOUT();}while(0)
1N/A#define CACHEIN() (ip=pp.in->nextchr)
1N/A#define CACHEOUT() (op=pp.token)
1N/A#define GETCHR() (*(unsigned char*)ip++)
1N/A#define LASTCHR() (*(ip-1))
1N/A#define PUTCHR(c) (*op++=(c))
1N/A#define SETCHR(c) (*op=(c))
1N/A#define SKIPIN() (ip++)
1N/A#define SYNC() do{SYNCIN();SYNCOUT();}while(0)
1N/A#define SYNCIN() (pp.in->nextchr=ip)
1N/A#define SYNCOUT() (pp.toknxt=op)
1N/A#define UNGETCHR(c) (*--ip=(c))
1N/A
1N/A#endif
1N/A
1N/APPCPP_T
1N/Appcpp(void)
1N/A{
1N/A register short* rp;
1N/A register char* ip;
1N/A register int state;
1N/A register int c;
1N/A register char* op;
1N/A char* bp;
1N/A int n;
1N/A int m;
1N/A int quot;
1N/A int quotquot;
1N/A int comdelim = 0;
1N/A int comstart = 0;
1N/A int comwarn = 0;
1N/A char* s;
1N/A struct ppsymbol* sym;
1N/A#if CPP
1N/A register long st;
1N/A char* tp;
1N/A char* xp;
1N/A char* sp = 0;
1N/A int qual = 0;
1N/A int spliced = 0;
1N/A#else
1N/A int qual;
1N/A#endif
1N/A
1N/A#if CPP
1N/A#if POOL
1N/A fsm_pool:
1N/A#endif
1N/A#else
1N/A count(pplex);
1N/A#endif
1N/A error_info.indent++;
1N/A pp.level++;
1N/A CACHE();
1N/A#if !CPP
1N/A fsm_top:
1N/A qual = 0;
1N/A#endif
1N/A fsm_start:
1N/A#if CPP
1N/A PPCHECKOUTSP();
1N/A tp = op;
1N/A#endif
1N/A state = START;
1N/A fsm_begin:
1N/A bp = ip;
1N/A do
1N/A {
1N/A rp = fsm[state];
1N/A fsm_get:
1N/A while (!(state = rp[c = GETCHR()]));
1N/A fsm_next:
1N/A ;
1N/A } while (state > 0);
1N/A if (((state = ~state) != S_COMMENT || pp.comment || c == '/' && !INCOMMENT(rp)) && (n = ip - bp - 1) > 0)
1N/A {
1N/A ip = bp;
1N/A#if CPP
1N/A if (op == tp && (st & (ADD|HIDDEN)) && !(st & PASSTHROUGH) && !(pp.option & PRESERVE))
1N/A switch (TERM(state))
1N/A {
1N/A case S_SHARP:
1N/A break;
1N/A case S_CHRB:
1N/A case S_NL:
1N/A if (*ip == '\n')
1N/A break;
1N/A /*FALLTHROUGH*/
1N/A default:
1N/A if ((pp.option & PRESERVE) && !(st & NEWLINE) && c != '\n')
1N/A break;
1N/A PPSYNCLINE();
1N/A tp = op;
1N/A break;
1N/A }
1N/A#endif
1N/A MEMCPY(op, ip, n);
1N/A ip++;
1N/A }
1N/A count(terminal);
1N/A#if CPP && (DEBUG & TRACE_debug)
1N/A hit[(state & SPLICE) ? (elementsof(hit) - 1) : (TERM(state) - TERMINAL)]++;
1N/A#endif
1N/A fsm_terminal:
1N/A 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)));
1N/A switch (TERM(state))
1N/A {
1N/A
1N/A#if !CPP
1N/A case S_CHR:
1N/A PUTCHR(c);
1N/A break;
1N/A#endif
1N/A
1N/A case S_CHRB:
1N/A BACKIN();
1N/A#if CPP
1N/A st &= ~NEWLINE;
1N/A pp.in->flags |= IN_tokens;
1N/A count(token);
1N/A goto fsm_start;
1N/A#else
1N/A c = *tp;
1N/A break;
1N/A#endif
1N/A
1N/A case S_COMMENT:
1N/A switch (c)
1N/A {
1N/A case '\n':
1N/A if (!INCOMMENTXX(rp))
1N/A {
1N/A qual = 0;
1N/A if (!comstart) comstart = comdelim = error_info.line;
1N/A error_info.line++;
1N/A if (pp.comment) PUTCHR(c);
1N/A else BACKOUT();
1N/A#if CPP
1N/A rp = fsm[COM2];
1N/A bp = ip;
1N/A goto fsm_get;
1N/A#else
1N/A state = COM2;
1N/A goto fsm_begin;
1N/A#endif
1N/A }
1N/A else if (comwarn < 0 && !(pp.mode & HOSTED))
1N/A error(1, "/* appears in // comment");
1N/A break;
1N/A case '*':
1N/A if (!comwarn && !(pp.mode & HOSTED))
1N/A {
1N/A if (INCOMMENTXX(rp)) comwarn = -1;
1N/A else if (comstart && comstart != error_info.line)
1N/A {
1N/A if (qual || comdelim < error_info.line - 1)
1N/A {
1N/A error(1, "/* appears in /* ... */ comment starting at line %d", comstart);
1N/A comwarn = 1;
1N/A }
1N/A else comdelim = error_info.line;
1N/A }
1N/A }
1N/A fsm_comment:
1N/A PUTCHR(c);
1N/A#if CPP
1N/A rp = fsm[INCOMMENTXX(rp) ? COM5 : COM3];
1N/A bp = ip;
1N/A goto fsm_get;
1N/A#else
1N/A state = INCOMMENTXX(rp) ? COM5 : COM3;
1N/A goto fsm_begin;
1N/A#endif
1N/A case '/':
1N/A if (!INCOMMENT(rp))
1N/A {
1N/A if (!(pp.mode & HOSTED))
1N/A error(1, "*/ appears outside of comment");
1N/A BACKIN();
1N/A#if CPP
1N/A st &= ~NEWLINE;
1N/A pp.in->flags |= IN_tokens;
1N/A count(token);
1N/A goto fsm_start;
1N/A#else
1N/A c = '*';
1N/A if (!pp.comment) PUTCHR(c);
1N/A goto fsm_token;
1N/A#endif
1N/A }
1N/A else if (INCOMMENTXX(rp))
1N/A {
1N/A if (!(pp.mode & HOSTED))
1N/A {
1N/A if (comwarn < 0) comwarn = 0;
1N/A else if (!comwarn)
1N/A {
1N/A comwarn = 1;
1N/A error(1, "*/ appears in // comment");
1N/A }
1N/A }
1N/A goto fsm_comment;
1N/A }
1N/A break;
1N/A case EOF:
1N/A BACKIN();
1N/A if (!(pp.mode & HOSTED))
1N/A {
1N/A if (comstart) error(2, "unterminated /* ... */ comment starting at line %d", comstart);
1N/A else if (INCOMMENTXX(rp)) error(2, "unterminated // ... comment");
1N/A else error(2, "unterminated /* ... */ comment");
1N/A }
1N/A break;
1N/A }
1N/A#if CPP
1N/A if (!pp.comment || sp)
1N/A {
1N/A#if COMPATIBLE
1N/A if (!(pp.state & COMPATIBILITY) || *bp == ' ' || *bp == '\t')
1N/A#endif
1N/A {
1N/A BACKOUT();
1N/A PUTCHR(' ');
1N/A tp = op;
1N/A }
1N/A }
1N/A else if (pp.in->type & IN_TOP)
1N/A#else
1N/A if (pp.comment && !(st & (COLLECTING|DIRECTIVE|JOINING)) && !(*pp.control & SKIP) && (pp.in->type & IN_TOP))
1N/A#endif
1N/A {
1N/A st &= ~HIDDEN;
1N/A pp.hidden = 0;
1N/A *(op - (c != '\n')) = 0;
1N/A m = (op - (c != '\n') - tp > MAXTOKEN - 6) ? (error_info.line - MAXHIDDEN) : 0;
1N/A BACKOUT();
1N/A SYNC();
1N/A while (*tp != '/') tp++;
1N/A (*pp.comment)(c == '\n' ? "//" : "/*", tp + 2, c == '\n' ? "" : (st & HEADER) ? "*/\n" : "*/", comstart ? comstart : error_info.line);
1N/A CACHE();
1N/A comstart = m;
1N/A }
1N/A if (comstart)
1N/A {
1N/A st |= HIDDEN;
1N/A pp.hidden += error_info.line - comstart;
1N/A comstart = 0;
1N/A }
1N/A qual = comwarn = comdelim = 0;
1N/A BACKOUT();
1N/A if (c == '\n') goto fsm_newline;
1N/A if ((st & PASSTHROUGH) && ((st & (HIDDEN|NEWLINE)) || *ip == '\n'))
1N/A {
1N/A if (*ip == '\n')
1N/A ip++;
1N/A goto fsm_newline;
1N/A }
1N/A#if COMPATIBLE
1N/A if ((st & (COMPATIBILITY|TRANSITION)) == COMPATIBILITY) st &= ~NEWLINE;
1N/A#endif
1N/A#if !CPP
1N/A if (pp.level > 1 && !(st & (NOSPACE|SKIPCONTROL)))
1N/A {
1N/A#if COMPATIBLE
1N/A c = ((st & (COMPATIBILITY|DEFINITION)) == ((COMPATIBILITY|DEFINITION))) ? '\t' : ' ';
1N/A#else
1N/A c = ' ';
1N/A#endif
1N/A goto fsm_return;
1N/A }
1N/A#endif
1N/A goto fsm_start;
1N/A
1N/A case S_EOB:
1N/A if (c)
1N/A {
1N/A if (state = fsm[TERMINAL][INDEX(rp)+1])
1N/A goto fsm_terminal;
1N/A#if CPP
1N/A#if POOL
1N/A if (pp.pool.input)
1N/A {
1N/A BACKIN();
1N/A SYNC();
1N/A pool();
1N/A CACHE();
1N/A goto fsm_pool;
1N/A }
1N/A#endif
1N/A SYNCOUT();
1N/A return;
1N/A#else
1N/A BACKIN();
1N/A c = 0;
1N/A goto fsm_return;
1N/A#endif
1N/A }
1N/A {
1N/A register struct ppinstk* cur = pp.in;
1N/A register struct ppinstk* prv = pp.in->prev;
1N/A
1N/A#if CPP
1N/A if (sp) op = sp;
1N/A#endif
1N/A switch (cur->type)
1N/A {
1N/A case IN_BUFFER:
1N/A case IN_INIT:
1N/A case IN_RESCAN:
1N/A#if CPP
1N/A if (prv)
1N/A#else
1N/A if (!(st & PASSEOF) && prv)
1N/A#endif
1N/A {
1N/A if (cur->type == IN_RESCAN || cur->type == IN_BUFFER)
1N/A {
1N/A fsm_pop:
1N/A#if PROTOTYPE
1N/A if (cur->flags & IN_prototype)
1N/A pppclose(cur->buffer + PPBAKSIZ);
1N/A else
1N/A#endif
1N/A if (!(cur->flags & IN_static))
1N/A free(cur->buffer);
1N/A }
1N/A while (pp.control-- != cur->control)
1N/A error(2, "#%s on line %d has no #%s", dirname(IF), GETIFLINE(pp.control+1), dirname(ENDIF));
1N/A st |= NEWLINE;
1N/A error_info.file = cur->file;
1N/A error_info.line = cur->line;
1N/A pp.hidden = 0;
1N/A#if CPP
1N/A spliced = 0;
1N/A#endif
1N/A if (cur->flags & IN_hosted)
1N/A {
1N/A pp.mode |= HOSTED;
1N/A pp.flags |= PP_hosted;
1N/A }
1N/A else
1N/A {
1N/A pp.mode &= ~HOSTED;
1N/A pp.flags &= ~PP_hosted;
1N/A }
1N/A#if !CPP && CATSTRINGS
1N/A if (st & JOINING) st |= HIDDEN|SYNCLINE;
1N/A else
1N/A#endif
1N/A {
1N/A st &= ~(HIDDEN|SYNCLINE);
1N/A switch (cur->type)
1N/A {
1N/A case IN_BUFFER:
1N/A case IN_INIT:
1N/A if (!prv->prev) break;
1N/A /*FALLTHROUGH*/
1N/A case IN_FILE:
1N/A case IN_RESCAN:
1N/A if (prv->type == IN_FILE || cur->type == IN_FILE && (prv->type == IN_RESCAN || prv->type == IN_MULTILINE))
1N/A {
1N/A if (pp.linesync && (cur->type != IN_RESCAN || (cur->flags & IN_sync)))
1N/A {
1N/A POP();
1N/A SYNCOUT();
1N/A (*pp.linesync)(error_info.line, error_info.file);
1N/A CACHEOUT();
1N/A prv = pp.in;
1N/A }
1N/A }
1N/A#if DEBUG
1N/A else if (!prv->prev)
1N/A {
1N/A /*UNDENT*/
1N/A c = 0;
1N/A#if DEBUG & TRACE_count
1N/A if (pp.test & TEST_count)
1N/A {
1N/A c = 1;
1N/A sfprintf(sfstderr, "\n");
1N/A sfprintf(sfstderr, "%7d: pplex calls\n", pp.counter.pplex);
1N/A sfprintf(sfstderr, "%7d: terminal states\n", pp.counter.terminal);
1N/A sfprintf(sfstderr, "%7d: emitted tokens\n", pp.counter.token);
1N/A sfprintf(sfstderr, "%7d: input stream pushes\n", pp.counter.push);
1N/A sfprintf(sfstderr, "%7d: macro candidates\n", pp.counter.candidate);
1N/A sfprintf(sfstderr, "%7d: macro expansions\n", pp.counter.macro);
1N/A sfprintf(sfstderr, "%7d: function macros\n", pp.counter.function);
1N/A }
1N/A#endif
1N/A#if CPP && (DEBUG & TRACE_debug)
1N/A if (pp.test & TEST_hit)
1N/A {
1N/A c = 1;
1N/A sfprintf(sfstderr, "\n");
1N/A if (hit[elementsof(hit) - 1])
1N/A sfprintf(sfstderr, "%7d: SPLICE\n", hit[elementsof(hit) - 1]);
1N/A for (n = 0; n < elementsof(hit) - 1; n++)
1N/A if (hit[n])
1N/A sfprintf(sfstderr, "%7d: %s\n", hit[n], pplexstr(TERMINAL + n));
1N/A }
1N/A#endif
1N/A if (pp.test & (TEST_hashcount|TEST_hashdump))
1N/A {
1N/A c = 1;
1N/A sfprintf(sfstderr, "\n");
1N/A hashdump(NiL, (pp.test & TEST_hashdump) ? HASH_BUCKET : 0);
1N/A }
1N/A if (c) sfprintf(sfstderr, "\n");
1N/A /*INDENT*/
1N/A }
1N/A#endif
1N/A break;
1N/A }
1N/A }
1N/A#if CHECKPOINT
1N/A if (cur->index)
1N/A {
1N/A SYNCOUT();
1N/A cur->index->end = ppoffset();
1N/A cur->index = 0;
1N/A CACHEOUT();
1N/A }
1N/A#endif
1N/A POP();
1N/A bp = ip;
1N/A tp = op;
1N/A goto fsm_get;
1N/A }
1N/A c = EOF;
1N/A break;
1N/A case IN_COPY:
1N/A if (prv)
1N/A {
1N/A error_info.line = cur->line;
1N/A if (!(prv->symbol->flags & SYM_MULTILINE))
1N/A prv->symbol->flags |= SYM_DISABLED;
1N/A POP();
1N/A bp = ip;
1N/A goto fsm_get;
1N/A }
1N/A c = EOF;
1N/A break;
1N/A case IN_EXPAND:
1N/A if (prv)
1N/A {
1N/A error_info.line = cur->line;
1N/A free(cur->buffer);
1N/A POP();
1N/A bp = ip;
1N/A goto fsm_get;
1N/A }
1N/A c = EOF;
1N/A break;
1N/A case IN_FILE:
1N/A FGET(c, c, tp, xp);
1N/A if (c == EOB)
1N/A {
1N/A#if CPP
1N/A if ((st & (NOTEXT|HIDDEN)) == HIDDEN && LASTOUT() != '\n')
1N/A PUTCHR('\n');
1N/A if (prv)
1N/A#else
1N/A if (st & EOF2NL)
1N/A {
1N/A st &= ~EOF2NL;
1N/A *(ip - 1) = c = '\n';
1N/A }
1N/A else if (!(st & (FILEPOP|PASSEOF)) && prv)
1N/A#endif
1N/A {
1N/A if (!(cur->flags & IN_newline))
1N/A {
1N/A cur->flags |= IN_newline;
1N/A if ((pp.mode & (HOSTED|PEDANTIC)) == PEDANTIC && LASTCHR() != '\f' && LASTCHR() != CC_sub)
1N/A error(1, "file does not end with %s", pptokchr('\n'));
1N/A *(ip - 1) = c = '\n';
1N/A }
1N/A else
1N/A {
1N/A if (!(cur->flags & (IN_noguard|IN_tokens)) && cur->symbol)
1N/A ppmultiple(ppsetfile(error_info.file), cur->symbol);
1N/A if (cur->fd >= 0)
1N/A close(cur->fd);
1N/A if (pp.incref && !(pp.mode & INIT))
1N/A {
1N/A SYNCOUT();
1N/A (*pp.incref)(error_info.file, cur->file, error_info.line - 1, PP_SYNC_POP);
1N/A CACHEOUT();
1N/A }
1N/A goto fsm_pop;
1N/A }
1N/A }
1N/A else
1N/A c = EOF;
1N/A }
1N/A break;
1N/A case IN_MACRO:
1N/A case IN_MULTILINE:
1N/A#if !CPP
1N/A if (!(st & PASSEOF))
1N/A#endif
1N/A#if COMPATIBLE
1N/A if (prv && (!INMACRO(rp) || (st & (COMPATIBILITY|TRANSITION)) == COMPATIBILITY && ppismac(*prv->nextchr)))
1N/A#else
1N/A if (prv && !INMACRO(rp))
1N/A#endif
1N/A {
1N/A if (cur->type == IN_MULTILINE)
1N/A {
1N/A while (pp.control-- != cur->control)
1N/A error(2, "#%s on line %d has no #%s", dirname(IF), GETIFLINE(pp.control+1), dirname(ENDIF));
1N/A free(cur->buffer);
1N/A error_info.file = cur->file;
1N/A error_info.line = cur->line;
1N/A if (pp.linesync)
1N/A {
1N/A SYNCOUT();
1N/A (*pp.linesync)(error_info.line, error_info.file);
1N/A CACHEOUT();
1N/A }
1N/A }
1N/A cur->symbol->flags &= ~SYM_DISABLED;
1N/A if (cur->symbol->flags & SYM_FUNCTION)
1N/A popframe(pp.macp);
1N/A POP();
1N/A#if CPP
1N/A if (!(st & COMPATIBILITY) && ppisidig(*(op - 1)) && ppisidig(*ip)) UNGETCHR(' ');
1N/A#endif
1N/A bp = ip;
1N/A goto fsm_get;
1N/A }
1N/A c = EOF;
1N/A break;
1N/A case IN_QUOTE:
1N/A if (prv)
1N/A {
1N/A error_info.line = cur->line;
1N/A st &= ~(ESCAPE|QUOTE);
1N/A POP();
1N/A c = '"';
1N/A }
1N/A else c = EOF;
1N/A break;
1N/A case IN_SQUOTE:
1N/A if (prv)
1N/A {
1N/A error_info.line = cur->line;
1N/A st &= ~(ESCAPE|SQUOTE);
1N/A POP();
1N/A c = '\'';
1N/A }
1N/A else c = EOF;
1N/A break;
1N/A case IN_STRING:
1N/A#if CPP
1N/A if (prv)
1N/A#else
1N/A if (!(st & PASSEOF) && !(cur->flags & IN_expand) && prv)
1N/A#endif
1N/A {
1N/A if (cur->flags & IN_disable) st |= DISABLE;
1N/A else st &= ~DISABLE;
1N/A POP();
1N/A bp = ip;
1N/A goto fsm_get;
1N/A }
1N/A c = EOF;
1N/A break;
1N/A default:
1N/A c = EOF;
1N/A break;
1N/A }
1N/A }
1N/A bp = ip - 1;
1N/A if (state = rp[c]) goto fsm_next;
1N/A goto fsm_get;
1N/A
1N/A#if !CPP
1N/A case S_HUH:
1N/A if (INOPSPACE(rp))
1N/A {
1N/A if (c == '=')
1N/A {
1N/A#if PROTOTYPE
1N/A if (pp.in->flags & IN_prototype) PUTCHR(c);
1N/A else
1N/A {
1N/A#endif
1N/A while (*(op - 1) == ' ' || *(op - 1) == '\t') op--;
1N/A PUTCHR(c);
1N/A if (st & (STRICT|WARN)) error(1, "%-*.*s: space ignored in operator", op - tp, op - tp, tp);
1N/A#if PROTOTYPE
1N/A }
1N/A#endif
1N/A switch (*tp)
1N/A {
1N/A case '/':
1N/A c = T_DIVEQ;
1N/A break;
1N/A case '%':
1N/A c = T_MODEQ;
1N/A break;
1N/A case '&':
1N/A c = T_ANDEQ;
1N/A break;
1N/A case '*':
1N/A c = T_MPYEQ;
1N/A break;
1N/A case '+':
1N/A c = T_ADDEQ;
1N/A break;
1N/A case '-':
1N/A c = T_SUBEQ;
1N/A break;
1N/A case '^':
1N/A c = T_XOREQ;
1N/A break;
1N/A case '|':
1N/A c = T_OREQ;
1N/A break;
1N/A case '<':
1N/A c = T_LSHIFTEQ;
1N/A break;
1N/A case '>':
1N/A c = T_RSHIFTEQ;
1N/A break;
1N/A }
1N/A }
1N/A else
1N/A {
1N/A BACKIN();
1N/A switch (c = *tp)
1N/A {
1N/A case '<':
1N/A c = T_LSHIFT;
1N/A break;
1N/A case '>':
1N/A c = T_RSHIFT;
1N/A break;
1N/A }
1N/A }
1N/A }
1N/A else if (pp.level > 1 || (pp.option & PRESERVE)) PUTCHR(c);
1N/A else if (tp == op)
1N/A {
1N/A if (pp.in->type != IN_BUFFER)
1N/A {
1N/A if (!(pp.option & ALLPOSSIBLE))
1N/A error(1, "%s: invalid character ignored", pptokchr(c));
1N/A goto fsm_top;
1N/A }
1N/A PUTCHR(c);
1N/A }
1N/A else if (*tp == ':')
1N/A {
1N/A PUTCHR(c);
1N/A if (c == '=') error(2, "real programmers use =");
1N/A else c = '+';
1N/A }
1N/A else
1N/A {
1N/A BACKIN();
1N/A c = *tp;
1N/A }
1N/A break;
1N/A#endif
1N/A
1N/A case S_QUAL:
1N/A if ((state = NEXT(state)) != LIT1)
1N/A {
1N/A rp = fsm[state];
1N/A bp = ip;
1N/A#if CPP
1N/A qual = 1;
1N/A#if COMPATIBLE
1N/A if (!(st & COMPATIBILITY) || c != 'u' && c != 'U')
1N/A#endif
1N/A PUTCHR(c);
1N/A#else
1N/A switch (c)
1N/A {
1N/A case 'f':
1N/A case 'F':
1N/A qual |= N_FLOAT;
1N/A#if COMPATIBLE
1N/A if (!(st & COMPATIBILITY))
1N/A#endif
1N/A PUTCHR(c);
1N/A break;
1N/A case 'l':
1N/A case 'L':
1N/A qual |= N_LONG;
1N/A PUTCHR(c);
1N/A break;
1N/A case 'u':
1N/A case 'U':
1N/A qual |= N_UNSIGNED;
1N/A#if COMPATIBLE
1N/A if (!(st & COMPATIBILITY))
1N/A#endif
1N/A PUTCHR(c);
1N/A break;
1N/A default:
1N/A PUTCHR(c);
1N/A break;
1N/A }
1N/A#endif
1N/A goto fsm_get;
1N/A }
1N/A#if !CPP
1N/A qual |= N_WIDE;
1N/A if (DOSTRIP()) BACKOUT();
1N/A#endif
1N/A /*FALLTHROUGH*/
1N/A
1N/A case S_LITBEG:
1N/A#if CPP
1N/A quot = c;
1N/A rp = fsm[LIT1];
1N/A if (op == tp)
1N/A {
1N/A PPSYNCLINE();
1N/A tp = op;
1N/A }
1N/A#else
1N/A if ((quot = c) == '<')
1N/A {
1N/A 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)
1N/A {
1N/A PUTCHR(c);
1N/A bp = ip;
1N/A rp = fsm[LT1];
1N/A goto fsm_get;
1N/A }
1N/A quot = '>';
1N/A rp = fsm[HDR1];
1N/A }
1N/A else rp = fsm[LIT1];
1N/A if (!DOSTRIP())
1N/A#endif
1N/A PUTCHR(c);
1N/A bp = ip;
1N/A goto fsm_get;
1N/A
1N/A case S_LITEND:
1N/A n = 1;
1N/A if (c != quot)
1N/A {
1N/A if (c != '\n' && c != EOF)
1N/A {
1N/A if (st & (QUOTE|SQUOTE))
1N/A {
1N/A if (!(st & ESCAPE))
1N/A {
1N/A st |= ESCAPE;
1N/A quotquot = c;
1N/A }
1N/A else if (c == quotquot) st &= ~ESCAPE;
1N/A }
1N/A PUTCHR(c);
1N/A bp = ip;
1N/A goto fsm_get;
1N/A }
1N/A#if CPP
1N/A if ((st & PASSTHROUGH) || (pp.option & PRESERVE))
1N/A {
1N/A if (c == '\n') goto fsm_newline;
1N/A bp = ip;
1N/A goto fsm_start;
1N/A }
1N/A#endif
1N/A m = (st & SKIPCONTROL) && (pp.mode & HOSTED) ? -1 : 1;
1N/A if (c == '\n' && quot == '\'' && (pp.option & STRINGSPAN)) n = 0;
1N/A else
1N/A#if COMPATIBLE && !CPP
1N/A if ((st & (COMPATIBILITY|DEFINITION)) != (COMPATIBILITY|DEFINITION))
1N/A#endif
1N/A {
1N/A switch (quot)
1N/A {
1N/A case '"':
1N/A if (c == '\n')
1N/A {
1N/A if (!(pp.option & STRINGSPAN) || (st & (COMPATIBILITY|STRICT)) == STRICT)
1N/A error(m, "%s in string", pptokchr(c));
1N/A error_info.line++;
1N/A if (!(pp.option & STRINGSPAN))
1N/A {
1N/A PUTCHR('\\');
1N/A c = 'n';
1N/A }
1N/A else if (pp.option & STRINGSPLIT)
1N/A {
1N/A PUTCHR('\\');
1N/A PUTCHR('n');
1N/A PUTCHR('"');
1N/A PUTCHR('\n');
1N/A c = '"';
1N/A }
1N/A PUTCHR(c);
1N/A bp = ip;
1N/A goto fsm_get;
1N/A }
1N/A error(m, "%s in string", pptokchr(c));
1N/A c = '\n';
1N/A break;
1N/A case '\'':
1N/A if (!(st & DIRECTIVE) || !(pp.mode & (HOSTED|RELAX)))
1N/A error(m, "%s in character constant", pptokchr(c));
1N/A break;
1N/A case '>':
1N/A error(m, "%s in header constant", pptokchr(c));
1N/A break;
1N/A default:
1N/A error(m, "%s in %c quote", pptokchr(c), quot);
1N/A break;
1N/A }
1N/A#if !CPP
1N/A if (!DOSTRIP())
1N/A#endif
1N/A PUTCHR(quot);
1N/A }
1N/A if (c == '\n')
1N/A {
1N/A UNGETCHR(c);
1N/A c = quot;
1N/A }
1N/A }
1N/A else if (st & (SQUOTE|QUOTE))
1N/A {
1N/A if (!(st & ESCAPE))
1N/A {
1N/A st |= ESCAPE;
1N/A quotquot = c;
1N/A }
1N/A else if (c == quotquot) st &= ~ESCAPE;
1N/A PUTCHR('\\');
1N/A PUTCHR(c);
1N/A bp = ip;
1N/A goto fsm_get;
1N/A }
1N/A#if CPP
1N/A else PUTCHR(c);
1N/A#else
1N/A else if (!DOSTRIP()) PUTCHR(c);
1N/A#endif
1N/A#if CATSTRINGS
1N/A#if CPP
1N/A if (c == '"' && !(st & (COLLECTING|NOTEXT|PASSTHROUGH|SKIPCONTROL)) && (pp.mode & CATLITERAL))
1N/A#else
1N/A if (c == '"' && pp.level == 1 && !(st & (COLLECTING|JOINING|NOTEXT|SKIPCONTROL)) && (pp.mode & CATLITERAL))
1N/A#endif
1N/A {
1N/A char* pptoken;
1N/A long ppstate;
1N/A
1N/A pptoken = pp.token;
1N/A pp.token = pp.catbuf;
1N/A *pp.token++ = 0;
1N/A ppstate = (st & STRIP);
1N/A if (DOSTRIP())
1N/A ppstate |= ADD|QUOTE;
1N/A st |= JOINING;
1N/A st &= ~(NEWLINE|STRIP);
1N/A
1N/A /*
1N/A * revert to the top level since string
1N/A * concatenation crosses file boundaries
1N/A * (allowing intervening directives)
1N/A */
1N/A
1N/A pp.level = 0;
1N/A SYNCIN();
1N/A m = n = 0;
1N/A for (;;)
1N/A {
1N/A switch (c = pplex())
1N/A {
1N/A case '\n':
1N/A m++;
1N/A continue;
1N/A case ' ':
1N/A *pp.catbuf = ' ';
1N/A continue;
1N/A case T_WSTRING:
1N/A#if !CPP
1N/A qual = N_WIDE;
1N/A#endif
1N/A if (ppstate & ADD)
1N/A ppstate &= ~ADD;
1N/A else if (m == n || !(st & SPACEOUT))
1N/A op--;
1N/A else
1N/A {
1N/A n = m;
1N/A *(op - 1) = '\\';
1N/A *op++ = '\n';
1N/A }
1N/A STRCOPY(op, pp.token + 2 + (*pp.token == ' '), s);
1N/A continue;
1N/A case T_STRING:
1N/A if (ppstate & ADD)
1N/A ppstate &= ~ADD;
1N/A else if (m == n || !(st & SPACEOUT))
1N/A op--;
1N/A else
1N/A {
1N/A n = m;
1N/A *(op - 1) = '\\';
1N/A *op++ = '\n';
1N/A }
1N/A STRCOPY(op, pp.token + 1 + (*pp.token == ' '), s);
1N/A continue;
1N/A case 0:
1N/A m = error_info.line ? (error_info.line - 1) : 0;
1N/A *pp.token = 0;
1N/A /*FALLTHROUGH*/
1N/A default:
1N/A if (m)
1N/A {
1N/A if (--m)
1N/A {
1N/A pp.state |= HIDDEN|SYNCLINE;
1N/A pp.hidden += m;
1N/A }
1N/A#if COMPATIBLE
1N/A if ((st & COMPATIBILITY) && c == '#' && *(pp.token - 1))
1N/A {
1N/A *(pp.token + 3) = *(pp.token + 2);
1N/A *(pp.token + 2) = *(pp.token + 1);
1N/A *(pp.token + 1) = *pp.token;
1N/A *pp.token = *(pp.token - 1);
1N/A }
1N/A error_info.line--;
1N/A *--pp.token = '\n';
1N/A#endif
1N/A }
1N/A else if (*(pp.token - 1))
1N/A pp.token--;
1N/A if (ppisidig(*pp.token))
1N/A *op++ = ' ';
1N/A if (pp.in->type == IN_MACRO && (s = strchr(pp.token, MARK)) && !*(s + 1))
1N/A {
1N/A *(s + 1) = MARK;
1N/A *(s + 2) = 0;
1N/A }
1N/A PUSH_STRING(pp.token);
1N/A pp.state &= ~(JOINING|NEWLINE);
1N/A pp.state |= ppstate & ~(ADD|QUOTE);
1N/A if ((ppstate & (ADD|QUOTE)) == QUOTE)
1N/A op--;
1N/A break;
1N/A }
1N/A break;
1N/A }
1N/A pp.token = pptoken;
1N/A CACHEIN();
1N/A pp.level = 1;
1N/A#if !CPP
1N/A c = T_STRING | qual;
1N/A break;
1N/A#endif
1N/A }
1N/A#endif
1N/A#if CPP
1N/A if (n && !(st & (PASSTHROUGH|SKIPCONTROL|NOTEXT)) && c == '\'' && (op - tp) <= 2 && !(pp.mode & (HOSTED|RELAX)))
1N/A error(1, "empty character constant");
1N/A if (pp.option & PRESERVE)
1N/A st &= ~ESCAPE;
1N/A else
1N/A st &= ~(ESCAPE|NEWLINE);
1N/A pp.in->flags |= IN_tokens;
1N/A count(token);
1N/A goto fsm_start;
1N/A#else
1N/A st &= ~ESCAPE;
1N/A switch (quot)
1N/A {
1N/A case '\'':
1N/A if (n && !(st & NOTEXT) && (op - tp) <= (DOSTRIP() ? 0 : 2) && !(pp.mode & (HOSTED|RELAX)))
1N/A error(1, "empty character constant");
1N/A c = T_CHARCONST | qual;
1N/A break;
1N/A case '>':
1N/A c = T_HEADER;
1N/A break;
1N/A default:
1N/A if (c == quot)
1N/A c = T_STRING | qual;
1N/A break;
1N/A }
1N/A break;
1N/A#endif
1N/A
1N/A case S_LITESC:
1N/A if (st & (COLLECTING|DIRECTIVE|QUOTE|SQUOTE))
1N/A {
1N/A if (st & ESCAPE)
1N/A {
1N/A PUTCHR('\\');
1N/A if (c == quot) PUTCHR('\\');
1N/A }
1N/A PUTCHR(c);
1N/A }
1N/A#if CPP
1N/A else if (st & PASSTHROUGH) PUTCHR(c);
1N/A#endif
1N/A else if (pp.option & PRESERVE) PUTCHR(c);
1N/A else switch (c)
1N/A {
1N/A case 'b':
1N/A case 'f':
1N/A case 'n':
1N/A case 'r':
1N/A case 't':
1N/A case '\\':
1N/A case '\'':
1N/A case '"':
1N/A case '?':
1N/A PUTCHR(c);
1N/A break;
1N/A#if COMPATIBLE
1N/A case '8':
1N/A case '9':
1N/A if (!(st & COMPATIBILITY)) goto unknown;
1N/A if (st & STRICT) error(1, "%c: invalid character in octal character escape", c);
1N/A /*FALLTHROUGH*/
1N/A#endif
1N/A case '0':
1N/A case '1':
1N/A case '2':
1N/A case '3':
1N/A case '4':
1N/A case '5':
1N/A case '6':
1N/A case '7':
1N/A n = c - '0';
1N/A for (m = 0; m < 2; m++)
1N/A {
1N/A GET(c, c, tp, xp);
1N/A switch (c)
1N/A {
1N/A#if COMPATIBLE
1N/A case '8':
1N/A case '9':
1N/A if (!(st & COMPATIBILITY))
1N/A {
1N/A UNGETCHR(c);
1N/A break;
1N/A }
1N/A if (st & STRICT) error(1, "%c: invalid character in octal character escape", c);
1N/A /*FALLTHROUGH*/
1N/A#endif
1N/A case '0':
1N/A case '1':
1N/A case '2':
1N/A case '3':
1N/A case '4':
1N/A case '5':
1N/A case '6':
1N/A case '7':
1N/A n = (n << 3) + c - '0';
1N/A continue;
1N/A default:
1N/A UNGETCHR(c);
1N/A break;
1N/A }
1N/A break;
1N/A }
1N/A if (n & ~0777) error(1, "octal character constant too large");
1N/A goto octal;
1N/A case 'a':
1N/A if (pp.option & MODERN)
1N/A {
1N/A PUTCHR(c);
1N/A break;
1N/A }
1N/A#if COMPATIBLE
1N/A if (st & COMPATIBILITY) goto unknown;
1N/A#endif
1N/A n = CC_bel;
1N/A goto octal;
1N/A case 'v':
1N/A if (pp.option & MODERN)
1N/A {
1N/A PUTCHR(c);
1N/A break;
1N/A }
1N/A n = CC_vt;
1N/A goto octal;
1N/A case 'E':
1N/A if (st & (COMPATIBILITY|STRICT)) goto unknown;
1N/A n = CC_esc;
1N/A goto octal;
1N/A case 'x':
1N/A#if COMPATIBLE
1N/A if (st & COMPATIBILITY) goto unknown;
1N/A#endif
1N/A n = 0;
1N/A for (m = 0; m < 3; m++)
1N/A {
1N/A GET(c, c, tp, xp);
1N/A switch (c)
1N/A {
1N/A case '0':
1N/A case '1':
1N/A case '2':
1N/A case '3':
1N/A case '4':
1N/A case '5':
1N/A case '6':
1N/A case '7':
1N/A case '8':
1N/A case '9':
1N/A n = (n << 4) + c - '0';
1N/A continue;
1N/A case 'a':
1N/A case 'b':
1N/A case 'c':
1N/A case 'd':
1N/A case 'e':
1N/A case 'f':
1N/A n = (n << 4) + c - 'a' + 10;
1N/A continue;
1N/A case 'A':
1N/A case 'B':
1N/A case 'C':
1N/A case 'D':
1N/A case 'E':
1N/A case 'F':
1N/A n = (n << 4) + c - 'A' + 10;
1N/A continue;
1N/A default:
1N/A if (!m) error(1, "\\x%c: invalid character in hexadecimal character constant", c);
1N/A UNGETCHR(c);
1N/A break;
1N/A }
1N/A break;
1N/A }
1N/A if (n & ~0777) error(1, "hexadecimal character constant too large");
1N/A octal:
1N/A PUTCHR(((n >> 6) & 07) + '0');
1N/A PUTCHR(((n >> 3) & 07) + '0');
1N/A PUTCHR((n & 07) + '0');
1N/A break;
1N/A default:
1N/A unknown:
1N/A if (st & (STRICT|WARN)) error(1, "\\%c: non-standard character constant", c);
1N/A PUTCHR(c);
1N/A break;
1N/A }
1N/A state = LIT1;
1N/A goto fsm_begin;
1N/A
1N/A case S_MACRO:
1N/A BACKIN();
1N/A#if CPP
1N/A if (st & (DISABLE|SKIPCONTROL|SKIPMACRO))
1N/A {
1N/A if (st & SKIPMACRO)
1N/A pp.mode |= MARKMACRO;
1N/A st &= ~(NEWLINE|SKIPMACRO);
1N/A pp.in->flags |= IN_tokens;
1N/A count(token);
1N/A goto fsm_start;
1N/A }
1N/A count(candidate);
1N/A SETCHR(0);
1N/A switch (state = INDEX(rp))
1N/A {
1N/A case HIT0:
1N/A tp = op - 1;
1N/A break;
1N/A case HITN:
1N/A bp = tp;
1N/A tp = op - ((pp.truncate && pp.truncate < (HITN - HIT0)) ? (pp.truncate - 1) : (HITN - HIT0));
1N/A while (tp > bp && ppisidig(*(tp - 1))) tp--;
1N/A break;
1N/A default:
1N/A bp = tp;
1N/A if ((tp = op - (state - HIT0)) > bp && *(tp - 1) == 'L') tp--;
1N/A break;
1N/A }
1N/A if (sym = ppsymref(pp.symtab, tp))
1N/A {
1N/A SYNCIN();
1N/A n = ppcall(sym, 0);
1N/A CACHEIN();
1N/A if (n >= 0)
1N/A {
1N/A BACKOUT();
1N/A if (!n)
1N/A {
1N/A if (sp) op = sp;
1N/A else
1N/A {
1N/A s = ip;
1N/A ip = sym->macro->value;
1N/A c = sym->macro->size;
1N/A while (c > 0)
1N/A {
1N/A if (op + c < xp + PPBUFSIZ) n = c;
1N/A else n = xp + PPBUFSIZ - op;
1N/A MEMCPY(op, ip, n);
1N/A c -= n;
1N/A PPCHECKOUT();
1N/A }
1N/A ip = s;
1N/A }
1N/A }
1N/A else if ((sym->flags & SYM_MULTILINE) && pp.linesync)
1N/A {
1N/A SYNCOUT();
1N/A if (!(state & NEWLINE))
1N/A ppputchar('\n');
1N/A (*pp.linesync)(error_info.line, error_info.file);
1N/A CACHEOUT();
1N/A }
1N/A }
1N/A }
1N/A pp.in->flags |= IN_tokens;
1N/A goto fsm_start;
1N/A#else
1N/A if (st & (COLLECTING|DEFINITION|DISABLE|SKIPCONTROL|SKIPMACRO))
1N/A {
1N/A if (st & SKIPMACRO)
1N/A pp.mode |= MARKMACRO;
1N/A st &= ~(NEWLINE|NOEXPAND|SKIPMACRO);
1N/A c = T_ID;
1N/A if (pp.level == 1)
1N/A {
1N/A pp.in->flags |= IN_tokens;
1N/A if (st & NOTEXT)
1N/A {
1N/A BACKOUT();
1N/A goto fsm_top;
1N/A }
1N/A if (st & COMPILE)
1N/A {
1N/A SETCHR(0);
1N/A if (pp.truncate && (op - tp) > pp.truncate) tp[pp.truncate] = 0;
1N/A sym = (pp.option & NOHASH) ? ppsymref(pp.symtab, tp) : ppsymset(pp.symtab, tp);
1N/A fsm_noise:
1N/A if (pp.symbol = sym)
1N/A {
1N/A 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)))
1N/A {
1N/A c = ((struct ppsymkey*)sym)->lex;
1N/A /*UNDENT*/
1N/A
1N/A#define ADVANCE() do{if(pp.toknxt<op)pp.token=pp.toknxt;}while(0)
1N/A
1N/A#define NOISE_BRACE 01
1N/A#define NOISE_NOSPACEOUT 02
1N/A#define NOISE_PAREN 04
1N/A
1N/A if ((pp.option & NOISE) && ppisnoise(c))
1N/A {
1N/A if (c != T_NOISE)
1N/A {
1N/A int p;
1N/A int f;
1N/A char* pptoken;
1N/A PPCOMMENT ppcomment;
1N/A
1N/A SYNCIN();
1N/A pp.toknxt = op;
1N/A f = 0;
1N/A if (!(pp.state & SPACEOUT))
1N/A {
1N/A pp.state |= SPACEOUT;
1N/A f |= NOISE_NOSPACEOUT;
1N/A }
1N/A ppcomment = pp.comment;
1N/A pp.comment = 0;
1N/A op = (pptoken = tp) + MAXTOKEN;
1N/A switch (c)
1N/A {
1N/A case T_X_GROUP:
1N/A m = p = 0;
1N/A quot = 1;
1N/A for (;;)
1N/A {
1N/A ADVANCE();
1N/A switch (c = pplex())
1N/A {
1N/A case '(':
1N/A case '{':
1N/A if (!p)
1N/A {
1N/A if (c == '(')
1N/A {
1N/A if (f & NOISE_PAREN)
1N/A {
1N/A ungetchr(c);
1N/A *--pp.toknxt = 0;
1N/A break;
1N/A }
1N/A f |= NOISE_PAREN;
1N/A p = ')';
1N/A }
1N/A else
1N/A {
1N/A f |= NOISE_BRACE|NOISE_PAREN;
1N/A p = '}';
1N/A }
1N/A n = 1;
1N/A m = c;
1N/A }
1N/A else if (c == m) n++;
1N/A quot = 0;
1N/A continue;
1N/A case ')':
1N/A case '}':
1N/A if (c == p && --n <= 0)
1N/A {
1N/A if (c == '}') break;
1N/A m = '\n';
1N/A p = 0;
1N/A }
1N/A quot = 0;
1N/A continue;
1N/A case ' ':
1N/A continue;
1N/A case '\n':
1N/A error_info.line++;
1N/A if (!m) m = '\n';
1N/A continue;
1N/A case 0:
1N/A break;
1N/A case T_ID:
1N/A if (quot) continue;
1N/A /*FALLTHROUGH*/
1N/A default:
1N/A if (m == '\n')
1N/A {
1N/A /*
1N/A * NOTE: token expanded again
1N/A */
1N/A
1N/A s = pp.toknxt;
1N/A while (s > pp.token) ungetchr(*--s);
1N/A *(pp.toknxt = s) = 0;
1N/A break;
1N/A }
1N/A continue;
1N/A }
1N/A break;
1N/A }
1N/A break;
1N/A case T_X_LINE:
1N/A for (;;)
1N/A {
1N/A ADVANCE();
1N/A switch (pplex())
1N/A {
1N/A case 0:
1N/A break;
1N/A case '\n':
1N/A error_info.line++;
1N/A break;
1N/A default:
1N/A continue;
1N/A }
1N/A break;
1N/A }
1N/A break;
1N/A case T_X_STATEMENT:
1N/A for (;;)
1N/A {
1N/A ADVANCE();
1N/A switch (pplex())
1N/A {
1N/A case 0:
1N/A break;
1N/A case ';':
1N/A ungetchr(';');
1N/A *(pp.toknxt = pp.token) = 0;
1N/A break;
1N/A default:
1N/A continue;
1N/A }
1N/A break;
1N/A }
1N/A break;
1N/A }
1N/A pp.comment = ppcomment;
1N/A if (f & NOISE_NOSPACEOUT)
1N/A pp.state &= ~SPACEOUT;
1N/A CACHEIN();
1N/A tp = pptoken;
1N/A op = pp.toknxt;
1N/A c = T_NOISES;
1N/A }
1N/A if (pp.option & NOISEFILTER)
1N/A {
1N/A BACKOUT();
1N/A goto fsm_top;
1N/A }
1N/A }
1N/A
1N/A /*INDENT*/
1N/A }
1N/A else if ((pp.option & NOISE) && c == T_ID && strneq(tp, "__builtin_", 10))
1N/A {
1N/A hashlook(pp.symtab, tp, HASH_DELETE, NiL);
1N/A pp.symbol = sym = (struct ppsymbol*)ppkeyset(pp.symtab, tp);
1N/A sym->flags |= SYM_KEYWORD;
1N/A c = ((struct ppsymkey*)sym)->lex = T_BUILTIN;
1N/A }
1N/A }
1N/A }
1N/A goto fsm_symbol;
1N/A }
1N/A goto fsm_check;
1N/A }
1N/A if (pp.level == 1)
1N/A {
1N/A st &= ~(NEWLINE|PASSEOF);
1N/A pp.in->flags |= IN_tokens;
1N/A }
1N/A else st &= ~PASSEOF;
1N/A count(candidate);
1N/A SETCHR(0);
1N/A if (sym = ppsymref(pp.symtab, tp))
1N/A {
1N/A SYNCIN();
1N/A c = ppcall(sym, 1);
1N/A CACHEIN();
1N/A if (c >= 0)
1N/A {
1N/A BACKOUT();
1N/A if ((sym->flags & SYM_MULTILINE) && pp.linesync)
1N/A {
1N/A SYNCOUT();
1N/A (*pp.linesync)(error_info.line, error_info.file);
1N/A CACHEOUT();
1N/A }
1N/A goto fsm_top;
1N/A }
1N/A }
1N/A c = T_ID;
1N/A if (pp.level == 1)
1N/A {
1N/A if (st & NOTEXT)
1N/A {
1N/A BACKOUT();
1N/A goto fsm_top;
1N/A }
1N/A if (st & COMPILE)
1N/A {
1N/A if (pp.truncate && (op - tp) > pp.truncate)
1N/A {
1N/A tp[pp.truncate] = 0;
1N/A sym = 0;
1N/A }
1N/A if (!sym)
1N/A {
1N/A if (!(pp.option & NOHASH)) sym = ppsymset(pp.symtab, tp);
1N/A else if (!(sym = ppsymref(pp.symtab, tp))) goto fsm_symbol;
1N/A }
1N/A goto fsm_noise;
1N/A }
1N/A goto fsm_symbol;
1N/A }
1N/A goto fsm_check;
1N/A#endif
1N/A
1N/A case S_SHARP:
1N/A if (c == '(')
1N/A {
1N/A pp.in->flags |= IN_tokens;
1N/A if ((st & STRICT) && pp.in->type != IN_MACRO && pp.in->type != IN_MULTILINE)
1N/A {
1N/A if (!(pp.mode & HOSTED)) error(1, "non-standard reference to #(...)");
1N/A if (st & STRICT)
1N/A {
1N/A PUTCHR(c);
1N/A#if CPP
1N/A st &= ~NEWLINE;
1N/A count(token);
1N/A goto fsm_start;
1N/A#else
1N/A break;
1N/A#endif
1N/A }
1N/A }
1N/A if (st & (COLLECTING|DEFINITION|DISABLE|SKIPCONTROL))
1N/A {
1N/A PUTCHR(c);
1N/A#if CPP
1N/A st &= ~NEWLINE;
1N/A count(token);
1N/A goto fsm_start;
1N/A#else
1N/A st &= ~NOEXPAND;
1N/A break;
1N/A#endif
1N/A }
1N/A op--;
1N/A SYNC();
1N/A ppbuiltin();
1N/A CACHE();
1N/A#if CPP
1N/A count(token);
1N/A goto fsm_start;
1N/A#else
1N/A goto fsm_top;
1N/A#endif
1N/A }
1N/A BACKIN();
1N/A#if CPP
1N/A if (!(st & NEWLINE) || !(pp.in->type & IN_TOP))
1N/A {
1N/A fsm_nondirective:
1N/A st &= ~NEWLINE;
1N/A pp.in->flags |= IN_tokens;
1N/A count(token);
1N/A goto fsm_start;
1N/A }
1N/A if (*(s = tp) != '#')
1N/A {
1N/A#if COMPATIBLE
1N/A if ((st & (COMPATIBILITY|TRANSITION)) == COMPATIBILITY) goto fsm_nondirective;
1N/A#endif
1N/A while (*s == ' ' || *s == '\t') s++;
1N/A if (*s != '#') goto fsm_nondirective;
1N/A }
1N/A BACKOUT();
1N/A#else
1N/A if (!(st & NEWLINE) || (st & DEFINITION) || !(pp.in->type & IN_TOP))
1N/A {
1N/A if (c == '#')
1N/A {
1N/A SKIPIN();
1N/A if (!(st & DEFINITION))
1N/A PUTCHR(c);
1N/A c = T_TOKCAT;
1N/A }
1N/A else if (pp.level == 1 && !(st & (JOINING|SPACEOUT)) && !(pp.option & PRESERVE))
1N/A {
1N/A char* pptoken;
1N/A char* oop;
1N/A PPCOMMENT ppcomment;
1N/A
1N/A SYNCIN();
1N/A pp.toknxt = oop = op;
1N/A pp.state |= SPACEOUT;
1N/A ppcomment = pp.comment;
1N/A pp.comment = 0;
1N/A op = (pptoken = tp) + MAXTOKEN;
1N/A for (;;)
1N/A {
1N/A ADVANCE();
1N/A switch (pplex())
1N/A {
1N/A case 0:
1N/A break;
1N/A case '\n':
1N/A error_info.line++;
1N/A break;
1N/A default:
1N/A continue;
1N/A }
1N/A break;
1N/A }
1N/A pp.comment = ppcomment;
1N/A pp.state &= ~SPACEOUT;
1N/A CACHEIN();
1N/A tp = pptoken;
1N/A *--op = 0;
1N/A op = oop;
1N/A if (pp.pragma && !(st & NOTEXT))
1N/A {
1N/A *s = 0;
1N/A SYNC();
1N/A (*pp.pragma)(NiL, NiL, NiL, tp, 1);
1N/A CACHE();
1N/A }
1N/A if (!c) BACKIN();
1N/A goto fsm_top;
1N/A }
1N/A else c = '#';
1N/A break;
1N/A }
1N/A if ((st & (COLLECTING|STRICT)) == (COLLECTING|STRICT))
1N/A error(1, "directives in macro call arguments are not portable");
1N/A#endif
1N/A if (c == '#' && pp.in->type == IN_RESCAN)
1N/A {
1N/A /*
1N/A * pass line to pp.pragma VERBATIM
1N/A */
1N/A
1N/A SKIPIN();
1N/A s = pp.valbuf;
1N/A while ((c = GETCHR()) && c != '\n')
1N/A if ((*s++ = c) == MARK) SKIPIN();
1N/A if (pp.pragma && !(st & NOTEXT))
1N/A {
1N/A *s = 0;
1N/A SYNC();
1N/A (*pp.pragma)(NiL, NiL, NiL, pp.valbuf, 1);
1N/A CACHE();
1N/A }
1N/A if (!c) BACKIN();
1N/A#if CPP
1N/A goto fsm_start;
1N/A#else
1N/A goto fsm_top;
1N/A#endif
1N/A }
1N/A SYNC();
1N/A ppcontrol();
1N/A CACHE();
1N/A#if CPP
1N/A if (st & (NOTEXT|SKIPCONTROL))
1N/A {
1N/A if (!sp)
1N/A {
1N/A PPCHECKOUTTP();
1N/A sp = tp;
1N/A }
1N/A }
1N/A else if (sp)
1N/A {
1N/A tp = op = sp;
1N/A sp = 0;
1N/A }
1N/A goto fsm_start;
1N/A#else
1N/A goto fsm_top;
1N/A#endif
1N/A
1N/A case S_NL:
1N/A#if CPP
1N/A if (op == tp && !(st & JOINING) && pp.in->type == IN_FILE && !(pp.option & PRESERVE))
1N/A {
1N/A st |= NEWLINE|HIDDEN;
1N/A pp.hidden++;
1N/A error_info.line++;
1N/A goto fsm_start;
1N/A }
1N/A#endif
1N/A fsm_newline:
1N/A#if CPP
1N/A if (sp)
1N/A op = sp;
1N/A else if (!(pp.in->flags & IN_noguard))
1N/A {
1N/A while (tp < op)
1N/A if ((c = *tp++) != ' ' && c != '\t')
1N/A {
1N/A pp.in->flags |= IN_tokens;
1N/A break;
1N/A }
1N/A c = '\n';
1N/A }
1N/A st |= NEWLINE;
1N/A error_info.line++;
1N/A if (*ip == '\n' && *(ip + 1) != '\n' && !pp.macref && !(st & (ADD|HIDDEN)))
1N/A {
1N/A ip++;
1N/A PUTCHR('\n');
1N/A error_info.line++;
1N/A }
1N/A if ((st & NOTEXT) && ((pp.mode & FILEDEPS) || (pp.option & (DEFINITIONS|PREDEFINITIONS))))
1N/A BACKOUT();
1N/A else
1N/A {
1N/A debug((-5, "token[%d] %03o = %s [line=%d]", pp.level, c, pptokchr(c), error_info.line));
1N/A PUTCHR('\n');
1N/A PPSYNCLINE();
1N/A if (sp)
1N/A {
1N/A PPCHECKOUT();
1N/A sp = op;
1N/A }
1N/A }
1N/A goto fsm_start;
1N/A#else
1N/A st |= NEWLINE;
1N/A if (pp.level == 1)
1N/A {
1N/A error_info.line++;
1N/A if (!(st & (JOINING|SPACEOUT)))
1N/A {
1N/A debug((-5, "token[%d] %03o = %s [line=%d]", pp.level, c, pptokchr(c), error_info.line));
1N/A BACKOUT();
1N/A goto fsm_top;
1N/A }
1N/A }
1N/A BACKOUT();
1N/A if (st & SKIPCONTROL)
1N/A {
1N/A error_info.line++;
1N/A st |= HIDDEN;
1N/A pp.hidden++;
1N/A goto fsm_start;
1N/A }
1N/A PUTCHR(c = '\n');
1N/A goto fsm_return;
1N/A#endif
1N/A
1N/A#if !CPP
1N/A case S_TOK:
1N/A PUTCHR(c);
1N/A c = TYPE(state) | qual;
1N/A break;
1N/A
1N/A case S_TOKB:
1N/A BACKIN();
1N/A c = TYPE(state) | qual;
1N/A break;
1N/A#endif
1N/A
1N/A case S_VS:
1N/A PUTCHR(c);
1N/A#if !CPP
1N/A if (st & NOVERTICAL)
1N/A {
1N/A error(1, "%s invalid in directives", pptokchr(c));
1N/A st &= ~NOVERTICAL;
1N/A }
1N/A#endif
1N/A#if COMPATIBLE
1N/A if (st & COMPATIBILITY) st |= NEWLINE;
1N/A#endif
1N/A#if CPP
1N/A if (!(pp.in->flags & IN_noguard))
1N/A while (tp < op)
1N/A if ((c = *tp++) != ' ' && c != '\t')
1N/A {
1N/A pp.in->flags |= IN_tokens;
1N/A break;
1N/A }
1N/A goto fsm_start;
1N/A#else
1N/A bp = ip;
1N/A rp = fsm[WS1];
1N/A goto fsm_get;
1N/A#endif
1N/A
1N/A#if !CPP
1N/A case S_WS:
1N/A#if COMPATIBLE
1N/A if ((st & (COMPATIBILITY|TRANSITION)) == COMPATIBILITY) st &= ~NEWLINE;
1N/A#endif
1N/A if (pp.level == 1)
1N/A {
1N/A if ((st & (COMPATIBILITY|SPACEOUT)) && !(st & TRANSITION))
1N/A {
1N/A if (st & (COMPILE|NOTEXT))
1N/A {
1N/A#if CATSTRINGS
1N/A if ((st & (JOINING|NOTEXT|SPACEOUT)) != SPACEOUT)
1N/A#else
1N/A if ((st & (NOTEXT|SPACEOUT)) != SPACEOUT)
1N/A#endif
1N/A {
1N/A BACKOUT();
1N/A bp = ip - 1;
1N/A rp = fsm[START];
1N/A if (state = rp[c]) goto fsm_next;
1N/A goto fsm_get;
1N/A }
1N/A }
1N/A else
1N/A#if CATSTRINGS
1N/A if (!(st & JOINING))
1N/A#endif
1N/A {
1N/A tp = op;
1N/A bp = ip - 1;
1N/A rp = fsm[START];
1N/A if (state = rp[c]) goto fsm_next;
1N/A goto fsm_get;
1N/A }
1N/A BACKIN();
1N/A c = ' ';
1N/A goto fsm_return;
1N/A }
1N/A BACKOUT();
1N/A bp = ip - 1;
1N/A rp = fsm[START];
1N/A if (state = rp[c]) goto fsm_next;
1N/A goto fsm_get;
1N/A }
1N/A if (st & (NOSPACE|SKIPCONTROL))
1N/A {
1N/A BACKOUT();
1N/A bp = ip - 1;
1N/A rp = fsm[START];
1N/A if (state = rp[c]) goto fsm_next;
1N/A goto fsm_get;
1N/A }
1N/A if (c != '\n')
1N/A {
1N/A BACKIN();
1N/A c = ' ';
1N/A }
1N/A if (!(pp.option & PRESERVE))
1N/A {
1N/A BACKOUT();
1N/A PUTCHR(c);
1N/A }
1N/A goto fsm_return;
1N/A#endif
1N/A
1N/A default:
1N/A if (state & SPLICE)
1N/A {
1N/A switch (c)
1N/A {
1N/A case MARK:
1N/A /*
1N/A * internal mark
1N/A */
1N/A
1N/A switch (pp.in->type)
1N/A {
1N/A case IN_BUFFER:
1N/A case IN_FILE:
1N/A#if !CPP
1N/A case IN_INIT:
1N/A#if CATSTRINGS
1N/A if ((st & JOINING) && (!INQUOTE(rp) || quot != '"') || pp.level > 1 && (rp == fsm[START] || INQUOTE(rp)))
1N/A#else
1N/A if (pp.level > 1 && (rp == fsm[START] || INQUOTE(rp)))
1N/A#endif
1N/A PUTCHR(c);
1N/A#endif
1N/A break;
1N/A default:
1N/A switch (GETCHR())
1N/A {
1N/A case 'A':
1N/A if (!(st & (DEFINITION|DISABLE)))
1N/A {
1N/A c = GETCHR();
1N/A SYNCIN();
1N/A if (pp.macp->arg[c - ARGOFFSET][-1])
1N/A PUSH_EXPAND(pp.macp->arg[c - ARGOFFSET], pp.macp->line);
1N/A else
1N/A PUSH_COPY(pp.macp->arg[c - ARGOFFSET], pp.macp->line);
1N/A CACHEIN();
1N/A bp = ip;
1N/A goto fsm_get;
1N/A }
1N/A /*FALLTHROUGH*/
1N/A case 'C':
1N/A c = GETCHR() - ARGOFFSET;
1N/A if (!*(s = pp.macp->arg[c]) && (pp.in->symbol->flags & SYM_VARIADIC) && pp.in->symbol->macro->arity == (c + 1))
1N/A {
1N/A s = ip - 3;
1N/A while (--op > tp && --s > bp && ppisidig(*s));
1N/A }
1N/A else
1N/A {
1N/A SYNCIN();
1N/A PUSH_COPY(s, pp.macp->line);
1N/A CACHEIN();
1N/A }
1N/A bp = ip;
1N/A goto fsm_get;
1N/A case 'F':
1N/A error_info.file = (char*)strtoul(ip, &s, 16);
1N/A debug((-6, "actual sync: file = \"%s\"", error_info.file));
1N/A bp = ip = s + 1;
1N/A goto fsm_get;
1N/A case 'L':
1N/A error_info.line = strtoul(ip, &s, 16);
1N/A debug((-6, "actual sync: line = %d", error_info.line));
1N/A bp = ip = s + 1;
1N/A goto fsm_get;
1N/A case 'Q':
1N/A c = GETCHR();
1N/A SYNCIN();
1N/A PUSH_QUOTE(pp.macp->arg[c - ARGOFFSET], pp.macp->line);
1N/A CACHEIN();
1N/A *(bp = ip - 1) = '"';
1N/A if (st & (COLLECTING|EOF2NL|JOINING)) rp = fsm[START];
1N/A if (state = rp[c = '"']) goto fsm_next;
1N/A goto fsm_get;
1N/A case 'S':
1N/A c = GETCHR();
1N/A SYNCIN();
1N/A PUSH_SQUOTE(pp.macp->arg[c - ARGOFFSET], pp.macp->line);
1N/A CACHEIN();
1N/A bp = ip - 1;
1N/A if (st & COLLECTING) rp = fsm[START];
1N/A if (state = rp[c = '\'']) goto fsm_next;
1N/A goto fsm_get;
1N/A case 'X':
1N/A if (pp.in->type != IN_COPY)
1N/A st |= SKIPMACRO;
1N/A if (pp.level <= 1)
1N/A {
1N/A bp = ip;
1N/A goto fsm_get;
1N/A }
1N/A if (pp.in->type == IN_EXPAND)
1N/A {
1N/A st &= ~SKIPMACRO;
1N/A PUTCHR(c);
1N/A PUTCHR('X');
1N/A }
1N/A c = GETCHR();
1N/A break;
1N/A case 0:
1N/A if ((state &= ~SPLICE) >= TERMINAL) goto fsm_terminal;
1N/A goto fsm_begin;
1N/A default:
1N/A#if DEBUG
1N/A error(PANIC, "invalid mark op `%c'", LASTCHR());
1N/A /*FALLTHROUGH*/
1N/A case MARK:
1N/A#endif
1N/A#if CATSTRINGS
1N/A if ((st & (JOINING|QUOTE)) == JOINING)
1N/A {
1N/A if (!INQUOTE(rp))
1N/A PUTCHR(c);
1N/A }
1N/A else
1N/A#endif
1N/A#if CPP
1N/A if (rp != fsm[START] && !INQUOTE(rp))
1N/A UNGETCHR(c);
1N/A#else
1N/A if (rp != fsm[START] && !INQUOTE(rp))
1N/A UNGETCHR(c);
1N/A else if (pp.level > 1)
1N/A PUTCHR(c);
1N/A#endif
1N/A break;
1N/A }
1N/A break;
1N/A }
1N/A break;
1N/A case '?':
1N/A /*
1N/A * trigraph
1N/A */
1N/A
1N/A if (pp.in->type == IN_FILE)
1N/A {
1N/A GET(c, n, tp, xp);
1N/A if (n == '?')
1N/A {
1N/A GET(c, n, tp, xp);
1N/A if (c = trigraph[n])
1N/A {
1N/A if ((st & WARN) && (st & (COMPATIBILITY|TRANSITION)) && !(pp.mode & HOSTED) && !INCOMMENT(rp))
1N/A error(1, "trigraph conversion %c%c%c -> %c%s", '?', '?', n, c, (st & TRANSITION) ? "" : " inhibited");
1N/A#if COMPATIBLE
1N/A if ((st & (COMPATIBILITY|TRANSITION)) != COMPATIBILITY)
1N/A {
1N/A#endif
1N/A *(bp = ip - 1) = c;
1N/A if (state = rp[c]) goto fsm_next;
1N/A goto fsm_get;
1N/A#if COMPATIBLE
1N/A }
1N/A#endif
1N/A }
1N/A if (n != EOB) BACKIN();
1N/A UNGETCHR(c = '?');
1N/A }
1N/A else if (n != EOB) BACKIN();
1N/A }
1N/A break;
1N/A case '%':
1N/A case '<':
1N/A case ':':
1N/A /*
1N/A * digraph = --trigraph
1N/A */
1N/A
1N/A if (pp.in->type == IN_FILE && (pp.option & PLUSPLUS))
1N/A {
1N/A m = 0;
1N/A GET(c, n, tp, xp);
1N/A switch (n)
1N/A {
1N/A case '%':
1N/A if (c == '<') m = '{';
1N/A break;
1N/A case '>':
1N/A if (c == '%') m = '}';
1N/A else if (c == ':') m = ']';
1N/A break;
1N/A case ':':
1N/A if (c == '%') m = '#';
1N/A else if (c == '<') m = '[';
1N/A break;
1N/A }
1N/A if (m)
1N/A {
1N/A if ((st & WARN) && (st & (COMPATIBILITY|TRANSITION)) && !(pp.mode & HOSTED) && !INCOMMENT(rp))
1N/A error(1, "digraph conversion %c%c -> %c%s", c, n, m, (st & TRANSITION) ? "" : " inhibited");
1N/A#if COMPATIBLE
1N/A if ((st & (COMPATIBILITY|TRANSITION)) != COMPATIBILITY)
1N/A {
1N/A#endif
1N/A *(bp = ip - 1) = c = m;
1N/A if (state = rp[c]) goto fsm_next;
1N/A goto fsm_get;
1N/A#if COMPATIBLE
1N/A }
1N/A#endif
1N/A }
1N/A if (n != EOB) BACKIN();
1N/A }
1N/A break;
1N/A case '\\':
1N/A /*
1N/A * line splice
1N/A */
1N/A
1N/A if (pp.in->type == IN_FILE && (!(pp.option & PLUSSPLICE) || !INCOMMENTXX(rp)))
1N/A {
1N/A m = 0;
1N/A GET(c, n, tp, xp);
1N/A if ((pp.option & SPLICESPACE) && !INQUOTE(rp))
1N/A while (n == ' ')
1N/A {
1N/A GET(c, n, tp, xp);
1N/A m = 1;
1N/A }
1N/A if (n == '\r')
1N/A {
1N/A GET(c, n, tp, xp);
1N/A if (n != '\n' && n != EOB)
1N/A BACKIN();
1N/A }
1N/A if (n == '\n')
1N/A {
1N/A#if CPP
1N/A if (INQUOTE(rp))
1N/A {
1N/A if ((pp.option & STRINGSPLIT) && quot == '"')
1N/A {
1N/A PUTCHR(quot);
1N/A PUTCHR(n);
1N/A PUTCHR(quot);
1N/A }
1N/A else if (*pp.lineid)
1N/A {
1N/A PUTCHR(c);
1N/A PUTCHR(n);
1N/A }
1N/A else
1N/A {
1N/A st |= HIDDEN;
1N/A pp.hidden++;
1N/A }
1N/A }
1N/A else
1N/A#else
1N/A#if COMPATIBLE
1N/A if (!INQUOTE(rp) && (st & (COMPATIBILITY|DEFINITION|TRANSITION)) == (COMPATIBILITY|DEFINITION))
1N/A {
1N/A if (op == tp)
1N/A {
1N/A st |= HIDDEN;
1N/A pp.hidden++;
1N/A error_info.line++;
1N/A if (st & SPACEOUT)
1N/A goto fsm_start;
1N/A c = (pp.option & SPLICECAT) ? '\t' : ' ';
1N/A PUTCHR(c);
1N/A goto fsm_check;
1N/A }
1N/A UNGETCHR(n);
1N/A state &= ~SPLICE;
1N/A goto fsm_terminal;
1N/A }
1N/A#endif
1N/A#endif
1N/A {
1N/A st |= HIDDEN;
1N/A pp.hidden++;
1N/A }
1N/A#if CPP
1N/A spliced++;
1N/A#else
1N/A error_info.line++;
1N/A#endif
1N/A bp = ip;
1N/A goto fsm_get;
1N/A }
1N/A else if ((n == 'u' || n == 'U') && !INQUOTE(rp))
1N/A {
1N/A PUTCHR(c);
1N/A PUTCHR(n);
1N/A bp = ip;
1N/A goto fsm_get;
1N/A }
1N/A#if COMPATIBLE
1N/A else if ((st & (COMPATIBILITY|TRANSITION)) == COMPATIBILITY && (n == '"' || n == '\'') && !INQUOTE(rp))
1N/A {
1N/A PUTCHR(c);
1N/A PUTCHR(n);
1N/A bp = ip;
1N/A goto fsm_get;
1N/A }
1N/A#endif
1N/A else if (n != EOB)
1N/A BACKIN();
1N/A if (m && INSPACE(rp))
1N/A UNGETCHR(c);
1N/A }
1N/A#if COMPATIBLE
1N/A else if ((st & (COMPATIBILITY|TRANSITION)) == COMPATIBILITY && !INQUOTE(rp))
1N/A {
1N/A GET(c, n, tp, xp);
1N/A if (n == '"' || n == '\'')
1N/A {
1N/A PUTCHR(c);
1N/A PUTCHR(n);
1N/A bp = ip;
1N/A goto fsm_get;
1N/A }
1N/A if (n != EOB)
1N/A BACKIN();
1N/A }
1N/A#endif
1N/A break;
1N/A case '\r':
1N/A /*
1N/A * barf
1N/A */
1N/A
1N/A if (pp.in->type == IN_FILE)
1N/A {
1N/A GET(c, n, tp, xp);
1N/A if (n == '\n')
1N/A {
1N/A *(bp = ip - 1) = c = n;
1N/A if (state = rp[c]) goto fsm_next;
1N/A goto fsm_get;
1N/A }
1N/A if (n != EOB) BACKIN();
1N/A }
1N/A break;
1N/A case CC_sub:
1N/A /*
1N/A * barf & puke
1N/A */
1N/A
1N/A if ((pp.option & ZEOF) && pp.in->type == IN_FILE)
1N/A {
1N/A pp.in->flags |= IN_eof;
1N/A c = 0;
1N/A state = S_EOB;
1N/A goto fsm_terminal;
1N/A }
1N/A break;
1N/A }
1N/A if ((state &= ~SPLICE) >= TERMINAL)
1N/A goto fsm_terminal;
1N/A PUTCHR(c);
1N/A goto fsm_begin;
1N/A }
1N/A#if CPP
1N/A if (INOPSPACE(rp))
1N/A {
1N/A BACKIN();
1N/A goto fsm_start;
1N/A }
1N/A#endif
1N/A PUTCHR(c);
1N/A bp = ip;
1N/A goto fsm_get;
1N/A }
1N/A#if !CPP
1N/A fsm_token:
1N/A st &= ~NEWLINE;
1N/A if (pp.level == 1)
1N/A {
1N/A pp.in->flags |= IN_tokens;
1N/A if (st & NOTEXT)
1N/A {
1N/A BACKOUT();
1N/A goto fsm_top;
1N/A }
1N/A fsm_symbol:
1N/A count(token);
1N/A }
1N/A fsm_check:
1N/A if (st & SKIPCONTROL)
1N/A {
1N/A BACKOUT();
1N/A goto fsm_start;
1N/A }
1N/A fsm_return:
1N/A#if CPP
1N/A error_info.line += spliced;
1N/A#endif
1N/A SETCHR(0);
1N/A debug((-5, "token[%d] %03o = %s", pp.level, c, pptokstr(tp, 0)));
1N/A SYNC();
1N/A pp.level--;
1N/A error_info.indent--;
1N/A return c;
1N/A#endif
1N/A}
1N/A
1N/A#if CPP && POOL
1N/A
1N/A#include <ls.h>
1N/A#include <wait.h>
1N/A
1N/A/*
1N/A * output pool status on exit
1N/A */
1N/A
1N/Astatic void
1N/Apoolstatus(void)
1N/A{
1N/A error(ERROR_OUTPUT|0, pp.pool.output, "%d", error_info.errors != 0);
1N/A}
1N/A
1N/A/*
1N/A * loop on < input output >
1N/A */
1N/A
1N/Astatic void
1N/Apool(void)
1N/A{
1N/A char* ifile;
1N/A char* ofile;
1N/A
1N/A ppflushout();
1N/A if (!sfnew(sfstdin, NiL, SF_UNBOUND, pp.pool.input, SF_READ))
1N/A error(ERROR_SYSTEM|3, "cannot dup pool input");
1N/A
1N/A /*
1N/A * kick the -I cache
1N/A */
1N/A
1N/A ppsearch(".", T_STRING, SEARCH_EXISTS);
1N/A
1N/A /*
1N/A * loop on < input output >
1N/A */
1N/A
1N/A pp.pool.input = 0;
1N/A while (ifile = sfgetr(sfstdin, '\n', 1))
1N/A {
1N/A if (!(ofile = strchr(ifile, ' ')))
1N/A error(3, "%s: pool output file expected", ifile);
1N/A *ofile++ = 0;
1N/A waitpid(0, NiL, WNOHANG);
1N/A switch (fork())
1N/A {
1N/A case -1:
1N/A error(ERROR_SYSTEM|3, "cannot fork pool");
1N/A case 0:
1N/A atexit(poolstatus);
1N/A error_info.errors = 0;
1N/A error_info.warnings = 0;
1N/A close(0);
1N/A if (open(ifile, O_RDONLY))
1N/A error(ERROR_SYSTEM|3, "%s: cannot read", ifile);
1N/A close(1);
1N/A if (open(ofile, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) != 1)
1N/A error(ERROR_SYSTEM|3, "%s: cannot create", ofile);
1N/A pp.outfile = ofile;
1N/A pathcanon(ifile, 0, 0);
1N/A ifile = ppsetfile(ifile)->name;
1N/A#if CHECKPOINT
1N/A if (pp.mode & DUMP)
1N/A {
1N/A if (!pp.pragma)
1N/A error(3, "#%s must be enabled for checkpoints", dirname(PRAGMA));
1N/A (*pp.pragma)(dirname(PRAGMA), pp.pass, keyname(X_CHECKPOINT), pp.checkpoint, 1);
1N/A }
1N/A#endif
1N/A PUSH_FILE(ifile, 0);
1N/A return;
1N/A }
1N/A }
1N/A while (wait(NiL) != -1);
1N/A}
1N/A
1N/A#endif