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

Archive Download this file



interactive