Merge branch 'topic/cs423x-merge' into for-linus
[linux-2.6] / 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 char nohelp_text[] = N_("Sorry, no help available for this option yet.\n");
42
43 static const char *get_help(struct menu *menu)
44 {
45         if (menu_has_help(menu))
46                 return _(menu_get_help(menu));
47         else
48                 return nohelp_text;
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 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                                 printf("\n%s\n", get_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                 printf("\n%s\n", get_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                                 printf("\n%s\n", get_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                         printf("\n%s\n", get_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                 if (stat(".config", &tmpstat)) {
502                         fprintf(stderr, _("***\n"
503                                 "*** You have not yet configured your kernel!\n"
504                                 "*** (missing kernel .config file)\n"
505                                 "***\n"
506                                 "*** Please run some configurator (e.g. \"make oldconfig\" or\n"
507                                 "*** \"make menuconfig\" or \"make xconfig\").\n"
508                                 "***\n"));
509                         exit(1);
510                 }
511         }
512
513         switch (input_mode) {
514         case set_default:
515                 if (!defconfig_file)
516                         defconfig_file = conf_get_default_confname();
517                 if (conf_read(defconfig_file)) {
518                         printf(_("***\n"
519                                 "*** Can't find default configuration \"%s\"!\n"
520                                 "***\n"), defconfig_file);
521                         exit(1);
522                 }
523                 break;
524         case ask_silent:
525         case ask_all:
526         case ask_new:
527                 conf_read(NULL);
528                 break;
529         case set_no:
530         case set_mod:
531         case set_yes:
532         case set_random:
533                 name = getenv("KCONFIG_ALLCONFIG");
534                 if (name && !stat(name, &tmpstat)) {
535                         conf_read_simple(name, S_DEF_USER);
536                         break;
537                 }
538                 switch (input_mode) {
539                 case set_no:     name = "allno.config"; break;
540                 case set_mod:    name = "allmod.config"; break;
541                 case set_yes:    name = "allyes.config"; break;
542                 case set_random: name = "allrandom.config"; break;
543                 default: break;
544                 }
545                 if (!stat(name, &tmpstat))
546                         conf_read_simple(name, S_DEF_USER);
547                 else if (!stat("all.config", &tmpstat))
548                         conf_read_simple("all.config", S_DEF_USER);
549                 break;
550         default:
551                 break;
552         }
553
554         if (sync_kconfig) {
555                 if (conf_get_changed()) {
556                         name = getenv("KCONFIG_NOSILENTUPDATE");
557                         if (name && *name) {
558                                 fprintf(stderr,
559                                         _("\n*** Kernel configuration requires explicit update.\n\n"));
560                                 return 1;
561                         }
562                 }
563                 valid_stdin = isatty(0) && isatty(1) && isatty(2);
564         }
565
566         switch (input_mode) {
567         case set_no:
568                 conf_set_all_new_symbols(def_no);
569                 break;
570         case set_yes:
571                 conf_set_all_new_symbols(def_yes);
572                 break;
573         case set_mod:
574                 conf_set_all_new_symbols(def_mod);
575                 break;
576         case set_random:
577                 conf_set_all_new_symbols(def_random);
578                 break;
579         case set_default:
580                 conf_set_all_new_symbols(def_default);
581                 break;
582         case ask_new:
583         case ask_all:
584                 rootEntry = &rootmenu;
585                 conf(&rootmenu);
586                 input_mode = ask_silent;
587                 /* fall through */
588         case ask_silent:
589                 /* Update until a loop caused no more changes */
590                 do {
591                         conf_cnt = 0;
592                         check_conf(&rootmenu);
593                 } while (conf_cnt);
594                 break;
595         }
596
597         if (sync_kconfig) {
598                 /* silentoldconfig is used during the build so we shall update autoconf.
599                  * All other commands are only used to generate a config.
600                  */
601                 if (conf_get_changed() && conf_write(NULL)) {
602                         fprintf(stderr, _("\n*** Error during writing of the kernel configuration.\n\n"));
603                         exit(1);
604                 }
605                 if (conf_write_autoconf()) {
606                         fprintf(stderr, _("\n*** Error during update of the kernel configuration.\n\n"));
607                         return 1;
608                 }
609         } else {
610                 if (conf_write(NULL)) {
611                         fprintf(stderr, _("\n*** Error during writing of the kernel configuration.\n\n"));
612                         exit(1);
613                 }
614         }
615         return 0;
616 }