commit d283034

shrub  ·  2026-04-22 09:34:23 +0000 UTC
parent f57d326
handle recipeprefix and posix targets
13 files changed,  +189, -26
+1, -0
1@@ -10,6 +10,7 @@ SRCS =  cli/main.c \
2 	src/graph/graph.c \
3 	src/graph/subgraph.c \
4 	src/posix.c \
5+	src/targets.c \
6 	src/gnu/pattern.c \
7 	backends/ninja.c \
8 	backends/graphviz.c \
+7, -0
 1@@ -215,6 +215,7 @@ main(int argc, char **argv)
 2 	char *src;
 3 	int dump_ast;
 4 	int dump_graph;
 5+	int env_override;
 6 	int i;
 7 	char **assigns;
 8 	size_t nassigns;
 9@@ -227,6 +228,7 @@ main(int argc, char **argv)
10 	pathbuf = 0;
11 	dump_ast = 0;
12 	dump_graph = 0;
13+	env_override = 0;
14 	gen = GEN_NINJA;
15 	assigns = 0;
16 	nassigns = 0;
17@@ -280,6 +282,8 @@ main(int argc, char **argv)
18 			}
19 			++i;
20 			path = argv[i];
21+		} else if (strcmp(argv[i], "-e") == 0) {
22+			env_override = 1;
23 		} else if (isvarassign(argv[i])) {
24 			assigns = realloc(assigns, (nassigns + 1) * sizeof(assigns[0]));
25 			if (!assigns) {
26@@ -342,6 +346,7 @@ main(int argc, char **argv)
27 			freesubgraph(&sg);
28 			return 1;
29 		}
30+		rs.envoverride = env_override;
31 		dumpruleset(&rs);
32 		freeruleset(&rs);
33 		freeast(&ast);
34@@ -349,6 +354,8 @@ main(int argc, char **argv)
35 	}
36 	if (path)
37 		sg.makefile = xstrdup(path);
38+	if (env_override)
39+		addstr(&sg.flags, "-e");
40 	free(assigns);
41 	assigns = 0;
42 	if (buildsubgraph(&sg) < 0) {
+9, -1
 1@@ -212,6 +212,9 @@ static int
 2 evalnodes(const struct NodeList *in, struct RuleSet *out, struct EvalCtx *ctx)
 3 {
 4 	size_t i;
 5+	struct SpecialTargets targets;
 6+
 7+	initspecialtargets(&targets);
 8 
 9 	for (i = 0; i < in->n; i++) {
10 		const struct Node *src;
11@@ -243,6 +246,7 @@ evalnodes(const struct NodeList *in, struct RuleSet *out, struct EvalCtx *ctx)
12 			}
13 			continue;
14 		case NODE_ASSIGN:
15+			updatespecialassign(&targets, src->data.assign.lhs, src->data.assign.rhs);
16 			if (src->data.assign.tspec) {
17 				addrulesetassign(&out->tvars, &out->ntvars, src, ctx);
18 			} else {
19@@ -251,10 +255,14 @@ evalnodes(const struct NodeList *in, struct RuleSet *out, struct EvalCtx *ctx)
20 			}
21 			break;
22 		case NODE_RULE:
23+			if (handlespecialrule(&targets, &src->data.rule))
24+				break;
25 			addrulesetrule(out, &src->data.rule, ctx);
26 			break;
27 		}
28 	}
29+	if (out)
30+		out->posix = targets.posix;
31 	return 0;
32 }
33 
34@@ -281,7 +289,7 @@ eval(const struct Ast *ast, struct RuleSet *out)
35 	memset(out, 0, sizeof(*out));
36 	memset(&env, 0, sizeof(env));
37 	memset(&ctx, 0, sizeof(ctx));
38-	seedenv(&env);
39+	seedenv(&env, 0, out->envoverride);
40 	ctx.env = &env;
41 	ctx.out = out;
42 	rc = evalnodes((const struct NodeList *)ast, out, &ctx);
+6, -0
 1@@ -539,9 +539,15 @@ fnorigin(struct EvalCtx *ctx, const char *args)
 2 	case ORIGIN_DEFAULT:
 3 		origin = "default";
 4 		break;
 5+	case ORIGIN_ENV:
 6+		origin = "environment";
 7+		break;
 8 	case ORIGIN_FILE:
 9 		origin = "file";
