diff --git a/include/asm/rpn.h b/include/asm/rpn.h index b525125f..c971bf98 100644 --- a/include/asm/rpn.h +++ b/include/asm/rpn.h @@ -46,7 +46,7 @@ static inline bool rpn_isSymbol(const struct Expression *expr) return expr->isSymbol; } -void rpn_Symbol(struct Expression *expr, char *tzSym); +void rpn_Symbol(struct Expression *expr, char const *tzSym); void rpn_Number(struct Expression *expr, uint32_t i); void rpn_LOGNOT(struct Expression *expr, const struct Expression *src); struct Symbol const *rpn_SymbolOf(struct Expression const *expr); diff --git a/include/asm/symbol.h b/include/asm/symbol.h index 7bcc1407..4974a988 100644 --- a/include/asm/symbol.h +++ b/include/asm/symbol.h @@ -121,7 +121,19 @@ struct Symbol *sym_AddSet(char const *symName, int32_t value); uint32_t sym_GetPCValue(void); uint32_t sym_GetConstantSymValue(struct Symbol const *sym); uint32_t sym_GetConstantValue(char const *s); -struct Symbol *sym_FindSymbol(char const *symName); +/* + * Find a symbol by exact name, bypassing expansion checks + */ +struct Symbol *sym_FindExactSymbol(char const *name); +/* + * Find a symbol by exact name; may not be scoped, produces an error if it is + */ +struct Symbol *sym_FindUnscopedSymbol(char const *name); +/* + * Find a symbol, possibly scoped, by name + */ +struct Symbol *sym_FindScopedSymbol(char const *name); +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); struct Symbol *sym_AddString(char const *symName, char const *value); diff --git a/src/asm/fstack.c b/src/asm/fstack.c index 33387ad7..a9b6fe57 100644 --- a/src/asm/fstack.c +++ b/src/asm/fstack.c @@ -317,7 +317,7 @@ void fstk_RunMacro(char const *macroName, struct MacroArgs *args) { dbgPrint("Running macro \"%s\"\n", macroName); - struct Symbol *macro = sym_FindSymbol(macroName); + struct Symbol *macro = sym_FindExactSymbol(macroName); if (!macro) { error("Macro \"%s\" not defined\n", macroName); diff --git a/src/asm/lexer.c b/src/asm/lexer.c index 0c28fae9..5651d42a 100644 --- a/src/asm/lexer.c +++ b/src/asm/lexer.c @@ -1311,7 +1311,7 @@ static char const *readInterpolation(void) } symName[i] = '\0'; - struct Symbol const *sym = sym_FindSymbol(symName); + struct Symbol const *sym = sym_FindScopedSymbol(symName); if (!sym) { error("Interpolated symbol \"%s\" does not exist\n", symName); @@ -1691,9 +1691,10 @@ static int yylex_NORMAL(void) if (tokenType != T_ID && tokenType != T_LOCAL_ID) return tokenType; - if (lexerState->expandStrings) { + /* Local symbols cannot be string expansions */ + if (tokenType == T_ID && lexerState->expandStrings) { /* Attempt string expansion */ - struct Symbol const *sym = sym_FindSymbol(yylval.tzSym); + struct Symbol const *sym = sym_FindExactSymbol(yylval.tzSym); if (sym && sym->type == SYM_EQUS) { char const *s = sym_GetStringValue(sym); diff --git a/src/asm/output.c b/src/asm/output.c index 4e7585f3..961b8fcb 100644 --- a/src/asm/output.c +++ b/src/asm/output.c @@ -296,6 +296,11 @@ static void writerpn(uint8_t *rpnexpr, uint32_t *rpnptr, uint8_t *rpn, uint8_t rpndata = popbyte(); switch (rpndata) { + struct Symbol *sym; + uint32_t value; + uint8_t b; + size_t i; + case RPN_CONST: writebyte(RPN_CONST); writebyte(popbyte()); @@ -303,13 +308,15 @@ static void writerpn(uint8_t *rpnexpr, uint32_t *rpnptr, uint8_t *rpn, writebyte(popbyte()); writebyte(popbyte()); break; - case RPN_SYM: - { - for (unsigned int i = -1; (tzSym[++i] = popbyte()); ) - ; - struct Symbol *sym = sym_FindSymbol(tzSym); - uint32_t value; + case RPN_SYM: + i = 0; + do { + tzSym[i] = popbyte(); + } while (tzSym[i++]); + + // The symbol name is always written expanded + sym = sym_FindExactSymbol(tzSym); if (sym_IsConstant(sym)) { writebyte(RPN_CONST); value = sym_GetConstantValue(tzSym); @@ -317,18 +324,22 @@ static void writerpn(uint8_t *rpnexpr, uint32_t *rpnptr, uint8_t *rpn, writebyte(RPN_SYM); value = getSymbolID(sym); } + writebyte(value & 0xFF); writebyte(value >> 8); writebyte(value >> 16); writebyte(value >> 24); break; - } + case RPN_BANK_SYM: - { - for (unsigned int i = -1; (tzSym[++i] = popbyte()); ) - ; - struct Symbol *sym = sym_FindSymbol(tzSym); - uint32_t value = getSymbolID(sym); + i = 0; + do { + tzSym[i] = popbyte(); + } while (tzSym[i++]); + + // The symbol name is always written expanded + sym = sym_FindExactSymbol(tzSym); + value = getSymbolID(sym); writebyte(RPN_BANK_SYM); writebyte(value & 0xFF); @@ -336,18 +347,15 @@ static void writerpn(uint8_t *rpnexpr, uint32_t *rpnptr, uint8_t *rpn, writebyte(value >> 16); writebyte(value >> 24); break; - } - case RPN_BANK_SECT: - { - uint8_t b; + case RPN_BANK_SECT: writebyte(RPN_BANK_SECT); do { b = popbyte(); writebyte(b); } while (b != 0); break; - } + default: writebyte(rpndata); break; diff --git a/src/asm/parser.y b/src/asm/parser.y index 9e574620..18452841 100644 --- a/src/asm/parser.y +++ b/src/asm/parser.y @@ -932,7 +932,7 @@ relocexpr_no_str : scoped_id { rpn_Symbol(&$$, $1); } | T_OP_DEF { lexer_ToggleStringExpansion(false); } '(' scoped_id ')' { - struct Symbol const *sym = sym_FindSymbol($4); + struct Symbol const *sym = sym_FindScopedSymbol($4); rpn_Number(&$$, !!sym); diff --git a/src/asm/rpn.c b/src/asm/rpn.c index 7e51df86..112015d4 100644 --- a/src/asm/rpn.c +++ b/src/asm/rpn.c @@ -104,9 +104,9 @@ void rpn_Number(struct Expression *expr, uint32_t i) expr->nVal = i; } -void rpn_Symbol(struct Expression *expr, char *tzSym) +void rpn_Symbol(struct Expression *expr, char const *tzSym) { - struct Symbol *sym = sym_FindSymbol(tzSym); + struct Symbol *sym = sym_FindScopedSymbol(tzSym); if (sym_IsPC(sym) && !sect_GetSymbolSection()) { error("PC has no value outside a section\n"); @@ -115,15 +115,15 @@ void rpn_Symbol(struct Expression *expr, char *tzSym) rpn_Init(expr); expr->isSymbol = true; - sym_Ref(tzSym); makeUnknown(expr, sym_IsPC(sym) ? "PC is not constant at assembly time" : "'%s' is not constant at assembly time", tzSym); + sym = sym_Ref(tzSym); expr->nRPNPatchSize += 5; /* 1-byte opcode + 4-byte symbol ID */ - size_t nameLen = strlen(tzSym) + 1; /* Don't forget NUL! */ + size_t nameLen = strlen(sym->name) + 1; /* Don't forget NUL! */ uint8_t *ptr = reserveSpace(expr, nameLen + 1); *ptr++ = RPN_SYM; - memcpy(ptr, tzSym, nameLen); + memcpy(ptr, sym->name, nameLen); /* RGBLINK assumes PC is at the byte being computed... */ if (sym_IsPC(sym) && nPCOffset) { @@ -157,7 +157,7 @@ void rpn_BankSelf(struct Expression *expr) void rpn_BankSymbol(struct Expression *expr, char const *tzSym) { - struct Symbol const *sym = sym_FindSymbol(tzSym); + struct Symbol const *sym = sym_FindScopedSymbol(tzSym); /* The @ symbol is treated differently. */ if (sym_IsPC(sym)) { @@ -169,10 +169,8 @@ void rpn_BankSymbol(struct Expression *expr, char const *tzSym) if (sym && !sym_IsLabel(sym)) { error("BANK argument must be a label\n"); } else { - sym_Ref(tzSym); - if (!sym) - /* If the symbol didn't exist, `sym_Ref` created it */ - sym = sym_FindSymbol(tzSym); + sym = sym_Ref(tzSym); + assert(sym); // If the symbol didn't exist, it should have been created if (sym_GetSection(sym) && sym_GetSection(sym)->bank != -1) { /* Symbol's section is known and bank is fixed */ @@ -181,10 +179,10 @@ void rpn_BankSymbol(struct Expression *expr, char const *tzSym) makeUnknown(expr, "\"%s\"'s bank is not known", tzSym); expr->nRPNPatchSize += 5; /* opcode + 4-byte sect ID */ - size_t nameLen = strlen(tzSym) + 1; /* Room for NUL! */ + size_t nameLen = strlen(sym->name) + 1; /* Room for NUL! */ uint8_t *ptr = reserveSpace(expr, nameLen + 1); *ptr++ = RPN_BANK_SYM; - memcpy(ptr, tzSym, nameLen); + memcpy(ptr, sym->name, nameLen); } } } @@ -298,7 +296,7 @@ struct Symbol const *rpn_SymbolOf(struct Expression const *expr) { if (!rpn_isSymbol(expr)) return NULL; - return sym_FindSymbol((char *)expr->tRPN + 1); + return sym_FindScopedSymbol((char *)expr->tRPN + 1); } bool rpn_IsDiffConstant(struct Expression const *src, struct Symbol const *sym) diff --git a/src/asm/section.c b/src/asm/section.c index d2cbfd8f..253c8e28 100644 --- a/src/asm/section.c +++ b/src/asm/section.c @@ -620,7 +620,7 @@ void out_PCRelByte(struct Expression *expr) { checkcodesection(); reserveSpace(1); - struct Symbol const *pc = sym_FindSymbol("@"); + struct Symbol const *pc = sym_GetPC(); if (!rpn_IsDiffConstant(expr, pc)) { createPatch(PATCHTYPE_JR, expr); diff --git a/src/asm/symbol.c b/src/asm/symbol.c index 00704624..21e73b6a 100644 --- a/src/asm/symbol.c +++ b/src/asm/symbol.c @@ -222,32 +222,42 @@ static void fullSymbolName(char *output, size_t outputSize, fatalerror("Symbol name is too long: '%s%s'\n", scopeName, localName); } -/* - * Find a symbol by name and scope - */ -static struct Symbol *findsymbol(char const *s, char const *scope) +struct Symbol *sym_FindExactSymbol(char const *name) { - char fullname[MAXSYMLEN + 1]; - - if (s[0] == '.' && scope) { - fullSymbolName(fullname, sizeof(fullname), s, scope); - s = fullname; - } - - char const *separator = strchr(s, '.'); - - if (separator && strchr(separator + 1, '.')) - fatalerror("'%s' is a nonsensical reference to a nested local symbol\n", s); - - return hash_GetElement(symbols, s); + return hash_GetElement(symbols, name); } -/* - * Find a symbol by name, with automatically determined scope - */ -struct Symbol *sym_FindSymbol(char const *symName) +struct Symbol *sym_FindUnscopedSymbol(char const *name) { - return findsymbol(symName, symName[0] == '.' ? labelScope : NULL); + if (strchr(name, '.')) { + error("Expected non-scoped symbol name, not \"%s\"\n", name); + return NULL; + } + return sym_FindExactSymbol(name); +} + +struct Symbol *sym_FindScopedSymbol(char const *name) +{ + char const *dotPtr = strchr(name, '.'); + + if (dotPtr) { + if (strchr(dotPtr + 1, '.')) + fatalerror("'%s' is a nonsensical reference to a nested local symbol\n", + name); + /* If auto-scoped local label, expand the name */ + if (dotPtr == name) { /* Meaning, the name begins with the dot */ + char fullname[MAXSYMLEN + 1]; + + fullSymbolName(fullname, sizeof(fullname), name, labelScope); + return sym_FindExactSymbol(fullname); + } + } + return sym_FindExactSymbol(name); +} + +struct Symbol const *sym_GetPC(void) +{ + return PCSymbol; } static inline bool isReferenced(struct Symbol const *sym) @@ -260,7 +270,7 @@ static inline bool isReferenced(struct Symbol const *sym) */ void sym_Purge(char const *symName) { - struct Symbol *symbol = sym_FindSymbol(symName); + struct Symbol *symbol = sym_FindScopedSymbol(symName); if (!symbol) { error("'%s' not defined\n", symName); @@ -312,7 +322,7 @@ uint32_t sym_GetConstantSymValue(struct Symbol const *sym) */ uint32_t sym_GetConstantValue(char const *s) { - struct Symbol const *sym = sym_FindSymbol(s); + struct Symbol const *sym = sym_FindScopedSymbol(s); if (sym == NULL) error("'%s' not defined\n", s); @@ -339,11 +349,11 @@ void sym_SetCurrentSymbolScope(char const *newScope) */ static struct Symbol *createNonrelocSymbol(char const *symbolName) { - struct Symbol *symbol = findsymbol(symbolName, NULL); + struct Symbol *symbol = sym_FindExactSymbol(symbolName); - if (!symbol) + if (!symbol) { symbol = createsymbol(symbolName); - else if (sym_IsDefined(symbol)) { + } else if (sym_IsDefined(symbol)) { error("'%s' already defined at ", symbolName); dumpFilename(symbol); putc('\n', stderr); @@ -400,7 +410,7 @@ struct Symbol *sym_AddString(char const *symName, char const *value) */ struct Symbol *sym_AddSet(char const *symName, int32_t value) { - struct Symbol *sym = findsymbol(symName, NULL); + struct Symbol *sym = sym_FindExactSymbol(symName); if (sym == NULL) { sym = createsymbol(symName); @@ -411,7 +421,6 @@ struct Symbol *sym_AddSet(char const *symName, int32_t value) putc('\n', stderr); return sym; } else { - /* TODO: can the scope be incorrect when taking over refs? */ updateSymbolFilename(sym); } @@ -429,7 +438,7 @@ struct Symbol *sym_AddSet(char const *symName, int32_t value) static struct Symbol *addLabel(char const *name) { assert(name[0] != '.'); /* The symbol name must have been expanded prior */ - struct Symbol *sym = findsymbol(name, NULL); /* Due to this, don't look for expansions */ + struct Symbol *sym = sym_FindExactSymbol(name); if (!sym) { sym = createsymbol(name); @@ -511,7 +520,7 @@ struct Symbol *sym_AddLabel(char const *name) */ void sym_Export(char const *symName) { - struct Symbol *sym = sym_FindSymbol(symName); + struct Symbol *sym = sym_FindScopedSymbol(symName); /* If the symbol doesn't exist, create a ref that can be purged */ if (!sym) @@ -545,7 +554,7 @@ struct Symbol *sym_AddMacro(char const *symName, int32_t defLineNo, char *body, */ struct Symbol *sym_Ref(char const *symName) { - struct Symbol *nsym = sym_FindSymbol(symName); + struct Symbol *nsym = sym_FindScopedSymbol(symName); if (nsym == NULL) { char fullname[MAXSYMLEN + 1];