Allow local symbols to be referenced

Local symbols can now be referenced outside the scope of their parent, by using the syntax “Parent.Chlid”.

- Local symbol names are now stored internally as “Parent.Child”.
- The symbol’s scope field no longer forms a linked list of the prior local symbols; it will now always contain the parent.
- Add the ability use EXPORT and GLOBAL with local symbols.
- Reduce duplication between findsymbol() and findpsymbol(), as well as between sym_AddLocalReloc() and sym_AddReloc().
This commit is contained in:
Ben10do
2017-06-12 19:12:24 +01:00
parent ff2321a8ce
commit ce8a13a562
4 changed files with 78 additions and 56 deletions

View File

@@ -587,7 +587,11 @@ label : /* empty */
else else
sym_AddReloc($1); sym_AddReloc($1);
} | T_LABEL ':' ':' { } | T_LABEL ':' ':' {
sym_AddReloc($1); if ($1[0] == '.') {
sym_AddLocalReloc($1);
} else {
sym_AddReloc($1);
}
sym_Export($1); sym_Export($1);
}; };

View File

@@ -475,6 +475,7 @@ setuplex(void)
lex_FloatAddSecondRange(id, '\\', '\\'); lex_FloatAddSecondRange(id, '\\', '\\');
lex_FloatAddSecondRange(id, '@', '@'); 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, 'A', 'Z'); lex_FloatAddRange(id, 'A', 'Z');
lex_FloatAddRange(id, '0', '9'); lex_FloatAddRange(id, '0', '9');

View File

@@ -260,11 +260,7 @@ writesymbol(struct sSymbol * pSym, FILE * f)
sectid = -1; sectid = -1;
type = SYM_IMPORT; type = SYM_IMPORT;
} else { } else {
if (pSym->nType & SYMF_LOCAL) { strcpy(symname, pSym->tzName);
strcpy(symname, pSym->pScope->tzName);
strcat(symname, pSym->tzName);
} else
strcpy(symname, pSym->tzName);
if (pSym->nType & SYMF_EXPORT) { if (pSym->nType & SYMF_EXPORT) {
/* Symbol should be exported */ /* Symbol should be exported */

View File

@@ -114,26 +114,16 @@ createsymbol(char *s)
return (NULL); 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 * size_t
findsymbol(char *s, struct sSymbol * scope) fullSymbolName(char *output, size_t outputSize, char *localName, struct sSymbol *scope)
{ {
struct sSymbol **ppsym; struct sSymbol *parent = scope->pScope ? scope->pScope : scope;
SLONG hash; return snprintf(output, outputSize, "%s%s", parent->tzName, localName);
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);
} }
/* /*
@@ -144,13 +134,25 @@ findpsymbol(char *s, struct sSymbol * scope)
{ {
struct sSymbol **ppsym; struct sSymbol **ppsym;
SLONG hash; 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); hash = calchash(s);
ppsym = &(tHashedSymbols[hash]); ppsym = &(tHashedSymbols[hash]);
while ((*ppsym) != NULL) { while ((*ppsym) != NULL) {
if ((strcmp(s, (*ppsym)->tzName) == 0) if ((strcmp(s, (*ppsym)->tzName) == 0)) {
&& ((*ppsym)->pScope == scope)) {
return (ppsym); return (ppsym);
} else } else
ppsym = &((*ppsym)->pNext); ppsym = &((*ppsym)->pNext);
@@ -158,6 +160,16 @@ findpsymbol(char *s, struct sSymbol * scope)
return (NULL); 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 * Find a symbol by name and scope
*/ */
@@ -593,31 +605,17 @@ sym_AddSet(char *tzSym, SLONG value)
void void
sym_AddLocalReloc(char *tzSym) sym_AddLocalReloc(char *tzSym)
{ {
if ((nPass == 1) if (pScope) {
|| ((nPass == 2) && (sym_isDefined(tzSym) == 0))) { if (strlen(tzSym) + strlen(pScope->tzName) > MAXSYMLEN) {
/* only add local reloc symbols in pass 1 */ fatalerror("Symbol too long");
struct sSymbol *nsym; }
if (pScope) { char fullname[MAXSYMLEN + 1];
if ((nsym = findsymbol(tzSym, pScope)) != NULL) { fullSymbolName(fullname, sizeof(fullname), tzSym, pScope);
if (nsym->nType & SYMF_DEFINED) { sym_AddReloc(fullname);
yyerror("'%s' already defined", tzSym);
}
} else
nsym = createsymbol(tzSym);
if (nsym) { } else {
nsym->nValue = nPC; fatalerror("Local label in main scope");
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");
} }
} }
@@ -627,12 +625,32 @@ sym_AddLocalReloc(char *tzSym)
void void
sym_AddReloc(char *tzSym) sym_AddReloc(char *tzSym)
{ {
struct sSymbol* scope = NULL;
if ((nPass == 1) if ((nPass == 1)
|| ((nPass == 2) && (sym_isDefined(tzSym) == 0))) { || ((nPass == 2) && (sym_isDefined(tzSym) == 0))) {
/* only add reloc symbols in pass 1 */ /* only add reloc symbols in pass 1 */
struct sSymbol *nsym; 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) { if (nsym->nType & SYMF_DEFINED) {
yyerror("'%s' already defined", tzSym); yyerror("'%s' already defined", tzSym);
} }
@@ -642,14 +660,17 @@ sym_AddReloc(char *tzSym)
if (nsym) { if (nsym) {
nsym->nValue = nPC; nsym->nValue = nPC;
nsym->nType |= SYMF_RELOC | SYMF_DEFINED; nsym->nType |= SYMF_RELOC | SYMF_DEFINED;
if (localPtr) {
nsym->nType |= SYMF_LOCAL;
}
if (exportall) { if (exportall) {
nsym->nType |= SYMF_EXPORT; nsym->nType |= SYMF_EXPORT;
} }
nsym->pScope = NULL; nsym->pScope = scope;
nsym->pSection = pCurrentSection; 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 */ /* only export symbols in pass 1 */
struct sSymbol *nsym; struct sSymbol *nsym;
if ((nsym = findsymbol(tzSym, 0)) == NULL) if ((nsym = sym_FindSymbol(tzSym)) == NULL)
nsym = createsymbol(tzSym); nsym = createsymbol(tzSym);
if (nsym) if (nsym)
@@ -713,7 +734,7 @@ sym_Export(char *tzSym)
} else { } else {
struct sSymbol *nsym; struct sSymbol *nsym;
if ((nsym = findsymbol(tzSym, 0)) != NULL) { if ((nsym = sym_FindSymbol(tzSym)) != NULL) {
if (nsym->nType & SYMF_DEFINED) if (nsym->nType & SYMF_DEFINED)
return; return;
} }
@@ -732,7 +753,7 @@ sym_Global(char *tzSym)
/* only globalize symbols in pass 2 */ /* only globalize symbols in pass 2 */
struct sSymbol *nsym; struct sSymbol *nsym;
nsym = findsymbol(tzSym, 0); nsym = sym_FindSymbol(tzSym);
if ((nsym == NULL) || ((nsym->nType & SYMF_DEFINED) == 0)) { if ((nsym == NULL) || ((nsym->nType & SYMF_DEFINED) == 0)) {
if (nsym == NULL) if (nsym == NULL)