Refactor structs to use methods instead of functions (#1322)

This commit is contained in:
Sylvie
2024-03-01 13:11:45 -05:00
committed by GitHub
parent e14ba664ea
commit 1ac3c0262f
18 changed files with 364 additions and 446 deletions

View File

@@ -15,7 +15,7 @@ enum FormatState {
FORMAT_INVALID, // got unexpected character FORMAT_INVALID, // got unexpected character
}; };
struct FormatSpec { class FormatSpec {
enum FormatState state; enum FormatState state;
int sign; int sign;
bool prefix; bool prefix;
@@ -26,15 +26,16 @@ struct FormatSpec {
size_t fracWidth; size_t fracWidth;
int type; int type;
bool valid; bool valid;
public:
bool isEmpty() const { return !state; }
bool isValid() const { return valid || state == FORMAT_DONE; }
bool isFinished() const { return state >= FORMAT_DONE;}
void useCharacter(int c);
void finishCharacters();
void printString(char *buf, size_t bufLen, char const *value);
void printNumber(char *buf, size_t bufLen, uint32_t value);
}; };
FormatSpec fmt_NewSpec();
bool fmt_IsEmpty(FormatSpec const *fmt);
bool fmt_IsValid(FormatSpec const *fmt);
bool fmt_IsFinished(FormatSpec const *fmt);
void fmt_UseCharacter(FormatSpec *fmt, int c);
void fmt_FinishCharacters(FormatSpec *fmt);
void fmt_PrintString(char *buf, size_t bufLen, FormatSpec const *fmt, char const *value);
void fmt_PrintNumber(char *buf, size_t bufLen, FormatSpec const *fmt, uint32_t value);
#endif // RGBDS_FORMAT_SPEC_H #endif // RGBDS_FORMAT_SPEC_H

View File

@@ -36,6 +36,8 @@ struct FileStackNode {
// File name for files, file::macro name for macros // File name for files, file::macro name for macros
std::string &name(); std::string &name();
std::string const &name() const; std::string const &name() const;
void dump(uint32_t curLineNo) const;
}; };
#define DEFAULT_MAX_DEPTH 64 #define DEFAULT_MAX_DEPTH 64
@@ -43,7 +45,6 @@ extern size_t maxRecursionDepth;
struct MacroArgs; struct MacroArgs;
void fstk_Dump(FileStackNode const *node, uint32_t lineNo);
void fstk_DumpCurrent(); void fstk_DumpCurrent();
FileStackNode *fstk_GetFileStack(); FileStackNode *fstk_GetFileStack();
// The lifetime of the returned chars is until reaching the end of that file // The lifetime of the returned chars is until reaching the end of that file

View File

@@ -5,18 +5,22 @@
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include <vector>
#include "asm/warning.hpp" #include "asm/warning.hpp"
#include "helpers.hpp" #include "helpers.hpp"
struct MacroArgs; struct MacroArgs {
unsigned int shift;
std::vector<char *> args;
void append(char *s);
void clear();
};
MacroArgs *macro_GetCurrentArgs(); MacroArgs *macro_GetCurrentArgs();
MacroArgs *macro_NewArgs();
void macro_AppendArg(MacroArgs *args, char *s);
void macro_UseNewArgs(MacroArgs *args); void macro_UseNewArgs(MacroArgs *args);
void macro_FreeArgs(MacroArgs *args);
char const *macro_GetArg(uint32_t i); char const *macro_GetArg(uint32_t i);
char const *macro_GetAllArgs(); char const *macro_GetAllArgs();

View File

@@ -13,29 +13,19 @@ struct Symbol;
struct Expression { struct Expression {
int32_t val; // If the expression's value is known, it's here int32_t val; // If the expression's value is known, it's here
std::string *reason; // Why the expression is not known, if it isn't std::string *reason; // Why the expression is not known, if it isn't
bool isKnown; // Whether the expression's value is known bool isKnown; // Whether the expression's value is known at assembly time
bool isSymbol; // Whether the expression represents a symbol bool isSymbol; // Whether the expression represents a symbol suitable for const diffing
std::vector<uint8_t> *rpn; // Bytes serializing the RPN expression std::vector<uint8_t> *rpn; // Bytes serializing the RPN expression
uint32_t rpnPatchSize; // Size the expression will take in the object file uint32_t rpnPatchSize; // Size the expression will take in the object file
int32_t getConstVal() const;
Symbol const *symbolOf() const;
bool isDiffConstant(Symbol const *symName) const;
}; };
// Determines if an expression is known at assembly time
static inline bool rpn_isKnown(Expression const *expr)
{
return expr->isKnown;
}
// Determines if an expression is a symbol suitable for const diffing
static inline bool rpn_isSymbol(const Expression *expr)
{
return expr->isSymbol;
}
void rpn_Symbol(Expression *expr, char const *symName); void rpn_Symbol(Expression *expr, char const *symName);
void rpn_Number(Expression *expr, uint32_t i); void rpn_Number(Expression *expr, uint32_t i);
void rpn_LOGNOT(Expression *expr, const Expression *src); void rpn_LOGNOT(Expression *expr, const Expression *src);
Symbol const *rpn_SymbolOf(Expression const *expr);
bool rpn_IsDiffConstant(Expression const *src, Symbol const *symName);
void rpn_BinaryOp(enum RPNCommand op, Expression *expr, const Expression *src1, const Expression *src2); void rpn_BinaryOp(enum RPNCommand op, Expression *expr, const Expression *src1, const Expression *src2);
void rpn_HIGH(Expression *expr, const Expression *src); void rpn_HIGH(Expression *expr, const Expression *src);
void rpn_LOW(Expression *expr, const Expression *src); void rpn_LOW(Expression *expr, const Expression *src);
@@ -49,10 +39,11 @@ void rpn_SizeOfSection(Expression *expr, char const *sectionName);
void rpn_StartOfSection(Expression *expr, char const *sectionName); void rpn_StartOfSection(Expression *expr, char const *sectionName);
void rpn_SizeOfSectionType(Expression *expr, enum SectionType type); void rpn_SizeOfSectionType(Expression *expr, enum SectionType type);
void rpn_StartOfSectionType(Expression *expr, enum SectionType type); void rpn_StartOfSectionType(Expression *expr, enum SectionType type);
void rpn_Free(Expression *expr); void rpn_Free(Expression *expr);
void rpn_CheckHRAM(Expression *expr, const Expression *src); void rpn_CheckHRAM(Expression *expr, const Expression *src);
void rpn_CheckRST(Expression *expr, const Expression *src); void rpn_CheckRST(Expression *expr, const Expression *src);
void rpn_CheckNBit(Expression const *expr, uint8_t n); void rpn_CheckNBit(Expression const *expr, uint8_t n);
int32_t rpn_GetConstVal(Expression const *expr);
#endif // RGBDS_ASM_RPN_H #endif // RGBDS_ASM_RPN_H

View File

