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