From 50aeef05f9f8fdb2e56ddc201b1ae7a8d56e3233 Mon Sep 17 00:00:00 2001 From: Michael Forney Date: Sun, 24 Feb 2019 20:21:59 -0800 Subject: Use a stack of scanners This is necessary to implement the #include directive. --- main.c | 4 +--- pp.c | 6 +++--- scan.c | 50 +++++++++++++++++++++++++++++++++++--------------- scan.h | 4 ++-- 4 files changed, 41 insertions(+), 23 deletions(-) diff --git a/main.c b/main.c index 89e0b18..d526bae 100644 --- a/main.c +++ b/main.c @@ -37,12 +37,10 @@ main(int argc, char *argv[]) if (argc > 1) usage(); - if (argc == 1 && !freopen(argv[0], "r", stdin)) - fatal("open %s:", argv[0]); if (output && !freopen(output, "w", stdout)) fatal("open %s:", output); - ppinit(argc ? argv[0] : ""); + ppinit(argv[0]); if (pponly) { while (tok.kind != TEOF) { tokprint(&tok); diff --git a/pp.c b/pp.c index 9772499..3cb4244 100644 --- a/pp.c +++ b/pp.c @@ -8,7 +8,6 @@ #include "scan.h" #include "token.h" -static struct scanner *scanner; static struct token pending; static void @@ -85,14 +84,15 @@ keyword(struct token *tok) void ppinit(const char *file) { - scanner = mkscanner(file); + if (scanfrom(file) < 0) + fatal("open %s:", file); next(); } static void nextinto(struct token *t) { - do scan(scanner, t); + do scan(t); while (t->kind == TNEWLINE); if (t->kind == TIDENT) keyword(t); diff --git a/scan.c b/scan.c index e6b7d70..8db5136 100644 --- a/scan.c +++ b/scan.c @@ -16,10 +16,14 @@ struct buffer { struct scanner { int chr; bool usebuf; + FILE *file; struct location loc; struct buffer buf; + struct scanner *next; }; +static struct scanner *scanner; + static void bufadd(struct buffer *b, char c) { @@ -51,16 +55,16 @@ nextchar(struct scanner *s) if (s->usebuf) bufadd(&s->buf, s->chr); for (;;) { - s->chr = getchar(); + s->chr = getc(s->file); if (s->chr == '\n') ++s->loc.line, s->loc.col = 1; else ++s->loc.col; if (s->chr != '\\') break; - c = getchar(); + c = getc(s->file); if (c != '\n') { - ungetc(c, stdin); + ungetc(c, s->file); break; } ++s->loc.line, s->loc.col = 1; @@ -337,7 +341,7 @@ again: loc = s->loc; nextchar(s); if (s->chr != '.') { - ungetc(s->chr, stdout); + ungetc(s->chr, s->file); s->loc = loc; s->chr = '.'; return TPERIOD; @@ -372,32 +376,48 @@ again: } } -struct scanner * -mkscanner(const char *file) +int +scanfrom(const char *name) { struct scanner *s; + FILE *file; + if (name) { + file = fopen(name, "r"); + if (!file) + return -1; + } else { + file = stdin; + name = ""; + } s = xmalloc(sizeof(*s)); + s->file = file; s->buf.str = NULL; s->buf.len = 0; s->buf.cap = 0; s->usebuf = false; - s->loc.file = file; + s->loc.file = name; s->loc.line = 1; s->loc.col = 0; + s->next = scanner; + scanner = s; nextchar(s); - - return s; + return 0; } void -scan(struct scanner *s, struct token *t) +scan(struct token *t) { - t->loc = s->loc; - t->kind = scankind(s); - if (s->usebuf) { - t->lit = bufget(&s->buf); - s->usebuf = false; + for (;;) { + t->loc = scanner->loc; + t->kind = scankind(scanner); + if (t->kind != TEOF || !scanner->next) + break; + scanner = scanner->next; + } + if (scanner->usebuf) { + t->lit = bufget(&scanner->buf); + scanner->usebuf = false; } else { t->lit = NULL; } diff --git a/scan.h b/scan.h index eaf3c6d..ebfd513 100644 --- a/scan.h +++ b/scan.h @@ -1,4 +1,4 @@ struct token; -struct scanner *mkscanner(const char *file); -void scan(struct scanner *, struct token *); +int scanfrom(const char *file); +void scan(struct token *); -- cgit v1.2.3