mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 18:22:07 +00:00
Enable RGBGFX's CLI "at-files" for all programs (#1848)
This commit is contained in:
@@ -307,10 +307,10 @@ yy::parser::symbol_type yylex() {
|
||||
// Not marking as unreachable; this will generate a warning if any codepath forgets to return.
|
||||
}
|
||||
|
||||
bool lexer_Init(char const *linkerScriptName) {
|
||||
bool lexer_Init(std::string const &linkerScriptName) {
|
||||
if (LexerStackEntry &newContext = lexerStack.emplace_back(std::string(linkerScriptName));
|
||||
!newContext.file.open(newContext.path, std::ios_base::in)) {
|
||||
error("Failed to open linker script \"%s\"", linkerScriptName);
|
||||
error("Failed to open linker script \"%s\"", linkerScriptName.c_str());
|
||||
lexerStack.clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
#include <utility>
|
||||
|
||||
#include "backtrace.hpp"
|
||||
#include "cli.hpp"
|
||||
#include "diagnostics.hpp"
|
||||
#include "extern/getopt.hpp"
|
||||
#include "linkdefs.hpp"
|
||||
#include "script.hpp" // Generated from script.y
|
||||
#include "style.hpp"
|
||||
@@ -33,12 +33,16 @@
|
||||
|
||||
Options options;
|
||||
|
||||
static char const *linkerScriptName = nullptr; // -l
|
||||
// Flags which must be processed after the option parsing finishes
|
||||
static struct LocalOptions {
|
||||
std::optional<std::string> linkerScriptName; // -l
|
||||
std::vector<std::string> inputFileNames; // <file>...
|
||||
} localOptions;
|
||||
|
||||
// Short options
|
||||
static char const *optstring = "B:dhl:m:Mn:O:o:p:S:tVvW:wx";
|
||||
|
||||
// Variables for the long-only options
|
||||
// Long-only option variable
|
||||
static int longOpt; // `--color`
|
||||
|
||||
// Equivalent long options
|
||||
@@ -90,97 +94,6 @@ static Usage usage = {
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
// LCOV_EXCL_START
|
||||
static void verboseOutputConfig(int argc, char *argv[]) {
|
||||
if (!checkVerbosity(VERB_CONFIG)) {
|
||||
return;
|
||||
}
|
||||
|
||||
style_Set(stderr, STYLE_MAGENTA, false);
|
||||
|
||||
fprintf(stderr, "rgblink %s\n", get_package_version_string());
|
||||
|
||||
printVVVVVVerbosity();
|
||||
|
||||
fputs("Options:\n", stderr);
|
||||
// -d/--dmg
|
||||
if (options.isDmgMode) {
|
||||
fputs("\tDMG mode prohibits non-DMG section types\n", stderr);
|
||||
}
|
||||
// -t/--tiny
|
||||
if (options.is32kMode) {
|
||||
fputs("\tROM0 covers the full 32 KiB of ROM\n", stderr);
|
||||
}
|
||||
// -w/--wramx
|
||||
if (options.isWRAM0Mode) {
|
||||
fputs("\tWRAM0 covers the full 8 KiB of WRAM\n", stderr);
|
||||
}
|
||||
// -x/--nopad
|
||||
if (options.disablePadding) {
|
||||
fputs("\tNo padding at the end of the ROM file\n", stderr);
|
||||
}
|
||||
// -p/--pad
|
||||
fprintf(stderr, "\tPad value: 0x%02" PRIx8 "\n", options.padValue);
|
||||
// -S/--scramble
|
||||
if (options.scrambleROMX || options.scrambleWRAMX || options.scrambleSRAM) {
|
||||
fputs("\tScramble: ", stderr);
|
||||
if (options.scrambleROMX) {
|
||||
fprintf(stderr, "ROMX = %" PRIu16, options.scrambleROMX);
|
||||
if (options.scrambleWRAMX || options.scrambleSRAM) {
|
||||
fputs(", ", stderr);
|
||||
}
|
||||
}
|
||||
if (options.scrambleWRAMX) {
|
||||
fprintf(stderr, "WRAMX = %" PRIu16, options.scrambleWRAMX);
|
||||
if (options.scrambleSRAM) {
|
||||
fputs(", ", stderr);
|
||||
}
|
||||
}
|
||||
if (options.scrambleSRAM) {
|
||||
fprintf(stderr, "SRAM = %" PRIu16, options.scrambleSRAM);
|
||||
}
|
||||
putc('\n', stderr);
|
||||
}
|
||||
// file ...
|
||||
if (musl_optind < argc) {
|
||||
fprintf(stderr, "\tInput object files: ");
|
||||
for (int i = musl_optind; i < argc; ++i) {
|
||||
if (i > musl_optind) {
|
||||
fputs(", ", stderr);
|
||||
}
|
||||
if (i - musl_optind == 10) {
|
||||
fprintf(stderr, "and %d more", argc - i);
|
||||
break;
|
||||
}
|
||||
fputs(argv[i], stderr);
|
||||
}
|
||||
putc('\n', stderr);
|
||||
}
|
||||
auto printPath = [](char const *name, char const *path) {
|
||||
if (path) {
|
||||
fprintf(stderr, "\t%s: %s\n", name, path);
|
||||
}
|
||||
};
|
||||
// -O/--overlay
|
||||
printPath("Overlay file", options.overlayFileName);
|
||||
// -l/--linkerscript
|
||||
printPath("Linker script", linkerScriptName);
|
||||
// -o/--output
|
||||
printPath("Output ROM file", options.outputFileName);
|
||||
// -m/--map
|
||||
printPath("Output map file", options.mapFileName);
|
||||
// -M/--no-sym-in-map
|
||||
if (options.mapFileName && options.noSymInMap) {
|
||||
fputs("\tNo symbols in map file\n", stderr);
|
||||
}
|
||||
// -n/--sym
|
||||
printPath("Output sym file", options.symFileName);
|
||||
fputs("Ready.\n", stderr);
|
||||
|
||||
style_Reset(stderr);
|
||||
}
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
static size_t skipBlankSpace(char const *str) {
|
||||
return strspn(str, " \t");
|
||||
}
|
||||
@@ -292,124 +205,221 @@ static void parseScrambleSpec(char *spec) {
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
// Parse CLI options
|
||||
for (int ch; (ch = musl_getopt_long_only(argc, argv, optstring, longopts, nullptr)) != -1;) {
|
||||
switch (ch) {
|
||||
case 'B':
|
||||
if (!trace_ParseTraceDepth(musl_optarg)) {
|
||||
fatal("Invalid argument for option '-B'");
|
||||
}
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
options.isDmgMode = true;
|
||||
options.isWRAM0Mode = true;
|
||||
break;
|
||||
|
||||
// LCOV_EXCL_START
|
||||
case 'h':
|
||||
usage.printAndExit(0);
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
case 'l':
|
||||
if (linkerScriptName) {
|
||||
warnx("Overriding linker script file \"%s\"", linkerScriptName);
|
||||
}
|
||||
linkerScriptName = musl_optarg;
|
||||
break;
|
||||
|
||||
case 'M':
|
||||
options.noSymInMap = true;
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
if (options.mapFileName) {
|
||||
warnx("Overriding map file \"%s\"", options.mapFileName);
|
||||
}
|
||||
options.mapFileName = musl_optarg;
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
if (options.symFileName) {
|
||||
warnx("Overriding sym file \"%s\"", options.symFileName);
|
||||
}
|
||||
options.symFileName = musl_optarg;
|
||||
break;
|
||||
|
||||
case 'O':
|
||||
if (options.overlayFileName) {
|
||||
warnx("Overriding overlay file \"%s\"", options.overlayFileName);
|
||||
}
|
||||
options.overlayFileName = musl_optarg;
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
if (options.outputFileName) {
|
||||
warnx("Overriding output file \"%s\"", options.outputFileName);
|
||||
}
|
||||
options.outputFileName = musl_optarg;
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
if (std::optional<uint64_t> value = parseWholeNumber(musl_optarg); !value) {
|
||||
fatal("Invalid argument for option '-p'");
|
||||
} else if (*value > 0xFF) {
|
||||
fatal("Argument for option '-p' must be between 0 and 0xFF");
|
||||
} else {
|
||||
options.padValue = *value;
|
||||
options.hasPadValue = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
parseScrambleSpec(musl_optarg);
|
||||
break;
|
||||
|
||||
case 't':
|
||||
options.is32kMode = true;
|
||||
break;
|
||||
|
||||
// LCOV_EXCL_START
|
||||
case 'V':
|
||||
printf("rgblink %s\n", get_package_version_string());
|
||||
exit(0);
|
||||
|
||||
case 'v':
|
||||
incrementVerbosity();
|
||||
break;
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
case 'W':
|
||||
warnings.processWarningFlag(musl_optarg);
|
||||
break;
|
||||
|
||||
case 'w':
|
||||
options.isWRAM0Mode = true;
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
options.disablePadding = true;
|
||||
// implies tiny mode
|
||||
options.is32kMode = true;
|
||||
break;
|
||||
|
||||
case 0: // Long-only options
|
||||
if (longOpt == 'c' && !style_Parse(musl_optarg)) {
|
||||
fatal("Invalid argument for option '--color'");
|
||||
}
|
||||
break;
|
||||
|
||||
// LCOV_EXCL_START
|
||||
default:
|
||||
usage.printAndExit(1);
|
||||
// LCOV_EXCL_STOP
|
||||
static void parseArg(int ch, char *arg) {
|
||||
switch (ch) {
|
||||
case 'B':
|
||||
if (!trace_ParseTraceDepth(arg)) {
|
||||
fatal("Invalid argument for option '-B'");
|
||||
}
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
options.isDmgMode = true;
|
||||
options.isWRAM0Mode = true;
|
||||
break;
|
||||
|
||||
// LCOV_EXCL_START
|
||||
case 'h':
|
||||
usage.printAndExit(0);
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
case 'l':
|
||||
if (localOptions.linkerScriptName) {
|
||||
warnx("Overriding linker script file \"%s\"", localOptions.linkerScriptName->c_str());
|
||||
}
|
||||
localOptions.linkerScriptName = arg;
|
||||
break;
|
||||
|
||||
case 'M':
|
||||
options.noSymInMap = true;
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
if (options.mapFileName) {
|
||||
warnx("Overriding map file \"%s\"", options.mapFileName->c_str());
|
||||
}
|
||||
options.mapFileName = arg;
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
if (options.symFileName) {
|
||||
warnx("Overriding sym file \"%s\"", options.symFileName->c_str());
|
||||
}
|
||||
options.symFileName = arg;
|
||||
break;
|
||||
|
||||
case 'O':
|
||||
if (options.overlayFileName) {
|
||||
warnx("Overriding overlay file \"%s\"", options.overlayFileName->c_str());
|
||||
}
|
||||
options.overlayFileName = arg;
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
if (options.outputFileName) {
|
||||
warnx("Overriding output file \"%s\"", options.outputFileName->c_str());
|
||||
}
|
||||
options.outputFileName = arg;
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
if (std::optional<uint64_t> value = parseWholeNumber(arg); !value) {
|
||||
fatal("Invalid argument for option '-p'");
|
||||
} else if (*value > 0xFF) {
|
||||
fatal("Argument for option '-p' must be between 0 and 0xFF");
|
||||
} else {
|
||||
options.padValue = *value;
|
||||
options.hasPadValue = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
parseScrambleSpec(arg);
|
||||
break;
|
||||
|
||||
case 't':
|
||||
options.is32kMode = true;
|
||||
break;
|
||||
|
||||
// LCOV_EXCL_START
|
||||
case 'V':
|
||||
printf("rgblink %s\n", get_package_version_string());
|
||||
exit(0);
|
||||
|
||||
case 'v':
|
||||
incrementVerbosity();
|
||||
break;
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
case 'W':
|
||||
warnings.processWarningFlag(arg);
|
||||
break;
|
||||
|
||||
case 'w':
|
||||
options.isWRAM0Mode = true;
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
options.disablePadding = true;
|
||||
// implies tiny mode
|
||||
options.is32kMode = true;
|
||||
break;
|
||||
|
||||
case 0: // Long-only options
|
||||
if (longOpt == 'c' && !style_Parse(arg)) {
|
||||
fatal("Invalid argument for option '--color'");
|
||||
}
|
||||
break;
|
||||
|
||||
case 1: // Positional argument
|
||||
localOptions.inputFileNames.push_back(arg);
|
||||
break;
|
||||
|
||||
// LCOV_EXCL_START
|
||||
default:
|
||||
usage.printAndExit(1);
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
}
|
||||
|
||||
// LCOV_EXCL_START
|
||||
static void verboseOutputConfig() {
|
||||
if (!checkVerbosity(VERB_CONFIG)) {
|
||||
return;
|
||||
}
|
||||
|
||||
verboseOutputConfig(argc, argv);
|
||||
style_Set(stderr, STYLE_MAGENTA, false);
|
||||
|
||||
if (musl_optind == argc) {
|
||||
fprintf(stderr, "rgblink %s\n", get_package_version_string());
|
||||
|
||||
printVVVVVVerbosity();
|
||||
|
||||
fputs("Options:\n", stderr);
|
||||
// -d/--dmg
|
||||
if (options.isDmgMode) {
|
||||
fputs("\tDMG mode prohibits non-DMG section types\n", stderr);
|
||||
}
|
||||
// -t/--tiny
|
||||
if (options.is32kMode) {
|
||||
fputs("\tROM0 covers the full 32 KiB of ROM\n", stderr);
|
||||
}
|
||||
// -w/--wramx
|
||||
if (options.isWRAM0Mode) {
|
||||
fputs("\tWRAM0 covers the full 8 KiB of WRAM\n", stderr);
|
||||
}
|
||||
// -x/--nopad
|
||||
if (options.disablePadding) {
|
||||
fputs("\tNo padding at the end of the ROM file\n", stderr);
|
||||
}
|
||||
// -p/--pad
|
||||
fprintf(stderr, "\tPad value: 0x%02" PRIx8 "\n", options.padValue);
|
||||
// -S/--scramble
|
||||
if (options.scrambleROMX || options.scrambleWRAMX || options.scrambleSRAM) {
|
||||
fputs("\tScramble: ", stderr);
|
||||
if (options.scrambleROMX) {
|
||||
fprintf(stderr, "ROMX = %" PRIu16, options.scrambleROMX);
|
||||
if (options.scrambleWRAMX || options.scrambleSRAM) {
|
||||
fputs(", ", stderr);
|
||||
}
|
||||
}
|
||||
if (options.scrambleWRAMX) {
|
||||
fprintf(stderr, "WRAMX = %" PRIu16, options.scrambleWRAMX);
|
||||
if (options.scrambleSRAM) {
|
||||
fputs(", ", stderr);
|
||||
}
|
||||
}
|
||||
if (options.scrambleSRAM) {
|
||||
fprintf(stderr, "SRAM = %" PRIu16, options.scrambleSRAM);
|
||||
}
|
||||
putc('\n', stderr);
|
||||
}
|
||||
// file ...
|
||||
if (!localOptions.inputFileNames.empty()) {
|
||||
fprintf(stderr, "\tInput object files: ");
|
||||
size_t nbFiles = localOptions.inputFileNames.size();
|
||||
for (size_t i = 0; i < nbFiles; ++i) {
|
||||
if (i > 0) {
|
||||
fputs(", ", stderr);
|
||||
}
|
||||
if (i == 10) {
|
||||
fprintf(stderr, "and %zu more", nbFiles - i);
|
||||
break;
|
||||
}
|
||||
fputs(localOptions.inputFileNames[i].c_str(), stderr);
|
||||
}
|
||||
putc('\n', stderr);
|
||||
}
|
||||
auto printPath = [](char const *name, std::optional<std::string> const &path) {
|
||||
if (path) {
|
||||
fprintf(stderr, "\t%s: %s\n", name, path->c_str());
|
||||
}
|
||||
};
|
||||
// -O/--overlay
|
||||
printPath("Overlay file", options.overlayFileName);
|
||||
// -l/--linkerscript
|
||||
printPath("Linker script", localOptions.linkerScriptName);
|
||||
// -o/--output
|
||||
printPath("Output ROM file", options.outputFileName);
|
||||
// -m/--map
|
||||
printPath("Output map file", options.mapFileName);
|
||||
// -M/--no-sym-in-map
|
||||
if (options.mapFileName && options.noSymInMap) {
|
||||
fputs("\tNo symbols in map file\n", stderr);
|
||||
}
|
||||
// -n/--sym
|
||||
printPath("Output sym file", options.symFileName);
|
||||
fputs("Ready.\n", stderr);
|
||||
|
||||
style_Reset(stderr);
|
||||
}
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
cli_ParseArgs(argc, argv, optstring, longopts, parseArg, fatal);
|
||||
|
||||
verboseOutputConfig();
|
||||
|
||||
if (localOptions.inputFileNames.empty()) {
|
||||
usage.printAndExit("No input file specified (pass \"-\" to read from standard input)");
|
||||
}
|
||||
|
||||
@@ -427,16 +437,17 @@ int main(int argc, char *argv[]) {
|
||||
}
|
||||
|
||||
// Read all object files first,
|
||||
obj_Setup(argc - musl_optind);
|
||||
for (int i = musl_optind; i < argc; ++i) {
|
||||
obj_ReadFile(argv[i], argc - i - 1);
|
||||
size_t nbFiles = localOptions.inputFileNames.size();
|
||||
obj_Setup(nbFiles);
|
||||
for (size_t i = 0; i < nbFiles; ++i) {
|
||||
obj_ReadFile(localOptions.inputFileNames[i], nbFiles - i - 1);
|
||||
}
|
||||
|
||||
// apply the linker script's modifications,
|
||||
if (linkerScriptName) {
|
||||
if (localOptions.linkerScriptName) {
|
||||
verbosePrint(VERB_NOTICE, "Reading linker script...\n");
|
||||
|
||||
if (lexer_Init(linkerScriptName)) {
|
||||
if (lexer_Init(*localOptions.linkerScriptName)) {
|
||||
if (yy::parser parser; parser.parse() != 0) {
|
||||
// Exited due to YYABORT or YYNOMEM
|
||||
fatal("Unrecoverable error while reading linker script"); // LCOV_EXCL_LINE
|
||||
|
||||
@@ -405,9 +405,10 @@ static void readAssertion(
|
||||
tryReadString(assert.message, file, "%s: Cannot read assertion's message: %s", fileName);
|
||||
}
|
||||
|
||||
void obj_ReadFile(char const *fileName, unsigned int fileID) {
|
||||
void obj_ReadFile(std::string const &filePath, size_t fileID) {
|
||||
FILE *file;
|
||||
if (strcmp(fileName, "-")) {
|
||||
char const *fileName = filePath.c_str();
|
||||
if (filePath != "-") {
|
||||
file = fopen(fileName, "rb");
|
||||
} else {
|
||||
fileName = "<stdin>";
|
||||
@@ -553,6 +554,6 @@ void obj_ReadFile(char const *fileName, unsigned int fileID) {
|
||||
}
|
||||
}
|
||||
|
||||
void obj_Setup(unsigned int nbFiles) {
|
||||
void obj_Setup(size_t nbFiles) {
|
||||
nodes.resize(nbFiles);
|
||||
}
|
||||
|
||||
@@ -208,15 +208,16 @@ static void
|
||||
|
||||
static void writeROM() {
|
||||
if (options.outputFileName) {
|
||||
if (strcmp(options.outputFileName, "-")) {
|
||||
outputFile = fopen(options.outputFileName, "wb");
|
||||
char const *outputFileName = options.outputFileName->c_str();
|
||||
if (*options.outputFileName != "-") {
|
||||
outputFile = fopen(outputFileName, "wb");
|
||||
} else {
|
||||
options.outputFileName = "<stdout>";
|
||||
outputFileName = "<stdout>";
|
||||
(void)setmode(STDOUT_FILENO, O_BINARY);
|
||||
outputFile = stdout;
|
||||
}
|
||||
if (!outputFile) {
|
||||
fatal("Failed to open output file \"%s\": %s", options.outputFileName, strerror(errno));
|
||||
fatal("Failed to open output file \"%s\": %s", outputFileName, strerror(errno));
|
||||
}
|
||||
}
|
||||
Defer closeOutputFile{[&] {
|
||||
@@ -226,17 +227,16 @@ static void writeROM() {
|
||||
}};
|
||||
|
||||
if (options.overlayFileName) {
|
||||
if (strcmp(options.overlayFileName, "-")) {
|
||||
overlayFile = fopen(options.overlayFileName, "rb");
|
||||
char const *overlayFileName = options.overlayFileName->c_str();
|
||||
if (*options.overlayFileName != "-") {
|
||||
overlayFile = fopen(overlayFileName, "rb");
|
||||
} else {
|
||||
options.overlayFileName = "<stdin>";
|
||||
overlayFileName = "<stdin>";
|
||||
(void)setmode(STDIN_FILENO, O_BINARY);
|
||||
overlayFile = stdin;
|
||||
}
|
||||
if (!overlayFile) {
|
||||
fatal(
|
||||
"Failed to open overlay file \"%s\": %s", options.overlayFileName, strerror(errno)
|
||||
);
|
||||
fatal("Failed to open overlay file \"%s\": %s", overlayFileName, strerror(errno));
|
||||
}
|
||||
}
|
||||
Defer closeOverlayFile{[&] {
|
||||
@@ -548,15 +548,16 @@ static void writeSym() {
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(options.symFileName, "-")) {
|
||||
symFile = fopen(options.symFileName, "w");
|
||||
char const *symFileName = options.symFileName->c_str();
|
||||
if (*options.symFileName != "-") {
|
||||
symFile = fopen(symFileName, "w");
|
||||
} else {
|
||||
options.symFileName = "<stdout>";
|
||||
symFileName = "<stdout>";
|
||||
(void)setmode(STDOUT_FILENO, O_TEXT); // May have been set to O_BINARY previously
|
||||
symFile = stdout;
|
||||
}
|
||||
if (!symFile) {
|
||||
fatal("Failed to open sym file \"%s\": %s", options.symFileName, strerror(errno));
|
||||
fatal("Failed to open sym file \"%s\": %s", symFileName, strerror(errno));
|
||||
}
|
||||
Defer closeSymFile{[&] { fclose(symFile); }};
|
||||
|
||||
@@ -598,15 +599,16 @@ static void writeMap() {
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(options.mapFileName, "-")) {
|
||||
mapFile = fopen(options.mapFileName, "w");
|
||||
char const *mapFileName = options.mapFileName->c_str();
|
||||
if (*options.mapFileName != "-") {
|
||||
mapFile = fopen(mapFileName, "w");
|
||||
} else {
|
||||
options.mapFileName = "<stdout>";
|
||||
mapFileName = "<stdout>";
|
||||
(void)setmode(STDOUT_FILENO, O_TEXT); // May have been set to O_BINARY previously
|
||||
mapFile = stdout;
|
||||
}
|
||||
if (!mapFile) {
|
||||
fatal("Failed to open map file \"%s\": %s", options.mapFileName, strerror(errno));
|
||||
fatal("Failed to open map file \"%s\": %s", mapFileName, strerror(errno));
|
||||
}
|
||||
Defer closeMapFile{[&] { fclose(mapFile); }};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user