xref: /OK3568_Linux_fs/kernel/scripts/kconfig/preprocess.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun //
3*4882a593Smuzhiyun // Copyright (C) 2018 Masahiro Yamada <yamada.masahiro@socionext.com>
4*4882a593Smuzhiyun 
5*4882a593Smuzhiyun #include <ctype.h>
6*4882a593Smuzhiyun #include <stdarg.h>
7*4882a593Smuzhiyun #include <stdbool.h>
8*4882a593Smuzhiyun #include <stdio.h>
9*4882a593Smuzhiyun #include <stdlib.h>
10*4882a593Smuzhiyun #include <string.h>
11*4882a593Smuzhiyun 
12*4882a593Smuzhiyun #include "list.h"
13*4882a593Smuzhiyun #include "lkc.h"
14*4882a593Smuzhiyun 
15*4882a593Smuzhiyun #define ARRAY_SIZE(arr)		(sizeof(arr) / sizeof((arr)[0]))
16*4882a593Smuzhiyun 
17*4882a593Smuzhiyun static char *expand_string_with_args(const char *in, int argc, char *argv[]);
18*4882a593Smuzhiyun static char *expand_string(const char *in);
19*4882a593Smuzhiyun 
pperror(const char * format,...)20*4882a593Smuzhiyun static void __attribute__((noreturn)) pperror(const char *format, ...)
21*4882a593Smuzhiyun {
22*4882a593Smuzhiyun 	va_list ap;
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun 	fprintf(stderr, "%s:%d: ", current_file->name, yylineno);
25*4882a593Smuzhiyun 	va_start(ap, format);
26*4882a593Smuzhiyun 	vfprintf(stderr, format, ap);
27*4882a593Smuzhiyun 	va_end(ap);
28*4882a593Smuzhiyun 	fprintf(stderr, "\n");
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun 	exit(1);
31*4882a593Smuzhiyun }
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun /*
34*4882a593Smuzhiyun  * Environment variables
35*4882a593Smuzhiyun  */
36*4882a593Smuzhiyun static LIST_HEAD(env_list);
37*4882a593Smuzhiyun 
38*4882a593Smuzhiyun struct env {
39*4882a593Smuzhiyun 	char *name;
40*4882a593Smuzhiyun 	char *value;
41*4882a593Smuzhiyun 	struct list_head node;
42*4882a593Smuzhiyun };
43*4882a593Smuzhiyun 
env_add(const char * name,const char * value)44*4882a593Smuzhiyun static void env_add(const char *name, const char *value)
45*4882a593Smuzhiyun {
46*4882a593Smuzhiyun 	struct env *e;
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun 	e = xmalloc(sizeof(*e));
49*4882a593Smuzhiyun 	e->name = xstrdup(name);
50*4882a593Smuzhiyun 	e->value = xstrdup(value);
51*4882a593Smuzhiyun 
52*4882a593Smuzhiyun 	list_add_tail(&e->node, &env_list);
53*4882a593Smuzhiyun }
54*4882a593Smuzhiyun 
env_del(struct env * e)55*4882a593Smuzhiyun static void env_del(struct env *e)
56*4882a593Smuzhiyun {
57*4882a593Smuzhiyun 	list_del(&e->node);
58*4882a593Smuzhiyun 	free(e->name);
59*4882a593Smuzhiyun 	free(e->value);
60*4882a593Smuzhiyun 	free(e);
61*4882a593Smuzhiyun }
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun /* The returned pointer must be freed when done */
env_expand(const char * name)64*4882a593Smuzhiyun static char *env_expand(const char *name)
65*4882a593Smuzhiyun {
66*4882a593Smuzhiyun 	struct env *e;
67*4882a593Smuzhiyun 	const char *value;
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun 	if (!*name)
70*4882a593Smuzhiyun 		return NULL;
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun 	list_for_each_entry(e, &env_list, node) {
73*4882a593Smuzhiyun 		if (!strcmp(name, e->name))
74*4882a593Smuzhiyun 			return xstrdup(e->value);
75*4882a593Smuzhiyun 	}
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun 	value = getenv(name);
78*4882a593Smuzhiyun 	if (!value)
79*4882a593Smuzhiyun 		return NULL;
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun 	/*
82*4882a593Smuzhiyun 	 * We need to remember all referenced environment variables.
83*4882a593Smuzhiyun 	 * They will be written out to include/config/auto.conf.cmd
84*4882a593Smuzhiyun 	 */
85*4882a593Smuzhiyun 	env_add(name, value);
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun 	return xstrdup(value);
88*4882a593Smuzhiyun }
89*4882a593Smuzhiyun 
env_write_dep(FILE * f,const char * autoconfig_name)90*4882a593Smuzhiyun void env_write_dep(FILE *f, const char *autoconfig_name)
91*4882a593Smuzhiyun {
92*4882a593Smuzhiyun 	struct env *e, *tmp;
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun 	list_for_each_entry_safe(e, tmp, &env_list, node) {
95*4882a593Smuzhiyun 		fprintf(f, "ifneq \"$(%s)\" \"%s\"\n", e->name, e->value);
96*4882a593Smuzhiyun 		fprintf(f, "%s: FORCE\n", autoconfig_name);
97*4882a593Smuzhiyun 		fprintf(f, "endif\n");
98*4882a593Smuzhiyun 		env_del(e);
99*4882a593Smuzhiyun 	}
100*4882a593Smuzhiyun }
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun /*
103*4882a593Smuzhiyun  * Built-in functions
104*4882a593Smuzhiyun  */
105*4882a593Smuzhiyun struct function {
106*4882a593Smuzhiyun 	const char *name;
107*4882a593Smuzhiyun 	unsigned int min_args;
108*4882a593Smuzhiyun 	unsigned int max_args;
109*4882a593Smuzhiyun 	char *(*func)(int argc, char *argv[]);
110*4882a593Smuzhiyun };
111*4882a593Smuzhiyun 
do_error_if(int argc,char * argv[])112*4882a593Smuzhiyun static char *do_error_if(int argc, char *argv[])
113*4882a593Smuzhiyun {
114*4882a593Smuzhiyun 	if (!strcmp(argv[0], "y"))
115*4882a593Smuzhiyun 		pperror("%s", argv[1]);
116*4882a593Smuzhiyun 
117*4882a593Smuzhiyun 	return xstrdup("");
118*4882a593Smuzhiyun }
119*4882a593Smuzhiyun 
do_filename(int argc,char * argv[])120*4882a593Smuzhiyun static char *do_filename(int argc, char *argv[])
121*4882a593Smuzhiyun {
122*4882a593Smuzhiyun 	return xstrdup(current_file->name);
123*4882a593Smuzhiyun }
124*4882a593Smuzhiyun 
do_info(int argc,char * argv[])125*4882a593Smuzhiyun static char *do_info(int argc, char *argv[])
126*4882a593Smuzhiyun {
127*4882a593Smuzhiyun 	printf("%s\n", argv[0]);
128*4882a593Smuzhiyun 
129*4882a593Smuzhiyun 	return xstrdup("");
130*4882a593Smuzhiyun }
131*4882a593Smuzhiyun 
do_lineno(int argc,char * argv[])132*4882a593Smuzhiyun static char *do_lineno(int argc, char *argv[])
133*4882a593Smuzhiyun {
134*4882a593Smuzhiyun 	char buf[16];
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun 	sprintf(buf, "%d", yylineno);
137*4882a593Smuzhiyun 
138*4882a593Smuzhiyun 	return xstrdup(buf);
139*4882a593Smuzhiyun }
140*4882a593Smuzhiyun 
do_shell(int argc,char * argv[])141*4882a593Smuzhiyun static char *do_shell(int argc, char *argv[])
142*4882a593Smuzhiyun {
143*4882a593Smuzhiyun 	FILE *p;
144*4882a593Smuzhiyun 	char buf[4096];
145*4882a593Smuzhiyun 	char *cmd;
146*4882a593Smuzhiyun 	size_t nread;
147*4882a593Smuzhiyun 	int i;
148*4882a593Smuzhiyun 
149*4882a593Smuzhiyun 	cmd = argv[0];
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun 	p = popen(cmd, "r");
152*4882a593Smuzhiyun 	if (!p) {
153*4882a593Smuzhiyun 		perror(cmd);
154*4882a593Smuzhiyun 		exit(1);
155*4882a593Smuzhiyun 	}
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun 	nread = fread(buf, 1, sizeof(buf), p);
158*4882a593Smuzhiyun 	if (nread == sizeof(buf))
159*4882a593Smuzhiyun 		nread--;
160*4882a593Smuzhiyun 
161*4882a593Smuzhiyun 	/* remove trailing new lines */
162*4882a593Smuzhiyun 	while (nread > 0 && buf[nread - 1] == '\n')
163*4882a593Smuzhiyun 		nread--;
164*4882a593Smuzhiyun 
165*4882a593Smuzhiyun 	buf[nread] = 0;
166*4882a593Smuzhiyun 
167*4882a593Smuzhiyun 	/* replace a new line with a space */
168*4882a593Smuzhiyun 	for (i = 0; i < nread; i++) {
169*4882a593Smuzhiyun 		if (buf[i] == '\n')
170*4882a593Smuzhiyun 			buf[i] = ' ';
171*4882a593Smuzhiyun 	}
172*4882a593Smuzhiyun 
173*4882a593Smuzhiyun 	if (pclose(p) == -1) {
174*4882a593Smuzhiyun 		perror(cmd);
175*4882a593Smuzhiyun 		exit(1);
176*4882a593Smuzhiyun 	}
177*4882a593Smuzhiyun 
178*4882a593Smuzhiyun 	return xstrdup(buf);
179*4882a593Smuzhiyun }
180*4882a593Smuzhiyun 
do_warning_if(int argc,char * argv[])181*4882a593Smuzhiyun static char *do_warning_if(int argc, char *argv[])
182*4882a593Smuzhiyun {
183*4882a593Smuzhiyun 	if (!strcmp(argv[0], "y"))
184*4882a593Smuzhiyun 		fprintf(stderr, "%s:%d: %s\n",
185*4882a593Smuzhiyun 			current_file->name, yylineno, argv[1]);
186*4882a593Smuzhiyun 
187*4882a593Smuzhiyun 	return xstrdup("");
188*4882a593Smuzhiyun }
189*4882a593Smuzhiyun 
190*4882a593Smuzhiyun static const struct function function_table[] = {
191*4882a593Smuzhiyun 	/* Name		MIN	MAX	Function */
192*4882a593Smuzhiyun 	{ "error-if",	2,	2,	do_error_if },
193*4882a593Smuzhiyun 	{ "filename",	0,	0,	do_filename },
194*4882a593Smuzhiyun 	{ "info",	1,	1,	do_info },
195*4882a593Smuzhiyun 	{ "lineno",	0,	0,	do_lineno },
196*4882a593Smuzhiyun 	{ "shell",	1,	1,	do_shell },
197*4882a593Smuzhiyun 	{ "warning-if",	2,	2,	do_warning_if },
198*4882a593Smuzhiyun };
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun #define FUNCTION_MAX_ARGS		16
201*4882a593Smuzhiyun 
function_expand(const char * name,int argc,char * argv[])202*4882a593Smuzhiyun static char *function_expand(const char *name, int argc, char *argv[])
203*4882a593Smuzhiyun {
204*4882a593Smuzhiyun 	const struct function *f;
205*4882a593Smuzhiyun 	int i;
206*4882a593Smuzhiyun 
207*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(function_table); i++) {
208*4882a593Smuzhiyun 		f = &function_table[i];
209*4882a593Smuzhiyun 		if (strcmp(f->name, name))
210*4882a593Smuzhiyun 			continue;
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun 		if (argc < f->min_args)
213*4882a593Smuzhiyun 			pperror("too few function arguments passed to '%s'",
214*4882a593Smuzhiyun 				name);
215*4882a593Smuzhiyun 
216*4882a593Smuzhiyun 		if (argc > f->max_args)
217*4882a593Smuzhiyun 			pperror("too many function arguments passed to '%s'",
218*4882a593Smuzhiyun 				name);
219*4882a593Smuzhiyun 
220*4882a593Smuzhiyun 		return f->func(argc, argv);
221*4882a593Smuzhiyun 	}
222*4882a593Smuzhiyun 
223*4882a593Smuzhiyun 	return NULL;
224*4882a593Smuzhiyun }
225*4882a593Smuzhiyun 
226*4882a593Smuzhiyun /*
227*4882a593Smuzhiyun  * Variables (and user-defined functions)
228*4882a593Smuzhiyun  */
229*4882a593Smuzhiyun static LIST_HEAD(variable_list);
230*4882a593Smuzhiyun 
231*4882a593Smuzhiyun struct variable {
232*4882a593Smuzhiyun 	char *name;
233*4882a593Smuzhiyun 	char *value;
234*4882a593Smuzhiyun 	enum variable_flavor flavor;
235*4882a593Smuzhiyun 	int exp_count;
236*4882a593Smuzhiyun 	struct list_head node;
237*4882a593Smuzhiyun };
238*4882a593Smuzhiyun 
variable_lookup(const char * name)239*4882a593Smuzhiyun static struct variable *variable_lookup(const char *name)
240*4882a593Smuzhiyun {
241*4882a593Smuzhiyun 	struct variable *v;
242*4882a593Smuzhiyun 
243*4882a593Smuzhiyun 	list_for_each_entry(v, &variable_list, node) {
244*4882a593Smuzhiyun 		if (!strcmp(name, v->name))
245*4882a593Smuzhiyun 			return v;
246*4882a593Smuzhiyun 	}
247*4882a593Smuzhiyun 
248*4882a593Smuzhiyun 	return NULL;
249*4882a593Smuzhiyun }
250*4882a593Smuzhiyun 
variable_expand(const char * name,int argc,char * argv[])251*4882a593Smuzhiyun static char *variable_expand(const char *name, int argc, char *argv[])
252*4882a593Smuzhiyun {
253*4882a593Smuzhiyun 	struct variable *v;
254*4882a593Smuzhiyun 	char *res;
255*4882a593Smuzhiyun 
256*4882a593Smuzhiyun 	v = variable_lookup(name);
257*4882a593Smuzhiyun 	if (!v)
258*4882a593Smuzhiyun 		return NULL;
259*4882a593Smuzhiyun 
260*4882a593Smuzhiyun 	if (argc == 0 && v->exp_count)
261*4882a593Smuzhiyun 		pperror("Recursive variable '%s' references itself (eventually)",
262*4882a593Smuzhiyun 			name);
263*4882a593Smuzhiyun 
264*4882a593Smuzhiyun 	if (v->exp_count > 1000)
265*4882a593Smuzhiyun 		pperror("Too deep recursive expansion");
266*4882a593Smuzhiyun 
267*4882a593Smuzhiyun 	v->exp_count++;
268*4882a593Smuzhiyun 
269*4882a593Smuzhiyun 	if (v->flavor == VAR_RECURSIVE)
270*4882a593Smuzhiyun 		res = expand_string_with_args(v->value, argc, argv);
271*4882a593Smuzhiyun 	else
272*4882a593Smuzhiyun 		res = xstrdup(v->value);
273*4882a593Smuzhiyun 
274*4882a593Smuzhiyun 	v->exp_count--;
275*4882a593Smuzhiyun 
276*4882a593Smuzhiyun 	return res;
277*4882a593Smuzhiyun }
278*4882a593Smuzhiyun 
variable_add(const char * name,const char * value,enum variable_flavor flavor)279*4882a593Smuzhiyun void variable_add(const char *name, const char *value,
280*4882a593Smuzhiyun 		  enum variable_flavor flavor)
281*4882a593Smuzhiyun {
282*4882a593Smuzhiyun 	struct variable *v;
283*4882a593Smuzhiyun 	char *new_value;
284*4882a593Smuzhiyun 	bool append = false;
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun 	v = variable_lookup(name);
287*4882a593Smuzhiyun 	if (v) {
288*4882a593Smuzhiyun 		/* For defined variables, += inherits the existing flavor */
289*4882a593Smuzhiyun 		if (flavor == VAR_APPEND) {
290*4882a593Smuzhiyun 			flavor = v->flavor;
291*4882a593Smuzhiyun 			append = true;
292*4882a593Smuzhiyun 		} else {
293*4882a593Smuzhiyun 			free(v->value);
294*4882a593Smuzhiyun 		}
295*4882a593Smuzhiyun 	} else {
296*4882a593Smuzhiyun 		/* For undefined variables, += assumes the recursive flavor */
297*4882a593Smuzhiyun 		if (flavor == VAR_APPEND)
298*4882a593Smuzhiyun 			flavor = VAR_RECURSIVE;
299*4882a593Smuzhiyun 
300*4882a593Smuzhiyun 		v = xmalloc(sizeof(*v));
301*4882a593Smuzhiyun 		v->name = xstrdup(name);
302*4882a593Smuzhiyun 		v->exp_count = 0;
303*4882a593Smuzhiyun 		list_add_tail(&v->node, &variable_list);
304*4882a593Smuzhiyun 	}
305*4882a593Smuzhiyun 
306*4882a593Smuzhiyun 	v->flavor = flavor;
307*4882a593Smuzhiyun 
308*4882a593Smuzhiyun 	if (flavor == VAR_SIMPLE)
309*4882a593Smuzhiyun 		new_value = expand_string(value);
310*4882a593Smuzhiyun 	else
311*4882a593Smuzhiyun 		new_value = xstrdup(value);
312*4882a593Smuzhiyun 
313*4882a593Smuzhiyun 	if (append) {
314*4882a593Smuzhiyun 		v->value = xrealloc(v->value,
315*4882a593Smuzhiyun 				    strlen(v->value) + strlen(new_value) + 2);
316*4882a593Smuzhiyun 		strcat(v->value, " ");
317*4882a593Smuzhiyun 		strcat(v->value, new_value);
318*4882a593Smuzhiyun 		free(new_value);
319*4882a593Smuzhiyun 	} else {
320*4882a593Smuzhiyun 		v->value = new_value;
321*4882a593Smuzhiyun 	}
322*4882a593Smuzhiyun }
323*4882a593Smuzhiyun 
variable_del(struct variable * v)324*4882a593Smuzhiyun static void variable_del(struct variable *v)
325*4882a593Smuzhiyun {
326*4882a593Smuzhiyun 	list_del(&v->node);
327*4882a593Smuzhiyun 	free(v->name);
328*4882a593Smuzhiyun 	free(v->value);
329*4882a593Smuzhiyun 	free(v);
330*4882a593Smuzhiyun }
331*4882a593Smuzhiyun 
variable_all_del(void)332*4882a593Smuzhiyun void variable_all_del(void)
333*4882a593Smuzhiyun {
334*4882a593Smuzhiyun 	struct variable *v, *tmp;
335*4882a593Smuzhiyun 
336*4882a593Smuzhiyun 	list_for_each_entry_safe(v, tmp, &variable_list, node)
337*4882a593Smuzhiyun 		variable_del(v);
338*4882a593Smuzhiyun }
339*4882a593Smuzhiyun 
340*4882a593Smuzhiyun /*
341*4882a593Smuzhiyun  * Evaluate a clause with arguments.  argc/argv are arguments from the upper
342*4882a593Smuzhiyun  * function call.
343*4882a593Smuzhiyun  *
344*4882a593Smuzhiyun  * Returned string must be freed when done
345*4882a593Smuzhiyun  */
eval_clause(const char * str,size_t len,int argc,char * argv[])346*4882a593Smuzhiyun static char *eval_clause(const char *str, size_t len, int argc, char *argv[])
347*4882a593Smuzhiyun {
348*4882a593Smuzhiyun 	char *tmp, *name, *res, *endptr, *prev, *p;
349*4882a593Smuzhiyun 	int new_argc = 0;
350*4882a593Smuzhiyun 	char *new_argv[FUNCTION_MAX_ARGS];
351*4882a593Smuzhiyun 	int nest = 0;
352*4882a593Smuzhiyun 	int i;
353*4882a593Smuzhiyun 	unsigned long n;
354*4882a593Smuzhiyun 
355*4882a593Smuzhiyun 	tmp = xstrndup(str, len);
356*4882a593Smuzhiyun 
357*4882a593Smuzhiyun 	/*
358*4882a593Smuzhiyun 	 * If variable name is '1', '2', etc.  It is generally an argument
359*4882a593Smuzhiyun 	 * from a user-function call (i.e. local-scope variable).  If not
360*4882a593Smuzhiyun 	 * available, then look-up global-scope variables.
361*4882a593Smuzhiyun 	 */
362*4882a593Smuzhiyun 	n = strtoul(tmp, &endptr, 10);
363*4882a593Smuzhiyun 	if (!*endptr && n > 0 && n <= argc) {
364*4882a593Smuzhiyun 		res = xstrdup(argv[n - 1]);
365*4882a593Smuzhiyun 		goto free_tmp;
366*4882a593Smuzhiyun 	}
367*4882a593Smuzhiyun 
368*4882a593Smuzhiyun 	prev = p = tmp;
369*4882a593Smuzhiyun 
370*4882a593Smuzhiyun 	/*
371*4882a593Smuzhiyun 	 * Split into tokens
372*4882a593Smuzhiyun 	 * The function name and arguments are separated by a comma.
373*4882a593Smuzhiyun 	 * For example, if the function call is like this:
374*4882a593Smuzhiyun 	 *   $(foo,$(x),$(y))
375*4882a593Smuzhiyun 	 *
376*4882a593Smuzhiyun 	 * The input string for this helper should be:
377*4882a593Smuzhiyun 	 *   foo,$(x),$(y)
378*4882a593Smuzhiyun 	 *
379*4882a593Smuzhiyun 	 * and split into:
380*4882a593Smuzhiyun 	 *   new_argv[0] = 'foo'
381*4882a593Smuzhiyun 	 *   new_argv[1] = '$(x)'
382*4882a593Smuzhiyun 	 *   new_argv[2] = '$(y)'
383*4882a593Smuzhiyun 	 */
384*4882a593Smuzhiyun 	while (*p) {
385*4882a593Smuzhiyun 		if (nest == 0 && *p == ',') {
386*4882a593Smuzhiyun 			*p = 0;
387*4882a593Smuzhiyun 			if (new_argc >= FUNCTION_MAX_ARGS)
388*4882a593Smuzhiyun 				pperror("too many function arguments");
389*4882a593Smuzhiyun 			new_argv[new_argc++] = prev;
390*4882a593Smuzhiyun 			prev = p + 1;
391*4882a593Smuzhiyun 		} else if (*p == '(') {
392*4882a593Smuzhiyun 			nest++;
393*4882a593Smuzhiyun 		} else if (*p == ')') {
394*4882a593Smuzhiyun 			nest--;
395*4882a593Smuzhiyun 		}
396*4882a593Smuzhiyun 
397*4882a593Smuzhiyun 		p++;
398*4882a593Smuzhiyun 	}
399*4882a593Smuzhiyun 	new_argv[new_argc++] = prev;
400*4882a593Smuzhiyun 
401*4882a593Smuzhiyun 	/*
402*4882a593Smuzhiyun 	 * Shift arguments
403*4882a593Smuzhiyun 	 * new_argv[0] represents a function name or a variable name.  Put it
404*4882a593Smuzhiyun 	 * into 'name', then shift the rest of the arguments.  This simplifies
405*4882a593Smuzhiyun 	 * 'const' handling.
406*4882a593Smuzhiyun 	 */
407*4882a593Smuzhiyun 	name = expand_string_with_args(new_argv[0], argc, argv);
408*4882a593Smuzhiyun 	new_argc--;
409*4882a593Smuzhiyun 	for (i = 0; i < new_argc; i++)
410*4882a593Smuzhiyun 		new_argv[i] = expand_string_with_args(new_argv[i + 1],
411*4882a593Smuzhiyun 						      argc, argv);
412*4882a593Smuzhiyun 
413*4882a593Smuzhiyun 	/* Search for variables */
414*4882a593Smuzhiyun 	res = variable_expand(name, new_argc, new_argv);
415*4882a593Smuzhiyun 	if (res)
416*4882a593Smuzhiyun 		goto free;
417*4882a593Smuzhiyun 
418*4882a593Smuzhiyun 	/* Look for built-in functions */
419*4882a593Smuzhiyun 	res = function_expand(name, new_argc, new_argv);
420*4882a593Smuzhiyun 	if (res)
421*4882a593Smuzhiyun 		goto free;
422*4882a593Smuzhiyun 
423*4882a593Smuzhiyun 	/* Last, try environment variable */
424*4882a593Smuzhiyun 	if (new_argc == 0) {
425*4882a593Smuzhiyun 		res = env_expand(name);
426*4882a593Smuzhiyun 		if (res)
427*4882a593Smuzhiyun 			goto free;
428*4882a593Smuzhiyun 	}
429*4882a593Smuzhiyun 
430*4882a593Smuzhiyun 	res = xstrdup("");
431*4882a593Smuzhiyun free:
432*4882a593Smuzhiyun 	for (i = 0; i < new_argc; i++)
433*4882a593Smuzhiyun 		free(new_argv[i]);
434*4882a593Smuzhiyun 	free(name);
435*4882a593Smuzhiyun free_tmp:
436*4882a593Smuzhiyun 	free(tmp);
437*4882a593Smuzhiyun 
438*4882a593Smuzhiyun 	return res;
439*4882a593Smuzhiyun }
440*4882a593Smuzhiyun 
441*4882a593Smuzhiyun /*
442*4882a593Smuzhiyun  * Expand a string that follows '$'
443*4882a593Smuzhiyun  *
444*4882a593Smuzhiyun  * For example, if the input string is
445*4882a593Smuzhiyun  *     ($(FOO)$($(BAR)))$(BAZ)
446*4882a593Smuzhiyun  * this helper evaluates
447*4882a593Smuzhiyun  *     $($(FOO)$($(BAR)))
448*4882a593Smuzhiyun  * and returns a new string containing the expansion (note that the string is
449*4882a593Smuzhiyun  * recursively expanded), also advancing 'str' to point to the next character
450*4882a593Smuzhiyun  * after the corresponding closing parenthesis, in this case, *str will be
451*4882a593Smuzhiyun  *     $(BAR)
452*4882a593Smuzhiyun  */
expand_dollar_with_args(const char ** str,int argc,char * argv[])453*4882a593Smuzhiyun static char *expand_dollar_with_args(const char **str, int argc, char *argv[])
454*4882a593Smuzhiyun {
455*4882a593Smuzhiyun 	const char *p = *str;
456*4882a593Smuzhiyun 	const char *q;
457*4882a593Smuzhiyun 	int nest = 0;
458*4882a593Smuzhiyun 
459*4882a593Smuzhiyun 	/*
460*4882a593Smuzhiyun 	 * In Kconfig, variable/function references always start with "$(".
461*4882a593Smuzhiyun 	 * Neither single-letter variables as in $A nor curly braces as in ${CC}
462*4882a593Smuzhiyun 	 * are supported.  '$' not followed by '(' loses its special meaning.
463*4882a593Smuzhiyun 	 */
464*4882a593Smuzhiyun 	if (*p != '(') {
465*4882a593Smuzhiyun 		*str = p;
466*4882a593Smuzhiyun 		return xstrdup("$");
467*4882a593Smuzhiyun 	}
468*4882a593Smuzhiyun 
469*4882a593Smuzhiyun 	p++;
470*4882a593Smuzhiyun 	q = p;
471*4882a593Smuzhiyun 	while (*q) {
472*4882a593Smuzhiyun 		if (*q == '(') {
473*4882a593Smuzhiyun 			nest++;
474*4882a593Smuzhiyun 		} else if (*q == ')') {
475*4882a593Smuzhiyun 			if (nest-- == 0)
476*4882a593Smuzhiyun 				break;
477*4882a593Smuzhiyun 		}
478*4882a593Smuzhiyun 		q++;
479*4882a593Smuzhiyun 	}
480*4882a593Smuzhiyun 
481*4882a593Smuzhiyun 	if (!*q)
482*4882a593Smuzhiyun 		pperror("unterminated reference to '%s': missing ')'", p);
483*4882a593Smuzhiyun 
484*4882a593Smuzhiyun 	/* Advance 'str' to after the expanded initial portion of the string */
485*4882a593Smuzhiyun 	*str = q + 1;
486*4882a593Smuzhiyun 
487*4882a593Smuzhiyun 	return eval_clause(p, q - p, argc, argv);
488*4882a593Smuzhiyun }
489*4882a593Smuzhiyun 
expand_dollar(const char ** str)490*4882a593Smuzhiyun char *expand_dollar(const char **str)
491*4882a593Smuzhiyun {
492*4882a593Smuzhiyun 	return expand_dollar_with_args(str, 0, NULL);
493*4882a593Smuzhiyun }
494*4882a593Smuzhiyun 
__expand_string(const char ** str,bool (* is_end)(char c),int argc,char * argv[])495*4882a593Smuzhiyun static char *__expand_string(const char **str, bool (*is_end)(char c),
496*4882a593Smuzhiyun 			     int argc, char *argv[])
497*4882a593Smuzhiyun {
498*4882a593Smuzhiyun 	const char *in, *p;
499*4882a593Smuzhiyun 	char *expansion, *out;
500*4882a593Smuzhiyun 	size_t in_len, out_len;
501*4882a593Smuzhiyun 
502*4882a593Smuzhiyun 	out = xmalloc(1);
503*4882a593Smuzhiyun 	*out = 0;
504*4882a593Smuzhiyun 	out_len = 1;
505*4882a593Smuzhiyun 
506*4882a593Smuzhiyun 	p = in = *str;
507*4882a593Smuzhiyun 
508*4882a593Smuzhiyun 	while (1) {
509*4882a593Smuzhiyun 		if (*p == '$') {
510*4882a593Smuzhiyun 			in_len = p - in;
511*4882a593Smuzhiyun 			p++;
512*4882a593Smuzhiyun 			expansion = expand_dollar_with_args(&p, argc, argv);
513*4882a593Smuzhiyun 			out_len += in_len + strlen(expansion);
514*4882a593Smuzhiyun 			out = xrealloc(out, out_len);
515*4882a593Smuzhiyun 			strncat(out, in, in_len);
516*4882a593Smuzhiyun 			strcat(out, expansion);
517*4882a593Smuzhiyun 			free(expansion);
518*4882a593Smuzhiyun 			in = p;
519*4882a593Smuzhiyun 			continue;
520*4882a593Smuzhiyun 		}
521*4882a593Smuzhiyun 
522*4882a593Smuzhiyun 		if (is_end(*p))
523*4882a593Smuzhiyun 			break;
524*4882a593Smuzhiyun 
525*4882a593Smuzhiyun 		p++;
526*4882a593Smuzhiyun 	}
527*4882a593Smuzhiyun 
528*4882a593Smuzhiyun 	in_len = p - in;
529*4882a593Smuzhiyun 	out_len += in_len;
530*4882a593Smuzhiyun 	out = xrealloc(out, out_len);
531*4882a593Smuzhiyun 	strncat(out, in, in_len);
532*4882a593Smuzhiyun 
533*4882a593Smuzhiyun 	/* Advance 'str' to the end character */
534*4882a593Smuzhiyun 	*str = p;
535*4882a593Smuzhiyun 
536*4882a593Smuzhiyun 	return out;
537*4882a593Smuzhiyun }
538*4882a593Smuzhiyun 
is_end_of_str(char c)539*4882a593Smuzhiyun static bool is_end_of_str(char c)
540*4882a593Smuzhiyun {
541*4882a593Smuzhiyun 	return !c;
542*4882a593Smuzhiyun }
543*4882a593Smuzhiyun 
544*4882a593Smuzhiyun /*
545*4882a593Smuzhiyun  * Expand variables and functions in the given string.  Undefined variables
546*4882a593Smuzhiyun  * expand to an empty string.
547*4882a593Smuzhiyun  * The returned string must be freed when done.
548*4882a593Smuzhiyun  */
expand_string_with_args(const char * in,int argc,char * argv[])549*4882a593Smuzhiyun static char *expand_string_with_args(const char *in, int argc, char *argv[])
550*4882a593Smuzhiyun {
551*4882a593Smuzhiyun 	return __expand_string(&in, is_end_of_str, argc, argv);
552*4882a593Smuzhiyun }
553*4882a593Smuzhiyun 
expand_string(const char * in)554*4882a593Smuzhiyun static char *expand_string(const char *in)
555*4882a593Smuzhiyun {
556*4882a593Smuzhiyun 	return expand_string_with_args(in, 0, NULL);
557*4882a593Smuzhiyun }
558*4882a593Smuzhiyun 
is_end_of_token(char c)559*4882a593Smuzhiyun static bool is_end_of_token(char c)
560*4882a593Smuzhiyun {
561*4882a593Smuzhiyun 	return !(isalnum(c) || c == '_' || c == '-');
562*4882a593Smuzhiyun }
563*4882a593Smuzhiyun 
564*4882a593Smuzhiyun /*
565*4882a593Smuzhiyun  * Expand variables in a token.  The parsing stops when a token separater
566*4882a593Smuzhiyun  * (in most cases, it is a whitespace) is encountered.  'str' is updated to
567*4882a593Smuzhiyun  * point to the next character.
568*4882a593Smuzhiyun  *
569*4882a593Smuzhiyun  * The returned string must be freed when done.
570*4882a593Smuzhiyun  */
expand_one_token(const char ** str)571*4882a593Smuzhiyun char *expand_one_token(const char **str)
572*4882a593Smuzhiyun {
573*4882a593Smuzhiyun 	return __expand_string(str, is_end_of_token, 0, NULL);
574*4882a593Smuzhiyun }
575