1104daea1SMasahiro Yamada // SPDX-License-Identifier: GPL-2.0
2104daea1SMasahiro Yamada //
3104daea1SMasahiro Yamada // Copyright (C) 2018 Masahiro Yamada <[email protected]>
4104daea1SMasahiro Yamada
5558e78e3SMasahiro Yamada #include <ctype.h>
6104daea1SMasahiro Yamada #include <stdarg.h>
7104daea1SMasahiro Yamada #include <stdbool.h>
8104daea1SMasahiro Yamada #include <stdio.h>
9104daea1SMasahiro Yamada #include <stdlib.h>
10104daea1SMasahiro Yamada #include <string.h>
11104daea1SMasahiro Yamada
12fbaf242cSMasahiro Yamada #include <array_size.h>
13fbaf242cSMasahiro Yamada #include <list.h>
14*a9d83d74SMasahiro Yamada #include <xalloc.h>
154ff7ceaeSMasahiro Yamada #include "internal.h"
16558e78e3SMasahiro Yamada #include "lkc.h"
17d3d16228SMasahiro Yamada #include "preprocess.h"
18104daea1SMasahiro Yamada
19e298f3b4SMasahiro Yamada static char *expand_string_with_args(const char *in, int argc, char *argv[]);
205533397dSMasahiro Yamada static char *expand_string(const char *in);
21e298f3b4SMasahiro Yamada
pperror(const char * format,...)22104daea1SMasahiro Yamada static void __attribute__((noreturn)) pperror(const char *format, ...)
23104daea1SMasahiro Yamada {
24104daea1SMasahiro Yamada va_list ap;
25104daea1SMasahiro Yamada
264ff7ceaeSMasahiro Yamada fprintf(stderr, "%s:%d: ", cur_filename, yylineno);
27104daea1SMasahiro Yamada va_start(ap, format);
28104daea1SMasahiro Yamada vfprintf(stderr, format, ap);
29104daea1SMasahiro Yamada va_end(ap);
30104daea1SMasahiro Yamada fprintf(stderr, "\n");
31104daea1SMasahiro Yamada
32104daea1SMasahiro Yamada exit(1);
33104daea1SMasahiro Yamada }
34104daea1SMasahiro Yamada
35104daea1SMasahiro Yamada /*
36104daea1SMasahiro Yamada * Environment variables
37104daea1SMasahiro Yamada */
38104daea1SMasahiro Yamada static LIST_HEAD(env_list);
39104daea1SMasahiro Yamada
40104daea1SMasahiro Yamada struct env {
41104daea1SMasahiro Yamada char *name;
42104daea1SMasahiro Yamada char *value;
43104daea1SMasahiro Yamada struct list_head node;
44104daea1SMasahiro Yamada };
45104daea1SMasahiro Yamada
env_add(const char * name,const char * value)46104daea1SMasahiro Yamada static void env_add(const char *name, const char *value)
47104daea1SMasahiro Yamada {
48104daea1SMasahiro Yamada struct env *e;
49104daea1SMasahiro Yamada
50104daea1SMasahiro Yamada e = xmalloc(sizeof(*e));
51104daea1SMasahiro Yamada e->name = xstrdup(name);
52104daea1SMasahiro Yamada e->value = xstrdup(value);
53104daea1SMasahiro Yamada
54104daea1SMasahiro Yamada list_add_tail(&e->node, &env_list);
55104daea1SMasahiro Yamada }
56104daea1SMasahiro Yamada
env_del(struct env * e)57104daea1SMasahiro Yamada static void env_del(struct env *e)
58104daea1SMasahiro Yamada {
59104daea1SMasahiro Yamada list_del(&e->node);
60104daea1SMasahiro Yamada free(e->name);
61104daea1SMasahiro Yamada free(e->value);
62104daea1SMasahiro Yamada free(e);
63104daea1SMasahiro Yamada }
64104daea1SMasahiro Yamada
65104daea1SMasahiro Yamada /* The returned pointer must be freed when done */
env_expand(const char * name)66104daea1SMasahiro Yamada static char *env_expand(const char *name)
67104daea1SMasahiro Yamada {
68104daea1SMasahiro Yamada struct env *e;
69104daea1SMasahiro Yamada const char *value;
70104daea1SMasahiro Yamada
71104daea1SMasahiro Yamada if (!*name)
72104daea1SMasahiro Yamada return NULL;
73104daea1SMasahiro Yamada
74104daea1SMasahiro Yamada list_for_each_entry(e, &env_list, node) {
75104daea1SMasahiro Yamada if (!strcmp(name, e->name))
76104daea1SMasahiro Yamada return xstrdup(e->value);
77104daea1SMasahiro Yamada }
78104daea1SMasahiro Yamada
79104daea1SMasahiro Yamada value = getenv(name);
80104daea1SMasahiro Yamada if (!value)
81104daea1SMasahiro Yamada return NULL;
82104daea1SMasahiro Yamada
83104daea1SMasahiro Yamada /*
84104daea1SMasahiro Yamada * We need to remember all referenced environment variables.
85104daea1SMasahiro Yamada * They will be written out to include/config/auto.conf.cmd
86104daea1SMasahiro Yamada */
87104daea1SMasahiro Yamada env_add(name, value);
88104daea1SMasahiro Yamada
89104daea1SMasahiro Yamada return xstrdup(value);
90104daea1SMasahiro Yamada }
91104daea1SMasahiro Yamada
env_write_dep(struct gstr * s)9256e634b0SMasahiro Yamada void env_write_dep(struct gstr *s)
93104daea1SMasahiro Yamada {
94104daea1SMasahiro Yamada struct env *e, *tmp;
95104daea1SMasahiro Yamada
96104daea1SMasahiro Yamada list_for_each_entry_safe(e, tmp, &env_list, node) {
9756e634b0SMasahiro Yamada str_printf(s,
9856e634b0SMasahiro Yamada "\n"
9956e634b0SMasahiro Yamada "ifneq \"$(%s)\" \"%s\"\n"
10056e634b0SMasahiro Yamada "$(autoconfig): FORCE\n"
10156e634b0SMasahiro Yamada "endif\n",
10256e634b0SMasahiro Yamada e->name, e->value);
103104daea1SMasahiro Yamada env_del(e);
104104daea1SMasahiro Yamada }
105104daea1SMasahiro Yamada }
106104daea1SMasahiro Yamada
107e298f3b4SMasahiro Yamada /*
108e298f3b4SMasahiro Yamada * Built-in functions
109e298f3b4SMasahiro Yamada */
110e298f3b4SMasahiro Yamada struct function {
111e298f3b4SMasahiro Yamada const char *name;
112e298f3b4SMasahiro Yamada unsigned int min_args;
113e298f3b4SMasahiro Yamada unsigned int max_args;
114e298f3b4SMasahiro Yamada char *(*func)(int argc, char *argv[]);
115e298f3b4SMasahiro Yamada };
116e298f3b4SMasahiro Yamada
do_error_if(int argc,char * argv[])1171d6272e6SMasahiro Yamada static char *do_error_if(int argc, char *argv[])
1181d6272e6SMasahiro Yamada {
1191d6272e6SMasahiro Yamada if (!strcmp(argv[0], "y"))
1201d6272e6SMasahiro Yamada pperror("%s", argv[1]);
1211d6272e6SMasahiro Yamada
122135b4957SMasahiro Yamada return xstrdup("");
1231d6272e6SMasahiro Yamada }
1241d6272e6SMasahiro Yamada
do_filename(int argc,char * argv[])125a702a617SMasahiro Yamada static char *do_filename(int argc, char *argv[])
126a702a617SMasahiro Yamada {
1274ff7ceaeSMasahiro Yamada return xstrdup(cur_filename);
128a702a617SMasahiro Yamada }
129a702a617SMasahiro Yamada
do_info(int argc,char * argv[])1301d6272e6SMasahiro Yamada static char *do_info(int argc, char *argv[])
1311d6272e6SMasahiro Yamada {
1321d6272e6SMasahiro Yamada printf("%s\n", argv[0]);
1331d6272e6SMasahiro Yamada
1341d6272e6SMasahiro Yamada return xstrdup("");
1351d6272e6SMasahiro Yamada }
1361d6272e6SMasahiro Yamada
do_lineno(int argc,char * argv[])137a702a617SMasahiro Yamada static char *do_lineno(int argc, char *argv[])
138a702a617SMasahiro Yamada {
139a702a617SMasahiro Yamada char buf[16];
140a702a617SMasahiro Yamada
141a702a617SMasahiro Yamada sprintf(buf, "%d", yylineno);
142a702a617SMasahiro Yamada
143a702a617SMasahiro Yamada return xstrdup(buf);
144a702a617SMasahiro Yamada }
145a702a617SMasahiro Yamada
do_shell(int argc,char * argv[])1462fd5b09cSMasahiro Yamada static char *do_shell(int argc, char *argv[])
1472fd5b09cSMasahiro Yamada {
1482fd5b09cSMasahiro Yamada FILE *p;
1498a4c5b2aSBrenda Streiff char buf[4096];
1502fd5b09cSMasahiro Yamada char *cmd;
1512fd5b09cSMasahiro Yamada size_t nread;
1522fd5b09cSMasahiro Yamada int i;
1532fd5b09cSMasahiro Yamada
1542fd5b09cSMasahiro Yamada cmd = argv[0];
1552fd5b09cSMasahiro Yamada
1562fd5b09cSMasahiro Yamada p = popen(cmd, "r");
1572fd5b09cSMasahiro Yamada if (!p) {
1582fd5b09cSMasahiro Yamada perror(cmd);
1592fd5b09cSMasahiro Yamada exit(1);
1602fd5b09cSMasahiro Yamada }
1612fd5b09cSMasahiro Yamada
1622fd5b09cSMasahiro Yamada nread = fread(buf, 1, sizeof(buf), p);
1632fd5b09cSMasahiro Yamada if (nread == sizeof(buf))
1642fd5b09cSMasahiro Yamada nread--;
1652fd5b09cSMasahiro Yamada
1662fd5b09cSMasahiro Yamada /* remove trailing new lines */
16773d1c580SJerry James while (nread > 0 && buf[nread - 1] == '\n')
1682fd5b09cSMasahiro Yamada nread--;
1692fd5b09cSMasahiro Yamada
1702fd5b09cSMasahiro Yamada buf[nread] = 0;
1712fd5b09cSMasahiro Yamada
1722fd5b09cSMasahiro Yamada /* replace a new line with a space */
1732fd5b09cSMasahiro Yamada for (i = 0; i < nread; i++) {
1742fd5b09cSMasahiro Yamada if (buf[i] == '\n')
1752fd5b09cSMasahiro Yamada buf[i] = ' ';
1762fd5b09cSMasahiro Yamada }
1772fd5b09cSMasahiro Yamada
1782fd5b09cSMasahiro Yamada if (pclose(p) == -1) {
1792fd5b09cSMasahiro Yamada perror(cmd);
1802fd5b09cSMasahiro Yamada exit(1);
1812fd5b09cSMasahiro Yamada }
1822fd5b09cSMasahiro Yamada
1832fd5b09cSMasahiro Yamada return xstrdup(buf);
1842fd5b09cSMasahiro Yamada }
1852fd5b09cSMasahiro Yamada
do_warning_if(int argc,char * argv[])1861d6272e6SMasahiro Yamada static char *do_warning_if(int argc, char *argv[])
1871d6272e6SMasahiro Yamada {
1881d6272e6SMasahiro Yamada if (!strcmp(argv[0], "y"))
1894ff7ceaeSMasahiro Yamada fprintf(stderr, "%s:%d: %s\n", cur_filename, yylineno, argv[1]);
1901d6272e6SMasahiro Yamada
1911d6272e6SMasahiro Yamada return xstrdup("");
1921d6272e6SMasahiro Yamada }
1931d6272e6SMasahiro Yamada
194e298f3b4SMasahiro Yamada static const struct function function_table[] = {
195e298f3b4SMasahiro Yamada /* Name MIN MAX Function */
1961d6272e6SMasahiro Yamada { "error-if", 2, 2, do_error_if },
197a702a617SMasahiro Yamada { "filename", 0, 0, do_filename },
1981d6272e6SMasahiro Yamada { "info", 1, 1, do_info },
199a702a617SMasahiro Yamada { "lineno", 0, 0, do_lineno },
2002fd5b09cSMasahiro Yamada { "shell", 1, 1, do_shell },
2011d6272e6SMasahiro Yamada { "warning-if", 2, 2, do_warning_if },
202e298f3b4SMasahiro Yamada };
203e298f3b4SMasahiro Yamada
204e298f3b4SMasahiro Yamada #define FUNCTION_MAX_ARGS 16
205e298f3b4SMasahiro Yamada
function_expand(const char * name,int argc,char * argv[])206e298f3b4SMasahiro Yamada static char *function_expand(const char *name, int argc, char *argv[])
207104daea1SMasahiro Yamada {
208e298f3b4SMasahiro Yamada const struct function *f;
209e298f3b4SMasahiro Yamada int i;
210e298f3b4SMasahiro Yamada
211e298f3b4SMasahiro Yamada for (i = 0; i < ARRAY_SIZE(function_table); i++) {
212e298f3b4SMasahiro Yamada f = &function_table[i];
213e298f3b4SMasahiro Yamada if (strcmp(f->name, name))
214e298f3b4SMasahiro Yamada continue;
215e298f3b4SMasahiro Yamada
216e298f3b4SMasahiro Yamada if (argc < f->min_args)
217e298f3b4SMasahiro Yamada pperror("too few function arguments passed to '%s'",
218e298f3b4SMasahiro Yamada name);
219e298f3b4SMasahiro Yamada
220e298f3b4SMasahiro Yamada if (argc > f->max_args)
221e298f3b4SMasahiro Yamada pperror("too many function arguments passed to '%s'",
222e298f3b4SMasahiro Yamada name);
223e298f3b4SMasahiro Yamada
224e298f3b4SMasahiro Yamada return f->func(argc, argv);
225e298f3b4SMasahiro Yamada }
226e298f3b4SMasahiro Yamada
227e298f3b4SMasahiro Yamada return NULL;
228e298f3b4SMasahiro Yamada }
229e298f3b4SMasahiro Yamada
230e298f3b4SMasahiro Yamada /*
2319ced3bddSMasahiro Yamada * Variables (and user-defined functions)
2329ced3bddSMasahiro Yamada */
2339ced3bddSMasahiro Yamada static LIST_HEAD(variable_list);
2349ced3bddSMasahiro Yamada
2359ced3bddSMasahiro Yamada struct variable {
2369ced3bddSMasahiro Yamada char *name;
2379ced3bddSMasahiro Yamada char *value;
2381175c025SMasahiro Yamada enum variable_flavor flavor;
239915f6490SMasahiro Yamada int exp_count;
2409ced3bddSMasahiro Yamada struct list_head node;
2419ced3bddSMasahiro Yamada };
2429ced3bddSMasahiro Yamada
variable_lookup(const char * name)2439ced3bddSMasahiro Yamada static struct variable *variable_lookup(const char *name)
2449ced3bddSMasahiro Yamada {
2459ced3bddSMasahiro Yamada struct variable *v;
2469ced3bddSMasahiro Yamada
2479ced3bddSMasahiro Yamada list_for_each_entry(v, &variable_list, node) {
2489ced3bddSMasahiro Yamada if (!strcmp(name, v->name))
2499ced3bddSMasahiro Yamada return v;
2509ced3bddSMasahiro Yamada }
2519ced3bddSMasahiro Yamada
2529ced3bddSMasahiro Yamada return NULL;
2539ced3bddSMasahiro Yamada }
2549ced3bddSMasahiro Yamada
variable_expand(const char * name,int argc,char * argv[])2559ced3bddSMasahiro Yamada static char *variable_expand(const char *name, int argc, char *argv[])
2569ced3bddSMasahiro Yamada {
2579ced3bddSMasahiro Yamada struct variable *v;
2581175c025SMasahiro Yamada char *res;
2599ced3bddSMasahiro Yamada
2609ced3bddSMasahiro Yamada v = variable_lookup(name);
2619ced3bddSMasahiro Yamada if (!v)
2629ced3bddSMasahiro Yamada return NULL;
2639ced3bddSMasahiro Yamada
264915f6490SMasahiro Yamada if (argc == 0 && v->exp_count)
265915f6490SMasahiro Yamada pperror("Recursive variable '%s' references itself (eventually)",
266915f6490SMasahiro Yamada name);
267915f6490SMasahiro Yamada
268915f6490SMasahiro Yamada if (v->exp_count > 1000)
269915f6490SMasahiro Yamada pperror("Too deep recursive expansion");
270915f6490SMasahiro Yamada
271915f6490SMasahiro Yamada v->exp_count++;
272915f6490SMasahiro Yamada
2731175c025SMasahiro Yamada if (v->flavor == VAR_RECURSIVE)
2741175c025SMasahiro Yamada res = expand_string_with_args(v->value, argc, argv);
2751175c025SMasahiro Yamada else
2761175c025SMasahiro Yamada res = xstrdup(v->value);
2771175c025SMasahiro Yamada
278915f6490SMasahiro Yamada v->exp_count--;
279915f6490SMasahiro Yamada
2801175c025SMasahiro Yamada return res;
2819ced3bddSMasahiro Yamada }
2829ced3bddSMasahiro Yamada
variable_add(const char * name,const char * value,enum variable_flavor flavor)2831175c025SMasahiro Yamada void variable_add(const char *name, const char *value,
2841175c025SMasahiro Yamada enum variable_flavor flavor)
2859ced3bddSMasahiro Yamada {
2869ced3bddSMasahiro Yamada struct variable *v;
287ed2a22f2SMasahiro Yamada char *new_value;
288ed2a22f2SMasahiro Yamada bool append = false;
2899ced3bddSMasahiro Yamada
2909ced3bddSMasahiro Yamada v = variable_lookup(name);
2919ced3bddSMasahiro Yamada if (v) {
292ed2a22f2SMasahiro Yamada /* For defined variables, += inherits the existing flavor */
293ed2a22f2SMasahiro Yamada if (flavor == VAR_APPEND) {
294ed2a22f2SMasahiro Yamada flavor = v->flavor;
295ed2a22f2SMasahiro Yamada append = true;
2969ced3bddSMasahiro Yamada } else {
297ed2a22f2SMasahiro Yamada free(v->value);
298ed2a22f2SMasahiro Yamada }
299ed2a22f2SMasahiro Yamada } else {
300ed2a22f2SMasahiro Yamada /* For undefined variables, += assumes the recursive flavor */
301ed2a22f2SMasahiro Yamada if (flavor == VAR_APPEND)
302ed2a22f2SMasahiro Yamada flavor = VAR_RECURSIVE;
303ed2a22f2SMasahiro Yamada
3049ced3bddSMasahiro Yamada v = xmalloc(sizeof(*v));
3059ced3bddSMasahiro Yamada v->name = xstrdup(name);
306915f6490SMasahiro Yamada v->exp_count = 0;
3079ced3bddSMasahiro Yamada list_add_tail(&v->node, &variable_list);
3089ced3bddSMasahiro Yamada }
3099ced3bddSMasahiro Yamada
3101175c025SMasahiro Yamada v->flavor = flavor;
3111175c025SMasahiro Yamada
3121175c025SMasahiro Yamada if (flavor == VAR_SIMPLE)
313ed2a22f2SMasahiro Yamada new_value = expand_string(value);
3141175c025SMasahiro Yamada else
315ed2a22f2SMasahiro Yamada new_value = xstrdup(value);
316ed2a22f2SMasahiro Yamada
317ed2a22f2SMasahiro Yamada if (append) {
318ed2a22f2SMasahiro Yamada v->value = xrealloc(v->value,
319ed2a22f2SMasahiro Yamada strlen(v->value) + strlen(new_value) + 2);
320ed2a22f2SMasahiro Yamada strcat(v->value, " ");
321ed2a22f2SMasahiro Yamada strcat(v->value, new_value);
322ed2a22f2SMasahiro Yamada free(new_value);
323ed2a22f2SMasahiro Yamada } else {
324ed2a22f2SMasahiro Yamada v->value = new_value;
325ed2a22f2SMasahiro Yamada }
3269ced3bddSMasahiro Yamada }
3279ced3bddSMasahiro Yamada
variable_del(struct variable * v)3289ced3bddSMasahiro Yamada static void variable_del(struct variable *v)
3299ced3bddSMasahiro Yamada {
3309ced3bddSMasahiro Yamada list_del(&v->node);
3319ced3bddSMasahiro Yamada free(v->name);
3329ced3bddSMasahiro Yamada free(v->value);
3339ced3bddSMasahiro Yamada free(v);
3349ced3bddSMasahiro Yamada }
3359ced3bddSMasahiro Yamada
variable_all_del(void)3369ced3bddSMasahiro Yamada void variable_all_del(void)
3379ced3bddSMasahiro Yamada {
3389ced3bddSMasahiro Yamada struct variable *v, *tmp;
3399ced3bddSMasahiro Yamada
3409ced3bddSMasahiro Yamada list_for_each_entry_safe(v, tmp, &variable_list, node)
3419ced3bddSMasahiro Yamada variable_del(v);
3429ced3bddSMasahiro Yamada }
3439ced3bddSMasahiro Yamada
3449ced3bddSMasahiro Yamada /*
345e298f3b4SMasahiro Yamada * Evaluate a clause with arguments. argc/argv are arguments from the upper
346e298f3b4SMasahiro Yamada * function call.
347e298f3b4SMasahiro Yamada *
348e298f3b4SMasahiro Yamada * Returned string must be freed when done
349e298f3b4SMasahiro Yamada */
eval_clause(const char * str,size_t len,int argc,char * argv[])350e298f3b4SMasahiro Yamada static char *eval_clause(const char *str, size_t len, int argc, char *argv[])
351e298f3b4SMasahiro Yamada {
3529ced3bddSMasahiro Yamada char *tmp, *name, *res, *endptr, *prev, *p;
353e298f3b4SMasahiro Yamada int new_argc = 0;
354e298f3b4SMasahiro Yamada char *new_argv[FUNCTION_MAX_ARGS];
355e298f3b4SMasahiro Yamada int nest = 0;
356e298f3b4SMasahiro Yamada int i;
3579ced3bddSMasahiro Yamada unsigned long n;
358104daea1SMasahiro Yamada
359104daea1SMasahiro Yamada tmp = xstrndup(str, len);
360104daea1SMasahiro Yamada
3619ced3bddSMasahiro Yamada /*
3629ced3bddSMasahiro Yamada * If variable name is '1', '2', etc. It is generally an argument
3639ced3bddSMasahiro Yamada * from a user-function call (i.e. local-scope variable). If not
3649ced3bddSMasahiro Yamada * available, then look-up global-scope variables.
3659ced3bddSMasahiro Yamada */
3669ced3bddSMasahiro Yamada n = strtoul(tmp, &endptr, 10);
3679ced3bddSMasahiro Yamada if (!*endptr && n > 0 && n <= argc) {
3689ced3bddSMasahiro Yamada res = xstrdup(argv[n - 1]);
3699ced3bddSMasahiro Yamada goto free_tmp;
3709ced3bddSMasahiro Yamada }
3719ced3bddSMasahiro Yamada
372e298f3b4SMasahiro Yamada prev = p = tmp;
373104daea1SMasahiro Yamada
374e298f3b4SMasahiro Yamada /*
375e298f3b4SMasahiro Yamada * Split into tokens
376e298f3b4SMasahiro Yamada * The function name and arguments are separated by a comma.
377e298f3b4SMasahiro Yamada * For example, if the function call is like this:
378e298f3b4SMasahiro Yamada * $(foo,$(x),$(y))
379e298f3b4SMasahiro Yamada *
380e298f3b4SMasahiro Yamada * The input string for this helper should be:
381e298f3b4SMasahiro Yamada * foo,$(x),$(y)
382e298f3b4SMasahiro Yamada *
383e298f3b4SMasahiro Yamada * and split into:
384e298f3b4SMasahiro Yamada * new_argv[0] = 'foo'
385e298f3b4SMasahiro Yamada * new_argv[1] = '$(x)'
386e298f3b4SMasahiro Yamada * new_argv[2] = '$(y)'
387e298f3b4SMasahiro Yamada */
388e298f3b4SMasahiro Yamada while (*p) {
389e298f3b4SMasahiro Yamada if (nest == 0 && *p == ',') {
390e298f3b4SMasahiro Yamada *p = 0;
391e298f3b4SMasahiro Yamada if (new_argc >= FUNCTION_MAX_ARGS)
392e298f3b4SMasahiro Yamada pperror("too many function arguments");
393e298f3b4SMasahiro Yamada new_argv[new_argc++] = prev;
394e298f3b4SMasahiro Yamada prev = p + 1;
395e298f3b4SMasahiro Yamada } else if (*p == '(') {
396e298f3b4SMasahiro Yamada nest++;
397e298f3b4SMasahiro Yamada } else if (*p == ')') {
398e298f3b4SMasahiro Yamada nest--;
399e298f3b4SMasahiro Yamada }
400e298f3b4SMasahiro Yamada
401e298f3b4SMasahiro Yamada p++;
402e298f3b4SMasahiro Yamada }
403a3b7039bSKonstantin Meskhidze
404a3b7039bSKonstantin Meskhidze if (new_argc >= FUNCTION_MAX_ARGS)
405a3b7039bSKonstantin Meskhidze pperror("too many function arguments");
406e298f3b4SMasahiro Yamada new_argv[new_argc++] = prev;
407e298f3b4SMasahiro Yamada
408e298f3b4SMasahiro Yamada /*
409e298f3b4SMasahiro Yamada * Shift arguments
410e298f3b4SMasahiro Yamada * new_argv[0] represents a function name or a variable name. Put it
411e298f3b4SMasahiro Yamada * into 'name', then shift the rest of the arguments. This simplifies
412e298f3b4SMasahiro Yamada * 'const' handling.
413e298f3b4SMasahiro Yamada */
414e298f3b4SMasahiro Yamada name = expand_string_with_args(new_argv[0], argc, argv);
415e298f3b4SMasahiro Yamada new_argc--;
416e298f3b4SMasahiro Yamada for (i = 0; i < new_argc; i++)
417e298f3b4SMasahiro Yamada new_argv[i] = expand_string_with_args(new_argv[i + 1],
418e298f3b4SMasahiro Yamada argc, argv);
419e298f3b4SMasahiro Yamada
4209ced3bddSMasahiro Yamada /* Search for variables */
4219ced3bddSMasahiro Yamada res = variable_expand(name, new_argc, new_argv);
4229ced3bddSMasahiro Yamada if (res)
4239ced3bddSMasahiro Yamada goto free;
4249ced3bddSMasahiro Yamada
425e298f3b4SMasahiro Yamada /* Look for built-in functions */
426e298f3b4SMasahiro Yamada res = function_expand(name, new_argc, new_argv);
427104daea1SMasahiro Yamada if (res)
428104daea1SMasahiro Yamada goto free;
429104daea1SMasahiro Yamada
430e298f3b4SMasahiro Yamada /* Last, try environment variable */
431e298f3b4SMasahiro Yamada if (new_argc == 0) {
432e298f3b4SMasahiro Yamada res = env_expand(name);
433e298f3b4SMasahiro Yamada if (res)
434e298f3b4SMasahiro Yamada goto free;
435e298f3b4SMasahiro Yamada }
436e298f3b4SMasahiro Yamada
437104daea1SMasahiro Yamada res = xstrdup("");
438104daea1SMasahiro Yamada free:
439e298f3b4SMasahiro Yamada for (i = 0; i < new_argc; i++)
440e298f3b4SMasahiro Yamada free(new_argv[i]);
441104daea1SMasahiro Yamada free(name);
4429ced3bddSMasahiro Yamada free_tmp:
443104daea1SMasahiro Yamada free(tmp);
444104daea1SMasahiro Yamada
445104daea1SMasahiro Yamada return res;
446104daea1SMasahiro Yamada }
447104daea1SMasahiro Yamada
448104daea1SMasahiro Yamada /*
449104daea1SMasahiro Yamada * Expand a string that follows '$'
450104daea1SMasahiro Yamada *
451104daea1SMasahiro Yamada * For example, if the input string is
452104daea1SMasahiro Yamada * ($(FOO)$($(BAR)))$(BAZ)
453104daea1SMasahiro Yamada * this helper evaluates
454104daea1SMasahiro Yamada * $($(FOO)$($(BAR)))
455104daea1SMasahiro Yamada * and returns a new string containing the expansion (note that the string is
456104daea1SMasahiro Yamada * recursively expanded), also advancing 'str' to point to the next character
457104daea1SMasahiro Yamada * after the corresponding closing parenthesis, in this case, *str will be
458104daea1SMasahiro Yamada * $(BAR)
459104daea1SMasahiro Yamada */
expand_dollar_with_args(const char ** str,int argc,char * argv[])460e298f3b4SMasahiro Yamada static char *expand_dollar_with_args(const char **str, int argc, char *argv[])
461104daea1SMasahiro Yamada {
462104daea1SMasahiro Yamada const char *p = *str;
463104daea1SMasahiro Yamada const char *q;
464104daea1SMasahiro Yamada int nest = 0;
465104daea1SMasahiro Yamada
466104daea1SMasahiro Yamada /*
467e298f3b4SMasahiro Yamada * In Kconfig, variable/function references always start with "$(".
468104daea1SMasahiro Yamada * Neither single-letter variables as in $A nor curly braces as in ${CC}
469104daea1SMasahiro Yamada * are supported. '$' not followed by '(' loses its special meaning.
470104daea1SMasahiro Yamada */
471104daea1SMasahiro Yamada if (*p != '(') {
472104daea1SMasahiro Yamada *str = p;
473104daea1SMasahiro Yamada return xstrdup("$");
474104daea1SMasahiro Yamada }
475104daea1SMasahiro Yamada
476104daea1SMasahiro Yamada p++;
477104daea1SMasahiro Yamada q = p;
478104daea1SMasahiro Yamada while (*q) {
479104daea1SMasahiro Yamada if (*q == '(') {
480104daea1SMasahiro Yamada nest++;
481104daea1SMasahiro Yamada } else if (*q == ')') {
482104daea1SMasahiro Yamada if (nest-- == 0)
483104daea1SMasahiro Yamada break;
484104daea1SMasahiro Yamada }
485104daea1SMasahiro Yamada q++;
486104daea1SMasahiro Yamada }
487104daea1SMasahiro Yamada
488104daea1SMasahiro Yamada if (!*q)
489104daea1SMasahiro Yamada pperror("unterminated reference to '%s': missing ')'", p);
490104daea1SMasahiro Yamada
491104daea1SMasahiro Yamada /* Advance 'str' to after the expanded initial portion of the string */
492104daea1SMasahiro Yamada *str = q + 1;
493104daea1SMasahiro Yamada
494e298f3b4SMasahiro Yamada return eval_clause(p, q - p, argc, argv);
495104daea1SMasahiro Yamada }
496104daea1SMasahiro Yamada
expand_dollar(const char ** str)497e298f3b4SMasahiro Yamada char *expand_dollar(const char **str)
498e298f3b4SMasahiro Yamada {
499e298f3b4SMasahiro Yamada return expand_dollar_with_args(str, 0, NULL);
500e298f3b4SMasahiro Yamada }
501e298f3b4SMasahiro Yamada
__expand_string(const char ** str,bool (* is_end)(char c),int argc,char * argv[])502e298f3b4SMasahiro Yamada static char *__expand_string(const char **str, bool (*is_end)(char c),
503e298f3b4SMasahiro Yamada int argc, char *argv[])
504104daea1SMasahiro Yamada {
505104daea1SMasahiro Yamada const char *in, *p;
506104daea1SMasahiro Yamada char *expansion, *out;
507104daea1SMasahiro Yamada size_t in_len, out_len;
508104daea1SMasahiro Yamada
509104daea1SMasahiro Yamada out = xmalloc(1);
510104daea1SMasahiro Yamada *out = 0;
511104daea1SMasahiro Yamada out_len = 1;
512104daea1SMasahiro Yamada
513104daea1SMasahiro Yamada p = in = *str;
514104daea1SMasahiro Yamada
515104daea1SMasahiro Yamada while (1) {
516104daea1SMasahiro Yamada if (*p == '$') {
517104daea1SMasahiro Yamada in_len = p - in;
518104daea1SMasahiro Yamada p++;
519e298f3b4SMasahiro Yamada expansion = expand_dollar_with_args(&p, argc, argv);
520104daea1SMasahiro Yamada out_len += in_len + strlen(expansion);
521104daea1SMasahiro Yamada out = xrealloc(out, out_len);
522104daea1SMasahiro Yamada strncat(out, in, in_len);
523104daea1SMasahiro Yamada strcat(out, expansion);
524104daea1SMasahiro Yamada free(expansion);
525104daea1SMasahiro Yamada in = p;
526104daea1SMasahiro Yamada continue;
527104daea1SMasahiro Yamada }
528104daea1SMasahiro Yamada
529104daea1SMasahiro Yamada if (is_end(*p))
530104daea1SMasahiro Yamada break;
531104daea1SMasahiro Yamada
532104daea1SMasahiro Yamada p++;
533104daea1SMasahiro Yamada }
534104daea1SMasahiro Yamada
535104daea1SMasahiro Yamada in_len = p - in;
536104daea1SMasahiro Yamada out_len += in_len;
537104daea1SMasahiro Yamada out = xrealloc(out, out_len);
538104daea1SMasahiro Yamada strncat(out, in, in_len);
539104daea1SMasahiro Yamada
540104daea1SMasahiro Yamada /* Advance 'str' to the end character */
541104daea1SMasahiro Yamada *str = p;
542104daea1SMasahiro Yamada
543104daea1SMasahiro Yamada return out;
544104daea1SMasahiro Yamada }
545104daea1SMasahiro Yamada
is_end_of_str(char c)546104daea1SMasahiro Yamada static bool is_end_of_str(char c)
547104daea1SMasahiro Yamada {
548104daea1SMasahiro Yamada return !c;
549104daea1SMasahiro Yamada }
550104daea1SMasahiro Yamada
551104daea1SMasahiro Yamada /*
552e298f3b4SMasahiro Yamada * Expand variables and functions in the given string. Undefined variables
553104daea1SMasahiro Yamada * expand to an empty string.
554104daea1SMasahiro Yamada * The returned string must be freed when done.
555104daea1SMasahiro Yamada */
expand_string_with_args(const char * in,int argc,char * argv[])556e298f3b4SMasahiro Yamada static char *expand_string_with_args(const char *in, int argc, char *argv[])
557e298f3b4SMasahiro Yamada {
558e298f3b4SMasahiro Yamada return __expand_string(&in, is_end_of_str, argc, argv);
559e298f3b4SMasahiro Yamada }
560e298f3b4SMasahiro Yamada
expand_string(const char * in)5615533397dSMasahiro Yamada static char *expand_string(const char *in)
562104daea1SMasahiro Yamada {
563e298f3b4SMasahiro Yamada return expand_string_with_args(in, 0, NULL);
564104daea1SMasahiro Yamada }
565104daea1SMasahiro Yamada
is_end_of_token(char c)566104daea1SMasahiro Yamada static bool is_end_of_token(char c)
567104daea1SMasahiro Yamada {
568f5451582SMasahiro Yamada return !(isalnum(c) || c == '_' || c == '-');
569104daea1SMasahiro Yamada }
570104daea1SMasahiro Yamada
571104daea1SMasahiro Yamada /*
572104daea1SMasahiro Yamada * Expand variables in a token. The parsing stops when a token separater
573104daea1SMasahiro Yamada * (in most cases, it is a whitespace) is encountered. 'str' is updated to
574104daea1SMasahiro Yamada * point to the next character.
575104daea1SMasahiro Yamada *
576104daea1SMasahiro Yamada * The returned string must be freed when done.
577104daea1SMasahiro Yamada */
expand_one_token(const char ** str)578104daea1SMasahiro Yamada char *expand_one_token(const char **str)
579104daea1SMasahiro Yamada {
580e298f3b4SMasahiro Yamada return __expand_string(str, is_end_of_token, 0, NULL);
581104daea1SMasahiro Yamada }
582