From 9ec5bed6a7d715ffa69851569485a685dd69db2e Mon Sep 17 00:00:00 2001 From: Nicholas Noll Date: Sun, 17 May 2020 16:19:17 -0700 Subject: prototype of front end cli --- sys/cmd/cc/cc.c | 237 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 230 insertions(+), 7 deletions(-) (limited to 'sys/cmd/cc/cc.c') diff --git a/sys/cmd/cc/cc.c b/sys/cmd/cc/cc.c index cddea01..39ad5f2 100644 --- a/sys/cmd/cc/cc.c +++ b/sys/cmd/cc/cc.c @@ -1,6 +1,9 @@ #include "cc.h" #include +// ----------------------------------------------------------------------- +// string interning + /* jenkins' one at a time hash */ static int32 @@ -24,8 +27,22 @@ hash_string(byte* s) return h; } +static +int +streq(byte *s, byte *t) +{ + if (s == nil) { + if (t == nil) + return 1; + else + return 0; + } + + return (t == nil) ? 0 : strcmp(s, t) == 0; +} + #define HASH(s) hash_string(s) -#define EQUAL(s, t) (strcmp(s, t) == 0) +#define EQUAL(s, t) (streq(s, t)) static int getstr(string key, int *ok) @@ -74,20 +91,226 @@ END: return C.strs.vals[i]; } +// ----------------------------------------------------------------------- +// io buffer management + +#define asrdr(x) (io·Reader){(int (*)(void *, int, int, void *))x} +// path should be absolute +Io* +openio(byte *path) +{ + Io *it; + Stream *f; + + intern(&path); + + // See if we have already opened file; + // If so, and it hasn't been flagged return it + for (it = C.iostk; it != C.io + 1; ++it) { + if ((uintptr)it->path == (uintptr)path) { + if (it->kind & IOonce) { + return nil; + } + return it; + } + } + + if ((C.io - C.iostk) >= arrlen(C.iostk)-1) + panicf("out of I/O space!"); + + C.io->f = io·open(path, "r"); + C.io->path = path; + bufio·initreader(&C.io->buf, asrdr(io·read), C.io->f); + + return C.io++; +} + +Io* +makeio() +{ + if ((C.io - C.iostk) >= arrlen(C.iostk)-1) + panicf("out of I/O space!"); + + C.io->path = ""; + C.io->buf = (io·Buffer) { + .state = bufio·rdr | bufio·end, + .runesize = 0, + .h = nil, + .size = bufio·size, + .beg = C.io->buf.buf + bufio·ungets, + .pos = C.io->buf.buf + bufio·ungets, + .end = C.io->buf.buf + bufio·ungets, + }; + C.io->b = C.io->buf.buf; + + return C.io++; +} +#undef asrdr + +// TODO: Think about if this is always at the _end_ of the stack. +// Right now we don't have access to it. +void +freeio(Io *io) +{ + if (io->kind & ~IOmac) { + free(io->b); + } else { + io·close(io->f); + } + io->link = nil; + io->path = nil; + io->store = (Pos){ 0 }; +} + +// ----------------------------------------------------------------------- +// universal compiler builtins + +#define KEYWORD(a, b) b, +byte *keywords[NUM_KEYWORDS] = { KEYWORDS }; +#undef KEYWORD + +#define DIRECTIVE(a, b, c) b, +byte *directives[NUM_DIRECTIVES] = { DIRECTIVES }; +#undef DIRECTIVE + +struct Compiler C = { 0 }; + +// ----------------------------------------------------------------------- +// flag handlers + +void +pushinclude(byte *dirs) +{ + string d, s, *it, *end; + + while (*dirs != 0) { + d = strchr(dirs, ' '); + if (d != nil) + *d = '\0'; + + s = d; + intern(&s); + for (it = C.inc.dir, end = it + C.inc.len; it != end; ++it) { + if ((uintptr)s == (uintptr)(*it)) + goto Nextdir; + } + + if (C.inc.len == C.inc.cap) { + C.inc.cap += 20; + C.inc.dir = realloc(C.inc.dir, C.inc.cap*sizeof(*C.inc.dir)); + C.inc.dir[C.inc.len++] = s; + } + +Nextdir: + if (d == nil) + break; + dirs = d + 1; + } + +} + +// ----------------------------------------------------------------------- +// main point of entry + void -init() +init(void) { - int i, n; + int i; for (i = 0; i < arrlen(keywords); i++) { intern(&keywords[i]); - printf("keyword %d: %s", i, keywords[i]); } + + for (i = 0; i < arrlen(directives); i++) { + intern(&directives[i]); + } + + C.heap = mem·makearena(mem·sys, nil); + + 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.outfile = nil; + C.lxr = (Lexer){ 0 }; } -int -main() +error +compile(byte *path) +{ + Io *io; + Token tok; + byte *p, file[400]; + + strcpy(file, path); + p = utf8·findrrune(file, '/'); + if (p) + *p++ = '\0'; + else + p = file; + + if (!C.outfile) { + C.outfile = p; + if (C.outfile) { + if ((p = utf8·findrrune(C.outfile, '.'))) { + p[0] = '.'; + p[1] = 'o'; + p[2] = '\0'; + } + } else { + C.outfile = "/dev/null"; + } + } + + C.lxr.io = openio(file); + while (tok = lex(&C.lxr), tok.kind > Aeof) { + ; + } + freeio(C.lxr.io); + + return tok.kind != Anil; +} + +error +main(int argc, byte *argv[]) { + byte *a, *src; + int err; + init(); - return 0; + + ARGBEGIN { + case 'o': + C.outfile = ARGF(); + break; + + case 'D': + a = ARGF(); + if (a) { + intern(&a); + dodefine(&C.lxr, a); + } + break; + + case 'I': + a = ARGF(); + if (a) + pushinclude(a); + break; + } ARGEND + + if (argc < 1 && C.outfile == nil) { + printf("usage: cc [-options] files\n"); + exit(1); + } + + src = (argc == 0) ? "" : argv[0]; + intern(&src); + + if ((err = compile(src)), err) { + exit(2); + } + + exit(0); } -- cgit v1.2.1