Group extern RGBASM variables in an Options struct

This commit is contained in:
Rangi42
2025-07-21 19:01:23 -04:00
parent d652212857
commit d1493a9f96
18 changed files with 133 additions and 156 deletions

View File

@@ -10,12 +10,6 @@
#define M_PI 3.14159265358979323846
#endif
uint8_t fixPrecision;
uint8_t fix_Precision() {
return fixPrecision;
}
static double fix2double(int32_t i, int32_t q) {
return i / pow(2.0, q);
}

View File

@@ -10,6 +10,7 @@
#include <string.h>
#include "asm/fixpoint.hpp"
#include "asm/main.hpp" // options
#include "asm/warning.hpp"
void FormatSpec::useCharacter(int c) {
@@ -258,7 +259,7 @@ void FormatSpec::appendNumber(std::string &str, uint32_t value) const {
useFracWidth = 255;
}
size_t defaultPrec = fix_Precision();
size_t defaultPrec = options.fixPrecision;
size_t usePrec = hasPrec ? precision : defaultPrec;
if (usePrec < 1 || usePrec > 31) {
error(

View File

@@ -42,7 +42,6 @@ struct Context {
};
static std::stack<Context> contextStack;
size_t maxRecursionDepth;
// The first include path for `fstk_FindFile` to try is none at all
static std::vector<std::string> includePaths = {""};
@@ -134,11 +133,9 @@ static bool isValidFilePath(std::string const &path) {
}
static void printDep(std::string const &path) {
if (dependFile) {
fprintf(dependFile, "%s: %s\n", targetFileName.c_str(), path.c_str());
if (generatePhonyDeps && isValidFilePath(path)) {
fprintf(dependFile, "%s:\n", path.c_str());
}
options.printDep(path);
if (options.dependFile && options.generatePhonyDeps && isValidFilePath(path)) {
fprintf(options.dependFile, "%s:\n", path.c_str());
}
}
@@ -151,7 +148,7 @@ std::optional<std::string> fstk_FindFile(std::string const &path) {
}
errno = ENOENT;
if (missingIncludeState != INC_ERROR) {
if (options.missingIncludeState != INC_ERROR) {
printDep(path);
}
return std::nullopt;
@@ -212,8 +209,8 @@ bool yywrap() {
}
static void checkRecursionDepth() {
if (contextStack.size() > maxRecursionDepth) {
fatal("Recursion limit (%zu) exceeded", maxRecursionDepth);
if (contextStack.size() > options.maxRecursionDepth) {
fatal("Recursion limit (%zu) exceeded", options.maxRecursionDepth);
}
}
@@ -304,18 +301,18 @@ static Context &newReptContext(int32_t reptLineNo, ContentSpan const &span, uint
}
bool fstk_FileError(std::string const &path, char const *functionName) {
if (missingIncludeState == INC_ERROR) {
if (options.missingIncludeState == INC_ERROR) {
error("Error opening %s file '%s': %s", functionName, path.c_str(), strerror(errno));
} else {
failedOnMissingInclude = true;
// LCOV_EXCL_START
if (missingIncludeState == GEN_EXIT) {
if (options.missingIncludeState == GEN_EXIT) {
verbosePrint(
"Aborting (-MG) on %s file '%s' (%s)\n", functionName, path.c_str(), strerror(errno)
);
return true;
}
assume(missingIncludeState == GEN_CONTINUE);
assume(options.missingIncludeState == GEN_CONTINUE);
// LCOV_EXCL_STOP
}
return false;
@@ -406,13 +403,13 @@ void fstk_NewRecursionDepth(size_t newDepth) {
if (contextStack.size() > newDepth + 1) {
fatal("Recursion limit (%zu) exceeded", newDepth);
}
maxRecursionDepth = newDepth;
options.maxRecursionDepth = newDepth;
}
void fstk_Init(std::string const &mainPath, size_t maxDepth) {
newFileContext(mainPath, true);
maxRecursionDepth = maxDepth;
options.maxRecursionDepth = maxDepth;
for (std::string const &name : preIncludeNames) {
if (std::optional<std::string> fullPath = fstk_FindFile(name); fullPath) {

View File

@@ -587,8 +587,8 @@ static void beginExpansion(std::shared_ptr<std::string> str, std::optional<std::
}
void lexer_CheckRecursionDepth() {
if (lexerState->expansions.size() > maxRecursionDepth + 1) {
fatal("Recursion limit (%zu) exceeded", maxRecursionDepth);
if (lexerState->expansions.size() > options.maxRecursionDepth + 1) {
fatal("Recursion limit (%zu) exceeded", options.maxRecursionDepth);
}
}
@@ -1043,10 +1043,10 @@ static uint32_t readFractionalPart(uint32_t integer) {
if (state >= READFRACTIONALPART_PRECISION) {
error("Invalid fixed-point constant, no significant digits after 'q'");
}
precision = fixPrecision;
precision = options.fixPrecision;
} else if (precision > 31) {
error("Fixed-point constant precision must be between 1 and 31");
precision = fixPrecision;
precision = options.fixPrecision;
}
if (integer >= (1ULL << (32 - precision))) {
@@ -1060,9 +1060,6 @@ static uint32_t readFractionalPart(uint32_t integer) {
return (integer << precision) | fractional;
}
char binDigits[2];
char gfxDigits[4];
static bool isValidDigit(char c) {
return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '.'
|| c == '#' || c == '@';
@@ -1094,14 +1091,14 @@ static bool checkDigitErrors(char const *digits, size_t n, char const *type) {
}
void lexer_SetBinDigits(char const digits[2]) {
if (size_t n = std::size(binDigits); checkDigitErrors(digits, n, "binary")) {
memcpy(binDigits, digits, n);
if (size_t n = std::size(options.binDigits); checkDigitErrors(digits, n, "binary")) {
memcpy(options.binDigits, digits, n);
}
}
void lexer_SetGfxDigits(char const digits[4]) {
if (size_t n = std::size(gfxDigits); checkDigitErrors(digits, n, "graphics")) {
memcpy(gfxDigits, digits, n);
if (size_t n = std::size(options.gfxDigits); checkDigitErrors(digits, n, "graphics")) {
memcpy(options.gfxDigits, digits, n);
}
}
@@ -1114,9 +1111,9 @@ static uint32_t readBinaryNumber() {
if (c == '_' && !empty) {
continue;
} else if (c == '0' || c == binDigits[0]) {
} else if (c == '0' || c == options.binDigits[0]) {
bit = 0;
} else if (c == '1' || c == binDigits[1]) {
} else if (c == '1' || c == options.binDigits[1]) {
bit = 1;
} else {
break;
@@ -1227,13 +1224,13 @@ static uint32_t readGfxConstant() {
if (c == '_' && width > 0) {
continue;
} else if (c == '0' || c == gfxDigits[0]) {
} else if (c == '0' || c == options.gfxDigits[0]) {
pixel = 0;
} else if (c == '1' || c == gfxDigits[1]) {
} else if (c == '1' || c == options.gfxDigits[1]) {
pixel = 1;
} else if (c == '2' || c == gfxDigits[2]) {
} else if (c == '2' || c == options.gfxDigits[2]) {
pixel = 2;
} else if (c == '3' || c == gfxDigits[3]) {
} else if (c == '3' || c == options.gfxDigits[3]) {
pixel = 3;
} else {
break;
@@ -1297,8 +1294,8 @@ static Token readIdentifier(char firstChar, bool raw) {
// Functions to read strings
static std::shared_ptr<std::string> readInterpolation(size_t depth) {
if (depth > maxRecursionDepth) {
fatal("Recursion limit (%zu) exceeded", maxRecursionDepth);
if (depth > options.maxRecursionDepth) {
fatal("Recursion limit (%zu) exceeded", options.maxRecursionDepth);
}
std::string fmtBuf;
@@ -1891,7 +1888,8 @@ static Token yylex_NORMAL() {
if (c == '=') {
shiftChar();
return Token(T_(POP_MODEQ));
} else if (c == '0' || c == '1' || c == binDigits[0] || c == binDigits[1]) {
} else if (c == '0' || c == '1' || c == options.binDigits[0]
|| c == options.binDigits[1]) {
return Token(T_(NUMBER), readBinaryNumber());
}
return Token(T_(OP_MOD));

View File

@@ -24,12 +24,8 @@
#include "asm/symbol.hpp"
#include "asm/warning.hpp"
bool verbose = false; // -v
Options options;
FILE *dependFile = nullptr; // -M
MissingInclude missingIncludeState = INC_ERROR; // -MC, -MG
bool generatePhonyDeps = false; // -MP
std::string targetFileName; // -MQ, -MT
bool failedOnMissingInclude = false;
// Escapes Make-special chars from a string
@@ -178,20 +174,10 @@ int main(int argc, char *argv[]) {
now = static_cast<time_t>(strtoul(sourceDateEpoch, nullptr, 0));
}
Defer closeDependFile{[&] {
if (dependFile) {
fclose(dependFile);
}
}};
// Perform some init for below
sym_Init(now);
// Set defaults
opt_B("01");
opt_G("0123");
opt_P(0);
opt_Q(16);
sym_SetExportAll(false);
uint32_t maxDepth = 64;
char const *dependFileName = nullptr;
@@ -199,7 +185,7 @@ int main(int argc, char *argv[]) {
std::string newTarget;
// Maximum of 100 errors only applies if rgbasm is printing errors to a terminal.
if (isatty(STDERR_FILENO)) {
maxErrors = 100;
options.maxErrors = 100;
}
for (int ch; (ch = musl_getopt_long_only(argc, argv, optstring, longopts, nullptr)) != -1;) {
@@ -248,17 +234,17 @@ int main(int argc, char *argv[]) {
break;
case 'M':
if (dependFile) {
if (options.dependFile) {
warnx("Overriding dependfile %s", dependFileName);
}
if (strcmp("-", musl_optarg)) {
dependFile = fopen(musl_optarg, "w");
options.dependFile = fopen(musl_optarg, "w");
dependFileName = musl_optarg;
} else {
dependFile = stdout;
options.dependFile = stdout;
dependFileName = "<stdout>";
}
if (dependFile == nullptr) {
if (options.dependFile == nullptr) {
// LCOV_EXCL_START
fatal("Failed to open dependfile \"%s\": %s", dependFileName, strerror(errno));
// LCOV_EXCL_STOP
@@ -340,7 +326,7 @@ int main(int argc, char *argv[]) {
case 'v':
// LCOV_EXCL_START
verbose = true;
options.verbose = true;
break;
// LCOV_EXCL_STOP
@@ -352,34 +338,34 @@ int main(int argc, char *argv[]) {
warnings.state.warningsEnabled = false;
break;
unsigned long maxValue;
unsigned long maxErrors;
case 'X':
maxValue = strtoul(musl_optarg, &endptr, 0);
maxErrors = strtoul(musl_optarg, &endptr, 0);
if (musl_optarg[0] == '\0' || *endptr != '\0') {
fatal("Invalid argument for option 'X'");
}
if (maxValue > UINT_MAX) {
if (maxErrors > UINT_MAX) {
fatal("Argument for option 'X' must be between 0 and %u", UINT_MAX);
}
maxErrors = maxValue;
options.maxErrors = maxErrors;
break;
// Long-only options
case 0:
switch (depType) {
case 'C':
missingIncludeState = GEN_CONTINUE;
options.missingIncludeState = GEN_CONTINUE;
break;
case 'G':
missingIncludeState = GEN_EXIT;
options.missingIncludeState = GEN_EXIT;
break;
case 'P':
generatePhonyDeps = true;
options.generatePhonyDeps = true;
break;
case 'Q':
@@ -388,10 +374,10 @@ int main(int argc, char *argv[]) {
if (depType == 'Q') {
newTarget = make_escape(newTarget);
}
if (!targetFileName.empty()) {
targetFileName += ' ';
if (!options.targetFileName.empty()) {
options.targetFileName += ' ';
}
targetFileName += newTarget;
options.targetFileName += newTarget;
break;
}
break;
@@ -405,8 +391,8 @@ int main(int argc, char *argv[]) {
}
}
if (targetFileName.empty() && !objectFileName.empty()) {
targetFileName = objectFileName;
if (options.targetFileName.empty() && !options.objectFileName.empty()) {
options.targetFileName = options.objectFileName;
}
if (argc == musl_optind) {
@@ -419,14 +405,11 @@ int main(int argc, char *argv[]) {
verbosePrint("Assembling %s\n", mainFileName.c_str()); // LCOV_EXCL_LINE
if (dependFile) {
if (targetFileName.empty()) {
fatal("Dependency files can only be created if a target file is specified with either "
"-o, -MQ or -MT");
}
fprintf(dependFile, "%s: %s\n", targetFileName.c_str(), mainFileName.c_str());
if (options.dependFile && options.targetFileName.empty()) {
fatal("Dependency files can only be created if a target file is specified with either "
"-o, -MQ or -MT");
}
options.printDep(mainFileName);
charmap_New(DEFAULT_CHARMAP_NAME, nullptr);

View File

@@ -12,6 +12,7 @@
#include "asm/fixpoint.hpp"
#include "asm/fstack.hpp"
#include "asm/lexer.hpp"
#include "asm/main.hpp" // options
#include "asm/section.hpp"
#include "asm/warning.hpp"
@@ -19,31 +20,31 @@ struct OptStackEntry {
char binDigits[2];
char gfxDigits[4];
uint8_t fixPrecision;
uint8_t fillByte;
uint8_t padByte;
size_t maxRecursionDepth;
DiagnosticsState<WarningID> warningStates;
};
static std::stack<OptStackEntry> stack;
void opt_B(char const chars[2]) {
lexer_SetBinDigits(chars);
void opt_B(char const binDigits[2]) {
lexer_SetBinDigits(binDigits);
}
void opt_G(char const chars[4]) {
lexer_SetGfxDigits(chars);
void opt_G(char const gfxDigits[4]) {
lexer_SetGfxDigits(gfxDigits);
}
void opt_P(uint8_t padByte) {
fillByte = padByte;
options.padByte = padByte;
}
void opt_Q(uint8_t precision) {
fixPrecision = precision;
void opt_Q(uint8_t fixPrecision) {
options.fixPrecision = fixPrecision;
}
void opt_R(size_t newDepth) {
fstk_NewRecursionDepth(newDepth);
void opt_R(size_t maxRecursionDepth) {
fstk_NewRecursionDepth(maxRecursionDepth);
lexer_CheckRecursionDepth();
}
@@ -97,15 +98,15 @@ void opt_Parse(char const *s) {
}
if (strlen(precisionArg) <= 2) {
int result;
unsigned int precision;
unsigned int fixPrecision;
result = sscanf(precisionArg, "%u", &precision);
result = sscanf(precisionArg, "%u", &fixPrecision);
if (result != 1) {
error("Invalid argument for option 'Q'");
} else if (precision < 1 || precision > 31) {
} else if (fixPrecision < 1 || fixPrecision > 31) {
error("Argument for option 'Q' must be between 1 and 31");
} else {
opt_Q(precision);
opt_Q(fixPrecision);
}
} else {
error("Invalid argument for option 'Q'");
@@ -124,14 +125,14 @@ void opt_Parse(char const *s) {
}
char *endptr;
unsigned long newDepth = strtoul(s, &endptr, 10);
unsigned long maxRecursionDepth = strtoul(s, &endptr, 10);
if (*endptr != '\0') {
error("Invalid argument to option 'r' (\"%s\")", s);
} else if (errno == ERANGE) {
error("Argument to 'r' is out of range (\"%s\")", s);
} else {
opt_R(newDepth);
opt_R(maxRecursionDepth);
}
break;
}
@@ -153,17 +154,12 @@ void opt_Parse(char const *s) {
void opt_Push() {
OptStackEntry entry;
// Both of these are pulled from lexer.hpp
memcpy(entry.binDigits, binDigits, std::size(binDigits));
memcpy(entry.gfxDigits, gfxDigits, std::size(gfxDigits));
entry.fixPrecision = fixPrecision; // Pulled from fixpoint.hpp
entry.fillByte = fillByte; // Pulled from section.hpp
entry.warningStates = warnings.state; // Pulled from warning.hpp
entry.maxRecursionDepth = maxRecursionDepth; // Pulled from fstack.h
memcpy(entry.binDigits, options.binDigits, std::size(options.binDigits));
memcpy(entry.gfxDigits, options.gfxDigits, std::size(options.gfxDigits));
entry.padByte = options.padByte;
entry.fixPrecision = options.fixPrecision;
entry.maxRecursionDepth = options.maxRecursionDepth;
entry.warningStates = warnings.state;
stack.push(entry);
}
@@ -179,7 +175,7 @@ void opt_Pop() {
opt_B(entry.binDigits);
opt_G(entry.gfxDigits);
opt_P(entry.fillByte);
opt_P(entry.padByte);
opt_Q(entry.fixPrecision);
opt_R(entry.maxRecursionDepth);

View File

@@ -30,8 +30,6 @@ struct Assertion {
std::string message;
};
std::string objectFileName;
// List of symbols to put in the object file
static std::vector<Symbol *> objectSymbols;
@@ -316,21 +314,23 @@ static void writeFileStackNode(FileStackNode const &node, FILE *file) {
}
void out_WriteObject() {
if (objectFileName.empty()) {
if (options.objectFileName.empty()) {
return;
}
FILE *file;
if (objectFileName != "-") {
file = fopen(objectFileName.c_str(), "wb");
if (options.objectFileName != "-") {
file = fopen(options.objectFileName.c_str(), "wb");
} else {
objectFileName = "<stdout>";
options.objectFileName = "<stdout>";
(void)setmode(STDOUT_FILENO, O_BINARY);
file = stdout;
}
if (!file) {
// LCOV_EXCL_START
fatal("Failed to open object file '%s': %s", objectFileName.c_str(), strerror(errno));
fatal(
"Failed to open object file '%s': %s", options.objectFileName.c_str(), strerror(errno)
);
// LCOV_EXCL_STOP
}
Defer closeFile{[&] { fclose(file); }};
@@ -370,11 +370,11 @@ void out_WriteObject() {
}
void out_SetFileName(std::string const &name) {
if (!objectFileName.empty()) {
warnx("Overriding output filename %s", objectFileName.c_str());
if (!options.objectFileName.empty()) {
warnx("Overriding output filename %s", options.objectFileName.c_str());
}
objectFileName = name;
verbosePrint("Output filename %s\n", objectFileName.c_str()); // LCOV_EXCL_LINE
options.objectFileName = name;
verbosePrint("Output filename %s\n", options.objectFileName.c_str()); // LCOV_EXCL_LINE
}
static void dumpString(std::string const &escape, FILE *file) {

View File

@@ -1671,13 +1671,13 @@ iconst:
precision_arg:
%empty {
$$ = fix_Precision();
$$ = options.fixPrecision;
}
| COMMA iconst {
$$ = $2;
if ($$ < 1 || $$ > 31) {
::error("Fixed-point precision must be between 1 and 31, not %" PRId32, $$);
$$ = fix_Precision();
$$ = options.fixPrecision;
}
}
;

View File

@@ -24,8 +24,6 @@
using namespace std::literals;
uint8_t fillByte;
struct UnionStackEntry {
uint32_t start;
uint32_t size;
@@ -782,7 +780,7 @@ void sect_Skip(uint32_t skip, bool ds) {
}
// We know we're in a code SECTION
while (skip--) {
writeByte(fillByte);
writeByte(options.padByte);
}
}
}

View File

@@ -18,7 +18,6 @@
#include "asm/main.hpp"
unsigned int nbErrors = 0;
unsigned int maxErrors = 0;
// clang-format off: nested initializers
Diagnostics<WarningLevel, WarningID> warnings = {
@@ -81,7 +80,7 @@ static void printDiag(
static void incrementErrors() {
// This intentionally makes 0 act as "unlimited" (or at least "limited to sizeof(unsigned)")
if (++nbErrors == maxErrors) {
if (++nbErrors == options.maxErrors) {
fprintf(
stderr,
"Assembly aborted after the maximum of %u error%s! (configure with "