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