shithub: rgbds

Download patch

ref: 08545643cfb75b02a23e1af6b853f1432dd422f0
parent: 140c6b169e1b70443ddb1fe3b8ecf235e7fd0dcd
author: Rangi <35663410+Rangi42@users.noreply.github.com>
date: Fri Sep 30 15:04:03 EDT 2022

Only define `@` and `_NARG` when they have values (#1073)

Fixes #1069

Co-authored-by: Eldred Habert <eldredhabert0@gmail.com>

--- a/include/asm/symbol.h
+++ b/include/asm/symbol.h
@@ -127,6 +127,8 @@
 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);
--- a/src/asm/lexer.c
+++ b/src/asm/lexer.c
@@ -733,7 +733,7 @@
 		}
 		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 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);
--- a/src/asm/parser.y
+++ b/src/asm/parser.y
@@ -1462,10 +1462,8 @@
 		| T_OP_DEF {
 			lexer_ToggleStringExpansion(false);
 		} T_LPAREN scoped_anon_id T_RPAREN {
-			struct Symbol const *sym = sym_FindScopedSymbol($4);
+			rpn_Number(&$$, sym_FindScopedValidSymbol($4) != NULL);
 
-			rpn_Number(&$$, !!sym);
-
 			lexer_ToggleStringExpansion(true);
 		}
 		| T_OP_ROUND T_LPAREN const T_RPAREN {
@@ -1590,7 +1588,7 @@
 			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);
--- a/src/asm/symbol.c
+++ b/src/asm/symbol.c
@@ -36,6 +36,7 @@
 
 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 @@
 	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 @@
 // 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 @@
 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
--- a/test/asm/if@-no-sect.asm
+++ /dev/null
@@ -1,2 +1,0 @@
-if "{@}"
-endc
--- a/test/asm/if@-no-sect.err
+++ /dev/null
@@ -1,5 +1,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)!
--- a/test/asm/narg-nosect.asm
+++ /dev/null
@@ -1,1 +1,0 @@
-	PRINTLN "{_NARG}"
--- a/test/asm/narg-nosect.err
+++ /dev/null
@@ -1,3 +1,0 @@
-error: narg-nosect.asm(1):
-    _NARG does not make sense outside of a macro
-error: Assembly aborted (1 error)!
--- a/test/asm/narg-nosect.out
+++ /dev/null
@@ -1,1 +1,0 @@
-$0
--- a/test/asm/pc-def.asm
+++ /dev/null
@@ -1,5 +1,0 @@
-IF DEF(@)
-	PRINTLN "defined"
-ELSE
-	PRINTLN "not defined"
-ENDC
--- a/test/asm/pc-def.out
+++ /dev/null
@@ -1,1 +1,0 @@
-defined
--- /dev/null
+++ b/test/asm/undefined-builtins.asm
@@ -1,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
--- /dev/null
+++ b/test/asm/undefined-builtins.err
@@ -1,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)!
--- /dev/null
+++ b/test/asm/undefined-builtins.out
@@ -1,0 +1,8 @@
+$0
+?
+$0
+?
+$42
+$42!
+$3
+$3!