summary refs log tree commit diff
path: root/parse.c
diff options
context:
space:
mode:
authorQuentin Carbonneaux <quentin@c9x.me>2022-01-31 22:03:18 +0100
committerQuentin Carbonneaux <quentin@c9x.me>2022-02-02 21:09:37 +0100
commit2ca6fb25a238842418019a3f9ee8d1beb1327f7e (patch)
treebe083fc02dc8c1175f454b0adfd23d662f96476f /parse.c
parent20ee522ce8c4d1ffdd7b6e24a4f7af587c35404a (diff)
downloadroux-2ca6fb25a238842418019a3f9ee8d1beb1327f7e.tar.gz
shared linkage logic for func/data
Diffstat (limited to 'parse.c')
-rw-r--r--parse.c83
1 files changed, 45 insertions, 38 deletions
diff --git a/parse.c b/parse.c
index e97b196..5e5ab66 100644
--- a/parse.c
+++ b/parse.c
@@ -792,7 +792,7 @@ typecheck(Fn *fn)
 }
 
 static Fn *
-parsefn(int export)
+parsefn(Lnk *lnk)
 {
 	Blk *b;
 	int i;
@@ -812,7 +812,7 @@ parsefn(int export)
 		else
 			newtmp(0, Kl, curf);
 	curf->con[0].type = CBits;
-	curf->export = export;
+	curf->lnk = *lnk;
 	blink = &curf->start;
 	curf->retty = Kx;
 	if (peek() != Tglo)
@@ -973,7 +973,7 @@ parsedatref(Dat *d)
 	int t;
 
 	d->isref = 1;
-	d->u.ref.nam = tokval.str;
+	d->u.ref.name = tokval.str;
 	d->u.ref.off = 0;
 	t = peek();
 	if (t == Tplus) {
@@ -992,7 +992,7 @@ parsedatstr(Dat *d)
 }
 
 static void
-parsedat(void cb(Dat *), int export)
+parsedat(void cb(Dat *), Lnk *lnk)
 {
 	char name[NString] = {0};
 	int t;
@@ -1002,28 +1002,16 @@ parsedat(void cb(Dat *), int export)
 		err("data name, then = expected");
 	strncpy(name, tokval.str, NString-1);
 	t = nextnl();
-	d.u.str = 0;
-	if (t == Tsection) {
-		if (nextnl() != Tstr)
-			err("section \"name\" expected");
-		d.u.str = tokval.str;
-		t = nextnl();
-	}
-	d.type = DStart;
-	cb(&d);
+	lnk->align = 8;
 	if (t == Talign) {
 		if (nextnl() != Tint)
 			err("alignment expected");
-		d.type = DAlign;
-		d.u.num = tokval.num;
-		d.isstr = 0;
-		d.isref = 0;
-		cb(&d);
+		lnk->align = tokval.num;
 		t = nextnl();
 	}
-	d.type = DName;
-	d.u.str = name;
-	d.export = export;
+	d.type = DStart;
+	d.u.start.name = name;
+	d.u.start.lnk = lnk;
 	cb(&d);
 
 	if (t != Tlbrace)
@@ -1070,10 +1058,38 @@ Done:
 	cb(&d);
 }
 
+static int
+parselnk(Lnk *lnk)
+{
+	int t, haslnk;
+
+	for (haslnk=0;; haslnk=1)
+		switch ((t=nextnl())) {
+		case Texport:
+			lnk->export = 1;
+			break;
+		case Tsection:
+			if (next() != Tstr)
+				err("section \"name\" expected");
+			lnk->sec = tokval.str;
+			if (peek() == Tstr) {
+				next();
+				lnk->secf = tokval.str;
+			}
+			break;
+		default:
+			if (haslnk)
+			if (t != Tdata)
+			if (t != Tfunc)
+				err("only data and function have linkage");
+			return t;
+		}
+}
+
 void
 parse(FILE *f, char *path, void data(Dat *), void func(Fn *))
 {
-	int t, export;
+	Lnk lnk;
 
 	lexinit();
 	inf = f;
@@ -1083,25 +1099,16 @@ parse(FILE *f, char *path, void data(Dat *), void func(Fn *))
 	ntyp = 0;
 	typ = vnew(0, sizeof typ[0], Pheap);
 	for (;;) {
-		export = 0;
-		switch (nextnl()) {
+		lnk = (Lnk){0};
+		switch (parselnk(&lnk)) {
 		default:
 			err("top-level definition expected");
-		case Texport:
-			export = 1;
-			t = nextnl();
-			if (t == Tfunc) {
 		case Tfunc:
-				func(parsefn(export));
-				break;
-			}
-			else if (t == Tdata) {
+			func(parsefn(&lnk));
+			break;
 		case Tdata:
-				parsedat(data, export);
-				break;
-			}
-			else
-				err("export can only qualify data and function");
+			parsedat(data, &lnk);
+			break;
 		case Ttype:
 			parsetyp();
 			break;
@@ -1198,7 +1205,7 @@ printfn(Fn *fn, FILE *f)
 	Ins *i;
 	uint n;
 
-	if (fn->export)
+	if (fn->lnk.export)
 		fprintf(f, "export ");
 	fprintf(f, "function $%s() {\n", fn->name);
 	for (b=fn->start; b; b=b->link) {