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)!