Use std::string for symbol names

This commit is contained in:
Rangi42
2024-03-07 11:37:32 -05:00
parent bf45ebb178
commit 097b7c3baf
9 changed files with 163 additions and 193 deletions

View File

@@ -11,8 +11,6 @@
#include "platform.hpp" // SSIZE_MAX #include "platform.hpp" // SSIZE_MAX
#include "asm/symbol.hpp" // MAXSYMLEN
#define MAXSTRLEN 255 #define MAXSTRLEN 255
#define LEXER_BUF_SIZE 42 // TODO: determine a sane value for this #define LEXER_BUF_SIZE 42 // TODO: determine a sane value for this
@@ -145,10 +143,6 @@ struct String {
char string[MAXSTRLEN + 1]; char string[MAXSTRLEN + 1];
}; };
struct SymName {
char symName[MAXSYMLEN + 1];
};
void lexer_CheckRecursionDepth(); void lexer_CheckRecursionDepth();
char const *lexer_GetFileName(); char const *lexer_GetFileName();
uint32_t lexer_GetLineNo(); uint32_t lexer_GetLineNo();

View File

@@ -3,6 +3,7 @@
#ifndef RGBDS_SYMBOL_H #ifndef RGBDS_SYMBOL_H
#define RGBDS_SYMBOL_H #define RGBDS_SYMBOL_H
#include <optional>
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
#include <string> #include <string>
@@ -12,8 +13,6 @@
#include "asm/section.hpp" #include "asm/section.hpp"
#define MAXSYMLEN 255
enum SymbolType { enum SymbolType {
SYM_LABEL, SYM_LABEL,
SYM_EQU, 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 bool sym_IsPC(Symbol const *sym); // For the inline `getSection` method
struct Symbol { struct Symbol {
char name[MAXSYMLEN + 1]; std::string name;
enum SymbolType type; enum SymbolType type;
bool isExported; // Whether the symbol is to be exported bool isExported; // Whether the symbol is to be exported
bool isBuiltin; // Whether the symbol is a built-in 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_AddLocalLabel(char const *symName);
Symbol *sym_AddLabel(char const *symName); Symbol *sym_AddLabel(char const *symName);
Symbol *sym_AddAnonLabel(); 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); void sym_Export(char const *symName);
Symbol *sym_AddEqu(char const *symName, int32_t value); Symbol *sym_AddEqu(char const *symName, int32_t value);
Symbol *sym_RedefEqu(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); void sym_Init(time_t now);
// Functions to save and restore the current symbol scope. // Functions to save and restore the current symbol scope.
char const *sym_GetCurrentSymbolScope(); std::optional<std::string> const &sym_GetCurrentSymbolScope();
void sym_SetCurrentSymbolScope(char const *newScope); void sym_SetCurrentSymbolScope(std::optional<std::string> const &newScope);
#endif // RGBDS_SYMBOL_H #endif // RGBDS_SYMBOL_H

View File

@@ -340,7 +340,7 @@ void fstk_RunMacro(char const *macroName, MacroArgs &args) {
FileStackNode *fileInfo = new (std::nothrow) FileStackNode(NODE_MACRO, ""); FileStackNode *fileInfo = new (std::nothrow) FileStackNode(NODE_MACRO, "");
if (!fileInfo) { 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; return;
} }

View File

@@ -94,18 +94,21 @@
} while (0) } while (0)
#endif // !( defined(_MSC_VER) || defined(__MINGW32__) ) #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 // Bison 3.6 changed token "types" to "kinds"; cast to int for simple compatibility
#define T_(name) (int)yy::parser::token::name #define T_(name) (int)yy::parser::token::name
struct Token { struct Token {
int type; int type;
std::variant<std::monostate, uint32_t, String, SymName> value; std::variant<std::monostate, uint32_t, String, std::string> value;
Token() : type(T_(NUMBER)), value(std::monostate{}) {} Token() : type(T_(NUMBER)), value(std::monostate{}) {}
Token(int type_) : type(type_), value(std::monostate{}) {} Token(int type_) : type(type_), value(std::monostate{}) {}
Token(int type_, uint32_t value_) : type(type_), value(value_) {} Token(int type_, uint32_t value_) : type(type_), value(value_) {}
Token(int type_, String &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 { struct CaseInsensitive {
@@ -555,29 +558,26 @@ static uint32_t readBracketedMacroArgNum() {
if (c >= '0' && c <= '9') { if (c >= '0' && c <= '9') {
num = readNumber(10, 0); num = readNumber(10, 0);
} else if (startsIdentifier(c)) { } else if (startsIdentifier(c)) {
char symName[MAXSYMLEN + 1]; std::string symName;
size_t i = 0;
for (; continuesIdentifier(c); c = peek()) { for (; continuesIdentifier(c); c = peek()) {
if (i < sizeof(symName)) symName += c;
symName[i++] = c;
shiftChar(); shiftChar();
} }
if (i == sizeof(symName)) { if (symName.length() > MAXSYMLEN) {
warning(WARNING_LONG_STR, "Bracketed symbol name too long, got truncated\n"); 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) { if (!sym) {
error("Bracketed symbol \"%s\" does not exist\n", symName); error("Bracketed symbol \"%s\" does not exist\n", symName.c_str());
num = 0; num = 0;
symbolError = true; symbolError = true;
} else if (!sym->isNumeric()) { } 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; num = 0;
symbolError = true; symbolError = true;
} else { } else {
@@ -927,7 +927,7 @@ static void discardLineContinuation() {
// Functions to read tokenizable values // Functions to read tokenizable values
static void readAnonLabelRef(SymName &yylval, char c) { static std::string readAnonLabelRef(char c) {
uint32_t n = 0; uint32_t n = 0;
// We come here having already peeked at one char, so no need to do it again // 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++; n++;
} while (peek() == c); } while (peek() == c);
sym_WriteAnonLabelName(yylval.symName, n, c == '-'); return sym_MakeAnonLabelName(n, c == '-');
} }
static uint32_t readNumber(int radix, uint32_t baseValue) { static uint32_t readNumber(int radix, uint32_t baseValue) {
@@ -1130,33 +1130,28 @@ static bool continuesIdentifier(int c) {
static Token readIdentifier(char firstChar) { static Token readIdentifier(char firstChar) {
// Lex while checking for a keyword // Lex while checking for a keyword
SymName yylval; std::string yylval(1, firstChar);
yylval.symName[0] = firstChar;
int tokenType = firstChar == '.' ? T_(LOCAL_ID) : T_(ID); int tokenType = firstChar == '.' ? T_(LOCAL_ID) : T_(ID);
size_t i = 1;
// Continue reading while the char is in the symbol charset // 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(); shiftChar();
if (i < sizeof(yylval.symName) - 1) { if (yylval.length() == MAXSYMLEN) {
warning(WARNING_LONG_STR, "Symbol name too long, got truncated\n");
break;
}
// Write the char to the identifier's name // Write the char to the identifier's name
yylval.symName[i] = c; yylval += c;
// If the char was a dot, mark the identifier as local // If the char was a dot, mark the identifier as local
if (c == '.') if (c == '.')
tokenType = T_(LOCAL_ID); tokenType = T_(LOCAL_ID);
} }
}
if (i > sizeof(yylval.symName) - 1) {
warning(WARNING_LONG_STR, "Symbol name too long, got truncated\n");
i = sizeof(yylval.symName) - 1;
}
yylval.symName[i] = '\0'; // Terminate the string
// Attempt to check for a keyword // 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); return search != keywordDict.end() ? Token(search->second) : Token(tokenType, yylval);
} }
@@ -1166,8 +1161,7 @@ static char const *readInterpolation(size_t depth) {
if (depth > maxRecursionDepth) if (depth > maxRecursionDepth)
fatalerror("Recursion limit (%zu) exceeded\n", maxRecursionDepth); fatalerror("Recursion limit (%zu) exceeded\n", maxRecursionDepth);
char symName[MAXSYMLEN + 1]; std::string fmtBuf;
size_t i = 0;
FormatSpec fmt{}; FormatSpec fmt{};
bool disableInterpolation = lexerState->disableInterpolation; bool disableInterpolation = lexerState->disableInterpolation;
@@ -1194,39 +1188,36 @@ static char const *readInterpolation(size_t depth) {
break; break;
} else if (c == ':' && !fmt.isFinished()) { // Format spec, only once } else if (c == ':' && !fmt.isFinished()) { // Format spec, only once
shiftChar(); shiftChar();
if (i == sizeof(symName)) { if (fmtBuf.length() > MAXSTRLEN) {
warning(WARNING_LONG_STR, "Format spec too long, got truncated\n"); warning(WARNING_LONG_STR, "Format spec too long, got truncated\n");
i = sizeof(symName) - 1; fmtBuf.resize(MAXSTRLEN);
} }
symName[i] = '\0'; for (char f : fmtBuf)
for (size_t j = 0; j < i; j++) fmt.useCharacter(f);
fmt.useCharacter(symName[j]);
fmt.finishCharacters(); fmt.finishCharacters();
if (!fmt.isValid()) if (!fmt.isValid())
error("Invalid format spec '%s'\n", symName); error("Invalid format spec '%s'\n", fmtBuf.c_str());
i = 0; // Now that format has been set, restart at beginning of string fmtBuf.clear(); // Now that format has been set, restart at beginning of string
} else { } else {
shiftChar(); shiftChar();
if (i < sizeof(symName)) // Allow writing an extra char to flag overflow fmtBuf += c;
symName[i++] = c;
} }
} }
if (i == sizeof(symName)) { if (fmtBuf.length() > MAXSYMLEN) {
warning(WARNING_LONG_STR, "Interpolated symbol name too long, got truncated\n"); 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! // Don't return before `lexerState->disableInterpolation` is reset!
lexerState->disableInterpolation = disableInterpolation; lexerState->disableInterpolation = disableInterpolation;
static char buf[MAXSTRLEN + 1]; static char buf[MAXSTRLEN + 1];
Symbol const *sym = sym_FindScopedValidSymbol(symName); Symbol const *sym = sym_FindScopedValidSymbol(fmtBuf.c_str());
if (!sym) { 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) { } else if (sym->type == SYM_EQUS) {
fmt.printString(buf, sizeof(buf), sym->getEqus()->c_str()); fmt.printString(buf, sizeof(buf), sym->getEqus()->c_str());
return buf; return buf;
@@ -1602,10 +1593,8 @@ static Token yylex_NORMAL() {
return Token(T_(OP_NOT)); return Token(T_(OP_NOT));
case '@': { case '@': {
SymName yylval; std::string symName("@");
yylval.symName[0] = '@'; return Token(T_(ID), symName);
yylval.symName[1] = '\0';
return Token(T_(ID), yylval);
} }
case '[': case '[':
@@ -1741,9 +1730,8 @@ static Token yylex_NORMAL() {
return Token(T_(DOUBLE_COLON)); return Token(T_(DOUBLE_COLON));
case '+': case '+':
case '-': { case '-': {
SymName yylval; std::string symName = readAnonLabelRef(c);
readAnonLabelRef(yylval, c); return Token(T_(ANON), symName);
return Token(T_(ANON), yylval);
} }
default: default:
return Token(T_(COLON)); return Token(T_(COLON));
@@ -1852,20 +1840,22 @@ static Token yylex_NORMAL() {
if (token.type != T_(ID) && token.type != T_(LOCAL_ID)) if (token.type != T_(ID) && token.type != T_(LOCAL_ID))
return token; return token;
// `token` is either an `ID` or a `LOCAL_ID`, and both have a `SymName` value. // `token` is either an `ID` or a `LOCAL_ID`, and both have a `std::string` value.
assert(std::holds_alternative<SymName>(token.value)); assert(std::holds_alternative<std::string>(token.value));
// Local symbols cannot be string expansions // Local symbols cannot be string expansions
if (token.type == T_(ID) && lexerState->expandStrings) { if (token.type == T_(ID) && lexerState->expandStrings) {
// Attempt string expansion // Attempt string expansion
Symbol const *sym = sym_FindExactSymbol(std::get<SymName>(token.value).symName); Symbol const *sym = sym_FindExactSymbol(
std::get<std::string>(token.value).c_str()
);
if (sym && sym->type == SYM_EQUS) { if (sym && sym->type == SYM_EQUS) {
char const *str = sym->getEqus()->c_str(); char const *str = sym->getEqus()->c_str();
assert(str); assert(str);
if (str[0]) if (str[0])
beginExpansion(str, false, sym->name); beginExpansion(str, false, sym->name.c_str());
continue; // Restart, reading from the new buffer continue; // Restart, reading from the new buffer
} }
} }

View File

@@ -51,9 +51,9 @@ static void putlong(uint32_t i, FILE *f) {
} }
// Write a NUL-terminated string to a file // Write a NUL-terminated string to a file
static void putstring(char const *s, FILE *f) { static void putstring(std::string const &s, FILE *f) {
while (*s) for (char c : s)
putc(*s++, f); putc(c, f);
putc(0, f); putc(0, f);
} }
@@ -108,7 +108,7 @@ static void writepatch(Patch const &patch, FILE *f) {
// Write a section to a file // Write a section to a file
static void writesection(Section const &sect, FILE *f) { static void writesection(Section const &sect, FILE *f) {
putstring(sect.name.c_str(), f); putstring(sect.name, f);
putlong(sect.size, f); putlong(sect.size, f);
@@ -303,7 +303,7 @@ void out_CreateAssert(
static void writeassert(Assertion &assert, FILE *f) { static void writeassert(Assertion &assert, FILE *f) {
writepatch(assert.patch, f); writepatch(assert.patch, f);
putstring(assert.message.c_str(), f); putstring(assert.message, f);
} }
static void writeFileStackNode(FileStackNode const &node, FILE *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); putlong(node.lineNo, f);
putc(node.type, f); putc(node.type, f);
if (node.type != NODE_REPT) { if (node.type != NODE_REPT) {
putstring(node.name().c_str(), f); putstring(node.name(), f);
} else { } else {
std::vector<uint32_t> const &nodeIters = node.iters(); std::vector<uint32_t> const &nodeIters = node.iters();

View File

@@ -194,14 +194,14 @@
%token OP_CHARSUB "CHARSUB" %token OP_CHARSUB "CHARSUB"
%token OP_INCHARMAP "INCHARMAP" %token OP_INCHARMAP "INCHARMAP"
%token <SymName> LABEL "label" %token <std::string> LABEL "label"
%token <SymName> ID "identifier" %token <std::string> ID "identifier"
%token <SymName> LOCAL_ID "local identifier" %token <std::string> LOCAL_ID "local identifier"
%token <SymName> ANON "anonymous label" %token <std::string> ANON "anonymous label"
%type <SymName> def_id %type <std::string> def_id
%type <SymName> redef_id %type <std::string> redef_id
%type <SymName> scoped_id %type <std::string> scoped_id
%type <SymName> scoped_anon_id %type <std::string> scoped_anon_id
%token POP_EQU "EQU" %token POP_EQU "EQU"
%token POP_EQUAL "=" %token POP_EQUAL "="
%token POP_EQUS "EQUS" %token POP_EQUS "EQUS"
@@ -354,13 +354,13 @@ line:
lexer_SetMode(LEXER_NORMAL); lexer_SetMode(LEXER_NORMAL);
lexer_ToggleStringExpansion(true); lexer_ToggleStringExpansion(true);
} endofline { } endofline {
Symbol *macro = sym_FindExactSymbol($1.symName); Symbol *macro = sym_FindExactSymbol($1.c_str());
if (macro && macro->type == SYM_MACRO) if (macro && macro->type == SYM_MACRO)
fprintf( fprintf(
stderr, stderr,
" To invoke `%s` as a macro it must be indented\n", " To invoke `%s` as a macro it must be indented\n",
$1.symName $1.c_str()
); );
fstk_StopRept(); fstk_StopRept();
yyerrok; yyerrok;
@@ -474,21 +474,21 @@ label:
sym_AddAnonLabel(); sym_AddAnonLabel();
} }
| LOCAL_ID { | LOCAL_ID {
sym_AddLocalLabel($1.symName); sym_AddLocalLabel($1.c_str());
} }
| LOCAL_ID COLON { | LOCAL_ID COLON {
sym_AddLocalLabel($1.symName); sym_AddLocalLabel($1.c_str());
} }
| LABEL COLON { | LABEL COLON {
sym_AddLabel($1.symName); sym_AddLabel($1.c_str());
} }
| LOCAL_ID DOUBLE_COLON { | LOCAL_ID DOUBLE_COLON {
sym_AddLocalLabel($1.symName); sym_AddLocalLabel($1.c_str());
sym_Export($1.symName); sym_Export($1.c_str());
} }
| LABEL DOUBLE_COLON { | LABEL DOUBLE_COLON {
sym_AddLabel($1.symName); sym_AddLabel($1.c_str());
sym_Export($1.symName); sym_Export($1.c_str());
} }
; ;
@@ -497,7 +497,7 @@ macro:
// Parsing 'macroargs' will restore the lexer's normal mode // Parsing 'macroargs' will restore the lexer's normal mode
lexer_SetMode(LEXER_RAW); lexer_SetMode(LEXER_RAW);
} macroargs { } macroargs {
fstk_RunMacro($1.symName, *$3); fstk_RunMacro($1.c_str(), *$3);
} }
; ;
@@ -600,17 +600,17 @@ equ:
warning( warning(
WARNING_OBSOLETE, WARNING_OBSOLETE,
"`%s EQU` is deprecated; use `DEF %s EQU`\n", "`%s EQU` is deprecated; use `DEF %s EQU`\n",
$1.symName, $1.c_str(),
$1.symName $1.c_str()
); );
sym_AddEqu($1.symName, $3); sym_AddEqu($1.c_str(), $3);
} }
; ;
assignment: assignment:
LABEL POP_EQUAL const { LABEL POP_EQUAL const {
warning(WARNING_OBSOLETE, "`%s =` is deprecated; use `DEF %s =`\n", $1.symName, $1.symName); warning(WARNING_OBSOLETE, "`%s =` is deprecated; use `DEF %s =`\n", $1.c_str(), $1.c_str());
sym_AddVar($1.symName, $3); sym_AddVar($1.c_str(), $3);
} }
| LABEL compoundeq const { | LABEL compoundeq const {
const char *compoundEqOperator = nullptr; const char *compoundEqOperator = nullptr;
@@ -631,12 +631,12 @@ assignment:
warning( warning(
WARNING_OBSOLETE, WARNING_OBSOLETE,
"`%s %s` is deprecated; use `DEF %s %s`\n", "`%s %s` is deprecated; use `DEF %s %s`\n",
$1.symName, $1.c_str(),
compoundEqOperator, compoundEqOperator,
$1.symName, $1.c_str(),
compoundEqOperator compoundEqOperator
); );
compoundAssignment($1.symName, $2, $3); compoundAssignment($1.c_str(), $2, $3);
} }
; ;
@@ -645,10 +645,10 @@ equs:
warning( warning(
WARNING_OBSOLETE, WARNING_OBSOLETE,
"`%s EQUS` is deprecated; use `DEF %s EQUS`\n", "`%s EQUS` is deprecated; use `DEF %s EQUS`\n",
$1.symName, $1.c_str(),
$1.symName $1.c_str()
); );
sym_AddString($1.symName, $3.string); sym_AddString($1.c_str(), $3.string);
} }
; ;
@@ -657,10 +657,10 @@ rb:
warning( warning(
WARNING_OBSOLETE, WARNING_OBSOLETE,
"`%s RB` is deprecated; use `DEF %s RB`\n", "`%s RB` is deprecated; use `DEF %s RB`\n",
$1.symName, $1.c_str(),
$1.symName $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); sym_AddVar("_RS", sym_GetConstantValue("_RS") + $3);
} }
; ;
@@ -670,10 +670,10 @@ rw:
warning( warning(
WARNING_OBSOLETE, WARNING_OBSOLETE,
"`%s RW` is deprecated; use `DEF %s RW`\n", "`%s RW` is deprecated; use `DEF %s RW`\n",
$1.symName, $1.c_str(),
$1.symName $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); sym_AddVar("_RS", sym_GetConstantValue("_RS") + 2 * $3);
} }
; ;
@@ -683,10 +683,10 @@ rl:
warning( warning(
WARNING_OBSOLETE, WARNING_OBSOLETE,
"`%s RL` is deprecated; use `DEF %s RL`\n", "`%s RL` is deprecated; use `DEF %s RL`\n",
$1.symName, $1.c_str(),
$1.symName $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); sym_AddVar("_RS", sym_GetConstantValue("_RS") + 4 * $3);
} }
; ;
@@ -860,7 +860,7 @@ for:
} COMMA for_args NEWLINE capture_rept endofline { } COMMA for_args NEWLINE capture_rept endofline {
if ($8) if ($8)
fstk_RunFor( fstk_RunFor(
$3.symName, $3.c_str(),
$6.start, $6.start,
$6.stop, $6.stop,
$6.step, $6.step,
@@ -909,7 +909,7 @@ macrodef:
lexer_ToggleStringExpansion(true); lexer_ToggleStringExpansion(true);
} NEWLINE capture_macro endofline { } NEWLINE capture_macro endofline {
if ($6) 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_equ:
def_id POP_EQU const { def_id POP_EQU const {
sym_AddEqu($1.symName, $3); sym_AddEqu($1.c_str(), $3);
} }
; ;
redef_equ: redef_equ:
redef_id POP_EQU const { redef_id POP_EQU const {
sym_RedefEqu($1.symName, $3); sym_RedefEqu($1.c_str(), $3);
} }
; ;
def_set: def_set:
def_id POP_EQUAL const { def_id POP_EQUAL const {
sym_AddVar($1.symName, $3); sym_AddVar($1.c_str(), $3);
} }
| redef_id POP_EQUAL const { | redef_id POP_EQUAL const {
sym_AddVar($1.symName, $3); sym_AddVar($1.c_str(), $3);
} }
| def_id compoundeq const { | def_id compoundeq const {
compoundAssignment($1.symName, $2, $3); compoundAssignment($1.c_str(), $2, $3);
} }
| redef_id compoundeq const { | redef_id compoundeq const {
compoundAssignment($1.symName, $2, $3); compoundAssignment($1.c_str(), $2, $3);
} }
; ;
def_rb: def_rb:
def_id POP_RB rs_uconst { 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); sym_AddVar("_RS", sym_GetConstantValue("_RS") + $3);
} }
; ;
def_rw: def_rw:
def_id POP_RW rs_uconst { 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); sym_AddVar("_RS", sym_GetConstantValue("_RS") + 2 * $3);
} }
; ;
def_rl: def_rl:
def_id Z80_RL rs_uconst { 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); sym_AddVar("_RS", sym_GetConstantValue("_RS") + 4 * $3);
} }
; ;
def_equs: def_equs:
def_id POP_EQUS string { def_id POP_EQUS string {
sym_AddString($1.symName, $3.string); sym_AddString($1.c_str(), $3.string);
} }
; ;
redef_equs: redef_equs:
redef_id POP_EQUS string { 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: purge_args:
scoped_id { scoped_id {
$$.push_back($1.symName); $$.push_back($1.c_str());
} }
| purge_args COMMA scoped_id { | purge_args COMMA scoped_id {
$1.push_back($3.symName); $1.push_back($3.c_str());
$$ = $1; $$ = $1;
} }
; ;
@@ -1097,7 +1097,7 @@ export_list:
export_list_entry: export_list_entry:
scoped_id { scoped_id {
sym_Export($1.symName); sym_Export($1.c_str());
} }
; ;
@@ -1135,16 +1135,16 @@ charmap:
newcharmap: newcharmap:
POP_NEWCHARMAP ID { POP_NEWCHARMAP ID {
charmap_New($2.symName, nullptr); charmap_New($2.c_str(), nullptr);
} }
| POP_NEWCHARMAP ID COMMA ID { | POP_NEWCHARMAP ID COMMA ID {
charmap_New($2.symName, $4.symName); charmap_New($2.c_str(), $4.c_str());
} }
; ;
setcharmap: setcharmap:
POP_SETCHARMAP ID { POP_SETCHARMAP ID {
charmap_Set($2.symName); charmap_Set($2.c_str());
} }
; ;
@@ -1302,7 +1302,7 @@ relocexpr:
relocexpr_no_str: relocexpr_no_str:
scoped_anon_id { scoped_anon_id {
rpn_Symbol($$, $1.symName); rpn_Symbol($$, $1.c_str());
} }
| NUMBER { | NUMBER {
rpn_Number($$, $1); rpn_Number($$, $1);
@@ -1390,7 +1390,7 @@ relocexpr_no_str:
} }
| OP_BANK LPAREN scoped_anon_id RPAREN { | OP_BANK LPAREN scoped_anon_id RPAREN {
// '@' is also an ID; it is handled here // '@' is also an ID; it is handled here
rpn_BankSymbol($$, $3.symName); rpn_BankSymbol($$, $3.c_str());
} }
| OP_BANK LPAREN string RPAREN { | OP_BANK LPAREN string RPAREN {
rpn_BankSection($$, $3.string); rpn_BankSection($$, $3.string);
@@ -1410,7 +1410,7 @@ relocexpr_no_str:
| OP_DEF { | OP_DEF {
lexer_ToggleStringExpansion(false); lexer_ToggleStringExpansion(false);
} LPAREN scoped_anon_id RPAREN { } LPAREN scoped_anon_id RPAREN {
rpn_Number($$, sym_FindScopedValidSymbol($4.symName) != nullptr); rpn_Number($$, sym_FindScopedValidSymbol($4.c_str()) != nullptr);
lexer_ToggleStringExpansion(true); lexer_ToggleStringExpansion(true);
} }
| OP_ROUND LPAREN const opt_q_arg RPAREN { | OP_ROUND LPAREN const opt_q_arg RPAREN {
@@ -1564,14 +1564,14 @@ string:
strfmt($$.string, sizeof($$.string), $3.format.c_str(), $3.args); strfmt($$.string, sizeof($$.string), $3.format.c_str(), $3.args);
} }
| POP_SECTION LPAREN scoped_anon_id RPAREN { | POP_SECTION LPAREN scoped_anon_id RPAREN {
Symbol *sym = sym_FindScopedValidSymbol($3.symName); Symbol *sym = sym_FindScopedValidSymbol($3.c_str());
if (!sym) if (!sym)
fatalerror("Unknown symbol \"%s\"\n", $3.symName); fatalerror("Unknown symbol \"%s\"\n", $3.c_str());
Section const *section = sym->getSection(); Section const *section = sym->getSection();
if (!section) 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, // Section names are capped by rgbasm's maximum string length,
// so this currently can't overflow. // so this currently can't overflow.
strcpy($$.string, section->name.c_str()); strcpy($$.string, section->name.c_str());

View File

@@ -84,10 +84,10 @@ void rpn_Symbol(Expression &expr, char const *symName) {
sym = sym_Ref(symName); sym = sym_Ref(symName);
expr.rpnPatchSize += 5; // 1-byte opcode + 4-byte symbol ID 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); uint8_t *ptr = reserveSpace(expr, nameLen + 1);
*ptr++ = RPN_SYM; *ptr++ = RPN_SYM;
memcpy(ptr, sym->name, nameLen); memcpy(ptr, sym->name.c_str(), nameLen);
} else { } else {
expr.val = sym_GetConstantValue(symName); 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"); makeUnknown(expr, "\"", symName, "\"'s bank is not known");
expr.rpnPatchSize += 5; // opcode + 4-byte sect ID 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); uint8_t *ptr = reserveSpace(expr, nameLen + 1);
*ptr++ = RPN_BANK_SYM; *ptr++ = RPN_BANK_SYM;
memcpy(ptr, sym->name, nameLen); memcpy(ptr, sym->name.c_str(), nameLen);
} }
} }
} }

View File

@@ -7,6 +7,7 @@
#include <deque> #include <deque>
#include <errno.h> #include <errno.h>
#include <inttypes.h> #include <inttypes.h>
#include <optional>
#include <stack> #include <stack>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@@ -34,7 +35,7 @@ struct UnionStackEntry {
struct SectionStackEntry { struct SectionStackEntry {
Section *section; Section *section;
Section *loadSection; Section *loadSection;
char const *scope; // Section's symbol scope std::optional<std::string> scope; // Section's symbol scope
uint32_t offset; uint32_t offset;
int32_t loadOffset; int32_t loadOffset;
std::stack<UnionStackEntry> unionStack; std::stack<UnionStackEntry> unionStack;
@@ -46,7 +47,7 @@ std::deque<Section> sectionList;
uint32_t curOffset; // Offset into the current section (see sect_GetSymbolOffset) uint32_t curOffset; // Offset into the current section (see sect_GetSymbolOffset)
Section *currentSection = nullptr; Section *currentSection = nullptr;
static Section *currentLoadSection = nullptr; static Section *currentLoadSection = nullptr;
char const *currentLoadScope = nullptr; std::optional<std::string> currentLoadScope = std::nullopt;
int32_t loadOffset; // Offset into the LOAD section's parent (see sect_GetOutputOffset) int32_t loadOffset; // Offset into the LOAD section's parent (see sect_GetOutputOffset)
// A quick check to see if we have an initialized section // A quick check to see if we have an initialized section
@@ -421,7 +422,7 @@ static void changeSection() {
if (!currentUnionStack.empty()) if (!currentUnionStack.empty())
fatalerror("Cannot change the section within a UNION\n"); fatalerror("Cannot change the section within a UNION\n");
sym_SetCurrentSymbolScope(nullptr); sym_SetCurrentSymbolScope(std::nullopt);
} }
bool Section::isSizeKnown() const { bool Section::isSizeKnown() const {
@@ -990,7 +991,7 @@ void sect_PushSection() {
// Reset the section scope // Reset the section scope
currentSection = nullptr; currentSection = nullptr;
currentLoadSection = nullptr; currentLoadSection = nullptr;
sym_SetCurrentSymbolScope(nullptr); sym_SetCurrentSymbolScope(std::nullopt);
std::swap(currentUnionStack, sectionStack.front().unionStack); std::swap(currentUnionStack, sectionStack.front().unionStack);
} }
@@ -1025,5 +1026,5 @@ void sect_EndSection() {
// Reset the section scope // Reset the section scope
currentSection = nullptr; currentSection = nullptr;
sym_SetCurrentSymbolScope(nullptr); sym_SetCurrentSymbolScope(std::nullopt);
} }

View File

@@ -8,6 +8,7 @@
#include <limits.h> #include <limits.h>
#include <map> #include <map>
#include <new> #include <new>
#include <optional>
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@@ -31,7 +32,7 @@
std::map<std::string, Symbol> symbols; std::map<std::string, Symbol> symbols;
static const char *labelScope; // Current section's label scope static std::optional<std::string> labelScope = std::nullopt; // Current section's label scope
static Symbol *PCSymbol; static Symbol *PCSymbol;
static Symbol *_NARGSymbol; static Symbol *_NARGSymbol;
static char savedTIME[256]; static char savedTIME[256];
@@ -123,9 +124,7 @@ static void updateSymbolFilename(Symbol &sym) {
static Symbol &createsymbol(char const *symName) { static Symbol &createsymbol(char const *symName) {
Symbol &sym = symbols[symName]; Symbol &sym = symbols[symName];
if (snprintf(sym.name, MAXSYMLEN + 1, "%s", symName) > MAXSYMLEN) sym.name = symName;
warning(WARNING_LONG_STR, "Symbol name is too long: '%s'\n", symName);
sym.isExported = false; sym.isExported = false;
sym.isBuiltin = false; sym.isBuiltin = false;
sym.section = nullptr; sym.section = nullptr;
@@ -135,18 +134,6 @@ static Symbol &createsymbol(char const *symName) {
return sym; 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) { static void assignStringSymbol(Symbol &sym, char const *value) {
std::string *equs = new (std::nothrow) std::string(value); std::string *equs = new (std::nothrow) std::string(value);
if (!equs) 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); fatalerror("'%s' is a nonsensical reference to a nested local symbol\n", symName);
// If auto-scoped local label, expand the name // If auto-scoped local label, expand the name
if (localName == symName) { // Meaning, the name begins with the dot 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.c_str());
return sym_FindExactSymbol(fullName);
} }
} }
return sym_FindExactSymbol(symName); return sym_FindExactSymbol(symName);
@@ -206,7 +192,7 @@ void sym_Purge(std::string const &symName) {
} else { } else {
// Do not keep a reference to the label's name after purging it // Do not keep a reference to the label's name after purging it
if (sym->name == labelScope) if (sym->name == labelScope)
sym_SetCurrentSymbolScope(nullptr); labelScope = std::nullopt;
// FIXME: this leaks `sym->getEqus()` for SYM_EQUS and `sym->getMacro()` for SYM_MACRO, // 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. // 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()) if (isConstant())
return getValue(); 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; return 0;
} }
@@ -248,11 +234,11 @@ uint32_t sym_GetConstantValue(char const *symName) {
return 0; return 0;
} }
char const *sym_GetCurrentSymbolScope() { std::optional<std::string> const &sym_GetCurrentSymbolScope() {
return labelScope; return labelScope;
} }
void sym_SetCurrentSymbolScope(char const *newScope) { void sym_SetCurrentSymbolScope(std::optional<std::string> const &newScope) {
labelScope = newScope; labelScope = newScope;
} }
@@ -428,9 +414,8 @@ static Symbol *addLabel(char const *symName) {
// Add a local (`.name` or `Parent.name`) relocatable symbol // Add a local (`.name` or `Parent.name`) relocatable symbol
Symbol *sym_AddLocalLabel(char const *symName) { Symbol *sym_AddLocalLabel(char const *symName) {
// Assuming no dots in `labelScope` if defined // 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, '.'); char const *localName = strchr(symName, '.');
assert(localName); // There should be at least one dot in `symName` assert(localName); // There should be at least one dot in `symName`
@@ -444,17 +429,17 @@ Symbol *sym_AddLocalLabel(char const *symName) {
fatalerror("'%s' is a nonsensical reference to a nested local label\n", symName); fatalerror("'%s' is a nonsensical reference to a nested local label\n", symName);
if (localName == symName) { if (localName == symName) {
if (!labelScope) { if (!labelScope.has_value()) {
error("Unqualified local label '%s' in main scope\n", symName); error("Unqualified local label '%s' in main scope\n", symName);
return nullptr; return nullptr;
} }
// Expand `symName` to the full `labelScope.symName` name std::string fullName = *labelScope + symName;
fullSymbolName(fullName, sizeof(fullName), symName, labelScope);
symName = fullName;
}
return addLabel(fullName.c_str());
} else {
return addLabel(symName); return addLabel(symName);
} }
}
// Add a relocatable symbol // Add a relocatable symbol
Symbol *sym_AddLabel(char const *symName) { Symbol *sym_AddLabel(char const *symName) {
@@ -462,7 +447,7 @@ Symbol *sym_AddLabel(char const *symName) {
// Set the symbol as the new scope // Set the symbol as the new scope
if (sym) if (sym)
sym_SetCurrentSymbolScope(sym->name); labelScope = sym->name;
return sym; return sym;
} }
@@ -474,15 +459,14 @@ Symbol *sym_AddAnonLabel() {
error("Only %" PRIu32 " anonymous labels can be created!", anonLabelID); error("Only %" PRIu32 " anonymous labels can be created!", anonLabelID);
return nullptr; 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++; anonLabelID++;
return addLabel(name); return addLabel(anon.c_str());
} }
// Write an anonymous label's name to a buffer // 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; uint32_t id = 0;
if (neg) { if (neg) {
@@ -509,7 +493,9 @@ void sym_WriteAnonLabelName(char buf[MAXSYMLEN + 1], uint32_t ofs, bool neg) {
id = anonLabelID + ofs; id = anonLabelID + ofs;
} }
sprintf(buf, "!%u", id); std::string anon("!");
anon += std::to_string(id);
return anon;
} }
// Export a symbol // Export a symbol
@@ -554,16 +540,16 @@ Symbol *sym_Ref(char const *symName) {
Symbol *sym = sym_FindScopedSymbol(symName); Symbol *sym = sym_FindScopedSymbol(symName);
if (!sym) { if (!sym) {
char fullname[MAXSYMLEN + 1];
if (symName[0] == '.') { if (symName[0] == '.') {
if (!labelScope) if (!labelScope.has_value())
fatalerror("Local label reference '%s' in main scope\n", symName); fatalerror("Local label reference '%s' in main scope\n", symName);
fullSymbolName(fullname, sizeof(fullname), symName, labelScope); std::string fullName = *labelScope + symName;
symName = fullname;
sym = &createsymbol(fullName.c_str());
} else {
sym = &createsymbol(symName);
} }
sym = &createsymbol(symName);
sym->type = SYM_REF; sym->type = SYM_REF;
} }
@@ -656,6 +642,6 @@ void sym_Init(time_t now) {
#undef addString #undef addString
#undef addSym #undef addSym
sym_SetCurrentSymbolScope(nullptr); labelScope = std::nullopt;
anonLabelID = 0; anonLabelID = 0;
} }