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