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