diff --git a/Makefile b/Makefile index aaa6d8fc..73f2bc0d 100644 --- a/Makefile +++ b/Makefile @@ -106,9 +106,16 @@ $(OUT)/%.o: %.c $(Q)$(CC) -o $@ $(CFLAGS) -c -MMD -MF $@.d $< SHELL_HACK := $(shell mkdir -p $(OUT) $(OUT)/$(SRCDIR) $(OUT)/tests) -$(OUT)/libc.inc: $(OUT)/inliner $(LIBDIR)/c.c + +$(OUT)/norm-lf: tools/norm-lf.c + $(VECHO) " CC+LD\t$@\n" + $(Q)$(CC) $(CFLAGS) -o $@ $^ + +$(OUT)/libc.inc: $(OUT)/inliner $(OUT)/norm-lf $(LIBDIR)/c.c $(VECHO) " GEN\t$@\n" - $(Q)$(OUT)/inliner $(LIBDIR)/c.c $@ + $(Q)$(OUT)/norm-lf $(LIBDIR)/c.c $(OUT)/c.normalized.c + $(Q)$(OUT)/inliner $(OUT)/c.normalized.c $@ + $(Q)$(RM) $(OUT)/c.normalized.c $(OUT)/inliner: tools/inliner.c $(VECHO) " CC+LD\t$@\n" @@ -146,7 +153,7 @@ clean: -$(RM) $(OUT)/libc.inc distclean: clean - -$(RM) $(OUT)/inliner $(OUT)/target $(SRCDIR)/codegen.c config $(BUILD_SESSION) + -$(RM) $(OUT)/inliner $(OUT)/norm-lf $(OUT)/target $(SRCDIR)/codegen.c config $(BUILD_SESSION) -$(RM) DOM.dot CFG.dot -include $(deps) diff --git a/tools/inliner.c b/tools/inliner.c index 03a4483b..7c632026 100644 --- a/tools/inliner.c +++ b/tools/inliner.c @@ -10,6 +10,9 @@ * The inliner is used at build-time, and developers can use the * "inline C" feature to implement target-specific parts such as * C runtime and essential libraries. + * + * Note: Input files are preprocessed by norm-lf tool to ensure + * consistent LF (Unix) line endings before processing. */ #include @@ -110,7 +113,10 @@ void write_line(char *src) { write_str(" __c(\""); for (int i = 0; src[i]; i++) { - if (src[i] == '\"') { + if (src[i] == '\\') { + write_char('\\'); + write_char('\\'); + } else if (src[i] == '\"') { write_char('\\'); write_char('\"'); } else if (src[i] != '\n') { diff --git a/tools/norm-lf.c b/tools/norm-lf.c new file mode 100644 index 00000000..74589ced --- /dev/null +++ b/tools/norm-lf.c @@ -0,0 +1,85 @@ +/* + * Convert all line endings to LF (Unix style) + * + * This tool ensures consistent line endings before processing with inliner. + * It converts CR-only (old Mac) and CRLF (Windows) to LF (Unix). + */ + +#include +#include +#include + +int main(int argc, char *argv[]) +{ + if (argc != 3) { + fprintf(stderr, "Usage: %s \n", argv[0]); + return 1; + } + + FILE *input = fopen(argv[1], "rb"); + if (!input) { + fprintf(stderr, "Error: Cannot open input file '%s'\n", argv[1]); + return 1; + } + + FILE *output = fopen(argv[2], "wb"); + if (!output) { + fprintf(stderr, "Error: Cannot create output file '%s'\n", argv[2]); + fclose(input); + return 1; + } + + int c; + int prev_cr = 0; + bool has_crlf = false; + bool has_lf = false; + bool has_cr_only = false; + + while ((c = fgetc(input)) != EOF) { + if (c == '\r') { + /* Mark that we saw a CR, but don't output it yet */ + prev_cr = 1; + } else if (c == '\n') { + if (prev_cr) { + /* CRLF sequence - output single LF */ + has_crlf = true; + } else { + /* LF only */ + has_lf = true; + } + fputc('\n', output); + prev_cr = 0; + } else { + if (prev_cr) { + /* CR not followed by LF - convert to LF */ + fputc('\n', output); + has_cr_only = true; + } + fputc(c, output); + prev_cr = 0; + } + } + + /* Handle CR at end of file */ + if (prev_cr) { + fputc('\n', output); + has_cr_only = true; + } + + fclose(input); + fclose(output); + + /* Report what was found and converted */ + if (has_cr_only) { + fprintf(stderr, + "Warning: Converted CR-only line endings to LF in '%s'\n", + argv[1]); + } + if ((has_crlf && has_lf) || (has_crlf && has_cr_only) || + (has_lf && has_cr_only)) { + fprintf(stderr, "Warning: Converted mixed line endings to LF in '%s'\n", + argv[1]); + } + + return 0; +}