mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-23 19:42:08 +00:00
Refactor warnings and errors (#1728)
* Remove `err` and `warn`, keep `errx` and `warnx`, using them in RGBGFX too * Separate RGBGFX and RGBLINK warnings/errors from main options * Separate `report` function into `error` and `fatal` messages * Implicit newlines for most RGBASM errors
This commit is contained in:
@@ -86,14 +86,14 @@ void charmap_New(std::string const &name, std::string const *baseName) {
|
||||
|
||||
if (baseName != nullptr) {
|
||||
if (auto search = charmapMap.find(*baseName); search == charmapMap.end()) {
|
||||
error("Base charmap '%s' doesn't exist\n", baseName->c_str());
|
||||
error("Base charmap '%s' doesn't exist", baseName->c_str());
|
||||
} else {
|
||||
baseIdx = search->second;
|
||||
}
|
||||
}
|
||||
|
||||
if (charmapMap.find(name) != charmapMap.end()) {
|
||||
error("Charmap '%s' already exists\n", name.c_str());
|
||||
error("Charmap '%s' already exists", name.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ void charmap_New(std::string const &name, std::string const *baseName) {
|
||||
|
||||
void charmap_Set(std::string const &name) {
|
||||
if (auto search = charmapMap.find(name); search == charmapMap.end()) {
|
||||
error("Charmap '%s' doesn't exist\n", name.c_str());
|
||||
error("Charmap '%s' doesn't exist", name.c_str());
|
||||
} else {
|
||||
currentCharmap = &charmapList[search->second];
|
||||
}
|
||||
@@ -126,7 +126,7 @@ void charmap_Push() {
|
||||
|
||||
void charmap_Pop() {
|
||||
if (charmapStack.empty()) {
|
||||
error("No entries in the charmap stack\n");
|
||||
error("No entries in the charmap stack");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -136,13 +136,13 @@ void charmap_Pop() {
|
||||
|
||||
void charmap_CheckStack() {
|
||||
if (!charmapStack.empty()) {
|
||||
warning(WARNING_UNMATCHED_DIRECTIVE, "`PUSHC` without corresponding `POPC`\n");
|
||||
warning(WARNING_UNMATCHED_DIRECTIVE, "`PUSHC` without corresponding `POPC`");
|
||||
}
|
||||
}
|
||||
|
||||
void charmap_Add(std::string const &mapping, std::vector<int32_t> &&value) {
|
||||
if (mapping.empty()) {
|
||||
error("Cannot map an empty string\n");
|
||||
error("Cannot map an empty string");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -168,7 +168,7 @@ void charmap_Add(std::string const &mapping, std::vector<int32_t> &&value) {
|
||||
CharmapNode &node = charmap.nodes[nodeIdx];
|
||||
|
||||
if (node.isTerminal()) {
|
||||
warning(WARNING_CHARMAP_REDEF, "Overriding charmap mapping\n");
|
||||
warning(WARNING_CHARMAP_REDEF, "Overriding charmap mapping");
|
||||
}
|
||||
|
||||
std::swap(node.value, value);
|
||||
@@ -268,7 +268,7 @@ size_t charmap_ConvertNext(std::string_view &input, std::vector<int32_t> *output
|
||||
// This will write the codepoint's value to `output`, little-endian
|
||||
for (uint32_t state = 0, codepoint = 0; inputIdx + codepointLen < input.length();) {
|
||||
if (decode(&state, &codepoint, input[inputIdx + codepointLen]) == 1) {
|
||||
error("Input string is not valid UTF-8\n");
|
||||
error("Input string is not valid UTF-8");
|
||||
codepointLen = 1;
|
||||
break;
|
||||
}
|
||||
@@ -286,11 +286,11 @@ size_t charmap_ConvertNext(std::string_view &input, std::vector<int32_t> *output
|
||||
|
||||
// Warn if this character is not mapped but any others are
|
||||
if (int firstChar = input[inputIdx]; charmap.nodes.size() > 1) {
|
||||
warning(WARNING_UNMAPPED_CHAR_1, "Unmapped character %s\n", printChar(firstChar));
|
||||
warning(WARNING_UNMAPPED_CHAR_1, "Unmapped character %s", printChar(firstChar));
|
||||
} else if (charmap.name != DEFAULT_CHARMAP_NAME) {
|
||||
warning(
|
||||
WARNING_UNMAPPED_CHAR_2,
|
||||
"Unmapped character %s not in " DEFAULT_CHARMAP_NAME " charmap\n",
|
||||
"Unmapped character %s not in " DEFAULT_CHARMAP_NAME " charmap",
|
||||
printChar(firstChar)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -162,19 +162,19 @@ void FormatSpec::appendString(std::string &str, std::string const &value) const
|
||||
}
|
||||
|
||||
if (sign) {
|
||||
error("Formatting string with sign flag '%c'\n", sign);
|
||||
error("Formatting string with sign flag '%c'", sign);
|
||||
}
|
||||
if (padZero) {
|
||||
error("Formatting string with padding flag '0'\n");
|
||||
error("Formatting string with padding flag '0'");
|
||||
}
|
||||
if (hasFrac) {
|
||||
error("Formatting string with fractional width\n");
|
||||
error("Formatting string with fractional width");
|
||||
}
|
||||
if (hasPrec) {
|
||||
error("Formatting string with fractional precision\n");
|
||||
error("Formatting string with fractional precision");
|
||||
}
|
||||
if (useType != 's') {
|
||||
error("Formatting string as type '%c'\n", useType);
|
||||
error("Formatting string as type '%c'", useType);
|
||||
}
|
||||
|
||||
std::string useValue = exact ? escapeString(value) : value;
|
||||
@@ -203,16 +203,16 @@ void FormatSpec::appendNumber(std::string &str, uint32_t value) const {
|
||||
|
||||
if (useType != 'X' && useType != 'x' && useType != 'b' && useType != 'o' && useType != 'f'
|
||||
&& useExact) {
|
||||
error("Formatting type '%c' with exact flag '#'\n", useType);
|
||||
error("Formatting type '%c' with exact flag '#'", useType);
|
||||
}
|
||||
if (useType != 'f' && hasFrac) {
|
||||
error("Formatting type '%c' with fractional width\n", useType);
|
||||
error("Formatting type '%c' with fractional width", useType);
|
||||
}
|
||||
if (useType != 'f' && hasPrec) {
|
||||
error("Formatting type '%c' with fractional precision\n", useType);
|
||||
error("Formatting type '%c' with fractional precision", useType);
|
||||
}
|
||||
if (useType == 's') {
|
||||
error("Formatting number as type 's'\n");
|
||||
error("Formatting number as type 's'");
|
||||
}
|
||||
|
||||
char signChar = sign; // 0 or ' ' or '+'
|
||||
@@ -254,7 +254,7 @@ void FormatSpec::appendNumber(std::string &str, uint32_t value) const {
|
||||
// Default fractional width (C++'s is 6 for "%f"; here 5 is enough for Q16.16)
|
||||
size_t useFracWidth = hasFrac ? fracWidth : 5;
|
||||
if (useFracWidth > 255) {
|
||||
error("Fractional width %zu too long, limiting to 255\n", useFracWidth);
|
||||
error("Fractional width %zu too long, limiting to 255", useFracWidth);
|
||||
useFracWidth = 255;
|
||||
}
|
||||
|
||||
@@ -262,7 +262,7 @@ void FormatSpec::appendNumber(std::string &str, uint32_t value) const {
|
||||
size_t usePrec = hasPrec ? precision : defaultPrec;
|
||||
if (usePrec < 1 || usePrec > 31) {
|
||||
error(
|
||||
"Fixed-point constant precision %zu invalid, defaulting to %zu\n",
|
||||
"Fixed-point constant precision %zu invalid, defaulting to %zu",
|
||||
usePrec,
|
||||
defaultPrec
|
||||
);
|
||||
|
||||
@@ -160,7 +160,7 @@ bool yywrap() {
|
||||
|
||||
if (ifDepth != 0) {
|
||||
fatalerror(
|
||||
"Ended block with %" PRIu32 " unterminated IF construct%s\n",
|
||||
"Ended block with %" PRIu32 " unterminated IF construct%s",
|
||||
ifDepth,
|
||||
ifDepth == 1 ? "" : "s"
|
||||
);
|
||||
@@ -188,7 +188,7 @@ bool yywrap() {
|
||||
|
||||
// This error message will refer to the current iteration
|
||||
if (sym->type != SYM_VAR) {
|
||||
fatalerror("Failed to update FOR symbol value\n");
|
||||
fatalerror("Failed to update FOR symbol value");
|
||||
}
|
||||
}
|
||||
// Advance to the next iteration
|
||||
@@ -211,7 +211,7 @@ bool yywrap() {
|
||||
|
||||
static void checkRecursionDepth() {
|
||||
if (contextStack.size() > maxRecursionDepth) {
|
||||
fatalerror("Recursion limit (%zu) exceeded\n", maxRecursionDepth);
|
||||
fatalerror("Recursion limit (%zu) exceeded", maxRecursionDepth);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -317,13 +317,13 @@ void fstk_RunInclude(std::string const &path, bool preInclude) {
|
||||
// LCOV_EXCL_STOP
|
||||
failedOnMissingInclude = true;
|
||||
} else {
|
||||
error("Unable to open included file '%s': %s\n", path.c_str(), strerror(errno));
|
||||
error("Unable to open included file '%s': %s", path.c_str(), strerror(errno));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!newFileContext(*fullPath, false)) {
|
||||
fatalerror("Failed to set up lexer for file include\n"); // LCOV_EXCL_LINE
|
||||
fatalerror("Failed to set up lexer for file include"); // LCOV_EXCL_LINE
|
||||
}
|
||||
}
|
||||
|
||||
@@ -332,14 +332,14 @@ void fstk_RunMacro(std::string const ¯oName, std::shared_ptr<MacroArgs> macr
|
||||
|
||||
if (!macro) {
|
||||
if (sym_IsPurgedExact(macroName)) {
|
||||
error("Macro \"%s\" not defined; it was purged\n", macroName.c_str());
|
||||
error("Macro \"%s\" not defined; it was purged", macroName.c_str());
|
||||
} else {
|
||||
error("Macro \"%s\" not defined\n", macroName.c_str());
|
||||
error("Macro \"%s\" not defined", macroName.c_str());
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (macro->type != SYM_MACRO) {
|
||||
error("\"%s\" is not a macro\n", macroName.c_str());
|
||||
error("\"%s\" is not a macro", macroName.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -372,13 +372,11 @@ void fstk_RunFor(
|
||||
} else if (step < 0 && stop < start) {
|
||||
count = (static_cast<int64_t>(start) - stop - 1) / -static_cast<int64_t>(step) + 1;
|
||||
} else if (step == 0) {
|
||||
error("FOR cannot have a step value of 0\n");
|
||||
error("FOR cannot have a step value of 0");
|
||||
}
|
||||
|
||||
if ((step > 0 && start > stop) || (step < 0 && start < stop)) {
|
||||
warning(
|
||||
WARNING_BACKWARDS_FOR, "FOR goes backwards from %d to %d by %d\n", start, stop, step
|
||||
);
|
||||
warning(WARNING_BACKWARDS_FOR, "FOR goes backwards from %d to %d by %d", start, stop, step);
|
||||
}
|
||||
|
||||
if (count == 0) {
|
||||
@@ -394,7 +392,7 @@ void fstk_RunFor(
|
||||
|
||||
bool fstk_Break() {
|
||||
if (contextStack.top().fileInfo->type != NODE_REPT) {
|
||||
error("BREAK can only be used inside a REPT/FOR block\n");
|
||||
error("BREAK can only be used inside a REPT/FOR block");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -404,14 +402,14 @@ bool fstk_Break() {
|
||||
|
||||
void fstk_NewRecursionDepth(size_t newDepth) {
|
||||
if (contextStack.size() > newDepth + 1) {
|
||||
fatalerror("Recursion limit (%zu) exceeded\n", newDepth);
|
||||
fatalerror("Recursion limit (%zu) exceeded", newDepth);
|
||||
}
|
||||
maxRecursionDepth = newDepth;
|
||||
}
|
||||
|
||||
void fstk_Init(std::string const &mainPath, size_t maxDepth) {
|
||||
if (!newFileContext(mainPath, true)) {
|
||||
fatalerror("Failed to open main file\n");
|
||||
fatalerror("Failed to open main file");
|
||||
}
|
||||
|
||||
maxRecursionDepth = maxDepth;
|
||||
|
||||
@@ -384,7 +384,7 @@ void lexer_IncIFDepth() {
|
||||
|
||||
void lexer_DecIFDepth() {
|
||||
if (lexerState->ifStack.empty()) {
|
||||
fatalerror("Found ENDC outside of an IF construct\n");
|
||||
fatalerror("Found ENDC outside of an IF construct");
|
||||
}
|
||||
|
||||
lexerState->ifStack.pop_front();
|
||||
@@ -423,7 +423,7 @@ bool LexerState::setFileAsNextState(std::string const &filePath, bool updateStat
|
||||
struct stat statBuf;
|
||||
if (stat(filePath.c_str(), &statBuf) != 0) {
|
||||
// LCOV_EXCL_START
|
||||
error("Failed to stat file \"%s\": %s\n", filePath.c_str(), strerror(errno));
|
||||
error("Failed to stat file \"%s\": %s", filePath.c_str(), strerror(errno));
|
||||
return false;
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
@@ -432,7 +432,7 @@ bool LexerState::setFileAsNextState(std::string const &filePath, bool updateStat
|
||||
int fd = open(path.c_str(), O_RDONLY);
|
||||
if (fd < 0) {
|
||||
// LCOV_EXCL_START
|
||||
error("Failed to open file \"%s\": %s\n", path.c_str(), strerror(errno));
|
||||
error("Failed to open file \"%s\": %s", path.c_str(), strerror(errno));
|
||||
return false;
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
@@ -565,7 +565,7 @@ size_t BufferedContent::readMore(size_t startIndex, size_t nbChars) {
|
||||
|
||||
if (nbReadChars == -1) {
|
||||
// LCOV_EXCL_START
|
||||
fatalerror("Error while reading \"%s\": %s\n", lexerState->path.c_str(), strerror(errno));
|
||||
fatalerror("Error while reading \"%s\": %s", lexerState->path.c_str(), strerror(errno));
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
|
||||
@@ -600,7 +600,7 @@ static void beginExpansion(std::shared_ptr<std::string> str, std::optional<std::
|
||||
|
||||
void lexer_CheckRecursionDepth() {
|
||||
if (lexerState->expansions.size() > maxRecursionDepth + 1) {
|
||||
fatalerror("Recursion limit (%zu) exceeded\n", maxRecursionDepth);
|
||||
fatalerror("Recursion limit (%zu) exceeded", maxRecursionDepth);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -637,7 +637,7 @@ static uint32_t readBracketedMacroArgNum() {
|
||||
if (c >= '0' && c <= '9') {
|
||||
uint32_t n = readDecimalNumber(0);
|
||||
if (n > INT32_MAX) {
|
||||
error("Number in bracketed macro argument is too large\n");
|
||||
error("Number in bracketed macro argument is too large");
|
||||
return 0;
|
||||
}
|
||||
num = negative ? -n : static_cast<int32_t>(n);
|
||||
@@ -646,7 +646,7 @@ static uint32_t readBracketedMacroArgNum() {
|
||||
shiftChar();
|
||||
c = peek();
|
||||
if (!startsIdentifier(c)) {
|
||||
error("Empty raw symbol in bracketed macro argument\n");
|
||||
error("Empty raw symbol in bracketed macro argument");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -662,14 +662,14 @@ static uint32_t readBracketedMacroArgNum() {
|
||||
|
||||
if (!sym) {
|
||||
if (sym_IsPurgedScoped(symName)) {
|
||||
error("Bracketed symbol \"%s\" does not exist; it was purged\n", symName.c_str());
|
||||
error("Bracketed symbol \"%s\" does not exist; it was purged", symName.c_str());
|
||||
} else {
|
||||
error("Bracketed symbol \"%s\" does not exist\n", symName.c_str());
|
||||
error("Bracketed symbol \"%s\" does not exist", symName.c_str());
|
||||
}
|
||||
num = 0;
|
||||
symbolError = true;
|
||||
} else if (!sym->isNumeric()) {
|
||||
error("Bracketed symbol \"%s\" is not numeric\n", symName.c_str());
|
||||
error("Bracketed symbol \"%s\" is not numeric", symName.c_str());
|
||||
num = 0;
|
||||
symbolError = true;
|
||||
} else {
|
||||
@@ -682,13 +682,13 @@ static uint32_t readBracketedMacroArgNum() {
|
||||
c = peek();
|
||||
shiftChar();
|
||||
if (c != '>') {
|
||||
error("Invalid character in bracketed macro argument %s\n", printChar(c));
|
||||
error("Invalid character in bracketed macro argument %s", printChar(c));
|
||||
return 0;
|
||||
} else if (empty) {
|
||||
error("Empty bracketed macro argument\n");
|
||||
error("Empty bracketed macro argument");
|
||||
return 0;
|
||||
} else if (num == 0 && !symbolError) {
|
||||
error("Invalid bracketed macro argument '\\<0>'\n");
|
||||
error("Invalid bracketed macro argument '\\<0>'");
|
||||
return 0;
|
||||
} else {
|
||||
return num;
|
||||
@@ -699,13 +699,13 @@ static std::shared_ptr<std::string> readMacroArg(char name) {
|
||||
if (name == '@') {
|
||||
auto str = fstk_GetUniqueIDStr();
|
||||
if (!str) {
|
||||
error("'\\@' cannot be used outside of a macro or REPT/FOR block\n");
|
||||
error("'\\@' cannot be used outside of a macro or REPT/FOR block");
|
||||
}
|
||||
return str;
|
||||
} else if (name == '#') {
|
||||
MacroArgs *macroArgs = fstk_GetCurrentMacroArgs();
|
||||
if (!macroArgs) {
|
||||
error("'\\#' cannot be used outside of a macro\n");
|
||||
error("'\\#' cannot be used outside of a macro");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -721,13 +721,13 @@ static std::shared_ptr<std::string> readMacroArg(char name) {
|
||||
|
||||
MacroArgs *macroArgs = fstk_GetCurrentMacroArgs();
|
||||
if (!macroArgs) {
|
||||
error("'\\<%" PRIu32 ">' cannot be used outside of a macro\n", num);
|
||||
error("'\\<%" PRIu32 ">' cannot be used outside of a macro", num);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto str = macroArgs->getArg(num);
|
||||
if (!str) {
|
||||
error("Macro argument '\\<%" PRId32 ">' not defined\n", num);
|
||||
error("Macro argument '\\<%" PRId32 ">' not defined", num);
|
||||
}
|
||||
return str;
|
||||
} else {
|
||||
@@ -735,13 +735,13 @@ static std::shared_ptr<std::string> readMacroArg(char name) {
|
||||
|
||||
MacroArgs *macroArgs = fstk_GetCurrentMacroArgs();
|
||||
if (!macroArgs) {
|
||||
error("'\\%c' cannot be used outside of a macro\n", name);
|
||||
error("'\\%c' cannot be used outside of a macro", name);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto str = macroArgs->getArg(name - '0');
|
||||
if (!str) {
|
||||
error("Macro argument '\\%c' not defined\n", name);
|
||||
error("Macro argument '\\%c' not defined", name);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
@@ -945,7 +945,7 @@ static void discardBlockComment() {
|
||||
|
||||
switch (c) {
|
||||
case EOF:
|
||||
error("Unterminated block comment\n");
|
||||
error("Unterminated block comment");
|
||||
return;
|
||||
case '\r':
|
||||
handleCRLF(c);
|
||||
@@ -957,7 +957,7 @@ static void discardBlockComment() {
|
||||
continue;
|
||||
case '/':
|
||||
if (peek() == '*') {
|
||||
warning(WARNING_NESTED_COMMENT, "/* in block comment\n");
|
||||
warning(WARNING_NESTED_COMMENT, "/* in block comment");
|
||||
}
|
||||
continue;
|
||||
case '*':
|
||||
@@ -999,7 +999,7 @@ static void discardLineContinuation() {
|
||||
} else if (c == ';') {
|
||||
discardComment();
|
||||
} else {
|
||||
error("Begun line continuation, but encountered character %s\n", printChar(c));
|
||||
error("Begun line continuation, but encountered character %s", printChar(c));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1041,7 +1041,7 @@ static uint32_t readFractionalPart(uint32_t integer) {
|
||||
break;
|
||||
}
|
||||
if (divisor > (UINT32_MAX - (c - '0')) / 10) {
|
||||
warning(WARNING_LARGE_CONSTANT, "Precision of fixed-point constant is too large\n");
|
||||
warning(WARNING_LARGE_CONSTANT, "Precision of fixed-point constant is too large");
|
||||
// Discard any additional digits
|
||||
shiftChar();
|
||||
while (c = peek(), (c >= '0' && c <= '9') || c == '_') {
|
||||
@@ -1064,16 +1064,16 @@ static uint32_t readFractionalPart(uint32_t integer) {
|
||||
|
||||
if (precision == 0) {
|
||||
if (state >= READFRACTIONALPART_PRECISION) {
|
||||
error("Invalid fixed-point constant, no significant digits after 'q'\n");
|
||||
error("Invalid fixed-point constant, no significant digits after 'q'");
|
||||
}
|
||||
precision = fixPrecision;
|
||||
} else if (precision > 31) {
|
||||
error("Fixed-point constant precision must be between 1 and 31\n");
|
||||
error("Fixed-point constant precision must be between 1 and 31");
|
||||
precision = fixPrecision;
|
||||
}
|
||||
|
||||
if (integer >= (1ULL << (32 - precision))) {
|
||||
warning(WARNING_LARGE_CONSTANT, "Magnitude of fixed-point constant is too large\n");
|
||||
warning(WARNING_LARGE_CONSTANT, "Magnitude of fixed-point constant is too large");
|
||||
}
|
||||
|
||||
// Cast to unsigned avoids undefined overflow behavior
|
||||
@@ -1096,18 +1096,18 @@ static bool checkDigitErrors(char const *digits, size_t n, char const *type) {
|
||||
char c = digits[i];
|
||||
|
||||
if (!isValidDigit(c)) {
|
||||
error("Invalid digit for %s constant %s\n", type, printChar(c));
|
||||
error("Invalid digit for %s constant %s", type, printChar(c));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (c >= '0' && c < static_cast<char>(n + '0') && c != static_cast<char>(i + '0')) {
|
||||
error("Changed digit for %s constant %s\n", type, printChar(c));
|
||||
error("Changed digit for %s constant %s", type, printChar(c));
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t j = i + 1; j < n; j++) {
|
||||
if (c == digits[j]) {
|
||||
error("Repeated digit for %s constant %s\n", type, printChar(c));
|
||||
error("Repeated digit for %s constant %s", type, printChar(c));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1146,7 +1146,7 @@ static uint32_t readBinaryNumber() {
|
||||
break;
|
||||
}
|
||||
if (value > (UINT32_MAX - bit) / 2) {
|
||||
warning(WARNING_LARGE_CONSTANT, "Integer constant is too large\n");
|
||||
warning(WARNING_LARGE_CONSTANT, "Integer constant is too large");
|
||||
}
|
||||
value = value * 2 + bit;
|
||||
|
||||
@@ -1154,7 +1154,7 @@ static uint32_t readBinaryNumber() {
|
||||
}
|
||||
|
||||
if (empty) {
|
||||
error("Invalid integer constant, no digits after '%%'\n");
|
||||
error("Invalid integer constant, no digits after '%%'");
|
||||
}
|
||||
|
||||
return value;
|
||||
@@ -1176,7 +1176,7 @@ static uint32_t readOctalNumber() {
|
||||
}
|
||||
|
||||
if (value > (UINT32_MAX - c) / 8) {
|
||||
warning(WARNING_LARGE_CONSTANT, "Integer constant is too large\n");
|
||||
warning(WARNING_LARGE_CONSTANT, "Integer constant is too large");
|
||||
}
|
||||
value = value * 8 + c;
|
||||
|
||||
@@ -1184,7 +1184,7 @@ static uint32_t readOctalNumber() {
|
||||
}
|
||||
|
||||
if (empty) {
|
||||
error("Invalid integer constant, no digits after '&'\n");
|
||||
error("Invalid integer constant, no digits after '&'");
|
||||
}
|
||||
|
||||
return value;
|
||||
@@ -1206,7 +1206,7 @@ static uint32_t readDecimalNumber(int initial) {
|
||||
}
|
||||
|
||||
if (value > (UINT32_MAX - c) / 10) {
|
||||
warning(WARNING_LARGE_CONSTANT, "Integer constant is too large\n");
|
||||
warning(WARNING_LARGE_CONSTANT, "Integer constant is too large");
|
||||
}
|
||||
value = value * 10 + c;
|
||||
|
||||
@@ -1214,7 +1214,7 @@ static uint32_t readDecimalNumber(int initial) {
|
||||
}
|
||||
|
||||
if (empty) {
|
||||
error("Invalid integer constant, no digits\n");
|
||||
error("Invalid integer constant, no digits");
|
||||
}
|
||||
|
||||
return value;
|
||||
@@ -1240,7 +1240,7 @@ static uint32_t readHexNumber() {
|
||||
}
|
||||
|
||||
if (value > (UINT32_MAX - c) / 16) {
|
||||
warning(WARNING_LARGE_CONSTANT, "Integer constant is too large\n");
|
||||
warning(WARNING_LARGE_CONSTANT, "Integer constant is too large");
|
||||
}
|
||||
value = value * 16 + c;
|
||||
|
||||
@@ -1248,7 +1248,7 @@ static uint32_t readHexNumber() {
|
||||
}
|
||||
|
||||
if (empty) {
|
||||
error("Invalid integer constant, no digits after '$'\n");
|
||||
error("Invalid integer constant, no digits after '$'");
|
||||
}
|
||||
|
||||
return value;
|
||||
@@ -1286,11 +1286,10 @@ static uint32_t readGfxConstant() {
|
||||
}
|
||||
|
||||
if (width == 0) {
|
||||
error("Invalid graphics constant, no digits after '`'\n");
|
||||
error("Invalid graphics constant, no digits after '`'");
|
||||
} else if (width == 9) {
|
||||
warning(
|
||||
WARNING_LARGE_CONSTANT,
|
||||
"Graphics constant is too long, only first 8 pixels considered\n"
|
||||
WARNING_LARGE_CONSTANT, "Graphics constant is too long, only first 8 pixels considered"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1320,7 +1319,7 @@ static Token readIdentifier(char firstChar, bool raw) {
|
||||
if (!raw) {
|
||||
if (auto search = keywordDict.find(identifier); search != keywordDict.end()) {
|
||||
if (search == ldio) {
|
||||
warning(WARNING_OBSOLETE, "LDIO is deprecated; use LDH\n");
|
||||
warning(WARNING_OBSOLETE, "LDIO is deprecated; use LDH");
|
||||
}
|
||||
return Token(search->second);
|
||||
}
|
||||
@@ -1338,7 +1337,7 @@ static Token readIdentifier(char firstChar, bool raw) {
|
||||
|
||||
static std::shared_ptr<std::string> readInterpolation(size_t depth) {
|
||||
if (depth > maxRecursionDepth) {
|
||||
fatalerror("Recursion limit (%zu) exceeded\n", maxRecursionDepth);
|
||||
fatalerror("Recursion limit (%zu) exceeded", maxRecursionDepth);
|
||||
}
|
||||
|
||||
std::string fmtBuf;
|
||||
@@ -1360,7 +1359,7 @@ static std::shared_ptr<std::string> readInterpolation(size_t depth) {
|
||||
}
|
||||
continue; // Restart, reading from the new buffer
|
||||
} else if (c == EOF || c == '\r' || c == '\n' || c == '"') {
|
||||
error("Missing }\n");
|
||||
error("Missing }");
|
||||
break;
|
||||
} else if (c == '}') {
|
||||
shiftChar();
|
||||
@@ -1372,7 +1371,7 @@ static std::shared_ptr<std::string> readInterpolation(size_t depth) {
|
||||
}
|
||||
fmt.finishCharacters();
|
||||
if (!fmt.isValid()) {
|
||||
error("Invalid format spec '%s'\n", fmtBuf.c_str());
|
||||
error("Invalid format spec '%s'", fmtBuf.c_str());
|
||||
}
|
||||
fmtBuf.clear(); // Now that format has been set, restart at beginning of string
|
||||
} else {
|
||||
@@ -1391,7 +1390,7 @@ static std::shared_ptr<std::string> readInterpolation(size_t depth) {
|
||||
// Don't allow symbols that alias keywords without a '#' prefix.
|
||||
error(
|
||||
"Interpolated symbol \"%s\" is a reserved keyword; add a '#' prefix to use it as a raw "
|
||||
"symbol\n",
|
||||
"symbol",
|
||||
fmtBuf.c_str()
|
||||
);
|
||||
return nullptr;
|
||||
@@ -1401,9 +1400,9 @@ static std::shared_ptr<std::string> readInterpolation(size_t depth) {
|
||||
|
||||
if (!sym || !sym->isDefined()) {
|
||||
if (sym_IsPurgedScoped(fmtBuf)) {
|
||||
error("Interpolated symbol \"%s\" does not exist; it was purged\n", fmtBuf.c_str());
|
||||
error("Interpolated symbol \"%s\" does not exist; it was purged", fmtBuf.c_str());
|
||||
} else {
|
||||
error("Interpolated symbol \"%s\" does not exist\n", fmtBuf.c_str());
|
||||
error("Interpolated symbol \"%s\" does not exist", fmtBuf.c_str());
|
||||
}
|
||||
} else if (sym->type == SYM_EQUS) {
|
||||
auto buf = std::make_shared<std::string>();
|
||||
@@ -1414,7 +1413,7 @@ static std::shared_ptr<std::string> readInterpolation(size_t depth) {
|
||||
fmt.appendNumber(*buf, sym->getConstantValue());
|
||||
return buf;
|
||||
} else {
|
||||
error("Interpolated symbol \"%s\" is not a numeric or string symbol\n", fmtBuf.c_str());
|
||||
error("Interpolated symbol \"%s\" is not a numeric or string symbol", fmtBuf.c_str());
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
@@ -1472,7 +1471,7 @@ static std::string readString(bool raw) {
|
||||
|
||||
// '\r', '\n' or EOF ends a single-line string early
|
||||
if (c == EOF || (!multiline && (c == '\r' || c == '\n'))) {
|
||||
error("Unterminated string\n");
|
||||
error("Unterminated string");
|
||||
return str;
|
||||
}
|
||||
|
||||
@@ -1560,12 +1559,12 @@ static std::string readString(bool raw) {
|
||||
continue; // Do not copy an additional character
|
||||
|
||||
case EOF: // Can't really print that one
|
||||
error("Illegal character escape at end of input\n");
|
||||
error("Illegal character escape at end of input");
|
||||
c = '\\';
|
||||
break;
|
||||
|
||||
default:
|
||||
error("Illegal character escape %s\n", printChar(c));
|
||||
error("Illegal character escape %s", printChar(c));
|
||||
shiftChar();
|
||||
break;
|
||||
}
|
||||
@@ -1616,7 +1615,7 @@ static void appendStringLiteral(std::string &str, bool raw) {
|
||||
|
||||
// '\r', '\n' or EOF ends a single-line string early
|
||||
if (c == EOF || (!multiline && (c == '\r' || c == '\n'))) {
|
||||
error("Unterminated string\n");
|
||||
error("Unterminated string");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1697,12 +1696,12 @@ static void appendStringLiteral(std::string &str, bool raw) {
|
||||
}
|
||||
|
||||
case EOF: // Can't really print that one
|
||||
error("Illegal character escape at end of input\n");
|
||||
error("Illegal character escape at end of input");
|
||||
c = '\\';
|
||||
break;
|
||||
|
||||
default:
|
||||
error("Illegal character escape %s\n", printChar(c));
|
||||
error("Illegal character escape %s", printChar(c));
|
||||
shiftChar();
|
||||
break;
|
||||
}
|
||||
@@ -2077,9 +2076,9 @@ static Token yylex_NORMAL() {
|
||||
garbage += ", ";
|
||||
garbage += printChar(c);
|
||||
}
|
||||
error("Unknown characters %s\n", garbage.c_str());
|
||||
error("Unknown characters %s", garbage.c_str());
|
||||
} else {
|
||||
error("Unknown character %s\n", printChar(c));
|
||||
error("Unknown character %s", printChar(c));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2203,7 +2202,7 @@ backslash:
|
||||
continue;
|
||||
|
||||
case EOF: // Can't really print that one
|
||||
error("Illegal character escape at end of input\n");
|
||||
error("Illegal character escape at end of input");
|
||||
c = '\\';
|
||||
break;
|
||||
|
||||
@@ -2211,7 +2210,7 @@ backslash:
|
||||
// '\#', and '\0'-'\9' should not occur here.
|
||||
|
||||
default:
|
||||
error("Illegal character escape %s\n", printChar(c));
|
||||
error("Illegal character escape %s", printChar(c));
|
||||
break;
|
||||
}
|
||||
[[fallthrough]];
|
||||
@@ -2293,7 +2292,7 @@ static Token skipIfBlock(bool toEndc) {
|
||||
case T_(POP_ELIF):
|
||||
if (lexer_ReachedELSEBlock()) {
|
||||
// This should be redundant, as the parser handles this error first.
|
||||
fatalerror("Found ELIF after an ELSE block\n"); // LCOV_EXCL_LINE
|
||||
fatalerror("Found ELIF after an ELSE block"); // LCOV_EXCL_LINE
|
||||
}
|
||||
if (!toEndc && lexer_GetIFDepth() == startingDepth) {
|
||||
return token;
|
||||
@@ -2302,7 +2301,7 @@ static Token skipIfBlock(bool toEndc) {
|
||||
|
||||
case T_(POP_ELSE):
|
||||
if (lexer_ReachedELSEBlock()) {
|
||||
fatalerror("Found ELSE after an ELSE block\n");
|
||||
fatalerror("Found ELSE after an ELSE block");
|
||||
}
|
||||
lexer_ReachELSEBlock();
|
||||
if (!toEndc && lexer_GetIFDepth() == startingDepth) {
|
||||
@@ -2552,7 +2551,7 @@ Capture lexer_CaptureRept() {
|
||||
// Just consume characters until EOL or EOF
|
||||
for (;; c = nextChar()) {
|
||||
if (c == EOF) {
|
||||
error("Unterminated REPT/FOR block\n");
|
||||
error("Unterminated REPT/FOR block");
|
||||
endCapture(capture);
|
||||
capture.span.ptr = nullptr; // Indicates that it reached EOF before an ENDR
|
||||
return capture;
|
||||
@@ -2595,7 +2594,7 @@ Capture lexer_CaptureMacro() {
|
||||
// Just consume characters until EOL or EOF
|
||||
for (;; c = nextChar()) {
|
||||
if (c == EOF) {
|
||||
error("Unterminated macro definition\n");
|
||||
error("Unterminated macro definition");
|
||||
endCapture(capture);
|
||||
capture.span.ptr = nullptr; // Indicates that it reached EOF before an ENDM
|
||||
return capture;
|
||||
|
||||
@@ -52,7 +52,7 @@ std::shared_ptr<std::string> MacroArgs::getAllArgs() const {
|
||||
|
||||
void MacroArgs::appendArg(std::shared_ptr<std::string> arg) {
|
||||
if (arg->empty()) {
|
||||
warning(WARNING_EMPTY_MACRO_ARG, "Empty macro argument\n");
|
||||
warning(WARNING_EMPTY_MACRO_ARG, "Empty macro argument");
|
||||
}
|
||||
args.push_back(arg);
|
||||
}
|
||||
@@ -60,10 +60,10 @@ void MacroArgs::appendArg(std::shared_ptr<std::string> arg) {
|
||||
void MacroArgs::shiftArgs(int32_t count) {
|
||||
if (size_t nbArgs = args.size();
|
||||
count > 0 && (static_cast<uint32_t>(count) > nbArgs || shift > nbArgs - count)) {
|
||||
warning(WARNING_MACRO_SHIFT, "Cannot shift macro arguments past their end\n");
|
||||
warning(WARNING_MACRO_SHIFT, "Cannot shift macro arguments past their end");
|
||||
shift = nbArgs;
|
||||
} else if (count < 0 && shift < static_cast<uint32_t>(-count)) {
|
||||
warning(WARNING_MACRO_SHIFT, "Cannot shift macro arguments past their beginning\n");
|
||||
warning(WARNING_MACRO_SHIFT, "Cannot shift macro arguments past their beginning");
|
||||
shift = 0;
|
||||
} else {
|
||||
shift += count;
|
||||
|
||||
@@ -3,8 +3,10 @@
|
||||
#include "asm/main.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <memory>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
@@ -109,6 +111,19 @@ static void printUsage() {
|
||||
}
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
[[gnu::format(printf, 1, 2), noreturn]]
|
||||
static void fatalWithUsage(char const *fmt, ...) {
|
||||
va_list ap;
|
||||
fputs("FATAL: ", stderr);
|
||||
va_start(ap, fmt);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
putc('\n', stderr);
|
||||
|
||||
printUsage();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
time_t now = time(nullptr);
|
||||
// Support SOURCE_DATE_EPOCH for reproducible builds
|
||||
@@ -198,7 +213,9 @@ int main(int argc, char *argv[]) {
|
||||
dependFileName = "<stdout>";
|
||||
}
|
||||
if (dependFile == nullptr) {
|
||||
err("Failed to open dependfile \"%s\"", dependFileName); // LCOV_EXCL_LINE
|
||||
// LCOV_EXCL_START
|
||||
errx("Failed to open dependfile \"%s\": %s", dependFileName, strerror(errno));
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -386,15 +403,9 @@ int main(int argc, char *argv[]) {
|
||||
}
|
||||
|
||||
if (argc == musl_optind) {
|
||||
fputs(
|
||||
"FATAL: Please specify an input file (pass `-` to read from standard input)\n", stderr
|
||||
);
|
||||
printUsage();
|
||||
exit(1);
|
||||
fatalWithUsage("Please specify an input file (pass `-` to read from standard input)");
|
||||
} else if (argc != musl_optind + 1) {
|
||||
fputs("FATAL: More than one input file specified\n", stderr);
|
||||
printUsage();
|
||||
exit(1);
|
||||
fatalWithUsage("More than one input file specified");
|
||||
}
|
||||
|
||||
std::string mainFileName = argv[musl_optind];
|
||||
|
||||
@@ -47,7 +47,7 @@ void opt_R(size_t newDepth) {
|
||||
|
||||
void opt_W(char const *flag) {
|
||||
if (warnings.processWarningFlag(flag) == "numeric-string") {
|
||||
warning(WARNING_OBSOLETE, "Warning flag \"numeric-string\" is deprecated\n");
|
||||
warning(WARNING_OBSOLETE, "Warning flag \"numeric-string\" is deprecated");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ void opt_Parse(char const *s) {
|
||||
if (strlen(&s[1]) == 2) {
|
||||
opt_B(&s[1]);
|
||||
} else {
|
||||
error("Must specify exactly 2 characters for option 'b'\n");
|
||||
error("Must specify exactly 2 characters for option 'b'");
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -65,7 +65,7 @@ void opt_Parse(char const *s) {
|
||||
if (strlen(&s[1]) == 4) {
|
||||
opt_G(&s[1]);
|
||||
} else {
|
||||
error("Must specify exactly 4 characters for option 'g'\n");
|
||||
error("Must specify exactly 4 characters for option 'g'");
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -76,14 +76,14 @@ void opt_Parse(char const *s) {
|
||||
|
||||
result = sscanf(&s[1], "%x", &padByte);
|
||||
if (result != 1) {
|
||||
error("Invalid argument for option 'p'\n");
|
||||
error("Invalid argument for option 'p'");
|
||||
} else if (padByte > 0xFF) {
|
||||
error("Argument for option 'p' must be between 0 and 0xFF\n");
|
||||
error("Argument for option 'p' must be between 0 and 0xFF");
|
||||
} else {
|
||||
opt_P(padByte);
|
||||
}
|
||||
} else {
|
||||
error("Invalid argument for option 'p'\n");
|
||||
error("Invalid argument for option 'p'");
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -99,14 +99,14 @@ void opt_Parse(char const *s) {
|
||||
|
||||
result = sscanf(precisionArg, "%u", &precision);
|
||||
if (result != 1) {
|
||||
error("Invalid argument for option 'Q'\n");
|
||||
error("Invalid argument for option 'Q'");
|
||||
} else if (precision < 1 || precision > 31) {
|
||||
error("Argument for option 'Q' must be between 1 and 31\n");
|
||||
error("Argument for option 'Q' must be between 1 and 31");
|
||||
} else {
|
||||
opt_Q(precision);
|
||||
}
|
||||
} else {
|
||||
error("Invalid argument for option 'Q'\n");
|
||||
error("Invalid argument for option 'Q'");
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -117,7 +117,7 @@ void opt_Parse(char const *s) {
|
||||
}
|
||||
|
||||
if (s[0] == '\0') {
|
||||
error("Missing argument to option 'r'\n");
|
||||
error("Missing argument to option 'r'");
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -125,9 +125,9 @@ void opt_Parse(char const *s) {
|
||||
unsigned long newDepth = strtoul(s, &endptr, 10);
|
||||
|
||||
if (*endptr != '\0') {
|
||||
error("Invalid argument to option 'r' (\"%s\")\n", s);
|
||||
error("Invalid argument to option 'r' (\"%s\")", s);
|
||||
} else if (errno == ERANGE) {
|
||||
error("Argument to 'r' is out of range (\"%s\")\n", s);
|
||||
error("Argument to 'r' is out of range (\"%s\")", s);
|
||||
} else {
|
||||
opt_R(newDepth);
|
||||
}
|
||||
@@ -138,12 +138,12 @@ void opt_Parse(char const *s) {
|
||||
if (strlen(&s[1]) > 0) {
|
||||
opt_W(&s[1]);
|
||||
} else {
|
||||
error("Must specify an argument for option 'W'\n");
|
||||
error("Must specify an argument for option 'W'");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
error("Unknown option '%c'\n", s[0]);
|
||||
error("Unknown option '%c'", s[0]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -168,7 +168,7 @@ void opt_Push() {
|
||||
|
||||
void opt_Pop() {
|
||||
if (stack.empty()) {
|
||||
error("No entries in the option stack\n");
|
||||
error("No entries in the option stack");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -187,6 +187,6 @@ void opt_Pop() {
|
||||
|
||||
void opt_CheckStack() {
|
||||
if (!stack.empty()) {
|
||||
warning(WARNING_UNMATCHED_DIRECTIVE, "`PUSHO` without corresponding `POPO`\n");
|
||||
warning(WARNING_UNMATCHED_DIRECTIVE, "`PUSHO` without corresponding `POPO`");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <deque>
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -72,7 +73,7 @@ static uint32_t getSectIDIfAny(Section *sect) {
|
||||
}
|
||||
|
||||
// Every section that exists should be in `sectionMap`
|
||||
fatalerror("Unknown section '%s'\n", sect->name.c_str()); // LCOV_EXCL_LINE
|
||||
fatalerror("Unknown section '%s'", sect->name.c_str()); // LCOV_EXCL_LINE
|
||||
}
|
||||
|
||||
static void writePatch(Patch const &patch, FILE *file) {
|
||||
@@ -324,7 +325,9 @@ void out_WriteObject() {
|
||||
file = stdout;
|
||||
}
|
||||
if (!file) {
|
||||
err("Failed to open object file '%s'", objectFileName.c_str()); // LCOV_EXCL_LINE
|
||||
// LCOV_EXCL_START
|
||||
errx("Failed to open object file '%s': %s", objectFileName.c_str(), strerror(errno));
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
Defer closeFile{[&] { fclose(file); }};
|
||||
|
||||
@@ -524,7 +527,9 @@ void out_WriteState(std::string name, std::vector<StateFeature> const &features)
|
||||
file = stdout;
|
||||
}
|
||||
if (!file) {
|
||||
err("Failed to open state file '%s'", name.c_str()); // LCOV_EXCL_LINE
|
||||
// LCOV_EXCL_START
|
||||
errx("Failed to open state file '%s': %s", name.c_str(), strerror(errno));
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
Defer closeFile{[&] { fclose(file); }};
|
||||
|
||||
|
||||
118
src/asm/parser.y
118
src/asm/parser.y
@@ -438,12 +438,12 @@ diff_mark:
|
||||
%empty // OK
|
||||
| OP_ADD {
|
||||
::error(
|
||||
"syntax error, unexpected + at the beginning of the line (is it a leftover diff mark?)\n"
|
||||
"syntax error, unexpected + at the beginning of the line (is it a leftover diff mark?)"
|
||||
);
|
||||
}
|
||||
| OP_SUB {
|
||||
::error(
|
||||
"syntax error, unexpected - at the beginning of the line (is it a leftover diff mark?)\n"
|
||||
"syntax error, unexpected - at the beginning of the line (is it a leftover diff mark?)"
|
||||
);
|
||||
}
|
||||
;
|
||||
@@ -488,11 +488,11 @@ if:
|
||||
elif:
|
||||
POP_ELIF iconst NEWLINE {
|
||||
if (lexer_GetIFDepth() == 0) {
|
||||
fatalerror("Found ELIF outside of an IF construct\n");
|
||||
fatalerror("Found ELIF outside of an IF construct");
|
||||
}
|
||||
if (lexer_RanIFBlock()) {
|
||||
if (lexer_ReachedELSEBlock()) {
|
||||
fatalerror("Found ELIF after an ELSE block\n");
|
||||
fatalerror("Found ELIF after an ELSE block");
|
||||
}
|
||||
lexer_SetMode(LEXER_SKIP_TO_ENDC);
|
||||
} else if ($2) {
|
||||
@@ -506,11 +506,11 @@ elif:
|
||||
else:
|
||||
POP_ELSE NEWLINE {
|
||||
if (lexer_GetIFDepth() == 0) {
|
||||
fatalerror("Found ELSE outside of an IF construct\n");
|
||||
fatalerror("Found ELSE outside of an IF construct");
|
||||
}
|
||||
if (lexer_RanIFBlock()) {
|
||||
if (lexer_ReachedELSEBlock()) {
|
||||
fatalerror("Found ELSE after an ELSE block\n");
|
||||
fatalerror("Found ELSE after an ELSE block");
|
||||
}
|
||||
lexer_SetMode(LEXER_SKIP_TO_ENDC);
|
||||
} else {
|
||||
@@ -695,7 +695,7 @@ align:
|
||||
align_spec:
|
||||
uconst {
|
||||
if ($1 > 16) {
|
||||
::error("Alignment must be between 0 and 16, not %u\n", $1);
|
||||
::error("Alignment must be between 0 and 16, not %u", $1);
|
||||
$$.alignment = $$.alignOfs = 0;
|
||||
} else {
|
||||
$$.alignment = $1;
|
||||
@@ -704,11 +704,11 @@ align_spec:
|
||||
}
|
||||
| uconst COMMA iconst {
|
||||
if ($1 > 16) {
|
||||
::error("Alignment must be between 0 and 16, not %u\n", $1);
|
||||
::error("Alignment must be between 0 and 16, not %u", $1);
|
||||
$$.alignment = $$.alignOfs = 0;
|
||||
} else if ($3 <= -(1 << $1) || $3 >= 1 << $1) {
|
||||
::error(
|
||||
"The absolute alignment offset (%" PRIu32 ") must be less than alignment size (%d)\n",
|
||||
"The absolute alignment offset (%" PRIu32 ") must be less than alignment size (%d)",
|
||||
static_cast<uint32_t>($3 < 0 ? -$3 : $3),
|
||||
1 << $1
|
||||
);
|
||||
@@ -779,13 +779,13 @@ endsection:
|
||||
|
||||
fail:
|
||||
POP_FAIL string {
|
||||
fatalerror("%s\n", $2.c_str());
|
||||
fatalerror("%s", $2.c_str());
|
||||
}
|
||||
;
|
||||
|
||||
warn:
|
||||
POP_WARN string {
|
||||
warning(WARNING_USER, "%s\n", $2.c_str());
|
||||
warning(WARNING_USER, "%s", $2.c_str());
|
||||
}
|
||||
;
|
||||
|
||||
@@ -836,7 +836,7 @@ shift:
|
||||
if (MacroArgs *macroArgs = fstk_GetCurrentMacroArgs(); macroArgs) {
|
||||
macroArgs->shiftArgs($2);
|
||||
} else {
|
||||
::error("Cannot shift macro arguments outside of a macro\n");
|
||||
::error("Cannot shift macro arguments outside of a macro");
|
||||
}
|
||||
}
|
||||
;
|
||||
@@ -1577,7 +1577,7 @@ relocexpr_no_str:
|
||||
| OP_CHARSIZE LPAREN string RPAREN {
|
||||
size_t charSize = charmap_CharSize($3);
|
||||
if (charSize == 0) {
|
||||
::error("CHARSIZE: No character mapping for \"%s\"\n", $3.c_str());
|
||||
::error("CHARSIZE: No character mapping for \"%s\"", $3.c_str());
|
||||
}
|
||||
$$.makeNumber(charSize);
|
||||
}
|
||||
@@ -1589,13 +1589,13 @@ relocexpr_no_str:
|
||||
} else {
|
||||
warning(
|
||||
WARNING_BUILTIN_ARG,
|
||||
"CHARVAL: Index %" PRIu32 " is past the end of the character mapping\n",
|
||||
"CHARVAL: Index %" PRIu32 " is past the end of the character mapping",
|
||||
idx
|
||||
);
|
||||
$$.makeNumber(0);
|
||||
}
|
||||
} else {
|
||||
::error("CHARVAL: No character mapping for \"%s\"\n", $3.c_str());
|
||||
::error("CHARVAL: No character mapping for \"%s\"", $3.c_str());
|
||||
$$.makeNumber(0);
|
||||
}
|
||||
}
|
||||
@@ -1608,7 +1608,7 @@ uconst:
|
||||
iconst {
|
||||
$$ = $1;
|
||||
if ($$ < 0) {
|
||||
fatalerror("Constant must not be negative: %d\n", $$);
|
||||
fatalerror("Constant must not be negative: %d", $$);
|
||||
}
|
||||
}
|
||||
;
|
||||
@@ -1626,7 +1626,7 @@ precision_arg:
|
||||
| COMMA iconst {
|
||||
$$ = $2;
|
||||
if ($$ < 1 || $$ > 31) {
|
||||
::error("Fixed-point precision must be between 1 and 31, not %" PRId32 "\n", $$);
|
||||
::error("Fixed-point precision must be between 1 and 31, not %" PRId32, $$);
|
||||
$$ = fix_Precision();
|
||||
}
|
||||
}
|
||||
@@ -1675,9 +1675,9 @@ string_literal:
|
||||
bool unique;
|
||||
$$ = charmap_Reverse($3, unique);
|
||||
if (!unique) {
|
||||
::error("REVCHAR: Multiple character mappings to values\n");
|
||||
::error("REVCHAR: Multiple character mappings to values");
|
||||
} else if ($$.empty()) {
|
||||
::error("REVCHAR: No character mapping to values\n");
|
||||
::error("REVCHAR: No character mapping to values");
|
||||
}
|
||||
}
|
||||
| OP_STRCAT LPAREN RPAREN {
|
||||
@@ -1705,15 +1705,15 @@ string_literal:
|
||||
|
||||
if (!sym) {
|
||||
if (sym_IsPurgedScoped($3)) {
|
||||
fatalerror("Unknown symbol \"%s\"; it was purged\n", $3.c_str());
|
||||
fatalerror("Unknown symbol \"%s\"; it was purged", $3.c_str());
|
||||
} else {
|
||||
fatalerror("Unknown symbol \"%s\"\n", $3.c_str());
|
||||
fatalerror("Unknown symbol \"%s\"", $3.c_str());
|
||||
}
|
||||
}
|
||||
Section const *section = sym->getSection();
|
||||
|
||||
if (!section) {
|
||||
fatalerror("\"%s\" does not belong to any section\n", sym->name.c_str());
|
||||
fatalerror("\"%s\" does not belong to any section", sym->name.c_str());
|
||||
}
|
||||
// Section names are capped by rgbasm's maximum string length,
|
||||
// so this currently can't overflow.
|
||||
@@ -1729,7 +1729,7 @@ string:
|
||||
if (Symbol *sym = sym_FindScopedSymbol($1); sym && sym->type == SYM_EQUS) {
|
||||
$$ = *sym->getEqus();
|
||||
} else {
|
||||
::error("'%s' is not a string symbol\n", $1.c_str());
|
||||
::error("'%s' is not a string symbol", $1.c_str());
|
||||
}
|
||||
}
|
||||
;
|
||||
@@ -1833,7 +1833,7 @@ sect_org:
|
||||
| LBRACK uconst RBRACK {
|
||||
$$ = $2;
|
||||
if ($$ < 0 || $$ > 0xFFFF) {
|
||||
::error("Address $%x is not 16-bit\n", $$);
|
||||
::error("Address $%x is not 16-bit", $$);
|
||||
$$ = -1;
|
||||
}
|
||||
}
|
||||
@@ -2088,7 +2088,7 @@ sm83_ldh:
|
||||
if ($4.makeCheckHRAM()) {
|
||||
warning(
|
||||
WARNING_OBSOLETE,
|
||||
"LDH is deprecated with values from $00 to $FF; use $FF00 to $FFFF\n"
|
||||
"LDH is deprecated with values from $00 to $FF; use $FF00 to $FFFF"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2099,7 +2099,7 @@ sm83_ldh:
|
||||
if ($2.makeCheckHRAM()) {
|
||||
warning(
|
||||
WARNING_OBSOLETE,
|
||||
"LDH is deprecated with values from $00 to $FF; use $FF00 to $FFFF\n"
|
||||
"LDH is deprecated with values from $00 to $FF; use $FF00 to $FFFF"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2126,7 +2126,7 @@ ff00_c_ind:
|
||||
LBRACK relocexpr OP_ADD MODE_C RBRACK {
|
||||
// This has to use `relocexpr`, not `iconst`, to avoid a shift/reduce conflict
|
||||
if ($2.getConstVal() != 0xFF00) {
|
||||
::error("Base value must be equal to $FF00 for $FF00+C\n");
|
||||
::error("Base value must be equal to $FF00 for $FF00+C");
|
||||
}
|
||||
}
|
||||
;
|
||||
@@ -2148,7 +2148,7 @@ sm83_ld_hl:
|
||||
sect_RelByte($5, 1);
|
||||
}
|
||||
| SM83_LD MODE_HL COMMA MODE_SP {
|
||||
::error("LD HL, SP is not a valid instruction; use LD HL, SP + 0\n");
|
||||
::error("LD HL, SP is not a valid instruction; use LD HL, SP + 0");
|
||||
}
|
||||
| SM83_LD MODE_HL COMMA reloc_16bit {
|
||||
sect_ConstByte(0x01 | (REG_HL << 4));
|
||||
@@ -2156,7 +2156,7 @@ sm83_ld_hl:
|
||||
}
|
||||
| SM83_LD MODE_HL COMMA reg_tt_no_af {
|
||||
::error(
|
||||
"LD HL, %s is not a valid instruction; use LD H, %s and LD L, %s\n",
|
||||
"LD HL, %s is not a valid instruction; use LD H, %s and LD L, %s",
|
||||
reg_tt_names[$4],
|
||||
reg_tt_high_names[$4],
|
||||
reg_tt_low_names[$4]
|
||||
@@ -2169,7 +2169,7 @@ sm83_ld_sp:
|
||||
sect_ConstByte(0xF9);
|
||||
}
|
||||
| SM83_LD MODE_SP COMMA reg_bc_or_de {
|
||||
::error("LD SP, %s is not a valid instruction\n", reg_tt_names[$4]);
|
||||
::error("LD SP, %s is not a valid instruction", reg_tt_names[$4]);
|
||||
}
|
||||
| SM83_LD MODE_SP COMMA reloc_16bit {
|
||||
sect_ConstByte(0x01 | (REG_SP << 4));
|
||||
@@ -2193,7 +2193,7 @@ sm83_ld_c_ind:
|
||||
sect_ConstByte(0xE2);
|
||||
}
|
||||
| SM83_LD c_ind COMMA MODE_A {
|
||||
warning(WARNING_OBSOLETE, "LD [C], A is deprecated; use LDH [C], A\n");
|
||||
warning(WARNING_OBSOLETE, "LD [C], A is deprecated; use LDH [C], A");
|
||||
sect_ConstByte(0xE2);
|
||||
}
|
||||
;
|
||||
@@ -2211,7 +2211,7 @@ sm83_ld_r_no_a:
|
||||
}
|
||||
| SM83_LD reg_r_no_a COMMA reg_r {
|
||||
if ($2 == REG_HL_IND && $4 == REG_HL_IND) {
|
||||
::error("LD [HL], [HL] is not a valid instruction\n");
|
||||
::error("LD [HL], [HL] is not a valid instruction");
|
||||
} else {
|
||||
sect_ConstByte(0x40 | ($2 << 3) | $4);
|
||||
}
|
||||
@@ -2230,7 +2230,7 @@ sm83_ld_a:
|
||||
sect_ConstByte(0xF2);
|
||||
}
|
||||
| SM83_LD reg_a COMMA c_ind {
|
||||
warning(WARNING_OBSOLETE, "LD A, [C] is deprecated; use LDH A, [C]\n");
|
||||
warning(WARNING_OBSOLETE, "LD A, [C] is deprecated; use LDH A, [C]");
|
||||
sect_ConstByte(0xF2);
|
||||
}
|
||||
| SM83_LD reg_a COMMA reg_rr {
|
||||
@@ -2249,7 +2249,7 @@ sm83_ld_ss:
|
||||
}
|
||||
| SM83_LD reg_bc_or_de COMMA reg_tt_no_af {
|
||||
::error(
|
||||
"LD %s, %s is not a valid instruction; use LD %s, %s and LD %s, %s\n",
|
||||
"LD %s, %s is not a valid instruction; use LD %s, %s and LD %s, %s",
|
||||
reg_tt_names[$2],
|
||||
reg_tt_names[$4],
|
||||
reg_tt_high_names[$2],
|
||||
@@ -2644,7 +2644,7 @@ hl_ind_dec:
|
||||
/******************** Semantic actions ********************/
|
||||
|
||||
void yy::parser::error(std::string const &str) {
|
||||
::error("%s\n", str.c_str());
|
||||
::error("%s", str.c_str());
|
||||
}
|
||||
|
||||
static uint32_t strToNum(std::vector<int32_t> const &s) {
|
||||
@@ -2656,7 +2656,7 @@ static uint32_t strToNum(std::vector<int32_t> const &s) {
|
||||
return static_cast<uint32_t>(s[0]);
|
||||
}
|
||||
|
||||
warning(WARNING_OBSOLETE, "Treating multi-unit strings as numbers is deprecated\n");
|
||||
warning(WARNING_OBSOLETE, "Treating multi-unit strings as numbers is deprecated");
|
||||
|
||||
for (int32_t v : s) {
|
||||
if (!checkNBit(v, 8, "All character units")) {
|
||||
@@ -2675,7 +2675,7 @@ static uint32_t strToNum(std::vector<int32_t> const &s) {
|
||||
}
|
||||
|
||||
static void errorInvalidUTF8Byte(uint8_t byte, char const *functionName) {
|
||||
error("%s: Invalid UTF-8 byte 0x%02hhX\n", functionName, byte);
|
||||
error("%s: Invalid UTF-8 byte 0x%02hhX", functionName, byte);
|
||||
}
|
||||
|
||||
static size_t strlenUTF8(std::string const &str, bool printErrors) {
|
||||
@@ -2702,7 +2702,7 @@ static size_t strlenUTF8(std::string const &str, bool printErrors) {
|
||||
// Check for partial code point.
|
||||
if (state != 0) {
|
||||
if (printErrors) {
|
||||
error("STRLEN: Incomplete UTF-8 character\n");
|
||||
error("STRLEN: Incomplete UTF-8 character");
|
||||
}
|
||||
len++;
|
||||
}
|
||||
@@ -2736,7 +2736,7 @@ static std::string strsliceUTF8(std::string const &str, uint32_t start, uint32_t
|
||||
if (!ptr[index] && start > curIdx) {
|
||||
warning(
|
||||
WARNING_BUILTIN_ARG,
|
||||
"STRSLICE: Start index %" PRIu32 " is past the end of the string\n",
|
||||
"STRSLICE: Start index %" PRIu32 " is past the end of the string",
|
||||
start
|
||||
);
|
||||
}
|
||||
@@ -2759,14 +2759,14 @@ static std::string strsliceUTF8(std::string const &str, uint32_t start, uint32_t
|
||||
|
||||
// Check for partial code point.
|
||||
if (state != 0) {
|
||||
error("STRSLICE: Incomplete UTF-8 character\n");
|
||||
error("STRSLICE: Incomplete UTF-8 character");
|
||||
curIdx++;
|
||||
}
|
||||
|
||||
if (curIdx < stop) {
|
||||
warning(
|
||||
WARNING_BUILTIN_ARG,
|
||||
"STRSLICE: Stop index %" PRIu32 " is past the end of the string\n",
|
||||
"STRSLICE: Stop index %" PRIu32 " is past the end of the string",
|
||||
stop
|
||||
);
|
||||
}
|
||||
@@ -2799,7 +2799,7 @@ static std::string strsubUTF8(std::string const &str, uint32_t pos, uint32_t len
|
||||
// "Length too big" warning below if the length is nonzero.
|
||||
if (!ptr[index] && pos > curPos) {
|
||||
warning(
|
||||
WARNING_BUILTIN_ARG, "STRSUB: Position %" PRIu32 " is past the end of the string\n", pos
|
||||
WARNING_BUILTIN_ARG, "STRSUB: Position %" PRIu32 " is past the end of the string", pos
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2822,12 +2822,12 @@ static std::string strsubUTF8(std::string const &str, uint32_t pos, uint32_t len
|
||||
|
||||
// Check for partial code point.
|
||||
if (state != 0) {
|
||||
error("STRSUB: Incomplete UTF-8 character\n");
|
||||
error("STRSUB: Incomplete UTF-8 character");
|
||||
curLen++;
|
||||
}
|
||||
|
||||
if (curLen < len) {
|
||||
warning(WARNING_BUILTIN_ARG, "STRSUB: Length too big: %" PRIu32 "\n", len);
|
||||
warning(WARNING_BUILTIN_ARG, "STRSUB: Length too big: %" PRIu32, len);
|
||||
}
|
||||
|
||||
return std::string(ptr + startIndex, ptr + index);
|
||||
@@ -2856,7 +2856,7 @@ static std::string strcharUTF8(std::string const &str, uint32_t idx) {
|
||||
if (!charmap_ConvertNext(view, nullptr)) {
|
||||
warning(
|
||||
WARNING_BUILTIN_ARG,
|
||||
"STRCHAR: Index %" PRIu32 " is past the end of the string\n",
|
||||
"STRCHAR: Index %" PRIu32 " is past the end of the string",
|
||||
idx
|
||||
);
|
||||
}
|
||||
@@ -2879,7 +2879,7 @@ static std::string charsubUTF8(std::string const &str, uint32_t pos) {
|
||||
if (!charmap_ConvertNext(view, nullptr)) {
|
||||
warning(
|
||||
WARNING_BUILTIN_ARG,
|
||||
"CHARSUB: Position %" PRIu32 " is past the end of the string\n",
|
||||
"CHARSUB: Position %" PRIu32 " is past the end of the string",
|
||||
pos
|
||||
);
|
||||
}
|
||||
@@ -2922,7 +2922,7 @@ static uint32_t adjustNegativeIndex(int32_t idx, size_t len, char const *functio
|
||||
idx += len;
|
||||
}
|
||||
if (idx < 0) {
|
||||
warning(WARNING_BUILTIN_ARG, "%s: Index starts at 0\n", functionName);
|
||||
warning(WARNING_BUILTIN_ARG, "%s: Index starts at 0", functionName);
|
||||
idx = 0;
|
||||
}
|
||||
return static_cast<uint32_t>(idx);
|
||||
@@ -2935,7 +2935,7 @@ static uint32_t adjustNegativePos(int32_t pos, size_t len, char const *functionN
|
||||
pos += len + 1;
|
||||
}
|
||||
if (pos < 1) {
|
||||
warning(WARNING_BUILTIN_ARG, "%s: Position starts at 1\n", functionName);
|
||||
warning(WARNING_BUILTIN_ARG, "%s: Position starts at 1", functionName);
|
||||
pos = 1;
|
||||
}
|
||||
return static_cast<uint32_t>(pos);
|
||||
@@ -2943,7 +2943,7 @@ static uint32_t adjustNegativePos(int32_t pos, size_t len, char const *functionN
|
||||
|
||||
static std::string strrpl(std::string_view str, std::string const &old, std::string const &rep) {
|
||||
if (old.empty()) {
|
||||
warning(WARNING_EMPTY_STRRPL, "STRRPL: Cannot replace an empty string\n");
|
||||
warning(WARNING_EMPTY_STRRPL, "STRRPL: Cannot replace an empty string");
|
||||
return std::string(str);
|
||||
}
|
||||
|
||||
@@ -2994,13 +2994,13 @@ static std::string
|
||||
}
|
||||
|
||||
if (fmt.isEmpty()) {
|
||||
error("STRFMT: Illegal '%%' at end of format string\n");
|
||||
error("STRFMT: Illegal '%%' at end of format string");
|
||||
str += '%';
|
||||
break;
|
||||
}
|
||||
|
||||
if (!fmt.isValid()) {
|
||||
error("STRFMT: Invalid format spec for argument %zu\n", argIndex + 1);
|
||||
error("STRFMT: Invalid format spec for argument %zu", argIndex + 1);
|
||||
str += '%';
|
||||
} else if (argIndex >= args.size()) {
|
||||
// Will warn after formatting is done.
|
||||
@@ -3015,10 +3015,10 @@ static std::string
|
||||
}
|
||||
|
||||
if (argIndex < args.size()) {
|
||||
error("STRFMT: %zu unformatted argument(s)\n", args.size() - argIndex);
|
||||
error("STRFMT: %zu unformatted argument(s)", args.size() - argIndex);
|
||||
} else if (argIndex > args.size()) {
|
||||
error(
|
||||
"STRFMT: Not enough arguments for format spec, got: %zu, need: %zu\n",
|
||||
"STRFMT: Not enough arguments for format spec, got: %zu, need: %zu",
|
||||
args.size(),
|
||||
argIndex
|
||||
);
|
||||
@@ -3041,12 +3041,12 @@ static void compoundAssignment(std::string const &symName, RPNCommand op, int32_
|
||||
static void failAssert(AssertionType type) {
|
||||
switch (type) {
|
||||
case ASSERT_FATAL:
|
||||
fatalerror("Assertion failed\n");
|
||||
fatalerror("Assertion failed");
|
||||
case ASSERT_ERROR:
|
||||
error("Assertion failed\n");
|
||||
error("Assertion failed");
|
||||
break;
|
||||
case ASSERT_WARN:
|
||||
warning(WARNING_ASSERT, "Assertion failed\n");
|
||||
warning(WARNING_ASSERT, "Assertion failed");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -3054,12 +3054,12 @@ static void failAssert(AssertionType type) {
|
||||
static void failAssertMsg(AssertionType type, std::string const &message) {
|
||||
switch (type) {
|
||||
case ASSERT_FATAL:
|
||||
fatalerror("Assertion failed: %s\n", message.c_str());
|
||||
fatalerror("Assertion failed: %s", message.c_str());
|
||||
case ASSERT_ERROR:
|
||||
error("Assertion failed: %s\n", message.c_str());
|
||||
error("Assertion failed: %s", message.c_str());
|
||||
break;
|
||||
case ASSERT_WARN:
|
||||
warning(WARNING_ASSERT, "Assertion failed: %s\n", message.c_str());
|
||||
warning(WARNING_ASSERT, "Assertion failed: %s", message.c_str());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ uint8_t *Expression::reserveSpace(uint32_t size, uint32_t patchSize) {
|
||||
|
||||
int32_t Expression::getConstVal() const {
|
||||
if (!isKnown()) {
|
||||
error("Expected constant expression: %s\n", data.get<std::string>().c_str());
|
||||
error("Expected constant expression: %s", data.get<std::string>().c_str());
|
||||
return 0;
|
||||
}
|
||||
return value();
|
||||
@@ -73,10 +73,10 @@ void Expression::makeNumber(uint32_t value) {
|
||||
void Expression::makeSymbol(std::string const &symName) {
|
||||
clear();
|
||||
if (Symbol *sym = sym_FindScopedSymbol(symName); sym_IsPC(sym) && !sect_GetSymbolSection()) {
|
||||
error("PC has no value outside of a section\n");
|
||||
error("PC has no value outside of a section");
|
||||
data = 0;
|
||||
} else if (sym && !sym->isNumeric() && !sym->isLabel()) {
|
||||
error("'%s' is not a numeric symbol\n", symName.c_str());
|
||||
error("'%s' is not a numeric symbol", symName.c_str());
|
||||
data = 0;
|
||||
} else if (!sym || !sym->isConstant()) {
|
||||
isSymbol = true;
|
||||
@@ -103,7 +103,7 @@ void Expression::makeBankSymbol(std::string const &symName) {
|
||||
if (Symbol const *sym = sym_FindScopedSymbol(symName); sym_IsPC(sym)) {
|
||||
// The @ symbol is treated differently.
|
||||
if (!currentSection) {
|
||||
error("PC has no bank outside of a section\n");
|
||||
error("PC has no bank outside of a section");
|
||||
data = 1;
|
||||
} else if (currentSection->bank == UINT32_MAX) {
|
||||
data = "Current section's bank is not known";
|
||||
@@ -114,7 +114,7 @@ void Expression::makeBankSymbol(std::string const &symName) {
|
||||
}
|
||||
return;
|
||||
} else if (sym && !sym->isLabel()) {
|
||||
error("BANK argument must be a label\n");
|
||||
error("BANK argument must be a label");
|
||||
data = 1;
|
||||
} else {
|
||||
sym = sym_Ref(symName);
|
||||
@@ -394,43 +394,37 @@ void Expression::makeBinaryOp(RPNCommand op, Expression &&src1, Expression const
|
||||
break;
|
||||
case RPN_SHL:
|
||||
if (rval < 0) {
|
||||
warning(
|
||||
WARNING_SHIFT_AMOUNT, "Shifting left by negative amount %" PRId32 "\n", rval
|
||||
);
|
||||
warning(WARNING_SHIFT_AMOUNT, "Shifting left by negative amount %" PRId32, rval);
|
||||
}
|
||||
|
||||
if (rval >= 32) {
|
||||
warning(WARNING_SHIFT_AMOUNT, "Shifting left by large amount %" PRId32 "\n", rval);
|
||||
warning(WARNING_SHIFT_AMOUNT, "Shifting left by large amount %" PRId32, rval);
|
||||
}
|
||||
|
||||
data = op_shift_left(lval, rval);
|
||||
break;
|
||||
case RPN_SHR:
|
||||
if (lval < 0) {
|
||||
warning(WARNING_SHIFT, "Shifting right negative value %" PRId32 "\n", lval);
|
||||
warning(WARNING_SHIFT, "Shifting right negative value %" PRId32, lval);
|
||||
}
|
||||
|
||||
if (rval < 0) {
|
||||
warning(
|
||||
WARNING_SHIFT_AMOUNT, "Shifting right by negative amount %" PRId32 "\n", rval
|
||||
);
|
||||
warning(WARNING_SHIFT_AMOUNT, "Shifting right by negative amount %" PRId32, rval);
|
||||
}
|
||||
|
||||
if (rval >= 32) {
|
||||
warning(WARNING_SHIFT_AMOUNT, "Shifting right by large amount %" PRId32 "\n", rval);
|
||||
warning(WARNING_SHIFT_AMOUNT, "Shifting right by large amount %" PRId32, rval);
|
||||
}
|
||||
|
||||
data = op_shift_right(lval, rval);
|
||||
break;
|
||||
case RPN_USHR:
|
||||
if (rval < 0) {
|
||||
warning(
|
||||
WARNING_SHIFT_AMOUNT, "Shifting right by negative amount %" PRId32 "\n", rval
|
||||
);
|
||||
warning(WARNING_SHIFT_AMOUNT, "Shifting right by negative amount %" PRId32, rval);
|
||||
}
|
||||
|
||||
if (rval >= 32) {
|
||||
warning(WARNING_SHIFT_AMOUNT, "Shifting right by large amount %" PRId32 "\n", rval);
|
||||
warning(WARNING_SHIFT_AMOUNT, "Shifting right by large amount %" PRId32, rval);
|
||||
}
|
||||
|
||||
data = op_shift_right_unsigned(lval, rval);
|
||||
@@ -440,13 +434,13 @@ void Expression::makeBinaryOp(RPNCommand op, Expression &&src1, Expression const
|
||||
break;
|
||||
case RPN_DIV:
|
||||
if (rval == 0) {
|
||||
fatalerror("Division by zero\n");
|
||||
fatalerror("Division by zero");
|
||||
}
|
||||
|
||||
if (lval == INT32_MIN && rval == -1) {
|
||||
warning(
|
||||
WARNING_DIV,
|
||||
"Division of %" PRId32 " by -1 yields %" PRId32 "\n",
|
||||
"Division of %" PRId32 " by -1 yields %" PRId32,
|
||||
INT32_MIN,
|
||||
INT32_MIN
|
||||
);
|
||||
@@ -457,7 +451,7 @@ void Expression::makeBinaryOp(RPNCommand op, Expression &&src1, Expression const
|
||||
break;
|
||||
case RPN_MOD:
|
||||
if (rval == 0) {
|
||||
fatalerror("Modulo by zero\n");
|
||||
fatalerror("Modulo by zero");
|
||||
}
|
||||
|
||||
if (lval == INT32_MIN && rval == -1) {
|
||||
@@ -468,7 +462,7 @@ void Expression::makeBinaryOp(RPNCommand op, Expression &&src1, Expression const
|
||||
break;
|
||||
case RPN_EXP:
|
||||
if (rval < 0) {
|
||||
fatalerror("Exponentiation by negative power\n");
|
||||
fatalerror("Exponentiation by negative power");
|
||||
}
|
||||
|
||||
data = op_exponent(lval, rval);
|
||||
@@ -551,7 +545,7 @@ bool Expression::makeCheckHRAM() {
|
||||
// That range is valid, but deprecated
|
||||
return true;
|
||||
} else {
|
||||
error("Source address $%" PRIx32 " not between $FF00 to $FFFF\n", val);
|
||||
error("Source address $%" PRIx32 " not between $FF00 to $FFFF", val);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -561,7 +555,7 @@ void Expression::makeCheckRST() {
|
||||
*reserveSpace(1) = RPN_RST;
|
||||
} else if (int32_t val = value(); val & ~0x38) {
|
||||
// A valid RST address must be masked with 0x38
|
||||
error("Invalid address $%" PRIx32 " for RST\n", val);
|
||||
error("Invalid address $%" PRIx32 " for RST", val);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -575,7 +569,7 @@ void Expression::makeCheckBitIndex(uint8_t mask) {
|
||||
} else if (int32_t val = value(); val & ~0x07) {
|
||||
// A valid bit index must be masked with 0x07
|
||||
static char const *instructions[4] = {"instruction", "BIT", "RES", "SET"};
|
||||
error("Invalid bit index %" PRId32 " for %s\n", val, instructions[mask >> 6]);
|
||||
error("Invalid bit index %" PRId32 " for %s", val, instructions[mask >> 6]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -593,20 +587,20 @@ bool checkNBit(int32_t v, uint8_t n, char const *name) {
|
||||
if (v < -(1 << n) || v >= 1 << n) {
|
||||
warning(
|
||||
WARNING_TRUNCATION_1,
|
||||
n == 8 && !name ? "%s must be %u-bit; use LOW() to force 8-bit\n"
|
||||
: "%s must be %u-bit\n",
|
||||
"%s must be %u-bit%s",
|
||||
name ? name : "Expression",
|
||||
n
|
||||
n,
|
||||
n == 8 && !name ? "; use LOW() to force 8-bit" : ""
|
||||
);
|
||||
return false;
|
||||
}
|
||||
if (v < -(1 << (n - 1))) {
|
||||
warning(
|
||||
WARNING_TRUNCATION_2,
|
||||
n == 8 && !name ? "%s must be %u-bit; use LOW() to force 8-bit\n"
|
||||
: "%s must be %u-bit\n",
|
||||
"%s must be %u-bit%s",
|
||||
name ? name : "Expression",
|
||||
n
|
||||
n,
|
||||
n == 8 && !name ? "; use LOW() to force 8-bit" : ""
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ static bool requireSection() {
|
||||
return true;
|
||||
}
|
||||
|
||||
error("Cannot output data outside of a SECTION\n");
|
||||
error("Cannot output data outside of a SECTION");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -72,8 +72,7 @@ static bool requireCodeSection() {
|
||||
}
|
||||
|
||||
error(
|
||||
"Section '%s' cannot contain code or data (not ROM0 or ROMX)\n",
|
||||
currentSection->name.c_str()
|
||||
"Section '%s' cannot contain code or data (not ROM0 or ROMX)", currentSection->name.c_str()
|
||||
);
|
||||
return false;
|
||||
}
|
||||
@@ -82,8 +81,7 @@ void sect_CheckSizes() {
|
||||
for (Section const § : sectionList) {
|
||||
if (uint32_t maxSize = sectionTypeInfo[sect.type].size; sect.size > maxSize) {
|
||||
error(
|
||||
"Section '%s' grew too big (max size = 0x%" PRIX32 " bytes, reached 0x%" PRIX32
|
||||
")\n",
|
||||
"Section '%s' grew too big (max size = 0x%" PRIX32 " bytes, reached 0x%" PRIX32 ")",
|
||||
sect.name.c_str(),
|
||||
maxSize,
|
||||
sect.size
|
||||
@@ -113,18 +111,18 @@ static unsigned int mergeSectUnion(
|
||||
// Unionized sections only need "compatible" constraints, and they end up with the strictest
|
||||
// combination of both.
|
||||
if (sect_HasData(type)) {
|
||||
sectError("Cannot declare ROM sections as UNION\n");
|
||||
sectError("Cannot declare ROM sections as UNION");
|
||||
}
|
||||
|
||||
if (org != UINT32_MAX) {
|
||||
// If both are fixed, they must be the same
|
||||
if (sect.org != UINT32_MAX && sect.org != org) {
|
||||
sectError(
|
||||
"Section already declared as fixed at different address $%04" PRIx32 "\n", sect.org
|
||||
"Section already declared as fixed at different address $%04" PRIx32, sect.org
|
||||
);
|
||||
} else if (sect.align != 0 && (mask(sect.align) & (org - sect.alignOfs))) {
|
||||
sectError(
|
||||
"Section already declared as aligned to %u bytes (offset %" PRIu16 ")\n",
|
||||
"Section already declared as aligned to %u bytes (offset %" PRIu16 ")",
|
||||
1U << sect.align,
|
||||
sect.alignOfs
|
||||
);
|
||||
@@ -138,15 +136,14 @@ static unsigned int mergeSectUnion(
|
||||
if (sect.org != UINT32_MAX) {
|
||||
if ((sect.org - alignOffset) & mask(alignment)) {
|
||||
sectError(
|
||||
"Section already declared as fixed at incompatible address $%04" PRIx32 "\n",
|
||||
"Section already declared as fixed at incompatible address $%04" PRIx32,
|
||||
sect.org
|
||||
);
|
||||
}
|
||||
// Check if alignment offsets are compatible
|
||||
} else if ((alignOffset & mask(sect.align)) != (sect.alignOfs & mask(alignment))) {
|
||||
sectError(
|
||||
"Section already declared with incompatible %u"
|
||||
"-byte alignment (offset %" PRIu16 ")\n",
|
||||
"Section already declared with incompatible %u-byte alignment (offset %" PRIu16 ")",
|
||||
1U << sect.align,
|
||||
sect.alignOfs
|
||||
);
|
||||
@@ -174,12 +171,11 @@ static unsigned int
|
||||
// If both are fixed, they must be the same
|
||||
if (sect.org != UINT32_MAX && sect.org != curOrg) {
|
||||
sectError(
|
||||
"Section already declared as fixed at incompatible address $%04" PRIx32 "\n",
|
||||
sect.org
|
||||
"Section already declared as fixed at incompatible address $%04" PRIx32, sect.org
|
||||
);
|
||||
} else if (sect.align != 0 && (mask(sect.align) & (curOrg - sect.alignOfs))) {
|
||||
sectError(
|
||||
"Section already declared as aligned to %u bytes (offset %" PRIu16 ")\n",
|
||||
"Section already declared as aligned to %u bytes (offset %" PRIu16 ")",
|
||||
1U << sect.align,
|
||||
sect.alignOfs
|
||||
);
|
||||
@@ -199,15 +195,14 @@ static unsigned int
|
||||
if (sect.org != UINT32_MAX) {
|
||||
if ((sect.org - curOfs) & mask(alignment)) {
|
||||
sectError(
|
||||
"Section already declared as fixed at incompatible address $%04" PRIx32 "\n",
|
||||
"Section already declared as fixed at incompatible address $%04" PRIx32,
|
||||
sect.org
|
||||
);
|
||||
}
|
||||
// Check if alignment offsets are compatible
|
||||
} else if ((curOfs & mask(sect.align)) != (sect.alignOfs & mask(alignment))) {
|
||||
sectError(
|
||||
"Section already declared with incompatible %u"
|
||||
"-byte alignment (offset %" PRIu16 ")\n",
|
||||
"Section already declared with incompatible %u-byte alignment (offset %" PRIu16 ")",
|
||||
1U << sect.align,
|
||||
sect.alignOfs
|
||||
);
|
||||
@@ -234,12 +229,12 @@ static void mergeSections(
|
||||
|
||||
if (type != sect.type) {
|
||||
sectError(
|
||||
"Section already exists but with type %s\n", sectionTypeInfo[sect.type].name.c_str()
|
||||
"Section already exists but with type %s", sectionTypeInfo[sect.type].name.c_str()
|
||||
);
|
||||
}
|
||||
|
||||
if (sect.modifier != mod) {
|
||||
sectError("Section already declared as SECTION %s\n", sectionModNames[sect.modifier]);
|
||||
sectError("Section already declared as SECTION %s", sectionModNames[sect.modifier]);
|
||||
} else {
|
||||
switch (mod) {
|
||||
case SECTION_UNION:
|
||||
@@ -256,21 +251,22 @@ static void mergeSections(
|
||||
}
|
||||
// If both specify a bank, it must be the same one
|
||||
else if (bank != UINT32_MAX && sect.bank != bank) {
|
||||
sectError("Section already declared with different bank %" PRIu32 "\n", sect.bank);
|
||||
sectError("Section already declared with different bank %" PRIu32, sect.bank);
|
||||
}
|
||||
break;
|
||||
|
||||
case SECTION_NORMAL:
|
||||
sectError("Section already defined previously at ");
|
||||
errorNoNewline("Section already defined previously at ");
|
||||
sect.src->dump(sect.fileLine);
|
||||
putc('\n', stderr);
|
||||
nbSectErrors++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (nbSectErrors) {
|
||||
fatalerror(
|
||||
"Cannot create section \"%s\" (%u error%s)\n",
|
||||
"Cannot create section \"%s\" (%u error%s)",
|
||||
sect.name.c_str(),
|
||||
nbSectErrors,
|
||||
nbSectErrors == 1 ? "" : "s"
|
||||
@@ -332,11 +328,11 @@ static Section *getSection(
|
||||
if (bank != UINT32_MAX) {
|
||||
if (type != SECTTYPE_ROMX && type != SECTTYPE_VRAM && type != SECTTYPE_SRAM
|
||||
&& type != SECTTYPE_WRAMX) {
|
||||
error("BANK only allowed for ROMX, WRAMX, SRAM, or VRAM sections\n");
|
||||
error("BANK only allowed for ROMX, WRAMX, SRAM, or VRAM sections");
|
||||
} else if (bank < sectionTypeInfo[type].firstBank
|
||||
|| bank > sectionTypeInfo[type].lastBank) {
|
||||
error(
|
||||
"%s bank value $%04" PRIx32 " out of range ($%04" PRIx32 " to $%04" PRIx32 ")\n",
|
||||
"%s bank value $%04" PRIx32 " out of range ($%04" PRIx32 " to $%04" PRIx32 ")",
|
||||
sectionTypeInfo[type].name.c_str(),
|
||||
bank,
|
||||
sectionTypeInfo[type].firstBank,
|
||||
@@ -350,7 +346,7 @@ static Section *getSection(
|
||||
|
||||
if (alignOffset >= 1 << alignment) {
|
||||
error(
|
||||
"Alignment offset (%" PRIu16 ") must be smaller than alignment size (%u)\n",
|
||||
"Alignment offset (%" PRIu16 ") must be smaller than alignment size (%u)",
|
||||
alignOffset,
|
||||
1U << alignment
|
||||
);
|
||||
@@ -361,7 +357,7 @@ static Section *getSection(
|
||||
if (org < sectionTypeInfo[type].startAddr || org > endaddr(type)) {
|
||||
error(
|
||||
"Section \"%s\"'s fixed address $%04" PRIx32 " is outside of range [$%04" PRIx16
|
||||
"; $%04" PRIx16 "]\n",
|
||||
"; $%04" PRIx16 "]",
|
||||
name.c_str(),
|
||||
org,
|
||||
sectionTypeInfo[type].startAddr,
|
||||
@@ -372,7 +368,7 @@ static Section *getSection(
|
||||
|
||||
if (alignment != 0) {
|
||||
if (alignment > 16) {
|
||||
error("Alignment must be between 0 and 16, not %u\n", alignment);
|
||||
error("Alignment must be between 0 and 16, not %u", alignment);
|
||||
alignment = 16;
|
||||
}
|
||||
// It doesn't make sense to have both alignment and org set
|
||||
@@ -380,12 +376,12 @@ static Section *getSection(
|
||||
|
||||
if (org != UINT32_MAX) {
|
||||
if ((org - alignOffset) & mask) {
|
||||
error("Section \"%s\"'s fixed address doesn't match its alignment\n", name.c_str());
|
||||
error("Section \"%s\"'s fixed address doesn't match its alignment", name.c_str());
|
||||
}
|
||||
alignment = 0; // Ignore it if it's satisfied
|
||||
} else if (sectionTypeInfo[type].startAddr & mask) {
|
||||
error(
|
||||
"Section \"%s\"'s alignment cannot be attained in %s\n",
|
||||
"Section \"%s\"'s alignment cannot be attained in %s",
|
||||
name.c_str(),
|
||||
sectionTypeInfo[type].name.c_str()
|
||||
);
|
||||
@@ -415,7 +411,7 @@ static Section *getSection(
|
||||
// Set the current section
|
||||
static void changeSection() {
|
||||
if (!currentUnionStack.empty()) {
|
||||
fatalerror("Cannot change the section within a UNION\n");
|
||||
fatalerror("Cannot change the section within a UNION");
|
||||
}
|
||||
|
||||
sym_ResetCurrentLabelScopes();
|
||||
@@ -452,7 +448,7 @@ void sect_NewSection(
|
||||
) {
|
||||
for (SectionStackEntry &entry : sectionStack) {
|
||||
if (entry.section && entry.section->name == name) {
|
||||
fatalerror("Section '%s' is already on the stack\n", name.c_str());
|
||||
fatalerror("Section '%s' is already on the stack", name.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -486,7 +482,7 @@ void sect_SetLoadSection(
|
||||
}
|
||||
|
||||
if (sect_HasData(type)) {
|
||||
error("`LOAD` blocks cannot create a ROM section\n");
|
||||
error("`LOAD` blocks cannot create a ROM section");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -505,13 +501,11 @@ void sect_SetLoadSection(
|
||||
|
||||
void sect_EndLoadSection(char const *cause) {
|
||||
if (cause) {
|
||||
warning(
|
||||
WARNING_UNTERMINATED_LOAD, "`LOAD` block without `ENDL` terminated by `%s`\n", cause
|
||||
);
|
||||
warning(WARNING_UNTERMINATED_LOAD, "`LOAD` block without `ENDL` terminated by `%s`", cause);
|
||||
}
|
||||
|
||||
if (!currentLoadSection) {
|
||||
error("Found `ENDL` outside of a `LOAD` block\n");
|
||||
error("Found `ENDL` outside of a `LOAD` block");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -524,7 +518,7 @@ void sect_EndLoadSection(char const *cause) {
|
||||
|
||||
void sect_CheckLoadClosed() {
|
||||
if (currentLoadSection) {
|
||||
warning(WARNING_UNTERMINATED_LOAD, "`LOAD` block without `ENDL` terminated by EOF\n");
|
||||
warning(WARNING_UNTERMINATED_LOAD, "`LOAD` block without `ENDL` terminated by EOF");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -575,7 +569,7 @@ void sect_AlignPC(uint8_t alignment, uint16_t offset) {
|
||||
if (uint32_t actualOffset = (sect->org + curOffset) % alignSize; actualOffset != offset) {
|
||||
error(
|
||||
"Section is misaligned (at PC = $%04" PRIx32 ", expected ALIGN[%" PRIu32
|
||||
", %" PRIu32 "], got ALIGN[%" PRIu32 ", %" PRIu32 "])\n",
|
||||
", %" PRIu32 "], got ALIGN[%" PRIu32 ", %" PRIu32 "])",
|
||||
sect->org + curOffset,
|
||||
alignment,
|
||||
offset,
|
||||
@@ -590,7 +584,7 @@ void sect_AlignPC(uint8_t alignment, uint16_t offset) {
|
||||
error(
|
||||
"Section is misaligned ($%04" PRIx32
|
||||
" bytes into the section, expected ALIGN[%" PRIu32 ", %" PRIu32
|
||||
"], got ALIGN[%" PRIu32 ", %" PRIu32 "])\n",
|
||||
"], got ALIGN[%" PRIu32 ", %" PRIu32 "])",
|
||||
curOffset,
|
||||
alignment,
|
||||
offset,
|
||||
@@ -601,7 +595,7 @@ void sect_AlignPC(uint8_t alignment, uint16_t offset) {
|
||||
// Treat an alignment large enough as fixing the address.
|
||||
// Note that this also ensures that a section's alignment never becomes 16 or greater.
|
||||
if (alignment > 16) {
|
||||
error("Alignment must be between 0 and 16, not %u\n", alignment);
|
||||
error("Alignment must be between 0 and 16, not %u", alignment);
|
||||
}
|
||||
sect->align = 0; // Reset the alignment, since we're fixing the address.
|
||||
sect->org = offset - curOffset;
|
||||
@@ -615,7 +609,7 @@ void sect_AlignPC(uint8_t alignment, uint16_t offset) {
|
||||
|
||||
static void growSection(uint32_t growth) {
|
||||
if (growth > 0 && curOffset > UINT32_MAX - growth) {
|
||||
fatalerror("Section size would overflow internal counter\n");
|
||||
fatalerror("Section size would overflow internal counter");
|
||||
}
|
||||
curOffset += growth;
|
||||
if (uint32_t outOffset = sect_GetOutputOffset(); outOffset > currentSection->size) {
|
||||
@@ -656,11 +650,11 @@ void sect_StartUnion() {
|
||||
// your own peril! ^^
|
||||
|
||||
if (!currentSection) {
|
||||
error("UNIONs must be inside a SECTION\n");
|
||||
error("UNIONs must be inside a SECTION");
|
||||
return;
|
||||
}
|
||||
if (sect_HasData(currentSection->type)) {
|
||||
error("Cannot use UNION inside of ROM0 or ROMX sections\n");
|
||||
error("Cannot use UNION inside of ROM0 or ROMX sections");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -679,7 +673,7 @@ static void endUnionMember() {
|
||||
|
||||
void sect_NextUnionMember() {
|
||||
if (currentUnionStack.empty()) {
|
||||
error("Found NEXTU outside of a UNION construct\n");
|
||||
error("Found NEXTU outside of a UNION construct");
|
||||
return;
|
||||
}
|
||||
endUnionMember();
|
||||
@@ -687,7 +681,7 @@ void sect_NextUnionMember() {
|
||||
|
||||
void sect_EndUnion() {
|
||||
if (currentUnionStack.empty()) {
|
||||
error("Found ENDU outside of a UNION construct\n");
|
||||
error("Found ENDU outside of a UNION construct");
|
||||
return;
|
||||
}
|
||||
endUnionMember();
|
||||
@@ -697,7 +691,7 @@ void sect_EndUnion() {
|
||||
|
||||
void sect_CheckUnionClosed() {
|
||||
if (!currentUnionStack.empty()) {
|
||||
error("Unterminated UNION construct\n");
|
||||
error("Unterminated UNION construct");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -767,7 +761,7 @@ void sect_Skip(uint32_t skip, bool ds) {
|
||||
if (!ds) {
|
||||
warning(
|
||||
WARNING_EMPTY_DATA_DIRECTIVE,
|
||||
"%s directive without data in ROM\n",
|
||||
"%s directive without data in ROM",
|
||||
(skip == 4) ? "DL"
|
||||
: (skip == 2) ? "DW"
|
||||
: "DB"
|
||||
@@ -862,7 +856,7 @@ void sect_PCRelByte(Expression const &expr, uint32_t pcShift) {
|
||||
if (offset < -128 || offset > 127) {
|
||||
error(
|
||||
"JR target must be between -128 and 127 bytes away, not %" PRId16
|
||||
"; use JP instead\n",
|
||||
"; use JP instead",
|
||||
offset
|
||||
);
|
||||
writeByte(0);
|
||||
@@ -875,7 +869,7 @@ void sect_PCRelByte(Expression const &expr, uint32_t pcShift) {
|
||||
// Output a binary file
|
||||
void sect_BinaryFile(std::string const &name, int32_t startPos) {
|
||||
if (startPos < 0) {
|
||||
error("Start position cannot be negative (%" PRId32 ")\n", startPos);
|
||||
error("Start position cannot be negative (%" PRId32 ")", startPos);
|
||||
startPos = 0;
|
||||
}
|
||||
if (!requireCodeSection()) {
|
||||
@@ -895,7 +889,7 @@ void sect_BinaryFile(std::string const &name, int32_t startPos) {
|
||||
// LCOV_EXCL_STOP
|
||||
failedOnMissingInclude = true;
|
||||
} else {
|
||||
error("Error opening INCBIN file '%s': %s\n", name.c_str(), strerror(errno));
|
||||
error("Error opening INCBIN file '%s': %s", name.c_str(), strerror(errno));
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -903,23 +897,19 @@ void sect_BinaryFile(std::string const &name, int32_t startPos) {
|
||||
|
||||
if (fseek(file, 0, SEEK_END) != -1) {
|
||||
if (startPos > ftell(file)) {
|
||||
error("Specified start position is greater than length of file '%s'\n", name.c_str());
|
||||
error("Specified start position is greater than length of file '%s'", name.c_str());
|
||||
return;
|
||||
}
|
||||
// The file is seekable; skip to the specified start position
|
||||
fseek(file, startPos, SEEK_SET);
|
||||
} else {
|
||||
if (errno != ESPIPE) {
|
||||
error(
|
||||
"Error determining size of INCBIN file '%s': %s\n", name.c_str(), strerror(errno)
|
||||
);
|
||||
error("Error determining size of INCBIN file '%s': %s", name.c_str(), strerror(errno));
|
||||
}
|
||||
// The file isn't seekable, so we'll just skip bytes one at a time
|
||||
while (startPos--) {
|
||||
if (fgetc(file) == EOF) {
|
||||
error(
|
||||
"Specified start position is greater than length of file '%s'\n", name.c_str()
|
||||
);
|
||||
error("Specified start position is greater than length of file '%s'", name.c_str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -930,18 +920,18 @@ void sect_BinaryFile(std::string const &name, int32_t startPos) {
|
||||
}
|
||||
|
||||
if (ferror(file)) {
|
||||
error("Error reading INCBIN file '%s': %s\n", name.c_str(), strerror(errno));
|
||||
error("Error reading INCBIN file '%s': %s", name.c_str(), strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
// Output a slice of a binary file
|
||||
void sect_BinaryFileSlice(std::string const &name, int32_t startPos, int32_t length) {
|
||||
if (startPos < 0) {
|
||||
error("Start position cannot be negative (%" PRId32 ")\n", startPos);
|
||||
error("Start position cannot be negative (%" PRId32 ")", startPos);
|
||||
startPos = 0;
|
||||
}
|
||||
if (length < 0) {
|
||||
error("Number of bytes to read cannot be negative (%" PRId32 ")\n", length);
|
||||
error("Number of bytes to read cannot be negative (%" PRId32 ")", length);
|
||||
length = 0;
|
||||
}
|
||||
if (!requireCodeSection()) {
|
||||
@@ -964,7 +954,7 @@ void sect_BinaryFileSlice(std::string const &name, int32_t startPos, int32_t len
|
||||
// LCOV_EXCL_STOP
|
||||
failedOnMissingInclude = true;
|
||||
} else {
|
||||
error("Error opening INCBIN file '%s': %s\n", name.c_str(), strerror(errno));
|
||||
error("Error opening INCBIN file '%s': %s", name.c_str(), strerror(errno));
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -972,12 +962,12 @@ void sect_BinaryFileSlice(std::string const &name, int32_t startPos, int32_t len
|
||||
|
||||
if (fseek(file, 0, SEEK_END) != -1) {
|
||||
if (int32_t fsize = ftell(file); startPos > fsize) {
|
||||
error("Specified start position is greater than length of file '%s'\n", name.c_str());
|
||||
error("Specified start position is greater than length of file '%s'", name.c_str());
|
||||
return;
|
||||
} else if (startPos + length > fsize) {
|
||||
error(
|
||||
"Specified range in INCBIN file '%s' is out of bounds (%" PRIu32 " + %" PRIu32
|
||||
" > %" PRIu32 ")\n",
|
||||
" > %" PRIu32 ")",
|
||||
name.c_str(),
|
||||
startPos,
|
||||
length,
|
||||
@@ -989,16 +979,12 @@ void sect_BinaryFileSlice(std::string const &name, int32_t startPos, int32_t len
|
||||
fseek(file, startPos, SEEK_SET);
|
||||
} else {
|
||||
if (errno != ESPIPE) {
|
||||
error(
|
||||
"Error determining size of INCBIN file '%s': %s\n", name.c_str(), strerror(errno)
|
||||
);
|
||||
error("Error determining size of INCBIN file '%s': %s", name.c_str(), strerror(errno));
|
||||
}
|
||||
// The file isn't seekable, so we'll just skip bytes one at a time
|
||||
while (startPos--) {
|
||||
if (fgetc(file) == EOF) {
|
||||
error(
|
||||
"Specified start position is greater than length of file '%s'\n", name.c_str()
|
||||
);
|
||||
error("Specified start position is greater than length of file '%s'", name.c_str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1008,10 +994,10 @@ void sect_BinaryFileSlice(std::string const &name, int32_t startPos, int32_t len
|
||||
if (int byte = fgetc(file); byte != EOF) {
|
||||
writeByte(byte);
|
||||
} else if (ferror(file)) {
|
||||
error("Error reading INCBIN file '%s': %s\n", name.c_str(), strerror(errno));
|
||||
error("Error reading INCBIN file '%s': %s", name.c_str(), strerror(errno));
|
||||
} else {
|
||||
error(
|
||||
"Premature end of INCBIN file '%s' (%" PRId32 " bytes left to read)\n",
|
||||
"Premature end of INCBIN file '%s' (%" PRId32 " bytes left to read)",
|
||||
name.c_str(),
|
||||
length + 1
|
||||
);
|
||||
@@ -1039,7 +1025,7 @@ void sect_PushSection() {
|
||||
|
||||
void sect_PopSection() {
|
||||
if (sectionStack.empty()) {
|
||||
fatalerror("No entries in the section stack\n");
|
||||
fatalerror("No entries in the section stack");
|
||||
}
|
||||
|
||||
if (currentLoadSection) {
|
||||
@@ -1060,17 +1046,17 @@ void sect_PopSection() {
|
||||
|
||||
void sect_CheckStack() {
|
||||
if (!sectionStack.empty()) {
|
||||
warning(WARNING_UNMATCHED_DIRECTIVE, "`PUSHS` without corresponding `POPS`\n");
|
||||
warning(WARNING_UNMATCHED_DIRECTIVE, "`PUSHS` without corresponding `POPS`");
|
||||
}
|
||||
}
|
||||
|
||||
void sect_EndSection() {
|
||||
if (!currentSection) {
|
||||
fatalerror("Cannot end the section outside of a SECTION\n");
|
||||
fatalerror("Cannot end the section outside of a SECTION");
|
||||
}
|
||||
|
||||
if (!currentUnionStack.empty()) {
|
||||
fatalerror("Cannot end the section within a UNION\n");
|
||||
fatalerror("Cannot end the section within a UNION");
|
||||
}
|
||||
|
||||
if (currentLoadSection) {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "asm/symbol.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <unordered_map>
|
||||
@@ -51,14 +52,14 @@ static int32_t NARGCallback() {
|
||||
if (MacroArgs const *macroArgs = fstk_GetCurrentMacroArgs(); macroArgs) {
|
||||
return macroArgs->nbArgs();
|
||||
} else {
|
||||
error("_NARG has no value outside of a macro\n");
|
||||
error("_NARG has no value outside of a macro");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static std::shared_ptr<std::string> globalScopeCallback() {
|
||||
if (!globalScope) {
|
||||
error("\".\" has no value outside of a label scope\n");
|
||||
error("\".\" has no value outside of a label scope");
|
||||
return std::make_shared<std::string>("");
|
||||
}
|
||||
return std::make_shared<std::string>(globalScope->name);
|
||||
@@ -66,7 +67,7 @@ static std::shared_ptr<std::string> globalScopeCallback() {
|
||||
|
||||
static std::shared_ptr<std::string> localScopeCallback() {
|
||||
if (!localScope) {
|
||||
error("\"..\" has no value outside of a local label scope\n");
|
||||
error("\"..\" has no value outside of a local label scope");
|
||||
return std::make_shared<std::string>("");
|
||||
}
|
||||
return std::make_shared<std::string>(localScope->name);
|
||||
@@ -111,6 +112,7 @@ std::shared_ptr<std::string> Symbol::getEqus() const {
|
||||
}
|
||||
|
||||
static void dumpFilename(Symbol const &sym) {
|
||||
fputs(" at ", stderr);
|
||||
if (sym.src) {
|
||||
sym.src->dump(sym.fileLine);
|
||||
putc('\n', stderr);
|
||||
@@ -140,13 +142,12 @@ static bool isValidIdentifier(std::string const &s) {
|
||||
static void alreadyDefinedError(Symbol const &sym, char const *asType) {
|
||||
if (sym.isBuiltin && !sym_FindScopedValidSymbol(sym.name)) {
|
||||
// `DEF()` would return false, so we should not claim the symbol is already defined
|
||||
error("'%s' is reserved for a built-in symbol\n", sym.name.c_str());
|
||||
error("'%s' is reserved for a built-in symbol", sym.name.c_str());
|
||||
} else {
|
||||
error("'%s' already defined", sym.name.c_str());
|
||||
errorNoNewline("'%s' already defined", sym.name.c_str());
|
||||
if (asType) {
|
||||
fprintf(stderr, " as %s", asType);
|
||||
}
|
||||
fputs(" at ", stderr);
|
||||
dumpFilename(sym);
|
||||
if (sym.type == SYM_EQUS) {
|
||||
if (std::string const &contents = *sym.getEqus(); isValidIdentifier(contents)) {
|
||||
@@ -164,9 +165,9 @@ static void redefinedError(Symbol const &sym) {
|
||||
assume(sym.isBuiltin);
|
||||
if (!sym_FindScopedValidSymbol(sym.name)) {
|
||||
// `DEF()` would return false, so we should not imply the symbol is already defined
|
||||
error("'%s' is reserved for a built-in symbol\n", sym.name.c_str());
|
||||
error("'%s' is reserved for a built-in symbol", sym.name.c_str());
|
||||
} else {
|
||||
error("Built-in symbol '%s' cannot be redefined\n", sym.name.c_str());
|
||||
error("Built-in symbol '%s' cannot be redefined", sym.name.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -215,12 +216,12 @@ static bool isAutoScoped(std::string const &symName) {
|
||||
|
||||
// Check for nothing after the dot
|
||||
if (dotPos == symName.length() - 1) {
|
||||
fatalerror("'%s' is a nonsensical reference to an empty local label\n", symName.c_str());
|
||||
fatalerror("'%s' is a nonsensical reference to an empty local label", symName.c_str());
|
||||
}
|
||||
|
||||
// Check for more than one dot
|
||||
if (symName.find('.', dotPos + 1) != std::string::npos) {
|
||||
fatalerror("'%s' is a nonsensical reference to a nested local label\n", symName.c_str());
|
||||
fatalerror("'%s' is a nonsensical reference to a nested local label", symName.c_str());
|
||||
}
|
||||
|
||||
// Check for already-qualified local label
|
||||
@@ -230,7 +231,7 @@ static bool isAutoScoped(std::string const &symName) {
|
||||
|
||||
// Check for unqualifiable local label
|
||||
if (!globalScope) {
|
||||
fatalerror("Unqualified local label '%s' in main scope\n", symName.c_str());
|
||||
fatalerror("Unqualified local label '%s' in main scope", symName.c_str());
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -279,19 +280,19 @@ void sym_Purge(std::string const &symName) {
|
||||
|
||||
if (!sym) {
|
||||
if (sym_IsPurgedScoped(symName)) {
|
||||
error("'%s' was already purged\n", symName.c_str());
|
||||
error("'%s' was already purged", symName.c_str());
|
||||
} else {
|
||||
error("'%s' not defined\n", symName.c_str());
|
||||
error("'%s' not defined", symName.c_str());
|
||||
}
|
||||
} else if (sym->isBuiltin) {
|
||||
error("Built-in symbol '%s' cannot be purged\n", symName.c_str());
|
||||
error("Built-in symbol '%s' cannot be purged", symName.c_str());
|
||||
} else if (sym->ID != UINT32_MAX) {
|
||||
error("Symbol \"%s\" is referenced and thus cannot be purged\n", symName.c_str());
|
||||
error("Symbol \"%s\" is referenced and thus cannot be purged", symName.c_str());
|
||||
} else {
|
||||
if (sym->isExported) {
|
||||
warning(WARNING_PURGE_1, "Purging an exported symbol \"%s\"\n", symName.c_str());
|
||||
warning(WARNING_PURGE_1, "Purging an exported symbol \"%s\"", symName.c_str());
|
||||
} else if (sym->isLabel()) {
|
||||
warning(WARNING_PURGE_2, "Purging a label \"%s\"\n", symName.c_str());
|
||||
warning(WARNING_PURGE_2, "Purging a label \"%s\"", symName.c_str());
|
||||
}
|
||||
// Do not keep a reference to the label after purging it
|
||||
if (sym == globalScope) {
|
||||
@@ -331,12 +332,12 @@ uint32_t Symbol::getConstantValue() const {
|
||||
|
||||
if (sym_IsPC(this)) {
|
||||
if (!getSection()) {
|
||||
error("PC has no value outside of a section\n");
|
||||
error("PC has no value outside of a section");
|
||||
} else {
|
||||
error("PC does not have a constant value; the current section is not fixed\n");
|
||||
error("PC does not have a constant value; the current section is not fixed");
|
||||
}
|
||||
} else {
|
||||
error("\"%s\" does not have a constant value\n", name.c_str());
|
||||
error("\"%s\" does not have a constant value", name.c_str());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -371,7 +372,7 @@ static Symbol *createNonrelocSymbol(std::string const &symName, bool numeric) {
|
||||
return nullptr; // Don't allow overriding the symbol, that'd be bad!
|
||||
} else if (!numeric) {
|
||||
// The symbol has already been referenced, but it's not allowed
|
||||
error("'%s' already referenced at ", symName.c_str());
|
||||
errorNoNewline("'%s' already referenced", symName.c_str());
|
||||
dumpFilename(*sym);
|
||||
return nullptr; // Don't allow overriding the symbol, that'd be bad!
|
||||
}
|
||||
@@ -437,7 +438,7 @@ Symbol *sym_RedefString(std::string const &symName, std::shared_ptr<std::string>
|
||||
if (sym->isDefined()) {
|
||||
alreadyDefinedError(*sym, "non-EQUS");
|
||||
} else {
|
||||
error("'%s' already referenced at ", symName.c_str());
|
||||
errorNoNewline("'%s' already referenced", symName.c_str());
|
||||
dumpFilename(*sym);
|
||||
}
|
||||
return nullptr;
|
||||
@@ -493,7 +494,7 @@ static Symbol *addLabel(std::string const &symName) {
|
||||
sym->section = sect_GetSymbolSection();
|
||||
|
||||
if (sym && !sym->section) {
|
||||
error("Label \"%s\" created outside of a SECTION\n", symName.c_str());
|
||||
error("Label \"%s\" created outside of a SECTION", symName.c_str());
|
||||
}
|
||||
|
||||
return sym;
|
||||
@@ -549,7 +550,7 @@ std::string sym_MakeAnonLabelName(uint32_t ofs, bool neg) {
|
||||
if (ofs > anonLabelID) {
|
||||
error(
|
||||
"Reference to anonymous label %" PRIu32 " before, when only %" PRIu32
|
||||
" ha%s been created so far\n",
|
||||
" ha%s been created so far",
|
||||
ofs,
|
||||
anonLabelID,
|
||||
anonLabelID == 1 ? "s" : "ve"
|
||||
@@ -563,7 +564,7 @@ std::string sym_MakeAnonLabelName(uint32_t ofs, bool neg) {
|
||||
// LCOV_EXCL_START
|
||||
error(
|
||||
"Reference to anonymous label %" PRIu32 " after, when only %" PRIu32
|
||||
" may still be created\n",
|
||||
" may still be created",
|
||||
ofs + 1,
|
||||
UINT32_MAX - anonLabelID
|
||||
);
|
||||
@@ -580,7 +581,7 @@ void sym_Export(std::string const &symName) {
|
||||
if (symName.starts_with('!')) {
|
||||
// LCOV_EXCL_START
|
||||
// The parser does not accept anonymous labels for an `EXPORT` directive
|
||||
error("Anonymous labels cannot be exported\n");
|
||||
error("Anonymous labels cannot be exported");
|
||||
return;
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
@@ -666,7 +667,7 @@ void sym_Init(time_t now) {
|
||||
|
||||
// LCOV_EXCL_START
|
||||
if (now == static_cast<time_t>(-1)) {
|
||||
warn("Failed to determine current time");
|
||||
warnx("Failed to determine current time: %s", strerror(errno));
|
||||
// Fall back by pretending we are at the Epoch
|
||||
now = 0;
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ Diagnostics<WarningLevel, WarningID> warnings = {
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
void printDiag(
|
||||
static void printDiag(
|
||||
char const *fmt, va_list args, char const *type, char const *flagfmt, char const *flag
|
||||
) {
|
||||
fputs(type, stderr);
|
||||
@@ -74,6 +74,7 @@ void printDiag(
|
||||
fprintf(stderr, flagfmt, flag);
|
||||
fputs("\n ", stderr);
|
||||
vfprintf(stderr, fmt, args);
|
||||
putc('\n', stderr);
|
||||
lexer_DumpStringExpansions();
|
||||
}
|
||||
|
||||
@@ -96,6 +97,28 @@ void error(char const *fmt, ...) {
|
||||
}
|
||||
}
|
||||
|
||||
void errorNoNewline(char const *fmt, ...) {
|
||||
va_list args;
|
||||
|
||||
fputs("error: ", stderr);
|
||||
fstk_DumpCurrent();
|
||||
fputs(":\n ", stderr);
|
||||
va_start(args, fmt);
|
||||
vfprintf(stderr, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
// This intentionally makes 0 act as "unlimited" (or at least "limited to sizeof(unsigned)")
|
||||
nbErrors++;
|
||||
if (nbErrors == maxErrors) {
|
||||
errx(
|
||||
"The maximum of %u error%s was reached (configure with \"-X/--max-errors\"); assembly "
|
||||
"aborted!",
|
||||
maxErrors,
|
||||
maxErrors == 1 ? "" : "s"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
[[noreturn]]
|
||||
void fatalerror(char const *fmt, ...) {
|
||||
va_list args;
|
||||
|
||||
Reference in New Issue
Block a user