gbdk-2020 | GameBoy Development Kit |
| download: https://git.y1.nz/archives/gbdk.tar.gz | |
| README | Files | Log | Refs | LICENSE |
commit 13af6a39d0f605369ae5c3af71438d0a74d20c44 parent 7028bded45f325923073529fc743481b52294d61 Author: Toxa <56631470+untoxa@users.noreply.github.com> Date: Sat, 14 Nov 2020 00:16:29 +0300 Merge pull request #85 from bbbbbr/develop_ihxcheck Add multiple write check for IHX files (ihxcheck) to build process Diffstat:
| M | Makefile | 10 | ++++++++++ |
| A | gbdk-support/ihxcheck/LICENSE | 24 | ++++++++++++++++++++++++ |
| A | gbdk-support/ihxcheck/Makefile | 17 | +++++++++++++++++ |
| A | gbdk-support/ihxcheck/areas.c | 98 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | gbdk-support/ihxcheck/areas.h | 20 | ++++++++++++++++++++ |
| A | gbdk-support/ihxcheck/ihx_file.c | 262 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | gbdk-support/ihxcheck/ihx_file.h | 13 | +++++++++++++ |
| A | gbdk-support/ihxcheck/ihxcheck.c | 88 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| M | gbdk-support/lcc/gb.c | 7 | +++++++ |
| M | gbdk-support/lcc/lcc.c | 24 | ++++++++++++++++++++---- |
10 files changed, 559 insertions(+), 4 deletions(-)
diff --git a/Makefile b/Makefile @@ -117,6 +117,9 @@ gbdk-support-build: @echo Building lcc @$(MAKE) -C $(GBDKSUPPORTDIR)/lcc TOOLSPREFIX=$(TOOLSPREFIX) TARGETDIR=$(TARGETDIR)/ --no-print-directory @echo + @echo Building ihxcheck + @$(MAKE) -C $(GBDKSUPPORTDIR)/ihxcheck TOOLSPREFIX=$(TOOLSPREFIX) TARGETDIR=$(TARGETDIR)/ --no-print-directory + @echo gbdk-support-install: gbdk-support-build $(BUILDDIR)/bin @echo Installing lcc @@ -125,11 +128,18 @@ gbdk-support-install: gbdk-support-build $(BUILDDIR)/bin @cp $(GBDKSUPPORTDIR)/ChangeLog $(BUILDDIR) @cp $(GBDKSUPPORTDIR)/README $(BUILDDIR) @echo + @echo Installing ihxcheck + @cp $(GBDKSUPPORTDIR)/ihxcheck/ihxcheck $(BUILDDIR)/bin/ihxcheck$(EXEEXTENSION) + @$(TARGETSTRIP) $(BUILDDIR)/bin/ihxcheck* + @echo gbdk-support-clean: @echo Cleaning lcc @$(MAKE) -C $(GBDKSUPPORTDIR)/lcc clean --no-print-directory @echo + @echo Cleaning ihxcheck + @$(MAKE) -C $(GBDKSUPPORTDIR)/ihxcheck clean --no-print-directory + @echo # Rules for gbdk-lib gbdk-lib-build: check-SDCCDIR diff --git a/gbdk-support/ihxcheck/LICENSE b/gbdk-support/ihxcheck/LICENSE @@ -0,0 +1,24 @@ +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to <https://unlicense.org> diff --git a/gbdk-support/ihxcheck/Makefile b/gbdk-support/ihxcheck/Makefile @@ -0,0 +1,17 @@ +# ihxcheck makefile + +ifndef TARGETDIR +TARGETDIR = /opt/gbdk +endif + +CC = $(TOOLSPREFIX)gcc +CFLAGS = -ggdb -O -Wno-incompatible-pointer-types -DGBDKLIBDIR=\"$(TARGETDIR)\" +OBJ = ihxcheck.o areas.o ihx_file.o +BIN = ihxcheck + +all: $(BIN) + +$(BIN): $(OBJ) + +clean: + rm -f *.o $(BIN) *~ diff --git a/gbdk-support/ihxcheck/areas.c b/gbdk-support/ihxcheck/areas.c @@ -0,0 +1,97 @@ +// This is free and unencumbered software released into the public domain. +// For more information, please refer to <https://unlicense.org> +// bbbbbr 2020 + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +// #include <unistd.h> +#include <stdbool.h> +#include <stdint.h> + +#include "areas.h" + +#define AREA_GROW_SIZE 500 + +area_item * arealist; +uint32_t arealist_size; +uint32_t arealist_count; + + +uint32_t min(uint32_t a, uint32_t b) { + return (a < b) ? a : b; +} + +uint32_t max(uint32_t a, uint32_t b) { + return (a > b) ? a : b; +} + + +// Returns size of overlap between two address ranges, +// if zero then no overlap +static uint32_t addrs_check_overlap(uint32_t a_start, uint32_t a_end, uint32_t b_start, uint32_t b_end) { + + uint32_t size_used; + + // Check whether the address range *doesn't* overlap + if ((b_start > a_end) || (b_end < a_start)) { + size_used = 0; // no overlap, size = 0 + } else { + size_used = min(b_end, a_end) - max(b_start, a_start) + 1; // Calculate minimum overlap + + printf("WARNING: Multiple write of %5d bytes at 0x%x -> 0x%x (%x -> %x, %x -> %x)\n", + size_used, max(b_start, a_start), min(b_end, a_end), + a_start, a_end, b_start, b_end); + } + return size_used; +} + + +void arealist_additem(area_item * p_area) { + + arealist_count++; + // Grow array if needed + if (arealist_count == arealist_size) { + arealist_size += AREA_GROW_SIZE; + arealist = (area_item *)realloc(arealist, arealist_size * sizeof(area_item)); + } + + arealist[arealist_count-1] = *p_area; +} + + +void areas_init(void) { + arealist_count = 0; + arealist_size = AREA_GROW_SIZE; + arealist = (area_item *)malloc(arealist_size * sizeof(area_item)); +} + + +void areas_cleanup(void) { + if (arealist) + free (arealist); +} + + +int areas_add(area_item * p_area) { + + uint32_t c; + uint32_t size_used; + int ret = true; // default to success + + // Check for overlap with existing areas + for (c = 0; c < arealist_count; c++) { + + size_used = addrs_check_overlap(arealist[c].start, arealist[c].end, + p_area->start, p_area->end); + // Signal failure on any overlap + // (Keep looping to display all warnings though) + if (size_used > 0) + ret = false; + } + + // Now add the area + arealist_additem(p_area); + + return ret; +} + diff --git a/gbdk-support/ihxcheck/areas.h b/gbdk-support/ihxcheck/areas.h @@ -0,0 +1,19 @@ +// This is free and unencumbered software released into the public domain. +// For more information, please refer to <https://unlicense.org> +// bbbbbr 2020 + +#ifndef _AREAS_H +#define _AREAS_H + +typedef struct area_item { + uint32_t start; + uint32_t end; + uint32_t length; +} area_item; + + +void areas_init(void); +void areas_cleanup(void); +int areas_add(area_item * p_area); + +#endif // _AREAS_H + diff --git a/gbdk-support/ihxcheck/ihx_file.c b/gbdk-support/ihxcheck/ihx_file.c @@ -0,0 +1,262 @@ +// This is free and unencumbered software released into the public domain. +// For more information, please refer to <https://unlicense.org> +// bbbbbr 2020 + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <stdbool.h> +#include <stdint.h> + +#include "areas.h" +#include "ihx_file.h" + +// Example data to parse from a .ihx file +// No area names +// : 01 0020 00 E9 F6 +// S BB AAAA RR DD CC +// +// S: Start (":") (1 char) +// BB: ByteCount (2 chars, one byte) +// AAAA: Address (4 chars, two bytes) +// RR: Record Type (2 chars, one byte. 00=data, 01=EOF, Others) +// DD: Data (<ByteCount> bytes) +// CC: Checksum (2 chars, one byte. Sum record bytes, 2's complement of LSByte) +/* +:01002000E9F6 +:05002800220D20FCC9BF +:070030001A22130D20FAC98A +. +. +. +:00000001FF (EOF indicator) +*/ + +/* TODO/WARNING/BUG: 100% full banks +It may not be possible to easily tell the difference between a perfectly filled +bank (100% and no more) and an adjacent partially filled bank that starts at +zero - versus - the first bank overflowed into the second that is empty. + +Currently the 100% bank will get merged into the next one and present as overflow +*/ + + +#define BANK_NUM(addr) ((addr & 0xFFFFC000U) >> 14) +#define ADDR_UNSET 0xFFFFFFFEU + +#define MAX_STR_LEN 4096 +#define IHX_DATA_LEN_MAX 255 +#define IHX_REC_LEN_MIN (1 + 2 + 4 + 2 + 0 + 2) // Start(1), ByteCount(2), Addr(4), Rec(2), Data(0..255x2), Checksum(2) + +// IHX record types +#define IHX_REC_DATA 0x00U +#define IHX_REC_EOF 0x01U +#define IHX_REC_EXTSEG 0x02U +#define IHX_REC_STARTSEG 0x03U +#define IHX_REC_EXTLIN 0x04U +#define IHX_REC_STARTLIN 0x05U + +typedef struct ihx_record { + uint16_t length; + uint32_t byte_count; + uint32_t address; + uint32_t address_end; + uint32_t type; + uint32_t checksum; // Would prefer this be a uint8_t, but mingw sscanf("%2hhx") has a buffer overflow that corrupts adjacent data +} ihx_record; + +uint32_t g_address_upper; +bool g_option_warnings_as_errors = false; + +void set_option_warnings_as_errors(bool new_val) { + g_option_warnings_as_errors = new_val; +} + + +// Return false if any character isn't a valid hex digit +int check_hex(char * c) { + while (*c != '\0') { + if ((*c >= '0') && (*c <= '9')) + c++; + if ((*c >= 'A') && (*c <= 'F')) + c++; + if ((*c >= 'a') && (*c <= 'f')) + c++; + else + return false; + } + + return true; +} + + +// Parse and validate an IHX record +int ihx_parse_and_validate_record(char * p_str, ihx_record * p_rec) { + + int calc_length = 0; + int c; + uint32_t ctemp, checksum_calc = 0; // Avoid mingw sscanf("%2hhx") buffer overflow with uint8_t + + // Remove trailing CR and LF + p_rec->length = strlen(p_str); + for (c = 0;c < p_rec->length;c++) { + if (p_str[c] == '\n' || p_str[c] == '\r') { + p_str[c] = '\0'; // Replace char with string terminator + p_rec->length = c; // Shrink length to truncated size + break; // Exit loop after finding first CR or LF + } + } + + // Only parse lines that start with ':' character (Start token for IHX record) + if (p_str[0] != ':') { + printf("Warning: IHX: Invalid start of line token for line: %s \n", p_str); + return false; + } + + // Require minimum length + if (p_rec->length < IHX_REC_LEN_MIN) { + printf("Warning: IHX: Invalid line, too few characters: %s. Is %d, needs at least %d \n", p_str, p_rec->length, IHX_REC_LEN_MIN); + return false; + } + + // Only hex characters are allowed after start token + p_str++; // Advance past Start code + if (check_hex(p_str)) { + printf("Warning: IHX: Invalid line, non-hex characters present: %s\n", p_str); + return false; + } + + // Read record header: byte count, start address, type + sscanf(p_str, "%2x%4x%2x", &p_rec->byte_count, &p_rec->address, &p_rec->type); + p_str += (2 + 4 + 2); + + // Apply extended linear address (upper 16 bits of address space) + // Calculate end address + p_rec->address |= g_address_upper; + p_rec->address_end = p_rec->address + p_rec->byte_count - 1; + + + // Require expected data byte count to fit within record length (at 2 chars per hex byte) + calc_length = IHX_REC_LEN_MIN + (p_rec->byte_count * 2); + if (p_rec->length != calc_length) { + printf("Warning: IHX: byte count doesn't match length available in record! Record length = %d, Calc length = %d, bytecount = %d \n", p_rec->length, calc_length, p_rec->byte_count); + return false; + } + + // Is this an extended linear address record? Read in offset address if so + if (p_rec->type == IHX_REC_EXTLIN) { + sscanf(p_str, "%4x", &g_address_upper); + g_address_upper <<= 16; // Shift into upper 16 bits of address space + } + + // Read data segment and calculate checsum of data + headers + checksum_calc = p_rec->byte_count + (p_rec->address & 0xFF) + ((p_rec->address >> 8) & 0xFF) + p_rec->type; + for (c = 0;c < p_rec->byte_count;c++) { + sscanf(p_str, "%2x", &ctemp); + p_str += 2; + checksum_calc += ctemp; + } + + // Final calculated checeksum is 2's complement of LSByte + checksum_calc = (((checksum_calc & 0xFF) ^ 0xFF) + 1) & 0xFF; + + // Read checksum from data + sscanf(p_str, "%2x", &p_rec->checksum); + p_str += 2; + + if (p_rec->checksum != checksum_calc) { + printf("Warning: IHX: record checksum %x didn't match calculated checksum %x\n", p_rec->checksum, checksum_calc); + return false; + } + + // For records that start in banks above the unbanked region (0x000 - 0x3FFF) + // Warn (but don't error) if they cross the boundary between different banks + if ((p_rec->address >= 0x00004000U) && + ((p_rec->address & 0xFFFFC000U) != (p_rec->address_end & 0xFFFFC000U))) { + printf("Warning: Write from one bank spans into the next. %x -> %x (bank %d -> %d)\n", + p_rec->address, p_rec->address_end, BANK_NUM(p_rec->address), BANK_NUM(p_rec->address_end)); + } + + return true; +} + + +int ihx_file_process_areas(char * filename_in) { + + int ret = EXIT_SUCCESS; // default to success + char cols; + char strline_in[MAX_STR_LEN] = ""; + FILE * ihx_file = fopen(filename_in, "r"); + area_item area; + ihx_record ihx_rec; + + areas_init(); + + // Initialize global upper address modifier + g_address_upper = 0x0000; + + // Initialize area record + area.start = ADDR_UNSET; + area.end = ADDR_UNSET; + + + if (ihx_file) { + + // Read one line at a time into \0 terminated string + while (fgets(strline_in, sizeof(strline_in), ihx_file) != NULL) { + + // Parse record, skip if fails validation + if (!ihx_parse_and_validate_record(strline_in, &ihx_rec)) + continue; + + // Process the pending record and exit if last record (EOF) + // Also ignore non-default data records (don't seem to occur for gbz80) + if (ihx_rec.type == IHX_REC_EOF) { + if (!areas_add(&area) && g_option_warnings_as_errors) + ret = EXIT_FAILURE; + continue; + } else if (ihx_rec.type == IHX_REC_EXTLIN) { + // printf("Extended linear address changed to %08x %s\n\n\n", g_address_upper, strline_in); + continue; + } else if (ihx_rec.type != IHX_REC_DATA) { + printf("Warning: IHX: dropped record %s of type %d\n", strline_in, ihx_rec.type); + continue; + } + + // Records are left pending (non-processed) until they don't merge + // with the current incoming record *or* the final (EOF) record is found. + + // Try to merge with (pending) previous record if it's address-adjacent, + // except when the new record starts or ends on a bank boundary + // (this reduces count from 1000's since most are only 32 bytes long) + if ((ihx_rec.address == area.end + 1) && ((ihx_rec.address & 0x00003FFFU) != 0x00000000U)) { + area.end = ihx_rec.address_end; // append to previous area + } else if ((ihx_rec.address_end == area.start + 1) && !((ihx_rec.address_end & 0x00003FFFU) != 0x00003FFFU)) { + area.start = ihx_rec.address; // pre-pend to previous area + } else { + // New record was *not* adjacent to last, + // so process the last/pending record + if (area.start != ADDR_UNSET) { + if (!areas_add(&area) && g_option_warnings_as_errors) + ret = EXIT_FAILURE; + } + // Now queue current record as pending for next loop + area.start = ihx_rec.address; + area.end = ihx_rec.address + ihx_rec.byte_count - 1; + } + + } // end: while still lines to process + + fclose(ihx_file); + + } // end: if valid file + else { + printf("Problem with filename or unable to open file! %s\n", filename_in); + ret = EXIT_FAILURE; + } + + areas_cleanup(); + return ret; +} + diff --git a/gbdk-support/ihxcheck/ihx_file.h b/gbdk-support/ihxcheck/ihx_file.h @@ -0,0 +1,12 @@ +// This is free and unencumbered software released into the public domain. +// For more information, please refer to <https://unlicense.org> +// bbbbbr 2020 + + +#ifndef _IHX_FILE_H +#define _IHX_FILE_H + +int ihx_file_process_areas(char * filename_in); +void set_option_warnings_as_errors(bool new_val); + +#endif // _IHX_FILE_H + diff --git a/gbdk-support/ihxcheck/ihxcheck.c b/gbdk-support/ihxcheck/ihxcheck.c @@ -0,0 +1,87 @@ +// This is free and unencumbered software released into the public domain. +// For more information, please refer to <https://unlicense.org> +// bbbbbr 2020 + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <stdbool.h> +#include <stdint.h> + +#include "ihx_file.h" +#include "areas.h" + +#define MAX_STR_LEN 4096 + +void display_help(void); +int handle_args(int argc, char * argv[]); + +char filename_in[MAX_STR_LEN] = {'\0'}; + + +void display_help(void) { + fprintf(stdout, + "ihx_check input_file.ihx [options]\n" + "\n" + "Options\n" + "-h : Show this help\n" + "-e : Treat warnings as errors\n" + "\n" + "Use: Read a .ihx and warn about overlapped areas.\n" + "Example: \"ihx_check build/MyProject.ihx\"\n" + ); +} + + +int handle_args(int argc, char * argv[]) { + + int i; + + if( argc < 2 ) { + display_help(); + return false; + } + + // Copy input filename (if not preceded with option dash) + if (argv[1][0] != '-') + snprintf(filename_in, sizeof(filename_in), "%s", argv[1]); + + // Start at first optional argument, argc is zero based + for (i = 1; i <= (argc -1); i++ ) { + + if (strstr(argv[i], "-h")) { + display_help(); + return false; // Don't parse input when -h is used + } else if (strstr(argv[i], "-e")) { + set_option_warnings_as_errors(true); + } + + } + + return true; +} + + +int matches_extension(char * filename, char * extension) { + return (strcmp(filename + (strlen(filename) - strlen(extension)), extension) == 0); +} + + +int main( int argc, char *argv[] ) { + + int ret = EXIT_FAILURE; // Exit with failure by default + + if (handle_args(argc, argv)) { + + // Must at least have extension + if (strlen(filename_in) >=5) { + // detect file extension + if (matches_extension(filename_in, (char *)".ihx")) { + ret = ihx_file_process_areas(filename_in); + } + } + } + + return ret; // Exit with failure by default +} + diff --git a/gbdk-support/lcc/gb.c b/gbdk-support/lcc/gb.c @@ -25,6 +25,7 @@ typedef struct { const char *com; const char *as; const char *ld; + const char *ihxcheck; const char *mkbin; } CLASS; @@ -53,6 +54,7 @@ static struct { { "libdir", "%prefix%lib/%libmodel%/asxxxx/" }, { "libmodel", "small" }, { "bindir", "%prefix%bin/" }, + { "ihxcheck", "%sdccdir%ihxcheck" }, { "mkbin", "%sdccdir%makebin" } }; @@ -96,6 +98,7 @@ static CLASS classes[] = { "%as% -pog $1 $3 $2", "%ld% -n -i $1 -k %libdir%%port%/ -l %port%.lib " "-k %libdir%%plat%/ -l %plat%.lib $3 %libdir%%plat%/crt0.o $2", + "%ihxcheck% $2 $1", "%mkbin% -Z $1 $2 $3" }, { "z80", @@ -107,6 +110,7 @@ static CLASS classes[] = { "%as% -pog $1 $3 $2", "%ld% -n -- -i $1 -b_CODE=0x8100 -k%libdir%%port%/ -l%port%.lib " "-k%libdir%%plat%/ -l%plat%.lib $3 %libdir%%plat%/crt0.o $2", + "%ihxcheck% $2 $1", "%mkbin% -Z $1 $2 $3" }, { "z80", @@ -118,6 +122,7 @@ static CLASS classes[] = { "%as% -pog $1 $3 $2", "%ld% -n -- -i $1 -b_DATA=0x8000 -b_CODE=0x200 -k%libdir%%port%/ -l%port%.lib " "-k%libdir%%plat%/ -l%plat%.lib $3 %libdir%%plat%/crt0.o $2", + "%ihxcheck% $2 $1", "%mkbin% -Z $1 $2 $3" } }; @@ -227,6 +232,7 @@ char *include[256]; char *com[256] = { "", "", "" }; char *as[256]; char *ld[256]; +char *ihxcheck[256]; char *mkbin[256]; const char *starts_with(const char *s1, const char *s2) @@ -299,6 +305,7 @@ void finalise(void) buildArgs(com, _class->com); buildArgs(as, _class->as); buildArgs(ld, _class->ld); + buildArgs(ihxcheck, _class->ihxcheck); buildArgs(mkbin, _class->mkbin); } diff --git a/gbdk-support/lcc/lcc.c b/gbdk-support/lcc/lcc.c @@ -57,7 +57,7 @@ extern char *tempname(char *); static void Fixllist(); -extern char *cpp[], *include[], *com[], *as[], *ld[], *mkbin[], inputs[], *suffixes[]; +extern char *cpp[], *include[], *com[], *as[], *ld[], *ihxcheck[], *mkbin[], inputs[], *suffixes[]; extern int option(char *); extern void set_gbdk_dir(char*); @@ -67,7 +67,9 @@ static int errcnt; /* number of errors */ static int Eflag; /* -E specified */ static int Sflag; /* -S specified */ static int cflag; /* -c specified */ +static int Kflag; /* -K specified */ static int verbose; /* incremented for each -v */ +static List ihxchecklist; /* ihxcheck flags */ static List mkbinlist; /* loader files, flags */ static List llist[2]; /* loader files, flags */ static List alist; /* assembler flags */ @@ -192,7 +194,7 @@ int main(int argc, char *argv[]) { ihxFile[lastP] = '\0'; strcat(ihxFile, ".ihx"); - // Only remove .ihx if it's not the final target + // Only remove .ihx from the delete-list if it's not the final target if (!target_is_ihx) append(ihxFile, rmlist); @@ -201,6 +203,13 @@ int main(int argc, char *argv[]) { if (callsys(av)) errcnt++; + // ihxcheck (test for multiple writes to the same ROM address) + if (!Kflag) { + compose(ihxcheck, ihxchecklist, append(ihxFile, 0), 0); + if (callsys(av)) + errcnt++; + } + // No need to makebin (.ihx -> .gb) if .ihx is final target if (!target_is_ihx) { @@ -209,7 +218,7 @@ int main(int argc, char *argv[]) { //makebin compose(mkbin, mkbinlist, append(ihxFile, 0), append(outfile, 0)); if (callsys(av)) - errcnt++; + errcnt++; } } } @@ -643,6 +652,7 @@ static void help(void) { "-g produce symbol table information for debuggers\n", "-help or -? print this message\n", "-Idir add `dir' to the beginning of the list of #include directories\n", +"-K don't run ihxcheck test on linker ihx output\n", "-lx search library `x'\n", "-N do not search the standard directories for #include files\n", "-n emit code to check for dereferencing zero pointers\n", @@ -661,7 +671,7 @@ static void help(void) { "-v show commands as they are executed; 2nd -v suppresses execution\n", "-w suppress warnings\n", "-Woarg specify system-specific `arg'\n", -"-W[pfalm]arg pass `arg' to the preprocessor, compiler, assembler, linker, or makebin\n", +"-W[pfalim]arg pass `arg' to the preprocessor, compiler, assembler, linker, ihxcheck, or makebin\n", 0 }; int i; char *s; @@ -740,6 +750,9 @@ static void opt(char *arg) { case 'a': /* Assembler */ alist = append(&arg[3], alist); return; + case 'i': /* ihxcheck arg list */ + ihxchecklist = append(&arg[3], ihxchecklist); + return; case 'l': /* Linker */ if(arg[4] == 'y' && (arg[5] == 't' || arg[5] == 'o' || arg[5] == 'a') && (arg[6] != '\0' && arg[6] != ' ')) goto makebinoption; //automatically pass -yo -ya -yt options to makebin (backwards compatibility) @@ -795,6 +808,9 @@ static void opt(char *arg) { case 'I': /* -Idir */ clist = append(arg, clist); return; + case 'K': + Kflag++; + return; case 'B': /* -Bdir -Bstatic -Bdynamic */ #ifdef sparc if (strcmp(arg, "-Bstatic") == 0 || strcmp(arg, "-Bdynamic") == 0)
This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.