/* * Check for (and convert) trigraphs. */ static int chktg(void) { int ch; if ((ch = inpch()) != '?') { unch(ch); return 0; } switch (ch = inpch()) { case '=': return '#'; case '(': return '['; case ')': return ']'; case '<': return '{'; case '>': return '}'; case '/': return '\\'; case '\'': return '^'; case '!': return '|'; case '-': return '~'; } unch(ch); unch('?'); return 0; }
/* * Check for (and convert) trigraphs. */ int chktg() { int c; if ((c = inpch()) != '?') { unch(c); return 0; } switch (c = inpch()) { case '=': c = '#'; break; case '(': c = '['; break; case ')': c = ']'; break; case '<': c = '{'; break; case '>': c = '}'; break; case '/': c = '\\'; break; case '\'': c = '^'; break; case '!': c = '|'; break; case '-': c = '~'; break; default: unch(c); unch('?'); c = 0; } return c; }
/* * check for (and eat) end-of-line */ static int chkeol(void) { int ch; ch = inpch(); if (ch == '\r') { ch = inpch(); if (ch == '\n') return '\n'; unch(ch); unch('\r'); return 0; } if (ch == '\n') return '\n'; unch(ch); return 0; }
/* * return next char, after converting trigraphs and * skipping escaped line endings */ static inline int inch(void) { int ch; for (;;) { ch = inpch(); if (ch == '?' && (ch = chktg()) == 0) return '?'; if (ch != '\\' || chkeol() == 0) return ch; ifiles->escln++; } }
static int inch(void) { int c; again: switch (c = inpch()) { case '\\': /* continued lines */ msdos: if ((c = inpch()) == '\n') { ifiles->lineno++; goto again; } else if (c == '\r') goto msdos; unch(c); return '\\'; case '?': /* trigraphs */ if ((c = chktg())) { unch(c); goto again; } return '?'; default: return c; } }
static int inpch(void) { int len; if (ifiles->curptr < ifiles->maxread) return *ifiles->curptr++; if (ifiles->infil == -1) return -1; if ((len = read(ifiles->infil, ifiles->buffer, CPPBUF)) < 0) error("read error on file %s", ifiles->orgfn); if (len == 0) return -1; ifiles->curptr = ifiles->buffer; ifiles->maxread = ifiles->buffer + len; return inpch(); }
int yylex() { static int ifdef, noex; struct symtab *nl; int ch, c2; while ((ch = sloscan()) == WSPACE) ; if (ch < 128 && spechr[ch] & C_2) c2 = inpch(); else c2 = 0; #define C2(a,b,c) case a: if (c2 == b) return c; break switch (ch) { C2('=', '=', EQ); C2('!', '=', NE); C2('|', '|', OROR); C2('&', '&', ANDAND); case '<': if (c2 == '<') return LS; if (c2 == '=') return LE; break; case '>': if (c2 == '>') return RS; if (c2 == '=') return GE; break; case '+': case '-': if (ch == c2) badop(""); break; case '/': if (Cflag == 0 || c2 != '*') break; /* Found comment that need to be skipped */ for (;;) { ch = inpch(); c1: if (ch != '*') continue; if ((ch = inpch()) == '/') break; goto c1; } return yylex(); case NUMBER: if (yytext[0] == '\'') { yylval.node.op = NUMBER; yylval.node.nd_val = charcon((usch *)yytext); } else cvtdig(yytext[0] != '0' ? 10 : yytext[1] == 'x' || yytext[1] == 'X' ? 16 : 8); return NUMBER; case IDENT: if (strcmp(yytext, "defined") == 0) { ifdef = 1; return DEFINED; } nl = lookup((usch *)yytext, FIND); if (ifdef) { yylval.node.nd_val = nl != NULL; ifdef = 0; } else if (nl && noex == 0) { usch *c, *och = stringbuf; c = gotident(nl); unch(1); unpstr(c); stringbuf = och; noex = 1; return yylex(); } else { yylval.node.nd_val = 0; } yylval.node.op = NUMBER; return NUMBER; case 1: /* WARN */ noex = 0; return yylex(); default: return ch; } unch(c2); return ch; }