1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> |
4 | */ |
5 | |
6 | #include <ctype.h> |
7 | #include <limits.h> |
8 | #include <stdio.h> |
9 | #include <stdlib.h> |
10 | #include <string.h> |
11 | #include <time.h> |
12 | #include <unistd.h> |
13 | #include <getopt.h> |
14 | #include <sys/time.h> |
15 | #include <errno.h> |
16 | |
17 | #include "internal.h" |
18 | #include "lkc.h" |
19 | |
20 | static void conf(struct menu *); |
21 | static void check_conf(struct menu *); |
22 | |
23 | enum input_mode { |
24 | oldaskconfig, |
25 | syncconfig, |
26 | oldconfig, |
27 | allnoconfig, |
28 | allyesconfig, |
29 | allmodconfig, |
30 | alldefconfig, |
31 | randconfig, |
32 | defconfig, |
33 | savedefconfig, |
34 | listnewconfig, |
35 | helpnewconfig, |
36 | olddefconfig, |
37 | yes2modconfig, |
38 | mod2yesconfig, |
39 | mod2noconfig, |
40 | }; |
41 | static enum input_mode input_mode = oldaskconfig; |
42 | static int input_mode_opt; |
43 | static int indent = 1; |
44 | static int tty_stdio; |
45 | static int sync_kconfig; |
46 | static int conf_cnt; |
47 | static char line[PATH_MAX]; |
48 | static struct menu *rootEntry; |
49 | |
50 | static void print_help(struct menu *) |
51 | { |
52 | struct gstr help = str_new(); |
53 | |
54 | menu_get_ext_help(menu, help: &help); |
55 | |
56 | printf(format: "\n%s\n" , str_get(gs: &help)); |
57 | str_free(gs: &help); |
58 | } |
59 | |
60 | static void strip(char *str) |
61 | { |
62 | char *p = str; |
63 | int l; |
64 | |
65 | while ((isspace(*p))) |
66 | p++; |
67 | l = strlen(s: p); |
68 | if (p != str) |
69 | memmove(dest: str, src: p, n: l + 1); |
70 | if (!l) |
71 | return; |
72 | p = str + l - 1; |
73 | while ((isspace(*p))) |
74 | *p-- = 0; |
75 | } |
76 | |
77 | /* Helper function to facilitate fgets() by Jean Sacren. */ |
78 | static void xfgets(char *str, int size, FILE *in) |
79 | { |
80 | if (!fgets(s: str, n: size, stream: in)) |
81 | fprintf(stderr, format: "\nError in reading or end of file.\n" ); |
82 | |
83 | if (!tty_stdio) |
84 | printf(format: "%s" , str); |
85 | } |
86 | |
87 | static void set_randconfig_seed(void) |
88 | { |
89 | unsigned int seed; |
90 | char *env; |
91 | bool seed_set = false; |
92 | |
93 | env = getenv(name: "KCONFIG_SEED" ); |
94 | if (env && *env) { |
95 | char *endp; |
96 | |
97 | seed = strtol(nptr: env, endptr: &endp, base: 0); |
98 | if (*endp == '\0') |
99 | seed_set = true; |
100 | } |
101 | |
102 | if (!seed_set) { |
103 | struct timeval now; |
104 | |
105 | /* |
106 | * Use microseconds derived seed, compensate for systems where it may |
107 | * be zero. |
108 | */ |
109 | gettimeofday(tv: &now, NULL); |
110 | seed = (now.tv_sec + 1) * (now.tv_usec + 1); |
111 | } |
112 | |
113 | printf(format: "KCONFIG_SEED=0x%X\n" , seed); |
114 | srand(seed: seed); |
115 | } |
116 | |
117 | static bool randomize_choice_values(struct symbol *csym) |
118 | { |
119 | struct property *prop; |
120 | struct symbol *sym; |
121 | struct expr *e; |
122 | int cnt, def; |
123 | |
124 | /* |
125 | * If choice is mod then we may have more items selected |
126 | * and if no then no-one. |
127 | * In both cases stop. |
128 | */ |
129 | if (csym->curr.tri != yes) |
130 | return false; |
131 | |
132 | prop = sym_get_choice_prop(sym: csym); |
133 | |
134 | /* count entries in choice block */ |
135 | cnt = 0; |
136 | expr_list_for_each_sym(prop->expr, e, sym) |
137 | cnt++; |
138 | |
139 | /* |
140 | * find a random value and set it to yes, |
141 | * set the rest to no so we have only one set |
142 | */ |
143 | def = rand() % cnt; |
144 | |
145 | cnt = 0; |
146 | expr_list_for_each_sym(prop->expr, e, sym) { |
147 | if (def == cnt++) { |
148 | sym->def[S_DEF_USER].tri = yes; |
149 | csym->def[S_DEF_USER].val = sym; |
150 | } else { |
151 | sym->def[S_DEF_USER].tri = no; |
152 | } |
153 | sym->flags |= SYMBOL_DEF_USER; |
154 | /* clear VALID to get value calculated */ |
155 | sym->flags &= ~SYMBOL_VALID; |
156 | } |
157 | csym->flags |= SYMBOL_DEF_USER; |
158 | /* clear VALID to get value calculated */ |
159 | csym->flags &= ~SYMBOL_VALID; |
160 | |
161 | return true; |
162 | } |
163 | |
164 | enum conf_def_mode { |
165 | def_default, |
166 | def_yes, |
167 | def_mod, |
168 | def_no, |
169 | def_random |
170 | }; |
171 | |
172 | static bool conf_set_all_new_symbols(enum conf_def_mode mode) |
173 | { |
174 | struct symbol *sym, *csym; |
175 | int cnt; |
176 | /* |
177 | * can't go as the default in switch-case below, otherwise gcc whines |
178 | * about -Wmaybe-uninitialized |
179 | */ |
180 | int pby = 50; /* probability of bool = y */ |
181 | int pty = 33; /* probability of tristate = y */ |
182 | int ptm = 33; /* probability of tristate = m */ |
183 | bool has_changed = false; |
184 | |
185 | if (mode == def_random) { |
186 | int n, p[3]; |
187 | char *env = getenv(name: "KCONFIG_PROBABILITY" ); |
188 | |
189 | n = 0; |
190 | while (env && *env) { |
191 | char *endp; |
192 | int tmp = strtol(nptr: env, endptr: &endp, base: 10); |
193 | |
194 | if (tmp >= 0 && tmp <= 100) { |
195 | p[n++] = tmp; |
196 | } else { |
197 | errno = ERANGE; |
198 | perror(s: "KCONFIG_PROBABILITY" ); |
199 | exit(status: 1); |
200 | } |
201 | env = (*endp == ':') ? endp + 1 : endp; |
202 | if (n >= 3) |
203 | break; |
204 | } |
205 | switch (n) { |
206 | case 1: |
207 | pby = p[0]; |
208 | ptm = pby / 2; |
209 | pty = pby - ptm; |
210 | break; |
211 | case 2: |
212 | pty = p[0]; |
213 | ptm = p[1]; |
214 | pby = pty + ptm; |
215 | break; |
216 | case 3: |
217 | pby = p[0]; |
218 | pty = p[1]; |
219 | ptm = p[2]; |
220 | break; |
221 | } |
222 | |
223 | if (pty + ptm > 100) { |
224 | errno = ERANGE; |
225 | perror(s: "KCONFIG_PROBABILITY" ); |
226 | exit(status: 1); |
227 | } |
228 | } |
229 | |
230 | for_all_symbols(sym) { |
231 | if (sym_has_value(sym) || sym->flags & SYMBOL_VALID) |
232 | continue; |
233 | switch (sym_get_type(sym)) { |
234 | case S_BOOLEAN: |
235 | case S_TRISTATE: |
236 | has_changed = true; |
237 | switch (mode) { |
238 | case def_yes: |
239 | sym->def[S_DEF_USER].tri = yes; |
240 | break; |
241 | case def_mod: |
242 | sym->def[S_DEF_USER].tri = mod; |
243 | break; |
244 | case def_no: |
245 | sym->def[S_DEF_USER].tri = no; |
246 | break; |
247 | case def_random: |
248 | sym->def[S_DEF_USER].tri = no; |
249 | cnt = rand() % 100; |
250 | if (sym->type == S_TRISTATE) { |
251 | if (cnt < pty) |
252 | sym->def[S_DEF_USER].tri = yes; |
253 | else if (cnt < pty + ptm) |
254 | sym->def[S_DEF_USER].tri = mod; |
255 | } else if (cnt < pby) |
256 | sym->def[S_DEF_USER].tri = yes; |
257 | break; |
258 | default: |
259 | continue; |
260 | } |
261 | if (!(sym_is_choice(sym) && mode == def_random)) |
262 | sym->flags |= SYMBOL_DEF_USER; |
263 | break; |
264 | default: |
265 | break; |
266 | } |
267 | |
268 | } |
269 | |
270 | sym_clear_all_valid(); |
271 | |
272 | /* |
273 | * We have different type of choice blocks. |
274 | * If curr.tri equals to mod then we can select several |
275 | * choice symbols in one block. |
276 | * In this case we do nothing. |
277 | * If curr.tri equals yes then only one symbol can be |
278 | * selected in a choice block and we set it to yes, |
279 | * and the rest to no. |
280 | */ |
281 | if (mode != def_random) { |
282 | for_all_symbols(csym) { |
283 | if ((sym_is_choice(sym: csym) && !sym_has_value(sym: csym)) || |
284 | sym_is_choice_value(sym: csym)) |
285 | csym->flags |= SYMBOL_NEED_SET_CHOICE_VALUES; |
286 | } |
287 | } |
288 | |
289 | for_all_symbols(csym) { |
290 | if (sym_has_value(sym: csym) || !sym_is_choice(sym: csym)) |
291 | continue; |
292 | |
293 | sym_calc_value(sym: csym); |
294 | if (mode == def_random) |
295 | has_changed |= randomize_choice_values(csym); |
296 | else { |
297 | set_all_choice_values(csym); |
298 | has_changed = true; |
299 | } |
300 | } |
301 | |
302 | return has_changed; |
303 | } |
304 | |
305 | static void conf_rewrite_tristates(tristate old_val, tristate new_val) |
306 | { |
307 | struct symbol *sym; |
308 | |
309 | for_all_symbols(sym) { |
310 | if (sym_get_type(sym) == S_TRISTATE && |
311 | sym->def[S_DEF_USER].tri == old_val) |
312 | sym->def[S_DEF_USER].tri = new_val; |
313 | } |
314 | sym_clear_all_valid(); |
315 | } |
316 | |
317 | static int conf_askvalue(struct symbol *sym, const char *def) |
318 | { |
319 | if (!sym_has_value(sym)) |
320 | printf(format: "(NEW) " ); |
321 | |
322 | line[0] = '\n'; |
323 | line[1] = 0; |
324 | |
325 | if (!sym_is_changeable(sym)) { |
326 | printf(format: "%s\n" , def); |
327 | line[0] = '\n'; |
328 | line[1] = 0; |
329 | return 0; |
330 | } |
331 | |
332 | switch (input_mode) { |
333 | case oldconfig: |
334 | case syncconfig: |
335 | if (sym_has_value(sym)) { |
336 | printf(format: "%s\n" , def); |
337 | return 0; |
338 | } |
339 | /* fall through */ |
340 | default: |
341 | fflush(stdout); |
342 | xfgets(str: line, size: sizeof(line), stdin); |
343 | break; |
344 | } |
345 | |
346 | return 1; |
347 | } |
348 | |
349 | static int conf_string(struct menu *) |
350 | { |
351 | struct symbol *sym = menu->sym; |
352 | const char *def; |
353 | |
354 | while (1) { |
355 | printf(format: "%*s%s " , indent - 1, "" , menu->prompt->text); |
356 | printf(format: "(%s) " , sym->name); |
357 | def = sym_get_string_value(sym); |
358 | if (def) |
359 | printf(format: "[%s] " , def); |
360 | if (!conf_askvalue(sym, def)) |
361 | return 0; |
362 | switch (line[0]) { |
363 | case '\n': |
364 | break; |
365 | case '?': |
366 | /* print help */ |
367 | if (line[1] == '\n') { |
368 | print_help(menu); |
369 | def = NULL; |
370 | break; |
371 | } |
372 | /* fall through */ |
373 | default: |
374 | line[strlen(s: line)-1] = 0; |
375 | def = line; |
376 | } |
377 | if (def && sym_set_string_value(sym, newval: def)) |
378 | return 0; |
379 | } |
380 | } |
381 | |
382 | static int conf_sym(struct menu *) |
383 | { |
384 | struct symbol *sym = menu->sym; |
385 | tristate oldval, newval; |
386 | |
387 | while (1) { |
388 | printf(format: "%*s%s " , indent - 1, "" , menu->prompt->text); |
389 | if (sym->name) |
390 | printf(format: "(%s) " , sym->name); |
391 | putchar(c: '['); |
392 | oldval = sym_get_tristate_value(sym); |
393 | switch (oldval) { |
394 | case no: |
395 | putchar(c: 'N'); |
396 | break; |
397 | case mod: |
398 | putchar(c: 'M'); |
399 | break; |
400 | case yes: |
401 | putchar(c: 'Y'); |
402 | break; |
403 | } |
404 | if (oldval != no && sym_tristate_within_range(sym, tri: no)) |
405 | printf(format: "/n" ); |
406 | if (oldval != mod && sym_tristate_within_range(sym, tri: mod)) |
407 | printf(format: "/m" ); |
408 | if (oldval != yes && sym_tristate_within_range(sym, tri: yes)) |
409 | printf(format: "/y" ); |
410 | printf(format: "/?] " ); |
411 | if (!conf_askvalue(sym, def: sym_get_string_value(sym))) |
412 | return 0; |
413 | strip(str: line); |
414 | |
415 | switch (line[0]) { |
416 | case 'n': |
417 | case 'N': |
418 | newval = no; |
419 | if (!line[1] || !strcmp(s1: &line[1], s2: "o" )) |
420 | break; |
421 | continue; |
422 | case 'm': |
423 | case 'M': |
424 | newval = mod; |
425 | if (!line[1]) |
426 | break; |
427 | continue; |
428 | case 'y': |
429 | case 'Y': |
430 | newval = yes; |
431 | if (!line[1] || !strcmp(s1: &line[1], s2: "es" )) |
432 | break; |
433 | continue; |
434 | case 0: |
435 | newval = oldval; |
436 | break; |
437 | case '?': |
438 | goto help; |
439 | default: |
440 | continue; |
441 | } |
442 | if (sym_set_tristate_value(sym, tri: newval)) |
443 | return 0; |
444 | help: |
445 | print_help(menu); |
446 | } |
447 | } |
448 | |
449 | static int conf_choice(struct menu *) |
450 | { |
451 | struct symbol *sym, *def_sym; |
452 | struct menu *child; |
453 | bool is_new; |
454 | |
455 | sym = menu->sym; |
456 | is_new = !sym_has_value(sym); |
457 | if (sym_is_changeable(sym)) { |
458 | conf_sym(menu); |
459 | sym_calc_value(sym); |
460 | switch (sym_get_tristate_value(sym)) { |
461 | case no: |
462 | return 1; |
463 | case mod: |
464 | return 0; |
465 | case yes: |
466 | break; |
467 | } |
468 | } else { |
469 | switch (sym_get_tristate_value(sym)) { |
470 | case no: |
471 | return 1; |
472 | case mod: |
473 | printf(format: "%*s%s\n" , indent - 1, "" , menu_get_prompt(menu)); |
474 | return 0; |
475 | case yes: |
476 | break; |
477 | } |
478 | } |
479 | |
480 | while (1) { |
481 | int cnt, def; |
482 | |
483 | printf(format: "%*s%s\n" , indent - 1, "" , menu_get_prompt(menu)); |
484 | def_sym = sym_get_choice_value(sym); |
485 | cnt = def = 0; |
486 | line[0] = 0; |
487 | for (child = menu->list; child; child = child->next) { |
488 | if (!menu_is_visible(menu: child)) |
489 | continue; |
490 | if (!child->sym) { |
491 | printf(format: "%*c %s\n" , indent, '*', menu_get_prompt(menu: child)); |
492 | continue; |
493 | } |
494 | cnt++; |
495 | if (child->sym == def_sym) { |
496 | def = cnt; |
497 | printf(format: "%*c" , indent, '>'); |
498 | } else |
499 | printf(format: "%*c" , indent, ' '); |
500 | printf(format: " %d. %s" , cnt, menu_get_prompt(menu: child)); |
501 | if (child->sym->name) |
502 | printf(format: " (%s)" , child->sym->name); |
503 | if (!sym_has_value(sym: child->sym)) |
504 | printf(format: " (NEW)" ); |
505 | printf(format: "\n" ); |
506 | } |
507 | printf(format: "%*schoice" , indent - 1, "" ); |
508 | if (cnt == 1) { |
509 | printf(format: "[1]: 1\n" ); |
510 | goto conf_childs; |
511 | } |
512 | printf(format: "[1-%d?]: " , cnt); |
513 | switch (input_mode) { |
514 | case oldconfig: |
515 | case syncconfig: |
516 | if (!is_new) { |
517 | cnt = def; |
518 | printf(format: "%d\n" , cnt); |
519 | break; |
520 | } |
521 | /* fall through */ |
522 | case oldaskconfig: |
523 | fflush(stdout); |
524 | xfgets(str: line, size: sizeof(line), stdin); |
525 | strip(str: line); |
526 | if (line[0] == '?') { |
527 | print_help(menu); |
528 | continue; |
529 | } |
530 | if (!line[0]) |
531 | cnt = def; |
532 | else if (isdigit(line[0])) |
533 | cnt = atoi(nptr: line); |
534 | else |
535 | continue; |
536 | break; |
537 | default: |
538 | break; |
539 | } |
540 | |
541 | conf_childs: |
542 | for (child = menu->list; child; child = child->next) { |
543 | if (!child->sym || !menu_is_visible(menu: child)) |
544 | continue; |
545 | if (!--cnt) |
546 | break; |
547 | } |
548 | if (!child) |
549 | continue; |
550 | if (line[0] && line[strlen(s: line) - 1] == '?') { |
551 | print_help(menu: child); |
552 | continue; |
553 | } |
554 | sym_set_tristate_value(sym: child->sym, tri: yes); |
555 | return 1; |
556 | } |
557 | } |
558 | |
559 | static void conf(struct menu *) |
560 | { |
561 | struct symbol *sym; |
562 | struct property *prop; |
563 | struct menu *child; |
564 | |
565 | if (!menu_is_visible(menu)) |
566 | return; |
567 | |
568 | sym = menu->sym; |
569 | prop = menu->prompt; |
570 | if (prop) { |
571 | const char *prompt; |
572 | |
573 | switch (prop->type) { |
574 | case P_MENU: |
575 | /* |
576 | * Except in oldaskconfig mode, we show only menus that |
577 | * contain new symbols. |
578 | */ |
579 | if (input_mode != oldaskconfig && rootEntry != menu) { |
580 | check_conf(menu); |
581 | return; |
582 | } |
583 | /* fall through */ |
584 | case P_COMMENT: |
585 | prompt = menu_get_prompt(menu); |
586 | if (prompt) |
587 | printf(format: "%*c\n%*c %s\n%*c\n" , |
588 | indent, '*', |
589 | indent, '*', prompt, |
590 | indent, '*'); |
591 | default: |
592 | ; |
593 | } |
594 | } |
595 | |
596 | if (!sym) |
597 | goto conf_childs; |
598 | |
599 | if (sym_is_choice(sym)) { |
600 | conf_choice(menu); |
601 | if (sym->curr.tri != mod) |
602 | return; |
603 | goto conf_childs; |
604 | } |
605 | |
606 | switch (sym->type) { |
607 | case S_INT: |
608 | case S_HEX: |
609 | case S_STRING: |
610 | conf_string(menu); |
611 | break; |
612 | default: |
613 | conf_sym(menu); |
614 | break; |
615 | } |
616 | |
617 | conf_childs: |
618 | if (sym) |
619 | indent += 2; |
620 | for (child = menu->list; child; child = child->next) |
621 | conf(menu: child); |
622 | if (sym) |
623 | indent -= 2; |
624 | } |
625 | |
626 | static void check_conf(struct menu *) |
627 | { |
628 | struct symbol *sym; |
629 | struct menu *child; |
630 | |
631 | if (!menu_is_visible(menu)) |
632 | return; |
633 | |
634 | sym = menu->sym; |
635 | if (sym && !sym_has_value(sym) && |
636 | (sym_is_changeable(sym) || |
637 | (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes))) { |
638 | |
639 | switch (input_mode) { |
640 | case listnewconfig: |
641 | if (sym->name) |
642 | print_symbol_for_listconfig(sym); |
643 | break; |
644 | case helpnewconfig: |
645 | printf(format: "-----\n" ); |
646 | print_help(menu); |
647 | printf(format: "-----\n" ); |
648 | break; |
649 | default: |
650 | if (!conf_cnt++) |
651 | printf(format: "*\n* Restart config...\n*\n" ); |
652 | rootEntry = menu_get_parent_menu(menu); |
653 | conf(menu: rootEntry); |
654 | break; |
655 | } |
656 | } |
657 | |
658 | for (child = menu->list; child; child = child->next) |
659 | check_conf(menu: child); |
660 | } |
661 | |
662 | static const struct option long_opts[] = { |
663 | {"help" , no_argument, NULL, 'h'}, |
664 | {"silent" , no_argument, NULL, 's'}, |
665 | {"oldaskconfig" , no_argument, &input_mode_opt, oldaskconfig}, |
666 | {"oldconfig" , no_argument, &input_mode_opt, oldconfig}, |
667 | {"syncconfig" , no_argument, &input_mode_opt, syncconfig}, |
668 | {"defconfig" , required_argument, &input_mode_opt, defconfig}, |
669 | {"savedefconfig" , required_argument, &input_mode_opt, savedefconfig}, |
670 | {"allnoconfig" , no_argument, &input_mode_opt, allnoconfig}, |
671 | {"allyesconfig" , no_argument, &input_mode_opt, allyesconfig}, |
672 | {"allmodconfig" , no_argument, &input_mode_opt, allmodconfig}, |
673 | {"alldefconfig" , no_argument, &input_mode_opt, alldefconfig}, |
674 | {"randconfig" , no_argument, &input_mode_opt, randconfig}, |
675 | {"listnewconfig" , no_argument, &input_mode_opt, listnewconfig}, |
676 | {"helpnewconfig" , no_argument, &input_mode_opt, helpnewconfig}, |
677 | {"olddefconfig" , no_argument, &input_mode_opt, olddefconfig}, |
678 | {"yes2modconfig" , no_argument, &input_mode_opt, yes2modconfig}, |
679 | {"mod2yesconfig" , no_argument, &input_mode_opt, mod2yesconfig}, |
680 | {"mod2noconfig" , no_argument, &input_mode_opt, mod2noconfig}, |
681 | {NULL, 0, NULL, 0} |
682 | }; |
683 | |
684 | static void conf_usage(const char *progname) |
685 | { |
686 | printf(format: "Usage: %s [options] <kconfig-file>\n" , progname); |
687 | printf(format: "\n" ); |
688 | printf(format: "Generic options:\n" ); |
689 | printf(format: " -h, --help Print this message and exit.\n" ); |
690 | printf(format: " -s, --silent Do not print log.\n" ); |
691 | printf(format: "\n" ); |
692 | printf(format: "Mode options:\n" ); |
693 | printf(format: " --listnewconfig List new options\n" ); |
694 | printf(format: " --helpnewconfig List new options and help text\n" ); |
695 | printf(format: " --oldaskconfig Start a new configuration using a line-oriented program\n" ); |
696 | printf(format: " --oldconfig Update a configuration using a provided .config as base\n" ); |
697 | printf(format: " --syncconfig Similar to oldconfig but generates configuration in\n" |
698 | " include/{generated/,config/}\n" ); |
699 | printf(format: " --olddefconfig Same as oldconfig but sets new symbols to their default value\n" ); |
700 | printf(format: " --defconfig <file> New config with default defined in <file>\n" ); |
701 | printf(format: " --savedefconfig <file> Save the minimal current configuration to <file>\n" ); |
702 | printf(format: " --allnoconfig New config where all options are answered with no\n" ); |
703 | printf(format: " --allyesconfig New config where all options are answered with yes\n" ); |
704 | printf(format: " --allmodconfig New config where all options are answered with mod\n" ); |
705 | printf(format: " --alldefconfig New config with all symbols set to default\n" ); |
706 | printf(format: " --randconfig New config with random answer to all options\n" ); |
707 | printf(format: " --yes2modconfig Change answers from yes to mod if possible\n" ); |
708 | printf(format: " --mod2yesconfig Change answers from mod to yes if possible\n" ); |
709 | printf(format: " --mod2noconfig Change answers from mod to no if possible\n" ); |
710 | printf(format: " (If none of the above is given, --oldaskconfig is the default)\n" ); |
711 | } |
712 | |
713 | int main(int ac, char **av) |
714 | { |
715 | const char *progname = av[0]; |
716 | int opt; |
717 | const char *name, *defconfig_file = NULL /* gcc uninit */; |
718 | int no_conf_write = 0; |
719 | |
720 | tty_stdio = isatty(fd: 0) && isatty(fd: 1); |
721 | |
722 | while ((opt = getopt_long(argc: ac, argv: av, shortopts: "hs" , longopts: long_opts, NULL)) != -1) { |
723 | switch (opt) { |
724 | case 'h': |
725 | conf_usage(progname); |
726 | exit(status: 1); |
727 | break; |
728 | case 's': |
729 | conf_set_message_callback(NULL); |
730 | break; |
731 | case 0: |
732 | input_mode = input_mode_opt; |
733 | switch (input_mode) { |
734 | case syncconfig: |
735 | /* |
736 | * syncconfig is invoked during the build stage. |
737 | * Suppress distracting |
738 | * "configuration written to ..." |
739 | */ |
740 | conf_set_message_callback(NULL); |
741 | sync_kconfig = 1; |
742 | break; |
743 | case defconfig: |
744 | case savedefconfig: |
745 | defconfig_file = optarg; |
746 | break; |
747 | case randconfig: |
748 | set_randconfig_seed(); |
749 | break; |
750 | default: |
751 | break; |
752 | } |
753 | default: |
754 | break; |
755 | } |
756 | } |
757 | if (ac == optind) { |
758 | fprintf(stderr, format: "%s: Kconfig file missing\n" , av[0]); |
759 | conf_usage(progname); |
760 | exit(status: 1); |
761 | } |
762 | conf_parse(name: av[optind]); |
763 | //zconfdump(stdout); |
764 | |
765 | switch (input_mode) { |
766 | case defconfig: |
767 | if (conf_read(name: defconfig_file)) { |
768 | fprintf(stderr, |
769 | format: "***\n" |
770 | "*** Can't find default configuration \"%s\"!\n" |
771 | "***\n" , |
772 | defconfig_file); |
773 | exit(status: 1); |
774 | } |
775 | break; |
776 | case savedefconfig: |
777 | case syncconfig: |
778 | case oldaskconfig: |
779 | case oldconfig: |
780 | case listnewconfig: |
781 | case helpnewconfig: |
782 | case olddefconfig: |
783 | case yes2modconfig: |
784 | case mod2yesconfig: |
785 | case mod2noconfig: |
786 | conf_read(NULL); |
787 | break; |
788 | case allnoconfig: |
789 | case allyesconfig: |
790 | case allmodconfig: |
791 | case alldefconfig: |
792 | case randconfig: |
793 | name = getenv(name: "KCONFIG_ALLCONFIG" ); |
794 | if (!name) |
795 | break; |
796 | if ((strcmp(s1: name, s2: "" ) != 0) && (strcmp(s1: name, s2: "1" ) != 0)) { |
797 | if (conf_read_simple(name, S_DEF_USER)) { |
798 | fprintf(stderr, |
799 | format: "*** Can't read seed configuration \"%s\"!\n" , |
800 | name); |
801 | exit(status: 1); |
802 | } |
803 | break; |
804 | } |
805 | switch (input_mode) { |
806 | case allnoconfig: name = "allno.config" ; break; |
807 | case allyesconfig: name = "allyes.config" ; break; |
808 | case allmodconfig: name = "allmod.config" ; break; |
809 | case alldefconfig: name = "alldef.config" ; break; |
810 | case randconfig: name = "allrandom.config" ; break; |
811 | default: break; |
812 | } |
813 | if (conf_read_simple(name, S_DEF_USER) && |
814 | conf_read_simple(name: "all.config" , S_DEF_USER)) { |
815 | fprintf(stderr, |
816 | format: "*** KCONFIG_ALLCONFIG set, but no \"%s\" or \"all.config\" file found\n" , |
817 | name); |
818 | exit(status: 1); |
819 | } |
820 | break; |
821 | default: |
822 | break; |
823 | } |
824 | |
825 | if (conf_errors()) |
826 | exit(status: 1); |
827 | |
828 | if (sync_kconfig) { |
829 | name = getenv(name: "KCONFIG_NOSILENTUPDATE" ); |
830 | if (name && *name) { |
831 | if (conf_get_changed()) { |
832 | fprintf(stderr, |
833 | format: "\n*** The configuration requires explicit update.\n\n" ); |
834 | return 1; |
835 | } |
836 | no_conf_write = 1; |
837 | } |
838 | } |
839 | |
840 | switch (input_mode) { |
841 | case allnoconfig: |
842 | conf_set_all_new_symbols(mode: def_no); |
843 | break; |
844 | case allyesconfig: |
845 | conf_set_all_new_symbols(mode: def_yes); |
846 | break; |
847 | case allmodconfig: |
848 | conf_set_all_new_symbols(mode: def_mod); |
849 | break; |
850 | case alldefconfig: |
851 | conf_set_all_new_symbols(mode: def_default); |
852 | break; |
853 | case randconfig: |
854 | /* Really nothing to do in this loop */ |
855 | while (conf_set_all_new_symbols(mode: def_random)) ; |
856 | break; |
857 | case defconfig: |
858 | conf_set_all_new_symbols(mode: def_default); |
859 | break; |
860 | case savedefconfig: |
861 | break; |
862 | case yes2modconfig: |
863 | conf_rewrite_tristates(old_val: yes, new_val: mod); |
864 | break; |
865 | case mod2yesconfig: |
866 | conf_rewrite_tristates(old_val: mod, new_val: yes); |
867 | break; |
868 | case mod2noconfig: |
869 | conf_rewrite_tristates(old_val: mod, new_val: no); |
870 | break; |
871 | case oldaskconfig: |
872 | rootEntry = &rootmenu; |
873 | conf(menu: &rootmenu); |
874 | input_mode = oldconfig; |
875 | /* fall through */ |
876 | case oldconfig: |
877 | case listnewconfig: |
878 | case helpnewconfig: |
879 | case syncconfig: |
880 | /* Update until a loop caused no more changes */ |
881 | do { |
882 | conf_cnt = 0; |
883 | check_conf(menu: &rootmenu); |
884 | } while (conf_cnt); |
885 | break; |
886 | case olddefconfig: |
887 | default: |
888 | break; |
889 | } |
890 | |
891 | if (sym_dep_errors()) |
892 | exit(status: 1); |
893 | |
894 | if (input_mode == savedefconfig) { |
895 | if (conf_write_defconfig(name: defconfig_file)) { |
896 | fprintf(stderr, format: "n*** Error while saving defconfig to: %s\n\n" , |
897 | defconfig_file); |
898 | return 1; |
899 | } |
900 | } else if (input_mode != listnewconfig && input_mode != helpnewconfig) { |
901 | if (!no_conf_write && conf_write(NULL)) { |
902 | fprintf(stderr, format: "\n*** Error during writing of the configuration.\n\n" ); |
903 | exit(status: 1); |
904 | } |
905 | |
906 | /* |
907 | * Create auto.conf if it does not exist. |
908 | * This prevents GNU Make 4.1 or older from emitting |
909 | * "include/config/auto.conf: No such file or directory" |
910 | * in the top-level Makefile |
911 | * |
912 | * syncconfig always creates or updates auto.conf because it is |
913 | * used during the build. |
914 | */ |
915 | if (conf_write_autoconf(overwrite: sync_kconfig) && sync_kconfig) { |
916 | fprintf(stderr, |
917 | format: "\n*** Error during sync of the configuration.\n\n" ); |
918 | return 1; |
919 | } |
920 | } |
921 | return 0; |
922 | } |
923 | |