diff options
Diffstat (limited to 'scripts/kconfig/confdata.c')
-rw-r--r-- | scripts/kconfig/confdata.c | 112 |
1 files changed, 91 insertions, 21 deletions
diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c index 02f670cc6bb9..ccd45130c482 100644 --- a/scripts/kconfig/confdata.c +++ b/scripts/kconfig/confdata.c | |||
@@ -14,6 +14,12 @@ | |||
14 | #define LKC_DIRECT_LINK | 14 | #define LKC_DIRECT_LINK |
15 | #include "lkc.h" | 15 | #include "lkc.h" |
16 | 16 | ||
17 | static void conf_warning(const char *fmt, ...) | ||
18 | __attribute__ ((format (printf, 1, 2))); | ||
19 | |||
20 | static const char *conf_filename; | ||
21 | static int conf_lineno, conf_warnings, conf_unsaved; | ||
22 | |||
17 | const char conf_def_filename[] = ".config"; | 23 | const char conf_def_filename[] = ".config"; |
18 | 24 | ||
19 | const char conf_defname[] = "arch/$ARCH/defconfig"; | 25 | const char conf_defname[] = "arch/$ARCH/defconfig"; |
@@ -27,6 +33,17 @@ const char *conf_confnames[] = { | |||
27 | NULL, | 33 | NULL, |
28 | }; | 34 | }; |
29 | 35 | ||
36 | static void conf_warning(const char *fmt, ...) | ||
37 | { | ||
38 | va_list ap; | ||
39 | va_start(ap, fmt); | ||
40 | fprintf(stderr, "%s:%d:warning: ", conf_filename, conf_lineno); | ||
41 | vfprintf(stderr, fmt, ap); | ||
42 | fprintf(stderr, "\n"); | ||
43 | va_end(ap); | ||
44 | conf_warnings++; | ||
45 | } | ||
46 | |||
30 | static char *conf_expand_value(const char *in) | 47 | static char *conf_expand_value(const char *in) |
31 | { | 48 | { |
32 | struct symbol *sym; | 49 | struct symbol *sym; |
@@ -69,15 +86,12 @@ char *conf_get_default_confname(void) | |||
69 | return name; | 86 | return name; |
70 | } | 87 | } |
71 | 88 | ||
72 | int conf_read(const char *name) | 89 | int conf_read_simple(const char *name) |
73 | { | 90 | { |
74 | FILE *in = NULL; | 91 | FILE *in = NULL; |
75 | char line[1024]; | 92 | char line[1024]; |
76 | char *p, *p2; | 93 | char *p, *p2; |
77 | int lineno = 0; | ||
78 | struct symbol *sym; | 94 | struct symbol *sym; |
79 | struct property *prop; | ||
80 | struct expr *e; | ||
81 | int i; | 95 | int i; |
82 | 96 | ||
83 | if (name) { | 97 | if (name) { |
@@ -95,12 +109,18 @@ int conf_read(const char *name) | |||
95 | } | 109 | } |
96 | } | 110 | } |
97 | } | 111 | } |
98 | |||
99 | if (!in) | 112 | if (!in) |
100 | return 1; | 113 | return 1; |
101 | 114 | ||
115 | conf_filename = name; | ||
116 | conf_lineno = 0; | ||
117 | conf_warnings = 0; | ||
118 | conf_unsaved = 0; | ||
119 | |||
102 | for_all_symbols(i, sym) { | 120 | for_all_symbols(i, sym) { |
103 | sym->flags |= SYMBOL_NEW | SYMBOL_CHANGED; | 121 | sym->flags |= SYMBOL_NEW | SYMBOL_CHANGED; |
122 | if (sym_is_choice(sym)) | ||
123 | sym->flags &= ~SYMBOL_NEW; | ||
104 | sym->flags &= ~SYMBOL_VALID; | 124 | sym->flags &= ~SYMBOL_VALID; |
105 | switch (sym->type) { | 125 | switch (sym->type) { |
106 | case S_INT: | 126 | case S_INT: |
@@ -115,7 +135,7 @@ int conf_read(const char *name) | |||
115 | } | 135 | } |
116 | 136 | ||
117 | while (fgets(line, sizeof(line), in)) { | 137 | while (fgets(line, sizeof(line), in)) { |
118 | lineno++; | 138 | conf_lineno++; |
119 | sym = NULL; | 139 | sym = NULL; |
120 | switch (line[0]) { | 140 | switch (line[0]) { |
121 | case '#': | 141 | case '#': |
@@ -129,7 +149,10 @@ int conf_read(const char *name) | |||
129 | continue; | 149 | continue; |
130 | sym = sym_find(line + 9); | 150 | sym = sym_find(line + 9); |
131 | if (!sym) { | 151 | if (!sym) { |
132 | fprintf(stderr, "%s:%d: trying to assign nonexistent symbol %s\n", name, lineno, line + 9); | 152 | conf_warning("trying to assign nonexistent symbol %s", line + 9); |
153 | break; | ||
154 | } else if (!(sym->flags & SYMBOL_NEW)) { | ||
155 | conf_warning("trying to reassign symbol %s", sym->name); | ||
133 | break; | 156 | break; |
134 | } | 157 | } |
135 | switch (sym->type) { | 158 | switch (sym->type) { |
@@ -143,8 +166,10 @@ int conf_read(const char *name) | |||
143 | } | 166 | } |
144 | break; | 167 | break; |
145 | case 'C': | 168 | case 'C': |
146 | if (memcmp(line, "CONFIG_", 7)) | 169 | if (memcmp(line, "CONFIG_", 7)) { |
170 | conf_warning("unexpected data"); | ||
147 | continue; | 171 | continue; |
172 | } | ||
148 | p = strchr(line + 7, '='); | 173 | p = strchr(line + 7, '='); |
149 | if (!p) | 174 | if (!p) |
150 | continue; | 175 | continue; |
@@ -154,7 +179,10 @@ int conf_read(const char *name) | |||
154 | *p2 = 0; | 179 | *p2 = 0; |
155 | sym = sym_find(line + 7); | 180 | sym = sym_find(line + 7); |
156 | if (!sym) { | 181 | if (!sym) { |
157 | fprintf(stderr, "%s:%d: trying to assign nonexistent symbol %s\n", name, lineno, line + 7); | 182 | conf_warning("trying to assign nonexistent symbol %s", line + 7); |
183 | break; | ||
184 | } else if (!(sym->flags & SYMBOL_NEW)) { | ||
185 | conf_warning("trying to reassign symbol %s", sym->name); | ||
158 | break; | 186 | break; |
159 | } | 187 | } |
160 | switch (sym->type) { | 188 | switch (sym->type) { |
@@ -175,6 +203,7 @@ int conf_read(const char *name) | |||
175 | sym->flags &= ~SYMBOL_NEW; | 203 | sym->flags &= ~SYMBOL_NEW; |
176 | break; | 204 | break; |
177 | } | 205 | } |
206 | conf_warning("symbol value '%s' invalid for %s", p, sym->name); | ||
178 | break; | 207 | break; |
179 | case S_STRING: | 208 | case S_STRING: |
180 | if (*p++ != '"') | 209 | if (*p++ != '"') |
@@ -187,8 +216,8 @@ int conf_read(const char *name) | |||
187 | memmove(p2, p2 + 1, strlen(p2)); | 216 | memmove(p2, p2 + 1, strlen(p2)); |
188 | } | 217 | } |
189 | if (!p2) { | 218 | if (!p2) { |
190 | fprintf(stderr, "%s:%d: invalid string found\n", name, lineno); | 219 | conf_warning("invalid string found"); |
191 | exit(1); | 220 | continue; |
192 | } | 221 | } |
193 | case S_INT: | 222 | case S_INT: |
194 | case S_HEX: | 223 | case S_HEX: |
@@ -196,8 +225,8 @@ int conf_read(const char *name) | |||
196 | sym->user.val = strdup(p); | 225 | sym->user.val = strdup(p); |
197 | sym->flags &= ~SYMBOL_NEW; | 226 | sym->flags &= ~SYMBOL_NEW; |
198 | } else { | 227 | } else { |
199 | fprintf(stderr, "%s:%d: symbol value '%s' invalid for %s\n", name, lineno, p, sym->name); | 228 | conf_warning("symbol value '%s' invalid for %s", p, sym->name); |
200 | exit(1); | 229 | continue; |
201 | } | 230 | } |
202 | break; | 231 | break; |
203 | default: | 232 | default: |
@@ -207,6 +236,7 @@ int conf_read(const char *name) | |||
207 | case '\n': | 236 | case '\n': |
208 | break; | 237 | break; |
209 | default: | 238 | default: |
239 | conf_warning("unexpected data"); | ||
210 | continue; | 240 | continue; |
211 | } | 241 | } |
212 | if (sym && sym_is_choice_value(sym)) { | 242 | if (sym && sym_is_choice_value(sym)) { |
@@ -215,25 +245,63 @@ int conf_read(const char *name) | |||
215 | case no: | 245 | case no: |
216 | break; | 246 | break; |
217 | case mod: | 247 | case mod: |
218 | if (cs->user.tri == yes) | 248 | if (cs->user.tri == yes) { |
219 | /* warn? */; | 249 | conf_warning("%s creates inconsistent choice state", sym->name); |
250 | cs->flags |= SYMBOL_NEW; | ||
251 | } | ||
220 | break; | 252 | break; |
221 | case yes: | 253 | case yes: |
222 | if (cs->user.tri != no) | 254 | if (cs->user.tri != no) { |
223 | /* warn? */; | 255 | conf_warning("%s creates inconsistent choice state", sym->name); |
224 | cs->user.val = sym; | 256 | cs->flags |= SYMBOL_NEW; |
257 | } else | ||
258 | cs->user.val = sym; | ||
225 | break; | 259 | break; |
226 | } | 260 | } |
227 | cs->user.tri = E_OR(cs->user.tri, sym->user.tri); | 261 | cs->user.tri = E_OR(cs->user.tri, sym->user.tri); |
228 | cs->flags &= ~SYMBOL_NEW; | ||
229 | } | 262 | } |
230 | } | 263 | } |
231 | fclose(in); | 264 | fclose(in); |
232 | 265 | ||
233 | if (modules_sym) | 266 | if (modules_sym) |
234 | sym_calc_value(modules_sym); | 267 | sym_calc_value(modules_sym); |
268 | return 0; | ||
269 | } | ||
270 | |||
271 | int conf_read(const char *name) | ||
272 | { | ||
273 | struct symbol *sym; | ||
274 | struct property *prop; | ||
275 | struct expr *e; | ||
276 | int i; | ||
277 | |||
278 | if (conf_read_simple(name)) | ||
279 | return 1; | ||
280 | |||
235 | for_all_symbols(i, sym) { | 281 | for_all_symbols(i, sym) { |
236 | sym_calc_value(sym); | 282 | sym_calc_value(sym); |
283 | if (sym_is_choice(sym) || (sym->flags & SYMBOL_AUTO)) | ||
284 | goto sym_ok; | ||
285 | if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) { | ||
286 | /* check that calculated value agrees with saved value */ | ||
287 | switch (sym->type) { | ||
288 | case S_BOOLEAN: | ||
289 | case S_TRISTATE: | ||
290 | if (sym->user.tri != sym_get_tristate_value(sym)) | ||
291 | break; | ||
292 | if (!sym_is_choice(sym)) | ||
293 | goto sym_ok; | ||
294 | default: | ||
295 | if (!strcmp(sym->curr.val, sym->user.val)) | ||
296 | goto sym_ok; | ||
297 | break; | ||
298 | } | ||
299 | } else if (!sym_has_value(sym) && !(sym->flags & SYMBOL_WRITE)) | ||
300 | /* no previous value and not saved */ | ||
301 | goto sym_ok; | ||
302 | conf_unsaved++; | ||
303 | /* maybe print value in verbose mode... */ | ||
304 | sym_ok: | ||
237 | if (sym_has_value(sym) && !sym_is_choice_value(sym)) { | 305 | if (sym_has_value(sym) && !sym_is_choice_value(sym)) { |
238 | if (sym->visible == no) | 306 | if (sym->visible == no) |
239 | sym->flags |= SYMBOL_NEW; | 307 | sym->flags |= SYMBOL_NEW; |
@@ -241,8 +309,10 @@ int conf_read(const char *name) | |||
241 | case S_STRING: | 309 | case S_STRING: |
242 | case S_INT: | 310 | case S_INT: |
243 | case S_HEX: | 311 | case S_HEX: |
244 | if (!sym_string_within_range(sym, sym->user.val)) | 312 | if (!sym_string_within_range(sym, sym->user.val)) { |
245 | sym->flags |= SYMBOL_NEW; | 313 | sym->flags |= SYMBOL_NEW; |
314 | sym->flags &= ~SYMBOL_VALID; | ||
315 | } | ||
246 | default: | 316 | default: |
247 | break; | 317 | break; |
248 | } | 318 | } |
@@ -255,7 +325,7 @@ int conf_read(const char *name) | |||
255 | sym->flags |= e->right.sym->flags & SYMBOL_NEW; | 325 | sym->flags |= e->right.sym->flags & SYMBOL_NEW; |
256 | } | 326 | } |
257 | 327 | ||
258 | sym_change_count = 1; | 328 | sym_change_count = conf_warnings && conf_unsaved; |
259 | 329 | ||
260 | return 0; | 330 | return 0; |
261 | } | 331 | } |