scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | README | LICENSE

commit 4e925d3950f940b0548c667562bbdd0b26215f8a
parent b4dd373179be477ee99841c21119700ae4159510
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Thu,  1 Feb 2018 19:57:54 +0100

[as] Add support for recursive inclusion

Diffstat:
Mas/as.h | 2++
Mas/expr.c | 8+-------
Mas/ins.c | 6++++++
Mas/main.c | 5+----
Mas/parser.c | 72+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
Mas/target/x80/x80.dat | 1+
6 files changed, 76 insertions(+), 18 deletions(-)

diff --git a/as/as.h b/as/as.h @@ -176,6 +176,8 @@ int next(void); 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); diff --git a/as/expr.c b/as/expr.c @@ -164,20 +164,14 @@ unaryop(int op, Node *np) 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 '(': diff --git a/as/ins.c b/as/ins.c @@ -241,3 +241,9 @@ end(Op *op, Node **args) { endpass = 1; } + +void +include(Op *op, Node **args) +{ + addinput(args[0]->sym->name.buf); +} diff --git a/as/main.c b/as/main.c @@ -74,8 +74,7 @@ dopass(char *fname) 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 @@ dopass(char *fname) error("arguments without an opcode"); } - 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 @@ -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 @@ static char sccsid[] = "@(#) ./as/parser.c"; #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 @@ union yylval yylval; 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 @@ static int 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 @@ void 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 @@ operand(char **strp) 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 @@ getline(FILE *fp, char buff[MAXLINE]) 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 ((n = getline(ip->fp, buff)) == 0) goto repeat; - if (++lineno == 0) + 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; +} diff --git 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