diff --git a/src/asm/rgbasm.5 b/src/asm/rgbasm.5 index b3f76847c5..4cf5627339 100644 --- a/src/asm/rgbasm.5 +++ b/src/asm/rgbasm.5 @@ -1258,6 +1258,7 @@ The following symbols are defined by the assembler: .It Dv _NARG Ta Ic EQU Ta Number of arguments passed to macro, updated by Ic SHIFT .It Dv __LINE__ Ta Ic EQU Ta The current line number .It Dv __FILE__ Ta Ic EQUS Ta The current filename +.It Dv __SCOPE__ Ta Ic EQU Ta The current scoped label (empty if none is scoped) .It Dv __DATE__ Ta Ic EQUS Ta Today's date .It Dv __TIME__ Ta Ic EQUS Ta The current time .It Dv __ISO_8601_LOCAL__ Ta Ic EQUS Ta ISO 8601 timestamp (local) diff --git a/src/asm/symbol.c b/src/asm/symbol.c index 57e04e2206..1bae61bd06 100644 --- a/src/asm/symbol.c +++ b/src/asm/symbol.c @@ -90,7 +90,7 @@ static int32_t Callback__LINE__(void) return lexer_GetLineNo(); } -static char const *Callback__FILE__(void) +static const char *Callback__FILE__(void) { /* * FIXME: this is dangerous, and here's why this is CURRENTLY okay. It's still bad, fix it. @@ -129,6 +129,22 @@ static char const *Callback__FILE__(void) return buf; } +static const char *Callback__SCOPE__(void) +{ + static char buf[MAXSYMLEN + 1]; + + if (!labelScope) { + // __SCOPE__ is empty inside the main scope (no global label) + buf[0] = '\0'; + } else { + // labelScope is a valid label, so it will fit within MAXSYMLEN characters + assert(strlen(labelScope) < sizeof(buf)); + strcpy(buf, labelScope); + } + + return buf; +} + static int32_t CallbackPC(void) { struct Section const *section = sect_GetSymbolSection(); @@ -717,6 +733,7 @@ void sym_Init(time_t now) struct Symbol *_NARGSymbol = createBuiltinSymbol("_NARG"); struct Symbol *__LINE__Symbol = createBuiltinSymbol("__LINE__"); struct Symbol *__FILE__Symbol = createBuiltinSymbol("__FILE__"); + struct Symbol *__SCOPE__Symbol = createBuiltinSymbol("__SCOPE__"); PCSymbol->type = SYM_LABEL; PCSymbol->section = NULL; @@ -727,6 +744,8 @@ void sym_Init(time_t now) __LINE__Symbol->numCallback = Callback__LINE__; __FILE__Symbol->type = SYM_EQUS; __FILE__Symbol->strCallback = Callback__FILE__; + __SCOPE__Symbol->type = SYM_EQUS; + __SCOPE__Symbol->strCallback = Callback__SCOPE__; sym_AddSet("_RS", 0)->isBuiltin = true; sym_AddEqu("__RGBDS_MAJOR__", PACKAGE_VERSION_MAJOR)->isBuiltin = true; diff --git a/test/asm/scope-noscope.asm b/test/asm/scope-noscope.asm new file mode 100644 index 0000000000..c343424bdb --- /dev/null +++ b/test/asm/scope-noscope.asm @@ -0,0 +1 @@ + PRINTLN "inside {__SCOPE__}" diff --git a/test/asm/scope-noscope.err b/test/asm/scope-noscope.err new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/asm/scope-noscope.out b/test/asm/scope-noscope.out new file mode 100644 index 0000000000..25cb6f1151 --- /dev/null +++ b/test/asm/scope-noscope.out @@ -0,0 +1 @@ +inside diff --git a/test/asm/scope.asm b/test/asm/scope.asm new file mode 100644 index 0000000000..7204fdbe97 --- /dev/null +++ b/test/asm/scope.asm @@ -0,0 +1,28 @@ +SECTION "test", ROM0 + + assert !STRLEN("{__SCOPE__}") + +SomeFunction: + println __FILE__, ":{d:__LINE__}:{__SCOPE__}: 2 + 2 = ", 2+2 + +verify: MACRO + assert !STRCMP("{__SCOPE__}", "\1") + assert __SCOPE__ == \1 +ENDM + +Alpha: + verify Alpha +.local + verify Alpha + +Beta:: +.local:: + verify Beta + +S EQUS """ +Gamma: + verify Gamma +""" + S + PURGE S + verify Gamma diff --git a/test/asm/scope.err b/test/asm/scope.err new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/asm/scope.out b/test/asm/scope.out new file mode 100644 index 0000000000..c09aa03fd3 --- /dev/null +++ b/test/asm/scope.out @@ -0,0 +1 @@ +scope.asm:6:SomeFunction: 2 + 2 = $4