Skip to content

Commit f2d99dd

Browse files
authored
Merge pull request #233 from sysprog21/linebreak-compat
Fix inliner string escaping
2 parents ea1b6ab + 6f63efa commit f2d99dd

File tree

3 files changed

+102
-4
lines changed

3 files changed

+102
-4
lines changed

Makefile

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,9 +106,16 @@ $(OUT)/%.o: %.c
106106
$(Q)$(CC) -o $@ $(CFLAGS) -c -MMD -MF $@.d $<
107107

108108
SHELL_HACK := $(shell mkdir -p $(OUT) $(OUT)/$(SRCDIR) $(OUT)/tests)
109-
$(OUT)/libc.inc: $(OUT)/inliner $(LIBDIR)/c.c
109+
110+
$(OUT)/norm-lf: tools/norm-lf.c
111+
$(VECHO) " CC+LD\t$@\n"
112+
$(Q)$(CC) $(CFLAGS) -o $@ $^
113+
114+
$(OUT)/libc.inc: $(OUT)/inliner $(OUT)/norm-lf $(LIBDIR)/c.c
110115
$(VECHO) " GEN\t$@\n"
111-
$(Q)$(OUT)/inliner $(LIBDIR)/c.c $@
116+
$(Q)$(OUT)/norm-lf $(LIBDIR)/c.c $(OUT)/c.normalized.c
117+
$(Q)$(OUT)/inliner $(OUT)/c.normalized.c $@
118+
$(Q)$(RM) $(OUT)/c.normalized.c
112119

113120
$(OUT)/inliner: tools/inliner.c
114121
$(VECHO) " CC+LD\t$@\n"
@@ -146,7 +153,7 @@ clean:
146153
-$(RM) $(OUT)/libc.inc
147154

148155
distclean: clean
149-
-$(RM) $(OUT)/inliner $(OUT)/target $(SRCDIR)/codegen.c config $(BUILD_SESSION)
156+
-$(RM) $(OUT)/inliner $(OUT)/norm-lf $(OUT)/target $(SRCDIR)/codegen.c config $(BUILD_SESSION)
150157
-$(RM) DOM.dot CFG.dot
151158

152159
-include $(deps)

tools/inliner.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
* The inliner is used at build-time, and developers can use the
1111
* "inline C" feature to implement target-specific parts such as
1212
* C runtime and essential libraries.
13+
*
14+
* Note: Input files are preprocessed by norm-lf tool to ensure
15+
* consistent LF (Unix) line endings before processing.
1316
*/
1417

1518
#include <stdbool.h>
@@ -110,7 +113,10 @@ void write_line(char *src)
110113
{
111114
write_str(" __c(\"");
112115
for (int i = 0; src[i]; i++) {
113-
if (src[i] == '\"') {
116+
if (src[i] == '\\') {
117+
write_char('\\');
118+
write_char('\\');
119+
} else if (src[i] == '\"') {
114120
write_char('\\');
115121
write_char('\"');
116122
} else if (src[i] != '\n') {

tools/norm-lf.c

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/*
2+
* Convert all line endings to LF (Unix style)
3+
*
4+
* This tool ensures consistent line endings before processing with inliner.
5+
* It converts CR-only (old Mac) and CRLF (Windows) to LF (Unix).
6+
*/
7+
8+
#include <stdbool.h>
9+
#include <stdio.h>
10+
#include <stdlib.h>
11+
12+
int main(int argc, char *argv[])
13+
{
14+
if (argc != 3) {
15+
fprintf(stderr, "Usage: %s <input> <output>\n", argv[0]);
16+
return 1;
17+
}
18+
19+
FILE *input = fopen(argv[1], "rb");
20+
if (!input) {
21+
fprintf(stderr, "Error: Cannot open input file '%s'\n", argv[1]);
22+
return 1;
23+
}
24+
25+
FILE *output = fopen(argv[2], "wb");
26+
if (!output) {
27+
fprintf(stderr, "Error: Cannot create output file '%s'\n", argv[2]);
28+
fclose(input);
29+
return 1;
30+
}
31+
32+
int c;
33+
int prev_cr = 0;
34+
bool has_crlf = false;
35+
bool has_lf = false;
36+
bool has_cr_only = false;
37+
38+
while ((c = fgetc(input)) != EOF) {
39+
if (c == '\r') {
40+
/* Mark that we saw a CR, but don't output it yet */
41+
prev_cr = 1;
42+
} else if (c == '\n') {
43+
if (prev_cr) {
44+
/* CRLF sequence - output single LF */
45+
has_crlf = true;
46+
} else {
47+
/* LF only */
48+
has_lf = true;
49+
}
50+
fputc('\n', output);
51+
prev_cr = 0;
52+
} else {
53+
if (prev_cr) {
54+
/* CR not followed by LF - convert to LF */
55+
fputc('\n', output);
56+
has_cr_only = true;
57+
}
58+
fputc(c, output);
59+
prev_cr = 0;
60+
}
61+
}
62+
63+
/* Handle CR at end of file */
64+
if (prev_cr) {
65+
fputc('\n', output);
66+
has_cr_only = true;
67+
}
68+
69+
fclose(input);
70+
fclose(output);
71+
72+
/* Report what was found and converted */
73+
if (has_cr_only) {
74+
fprintf(stderr,
75+
"Warning: Converted CR-only line endings to LF in '%s'\n",
76+
argv[1]);
77+
}
78+
if ((has_crlf && has_lf) || (has_crlf && has_cr_only) ||
79+
(has_lf && has_cr_only)) {
80+
fprintf(stderr, "Warning: Converted mixed line endings to LF in '%s'\n",
81+
argv[1]);
82+
}
83+
84+
return 0;
85+
}

0 commit comments

Comments
 (0)