diff options
Diffstat (limited to 'scripts/kconfig/confdata.c')
-rw-r--r-- | scripts/kconfig/confdata.c | 491 |
1 files changed, 362 insertions, 129 deletions
diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c index 1b5df589f3ae..2ee48c377b66 100644 --- a/scripts/kconfig/confdata.c +++ b/scripts/kconfig/confdata.c | |||
@@ -5,6 +5,7 @@ | |||
5 | 5 | ||
6 | #include <sys/stat.h> | 6 | #include <sys/stat.h> |
7 | #include <ctype.h> | 7 | #include <ctype.h> |
8 | #include <fcntl.h> | ||
8 | #include <stdio.h> | 9 | #include <stdio.h> |
9 | #include <stdlib.h> | 10 | #include <stdlib.h> |
10 | #include <string.h> | 11 | #include <string.h> |
@@ -20,19 +21,8 @@ static void conf_warning(const char *fmt, ...) | |||
20 | static const char *conf_filename; | 21 | static const char *conf_filename; |
21 | static int conf_lineno, conf_warnings, conf_unsaved; | 22 | static int conf_lineno, conf_warnings, conf_unsaved; |
22 | 23 | ||
23 | const char conf_def_filename[] = ".config"; | ||
24 | |||
25 | const char conf_defname[] = "arch/$ARCH/defconfig"; | 24 | const char conf_defname[] = "arch/$ARCH/defconfig"; |
26 | 25 | ||
27 | const char *conf_confnames[] = { | ||
28 | ".config", | ||
29 | "/lib/modules/$UNAME_RELEASE/.config", | ||
30 | "/etc/kernel-config", | ||
31 | "/boot/config-$UNAME_RELEASE", | ||
32 | conf_defname, | ||
33 | NULL, | ||
34 | }; | ||
35 | |||
36 | static void conf_warning(const char *fmt, ...) | 26 | static void conf_warning(const char *fmt, ...) |
37 | { | 27 | { |
38 | va_list ap; | 28 | va_list ap; |
@@ -44,6 +34,13 @@ static void conf_warning(const char *fmt, ...) | |||
44 | conf_warnings++; | 34 | conf_warnings++; |
45 | } | 35 | } |
46 | 36 | ||
37 | const char *conf_get_configname(void) | ||
38 | { | ||
39 | char *name = getenv("KCONFIG_CONFIG"); | ||
40 | |||
41 | return name ? name : ".config"; | ||
42 | } | ||
43 | |||
47 | static char *conf_expand_value(const char *in) | 44 | static char *conf_expand_value(const char *in) |
48 | { | 45 | { |
49 | struct symbol *sym; | 46 | struct symbol *sym; |
@@ -86,51 +83,65 @@ char *conf_get_default_confname(void) | |||
86 | return name; | 83 | return name; |
87 | } | 84 | } |
88 | 85 | ||
89 | int conf_read_simple(const char *name) | 86 | int conf_read_simple(const char *name, int def) |
90 | { | 87 | { |
91 | FILE *in = NULL; | 88 | FILE *in = NULL; |
92 | char line[1024]; | 89 | char line[1024]; |
93 | char *p, *p2; | 90 | char *p, *p2; |
94 | struct symbol *sym; | 91 | struct symbol *sym; |
95 | int i; | 92 | int i, def_flags; |
96 | 93 | ||
97 | if (name) { | 94 | if (name) { |
98 | in = zconf_fopen(name); | 95 | in = zconf_fopen(name); |
99 | } else { | 96 | } else { |
100 | const char **names = conf_confnames; | 97 | struct property *prop; |
101 | while ((name = *names++)) { | 98 | |
102 | name = conf_expand_value(name); | 99 | name = conf_get_configname(); |
100 | in = zconf_fopen(name); | ||
101 | if (in) | ||
102 | goto load; | ||
103 | sym_change_count++; | ||
104 | if (!sym_defconfig_list) | ||
105 | return 1; | ||
106 | |||
107 | for_all_defaults(sym_defconfig_list, prop) { | ||
108 | if (expr_calc_value(prop->visible.expr) == no || | ||
109 | prop->expr->type != E_SYMBOL) | ||
110 | continue; | ||
111 | name = conf_expand_value(prop->expr->left.sym->name); | ||
103 | in = zconf_fopen(name); | 112 | in = zconf_fopen(name); |
104 | if (in) { | 113 | if (in) { |
105 | printf(_("#\n" | 114 | printf(_("#\n" |
106 | "# using defaults found in %s\n" | 115 | "# using defaults found in %s\n" |
107 | "#\n"), name); | 116 | "#\n"), name); |
108 | break; | 117 | goto load; |
109 | } | 118 | } |
110 | } | 119 | } |
111 | } | 120 | } |
112 | if (!in) | 121 | if (!in) |
113 | return 1; | 122 | return 1; |
114 | 123 | ||
124 | load: | ||
115 | conf_filename = name; | 125 | conf_filename = name; |
116 | conf_lineno = 0; | 126 | conf_lineno = 0; |
117 | conf_warnings = 0; | 127 | conf_warnings = 0; |
118 | conf_unsaved = 0; | 128 | conf_unsaved = 0; |
119 | 129 | ||
130 | def_flags = SYMBOL_DEF << def; | ||
120 | for_all_symbols(i, sym) { | 131 | for_all_symbols(i, sym) { |
121 | sym->flags |= SYMBOL_NEW | SYMBOL_CHANGED; | 132 | sym->flags |= SYMBOL_CHANGED; |
133 | sym->flags &= ~(def_flags|SYMBOL_VALID); | ||
122 | if (sym_is_choice(sym)) | 134 | if (sym_is_choice(sym)) |
123 | sym->flags &= ~SYMBOL_NEW; | 135 | sym->flags |= def_flags; |
124 | sym->flags &= ~SYMBOL_VALID; | ||
125 | switch (sym->type) { | 136 | switch (sym->type) { |
126 | case S_INT: | 137 | case S_INT: |
127 | case S_HEX: | 138 | case S_HEX: |
128 | case S_STRING: | 139 | case S_STRING: |
129 | if (sym->user.val) | 140 | if (sym->def[def].val) |
130 | free(sym->user.val); | 141 | free(sym->def[def].val); |
131 | default: | 142 | default: |
132 | sym->user.val = NULL; | 143 | sym->def[def].val = NULL; |
133 | sym->user.tri = no; | 144 | sym->def[def].tri = no; |
134 | } | 145 | } |
135 | } | 146 | } |
136 | 147 | ||
@@ -147,19 +158,26 @@ int conf_read_simple(const char *name) | |||
147 | *p++ = 0; | 158 | *p++ = 0; |
148 | if (strncmp(p, "is not set", 10)) | 159 | if (strncmp(p, "is not set", 10)) |
149 | continue; | 160 | continue; |
150 | sym = sym_find(line + 9); | 161 | if (def == S_DEF_USER) { |
151 | if (!sym) { | 162 | sym = sym_find(line + 9); |
152 | conf_warning("trying to assign nonexistent symbol %s", line + 9); | 163 | if (!sym) { |
153 | break; | 164 | conf_warning("trying to assign nonexistent symbol %s", line + 9); |
154 | } else if (!(sym->flags & SYMBOL_NEW)) { | 165 | break; |
166 | } | ||
167 | } else { | ||
168 | sym = sym_lookup(line + 9, 0); | ||
169 | if (sym->type == S_UNKNOWN) | ||
170 | sym->type = S_BOOLEAN; | ||
171 | } | ||
172 | if (sym->flags & def_flags) { | ||
155 | conf_warning("trying to reassign symbol %s", sym->name); | 173 | conf_warning("trying to reassign symbol %s", sym->name); |
156 | break; | 174 | break; |
157 | } | 175 | } |
158 | switch (sym->type) { | 176 | switch (sym->type) { |
159 | case S_BOOLEAN: | 177 | case S_BOOLEAN: |
160 | case S_TRISTATE: | 178 | case S_TRISTATE: |
161 | sym->user.tri = no; | 179 | sym->def[def].tri = no; |
162 | sym->flags &= ~SYMBOL_NEW; | 180 | sym->flags |= def_flags; |
163 | break; | 181 | break; |
164 | default: | 182 | default: |
165 | ; | 183 | ; |
@@ -177,34 +195,48 @@ int conf_read_simple(const char *name) | |||
177 | p2 = strchr(p, '\n'); | 195 | p2 = strchr(p, '\n'); |
178 | if (p2) | 196 | if (p2) |
179 | *p2 = 0; | 197 | *p2 = 0; |
180 | sym = sym_find(line + 7); | 198 | if (def == S_DEF_USER) { |
181 | if (!sym) { | 199 | sym = sym_find(line + 7); |
182 | conf_warning("trying to assign nonexistent symbol %s", line + 7); | 200 | if (!sym) { |
183 | break; | 201 | conf_warning("trying to assign nonexistent symbol %s", line + 7); |
184 | } else if (!(sym->flags & SYMBOL_NEW)) { | 202 | break; |
203 | } | ||
204 | } else { | ||
205 | sym = sym_lookup(line + 7, 0); | ||
206 | if (sym->type == S_UNKNOWN) | ||
207 | sym->type = S_OTHER; | ||
208 | } | ||
209 | if (sym->flags & def_flags) { | ||
185 | conf_warning("trying to reassign symbol %s", sym->name); | 210 | conf_warning("trying to reassign symbol %s", sym->name); |
186 | break; | 211 | break; |
187 | } | 212 | } |
188 | switch (sym->type) { | 213 | switch (sym->type) { |
189 | case S_TRISTATE: | 214 | case S_TRISTATE: |
190 | if (p[0] == 'm') { | 215 | if (p[0] == 'm') { |
191 | sym->user.tri = mod; | 216 | sym->def[def].tri = mod; |
192 | sym->flags &= ~SYMBOL_NEW; | 217 | sym->flags |= def_flags; |
193 | break; | 218 | break; |
194 | } | 219 | } |
195 | case S_BOOLEAN: | 220 | case S_BOOLEAN: |
196 | if (p[0] == 'y') { | 221 | if (p[0] == 'y') { |
197 | sym->user.tri = yes; | 222 | sym->def[def].tri = yes; |
198 | sym->flags &= ~SYMBOL_NEW; | 223 | sym->flags |= def_flags; |
199 | break; | 224 | break; |
200 | } | 225 | } |
201 | if (p[0] == 'n') { | 226 | if (p[0] == 'n') { |
202 | sym->user.tri = no; | 227 | sym->def[def].tri = no; |
203 | sym->flags &= ~SYMBOL_NEW; | 228 | sym->flags |= def_flags; |
204 | break; | 229 | break; |
205 | } | 230 | } |
206 | conf_warning("symbol value '%s' invalid for %s", p, sym->name); | 231 | conf_warning("symbol value '%s' invalid for %s", p, sym->name); |
207 | break; | 232 | break; |
233 | case S_OTHER: | ||
234 | if (*p != '"') { | ||
235 | for (p2 = p; *p2 && !isspace(*p2); p2++) | ||
236 | ; | ||
237 | sym->type = S_STRING; | ||
238 | goto done; | ||
239 | } | ||
208 | case S_STRING: | 240 | case S_STRING: |
209 | if (*p++ != '"') | 241 | if (*p++ != '"') |
210 | break; | 242 | break; |
@@ -221,9 +253,10 @@ int conf_read_simple(const char *name) | |||
221 | } | 253 | } |
222 | case S_INT: | 254 | case S_INT: |
223 | case S_HEX: | 255 | case S_HEX: |
256 | done: | ||
224 | if (sym_string_valid(sym, p)) { | 257 | if (sym_string_valid(sym, p)) { |
225 | sym->user.val = strdup(p); | 258 | sym->def[def].val = strdup(p); |
226 | sym->flags &= ~SYMBOL_NEW; | 259 | sym->flags |= def_flags; |
227 | } else { | 260 | } else { |
228 | conf_warning("symbol value '%s' invalid for %s", p, sym->name); | 261 | conf_warning("symbol value '%s' invalid for %s", p, sym->name); |
229 | continue; | 262 | continue; |
@@ -241,24 +274,24 @@ int conf_read_simple(const char *name) | |||
241 | } | 274 | } |
242 | if (sym && sym_is_choice_value(sym)) { | 275 | if (sym && sym_is_choice_value(sym)) { |
243 | struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym)); | 276 | struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym)); |
244 | switch (sym->user.tri) { | 277 | switch (sym->def[def].tri) { |
245 | case no: | 278 | case no: |
246 | break; | 279 | break; |
247 | case mod: | 280 | case mod: |
248 | if (cs->user.tri == yes) { | 281 | if (cs->def[def].tri == yes) { |
249 | conf_warning("%s creates inconsistent choice state", sym->name); | 282 | conf_warning("%s creates inconsistent choice state", sym->name); |
250 | cs->flags |= SYMBOL_NEW; | 283 | cs->flags &= ~def_flags; |
251 | } | 284 | } |
252 | break; | 285 | break; |
253 | case yes: | 286 | case yes: |
254 | if (cs->user.tri != no) { | 287 | if (cs->def[def].tri != no) { |
255 | conf_warning("%s creates inconsistent choice state", sym->name); | 288 | conf_warning("%s creates inconsistent choice state", sym->name); |
256 | cs->flags |= SYMBOL_NEW; | 289 | cs->flags &= ~def_flags; |
257 | } else | 290 | } else |
258 | cs->user.val = sym; | 291 | cs->def[def].val = sym; |
259 | break; | 292 | break; |
260 | } | 293 | } |
261 | cs->user.tri = E_OR(cs->user.tri, sym->user.tri); | 294 | cs->def[def].tri = E_OR(cs->def[def].tri, sym->def[def].tri); |
262 | } | 295 | } |
263 | } | 296 | } |
264 | fclose(in); | 297 | fclose(in); |
@@ -273,9 +306,11 @@ int conf_read(const char *name) | |||
273 | struct symbol *sym; | 306 | struct symbol *sym; |
274 | struct property *prop; | 307 | struct property *prop; |
275 | struct expr *e; | 308 | struct expr *e; |
276 | int i; | 309 | int i, flags; |
310 | |||
311 | sym_change_count = 0; | ||
277 | 312 | ||
278 | if (conf_read_simple(name)) | 313 | if (conf_read_simple(name, S_DEF_USER)) |
279 | return 1; | 314 | return 1; |
280 | 315 | ||
281 | for_all_symbols(i, sym) { | 316 | for_all_symbols(i, sym) { |
@@ -287,12 +322,12 @@ int conf_read(const char *name) | |||
287 | switch (sym->type) { | 322 | switch (sym->type) { |
288 | case S_BOOLEAN: | 323 | case S_BOOLEAN: |
289 | case S_TRISTATE: | 324 | case S_TRISTATE: |
290 | if (sym->user.tri != sym_get_tristate_value(sym)) | 325 | if (sym->def[S_DEF_USER].tri != sym_get_tristate_value(sym)) |
291 | break; | 326 | break; |
292 | if (!sym_is_choice(sym)) | 327 | if (!sym_is_choice(sym)) |
293 | goto sym_ok; | 328 | goto sym_ok; |
294 | default: | 329 | default: |
295 | if (!strcmp(sym->curr.val, sym->user.val)) | 330 | if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val)) |
296 | goto sym_ok; | 331 | goto sym_ok; |
297 | break; | 332 | break; |
298 | } | 333 | } |
@@ -304,15 +339,13 @@ int conf_read(const char *name) | |||
304 | sym_ok: | 339 | sym_ok: |
305 | if (sym_has_value(sym) && !sym_is_choice_value(sym)) { | 340 | if (sym_has_value(sym) && !sym_is_choice_value(sym)) { |
306 | if (sym->visible == no) | 341 | if (sym->visible == no) |
307 | sym->flags |= SYMBOL_NEW; | 342 | sym->flags &= ~SYMBOL_DEF_USER; |
308 | switch (sym->type) { | 343 | switch (sym->type) { |
309 | case S_STRING: | 344 | case S_STRING: |
310 | case S_INT: | 345 | case S_INT: |
311 | case S_HEX: | 346 | case S_HEX: |
312 | if (!sym_string_within_range(sym, sym->user.val)) { | 347 | if (!sym_string_within_range(sym, sym->def[S_DEF_USER].val)) |
313 | sym->flags |= SYMBOL_NEW; | 348 | sym->flags &= ~(SYMBOL_VALID|SYMBOL_DEF_USER); |
314 | sym->flags &= ~SYMBOL_VALID; | ||
315 | } | ||
316 | default: | 349 | default: |
317 | break; | 350 | break; |
318 | } | 351 | } |
@@ -320,19 +353,21 @@ int conf_read(const char *name) | |||
320 | if (!sym_is_choice(sym)) | 353 | if (!sym_is_choice(sym)) |
321 | continue; | 354 | continue; |
322 | prop = sym_get_choice_prop(sym); | 355 | prop = sym_get_choice_prop(sym); |
356 | flags = sym->flags; | ||
323 | for (e = prop->expr; e; e = e->left.expr) | 357 | for (e = prop->expr; e; e = e->left.expr) |
324 | if (e->right.sym->visible != no) | 358 | if (e->right.sym->visible != no) |
325 | sym->flags |= e->right.sym->flags & SYMBOL_NEW; | 359 | flags &= e->right.sym->flags; |
360 | sym->flags |= flags & SYMBOL_DEF_USER; | ||
326 | } | 361 | } |
327 | 362 | ||
328 | sym_change_count = conf_warnings || conf_unsaved; | 363 | sym_change_count += conf_warnings || conf_unsaved; |
329 | 364 | ||
330 | return 0; | 365 | return 0; |
331 | } | 366 | } |
332 | 367 | ||
333 | int conf_write(const char *name) | 368 | int conf_write(const char *name) |
334 | { | 369 | { |
335 | FILE *out, *out_h; | 370 | FILE *out; |
336 | struct symbol *sym; | 371 | struct symbol *sym; |
337 | struct menu *menu; | 372 | struct menu *menu; |
338 | const char *basename; | 373 | const char *basename; |
@@ -351,7 +386,7 @@ int conf_write(const char *name) | |||
351 | if (!stat(name, &st) && S_ISDIR(st.st_mode)) { | 386 | if (!stat(name, &st) && S_ISDIR(st.st_mode)) { |
352 | strcpy(dirname, name); | 387 | strcpy(dirname, name); |
353 | strcat(dirname, "/"); | 388 | strcat(dirname, "/"); |
354 | basename = conf_def_filename; | 389 | basename = conf_get_configname(); |
355 | } else if ((slash = strrchr(name, '/'))) { | 390 | } else if ((slash = strrchr(name, '/'))) { |
356 | int size = slash - name + 1; | 391 | int size = slash - name + 1; |
357 | memcpy(dirname, name, size); | 392 | memcpy(dirname, name, size); |
@@ -359,23 +394,24 @@ int conf_write(const char *name) | |||
359 | if (slash[1]) | 394 | if (slash[1]) |
360 | basename = slash + 1; | 395 | basename = slash + 1; |
361 | else | 396 | else |
362 | basename = conf_def_filename; | 397 | basename = conf_get_configname(); |
363 | } else | 398 | } else |
364 | basename = name; | 399 | basename = name; |
365 | } else | 400 | } else |
366 | basename = conf_def_filename; | 401 | basename = conf_get_configname(); |
367 | 402 | ||
368 | sprintf(newname, "%s.tmpconfig.%d", dirname, (int)getpid()); | 403 | sprintf(newname, "%s%s", dirname, basename); |
369 | out = fopen(newname, "w"); | 404 | env = getenv("KCONFIG_OVERWRITECONFIG"); |
405 | if (!env || !*env) { | ||
406 | sprintf(tmpname, "%s.tmpconfig.%d", dirname, (int)getpid()); | ||
407 | out = fopen(tmpname, "w"); | ||
408 | } else { | ||
409 | *tmpname = 0; | ||
410 | out = fopen(newname, "w"); | ||
411 | } | ||
370 | if (!out) | 412 | if (!out) |
371 | return 1; | 413 | return 1; |
372 | out_h = NULL; | 414 | |
373 | if (!name) { | ||
374 | out_h = fopen(".tmpconfig.h", "w"); | ||
375 | if (!out_h) | ||
376 | return 1; | ||
377 | file_write_dep(NULL); | ||
378 | } | ||
379 | sym = sym_lookup("KERNELVERSION", 0); | 415 | sym = sym_lookup("KERNELVERSION", 0); |
380 | sym_calc_value(sym); | 416 | sym_calc_value(sym); |
381 | time(&now); | 417 | time(&now); |
@@ -391,16 +427,6 @@ int conf_write(const char *name) | |||
391 | sym_get_string_value(sym), | 427 | sym_get_string_value(sym), |
392 | use_timestamp ? "# " : "", | 428 | use_timestamp ? "# " : "", |
393 | use_timestamp ? ctime(&now) : ""); | 429 | use_timestamp ? ctime(&now) : ""); |
394 | if (out_h) | ||
395 | fprintf(out_h, "/*\n" | ||
396 | " * Automatically generated C config: don't edit\n" | ||
397 | " * Linux kernel version: %s\n" | ||
398 | "%s%s" | ||
399 | " */\n" | ||
400 | "#define AUTOCONF_INCLUDED\n", | ||
401 | sym_get_string_value(sym), | ||
402 | use_timestamp ? " * " : "", | ||
403 | use_timestamp ? ctime(&now) : ""); | ||
404 | 430 | ||
405 | if (!sym_change_count) | 431 | if (!sym_change_count) |
406 | sym_clear_all_valid(); | 432 | sym_clear_all_valid(); |
@@ -416,11 +442,6 @@ int conf_write(const char *name) | |||
416 | "#\n" | 442 | "#\n" |
417 | "# %s\n" | 443 | "# %s\n" |
418 | "#\n", str); | 444 | "#\n", str); |
419 | if (out_h) | ||
420 | fprintf(out_h, "\n" | ||
421 | "/*\n" | ||
422 | " * %s\n" | ||
423 | " */\n", str); | ||
424 | } else if (!(sym->flags & SYMBOL_CHOICE)) { | 445 | } else if (!(sym->flags & SYMBOL_CHOICE)) { |
425 | sym_calc_value(sym); | 446 | sym_calc_value(sym); |
426 | if (!(sym->flags & SYMBOL_WRITE)) | 447 | if (!(sym->flags & SYMBOL_WRITE)) |
@@ -438,59 +459,39 @@ int conf_write(const char *name) | |||
438 | switch (sym_get_tristate_value(sym)) { | 459 | switch (sym_get_tristate_value(sym)) { |
439 | case no: | 460 | case no: |
440 | fprintf(out, "# CONFIG_%s is not set\n", sym->name); | 461 | fprintf(out, "# CONFIG_%s is not set\n", sym->name); |
441 | if (out_h) | ||
442 | fprintf(out_h, "#undef CONFIG_%s\n", sym->name); | ||
443 | break; | 462 | break; |
444 | case mod: | 463 | case mod: |
445 | fprintf(out, "CONFIG_%s=m\n", sym->name); | 464 | fprintf(out, "CONFIG_%s=m\n", sym->name); |
446 | if (out_h) | ||
447 | fprintf(out_h, "#define CONFIG_%s_MODULE 1\n", sym->name); | ||
448 | break; | 465 | break; |
449 | case yes: | 466 | case yes: |
450 | fprintf(out, "CONFIG_%s=y\n", sym->name); | 467 | fprintf(out, "CONFIG_%s=y\n", sym->name); |
451 | if (out_h) | ||
452 | fprintf(out_h, "#define CONFIG_%s 1\n", sym->name); | ||
453 | break; | 468 | break; |
454 | } | 469 | } |
455 | break; | 470 | break; |
456 | case S_STRING: | 471 | case S_STRING: |
457 | // fix me | ||
458 | str = sym_get_string_value(sym); | 472 | str = sym_get_string_value(sym); |
459 | fprintf(out, "CONFIG_%s=\"", sym->name); | 473 | fprintf(out, "CONFIG_%s=\"", sym->name); |
460 | if (out_h) | 474 | while (1) { |
461 | fprintf(out_h, "#define CONFIG_%s \"", sym->name); | ||
462 | do { | ||
463 | l = strcspn(str, "\"\\"); | 475 | l = strcspn(str, "\"\\"); |
464 | if (l) { | 476 | if (l) { |
465 | fwrite(str, l, 1, out); | 477 | fwrite(str, l, 1, out); |
466 | if (out_h) | 478 | str += l; |
467 | fwrite(str, l, 1, out_h); | ||
468 | } | ||
469 | str += l; | ||
470 | while (*str == '\\' || *str == '"') { | ||
471 | fprintf(out, "\\%c", *str); | ||
472 | if (out_h) | ||
473 | fprintf(out_h, "\\%c", *str); | ||
474 | str++; | ||
475 | } | 479 | } |
476 | } while (*str); | 480 | if (!*str) |
481 | break; | ||
482 | fprintf(out, "\\%c", *str++); | ||
483 | } | ||
477 | fputs("\"\n", out); | 484 | fputs("\"\n", out); |
478 | if (out_h) | ||
479 | fputs("\"\n", out_h); | ||
480 | break; | 485 | break; |
481 | case S_HEX: | 486 | case S_HEX: |
482 | str = sym_get_string_value(sym); | 487 | str = sym_get_string_value(sym); |
483 | if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) { | 488 | if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) { |
484 | fprintf(out, "CONFIG_%s=%s\n", sym->name, str); | 489 | fprintf(out, "CONFIG_%s=%s\n", sym->name, str); |
485 | if (out_h) | ||
486 | fprintf(out_h, "#define CONFIG_%s 0x%s\n", sym->name, str); | ||
487 | break; | 490 | break; |
488 | } | 491 | } |
489 | case S_INT: | 492 | case S_INT: |
490 | str = sym_get_string_value(sym); | 493 | str = sym_get_string_value(sym); |
491 | fprintf(out, "CONFIG_%s=%s\n", sym->name, str); | 494 | fprintf(out, "CONFIG_%s=%s\n", sym->name, str); |
492 | if (out_h) | ||
493 | fprintf(out_h, "#define CONFIG_%s %s\n", sym->name, str); | ||
494 | break; | 495 | break; |
495 | } | 496 | } |
496 | } | 497 | } |
@@ -510,21 +511,253 @@ int conf_write(const char *name) | |||
510 | } | 511 | } |
511 | } | 512 | } |
512 | fclose(out); | 513 | fclose(out); |
513 | if (out_h) { | 514 | |
514 | fclose(out_h); | 515 | if (*tmpname) { |
515 | rename(".tmpconfig.h", "include/linux/autoconf.h"); | 516 | strcat(dirname, name ? name : conf_get_configname()); |
517 | strcat(dirname, ".old"); | ||
518 | rename(newname, dirname); | ||
519 | if (rename(tmpname, newname)) | ||
520 | return 1; | ||
516 | } | 521 | } |
517 | if (!name || basename != conf_def_filename) { | 522 | |
518 | if (!name) | 523 | printf(_("#\n" |
519 | name = conf_def_filename; | 524 | "# configuration written to %s\n" |
520 | sprintf(tmpname, "%s.old", name); | 525 | "#\n"), newname); |
521 | rename(name, tmpname); | 526 | |
527 | sym_change_count = 0; | ||
528 | |||
529 | return 0; | ||
530 | } | ||
531 | |||
532 | int conf_split_config(void) | ||
533 | { | ||
534 | char *name, path[128]; | ||
535 | char *s, *d, c; | ||
536 | struct symbol *sym; | ||
537 | struct stat sb; | ||
538 | int res, i, fd; | ||
539 | |||
540 | name = getenv("KCONFIG_AUTOCONFIG"); | ||
541 | if (!name) | ||
542 | name = "include/config/auto.conf"; | ||
543 | conf_read_simple(name, S_DEF_AUTO); | ||
544 | |||
545 | if (chdir("include/config")) | ||
546 | return 1; | ||
547 | |||
548 | res = 0; | ||
549 | for_all_symbols(i, sym) { | ||
550 | sym_calc_value(sym); | ||
551 | if ((sym->flags & SYMBOL_AUTO) || !sym->name) | ||
552 | continue; | ||
553 | if (sym->flags & SYMBOL_WRITE) { | ||
554 | if (sym->flags & SYMBOL_DEF_AUTO) { | ||
555 | /* | ||
556 | * symbol has old and new value, | ||
557 | * so compare them... | ||
558 | */ | ||
559 | switch (sym->type) { | ||
560 | case S_BOOLEAN: | ||
561 | case S_TRISTATE: | ||
562 | if (sym_get_tristate_value(sym) == | ||
563 | sym->def[S_DEF_AUTO].tri) | ||
564 | continue; | ||
565 | break; | ||
566 | case S_STRING: | ||
567 | case S_HEX: | ||
568 | case S_INT: | ||
569 | if (!strcmp(sym_get_string_value(sym), | ||
570 | sym->def[S_DEF_AUTO].val)) | ||
571 | continue; | ||
572 | break; | ||
573 | default: | ||
574 | break; | ||
575 | } | ||
576 | } else { | ||
577 | /* | ||
578 | * If there is no old value, only 'no' (unset) | ||
579 | * is allowed as new value. | ||
580 | */ | ||
581 | switch (sym->type) { | ||
582 | case S_BOOLEAN: | ||
583 | case S_TRISTATE: | ||
584 | if (sym_get_tristate_value(sym) == no) | ||
585 | continue; | ||
586 | break; | ||
587 | default: | ||
588 | break; | ||
589 | } | ||
590 | } | ||
591 | } else if (!(sym->flags & SYMBOL_DEF_AUTO)) | ||
592 | /* There is neither an old nor a new value. */ | ||
593 | continue; | ||
594 | /* else | ||
595 | * There is an old value, but no new value ('no' (unset) | ||
596 | * isn't saved in auto.conf, so the old value is always | ||
597 | * different from 'no'). | ||
598 | */ | ||
599 | |||
600 | /* Replace all '_' and append ".h" */ | ||
601 | s = sym->name; | ||
602 | d = path; | ||
603 | while ((c = *s++)) { | ||
604 | c = tolower(c); | ||
605 | *d++ = (c == '_') ? '/' : c; | ||
606 | } | ||
607 | strcpy(d, ".h"); | ||
608 | |||
609 | /* Assume directory path already exists. */ | ||
610 | fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644); | ||
611 | if (fd == -1) { | ||
612 | if (errno != ENOENT) { | ||
613 | res = 1; | ||
614 | break; | ||
615 | } | ||
616 | /* | ||
617 | * Create directory components, | ||
618 | * unless they exist already. | ||
619 | */ | ||
620 | d = path; | ||
621 | while ((d = strchr(d, '/'))) { | ||
622 | *d = 0; | ||
623 | if (stat(path, &sb) && mkdir(path, 0755)) { | ||
624 | res = 1; | ||
625 | goto out; | ||
626 | } | ||
627 | *d++ = '/'; | ||
628 | } | ||
629 | /* Try it again. */ | ||
630 | fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644); | ||
631 | if (fd == -1) { | ||
632 | res = 1; | ||
633 | break; | ||
634 | } | ||
635 | } | ||
636 | close(fd); | ||
522 | } | 637 | } |
523 | sprintf(tmpname, "%s%s", dirname, basename); | 638 | out: |
524 | if (rename(newname, tmpname)) | 639 | if (chdir("../..")) |
525 | return 1; | 640 | return 1; |
526 | 641 | ||
527 | sym_change_count = 0; | 642 | return res; |
643 | } | ||
644 | |||
645 | int conf_write_autoconf(void) | ||
646 | { | ||
647 | struct symbol *sym; | ||
648 | const char *str; | ||
649 | char *name; | ||
650 | FILE *out, *out_h; | ||
651 | time_t now; | ||
652 | int i, l; | ||
653 | |||
654 | sym_clear_all_valid(); | ||
655 | |||
656 | file_write_dep("include/config/auto.conf.cmd"); | ||
657 | |||
658 | if (conf_split_config()) | ||
659 | return 1; | ||
660 | |||
661 | out = fopen(".tmpconfig", "w"); | ||
662 | if (!out) | ||
663 | return 1; | ||
664 | |||
665 | out_h = fopen(".tmpconfig.h", "w"); | ||
666 | if (!out_h) { | ||
667 | fclose(out); | ||
668 | return 1; | ||
669 | } | ||
670 | |||
671 | sym = sym_lookup("KERNELVERSION", 0); | ||
672 | sym_calc_value(sym); | ||
673 | time(&now); | ||
674 | fprintf(out, "#\n" | ||
675 | "# Automatically generated make config: don't edit\n" | ||
676 | "# Linux kernel version: %s\n" | ||
677 | "# %s" | ||
678 | "#\n", | ||
679 | sym_get_string_value(sym), ctime(&now)); | ||
680 | fprintf(out_h, "/*\n" | ||
681 | " * Automatically generated C config: don't edit\n" | ||
682 | " * Linux kernel version: %s\n" | ||
683 | " * %s" | ||
684 | " */\n" | ||
685 | "#define AUTOCONF_INCLUDED\n", | ||
686 | sym_get_string_value(sym), ctime(&now)); | ||
687 | |||
688 | for_all_symbols(i, sym) { | ||
689 | sym_calc_value(sym); | ||
690 | if (!(sym->flags & SYMBOL_WRITE) || !sym->name) | ||
691 | continue; | ||
692 | switch (sym->type) { | ||
693 | case S_BOOLEAN: | ||
694 | case S_TRISTATE: | ||
695 | switch (sym_get_tristate_value(sym)) { | ||
696 | case no: | ||
697 | break; | ||
698 | case mod: | ||
699 | fprintf(out, "CONFIG_%s=m\n", sym->name); | ||
700 | fprintf(out_h, "#define CONFIG_%s_MODULE 1\n", sym->name); | ||
701 | break; | ||
702 | case yes: | ||
703 | fprintf(out, "CONFIG_%s=y\n", sym->name); | ||
704 | fprintf(out_h, "#define CONFIG_%s 1\n", sym->name); | ||
705 | break; | ||
706 | } | ||
707 | break; | ||
708 | case S_STRING: | ||
709 | str = sym_get_string_value(sym); | ||
710 | fprintf(out, "CONFIG_%s=\"", sym->name); | ||
711 | fprintf(out_h, "#define CONFIG_%s \"", sym->name); | ||
712 | while (1) { | ||
713 | l = strcspn(str, "\"\\"); | ||
714 | if (l) { | ||
715 | fwrite(str, l, 1, out); | ||
716 | fwrite(str, l, 1, out_h); | ||
717 | str += l; | ||
718 | } | ||
719 | if (!*str) | ||
720 | break; | ||
721 | fprintf(out, "\\%c", *str); | ||
722 | fprintf(out_h, "\\%c", *str); | ||
723 | str++; | ||
724 | } | ||
725 | fputs("\"\n", out); | ||
726 | fputs("\"\n", out_h); | ||
727 | break; | ||
728 | case S_HEX: | ||
729 | str = sym_get_string_value(sym); | ||
730 | if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) { | ||
731 | fprintf(out, "CONFIG_%s=%s\n", sym->name, str); | ||
732 | fprintf(out_h, "#define CONFIG_%s 0x%s\n", sym->name, str); | ||
733 | break; | ||
734 | } | ||
735 | case S_INT: | ||
736 | str = sym_get_string_value(sym); | ||
737 | fprintf(out, "CONFIG_%s=%s\n", sym->name, str); | ||
738 | fprintf(out_h, "#define CONFIG_%s %s\n", sym->name, str); | ||
739 | break; | ||
740 | default: | ||
741 | break; | ||
742 | } | ||
743 | } | ||
744 | fclose(out); | ||
745 | fclose(out_h); | ||
746 | |||
747 | name = getenv("KCONFIG_AUTOHEADER"); | ||
748 | if (!name) | ||
749 | name = "include/linux/autoconf.h"; | ||
750 | if (rename(".tmpconfig.h", name)) | ||
751 | return 1; | ||
752 | name = getenv("KCONFIG_AUTOCONFIG"); | ||
753 | if (!name) | ||
754 | name = "include/config/auto.conf"; | ||
755 | /* | ||
756 | * This must be the last step, kbuild has a dependency on auto.conf | ||
757 | * and this marks the successful completion of the previous steps. | ||
758 | */ | ||
759 | if (rename(".tmpconfig", name)) | ||
760 | return 1; | ||
528 | 761 | ||
529 | return 0; | 762 | return 0; |
530 | } | 763 | } |