preprocess.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  1. // SPDX-License-Identifier: GPL-2.0
  2. //
  3. // Copyright (C) 2018 Masahiro Yamada <yamada.masahiro@socionext.com>
  4. #include <stdarg.h>
  5. #include <stdbool.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include "list.h"
  10. #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
  11. static char *expand_string_with_args(const char *in, int argc, char *argv[]);
  12. static void __attribute__((noreturn)) pperror(const char *format, ...)
  13. {
  14. va_list ap;
  15. fprintf(stderr, "%s:%d: ", current_file->name, yylineno);
  16. va_start(ap, format);
  17. vfprintf(stderr, format, ap);
  18. va_end(ap);
  19. fprintf(stderr, "\n");
  20. exit(1);
  21. }
  22. /*
  23. * Environment variables
  24. */
  25. static LIST_HEAD(env_list);
  26. struct env {
  27. char *name;
  28. char *value;
  29. struct list_head node;
  30. };
  31. static void env_add(const char *name, const char *value)
  32. {
  33. struct env *e;
  34. e = xmalloc(sizeof(*e));
  35. e->name = xstrdup(name);
  36. e->value = xstrdup(value);
  37. list_add_tail(&e->node, &env_list);
  38. }
  39. static void env_del(struct env *e)
  40. {
  41. list_del(&e->node);
  42. free(e->name);
  43. free(e->value);
  44. free(e);
  45. }
  46. /* The returned pointer must be freed when done */
  47. static char *env_expand(const char *name)
  48. {
  49. struct env *e;
  50. const char *value;
  51. if (!*name)
  52. return NULL;
  53. list_for_each_entry(e, &env_list, node) {
  54. if (!strcmp(name, e->name))
  55. return xstrdup(e->value);
  56. }
  57. value = getenv(name);
  58. if (!value)
  59. return NULL;
  60. /*
  61. * We need to remember all referenced environment variables.
  62. * They will be written out to include/config/auto.conf.cmd
  63. */
  64. env_add(name, value);
  65. return xstrdup(value);
  66. }
  67. void env_write_dep(FILE *f, const char *autoconfig_name)
  68. {
  69. struct env *e, *tmp;
  70. list_for_each_entry_safe(e, tmp, &env_list, node) {
  71. fprintf(f, "ifneq \"$(%s)\" \"%s\"\n", e->name, e->value);
  72. fprintf(f, "%s: FORCE\n", autoconfig_name);
  73. fprintf(f, "endif\n");
  74. env_del(e);
  75. }
  76. }
  77. /*
  78. * Built-in functions
  79. */
  80. struct function {
  81. const char *name;
  82. unsigned int min_args;
  83. unsigned int max_args;
  84. char *(*func)(int argc, char *argv[]);
  85. };
  86. static char *do_shell(int argc, char *argv[])
  87. {
  88. FILE *p;
  89. char buf[256];
  90. char *cmd;
  91. size_t nread;
  92. int i;
  93. cmd = argv[0];
  94. p = popen(cmd, "r");
  95. if (!p) {
  96. perror(cmd);
  97. exit(1);
  98. }
  99. nread = fread(buf, 1, sizeof(buf), p);
  100. if (nread == sizeof(buf))
  101. nread--;
  102. /* remove trailing new lines */
  103. while (buf[nread - 1] == '\n')
  104. nread--;
  105. buf[nread] = 0;
  106. /* replace a new line with a space */
  107. for (i = 0; i < nread; i++) {
  108. if (buf[i] == '\n')
  109. buf[i] = ' ';
  110. }
  111. if (pclose(p) == -1) {
  112. perror(cmd);
  113. exit(1);
  114. }
  115. return xstrdup(buf);
  116. }
  117. static const struct function function_table[] = {
  118. /* Name MIN MAX Function */
  119. { "shell", 1, 1, do_shell },
  120. };
  121. #define FUNCTION_MAX_ARGS 16
  122. static char *function_expand(const char *name, int argc, char *argv[])
  123. {
  124. const struct function *f;
  125. int i;
  126. for (i = 0; i < ARRAY_SIZE(function_table); i++) {
  127. f = &function_table[i];
  128. if (strcmp(f->name, name))
  129. continue;
  130. if (argc < f->min_args)
  131. pperror("too few function arguments passed to '%s'",
  132. name);
  133. if (argc > f->max_args)
  134. pperror("too many function arguments passed to '%s'",
  135. name);
  136. return f->func(argc, argv);
  137. }
  138. return NULL;
  139. }
  140. /*
  141. * Evaluate a clause with arguments. argc/argv are arguments from the upper
  142. * function call.
  143. *
  144. * Returned string must be freed when done
  145. */
  146. static char *eval_clause(const char *str, size_t len, int argc, char *argv[])
  147. {
  148. char *tmp, *name, *res, *prev, *p;
  149. int new_argc = 0;
  150. char *new_argv[FUNCTION_MAX_ARGS];
  151. int nest = 0;
  152. int i;
  153. tmp = xstrndup(str, len);
  154. prev = p = tmp;
  155. /*
  156. * Split into tokens
  157. * The function name and arguments are separated by a comma.
  158. * For example, if the function call is like this:
  159. * $(foo,$(x),$(y))
  160. *
  161. * The input string for this helper should be:
  162. * foo,$(x),$(y)
  163. *
  164. * and split into:
  165. * new_argv[0] = 'foo'
  166. * new_argv[1] = '$(x)'
  167. * new_argv[2] = '$(y)'
  168. */
  169. while (*p) {
  170. if (nest == 0 && *p == ',') {
  171. *p = 0;
  172. if (new_argc >= FUNCTION_MAX_ARGS)
  173. pperror("too many function arguments");
  174. new_argv[new_argc++] = prev;
  175. prev = p + 1;
  176. } else if (*p == '(') {
  177. nest++;
  178. } else if (*p == ')') {
  179. nest--;
  180. }
  181. p++;
  182. }
  183. new_argv[new_argc++] = prev;
  184. /*
  185. * Shift arguments
  186. * new_argv[0] represents a function name or a variable name. Put it
  187. * into 'name', then shift the rest of the arguments. This simplifies
  188. * 'const' handling.
  189. */
  190. name = expand_string_with_args(new_argv[0], argc, argv);
  191. new_argc--;
  192. for (i = 0; i < new_argc; i++)
  193. new_argv[i] = expand_string_with_args(new_argv[i + 1],
  194. argc, argv);
  195. /* Look for built-in functions */
  196. res = function_expand(name, new_argc, new_argv);
  197. if (res)
  198. goto free;
  199. /* Last, try environment variable */
  200. if (new_argc == 0) {
  201. res = env_expand(name);
  202. if (res)
  203. goto free;
  204. }
  205. res = xstrdup("");
  206. free:
  207. for (i = 0; i < new_argc; i++)
  208. free(new_argv[i]);
  209. free(name);
  210. free(tmp);
  211. return res;
  212. }
  213. /*
  214. * Expand a string that follows '$'
  215. *
  216. * For example, if the input string is
  217. * ($(FOO)$($(BAR)))$(BAZ)
  218. * this helper evaluates
  219. * $($(FOO)$($(BAR)))
  220. * and returns a new string containing the expansion (note that the string is
  221. * recursively expanded), also advancing 'str' to point to the next character
  222. * after the corresponding closing parenthesis, in this case, *str will be
  223. * $(BAR)
  224. */
  225. static char *expand_dollar_with_args(const char **str, int argc, char *argv[])
  226. {
  227. const char *p = *str;
  228. const char *q;
  229. int nest = 0;
  230. /*
  231. * In Kconfig, variable/function references always start with "$(".
  232. * Neither single-letter variables as in $A nor curly braces as in ${CC}
  233. * are supported. '$' not followed by '(' loses its special meaning.
  234. */
  235. if (*p != '(') {
  236. *str = p;
  237. return xstrdup("$");
  238. }
  239. p++;
  240. q = p;
  241. while (*q) {
  242. if (*q == '(') {
  243. nest++;
  244. } else if (*q == ')') {
  245. if (nest-- == 0)
  246. break;
  247. }
  248. q++;
  249. }
  250. if (!*q)
  251. pperror("unterminated reference to '%s': missing ')'", p);
  252. /* Advance 'str' to after the expanded initial portion of the string */
  253. *str = q + 1;
  254. return eval_clause(p, q - p, argc, argv);
  255. }
  256. char *expand_dollar(const char **str)
  257. {
  258. return expand_dollar_with_args(str, 0, NULL);
  259. }
  260. static char *__expand_string(const char **str, bool (*is_end)(char c),
  261. int argc, char *argv[])
  262. {
  263. const char *in, *p;
  264. char *expansion, *out;
  265. size_t in_len, out_len;
  266. out = xmalloc(1);
  267. *out = 0;
  268. out_len = 1;
  269. p = in = *str;
  270. while (1) {
  271. if (*p == '$') {
  272. in_len = p - in;
  273. p++;
  274. expansion = expand_dollar_with_args(&p, argc, argv);
  275. out_len += in_len + strlen(expansion);
  276. out = xrealloc(out, out_len);
  277. strncat(out, in, in_len);
  278. strcat(out, expansion);
  279. free(expansion);
  280. in = p;
  281. continue;
  282. }
  283. if (is_end(*p))
  284. break;
  285. p++;
  286. }
  287. in_len = p - in;
  288. out_len += in_len;
  289. out = xrealloc(out, out_len);
  290. strncat(out, in, in_len);
  291. /* Advance 'str' to the end character */
  292. *str = p;
  293. return out;
  294. }
  295. static bool is_end_of_str(char c)
  296. {
  297. return !c;
  298. }
  299. /*
  300. * Expand variables and functions in the given string. Undefined variables
  301. * expand to an empty string.
  302. * The returned string must be freed when done.
  303. */
  304. static char *expand_string_with_args(const char *in, int argc, char *argv[])
  305. {
  306. return __expand_string(&in, is_end_of_str, argc, argv);
  307. }
  308. char *expand_string(const char *in)
  309. {
  310. return expand_string_with_args(in, 0, NULL);
  311. }
  312. static bool is_end_of_token(char c)
  313. {
  314. /* Why are '.' and '/' valid characters for symbols? */
  315. return !(isalnum(c) || c == '_' || c == '-' || c == '.' || c == '/');
  316. }
  317. /*
  318. * Expand variables in a token. The parsing stops when a token separater
  319. * (in most cases, it is a whitespace) is encountered. 'str' is updated to
  320. * point to the next character.
  321. *
  322. * The returned string must be freed when done.
  323. */
  324. char *expand_one_token(const char **str)
  325. {
  326. return __expand_string(str, is_end_of_token, 0, NULL);
  327. }