Root/
1 | /* |
2 | * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> |
3 | * Released under the terms of the GNU GPL v2.0. |
4 | */ |
5 | |
6 | #include <sys/stat.h> |
7 | #include <ctype.h> |
8 | #include <errno.h> |
9 | #include <fcntl.h> |
10 | #include <stdarg.h> |
11 | #include <stdio.h> |
12 | #include <stdlib.h> |
13 | #include <string.h> |
14 | #include <time.h> |
15 | #include <unistd.h> |
16 | |
17 | #include "lkc.h" |
18 | |
19 | static void conf_warning(const char *fmt, ...) |
20 | __attribute__ ((format (printf, 1, 2))); |
21 | |
22 | static void conf_message(const char *fmt, ...) |
23 | __attribute__ ((format (printf, 1, 2))); |
24 | |
25 | static const char *conf_filename; |
26 | static int conf_lineno, conf_warnings, conf_unsaved; |
27 | |
28 | const char conf_defname[] = "arch/$ARCH/defconfig"; |
29 | |
30 | static void conf_warning(const char *fmt, ...) |
31 | { |
32 | va_list ap; |
33 | va_start(ap, fmt); |
34 | fprintf(stderr, "%s:%d:warning: ", conf_filename, conf_lineno); |
35 | vfprintf(stderr, fmt, ap); |
36 | fprintf(stderr, "\n"); |
37 | va_end(ap); |
38 | conf_warnings++; |
39 | } |
40 | |
41 | static void conf_default_message_callback(const char *fmt, va_list ap) |
42 | { |
43 | printf("#\n# "); |
44 | vprintf(fmt, ap); |
45 | printf("\n#\n"); |
46 | } |
47 | |
48 | static void (*conf_message_callback) (const char *fmt, va_list ap) = |
49 | conf_default_message_callback; |
50 | void conf_set_message_callback(void (*fn) (const char *fmt, va_list ap)) |
51 | { |
52 | conf_message_callback = fn; |
53 | } |
54 | |
55 | static void conf_message(const char *fmt, ...) |
56 | { |
57 | va_list ap; |
58 | |
59 | va_start(ap, fmt); |
60 | if (conf_message_callback) |
61 | conf_message_callback(fmt, ap); |
62 | } |
63 | |
64 | const char *conf_get_configname(void) |
65 | { |
66 | char *name = getenv("KCONFIG_CONFIG"); |
67 | |
68 | return name ? name : ".config"; |
69 | } |
70 | |
71 | const char *conf_get_autoconfig_name(void) |
72 | { |
73 | char *name = getenv("KCONFIG_AUTOCONFIG"); |
74 | |
75 | return name ? name : "include/config/auto.conf"; |
76 | } |
77 | |
78 | static char *conf_expand_value(const char *in) |
79 | { |
80 | struct symbol *sym; |
81 | const char *src; |
82 | static char res_value[SYMBOL_MAXLENGTH]; |
83 | char *dst, name[SYMBOL_MAXLENGTH]; |
84 | |
85 | res_value[0] = 0; |
86 | dst = name; |
87 | while ((src = strchr(in, '$'))) { |
88 | strncat(res_value, in, src - in); |
89 | src++; |
90 | dst = name; |
91 | while (isalnum(*src) || *src == '_') |
92 | *dst++ = *src++; |
93 | *dst = 0; |
94 | sym = sym_lookup(name, 0); |
95 | sym_calc_value(sym); |
96 | strcat(res_value, sym_get_string_value(sym)); |
97 | in = src; |
98 | } |
99 | strcat(res_value, in); |
100 | |
101 | return res_value; |
102 | } |
103 | |
104 | char *conf_get_default_confname(void) |
105 | { |
106 | struct stat buf; |
107 | static char fullname[PATH_MAX+1]; |
108 | char *env, *name; |
109 | |
110 | name = conf_expand_value(conf_defname); |
111 | env = getenv(SRCTREE); |
112 | if (env) { |
113 | sprintf(fullname, "%s/%s", env, name); |
114 | if (!stat(fullname, &buf)) |
115 | return fullname; |
116 | } |
117 | return name; |
118 | } |
119 | |
120 | static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p) |
121 | { |
122 | char *p2; |
123 | |
124 | switch (sym->type) { |
125 | case S_TRISTATE: |
126 | if (p[0] == 'm') { |
127 | sym->def[def].tri = mod; |
128 | sym->flags |= def_flags; |
129 | break; |
130 | } |
131 | /* fall through */ |
132 | case S_BOOLEAN: |
133 | if (p[0] == 'y') { |
134 | sym->def[def].tri = yes; |
135 | sym->flags |= def_flags; |
136 | break; |
137 | } |
138 | if (p[0] == 'n') { |
139 | sym->def[def].tri = no; |
140 | sym->flags |= def_flags; |
141 | break; |
142 | } |
143 | if (def != S_DEF_AUTO) |
144 | conf_warning("symbol value '%s' invalid for %s", |
145 | p, sym->name); |
146 | return 1; |
147 | case S_OTHER: |
148 | if (*p != '"') { |
149 | for (p2 = p; *p2 && !isspace(*p2); p2++) |
150 | ; |
151 | sym->type = S_STRING; |
152 | goto done; |
153 | } |
154 | /* fall through */ |
155 | case S_STRING: |
156 | if (*p++ != '"') |
157 | break; |
158 | for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) { |
159 | if (*p2 == '"') { |
160 | *p2 = 0; |
161 | break; |
162 | } |
163 | memmove(p2, p2 + 1, strlen(p2)); |
164 | } |
165 | if (!p2) { |
166 | if (def != S_DEF_AUTO) |
167 | conf_warning("invalid string found"); |
168 | return 1; |
169 | } |
170 | /* fall through */ |
171 | case S_INT: |
172 | case S_HEX: |
173 | done: |
174 | if (sym_string_valid(sym, p)) { |
175 | sym->def[def].val = strdup(p); |
176 | sym->flags |= def_flags; |
177 | } else { |
178 | if (def != S_DEF_AUTO) |
179 | conf_warning("symbol value '%s' invalid for %s", |
180 | p, sym->name); |
181 | return 1; |
182 | } |
183 | break; |
184 | default: |
185 | ; |
186 | } |
187 | return 0; |
188 | } |
189 | |
190 | #define LINE_GROWTH 16 |
191 | static int add_byte(int c, char **lineptr, size_t slen, size_t *n) |
192 | { |
193 | char *nline; |
194 | size_t new_size = slen + 1; |
195 | if (new_size > *n) { |
196 | new_size += LINE_GROWTH - 1; |
197 | new_size *= 2; |
198 | nline = realloc(*lineptr, new_size); |
199 | if (!nline) |
200 | return -1; |
201 | |
202 | *lineptr = nline; |
203 | *n = new_size; |
204 | } |
205 | |
206 | (*lineptr)[slen] = c; |
207 | |
208 | return 0; |
209 | } |
210 | |
211 | static ssize_t compat_getline(char **lineptr, size_t *n, FILE *stream) |
212 | { |
213 | char *line = *lineptr; |
214 | size_t slen = 0; |
215 | |
216 | for (;;) { |
217 | int c = getc(stream); |
218 | |
219 | switch (c) { |
220 | case '\n': |
221 | if (add_byte(c, &line, slen, n) < 0) |
222 | goto e_out; |
223 | slen++; |
224 | /* fall through */ |
225 | case EOF: |
226 | if (add_byte('\0', &line, slen, n) < 0) |
227 | goto e_out; |
228 | *lineptr = line; |
229 | if (slen == 0) |
230 | return -1; |
231 | return slen; |
232 | default: |
233 | if (add_byte(c, &line, slen, n) < 0) |
234 | goto e_out; |
235 | slen++; |
236 | } |
237 | } |
238 | |
239 | e_out: |
240 | line[slen-1] = '\0'; |
241 | *lineptr = line; |
242 | return -1; |
243 | } |
244 | |
245 | int conf_read_simple(const char *name, int def) |
246 | { |
247 | FILE *in = NULL; |
248 | char *line = NULL; |
249 | size_t line_asize = 0; |
250 | char *p, *p2; |
251 | struct symbol *sym; |
252 | int i, def_flags; |
253 | |
254 | if (name) { |
255 | in = zconf_fopen(name); |
256 | } else { |
257 | struct property *prop; |
258 | |
259 | name = conf_get_configname(); |
260 | in = zconf_fopen(name); |
261 | if (in) |
262 | goto load; |
263 | sym_add_change_count(1); |
264 | if (!sym_defconfig_list) { |
265 | if (modules_sym) |
266 | sym_calc_value(modules_sym); |
267 | return 1; |
268 | } |
269 | |
270 | for_all_defaults(sym_defconfig_list, prop) { |
271 | if (expr_calc_value(prop->visible.expr) == no || |
272 | prop->expr->type != E_SYMBOL) |
273 | continue; |
274 | name = conf_expand_value(prop->expr->left.sym->name); |
275 | in = zconf_fopen(name); |
276 | if (in) { |
277 | conf_message(_("using defaults found in %s"), |
278 | name); |
279 | goto load; |
280 | } |
281 | } |
282 | } |
283 | if (!in) |
284 | return 1; |
285 | |
286 | load: |
287 | conf_filename = name; |
288 | conf_lineno = 0; |
289 | conf_warnings = 0; |
290 | conf_unsaved = 0; |
291 | |
292 | def_flags = SYMBOL_DEF << def; |
293 | for_all_symbols(i, sym) { |
294 | sym->flags |= SYMBOL_CHANGED; |
295 | sym->flags &= ~(def_flags|SYMBOL_VALID); |
296 | if (sym_is_choice(sym)) |
297 | sym->flags |= def_flags; |
298 | switch (sym->type) { |
299 | case S_INT: |
300 | case S_HEX: |
301 | case S_STRING: |
302 | if (sym->def[def].val) |
303 | free(sym->def[def].val); |
304 | /* fall through */ |
305 | default: |
306 | sym->def[def].val = NULL; |
307 | sym->def[def].tri = no; |
308 | } |
309 | } |
310 | |
311 | while (compat_getline(&line, &line_asize, in) != -1) { |
312 | conf_lineno++; |
313 | sym = NULL; |
314 | if (line[0] == '#') { |
315 | if (memcmp(line + 2, CONFIG_, strlen(CONFIG_))) |
316 | continue; |
317 | p = strchr(line + 2 + strlen(CONFIG_), ' '); |
318 | if (!p) |
319 | continue; |
320 | *p++ = 0; |
321 | if (strncmp(p, "is not set", 10)) |
322 | continue; |
323 | if (def == S_DEF_USER) { |
324 | sym = sym_find(line + 2 + strlen(CONFIG_)); |
325 | if (!sym) { |
326 | sym_add_change_count(1); |
327 | goto setsym; |
328 | } |
329 | } else { |
330 | sym = sym_lookup(line + 2 + strlen(CONFIG_), 0); |
331 | if (sym->type == S_UNKNOWN) |
332 | sym->type = S_BOOLEAN; |
333 | } |
334 | if (sym->flags & def_flags) { |
335 | conf_warning("override: reassigning to symbol %s", sym->name); |
336 | } |
337 | switch (sym->type) { |
338 | case S_BOOLEAN: |
339 | case S_TRISTATE: |
340 | sym->def[def].tri = no; |
341 | sym->flags |= def_flags; |
342 | break; |
343 | default: |
344 | ; |
345 | } |
346 | } else if (memcmp(line, CONFIG_, strlen(CONFIG_)) == 0) { |
347 | p = strchr(line + strlen(CONFIG_), '='); |
348 | if (!p) |
349 | continue; |
350 | *p++ = 0; |
351 | p2 = strchr(p, '\n'); |
352 | if (p2) { |
353 | *p2-- = 0; |
354 | if (*p2 == '\r') |
355 | *p2 = 0; |
356 | } |
357 | if (def == S_DEF_USER) { |
358 | sym = sym_find(line + strlen(CONFIG_)); |
359 | if (!sym) { |
360 | sym_add_change_count(1); |
361 | goto setsym; |
362 | } |
363 | } else { |
364 | sym = sym_lookup(line + strlen(CONFIG_), 0); |
365 | if (sym->type == S_UNKNOWN) |
366 | sym->type = S_OTHER; |
367 | } |
368 | if (sym->flags & def_flags) { |
369 | conf_warning("override: reassigning to symbol %s", sym->name); |
370 | } |
371 | if (conf_set_sym_val(sym, def, def_flags, p)) |
372 | continue; |
373 | } else { |
374 | if (line[0] != '\r' && line[0] != '\n') |
375 | conf_warning("unexpected data"); |
376 | continue; |
377 | } |
378 | setsym: |
379 | if (sym && sym_is_choice_value(sym)) { |
380 | struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym)); |
381 | switch (sym->def[def].tri) { |
382 | case no: |
383 | break; |
384 | case mod: |
385 | if (cs->def[def].tri == yes) { |
386 | conf_warning("%s creates inconsistent choice state", sym->name); |
387 | cs->flags &= ~def_flags; |
388 | } |
389 | break; |
390 | case yes: |
391 | if (cs->def[def].tri != no) |
392 | conf_warning("override: %s changes choice state", sym->name); |
393 | cs->def[def].val = sym; |
394 | break; |
395 | } |
396 | cs->def[def].tri = EXPR_OR(cs->def[def].tri, sym->def[def].tri); |
397 | } |
398 | } |
399 | free(line); |
400 | fclose(in); |
401 | |
402 | if (modules_sym) |
403 | sym_calc_value(modules_sym); |
404 | return 0; |
405 | } |
406 | |
407 | int conf_read(const char *name) |
408 | { |
409 | struct symbol *sym; |
410 | int i; |
411 | |
412 | sym_set_change_count(0); |
413 | |
414 | if (conf_read_simple(name, S_DEF_USER)) |
415 | return 1; |
416 | |
417 | for_all_symbols(i, sym) { |
418 | sym_calc_value(sym); |
419 | if (sym_is_choice(sym) || (sym->flags & SYMBOL_AUTO)) |
420 | continue; |
421 | if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) { |
422 | /* check that calculated value agrees with saved value */ |
423 | switch (sym->type) { |
424 | case S_BOOLEAN: |
425 | case S_TRISTATE: |
426 | if (sym->def[S_DEF_USER].tri != sym_get_tristate_value(sym)) |
427 | break; |
428 | if (!sym_is_choice(sym)) |
429 | continue; |
430 | /* fall through */ |
431 | default: |
432 | if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val)) |
433 | continue; |
434 | break; |
435 | } |
436 | } else if (!sym_has_value(sym) && !(sym->flags & SYMBOL_WRITE)) |
437 | /* no previous value and not saved */ |
438 | continue; |
439 | conf_unsaved++; |
440 | /* maybe print value in verbose mode... */ |
441 | } |
442 | |
443 | for_all_symbols(i, sym) { |
444 | if (sym_has_value(sym) && !sym_is_choice_value(sym)) { |
445 | /* Reset values of generates values, so they'll appear |
446 | * as new, if they should become visible, but that |
447 | * doesn't quite work if the Kconfig and the saved |
448 | * configuration disagree. |
449 | */ |
450 | if (sym->visible == no && !conf_unsaved) |
451 | sym->flags &= ~SYMBOL_DEF_USER; |
452 | switch (sym->type) { |
453 | case S_STRING: |
454 | case S_INT: |
455 | case S_HEX: |
456 | /* Reset a string value if it's out of range */ |
457 | if (sym_string_within_range(sym, sym->def[S_DEF_USER].val)) |
458 | break; |
459 | sym->flags &= ~(SYMBOL_VALID|SYMBOL_DEF_USER); |
460 | conf_unsaved++; |
461 | break; |
462 | default: |
463 | break; |
464 | } |
465 | } |
466 | } |
467 | |
468 | sym_add_change_count(conf_warnings || conf_unsaved); |
469 | |
470 | return 0; |
471 | } |
472 | |
473 | /* |
474 | * Kconfig configuration printer |
475 | * |
476 | * This printer is used when generating the resulting configuration after |
477 | * kconfig invocation and `defconfig' files. Unset symbol might be omitted by |
478 | * passing a non-NULL argument to the printer. |
479 | * |
480 | */ |
481 | static void |
482 | kconfig_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) |
483 | { |
484 | |
485 | switch (sym->type) { |
486 | case S_BOOLEAN: |
487 | case S_TRISTATE: |
488 | if (*value == 'n') { |
489 | bool skip_unset = (arg != NULL); |
490 | |
491 | if (!skip_unset) |
492 | fprintf(fp, "# %s%s is not set\n", |
493 | CONFIG_, sym->name); |
494 | return; |
495 | } |
496 | break; |
497 | default: |
498 | break; |
499 | } |
500 | |
501 | fprintf(fp, "%s%s=%s\n", CONFIG_, sym->name, value); |
502 | } |
503 | |
504 | static void |
505 | kconfig_print_comment(FILE *fp, const char *value, void *arg) |
506 | { |
507 | const char *p = value; |
508 | size_t l; |
509 | |
510 | for (;;) { |
511 | l = strcspn(p, "\n"); |
512 | fprintf(fp, "#"); |
513 | if (l) { |
514 | fprintf(fp, " "); |
515 | xfwrite(p, l, 1, fp); |
516 | p += l; |
517 | } |
518 | fprintf(fp, "\n"); |
519 | if (*p++ == '\0') |
520 | break; |
521 | } |
522 | } |
523 | |
524 | static struct conf_printer kconfig_printer_cb = |
525 | { |
526 | .print_symbol = kconfig_print_symbol, |
527 | .print_comment = kconfig_print_comment, |
528 | }; |
529 | |
530 | /* |
531 | * Header printer |
532 | * |
533 | * This printer is used when generating the `include/generated/autoconf.h' file. |
534 | */ |
535 | static void |
536 | header_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) |
537 | { |
538 | |
539 | switch (sym->type) { |
540 | case S_BOOLEAN: |
541 | case S_TRISTATE: { |
542 | const char *suffix = ""; |
543 | |
544 | switch (*value) { |
545 | case 'n': |
546 | break; |
547 | case 'm': |
548 | suffix = "_MODULE"; |
549 | /* fall through */ |
550 | default: |
551 | fprintf(fp, "#define %s%s%s 1\n", |
552 | CONFIG_, sym->name, suffix); |
553 | } |
554 | break; |
555 | } |
556 | case S_HEX: { |
557 | const char *prefix = ""; |
558 | |
559 | if (value[0] != '0' || (value[1] != 'x' && value[1] != 'X')) |
560 | prefix = "0x"; |
561 | fprintf(fp, "#define %s%s %s%s\n", |
562 | CONFIG_, sym->name, prefix, value); |
563 | break; |
564 | } |
565 | case S_STRING: |
566 | case S_INT: |
567 | fprintf(fp, "#define %s%s %s\n", |
568 | CONFIG_, sym->name, value); |
569 | break; |
570 | default: |
571 | break; |
572 | } |
573 | |
574 | } |
575 | |
576 | static void |
577 | header_print_comment(FILE *fp, const char *value, void *arg) |
578 | { |
579 | const char *p = value; |
580 | size_t l; |
581 | |
582 | fprintf(fp, "/*\n"); |
583 | for (;;) { |
584 | l = strcspn(p, "\n"); |
585 | fprintf(fp, " *"); |
586 | if (l) { |
587 | fprintf(fp, " "); |
588 | xfwrite(p, l, 1, fp); |
589 | p += l; |
590 | } |
591 | fprintf(fp, "\n"); |
592 | if (*p++ == '\0') |
593 | break; |
594 | } |
595 | fprintf(fp, " */\n"); |
596 | } |
597 | |
598 | static struct conf_printer header_printer_cb = |
599 | { |
600 | .print_symbol = header_print_symbol, |
601 | .print_comment = header_print_comment, |
602 | }; |
603 | |
604 | /* |
605 | * Tristate printer |
606 | * |
607 | * This printer is used when generating the `include/config/tristate.conf' file. |
608 | */ |
609 | static void |
610 | tristate_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) |
611 | { |
612 | |
613 | if (sym->type == S_TRISTATE && *value != 'n') |
614 | fprintf(fp, "%s%s=%c\n", CONFIG_, sym->name, (char)toupper(*value)); |
615 | } |
616 | |
617 | static struct conf_printer tristate_printer_cb = |
618 | { |
619 | .print_symbol = tristate_print_symbol, |
620 | .print_comment = kconfig_print_comment, |
621 | }; |
622 | |
623 | static void conf_write_symbol(FILE *fp, struct symbol *sym, |
624 | struct conf_printer *printer, void *printer_arg) |
625 | { |
626 | const char *str; |
627 | |
628 | switch (sym->type) { |
629 | case S_OTHER: |
630 | case S_UNKNOWN: |
631 | break; |
632 | case S_STRING: |
633 | str = sym_get_string_value(sym); |
634 | str = sym_escape_string_value(str); |
635 | printer->print_symbol(fp, sym, str, printer_arg); |
636 | free((void *)str); |
637 | break; |
638 | default: |
639 | str = sym_get_string_value(sym); |
640 | printer->print_symbol(fp, sym, str, printer_arg); |
641 | } |
642 | } |
643 | |
644 | static void |
645 | conf_write_heading(FILE *fp, struct conf_printer *printer, void *printer_arg) |
646 | { |
647 | char buf[256]; |
648 | |
649 | snprintf(buf, sizeof(buf), |
650 | "\n" |
651 | "Automatically generated file; DO NOT EDIT.\n" |
652 | "%s\n", |
653 | rootmenu.prompt->text); |
654 | |
655 | printer->print_comment(fp, buf, printer_arg); |
656 | } |
657 | |
658 | /* |
659 | * Write out a minimal config. |
660 | * All values that has default values are skipped as this is redundant. |
661 | */ |
662 | int conf_write_defconfig(const char *filename) |
663 | { |
664 | struct symbol *sym; |
665 | struct menu *menu; |
666 | FILE *out; |
667 | |
668 | out = fopen(filename, "w"); |
669 | if (!out) |
670 | return 1; |
671 | |
672 | sym_clear_all_valid(); |
673 | |
674 | /* Traverse all menus to find all relevant symbols */ |
675 | menu = rootmenu.list; |
676 | |
677 | while (menu != NULL) |
678 | { |
679 | sym = menu->sym; |
680 | if (sym == NULL) { |
681 | if (!menu_is_visible(menu)) |
682 | goto next_menu; |
683 | } else if (!sym_is_choice(sym)) { |
684 | sym_calc_value(sym); |
685 | if (!(sym->flags & SYMBOL_WRITE)) |
686 | goto next_menu; |
687 | sym->flags &= ~SYMBOL_WRITE; |
688 | /* If we cannot change the symbol - skip */ |
689 | if (!sym_is_changable(sym)) |
690 | goto next_menu; |
691 | /* If symbol equals to default value - skip */ |
692 | if (strcmp(sym_get_string_value(sym), sym_get_string_default(sym)) == 0) |
693 | goto next_menu; |
694 | |
695 | /* |
696 | * If symbol is a choice value and equals to the |
697 | * default for a choice - skip. |
698 | * But only if value is bool and equal to "y" and |
699 | * choice is not "optional". |
700 | * (If choice is "optional" then all values can be "n") |
701 | */ |
702 | if (sym_is_choice_value(sym)) { |
703 | struct symbol *cs; |
704 | struct symbol *ds; |
705 | |
706 | cs = prop_get_symbol(sym_get_choice_prop(sym)); |
707 | ds = sym_choice_default(cs); |
708 | if (!sym_is_optional(cs) && sym == ds) { |
709 | if ((sym->type == S_BOOLEAN) && |
710 | sym_get_tristate_value(sym) == yes) |
711 | goto next_menu; |
712 | } |
713 | } |
714 | conf_write_symbol(out, sym, &kconfig_printer_cb, NULL); |
715 | } |
716 | next_menu: |
717 | if (menu->list != NULL) { |
718 | menu = menu->list; |
719 | } |
720 | else if (menu->next != NULL) { |
721 | menu = menu->next; |
722 | } else { |
723 | while ((menu = menu->parent)) { |
724 | if (menu->next != NULL) { |
725 | menu = menu->next; |
726 | break; |
727 | } |
728 | } |
729 | } |
730 | } |
731 | fclose(out); |
732 | return 0; |
733 | } |
734 | |
735 | int conf_write(const char *name) |
736 | { |
737 | FILE *out; |
738 | struct symbol *sym; |
739 | struct menu *menu; |
740 | const char *basename; |
741 | const char *str; |
742 | char dirname[PATH_MAX+1], tmpname[PATH_MAX+1], newname[PATH_MAX+1]; |
743 | char *env; |
744 | |
745 | dirname[0] = 0; |
746 | if (name && name[0]) { |
747 | struct stat st; |
748 | char *slash; |
749 | |
750 | if (!stat(name, &st) && S_ISDIR(st.st_mode)) { |
751 | strcpy(dirname, name); |
752 | strcat(dirname, "/"); |
753 | basename = conf_get_configname(); |
754 | } else if ((slash = strrchr(name, '/'))) { |
755 | int size = slash - name + 1; |
756 | memcpy(dirname, name, size); |
757 | dirname[size] = 0; |
758 | if (slash[1]) |
759 | basename = slash + 1; |
760 | else |
761 | basename = conf_get_configname(); |
762 | } else |
763 | basename = name; |
764 | } else |
765 | basename = conf_get_configname(); |
766 | |
767 | sprintf(newname, "%s%s", dirname, basename); |
768 | env = getenv("KCONFIG_OVERWRITECONFIG"); |
769 | if (!env || !*env) { |
770 | sprintf(tmpname, "%s.tmpconfig.%d", dirname, (int)getpid()); |
771 | out = fopen(tmpname, "w"); |
772 | } else { |
773 | *tmpname = 0; |
774 | out = fopen(newname, "w"); |
775 | } |
776 | if (!out) |
777 | return 1; |
778 | |
779 | conf_write_heading(out, &kconfig_printer_cb, NULL); |
780 | |
781 | if (!conf_get_changed()) |
782 | sym_clear_all_valid(); |
783 | |
784 | menu = rootmenu.list; |
785 | while (menu) { |
786 | sym = menu->sym; |
787 | if (!sym) { |
788 | if (!menu_is_visible(menu)) |
789 | goto next; |
790 | str = menu_get_prompt(menu); |
791 | fprintf(out, "\n" |
792 | "#\n" |
793 | "# %s\n" |
794 | "#\n", str); |
795 | } else if (!(sym->flags & SYMBOL_CHOICE)) { |
796 | sym_calc_value(sym); |
797 | if (!(sym->flags & SYMBOL_WRITE)) |
798 | goto next; |
799 | sym->flags &= ~SYMBOL_WRITE; |
800 | |
801 | conf_write_symbol(out, sym, &kconfig_printer_cb, NULL); |
802 | } |
803 | |
804 | next: |
805 | if (menu->list) { |
806 | menu = menu->list; |
807 | continue; |
808 | } |
809 | if (menu->next) |
810 | menu = menu->next; |
811 | else while ((menu = menu->parent)) { |
812 | if (menu->next) { |
813 | menu = menu->next; |
814 | break; |
815 | } |
816 | } |
817 | } |
818 | fclose(out); |
819 | |
820 | if (*tmpname) { |
821 | strcat(dirname, basename); |
822 | strcat(dirname, ".old"); |
823 | rename(newname, dirname); |
824 | if (rename(tmpname, newname)) |
825 | return 1; |
826 | } |
827 | |
828 | conf_message(_("configuration written to %s"), newname); |
829 | |
830 | sym_set_change_count(0); |
831 | |
832 | return 0; |
833 | } |
834 | |
835 | static int conf_split_config(void) |
836 | { |
837 | const char *name; |
838 | char path[PATH_MAX+1]; |
839 | char *s, *d, c; |
840 | struct symbol *sym; |
841 | struct stat sb; |
842 | int res, i, fd; |
843 | |
844 | name = conf_get_autoconfig_name(); |
845 | conf_read_simple(name, S_DEF_AUTO); |
846 | |
847 | if (chdir("include/config")) |
848 | return 1; |
849 | |
850 | res = 0; |
851 | for_all_symbols(i, sym) { |
852 | sym_calc_value(sym); |
853 | if ((sym->flags & SYMBOL_AUTO) || !sym->name) |
854 | continue; |
855 | if (sym->flags & SYMBOL_WRITE) { |
856 | if (sym->flags & SYMBOL_DEF_AUTO) { |
857 | /* |
858 | * symbol has old and new value, |
859 | * so compare them... |
860 | */ |
861 | switch (sym->type) { |
862 | case S_BOOLEAN: |
863 | case S_TRISTATE: |
864 | if (sym_get_tristate_value(sym) == |
865 | sym->def[S_DEF_AUTO].tri) |
866 | continue; |
867 | break; |
868 | case S_STRING: |
869 | case S_HEX: |
870 | case S_INT: |
871 | if (!strcmp(sym_get_string_value(sym), |
872 | sym->def[S_DEF_AUTO].val)) |
873 | continue; |
874 | break; |
875 | default: |
876 | break; |
877 | } |
878 | } else { |
879 | /* |
880 | * If there is no old value, only 'no' (unset) |
881 | * is allowed as new value. |
882 | */ |
883 | switch (sym->type) { |
884 | case S_BOOLEAN: |
885 | case S_TRISTATE: |
886 | if (sym_get_tristate_value(sym) == no) |
887 | continue; |
888 | break; |
889 | default: |
890 | break; |
891 | } |
892 | } |
893 | } else if (!(sym->flags & SYMBOL_DEF_AUTO)) |
894 | /* There is neither an old nor a new value. */ |
895 | continue; |
896 | /* else |
897 | * There is an old value, but no new value ('no' (unset) |
898 | * isn't saved in auto.conf, so the old value is always |
899 | * different from 'no'). |
900 | */ |
901 | |
902 | /* Replace all '_' and append ".h" */ |
903 | s = sym->name; |
904 | d = path; |
905 | while ((c = *s++)) { |
906 | c = tolower(c); |
907 | *d++ = (c == '_') ? '/' : c; |
908 | } |
909 | strcpy(d, ".h"); |
910 | |
911 | /* Assume directory path already exists. */ |
912 | fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644); |
913 | if (fd == -1) { |
914 | if (errno != ENOENT) { |
915 | res = 1; |
916 | break; |
917 | } |
918 | /* |
919 | * Create directory components, |
920 | * unless they exist already. |
921 | */ |
922 | d = path; |
923 | while ((d = strchr(d, '/'))) { |
924 | *d = 0; |
925 | if (stat(path, &sb) && mkdir(path, 0755)) { |
926 | res = 1; |
927 | goto out; |
928 | } |
929 | *d++ = '/'; |
930 | } |
931 | /* Try it again. */ |
932 | fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644); |
933 | if (fd == -1) { |
934 | res = 1; |
935 | break; |
936 | } |
937 | } |
938 | close(fd); |
939 | } |
940 | out: |
941 | if (chdir("../..")) |
942 | return 1; |
943 | |
944 | return res; |
945 | } |
946 | |
947 | int conf_write_autoconf(void) |
948 | { |
949 | struct symbol *sym; |
950 | const char *name; |
951 | FILE *out, *tristate, *out_h; |
952 | int i; |
953 | |
954 | sym_clear_all_valid(); |
955 | |
956 | file_write_dep("include/config/auto.conf.cmd"); |
957 | |
958 | if (conf_split_config()) |
959 | return 1; |
960 | |
961 | out = fopen(".tmpconfig", "w"); |
962 | if (!out) |
963 | return 1; |
964 | |
965 | tristate = fopen(".tmpconfig_tristate", "w"); |
966 | if (!tristate) { |
967 | fclose(out); |
968 | return 1; |
969 | } |
970 | |
971 | out_h = fopen(".tmpconfig.h", "w"); |
972 | if (!out_h) { |
973 | fclose(out); |
974 | fclose(tristate); |
975 | return 1; |
976 | } |
977 | |
978 | conf_write_heading(out, &kconfig_printer_cb, NULL); |
979 | |
980 | conf_write_heading(tristate, &tristate_printer_cb, NULL); |
981 | |
982 | conf_write_heading(out_h, &header_printer_cb, NULL); |
983 | |
984 | for_all_symbols(i, sym) { |
985 | sym_calc_value(sym); |
986 | if (!(sym->flags & SYMBOL_WRITE) || !sym->name) |
987 | continue; |
988 | |
989 | /* write symbol to auto.conf, tristate and header files */ |
990 | conf_write_symbol(out, sym, &kconfig_printer_cb, (void *)1); |
991 | |
992 | conf_write_symbol(tristate, sym, &tristate_printer_cb, (void *)1); |
993 | |
994 | conf_write_symbol(out_h, sym, &header_printer_cb, NULL); |
995 | } |
996 | fclose(out); |
997 | fclose(tristate); |
998 | fclose(out_h); |
999 | |
1000 | name = getenv("KCONFIG_AUTOHEADER"); |
1001 | if (!name) |
1002 | name = "include/generated/autoconf.h"; |
1003 | if (rename(".tmpconfig.h", name)) |
1004 | return 1; |
1005 | name = getenv("KCONFIG_TRISTATE"); |
1006 | if (!name) |
1007 | name = "include/config/tristate.conf"; |
1008 | if (rename(".tmpconfig_tristate", name)) |
1009 | return 1; |
1010 | name = conf_get_autoconfig_name(); |
1011 | /* |
1012 | * This must be the last step, kbuild has a dependency on auto.conf |
1013 | * and this marks the successful completion of the previous steps. |
1014 | */ |
1015 | if (rename(".tmpconfig", name)) |
1016 | return 1; |
1017 | |
1018 | return 0; |
1019 | } |
1020 | |
1021 | static int sym_change_count; |
1022 | static void (*conf_changed_callback)(void); |
1023 | |
1024 | void sym_set_change_count(int count) |
1025 | { |
1026 | int _sym_change_count = sym_change_count; |
1027 | sym_change_count = count; |
1028 | if (conf_changed_callback && |
1029 | (bool)_sym_change_count != (bool)count) |
1030 | conf_changed_callback(); |
1031 | } |
1032 | |
1033 | void sym_add_change_count(int count) |
1034 | { |
1035 | sym_set_change_count(count + sym_change_count); |
1036 | } |
1037 | |
1038 | bool conf_get_changed(void) |
1039 | { |
1040 | return sym_change_count; |
1041 | } |
1042 | |
1043 | void conf_set_changed_callback(void (*fn)(void)) |
1044 | { |
1045 | conf_changed_callback = fn; |
1046 | } |
1047 | |
1048 | static bool randomize_choice_values(struct symbol *csym) |
1049 | { |
1050 | struct property *prop; |
1051 | struct symbol *sym; |
1052 | struct expr *e; |
1053 | int cnt, def; |
1054 | |
1055 | /* |
1056 | * If choice is mod then we may have more items selected |
1057 | * and if no then no-one. |
1058 | * In both cases stop. |
1059 | */ |
1060 | if (csym->curr.tri != yes) |
1061 | return false; |
1062 | |
1063 | prop = sym_get_choice_prop(csym); |
1064 | |
1065 | /* count entries in choice block */ |
1066 | cnt = 0; |
1067 | expr_list_for_each_sym(prop->expr, e, sym) |
1068 | cnt++; |
1069 | |
1070 | /* |
1071 | * find a random value and set it to yes, |
1072 | * set the rest to no so we have only one set |
1073 | */ |
1074 | def = (rand() % cnt); |
1075 | |
1076 | cnt = 0; |
1077 | expr_list_for_each_sym(prop->expr, e, sym) { |
1078 | if (def == cnt++) { |
1079 | sym->def[S_DEF_USER].tri = yes; |
1080 | csym->def[S_DEF_USER].val = sym; |
1081 | } |
1082 | else { |
1083 | sym->def[S_DEF_USER].tri = no; |
1084 | } |
1085 | sym->flags |= SYMBOL_DEF_USER; |
1086 | /* clear VALID to get value calculated */ |
1087 | sym->flags &= ~SYMBOL_VALID; |
1088 | } |
1089 | csym->flags |= SYMBOL_DEF_USER; |
1090 | /* clear VALID to get value calculated */ |
1091 | csym->flags &= ~(SYMBOL_VALID); |
1092 | |
1093 | return true; |
1094 | } |
1095 | |
1096 | void set_all_choice_values(struct symbol *csym) |
1097 | { |
1098 | struct property *prop; |
1099 | struct symbol *sym; |
1100 | struct expr *e; |
1101 | |
1102 | prop = sym_get_choice_prop(csym); |
1103 | |
1104 | /* |
1105 | * Set all non-assinged choice values to no |
1106 | */ |
1107 | expr_list_for_each_sym(prop->expr, e, sym) { |
1108 | if (!sym_has_value(sym)) |
1109 | sym->def[S_DEF_USER].tri = no; |
1110 | } |
1111 | csym->flags |= SYMBOL_DEF_USER; |
1112 | /* clear VALID to get value calculated */ |
1113 | csym->flags &= ~(SYMBOL_VALID | SYMBOL_NEED_SET_CHOICE_VALUES); |
1114 | } |
1115 | |
1116 | bool conf_set_all_new_symbols(enum conf_def_mode mode) |
1117 | { |
1118 | struct symbol *sym, *csym; |
1119 | int i, cnt, pby, pty, ptm; /* pby: probability of boolean = y |
1120 | * pty: probability of tristate = y |
1121 | * ptm: probability of tristate = m |
1122 | */ |
1123 | |
1124 | pby = 50; pty = ptm = 33; /* can't go as the default in switch-case |
1125 | * below, otherwise gcc whines about |
1126 | * -Wmaybe-uninitialized */ |
1127 | if (mode == def_random) { |
1128 | int n, p[3]; |
1129 | char *env = getenv("KCONFIG_PROBABILITY"); |
1130 | n = 0; |
1131 | while( env && *env ) { |
1132 | char *endp; |
1133 | int tmp = strtol( env, &endp, 10 ); |
1134 | if( tmp >= 0 && tmp <= 100 ) { |
1135 | p[n++] = tmp; |
1136 | } else { |
1137 | errno = ERANGE; |
1138 | perror( "KCONFIG_PROBABILITY" ); |
1139 | exit( 1 ); |
1140 | } |
1141 | env = (*endp == ':') ? endp+1 : endp; |
1142 | if( n >=3 ) { |
1143 | break; |
1144 | } |
1145 | } |
1146 | switch( n ) { |
1147 | case 1: |
1148 | pby = p[0]; ptm = pby/2; pty = pby-ptm; |
1149 | break; |
1150 | case 2: |
1151 | pty = p[0]; ptm = p[1]; pby = pty + ptm; |
1152 | break; |
1153 | case 3: |
1154 | pby = p[0]; pty = p[1]; ptm = p[2]; |
1155 | break; |
1156 | } |
1157 | |
1158 | if( pty+ptm > 100 ) { |
1159 | errno = ERANGE; |
1160 | perror( "KCONFIG_PROBABILITY" ); |
1161 | exit( 1 ); |
1162 | } |
1163 | } |
1164 | bool has_changed = false; |
1165 | |
1166 | for_all_symbols(i, sym) { |
1167 | if (sym_has_value(sym) || (sym->flags & SYMBOL_VALID)) |
1168 | continue; |
1169 | switch (sym_get_type(sym)) { |
1170 | case S_BOOLEAN: |
1171 | case S_TRISTATE: |
1172 | has_changed = true; |
1173 | switch (mode) { |
1174 | case def_yes: |
1175 | sym->def[S_DEF_USER].tri = yes; |
1176 | break; |
1177 | case def_mod: |
1178 | sym->def[S_DEF_USER].tri = mod; |
1179 | break; |
1180 | case def_no: |
1181 | if (sym->flags & SYMBOL_ALLNOCONFIG_Y) |
1182 | sym->def[S_DEF_USER].tri = yes; |
1183 | else |
1184 | sym->def[S_DEF_USER].tri = no; |
1185 | break; |
1186 | case def_random: |
1187 | sym->def[S_DEF_USER].tri = no; |
1188 | cnt = rand() % 100; |
1189 | if (sym->type == S_TRISTATE) { |
1190 | if (cnt < pty) |
1191 | sym->def[S_DEF_USER].tri = yes; |
1192 | else if (cnt < (pty+ptm)) |
1193 | sym->def[S_DEF_USER].tri = mod; |
1194 | } else if (cnt < pby) |
1195 | sym->def[S_DEF_USER].tri = yes; |
1196 | break; |
1197 | default: |
1198 | continue; |
1199 | } |
1200 | if (!(sym_is_choice(sym) && mode == def_random)) |
1201 | sym->flags |= SYMBOL_DEF_USER; |
1202 | break; |
1203 | default: |
1204 | break; |
1205 | } |
1206 | |
1207 | } |
1208 | |
1209 | sym_clear_all_valid(); |
1210 | |
1211 | /* |
1212 | * We have different type of choice blocks. |
1213 | * If curr.tri equals to mod then we can select several |
1214 | * choice symbols in one block. |
1215 | * In this case we do nothing. |
1216 | * If curr.tri equals yes then only one symbol can be |
1217 | * selected in a choice block and we set it to yes, |
1218 | * and the rest to no. |
1219 | */ |
1220 | if (mode != def_random) { |
1221 | for_all_symbols(i, csym) { |
1222 | if ((sym_is_choice(csym) && !sym_has_value(csym)) || |
1223 | sym_is_choice_value(csym)) |
1224 | csym->flags |= SYMBOL_NEED_SET_CHOICE_VALUES; |
1225 | } |
1226 | } |
1227 | |
1228 | for_all_symbols(i, csym) { |
1229 | if (sym_has_value(csym) || !sym_is_choice(csym)) |
1230 | continue; |
1231 | |
1232 | sym_calc_value(csym); |
1233 | if (mode == def_random) |
1234 | has_changed = randomize_choice_values(csym); |
1235 | else { |
1236 | set_all_choice_values(csym); |
1237 | has_changed = true; |
1238 | } |
1239 | } |
1240 | |
1241 | return has_changed; |
1242 | } |
1243 |
Branches:
ben-wpan
ben-wpan-stefan
javiroman/ks7010
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9