aboutsummaryrefslogtreecommitdiff
path: root/sys/cmd/cc/cc.c
diff options
context:
space:
mode:
authorNicholas Noll <nbnoll@eml.cc>2020-05-17 16:19:17 -0700
committerNicholas Noll <nbnoll@eml.cc>2020-05-17 16:19:17 -0700
commit9ec5bed6a7d715ffa69851569485a685dd69db2e (patch)
treec25eaef1000f52caacf25ee398e54f63067b8feb /sys/cmd/cc/cc.c
parentc92c89280d036240a75ff122084dd58cde473394 (diff)
prototype of front end cli
Diffstat (limited to 'sys/cmd/cc/cc.c')
-rw-r--r--sys/cmd/cc/cc.c237
1 files changed, 230 insertions, 7 deletions
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 <libn/macro/map.h>
+// -----------------------------------------------------------------------
+// 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 = "<buffer>";
+ 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) ? "<stdin>" : argv[0];
+ intern(&src);
+
+ if ((err = compile(src)), err) {
+ exit(2);
+ }
+
+ exit(0);
}