1
0

preprocess.c 11 KB

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