commit 5ff05ee
shrub
·
2026-04-21 17:06:31 +0000 UTC
parent 32a97b4
handle # \ comment continuations that bearssl uses and evaluate include nodes when we need too
2 files changed,
+95,
-14
+39,
-0
1@@ -1,6 +1,7 @@
2 #include "shinobi.h"
3 #include "internal.h"
4
5+#include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8
9@@ -172,6 +173,41 @@ addrulesetrule(struct RuleSet *out, const struct RuleNode *src, struct EvalCtx *
10 addrecipes(&dst->recipes, &src->recipes);
11 }
12
13+static int
14+evalinclude(struct EvalCtx *ctx, const struct IncludeNode *inc)
15+{
16+ struct StrList paths;
17+ char *exp;
18+ size_t i;
19+
20+ exp = expandstr(ctx, inc->path);
21+ memset(&paths, 0, sizeof(paths));
22+ splitwords(&paths, exp, strlen(exp));
23+ free(exp);
24+ for (i = 0; i < paths.n; i++) {
25+ char *src;
26+
27+ src = readfile(paths.v[i]);
28+ if (!src) {
29+ if (!inc->optional) {
30+ fprintf(stderr, "eval: include not found: %s\n", paths.v[i]);
31+ ctx->errors++;
32+ freestrs(&paths);
33+ return -1;
34+ }
35+ continue;
36+ }
37+ if (evalsnippet(ctx, paths.v[i], src) < 0) {
38+ free(src);
39+ freestrs(&paths);
40+ return -1;
41+ }
42+ free(src);
43+ }
44+ freestrs(&paths);
45+ return 0;
46+}
47+
48 static int
49 evalnodes(const struct NodeList *in, struct RuleSet *out, struct EvalCtx *ctx)
50 {
51@@ -192,7 +228,10 @@ evalnodes(const struct NodeList *in, struct RuleSet *out, struct EvalCtx *ctx)
52 break;
53 }
54 case NODE_COMMENT:
55+ break;
56 case NODE_INCLUDE:
57+ if (evalinclude(ctx, &src->data.include) < 0)
58+ return -1;
59 break;
60 case NODE_COND:
61 if (testcond(ctx, &src->data.cond)) {
+56,
-14
1@@ -31,6 +31,8 @@ struct Inc {
2
3 static int parseerrs;
4
5+static int preprocfile(const char *path, const char *src_override, struct Pre *pre, struct Inc *inc);
6+
7 static void
8 parseerr(const struct PreLine *line, const char *msg, const char *detail)
9 {
10@@ -89,6 +91,16 @@ hascont(const char *s, size_t n)
11 return (count & 1) != 0;
12 }
13
14+static int
15+iscommentline(const char *s, size_t n)
16+{
17+ size_t i;
18+
19+ for (i = 0; i < n && isspace((unsigned char)s[i]); i++)
20+ ;
21+ return i < n && s[i] == '#';
22+}
23+
24 static int
25 skipref(const char *s, size_t n, size_t *i)
26 {
27@@ -247,6 +259,7 @@ readline(const char **src, int *lineno, struct PreLine *line)
28 size_t cap, len, chunk;
29 char *buf;
30 int line0, line1;
31+ int comment_cont;
32 int first;
33
34 p = *src;
35@@ -258,6 +271,7 @@ readline(const char **src, int *lineno, struct PreLine *line)
36 len = 0;
37 line0 = *lineno;
38 line1 = *lineno;
39+ comment_cont = 0;
40 first = 1;
41 line->isrecipe = 0;
42
43@@ -271,19 +285,30 @@ readline(const char **src, int *lineno, struct PreLine *line)
44
45 if (first && chunk > 0 && start[0] == '\t')
46 line->isrecipe = 1;
47-
48- if (len + chunk + 1 > cap) {
49- cap = (len + chunk + 1) * 2;
50- buf = xrealloc(buf, cap);
51+ /* a line that starts as a comment stays a comment across
52+ backslash line joins. this is a hack that bearssl uses
53+ to hide microsoft nmake directives, so nmake sees them
54+ and unix make doesn't, this is used to get nmake and make
55+ to include different files depending on what is used. */
56+ if (first && !line->isrecipe && iscommentline(start, chunk))
57+ comment_cont = 1;
58+
59+ if (!(comment_cont && !first)) {
60+ if (len + chunk + 1 > cap) {
61+ cap = (len + chunk + 1) * 2;
62+ buf = xrealloc(buf, cap);
63+ }
64+ memcpy(buf + len, start, chunk);
65+ len += chunk;
66+ buf[len] = 0;
67 }
68- memcpy(buf + len, start, chunk);
69- len += chunk;
70- buf[len] = 0;
71
72- if (!hascont(buf, len))
73+ if (!(comment_cont ? hascont(start, chunk) : hascont(buf, len)))
74 break;
75- len--;
76- buf[len++] = ' ';
77+ if (!comment_cont) {
78+ len--;
79+ buf[len++] = ' ';
80+ }
81 while (*p == ' ' || *p == '\t')
82 p++;
83 line1++;
84@@ -346,6 +371,26 @@ dirpart(const char *path)
85 return xstrndup(path, (size_t)(slash - path));
86 }
87
88+static int
89+preprocinclude(const char *dir, const char *incarg, struct Pre *pre, struct Inc *inc)
90+{
91+ int rc;
92+
93+ rc = preprocfile(incarg, 0, pre, inc);
94+ if (rc == 0)
95+ return 0;
96+ if (strcmp(dir, ".") == 0)
97+ return -1;
98+ {
99+ char *full;
100+
101+ full = joinpath(dir, incarg);
102+ rc = preprocfile(full, 0, pre, inc);
103+ free(full);
104+ return rc;
105+ }
106+}
107+
108 static int
109 preprocfile(const char *path, const char *src_override, struct Pre *pre, struct Inc *inc)
110 {
111@@ -379,7 +424,6 @@ preprocfile(const char *path, const char *src_override, struct Pre *pre, struct
112 stripcomment(line.text);
113 trim = trimdup(line.text, strlen(line.text));
114 if (haskw(trim, "include") || haskw(trim, "-include") || haskw(trim, "sinclude")) {
115- char *full;
116 int rc;
117 size_t kwlen;
118
119@@ -387,13 +431,11 @@ preprocfile(const char *path, const char *src_override, struct Pre *pre, struct
120 kwlen = haskw(trim, "-include") || haskw(trim, "sinclude") ? 8 : 7;
121 incarg = trimdup(trim + kwlen, strlen(trim + kwlen));
122 if (isplainpath(incarg)) {
123- full = joinpath(dir, incarg);
124 free(line.path);
125 free(line.text);
126 free(trim);
127+ rc = preprocinclude(dir, incarg, pre, inc);
128 free(incarg);
129- rc = preprocfile(full, 0, pre, inc);
130- free(full);
131 if (rc < 0 && !opt) {
132 free(dir);
133 free(src);