shithub: rgbds

Download patch

ref: e596dbfc80112c5da0fa8906fc262c63bb6c63c9
parent: 1aeaca2af602b19c5af2fc2bb2a71934eda2a0d0
author: Rangi <remy.oukaour+rangi42@gmail.com>
date: Tue Apr 20 07:51:01 EDT 2021

Make failed macro arg expansions non-fatal

Expanding empty strings is valid but pointless;
macro args already skipped doing so, now other
`beginExpansion` calls do too.

This also fixes failed interpolations (which were
already non-fatal) to continue reading characters,
not evaluate to their initial '{' character.

--- a/src/asm/lexer.c
+++ b/src/asm/lexer.c
@@ -739,6 +739,7 @@
 	uint32_t num = 0;
 	int c = peek();
 	bool empty = false;
+	bool symbolError = false;
 
 	if (c >= '0' && c <= '9') {
 		num = readNumber(10, 0);
@@ -760,25 +761,33 @@
 
 		struct Symbol const *sym = sym_FindScopedSymbol(symName);
 
-		if (!sym)
-			fatalerror("Bracketed symbol \"%s\" does not exist\n", symName);
-		else if (!sym_IsNumeric(sym))
-			fatalerror("Bracketed symbol \"%s\" is not numeric\n", symName);
-
-		num = sym_GetConstantSymValue(sym);
+		if (!sym) {
+			error("Bracketed symbol \"%s\" does not exist\n", symName);
+			num = 0;
+			symbolError = true;
+		} else if (!sym_IsNumeric(sym)) {
+			error("Bracketed symbol \"%s\" is not numeric\n", symName);
+			num = 0;
+			symbolError = true;
+		} else {
+			num = sym_GetConstantSymValue(sym);
+		}
 	} else {
 		empty = true;
 	}
 
 	c = peek();
-	if (c != '>')
-		fatalerror("Invalid character in bracketed macro argument %s\n", printChar(c));
-	else if (empty)
-		fatalerror("Empty bracketed macro argument\n");
-	else if (num == 0)
-		fatalerror("Invalid bracketed macro argument '\\<0>'\n");
-
 	shiftChar();
+	if (c != '>') {
+		error("Invalid character in bracketed macro argument %s\n", printChar(c));
+		return 0;
+	} else if (empty) {
+		error("Empty bracketed macro argument\n");
+		return 0;
+	} else if (num == 0 && !symbolError) {
+		error("Invalid bracketed macro argument '\\<0>'\n");
+		return 0;
+	}
 
 	lexerState->disableMacroArgs = disableMacroArgs;
 	lexerState->disableInterpolation = disableInterpolation;
@@ -787,7 +796,7 @@
 
 static char const *readMacroArg(char name)
 {
-	char const *str;
+	char const *str = NULL;
 
 	if (name == '@') {
 		str = macro_GetUniqueIDStr();
@@ -796,18 +805,22 @@
 	} else if (name == '<') {
 		uint32_t num = readBracketedMacroArgNum();
 
+		if (num == 0)
+			return NULL;
 		str = macro_GetArg(num);
 		if (!str)
-			fatalerror("Macro argument '\\<%" PRIu32 ">' not defined\n", num);
+			error("Macro argument '\\<%" PRIu32 ">' not defined\n", num);
+		return str;
 	} else if (name == '0') {
-		fatalerror("Invalid macro argument '\\0'\n");
+		error("Invalid macro argument '\\0'\n");
+		return NULL;
 	} else {
+		assert(name > '0' && name <= '9');
 		str = macro_GetArg(name - '0');
 	}
 
 	if (!str)
-		fatalerror("Macro argument '\\%c' not defined\n", name);
-
+		error("Macro argument '\\%c' not defined\n", name);
 	return str;
 }
 
@@ -907,10 +920,10 @@
 			char const *str = readMacroArg(c);
 
 			/*
-			 * If the macro arg is an empty string, it cannot be
+			 * If the macro arg is invalid or an empty string, it cannot be
 			 * expanded, so skip it and keep peeking.
 			 */
-			if (!str[0])
+			if (!str || !str[0])
 				goto restart;
 
 			beginExpansion(str, c == '#', NULL);