@@ -8,7 +8,6 @@
#include <vector> #include <vector>
#include "linkdefs.hpp" #include "linkdefs.hpp"
#include "platform.hpp" // NONNULL
extern uint8_t fillByte; extern uint8_t fillByte;
@@ -39,6 +38,8 @@ struct Section {
uint16_t alignOfs; uint16_t alignOfs;
std::deque<Patch> patches; std::deque<Patch> patches;
std::vector<uint8_t> data; std::vector<uint8_t> data;
bool isSizeKnown() const;
}; };
struct SectionSpec { struct SectionSpec {
@@ -85,6 +86,4 @@ void sect_EndSection();
void sect_PushSection(); void sect_PushSection();
void sect_PopSection(); void sect_PopSection();
bool sect_IsSizeKnown(Section const NONNULL(name));
#endif // RGBDS_SECTION_H #endif // RGBDS_SECTION_H

View File

@@ -29,6 +29,9 @@ struct strValue {
char *value; char *value;
}; };
struct Symbol; // For the `sym_IsPC` forward declaration
bool sym_IsPC(Symbol const *sym); // For the inline `getSection` method
struct Symbol { struct Symbol {
char name[MAXSYMLEN + 1]; char name[MAXSYMLEN + 1];
enum SymbolType type; enum SymbolType type;
@@ -40,7 +43,7 @@ struct Symbol {
bool hasCallback; bool hasCallback;
union { union {
// If sym_IsNumeric // If isNumeric()
int32_t value; int32_t value;
int32_t (*numCallback)(); // If hasCallback int32_t (*numCallback)(); // If hasCallback
// For SYM_MACRO // For SYM_MACRO
@@ -51,61 +54,28 @@ struct Symbol {
}; };
uint32_t ID; // ID of the symbol in the object file (-1 if none) uint32_t ID; // ID of the symbol in the object file (-1 if none)
};
bool sym_IsPC(Symbol const *sym); bool isDefined() const { return type != SYM_REF; }
bool isNumeric() const { return type == SYM_LABEL || type == SYM_EQU || type == SYM_VAR; }
static inline bool sym_IsDefined(Symbol const *sym) bool isLabel() const { return type == SYM_LABEL || type == SYM_REF; }
{
return sym->type != SYM_REF;
}
static inline Section *sym_GetSection(Symbol const *sym)
{
return sym_IsPC(sym) ? sect_GetSymbolSection() : sym->section;
}
static inline bool sym_IsConstant(Symbol const *sym)
{
if (sym->type == SYM_LABEL) {
Section const *sect = sym_GetSection(sym);
bool isConstant() const {
if (type == SYM_LABEL) {
Section const *sect = getSection();
return sect && sect->org != (uint32_t)-1; return sect && sect->org != (uint32_t)-1;
} }
return sym->type == SYM_EQU || sym->type == SYM_VAR; return type == SYM_EQU || type == SYM_VAR;
} }
static inline bool sym_IsNumeric(Symbol const *sym) Section *getSection() const { return sym_IsPC(this) ? sect_GetSymbolSection() : section; }
{
return sym->type == SYM_LABEL || sym->type == SYM_EQU || sym->type == SYM_VAR;
}
static inline bool sym_IsLabel(Symbol const *sym) int32_t getValue() const;
{ uint32_t getConstantValue() const;
return sym->type == SYM_LABEL || sym->type == SYM_REF; char const *getStringValue() const { return hasCallback ? strCallback() : equs.value; }
} };
static inline bool sym_IsLocal(Symbol const *sym)
{
return sym_IsLabel(sym) && strchr(sym->name, '.');
}
static inline bool sym_IsExported(Symbol const *sym)
{
return sym->isExported;
}
// Get a string equate's value
static inline char const *sym_GetStringValue(Symbol const *sym)
{
if (sym->hasCallback)
return sym->strCallback();
return sym->equs.value;
}
void sym_ForEach(void (*func)(Symbol *)); void sym_ForEach(void (*func)(Symbol *));
int32_t sym_GetValue(Symbol const *sym);
void sym_SetExportAll(bool set); 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);
@@ -116,7 +86,6 @@ 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);
Symbol *sym_AddVar(char const *symName, int32_t value); Symbol *sym_AddVar(char const *symName, int32_t value);
uint32_t sym_GetPCValue(); uint32_t sym_GetPCValue();
uint32_t sym_GetConstantSymValue(Symbol const *sym);
uint32_t sym_GetConstantValue(char const *symName); uint32_t sym_GetConstantValue(char const *symName);
// Find a symbol by exact name, bypassing expansion checks // Find a symbol by exact name, bypassing expansion checks
Symbol *sym_FindExactSymbol(char const *symName); Symbol *sym_FindExactSymbol(char const *symName);

View File

@@ -30,6 +30,12 @@ extern bool beVerbose;
extern bool isWRAM0Mode; extern bool isWRAM0Mode;
extern bool disablePadding; extern bool disablePadding;
// Helper macro for printing verbose-mode messages
#define verbosePrint(...) do { \
if (beVerbose) \
fprintf(stderr, __VA_ARGS__); \
} while (0)
struct FileStackNode { struct FileStackNode {
FileStackNode *parent; FileStackNode *parent;
// Line at which the parent context was exited; meaningless for the root level // Line at which the parent context was exited; meaningless for the root level
@@ -48,24 +54,12 @@ struct FileStackNode {
// File name for files, file::macro name for macros // File name for files, file::macro name for macros
std::string &name(); std::string &name();
std::string const &name() const; std::string const &name() const;
std::string const *dumpFileStack() const;
}; };
// Helper macro for printing verbose-mode messages
#define verbosePrint(...) do { \
if (beVerbose) \
fprintf(stderr, __VA_ARGS__); \
} while (0)
/*
* Dump a file stack to stderr
* @param node The leaf node to dump the context of
*/
std::string const *dumpFileStack(FileStackNode const *node);
void warning(FileStackNode const *where, uint32_t lineNo, char const *fmt, ...) format_(printf, 3, 4); void warning(FileStackNode const *where, uint32_t lineNo, char const *fmt, ...) format_(printf, 3, 4);
void error(FileStackNode const *where, uint32_t lineNo, char const *fmt, ...) format_(printf, 3, 4); void error(FileStackNode const *where, uint32_t lineNo, char const *fmt, ...) format_(printf, 3, 4);
[[noreturn]] void fatal(FileStackNode const *where, uint32_t lineNo, char const *fmt, ...) format_(printf, 3, 4); [[noreturn]] void fatal(FileStackNode const *where, uint32_t lineNo, char const *fmt, ...) format_(printf, 3, 4);
#endif // RGBDS_LINK_MAIN_H #endif // RGBDS_LINK_MAIN_H

View File

