]> git.proxmox.com Git - mirror_linux-firmware.git/blob - carl9170fw/config/conf.c
Merge branch 'robot/patch-0-1697735493' into 'main'
[mirror_linux-firmware.git] / carl9170fw / config / conf.c
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 <locale.h>
7 #include <ctype.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/stat.h>
15 #include <sys/time.h>
16
17 #include "lkc.h"
18
19 static void conf(struct menu *menu);
20 static void check_conf(struct menu *menu);
21 static void xfgets(char *str, int size, FILE *in);
22
23 enum input_mode {
24 oldaskconfig,
25 oldconfig,
26 allnoconfig,
27 allyesconfig,
28 allmodconfig,
29 alldefconfig,
30 randconfig,
31 defconfig,
32 savedefconfig,
33 listnewconfig,
34 oldnoconfig,
35 } input_mode = oldaskconfig;
36
37 static int indent = 1;
38 static int valid_stdin = 1;
39 static int conf_cnt;
40 static char line[128];
41 static struct menu *rootEntry;
42
43 static void print_help(struct menu *menu)
44 {
45 struct gstr help = str_new();
46
47 menu_get_ext_help(menu, &help);
48
49 printf("\n%s\n", str_get(&help));
50 str_free(&help);
51 }
52
53 static void strip(char *str)
54 {
55 char *p = str;
56 int l;
57
58 while ((isspace(*p)))
59 p++;
60 l = strlen(p);
61 if (p != str)
62 memmove(str, p, l + 1);
63 if (!l)
64 return;
65 p = str + l - 1;
66 while ((isspace(*p)))
67 *p-- = 0;
68 }
69
70 static void check_stdin(void)
71 {
72 if (!valid_stdin) {
73 printf(_("aborted!\n\n"));
74 printf(_("Console input/output is redirected. "));
75 printf(_("Run 'make config' to update configuration.\n\n"));
76 exit(1);
77 }
78 }
79
80 static int conf_askvalue(struct symbol *sym, const char *def)
81 {
82 enum symbol_type type = sym_get_type(sym);
83
84 if (!sym_has_value(sym))
85 printf(_("(NEW) "));
86
87 line[0] = '\n';
88 line[1] = 0;
89
90 if (!sym_is_changable(sym)) {
91 printf("%s\n", def);
92 line[0] = '\n';
93 line[1] = 0;
94 return 0;
95 }
96
97 switch (input_mode) {
98 case oldconfig:
99 if (sym_has_value(sym)) {
100 printf("%s\n", def);
101 return 0;
102 }
103 check_stdin();
104 /* fall through */
105 case oldaskconfig:
106 fflush(stdout);
107 xfgets(line, 128, stdin);
108 return 1;
109 default:
110 break;
111 }
112
113 switch (type) {
114 case S_INT:
115 case S_HEX:
116 case S_STRING:
117 printf("%s\n", def);
118 return 1;
119 default:
120 ;
121 }
122 printf("%s", line);
123 return 1;
124 }
125
126 static int conf_string(struct menu *menu)
127 {
128 struct symbol *sym = menu->sym;
129 const char *def;
130
131 while (1) {
132 printf("%*s%s ", indent - 1, "", _(menu->prompt->text));
133 printf("(%s) ", sym->name);
134 def = sym_get_string_value(sym);
135 if (sym_get_string_value(sym))
136 printf("[%s] ", def);
137 if (!conf_askvalue(sym, def))
138 return 0;
139 switch (line[0]) {
140 case '\n':
141 break;
142 case '?':
143 /* print help */
144 if (line[1] == '\n') {
145 print_help(menu);
146 def = NULL;
147 break;
148 }
149 /* fall through */
150 default:
151 line[strlen(line)-1] = 0;
152 def = line;
153 }
154 if (def && sym_set_string_value(sym, def))
155 return 0;
156 }
157 }
158
159 static int conf_sym(struct menu *menu)
160 {
161 struct symbol *sym = menu->sym;
162 tristate oldval, newval;
163
164 while (1) {
165 printf("%*s%s ", indent - 1, "", _(menu->prompt->text));
166 if (sym->name)
167 printf("(%s) ", sym->name);
168 putchar('[');
169 oldval = sym_get_tristate_value(sym);
170 switch (oldval) {
171 case no:
172 putchar('N');
173 break;
174 case mod:
175 putchar('M');
176 break;
177 case yes:
178 putchar('Y');
179 break;
180 }
181 if (oldval != no && sym_tristate_within_range(sym, no))
182 printf("/n");
183 if (oldval != mod && sym_tristate_within_range(sym, mod))
184 printf("/m");
185 if (oldval != yes && sym_tristate_within_range(sym, yes))
186 printf("/y");
187 if (menu_has_help(menu))
188 printf("/?");
189 printf("] ");
190 if (!conf_askvalue(sym, sym_get_string_value(sym)))
191 return 0;
192 strip(line);
193
194 switch (line[0]) {
195 case 'n':
196 case 'N':
197 newval = no;
198 if (!line[1] || !strcmp(&line[1], "o"))
199 break;
200 continue;
201 case 'm':
202 case 'M':
203 newval = mod;
204 if (!line[1])
205 break;
206 continue;
207 case 'y':
208 case 'Y':
209 newval = yes;
210 if (!line[1] || !strcmp(&line[1], "es"))
211 break;
212 continue;
213 case 0:
214 newval = oldval;
215 break;
216 case '?':
217 goto help;
218 default:
219 continue;
220 }
221 if (sym_set_tristate_value(sym, newval))
222 return 0;
223 help:
224 print_help(menu);
225 }
226 }
227
228 static int conf_choice(struct menu *menu)
229 {
230 struct symbol *sym, *def_sym;
231 struct menu *child;
232 bool is_new;
233
234 sym = menu->sym;
235 is_new = !sym_has_value(sym);
236 if (sym_is_changable(sym)) {
237 conf_sym(menu);
238 sym_calc_value(sym);
239 switch (sym_get_tristate_value(sym)) {
240 case no:
241 return 1;
242 case mod:
243 return 0;
244 case yes:
245 break;
246 }
247 } else {
248 switch (sym_get_tristate_value(sym)) {
249 case no:
250 return 1;
251 case mod:
252 printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu)));
253 return 0;
254 case yes:
255 break;
256 }
257 }
258
259 while (1) {
260 int cnt, def;
261
262 printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu)));
263 def_sym = sym_get_choice_value(sym);
264 cnt = def = 0;
265 line[0] = 0;
266 for (child = menu->list; child; child = child->next) {
267 if (!menu_is_visible(child))
268 continue;
269 if (!child->sym) {
270 printf("%*c %s\n", indent, '*', _(menu_get_prompt(child)));
271 continue;
272 }
273 cnt++;
274 if (child->sym == def_sym) {
275 def = cnt;
276 printf("%*c", indent, '>');
277 } else
278 printf("%*c", indent, ' ');
279 printf(" %d. %s", cnt, _(menu_get_prompt(child)));
280 if (child->sym->name)
281 printf(" (%s)", child->sym->name);
282 if (!sym_has_value(child->sym))
283 printf(_(" (NEW)"));
284 printf("\n");
285 }
286 printf(_("%*schoice"), indent - 1, "");
287 if (cnt == 1) {
288 printf("[1]: 1\n");
289 goto conf_childs;
290 }
291 printf("[1-%d", cnt);
292 if (menu_has_help(menu))
293 printf("?");
294 printf("]: ");
295 switch (input_mode) {
296 case oldconfig:
297 if (!is_new) {
298 cnt = def;
299 printf("%d\n", cnt);
300 break;
301 }
302 check_stdin();
303 /* fall through */
304 case oldaskconfig:
305 fflush(stdout);
306 xfgets(line, 128, stdin);
307 strip(line);
308 if (line[0] == '?') {
309 print_help(menu);
310 continue;
311 }
312 if (!line[0])
313 cnt = def;
314 else if (isdigit(line[0]))
315 cnt = atoi(line);
316 else
317 continue;
318 break;
319 default:
320 break;
321 }
322
323 conf_childs:
324 for (child = menu->list; child; child = child->next) {
325 if (!child->sym || !menu_is_visible(child))
326 continue;
327 if (!--cnt)
328 break;
329 }
330 if (!child)
331 continue;
332 if (line[0] && line[strlen(line) - 1] == '?') {
333 print_help(child);
334 continue;
335 }
336 sym_set_choice_value(sym, child->sym);
337 for (child = child->list; child; child = child->next) {
338 indent += 2;
339 conf(child);
340 indent -= 2;
341 }
342 return 1;
343 }
344 }
345
346 static void conf(struct menu *menu)
347 {
348 struct symbol *sym;
349 struct property *prop;
350 struct menu *child;
351
352 if (!menu_is_visible(menu))
353 return;
354
355 sym = menu->sym;
356 prop = menu->prompt;
357 if (prop) {
358 const char *prompt;
359
360 switch (prop->type) {
361 case P_MENU:
362 if ((input_mode == listnewconfig ||
363 input_mode == oldnoconfig) &&
364 rootEntry != menu) {
365 check_conf(menu);
366 return;
367 }
368 /* fall through */
369 case P_COMMENT:
370 prompt = menu_get_prompt(menu);
371 if (prompt)
372 printf("%*c\n%*c %s\n%*c\n",
373 indent, '*',
374 indent, '*', _(prompt),
375 indent, '*');
376 default:
377 ;
378 }
379 }
380
381 if (!sym)
382 goto conf_childs;
383
384 if (sym_is_choice(sym)) {
385 conf_choice(menu);
386 if (sym->curr.tri != mod)
387 return;
388 goto conf_childs;
389 }
390
391 switch (sym->type) {
392 case S_INT:
393 case S_HEX:
394 case S_STRING:
395 conf_string(menu);
396 break;
397 default:
398 conf_sym(menu);
399 break;
400 }
401
402 conf_childs:
403 if (sym)
404 indent += 2;
405 for (child = menu->list; child; child = child->next)
406 conf(child);
407 if (sym)
408 indent -= 2;
409 }
410
411 static void check_conf(struct menu *menu)
412 {
413 struct symbol *sym;
414 struct menu *child;
415
416 if (!menu_is_visible(menu))
417 return;
418
419 sym = menu->sym;
420 if (sym && !sym_has_value(sym)) {
421 if (sym_is_changable(sym) ||
422 (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) {
423 if (input_mode == listnewconfig) {
424 if (sym->name && !sym_is_choice_value(sym)) {
425 printf("%s%s\n", CONFIG_, sym->name);
426 }
427 } else if (input_mode != oldnoconfig) {
428 if (!conf_cnt++)
429 printf(_("*\n* Restart config...\n*\n"));
430 rootEntry = menu_get_parent_menu(menu);
431 conf(rootEntry);
432 }
433 }
434 }
435
436 for (child = menu->list; child; child = child->next)
437 check_conf(child);
438 }
439
440 static struct option long_opts[] = {
441 {"askconfig", no_argument, NULL, oldaskconfig},
442 {"config", no_argument, NULL, oldconfig},
443 {"defconfig", optional_argument, NULL, defconfig},
444 {"savedefconfig", required_argument, NULL, savedefconfig},
445 {"allnoconfig", no_argument, NULL, allnoconfig},
446 {"allyesconfig", no_argument, NULL, allyesconfig},
447 {"allmodconfig", no_argument, NULL, allmodconfig},
448 {"alldefconfig", no_argument, NULL, alldefconfig},
449 {"randconfig", no_argument, NULL, randconfig},
450 {"listnewconfig", no_argument, NULL, listnewconfig},
451 {"noconfig", no_argument, NULL, oldnoconfig},
452 {NULL, 0, NULL, 0}
453 };
454
455 static void conf_usage(const char *progname)
456 {
457
458 printf("Usage: %s [option] <kconfig-file>\n", progname);
459 printf("[option] is _one_ of the following:\n");
460 printf(" --listnewconfig List new options\n");
461 printf(" --askconfig Start a new configuration using a line-oriented program\n");
462 printf(" --config Update a configuration using a provided .config as base\n");
463 printf(" --silentconfig Same as config, but quietly, additionally update deps\n");
464 printf(" --noconfig Same as silentconfig but set new symbols to no\n");
465 printf(" --defconfig <file> New config with default defined in <file>\n");
466 printf(" --savedefconfig <file> Save the minimal current configuration to <file>\n");
467 printf(" --allnoconfig New config where all options are answered with no\n");
468 printf(" --allyesconfig New config where all options are answered with yes\n");
469 printf(" --allmodconfig New config where all options are answered with mod\n");
470 printf(" --alldefconfig New config with all symbols set to default\n");
471 printf(" --randconfig New config with random answer to all options\n");
472 }
473
474 int main(int ac, char **av)
475 {
476 const char *progname = av[0];
477 int opt;
478 const char *name, *defconfig_file = NULL /* gcc uninit */;
479 struct stat tmpstat;
480
481 setlocale(LC_ALL, "");
482 bindtextdomain(PACKAGE, LOCALEDIR);
483 textdomain(PACKAGE);
484
485 while ((opt = getopt_long(ac, av, "", long_opts, NULL)) != -1) {
486 input_mode = (enum input_mode)opt;
487 switch (opt) {
488 case defconfig:
489 case savedefconfig:
490 defconfig_file = optarg;
491 break;
492 case randconfig:
493 {
494 struct timeval now;
495 unsigned int seed;
496
497 /*
498 * Use microseconds derived seed,
499 * compensate for systems where it may be zero
500 */
501 gettimeofday(&now, NULL);
502
503 seed = (unsigned int)((now.tv_sec + 1) * (now.tv_usec + 1));
504 srand(seed);
505 break;
506 }
507 case oldaskconfig:
508 case oldconfig:
509 case allnoconfig:
510 case allyesconfig:
511 case allmodconfig:
512 case alldefconfig:
513 case listnewconfig:
514 case oldnoconfig:
515 break;
516 case '?':
517 conf_usage(progname);
518 exit(1);
519 break;
520 }
521 }
522 if (ac == optind) {
523 printf(_("%s: Kconfig file missing\n"), av[0]);
524 conf_usage(progname);
525 exit(1);
526 }
527 name = av[optind];
528 conf_parse(name);
529 //zconfdump(stdout);
530
531 switch (input_mode) {
532 case defconfig:
533 if (!defconfig_file)
534 defconfig_file = conf_get_default_confname();
535 if (conf_read(defconfig_file)) {
536 printf(_("***\n"
537 "*** Can't find default configuration \"%s\"!\n"
538 "***\n"), defconfig_file);
539 exit(1);
540 }
541 break;
542 case savedefconfig:
543 case oldaskconfig:
544 case oldconfig:
545 case listnewconfig:
546 case oldnoconfig:
547 conf_read(NULL);
548 break;
549 case allnoconfig:
550 case allyesconfig:
551 case allmodconfig:
552 case alldefconfig:
553 case randconfig:
554 name = getenv("KCONFIG_ALLCONFIG");
555 if (name && !stat(name, &tmpstat)) {
556 conf_read_simple(name, S_DEF_USER);
557 break;
558 }
559 switch (input_mode) {
560 case allnoconfig: name = "allno.config"; break;
561 case allyesconfig: name = "allyes.config"; break;
562 case allmodconfig: name = "allmod.config"; break;
563 case alldefconfig: name = "alldef.config"; break;
564 case randconfig: name = "allrandom.config"; break;
565 default: break;
566 }
567 if (!stat(name, &tmpstat))
568 conf_read_simple(name, S_DEF_USER);
569 else if (!stat("all.config", &tmpstat))
570 conf_read_simple("all.config", S_DEF_USER);
571 break;
572 default:
573 break;
574 }
575
576 valid_stdin = isatty(0) && isatty(1) && isatty(2);
577
578 switch (input_mode) {
579 case allnoconfig:
580 conf_set_all_new_symbols(def_no);
581 break;
582 case allyesconfig:
583 conf_set_all_new_symbols(def_yes);
584 break;
585 case allmodconfig:
586 conf_set_all_new_symbols(def_mod);
587 break;
588 case alldefconfig:
589 conf_set_all_new_symbols(def_default);
590 break;
591 case randconfig:
592 conf_set_all_new_symbols(def_random);
593 break;
594 case defconfig:
595 conf_set_all_new_symbols(def_default);
596 break;
597 case savedefconfig:
598 break;
599 case oldaskconfig:
600 rootEntry = &rootmenu;
601 conf(&rootmenu);
602 input_mode = oldconfig;
603 /* fall through */
604 case oldconfig:
605 case listnewconfig:
606 case oldnoconfig:
607 /* Update until a loop caused no more changes */
608 do {
609 conf_cnt = 0;
610 check_conf(&rootmenu);
611 } while (conf_cnt &&
612 (input_mode != listnewconfig &&
613 input_mode != oldnoconfig));
614 break;
615 }
616
617 if (input_mode == savedefconfig) {
618 if (conf_write_defconfig(defconfig_file)) {
619 fprintf(stderr, _("n*** Error while saving defconfig to: %s\n\n"),
620 defconfig_file);
621 return 1;
622 }
623 } else if (input_mode != listnewconfig) {
624 /*
625 * build so we shall update autoconf.
626 */
627 if (conf_write(NULL)) {
628 fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n"));
629 exit(1);
630 }
631 if (conf_write_autoconf()) {
632 fprintf(stderr, _("\n*** Error during update of the configuration.\n\n"));
633 return 1;
634 }
635 }
636 return 0;
637 }
638
639 /*
640 * Helper function to facilitate fgets() by Jean Sacren.
641 */
642 void xfgets(char *str, int size, FILE *in)
643 {
644 if (fgets(str, size, in) == NULL)
645 fprintf(stderr, "\nError in reading or end of file.\n");
646 }