scc

Simple C99 Compiler
Log | Files | Refs | README | LICENSE

commit 669e2ebc23002ffab0e05b1e9c97bf54a7ad9f4d
parent 2edbdb8b2a7914d14f1b080179a057879144378e
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Thu,  7 May 2015 15:50:39 +0200

Add FILE* to input

Diffstat:
cc1/cc1.h | 1+
cc1/decl.c | 3++-
cc1/lex.c | 114++++++++++++++++++++++++++++++++++++++++++++++---------------------------------
cc1/main.c | 7++-----
4 files changed, 72 insertions(+), 53 deletions(-)

diff --git a/cc1/cc1.h b/cc1/cc1.h @@ -265,6 +265,7 @@ extern void discard(void); extern char *filename(void); extern unsigned short fileline(void); extern void addinput(char *fname); +extern void delinput(void); #define accept(t) ((yytoken == (t)) ? next() : 0) /* code.c */ diff --git a/cc1/decl.c b/cc1/decl.c @@ -501,7 +501,8 @@ extdecl(void) extern jmp_buf recover; setsafe(END_DECL); - setjmp(recover); + if (setjmp(recover)) + return; switch (yytoken) { case IDEN: case TYPE: case TYPEIDEN: case SCLASS: case TQUALIFIER: diff --git a/cc1/lex.c b/cc1/lex.c @@ -15,6 +15,7 @@ typedef struct input Input; struct input { char *fname; unsigned short nline; + FILE *fp; struct input *next; }; @@ -34,28 +35,46 @@ addinput(char *fname) ip = xmalloc(sizeof(Input)); ip->next = input; + if (fname) { - if (!freopen(fname, "r", stdin)) - die("file '%s' not found", fname); + if ((ip->fp = fopen(fname, "r")) == NULL) + die("file '%s' not found", fname); ip->fname = xstrdup(fname); - ip->nline = 1; + } else if (!input) { + ip->fp = stdin; + ip->fname = "(stdin)"; } else { - ip->fname = NULL; - ip->nline = (input) ? input->nline : 1; + ip->fname = input->fname; + ip->fp = NULL; + ip->nline = input->nline; + return; } + + ip->nline = 1; input = ip; + next(); +} + +void +delinput(void) +{ + Input *ip = input; + FILE *fp = ip->fp; + + if (fp) { + if (fclose(fp)) + die("error reading from input file '%s'", ip->fname); + if (strcmp("(stdin)", input->fname)) + free(ip->fname); + } + input = ip->next; + free(ip); } char * filename(void) { - Input *ip; - - for (ip = input; ip; ip = ip->next) { - if (ip->fname) - return ip->fname; - } - return "(stdin)"; + return input->fname; } unsigned short @@ -81,7 +100,7 @@ integer(char *s, char base) size = sign = 0; type: - switch (ch = toupper(getchar())) { + switch (ch = toupper(getc(input->fp))) { case 'L': if (size == LLONG) goto wrong_type; @@ -92,7 +111,7 @@ type: goto wrong_type; goto type; default: - ungetc(ch, stdin); + ungetc(ch, input->fp); tp = ctype(INT, sign, size); break; wrong_type: @@ -114,7 +133,7 @@ digits(uint8_t base) char ch, *bp; for (bp = yytext ; bp < &yytext[IDENTSIZ]; *bp++ = ch) { - ch = getchar(); + ch = getc(input->fp); switch (base) { case 8: if (ch >= '7') @@ -134,7 +153,7 @@ end: if (bp == &yytext[IDENTSIZ]) error("number too long %s", yytext); *bp = '\0'; - ungetc(ch, stdin); + ungetc(ch, input->fp); return yytext; } @@ -144,16 +163,16 @@ number(void) char ch; static char base; - if ((ch = getchar()) == '0') { - if (toupper(ch = getchar()) == 'X') { + if ((ch = getc(input->fp)) == '0') { + if (toupper(ch = getc(input->fp)) == 'X') { base = 16; } else { base = 8; - ungetc(ch, stdin); + ungetc(ch, input->fp); } } else { base = 10; - ungetc(ch, stdin); + ungetc(ch, input->fp); } return integer(digits(base), base); @@ -166,7 +185,7 @@ escape(char *s) int c; repeat: - switch (getchar()) { + switch (getc(input->fp)) { case '\\': c = '\''; break; case 'a': c = '\a'; break; case 'f': c = '\f'; break; @@ -189,7 +208,7 @@ repeat: break; case '\n': newline(); - if ((c = getchar()) == '\\') + if ((c = getc(input->fp)) == '\\') goto repeat; break; default: @@ -207,11 +226,11 @@ character(void) static char c; Symbol *sym; - getchar(); /* discard the initial ' */ - c = getchar(); + getc(input->fp); /* discard the initial ' */ + c = getc(input->fp); if (c == '\\') escape(&c); - if (getchar() != '\'') + if (getc(input->fp) != '\'') error("invalid character constant"); sym = install("", NS_IDEN); sym->u.i = c; @@ -228,10 +247,10 @@ string(void) int c; static Symbol *sym; - getchar(); /* discard the initial " */ + getc(input->fp); /* discard the initial " */ for (bp = buf; bp < &buf[STRINGSIZ]; ) { - switch (c = getchar()) { + switch (c = getc(input->fp)) { case EOF: error("found EOF while parsing"); case '"': @@ -263,13 +282,13 @@ iden(void) Symbol *sym; for (bp = yytext; bp < &yytext[IDENTSIZ]; *bp++ = c) { - if (!isalnum(c = getchar()) && c != '_') + if (!isalnum(c = getc(input->fp)) && c != '_') break; } if (bp == &yytext[IDENTSIZ]) error("identifier too long %s", yytext); *bp = '\0'; - ungetc(c, stdin); + ungetc(c, input->fp); sym = yylval.sym = lookup(yytext, lex_ns); if (!sym || sym->token == IDEN) @@ -281,21 +300,21 @@ iden(void) static uint8_t follow(int expect, int ifyes, int ifno) { - int c = getchar(); + int c = getc(input->fp); if (c == expect) { yytext[1] = c; yytext[2] = 0; return ifyes; } - ungetc(c, stdin); + ungetc(c, input->fp); return ifno; } static uint8_t minus(void) { - int c = getchar(); + int c = getc(input->fp); yytext[1] = c; yytext[2] = '\0'; @@ -305,7 +324,7 @@ minus(void) case '=': return SUB_EQ; default: yytext[1] = '\0'; - ungetc(c, stdin); + ungetc(c, input->fp); return '-'; } } @@ -313,7 +332,7 @@ minus(void) static uint8_t plus(void) { - int c = getchar(); + int c = getc(input->fp); yytext[1] = c; yytext[2] = '\0'; @@ -322,7 +341,7 @@ plus(void) case '=': return ADD_EQ; default: yytext[1] = '\0'; - ungetc(c, stdin); + ungetc(c, input->fp); return '+'; } } @@ -330,7 +349,7 @@ plus(void) static uint8_t relational(uint8_t op, uint8_t equal, uint8_t shift, uint8_t assig) { - int c = getchar(); + int c = getc(input->fp); yytext[1] = c; yytext[2] = '\0'; @@ -339,7 +358,7 @@ relational(uint8_t op, uint8_t equal, uint8_t shift, uint8_t assig) return equal; if (c == op) return follow('=', assig, shift); - ungetc(c, stdin); + ungetc(c, input->fp); yytext[1] = '\0'; return op; } @@ -347,7 +366,7 @@ relational(uint8_t op, uint8_t equal, uint8_t shift, uint8_t assig) static uint8_t logic(uint8_t op, uint8_t equal, uint8_t logic) { - int c = getchar(); + int c = getc(input->fp); yytext[1] = c; yytext[2] = '\0'; @@ -356,7 +375,7 @@ logic(uint8_t op, uint8_t equal, uint8_t logic) return equal; if (c == op) return logic; - ungetc(c, stdin); + ungetc(c, input->fp); yytext[1] = '\0'; return op; } @@ -366,10 +385,10 @@ dot(void) { int c; - if ((c = getchar()) != '.') { - ungetc(c, stdin); + if ((c = getc(input->fp)) != '.') { + ungetc(c, input->fp); return '.'; - } else if ((c = getchar()) != '.') { + } else if ((c = getc(input->fp)) != '.') { error("incorrect token '%s'", yytext); } else { yytext[2] = yytext[1] = '.'; @@ -381,7 +400,7 @@ dot(void) static uint8_t operator(void) { - uint8_t c = getchar(); + uint8_t c = getc(input->fp); yytext[0] = c; yytext[1] = '\0'; @@ -408,7 +427,7 @@ skipspaces(void) int c; - while (isspace(c = getchar())) { + while (isspace(c = getc(input->fp))) { if (c == '\n') newline(); } @@ -420,7 +439,7 @@ next(void) { int c; - ungetc(c = skipspaces(), stdin); + ungetc(c = skipspaces(), input->fp); if (isalpha(c) || c == '_') { yytoken = iden(); @@ -457,7 +476,7 @@ ahead(void) { int c; - ungetc(c = skipspaces(), stdin); + ungetc(c = skipspaces(), input->fp); return c; } @@ -494,8 +513,9 @@ discard(void) goto jump; break; } - } while ((c = getchar()) != EOF); + } while ((c = getc(input->fp)) != EOF); + c = EOFTOK; jump: yytoken = c; longjmp(recover, 1); diff --git a/cc1/main.c b/cc1/main.c @@ -66,15 +66,12 @@ main(int argc, char *argv[]) usage(); ikeywords(); - addinput(*argv); - - next(); + addinput(*argv); while (yytoken != EOFTOK) extdecl(); + delinput(); - if (fclose(stdin)) - die("error reading from input:%s", strerror(errno)); if (fclose(stdout)) die("error writing in output:%s", strerror(errno)); return 0;