shithub: scc

Download patch

ref: 4dba5596398fe88df1210f15d0a1ccb68604c2da
parent: 33983a06ec430df20df57df38c3b142dc495c5a2
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Sat Sep 9 06:08:17 EDT 2017

[as] Add parser.c

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

--- a/as/Makefile
+++ b/as/Makefile
@@ -4,7 +4,7 @@
 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:
@@ -16,7 +16,6 @@
 
 $(LIBDIR)/libscc.a:
 	cd $(LIBDIR) && $(MAKE)
-
 
 dep:
 	./gendep.sh $(TARGETS)
--- a/as/as.h
+++ b/as/as.h
@@ -22,6 +22,12 @@
 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 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;
--- 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,60 +36,7 @@
 	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
+void
 incpc(int siz)
 {
 	TUINT pc, curpc;
@@ -145,54 +88,20 @@
 }
 
 int
-extract(char *p, char **lbl, char **ins, char **args)
+dopass(char *fname)
 {
-	*lbl = p;
-	*ins = NULL;
-	*args = NULL;
+	struct line line;
+	FILE *fp;
 
-	if ((p = strchr(p, '\t')) == NULL)
-		return 0;
-	*p++ = '\0';
+	if ((fp = fopen(fname, "r")) == NULL)
+		die("as: error opening '%s'", fname);
 
-	*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;
-}
-
-int
-dopass(char *file)
-{
-	FILE *in;
-	char line[MAXLINE], *ins, *lbl, *args;
-
-	if ((in = fopen(file, "r")) == NULL)
-		die("error opening '%s'", file);
-
 	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;
 }
 
--- /dev/null
+++ b/as/parser.c
@@ -1,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;
+}