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

Archive Download this file



interactive