10 		break;
11+	case ORIGIN_ENV_OVERRIDE:
12+		origin = "environment override";
13+		break;
14 	case ORIGIN_COMMAND:
15 		origin = "command line";
16 		break;
+2, -2
 1@@ -180,11 +180,11 @@ buildgraph(const struct RuleSet *ruleset, struct Graph *graph)
 2 	memset(&gs, 0, sizeof(gs));
 3 	memset(&ctx, 0, sizeof(ctx));
 4 	gs.graph = graph;
 5-	seedenv(&gs.env);
 6+	seedenv(&gs.env, ruleset->posix, ruleset->envoverride);
 7 	gs.rules = ruleset->rules;
 8 	gs.nrules = ruleset->nrules;
 9 	ctx.env = &gs.env;
10-	imprules(&gs.sufs);
11+	imprules(&gs.sufs, ruleset->posix);
12 
13 	for (i = 0; i < ruleset->nvars; i++)
14 		evalassign(&ctx, &ruleset->vars[i]);
+10, -0
 1@@ -487,6 +487,8 @@ buildsubgraph0(struct SubGraph *sg, struct SubGraphStack *stack)
 2 	int rc;
 3 	size_t marked;
 4 	size_t k;
 5+	size_t i;
 6+	int envoverride;
 7 
 8 	memset(&ast, 0, sizeof(ast));
 9 	memset(&rs, 0, sizeof(rs));
