summaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'scripts')
-rw-r--r--scripts/kconfig/confdata.c33
-rw-r--r--scripts/kconfig/kconf_id.c1
-rw-r--r--scripts/kconfig/lkc.h5
-rw-r--r--scripts/kconfig/lkc_proto.h6
-rw-r--r--scripts/kconfig/menu.c3
-rw-r--r--scripts/kconfig/preprocess.c238
-rw-r--r--scripts/kconfig/symbol.c56
-rw-r--r--scripts/kconfig/util.c29
-rw-r--r--scripts/kconfig/zconf.l67
-rw-r--r--scripts/kconfig/zconf.y2
10 files changed, 326 insertions, 114 deletions
diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c
index 569217168e96..5f87ad561b08 100644
--- a/scripts/kconfig/confdata.c
+++ b/scripts/kconfig/confdata.c
@@ -30,7 +30,7 @@ static void conf_message(const char *fmt, ...)
30static const char *conf_filename; 30static const char *conf_filename;
31static int conf_lineno, conf_warnings; 31static int conf_lineno, conf_warnings;
32 32
33const char conf_defname[] = "arch/$ARCH/defconfig"; 33const char conf_defname[] = "arch/$(ARCH)/defconfig";
34 34
35static void conf_warning(const char *fmt, ...) 35static void conf_warning(const char *fmt, ...)
36{ 36{
@@ -81,39 +81,13 @@ const char *conf_get_autoconfig_name(void)
81 return name ? name : "include/config/auto.conf"; 81 return name ? name : "include/config/auto.conf";
82} 82}
83 83
84static char *conf_expand_value(const char *in)
85{
86 struct symbol *sym;
87 const char *src;
88 static char res_value[SYMBOL_MAXLENGTH];
89 char *dst, name[SYMBOL_MAXLENGTH];
90
91 res_value[0] = 0;
92 dst = name;
93 while ((src = strchr(in, '$'))) {
94 strncat(res_value, in, src - in);
95 src++;
96 dst = name;
97 while (isalnum(*src) || *src == '_')
98 *dst++ = *src++;
99 *dst = 0;
100 sym = sym_lookup(name, 0);
101 sym_calc_value(sym);
102 strcat(res_value, sym_get_string_value(sym));
103 in = src;
104 }
105 strcat(res_value, in);
106
107 return res_value;
108}
109
110char *conf_get_default_confname(void) 84char *conf_get_default_confname(void)
111{ 85{
112 struct stat buf; 86 struct stat buf;
113 static char fullname[PATH_MAX+1]; 87 static char fullname[PATH_MAX+1];
114 char *env, *name; 88 char *env, *name;
115 89
116 name = conf_expand_value(conf_defname); 90 name = expand_string(conf_defname);
117 env = getenv(SRCTREE); 91 env = getenv(SRCTREE);
118 if (env) { 92 if (env) {
119 sprintf(fullname, "%s/%s", env, name); 93 sprintf(fullname, "%s/%s", env, name);
@@ -274,7 +248,8 @@ int conf_read_simple(const char *name, int def)
274 if (expr_calc_value(prop->visible.expr) == no || 248 if (expr_calc_value(prop->visible.expr) == no ||
275 prop->expr->type != E_SYMBOL) 249 prop->expr->type != E_SYMBOL)
276 continue; 250 continue;
277 name = conf_expand_value(prop->expr->left.sym->name); 251 sym_calc_value(prop->expr->left.sym);
252 name = sym_get_string_value(prop->expr->left.sym);
278 in = zconf_fopen(name); 253 in = zconf_fopen(name);
279 if (in) { 254 if (in) {
280 conf_message("using defaults found in %s", 255 conf_message("using defaults found in %s",
diff --git a/scripts/kconfig/kconf_id.c b/scripts/kconfig/kconf_id.c
index 3ea9c5f9f730..b3e0ea0ac732 100644
--- a/scripts/kconfig/kconf_id.c
+++ b/scripts/kconfig/kconf_id.c
@@ -32,7 +32,6 @@ static struct kconf_id kconf_id_array[] = {
32 { "on", T_ON, TF_PARAM }, 32 { "on", T_ON, TF_PARAM },
33 { "modules", T_OPT_MODULES, TF_OPTION }, 33 { "modules", T_OPT_MODULES, TF_OPTION },
34 { "defconfig_list", T_OPT_DEFCONFIG_LIST, TF_OPTION }, 34 { "defconfig_list", T_OPT_DEFCONFIG_LIST, TF_OPTION },
35 { "env", T_OPT_ENV, TF_OPTION },
36 { "allnoconfig_y", T_OPT_ALLNOCONFIG_Y, TF_OPTION }, 35 { "allnoconfig_y", T_OPT_ALLNOCONFIG_Y, TF_OPTION },
37}; 36};
38 37
diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h
index 2628bc6a2141..ed3ff88e60ba 100644
--- a/scripts/kconfig/lkc.h
+++ b/scripts/kconfig/lkc.h
@@ -44,7 +44,6 @@ enum conf_def_mode {
44 44
45#define T_OPT_MODULES 1 45#define T_OPT_MODULES 1
46#define T_OPT_DEFCONFIG_LIST 2 46#define T_OPT_DEFCONFIG_LIST 2
47#define T_OPT_ENV 3
48#define T_OPT_ALLNOCONFIG_Y 4 47#define T_OPT_ALLNOCONFIG_Y 4
49 48
50struct kconf_id { 49struct kconf_id {
@@ -103,6 +102,7 @@ void *xmalloc(size_t size);
103void *xcalloc(size_t nmemb, size_t size); 102void *xcalloc(size_t nmemb, size_t size);
104void *xrealloc(void *p, size_t size); 103void *xrealloc(void *p, size_t size);
105char *xstrdup(const char *s); 104char *xstrdup(const char *s);
105char *xstrndup(const char *s, size_t n);
106 106
107struct gstr { 107struct gstr {
108 size_t len; 108 size_t len;
@@ -120,9 +120,6 @@ void str_printf(struct gstr *gs, const char *fmt, ...);
120const char *str_get(struct gstr *gs); 120const char *str_get(struct gstr *gs);
121 121
122/* symbol.c */ 122/* symbol.c */
123extern struct expr *sym_env_list;
124
125void sym_init(void);
126void sym_clear_all_valid(void); 123void sym_clear_all_valid(void);
127struct symbol *sym_choice_default(struct symbol *sym); 124struct symbol *sym_choice_default(struct symbol *sym);
128const char *sym_get_string_default(struct symbol *sym); 125const char *sym_get_string_default(struct symbol *sym);
diff --git a/scripts/kconfig/lkc_proto.h b/scripts/kconfig/lkc_proto.h
index 9dc8abfb1dc3..9f465fe1ca85 100644
--- a/scripts/kconfig/lkc_proto.h
+++ b/scripts/kconfig/lkc_proto.h
@@ -49,5 +49,11 @@ const char * sym_get_string_value(struct symbol *sym);
49 49
50const char * prop_get_type_name(enum prop_type type); 50const char * prop_get_type_name(enum prop_type type);
51 51
52/* preprocess.c */
53void env_write_dep(FILE *f, const char *auto_conf_name);
54char *expand_string(const char *in);
55char *expand_dollar(const char **str);
56char *expand_one_token(const char **str);
57
52/* expr.c */ 58/* expr.c */
53void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken); 59void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken);
diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c
index 068a4e4db20a..379a119dcd1e 100644
--- a/scripts/kconfig/menu.c
+++ b/scripts/kconfig/menu.c
@@ -214,9 +214,6 @@ void menu_add_option(int token, char *arg)
214 zconf_error("trying to redefine defconfig symbol"); 214 zconf_error("trying to redefine defconfig symbol");
215 sym_defconfig_list->flags |= SYMBOL_AUTO; 215 sym_defconfig_list->flags |= SYMBOL_AUTO;
216 break; 216 break;
217 case T_OPT_ENV:
218 prop_add_env(arg);
219 break;
220 case T_OPT_ALLNOCONFIG_Y: 217 case T_OPT_ALLNOCONFIG_Y:
221 current_entry->sym->flags |= SYMBOL_ALLNOCONFIG_Y; 218 current_entry->sym->flags |= SYMBOL_ALLNOCONFIG_Y;
222 break; 219 break;
diff --git a/scripts/kconfig/preprocess.c b/scripts/kconfig/preprocess.c
new file mode 100644
index 000000000000..a2eb2eb02929
--- /dev/null
+++ b/scripts/kconfig/preprocess.c
@@ -0,0 +1,238 @@
1// SPDX-License-Identifier: GPL-2.0
2//
3// Copyright (C) 2018 Masahiro Yamada <yamada.masahiro@socionext.com>
4
5#include <stdarg.h>
6#include <stdbool.h>
7#include <stdio.h>
8#include <stdlib.h>
9#include <string.h>
10
11#include "list.h"
12
13static void __attribute__((noreturn)) pperror(const char *format, ...)
14{
15 va_list ap;
16
17 fprintf(stderr, "%s:%d: ", current_file->name, yylineno);
18 va_start(ap, format);
19 vfprintf(stderr, format, ap);
20 va_end(ap);
21 fprintf(stderr, "\n");
22
23 exit(1);
24}
25
26/*
27 * Environment variables
28 */
29static LIST_HEAD(env_list);
30
31struct env {
32 char *name;
33 char *value;
34 struct list_head node;
35};
36
37static void env_add(const char *name, const char *value)
38{
39 struct env *e;
40
41 e = xmalloc(sizeof(*e));
42 e->name = xstrdup(name);
43 e->value = xstrdup(value);
44
45 list_add_tail(&e->node, &env_list);
46}
47
48static void env_del(struct env *e)
49{
50 list_del(&e->node);
51 free(e->name);
52 free(e->value);
53 free(e);
54}
55
56/* The returned pointer must be freed when done */
57static char *env_expand(const char *name)
58{
59 struct env *e;
60 const char *value;
61
62 if (!*name)
63 return NULL;
64
65 list_for_each_entry(e, &env_list, node) {
66 if (!strcmp(name, e->name))
67 return xstrdup(e->value);
68 }
69
70 value = getenv(name);
71 if (!value)
72 return NULL;
73
74 /*
75 * We need to remember all referenced environment variables.
76 * They will be written out to include/config/auto.conf.cmd
77 */
78 env_add(name, value);
79
80 return xstrdup(value);
81}
82
83void env_write_dep(FILE *f, const char *autoconfig_name)
84{
85 struct env *e, *tmp;
86
87 list_for_each_entry_safe(e, tmp, &env_list, node) {
88 fprintf(f, "ifneq \"$(%s)\" \"%s\"\n", e->name, e->value);
89 fprintf(f, "%s: FORCE\n", autoconfig_name);
90 fprintf(f, "endif\n");
91 env_del(e);
92 }
93}
94
95static char *eval_clause(const char *str, size_t len)
96{
97 char *tmp, *name, *res;
98
99 tmp = xstrndup(str, len);
100
101 name = expand_string(tmp);
102
103 res = env_expand(name);
104 if (res)
105 goto free;
106
107 res = xstrdup("");
108free:
109 free(name);
110 free(tmp);
111
112 return res;
113}
114
115/*
116 * Expand a string that follows '$'
117 *
118 * For example, if the input string is
119 * ($(FOO)$($(BAR)))$(BAZ)
120 * this helper evaluates
121 * $($(FOO)$($(BAR)))
122 * and returns a new string containing the expansion (note that the string is
123 * recursively expanded), also advancing 'str' to point to the next character
124 * after the corresponding closing parenthesis, in this case, *str will be
125 * $(BAR)
126 */
127char *expand_dollar(const char **str)
128{
129 const char *p = *str;
130 const char *q;
131 int nest = 0;
132
133 /*
134 * In Kconfig, variable references always start with "$(".
135 * Neither single-letter variables as in $A nor curly braces as in ${CC}
136 * are supported. '$' not followed by '(' loses its special meaning.
137 */
138 if (*p != '(') {
139 *str = p;
140 return xstrdup("$");
141 }
142
143 p++;
144 q = p;
145 while (*q) {
146 if (*q == '(') {
147 nest++;
148 } else if (*q == ')') {
149 if (nest-- == 0)
150 break;
151 }
152 q++;
153 }
154
155 if (!*q)
156 pperror("unterminated reference to '%s': missing ')'", p);
157
158 /* Advance 'str' to after the expanded initial portion of the string */
159 *str = q + 1;
160
161 return eval_clause(p, q - p);
162}
163
164static char *__expand_string(const char **str, bool (*is_end)(char c))
165{
166 const char *in, *p;
167 char *expansion, *out;
168 size_t in_len, out_len;
169
170 out = xmalloc(1);
171 *out = 0;
172 out_len = 1;
173
174 p = in = *str;
175
176 while (1) {
177 if (*p == '$') {
178 in_len = p - in;
179 p++;
180 expansion = expand_dollar(&p);
181 out_len += in_len + strlen(expansion);
182 out = xrealloc(out, out_len);
183 strncat(out, in, in_len);
184 strcat(out, expansion);
185 free(expansion);
186 in = p;
187 continue;
188 }
189
190 if (is_end(*p))
191 break;
192
193 p++;
194 }
195
196 in_len = p - in;
197 out_len += in_len;
198 out = xrealloc(out, out_len);
199 strncat(out, in, in_len);
200
201 /* Advance 'str' to the end character */
202 *str = p;
203
204 return out;
205}
206
207static bool is_end_of_str(char c)
208{
209 return !c;
210}
211
212/*
213 * Expand variables in the given string. Undefined variables
214 * expand to an empty string.
215 * The returned string must be freed when done.
216 */
217char *expand_string(const char *in)
218{
219 return __expand_string(&in, is_end_of_str);
220}
221
222static bool is_end_of_token(char c)
223{
224 /* Why are '.' and '/' valid characters for symbols? */
225 return !(isalnum(c) || c == '_' || c == '-' || c == '.' || c == '/');
226}
227
228/*
229 * Expand variables in a token. The parsing stops when a token separater
230 * (in most cases, it is a whitespace) is encountered. 'str' is updated to
231 * point to the next character.
232 *
233 * The returned string must be freed when done.
234 */
235char *expand_one_token(const char **str)
236{
237 return __expand_string(str, is_end_of_token);
238}
diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c
index f0b2e3b3102d..2460648a581a 100644
--- a/scripts/kconfig/symbol.c
+++ b/scripts/kconfig/symbol.c
@@ -33,33 +33,6 @@ struct symbol *sym_defconfig_list;
33struct symbol *modules_sym; 33struct symbol *modules_sym;
34tristate modules_val; 34tristate modules_val;
35 35
36struct expr *sym_env_list;
37
38static void sym_add_default(struct symbol *sym, const char *def)
39{
40 struct property *prop = prop_alloc(P_DEFAULT, sym);
41
42 prop->expr = expr_alloc_symbol(sym_lookup(def, SYMBOL_CONST));
43}
44
45void sym_init(void)
46{
47 struct symbol *sym;
48 struct utsname uts;
49 static bool inited = false;
50
51 if (inited)
52 return;
53 inited = true;
54
55 uname(&uts);
56
57 sym = sym_lookup("UNAME_RELEASE", 0);
58 sym->type = S_STRING;
59 sym->flags |= SYMBOL_AUTO;
60 sym_add_default(sym, uts.release);
61}
62
63enum symbol_type sym_get_type(struct symbol *sym) 36enum symbol_type sym_get_type(struct symbol *sym)
64{ 37{
65 enum symbol_type type = sym->type; 38 enum symbol_type type = sym->type;
@@ -1401,32 +1374,3 @@ const char *prop_get_type_name(enum prop_type type)
1401 } 1374 }
1402 return "unknown"; 1375 return "unknown";
1403} 1376}
1404
1405static void prop_add_env(const char *env)
1406{
1407 struct symbol *sym, *sym2;
1408 struct property *prop;
1409 char *p;
1410
1411 sym = current_entry->sym;
1412 sym->flags |= SYMBOL_AUTO;
1413 for_all_properties(sym, prop, P_ENV) {
1414 sym2 = prop_get_symbol(prop);
1415 if (strcmp(sym2->name, env))
1416 menu_warn(current_entry, "redefining environment symbol from %s",
1417 sym2->name);
1418 return;
1419 }
1420
1421 prop = prop_alloc(P_ENV, sym);
1422 prop->expr = expr_alloc_symbol(sym_lookup(env, SYMBOL_CONST));
1423
1424 sym_env_list = expr_alloc_one(E_LIST, sym_env_list);
1425 sym_env_list->right.sym = sym;
1426
1427 p = getenv(env);
1428 if (p)
1429 sym_add_default(sym, p);
1430 else
1431 menu_warn(current_entry, "environment variable %s undefined", env);
1432}
diff --git a/scripts/kconfig/util.c b/scripts/kconfig/util.c
index c6f6e21b809f..703ee4904613 100644
--- a/scripts/kconfig/util.c
+++ b/scripts/kconfig/util.c
@@ -34,8 +34,6 @@ struct file *file_lookup(const char *name)
34/* write a dependency file as used by kbuild to track dependencies */ 34/* write a dependency file as used by kbuild to track dependencies */
35int file_write_dep(const char *name) 35int file_write_dep(const char *name)
36{ 36{
37 struct symbol *sym, *env_sym;
38 struct expr *e;
39 struct file *file; 37 struct file *file;
40 FILE *out; 38 FILE *out;
41 39
@@ -54,21 +52,7 @@ int file_write_dep(const char *name)
54 fprintf(out, "\n%s: \\\n" 52 fprintf(out, "\n%s: \\\n"
55 "\t$(deps_config)\n\n", conf_get_autoconfig_name()); 53 "\t$(deps_config)\n\n", conf_get_autoconfig_name());
56 54
57 expr_list_for_each_sym(sym_env_list, e, sym) { 55 env_write_dep(out, conf_get_autoconfig_name());
58 struct property *prop;
59 const char *value;
60
61 prop = sym_get_env_prop(sym);
62 env_sym = prop_get_symbol(prop);
63 if (!env_sym)
64 continue;
65 value = getenv(env_sym->name);
66 if (!value)
67 value = "";
68 fprintf(out, "ifneq \"$(%s)\" \"%s\"\n", env_sym->name, value);
69 fprintf(out, "%s: FORCE\n", conf_get_autoconfig_name());
70 fprintf(out, "endif\n");
71 }
72 56
73 fprintf(out, "\n$(deps_config): ;\n"); 57 fprintf(out, "\n$(deps_config): ;\n");
74 fclose(out); 58 fclose(out);
@@ -165,3 +149,14 @@ char *xstrdup(const char *s)
165 fprintf(stderr, "Out of memory.\n"); 149 fprintf(stderr, "Out of memory.\n");
166 exit(1); 150 exit(1);
167} 151}
152
153char *xstrndup(const char *s, size_t n)
154{
155 char *p;
156
157 p = strndup(s, n);
158 if (p)
159 return p;
160 fprintf(stderr, "Out of memory.\n");
161 exit(1);
162}
diff --git a/scripts/kconfig/zconf.l b/scripts/kconfig/zconf.l
index 045093d827e1..b3855909913c 100644
--- a/scripts/kconfig/zconf.l
+++ b/scripts/kconfig/zconf.l
@@ -1,6 +1,5 @@
1%option nostdinit noyywrap never-interactive full ecs 1%option nostdinit noyywrap never-interactive full ecs
2%option 8bit nodefault yylineno 2%option 8bit nodefault yylineno
3%option noinput
4%x COMMAND HELP STRING PARAM 3%x COMMAND HELP STRING PARAM
5%{ 4%{
6/* 5/*
@@ -35,6 +34,8 @@ struct buffer *current_buf;
35 34
36static int last_ts, first_ts; 35static int last_ts, first_ts;
37 36
37static char *expand_token(const char *in, size_t n);
38static void append_expanded_string(const char *in);
38static void zconf_endhelp(void); 39static void zconf_endhelp(void);
39static void zconf_endfile(void); 40static void zconf_endfile(void);
40 41
@@ -147,6 +148,13 @@ n [A-Za-z0-9_-]
147 yylval.string = text; 148 yylval.string = text;
148 return T_WORD; 149 return T_WORD;
149 } 150 }
151 ({n}|[/.$])+ {
152 /* this token includes at least one '$' */
153 yylval.string = expand_token(yytext, yyleng);
154 if (strlen(yylval.string))
155 return T_WORD;
156 free(yylval.string);
157 }
150 #.* /* comment */ 158 #.* /* comment */
151 \\\n ; 159 \\\n ;
152 [[:blank:]]+ 160 [[:blank:]]+
@@ -157,12 +165,13 @@ n [A-Za-z0-9_-]
157} 165}
158 166
159<STRING>{ 167<STRING>{
160 [^'"\\\n]+/\n { 168 "$".* append_expanded_string(yytext);
169 [^$'"\\\n]+/\n {
161 append_string(yytext, yyleng); 170 append_string(yytext, yyleng);
162 yylval.string = text; 171 yylval.string = text;
163 return T_WORD_QUOTE; 172 return T_WORD_QUOTE;
164 } 173 }
165 [^'"\\\n]+ { 174 [^$'"\\\n]+ {
166 append_string(yytext, yyleng); 175 append_string(yytext, yyleng);
167 } 176 }
168 \\.?/\n { 177 \\.?/\n {
@@ -249,6 +258,58 @@ n [A-Za-z0-9_-]
249} 258}
250 259
251%% 260%%
261static char *expand_token(const char *in, size_t n)
262{
263 char *out;
264 int c;
265 char c2;
266 const char *rest, *end;
267
268 new_string();
269 append_string(in, n);
270
271 /* get the whole line because we do not know the end of token. */
272 while ((c = input()) != EOF) {
273 if (c == '\n') {
274 unput(c);
275 break;
276 }
277 c2 = c;
278 append_string(&c2, 1);
279 }
280
281 rest = text;
282 out = expand_one_token(&rest);
283
284 /* push back unused characters to the input stream */
285 end = rest + strlen(rest);
286 while (end > rest)
287 unput(*--end);
288
289 free(text);
290
291 return out;
292}
293
294static void append_expanded_string(const char *str)
295{
296 const char *end;
297 char *res;
298
299 str++;
300
301 res = expand_dollar(&str);
302
303 /* push back unused characters to the input stream */
304 end = str + strlen(str);
305 while (end > str)
306 unput(*--end);
307
308 append_string(res, strlen(res));
309
310 free(res);
311}
312
252void zconf_starthelp(void) 313void zconf_starthelp(void)
253{ 314{
254 new_string(); 315 new_string();
diff --git a/scripts/kconfig/zconf.y b/scripts/kconfig/zconf.y
index 8bfaaf853d23..031b2e24ae00 100644
--- a/scripts/kconfig/zconf.y
+++ b/scripts/kconfig/zconf.y
@@ -534,7 +534,6 @@ void conf_parse(const char *name)
534 534
535 zconf_initscan(name); 535 zconf_initscan(name);
536 536
537 sym_init();
538 _menu_init(); 537 _menu_init();
539 538
540 if (getenv("ZCONF_DEBUG")) 539 if (getenv("ZCONF_DEBUG"))
@@ -780,3 +779,4 @@ void zconfdump(FILE *out)
780#include "expr.c" 779#include "expr.c"
781#include "symbol.c" 780#include "symbol.c"
782#include "menu.c" 781#include "menu.c"
782#include "preprocess.c"