@@ -12,63 +12,41 @@
#include "asm/format.hpp" #include "asm/format.hpp"
#include "asm/warning.hpp" #include "asm/warning.hpp"
FormatSpec fmt_NewSpec() void FormatSpec::useCharacter(int c)
{ {
FormatSpec fmt = {}; if (state == FORMAT_INVALID)
return fmt;
}
bool fmt_IsEmpty(FormatSpec const *fmt)
{
return !fmt->state;
}
bool fmt_IsValid(FormatSpec const *fmt)
{
return fmt->valid || fmt->state == FORMAT_DONE;
}
bool fmt_IsFinished(FormatSpec const *fmt)
{
return fmt->state >= FORMAT_DONE;
}
void fmt_UseCharacter(FormatSpec *fmt, int c)
{
if (fmt->state == FORMAT_INVALID)
return; return;
switch (c) { switch (c) {
// sign // sign
case ' ': case ' ':
case '+': case '+':
if (fmt->state > FORMAT_SIGN) if (state > FORMAT_SIGN)
goto invalid; goto invalid;
fmt->state = FORMAT_PREFIX; state = FORMAT_PREFIX;
fmt->sign = c; sign = c;
break; break;
// prefix // prefix
case '#': case '#':
if (fmt->state > FORMAT_PREFIX) if (state > FORMAT_PREFIX)
goto invalid; goto invalid;
fmt->state = FORMAT_ALIGN; state = FORMAT_ALIGN;
fmt->prefix = true; prefix = true;
break; break;
// align // align
case '-': case '-':
if (fmt->state > FORMAT_ALIGN) if (state > FORMAT_ALIGN)
goto invalid; goto invalid;
fmt->state = FORMAT_WIDTH; state = FORMAT_WIDTH;
fmt->alignLeft = true; alignLeft = true;
break; break;
// pad and width // pad and width
case '0': case '0':
if (fmt->state < FORMAT_WIDTH) if (state < FORMAT_WIDTH)
fmt->padZero = true; padZero = true;
// fallthrough // fallthrough
case '1': case '1':
case '2': case '2':
@@ -79,23 +57,23 @@ void fmt_UseCharacter(FormatSpec *fmt, int c)
case '7': case '7':
case '8': case '8':
case '9': case '9':
if (fmt->state < FORMAT_WIDTH) { if (state < FORMAT_WIDTH) {
fmt->state = FORMAT_WIDTH; state = FORMAT_WIDTH;
fmt->width = c - '0'; width = c - '0';
} else if (fmt->state == FORMAT_WIDTH) { } else if (state == FORMAT_WIDTH) {
fmt->width = fmt->width * 10 + (c - '0'); width = width * 10 + (c - '0');
} else if (fmt->state == FORMAT_FRAC) { } else if (state == FORMAT_FRAC) {
fmt->fracWidth = fmt->fracWidth * 10 + (c - '0'); fracWidth = fracWidth * 10 + (c - '0');
} else { } else {
goto invalid; goto invalid;
} }
break; break;
case '.': case '.':
if (fmt->state > FORMAT_WIDTH) if (state > FORMAT_WIDTH)
goto invalid; goto invalid;
fmt->state = FORMAT_FRAC; state = FORMAT_FRAC;
fmt->hasFrac = true; hasFrac = true;
break; break;
// type // type
@@ -107,41 +85,46 @@ void fmt_UseCharacter(FormatSpec *fmt, int c)
case 'o': case 'o':
case 'f': case 'f':
case 's': case 's':
if (fmt->state >= FORMAT_DONE) if (state >= FORMAT_DONE)
goto invalid; goto invalid;
fmt->state = FORMAT_DONE; state = FORMAT_DONE;
fmt->valid = true; valid = true;
fmt->type = c; type = c;
break; break;
default: default:
invalid: invalid:
fmt->state = FORMAT_INVALID; state = FORMAT_INVALID;
fmt->valid = false; valid = false;
} }
} }
void fmt_FinishCharacters(FormatSpec *fmt) void FormatSpec::finishCharacters()
{ {
if (!fmt_IsValid(fmt)) if (!isValid())
fmt->state = FORMAT_INVALID; state = FORMAT_INVALID;
} }
void fmt_PrintString(char *buf, size_t bufLen, FormatSpec const *fmt, char const *value) void FormatSpec::printString(char *buf, size_t bufLen, char const *value)
{ {
if (fmt->sign) if (isEmpty()) {
error("Formatting string with sign flag '%c'\n", fmt->sign); // No format was specified
if (fmt->prefix) type = 's';
}
if (sign)
error("Formatting string with sign flag '%c'\n", sign);
if (prefix)
error("Formatting string with prefix flag '#'\n"); error("Formatting string with prefix flag '#'\n");
if (fmt->padZero) if (padZero)
error("Formatting string with padding flag '0'\n"); error("Formatting string with padding flag '0'\n");
if (fmt->hasFrac) if (hasFrac)
error("Formatting string with fractional width\n"); error("Formatting string with fractional width\n");
if (fmt->type != 's') if (type != 's')
error("Formatting string as type '%c'\n", fmt->type); error("Formatting string as type '%c'\n", type);
size_t len = strlen(value); size_t len = strlen(value);
size_t totalLen = fmt->width > len ? fmt->width : len; size_t totalLen = width > len ? width : len;
if (totalLen > bufLen - 1) { // bufLen includes terminator if (totalLen > bufLen - 1) { // bufLen includes terminator
error("Formatted string value too long\n"); error("Formatted string value too long\n");
@@ -153,7 +136,7 @@ void fmt_PrintString(char *buf, size_t bufLen, FormatSpec const *fmt, char const
size_t padLen = totalLen - len; size_t padLen = totalLen - len;
if (fmt->alignLeft) { if (alignLeft) {
memcpy(buf, value, len); memcpy(buf, value, len);
for (size_t i = len; i < totalLen; i++) for (size_t i = len; i < totalLen; i++)
buf[i] = ' '; buf[i] = ' ';
@@ -166,37 +149,42 @@ void fmt_PrintString(char *buf, size_t bufLen, FormatSpec const *fmt, char const
buf[totalLen] = '\0'; buf[totalLen] = '\0';
} }
void fmt_PrintNumber(char *buf, size_t bufLen, FormatSpec const *fmt, uint32_t value) void FormatSpec::printNumber(char *buf, size_t bufLen, uint32_t value)
{ {
if (fmt->type != 'X' && fmt->type != 'x' && fmt->type != 'b' && fmt->type != 'o' if (isEmpty()) {
&& fmt->prefix) // No format was specified; default to uppercase $hex
error("Formatting type '%c' with prefix flag '#'\n", fmt->type); type = 'X';
if (fmt->type != 'f' && fmt->hasFrac) prefix = true;
error("Formatting type '%c' with fractional width\n", fmt->type); }
if (fmt->type == 's')
if (type != 'X' && type != 'x' && type != 'b' && type != 'o' && prefix)
error("Formatting type '%c' with prefix flag '#'\n", type);
if (type != 'f' && hasFrac)
error("Formatting type '%c' with fractional width\n", type);
if (type == 's')
error("Formatting number as type 's'\n"); error("Formatting number as type 's'\n");
char sign = fmt->sign; // 0 or ' ' or '+' char signChar = sign; // 0 or ' ' or '+'
if (fmt->type == 'd' || fmt->type == 'f') { if (type == 'd' || type == 'f') {
int32_t v = value; int32_t v = value;
if (v < 0 && v != INT32_MIN) { if (v < 0 && v != INT32_MIN) {
sign = '-'; signChar = '-';
value = -v; value = -v;
} }
} }
char prefix = !fmt->prefix ? 0 char prefixChar = !prefix ? 0
: fmt->type == 'X' ? '$' : type == 'X' ? '$'
: fmt->type == 'x' ? '$' : type == 'x' ? '$'
: fmt->type == 'b' ? '%' : type == 'b' ? '%'
: fmt->type == 'o' ? '&' : type == 'o' ? '&'
: 0; : 0;
char valueBuf[262]; // Max 5 digits + decimal + 255 fraction digits + terminator char valueBuf[262]; // Max 5 digits + decimal + 255 fraction digits + terminator
if (fmt->type == 'b') { if (type == 'b') {
// Special case for binary // Special case for binary
char *ptr = valueBuf; char *ptr = valueBuf;
@@ -216,34 +204,33 @@ void fmt_PrintNumber(char *buf, size_t bufLen, FormatSpec const *fmt, uint32_t v
valueBuf[i] = valueBuf[j]; valueBuf[i] = valueBuf[j];
valueBuf[j] = c; valueBuf[j] = c;
} }
} else if (fmt->type == 'f') { } else if (type == 'f') {
// Special case for fixed-point // Special case for fixed-point
// Default fractional width (C++'s is 6 for "%f"; here 5 is enough for Q16.16) // Default fractional width (C++'s is 6 for "%f"; here 5 is enough for Q16.16)
size_t fracWidth = fmt->hasFrac ? fmt->fracWidth : 5; size_t cappedFracWidth = hasFrac ? fracWidth : 5;
if (fracWidth > 255) { if (cappedFracWidth > 255) {
error("Fractional width %zu too long, limiting to 255\n", error("Fractional width %zu too long, limiting to 255\n", cappedFracWidth);
fracWidth); cappedFracWidth = 255;
fracWidth = 255;
} }
snprintf(valueBuf, sizeof(valueBuf), "%.*f", (int)fracWidth, snprintf(valueBuf, sizeof(valueBuf), "%.*f", (int)cappedFracWidth,
value / fix_PrecisionFactor()); value / fix_PrecisionFactor());
} else { } else {
char const *spec = fmt->type == 'd' ? "%" PRId32 char const *spec = type == 'd' ? "%" PRId32
: fmt->type == 'u' ? "%" PRIu32 : type == 'u' ? "%" PRIu32
: fmt->type == 'X' ? "%" PRIX32 : type == 'X' ? "%" PRIX32
: fmt->type == 'x' ? "%" PRIx32 : type == 'x' ? "%" PRIx32
: fmt->type == 'o' ? "%" PRIo32 : type == 'o' ? "%" PRIo32
: "%" PRId32; : "%" PRId32;
snprintf(valueBuf, sizeof(valueBuf), spec, value); snprintf(valueBuf, sizeof(valueBuf), spec, value);
} }
size_t len = strlen(valueBuf); size_t len = strlen(valueBuf);
size_t numLen = (sign != 0) + (prefix != 0) + len; size_t numLen = (signChar != 0) + (prefixChar != 0) + len;
size_t totalLen = fmt->width > numLen ? fmt->width : numLen; size_t totalLen = width > numLen ? width : numLen;
if (totalLen > bufLen - 1) { // bufLen includes terminator if (totalLen > bufLen - 1) { // bufLen includes terminator
error("Formatted numeric value too long\n"); error("Formatted numeric value too long\n");
@@ -258,31 +245,31 @@ void fmt_PrintNumber(char *buf, size_t bufLen, FormatSpec const *fmt, uint32_t v
size_t padLen = totalLen - numLen; size_t padLen = totalLen - numLen;
size_t pos = 0; size_t pos = 0;
if (fmt->alignLeft) { if (alignLeft) {
if (sign) if (signChar)
buf[pos++] = sign; buf[pos++] = signChar;
if (prefix) if (prefixChar)
buf[pos++] = prefix; buf[pos++] = prefixChar;
memcpy(buf + pos, valueBuf, len); memcpy(buf + pos, valueBuf, len);
for (size_t i = pos + len; i < totalLen; i++) for (size_t i = pos + len; i < totalLen; i++)
buf[i] = ' '; buf[i] = ' ';
} else { } else {
if (fmt->padZero) { if (padZero) {
// sign, then prefix, then zero padding // sign, then prefix, then zero padding
if (sign) if (signChar)
buf[pos++] = sign; buf[pos++] = signChar;
if (prefix) if (prefixChar)
buf[pos++] = prefix; buf[pos++] = prefixChar;
for (size_t i = 0; i < padLen; i++) for (size_t i = 0; i < padLen; i++)
buf[pos++] = '0'; buf[pos++] = '0';
} else { } else {
// space padding, then sign, then prefix // space padding, then sign, then prefix
for (size_t i = 0; i < padLen; i++) for (size_t i = 0; i < padLen; i++)
buf[pos++] = ' '; buf[pos++] = ' ';
if (sign) if (signChar)
buf[pos++] = sign; buf[pos++] = signChar;
if (prefix) if (prefixChar)
buf[pos++] = prefix; buf[pos++] = prefixChar;
} }
memcpy(buf + pos, valueBuf, len); memcpy(buf + pos, valueBuf, len);
} }

View File

@@ -42,6 +42,26 @@ static std::vector<std::string> includePaths = { "" };
static const char *preIncludeName; static const char *preIncludeName;
std::vector<uint32_t> &FileStackNode::iters() {
assert(std::holds_alternative<std::vector<uint32_t>>(data));
return std::get<std::vector<uint32_t>>(data);
}
std::vector<uint32_t> const &FileStackNode::iters() const {
assert(std::holds_alternative<std::vector<uint32_t>>(data));
return std::get<std::vector<uint32_t>>(data);
}
std::string &FileStackNode::name() {
assert(std::holds_alternative<std::string>(data));
return std::get<std::string>(data);
}
std::string const &FileStackNode::name() const {
assert(std::holds_alternative<std::string>(data));
return std::get<std::string>(data);
}
static const char *dumpNodeAndParents(FileStackNode const *node) static const char *dumpNodeAndParents(FileStackNode const *node)
{ {
char const *name; char const *name;
@@ -66,30 +86,10 @@ static const char *dumpNodeAndParents(FileStackNode const *node)
return name; return name;
} }
std::vector<uint32_t> &FileStackNode::iters() { void FileStackNode::dump(uint32_t curLineNo) const
assert(std::holds_alternative<std::vector<uint32_t>>(data));
return std::get<std::vector<uint32_t>>(data);
}
std::vector<uint32_t> const &FileStackNode::iters() const {
assert(std::holds_alternative<std::vector<uint32_t>>(data));
return std::get<std::vector<uint32_t>>(data);
}
std::string &FileStackNode::name() {
assert(std::holds_alternative<std::string>(data));
return std::get<std::string>(data);
}
std::string const &FileStackNode::name() const {
assert(std::holds_alternative<std::string>(data));
return std::get<std::string>(data);
}
void fstk_Dump(FileStackNode const *node, uint32_t lineNo)
{ {
dumpNodeAndParents(node); dumpNodeAndParents(this);
fprintf(stderr, "(%" PRIu32 ")", lineNo); fprintf(stderr, "(%" PRIu32 ")", curLineNo);
} }
void fstk_DumpCurrent() void fstk_DumpCurrent()
@@ -98,7 +98,7 @@ void fstk_DumpCurrent()
fputs("at top level", stderr); fputs("at top level", stderr);
return; return;
} }
fstk_Dump(contextStack.top().fileInfo, lexer_GetLineNo()); contextStack.top().fileInfo->dump(lexer_GetLineNo());
} }
FileStackNode *fstk_GetFileStack() FileStackNode *fstk_GetFileStack()
@@ -240,7 +240,7 @@ bool yywrap()
lexer_CleanupState(oldContext.lexerState); lexer_CleanupState(oldContext.lexerState);
// Restore args if a macro (not REPT) saved them // Restore args if a macro (not REPT) saved them
if (oldContext.fileInfo->type == NODE_MACRO) { if (oldContext.fileInfo->type == NODE_MACRO) {
macro_FreeArgs(macro_GetCurrentArgs()); macro_GetCurrentArgs()->clear();
macro_UseNewArgs(contextStack.top().macroArgs); macro_UseNewArgs(contextStack.top().macroArgs);
} }
// Free the file stack node // Free the file stack node

View File

@@ -579,12 +579,12 @@ static uint32_t readBracketedMacroArgNum()
error("Bracketed symbol \"%s\" does not exist\n", symName); error("Bracketed symbol \"%s\" does not exist\n", symName);
num = 0; num = 0;
symbolError = true; symbolError = true;
} else if (!sym_IsNumeric(sym)) { } else if (!sym->isNumeric()) {
error("Bracketed symbol \"%s\" is not numeric\n", symName); error("Bracketed symbol \"%s\" is not numeric\n", symName);
num = 0; num = 0;
symbolError = true; symbolError = true;
} else { } else {
num = sym_GetConstantSymValue(sym); num = sym->getConstantValue();
} }
} else { } else {
empty = true; empty = true;
@@ -1184,7 +1184,7 @@ static char const *readInterpolation(size_t depth)
char symName[MAXSYMLEN + 1]; char symName[MAXSYMLEN + 1];
size_t i = 0; size_t i = 0;
FormatSpec fmt = fmt_NewSpec(); FormatSpec fmt{};
bool disableInterpolation = lexerState->disableInterpolation; bool disableInterpolation = lexerState->disableInterpolation;
// In a context where `lexerState->disableInterpolation` is true, `peek` will expand // In a context where `lexerState->disableInterpolation` is true, `peek` will expand
@@ -1208,7 +1208,7 @@ static char const *readInterpolation(size_t depth)
} else if (c == '}') { } else if (c == '}') {
shiftChar(); shiftChar();
break; break;
} else if (c == ':' && !fmt_IsFinished(&fmt)) { // Format spec, only once } else if (c == ':' && !fmt.isFinished()) { // Format spec, only once
shiftChar(); shiftChar();
if (i == sizeof(symName)) { if (i == sizeof(symName)) {
warning(WARNING_LONG_STR, "Format spec too long, got truncated\n"); warning(WARNING_LONG_STR, "Format spec too long, got truncated\n");
@@ -1216,9 +1216,9 @@ static char const *readInterpolation(size_t depth)
} }
symName[i] = '\0'; symName[i] = '\0';
for (size_t j = 0; j < i; j++) for (size_t j = 0; j < i; j++)
fmt_UseCharacter(&fmt, symName[j]); fmt.useCharacter(symName[j]);
fmt_FinishCharacters(&fmt); fmt.finishCharacters();
if (!fmt_IsValid(&fmt)) if (!fmt.isValid())
error("Invalid format spec '%s'\n", symName); error("Invalid format spec '%s'\n", symName);
i = 0; // Now that format has been set, restart at beginning of string i = 0; // Now that format has been set, restart at beginning of string
} else { } else {
@@ -1244,18 +1244,10 @@ static char const *readInterpolation(size_t depth)
if (!sym) { if (!sym) {
error("Interpolated symbol \"%s\" does not exist\n", symName); error("Interpolated symbol \"%s\" does not exist\n", symName);
} else if (sym->type == SYM_EQUS) { } else if (sym->type == SYM_EQUS) {
if (fmt_IsEmpty(&fmt)) fmt.printString(buf, sizeof(buf), sym->getStringValue());
// No format was specified
fmt.type = 's';
fmt_PrintString(buf, sizeof(buf), &fmt, sym_GetStringValue(sym));
return buf; return buf;
} else if (sym_IsNumeric(sym)) { } else if (sym->isNumeric()) {
if (fmt_IsEmpty(&fmt)) { fmt.printNumber(buf, sizeof(buf), sym->getConstantValue());
// No format was specified; default to uppercase $hex
fmt.type = 'X';
fmt.prefix = true;
}
fmt_PrintNumber(buf, sizeof(buf), &fmt, sym_GetConstantSymValue(sym));
return buf; return buf;
} else { } else {
error("Only numerical and string symbols can be interpolated\n"); error("Only numerical and string symbols can be interpolated\n");
@@ -1884,7 +1876,7 @@ static int yylex_NORMAL()
Symbol const *sym = sym_FindExactSymbol(yylval.symName); Symbol const *sym = sym_FindExactSymbol(yylval.symName);
if (sym && sym->type == SYM_EQUS) { if (sym && sym->type == SYM_EQUS) {
char const *s = sym_GetStringValue(sym); char const *s = sym->getStringValue();
assert(s); assert(s);
if (s[0]) if (s[0])

View File

@@ -13,11 +13,6 @@
#define MAXMACROARGS 99999 #define MAXMACROARGS 99999
struct MacroArgs {
unsigned int shift;
std::vector<char *> args;
};
static MacroArgs *macroArgs = nullptr; static MacroArgs *macroArgs = nullptr;
static uint32_t uniqueID = 0; static uint32_t uniqueID = 0;
static uint32_t maxUniqueID = 0; static uint32_t maxUniqueID = 0;
@@ -27,42 +22,31 @@ static uint32_t maxUniqueID = 0;
static char uniqueIDBuf[] = "_u4294967295"; // UINT32_MAX static char uniqueIDBuf[] = "_u4294967295"; // UINT32_MAX
static char *uniqueIDPtr = nullptr; static char *uniqueIDPtr = nullptr;
void MacroArgs::append(char *s)
{
if (s[0] == '\0')
warning(WARNING_EMPTY_MACRO_ARG, "Empty macro argument\n");
if (args.size() == MAXMACROARGS)
error("A maximum of " EXPAND_AND_STR(MAXMACROARGS) " arguments is allowed\n");
args.push_back(s);
}
void MacroArgs::clear()
{
for (char *arg : args)
free(arg);
}
MacroArgs *macro_GetCurrentArgs() MacroArgs *macro_GetCurrentArgs()
{ {
return macroArgs; return macroArgs;
} }
MacroArgs *macro_NewArgs()
{
MacroArgs *args = new(std::nothrow) MacroArgs();
if (!args)
fatalerror("Unable to register macro arguments: %s\n", strerror(errno));
args->shift = 0;
return args;
}
void macro_AppendArg(MacroArgs *args, char *s)
{
if (s[0] == '\0')
warning(WARNING_EMPTY_MACRO_ARG, "Empty macro argument\n");
if (args->args.size() == MAXMACROARGS)
error("A maximum of " EXPAND_AND_STR(MAXMACROARGS) " arguments is allowed\n");
args->args.push_back(s);
}
void macro_UseNewArgs(MacroArgs *args) void macro_UseNewArgs(MacroArgs *args)
{ {
macroArgs = args; macroArgs = args;
} }
void macro_FreeArgs(MacroArgs *args)
{
for (char *arg : args->args)
free(arg);
}
char const *macro_GetArg(uint32_t i) char const *macro_GetArg(uint32_t i)
{ {
if (!macroArgs) if (!macroArgs)

View File

@@ -142,7 +142,7 @@ static void writesection(Section const &sect, FILE *f)
static void writesymbol(Symbol const *sym, FILE *f) static void writesymbol(Symbol const *sym, FILE *f)
{ {
putstring(sym->name, f); putstring(sym->name, f);
if (!sym_IsDefined(sym)) { if (!sym->isDefined()) {
putc(SYMTYPE_IMPORT, f); putc(SYMTYPE_IMPORT, f);
} else { } else {
assert(sym->src->ID != (uint32_t)-1); assert(sym->src->ID != (uint32_t)-1);
@@ -150,7 +150,7 @@ static void writesymbol(Symbol const *sym, FILE *f)
putc(sym->isExported ? SYMTYPE_EXPORT : SYMTYPE_LOCAL, f); putc(sym->isExported ? SYMTYPE_EXPORT : SYMTYPE_LOCAL, f);
putlong(sym->src->ID, f); putlong(sym->src->ID, f);
putlong(sym->fileLine, f); putlong(sym->fileLine, f);
putlong(getSectIDIfAny(sym_GetSection(sym)), f); putlong(getSectIDIfAny(sym->getSection()), f);
putlong(sym->value, f); putlong(sym->value, f);
} }
} }
@@ -203,7 +203,7 @@ static void writerpn(std::vector<uint8_t> &rpnexpr, const std::vector<uint8_t> &
// The symbol name is always written expanded // The symbol name is always written expanded
sym = sym_FindExactSymbol(symName); sym = sym_FindExactSymbol(symName);
if (sym_IsConstant(sym)) { if (sym->isConstant()) {
writebyte(RPN_CONST); writebyte(RPN_CONST);
value = sym_GetConstantValue(symName); value = sym_GetConstantValue(symName);
} else { } else {
@@ -280,7 +280,7 @@ static void initpatch(Patch &patch, uint32_t type, Expression const *expr, uint3
patch.pcSection = sect_GetSymbolSection(); patch.pcSection = sect_GetSymbolSection();
patch.pcOffset = sect_GetSymbolOffset(); patch.pcOffset = sect_GetSymbolOffset();
if (rpn_isKnown(expr)) { if (expr->isKnown) {
// If the RPN expr's value is known, output a constant directly // If the RPN expr's value is known, output a constant directly
patch.rpn.resize(5); patch.rpn.resize(5);
patch.rpn[0] = RPN_CONST; patch.rpn[0] = RPN_CONST;

View File

@@ -71,7 +71,7 @@
char const *rep); char const *rep);
static void initStrFmtArgList(StrFmtArgList *args); static void initStrFmtArgList(StrFmtArgList *args);
static void freeStrFmtArgList(StrFmtArgList *args); static void freeStrFmtArgList(StrFmtArgList *args);
static void strfmt(char *dest, size_t destLen, char const *fmt, static void strfmt(char *dest, size_t destLen, char const *spec,
std::vector<std::variant<uint32_t, char *>> &args); std::vector<std::variant<uint32_t, char *>> &args);
static void compoundAssignment(const char *symName, enum RPNCommand op, int32_t constValue); static void compoundAssignment(const char *symName, enum RPNCommand op, int32_t constValue);
static void initDsArgList(std::vector<Expression> *&args); static void initDsArgList(std::vector<Expression> *&args);
@@ -503,10 +503,14 @@ macro : T_ID {
; ;
macroargs : %empty { macroargs : %empty {
$$ = macro_NewArgs(); $$ = new(std::nothrow) MacroArgs();
if (!$$)
fatalerror("Failed to allocate memory for macro arguments: %s\n",
strerror(errno));
$$->shift = 0;
} }
| macroargs T_STRING { | macroargs T_STRING {
macro_AppendArg($$, strdup($2)); $$->append(strdup($2));
} }
; ;
@@ -705,7 +709,7 @@ assert_type : %empty { $$ = ASSERT_ERROR; }
; ;
assert : T_POP_ASSERT assert_type relocexpr { assert : T_POP_ASSERT assert_type relocexpr {
if (!rpn_isKnown(&$3)) { if (!$3.isKnown) {
out_CreateAssert($2, &$3, "", sect_GetOutputOffset()); out_CreateAssert($2, &$3, "", sect_GetOutputOffset());
} else if ($3.val == 0) { } else if ($3.val == 0) {
failAssert($2); failAssert($2);
@@ -713,7 +717,7 @@ assert : T_POP_ASSERT assert_type relocexpr {
rpn_Free(&$3); rpn_Free(&$3);
} }
| T_POP_ASSERT assert_type relocexpr T_COMMA string { | T_POP_ASSERT assert_type relocexpr T_COMMA string {
if (!rpn_isKnown(&$3)) { if (!$3.isKnown) {
out_CreateAssert($2, &$3, $5, sect_GetOutputOffset()); out_CreateAssert($2, &$3, $5, sect_GetOutputOffset());
} else if ($3.val == 0) { } else if ($3.val == 0) {
failAssertMsg($2, $5); failAssertMsg($2, $5);
@@ -1256,13 +1260,13 @@ uconst : const {
} }
; ;
const : relocexpr { $$ = rpn_GetConstVal(&$1); } const : relocexpr { $$ = $1.getConstVal(); }
; ;
const_no_str : relocexpr_no_str { $$ = rpn_GetConstVal(&$1); } const_no_str : relocexpr_no_str { $$ = $1.getConstVal(); }
; ;
const_8bit : reloc_8bit { $$ = rpn_GetConstVal(&$1); } const_8bit : reloc_8bit { $$ = $1.getConstVal(); }
; ;
opt_q_arg : %empty { $$ = fix_Precision(); } opt_q_arg : %empty { $$ = fix_Precision(); }
@@ -1319,7 +1323,7 @@ string : T_STRING
if (!sym) if (!sym)
fatalerror("Unknown symbol \"%s\"\n", $3); fatalerror("Unknown symbol \"%s\"\n", $3);
Section const *section = sym_GetSection(sym); 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);
@@ -1605,7 +1609,7 @@ z80_ldio : T_Z80_LDH T_MODE_A T_COMMA op_mem_ind {
c_ind : T_LBRACK T_MODE_C T_RBRACK c_ind : T_LBRACK T_MODE_C T_RBRACK
| T_LBRACK relocexpr T_OP_ADD T_MODE_C T_RBRACK { | T_LBRACK relocexpr T_OP_ADD T_MODE_C T_RBRACK {
if (!rpn_isKnown(&$2) || $2.val != 0xFF00) if (!$2.isKnown || $2.val != 0xFF00)
error("Expected constant expression equal to $FF00 for \"$ff00+c\"\n"); error("Expected constant expression equal to $FF00 for \"$ff00+c\"\n");
} }
; ;
@@ -1642,7 +1646,7 @@ z80_ld_mem : T_Z80_LD op_mem_ind T_COMMA T_MODE_SP {
sect_RelWord(&$2, 1); sect_RelWord(&$2, 1);
} }
| T_Z80_LD op_mem_ind T_COMMA T_MODE_A { | T_Z80_LD op_mem_ind T_COMMA T_MODE_A {
if (optimizeLoads && rpn_isKnown(&$2) if (optimizeLoads && $2.isKnown
&& $2.val >= 0xFF00) { && $2.val >= 0xFF00) {
if (warnOnLdOpt) { if (warnOnLdOpt) {
warnOnLdOpt = false; warnOnLdOpt = false;
@@ -1695,8 +1699,7 @@ z80_ld_a : T_Z80_LD reg_r T_COMMA c_ind {
} }
| T_Z80_LD reg_r T_COMMA op_mem_ind { | T_Z80_LD reg_r T_COMMA op_mem_ind {
if ($2 == REG_A) { if ($2 == REG_A) {
if (optimizeLoads && rpn_isKnown(&$4) if (optimizeLoads && $4.isKnown && $4.val >= 0xFF00) {
&& $4.val >= 0xFF00) {
if (warnOnLdOpt) { if (warnOnLdOpt) {
warnOnLdOpt = false; warnOnLdOpt = false;
warning(WARNING_OBSOLETE, warning(WARNING_OBSOLETE,
@@ -1795,7 +1798,7 @@ z80_rrca : T_Z80_RRCA { sect_AbsByte(0x0F); }
z80_rst : T_Z80_RST reloc_8bit { z80_rst : T_Z80_RST reloc_8bit {
rpn_CheckRST(&$2, &$2); rpn_CheckRST(&$2, &$2);
if (!rpn_isKnown(&$2)) if (!$2.isKnown)
sect_RelByte(&$2, 0); sect_RelByte(&$2, 0);
else else
sect_AbsByte(0xC7 | $2.val); sect_AbsByte(0xC7 | $2.val);
@@ -2197,14 +2200,14 @@ static void freeStrFmtArgList(StrFmtArgList *args)
delete args->args; delete args->args;
} }
static void strfmt(char *dest, size_t destLen, char const *fmt, static void strfmt(char *dest, size_t destLen, char const *spec,
std::vector<std::variant<uint32_t, char *>> &args) std::vector<std::variant<uint32_t, char *>> &args)
{ {
size_t a = 0; size_t a = 0;
size_t i = 0; size_t i = 0;
while (i < destLen) { while (i < destLen) {
int c = *fmt++; int c = *spec++;
if (c == '\0') { if (c == '\0') {
break; break;
@@ -2213,27 +2216,27 @@ static void strfmt(char *dest, size_t destLen, char const *fmt,
continue; continue;
} }
c = *fmt++; c = *spec++;
if (c == '%') { if (c == '%') {
dest[i++] = c; dest[i++] = c;
continue; continue;
} }
FormatSpec spec = fmt_NewSpec(); FormatSpec fmt{};
while (c != '\0') { while (c != '\0') {
fmt_UseCharacter(&spec, c); fmt.useCharacter(c);
if (fmt_IsFinished(&spec)) if (fmt.isFinished())
break; break;
c = *fmt++; c = *spec++;
} }
if (fmt_IsEmpty(&spec)) { if (fmt.isEmpty()) {
error("STRFMT: Illegal '%%' at end of format string\n"); error("STRFMT: Illegal '%%' at end of format string\n");
dest[i++] = '%'; dest[i++] = '%';
break; break;
} else if (!fmt_IsValid(&spec)) { } else if (!fmt.isValid()) {
error("STRFMT: Invalid format spec for argument %zu\n", a + 1); error("STRFMT: Invalid format spec for argument %zu\n", a + 1);
dest[i++] = '%'; dest[i++] = '%';
a++; a++;
@@ -2249,8 +2252,8 @@ static void strfmt(char *dest, size_t destLen, char const *fmt,
static char buf[MAXSTRLEN + 1]; static char buf[MAXSTRLEN + 1];
std::visit(Visitor{ std::visit(Visitor{
[&](uint32_t num) { fmt_PrintNumber(buf, sizeof(buf), &spec, num); }, [&](uint32_t num) { fmt.printNumber(buf, sizeof(buf), num); },
[&](char *str) { fmt_PrintString(buf, sizeof(buf), &spec, str); }, [&](char *str) { fmt.printString(buf, sizeof(buf), str); },
}, arg); }, arg);
i += snprintf(&dest[i], destLen - i, "%s", buf); i += snprintf(&dest[i], destLen - i, "%s", buf);
@@ -2277,7 +2280,7 @@ static void compoundAssignment(const char *symName, enum RPNCommand op, int32_t
rpn_Symbol(&oldExpr, symName); rpn_Symbol(&oldExpr, symName);
rpn_Number(&constExpr, constValue); rpn_Number(&constExpr, constValue);
rpn_BinaryOp(op, &newExpr, &oldExpr, &constExpr); rpn_BinaryOp(op, &newExpr, &oldExpr, &constExpr);
newValue = rpn_GetConstVal(&newExpr); newValue = newExpr.getConstVal();
sym_AddVar(symName, newValue); sym_AddVar(symName, newValue);
} }

View File

@@ -21,6 +21,16 @@
#include "opmath.hpp" #include "opmath.hpp"
// Init a RPN expression
static void initExpression(Expression *expr)
{
expr->reason = nullptr;
expr->isKnown = true;
expr->isSymbol = false;
expr->rpn = nullptr;
expr->rpnPatchSize = 0;
}
// Makes an expression "not known", also setting its error message // Makes an expression "not known", also setting its error message
template<typename... Ts> template<typename... Ts>
static void makeUnknown(Expression *expr, Ts ...parts) static void makeUnknown(Expression *expr, Ts ...parts)
@@ -46,28 +56,18 @@ static uint8_t *reserveSpace(Expression *expr, uint32_t size)
return &(*expr->rpn)[curSize]; return &(*expr->rpn)[curSize];
} }
// Init a RPN expression
static void rpn_Init(Expression *expr)
{
expr->reason = nullptr;
expr->isKnown = true;
expr->isSymbol = false;
expr->rpn = nullptr;
expr->rpnPatchSize = 0;
}
// Free the RPN expression // Free the RPN expression
void rpn_Free(Expression *expr) void rpn_Free(Expression *expr)
{ {
delete expr->rpn; delete expr->rpn;
delete expr->reason; delete expr->reason;
rpn_Init(expr); initExpression(expr);
} }
// Add symbols, constants and operators to expression // Add symbols, constants and operators to expression
void rpn_Number(Expression *expr, uint32_t i) void rpn_Number(Expression *expr, uint32_t i)
{ {
rpn_Init(expr); initExpression(expr);
expr->val = i; expr->val = i;
} }
@@ -78,8 +78,8 @@ void rpn_Symbol(Expression *expr, char const *symName)
if (sym_IsPC(sym) && !sect_GetSymbolSection()) { if (sym_IsPC(sym) && !sect_GetSymbolSection()) {
error("PC has no value outside a section\n"); error("PC has no value outside a section\n");
rpn_Number(expr, 0); rpn_Number(expr, 0);
} else if (!sym || !sym_IsConstant(sym)) { } else if (!sym || !sym->isConstant()) {
rpn_Init(expr); initExpression(expr);
expr->isSymbol = true; expr->isSymbol = true;
if (sym_IsPC(sym)) if (sym_IsPC(sym))
@@ -100,7 +100,7 @@ void rpn_Symbol(Expression *expr, char const *symName)
void rpn_BankSelf(Expression *expr) void rpn_BankSelf(Expression *expr)
{ {
rpn_Init(expr); initExpression(expr);
if (!currentSection) { if (!currentSection) {
error("PC has no bank outside a section\n"); error("PC has no bank outside a section\n");
@@ -124,22 +124,23 @@ void rpn_BankSymbol(Expression *expr, char const *symName)
return; return;
} }
rpn_Init(expr); initExpression(expr);
if (sym && !sym_IsLabel(sym)) { if (sym && !sym->isLabel()) {
error("BANK argument must be a label\n"); error("BANK argument must be a label\n");
} else { } else {
sym = sym_Ref(symName); sym = sym_Ref(symName);
assert(sym); // If the symbol didn't exist, it should have been created assert(sym); // If the symbol didn't exist, it should have been created
if (sym_GetSection(sym) && sym_GetSection(sym)->bank != (uint32_t)-1) { if (sym->getSection() && sym->getSection()->bank != (uint32_t)-1) {
// Symbol's section is known and bank is fixed // Symbol's section is known and bank is fixed
expr->val = sym_GetSection(sym)->bank; expr->val = sym->getSection()->bank;
} else { } else {
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 = strlen(sym->name) + 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, nameLen);
} }
@@ -148,7 +149,7 @@ void rpn_BankSymbol(Expression *expr, char const *symName)
void rpn_BankSection(Expression *expr, char const *sectionName) void rpn_BankSection(Expression *expr, char const *sectionName)
{ {
rpn_Init(expr); initExpression(expr);
Section *section = sect_FindSectionByName(sectionName); Section *section = sect_FindSectionByName(sectionName);
@@ -168,11 +169,11 @@ void rpn_BankSection(Expression *expr, char const *sectionName)
void rpn_SizeOfSection(Expression *expr, char const *sectionName) void rpn_SizeOfSection(Expression *expr, char const *sectionName)
{ {
rpn_Init(expr); initExpression(expr);
Section *section = sect_FindSectionByName(sectionName); Section *section = sect_FindSectionByName(sectionName);
if (section && sect_IsSizeKnown(section)) { if (section && section->isSizeKnown()) {
expr->val = section->size; expr->val = section->size;
} else { } else {
makeUnknown(expr, "Section \"", sectionName, "\"'s size is not known"); makeUnknown(expr, "Section \"", sectionName, "\"'s size is not known");
@@ -188,7 +189,7 @@ void rpn_SizeOfSection(Expression *expr, char const *sectionName)
void rpn_StartOfSection(Expression *expr, char const *sectionName) void rpn_StartOfSection(Expression *expr, char const *sectionName)
{ {
rpn_Init(expr); initExpression(expr);
Section *section = sect_FindSectionByName(sectionName); Section *section = sect_FindSectionByName(sectionName);
@@ -208,7 +209,7 @@ void rpn_StartOfSection(Expression *expr, char const *sectionName)
void rpn_SizeOfSectionType(Expression *expr, enum SectionType type) void rpn_SizeOfSectionType(Expression *expr, enum SectionType type)
{ {
rpn_Init(expr); initExpression(expr);
makeUnknown(expr, "Section type's size is not known"); makeUnknown(expr, "Section type's size is not known");
uint8_t *ptr = reserveSpace(expr, 2); uint8_t *ptr = reserveSpace(expr, 2);
@@ -220,7 +221,7 @@ void rpn_SizeOfSectionType(Expression *expr, enum SectionType type)
void rpn_StartOfSectionType(Expression *expr, enum SectionType type) void rpn_StartOfSectionType(Expression *expr, enum SectionType type)
{ {
rpn_Init(expr); initExpression(expr);
makeUnknown(expr, "Section type's start is not known"); makeUnknown(expr, "Section type's start is not known");
uint8_t *ptr = reserveSpace(expr, 2); uint8_t *ptr = reserveSpace(expr, 2);
@@ -235,7 +236,7 @@ void rpn_CheckHRAM(Expression *expr, const Expression *src)
*expr = *src; *expr = *src;
expr->isSymbol = false; expr->isSymbol = false;
if (!rpn_isKnown(expr)) { if (!expr->isKnown) {
expr->rpnPatchSize++; expr->rpnPatchSize++;
*reserveSpace(expr, 1) = RPN_HRAM; *reserveSpace(expr, 1) = RPN_HRAM;
} else if (expr->val >= 0xFF00 && expr->val <= 0xFFFF) { } else if (expr->val >= 0xFF00 && expr->val <= 0xFFFF) {
@@ -250,7 +251,7 @@ void rpn_CheckRST(Expression *expr, const Expression *src)
{ {
*expr = *src; *expr = *src;
if (rpn_isKnown(expr)) { if (expr->isKnown) {
// A valid RST address must be masked with 0x38 // A valid RST address must be masked with 0x38
if (expr->val & ~0x38) if (expr->val & ~0x38)
error("Invalid address $%" PRIx32 " for RST\n", expr->val); error("Invalid address $%" PRIx32 " for RST\n", expr->val);
@@ -268,7 +269,7 @@ void rpn_CheckNBit(Expression const *expr, uint8_t n)
assert(n != 0); // That doesn't make sense assert(n != 0); // That doesn't make sense
assert(n < CHAR_BIT * sizeof(int)); // Otherwise `1 << n` is UB assert(n < CHAR_BIT * sizeof(int)); // Otherwise `1 << n` is UB
if (rpn_isKnown(expr)) { if (expr->isKnown) {
int32_t val = expr->val; int32_t val = expr->val;
if (val < -(1 << n) || val >= 1 << n) if (val < -(1 << n) || val >= 1 << n)
@@ -278,13 +279,13 @@ void rpn_CheckNBit(Expression const *expr, uint8_t n)
} }
} }
int32_t rpn_GetConstVal(Expression const *expr) int32_t Expression::getConstVal() const
{ {
if (!rpn_isKnown(expr)) { if (!isKnown) {
error("Expected constant expression: %s\n", expr->reason->c_str()); error("Expected constant expression: %s\n", reason->c_str());
return 0; return 0;
} }
return expr->val; return val;
} }
void rpn_LOGNOT(Expression *expr, const Expression *src) void rpn_LOGNOT(Expression *expr, const Expression *src)
@@ -292,7 +293,7 @@ void rpn_LOGNOT(Expression *expr, const Expression *src)
*expr = *src; *expr = *src;
expr->isSymbol = false; expr->isSymbol = false;
if (rpn_isKnown(expr)) { if (expr->isKnown) {
expr->val = !expr->val; expr->val = !expr->val;
} else { } else {
expr->rpnPatchSize++; expr->rpnPatchSize++;
@@ -300,31 +301,26 @@ void rpn_LOGNOT(Expression *expr, const Expression *src)
} }
} }
Symbol const *rpn_SymbolOf(Expression const *expr) Symbol const *Expression::symbolOf() const
{ {
if (!rpn_isSymbol(expr)) if (!isSymbol)
return nullptr; return nullptr;
return sym_FindScopedSymbol((char const *)&(*expr->rpn)[1]); return sym_FindScopedSymbol((char const *)&(*rpn)[1]);
} }
bool rpn_IsDiffConstant(Expression const *src, Symbol const *sym) bool Expression::isDiffConstant(Symbol const *sym) const
{ {
// Check if both expressions only refer to a single symbol // Check if both expressions only refer to a single symbol
Symbol const *sym1 = rpn_SymbolOf(src); Symbol const *sym1 = symbolOf();
if (!sym1 || !sym || sym1->type != SYM_LABEL || sym->type != SYM_LABEL) if (!sym1 || !sym || sym1->type != SYM_LABEL || sym->type != SYM_LABEL)
return false; return false;
Section const *section1 = sym_GetSection(sym1); Section const *section1 = sym1->getSection();
Section const *section2 = sym_GetSection(sym); Section const *section2 = sym->getSection();
return section1 && (section1 == section2); return section1 && (section1 == section2);
} }
static bool isDiffConstant(Expression const *src1, Expression const *src2)
{
return rpn_IsDiffConstant(src1, rpn_SymbolOf(src2));
}
/* /*
* Attempts to compute a constant binary AND from non-constant operands * Attempts to compute a constant binary AND from non-constant operands
* This is possible if one operand is a symbol belonging to an `ALIGN[N]` section, and the other is * This is possible if one operand is a symbol belonging to an `ALIGN[N]` section, and the other is
@@ -334,33 +330,33 @@ static bool isDiffConstant(Expression const *src1, Expression const *src2)
*/ */
static int32_t tryConstMask(Expression const *lhs, Expression const *rhs) static int32_t tryConstMask(Expression const *lhs, Expression const *rhs)
{ {
Symbol const *sym = rpn_SymbolOf(lhs); Symbol const *sym = lhs->symbolOf();
Expression const *expr = rhs; Expression const *expr = rhs;
if (!sym || !sym_GetSection(sym)) { if (!sym || !sym->getSection()) {
// If the lhs isn't a symbol, try again the other way around // If the lhs isn't a symbol, try again the other way around
sym = rpn_SymbolOf(rhs); sym = rhs->symbolOf();
expr = lhs; expr = lhs;
if (!sym || !sym_GetSection(sym)) if (!sym || !sym->getSection())
return -1; return -1;
} }
assert(sym_IsNumeric(sym)); assert(sym->isNumeric());
if (!rpn_isKnown(expr)) if (!expr->isKnown)
return -1; return -1;
// We can now safely use `expr->val` // We can now safely use `expr->val`
Section const *sect = sym_GetSection(sym); Section const *sect = sym->getSection();
int32_t unknownBits = (1 << 16) - (1 << sect->align); // The max alignment is 16 int32_t unknownBits = (1 << 16) - (1 << sect->align); // The max alignment is 16
// The mask must ignore all unknown bits // The mask must ignore all unknown bits
if ((expr->val & unknownBits) != 0) if ((expr->val & unknownBits) != 0)
return -1; return -1;
// `sym_GetValue()` attempts to add the section's address, // `sym->getValue()` attempts to add the section's address, but that's "-1"
// but that's "-1" because the section is floating (otherwise we wouldn't be here) // because the section is floating (otherwise we wouldn't be here)
assert(sect->org == (uint32_t)-1); assert(sect->org == (uint32_t)-1);
int32_t symbolOfs = sym_GetValue(sym) + 1; int32_t symbolOfs = sym->getValue() + 1;
return (symbolOfs + sect->alignOfs) & ~unknownBits; return (symbolOfs + sect->alignOfs) & ~unknownBits;
} }
@@ -371,9 +367,9 @@ void rpn_BinaryOp(enum RPNCommand op, Expression *expr, const Expression *src1,
int32_t constMaskVal; int32_t constMaskVal;
// First, check if the expression is known // First, check if the expression is known
expr->isKnown = rpn_isKnown(src1) && rpn_isKnown(src2); expr->isKnown = src1->isKnown && src2->isKnown;
if (rpn_isKnown(expr)) { if (expr->isKnown) {
rpn_Init(expr); // Init the expression to something sane initExpression(expr); // Init the expression to something sane
// If both expressions are known, just compute the value // If both expressions are known, just compute the value
uint32_t uleft = src1->val, uright = src2->val; uint32_t uleft = src1->val, uright = src2->val;
@@ -509,11 +505,11 @@ void rpn_BinaryOp(enum RPNCommand op, Expression *expr, const Expression *src1,
fatalerror("%d is not a binary operator\n", op); fatalerror("%d is not a binary operator\n", op);
} }
} else if (op == RPN_SUB && isDiffConstant(src1, src2)) { } else if (op == RPN_SUB && src1->isDiffConstant(src2->symbolOf())) {
Symbol const *symbol1 = rpn_SymbolOf(src1); Symbol const *symbol1 = src1->symbolOf();
Symbol const *symbol2 = rpn_SymbolOf(src2); Symbol const *symbol2 = src2->symbolOf();
expr->val = sym_GetValue(symbol1) - sym_GetValue(symbol2); expr->val = symbol1->getValue() - symbol2->getValue();
expr->isKnown = true; expr->isKnown = true;
} else if (op == RPN_AND && (constMaskVal = tryConstMask(src1, src2)) != -1) { } else if (op == RPN_AND && (constMaskVal = tryConstMask(src1, src2)) != -1) {
expr->val = constMaskVal; expr->val = constMaskVal;
@@ -522,7 +518,7 @@ void rpn_BinaryOp(enum RPNCommand op, Expression *expr, const Expression *src1,
// If it's not known, start computing the RPN expression // If it's not known, start computing the RPN expression
// Convert the left-hand expression if it's constant // Convert the left-hand expression if it's constant
if (rpn_isKnown(src1)) { if (src1->isKnown) {
uint32_t lval = src1->val; uint32_t lval = src1->val;
uint8_t bytes[] = {RPN_CONST, (uint8_t)lval, (uint8_t)(lval >> 8), uint8_t bytes[] = {RPN_CONST, (uint8_t)lval, (uint8_t)(lval >> 8),
(uint8_t)(lval >> 16), (uint8_t)(lval >> 24)}; (uint8_t)(lval >> 16), (uint8_t)(lval >> 24)};
@@ -550,7 +546,7 @@ void rpn_BinaryOp(enum RPNCommand op, Expression *expr, const Expression *src1,
uint32_t rval = src2->val; uint32_t rval = src2->val;
uint8_t bytes[] = {RPN_CONST, (uint8_t)rval, (uint8_t)(rval >> 8), uint8_t bytes[] = {RPN_CONST, (uint8_t)rval, (uint8_t)(rval >> 8),
(uint8_t)(rval >> 16), (uint8_t)(rval >> 24)}; (uint8_t)(rval >> 16), (uint8_t)(rval >> 24)};
if (rpn_isKnown(src2)) { if (src2->isKnown) {
ptr = bytes; ptr = bytes;
len = sizeof(bytes); len = sizeof(bytes);
patchSize = sizeof(bytes); patchSize = sizeof(bytes);
@@ -577,7 +573,7 @@ void rpn_HIGH(Expression *expr, const Expression *src)
*expr = *src; *expr = *src;
expr->isSymbol = false; expr->isSymbol = false;
if (rpn_isKnown(expr)) { if (expr->isKnown) {
expr->val = (uint32_t)expr->val >> 8 & 0xFF; expr->val = (uint32_t)expr->val >> 8 & 0xFF;
} else { } else {
uint8_t bytes[] = {RPN_CONST, 8, 0, 0, 0, RPN_SHR, uint8_t bytes[] = {RPN_CONST, 8, 0, 0, 0, RPN_SHR,
@@ -592,7 +588,7 @@ void rpn_LOW(Expression *expr, const Expression *src)
*expr = *src; *expr = *src;
expr->isSymbol = false; expr->isSymbol = false;
if (rpn_isKnown(expr)) { if (expr->isKnown) {
expr->val = expr->val & 0xFF; expr->val = expr->val & 0xFF;
} else { } else {
uint8_t bytes[] = {RPN_CONST, 0xFF, 0, 0, 0, RPN_AND}; uint8_t bytes[] = {RPN_CONST, 0xFF, 0, 0, 0, RPN_AND};
@@ -604,8 +600,8 @@ void rpn_LOW(Expression *expr, const Expression *src)
void rpn_ISCONST(Expression *expr, const Expression *src) void rpn_ISCONST(Expression *expr, const Expression *src)
{ {
rpn_Init(expr); initExpression(expr);
expr->val = rpn_isKnown(src); expr->val = src->isKnown;
expr->isKnown = true; expr->isKnown = true;
expr->isSymbol = false; expr->isSymbol = false;
} }
@@ -615,7 +611,7 @@ void rpn_NEG(Expression *expr, const Expression *src)
*expr = *src; *expr = *src;
expr->isSymbol = false; expr->isSymbol = false;
if (rpn_isKnown(expr)) { if (expr->isKnown) {
expr->val = -(uint32_t)expr->val; expr->val = -(uint32_t)expr->val;
} else { } else {
expr->rpnPatchSize++; expr->rpnPatchSize++;
@@ -628,7 +624,7 @@ void rpn_NOT(Expression *expr, const Expression *src)
*expr = *src; *expr = *src;
expr->isSymbol = false; expr->isSymbol = false;
if (rpn_isKnown(expr)) { if (expr->isKnown) {
expr->val = ~expr->val; expr->val = ~expr->val;
} else { } else {
expr->rpnPatchSize++; expr->rpnPatchSize++;

View File

@@ -250,7 +250,7 @@ static void mergeSections(Section *sect, enum SectionType type, uint32_t org, ui
case SECTION_NORMAL: case SECTION_NORMAL:
fail("Section already defined previously at "); fail("Section already defined previously at ");
fstk_Dump(sect->src, sect->fileLine); sect->src->dump(sect->fileLine);
putc('\n', stderr); putc('\n', stderr);
break; break;
} }
@@ -375,6 +375,25 @@ static void changeSection()
sym_SetCurrentSymbolScope(nullptr); sym_SetCurrentSymbolScope(nullptr);
} }
bool Section::isSizeKnown() const
{
// SECTION UNION and SECTION FRAGMENT can still grow
if (modifier != SECTION_NORMAL)
return false;
// The current section (or current load section if within one) is still growing
if (this == currentSection || this == currentLoadSection)
return false;
// Any section on the stack is still growing
for (SectionStackEntry &entry : sectionStack) {
if (entry.section && !strcmp(name, entry.section->name))
return false;
}
return true;
}
// Set the current section by name and type // Set the current section by name and type
void sect_NewSection(char const *name, enum SectionType type, uint32_t org, void sect_NewSection(char const *name, enum SectionType type, uint32_t org,
SectionSpec const *attribs, enum SectionModifier mod) SectionSpec const *attribs, enum SectionModifier mod)
@@ -675,7 +694,7 @@ void sect_RelByte(Expression *expr, uint32_t pcShift)
if (!reserveSpace(1)) if (!reserveSpace(1))
return; return;
if (!rpn_isKnown(expr)) { if (!expr->isKnown) {
createPatch(PATCHTYPE_BYTE, expr, pcShift); createPatch(PATCHTYPE_BYTE, expr, pcShift);
writebyte(0); writebyte(0);
} else { } else {
@@ -696,7 +715,7 @@ void sect_RelBytes(uint32_t n, std::vector<Expression> &exprs)
for (uint32_t i = 0; i < n; i++) { for (uint32_t i = 0; i < n; i++) {
Expression &expr = exprs[i % exprs.size()]; Expression &expr = exprs[i % exprs.size()];
if (!rpn_isKnown(&expr)) { if (!expr.isKnown) {
createPatch(PATCHTYPE_BYTE, &expr, i); createPatch(PATCHTYPE_BYTE, &expr, i);
writebyte(0); writebyte(0);
} else { } else {
@@ -717,7 +736,7 @@ void sect_RelWord(Expression *expr, uint32_t pcShift)
if (!reserveSpace(2)) if (!reserveSpace(2))
return; return;
if (!rpn_isKnown(expr)) { if (!expr->isKnown) {
createPatch(PATCHTYPE_WORD, expr, pcShift); createPatch(PATCHTYPE_WORD, expr, pcShift);
writeword(0); writeword(0);
} else { } else {
@@ -735,7 +754,7 @@ void sect_RelLong(Expression *expr, uint32_t pcShift)
if (!reserveSpace(2)) if (!reserveSpace(2))
return; return;
if (!rpn_isKnown(expr)) { if (!expr->isKnown) {
createPatch(PATCHTYPE_LONG, expr, pcShift); createPatch(PATCHTYPE_LONG, expr, pcShift);
writelong(0); writelong(0);
} else { } else {
@@ -754,11 +773,11 @@ void sect_PCRelByte(Expression *expr, uint32_t pcShift)
return; return;
Symbol const *pc = sym_GetPC(); Symbol const *pc = sym_GetPC();
if (!rpn_IsDiffConstant(expr, pc)) { if (!expr->isDiffConstant(pc)) {
createPatch(PATCHTYPE_JR, expr, pcShift); createPatch(PATCHTYPE_JR, expr, pcShift);
writebyte(0); writebyte(0);
} else { } else {
Symbol const *sym = rpn_SymbolOf(expr); Symbol const *sym = expr->symbolOf();
// The offset wraps (jump from ROM to HRAM, for example) // The offset wraps (jump from ROM to HRAM, for example)
int16_t offset; int16_t offset;
@@ -766,7 +785,7 @@ void sect_PCRelByte(Expression *expr, uint32_t pcShift)
if (sym == pc) if (sym == pc)
offset = -2; // PC as operand to `jr` is lower than reference PC by 2 offset = -2; // PC as operand to `jr` is lower than reference PC by 2
else else
offset = sym_GetValue(sym) - (sym_GetValue(pc) + 1); offset = sym->getValue() - (pc->getValue() + 1);
if (offset < -128 || offset > 127) { if (offset < -128 || offset > 127) {
error("jr target out of reach (expected -129 < %" PRId16 " < 128)\n", error("jr target out of reach (expected -129 < %" PRId16 " < 128)\n",
@@ -973,22 +992,3 @@ void sect_EndSection()
currentSection = nullptr; currentSection = nullptr;
sym_SetCurrentSymbolScope(nullptr); sym_SetCurrentSymbolScope(nullptr);
} }
bool sect_IsSizeKnown(Section const NONNULL(sect))
{
// SECTION UNION and SECTION FRAGMENT can still grow
if (sect->modifier != SECTION_NORMAL)
return false;
// The current section (or current load section if within one) is still growing
if (sect == currentSection || sect == currentLoadSection)
return false;
// Any section on the stack is still growing
for (SectionStackEntry &entry : sectionStack) {
if (entry.section && !strcmp(sect->name, entry.section->name))
return false;
}
return true;
}

View File

@@ -66,22 +66,22 @@ static int32_t CallbackPC()
} }
// Get the value field of a symbol // Get the value field of a symbol
int32_t sym_GetValue(Symbol const *sym) int32_t Symbol::getValue() const
{ {
if (sym_IsNumeric(sym) && sym->hasCallback) if (isNumeric() && hasCallback)
return sym->numCallback(); return numCallback();
if (sym->type == SYM_LABEL) if (type == SYM_LABEL)
// TODO: do not use section's org directly // TODO: do not use section's org directly
return sym->value + sym_GetSection(sym)->org; return value + getSection()->org;
return sym->value; return value;
} }
static void dumpFilename(Symbol const *sym) static void dumpFilename(Symbol const *sym)
{ {
if (sym->src) if (sym->src)
fstk_Dump(sym->src, sym->fileLine); sym->src->dump(sym->fileLine);
else if (sym->fileLine == 0) else if (sym->fileLine == 0)
fputs("<command-line>", stderr); fputs("<command-line>", stderr);
else else
@@ -178,7 +178,7 @@ Symbol *sym_FindScopedValidSymbol(char const *symName)
Symbol *sym = sym_FindScopedSymbol(symName); Symbol *sym = sym_FindScopedSymbol(symName);
// `@` has no value outside a section // `@` has no value outside a section
if (sym == PCSymbol && !sect_GetSymbolSection()) { if (sym_IsPC(sym) && !sect_GetSymbolSection()) {
return nullptr; return nullptr;
} }
// `_NARG` has no value outside a macro // `_NARG` has no value outside a macro
@@ -235,28 +235,25 @@ uint32_t sym_GetPCValue()
} }
// Return a constant symbol's value, assuming it's defined // Return a constant symbol's value, assuming it's defined
uint32_t sym_GetConstantSymValue(Symbol const *sym) uint32_t Symbol::getConstantValue() const
{ {
if (sym == PCSymbol) if (sym_IsPC(this))
return sym_GetPCValue(); return sym_GetPCValue();
else if (!sym_IsConstant(sym))
error("\"%s\" does not have a constant value\n", sym->name);
else
return sym_GetValue(sym);
if (isConstant())
return getValue();
error("\"%s\" does not have a constant value\n", name);
return 0; return 0;
} }
// Return a constant symbol's value // Return a constant symbol's value
uint32_t sym_GetConstantValue(char const *symName) uint32_t sym_GetConstantValue(char const *symName)
{ {
Symbol const *sym = sym_FindScopedSymbol(symName); if (Symbol const *sym = sym_FindScopedSymbol(symName); sym)
return sym->getConstantValue();
if (!sym)
error("'%s' not defined\n", symName); error("'%s' not defined\n", symName);
else
return sym_GetConstantSymValue(sym);
return 0; return 0;
} }
@@ -283,7 +280,7 @@ static Symbol *createNonrelocSymbol(char const *symName, bool numeric)
if (!sym) { if (!sym) {
sym = createsymbol(symName); sym = createsymbol(symName);
} else if (sym_IsDefined(sym)) { } else if (sym->isDefined()) {
error("'%s' already defined at ", symName); error("'%s' already defined at ", symName);
dumpFilename(sym); dumpFilename(sym);
putc('\n', stderr); putc('\n', stderr);
@@ -320,7 +317,7 @@ Symbol *sym_RedefEqu(char const *symName, int32_t value)
if (!sym) if (!sym)
return sym_AddEqu(symName, value); return sym_AddEqu(symName, value);
if (sym_IsDefined(sym) && sym->type != SYM_EQU) { if (sym->isDefined() && sym->type != SYM_EQU) {
error("'%s' already defined as non-EQU at ", symName); error("'%s' already defined as non-EQU at ", symName);
dumpFilename(sym); dumpFilename(sym);
putc('\n', stderr); putc('\n', stderr);
@@ -368,7 +365,7 @@ Symbol *sym_RedefString(char const *symName, char const *value)
return sym_AddString(symName, value); return sym_AddString(symName, value);
if (sym->type != SYM_EQUS) { if (sym->type != SYM_EQUS) {
if (sym_IsDefined(sym)) if (sym->isDefined())
error("'%s' already defined as non-EQUS at ", symName); error("'%s' already defined as non-EQUS at ", symName);
else else
error("'%s' already referenced at ", symName); error("'%s' already referenced at ", symName);
@@ -395,7 +392,7 @@ Symbol *sym_AddVar(char const *symName, int32_t value)
if (!sym) { if (!sym) {
sym = createsymbol(symName); sym = createsymbol(symName);
} else if (sym_IsDefined(sym) && sym->type != SYM_VAR) { } else if (sym->isDefined() && sym->type != SYM_VAR) {
error("'%s' already defined as %s at ", error("'%s' already defined as %s at ",
symName, sym->type == SYM_LABEL ? "label" : "constant"); symName, sym->type == SYM_LABEL ? "label" : "constant");
dumpFilename(sym); dumpFilename(sym);
@@ -423,7 +420,7 @@ static Symbol *addLabel(char const *symName)
if (!sym) { if (!sym) {
sym = createsymbol(symName); sym = createsymbol(symName);
} else if (sym_IsDefined(sym)) { } else if (sym->isDefined()) {
error("'%s' already defined at ", symName); error("'%s' already defined at ", symName);
dumpFilename(sym); dumpFilename(sym);
putc('\n', stderr); putc('\n', stderr);

View File

@@ -72,23 +72,23 @@ std::string const &FileStackNode::name() const {
} }
// Helper function to dump a file stack to stderr // Helper function to dump a file stack to stderr
std::string const *dumpFileStack(FileStackNode const *node) std::string const *FileStackNode::dumpFileStack() const
{ {
std::string const *lastName; std::string const *lastName;
if (node->parent) { if (parent) {
lastName = dumpFileStack(node->parent); lastName = parent->dumpFileStack();
// REPT nodes use their parent's name // REPT nodes use their parent's name
if (node->type != NODE_REPT) if (type != NODE_REPT)
lastName = &node->name(); lastName = &name();
fprintf(stderr, "(%" PRIu32 ") -> %s", node->lineNo, lastName->c_str()); fprintf(stderr, "(%" PRIu32 ") -> %s", lineNo, lastName->c_str());
if (node->type == NODE_REPT) { if (type == NODE_REPT) {
for (uint32_t iter : node->iters()) for (uint32_t iter : iters())
fprintf(stderr, "::REPT~%" PRIu32, iter); fprintf(stderr, "::REPT~%" PRIu32, iter);
} }
} else { } else {
assert(node->type != NODE_REPT); assert(type != NODE_REPT);
lastName = &node->name(); lastName = &name();
fputs(lastName->c_str(), stderr); fputs(lastName->c_str(), stderr);
} }
@@ -101,7 +101,7 @@ void printDiag(char const *fmt, va_list args, char const *type,
fputs(type, stderr); fputs(type, stderr);
fputs(": ", stderr); fputs(": ", stderr);
if (where) { if (where) {
dumpFileStack(where); where->dumpFileStack();
fprintf(stderr, "(%" PRIu32 "): ", lineNo); fprintf(stderr, "(%" PRIu32 "): ", lineNo);
} }
vfprintf(stderr, fmt, args); vfprintf(stderr, fmt, args);

View File

@@ -18,9 +18,9 @@ void sym_AddSymbol(Symbol *symbol)
// Check if the symbol already exists // Check if the symbol already exists
if (Symbol *other = sym_GetSymbol(symbol->name); other) { if (Symbol *other = sym_GetSymbol(symbol->name); other) {
fprintf(stderr, "error: \"%s\" both in %s from ", symbol->name.c_str(), symbol->objFileName); fprintf(stderr, "error: \"%s\" both in %s from ", symbol->name.c_str(), symbol->objFileName);
dumpFileStack(symbol->src); symbol->src->dumpFileStack();
fprintf(stderr, "(%" PRIu32 ") and in %s from ", symbol->lineNo, other->objFileName); fprintf(stderr, "(%" PRIu32 ") and in %s from ", symbol->lineNo, other->objFileName);
dumpFileStack(other->src); other->src->dumpFileStack();
fprintf(stderr, "(%" PRIu32 ")\n", other->lineNo); fprintf(stderr, "(%" PRIu32 ")\n", other->lineNo);
exit(1); exit(1);
} }