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);