spec: change include to ignore duped includes across spec (#2777)

* spec: impl `include_once` and error on duped includes across spec

* duped includes fixups

* rm get_single_segment_by_name from spec.c (unused code)

* replace include logic with include_once's
This commit is contained in:
Dragorn421
2026-08-03 16:42:52 +02:00
committed by GitHub
parent da4a1f661c
commit 22d4ca0be7
4 changed files with 21 additions and 92 deletions
-8
View File
@@ -22,10 +22,8 @@
include "$(BUILD_DIR)/src/libultra/gu/us2dex.o"
include "$(BUILD_DIR)/src/libultra/libc/ll.o"
include "$(BUILD_DIR)/src/libultra/libc/llcvt.o"
#if !DEBUG_FEATURES
include "$(BUILD_DIR)/src/libultra/libc/string.o"
include "$(BUILD_DIR)/src/libultra/libc/xprintf.o"
#endif
include "$(BUILD_DIR)/src/libultra/io/dpgetstat.o"
include "$(BUILD_DIR)/src/libultra/io/dpsetstat.o"
include "$(BUILD_DIR)/src/libultra/io/spgetstat.o"
@@ -83,9 +81,7 @@
include "$(BUILD_DIR)/src/libultra/io/vimodempalhpf2.o"
include "$(BUILD_DIR)/src/libultra/io/vimodefpallpn1.o"
include "$(BUILD_DIR)/src/libultra/io/vimodefpallpf1.o"
#if !DEBUG_FEATURES
include "$(BUILD_DIR)/src/libultra/io/vimodefpallan1.o"
#endif
include "$(BUILD_DIR)/src/libultra/io/vimodefpallaf1.o"
include "$(BUILD_DIR)/src/libultra/io/vimodefpallpn2.o"
include "$(BUILD_DIR)/src/libultra/io/vimodefpallpf2.o"
@@ -122,14 +118,10 @@
include "$(BUILD_DIR)/src/libultra/audio/heapalloc.o"
include "$(BUILD_DIR)/src/libultra/audio/copy.o"
include "$(BUILD_DIR)/src/libultra/gu/libm_vals.o"
#if !DEBUG_FEATURES
include "$(BUILD_DIR)/src/libultra/libc/xlitob.o"
include "$(BUILD_DIR)/src/libultra/libc/xldtob.o"
#endif
include "$(BUILD_DIR)/src/libultra/io/sp.o"
include "$(BUILD_DIR)/src/libultra/io/spsetpc.o"
include "$(BUILD_DIR)/src/libultra/io/sprawdma.o"
include "$(BUILD_DIR)/src/libultra/mgu/normalize.o"
#if !DEBUG_FEATURES
include "$(BUILD_DIR)/src/libultra/libc/ldiv.o"
#endif
-8
View File
@@ -718,9 +718,7 @@ beginseg
include "$(BUILD_DIR)/src/libu64/padsetup.o"
#elif PLATFORM_IQUE
include "$(BUILD_DIR)/src/libu64/runtime.o"
#if !DEBUG_FEATURES
include "$(BUILD_DIR)/src/libu64/debug.o"
#endif
include "$(BUILD_DIR)/src/libu64/gfxprint.o"
include "$(BUILD_DIR)/src/libu64/logseverity_gc.o"
include "$(BUILD_DIR)/src/libu64/relocation_gc.o"
@@ -783,23 +781,17 @@ beginseg
#if PLATFORM_N64
include "$(BUILD_DIR)/src/libc/sqrt.o"
include "$(BUILD_DIR)/src/libc/fmodf.o"
#if !COMPILER_GCC
include "$(BUILD_DIR)/src/libc/memset.o"
include "$(BUILD_DIR)/src/libc/memmove.o"
#endif
#elif PLATFORM_GC
include "$(BUILD_DIR)/src/libc/sqrt.o"
include "$(BUILD_DIR)/src/libc/fabsf.o"
include "$(BUILD_DIR)/src/libc/fmodf.o"
#if !COMPILER_GCC
include "$(BUILD_DIR)/src/libc/memset.o"
include "$(BUILD_DIR)/src/libc/memmove.o"
#endif
#elif PLATFORM_IQUE
include "$(BUILD_DIR)/src/libc/fmodf.o"
#if !COMPILER_GCC
include "$(BUILD_DIR)/src/libc/memmove.o"
#endif
include "$(BUILD_DIR)/src/libc/fabsf.o"
include "$(BUILD_DIR)/src/libc/sqrt.o"
#endif
+21 -72
View File
@@ -157,7 +157,7 @@ STMTId get_stmt_id_by_stmt_name(const char *stmtName, int lineNum) {
return -1;
}
bool parse_segment_statement(struct Segment *currSeg, STMTId stmt, char* args, int lineNum) {
bool parse_segment_statement(struct Segment *currSeg, STMTId stmt, char* args, int lineNum, const struct Segment *segments, int segment_count) {
// ensure no duplicates (except for 'include' or 'pad_text')
if (stmt != STMT_include && stmt != STMT_pad_text &&
(currSeg->fields & (1 << stmt)))
@@ -211,15 +211,28 @@ bool parse_segment_statement(struct Segment *currSeg, STMTId stmt, char* args, i
if (!is_pow_of_2(currSeg->romalign))
util_fatal_error("line %i: alignment is not a power of two", lineNum);
break;
case STMT_include:
currSeg->includesCount++;
currSeg->includes = realloc(currSeg->includes, currSeg->includesCount * sizeof(*currSeg->includes));
case STMT_include: {
char *inc;
if (!parse_quoted_string(args, &currSeg->includes[currSeg->includesCount - 1].fpath))
if (!parse_quoted_string(args, &inc))
util_fatal_error("line %i: invalid filename", lineNum);
currSeg->includes[currSeg->includesCount - 1].linkerPadding = 0;
break;
bool inc_is_dup = false;
for (int i = 0; i < segment_count; i++) {
for (int j = 0; j < segments[i].includesCount; j++) {
if (strcmp(segments[i].includes[j].fpath, inc) == 0) {
inc_is_dup = true;
}
}
}
if (!inc_is_dup) {
currSeg->includesCount++;
currSeg->includes = realloc(currSeg->includes, currSeg->includesCount * sizeof(*currSeg->includes));
currSeg->includes[currSeg->includesCount - 1].fpath = inc;
currSeg->includes[currSeg->includesCount - 1].linkerPadding = 0;
}
} break;
case STMT_increment:
if (!parse_number(args, &currSeg->increment))
util_fatal_error("line %i: expected number after 'increment'", lineNum);
@@ -267,7 +280,7 @@ void parse_rom_spec(char *spec, struct Segment **segments, int *segment_count)
if (currSeg != NULL)
{
bool segmentEnded = parse_segment_statement(currSeg, stmt, args, lineNum);
bool segmentEnded = parse_segment_statement(currSeg, stmt, args, lineNum, *segments, *segment_count);
if (segmentEnded) {
currSeg = NULL;
}
@@ -296,70 +309,6 @@ void parse_rom_spec(char *spec, struct Segment **segments, int *segment_count)
}
}
/**
* @brief Parses the spec, looking only for the segment with the name `segmentName`.
* Returns true if the segment was found, false otherwise
*
* @param[out] dstSegment The Segment to be filled. Will only contain the data of the searched segment, or garbage if the segment was not found. dstSegment must be previously allocated, a stack variable is recommended
* @param[in,out] spec A null-terminated string containing the whole spec file. This string will be modified by this function
* @param[in] segmentName The name of the segment being searched
*/
bool get_single_segment_by_name(struct Segment* dstSegment, char *spec, const char *segmentName) {
bool insideSegment = false;
int lineNum = 1;
char *line = spec;
memset(dstSegment, 0, sizeof(struct Segment));
// iterate over lines
while (line[0] != '\0') {
char *nextLine = line_split(line);
char* stmtName = skip_whitespace(line);
if (stmtName[0] != '\0') {
char *args = token_split(stmtName);
STMTId stmt = get_stmt_id_by_stmt_name(stmtName, lineNum);
if (insideSegment) {
bool segmentEnded = parse_segment_statement(dstSegment, stmt, args, lineNum);
if (stmt == STMT_name) {
if (strcmp(segmentName, dstSegment->name) != 0) {
// Not the segment we are looking for
insideSegment = false;
}
} else if (segmentEnded) {
return true;
}
} else {
if (stmt == STMT_beginseg) {
insideSegment = true;
if (dstSegment->includes != NULL) {
free(dstSegment->includes);
}
memset(dstSegment, 0, sizeof(struct Segment));
}
}
}
line = nextLine;
lineNum++;
}
return false;
}
/**
* @brief Frees the elements of the passed Segment. Will not free the pointer itself
*
* @param segment
*/
void free_single_segment_elements(struct Segment *segment) {
if (segment->includes != NULL) {
free(segment->includes);
}
}
void free_rom_spec(struct Segment *segments, int segment_count)
{
int i;
-4
View File
@@ -55,10 +55,6 @@ typedef struct Segment {
void parse_rom_spec(char* spec, struct Segment** segments, int* segment_count);
bool get_single_segment_by_name(struct Segment* dstSegment, char *spec, const char *segmentName);
void free_single_segment_elements(struct Segment *segment);
void free_rom_spec(struct Segment* segments, int segment_count);
#endif