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:
M | as/Makefile | | | 3 | +-- |
M | as/as.h | | | 13 | +++++++++++++ |
M | as/main.c | | | 109 | +++++++------------------------------------------------------------------------ |
A | 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;
+}