aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Noll <nbnoll@eml.cc>2020-05-22 17:14:48 -0700
committerNicholas Noll <nbnoll@eml.cc>2020-05-22 17:14:48 -0700
commit69487ed29aed49ca0e3481e9783e02e9156258b2 (patch)
tree2d66daf2f8798b0ae8595f8cea593e076dbe971c
parent0d5942d8deaa70427df6df016b3ed9dedfb65b0d (diff)
fix: encapsulated the IO stack into the lexer
-rw-r--r--sys/cmd/cc/ast.c6
-rw-r--r--sys/cmd/cc/cc.c182
-rw-r--r--sys/cmd/cc/cc.h123
-rw-r--r--sys/cmd/cc/lex.c147
-rw-r--r--sys/cmd/cc/pp.c13
5 files changed, 249 insertions, 222 deletions
diff --git a/sys/cmd/cc/ast.c b/sys/cmd/cc/ast.c
index 4553b96..184ddaf 100644
--- a/sys/cmd/cc/ast.c
+++ b/sys/cmd/cc/ast.c
@@ -1275,12 +1275,10 @@ Bad:
// -----------------------------------------------------------------------
// top level api
-void
+error
parse(Parser *p, Lexer *lx)
{
Token tok;
- p->sp = p->spstk;
-
while ((tok = peek(p, 0)), tok.kind > Aeof) {
if (p->ast.len >= p->ast.cap) {
p->ast.cap += 20;
@@ -1288,4 +1286,6 @@ parse(Parser *p, Lexer *lx)
}
p->ast.decls[p->ast.len++] = decl(p, lx);
}
+
+ return 0;
}
diff --git a/sys/cmd/cc/cc.c b/sys/cmd/cc/cc.c
index cf479f8..c06d1c3 100644
--- a/sys/cmd/cc/cc.c
+++ b/sys/cmd/cc/cc.c
@@ -92,89 +92,6 @@ END:
}
// -----------------------------------------------------------------------
-// io buffer management
-
-#define asrdr(x) (io·Reader){(int (*)(void *, int, int, void *))x}
-// path should be absolute
-Io*
-openio(byte *path)
-{
- string *it, *end;
- Stream *f;
-
- intern(&path);
-
- // See if we have already opened file;
- // If so, and it hasn't been flagged return it
- for (it = C.omit.path, end = it + C.omit.len; it < end; ++it) {
- if ((uintptr)(*it) == (uintptr)(path))
- return nil;
- }
-
- // TODO: See if we have already loaded the file
- //
- if ((C.io - C.iostk) >= arrlen(C.iostk)-1)
- panicf("out of I/O space!");
-
- C.io->f = io·open(path, "r");
- if (!C.io->f)
- panicf("file %s not found", path);
-
- C.io->kind = IOfile;
- C.io->path = path;
- bufio·initreader(&C.io->rdr, asrdr(io·read), C.io->f);
-
- return C.io++;
-}
-
-Io*
-makeio(byte *name)
-{
- if ((C.io - C.iostk) >= arrlen(C.iostk)-1)
- panicf("out of I/O space!");
-
- C.io->path = name;
- C.io->rdr = (io·Buffer) {
- .state = bufio·rdr | bufio·end,
- .runesize = 0,
- .h = nil,
- .size = bufio·size,
- .beg = C.io->rdr.buf + bufio·ungets,
- .pos = C.io->rdr.buf + bufio·ungets,
- .end = C.io->rdr.buf + bufio·ungets,
- };
- C.io->b = C.io->rdr.beg;
-
- return C.io++;
-}
-#undef asrdr
-
-void
-freeio(Io *io)
-{
- if (io->kind & IOfile) {
- io·close(io->f);
- }
-
- io->rdr.state = 0;
- io->kind = 0;
- io->link = nil;
- io->path = nil;
- io->store = (Pos){ 0 };
- io->path = "<empty>";
-}
-
-void
-pushomit(string omit)
-{
- if (C.omit.len == C.omit.cap) {
- C.omit.cap += 20;
- C.omit.path = realloc(C.omit.path, C.omit.cap*sizeof(*C.omit.path));
- }
- C.omit.path[C.omit.len++] = omit;
-}
-
-// -----------------------------------------------------------------------
// universal compiler builtins
#define KEYWORD(a, b) b,
@@ -227,79 +144,102 @@ init(void)
{
int i;
- for (i = 0; i < arrlen(keywords); i++) {
+ for (i = 0; i < arrlen(keywords); i++)
intern(&keywords[i]);
- }
- for (i = 0; i < arrlen(directives); i++) {
+ for (i = 0; i < arrlen(directives); i++)
intern(&directives[i]);
- }
- C.heap = mem·makearena(mem·sys, nil);
+ C.heap = mem·makearena(mem·sys, nil);
+ /* compiler definitions */
+ C.def.len = 0;
+ C.def.cap = 100;
+ C.def.val = calloc(C.def.cap, sizeof(*C.def.val));
+
+ /* compiler include paths */
C.inc.len = 0;
C.inc.cap = 100;
C.inc.dir = calloc(C.inc.cap, sizeof(*C.inc.dir));
C.inc.dir[C.inc.len++] = ".";
- C.omit.len = 0;
- C.omit.cap = 100;
- C.omit.path = calloc(C.omit.cap, sizeof(*C.inc.dir));
-
C.outfile = nil;
- C.io = C.iostk;
- C.io->link = nil;
- memset(C.iostk, 0, sizeof(C.iostk));
+}
- C.lxr = (Lexer){ 0 };
- C.lxr.b = C.lxr.buf;
+void
+initl(Lexer *lx)
+{
+ int i;
+
+ *lx = (Lexer){ 0 };
+ lx->b = lx->buf;
/* predefine macros */
- dodefine(&C.lxr, "__LINE__");
- dodefine(&C.lxr, "__FILE__");
- C.lxr.macline = (uintptr)lookup(&C.lxr.sym, "__LINE__");
- C.lxr.macfile = (uintptr)lookup(&C.lxr.sym, "__FILE__");
+ dodefine(lx, "__LINE__");
+ dodefine(lx, "__FILE__");
+ lx->macline = (uintptr)lookup(&lx->sym, "__LINE__");
+ lx->macfile = (uintptr)lookup(&lx->sym, "__FILE__");
+
+ for (i = 0; i < C.def.len; i++)
+ dodefine(lx, C.def.val[i]);
+
+ lx->omit.len = 0;
+ lx->omit.cap = 100;
+ lx->omit.path = calloc(lx->omit.cap, sizeof(*C.inc.dir));
+
+ lx->io = lx->iostk;
+ lx->io->link = nil;
+ memset(lx->iostk, 0, sizeof(lx->iostk));
+}
+
+void
+initp(Parser *p)
+{
+ p->sp = p->spstk;
+ p->nm = p->nmstk;
+ p->dt = p->dtstk;
}
error
compile(byte *path)
{
- Io *io;
- Token tok;
- byte *p, out[400];
+ Lexer lx;
+ Parser p;
+ byte *sep, out[400];
intern(&path);
strcpy(out, path);
- p = utf8·findrrune(out, '/');
- if (p)
- *p++ = '\0';
+ sep = utf8·findrrune(out, '/');
+ if (sep)
+ *sep++ = '\0';
else
- p = out;
+ sep = out;
if (!C.outfile) {
- C.outfile = p;
+ C.outfile = sep;
if (C.outfile) {
- if ((p = utf8·findrrune(C.outfile, '.'))) {
- p[0] = '.';
- p[1] = 'o';
- p[2] = '\0';
+ if ((sep = utf8·findrrune(C.outfile, '.'))) {
+ sep[0] = '.';
+ sep[1] = 'o';
+ sep[2] = '\0';
}
} else {
C.outfile = "/dev/null";
}
}
- C.lxr.io = openio(path);
- C.lxr.pos = (Pos){
+ initl(&lx);
+ initp(&p);
+
+ lx.io = openio(path);
+ lx.pos = (Pos){
.path = path,
.line = 1,
.col = 1,
};
- parse(&C.psr, &C.lxr);
-
- return tok.kind != Anil;
+ return parse(&p, &lx);
}
error
@@ -319,7 +259,11 @@ main(int argc, byte *argv[])
a = ARGF();
if (a) {
intern(&a);
- dodefine(&C.lxr, a);
+ if (C.def.len >= C.def.cap) {
+ C.def.cap += 20;
+ C.def.val = realloc(C.def.val, C.def.cap * sizeof(*C.def.val));
+ }
+ C.def.val[C.def.len++] = a;
}
break;
diff --git a/sys/cmd/cc/cc.h b/sys/cmd/cc/cc.h
index 0d4c876..62837c4 100644
--- a/sys/cmd/cc/cc.h
+++ b/sys/cmd/cc/cc.h
@@ -263,17 +263,46 @@ Sym *lookup(SymTab *tab, string ident);
error forget(SymTab *tab, string ident);
void forgetall(SymTab *tab);
+enum
+{
+ IOnil = iota(0),
+ IOfile = iota(1),
+ IObuff = iota(2),
+};
+
+struct Io
+{
+ io·Buffer rdr;
+ string path;
+ uint32 kind;
+ union {
+ Stream *f;
+ byte *b;
+ };
+
+ Pos store;
+ struct Io *link;
+};
+
struct Lexer
{
Pos pos;
- Io *io;
- SymTab sym;
+ SymTab sym;
byte *b;
byte buf[2*1024];
/* predefined dynamic macros */
uintptr macfile;
uintptr macline;
+
+ /* i/o data */
+ Io *io, *new;
+ Io iostk[100];
+ struct {
+ int cap;
+ int len;
+ string *path;
+ } omit;
};
/* lex.c functions */
@@ -285,8 +314,11 @@ rune getrune(Lexer *);
byte ungetbyte(Lexer *);
rune ungetrune(Lexer *, rune r);
-void pushio(Lexer *lx, Io *new);
-void popio(Lexer *lx);
+Io* openio(Lexer *lx, byte *path);
+Io* makeio(Lexer *lx, byte *name);
+void freeio(Lexer *lx, Io *io);
+void pushio(Lexer *lx, Io *new);
+void popio(Lexer *lx);
void puttok(Token);
@@ -524,6 +556,7 @@ enum
Sbad = -1,
};
+/* intermediate nodes */
struct Ptr
{
uint64 kind;
@@ -551,29 +584,22 @@ struct Dtor
struct Decls
{
- union {
- struct Dtor;
- Dtor dtor;
- };
+ Type *type;
Expr *init;
struct Decls *link;
};
+/* final ast node */
struct Decl
{
struct Node;
- uint64 spec;
+ uint32 spec;
+ string name;
+ Type *type;
union {
- struct {
- struct Dtor;
- Stmt *body;
- } func;
- struct {
- struct Dtor;
- Expr *init;
- struct Decls *link;
- } var;
- struct Dtor type;
+ Stmt *func;
+ Expr *init;
+ struct Decls *link;
};
};
@@ -627,42 +653,23 @@ struct Parser
Decl **decls;
} ast;
+ /* static buffers */
Scope *sp;
Scope spstk[20];
+
+ Name *nm;
+ Name nmstk[40];
+
+ Dtor *dt;
+ Dtor dtstk[40];
};
/* ast.c functions */
-void parse(Parser *, Lexer *);
+error parse(Parser *, Lexer *);
// -----------------------------------------------------------------------
// global compiler
-enum
-{
- IOnil = iota(0),
- IOfile = iota(1),
- IObuff = iota(2),
-};
-
-struct Io
-{
- io·Buffer rdr;
- string path;
- uint32 kind;
- union {
- Stream *f;
- byte *b;
- };
-
- Pos store;
- struct Io *link;
-};
-
-/* cc.c io functions */
-Io* openio(byte *path);
-Io* makeio(byte *name);
-void freeio(Io *io);
-
struct StrTab
{
int32 n_buckets;
@@ -687,35 +694,27 @@ struct Compiler
string outfile;
struct {
- int cap;
- int len;
- Type *info;
- } type;
+ int cap;
+ int len;
+ string *val;
+ } def;
- /* i/o data */
struct {
int cap;
int len;
string *dir;
} inc;
- Io *io;
- Io iostk[100];
struct {
- int cap;
- int len;
- string *path;
- } omit;
-
- /* partitioned data for stages */
- Lexer lxr;
- Parser psr;
+ int cap;
+ int len;
+ Type *info;
+ } type;
};
extern Compiler C;
/* cc.c compiler functions */
-void pushomit(string omit);
void init();
#undef iota
diff --git a/sys/cmd/cc/lex.c b/sys/cmd/cc/lex.c
index a8dabec..1eb269c 100644
--- a/sys/cmd/cc/lex.c
+++ b/sys/cmd/cc/lex.c
@@ -23,6 +23,115 @@ puttok(Token tok)
}
// -----------------------------------------------------------------------
+// io buffer management
+
+#define asrdr(x) (io·Reader){(int (*)(void *, int, int, void *))x}
+
+// path should be absolute
+Io*
+openio(Lexer *lx, byte *path)
+{
+ string *it, *end;
+ Stream *f;
+
+ intern(&path);
+
+ // See if we have already opened file;
+ // If so, and it hasn't been flagged return it
+ for (it = lx->omit.path, end = it + lx->omit.len; it < end; ++it) {
+ if ((uintptr)(*it) == (uintptr)(path))
+ return nil;
+ }
+
+ // TODO: See if we have already loaded the file
+
+ if ((lx->new - lx->iostk) >= arrlen(lx->iostk)-1)
+ panicf("out of I/O space!");
+
+ lx->new->f = io·open(path, "r");
+ if (!lx->new->f)
+ panicf("file %s not found", path);
+
+ lx->new->kind = IOfile;
+ lx->new->path = path;
+ bufio·initreader(&lx->new->rdr, asrdr(io·read), lx->new->f);
+
+ return lx->new++;
+}
+
+static
+Io*
+makeio(Lexer *lx, byte *name)
+{
+ if ((lx->new - lx->iostk) >= arrlen(lx->iostk)-1)
+ panicf("out of I/O space!");
+
+ lx->new->path = name;
+ lx->new->rdr = (io·Buffer) {
+ .state = bufio·rdr | bufio·end,
+ .runesize = 0,
+ .h = nil,
+ .size = bufio·size,
+ .beg = lx->new->rdr.buf + bufio·ungets,
+ .pos = lx->new->rdr.buf + bufio·ungets,
+ .end = lx->new->rdr.buf + bufio·ungets,
+ };
+ lx->new->b = lx->new->rdr.beg;
+
+ return lx->new++;
+}
+#undef asrdr
+
+static
+void
+freeio(Lexer *lx, Io *io)
+{
+ if (io->kind & IOfile) {
+ io·close(io->f);
+ }
+
+ io->rdr.state = 0;
+ io->kind = 0;
+ io->link = nil;
+ io->path = nil;
+ io->store = (Pos){ 0 };
+ io->path = "<empty>";
+}
+
+void
+pushio(Lexer *lx, Io *new)
+{
+ new->link = lx->io;
+ lx->io->store = lx->pos;
+ lx->io = new;
+
+ lx->pos = (Pos){
+ .line = 1,
+ .col = 1,
+ .path = new->path,
+ };
+}
+
+void
+popio(Lexer *lx)
+{
+ Io *prev;
+
+ assert(lx->io == lx->new-1);
+ --lx->new;
+
+ prev = lx->io->link;
+ freeio(lx, lx->io);
+
+ lx->io = prev;
+ if (!prev) {
+ return;
+ }
+
+ lx->pos = prev->store;
+}
+
+// -----------------------------------------------------------------------
// simple wrappers
int
@@ -648,7 +757,7 @@ Dispatch:
tok.val.s = lx->pos.path;
goto Return;
}
- io = makeio(sym->name);
+ io = makeio(lx, sym->name);
io->rdr.end += expandmacro(lx, sym, io->b);
*io->rdr.end++ = EOF;
pushio(lx, io);
@@ -676,42 +785,6 @@ Nospace:
#undef CASE1
// -----------------------------------------------------------------------
-// push/pop io objects
-
-void
-pushio(Lexer *lx, Io *new)
-{
- new->link = lx->io;
- lx->io->store = lx->pos;
- lx->io = new;
-
- lx->pos = (Pos){
- .line = 1,
- .col = 1,
- .path = new->path,
- };
-}
-
-void
-popio(Lexer *lx)
-{
- Io *prev;
-
- assert(lx->io == C.io-1);
- --C.io;
-
- prev = lx->io->link;
- freeio(lx->io);
-
- lx->io = prev;
- if (!prev) {
- return;
- }
-
- lx->pos = prev->store;
-}
-
-// -----------------------------------------------------------------------
// symbol tables
#define PTR_HASH(p) (uintptr)(p)
diff --git a/sys/cmd/cc/pp.c b/sys/cmd/cc/pp.c
index 30a162b..5eed4b2 100644
--- a/sys/cmd/cc/pp.c
+++ b/sys/cmd/cc/pp.c
@@ -3,6 +3,17 @@
// -----------------------------------------------------------------------
// helper functions
+static
+void
+pushomit(Lexer *lx, string omit)
+{
+ if (lx->omit.len == lx->omit.cap) {
+ lx->omit.cap += 20;
+ lx->omit.path = realloc(lx->omit.path, lx->omit.cap*sizeof(*lx->omit.path));
+ }
+ lx->omit.path[lx->omit.len++] = omit;
+}
+
// NOTE: The iterator of lexer lx->b IS NOT reset.
// Its the caller's responsibility.
static
@@ -910,7 +921,7 @@ ppprag(Lexer *lx)
}
lx->b = lx->buf;
if (strcmp(s, "once") == 0) {
- pushomit(lx->io->path);
+ pushomit(lx, lx->io->path);
return 0;
}
Bad: