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