summaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
authorMasahiro Yamada <yamada.masahiro@socionext.com>2018-05-28 05:21:40 -0400
committerMasahiro Yamada <yamada.masahiro@socionext.com>2018-05-28 14:28:58 -0400
commit104daea149c45cc84842ce77a9bd6436d19f3dd8 (patch)
tree7f0aaa24e9fa03154a74b2bd7bcb93f24d678ea4 /scripts
parentf1089c92da791034af73478159626007cba7f092 (diff)
kconfig: reference environment variables directly and remove 'option env='
To get access to environment variables, Kconfig needs to define a symbol using "option env=" syntax. It is tedious to add a symbol entry for each environment variable given that we need to define much more such as 'CC', 'AS', 'srctree' etc. to evaluate the compiler capability in Kconfig. Adding '$' for symbol references is grammatically inconsistent. Looking at the code, the symbols prefixed with 'S' are expanded by: - conf_expand_value() This is used to expand 'arch/$ARCH/defconfig' and 'defconfig_list' - sym_expand_string_value() This is used to expand strings in 'source' and 'mainmenu' All of them are fixed values independent of user configuration. So, they can be changed into the direct expansion instead of symbols. This change makes the code much cleaner. The bounce symbols 'SRCARCH', 'ARCH', 'SUBARCH', 'KERNELVERSION' are gone. sym_init() hard-coding 'UNAME_RELEASE' is also gone. 'UNAME_RELEASE' should be replaced with an environment variable. ARCH_DEFCONFIG is a normal symbol, so it should be simply referenced without '$' prefix. The new syntax is addicted by Make. The variable reference needs parentheses, like $(FOO), but you can omit them for single-letter variables, like $F. Yet, in Makefiles, people tend to use the parenthetical form for consistency / clarification. At this moment, only the environment variable is supported, but I will extend the concept of 'variable' later on. The variables are expanded in the lexer so we can simplify the token handling on the parser side. For example, the following code works. [Example code] config MY_TOOLCHAIN_LIST string default "My tools: CC=$(CC), AS=$(AS), CPP=$(CPP)" [Result] $ make -s alldefconfig && tail -n 1 .config CONFIG_MY_TOOLCHAIN_LIST="My tools: CC=gcc, AS=as, CPP=gcc -E" Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com> Reviewed-by: Kees Cook <keescook@chromium.org>
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"