da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/***********************************************************************
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* This software is part of the ast package *
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz* Copyright (c) 1986-2009 AT&T Intellectual Property *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* and is licensed under the *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Common Public License, Version 1.0 *
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin* by AT&T Intellectual Property *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* A copy of the License is available at *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Information and Software Systems Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* AT&T Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Florham Park NJ *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Glenn Fowler <gsf@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin***********************************************************************/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Glenn Fowler
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * AT&T Research
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * preprocessor lexical analyzer
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * standalone and tokenizing lexer combined in one source
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * define CPP=1 for standalone
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * standalone entry point
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define CACHE() do{CACHEINX();CACHEOUTX();st=pp.state;if(!pp.hidden)spliced=0;}while(0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define CACHEIN() do{CACHEINX();st=pp.state;if(!pp.hidden)spliced=0;}while(0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define CACHEOUT() do{CACHEOUTX();st=pp.state;if(!pp.hidden)spliced=0;}while(0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define CACHEOUTX() do{tp=op=pp.outp;xp=pp.oute;if(sp)sp=op;}while(0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define SYNC() do{SYNCINX();SYNCOUTX();pp.state=st;}while(0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define SYNCOUTX() do{if(sp)op=tp=sp;pp.outp=op;}while(0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#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)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#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)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#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)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (m-- > 0) \
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin } while (0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * <wait.h> is poison here so pool moved to the end
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic void poolstatus(void);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic void pool(void);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * return next pp token
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * NOTE: pp.token points to at least MAXTOKEN*2 chars and is
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * truncated back to MAXTOKEN on EOB
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define DOSTRIP() ((st&STRIP)||pp.level==1&&(st&(COMPILE|JOINING))==COMPILE&&!(pp.option&PRESERVE))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int c;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin } while (state > 0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (((state = ~state) != S_COMMENT || pp.comment || c == '/' && !INCOMMENT(rp)) && (n = ip - bp - 1) > 0)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if (op == tp && (st & (ADD|HIDDEN)) && !(st & PASSTHROUGH) && !(pp.option & PRESERVE))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /*FALLTHROUGH*/
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if ((pp.option & PRESERVE) && !(st & NEWLINE) && c != '\n')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin hit[(state & SPLICE) ? (elementsof(hit) - 1) : (TERM(state) - TERMINAL)]++;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin 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)));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (c)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case '\n':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(1, "/* appears in /* ... */ comment starting at line %d", comstart);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (comstart) error(2, "unterminated /* ... */ comment starting at line %d", comstart);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (INCOMMENTXX(rp)) error(2, "unterminated // ... comment");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(pp.state & COMPATIBILITY) || *bp == ' ' || *bp == '\t')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (pp.comment && !(st & (COLLECTING|DIRECTIVE|JOINING)) && !(*pp.control & SKIP) && (pp.in->type & IN_TOP))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin m = (op - (c != '\n') - tp > MAXTOKEN - 6) ? (error_info.line - MAXHIDDEN) : 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin (*pp.comment)(c == '\n' ? "//" : "/*", tp + 2, c == '\n' ? "" : (st & HEADER) ? "*/\n" : "*/", comstart ? comstart : error_info.line);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((st & PASSTHROUGH) && ((st & (HIDDEN|NEWLINE)) || *ip == '\n'))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((st & (COMPATIBILITY|TRANSITION)) == COMPATIBILITY) st &= ~NEWLINE;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin c = ((st & (COMPATIBILITY|DEFINITION)) == ((COMPATIBILITY|DEFINITION))) ? '\t' : ' ';
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(2, "#%s on line %d has no #%s", dirname(IF), GETIFLINE(pp.control+1), dirname(ENDIF));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /*FALLTHROUGH*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (prv->type == IN_FILE || cur->type == IN_FILE && (prv->type == IN_RESCAN || prv->type == IN_MULTILINE))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (pp.linesync && (cur->type != IN_RESCAN || (cur->flags & IN_sync)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /*UNDENT*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfprintf(sfstderr, "%7d: pplex calls\n", pp.counter.pplex);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfprintf(sfstderr, "%7d: terminal states\n", pp.counter.terminal);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfprintf(sfstderr, "%7d: emitted tokens\n", pp.counter.token);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfprintf(sfstderr, "%7d: input stream pushes\n", pp.counter.push);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfprintf(sfstderr, "%7d: macro candidates\n", pp.counter.candidate);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfprintf(sfstderr, "%7d: macro expansions\n", pp.counter.macro);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfprintf(sfstderr, "%7d: function macros\n", pp.counter.function);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfprintf(sfstderr, "%7d: SPLICE\n", hit[elementsof(hit) - 1]);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfprintf(sfstderr, "%7d: %s\n", hit[n], pplexstr(TERMINAL + n));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin hashdump(NiL, (pp.test & TEST_hashdump) ? HASH_BUCKET : 0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /*INDENT*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((st & (NOTEXT|HIDDEN)) == HIDDEN && LASTOUT() != '\n')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((pp.mode & (HOSTED|PEDANTIC)) == PEDANTIC && LASTCHR() != '\f' && LASTCHR() != CC_sub)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(cur->flags & (IN_noguard|IN_tokens)) && cur->symbol)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin (*pp.incref)(error_info.file, cur->file, error_info.line - 1, PP_SYNC_POP);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (prv && (!INMACRO(rp) || (st & (COMPATIBILITY|TRANSITION)) == COMPATIBILITY && ppismac(*prv->nextchr)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(2, "#%s on line %d has no #%s", dirname(IF), GETIFLINE(pp.control+1), dirname(ENDIF));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(st & COMPATIBILITY) && ppisidig(*(op - 1)) && ppisidig(*ip)) UNGETCHR(' ');
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(st & PASSEOF) && !(cur->flags & IN_expand) && prv)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (c == '=')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (st & (STRICT|WARN)) error(1, "%-*.*s: space ignored in operator", op - tp, op - tp, tp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (c = *tp)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (pp.level > 1 || (pp.option & PRESERVE)) PUTCHR(c);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(1, "%s: invalid character ignored", pptokchr(c));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else c = '+';
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (c)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /*FALLTHROUGH*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin 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)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if ((st & PASSTHROUGH) || (pp.option & PRESERVE))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (c == '\n' && quot == '\'' && (pp.option & STRINGSPAN)) n = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((st & (COMPATIBILITY|DEFINITION)) != (COMPATIBILITY|DEFINITION))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (c == '\n')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(pp.option & STRINGSPAN) || (st & (COMPATIBILITY|STRICT)) == STRICT)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case '\'':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (c == '\n')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (c == '"' && !(st & (COLLECTING|NOTEXT|PASSTHROUGH|SKIPCONTROL)) && (pp.mode & CATLITERAL))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (c == '"' && pp.level == 1 && !(st & (COLLECTING|JOINING|NOTEXT|SKIPCONTROL)) && (pp.mode & CATLITERAL))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * revert to the top level since string
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * concatenation crosses file boundaries
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * (allowing intervening directives)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin m = n = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (c = pplex())
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case '\n':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /*FALLTHROUGH*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((st & COMPATIBILITY) && c == '#' && *(pp.token - 1))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (pp.in->type == IN_MACRO && (s = strchr(pp.token, MARK)) && !*(s + 1))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *(s + 2) = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (n && !(st & (PASSTHROUGH|SKIPCONTROL|NOTEXT)) && c == '\'' && (op - tp) <= 2 && !(pp.mode & (HOSTED|RELAX)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case '\'':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (n && !(st & NOTEXT) && (op - tp) <= (DOSTRIP() ? 0 : 2) && !(pp.mode & (HOSTED|RELAX)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else switch (c)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case '\\':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case '\'':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (st & STRICT) error(1, "%c: invalid character in octal character escape", c);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /*FALLTHROUGH*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = c - '0';
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (m = 0; m < 2; m++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (c)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (st & STRICT) error(1, "%c: invalid character in octal character escape", c);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /*FALLTHROUGH*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (n & ~0777) error(1, "octal character constant too large");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (m = 0; m < 3; m++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (c)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!m) error(1, "\\x%c: invalid character in hexadecimal character constant", c);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (n & ~0777) error(1, "hexadecimal character constant too large");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (st & (STRICT|WARN)) error(1, "\\%c: non-standard character constant", c);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin tp = op - ((pp.truncate && pp.truncate < (HITN - HIT0)) ? (pp.truncate - 1) : (HITN - HIT0));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((tp = op - (state - HIT0)) > bp && *(tp - 1) == 'L') tp--;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (n >= 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (c > 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (st & (COLLECTING|DEFINITION|DISABLE|SKIPCONTROL|SKIPMACRO))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (pp.truncate && (op - tp) > pp.truncate) tp[pp.truncate] = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sym = (pp.option & NOHASH) ? ppsymref(pp.symtab, tp) : ppsymset(pp.symtab, tp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin 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)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /*UNDENT*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define ADVANCE() do{if(pp.toknxt<op)pp.token=pp.toknxt;}while(0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (c)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin m = p = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (c = pplex())
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (c == '(')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (c == m) n++;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (c == p && --n <= 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (c == '}') break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case '\n':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!m) m = '\n';
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (quot) continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /*FALLTHROUGH*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (m == '\n')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * NOTE: token expanded again
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case '\n':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /*INDENT*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if ((pp.option & NOISE) && c == T_ID && strneq(tp, "__builtin_", 10))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pp.symbol = sym = (struct ppsymbol*)ppkeyset(pp.symtab, tp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (c >= 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(pp.option & NOHASH)) sym = ppsymset(pp.symtab, tp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (!(sym = ppsymref(pp.symtab, tp))) goto fsm_symbol;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (c == '(')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((st & STRICT) && pp.in->type != IN_MACRO && pp.in->type != IN_MULTILINE)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(pp.mode & HOSTED)) error(1, "non-standard reference to #(...)");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((st & (COMPATIBILITY|TRANSITION)) == COMPATIBILITY) goto fsm_nondirective;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(st & NEWLINE) || (st & DEFINITION) || !(pp.in->type & IN_TOP))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (c == '#')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (pp.level == 1 && !(st & (JOINING|SPACEOUT)) && !(pp.option & PRESERVE))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case '\n':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else c = '#';
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(1, "directives in macro call arguments are not portable");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * pass line to pp.pragma VERBATIM
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if (op == tp && !(st & JOINING) && pp.in->type == IN_FILE && !(pp.option & PRESERVE))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (*ip == '\n' && *(ip + 1) != '\n' && !pp.macref && !(st & (ADD|HIDDEN)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((st & NOTEXT) && ((pp.mode & FILEDEPS) || (pp.option & (DEFINITIONS|PREDEFINITIONS))))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin debug((-5, "token[%d] %03o = %s [line=%d]", pp.level, c, pptokchr(c), error_info.line));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin debug((-5, "token[%d] %03o = %s [line=%d]", pp.level, c, pptokchr(c), error_info.line));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((st & (COMPATIBILITY|TRANSITION)) == COMPATIBILITY) st &= ~NEWLINE;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((st & (COMPATIBILITY|SPACEOUT)) && !(st & TRANSITION))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (c != '\n')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (c)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * internal mark
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((st & JOINING) && (!INQUOTE(rp) || quot != '"') || pp.level > 1 && (rp == fsm[START] || INQUOTE(rp)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin PUSH_EXPAND(pp.macp->arg[c - ARGOFFSET], pp.macp->line);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /*FALLTHROUGH*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!*(s = pp.macp->arg[c]) && (pp.in->symbol->flags & SYM_VARIADIC) && pp.in->symbol->macro->arity == (c + 1))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin debug((-6, "actual sync: file = \"%s\"", error_info.file));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin debug((-6, "actual sync: line = %d", error_info.line));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin PUSH_QUOTE(pp.macp->arg[c - ARGOFFSET], pp.macp->line);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin PUSH_SQUOTE(pp.macp->arg[c - ARGOFFSET], pp.macp->line);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /*FALLTHROUGH*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * trigraph
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (n == '?')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (c = trigraph[n])
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((st & WARN) && (st & (COMPATIBILITY|TRANSITION)) && !(pp.mode & HOSTED) && !INCOMMENT(rp))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(1, "trigraph conversion %c%c%c -> %c%s", '?', '?', n, c, (st & TRANSITION) ? "" : " inhibited");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((st & (COMPATIBILITY|TRANSITION)) != COMPATIBILITY)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * digraph = --trigraph
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (n)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((st & WARN) && (st & (COMPATIBILITY|TRANSITION)) && !(pp.mode & HOSTED) && !INCOMMENT(rp))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(1, "digraph conversion %c%c -> %c%s", c, n, m, (st & TRANSITION) ? "" : " inhibited");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((st & (COMPATIBILITY|TRANSITION)) != COMPATIBILITY)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case '\\':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * line splice
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (pp.in->type == IN_FILE && (!(pp.option & PLUSSPLICE) || !INCOMMENTXX(rp)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (n == ' ')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (n == '\r')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (n == '\n')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!INQUOTE(rp) && (st & (COMPATIBILITY|DEFINITION|TRANSITION)) == (COMPATIBILITY|DEFINITION))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if ((st & (COMPATIBILITY|TRANSITION)) == COMPATIBILITY && (n == '"' || n == '\'') && !INQUOTE(rp))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (n != EOB)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if ((st & (COMPATIBILITY|TRANSITION)) == COMPATIBILITY && !INQUOTE(rp))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case '\r':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (n == '\n')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * barf & puke
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin debug((-5, "token[%d] %03o = %s", pp.level, c, pptokstr(tp, 0)));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * output pool status on exit
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic void
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_OUTPUT|0, pp.pool.output, "%d", error_info.errors != 0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * loop on < input output >
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic void
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!sfnew(sfstdin, NiL, SF_UNBOUND, pp.pool.input, SF_READ))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * kick the -I cache
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * loop on < input output >
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (fork())
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (open(ofile, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) != 1)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!pp.pragma)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(3, "#%s must be enabled for checkpoints", dirname(PRAGMA));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin (*pp.pragma)(dirname(PRAGMA), pp.pass, keyname(X_CHECKPOINT), pp.checkpoint, 1);