diff options
author | aiju <devnull@localhost> | 2018-11-10 13:46:16 +0000 |
---|---|---|
committer | aiju <devnull@localhost> | 2018-11-10 13:46:16 +0000 |
commit | e6d99771e5c1eef3f69fc847253d4709ffaa84be (patch) | |
tree | 16161401edc25c084ad24533519e094716965635 /sys/src/cmd/dtracy/lex.c | |
parent | 8c097ae84a500eae9c8e4ee21b7b3ea8f8d23259 (diff) |
adding dtracy (crude early version)
Diffstat (limited to 'sys/src/cmd/dtracy/lex.c')
-rw-r--r-- | sys/src/cmd/dtracy/lex.c | 390 |
1 files changed, 390 insertions, 0 deletions
diff --git a/sys/src/cmd/dtracy/lex.c b/sys/src/cmd/dtracy/lex.c new file mode 100644 index 000000000..15a959ffa --- /dev/null +++ b/sys/src/cmd/dtracy/lex.c @@ -0,0 +1,390 @@ +#include <u.h> +#include <libc.h> +#include <ctype.h> +#include <dtracy.h> +#include <bio.h> +#include "dat.h" +#include "fns.h" +#include "y.tab.h" + +char *str, *strp; +int lineno = 1; +int errors; + +typedef struct Keyword Keyword; +struct Keyword { + char *name; + int tok; +}; +/* both tables must be sorted */ +Keyword kwtab[] = { + "if", TIF, + "print", TPRINT, + "printf", TPRINTF, + "s16", TS16, + "s32", TS32, + "s64", TS64, + "s8", TS8, + "string", TSTRING, + "u16", TU16, + "u32", TU32, + "u64", TU64, + "u8", TU8, +}; +Keyword optab[] = { + "!=", TNE, + "&&", TAND, + "<<", TLSL, + "<=", TLE, + "==", TEQ, + ">=", TGE, + ">>", TLSR, + "||", TOR, +}; +Keyword *kwchar[128], *opchar[128]; + +void +lexinit(void) +{ + Keyword *kw; + + for(kw = kwtab; kw < kwtab + nelem(kwtab); kw++) + if(kwchar[*kw->name] == nil) + kwchar[*kw->name] = kw; + for(kw = optab; kw < optab + nelem(optab); kw++) + if(opchar[*kw->name] == nil) + opchar[*kw->name] = kw; +} + +void +lexstring(char *s) +{ + str = strp = s; +} + +void +error(char *fmt, ...) +{ + Fmt f; + char buf[128]; + va_list va; + + fmtfdinit(&f, 2, buf, sizeof(buf)); + fmtprint(&f, "%d ", lineno); + va_start(va, fmt); + fmtvprint(&f, fmt, va); + fmtrune(&f, '\n'); + va_end(va); + fmtfdflush(&f); + errors++; +} + +void +yyerror(char *msg) +{ + error("%s", msg); +} + +static int +getch(void) +{ + if(*strp == 0) return -1; + return *strp++; +} + +static void +ungetch(void) +{ + assert(strp > str); + if(*strp != 0) + strp--; +} + +int +yylex(void) +{ + int ch; + static char buf[512]; + char *p; + Keyword *kw; + u64int v; + +again: + while(ch = getch(), ch >= 0 && isspace(ch)){ + if(ch == '\n') + lineno++; + } + if(ch < 0) + return -1; + if(ch == '/'){ + ch = getch(); + if(ch == '/'){ + while(ch = getch(), ch >= 0 && ch != '\n') + ; + if(ch == '\n') + lineno++; + goto again; + } + if(ch == '*'){ + s1: + ch = getch(); + if(ch < 0) return -1; + if(ch == '\n') lineno++; + if(ch != '*') goto s1; + s2: + ch = getch(); + if(ch < 0) return -1; + if(ch == '\n') lineno++; + if(ch == '*') goto s2; + if(ch != '/') goto s1; + goto again; + } + ungetch(); + return '/'; + } + if(isalnum(ch) || ch == '_' || ch >= 0x80 || ch == ':'){ + p = buf; + *p++ = ch; + while(ch = getch(), isalnum(ch) || ch == '_' || ch >= 0x80 || ch == ':') + if(p < buf + sizeof(buf) - 1) + *p++ = ch; + *p = 0; + ungetch(); + v = strtoull(buf, &p, 0); + if(p != buf && *p == 0){ + yylval.num = v; + return TNUM; + } + if(strcmp(buf, ":") == 0) + return ':'; + if((uchar)buf[0] < 0x80 && kwchar[buf[0]] != nil) + for(kw = kwchar[buf[0]]; kw < kwtab + nelem(kwtab) && kw->name[0] == buf[0]; kw++) + if(strcmp(kw->name, buf) == 0) + return kw->tok; + yylval.sym = getsym(buf); + return TSYM; + } + if(ch == '"'){ + p = buf; + while(ch = getch(), ch >= 0 && ch != '"'){ + if(ch == '\n') + error("unterminated string"); + if(ch == '\\') + switch(ch = getch()){ + case 'n': ch = '\n'; break; + case 'r': ch = '\r'; break; + case 't': ch = '\t'; break; + case 'v': ch = '\v'; break; + case 'b': ch = '\b'; break; + case 'a': ch = '\a'; break; + case '"': case '\\': break; + default: error("unknown escape code \\%c", ch); + } + if(p < buf + sizeof(buf) - 1) + *p++ = ch; + } + if(ch < 0) error("unterminated string"); + *p = 0; + yylval.str = strdup(buf); + return TSTR; + } + if(opchar[ch] != nil){ + buf[0] = ch; + buf[1] = getch(); + for(kw = opchar[buf[0]]; kw < optab + nelem(optab) && kw->name[0] == buf[0]; kw++) + if(buf[1] == kw->name[1]){ + buf[2] = getch(); + buf[3] = 0; + if(kw + 1 < optab + nelem(optab) && strcmp(kw[1].name, buf) == 0) + return kw[1].tok; + ungetch(); + return kw->tok; + } + ungetch(); + } + return ch; +} + +int +nodetfmt(Fmt *f) +{ + int t; + static char *nodestr[] = { + [OINVAL] "OINVAL", + [OBIN] "OBIN", + [OLNOT] "OLNOT", + [OSYM] "OSYM", + [ONUM] "ONUM", + [OSTR] "OSTR", + [OTERN] "OTERN", + [ORECORD] "ORECORD", + [OCAST] "OCAST", + }; + + t = va_arg(f->args, int); + if(t >= nelem(nodestr) || nodestr[t] == nil) + return fmtprint(f, "??? (%d)", t); + else + return fmtprint(f, "%s", nodestr[t]); +} + +Node * +node(int type, ...) +{ + va_list va; + Node *n; + + n = emalloc(sizeof(Node)); + n->type = type; + va_start(va, type); + switch(type){ + case OBIN: + n->op = va_arg(va, int); + n->n1 = va_arg(va, Node *); + n->n2 = va_arg(va, Node *); + break; + case OLNOT: + n->n1 = va_arg(va, Node *); + break; + case OSYM: + n->sym = va_arg(va, Symbol *); + break; + case ONUM: + n->num = va_arg(va, s64int); + break; + case OTERN: + n->n1 = va_arg(va, Node *); + n->n2 = va_arg(va, Node *); + n->n3 = va_arg(va, Node *); + break; + case ORECORD: + n->n1 = va_arg(va, Node *); + break; + case OCAST: + n->typ = va_arg(va, Type *); + n->n1 = va_arg(va, Node *); + break; + case OSTR: + n->str = va_arg(va, char *); + break; + default: + sysfatal("node: unknown type %α", type); + } + va_end(va); + return n; +} + +SymTab globals; + +static u64int +hash(char *s) +{ + u64int h; + + h = 0xcbf29ce484222325ULL; + for(; *s != 0; s++){ + h ^= *s; + h *= 0x100000001b3ULL; + } + return h; +} + +Symbol * +getsym(char *name) +{ + u64int h; + Symbol **sp, *s; + + h = hash(name); + for(sp = &globals.sym[h % SYMHASH]; s = *sp, s != nil; sp = &s->next) + if(strcmp(s->name, name) == 0) + return s; + *sp = s = emalloc(sizeof(Symbol)); + s->name = strdup(name); + return s; +} + +int +typetfmt(Fmt *f) +{ + int t; + static char *tstr[] = { + [TYPINVAL] "TYPINVAL", + [TYPINT] "TYPINT", + [TYPPTR] "TYPPTR", + [TYPSTRING] "TYPSTRING", + }; + + t = va_arg(f->args, int); + if(t >= nelem(tstr) || tstr[t] == nil) + return fmtprint(f, "??? (%d)", t); + else + return fmtprint(f, "%s", tstr[t]); +} + +int +typefmt(Fmt *f) +{ + Type *t; + + t = va_arg(f->args, Type *); + switch(t->type){ + case TYPINT: return fmtprint(f, "%c%d", t->sign ? 's' : 'u', t->size * 8); + case TYPSTRING: return fmtprint(f, "string"); + case TYPPTR: return fmtprint(f, "%τ*", t->ref); + default: return fmtprint(f, "%t", t->type); + } +} + +static Type typu8 = {.type TYPINT, .size 1, .sign 0}; +static Type typs8 = {.type TYPINT, .size 1, .sign 1}; +static Type typu16 = {.type TYPINT, .size 2, .sign 0}; +static Type typs16 = {.type TYPINT, .size 2, .sign 1}; +static Type typu32 = {.type TYPINT, .size 4, .sign 0}; +static Type typs32 = {.type TYPINT, .size 4, .sign 1}; +static Type typu64 = {.type TYPINT, .size 8, .sign 0}; +static Type typs64 = {.type TYPINT, .size 8, .sign 1}; +static Type typstr = {.type TYPSTRING, .size DTSTRMAX }; +static Type *typereg; + +static Type * +mkptr(Type *t) +{ + Type *s; + + for(s = typereg; s != nil; s = s->typenext) + if(s->type == TYPPTR && s->ref == t) + return s; + s = emalloc(sizeof(Type)); + s->type = TYPPTR; + s->ref = t; + return s; +} + +Type * +type(int typ, ...) +{ + int size, sign; + va_list va; + + va_start(va, typ); + switch(typ){ + case TYPINT: + size = va_arg(va, int); + sign = va_arg(va, int); + switch(size << 4 | sign){ + case 0x10: return &typu8; + case 0x11: return &typs8; + case 0x20: return &typu16; + case 0x21: return &typs16; + case 0x40: return &typu32; + case 0x41: return &typs32; + case 0x80: return &typu64; + case 0x81: return &typs64; + default: sysfatal("type: invalid (size,sign) = (%d,%d)\n", size, sign); return nil; + } + case TYPSTRING: return &typstr; + case TYPPTR: return mkptr(va_arg(va, Type *)); + default: sysfatal("type: unknown %t", typ); return nil; + } +} |