Use std::string for RPN error reasons

This commit is contained in:
Rangi42
2024-02-25 10:43:49 -05:00
committed by Sylvie
parent cf42d035f2
commit 514044496f
2 changed files with 23 additions and 26 deletions

View File

@@ -4,12 +4,13 @@
#define RGBDS_ASM_RPN_H #define RGBDS_ASM_RPN_H
#include <stdint.h> #include <stdint.h>
#include <string>
#include "linkdefs.hpp" #include "linkdefs.hpp"
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
char *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
bool isSymbol; // Whether the expression represents a symbol bool isSymbol; // Whether the expression represents a symbol
std::vector<uint8_t> *rpn; // Bytes serializing the RPN expression std::vector<uint8_t> *rpn; // Bytes serializing the RPN expression

View File

@@ -22,21 +22,15 @@
#include "opmath.hpp" #include "opmath.hpp"
// Makes an expression "not known", also setting its error message // Makes an expression "not known", also setting its error message
#define makeUnknown(expr_, ...) do { \ template<typename... Ts>
struct Expression *_expr = expr_; \ static void makeUnknown(struct Expression *expr, Ts ...parts)
_expr->isKnown = false; \ {
/* If we had `asprintf` this would be great, but alas. */ \ expr->isKnown = false;
_expr->reason = (char *)malloc(128); /* Use an initial reasonable size */ \ expr->reason = new std::string();
if (!_expr->reason) \ if (!expr->reason)
fatalerror("Can't allocate err string: %s\n", strerror(errno)); \ fatalerror("Failed to allocate RPN error string: %s\n", strerror(errno));
int size = snprintf(_expr->reason, 128, __VA_ARGS__); \ (expr->reason->append(parts), ...);
if (size >= 128) { /* If this wasn't enough, try again */ \ }
_expr->reason = (char *)realloc(_expr->reason, size + 1); \
if (!_expr->reason) \
fatalerror("Can't allocate err string: %s\n", strerror(errno)); \
sprintf(_expr->reason, __VA_ARGS__); \
} \
} while (0)
static uint8_t *reserveSpace(struct Expression *expr, uint32_t size) static uint8_t *reserveSpace(struct Expression *expr, uint32_t size)
{ {
@@ -66,7 +60,7 @@ static void rpn_Init(struct Expression *expr)
void rpn_Free(struct Expression *expr) void rpn_Free(struct Expression *expr)
{ {
delete expr->rpn; delete expr->rpn;
free(expr->reason); delete expr->reason;
rpn_Init(expr); rpn_Init(expr);
} }
@@ -88,8 +82,10 @@ void rpn_Symbol(struct Expression *expr, char const *symName)
rpn_Init(expr); rpn_Init(expr);
expr->isSymbol = true; expr->isSymbol = true;
makeUnknown(expr, sym_IsPC(sym) ? "PC is not constant at assembly time" if (sym_IsPC(sym))
: "'%s' is not constant at assembly time", symName); makeUnknown(expr, "PC is not constant at assembly time");
else
makeUnknown(expr, "'", symName, "' is not constant at assembly time");
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
@@ -139,7 +135,7 @@ void rpn_BankSymbol(struct Expression *expr, char const *symName)
// 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(sym)->bank;
} else { } else {
makeUnknown(expr, "\"%s\"'s bank is not known", symName); 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!
@@ -159,7 +155,7 @@ void rpn_BankSection(struct Expression *expr, char const *sectionName)
if (section && section->bank != (uint32_t)-1) { if (section && section->bank != (uint32_t)-1) {
expr->val = section->bank; expr->val = section->bank;
} else { } else {
makeUnknown(expr, "Section \"%s\"'s bank is not known", sectionName); makeUnknown(expr, "Section \"", sectionName, "\"'s bank is not known");
size_t nameLen = strlen(sectionName) + 1; // Room for NUL! size_t nameLen = strlen(sectionName) + 1; // Room for NUL!
uint8_t *ptr = reserveSpace(expr, nameLen + 1); uint8_t *ptr = reserveSpace(expr, nameLen + 1);
@@ -179,7 +175,7 @@ void rpn_SizeOfSection(struct Expression *expr, char const *sectionName)
if (section && sect_IsSizeKnown(section)) { if (section && sect_IsSizeKnown(section)) {
expr->val = section->size; expr->val = section->size;
} else { } else {
makeUnknown(expr, "Section \"%s\"'s size is not known", sectionName); makeUnknown(expr, "Section \"", sectionName, "\"'s size is not known");
size_t nameLen = strlen(sectionName) + 1; // Room for NUL! size_t nameLen = strlen(sectionName) + 1; // Room for NUL!
uint8_t *ptr = reserveSpace(expr, nameLen + 1); uint8_t *ptr = reserveSpace(expr, nameLen + 1);
@@ -199,7 +195,7 @@ void rpn_StartOfSection(struct Expression *expr, char const *sectionName)
if (section && section->org != (uint32_t)-1) { if (section && section->org != (uint32_t)-1) {
expr->val = section->org; expr->val = section->org;
} else { } else {
makeUnknown(expr, "Section \"%s\"'s start is not known", sectionName); makeUnknown(expr, "Section \"", sectionName, "\"'s start is not known");
size_t nameLen = strlen(sectionName) + 1; // Room for NUL! size_t nameLen = strlen(sectionName) + 1; // Room for NUL!
uint8_t *ptr = reserveSpace(expr, nameLen + 1); uint8_t *ptr = reserveSpace(expr, nameLen + 1);
@@ -285,7 +281,7 @@ void rpn_CheckNBit(struct Expression const *expr, uint8_t n)
int32_t rpn_GetConstVal(struct Expression const *expr) int32_t rpn_GetConstVal(struct Expression const *expr)
{ {
if (!rpn_isKnown(expr)) { if (!rpn_isKnown(expr)) {
error("Expected constant expression: %s\n", expr->reason); error("Expected constant expression: %s\n", expr->reason->c_str());
return 0; return 0;
} }
return expr->val; return expr->val;
@@ -538,13 +534,13 @@ void rpn_BinaryOp(enum RPNCommand op, struct Expression *expr,
// Use the other expression's un-const reason // Use the other expression's un-const reason
expr->reason = src2->reason; expr->reason = src2->reason;
free(src1->reason); delete src1->reason;
} else { } else {
// Otherwise just reuse its RPN buffer // Otherwise just reuse its RPN buffer
expr->rpnPatchSize = src1->rpnPatchSize; expr->rpnPatchSize = src1->rpnPatchSize;
expr->rpn = src1->rpn; expr->rpn = src1->rpn;
expr->reason = src1->reason; expr->reason = src1->reason;
free(src2->reason); delete src2->reason;
} }
// Now, merge the right expression into the left one // Now, merge the right expression into the left one