10@@ -519,6 +521,13 @@ buildsubgraph0(struct SubGraph *sg, struct SubGraphStack *stack)
11 	}
12 	pushstack(stack, key);
13 	free(key);
14+	envoverride = 0;
15+	for (i = 0; i < sg->flags.n; i++) {
16+		if (strcmp(sg->flags.v[i], "-e") == 0) {
17+			envoverride = 1;
18+			break;
19+		}
20+	}
21 	src = appendassigns(src, &sg->assigns);
22 	rc = parse(path, src, &ast);
23 	if (rc < 0) {
24@@ -539,6 +548,7 @@ buildsubgraph0(struct SubGraph *sg, struct SubGraphStack *stack)
25 		fprintf(stderr, "eval error in %s/%s\n", sg->cwd, path);
26 		goto out;
27 	}
28+	rs.envoverride = envoverride;
29 	rc = buildgraph(&rs, &sg->graph);
30 	if (rc < 0) {
31 		fprintf(stderr, "graph error in %s/%s\n", sg->cwd, path);
+9, -1
 1@@ -21,6 +21,11 @@ struct EvalCtx {
 2 	struct StrList *side_effects;
 3 };
 4 
 5+struct SpecialTargets {
 6+	int posix;
 7+	char recipeprefix;
 8+};
 9+
10 void *xmalloc(size_t n);
11 void *xrealloc(void *p, size_t n);
12 char *xstrndup(const char *s, size_t n);
13@@ -50,10 +55,13 @@ int parsesubmake(struct SubMake *dst, const char *cmd);
14 void envsetvar(struct Env *env, const char *name, char *val, int simple, enum Origin origin);
15 struct Target *findtarget(struct Graph *graph, const char *name);
16 const struct Target *findctarget(const struct Graph *graph, const char *name);
17+void initspecialtargets(struct SpecialTargets *targets);
18+void updatespecialassign(struct SpecialTargets *targets, const char *lhs, const char *rhs);
19+int handlespecialrule(struct SpecialTargets *targets, const struct RuleNode *rule);
20 
21 struct Var *findvar(struct Env *env, const char *name);
22 char *expandstr(struct EvalCtx *ctx, const char *s);
23-void seedenv(struct Env *env);
24+void seedenv(struct Env *env, int posix, int envoverride);
25 void freeenv(struct Env *env);
26 void copyenv(struct Env *dst, const struct Env *src);
27 void evalassign(struct EvalCtx *ctx, const struct AssignNode *in);
+52, -13
  1@@ -32,6 +32,8 @@ struct Inc {
  2 static int parseerrs;
  3 
  4 static int preprocfile(const char *path, const char *src_override, struct Pre *pre, struct Inc *inc);
  5+static int preprocfile0(const char *path, const char *src_override, struct Pre *pre, struct Inc *inc,
  6+                        struct SpecialTargets *targets);
  7 
  8 static void
  9 parseerr(const struct PreLine *line, const char *msg, const char *detail)
 10@@ -253,7 +255,7 @@ splitwords(struct StrList *out, const char *s, size_t n)
 11 }
 12 
 13 static int
 14-readline(const char **src, int *lineno, struct PreLine *line)
 15+readline(const char **src, int *lineno, struct PreLine *line, char recipeprefix)
 16 {
 17 	const char *p, *start;
 18 	size_t cap, len, chunk;
 19@@ -274,6 +276,7 @@ readline(const char **src, int *lineno, struct PreLine *line)
 20 	comment_cont = 0;
 21 	first = 1;
 22 	line->isrecipe = 0;
 23+	line->recipeprefix = 0;
 24 
 25 	for (;;) {
 26 		start = p;
 27@@ -283,8 +286,10 @@ readline(const char **src, int *lineno, struct PreLine *line)
 28 		if (*p == '\n')
 29 			p++;
 30 
 31-		if (first && chunk > 0 && start[0] == '\t')
 32+		if (first && chunk > 0 && start[0] == recipeprefix) {
 33 			line->isrecipe = 1;
 34+			line->recipeprefix = recipeprefix;
 35+		}
 36 		/* a line that starts as a comment stays a comment across
 37 		   backslash line joins. this is a hack that bearssl uses
 38 		   to hide microsoft nmake directives, so nmake sees them
 39@@ -372,11 +377,12 @@ dirpart(const char *path)
 40 }
 41 
 42 static int
 43-preprocinclude(const char *dir, const char *incarg, struct Pre *pre, struct Inc *inc)
 44+preprocinclude(const char *dir, const char *incarg, struct Pre *pre, struct Inc *inc,
 45+               struct SpecialTargets *targets)
 46 {
 47 	int rc;
 48 
 49-	rc = preprocfile(incarg, 0, pre, inc);
 50+	rc = preprocfile0(incarg, 0, pre, inc, targets);
 51 	if (rc == 0)
 52 		return 0;
 53 	if (strcmp(dir, ".") == 0)
 54@@ -385,14 +391,15 @@ preprocinclude(const char *dir, const char *incarg, struct Pre *pre, struct Inc
 55 		char *full;
 56 
 57 		full = joinpath(dir, incarg);
 58-		rc = preprocfile(full, 0, pre, inc);
 59+		rc = preprocfile0(full, 0, pre, inc, targets);
 60 		free(full);
 61 		return rc;
 62 	}
 63 }
 64 
 65 static int
 66-preprocfile(const char *path, const char *src_override, struct Pre *pre, struct Inc *inc)
 67+preprocfile0(const char *path, const char *src_override, struct Pre *pre, struct Inc *inc,
 68+             struct SpecialTargets *targets)
 69 {
 70 	char *src, *dir;
 71 	const char *p;
 72@@ -415,7 +422,7 @@ preprocfile(const char *path, const char *src_override, struct Pre *pre, struct
 73 	dir = dirpart(path);
 74 	p = src;
 75 	lineno = 1;
 76-	while (readline(&p, &lineno, &line)) {
 77+	while (readline(&p, &lineno, &line, targets->recipeprefix)) {
 78 		line.path = xstrdup(path);
 79 		if (!line.isrecipe) {
 80 			char *trim, *incarg;
 81@@ -434,7 +441,7 @@ preprocfile(const char *path, const char *src_override, struct Pre *pre, struct
 82 					free(line.path);
 83 					free(line.text);
 84 					free(trim);
 85-					rc = preprocinclude(dir, incarg, pre, inc);
 86+					rc = preprocinclude(dir, incarg, pre, inc, targets);
 87 					free(incarg);
 88 					if (rc < 0 && !opt) {
 89 						free(dir);
 90@@ -446,6 +453,24 @@ preprocfile(const char *path, const char *src_override, struct Pre *pre, struct
 91 				}
 92 				free(incarg);
 93 			}
 94+			{
 95+				size_t n;
 96+				ptrdiff_t colon;
 97+				struct AssignScan as;
 98+
 99+				n = strlen(trim);
100+				colon = findtop(trim, n, ':');
101+				as = findassign(trim, n, 0);
102+				if (as.ok && (colon < 0 || as.pos <= (size_t)colon)) {
103+					char *lhs, *rhs;
104+
105+					lhs = trimdup(trim, as.pos);
106+					rhs = trimdup(trim + as.pos + as.len, n - as.pos - as.len);
107+					updatespecialassign(targets, lhs, rhs);
108+					free(lhs);
109+					free(rhs);
110+				}
111+			}
112 			free(trim);
113 		}
114 		pre->v = xrealloc(pre->v, (pre->n + 1) * sizeof(pre->v[0]));
115@@ -457,6 +482,15 @@ preprocfile(const char *path, const char *src_override, struct Pre *pre, struct
116 	return 0;
117 }
118 
119+static int
120+preprocfile(const char *path, const char *src_override, struct Pre *pre, struct Inc *inc)
121+{
122+	struct SpecialTargets targets;
123+
124+	initspecialtargets(&targets);
125+	return preprocfile0(path, src_override, pre, inc, &targets);
126+}
127+
128 int
129 preproc(const char *path, struct Pre *pre)
130 {
131@@ -887,7 +921,8 @@ parseline(const struct PreLine *line)
132 }
133 
134 static int
135-parseblock(const struct Pre *pre, size_t *i, struct NodeList *out, struct Node **last_rulep)
136+parseblock(const struct Pre *pre, size_t *i, struct NodeList *out, struct Node **last_rulep,
137+           struct SpecialTargets *targets)
138 {
139 	struct Node state;
140 	struct Node *last_rule;
141@@ -941,7 +976,7 @@ parseblock(const struct Pre *pre, size_t *i, struct NodeList *out, struct Node *
142 			state = parsecond(line, trim);
143 			free(trim);
144 			(*i)++;
145-			if (parseblock(pre, i, &state.data.cond.thenpart, &last_rule) < 0)
146+			if (parseblock(pre, i, &state.data.cond.thenpart, &last_rule, targets) < 0)
147 				return -1;
148 			if (*i < pre->n) {
149 				struct PreLine *endline;
150@@ -961,7 +996,7 @@ parseblock(const struct Pre *pre, size_t *i, struct NodeList *out, struct Node *
151 						free(endline->text);
152 						endline->text = rep;
153 						free(endtrim);
154-						if (parseblock(pre, i, &state.data.cond.elsepart, &last_rule) < 0)
155+						if (parseblock(pre, i, &state.data.cond.elsepart, &last_rule, targets) < 0)
156 							return -1;
157 						state.loc.line1 = endline->line1;
158 						addnode(out, state);
159@@ -971,7 +1006,7 @@ parseblock(const struct Pre *pre, size_t *i, struct NodeList *out, struct Node *
160 					}
161 					free(endtrim);
162 					(*i)++;
163-					if (parseblock(pre, i, &state.data.cond.elsepart, &last_rule) < 0)
164+					if (parseblock(pre, i, &state.data.cond.elsepart, &last_rule, targets) < 0)
165 						return -1;
166 					if (*i >= pre->n)
167 						return -1;
168@@ -996,6 +1031,8 @@ parseblock(const struct Pre *pre, size_t *i, struct NodeList *out, struct Node *
169 		free(trim);
170 
171 		state = parseline(line);
172+		if (state.kind == NODE_ASSIGN)
173+			updatespecialassign(targets, state.data.assign.lhs, state.data.assign.rhs);
174 		addnode(out, state);
175 		if (state.kind == NODE_RULE)
176 			last_rule = &out->v[out->n - 1];
177@@ -1012,12 +1049,14 @@ int
178 buildast(const char *path, const struct Pre *pre, struct Ast *ast)
179 {
180 	size_t i;
181+	struct SpecialTargets targets;
182 
183 	(void)path;
184 	memset(ast, 0, sizeof(*ast));
185 	parseerrs = 0;
186+	initspecialtargets(&targets);
187 	i = 0;
188-	if (parseblock(pre, &i, (struct NodeList *)ast, 0) < 0)
189+	if (parseblock(pre, &i, (struct NodeList *)ast, 0, &targets) < 0)
190 		return -1;
191 	if (parseerrs)
192 		return -1;
+36, -6
 1@@ -4,6 +4,8 @@
 2 #include <stdlib.h>
 3 #include <string.h>
 4 
 5+extern char **environ;
 6+
 7 static int
 8 sufeq(const char *a, const char *b)
 9 {
10@@ -215,8 +217,10 @@ expandauto(const char *s, const struct Target *t, const char *stem)
11 }
12 
13 void
14-seedenv(struct Env *env)
15+seedenv(struct Env *env, int posix, int envoverride)
16 {
17+	size_t i;
18+
19 	envsetvar(env, "CC", xstrdup("cc"), 1, ORIGIN_DEFAULT);
20 	envsetvar(env, "CFLAGS", xstrdup(""), 1, ORIGIN_DEFAULT);
21 	envsetvar(env, "CXX", xstrdup("c++"), 1, ORIGIN_DEFAULT);
22@@ -238,10 +242,28 @@ seedenv(struct Env *env)
23 	envsetvar(env, "YACC", xstrdup("yacc"), 1, ORIGIN_DEFAULT);
24 	envsetvar(env, "YFLAGS", xstrdup(""), 1, ORIGIN_DEFAULT);
25 	envsetvar(env, "SHELL", xstrdup("/bin/sh"), 1, ORIGIN_DEFAULT);
26+	envsetvar(env, "MAKE", xstrdup("make"), 1, ORIGIN_DEFAULT);
27+	if (posix) {
28+		envsetvar(env, "CC", xstrdup("c99"), 1, ORIGIN_DEFAULT);
29+		envsetvar(env, "CFLAGS", xstrdup("-O1"), 1, ORIGIN_DEFAULT);
30+		envsetvar(env, "FFLAGS", xstrdup("-O1"), 1, ORIGIN_DEFAULT);
31+	}
32+	for (i = 0; environ && environ[i]; i++) {
33+		const char *eq;
34+		char *name;
35+
36+		eq = strchr(environ[i], '=');
37+		if (!eq || eq == environ[i])
38+			continue;
39+		name = xstrndup(environ[i], (size_t)(eq - environ[i]));
40+		envsetvar(env, name, xstrdup(eq + 1), 1,
41+		          envoverride ? ORIGIN_ENV_OVERRIDE : ORIGIN_ENV);
42+		free(name);
43+	}
44 }
45 
46 void
47-imprules(struct SufRules *rules)
48+imprules(struct SufRules *rules, int posix)
49 {
50 	static const char *const c_bin[] = {
51 	    "$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<",
52@@ -253,14 +275,18 @@ imprules(struct SufRules *rules)
53 	    "cp $< $@",
54 	    "chmod a+x $@",
55 	};
56-	/* TODO -o here is NOT POSIX. im keeping it here for now for gnu compatibility,
57-	 * because it's conveinient. when .POSIX is passed, we should drop the -o. */
58 	static const char *const c_o[] = {
59 	    "$(CC) $(CFLAGS) -c -o $@ $<",
60 	};
61+	static const char *const c_o_posix[] = {
62+	    "$(CC) $(CFLAGS) -c $<",
63+	};
64 	static const char *const f_o[] = {
65 	    "$(FC) $(FFLAGS) -c -o $@ $<",
66 	};
67+	static const char *const f_o_posix[] = {
68+	    "$(FC) $(FFLAGS) -c $<",
69+	};
70 	static const char *const y_o[] = {
71 	    "$(YACC) $(YFLAGS) $<",
72 	    "$(CC) $(CFLAGS) -c y.tab.c",
73@@ -299,8 +325,12 @@ imprules(struct SufRules *rules)
74 	addimpsingle(rules, ".c", c_bin, sizeof(c_bin) / sizeof(c_bin[0]));
75 	addimpsingle(rules, ".f", f_bin, sizeof(f_bin) / sizeof(f_bin[0]));
76 	addimpsingle(rules, ".sh", sh_bin, sizeof(sh_bin) / sizeof(sh_bin[0]));
77-	addimpdouble(rules, ".c", ".o", c_o, sizeof(c_o) / sizeof(c_o[0]));
78-	addimpdouble(rules, ".f", ".o", f_o, sizeof(f_o) / sizeof(f_o[0]));
79+	addimpdouble(rules, ".c", ".o",
80+	             posix ? c_o_posix : c_o,
81+	             posix ? sizeof(c_o_posix) / sizeof(c_o_posix[0]) : sizeof(c_o) / sizeof(c_o[0]));
82+	addimpdouble(rules, ".f", ".o",
83+	             posix ? f_o_posix : f_o,
84+	             posix ? sizeof(f_o_posix) / sizeof(f_o_posix[0]) : sizeof(f_o) / sizeof(f_o[0]));
85 	addimpdouble(rules, ".y", ".o", y_o, sizeof(y_o) / sizeof(y_o[0]));
86 	addimpdouble(rules, ".l", ".o", l_o, sizeof(l_o) / sizeof(l_o[0]));
87 	addimpdouble(rules, ".y", ".c", y_c, sizeof(y_c) / sizeof(y_c[0]));
+2, -2
 1@@ -35,8 +35,8 @@ struct SufRules {
 2 
 3 int issinglesuf(const char *s, char **from);
 4 int issuf(const char *s, char **from, char **to);
 5-void seedenv(struct Env *env);
 6-void imprules(struct SufRules *rules);
 7+void seedenv(struct Env *env, int posix, int envoverride);
 8+void imprules(struct SufRules *rules, int posix);
 9 int collectsufrule(struct SufRules *rules, const struct RuleNode *rule);
10 int instsufrule(const struct SufRules *rules,
11                 const struct Graph *graph,
+5, -0
 1@@ -31,7 +31,9 @@ enum AssignOp {
 2 
 3 enum Origin {
 4 	ORIGIN_DEFAULT,
 5+	ORIGIN_ENV,
 6 	ORIGIN_FILE,
 7+	ORIGIN_ENV_OVERRIDE,
 8 	ORIGIN_COMMAND,
 9 	ORIGIN_OVERRIDE,
10 };
11@@ -56,6 +58,7 @@ struct PreLine {
12 	int line0;
13 	int line1;
14 	int isrecipe;
15+	char recipeprefix;
16 };
17 
18 struct Pre {
19@@ -157,6 +160,8 @@ struct RuleSet {
20 	size_t ntvars;
21 	struct RuleNode *rules;
22 	size_t nrules;
23+	int posix;
24+	int envoverride;
25 };
26 
27 struct Var {
+34, -0
 1@@ -0,0 +1,34 @@
 2+#include "internal.h"
 3+
 4+#include <ctype.h>
 5+#include <string.h>
 6+
 7+void
 8+initspecialtargets(struct SpecialTargets *targets)
 9+{
10+	targets->posix = 0;
11+	targets->recipeprefix = '\t';
12+}
13+
14+void
15+updatespecialassign(struct SpecialTargets *targets, const char *lhs, const char *rhs)
16+{
17+	size_t i;
18+
19+	if (strcmp(lhs, ".RECIPEPREFIX") != 0)
20+		return;
21+	for (i = 0; rhs[i] && isspace((unsigned char)rhs[i]); i++)
22+		;
23+	if (rhs[i])
24+		targets->recipeprefix = rhs[i];
25+}
26+
27+int
28+handlespecialrule(struct SpecialTargets *targets, const struct RuleNode *rule)
29+{
30+	if (rule->targets.n == 1 && strcmp(rule->targets.v[0], ".POSIX") == 0) {
31+		targets->posix = 1;
32+		return 1;
33+	}
34+	return 0;
35+}
+16, -1
 1@@ -14,6 +14,7 @@ dryrun=0
 2 jobs=
 3 targets=
 4 vars=
 5+pass_flags=
 6 
 7 lie() {
 8 	printf '%s\n' 'GNU Make 4.4'
 9@@ -127,7 +128,12 @@ while [ "$#" -gt 0 ]; do
10 		dryrun=1
11 		shift
12 		;;
13-	--no-print-directory|--warn-undefined-variables|-r|-R|-k|-B|-e|-i|-q|-t)
14+	-e)
15+		pass_flags=${pass_flags}${pass_flags:+'
16+'}$1
17+		shift
18+		;;
19+	--no-print-directory|--warn-undefined-variables|-r|-R|-k|-B|-i|-q|-t)
20 		shift
21 		;;
22 	--)
23@@ -183,6 +189,15 @@ if [ "$makefile_set" -eq 1 ]; then
24 else
25 	set -- "$shin_bin"
26 fi
27+if [ -n "$pass_flags" ]; then
28+	oldifs=$IFS
29+	IFS='
30+'
31+	for flag in $pass_flags; do
32+		set -- "$@" "$flag"
33+	done
34+	IFS=$oldifs
35+fi
36 if [ -n "$vars" ]; then
37 	oldifs=$IFS
38 	IFS='