@@ -930,10 +943,9 @@
 		shiftChar();
 		char const *ptr = readInterpolation(0);
 
-		if (ptr) {
+		if (ptr && ptr[0])
 			beginExpansion(ptr, false, ptr);
-			goto restart;
-		}
+		goto restart;
 	}
 
 	return c;
@@ -1369,10 +1381,9 @@
 			shiftChar();
 			char const *ptr = readInterpolation(depth + 1);
 
-			if (ptr) {
+			if (ptr && ptr[0])
 				beginExpansion(ptr, false, ptr);
-				continue; /* Restart, reading from the new buffer */
-			}
+			continue; /* Restart, reading from the new buffer */
 		} else if (c == EOF || c == '\r' || c == '\n' || c == '"') {
 			error("Missing }\n");
 			break;
@@ -1573,8 +1584,10 @@
 				shiftChar();
 				char const *str = readMacroArg(c);
 
-				while (*str)
-					append_yylval_string(*str++);
+				if (str) {
+					while (*str)
+						append_yylval_string(*str++);
+				}
 				continue; // Do not copy an additional character
 
 			case EOF: // Can't really print that one
@@ -1595,9 +1608,10 @@
 			lexerState->disableMacroArgs = false;
 			char const *ptr = readInterpolation(0);
 
-			if (ptr)
+			if (ptr) {
 				while (*ptr)
 					append_yylval_string(*ptr++);
+			}
 			lexerState->disableMacroArgs = true;
 			continue; // Do not copy an additional character
 
@@ -1719,7 +1733,8 @@
 				shiftChar();
 				char const *str = readMacroArg(c);
 
-				i = appendEscapedSubstring(str, i);
+				if (str)
+					i = appendEscapedSubstring(str, i);
 				continue; // Do not copy an additional character
 
 			case EOF: // Can't really print that one
@@ -1746,7 +1761,7 @@
 			lexerState->disableMacroArgs = false;
 			char const *ptr = readInterpolation(0);
 
-			if (ptr)
+			if (ptr && ptr[0])
 				i = appendEscapedSubstring(ptr, i);
 			lexerState->disableMacroArgs = true;
 			continue; // Do not copy an additional character
@@ -2012,7 +2027,9 @@
 					if (sym && sym->type == SYM_EQUS) {
 						char const *s = sym_GetStringValue(sym);
 
-						beginExpansion(s, false, sym->name);
+						assert(s);
+						if (s[0])
+							beginExpansion(s, false, sym->name);
 						continue; /* Restart, reading from the new buffer */
 					}
 				}
--- a/test/asm/interpolation-overflow.err
+++ b/test/asm/interpolation-overflow.err
@@ -5,5 +5,8 @@
 warning: interpolation-overflow.asm(4): [-Wlarge-constant]
     Precision of fixed-point constant is too large
 while expanding symbol "0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
-FATAL: interpolation-overflow.asm(4):
+ERROR: interpolation-overflow.asm(4):
     Macro argument '\1' not defined
+ERROR: interpolation-overflow.asm(4):
+    syntax error, unexpected number
+error: Assembly aborted (4 errors)!
--- a/test/asm/invalid-empty-macro-arg.err
+++ b/test/asm/invalid-empty-macro-arg.err
@@ -1,2 +1,3 @@
-FATAL: invalid-empty-macro-arg.asm(1):
+ERROR: invalid-empty-macro-arg.asm(1):
     Empty bracketed macro argument
+error: Assembly aborted (1 error)!
--- a/test/asm/invalid-macro-arg-character.err
+++ b/test/asm/invalid-macro-arg-character.err
@@ -1,2 +1,5 @@
-FATAL: invalid-macro-arg-character.asm(1):
+ERROR: invalid-macro-arg-character.asm(1):
     Invalid character in bracketed macro argument '!'
+ERROR: invalid-macro-arg-character.asm(1):
+    syntax error, unexpected >
+error: Assembly aborted (2 errors)!
--- a/test/asm/invalid-macro-arg-symbol.err
+++ b/test/asm/invalid-macro-arg-symbol.err
@@ -1,2 +1,3 @@
-FATAL: invalid-macro-arg-symbol.asm(1):
+ERROR: invalid-macro-arg-symbol.asm(1):
     Bracketed symbol "foo" does not exist
