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 "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();

View File

@@ -3,6 +3,7 @@
#ifndef RGBDS_SYMBOL_H
#define RGBDS_SYMBOL_H
#include <optional>
#include <stdint.h>
#include <string.h>
#include <string>
@@ -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<std::string> const &sym_GetCurrentSymbolScope();
void sym_SetCurrentSymbolScope(std::optional<std::string> const &newScope);
#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, "");
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;
}

View File

@@ -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<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(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<SymName>(token.value));
// `token` is either an `ID` or a `LOCAL_ID`, and both have a `std::string` value.
assert(std::holds_alternative<std::string>(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<SymName>(token.value).symName);
Symbol const *sym = sym_FindExactSymbol(
std::get<std::string>(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
}
}

View File

@@ -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 &sect, 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<uint32_t> const &nodeIters = node.iters();

View File

@@ -194,14 +194,14 @@
%token OP_CHARSUB "CHARSUB"
%token OP_INCHARMAP "INCHARMAP"
%token <SymName> LABEL "label"
%token <SymName> ID "identifier"
%token <SymName> LOCAL_ID "local identifier"
%token <SymName> ANON "anonymous label"
%type <SymName> def_id
%type <SymName> redef_id
%type <SymName> scoped_id
%type <SymName> scoped_anon_id
%token <std::string> LABEL "label"
%token <std::string> ID "identifier"
%token <std::string> LOCAL_ID "local identifier"
%token <std::string> ANON "anonymous label"
%type <std::string> def_id
%type <std::string> redef_id
%type <std::string> scoped_id
%type <std::string> 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());

View File

@@ -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);
}
}
}

View File

@@ -7,6 +7,7 @@
#include <deque>
#include <errno.h>
#include <inttypes.h>
#include <optional>
#include <stack>
#include <stdio.h>
#include <stdlib.h>
@@ -34,7 +35,7 @@ struct UnionStackEntry {
struct SectionStackEntry {
Section *section;
Section *loadSection;
char const *scope; // Section's symbol scope
std::optional<std::string> scope; // Section's symbol scope
uint32_t offset;
int32_t loadOffset;
std::stack<UnionStackEntry> unionStack;
@@ -46,7 +47,7 @@ std::deque<Section> 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<std::string> 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);
}

View File

@@ -8,6 +8,7 @@
#include <limits.h>
#include <map>
#include <new>
#include <optional>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
@@ -31,7 +32,7 @@
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 *_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<std::string> const &sym_GetCurrentSymbolScope() {
return labelScope;
}
void sym_SetCurrentSymbolScope(char const *newScope) {
void sym_SetCurrentSymbolScope(std::optional<std::string> 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;
}