mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 10:12:06 +00:00
Use std::string for symbol names
This commit is contained in:
@@ -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();
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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) {
|
||||||
// Write the char to the identifier's name
|
warning(WARNING_LONG_STR, "Symbol name too long, got truncated\n");
|
||||||
yylval.symName[i] = c;
|
break;
|
||||||
|
|
||||||
// If the char was a dot, mark the identifier as local
|
|
||||||
if (c == '.')
|
|
||||||
tokenType = T_(LOCAL_ID);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (i > sizeof(yylval.symName) - 1) {
|
// Write the char to the identifier's name
|
||||||
warning(WARNING_LONG_STR, "Symbol name too long, got truncated\n");
|
yylval += c;
|
||||||
i = sizeof(yylval.symName) - 1;
|
|
||||||
|
// 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
|
// 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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 §, FILE *f) {
|
static void writesection(Section const §, 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();
|
||||||
|
|
||||||
|
|||||||
126
src/asm/parser.y
126
src/asm/parser.y
@@ -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());
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,16 +429,16 @@ 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(symName);
|
return addLabel(fullName.c_str());
|
||||||
|
} else {
|
||||||
|
return addLabel(symName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a relocatable symbol
|
// Add a relocatable symbol
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user