diff --git a/include/asm/symbol.h b/include/asm/symbol.h index a440e92a..627868f4 100644 --- a/include/asm/symbol.h +++ b/include/asm/symbol.h @@ -127,6 +127,8 @@ struct Symbol *sym_FindExactSymbol(char const *symName); struct Symbol *sym_FindUnscopedSymbol(char const *symName); // Find a symbol, possibly scoped, by name struct Symbol *sym_FindScopedSymbol(char const *symName); +// Find a scoped symbol by name; do not return `@` or `_NARG` when they have no value +struct Symbol *sym_FindScopedValidSymbol(char const *symName); struct Symbol const *sym_GetPC(void); struct Symbol *sym_AddMacro(char const *symName, int32_t defLineNo, char *body, size_t size); struct Symbol *sym_Ref(char const *symName); diff --git a/src/asm/lexer.c b/src/asm/lexer.c index ec3171c0..96b0204c 100644 --- a/src/asm/lexer.c +++ b/src/asm/lexer.c @@ -733,7 +733,7 @@ static uint32_t readBracketedMacroArgNum(void) } symName[i] = '\0'; - struct Symbol const *sym = sym_FindScopedSymbol(symName); + struct Symbol const *sym = sym_FindScopedValidSymbol(symName); if (!sym) { error("Bracketed symbol \"%s\" does not exist\n", symName); @@ -1400,7 +1400,7 @@ static char const *readInterpolation(size_t depth) static char buf[MAXSTRLEN + 1]; - struct Symbol const *sym = sym_FindScopedSymbol(symName); + struct Symbol const *sym = sym_FindScopedValidSymbol(symName); if (!sym) { error("Interpolated symbol \"%s\" does not exist\n", symName); diff --git a/src/asm/parser.y b/src/asm/parser.y index 2f5d8ce1..56aea0da 100644 --- a/src/asm/parser.y +++ b/src/asm/parser.y @@ -1462,9 +1462,7 @@ relocexpr_no_str : scoped_anon_id { rpn_Symbol(&$$, $1); } | T_OP_DEF { lexer_ToggleStringExpansion(false); } T_LPAREN scoped_anon_id T_RPAREN { - struct Symbol const *sym = sym_FindScopedSymbol($4); - - rpn_Number(&$$, !!sym); + rpn_Number(&$$, sym_FindScopedValidSymbol($4) != NULL); lexer_ToggleStringExpansion(true); } @@ -1590,7 +1588,7 @@ string : T_STRING freeStrFmtArgList(&$3); } | T_POP_SECTION T_LPAREN scoped_anon_id T_RPAREN { - struct Symbol *sym = sym_FindScopedSymbol($3); + struct Symbol *sym = sym_FindScopedValidSymbol($3); if (!sym) fatalerror("Unknown symbol \"%s\"\n", $3); diff --git a/src/asm/symbol.c b/src/asm/symbol.c index 515c4c41..915d7b16 100644 --- a/src/asm/symbol.c +++ b/src/asm/symbol.c @@ -36,6 +36,7 @@ HashMap symbols; static const char *labelScope; // Current section's label scope static struct Symbol *PCSymbol; +static struct Symbol *_NARGSymbol; static char savedTIME[256]; static char savedDATE[256]; static char savedTIMESTAMP_ISO8601_LOCAL[256]; @@ -250,6 +251,21 @@ struct Symbol *sym_FindScopedSymbol(char const *symName) return sym_FindExactSymbol(symName); } +struct Symbol *sym_FindScopedValidSymbol(char const *symName) +{ + struct Symbol *sym = sym_FindScopedSymbol(symName); + + // `@` has no value outside a section + if (sym == PCSymbol && !sect_GetSymbolSection()) { + return NULL; + } + // `_NARG` has no value outside a macro + if (sym == _NARGSymbol && !macro_GetCurrentArgs()) { + return NULL; + } + return sym; +} + struct Symbol const *sym_GetPC(void) { return PCSymbol; @@ -263,7 +279,7 @@ static bool isReferenced(struct Symbol const *sym) // Purge a symbol void sym_Purge(char const *symName) { - struct Symbol *sym = sym_FindScopedSymbol(symName); + struct Symbol *sym = sym_FindScopedValidSymbol(symName); if (!sym) { error("'%s' not defined\n", symName); @@ -682,7 +698,7 @@ static struct Symbol *createBuiltinSymbol(char const *symName) void sym_Init(time_t now) { PCSymbol = createBuiltinSymbol("@"); - struct Symbol *_NARGSymbol = createBuiltinSymbol("_NARG"); + _NARGSymbol = createBuiltinSymbol("_NARG"); // __LINE__ is deprecated struct Symbol *__LINE__Symbol = createBuiltinSymbol("__LINE__"); // __FILE__ is deprecated diff --git a/test/asm/if@-no-sect.asm b/test/asm/if@-no-sect.asm deleted file mode 100644 index 5ea733f7..00000000 --- a/test/asm/if@-no-sect.asm +++ /dev/null @@ -1,2 +0,0 @@ -if "{@}" -endc diff --git a/test/asm/if@-no-sect.err b/test/asm/if@-no-sect.err deleted file mode 100644 index 8e7a281e..00000000 --- a/test/asm/if@-no-sect.err +++ /dev/null @@ -1,5 +0,0 @@ -error: if@-no-sect.asm(1): - PC has no value outside a section -warning: if@-no-sect.asm(1): [-Wnumeric-string] - Treating 2-character string as a number -error: Assembly aborted (1 error)! diff --git a/test/asm/if@-no-sect.out b/test/asm/if@-no-sect.out deleted file mode 100644 index e69de29b..00000000 diff --git a/test/asm/narg-nosect.asm b/test/asm/narg-nosect.asm deleted file mode 100644 index 874bf022..00000000 --- a/test/asm/narg-nosect.asm +++ /dev/null @@ -1 +0,0 @@ - PRINTLN "{_NARG}" diff --git a/test/asm/narg-nosect.err b/test/asm/narg-nosect.err deleted file mode 100644 index aa8b0c69..00000000 --- a/test/asm/narg-nosect.err +++ /dev/null @@ -1,3 +0,0 @@ -error: narg-nosect.asm(1): - _NARG does not make sense outside of a macro -error: Assembly aborted (1 error)! diff --git a/test/asm/narg-nosect.out b/test/asm/narg-nosect.out deleted file mode 100644 index ebfabbe4..00000000 --- a/test/asm/narg-nosect.out +++ /dev/null @@ -1 +0,0 @@ -$0 diff --git a/test/asm/pc-def.asm b/test/asm/pc-def.asm deleted file mode 100644 index 46396a5d..00000000 --- a/test/asm/pc-def.asm +++ /dev/null @@ -1,5 +0,0 @@ -IF DEF(@) - PRINTLN "defined" -ELSE - PRINTLN "not defined" -ENDC diff --git a/test/asm/pc-def.err b/test/asm/pc-def.err deleted file mode 100644 index e69de29b..00000000 diff --git a/test/asm/pc-def.out b/test/asm/pc-def.out deleted file mode 100644 index 59dbac95..00000000 --- a/test/asm/pc-def.out +++ /dev/null @@ -1 +0,0 @@ -defined diff --git a/test/asm/undefined-builtins.asm b/test/asm/undefined-builtins.asm new file mode 100644 index 00000000..9cac1f97 --- /dev/null +++ b/test/asm/undefined-builtins.asm @@ -0,0 +1,21 @@ +; not inside a section +assert !DEF(@) +println @ +println "{@}?" + +; not inside a macro +assert !DEF(_NARG) +println _NARG +println "{_NARG}?" + +SECTION "s", ROM0[$42] +assert DEF(@) +println @ +println "{@}!" + +MACRO m + assert DEF(_NARG) + println _NARG + println "{_NARG}!" +ENDM + m 1, 2, 3 diff --git a/test/asm/undefined-builtins.err b/test/asm/undefined-builtins.err new file mode 100644 index 00000000..a75ce6f7 --- /dev/null +++ b/test/asm/undefined-builtins.err @@ -0,0 +1,9 @@ +error: undefined-builtins.asm(3): + PC has no value outside a section +error: undefined-builtins.asm(4): + Interpolated symbol "@" does not exist +error: undefined-builtins.asm(8): + _NARG does not make sense outside of a macro +error: undefined-builtins.asm(9): + Interpolated symbol "_NARG" does not exist +error: Assembly aborted (4 errors)! diff --git a/test/asm/undefined-builtins.out b/test/asm/undefined-builtins.out new file mode 100644 index 00000000..42986700 --- /dev/null +++ b/test/asm/undefined-builtins.out @@ -0,0 +1,8 @@ +$0 +? +$0 +? +$42 +$42! +$3 +$3!