mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 10:12:06 +00:00
Merge pull request #181 from Ben10do/reference-local-symbols
Allow local labels to be referenced (and exported) Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
This commit is contained in:
@@ -587,7 +587,11 @@ label : /* empty */
|
||||
else
|
||||
sym_AddReloc($1);
|
||||
} | T_LABEL ':' ':' {
|
||||
sym_AddReloc($1);
|
||||
if ($1[0] == '.') {
|
||||
sym_AddLocalReloc($1);
|
||||
} else {
|
||||
sym_AddReloc($1);
|
||||
}
|
||||
sym_Export($1);
|
||||
};
|
||||
|
||||
|
||||
@@ -475,6 +475,7 @@ setuplex(void)
|
||||
lex_FloatAddSecondRange(id, '\\', '\\');
|
||||
lex_FloatAddSecondRange(id, '@', '@');
|
||||
lex_FloatAddSecondRange(id, '#', '#');
|
||||
lex_FloatAddRange(id, '.', '.');
|
||||
lex_FloatAddRange(id, 'a', 'z');
|
||||
lex_FloatAddRange(id, 'A', 'Z');
|
||||
lex_FloatAddRange(id, '0', '9');
|
||||
|
||||
@@ -260,11 +260,7 @@ writesymbol(struct sSymbol * pSym, FILE * f)
|
||||
sectid = -1;
|
||||
type = SYM_IMPORT;
|
||||
} else {
|
||||
if (pSym->nType & SYMF_LOCAL) {
|
||||
strcpy(symname, pSym->pScope->tzName);
|
||||
strcat(symname, pSym->tzName);
|
||||
} else
|
||||
strcpy(symname, pSym->tzName);
|
||||
strcpy(symname, pSym->tzName);
|
||||
|
||||
if (pSym->nType & SYMF_EXPORT) {
|
||||
/* Symbol should be exported */
|
||||
|
||||
117
src/asm/symbol.c
117
src/asm/symbol.c
@@ -114,26 +114,16 @@ createsymbol(char *s)
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Find a symbol by name and scope
|
||||
* Creates the full name of a local symbol in a given scope, by prepending
|
||||
* the name with the parent symbol's name.
|
||||
*/
|
||||
struct sSymbol *
|
||||
findsymbol(char *s, struct sSymbol * scope)
|
||||
size_t
|
||||
fullSymbolName(char *output, size_t outputSize, char *localName, struct sSymbol *scope)
|
||||
{
|
||||
struct sSymbol **ppsym;
|
||||
SLONG hash;
|
||||
|
||||
hash = calchash(s);
|
||||
ppsym = &(tHashedSymbols[hash]);
|
||||
|
||||
while ((*ppsym) != NULL) {
|
||||
if ((strcmp(s, (*ppsym)->tzName) == 0)
|
||||
&& ((*ppsym)->pScope == scope)) {
|
||||
return (*ppsym);
|
||||
} else
|
||||
ppsym = &((*ppsym)->pNext);
|
||||
}
|
||||
return (NULL);
|
||||
struct sSymbol *parent = scope->pScope ? scope->pScope : scope;
|
||||
return snprintf(output, outputSize, "%s%s", parent->tzName, localName);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -144,13 +134,25 @@ findpsymbol(char *s, struct sSymbol * scope)
|
||||
{
|
||||
struct sSymbol **ppsym;
|
||||
SLONG hash;
|
||||
char fullname[MAXSYMLEN + 1];
|
||||
|
||||
if (s[0] == '.' && scope) {
|
||||
fullSymbolName(fullname, sizeof(fullname), s, scope);
|
||||
s = fullname;
|
||||
}
|
||||
|
||||
char *seperator;
|
||||
if ((seperator = strchr(s, '.'))) {
|
||||
if (strchr(seperator + 1, '.')) {
|
||||
fatalerror("'%s' is a nonsensical reference to a nested local symbol", s);
|
||||
}
|
||||
}
|
||||
|
||||
hash = calchash(s);
|
||||
ppsym = &(tHashedSymbols[hash]);
|
||||
|
||||
while ((*ppsym) != NULL) {
|
||||
if ((strcmp(s, (*ppsym)->tzName) == 0)
|
||||
&& ((*ppsym)->pScope == scope)) {
|
||||
if ((strcmp(s, (*ppsym)->tzName) == 0)) {
|
||||
return (ppsym);
|
||||
} else
|
||||
ppsym = &((*ppsym)->pNext);
|
||||
@@ -158,6 +160,16 @@ findpsymbol(char *s, struct sSymbol * scope)
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find a symbol by name and scope
|
||||
*/
|
||||
struct sSymbol *
|
||||
findsymbol(char *s, struct sSymbol * scope)
|
||||
{
|
||||
struct sSymbol **ppsym = findpsymbol(s, scope);
|
||||
return ppsym ? *ppsym : NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find a symbol by name and scope
|
||||
*/
|
||||
@@ -593,31 +605,17 @@ sym_AddSet(char *tzSym, SLONG value)
|
||||
void
|
||||
sym_AddLocalReloc(char *tzSym)
|
||||
{
|
||||
if ((nPass == 1)
|
||||
|| ((nPass == 2) && (sym_isDefined(tzSym) == 0))) {
|
||||
/* only add local reloc symbols in pass 1 */
|
||||
struct sSymbol *nsym;
|
||||
if (pScope) {
|
||||
if (strlen(tzSym) + strlen(pScope->tzName) > MAXSYMLEN) {
|
||||
fatalerror("Symbol too long");
|
||||
}
|
||||
|
||||
if (pScope) {
|
||||
if ((nsym = findsymbol(tzSym, pScope)) != NULL) {
|
||||
if (nsym->nType & SYMF_DEFINED) {
|
||||
yyerror("'%s' already defined", tzSym);
|
||||
}
|
||||
} else
|
||||
nsym = createsymbol(tzSym);
|
||||
char fullname[MAXSYMLEN + 1];
|
||||
fullSymbolName(fullname, sizeof(fullname), tzSym, pScope);
|
||||
sym_AddReloc(fullname);
|
||||
|
||||
if (nsym) {
|
||||
nsym->nValue = nPC;
|
||||
nsym->nType |=
|
||||
SYMF_RELOC | SYMF_LOCAL | SYMF_DEFINED;
|
||||
if (exportall) {
|
||||
nsym->nType |= SYMF_EXPORT;
|
||||
}
|
||||
nsym->pScope = pScope;
|
||||
nsym->pSection = pCurrentSection;
|
||||
}
|
||||
} else
|
||||
fatalerror("Local label in main scope");
|
||||
} else {
|
||||
fatalerror("Local label in main scope");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -627,12 +625,32 @@ sym_AddLocalReloc(char *tzSym)
|
||||
void
|
||||
sym_AddReloc(char *tzSym)
|
||||
{
|
||||
struct sSymbol* scope = NULL;
|
||||
|
||||
if ((nPass == 1)
|
||||
|| ((nPass == 2) && (sym_isDefined(tzSym) == 0))) {
|
||||
/* only add reloc symbols in pass 1 */
|
||||
struct sSymbol *nsym;
|
||||
char *localPtr = NULL;
|
||||
|
||||
if ((nsym = findsymbol(tzSym, NULL)) != NULL) {
|
||||
if ((localPtr = strchr(tzSym, '.')) != NULL) {
|
||||
if (!pScope) {
|
||||
fatalerror("Local label in main scope");
|
||||
}
|
||||
|
||||
struct sSymbol *parent = pScope->pScope ? pScope->pScope : pScope;
|
||||
int parentLen = localPtr - tzSym;
|
||||
|
||||
if (strchr(localPtr + 1, '.') != NULL) {
|
||||
fatalerror("'%s' is a nonsensical reference to a nested local symbol", tzSym);
|
||||
} else if (strlen(parent->tzName) != parentLen || strncmp(tzSym, parent->tzName, parentLen) != 0) {
|
||||
yyerror("Not currently in the scope of '%.*s'", parentLen, tzSym);
|
||||
}
|
||||
|
||||
scope = parent;
|
||||
}
|
||||
|
||||
if ((nsym = findsymbol(tzSym, scope)) != NULL) {
|
||||
if (nsym->nType & SYMF_DEFINED) {
|
||||
yyerror("'%s' already defined", tzSym);
|
||||
}
|
||||
@@ -642,14 +660,17 @@ sym_AddReloc(char *tzSym)
|
||||
if (nsym) {
|
||||
nsym->nValue = nPC;
|
||||
nsym->nType |= SYMF_RELOC | SYMF_DEFINED;
|
||||
if (localPtr) {
|
||||
nsym->nType |= SYMF_LOCAL;
|
||||
}
|
||||
if (exportall) {
|
||||
nsym->nType |= SYMF_EXPORT;
|
||||
}
|
||||
nsym->pScope = NULL;
|
||||
nsym->pScope = scope;
|
||||
nsym->pSection = pCurrentSection;
|
||||
}
|
||||
}
|
||||
pScope = findsymbol(tzSym, NULL);
|
||||
pScope = findsymbol(tzSym, scope);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -705,7 +726,7 @@ sym_Export(char *tzSym)
|
||||
/* only export symbols in pass 1 */
|
||||
struct sSymbol *nsym;
|
||||
|
||||
if ((nsym = findsymbol(tzSym, 0)) == NULL)
|
||||
if ((nsym = sym_FindSymbol(tzSym)) == NULL)
|
||||
nsym = createsymbol(tzSym);
|
||||
|
||||
if (nsym)
|
||||
@@ -713,7 +734,7 @@ sym_Export(char *tzSym)
|
||||
} else {
|
||||
struct sSymbol *nsym;
|
||||
|
||||
if ((nsym = findsymbol(tzSym, 0)) != NULL) {
|
||||
if ((nsym = sym_FindSymbol(tzSym)) != NULL) {
|
||||
if (nsym->nType & SYMF_DEFINED)
|
||||
return;
|
||||
}
|
||||
@@ -732,7 +753,7 @@ sym_Global(char *tzSym)
|
||||
/* only globalize symbols in pass 2 */
|
||||
struct sSymbol *nsym;
|
||||
|
||||
nsym = findsymbol(tzSym, 0);
|
||||
nsym = sym_FindSymbol(tzSym);
|
||||
|
||||
if ((nsym == NULL) || ((nsym->nType & SYMF_DEFINED) == 0)) {
|
||||
if (nsym == NULL)
|
||||
|
||||
6
test/asm/local-wrong-parent.asm
Normal file
6
test/asm/local-wrong-parent.asm
Normal file
@@ -0,0 +1,6 @@
|
||||
SECTION "sec", ROM0
|
||||
|
||||
Parent:
|
||||
db 0
|
||||
WrongParent.child
|
||||
db 0
|
||||
3
test/asm/local-wrong-parent.out
Normal file
3
test/asm/local-wrong-parent.out
Normal file
@@ -0,0 +1,3 @@
|
||||
ERROR: local-wrong-parent.asm(5):
|
||||
Not currently in the scope of 'WrongParent'
|
||||
error: Assembly aborted in pass 1 (1 errors)!
|
||||
7
test/asm/remote-local-explicit.asm
Normal file
7
test/asm/remote-local-explicit.asm
Normal file
@@ -0,0 +1,7 @@
|
||||
SECTION "sec", ROM0
|
||||
|
||||
Parent:
|
||||
Parent.child::
|
||||
db 0
|
||||
NotParent:
|
||||
dw Parent.child
|
||||
0
test/asm/remote-local-explicit.out
Normal file
0
test/asm/remote-local-explicit.out
Normal file
7
test/asm/remote-local-noexist.asm
Normal file
7
test/asm/remote-local-noexist.asm
Normal file
@@ -0,0 +1,7 @@
|
||||
SECTION "sec", ROM0
|
||||
|
||||
Parent:
|
||||
.child:
|
||||
db 0
|
||||
NotParent:
|
||||
dw Parent.child.fail
|
||||
2
test/asm/remote-local-noexist.out
Normal file
2
test/asm/remote-local-noexist.out
Normal file
@@ -0,0 +1,2 @@
|
||||
ERROR: remote-local-noexist.asm(7):
|
||||
'Parent.child.fail' is a nonsensical reference to a nested local symbol
|
||||
7
test/asm/remote-local.asm
Normal file
7
test/asm/remote-local.asm
Normal file
@@ -0,0 +1,7 @@
|
||||
SECTION "sec", ROM0
|
||||
|
||||
Parent:
|
||||
.child:
|
||||
db 0
|
||||
NotParent:
|
||||
dw Parent.child
|
||||
0
test/asm/remote-local.out
Normal file
0
test/asm/remote-local.out
Normal file
Reference in New Issue
Block a user