diff --git a/include/asm/lexer.hpp b/include/asm/lexer.hpp index 2c65fed2..c583a07b 100644 --- a/include/asm/lexer.hpp +++ b/include/asm/lexer.hpp @@ -11,8 +11,6 @@ #include "platform.hpp" // SSIZE_MAX -#include "asm/symbol.hpp" // MAXSYMLEN - #define MAXSTRLEN 255 #define LEXER_BUF_SIZE 42 // TODO: determine a sane value for this @@ -145,10 +143,6 @@ struct String { char string[MAXSTRLEN + 1]; }; -struct SymName { - char symName[MAXSYMLEN + 1]; -}; - void lexer_CheckRecursionDepth(); char const *lexer_GetFileName(); uint32_t lexer_GetLineNo(); diff --git a/include/asm/symbol.hpp b/include/asm/symbol.hpp index 8f46daf8..0082850f 100644 --- a/include/asm/symbol.hpp +++ b/include/asm/symbol.hpp @@ -3,6 +3,7 @@ #ifndef RGBDS_SYMBOL_H #define RGBDS_SYMBOL_H +#include #include #include #include @@ -12,8 +13,6 @@ #include "asm/section.hpp" -#define MAXSYMLEN 255 - enum SymbolType { SYM_LABEL, SYM_EQU, @@ -27,7 +26,7 @@ struct Symbol; // For the `sym_IsPC` forward declaration bool sym_IsPC(Symbol const *sym); // For the inline `getSection` method struct Symbol { - char name[MAXSYMLEN + 1]; + std::string name; enum SymbolType type; bool isExported; // Whether the symbol is to be exported bool isBuiltin; // Whether the symbol is a built-in @@ -72,7 +71,7 @@ void sym_SetExportAll(bool set); Symbol *sym_AddLocalLabel(char const *symName); Symbol *sym_AddLabel(char const *symName); Symbol *sym_AddAnonLabel(); -void sym_WriteAnonLabelName(char buf[MAXSYMLEN + 1], uint32_t ofs, bool neg); +std::string sym_MakeAnonLabelName(uint32_t ofs, bool neg); void sym_Export(char const *symName); Symbol *sym_AddEqu(char const *symName, int32_t value); Symbol *sym_RedefEqu(char const *symName, int32_t value); @@ -94,7 +93,7 @@ void sym_Purge(std::string const &symName); void sym_Init(time_t now); // Functions to save and restore the current symbol scope. -char const *sym_GetCurrentSymbolScope(); -void sym_SetCurrentSymbolScope(char const *newScope); +std::optional const &sym_GetCurrentSymbolScope(); +void sym_SetCurrentSymbolScope(std::optional const &newScope); #endif // RGBDS_SYMBOL_H diff --git a/src/asm/fstack.cpp b/src/asm/fstack.cpp index 412dc309..f928316e 100644 --- a/src/asm/fstack.cpp +++ b/src/asm/fstack.cpp @@ -340,7 +340,7 @@ void fstk_RunMacro(char const *macroName, MacroArgs &args) { FileStackNode *fileInfo = new (std::nothrow) FileStackNode(NODE_MACRO, ""); if (!fileInfo) { - error("Failed to alloc file info for \"%s\": %s\n", macro->name, strerror(errno)); + error("Failed to alloc file info for \"%s\": %s\n", macro->name.c_str(), strerror(errno)); return; } diff --git a/src/asm/lexer.cpp b/src/asm/lexer.cpp index 14203986..143020f6 100644 --- a/src/asm/lexer.cpp +++ b/src/asm/lexer.cpp @@ -94,18 +94,21 @@ } while (0) #endif // !( defined(_MSC_VER) || defined(__MINGW32__) ) +// FIXME: get rid of this limitation +#define MAXSYMLEN 255 + // Bison 3.6 changed token "types" to "kinds"; cast to int for simple compatibility #define T_(name) (int)yy::parser::token::name struct Token { int type; - std::variant value; + std::variant value; Token() : type(T_(NUMBER)), value(std::monostate{}) {} Token(int type_) : type(type_), value(std::monostate{}) {} Token(int type_, uint32_t value_) : type(type_), value(value_) {} Token(int type_, String &value_) : type(type_), value(value_) {} - Token(int type_, SymName &value_) : type(type_), value(value_) {} + Token(int type_, std::string &value_) : type(type_), value(value_) {} }; struct CaseInsensitive { @@ -555,29 +558,26 @@ static uint32_t readBracketedMacroArgNum() { if (c >= '0' && c <= '9') { num = readNumber(10, 0); } else if (startsIdentifier(c)) { - char symName[MAXSYMLEN + 1]; - size_t i = 0; + std::string symName; for (; continuesIdentifier(c); c = peek()) { - if (i < sizeof(symName)) - symName[i++] = c; + symName += c; shiftChar(); } - if (i == sizeof(symName)) { + if (symName.length() > MAXSYMLEN) { warning(WARNING_LONG_STR, "Bracketed symbol name too long, got truncated\n"); - i--; + symName.resize(MAXSYMLEN); } - symName[i] = '\0'; - Symbol const *sym = sym_FindScopedValidSymbol(symName); + Symbol const *sym = sym_FindScopedValidSymbol(symName.c_str()); if (!sym) { - error("Bracketed symbol \"%s\" does not exist\n", symName); + error("Bracketed symbol \"%s\" does not exist\n", symName.c_str()); num = 0; symbolError = true; } else if (!sym->isNumeric()) { - error("Bracketed symbol \"%s\" is not numeric\n", symName); + error("Bracketed symbol \"%s\" is not numeric\n", symName.c_str()); num = 0; symbolError = true; } else { @@ -927,7 +927,7 @@ static void discardLineContinuation() { // Functions to read tokenizable values -static void readAnonLabelRef(SymName &yylval, char c) { +static std::string readAnonLabelRef(char c) { uint32_t n = 0; // We come here having already peeked at one char, so no need to do it again @@ -936,7 +936,7 @@ static void readAnonLabelRef(SymName &yylval, char c) { n++; } while (peek() == c); - sym_WriteAnonLabelName(yylval.symName, n, c == '-'); + return sym_MakeAnonLabelName(n, c == '-'); } static uint32_t readNumber(int radix, uint32_t baseValue) { @@ -1130,33 +1130,28 @@ static bool continuesIdentifier(int c) { static Token readIdentifier(char firstChar) { // Lex while checking for a keyword - SymName yylval; - yylval.symName[0] = firstChar; + std::string yylval(1, firstChar); int tokenType = firstChar == '.' ? T_(LOCAL_ID) : T_(ID); - size_t i = 1; // Continue reading while the char is in the symbol charset - for (int c = peek(); continuesIdentifier(c); i++, c = peek()) { + for (int c = peek(); continuesIdentifier(c); c = peek()) { shiftChar(); - if (i < sizeof(yylval.symName) - 1) { - // Write the char to the identifier's name - yylval.symName[i] = c; - - // If the char was a dot, mark the identifier as local - if (c == '.') - tokenType = T_(LOCAL_ID); + if (yylval.length() == MAXSYMLEN) { + warning(WARNING_LONG_STR, "Symbol name too long, got truncated\n"); + break; } - } - if (i > sizeof(yylval.symName) - 1) { - warning(WARNING_LONG_STR, "Symbol name too long, got truncated\n"); - i = sizeof(yylval.symName) - 1; + // Write the char to the identifier's name + yylval += c; + + // If the char was a dot, mark the identifier as local + if (c == '.') + tokenType = T_(LOCAL_ID); } - yylval.symName[i] = '\0'; // Terminate the string // Attempt to check for a keyword - auto search = keywordDict.find(yylval.symName); + auto search = keywordDict.find(yylval.c_str()); return search != keywordDict.end() ? Token(search->second) : Token(tokenType, yylval); } @@ -1166,8 +1161,7 @@ static char const *readInterpolation(size_t depth) { if (depth > maxRecursionDepth) fatalerror("Recursion limit (%zu) exceeded\n", maxRecursionDepth); - char symName[MAXSYMLEN + 1]; - size_t i = 0; + std::string fmtBuf; FormatSpec fmt{}; bool disableInterpolation = lexerState->disableInterpolation; @@ -1194,39 +1188,36 @@ static char const *readInterpolation(size_t depth) { break; } else if (c == ':' && !fmt.isFinished()) { // Format spec, only once shiftChar(); - if (i == sizeof(symName)) { + if (fmtBuf.length() > MAXSTRLEN) { warning(WARNING_LONG_STR, "Format spec too long, got truncated\n"); - i = sizeof(symName) - 1; + fmtBuf.resize(MAXSTRLEN); } - symName[i] = '\0'; - for (size_t j = 0; j < i; j++) - fmt.useCharacter(symName[j]); + for (char f : fmtBuf) + fmt.useCharacter(f); fmt.finishCharacters(); if (!fmt.isValid()) - error("Invalid format spec '%s'\n", symName); - i = 0; // Now that format has been set, restart at beginning of string + error("Invalid format spec '%s'\n", fmtBuf.c_str()); + fmtBuf.clear(); // Now that format has been set, restart at beginning of string } else { shiftChar(); - if (i < sizeof(symName)) // Allow writing an extra char to flag overflow - symName[i++] = c; + fmtBuf += c; } } - if (i == sizeof(symName)) { + if (fmtBuf.length() > MAXSYMLEN) { warning(WARNING_LONG_STR, "Interpolated symbol name too long, got truncated\n"); - i--; + fmtBuf.resize(MAXSYMLEN); } - symName[i] = '\0'; // Don't return before `lexerState->disableInterpolation` is reset! lexerState->disableInterpolation = disableInterpolation; static char buf[MAXSTRLEN + 1]; - Symbol const *sym = sym_FindScopedValidSymbol(symName); + Symbol const *sym = sym_FindScopedValidSymbol(fmtBuf.c_str()); if (!sym) { - error("Interpolated symbol \"%s\" does not exist\n", symName); + error("Interpolated symbol \"%s\" does not exist\n", fmtBuf.c_str()); } else if (sym->type == SYM_EQUS) { fmt.printString(buf, sizeof(buf), sym->getEqus()->c_str()); return buf; @@ -1602,10 +1593,8 @@ static Token yylex_NORMAL() { return Token(T_(OP_NOT)); case '@': { - SymName yylval; - yylval.symName[0] = '@'; - yylval.symName[1] = '\0'; - return Token(T_(ID), yylval); + std::string symName("@"); + return Token(T_(ID), symName); } case '[': @@ -1741,9 +1730,8 @@ static Token yylex_NORMAL() { return Token(T_(DOUBLE_COLON)); case '+': case '-': { - SymName yylval; - readAnonLabelRef(yylval, c); - return Token(T_(ANON), yylval); + std::string symName = readAnonLabelRef(c); + return Token(T_(ANON), symName); } default: return Token(T_(COLON)); @@ -1852,20 +1840,22 @@ static Token yylex_NORMAL() { if (token.type != T_(ID) && token.type != T_(LOCAL_ID)) return token; - // `token` is either an `ID` or a `LOCAL_ID`, and both have a `SymName` value. - assert(std::holds_alternative(token.value)); + // `token` is either an `ID` or a `LOCAL_ID`, and both have a `std::string` value. + assert(std::holds_alternative(token.value)); // Local symbols cannot be string expansions if (token.type == T_(ID) && lexerState->expandStrings) { // Attempt string expansion - Symbol const *sym = sym_FindExactSymbol(std::get(token.value).symName); + Symbol const *sym = sym_FindExactSymbol( + std::get(token.value).c_str() + ); if (sym && sym->type == SYM_EQUS) { char const *str = sym->getEqus()->c_str(); assert(str); if (str[0]) - beginExpansion(str, false, sym->name); + beginExpansion(str, false, sym->name.c_str()); continue; // Restart, reading from the new buffer } } diff --git a/src/asm/output.cpp b/src/asm/output.cpp index 2bbf7b82..bc5417e1 100644 --- a/src/asm/output.cpp +++ b/src/asm/output.cpp @@ -51,9 +51,9 @@ static void putlong(uint32_t i, FILE *f) { } // Write a NUL-terminated string to a file -static void putstring(char const *s, FILE *f) { - while (*s) - putc(*s++, f); +static void putstring(std::string const &s, FILE *f) { + for (char c : s) + putc(c, f); putc(0, f); } @@ -108,7 +108,7 @@ static void writepatch(Patch const &patch, FILE *f) { // Write a section to a file static void writesection(Section const §, FILE *f) { - putstring(sect.name.c_str(), f); + putstring(sect.name, f); putlong(sect.size, f); @@ -303,7 +303,7 @@ void out_CreateAssert( static void writeassert(Assertion &assert, FILE *f) { writepatch(assert.patch, f); - putstring(assert.message.c_str(), f); + putstring(assert.message, f); } static void writeFileStackNode(FileStackNode const &node, FILE *f) { @@ -311,7 +311,7 @@ static void writeFileStackNode(FileStackNode const &node, FILE *f) { putlong(node.lineNo, f); putc(node.type, f); if (node.type != NODE_REPT) { - putstring(node.name().c_str(), f); + putstring(node.name(), f); } else { std::vector const &nodeIters = node.iters(); diff --git a/src/asm/parser.y b/src/asm/parser.y index b8d8265b..2eecd992 100644 --- a/src/asm/parser.y +++ b/src/asm/parser.y @@ -194,14 +194,14 @@ %token OP_CHARSUB "CHARSUB" %token OP_INCHARMAP "INCHARMAP" -%token LABEL "label" -%token ID "identifier" -%token LOCAL_ID "local identifier" -%token ANON "anonymous label" -%type def_id -%type redef_id -%type scoped_id -%type scoped_anon_id +%token LABEL "label" +%token ID "identifier" +%token LOCAL_ID "local identifier" +%token ANON "anonymous label" +%type def_id +%type redef_id +%type scoped_id +%type scoped_anon_id %token POP_EQU "EQU" %token POP_EQUAL "=" %token POP_EQUS "EQUS" @@ -354,13 +354,13 @@ line: lexer_SetMode(LEXER_NORMAL); lexer_ToggleStringExpansion(true); } endofline { - Symbol *macro = sym_FindExactSymbol($1.symName); + Symbol *macro = sym_FindExactSymbol($1.c_str()); if (macro && macro->type == SYM_MACRO) fprintf( stderr, " To invoke `%s` as a macro it must be indented\n", - $1.symName + $1.c_str() ); fstk_StopRept(); yyerrok; @@ -474,21 +474,21 @@ label: sym_AddAnonLabel(); } | LOCAL_ID { - sym_AddLocalLabel($1.symName); + sym_AddLocalLabel($1.c_str()); } | LOCAL_ID COLON { - sym_AddLocalLabel($1.symName); + sym_AddLocalLabel($1.c_str()); } | LABEL COLON { - sym_AddLabel($1.symName); + sym_AddLabel($1.c_str()); } | LOCAL_ID DOUBLE_COLON { - sym_AddLocalLabel($1.symName); - sym_Export($1.symName); + sym_AddLocalLabel($1.c_str()); + sym_Export($1.c_str()); } | LABEL DOUBLE_COLON { - sym_AddLabel($1.symName); - sym_Export($1.symName); + sym_AddLabel($1.c_str()); + sym_Export($1.c_str()); } ; @@ -497,7 +497,7 @@ macro: // Parsing 'macroargs' will restore the lexer's normal mode lexer_SetMode(LEXER_RAW); } macroargs { - fstk_RunMacro($1.symName, *$3); + fstk_RunMacro($1.c_str(), *$3); } ; @@ -600,17 +600,17 @@ equ: warning( WARNING_OBSOLETE, "`%s EQU` is deprecated; use `DEF %s EQU`\n", - $1.symName, - $1.symName + $1.c_str(), + $1.c_str() ); - sym_AddEqu($1.symName, $3); + sym_AddEqu($1.c_str(), $3); } ; assignment: LABEL POP_EQUAL const { - warning(WARNING_OBSOLETE, "`%s =` is deprecated; use `DEF %s =`\n", $1.symName, $1.symName); - sym_AddVar($1.symName, $3); + warning(WARNING_OBSOLETE, "`%s =` is deprecated; use `DEF %s =`\n", $1.c_str(), $1.c_str()); + sym_AddVar($1.c_str(), $3); } | LABEL compoundeq const { const char *compoundEqOperator = nullptr; @@ -631,12 +631,12 @@ assignment: warning( WARNING_OBSOLETE, "`%s %s` is deprecated; use `DEF %s %s`\n", - $1.symName, + $1.c_str(), compoundEqOperator, - $1.symName, + $1.c_str(), compoundEqOperator ); - compoundAssignment($1.symName, $2, $3); + compoundAssignment($1.c_str(), $2, $3); } ; @@ -645,10 +645,10 @@ equs: warning( WARNING_OBSOLETE, "`%s EQUS` is deprecated; use `DEF %s EQUS`\n", - $1.symName, - $1.symName + $1.c_str(), + $1.c_str() ); - sym_AddString($1.symName, $3.string); + sym_AddString($1.c_str(), $3.string); } ; @@ -657,10 +657,10 @@ rb: warning( WARNING_OBSOLETE, "`%s RB` is deprecated; use `DEF %s RB`\n", - $1.symName, - $1.symName + $1.c_str(), + $1.c_str() ); - sym_AddEqu($1.symName, sym_GetConstantValue("_RS")); + sym_AddEqu($1.c_str(), sym_GetConstantValue("_RS")); sym_AddVar("_RS", sym_GetConstantValue("_RS") + $3); } ; @@ -670,10 +670,10 @@ rw: warning( WARNING_OBSOLETE, "`%s RW` is deprecated; use `DEF %s RW`\n", - $1.symName, - $1.symName + $1.c_str(), + $1.c_str() ); - sym_AddEqu($1.symName, sym_GetConstantValue("_RS")); + sym_AddEqu($1.c_str(), sym_GetConstantValue("_RS")); sym_AddVar("_RS", sym_GetConstantValue("_RS") + 2 * $3); } ; @@ -683,10 +683,10 @@ rl: warning( WARNING_OBSOLETE, "`%s RL` is deprecated; use `DEF %s RL`\n", - $1.symName, - $1.symName + $1.c_str(), + $1.c_str() ); - sym_AddEqu($1.symName, sym_GetConstantValue("_RS")); + sym_AddEqu($1.c_str(), sym_GetConstantValue("_RS")); sym_AddVar("_RS", sym_GetConstantValue("_RS") + 4 * $3); } ; @@ -860,7 +860,7 @@ for: } COMMA for_args NEWLINE capture_rept endofline { if ($8) fstk_RunFor( - $3.symName, + $3.c_str(), $6.start, $6.stop, $6.step, @@ -909,7 +909,7 @@ macrodef: lexer_ToggleStringExpansion(true); } NEWLINE capture_macro endofline { if ($6) - sym_AddMacro($3.symName, captureBody.lineNo, captureBody.body, captureBody.size); + sym_AddMacro($3.c_str(), captureBody.lineNo, captureBody.body, captureBody.size); } ; @@ -1010,61 +1010,61 @@ dl: def_equ: def_id POP_EQU const { - sym_AddEqu($1.symName, $3); + sym_AddEqu($1.c_str(), $3); } ; redef_equ: redef_id POP_EQU const { - sym_RedefEqu($1.symName, $3); + sym_RedefEqu($1.c_str(), $3); } ; def_set: def_id POP_EQUAL const { - sym_AddVar($1.symName, $3); + sym_AddVar($1.c_str(), $3); } | redef_id POP_EQUAL const { - sym_AddVar($1.symName, $3); + sym_AddVar($1.c_str(), $3); } | def_id compoundeq const { - compoundAssignment($1.symName, $2, $3); + compoundAssignment($1.c_str(), $2, $3); } | redef_id compoundeq const { - compoundAssignment($1.symName, $2, $3); + compoundAssignment($1.c_str(), $2, $3); } ; def_rb: def_id POP_RB rs_uconst { - sym_AddEqu($1.symName, sym_GetConstantValue("_RS")); + sym_AddEqu($1.c_str(), sym_GetConstantValue("_RS")); sym_AddVar("_RS", sym_GetConstantValue("_RS") + $3); } ; def_rw: def_id POP_RW rs_uconst { - sym_AddEqu($1.symName, sym_GetConstantValue("_RS")); + sym_AddEqu($1.c_str(), sym_GetConstantValue("_RS")); sym_AddVar("_RS", sym_GetConstantValue("_RS") + 2 * $3); } ; def_rl: def_id Z80_RL rs_uconst { - sym_AddEqu($1.symName, sym_GetConstantValue("_RS")); + sym_AddEqu($1.c_str(), sym_GetConstantValue("_RS")); sym_AddVar("_RS", sym_GetConstantValue("_RS") + 4 * $3); } ; def_equs: def_id POP_EQUS string { - sym_AddString($1.symName, $3.string); + sym_AddString($1.c_str(), $3.string); } ; redef_equs: redef_id POP_EQUS string { - sym_RedefString($1.symName, $3.string); + sym_RedefString($1.c_str(), $3.string); } ; @@ -1080,10 +1080,10 @@ purge: purge_args: scoped_id { - $$.push_back($1.symName); + $$.push_back($1.c_str()); } | purge_args COMMA scoped_id { - $1.push_back($3.symName); + $1.push_back($3.c_str()); $$ = $1; } ; @@ -1097,7 +1097,7 @@ export_list: export_list_entry: scoped_id { - sym_Export($1.symName); + sym_Export($1.c_str()); } ; @@ -1135,16 +1135,16 @@ charmap: newcharmap: POP_NEWCHARMAP ID { - charmap_New($2.symName, nullptr); + charmap_New($2.c_str(), nullptr); } | POP_NEWCHARMAP ID COMMA ID { - charmap_New($2.symName, $4.symName); + charmap_New($2.c_str(), $4.c_str()); } ; setcharmap: POP_SETCHARMAP ID { - charmap_Set($2.symName); + charmap_Set($2.c_str()); } ; @@ -1302,7 +1302,7 @@ relocexpr: relocexpr_no_str: scoped_anon_id { - rpn_Symbol($$, $1.symName); + rpn_Symbol($$, $1.c_str()); } | NUMBER { rpn_Number($$, $1); @@ -1390,7 +1390,7 @@ relocexpr_no_str: } | OP_BANK LPAREN scoped_anon_id RPAREN { // '@' is also an ID; it is handled here - rpn_BankSymbol($$, $3.symName); + rpn_BankSymbol($$, $3.c_str()); } | OP_BANK LPAREN string RPAREN { rpn_BankSection($$, $3.string); @@ -1410,7 +1410,7 @@ relocexpr_no_str: | OP_DEF { lexer_ToggleStringExpansion(false); } LPAREN scoped_anon_id RPAREN { - rpn_Number($$, sym_FindScopedValidSymbol($4.symName) != nullptr); + rpn_Number($$, sym_FindScopedValidSymbol($4.c_str()) != nullptr); lexer_ToggleStringExpansion(true); } | OP_ROUND LPAREN const opt_q_arg RPAREN { @@ -1564,14 +1564,14 @@ string: strfmt($$.string, sizeof($$.string), $3.format.c_str(), $3.args); } | POP_SECTION LPAREN scoped_anon_id RPAREN { - Symbol *sym = sym_FindScopedValidSymbol($3.symName); + Symbol *sym = sym_FindScopedValidSymbol($3.c_str()); if (!sym) - fatalerror("Unknown symbol \"%s\"\n", $3.symName); + fatalerror("Unknown symbol \"%s\"\n", $3.c_str()); Section const *section = sym->getSection(); if (!section) - fatalerror("\"%s\" does not belong to any section\n", sym->name); + fatalerror("\"%s\" does not belong to any section\n", sym->name.c_str()); // Section names are capped by rgbasm's maximum string length, // so this currently can't overflow. strcpy($$.string, section->name.c_str()); diff --git a/src/asm/rpn.cpp b/src/asm/rpn.cpp index 64f6ad6d..f436f0f5 100644 --- a/src/asm/rpn.cpp +++ b/src/asm/rpn.cpp @@ -84,10 +84,10 @@ void rpn_Symbol(Expression &expr, char const *symName) { sym = sym_Ref(symName); expr.rpnPatchSize += 5; // 1-byte opcode + 4-byte symbol ID - size_t nameLen = strlen(sym->name) + 1; // Don't forget NUL! + size_t nameLen = sym->name.length() + 1; // Don't forget NUL! uint8_t *ptr = reserveSpace(expr, nameLen + 1); *ptr++ = RPN_SYM; - memcpy(ptr, sym->name, nameLen); + memcpy(ptr, sym->name.c_str(), nameLen); } else { expr.val = sym_GetConstantValue(symName); } @@ -132,11 +132,11 @@ void rpn_BankSymbol(Expression &expr, char const *symName) { makeUnknown(expr, "\"", symName, "\"'s bank is not known"); expr.rpnPatchSize += 5; // opcode + 4-byte sect ID - size_t nameLen = strlen(sym->name) + 1; // Room for NUL! + size_t nameLen = sym->name.length() + 1; // Room for NUL! uint8_t *ptr = reserveSpace(expr, nameLen + 1); *ptr++ = RPN_BANK_SYM; - memcpy(ptr, sym->name, nameLen); + memcpy(ptr, sym->name.c_str(), nameLen); } } } diff --git a/src/asm/section.cpp b/src/asm/section.cpp index 9c1361f6..0e50b1bd 100644 --- a/src/asm/section.cpp +++ b/src/asm/section.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -34,7 +35,7 @@ struct UnionStackEntry { struct SectionStackEntry { Section *section; Section *loadSection; - char const *scope; // Section's symbol scope + std::optional scope; // Section's symbol scope uint32_t offset; int32_t loadOffset; std::stack unionStack; @@ -46,7 +47,7 @@ std::deque
sectionList; uint32_t curOffset; // Offset into the current section (see sect_GetSymbolOffset) Section *currentSection = nullptr; static Section *currentLoadSection = nullptr; -char const *currentLoadScope = nullptr; +std::optional currentLoadScope = std::nullopt; int32_t loadOffset; // Offset into the LOAD section's parent (see sect_GetOutputOffset) // A quick check to see if we have an initialized section @@ -421,7 +422,7 @@ static void changeSection() { if (!currentUnionStack.empty()) fatalerror("Cannot change the section within a UNION\n"); - sym_SetCurrentSymbolScope(nullptr); + sym_SetCurrentSymbolScope(std::nullopt); } bool Section::isSizeKnown() const { @@ -990,7 +991,7 @@ void sect_PushSection() { // Reset the section scope currentSection = nullptr; currentLoadSection = nullptr; - sym_SetCurrentSymbolScope(nullptr); + sym_SetCurrentSymbolScope(std::nullopt); std::swap(currentUnionStack, sectionStack.front().unionStack); } @@ -1025,5 +1026,5 @@ void sect_EndSection() { // Reset the section scope currentSection = nullptr; - sym_SetCurrentSymbolScope(nullptr); + sym_SetCurrentSymbolScope(std::nullopt); } diff --git a/src/asm/symbol.cpp b/src/asm/symbol.cpp index 1f3bcb7b..fe9d7f11 100644 --- a/src/asm/symbol.cpp +++ b/src/asm/symbol.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -31,7 +32,7 @@ std::map symbols; -static const char *labelScope; // Current section's label scope +static std::optional labelScope = std::nullopt; // Current section's label scope static Symbol *PCSymbol; static Symbol *_NARGSymbol; static char savedTIME[256]; @@ -123,9 +124,7 @@ static void updateSymbolFilename(Symbol &sym) { static Symbol &createsymbol(char const *symName) { Symbol &sym = symbols[symName]; - if (snprintf(sym.name, MAXSYMLEN + 1, "%s", symName) > MAXSYMLEN) - warning(WARNING_LONG_STR, "Symbol name is too long: '%s'\n", symName); - + sym.name = symName; sym.isExported = false; sym.isBuiltin = false; sym.section = nullptr; @@ -135,18 +134,6 @@ static Symbol &createsymbol(char const *symName) { return sym; } -// Creates the full name of a local symbol in a given scope, by prepending -// the name with the parent symbol's name. -static void - fullSymbolName(char *output, size_t outputSize, char const *localName, char const *scopeName) { - int ret = snprintf(output, outputSize, "%s%s", scopeName, localName); - - if (ret < 0) - fatalerror("snprintf error when expanding symbol name: %s", strerror(errno)); - else if ((size_t)ret >= outputSize) - fatalerror("Symbol name is too long: '%s%s'\n", scopeName, localName); -} - static void assignStringSymbol(Symbol &sym, char const *value) { std::string *equs = new (std::nothrow) std::string(value); if (!equs) @@ -166,10 +153,9 @@ Symbol *sym_FindScopedSymbol(char const *symName) { fatalerror("'%s' is a nonsensical reference to a nested local symbol\n", symName); // If auto-scoped local label, expand the name if (localName == symName) { // Meaning, the name begins with the dot - char fullName[MAXSYMLEN + 1]; + std::string fullName = labelScope.value_or(std::string()) + symName; - fullSymbolName(fullName, sizeof(fullName), symName, labelScope); - return sym_FindExactSymbol(fullName); + return sym_FindExactSymbol(fullName.c_str()); } } return sym_FindExactSymbol(symName); @@ -206,7 +192,7 @@ void sym_Purge(std::string const &symName) { } else { // Do not keep a reference to the label's name after purging it if (sym->name == labelScope) - sym_SetCurrentSymbolScope(nullptr); + labelScope = std::nullopt; // FIXME: this leaks `sym->getEqus()` for SYM_EQUS and `sym->getMacro()` for SYM_MACRO, // but this can't delete either of them because the expansion may be purging itself. @@ -235,7 +221,7 @@ uint32_t Symbol::getConstantValue() const { if (isConstant()) return getValue(); - error("\"%s\" does not have a constant value\n", name); + error("\"%s\" does not have a constant value\n", name.c_str()); return 0; } @@ -248,11 +234,11 @@ uint32_t sym_GetConstantValue(char const *symName) { return 0; } -char const *sym_GetCurrentSymbolScope() { +std::optional const &sym_GetCurrentSymbolScope() { return labelScope; } -void sym_SetCurrentSymbolScope(char const *newScope) { +void sym_SetCurrentSymbolScope(std::optional const &newScope) { labelScope = newScope; } @@ -428,9 +414,8 @@ static Symbol *addLabel(char const *symName) { // Add a local (`.name` or `Parent.name`) relocatable symbol Symbol *sym_AddLocalLabel(char const *symName) { // Assuming no dots in `labelScope` if defined - assert(!labelScope || !strchr(labelScope, '.')); + assert(!labelScope.has_value() || labelScope->find('.') == std::string::npos); - char fullName[MAXSYMLEN + 1]; char const *localName = strchr(symName, '.'); assert(localName); // There should be at least one dot in `symName` @@ -444,16 +429,16 @@ Symbol *sym_AddLocalLabel(char const *symName) { fatalerror("'%s' is a nonsensical reference to a nested local label\n", symName); if (localName == symName) { - if (!labelScope) { + if (!labelScope.has_value()) { error("Unqualified local label '%s' in main scope\n", symName); return nullptr; } - // Expand `symName` to the full `labelScope.symName` name - fullSymbolName(fullName, sizeof(fullName), symName, labelScope); - symName = fullName; - } + std::string fullName = *labelScope + symName; - return addLabel(symName); + return addLabel(fullName.c_str()); + } else { + return addLabel(symName); + } } // Add a relocatable symbol @@ -462,7 +447,7 @@ Symbol *sym_AddLabel(char const *symName) { // Set the symbol as the new scope if (sym) - sym_SetCurrentSymbolScope(sym->name); + labelScope = sym->name; return sym; } @@ -474,15 +459,14 @@ Symbol *sym_AddAnonLabel() { error("Only %" PRIu32 " anonymous labels can be created!", anonLabelID); return nullptr; } - char name[MAXSYMLEN + 1]; - sym_WriteAnonLabelName(name, 0, true); // The direction is important! + std::string anon = sym_MakeAnonLabelName(0, true); // The direction is important! anonLabelID++; - return addLabel(name); + return addLabel(anon.c_str()); } // Write an anonymous label's name to a buffer -void sym_WriteAnonLabelName(char buf[MAXSYMLEN + 1], uint32_t ofs, bool neg) { +std::string sym_MakeAnonLabelName(uint32_t ofs, bool neg) { uint32_t id = 0; if (neg) { @@ -509,7 +493,9 @@ void sym_WriteAnonLabelName(char buf[MAXSYMLEN + 1], uint32_t ofs, bool neg) { id = anonLabelID + ofs; } - sprintf(buf, "!%u", id); + std::string anon("!"); + anon += std::to_string(id); + return anon; } // Export a symbol @@ -554,16 +540,16 @@ Symbol *sym_Ref(char const *symName) { Symbol *sym = sym_FindScopedSymbol(symName); if (!sym) { - char fullname[MAXSYMLEN + 1]; - if (symName[0] == '.') { - if (!labelScope) + if (!labelScope.has_value()) fatalerror("Local label reference '%s' in main scope\n", symName); - fullSymbolName(fullname, sizeof(fullname), symName, labelScope); - symName = fullname; + std::string fullName = *labelScope + symName; + + sym = &createsymbol(fullName.c_str()); + } else { + sym = &createsymbol(symName); } - sym = &createsymbol(symName); sym->type = SYM_REF; } @@ -656,6 +642,6 @@ void sym_Init(time_t now) { #undef addString #undef addSym - sym_SetCurrentSymbolScope(nullptr); + labelScope = std::nullopt; anonLabelID = 0; }