mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 10:12:06 +00:00
@@ -245,18 +245,18 @@ struct Symbol *sym_FindUnscopedSymbol(char const *symName)
|
|||||||
|
|
||||||
struct Symbol *sym_FindScopedSymbol(char const *symName)
|
struct Symbol *sym_FindScopedSymbol(char const *symName)
|
||||||
{
|
{
|
||||||
char const *dotPtr = strchr(symName, '.');
|
char const *localName = strchr(symName, '.');
|
||||||
|
|
||||||
if (dotPtr) {
|
if (localName) {
|
||||||
if (strchr(dotPtr + 1, '.'))
|
if (strchr(localName + 1, '.'))
|
||||||
fatalerror("'%s' is a nonsensical reference to a nested local symbol\n",
|
fatalerror("'%s' is a nonsensical reference to a nested local symbol\n",
|
||||||
symName);
|
symName);
|
||||||
/* If auto-scoped local label, expand the name */
|
/* If auto-scoped local label, expand the name */
|
||||||
if (dotPtr == symName) { /* Meaning, the name begins with the dot */
|
if (localName == symName) { /* Meaning, the name begins with the dot */
|
||||||
char fullname[MAXSYMLEN + 1];
|
char fullName[MAXSYMLEN + 1];
|
||||||
|
|
||||||
fullSymbolName(fullname, sizeof(fullname), symName, labelScope);
|
fullSymbolName(fullName, sizeof(fullName), symName, labelScope);
|
||||||
return sym_FindExactSymbol(fullname);
|
return sym_FindExactSymbol(fullName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return sym_FindExactSymbol(symName);
|
return sym_FindExactSymbol(symName);
|
||||||
@@ -533,7 +533,7 @@ static struct Symbol *addLabel(char const *symName)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add a local (.name or Parent.name) relocatable symbol
|
* Add a local (`.name` or `Parent.name`) relocatable symbol
|
||||||
*/
|
*/
|
||||||
struct Symbol *sym_AddLocalLabel(char const *symName)
|
struct Symbol *sym_AddLocalLabel(char const *symName)
|
||||||
{
|
{
|
||||||
@@ -541,34 +541,40 @@ struct Symbol *sym_AddLocalLabel(char const *symName)
|
|||||||
error("Local label '%s' in main scope\n", symName);
|
error("Local label '%s' in main scope\n", symName);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
assert(!strchr(labelScope, '.')); /* Assuming no dots in `labelScope` */
|
||||||
|
|
||||||
char fullname[MAXSYMLEN + 1];
|
char fullName[MAXSYMLEN + 1];
|
||||||
|
char const *localName = strchr(symName, '.');
|
||||||
|
|
||||||
if (symName[0] == '.') {
|
assert(localName); /* There should be at least one dot in `symName` */
|
||||||
/* If symbol is of the form `.name`, expand to the full `Parent.name` name */
|
/* Check for something after the dot in `localName` */
|
||||||
fullSymbolName(fullname, sizeof(fullname), symName, labelScope);
|
if (localName[1] == '\0') {
|
||||||
symName = fullname; /* Use the expanded name instead */
|
fatalerror("'%s' is a nonsensical reference to an empty local label\n",
|
||||||
|
symName);
|
||||||
|
}
|
||||||
|
/* Check for more than one dot in `localName` */
|
||||||
|
if (strchr(localName + 1, '.'))
|
||||||
|
fatalerror("'%s' is a nonsensical reference to a nested local label\n",
|
||||||
|
symName);
|
||||||
|
|
||||||
|
if (localName == symName) {
|
||||||
|
/* Expand `symName` to the full `labelScope.symName` name */
|
||||||
|
fullSymbolName(fullName, sizeof(fullName), symName, labelScope);
|
||||||
|
symName = fullName;
|
||||||
} else {
|
} else {
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
|
|
||||||
/* Otherwise, check that `Parent` is in fact the current scope */
|
/* Find where `labelScope` and `symName` first differ */
|
||||||
while (labelScope[i] && symName[i] == labelScope[i])
|
while (labelScope[i] && symName[i] == labelScope[i])
|
||||||
i++;
|
i++;
|
||||||
/* Assuming no dots in `labelScope` */
|
|
||||||
assert(strchr(&symName[i], '.')); /* There should be at least one dot, though */
|
|
||||||
size_t parentLen = i + (strchr(&symName[i], '.') - symName);
|
|
||||||
|
|
||||||
/*
|
/* Check that `symName` starts with `labelScope` and then a '.' */
|
||||||
* Check that `labelScope[i]` ended the check, guaranteeing that `symName` is at
|
|
||||||
* least as long, and then that this was the entire `Parent` part of `symName`.
|
|
||||||
*/
|
|
||||||
if (labelScope[i] != '\0' || symName[i] != '.') {
|
if (labelScope[i] != '\0' || symName[i] != '.') {
|
||||||
|
size_t parentLen = localName - symName;
|
||||||
|
|
||||||
assert(parentLen <= INT_MAX);
|
assert(parentLen <= INT_MAX);
|
||||||
error("Not currently in the scope of '%.*s'\n", (int)parentLen, symName);
|
error("Not currently in the scope of '%.*s'\n", (int)parentLen, symName);
|
||||||
}
|
}
|
||||||
if (strchr(&symName[parentLen + 1], '.')) /* There will at least be a terminator */
|
|
||||||
fatalerror("'%s' is a nonsensical reference to a nested local label\n",
|
|
||||||
symName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return addLabel(symName);
|
return addLabel(symName);
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
FATAL: empty-local.asm(5):
|
||||||
|
'Label.' is a nonsensical reference to an empty local label
|
||||||
|
|||||||
7
test/asm/multiple-dots-local.asm
Normal file
7
test/asm/multiple-dots-local.asm
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
SECTION "sec", ROM0
|
||||||
|
|
||||||
|
Parent:
|
||||||
|
Parent.heir:
|
||||||
|
db 0
|
||||||
|
Parent...spare:
|
||||||
|
db 1
|
||||||
2
test/asm/multiple-dots-local.err
Normal file
2
test/asm/multiple-dots-local.err
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
FATAL: multiple-dots-local.asm(6):
|
||||||
|
'Parent...spare' is a nonsensical reference to a nested local label
|
||||||
0
test/asm/multiple-dots-local.out
Normal file
0
test/asm/multiple-dots-local.out
Normal file
8
test/asm/nested-local-reference.asm
Normal file
8
test/asm/nested-local-reference.asm
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
SECTION "sec", ROM0
|
||||||
|
|
||||||
|
Parent:
|
||||||
|
Parent.child:
|
||||||
|
db 0
|
||||||
|
.grandchild:
|
||||||
|
db 1
|
||||||
|
dw Parent.child.grandchild
|
||||||
2
test/asm/nested-local-reference.err
Normal file
2
test/asm/nested-local-reference.err
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
FATAL: nested-local-reference.asm(8):
|
||||||
|
'Parent.child.grandchild' is a nonsensical reference to a nested local symbol
|
||||||
0
test/asm/nested-local-reference.out
Normal file
0
test/asm/nested-local-reference.out
Normal file
7
test/asm/nested-local.asm
Normal file
7
test/asm/nested-local.asm
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
SECTION "sec", ROM0
|
||||||
|
|
||||||
|
Parent:
|
||||||
|
Parent.child:
|
||||||
|
db 0
|
||||||
|
Parent.child.grandchild:
|
||||||
|
db 1
|
||||||
2
test/asm/nested-local.err
Normal file
2
test/asm/nested-local.err
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
FATAL: nested-local.asm(6):
|
||||||
|
'Parent.child.grandchild' is a nonsensical reference to a nested local label
|
||||||
0
test/asm/nested-local.out
Normal file
0
test/asm/nested-local.out
Normal file
@@ -4,4 +4,4 @@ Parent:
|
|||||||
.child:
|
.child:
|
||||||
db 0
|
db 0
|
||||||
NotParent:
|
NotParent:
|
||||||
dw Parent.child.fail
|
dw Parent.orphan
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
FATAL: remote-local-noexist.asm(7):
|
|
||||||
'Parent.child.fail' is a nonsensical reference to a nested local symbol
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ ERROR: sym-scope.asm(4):
|
|||||||
ERROR: sym-scope.asm(5):
|
ERROR: sym-scope.asm(5):
|
||||||
Local label 'Nice.try' in main scope
|
Local label 'Nice.try' in main scope
|
||||||
ERROR: sym-scope.asm(17):
|
ERROR: sym-scope.asm(17):
|
||||||
Not currently in the scope of 'Parentheses.check'
|
Not currently in the scope of 'Parentheses'
|
||||||
ERROR: sym-scope.asm(21):
|
ERROR: sym-scope.asm(21):
|
||||||
Not currently in the scope of 'Parent.check'
|
Not currently in the scope of 'Parent'
|
||||||
error: Assembly aborted (4 errors)!
|
error: Assembly aborted (4 errors)!
|
||||||
|
|||||||
Reference in New Issue
Block a user