summaryrefslogtreecommitdiff
path: root/scripts/kconfig/conf.c
Unidiff
Diffstat (limited to 'scripts/kconfig/conf.c') (more/less context) (ignore whitespace changes)
-rw-r--r--scripts/kconfig/conf.c565
1 files changed, 565 insertions, 0 deletions
diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c
new file mode 100644
index 0000000..74c94c2
--- a/dev/null
+++ b/scripts/kconfig/conf.c
@@ -0,0 +1,565 @@
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 <string.h>
9#include <unistd.h>
10#include <time.h>
11#include <sys/stat.h>
12
13#define LKC_DIRECT_LINK
14#include "lkc.h"
15
16static void conf(struct menu *menu);
17static void check_conf(struct menu *menu);
18
19enum {
20 ask_all,
21 ask_new,
22 ask_silent,
23 set_default,
24 set_yes,
25 set_mod,
26 set_no,
27 set_random
28} input_mode = ask_all;
29
30static int indent = 1;
31static int valid_stdin = 1;
32static int conf_cnt;
33static char line[128];
34static struct menu *rootEntry;
35
36static char nohelp_text[] = "Sorry, no help available for this option yet.\n";
37
38#if 0
39static void printc(int ch)
40{
41 static int sep = 0;
42
43 if (!sep) {
44 putchar('[');
45 sep = 1;
46 } else if (ch)
47 putchar('/');
48 if (!ch) {
49 putchar(']');
50 putchar(' ');
51 sep = 0;
52 } else
53 putchar(ch);
54}
55#endif
56
57static void printo(const char *o)
58{
59 static int sep = 0;
60
61 if (!sep) {
62 putchar('(');
63 sep = 1;
64 } else if (o) {
65 putchar(',');
66 putchar(' ');
67 }
68 if (!o) {
69 putchar(')');
70 putchar(' ');
71 sep = 0;
72 } else
73 printf("%s", o);
74}
75
76static void strip(char *str)
77{
78 char *p = str;
79 int l;
80
81 while ((isspace(*p)))
82 p++;
83 l = strlen(p);
84 if (p != str)
85 memmove(str, p, l + 1);
86 if (!l)
87 return;
88 p = str + l - 1;
89 while ((isspace(*p)))
90 *p-- = 0;
91}
92
93static void conf_askvalue(struct symbol *sym, const char *def)
94{
95 enum symbol_type type = sym_get_type(sym);
96 tristate val;
97
98 if (!sym_has_value(sym))
99 printf("(NEW) ");
100
101 line[0] = '\n';
102 line[1] = 0;
103
104 switch (input_mode) {
105 case ask_new:
106 case ask_silent:
107 if (sym_has_value(sym)) {
108 printf("%s\n", def);
109 return;
110 }
111 if (!valid_stdin && input_mode == ask_silent) {
112 printf("aborted!\n\n");
113 printf("Console input/output is redirected. ");
114 printf("Run 'make oldconfig' to update configuration.\n\n");
115 exit(1);
116 }
117 case ask_all:
118 fgets(line, 128, stdin);
119 return;
120 case set_default:
121 printf("%s\n", def);
122 return;
123 default:
124 break;
125 }
126
127 switch (type) {
128 case S_INT:
129 case S_HEX:
130 case S_STRING:
131 printf("%s\n", def);
132 return;
133 default:
134 ;
135 }
136 switch (input_mode) {
137 case set_yes:
138 if (sym_tristate_within_range(sym, yes)) {
139 line[0] = 'y';
140 line[1] = '\n';
141 line[2] = 0;
142 break;
143 }
144 case set_mod:
145 if (type == S_TRISTATE) {
146 if (sym_tristate_within_range(sym, mod)) {
147 line[0] = 'm';
148 line[1] = '\n';
149 line[2] = 0;
150 break;
151 }
152 } else {
153 if (sym_tristate_within_range(sym, yes)) {
154 line[0] = 'y';
155 line[1] = '\n';
156 line[2] = 0;
157 break;
158 }
159 }
160 case set_no:
161 if (sym_tristate_within_range(sym, no)) {
162 line[0] = 'n';
163 line[1] = '\n';
164 line[2] = 0;
165 break;
166 }
167 case set_random:
168 do {
169 val = (tristate)(random() % 3);
170 } while (!sym_tristate_within_range(sym, val));
171 switch (val) {
172 case no: line[0] = 'n'; break;
173 case mod: line[0] = 'm'; break;
174 case yes: line[0] = 'y'; break;
175 }
176 line[1] = '\n';
177 line[2] = 0;
178 break;
179 default:
180 break;
181 }
182 printf("%s", line);
183}
184
185int conf_string(struct menu *menu)
186{
187 struct symbol *sym = menu->sym;
188 const char *def, *help;
189
190 while (1) {
191 printf("%*s%s ", indent - 1, "", menu->prompt->text);
192 printf("(%s) ", sym->name);
193 def = sym_get_string_value(sym);
194 if (sym_get_string_value(sym))
195 printf("[%s] ", def);
196 conf_askvalue(sym, def);
197 switch (line[0]) {
198 case '\n':
199 break;
200 case '?':
201 /* print help */
202 if (line[1] == 0) {
203 help = nohelp_text;
204 if (menu->sym->help)
205 help = menu->sym->help;
206 printf("\n%s\n", menu->sym->help);
207 def = NULL;
208 break;
209 }
210 default:
211 line[strlen(line)-1] = 0;
212 def = line;
213 }
214 if (def && sym_set_string_value(sym, def))
215 return 0;
216 }
217}
218
219static int conf_sym(struct menu *menu)
220{
221 struct symbol *sym = menu->sym;
222 int type;
223 tristate oldval, newval;
224 const char *help;
225
226 while (1) {
227 printf("%*s%s ", indent - 1, "", menu->prompt->text);
228 if (sym->name)
229 printf("(%s) ", sym->name);
230 type = sym_get_type(sym);
231 putchar('[');
232 oldval = sym_get_tristate_value(sym);
233 switch (oldval) {
234 case no:
235 putchar('N');
236 break;
237 case mod:
238 putchar('M');
239 break;
240 case yes:
241 putchar('Y');
242 break;
243 }
244 if (oldval != no && sym_tristate_within_range(sym, no))
245 printf("/n");
246 if (oldval != mod && sym_tristate_within_range(sym, mod))
247 printf("/m");
248 if (oldval != yes && sym_tristate_within_range(sym, yes))
249 printf("/y");
250 if (sym->help)
251 printf("/?");
252 printf("] ");
253 conf_askvalue(sym, sym_get_string_value(sym));
254 strip(line);
255
256 switch (line[0]) {
257 case 'n':
258 case 'N':
259 newval = no;
260 if (!line[1] || !strcmp(&line[1], "o"))
261 break;
262 continue;
263 case 'm':
264 case 'M':
265 newval = mod;
266 if (!line[1])
267 break;
268 continue;
269 case 'y':
270 case 'Y':
271 newval = yes;
272 if (!line[1] || !strcmp(&line[1], "es"))
273 break;
274 continue;
275 case 0:
276 newval = oldval;
277 break;
278 case '?':
279 goto help;
280 default:
281 continue;
282 }
283 if (sym_set_tristate_value(sym, newval))
284 return 0;
285help:
286 help = nohelp_text;
287 if (sym->help)
288 help = sym->help;
289 printf("\n%s\n", help);
290 }
291}
292
293static int conf_choice(struct menu *menu)
294{
295 struct symbol *sym, *def_sym;
296 struct menu *cmenu, *def_menu;
297 const char *help;
298 int type, len;
299 bool is_new;
300
301 sym = menu->sym;
302 type = sym_get_type(sym);
303 is_new = !sym_has_value(sym);
304 if (sym_is_changable(sym)) {
305 conf_sym(menu);
306 sym_calc_value(sym);
307 switch (sym_get_tristate_value(sym)) {
308 case no:
309 return 1;
310 case mod:
311 return 0;
312 case yes:
313 break;
314 }
315 } else {
316 sym->def = sym->curr;
317 if (S_TRI(sym->curr) == mod) {
318 printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu));
319 return 0;
320 }
321 }
322
323 while (1) {
324 printf("%*s%s ", indent - 1, "", menu_get_prompt(menu));
325 def_sym = sym_get_choice_value(sym);
326 def_menu = NULL;
327 for (cmenu = menu->list; cmenu; cmenu = cmenu->next) {
328 if (!menu_is_visible(cmenu))
329 continue;
330 printo(menu_get_prompt(cmenu));
331 if (cmenu->sym == def_sym)
332 def_menu = cmenu;
333 }
334 printo(NULL);
335 if (def_menu)
336 printf("[%s] ", menu_get_prompt(def_menu));
337 else {
338 printf("\n");
339 return 1;
340 }
341 switch (input_mode) {
342 case ask_new:
343 case ask_silent:
344 case ask_all:
345 conf_askvalue(sym, menu_get_prompt(def_menu));
346 strip(line);
347 break;
348 default:
349 line[0] = 0;
350 printf("\n");
351 }
352 if (line[0] == '?' && !line[1]) {
353 help = nohelp_text;
354 if (menu->sym->help)
355 help = menu->sym->help;
356 printf("\n%s\n", help);
357 continue;
358 }
359 if (line[0]) {
360 len = strlen(line) - 1;
361 line[len] = 0;
362
363 def_menu = NULL;
364 for (cmenu = menu->list; cmenu; cmenu = cmenu->next) {
365 if (!cmenu->sym || !menu_is_visible(cmenu))
366 continue;
367 if (!strncmp(line, menu_get_prompt(cmenu), len)) {
368 def_menu = cmenu;
369 break;
370 }
371 }
372 }
373 if (def_menu) {
374 sym_set_choice_value(sym, def_menu->sym);
375 if (def_menu->list) {
376 indent += 2;
377 conf(def_menu->list);
378 indent -= 2;
379 }
380 return 1;
381 }
382 }
383}
384
385static void conf(struct menu *menu)
386{
387 struct symbol *sym;
388 struct property *prop;
389 struct menu *child;
390
391 if (!menu_is_visible(menu))
392 return;
393
394 sym = menu->sym;
395 prop = menu->prompt;
396 if (prop) {
397 const char *prompt;
398
399 switch (prop->type) {
400 case P_MENU:
401 if (input_mode == ask_silent && rootEntry != menu) {
402 check_conf(menu);
403 return;
404 }
405 case P_COMMENT:
406 prompt = menu_get_prompt(menu);
407 if (prompt)
408 printf("%*c\n%*c %s\n%*c\n",
409 indent, '*',
410 indent, '*', prompt,
411 indent, '*');
412 default:
413 ;
414 }
415 }
416
417 if (!sym)
418 goto conf_childs;
419
420 if (sym_is_choice(sym)) {
421 conf_choice(menu);
422 if (S_TRI(sym->curr) != mod)
423 return;
424 goto conf_childs;
425 }
426
427 switch (sym->type) {
428 case S_INT:
429 case S_HEX:
430 case S_STRING:
431 conf_string(menu);
432 break;
433 default:
434 conf_sym(menu);
435 break;
436 }
437
438conf_childs:
439 if (sym)
440 indent += 2;
441 for (child = menu->list; child; child = child->next)
442 conf(child);
443 if (sym)
444 indent -= 2;
445}
446
447static void check_conf(struct menu *menu)
448{
449 struct symbol *sym;
450 struct menu *child;
451
452 if (!menu_is_visible(menu))
453 return;
454
455 sym = menu->sym;
456 if (!sym)
457 goto conf_childs;
458
459 if (sym_is_choice(sym)) {
460 if (!sym_has_value(sym)) {
461 if (!conf_cnt++)
462 printf("*\n* Restart config...\n*\n");
463 rootEntry = menu_get_parent_menu(menu);
464 conf(rootEntry);
465 }
466 if (sym_get_tristate_value(sym) != mod)
467 return;
468 goto conf_childs;
469 }
470
471 if (!sym_has_value(sym)) {
472 if (!conf_cnt++)
473 printf("*\n* Restart config...\n*\n");
474 rootEntry = menu_get_parent_menu(menu);
475 conf(rootEntry);
476 }
477
478conf_childs:
479 for (child = menu->list; child; child = child->next)
480 check_conf(child);
481}
482
483int main(int ac, char **av)
484{
485 const char *name;
486 struct stat tmpstat;
487
488 if (ac > 1 && av[1][0] == '-') {
489 switch (av[1][1]) {
490 case 'o':
491 input_mode = ask_new;
492 break;
493 case 's':
494 input_mode = ask_silent;
495 valid_stdin = isatty(0) && isatty(1) && isatty(2);
496 break;
497 case 'd':
498 input_mode = set_default;
499 break;
500 case 'n':
501 input_mode = set_no;
502 break;
503 case 'm':
504 input_mode = set_mod;
505 break;
506 case 'y':
507 input_mode = set_yes;
508 break;
509 case 'r':
510 input_mode = set_random;
511 srandom(time(NULL));
512 break;
513 case 'h':
514 case '?':
515 printf("%s [-o|-s] config\n", av[0]);
516 exit(0);
517 }
518 name = av[2];
519 } else
520 name = av[1];
521 conf_parse(name);
522 //zconfdump(stdout);
523 switch (input_mode) {
524 case set_default:
525 name = conf_get_default_confname();
526 if (conf_read(name)) {
527 printf("***\n"
528 "*** Can't find default configuration \"%s\"!\n"
529 "***\n", name);
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 "***\n"
538 "*** Please run some configurator (e.g. \"make oldconfig\" or\n"
539 "*** \"make menuconfig\" or \"make xconfig\").\n"
540 "***\n");
541 exit(1);
542 }
543 case ask_all:
544 case ask_new:
545 conf_read(NULL);
546 break;
547 default:
548 break;
549 }
550
551 if (input_mode != ask_silent) {
552 rootEntry = &rootmenu;
553 conf(&rootmenu);
554 if (input_mode == ask_all) {
555 input_mode = ask_silent;
556 valid_stdin = 1;
557 }
558 }
559 do {
560 conf_cnt = 0;
561 check_conf(&rootmenu);
562 } while (conf_cnt);
563 conf_write(NULL);
564 return 0;
565}