printf: fix printf "%u\n" +18446744073709551614
[oweals/busybox.git] / scripts / kconfig / 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 #define _XOPEN_SOURCE 700
7
8 #include <ctype.h>
9 #include <stdlib.h>
10 #include <stdio.h>
11 #include <string.h>
12 #include <unistd.h>
13 #include <time.h>
14 #include <sys/stat.h>
15
16 #define LKC_DIRECT_LINK
17 #include "lkc.h"
18
19 static void conf(struct menu *menu);
20 static void check_conf(struct menu *menu);
21
22 enum {
23         ask_all,
24         ask_new,
25         ask_silent,
26         set_default,
27         set_yes,
28         set_mod,
29         set_no,
30         set_random
31 } input_mode = ask_all;
32 char *defconfig_file;
33
34 static int indent = 1;
35 static int valid_stdin = 1;
36 static int conf_cnt;
37 static char line[128];
38 static struct menu *rootEntry;
39
40 static char nohelp_text[] = N_("Sorry, no help available for this option yet.\n");
41
42 static void strip(char *str)
43 {
44         char *p = str;
45         int l;
46
47         while ((isspace(*p)))
48                 p++;
49         l = strlen(p);
50         if (p != str)
51                 memmove(str, p, l + 1);
52         if (!l)
53                 return;
54         p = str + l - 1;
55         while ((isspace(*p)))
56                 *p-- = 0;
57 }
58
59 static void check_stdin(void)
60 {
61         if (!valid_stdin && input_mode == ask_silent) {
62                 printf(_("aborted!\n\n"));
63                 printf(_("Console input/output is redirected. "));
64                 printf(_("Run 'make oldconfig' to update configuration.\n\n"));
65                 exit(1);
66         }
67 }
68
69 static void conf_askvalue(struct symbol *sym, const char *def)
70 {
71         enum symbol_type type = sym_get_type(sym);
72         tristate val;
73
74         if (!sym_has_value(sym))
75                 printf("(NEW) ");
76
77         line[0] = '\n';
78         line[1] = 0;
79         line[2] = 0;
80
81         if (!sym_is_changable(sym)) {
82                 printf("%s\n", def);
83                 return;
84         }
85
86         // If autoconf run (allnoconfig and such), reset bool and tristates:
87         // "select ITEM" sets ITEM=y and then parent item might have been
88         // reset to "n" later. Try to set ITEM to "n" on the second run.
89         if (type == S_BOOLEAN || type == S_TRISTATE) {
90                 switch (input_mode) {
91                 case set_yes:
92                         if (sym_tristate_within_range(sym, yes)) {
93                                 line[0] = 'y';
94                                 line[1] = '\n';
95                                 printf("%s", line);
96                                 return;
97                         }
98                 case set_mod:
99                         if (type == S_TRISTATE) {
100                                 if (sym_tristate_within_range(sym, mod)) {
101                                         line[0] = 'm';
102                                         line[1] = '\n';
103                                         printf("%s", line);
104                                         return;
105                                 }
106                         } else {
107                                 if (sym_tristate_within_range(sym, yes)) {
108                                         line[0] = 'y';
109                                         line[1] = '\n';
110                                         printf("%s", line);
111                                         return;
112                                 }
113                         }
114                 case set_no:
115                         if (sym_tristate_within_range(sym, no)) {
116                                 line[0] = 'n';
117                                 line[1] = '\n';
118                                 printf("%s", line);
119                                 return;
120                         }
121                 default: // placate compiler
122                         break;
123                 }
124         }
125
126         switch (input_mode) {
127         case set_no:
128         case set_mod:
129         case set_yes:
130         case set_random:
131                 if (sym_has_value(sym)) {
132                         printf("%s\n", def);
133                         return;
134                 }
135                 break;
136         case ask_new:
137         case ask_silent:
138                 if (sym_has_value(sym)) {
139                         printf("%s\n", def);
140                         return;
141                 }
142                 check_stdin();
143         case ask_all:
144                 fflush(stdout);
145                 fgets(line, 128, stdin);
146                 return;
147         case set_default:
148                 printf("%s\n", def);
149                 return;
150         default:
151                 break;
152         }
153
154         switch (type) {
155         case S_INT:
156         case S_HEX:
157         case S_STRING:
158                 printf("%s\n", def);
159                 return;
160         default:
161                 ;
162         }
163         switch (input_mode) {
164         case set_yes:
165                 if (sym_tristate_within_range(sym, yes)) {
166                         line[0] = 'y';
167                         line[1] = '\n';
168                         line[2] = 0;
169                         break;
170                 }
171         case set_mod:
172                 if (type == S_TRISTATE) {
173                         if (sym_tristate_within_range(sym, mod)) {
174                                 line[0] = 'm';
175                                 line[1] = '\n';
176                                 line[2] = 0;
177                                 break;
178                         }
179                 } else {
180                         if (sym_tristate_within_range(sym, yes)) {
181                                 line[0] = 'y';
182                                 line[1] = '\n';
183                                 line[2] = 0;
184                                 break;
185                         }
186                 }
187         case set_no:
188                 if (sym_tristate_within_range(sym, no)) {
189                         line[0] = 'n';
190                         line[1] = '\n';
191                         line[2] = 0;
192                         break;
193                 }
194         case set_random:
195                 do {
196                         val = (tristate)(random() % 3);
197                 } while (!sym_tristate_within_range(sym, val));
198                 switch (val) {
199                 case no: line[0] = 'n'; break;
200                 case mod: line[0] = 'm'; break;
201                 case yes: line[0] = 'y'; break;
202                 }
203                 line[1] = '\n';
204                 line[2] = 0;
205                 break;
206         default:
207                 break;
208         }
209         printf("%s", line);
210 }
211
212 int conf_string(struct menu *menu)
213 {
214         struct symbol *sym = menu->sym;
215         const char *def;
216
217         while (1) {
218                 printf("%*s%s ", indent - 1, "", menu->prompt->text);
219                 printf("(%s) ", sym->name);
220                 def = sym_get_string_value(sym);
221                 if (sym_get_string_value(sym))
222                         printf("[%s] ", def);
223                 conf_askvalue(sym, def);
224                 switch (line[0]) {
225                 case '\n':
226                         break;
227                 case '?':
228                         /* print help */
229                         if (line[1] == '\n') {
230                                 printf("\n%s\n", menu->sym->help ? menu->sym->help : nohelp_text);
231                                 def = NULL;
232                                 break;
233                         }
234                 default:
235                         line[strlen(line)-1] = 0;
236                         def = line;
237                 }
238                 if (def && sym_set_string_value(sym, def))
239                         return 0;
240         }
241 }
242
243 static int conf_sym(struct menu *menu)
244 {
245         struct symbol *sym = menu->sym;
246         tristate oldval, newval;
247         const char *help;
248
249         while (1) {
250                 printf("%*s%s ", indent - 1, "", menu->prompt->text);
251                 if (sym->name)
252                         printf("(%s) ", sym->name);
253                 putchar('[');
254                 oldval = sym_get_tristate_value(sym);
255                 switch (oldval) {
256                 case no:
257                         putchar('N');
258                         break;
259                 case mod:
260                         putchar('M');
261                         break;
262                 case yes:
263                         putchar('Y');
264                         break;
265                 }
266                 if (oldval != no && sym_tristate_within_range(sym, no))
267                         printf("/n");
268                 if (oldval != mod && sym_tristate_within_range(sym, mod))
269                         printf("/m");
270                 if (oldval != yes && sym_tristate_within_range(sym, yes))
271                         printf("/y");
272                 if (sym->help)
273                         printf("/?");
274                 printf("] ");
275                 conf_askvalue(sym, sym_get_string_value(sym));
276                 strip(line);
277
278                 switch (line[0]) {
279                 case 'n':
280                 case 'N':
281                         newval = no;
282                         if (!line[1] || !strcmp(&line[1], "o"))
283                                 break;
284                         continue;
285                 case 'm':
286                 case 'M':
287                         newval = mod;
288                         if (!line[1])
289                                 break;
290                         continue;
291                 case 'y':
292                 case 'Y':
293                         newval = yes;
294                         if (!line[1] || !strcmp(&line[1], "es"))
295                                 break;
296                         continue;
297                 case 0:
298                         newval = oldval;
299                         break;
300                 case '?':
301                         goto help;
302                 default:
303                         continue;
304                 }
305                 if (sym_set_tristate_value(sym, newval))
306                         return 0;
307 help:
308                 help = nohelp_text;
309                 if (sym->help)
310                         help = sym->help;
311                 printf("\n%s\n", help);
312         }
313 }
314
315 static int conf_choice(struct menu *menu)
316 {
317         struct symbol *sym, *def_sym;
318         struct menu *child;
319         bool is_new;
320
321         sym = menu->sym;
322         is_new = !sym_has_value(sym);
323         if (sym_is_changable(sym)) {
324                 conf_sym(menu);
325                 sym_calc_value(sym);
326                 switch (sym_get_tristate_value(sym)) {
327                 case no:
328                         return 1;
329                 case mod:
330                         return 0;
331                 case yes:
332                         break;
333                 }
334         } else {
335                 switch (sym_get_tristate_value(sym)) {
336                 case no:
337                         return 1;
338                 case mod:
339                         printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu));
340                         return 0;
341                 case yes:
342                         break;
343                 }
344         }
345
346         while (1) {
347                 int cnt, def;
348
349                 printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu));
350                 def_sym = sym_get_choice_value(sym);
351                 cnt = def = 0;
352                 line[0] = 0;
353                 for (child = menu->list; child; child = child->next) {
354                         if (!menu_is_visible(child))
355                                 continue;
356                         if (!child->sym) {
357                                 printf("%*c %s\n", indent, '*', menu_get_prompt(child));
358                                 continue;
359                         }
360                         cnt++;
361                         if (child->sym == def_sym) {
362                                 def = cnt;
363                                 printf("%*c", indent, '>');
364                         } else
365                                 printf("%*c", indent, ' ');
366                         printf(" %d. %s", cnt, menu_get_prompt(child));
367                         if (child->sym->name)
368                                 printf(" (%s)", child->sym->name);
369                         if (!sym_has_value(child->sym))
370                                 printf(" (NEW)");
371                         printf("\n");
372                 }
373                 printf("%*schoice", indent - 1, "");
374                 if (cnt == 1) {
375                         printf("[1]: 1\n");
376                         goto conf_childs;
377                 }
378                 printf("[1-%d", cnt);
379                 if (sym->help)
380                         printf("?");
381                 printf("]: ");
382                 switch (input_mode) {
383                 case ask_new:
384                 case ask_silent:
385                         if (!is_new) {
386                                 cnt = def;
387                                 printf("%d\n", cnt);
388                                 break;
389                         }
390                         check_stdin();
391                 case ask_all:
392                         fflush(stdout);
393                         fgets(line, 128, stdin);
394                         strip(line);
395                         if (line[0] == '?') {
396                                 printf("\n%s\n", menu->sym->help ?
397                                         menu->sym->help : nohelp_text);
398                                 continue;
399                         }
400                         if (!line[0])
401                                 cnt = def;
402                         else if (isdigit(line[0]))
403                                 cnt = atoi(line);
404                         else
405                                 continue;
406                         break;
407                 case set_random:
408                         def = (random() % cnt) + 1;
409                 case set_default:
410                 case set_yes:
411                 case set_mod:
412                 case set_no:
413                         cnt = def;
414                         printf("%d\n", cnt);
415                         break;
416                 }
417
418         conf_childs:
419                 for (child = menu->list; child; child = child->next) {
420                         if (!child->sym || !menu_is_visible(child))
421                                 continue;
422                         if (!--cnt)
423                                 break;
424                 }
425                 if (!child)
426                         continue;
427                 if (strlen(line) > 0 && line[strlen(line) - 1] == '?') {
428                         printf("\n%s\n", child->sym->help ?
429                                 child->sym->help : nohelp_text);
430                         continue;
431                 }
432                 sym_set_choice_value(sym, child->sym);
433                 if (child->list) {
434                         indent += 2;
435                         conf(child->list);
436                         indent -= 2;
437                 }
438                 return 1;
439         }
440 }
441
442 static void conf(struct menu *menu)
443 {
444         struct symbol *sym;
445         struct property *prop;
446         struct menu *child;
447
448         if (!menu_is_visible(menu))
449                 return;
450
451         sym = menu->sym;
452         prop = menu->prompt;
453         if (prop) {
454                 const char *prompt;
455
456                 switch (prop->type) {
457                 case P_MENU:
458                         if (input_mode == ask_silent && rootEntry != menu) {
459                                 check_conf(menu);
460                                 return;
461                         }
462                 case P_COMMENT:
463                         prompt = menu_get_prompt(menu);
464                         if (prompt)
465                                 printf("%*c\n%*c %s\n%*c\n",
466                                         indent, '*',
467                                         indent, '*', prompt,
468                                         indent, '*');
469                 default:
470                         ;
471                 }
472         }
473
474         if (!sym)
475                 goto conf_childs;
476
477         if (sym_is_choice(sym)) {
478                 conf_choice(menu);
479                 if (sym->curr.tri != mod)
480                         return;
481                 goto conf_childs;
482         }
483
484         switch (sym->type) {
485         case S_INT:
486         case S_HEX:
487         case S_STRING:
488                 conf_string(menu);
489                 break;
490         default:
491                 conf_sym(menu);
492                 break;
493         }
494
495 conf_childs:
496         if (sym)
497                 indent += 2;
498         for (child = menu->list; child; child = child->next)
499                 conf(child);
500         if (sym)
501                 indent -= 2;
502 }
503
504 static void check_conf(struct menu *menu)
505 {
506         struct symbol *sym;
507         struct menu *child;
508
509         if (!menu_is_visible(menu))
510                 return;
511
512         sym = menu->sym;
513         if (sym && !sym_has_value(sym)) {
514                 if (sym_is_changable(sym) ||
515                     (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) {
516                         if (!conf_cnt++)
517                                 printf(_("*\n* Restart config...\n*\n"));
518                         rootEntry = menu_get_parent_menu(menu);
519                         conf(rootEntry);
520                 }
521         }
522
523         for (child = menu->list; child; child = child->next)
524                 check_conf(child);
525 }
526
527 int main(int ac, char **av)
528 {
529         int i = 1;
530         const char *name;
531         struct stat tmpstat;
532
533         if (ac > i && av[i][0] == '-') {
534                 switch (av[i++][1]) {
535                 case 'o':
536                         input_mode = ask_new;
537                         break;
538                 case 's':
539                         input_mode = ask_silent;
540                         valid_stdin = isatty(0); //bbox: && isatty(1) && isatty(2);
541                         break;
542                 case 'd':
543                         input_mode = set_default;
544                         break;
545                 case 'D':
546                         input_mode = set_default;
547                         defconfig_file = av[i++];
548                         if (!defconfig_file) {
549                                 printf(_("%s: No default config file specified\n"),
550                                         av[0]);
551                                 exit(1);
552                         }
553                         break;
554                 case 'n':
555                         input_mode = set_no;
556                         break;
557                 case 'm':
558                         input_mode = set_mod;
559                         break;
560                 case 'y':
561                         input_mode = set_yes;
562                         break;
563                 case 'r':
564                         input_mode = set_random;
565                         srandom(time(NULL));
566                         break;
567                 case 'h':
568                 case '?':
569                         fprintf(stderr, "See README for usage info\n");
570                         exit(0);
571                 }
572         }
573         name = av[i];
574         if (!name) {
575                 printf(_("%s: Kconfig file missing\n"), av[0]);
576         }
577         conf_parse(name);
578         //zconfdump(stdout);
579         switch (input_mode) {
580         case set_default:
581                 if (!defconfig_file)
582                         defconfig_file = conf_get_default_confname();
583                 if (conf_read(defconfig_file)) {
584                         printf("***\n"
585                                 "*** Can't find default configuration \"%s\"!\n"
586                                 "***\n", defconfig_file);
587                         exit(1);
588                 }
589                 break;
590         case ask_silent:
591                 if (stat(".config", &tmpstat)) {
592                         printf(_("***\n"
593                                 "*** You have not yet configured busybox!\n"
594                                 "***\n"
595                                 "*** Please run some configurator (e.g. \"make oldconfig\" or\n"
596                                 "*** \"make menuconfig\" or \"make defconfig\").\n"
597                                 "***\n"));
598                         exit(1);
599                 }
600         case ask_all:
601         case ask_new:
602                 conf_read(NULL);
603                 break;
604         case set_no:
605         case set_mod:
606         case set_yes:
607         case set_random:
608                 name = getenv("KCONFIG_ALLCONFIG");
609                 if (name && !stat(name, &tmpstat)) {
610                         conf_read_simple(name);
611                         break;
612                 }
613                 switch (input_mode) {
614                 case set_no:     name = "allno.config"; break;
615                 case set_mod:    name = "allmod.config"; break;
616                 case set_yes:    name = "allyes.config"; break;
617                 case set_random: name = "allrandom.config"; break;
618                 default: break;
619                 }
620                 if (!stat(name, &tmpstat))
621                         conf_read_simple(name);
622                 else if (!stat("all.config", &tmpstat))
623                         conf_read_simple("all.config");
624                 break;
625         default:
626                 break;
627         }
628
629         if (input_mode != ask_silent) {
630                 rootEntry = &rootmenu;
631                 conf(&rootmenu);
632                 // If autoconf run (allnoconfig and such), run it twice:
633                 // "select ITEM" sets ITEM=y and then parent item
634                 // is reset to "n" later. Second run sets ITEM to "n".
635                 // Example: ADDUSER selects LONG_OPTS.
636                 // allnoconfig must set _both_ to "n".
637                 // Before, LONG_OPTS remained "y".
638                 if (input_mode == set_no
639                  || input_mode == set_mod
640                  || input_mode == set_yes
641                 ) {
642                         rootEntry = &rootmenu;
643                         conf(&rootmenu);
644                 }
645                 if (input_mode == ask_all) {
646                         input_mode = ask_silent;
647                         valid_stdin = 1;
648                 }
649         }
650         do {
651                 conf_cnt = 0;
652                 check_conf(&rootmenu);
653         } while (conf_cnt);
654         if (conf_write(NULL)) {
655                 fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n"));
656                 return 1;
657         }
658         return 0;
659 }