commit 50c5af4290aed32a7733768c1bee2e64c93a7f84
parent ec7c4e0d60e22c10b6f7817436bd3f4abf2d5356
Author: Ori Bernstein <ori@eigenstate.org>
Date: Sun, 28 Feb 2016 20:02:36 -0800
Allow trailing and ',' and references in data.
This change adds support for two things:
data $foo {l 123,}
Which allows easier machine generation of data
statements. It also adds the ability to parse
and emit references in data declarations.
Diffstat:
3 files changed, 37 insertions(+), 4 deletions(-)
diff --git a/lisc/emit.c b/lisc/emit.c
@@ -553,7 +553,10 @@ emitdat(Dat *d, FILE *f)
fprintf(f, "\t.asciz \"%s\"\n", d->u.str);
break;
default:
- fprintf(f, "%s %"PRId64"\n", dtoa[d->type], d->u.num);
+ if (d->isref)
+ fprintf(f, "%s %s+%"PRId64"\n", dtoa[d->type], d->u.ref.nam, d->u.ref.off);
+ else
+ fprintf(f, "%s %"PRId64"\n", dtoa[d->type], d->u.num);
break;
}
}
diff --git a/lisc/lisc.h b/lisc/lisc.h
@@ -440,7 +440,12 @@ struct Dat {
double fltd;
float flts;
char *str;
+ struct {
+ char *nam;
+ int64_t off;
+ } ref;
} u;
+ char isref;
};
diff --git a/lisc/parse.c b/lisc/parse.c
@@ -88,6 +88,8 @@ enum {
TD,
TS,
+ TPlus,
+
TInt,
TFlts,
TFltd,
@@ -111,6 +113,7 @@ static FILE *inf;
static char *inpath;
static int thead;
static struct {
+ char chr;
double fltd;
float flts;
int64_t num;
@@ -186,6 +189,7 @@ lex()
c = fgetc(inf);
while (isblank(c));
t = TXXX;
+ tokval.chr = c;
switch (c) {
case EOF:
return TEOF;
@@ -201,6 +205,8 @@ lex()
return TRBrace;
case '=':
return TEq;
+ case '+':
+ return TPlus;
case 's':
if (fscanf(inf, "_%f", &tokval.flts) != 1)
break;
@@ -710,7 +716,7 @@ parsetyp()
for (;;) {
flt = 0;
switch (t) {
- default: err("invalid size specifier");
+ default: err("invalid size specifier %c", tokval.chr);
case TD: flt = 1;
case TL: s = 8; a = 3; break;
case TS: flt = 1;
@@ -761,6 +767,20 @@ parsetyp()
}
static void
+parsedataref(Dat *d)
+{
+ d->isref = 1;
+ d->u.ref.nam = tokval.str;
+ d->u.ref.off = 0;
+ if (peek() == TPlus) {
+ next();
+ if (next() != TInt)
+ err("invalid token after offset in ref");
+ d->u.ref.off = tokval.num;
+ }
+}
+
+static void
parsedat(void cb(Dat *))
{
char s[NString];
@@ -787,13 +807,15 @@ parsedat(void cb(Dat *))
if (t == TStr) {
d.type = DA;
d.u.str = tokval.str;
+ d.isref = 0;
cb(&d);
} else {
if (t != TLBrace)
err("data contents must be { .. } or \" .. \"");
for (;;) {
switch (nextnl()) {
- default: err("invalid size specifier in data");
+ default: err("invalid size specifier %c in data", tokval.chr);
+ case TRBrace: goto Done;
case TL: d.type = DL; break;
case TW: d.type = DW; break;
case TH: d.type = DH; break;
@@ -803,7 +825,7 @@ parsedat(void cb(Dat *))
}
t = nextnl();
do {
-
+ d.isref = 0;
memset(&d.u, 0, sizeof d.u);
if (t == TFlts)
d.u.flts = tokval.flts;
@@ -811,6 +833,8 @@ parsedat(void cb(Dat *))
d.u.fltd = tokval.fltd;
else if (t == TInt)
d.u.num = tokval.num;
+ else if (t == TGlo)
+ parsedataref(&d);
else
err("constant literal expected");
cb(&d);
@@ -822,6 +846,7 @@ parsedat(void cb(Dat *))
err(", or } expected");
}
}
+Done:
d.type = DEnd;
cb(&d);
}