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.
This commit is contained in:
Rangi
2021-04-20 11:51:01 -04:00
committed by Eldred Habert
parent 1aeaca2af6
commit e596dbfc80
13 changed files with 84 additions and 50 deletions

View File

@@ -739,6 +739,7 @@ static uint32_t readBracketedMacroArgNum(void)
uint32_t num = 0; uint32_t num = 0;
int c = peek(); int c = peek();
bool empty = false; bool empty = false;
bool symbolError = false;
if (c >= '0' && c <= '9') { if (c >= '0' && c <= '9') {
num = readNumber(10, 0); num = readNumber(10, 0);
@@ -760,25 +761,33 @@ static uint32_t readBracketedMacroArgNum(void)
struct Symbol const *sym = sym_FindScopedSymbol(symName); struct Symbol const *sym = sym_FindScopedSymbol(symName);
if (!sym) if (!sym) {
fatalerror("Bracketed symbol \"%s\" does not exist\n", symName); error("Bracketed symbol \"%s\" does not exist\n", symName);
else if (!sym_IsNumeric(sym)) num = 0;
fatalerror("Bracketed symbol \"%s\" is not numeric\n", symName); 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); num = sym_GetConstantSymValue(sym);
}
} else { } else {
empty = true; empty = true;
} }
c = peek(); 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(); 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->disableMacroArgs = disableMacroArgs;
lexerState->disableInterpolation = disableInterpolation; lexerState->disableInterpolation = disableInterpolation;
@@ -787,7 +796,7 @@ static uint32_t readBracketedMacroArgNum(void)
static char const *readMacroArg(char name) static char const *readMacroArg(char name)
{ {
char const *str; char const *str = NULL;
if (name == '@') { if (name == '@') {
str = macro_GetUniqueIDStr(); str = macro_GetUniqueIDStr();
@@ -796,18 +805,22 @@ static char const *readMacroArg(char name)
} else if (name == '<') { } else if (name == '<') {
uint32_t num = readBracketedMacroArgNum(); uint32_t num = readBracketedMacroArgNum();
if (num == 0)
return NULL;
str = macro_GetArg(num); str = macro_GetArg(num);
if (!str) if (!str)
fatalerror("Macro argument '\\<%" PRIu32 ">' not defined\n", num); error("Macro argument '\\<%" PRIu32 ">' not defined\n", num);
return str;
} else if (name == '0') { } else if (name == '0') {
fatalerror("Invalid macro argument '\\0'\n"); error("Invalid macro argument '\\0'\n");
return NULL;
} else { } else {
assert(name > '0' && name <= '9');
str = macro_GetArg(name - '0'); str = macro_GetArg(name - '0');
} }
if (!str) if (!str)
fatalerror("Macro argument '\\%c' not defined\n", name); error("Macro argument '\\%c' not defined\n", name);
return str; return str;
} }
@@ -907,10 +920,10 @@ restart:
char const *str = readMacroArg(c); 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. * expanded, so skip it and keep peeking.
*/ */
if (!str[0]) if (!str || !str[0])
goto restart; goto restart;
beginExpansion(str, c == '#', NULL); beginExpansion(str, c == '#', NULL);
@@ -930,11 +943,10 @@ restart:
shiftChar(); shiftChar();
char const *ptr = readInterpolation(0); char const *ptr = readInterpolation(0);
if (ptr) { if (ptr && ptr[0])
beginExpansion(ptr, false, ptr); beginExpansion(ptr, false, ptr);
goto restart; goto restart;
} }
}
return c; return c;
} }
@@ -1369,10 +1381,9 @@ static char const *readInterpolation(unsigned int depth)
shiftChar(); shiftChar();
char const *ptr = readInterpolation(depth + 1); char const *ptr = readInterpolation(depth + 1);
if (ptr) { if (ptr && ptr[0])
beginExpansion(ptr, false, ptr); 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 == '"') { } else if (c == EOF || c == '\r' || c == '\n' || c == '"') {
error("Missing }\n"); error("Missing }\n");
break; break;
@@ -1573,8 +1584,10 @@ static void readString(void)
shiftChar(); shiftChar();
char const *str = readMacroArg(c); char const *str = readMacroArg(c);
if (str) {
while (*str) while (*str)
append_yylval_string(*str++); append_yylval_string(*str++);
}
continue; // Do not copy an additional character continue; // Do not copy an additional character
case EOF: // Can't really print that one case EOF: // Can't really print that one
@@ -1595,9 +1608,10 @@ static void readString(void)
lexerState->disableMacroArgs = false; lexerState->disableMacroArgs = false;
char const *ptr = readInterpolation(0); char const *ptr = readInterpolation(0);
if (ptr) if (ptr) {
while (*ptr) while (*ptr)
append_yylval_string(*ptr++); append_yylval_string(*ptr++);
}
lexerState->disableMacroArgs = true; lexerState->disableMacroArgs = true;
continue; // Do not copy an additional character continue; // Do not copy an additional character
@@ -1719,6 +1733,7 @@ static size_t appendStringLiteral(size_t i)
shiftChar(); shiftChar();
char const *str = readMacroArg(c); char const *str = readMacroArg(c);
if (str)
i = appendEscapedSubstring(str, i); i = appendEscapedSubstring(str, i);
continue; // Do not copy an additional character continue; // Do not copy an additional character
@@ -1746,7 +1761,7 @@ static size_t appendStringLiteral(size_t i)
lexerState->disableMacroArgs = false; lexerState->disableMacroArgs = false;
char const *ptr = readInterpolation(0); char const *ptr = readInterpolation(0);
if (ptr) if (ptr && ptr[0])
i = appendEscapedSubstring(ptr, i); i = appendEscapedSubstring(ptr, i);
lexerState->disableMacroArgs = true; lexerState->disableMacroArgs = true;
continue; // Do not copy an additional character continue; // Do not copy an additional character
@@ -2012,6 +2027,8 @@ static int yylex_NORMAL(void)
if (sym && sym->type == SYM_EQUS) { if (sym && sym->type == SYM_EQUS) {
char const *s = sym_GetStringValue(sym); char const *s = sym_GetStringValue(sym);
assert(s);
if (s[0])
beginExpansion(s, false, sym->name); beginExpansion(s, false, sym->name);
continue; /* Restart, reading from the new buffer */ continue; /* Restart, reading from the new buffer */
} }

View File

@@ -5,5 +5,8 @@ ERROR: interpolation-overflow.asm(4):
warning: interpolation-overflow.asm(4): [-Wlarge-constant] warning: interpolation-overflow.asm(4): [-Wlarge-constant]
Precision of fixed-point constant is too large Precision of fixed-point constant is too large
while expanding symbol "0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" while expanding symbol "0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
FATAL: interpolation-overflow.asm(4): ERROR: interpolation-overflow.asm(4):
Macro argument '\1' not defined Macro argument '\1' not defined
ERROR: interpolation-overflow.asm(4):
syntax error, unexpected number
error: Assembly aborted (4 errors)!

View File

@@ -1,2 +1,3 @@
FATAL: invalid-empty-macro-arg.asm(1): ERROR: invalid-empty-macro-arg.asm(1):
Empty bracketed macro argument Empty bracketed macro argument
error: Assembly aborted (1 error)!

View File

@@ -1,2 +1,5 @@
FATAL: invalid-macro-arg-character.asm(1): ERROR: invalid-macro-arg-character.asm(1):
Invalid character in bracketed macro argument '!' Invalid character in bracketed macro argument '!'
ERROR: invalid-macro-arg-character.asm(1):
syntax error, unexpected >
error: Assembly aborted (2 errors)!

View File

@@ -1,2 +1,3 @@
FATAL: invalid-macro-arg-symbol.asm(1): ERROR: invalid-macro-arg-symbol.asm(1):
Bracketed symbol "foo" does not exist Bracketed symbol "foo" does not exist
error: Assembly aborted (1 error)!

View File

@@ -9,7 +9,7 @@ m: macro
SHIFT SHIFT
SHIFT SHIFT
SHIFT 256 SHIFT 256
PRINTLN "\1" PRINTLN "\1?"
endm endm
m This, used, not, to, work m This, used, not, to, work

View File

@@ -2,5 +2,6 @@ warning: rept-shift.asm(15) -> rept-shift.asm::m(10): [-Wmacro-shift]
Cannot shift macro arguments past their end Cannot shift macro arguments past their end
warning: rept-shift.asm(15) -> rept-shift.asm::m(11): [-Wmacro-shift] warning: rept-shift.asm(15) -> rept-shift.asm::m(11): [-Wmacro-shift]
Cannot shift macro arguments past their end 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 Macro argument '\1' not defined
error: Assembly aborted (1 error)!

View File

@@ -1 +1,2 @@
This works! This works!
?

View File

@@ -1 +1,2 @@
x\0 x\0 = 10
println x

View File

@@ -1,2 +1,3 @@
FATAL: symbol-invalid-macro-arg.asm(1): ERROR: symbol-invalid-macro-arg.asm(1):
Invalid macro argument '\0' Invalid macro argument '\0'
error: Assembly aborted (1 error)!

View File

@@ -0,0 +1 @@
$A

View File

@@ -1,4 +1,4 @@
warn_unique EQUS "WARN \"\\@\"" warn_unique EQUS "WARN \"\\@!\""
m: macro m: macro
warn_unique warn_unique

View File

@@ -1,27 +1,31 @@
warning: unique-id.asm(12) -> unique-id.asm::m(4): [-Wuser] warning: unique-id.asm(12) -> unique-id.asm::m(4): [-Wuser]
_u1 _u1!
while expanding symbol "warn_unique" while expanding symbol "warn_unique"
warning: unique-id.asm(12) -> unique-id.asm::m(5) -> unique-id.asm::m::REPT~1(6): [-Wuser] 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" while expanding symbol "warn_unique"
warning: unique-id.asm(12) -> unique-id.asm::m(5) -> unique-id.asm::m::REPT~2(6): [-Wuser] 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" while expanding symbol "warn_unique"
warning: unique-id.asm(12) -> unique-id.asm::m(8): [-Wuser] warning: unique-id.asm(12) -> unique-id.asm::m(8): [-Wuser]
_u1 _u1!
while expanding symbol "warn_unique" while expanding symbol "warn_unique"
warning: unique-id.asm(14) -> unique-id.asm::m(4): [-Wuser] warning: unique-id.asm(14) -> unique-id.asm::m(4): [-Wuser]
_u4 _u4!
while expanding symbol "warn_unique" while expanding symbol "warn_unique"
warning: unique-id.asm(14) -> unique-id.asm::m(5) -> unique-id.asm::m::REPT~1(6): [-Wuser] 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" while expanding symbol "warn_unique"
warning: unique-id.asm(14) -> unique-id.asm::m(5) -> unique-id.asm::m::REPT~2(6): [-Wuser] 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" while expanding symbol "warn_unique"
warning: unique-id.asm(14) -> unique-id.asm::m(8): [-Wuser] warning: unique-id.asm(14) -> unique-id.asm::m(8): [-Wuser]
_u4 _u4!
while expanding symbol "warn_unique" while expanding symbol "warn_unique"
FATAL: unique-id.asm(15): ERROR: unique-id.asm(15):
Macro argument '\@' not defined Macro argument '\@' not defined
while expanding symbol "warn_unique" while expanding symbol "warn_unique"
warning: unique-id.asm(15): [-Wuser]
!
while expanding symbol "warn_unique"
error: Assembly aborted (1 error)!