commit aaab3e3

Devine Lu Linvega  ·  2024-03-06 16:50:46 +0000 UTC
parent c95c615
(uxnasm) Stop after hitting refcount limit
1 files changed,  +83, -69
+83, -69
  1@@ -36,12 +36,12 @@ typedef struct {
  2 typedef struct {
  3 	Uint8 data[LENGTH];
  4 	Uint8 lambda_stack[0x100], lambda_ptr, lambda_count;
  5-	char scope[0x40], lambda[0x10];
  6+	char scope[0x40], lambda[0x10], *location, *entry;
  7 	unsigned int ptr, length;
  8 	Uint16 label_len, macro_len, refs_len;
  9 	Label labels[0x400];
 10 	Macro macros[0x100];
 11-	Reference refs[0x800];
 12+	Reference refs[0x1000];
 13 } Program;
 14 
 15 Program p;
 16@@ -70,17 +70,38 @@ static char *scat(char *dst, const char *src) { char *ptr = dst + slen(dst); whi
 17 static int parse(char *w, FILE *f);
 18 
 19 static int
 20-error(const char *name, const char *msg)
 21+error_top(const char *name, const char *msg)
 22 {
 23 	fprintf(stderr, "%s: %s\n", name, msg);
 24 	return 0;
 25 }
 26 
 27+static int
 28+error_asm(const char *name, const char *msg)
 29+{
 30+	fprintf(stderr, "%s: %s in @%s, %s:%d.\n", name, msg, p.scope, p.location, 123);
 31+	return 0;
 32+}
 33+
 34+static int
 35+error_res(const char *name, const char *msg)
 36+{
 37+	fprintf(stderr, "%s: %s.\n", name, msg);
 38+	return 0;
 39+}
 40+
 41+static char *
 42+setlocation(char *name)
 43+{
 44+	p.location = name;
 45+	return name;
 46+}
 47+
 48 static char *
 49 sublabel(char *src, char *scope, char *name)
 50 {
 51 	if(slen(scope) + slen(name) >= 0x3f) {
 52-		error("Sublabel length too long", name);
 53+		error_asm("Sublabel length too long", name);
 54 		return NULL;
 55 	}
 56 	return scat(scat(scpy(scope, src, 0x40), "/"), name);
 57@@ -137,22 +158,22 @@ makemacro(char *name, FILE *f)
 58 	Macro *m;
 59 	char word[0x40];
 60 	if(findmacro(name))
 61-		return error("Macro duplicate", name);
 62+		return error_asm("Macro duplicate", name);
 63 	if(sihx(name) && slen(name) % 2 == 0)
 64-		return error("Macro name is hex number", name);
 65+		return error_asm("Macro name is hex number", name);
 66 	if(findopcode(name) || scmp(name, "BRK", 4) || !slen(name))
 67-		return error("Macro name is invalid", name);
 68+		return error_asm("Macro name is invalid", name);
 69 	if(p.macro_len == 0x100)
 70-		return error("Macros limit exceeded", name);
 71+		return error_asm("Macros limit exceeded", name);
 72 	m = &p.macros[p.macro_len++];
 73 	scpy(name, m->name, 0x40);
 74 	while(fscanf(f, "%63s", word) == 1) {
 75 		if(word[0] == '{') continue;
 76 		if(word[0] == '}') break;
 77 		if(word[0] == '%')
 78-			return error("Macro error", name);
 79+			return error_asm("Macro error", name);
 80 		if(m->len >= 0x40)
 81-			return error("Macro size exceeded", name);
 82+			return error_asm("Macro size exceeded", name);
 83 		scpy(word, m->items[m->len++], 0x40);
 84 	}
 85 	return 1;
 86@@ -172,15 +193,15 @@ makelabel(char *name)
 87 {
 88 	Label *l;
 89 	if(findlabel(name))
 90-		return error("Label duplicate", name);
 91+		return error_asm("Label duplicate", name);
 92 	if(sihx(name) && (slen(name) == 2 || slen(name) == 4))
 93-		return error("Label name is hex number", name);
 94+		return error_asm("Label name is hex number", name);
 95 	if(findopcode(name) || scmp(name, "BRK", 4) || !slen(name))
 96-		return error("Label name is invalid", name);
 97+		return error_asm("Label name is invalid", name);
 98 	if(isrune(name[0]))
 99-		return error("Label name is runic", name);
100+		return error_asm("Label name is runic", name);
101 	if(p.label_len == 0x400)
102-		return error("Labels limit exceeded", name);
103+		return error_asm("Labels limit exceeded", name);
104 	l = &p.labels[p.label_len++];
105 	l->addr = p.ptr;
106 	l->refs = 0;
107@@ -202,15 +223,15 @@ makereference(char *scope, char *label, char rune, Uint16 addr)
108 {
109 	char subw[0x40], parent[0x40];
110 	Reference *r;
111-	if(p.refs_len >= 0x800)
112-		return error("References limit exceeded", label);
113+	if(p.refs_len >= 0x1000)
114+		return error_asm("References limit exceeded", label);
115 	r = &p.refs[p.refs_len++];
116 	if(label[0] == '{') {
117 		p.lambda_stack[p.lambda_ptr++] = p.lambda_count;
118 		scpy(makelambda(p.lambda_count++), r->name, 0x40);
119 	} else if(label[0] == '&' || label[0] == '/') {
120 		if(!sublabel(subw, scope, label + 1))
121-			return error("Invalid sublabel", label);
122+			return error_asm("Invalid sublabel", label);
123 		scpy(subw, r->name, 0x40);
124 	} else {
125 		int pos = spos(label, '/');
126@@ -230,11 +251,11 @@ static int
127 writebyte(Uint8 b)
128 {
129 	if(p.ptr < TRIM)
130-		return error("Writing in zero-page", "");
131+		return error_asm("Writing in zero-page", "");
132 	else if(p.ptr > 0xffff)
133-		return error("Writing after the end of RAM", "");
134+		return error_asm("Writing after the end of RAM", "");
135 	else if(p.ptr < p.length)
136-		return error("Memory overwrite", "");
137+		return error_asm("Memory overwrite", "");
138 	p.data[p.ptr++] = b;
139 	p.length = p.ptr;
140 	return 1;
141@@ -261,15 +282,15 @@ writelitbyte(Uint8 b)
142 }
143 
144 static int
145-doinclude(const char *filename)
146+doinclude(char *filename)
147 {
148 	FILE *f;
149 	char w[0x40];
150-	if(!(f = fopen(filename, "r")))
151-		return error("Include missing", filename);
152+	if(!(f = fopen(setlocation(filename), "r")))
153+		return error_asm("Include missing", filename);
154 	while(fscanf(f, "%63s", w) == 1)
155 		if(!parse(w, f))
156-			return error("Unknown token", w);
157+			return error_asm("Unknown token", w);
158 	fclose(f);
159 	return 1;
160 }
161@@ -282,7 +303,7 @@ parse(char *w, FILE *f)
162 	Label *l;
163 	Macro *m;
164 	if(slen(w) >= 63)
165-		return error("Invalid token", w);
166+		return error_asm("Invalid token", w);
167 	switch(w[0]) {
168 	case '(': /* comment */
169 		if(slen(w) != 1) fprintf(stderr, "-- Malformed comment: %s\n", w);
170@@ -298,22 +319,22 @@ parse(char *w, FILE *f)
171 		break;
172 	case '~': /* include */
173 		if(!doinclude(w + 1))
174-			return error("Invalid include", w);
175+			return error_asm("Invalid include", w);
176 		break;
177 	case '%': /* macro */
178 		if(!makemacro(w + 1, f))
179-			return error("Invalid macro", w);
180+			return error_asm("Invalid macro", w);
181 		break;
182 	case '|': /* pad-absolute */
183 		if(sihx(w + 1))
184 			p.ptr = shex(w + 1);
185 		else if(w[1] == '&') {
186 			if(!sublabel(subw, p.scope, w + 2) || !(l = findlabel(subw)))
187-				return error("Invalid sublabel", w);
188+				return error_asm("Invalid sublabel", w);
189 			p.ptr = l->addr;
190 		} else {
191 			if(!(l = findlabel(w + 1)))
192-				return error("Invalid label", w);
193+				return error_asm("Invalid label", w);
194 			p.ptr = l->addr;
195 		}
196 		break;
197@@ -322,17 +343,17 @@ parse(char *w, FILE *f)
198 			p.ptr += shex(w + 1);
199 		else if(w[1] == '&') {
200 			if(!sublabel(subw, p.scope, w + 2) || !(l = findlabel(subw)))
201-				return error("Invalid sublabel", w);
202+				return error_asm("Invalid sublabel", w);
203 			p.ptr += l->addr;
204 		} else {
205 			if(!(l = findlabel(w + 1)))
206-				return error("Invalid label", w);
207+				return error_asm("Invalid label", w);
208 			p.ptr += l->addr;
209 		}
210 		break;
211 	case '@': /* label */
212 		if(!makelabel(w + 1))
213-			return error("Invalid label", w);
214+			return error_asm("Invalid label", w);
215 		i = 0;
216 		while(w[i + 1] != '/' && i < 0x3e && (p.scope[i] = w[i + 1]))
217 			i++;
218@@ -340,7 +361,7 @@ parse(char *w, FILE *f)
219 		break;
220 	case '&': /* sublabel */
221 		if(!sublabel(subw, p.scope, w + 1) || !makelabel(subw))
222-			return error("Invalid sublabel", w);
223+			return error_asm("Invalid sublabel", w);
224 		break;
225 	case '#': /* literals hex */
226 		if(sihx(w + 1) && slen(w) == 3)
227@@ -348,32 +369,25 @@ parse(char *w, FILE *f)
228 		else if(sihx(w + 1) && slen(w) == 5)
229 			return writeshort(shex(w + 1), 1);
230 		else
231-			return error("Invalid hex literal", w);
232+			return error_asm("Invalid hex literal", w);
233 		break;
234 	case '_': /* raw byte relative */
235-		makereference(p.scope, w + 1, w[0], p.ptr);
236-		return writebyte(0xff);
237+		return writebyte(0xff) && makereference(p.scope, w + 1, w[0], p.ptr);
238 	case ',': /* literal byte relative */
239-		makereference(p.scope, w + 1, w[0], p.ptr + 1);
240-		return writelitbyte(0xff);
241+		return writelitbyte(0xff) && makereference(p.scope, w + 1, w[0], p.ptr + 1);
242 	case '-': /* raw byte absolute */
243-		makereference(p.scope, w + 1, w[0], p.ptr);
244-		return writebyte(0xff);
245+		return writebyte(0xff) && makereference(p.scope, w + 1, w[0], p.ptr);
246 	case '.': /* literal byte zero-page */
247-		makereference(p.scope, w + 1, w[0], p.ptr + 1);
248-		return writelitbyte(0xff);
249+		return writelitbyte(0xff) && makereference(p.scope, w + 1, w[0], p.ptr + 1);
250+	case ':': fprintf(stderr, "Deprecated rune %s, use =%s\n", w, w + 1);
251 	case '=': /* raw short absolute */
252-		makereference(p.scope, w + 1, w[0], p.ptr);
253-		return writeshort(0xffff, 0);
254+		return writeshort(0xffff, 0) && makereference(p.scope, w + 1, w[0], p.ptr);
255 	case ';': /* literal short absolute */
256-		makereference(p.scope, w + 1, w[0], p.ptr + 1);
257-		return writeshort(0xffff, 1);
258+		return writeshort(0xffff, 1) && makereference(p.scope, w + 1, w[0], p.ptr + 1);
259 	case '?': /* JCI */
260-		makereference(p.scope, w + 1, w[0], p.ptr + 1);
261-		return writebyte(0x20) && writeshort(0xffff, 0);
262+		return writebyte(0x20) && writeshort(0xffff, 0) && makereference(p.scope, w + 1, w[0], p.ptr + 1);
263 	case '!': /* JMI */
264-		makereference(p.scope, w + 1, w[0], p.ptr + 1);
265-		return writebyte(0x40) && writeshort(0xffff, 0);
266+		return writebyte(0x40) && writeshort(0xffff, 0) && makereference(p.scope, w + 1, w[0], p.ptr + 1);
267 	case '"': /* raw string */
268 		i = 0;
269 		while((c = w[++i]))
270@@ -381,7 +395,7 @@ parse(char *w, FILE *f)
271 		break;
272 	case '}': /* lambda end */
273 		if(!makelabel(makelambda(p.lambda_stack[--p.lambda_ptr])))
274-			return error("Invalid label", w);
275+			return error_asm("Invalid label", w);
276 		break;
277 	case '[':
278 	case ']':
279@@ -402,10 +416,8 @@ parse(char *w, FILE *f)
280 				if(!parse(m->items[i], f))
281 					return 0;
282 			return 1;
283-		} else {
284-			makereference(p.scope, w, ' ', p.ptr + 1);
285-			return writebyte(0x60) && writeshort(0xffff, 0);
286-		}
287+		} else
288+			return writebyte(0x60) && writeshort(0xffff, 0) && makereference(p.scope, w, ' ', p.ptr + 1);
289 	}
290 	return 1;
291 }
292@@ -422,23 +434,24 @@ resolve(void)
293 		case '_':
294 		case ',':
295 			if(!(l = findlabel(r->name)))
296-				return error("Unknown relative reference", r->name);
297+				return error_res("Unknown relative reference", r->name);
298 			p.data[r->addr] = (Sint8)(l->addr - r->addr - 2);
299 			if((Sint8)p.data[r->addr] != (l->addr - r->addr - 2))
300-				return error("Relative reference is too far", r->name);
301+				return error_asm("Relative reference is too far", r->name);
302 			l->refs++;
303 			break;
304 		case '-':
305 		case '.':
306 			if(!(l = findlabel(r->name)))
307-				return error("Unknown zero-page reference", r->name);
308+				return error_res("Unknown zero-page reference", r->name);
309 			p.data[r->addr] = l->addr & 0xff;
310 			l->refs++;
311 			break;
312+		case ':':
313 		case '=':
314 		case ';':
315 			if(!(l = findlabel(r->name)))
316-				return error("Unknown absolute reference", r->name);
317+				return error_res("Unknown absolute reference", r->name);
318 			p.data[r->addr] = l->addr >> 0x8;
319 			p.data[r->addr + 1] = l->addr & 0xff;
320 			l->refs++;
321@@ -447,7 +460,7 @@ resolve(void)
322 		case '!':
323 		default:
324 			if(!(l = findlabel(r->name)))
325-				return error("Unknown absolute reference", r->name);
326+				return error_res("Unknown absolute reference", r->name);
327 			a = l->addr - r->addr - 2;
328 			p.data[r->addr] = a >> 0x8;
329 			p.data[r->addr + 1] = a & 0xff;
330@@ -466,7 +479,7 @@ assemble(FILE *f)
331 	scpy("on-reset", p.scope, 0x40);
332 	while(fscanf(f, "%62s", w) == 1)
333 		if(slen(w) > 0x3d || !parse(w, f))
334-			return error("Invalid token", w);
335+			return error_asm("Invalid token", w);
336 	return resolve();
337 }
338 
339@@ -513,17 +526,18 @@ main(int argc, char *argv[])
340 {
341 	FILE *src, *dst;
342 	if(argc == 1)
343-		return error("usage", "uxnasm [-v] input.tal output.rom");
344+		return error_top("usage", "uxnasm [-v] input.tal output.rom");
345 	if(argv[1][0] == '-' && argv[1][1] == 'v')
346-		return !fprintf(stdout, "Uxnasm - Uxntal Assembler, 25 Feb 2024.\n");
347-	if(!(src = fopen(argv[1], "r")))
348-		return !error("Invalid input", argv[1]);
349+		return !fprintf(stdout, "Uxnasm - Uxntal Assembler, 6 Mar 2024.\n");
350+	if(!(src = fopen(setlocation(argv[1]), "r")))
351+		return !error_top("Invalid input", argv[1]);
352+	p.entry = argv[1];
353 	if(!assemble(src))
354-		return !error("Assembly", "Failed to assemble rom.");
355+		return !error_top("Assembly", "Failed to assemble rom.");
356 	if(!(dst = fopen(argv[2], "wb")))
357-		return !error("Invalid Output", argv[2]);
358+		return !error_top("Invalid Output", argv[2]);
359 	if(p.length <= TRIM)
360-		return !error("Assembly", "Output rom is empty.");
361+		return !error_top("Assembly", "Output rom is empty.");
362 	fwrite(p.data + TRIM, p.length - TRIM, 1, dst);
363 	if(!scmp(argv[2], "-", 2)) {
364 		review(argv[2]);