scc

simple C compiler
git clone git://git.2f30.org/scc
Log | Files | Refs | README | LICENSE

commit e267264d253dd0cecd0a3bd87b881b10df2a14cd
parent 03817ea82122c65ed529a36d448bebd3812e20be
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Wed, 27 Sep 2017 06:11:14 +0200

Merge remote-tracking branch 'origin/master'

Diffstat:
as/as.h | 2+-
as/expr.c | 80+++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------
as/main.c | 9++++++++-
as/parser.c | 33++++++++++-----------------------
as/symbol.c | 5+++--
as/target/x86/gen.awk | 23++++++++++++++---------
inc/scc.h | 1+
lib/c/include/ctype.h | 28++++++++++++++++------------
lib/c/src/ctype.c | 2++
lib/scc/casecmp.c | 11+++++++++++
lib/scc/libdep.mk | 1+
11 files changed, 123 insertions(+), 72 deletions(-)

diff --git a/as/as.h b/as/as.h @@ -107,7 +107,7 @@ extern int nextline(FILE *fp, struct line *linep); #endif /* expr.c */ -extern Node *expr(char *s); +extern Node *expr(char **s); extern void deltree(Node *np); /* proc.c */ diff --git a/as/expr.c b/as/expr.c @@ -11,6 +11,7 @@ static char sccsid[] = "@(#) ./as/node.c"; #define NNODES 10 enum tokens { + EOS = -1, IDEN = 1, NUMBER, REG, @@ -124,8 +125,10 @@ binary(int op, Node *l, Node *r) default: abort(); } + deltree(l); + deltree(r); - np = node(NUMBER, l, r); + np = node(NUMBER, NULL, NULL); np->sym = tmpsym(val); return np; @@ -175,8 +178,8 @@ iden(void) int c; char *p; - for (endp = textp; isalnum(c = *endp) || c == '_' || c == '.'; ++endp) - /* nothing */; + while (isalnum(c = *endp) || c == '_' || c == '.') + ++endp; tok2str(); yylval.sym = lookup(yytext); @@ -189,8 +192,8 @@ number(void) int c; char *p; - for (endp = textp; isxdigit(*endp); ++endp) - /* nothing */; + while (isxdigit(*endp)) + ++endp; tok2str(); yylval.sym = tmpsym(atoi(yytext)); /* TODO: parse the string */ @@ -203,8 +206,8 @@ character(void) int c; char *p; - for (endp = textp+1; *endp != '\''; ++endp) - /* nothing */; + while (*endp != '\'') + ++endp; return NUMBER; } @@ -214,34 +217,52 @@ string(void) int c; char *p; - for (endp = textp+1; *endp != '"'; ++endp) - /* nothing */; + while (*endp != '"') + ++endp; return STRING; } static int +operator(void) +{ + int c; + + ++endp; + if ((c = *textp) == '>') + c = follow('=', '>', LE, SHL, '>'); + else if (c == '<') + c = follow('=', '<', GE, SHR, '>'); + tok2str(); + + return c; +} + +static int next(void) { int c; while (isspace(*textp)) ++textp; - c = *textp; - if (isalpha(c) || c == '_' || c == '.') + + endp = textp; + if ((c = *textp) == '\0') { + strcpy(yytext, "EOS"); + yylen = 3; + c = EOS; + } else if (isalpha(c) || c == '_' || c == '.') { c = iden(); - else if (isdigit(c)) + } else if (isdigit(c)) { c = number(); - else if (c == '>') - c = follow('=', '>', LE, SHL, '>'); - else if (c == '<') - c = follow('=', '<', GE, SHR, '>'); - else if (c == '\'') - c = character(); - else if (c == '\"') + } else if (c == '\"') { c = string(); - tok2str(); + } else if (c == '\'') { + c = character(); + } else { + c = operator(); + } - return c; + return yytoken = c; } static void @@ -277,6 +298,12 @@ primary(void) np->sym = yylval.sym; next(); break; + case '[': + next(); + np = or(); + expect(']'); + np = node('@', np, NULL); + break; case '(': next(); np = or(); @@ -399,15 +426,20 @@ or(void) } Node * -expr(char *s) +expr(char **s) { Node *np; - textp = s; + textp = *s; + if (*textp == '\0') + return NULL; + next(); np = or(); - if (*textp != '\0') + if (yytoken != ',' && yytoken != EOS) error("trailing characters in expression '%s'", textp); + *s = endp; + return np; } diff --git a/as/main.c b/as/main.c @@ -1,5 +1,6 @@ static char sccsid[] = "@(#) ./as/main.c"; +#include <ctype.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -11,8 +12,14 @@ static int cmp(const void *f1, const void *f2) { const Ins *ins = f2; + const char *s = f1; + int d; - return strcmp(f1, ins->str); + d = toupper(*ins->str) - toupper(*s); + if (d != 0) + return d; + + return casecmp(s, ins->str); } static void diff --git a/as/parser.c b/as/parser.c @@ -35,32 +35,17 @@ error(char *msg, ...) Node ** getargs(char *s) { - char *t; - int ch, len; Node **ap; static Node *args[NARGS]; if (!s) return NULL; - for (ap = args; ; *ap++ = expr(t)) { - while (isspace(*s)) - ++s; - if (*s == '\0') - break; - if (ap == &args[NARGS-1]) - error("too many arguments in one instruction"); - - for (t = s; *s && *s != ','; s++) - /* nothing */; - *s++ = '\0'; - len = t - s; - if (len == 0) - error("wrong operand '%s'", t); + for (ap = args; ap < &args[NARGS-1]; ++ap) { + if ((*ap = expr(&s)) == NULL) + return args; } - *ap = NULL; - - return args; + error("too many arguments in one instruction"); } static char * @@ -92,9 +77,6 @@ field(char **oldp) if (c == '\0') error("unterminated string"); break; - default: - *s = toupper(*s); - break; } } @@ -106,9 +88,14 @@ static int extract(char *s, struct line *lp) { int r = 0; + size_t len; - if (lp->label = field(&s)) + if (lp->label = field(&s)) { + len = strlen(lp->label); + if (lp->label[len-1] == ':') + lp->label[len-1] = '\0'; r++; + } if (lp->op = field(&s)) r++; if (lp->args = field(&s)) diff --git a/as/symbol.c b/as/symbol.c @@ -1,5 +1,6 @@ static char sccsid[] = "@(#) ./as/symbol.c"; +#include <ctype.h> #include <stdio.h> #include <stdint.h> #include <string.h> @@ -55,11 +56,11 @@ lookup(char *name) h = h*33 ^ c; h &= HASHSIZ-1; - c = *name; + c = toupper(*name); list = &hashtbl[h]; for (sym = *list; sym; sym = sym->next) { t = sym->name; - if (c == *t && !strcmp(t, name)) + if (c == toupper(*t) && !casecmp(t, name)) return sym; } diff --git a/as/target/x86/gen.awk b/as/target/x86/gen.awk @@ -40,24 +40,29 @@ END { print "struct op optab[] = {" for (i = 0; i < nvar; i++) { printf "\t{\n" \ - "\t\t.bytes = (char []) {%s},\n"\ "\t\t.size = %d,\n"\ - "\t\t.format = %s,\n"\ - "\t\t.args = (char []) {%s}\n"\ - "\t},\n", - opbytes[i], opsize[i], opformat[i], str2args(opargs[i]) + "\t\t.format = %s,\n", + opsize[i], opformat[i] + + if (opbytes[i] != "") + printf "\t\t.bytes = (char []) {%s},\n", opbytes[i] + + a = str2args(opargs[i]) + if (a != "") + printf "\t\t.args = (char []) {%s}\n", a + + print "\t}," } print "};" } function str2args(s, args, i, out) { - split(s, args, /,/) + if (split(s, args, /,/) == 0 || args[1] == "none") + return "" for (i in args) { a = args[i] - if (a == "none") { - break - } else if (match(a, /^imm8/)) { + if (match(a, /^imm8/)) { out = "AIMM8" } else if (match(a, /^imm16/)) { out = "AIMM16" diff --git a/inc/scc.h b/inc/scc.h @@ -44,3 +44,4 @@ extern Alloc *alloc(size_t size, size_t nmemb); extern void dealloc(Alloc *allocp); extern void *new(Alloc *allocp); extern void delete(Alloc *allocp, void *p); +extern int casecmp(const char *s1, const char *s2); diff --git a/lib/c/include/ctype.h b/lib/c/include/ctype.h @@ -28,18 +28,22 @@ extern int toupper(int c); #define _SP 0x80 /* hard space (0x20) */ extern unsigned char __ctype[]; - -#define isalnum(c) ((__ctype+1)[(c)] & (_U|_L|_D)) -#define isalpha(c) ((__ctype+1)[(c)] & (_U|_L)) -#define iscntrl(c) ((__ctype+1)[(c)] & (_C)) -#define isdigit(c) ((__ctype+1)[(c)] & (_D)) -#define isgraph(c) ((__ctype+1)[(c)] & (_P|_U|_L|_D)) -#define islower(c) ((__ctype+1)[(c)] & (_L)) -#define isprint(c) ((__ctype+1)[(c)] & (_P|_U|_L|_D|_SP)) -#define ispunct(c) ((__ctype+1)[(c)] & (_P)) -#define isspace(c) ((__ctype+1)[(c)] & (_S)) -#define isupper(c) ((__ctype+1)[(c)] & (_U)) -#define isxdigit(c) ((__ctype+1)[(c)] & (_D|_X)) +extern int __ctmp; + +#define isalnum(c) ((__ctype+1)[c] & (_U|_L|_D)) +#define isalpha(c) ((__ctype+1)[c] & (_U|_L)) +#define iscntrl(c) ((__ctype+1)[c] & (_C)) +#define isdigit(c) ((__ctype+1)[c] & (_D)) +#define isgraph(c) ((__ctype+1)[c] & (_P|_U|_L|_D)) +#define islower(c) ((__ctype+1)[c] & (_L)) +#define isprint(c) ((__ctype+1)[c] & (_P|_U|_L|_D|_SP)) +#define ispunct(c) ((__ctype+1)[c] & (_P)) +#define isspace(c) ((__ctype+1)[c] & (_S)) +#define isupper(c) ((__ctype+1)[c] & (_U)) +#define isxdigit(c) ((__ctype+1)[c] & (_D|_X)) + +#define tolower(c) ((__ctmp=c, isupper(__ctmp) ? __ctmp | 0x20 : __ctmp)) +#define toupper(c) ((__ctmp=c, islower(__ctmp) ? __ctmp & ~0x20 : __ctmp)) #define isascii(c) ((unsigned)(c)<=0x7f) diff --git a/lib/c/src/ctype.c b/lib/c/src/ctype.c @@ -2,6 +2,8 @@ #include <ctype.h> #undef ctype +int __ctmp; + /* __ctype is shifted by one to match EOF */ unsigned char __ctype[257] = { 0, /* EOF */ diff --git a/lib/scc/casecmp.c b/lib/scc/casecmp.c @@ -0,0 +1,11 @@ +static char sccsid[] = "@(#) ./lib/scc/casecmp.c"; +#include <ctype.h> +#include "../../inc/scc.h" + +int +casecmp(const char *s1, const char *s2) +{ + while (*s1 && toupper(*s1) == toupper(*s2)) + ++s1, ++s2; + return *s1 - *s2; +} diff --git a/lib/scc/libdep.mk b/lib/scc/libdep.mk @@ -6,3 +6,4 @@ LIB-OBJ = $(LIBDIR)/debug.o \ $(LIBDIR)/xrealloc.o \ $(LIBDIR)/xstrdup.o \ $(LIBDIR)/alloc.o \ + $(LIBDIR)/casecmp.o \