diff --git a/include/link/main.hpp b/include/link/main.hpp index a981f87d..83a6c630 100644 --- a/include/link/main.hpp +++ b/include/link/main.hpp @@ -11,27 +11,31 @@ #include "linkdefs.hpp" -// Variables related to CLI options -extern bool isDmgMode; -extern char const *linkerScriptName; -extern char const *mapFileName; -extern bool noSymInMap; -extern char const *symFileName; -extern char const *overlayFileName; -extern char const *outputFileName; -extern uint8_t padValue; -extern bool hasPadValue; -extern uint16_t scrambleROMX; -extern uint8_t scrambleWRAMX; -extern uint8_t scrambleSRAM; -extern bool is32kMode; -extern bool beVerbose; -extern bool isWRAM0Mode; -extern bool disablePadding; +struct Options { + bool isDmgMode; // -d + char const *linkerScriptName; // -l + char const *mapFileName; // -m + bool noSymInMap; // -M + char const *symFileName; // -n + char const *overlayFileName; // -O + char const *outputFileName; // -o + uint8_t padValue; // -p + bool hasPadValue = false; + // Setting these three to 0 disables the functionality + uint16_t scrambleROMX = 0; // -S + uint8_t scrambleWRAMX = 0; + uint8_t scrambleSRAM = 0; + bool is32kMode; // -t + bool beVerbose; // -v + bool isWRAM0Mode; // -w + bool disablePadding; // -x +}; + +extern Options options; #define verbosePrint(...) \ do { \ - if (beVerbose) { \ + if (options.beVerbose) { \ fprintf(stderr, __VA_ARGS__); \ } \ } while (0) diff --git a/src/link/assign.cpp b/src/link/assign.cpp index 6cb2b766..828c40c1 100644 --- a/src/link/assign.cpp +++ b/src/link/assign.cpp @@ -96,19 +96,19 @@ static ssize_t getPlacement(Section const §ion, MemoryLocation &location) { // Determine which bank we should start searching in if (section.isBankFixed) { location.bank = section.bank; - } else if (scrambleROMX && section.type == SECTTYPE_ROMX) { + } else if (options.scrambleROMX && section.type == SECTTYPE_ROMX) { if (curScrambleROM < 1) { - curScrambleROM = scrambleROMX; + curScrambleROM = options.scrambleROMX; } location.bank = curScrambleROM--; - } else if (scrambleWRAMX && section.type == SECTTYPE_WRAMX) { + } else if (options.scrambleWRAMX && section.type == SECTTYPE_WRAMX) { if (curScrambleWRAM < 1) { - curScrambleWRAM = scrambleWRAMX; + curScrambleWRAM = options.scrambleWRAMX; } location.bank = curScrambleWRAM--; - } else if (scrambleSRAM && section.type == SECTTYPE_SRAM) { + } else if (options.scrambleSRAM && section.type == SECTTYPE_SRAM) { if (curScrambleSRAM < 0) { - curScrambleSRAM = scrambleSRAM; + curScrambleSRAM = options.scrambleSRAM; } location.bank = curScrambleSRAM--; } else { @@ -172,28 +172,30 @@ static ssize_t getPlacement(Section const §ion, MemoryLocation &location) { // available. Otherwise, try in ascending order. if (section.isBankFixed) { return -1; - } else if (scrambleROMX && section.type == SECTTYPE_ROMX && location.bank <= scrambleROMX) { + } else if (options.scrambleROMX && section.type == SECTTYPE_ROMX + && location.bank <= options.scrambleROMX) { if (location.bank > typeInfo.firstBank) { --location.bank; - } else if (scrambleROMX < typeInfo.lastBank) { - location.bank = scrambleROMX + 1; + } else if (options.scrambleROMX < typeInfo.lastBank) { + location.bank = options.scrambleROMX + 1; } else { return -1; } - } else if (scrambleWRAMX && section.type == SECTTYPE_WRAMX - && location.bank <= scrambleWRAMX) { + } else if (options.scrambleWRAMX && section.type == SECTTYPE_WRAMX + && location.bank <= options.scrambleWRAMX) { if (location.bank > typeInfo.firstBank) { --location.bank; - } else if (scrambleWRAMX < typeInfo.lastBank) { - location.bank = scrambleWRAMX + 1; + } else if (options.scrambleWRAMX < typeInfo.lastBank) { + location.bank = options.scrambleWRAMX + 1; } else { return -1; } - } else if (scrambleSRAM && section.type == SECTTYPE_SRAM && location.bank <= scrambleSRAM) { + } else if (options.scrambleSRAM && section.type == SECTTYPE_SRAM + && location.bank <= options.scrambleSRAM) { if (location.bank > typeInfo.firstBank) { --location.bank; - } else if (scrambleSRAM < typeInfo.lastBank) { - location.bank = scrambleSRAM + 1; + } else if (options.scrambleSRAM < typeInfo.lastBank) { + location.bank = options.scrambleSRAM + 1; } else { return -1; } @@ -388,7 +390,7 @@ void assign_AssignSections() { // Overlaying requires only fully-constrained sections verbosePrint("Assigning other sections...\n"); - if (overlayFileName) { + if (options.overlayFileName) { fputs("FATAL: All sections must be fixed when using an overlay file", stderr); uint8_t nbSections = 0; for (int8_t constraints = BANK_CONSTRAINED | ALIGN_CONSTRAINED; constraints >= 0; diff --git a/src/link/main.cpp b/src/link/main.cpp index 9e6390dc..34b5ecb2 100644 --- a/src/link/main.cpp +++ b/src/link/main.cpp @@ -25,23 +25,7 @@ #include "link/symbol.hpp" #include "link/warning.hpp" -bool isDmgMode; // -d -char const *linkerScriptName; // -l -char const *mapFileName; // -m -bool noSymInMap; // -M -char const *symFileName; // -n -char const *overlayFileName; // -O -char const *outputFileName; // -o -uint8_t padValue; // -p -bool hasPadValue = false; -// Setting these three to 0 disables the functionality -uint16_t scrambleROMX = 0; // -S -uint8_t scrambleWRAMX = 0; -uint8_t scrambleSRAM = 0; -bool is32kMode; // -t -bool beVerbose; // -v -bool isWRAM0Mode; // -w -bool disablePadding; // -x +Options options; FILE *linkerScript; @@ -243,20 +227,20 @@ static void parseScrambleSpec(char const *spec) { switch (region) { case SCRAMBLE_ROMX: - scrambleROMX = limit; + options.scrambleROMX = limit; break; case SCRAMBLE_SRAM: - scrambleSRAM = limit; + options.scrambleSRAM = limit; break; case SCRAMBLE_WRAMX: - scrambleWRAMX = limit; + options.scrambleWRAMX = limit; break; case SCRAMBLE_UNK: // The error has already been reported, do nothing break; } } else if (region == SCRAMBLE_WRAMX) { // Only WRAMX can be implied, since ROMX and SRAM size may vary - scrambleWRAMX = 7; + options.scrambleWRAMX = 7; } else { argErr('S', "Cannot imply limit for region \"%.*s\"", regionNameFmtLen, regionName); } @@ -279,8 +263,8 @@ int main(int argc, char *argv[]) { for (int ch; (ch = musl_getopt_long_only(argc, argv, optstring, longopts, nullptr)) != -1;) { switch (ch) { case 'd': - isDmgMode = true; - isWRAM0Mode = true; + options.isDmgMode = true; + options.isWRAM0Mode = true; break; case 'h': // LCOV_EXCL_START @@ -288,37 +272,37 @@ int main(int argc, char *argv[]) { exit(0); // LCOV_EXCL_STOP case 'l': - if (linkerScriptName) { - warnx("Overriding linker script %s", linkerScriptName); + if (options.linkerScriptName) { + warnx("Overriding linker script %s", options.linkerScriptName); } - linkerScriptName = musl_optarg; + options.linkerScriptName = musl_optarg; break; case 'M': - noSymInMap = true; + options.noSymInMap = true; break; case 'm': - if (mapFileName) { - warnx("Overriding map file %s", mapFileName); + if (options.mapFileName) { + warnx("Overriding map file %s", options.mapFileName); } - mapFileName = musl_optarg; + options.mapFileName = musl_optarg; break; case 'n': - if (symFileName) { - warnx("Overriding sym file %s", symFileName); + if (options.symFileName) { + warnx("Overriding sym file %s", options.symFileName); } - symFileName = musl_optarg; + options.symFileName = musl_optarg; break; case 'O': - if (overlayFileName) { - warnx("Overriding overlay file %s", overlayFileName); + if (options.overlayFileName) { + warnx("Overriding overlay file %s", options.overlayFileName); } - overlayFileName = musl_optarg; + options.overlayFileName = musl_optarg; break; case 'o': - if (outputFileName) { - warnx("Overriding output file %s", outputFileName); + if (options.outputFileName) { + warnx("Overriding output file %s", options.outputFileName); } - outputFileName = musl_optarg; + options.outputFileName = musl_optarg; break; case 'p': { char *endptr; @@ -328,15 +312,15 @@ int main(int argc, char *argv[]) { argErr('p', "Argument for 'p' must be a byte (between 0 and 0xFF)"); value = 0xFF; } - padValue = value; - hasPadValue = true; + options.padValue = value; + options.hasPadValue = true; break; } case 'S': parseScrambleSpec(musl_optarg); break; case 't': - is32kMode = true; + options.is32kMode = true; break; case 'V': // LCOV_EXCL_START @@ -345,19 +329,19 @@ int main(int argc, char *argv[]) { // LCOV_EXCL_STOP case 'v': // LCOV_EXCL_START - beVerbose = true; + options.beVerbose = true; break; // LCOV_EXCL_STOP case 'W': warnings.processWarningFlag(musl_optarg); break; case 'w': - isWRAM0Mode = true; + options.isWRAM0Mode = true; break; case 'x': - disablePadding = true; + options.disablePadding = true; // implies tiny mode - is32kMode = true; + options.is32kMode = true; break; default: // LCOV_EXCL_START @@ -375,15 +359,15 @@ int main(int argc, char *argv[]) { } // Patch the size array depending on command-line options - if (!is32kMode) { + if (!options.is32kMode) { sectionTypeInfo[SECTTYPE_ROM0].size = 0x4000; } - if (!isWRAM0Mode) { + if (!options.isWRAM0Mode) { sectionTypeInfo[SECTTYPE_WRAM0].size = 0x1000; } // Patch the bank ranges array depending on command-line options - if (isDmgMode) { + if (options.isDmgMode) { sectionTypeInfo[SECTTYPE_VRAM].lastBank = 0; } @@ -393,10 +377,10 @@ int main(int argc, char *argv[]) { } // apply the linker script's modifications, - if (linkerScriptName) { + if (options.linkerScriptName) { verbosePrint("Reading linker script...\n"); - script_ProcessScript(linkerScriptName); + script_ProcessScript(); // If the linker script produced any errors, some sections may be in an invalid state requireZeroErrors(); diff --git a/src/link/output.cpp b/src/link/output.cpp index 63422dc1..c610997a 100644 --- a/src/link/output.cpp +++ b/src/link/output.cpp @@ -125,7 +125,7 @@ static uint32_t checkOverlaySize() { if (overlaySize % BANK_SIZE) { warnx("Overlay file does not have a size multiple of 0x4000"); - } else if (is32kMode && overlaySize != 0x8000) { + } else if (options.is32kMode && overlaySize != 0x8000) { warnx("Overlay is not exactly 0x8000 bytes large"); } else if (overlaySize < 0x8000) { warnx("Overlay is less than 0x8000 bytes large"); @@ -138,7 +138,7 @@ static uint32_t checkOverlaySize() { // This ensures that `writeROM` will output each bank, even if some are not // covered by any sections. static void coverOverlayBanks(uint32_t nbOverlayBanks) { - // 2 if is32kMode, 1 otherwise + // 2 if options.is32kMode, 1 otherwise uint32_t nbRom0Banks = sectionTypeInfo[SECTTYPE_ROM0].size / BANK_SIZE; // Discount ROM0 banks to avoid outputting too much uint32_t nbUncoveredBanks = nbOverlayBanks - nbRom0Banks > sections[SECTTYPE_ROMX].size() @@ -159,13 +159,13 @@ static uint8_t getNextFillByte() { return c; } - if (static bool warned = false; !hasPadValue && !warned) { + if (static bool warned = false; !options.hasPadValue && !warned) { warnx("Output is larger than overlay file, but no padding value was specified"); warned = true; } } - return padValue; + return options.padValue; } static void @@ -193,7 +193,7 @@ static void } } - if (!disablePadding) { + if (!options.disablePadding) { while (offset < size) { putc(getNextFillByte(), outputFile); ++offset; @@ -202,16 +202,16 @@ static void } static void writeROM() { - if (outputFileName) { - if (strcmp(outputFileName, "-")) { - outputFile = fopen(outputFileName, "wb"); + if (options.outputFileName) { + if (strcmp(options.outputFileName, "-")) { + outputFile = fopen(options.outputFileName, "wb"); } else { - outputFileName = ""; + options.outputFileName = ""; (void)setmode(STDOUT_FILENO, O_BINARY); outputFile = stdout; } if (!outputFile) { - fatal("Failed to open output file \"%s\": %s", outputFileName, strerror(errno)); + fatal("Failed to open output file \"%s\": %s", options.outputFileName, strerror(errno)); } } Defer closeOutputFile{[&] { @@ -220,16 +220,18 @@ static void writeROM() { } }}; - if (overlayFileName) { - if (strcmp(overlayFileName, "-")) { - overlayFile = fopen(overlayFileName, "rb"); + if (options.overlayFileName) { + if (strcmp(options.overlayFileName, "-")) { + overlayFile = fopen(options.overlayFileName, "rb"); } else { - overlayFileName = ""; + options.overlayFileName = ""; (void)setmode(STDIN_FILENO, O_BINARY); overlayFile = stdin; } if (!overlayFile) { - fatal("Failed to open overlay file \"%s\": %s", overlayFileName, strerror(errno)); + fatal( + "Failed to open overlay file \"%s\": %s", options.overlayFileName, strerror(errno) + ); } } Defer closeOverlayFile{[&] { @@ -471,7 +473,7 @@ static void writeMapBank(SortedSections const §List, SectionType type, uint3 writeSectionName(sect.name, mapFile); fputs("\"]\n", mapFile); - if (!noSymInMap) { + if (!options.noSymInMap) { // Also print symbols in the following "pieces" writeMapSymbols(§); } @@ -529,19 +531,19 @@ static void writeMapSummary() { } static void writeSym() { - if (!symFileName) { + if (!options.symFileName) { return; } - if (strcmp(symFileName, "-")) { - symFile = fopen(symFileName, "w"); + if (strcmp(options.symFileName, "-")) { + symFile = fopen(options.symFileName, "w"); } else { - symFileName = ""; + options.symFileName = ""; (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", symFileName, strerror(errno)); + fatal("Failed to open sym file \"%s\": %s", options.symFileName, strerror(errno)); } Defer closeSymFile{[&] { fclose(symFile); }}; @@ -579,19 +581,19 @@ static void writeSym() { } static void writeMap() { - if (!mapFileName) { + if (!options.mapFileName) { return; } - if (strcmp(mapFileName, "-")) { - mapFile = fopen(mapFileName, "w"); + if (strcmp(options.mapFileName, "-")) { + mapFile = fopen(options.mapFileName, "w"); } else { - mapFileName = ""; + options.mapFileName = ""; (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", mapFileName, strerror(errno)); + fatal("Failed to open map file \"%s\": %s", options.mapFileName, strerror(errno)); } Defer closeMapFile{[&] { fclose(mapFile); }}; diff --git a/src/link/script.y b/src/link/script.y index 22a5022c..0f769b76 100644 --- a/src/link/script.y +++ b/src/link/script.y @@ -10,7 +10,7 @@ #include "linkdefs.hpp" - void script_ProcessScript(char const *path); + void script_ProcessScript(); } %code { @@ -828,12 +828,12 @@ static void placeSection(std::string const &name, bool isOptional) { /******************** External API ********************/ -void script_ProcessScript(char const *path) { +void script_ProcessScript() { activeType = SECTTYPE_INVALID; lexerStack.clear(); atEof = false; - LexerStackEntry &newContext = lexerStack.emplace_back(std::string(path)); + LexerStackEntry &newContext = lexerStack.emplace_back(std::string(options.linkerScriptName)); if (!newContext.file.open(newContext.path, std::ios_base::in)) { error("Failed to open linker script \"%s\"", newContext.path.c_str()); diff --git a/src/link/section.cpp b/src/link/section.cpp index d4b43e34..a3cd6497 100644 --- a/src/link/section.cpp +++ b/src/link/section.cpp @@ -247,7 +247,7 @@ static void doSanityChecks(Section §ion) { return; } - if (is32kMode && section.type == SECTTYPE_ROMX) { + if (options.is32kMode && section.type == SECTTYPE_ROMX) { if (section.isBankFixed && section.bank != 1) { error( "Section \"%s\" has type ROMX, which must be in bank 1 (if any) with option `-t`", @@ -257,7 +257,7 @@ static void doSanityChecks(Section §ion) { section.type = SECTTYPE_ROM0; } } - if (isWRAM0Mode && section.type == SECTTYPE_WRAMX) { + if (options.isWRAM0Mode && section.type == SECTTYPE_WRAMX) { if (section.isBankFixed && section.bank != 1) { error( "Section \"%s\" has type WRAMX, which must be in bank 1 with options `-w` or `-d`", @@ -267,7 +267,7 @@ static void doSanityChecks(Section §ion) { section.type = SECTTYPE_WRAM0; } } - if (isDmgMode && section.type == SECTTYPE_VRAM && section.bank == 1) { + if (options.isDmgMode && section.type == SECTTYPE_VRAM && section.bank == 1) { error( "Section \"%s\" has type VRAM, which must be in bank 0 with option `-d`", section.name.c_str()