scc

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

commit c3a5d9f3ceb74e55f3100d83077f9ed2dff81280
parent ff1d5bcf7a7c812523cb8be76fd5bde6322efe66
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Sat,  9 Sep 2017 10:08:17 +0200

[as] Add parser.c

Split the content of main.c between main control flow and parsing
functions.

Diffstat:
as/Makefile | 3+--
as/as.h | 13+++++++++++++
as/main.c | 109+++++++------------------------------------------------------------------------
as/parser.c | 109+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 132 insertions(+), 102 deletions(-)

diff --git a/as/Makefile b/as/Makefile @@ -4,7 +4,7 @@ LIBDIR = ../lib/scc include ../config.mk include $(LIBDIR)/libdep.mk -OBJ = main.o emit.o ins.o +OBJ = main.o emit.o ins.o parser.o HDR = ../inc/scc.h as.h all: @@ -17,7 +17,6 @@ as: $(OBJ) $(LIBDIR)/libscc.a: cd $(LIBDIR) && $(MAKE) - dep: ./gendep.sh $(TARGETS) diff --git a/as/as.h b/as/as.h @@ -22,6 +22,12 @@ typedef struct arg Arg; typedef void Format(Op *, Arg *); typedef struct section Section; +struct line { + char *label; + char *op; + char *args; +}; + struct ins { int begin, end; char *str; @@ -57,6 +63,13 @@ extern void emit(Section *sec, char *bytes, int nbytes); extern Section *section(char *name); extern void incpc(int siz); extern char *pack(TUINT v, int n, int inc); +extern void error(char *msg, ...); +extern Arg *getargs(char *s); + +/* Avoid errors in files where stdio is not included */ +#ifdef stdin +extern int next(FILE *fp, struct line *linep); +#endif extern Section *cursec; extern int nr_ins; diff --git a/as/main.c b/as/main.c @@ -1,5 +1,4 @@ -#include <ctype.h> #include <stdarg.h> #include <stdio.h> #include <stdlib.h> @@ -8,9 +7,6 @@ #include "../inc/scc.h" #include "as.h" -#define MAXLINE 100 -#define NARGS 20 - int nerrors; void @@ -40,59 +36,6 @@ match(Op *op, Arg *args) return 1; } -Arg -number(char *s, int base) -{ - Arg arg; - TUINT n; - - /* TODO: Check overflow here */ - arg.type = AIMM; - for (n = 0; *s; n += *s++ - '0') - n *= base; - arg.val = n; - - return arg; -} - -Arg * -getargs(char *s) -{ - char *t; - int ch, len; - Arg *ap; - static Arg args[NARGS]; - - for (ap = args; s; ++ap) { - while (isspace(*s)) - ++s; - if (*s == '\0') - break; - if (ap == &args[NARGS-1]) - die("too many arguments in one instruction"); - - for (t = s; *s && *s != ','; s++) - /* nothing */; - len = t - s; - if (len == 0) - goto wrong_operand; - - if (*s) - *s++ = '\0'; - - ch = *t; - if (isdigit(ch)) { - *ap = number(t, (s[len-1] == 'H') ? 16 : 10); - continue; - } -wrong_operand: - error("wrong operand '%s'", t); - } - ap->type = 0; - - return args; -} - void incpc(int siz) { @@ -145,54 +88,20 @@ as(char *text, char *xargs) } int -extract(char *p, char **lbl, char **ins, char **args) +dopass(char *fname) { - *lbl = p; - *ins = NULL; - *args = NULL; - - if ((p = strchr(p, '\t')) == NULL) - return 0; - *p++ = '\0'; - - *ins = p; - if ((p = strchr(p, '\t')) == NULL) - return 1; - *p++ = '\0'; - - *args = p; - if ((p = strchr(p, '\t')) == NULL) - return 2; - *p = '\0'; - return 3; -} + struct line line; + FILE *fp; -int -dopass(char *file) -{ - FILE *in; - char line[MAXLINE], *ins, *lbl, *args; - - if ((in = fopen(file, "r")) == NULL) - die("error opening '%s'", file); + if ((fp = fopen(fname, "r")) == NULL) + die("as: error opening '%s'", fname); isections(); + while (next(fp, &line)) + as(line.op, line.args); - while (fgets(line, sizeof(line), in)) { - size_t n = strlen(line); - if (n == 0 || line[0] == ';') - continue; - if (line[n-1] != '\n') { - error("line too long"); - continue; - } - line[n-1] = '\0'; - if (extract(line, &lbl, &ins, &args) > 0) - as(ins, args); - } - - if (fclose(in)) - die("error reading from input file"); + if (fclose(fp)) + die("as: error reading from input file '%s'", fname); return nerrors == 0; } diff --git a/as/parser.c b/as/parser.c @@ -0,0 +1,109 @@ +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "../inc/scc.h" +#include "as.h" + +#define NARGS 20 +#define MAXLINE 100 + + +Arg +number(char *s, int base) +{ + Arg arg; + TUINT n; + + /* TODO: Check overflow here */ + arg.type = AIMM; + for (n = 0; *s; n += *s++ - '0') + n *= base; + arg.val = n; + + return arg; +} + +Arg * +getargs(char *s) +{ + char *t; + int ch, len; + Arg *ap; + static Arg args[NARGS]; + + for (ap = args; s; ++ap) { + while (isspace(*s)) + ++s; + if (*s == '\0') + break; + if (ap == &args[NARGS-1]) + die("too many arguments in one instruction"); + + for (t = s; *s && *s != ','; s++) + /* nothing */; + len = t - s; + if (len == 0) + goto wrong_operand; + + if (*s) + *s++ = '\0'; + + ch = *t; + if (isdigit(ch)) { + *ap = number(t, (s[len-1] == 'H') ? 16 : 10); + continue; + } +wrong_operand: + error("wrong operand '%s'", t); + } + ap->type = 0; + + return args; +} + +int +extract(char *p, struct line *linep) +{ + linep->label = p; + linep->op = NULL; + linep->args = NULL; + + if ((p = strchr(p, '\t')) == NULL) + return 0; + *p++ = '\0'; + + linep->op = p; + if ((p = strchr(p, '\t')) == NULL) + return 1; + *p++ = '\0'; + + linep->args = p; + if ((p = strchr(p, '\t')) == NULL) + return 2; + *p = '\0'; + return 3; +} + +int +next(FILE *fp, struct line *linep) +{ + size_t n; + static char buff[MAXLINE]; + +repeat: + if (!fgets(buff, sizeof(buff), fp)) + return 0; + + n = strlen(buff); + if (n == 0 || buff[0] == ';') + goto repeat; + if (buff[n-1] != '\n') { + error("buff too long"); + goto repeat; + } + buff[n-1] = '\0'; + if (extract(buff, linep) == 0) + goto repeat; +}