From 22d4ca0be7c37ffe5aa5cd8582ca1fb4e2dc73a6 Mon Sep 17 00:00:00 2001 From: Dragorn421 Date: Mon, 3 Aug 2026 16:42:52 +0200 Subject: [PATCH] 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 --- spec/code_libultra_ique.inc | 8 ---- spec/spec | 8 ---- tools/spec.c | 93 +++++++++---------------------------- tools/spec.h | 4 -- 4 files changed, 21 insertions(+), 92 deletions(-) diff --git a/spec/code_libultra_ique.inc b/spec/code_libultra_ique.inc index 3079d11558..e99152cf98 100644 --- a/spec/code_libultra_ique.inc +++ b/spec/code_libultra_ique.inc @@ -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 diff --git a/spec/spec b/spec/spec index f89c5e8ad1..766d1cbfa2 100644 --- a/spec/spec +++ b/spec/spec @@ -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 diff --git a/tools/spec.c b/tools/spec.c index 4c079834f3..187549ead7 100644 --- a/tools/spec.c +++ b/tools/spec.c @@ -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; diff --git a/tools/spec.h b/tools/spec.h index 8c48910430..96ca6c16f6 100644 --- a/tools/spec.h +++ b/tools/spec.h @@ -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