+error: Assembly aborted (1 error)!
--- a/test/asm/rept-shift.asm
+++ b/test/asm/rept-shift.asm
@@ -9,7 +9,7 @@
 	SHIFT
 	SHIFT
 	SHIFT 256
-	PRINTLN "\1"
+	PRINTLN "\1?"
 endm
 
  m This, used, not, to, work
--- a/test/asm/rept-shift.err
+++ b/test/asm/rept-shift.err
@@ -2,5 +2,6 @@
     Cannot shift macro arguments past their end
 warning: rept-shift.asm(15) -> rept-shift.asm::m(11): [-Wmacro-shift]
     Cannot shift macro arguments past their end
-FATAL: rept-shift.asm(15) -> rept-shift.asm::m(12):
+ERROR: rept-shift.asm(15) -> rept-shift.asm::m(12):
     Macro argument '\1' not defined
+error: Assembly aborted (1 error)!
--- a/test/asm/rept-shift.out
+++ b/test/asm/rept-shift.out
@@ -1,1 +1,2 @@
 This works!
+?
--- a/test/asm/symbol-invalid-macro-arg.asm
+++ b/test/asm/symbol-invalid-macro-arg.asm
@@ -1,1 +1,2 @@
-x\0
+x\0 = 10
+println x
--- a/test/asm/symbol-invalid-macro-arg.err
+++ b/test/asm/symbol-invalid-macro-arg.err
@@ -1,2 +1,3 @@
-FATAL: symbol-invalid-macro-arg.asm(1):
+ERROR: symbol-invalid-macro-arg.asm(1):
     Invalid macro argument '\0'
+error: Assembly aborted (1 error)!
--- a/test/asm/symbol-invalid-macro-arg.out
+++ b/test/asm/symbol-invalid-macro-arg.out
@@ -1,0 +1,1 @@
+$A
--- a/test/asm/unique-id.asm
+++ b/test/asm/unique-id.asm
@@ -1,4 +1,4 @@
-warn_unique EQUS "WARN \"\\@\""
+warn_unique EQUS "WARN \"\\@!\""
 
 m: macro
     warn_unique
--- a/test/asm/unique-id.err
+++ b/test/asm/unique-id.err
@@ -1,27 +1,31 @@
 warning: unique-id.asm(12) -> unique-id.asm::m(4): [-Wuser]
-    _u1
+    _u1!
 while expanding symbol "warn_unique"
 warning: unique-id.asm(12) -> unique-id.asm::m(5) -> unique-id.asm::m::REPT~1(6): [-Wuser]
-    _u2
+    _u2!
 while expanding symbol "warn_unique"
 warning: unique-id.asm(12) -> unique-id.asm::m(5) -> unique-id.asm::m::REPT~2(6): [-Wuser]
-    _u3
+    _u3!
 while expanding symbol "warn_unique"
 warning: unique-id.asm(12) -> unique-id.asm::m(8): [-Wuser]
-    _u1
+    _u1!
 while expanding symbol "warn_unique"
 warning: unique-id.asm(14) -> unique-id.asm::m(4): [-Wuser]
-    _u4
+    _u4!
 while expanding symbol "warn_unique"
 warning: unique-id.asm(14) -> unique-id.asm::m(5) -> unique-id.asm::m::REPT~1(6): [-Wuser]
-    _u5
+    _u5!
 while expanding symbol "warn_unique"
 warning: unique-id.asm(14) -> unique-id.asm::m(5) -> unique-id.asm::m::REPT~2(6): [-Wuser]
-    _u6
+    _u6!
 while expanding symbol "warn_unique"
 warning: unique-id.asm(14) -> unique-id.asm::m(8): [-Wuser]
-    _u4
+    _u4!
 while expanding symbol "warn_unique"
-FATAL: unique-id.asm(15):
+ERROR: unique-id.asm(15):
     Macro argument '\@' not defined
 while expanding symbol "warn_unique"
+warning: unique-id.asm(15): [-Wuser]
+    !
+while expanding symbol "warn_unique"
+error: Assembly aborted (1 error)!