ref: bf75971a3a823a8bac2d4012c8ae0ccf33eec189
parent: 8a59994c0dd9e15fd50462d1242377fedcdcdad4
author: ISSOtm <[email protected]>
date: Fri Oct 11 05:04:50 EDT 2019
Only open files when necessary
--- a/include/link/main.h
+++ b/include/link/main.h
@@ -16,11 +16,11 @@
/* Variables related to CLI options */
extern bool isDmgMode;
-extern FILE *linkerScript;
-extern FILE *mapFile;
-extern FILE *symFile;
-extern FILE *overlayFile;
-extern FILE *outputFile;
+extern char const *linkerScriptName;
+extern char const *mapFileName;
+extern char const *symFileName;
+extern char const *overlayFileName;
+extern char const *outputFileName;
extern uint8_t padValue;
extern bool is32kMode;
extern bool beVerbose;
@@ -31,5 +31,19 @@
if (beVerbose) \
fprintf(stderr, __VA_ARGS__); \
} while (0)
+
+/**
+ * Opens a file if specified, and aborts on error.
+ * @param fileName The name of the file to open; if NULL, no file will be opened
+ * @param mode The mode to open the file with
+ * @return A pointer to a valid FILE structure, or NULL if fileName was NULL
+ */
+FILE *openFile(char const *fileName, char const *mode);
+
+#define closeFile(file) do { \
+ FILE *tmp = file; \
+ if (tmp) \
+ fclose(tmp); \
+ } while (0)
#endif /* RGBDS_LINK_MAIN_H */
--- a/include/link/script.h
+++ b/include/link/script.h
@@ -12,6 +12,8 @@
#include <stdint.h>
+extern FILE *linkerScript;
+
struct SectionPlacement {
struct Section *section;
uint16_t org;
--- a/src/link/assign.c
+++ b/src/link/assign.c
@@ -58,10 +58,12 @@
*/
static void processLinkerScript(void)
{
- if (!linkerScript)
+ if (!linkerScriptName)
return;
verbosePrint("Reading linker script...\n");
+ linkerScript = openFile(linkerScriptName, "r");
+
/* Modify all sections according to the linker script */
struct SectionPlacement *placement;
@@ -86,6 +88,8 @@
section->bank = placement->bank;
section->isAlignFixed = false; /* The alignment is satisfied */
}
+
+ fclose(linkerScript);
}
/**
@@ -385,7 +389,7 @@
/* Overlaying requires only fully-constrained sections */
verbosePrint("Assigning other sections...\n");
- if (overlayFile)
+ if (overlayFileName)
errx(1, "All sections must be fixed when using an overlay file; %u, %sn't",
nbSectionsToAssign, nbSectionsToAssign == 1 ? "is" : "are");
--- a/src/link/main.c
+++ b/src/link/main.c
@@ -6,6 +6,8 @@
* SPDX-License-Identifier: MIT
*/
+#include <sys/types.h>
+#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <stdbool.h>
@@ -22,17 +24,30 @@
#include "extern/err.h"
#include "version.h"
-bool isDmgMode; /* -d */
-FILE *linkerScript; /* -l */
-FILE *mapFile; /* -m */
-FILE *symFile; /* -n */
-FILE *overlayFile; /* -O */
-FILE *outputFile; /* -o */
-uint8_t padValue; /* -p */
-bool is32kMode; /* -t */
-bool beVerbose; /* -v */
-bool isWRA0Mode; /* -w */
+bool isDmgMode; /* -d */
+char const *linkerScriptName; /* -l */
+char const *mapFileName; /* -m */
+char const *symFileName; /* -n */
+char const *overlayFileName; /* -O */
+char const *outputFileName; /* -o */
+uint8_t padValue; /* -p */
+bool is32kMode; /* -t */
+bool beVerbose; /* -v */
+bool isWRA0Mode; /* -w */
+FILE *openFile(char const *fileName, char const *mode)
+{
+ if (!fileName)
+ return NULL;
+
+ FILE *file = fopen(fileName, mode);
+
+ if (!file)
+ err(1, "Could not open file \"%s\"", fileName);
+
+ return file;
+}
+
/**
* Prints the program's usage to stdout.
*/
@@ -43,41 +58,11 @@
}
/**
- * Helper function for `main`'s argument parsing.
- * For use with options which take a file name to operate on
- * If the file fails to be opened, an error message will be printed,
- * and the function `exit`s.
- * @param mode The mode to open the file in
- * @param failureMessage A format string that will be printed on failure.
- * A single (string) argument is given, the file name.
- * @return What `fopen` returned; this cannot be NULL.
- */
-static FILE *openArgFile(char const *mode, char const *failureMessage)
-{
- FILE *file = fopen(optarg, mode);
-
- if (!file)
- err(1, failureMessage, optarg);
- return file;
-}
-
-/**
* Cleans up what has been done
* Mostly here to please tools such as `valgrind` so actual errors can be seen
*/
static void cleanup(void)
{
- if (linkerScript)
- fclose(linkerScript);
- if (mapFile)
- fclose(mapFile);
- if (symFile)
- fclose(symFile);
- if (overlayFile)
- fclose(overlayFile);
- if (outputFile)
- fclose(outputFile);
-
obj_Cleanup();
}
@@ -95,19 +80,19 @@
isWRA0Mode = true;
break;
case 'l':
- linkerScript = openArgFile("r", "Could not open linker script file \"%s\"");
+ linkerScriptName = optarg;
break;
case 'm':
- mapFile = openArgFile("w", "Could not open map file \"%s\"");
+ mapFileName = optarg;
break;
case 'n':
- symFile = openArgFile("w", "Could not open sym file \"%s\"");
+ symFileName = optarg;
break;
case 'O':
- overlayFile = openArgFile("r+b", "Could not open overlay file \"%s\"");
+ overlayFileName = optarg;
break;
case 'o':
- outputFile = openArgFile("wb", "Could not open output file \"%s\"");
+ outputFileName = optarg;
break;
case 'p':
value = strtoul(optarg, &endptr, 0);
--- a/src/link/output.c
+++ b/src/link/output.c
@@ -9,6 +9,11 @@
#include "extern/err.h"
+FILE *outputFile;
+FILE *overlayFile;
+FILE *symFile;
+FILE *mapFile;
+
struct SortedSection {
struct Section const *section;
struct SortedSection *next;
@@ -158,6 +163,9 @@
*/
static void writeROM(void)
{
+ outputFile = openFile(outputFileName, "wb");
+ overlayFile = openFile(overlayFileName, "rb");
+
checkOverlay();
if (outputFile) {
@@ -177,6 +185,9 @@
funlockfile(overlayFile);
funlockfile(outputFile);
}
+
+ closeFile(outputFile);
+ closeFile(overlayFile);
}
/**
@@ -310,7 +321,7 @@
*/
static void writeSymAndMap(void)
{
- if (!symFile && !mapFile)
+ if (!symFileName && !mapFileName)
return;
enum SectionType typeMap[SECTTYPE_INVALID] = {
@@ -324,8 +335,12 @@
SECTTYPE_HRAM
};
- if (symFile)
+ symFile = openFile(symFileName, "w");
+ mapFile = openFile(mapFileName, "w");
+
+ if (symFileName) {
fputs("; File generated by rgblink\n", symFile);
+ }
for (uint8_t i = 0; i < SECTTYPE_INVALID; i++) {
enum SectionType type = typeMap[i];
@@ -339,6 +354,9 @@
}
}
}
+
+ closeFile(symFile);
+ closeFile(mapFile);
}
static void cleanupSections(struct SortedSection *section)
--- a/src/link/script.c
+++ b/src/link/script.c
@@ -11,6 +11,8 @@
#include "extern/err.h"
+FILE *linkerScript;
+
static inline bool isWhiteSpace(int c)
{
return c == ' ' || c == '\t';