1 // SPDX-License-Identifier: GPL-2.0
3 // Copyright (C) 2018 Masahiro Yamada <yamada.masahiro@socionext.com>
13 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
15 static char *expand_string_with_args(const char *in
, int argc
, char *argv
[]);
17 static void __attribute__((noreturn
)) pperror(const char *format
, ...)
21 fprintf(stderr
, "%s:%d: ", current_file
->name
, yylineno
);
23 vfprintf(stderr
, format
, ap
);
25 fprintf(stderr
, "\n");
31 * Environment variables
33 static LIST_HEAD(env_list
);
38 struct list_head node
;
41 static void env_add(const char *name
, const char *value
)
45 e
= xmalloc(sizeof(*e
));
46 e
->name
= xstrdup(name
);
47 e
->value
= xstrdup(value
);
49 list_add_tail(&e
->node
, &env_list
);
52 static void env_del(struct env
*e
)
60 /* The returned pointer must be freed when done */
61 static char *env_expand(const char *name
)
69 list_for_each_entry(e
, &env_list
, node
) {
70 if (!strcmp(name
, e
->name
))
71 return xstrdup(e
->value
);
79 * We need to remember all referenced environment variables.
80 * They will be written out to include/config/auto.conf.cmd
84 return xstrdup(value
);
87 void env_write_dep(FILE *f
, const char *autoconfig_name
)
91 list_for_each_entry_safe(e
, tmp
, &env_list
, node
) {
92 fprintf(f
, "ifneq \"$(%s)\" \"%s\"\n", e
->name
, e
->value
);
93 fprintf(f
, "%s: FORCE\n", autoconfig_name
);
94 fprintf(f
, "endif\n");
104 unsigned int min_args
;
105 unsigned int max_args
;
106 char *(*func
)(int argc
, char *argv
[]);
109 static char *do_error_if(int argc
, char *argv
[])
111 if (!strcmp(argv
[0], "y"))
112 pperror("%s", argv
[1]);
117 static char *do_filename(int argc
, char *argv
[])
119 return xstrdup(current_file
->name
);
122 static char *do_info(int argc
, char *argv
[])
124 printf("%s\n", argv
[0]);
129 static char *do_lineno(int argc
, char *argv
[])
133 sprintf(buf
, "%d", yylineno
);
138 static char *do_shell(int argc
, char *argv
[])
154 nread
= fread(buf
, 1, sizeof(buf
), p
);
155 if (nread
== sizeof(buf
))
158 /* remove trailing new lines */
159 while (nread
> 0 && buf
[nread
- 1] == '\n')
164 /* replace a new line with a space */
165 for (i
= 0; i
< nread
; i
++) {
170 if (pclose(p
) == -1) {
178 static char *do_warning_if(int argc
, char *argv
[])
180 if (!strcmp(argv
[0], "y"))
181 fprintf(stderr
, "%s:%d: %s\n",
182 current_file
->name
, yylineno
, argv
[1]);
187 static const struct function function_table
[] = {
188 /* Name MIN MAX Function */
189 { "error-if", 2, 2, do_error_if
},
190 { "filename", 0, 0, do_filename
},
191 { "info", 1, 1, do_info
},
192 { "lineno", 0, 0, do_lineno
},
193 { "shell", 1, 1, do_shell
},
194 { "warning-if", 2, 2, do_warning_if
},
197 #define FUNCTION_MAX_ARGS 16
199 static char *function_expand(const char *name
, int argc
, char *argv
[])
201 const struct function
*f
;
204 for (i
= 0; i
< ARRAY_SIZE(function_table
); i
++) {
205 f
= &function_table
[i
];
206 if (strcmp(f
->name
, name
))
209 if (argc
< f
->min_args
)
210 pperror("too few function arguments passed to '%s'",
213 if (argc
> f
->max_args
)
214 pperror("too many function arguments passed to '%s'",
217 return f
->func(argc
, argv
);
224 * Variables (and user-defined functions)
226 static LIST_HEAD(variable_list
);
231 enum variable_flavor flavor
;
233 struct list_head node
;
236 static struct variable
*variable_lookup(const char *name
)
240 list_for_each_entry(v
, &variable_list
, node
) {
241 if (!strcmp(name
, v
->name
))
248 static char *variable_expand(const char *name
, int argc
, char *argv
[])
253 v
= variable_lookup(name
);
257 if (argc
== 0 && v
->exp_count
)
258 pperror("Recursive variable '%s' references itself (eventually)",
261 if (v
->exp_count
> 1000)
262 pperror("Too deep recursive expansion");
266 if (v
->flavor
== VAR_RECURSIVE
)
267 res
= expand_string_with_args(v
->value
, argc
, argv
);
269 res
= xstrdup(v
->value
);
276 void variable_add(const char *name
, const char *value
,
277 enum variable_flavor flavor
)
283 v
= variable_lookup(name
);
285 /* For defined variables, += inherits the existing flavor */
286 if (flavor
== VAR_APPEND
) {
293 /* For undefined variables, += assumes the recursive flavor */
294 if (flavor
== VAR_APPEND
)
295 flavor
= VAR_RECURSIVE
;
297 v
= xmalloc(sizeof(*v
));
298 v
->name
= xstrdup(name
);
300 list_add_tail(&v
->node
, &variable_list
);
305 if (flavor
== VAR_SIMPLE
)
306 new_value
= expand_string(value
);
308 new_value
= xstrdup(value
);
311 v
->value
= xrealloc(v
->value
,
312 strlen(v
->value
) + strlen(new_value
) + 2);
313 strcat(v
->value
, " ");
314 strcat(v
->value
, new_value
);
317 v
->value
= new_value
;
321 static void variable_del(struct variable
*v
)
329 void variable_all_del(void)
331 struct variable
*v
, *tmp
;
333 list_for_each_entry_safe(v
, tmp
, &variable_list
, node
)
338 * Evaluate a clause with arguments. argc/argv are arguments from the upper
341 * Returned string must be freed when done
343 static char *eval_clause(const char *str
, size_t len
, int argc
, char *argv
[])
345 char *tmp
, *name
, *res
, *endptr
, *prev
, *p
;
347 char *new_argv
[FUNCTION_MAX_ARGS
];
352 tmp
= xstrndup(str
, len
);
355 * If variable name is '1', '2', etc. It is generally an argument
356 * from a user-function call (i.e. local-scope variable). If not
357 * available, then look-up global-scope variables.
359 n
= strtoul(tmp
, &endptr
, 10);
360 if (!*endptr
&& n
> 0 && n
<= argc
) {
361 res
= xstrdup(argv
[n
- 1]);
369 * The function name and arguments are separated by a comma.
370 * For example, if the function call is like this:
373 * The input string for this helper should be:
377 * new_argv[0] = 'foo'
378 * new_argv[1] = '$(x)'
379 * new_argv[2] = '$(y)'
382 if (nest
== 0 && *p
== ',') {
384 if (new_argc
>= FUNCTION_MAX_ARGS
)
385 pperror("too many function arguments");
386 new_argv
[new_argc
++] = prev
;
388 } else if (*p
== '(') {
390 } else if (*p
== ')') {
396 new_argv
[new_argc
++] = prev
;
400 * new_argv[0] represents a function name or a variable name. Put it
401 * into 'name', then shift the rest of the arguments. This simplifies
404 name
= expand_string_with_args(new_argv
[0], argc
, argv
);
406 for (i
= 0; i
< new_argc
; i
++)
407 new_argv
[i
] = expand_string_with_args(new_argv
[i
+ 1],
410 /* Search for variables */
411 res
= variable_expand(name
, new_argc
, new_argv
);
415 /* Look for built-in functions */
416 res
= function_expand(name
, new_argc
, new_argv
);
420 /* Last, try environment variable */
422 res
= env_expand(name
);
429 for (i
= 0; i
< new_argc
; i
++)
439 * Expand a string that follows '$'
441 * For example, if the input string is
442 * ($(FOO)$($(BAR)))$(BAZ)
443 * this helper evaluates
445 * and returns a new string containing the expansion (note that the string is
446 * recursively expanded), also advancing 'str' to point to the next character
447 * after the corresponding closing parenthesis, in this case, *str will be
450 static char *expand_dollar_with_args(const char **str
, int argc
, char *argv
[])
452 const char *p
= *str
;
457 * In Kconfig, variable/function references always start with "$(".
458 * Neither single-letter variables as in $A nor curly braces as in ${CC}
459 * are supported. '$' not followed by '(' loses its special meaning.
471 } else if (*q
== ')') {
479 pperror("unterminated reference to '%s': missing ')'", p
);
481 /* Advance 'str' to after the expanded initial portion of the string */
484 return eval_clause(p
, q
- p
, argc
, argv
);
487 char *expand_dollar(const char **str
)
489 return expand_dollar_with_args(str
, 0, NULL
);
492 static char *__expand_string(const char **str
, bool (*is_end
)(char c
),
493 int argc
, char *argv
[])
496 char *expansion
, *out
;
497 size_t in_len
, out_len
;
509 expansion
= expand_dollar_with_args(&p
, argc
, argv
);
510 out_len
+= in_len
+ strlen(expansion
);
511 out
= xrealloc(out
, out_len
);
512 strncat(out
, in
, in_len
);
513 strcat(out
, expansion
);
527 out
= xrealloc(out
, out_len
);
528 strncat(out
, in
, in_len
);
530 /* Advance 'str' to the end character */
536 static bool is_end_of_str(char c
)
542 * Expand variables and functions in the given string. Undefined variables
543 * expand to an empty string.
544 * The returned string must be freed when done.
546 static char *expand_string_with_args(const char *in
, int argc
, char *argv
[])
548 return __expand_string(&in
, is_end_of_str
, argc
, argv
);
551 char *expand_string(const char *in
)
553 return expand_string_with_args(in
, 0, NULL
);
556 static bool is_end_of_token(char c
)
558 /* Why are '.' and '/' valid characters for symbols? */
559 return !(isalnum(c
) || c
== '_' || c
== '-' || c
== '.' || c
== '/');
563 * Expand variables in a token. The parsing stops when a token separater
564 * (in most cases, it is a whitespace) is encountered. 'str' is updated to
565 * point to the next character.
567 * The returned string must be freed when done.
569 char *expand_one_token(const char **str
)
571 return __expand_string(str
, is_end_of_token
, 0, NULL
);