shithub: scc

Download patch

ref: 395a3c572792c6270427954ff55b76c6d976a479
parent: 60c8089ebc884a96d6a89c7388c579973d3e59fd
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Thu Feb 1 14:57:54 EST 2018

[as] Add support for recursive inclusion

--- a/as/as.h
+++ b/as/as.h
@@ -176,6 +176,8 @@
 extern void regctx(int mode);
 extern Node *getreg(void);
 extern Node *operand(char **s);
+extern void addinput(char *fname);
+extern int delinput(void);
 
 /* expr.c */
 extern Node *expr(void);
--- a/as/expr.c
+++ b/as/expr.c
@@ -164,20 +164,14 @@
 static Node *
 primary(void)
 {
-	int addr, op;
 	Node *np;
 
 	switch (yytoken) {
 	case IDEN:
 	case NUMBER:
-		addr = ANUMBER;
-		goto basic_atom;
-	case STRING:
-		addr = ASTR;
-	basic_atom:
 		np = node(yytoken, NULL, NULL);
 		np->sym = yylval.sym;
-		np->addr = addr;
+		np->addr = ANUMBER;
 		next();
 		break;
 	case '(':
--- a/as/ins.c
+++ b/as/ins.c
@@ -241,3 +241,9 @@
 {
 	endpass = 1;
 }
+
+void
+include(Op *op, Node **args)
+{
+	addinput(args[0]->sym->name.buf);
+}
--- a/as/main.c
+++ b/as/main.c
@@ -74,8 +74,7 @@
 	extern int nerrors;
 	extern jmp_buf recover;
 
-	if ((fp = fopen(fname, "r")) == NULL)
-		die("as: error opening '%s'", fname);
+	addinput(fname);
 	cleansecs();
 
 	endpass = 0;
@@ -92,8 +91,6 @@
 			error("arguments without an opcode");
 	}
 
-	if (fclose(fp))
-		die("as: error reading from input file '%s'", fname);
 	return nerrors == 0;
 }
 
--- a/as/parser.c
+++ b/as/parser.c
@@ -1,4 +1,5 @@
 static char sccsid[] = "@(#) ./as/parser.c";
+#include <assert.h>
 #include <ctype.h>
 #include <limits.h>
 #include <setjmp.h>
@@ -12,8 +13,15 @@
 #include "as.h"
 
 #define NARGS 20
+#define NR_INPUTS 10
 #define MAXLINE 100
 
+struct input {
+	char *fname;
+	unsigned lineno;
+	FILE *fp;
+};
+
 int nerrors;
 jmp_buf recover;
 char yytext[INTIDENTSIZ+1];
@@ -24,6 +32,7 @@
 static char *textp, *endp;
 static int regmode;
 static unsigned lineno;
+static struct input inputs[NR_INPUTS], *isp = inputs;
 
 static int
 follow(int expect1, int expect2, int ifyes1, int ifyes2, int ifno)
@@ -121,15 +130,20 @@
 string(void)
 {
 	int c;
-	char *p;
+	size_t l;
+	char *s;
+	Symbol *sym = tmpsym(0);
 
 	for (++endp; *endp != '"'; ++endp)
 		;
 	++endp;
 	tok2str();
-	yylval.sym = tmpsym(0);
+	yylval.sym = sym;
 	/* FIXME: this memory is not freed ever */
-	yylval.sym->name.buf = xstrdup(yytext);
+	l = yylen-2;
+	s = memcpy(xmalloc(l+1), yytext+1, l);
+	s[l] = '\0';
+	sym->name.buf = s;
 
 	return STRING;
 }
@@ -207,9 +221,13 @@
 error(char *msg, ...)
 {
 	va_list va;
+	struct input *ip;
 
+	assert(isp > inputs);
+	ip = &isp[-1];
+
 	va_start(va, msg);
-	fprintf(stderr, "as:%s:%u: ", infile, lineno);
+	fprintf(stderr, "as:%s:%u: ", ip->fname, ip->lineno);
 	vfprintf(stderr, msg, va);
 	putc('\n', stderr);
 	nerrors++;
@@ -253,6 +271,12 @@
 	case REG:
 		np = getreg();
 		break;
+	case STRING:
+		np = node(yytoken, NULL, NULL);
+		np->sym = yylval.sym;
+		np->addr = ASTR;
+		next();
+		break;
 	case '$':
 		next();
 		imm = 1;
@@ -403,17 +427,51 @@
 int
 nextline(FILE *fp, struct line *lp)
 {
+	struct input *ip;
 	size_t n;
 	static char buff[MAXLINE];
 
+	assert(isp > inputs);
 repeat:
-	if (feof(fp))
+	if (isp == inputs)
 		return 0;
-	if ((n = getline(fp, buff)) == 0)
+	ip = &isp[-1];
+	if (feof(ip->fp)) {
+		delinput();
 		goto repeat;
-	if (++lineno == 0)
+	}
+	if ((n = getline(ip->fp, buff)) == 0)
+		goto repeat;
+	if (++ip->lineno == 0)
 		die("as: file too long");
 	if (extract(buff, n, lp) == 0)
 		goto repeat;
 	return 1;
+}
+
+void
+addinput(char *fname)
+{
+	FILE *fp;
+
+	if (isp == &inputs[NR_INPUTS])
+		die("too many included files");
+	if ((fp = fopen(fname, "r")) == NULL)
+		die("error opening input file '%s'", fname);
+	isp->fname = xstrdup(fname);
+	isp->fp = fp;
+	isp->lineno = 0;
+	++isp;
+}
+
+int
+delinput(void)
+{
+	if (isp == inputs)
+		return EOF;
+	--isp;
+	if (fclose(isp->fp) == EOF)
+		die("error closing file '%s'", isp->fname);
+	free(isp->fname);
+	return 0;
 }
--- a/as/target/x80/x80.dat
+++ b/as/target/x80/x80.dat
@@ -32,6 +32,7 @@
 .ASCII	string+	0	none	ascii	Z80,R800,GB80
 .ALIGN	imm16+	0	none	align	Z80,R800,GB80
 .END	none	0	none	end	Z80,R800,GB80
+.INCLUDE	string	0	none	include	Z80,R800,GB80