linux/scripts/kconfig/conf.c
<<
>>
Prefs
   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#include <errno.h>
  17
  18#include "lkc.h"
  19
  20static void conf(struct menu *menu);
  21static void check_conf(struct menu *menu);
  22static void xfgets(char *str, int size, FILE *in);
  23
  24enum input_mode {
  25        oldaskconfig,
  26        silentoldconfig,
  27        oldconfig,
  28        allnoconfig,
  29        allyesconfig,
  30        allmodconfig,
  31        alldefconfig,
  32        randconfig,
  33        defconfig,
  34        savedefconfig,
  35        listnewconfig,
  36        olddefconfig,
  37} input_mode = oldaskconfig;
  38
  39static int indent = 1;
  40static int tty_stdio;
  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                /* fall through */
 110        case oldaskconfig:
 111                fflush(stdout);
 112                xfgets(line, 128, stdin);
 113                if (!tty_stdio)
 114                        printf("\n");
 115                return 1;
 116        default:
 117                break;
 118        }
 119
 120        switch (type) {
 121        case S_INT:
 122        case S_HEX:
 123        case S_STRING:
 124                printf("%s\n", def);
 125                return 1;
 126        default:
 127                ;
 128        }
 129        printf("%s", line);
 130        return 1;
 131}
 132
 133static int conf_string(struct menu *menu)
 134{
 135        struct symbol *sym = menu->sym;
 136        const char *def;
 137
 138        while (1) {
 139                printf("%*s%s ", indent - 1, "", _(menu->prompt->text));
 140                printf("(%s) ", sym->name);
 141                def = sym_get_string_value(sym);
 142                if (sym_get_string_value(sym))
 143                        printf("[%s] ", def);
 144                if (!conf_askvalue(sym, def))
 145                        return 0;
 146                switch (line[0]) {
 147                case '\n':
 148                        break;
 149                case '?':
 150                        /* print help */
 151                        if (line[1] == '\n') {
 152                                print_help(menu);
 153                                def = NULL;
 154                                break;
 155                        }
 156                        /* fall through */
 157                default:
 158                        line[strlen(line)-1] = 0;
 159                        def = line;
 160                }
 161                if (def && sym_set_string_value(sym, def))
 162                        return 0;
 163        }
 164}
 165
 166static int conf_sym(struct menu *menu)
 167{
 168        struct symbol *sym = menu->sym;
 169        tristate oldval, newval;
 170
 171        while (1) {
 172                printf("%*s%s ", indent - 1, "", _(menu->prompt->text));
 173                if (sym->name)
 174                        printf("(%s) ", sym->name);
 175                putchar('[');
 176                oldval = sym_get_tristate_value(sym);
 177                switch (oldval) {
 178                case no:
 179                        putchar('N');
 180                        break;
 181                case mod:
 182                        putchar('M');
 183                        break;
 184                case yes:
 185                        putchar('Y');
 186                        break;
 187                }
 188                if (oldval != no && sym_tristate_within_range(sym, no))
 189                        printf("/n");
 190                if (oldval != mod && sym_tristate_within_range(sym, mod))
 191                        printf("/m");
 192                if (oldval != yes && sym_tristate_within_range(sym, yes))
 193                        printf("/y");
 194                if (menu_has_help(menu))
 195                        printf("/?");
 196                printf("] ");
 197                if (!conf_askvalue(sym, sym_get_string_value(sym)))
 198                        return 0;
 199                strip(line);
 200
 201                switch (line[0]) {
 202                case 'n':
 203                case 'N':
 204                        newval = no;
 205                        if (!line[1] || !strcmp(&line[1], "o"))
 206                                break;
 207                        continue;
 208                case 'm':
 209                case 'M':
 210                        newval = mod;
 211                        if (!line[1])
 212                                break;
 213                        continue;
 214                case 'y':
 215                case 'Y':
 216                        newval = yes;
 217                        if (!line[1] || !strcmp(&line[1], "es"))
 218                                break;
 219                        continue;
 220                case 0:
 221                        newval = oldval;
 222                        break;
 223                case '?':
 224                        goto help;
 225                default:
 226                        continue;
 227                }
 228                if (sym_set_tristate_value(sym, newval))
 229                        return 0;
 230help:
 231                print_help(menu);
 232        }
 233}
 234
 235static int conf_choice(struct menu *menu)
 236{
 237        struct symbol *sym, *def_sym;
 238        struct menu *child;
 239        bool is_new;
 240
 241        sym = menu->sym;
 242        is_new = !sym_has_value(sym);
 243        if (sym_is_changable(sym)) {
 244                conf_sym(menu);
 245                sym_calc_value(sym);
 246                switch (sym_get_tristate_value(sym)) {
 247                case no:
 248                        return 1;
 249                case mod:
 250                        return 0;
 251                case yes:
 252                        break;
 253                }
 254        } else {
 255                switch (sym_get_tristate_value(sym)) {
 256                case no:
 257                        return 1;
 258                case mod:
 259                        printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu)));
 260                        return 0;
 261                case yes:
 262                        break;
 263                }
 264        }
 265
 266        while (1) {
 267                int cnt, def;
 268
 269                printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu)));
 270                def_sym = sym_get_choice_value(sym);
 271                cnt = def = 0;
 272                line[0] = 0;
 273                for (child = menu->list; child; child = child->next) {
 274                        if (!menu_is_visible(child))
 275                                continue;
 276                        if (!child->sym) {
 277                                printf("%*c %s\n", indent, '*', _(menu_get_prompt(child)));
 278                                continue;
 279                        }
 280                        cnt++;
 281                        if (child->sym == def_sym) {
 282                                def = cnt;
 283                                printf("%*c", indent, '>');
 284                        } else
 285                                printf("%*c", indent, ' ');
 286                        printf(" %d. %s", cnt, _(menu_get_prompt(child)));
 287                        if (child->sym->name)
 288                                printf(" (%s)", child->sym->name);
 289                        if (!sym_has_value(child->sym))
 290                                printf(_(" (NEW)"));
 291                        printf("\n");
 292                }
 293                printf(_("%*schoice"), indent - 1, "");
 294                if (cnt == 1) {
 295                        printf("[1]: 1\n");
 296                        goto conf_childs;
 297                }
 298                printf("[1-%d", cnt);
 299                if (menu_has_help(menu))
 300                        printf("?");
 301                printf("]: ");
 302                switch (input_mode) {
 303                case oldconfig:
 304                case silentoldconfig:
 305                        if (!is_new) {
 306                                cnt = def;
 307                                printf("%d\n", cnt);
 308                                break;
 309                        }
 310                        check_stdin();
 311                        /* fall through */
 312                case oldaskconfig:
 313                        fflush(stdout);
 314                        xfgets(line, 128, stdin);
 315                        strip(line);
 316                        if (line[0] == '?') {
 317                                print_help(menu);
 318                                continue;
 319                        }
 320                        if (!line[0])
 321                                cnt = def;
 322                        else if (isdigit(line[0]))
 323                                cnt = atoi(line);
 324                        else
 325                                continue;
 326                        break;
 327                default:
 328                        break;
 329                }
 330
 331        conf_childs:
 332                for (child = menu->list; child; child = child->next) {
 333                        if (!child->sym || !menu_is_visible(child))
 334                                continue;
 335                        if (!--cnt)
 336                                break;
 337                }
 338                if (!child)
 339                        continue;
 340                if (line[0] && line[strlen(line) - 1] == '?') {
 341                        print_help(child);
 342                        continue;
 343                }
 344                sym_set_choice_value(sym, child->sym);
 345                for (child = child->list; child; child = child->next) {
 346                        indent += 2;
 347                        conf(child);
 348                        indent -= 2;
 349                }
 350                return 1;
 351        }
 352}
 353
 354static void conf(struct menu *menu)
 355{
 356        struct symbol *sym;
 357        struct property *prop;
 358        struct menu *child;
 359
 360        if (!menu_is_visible(menu))
 361                return;
 362
 363        sym = menu->sym;
 364        prop = menu->prompt;
 365        if (prop) {
 366                const char *prompt;
 367
 368                switch (prop->type) {
 369                case P_MENU:
 370                        if ((input_mode == silentoldconfig ||
 371                             input_mode == listnewconfig ||
 372                             input_mode == olddefconfig) &&
 373                            rootEntry != menu) {
 374                                check_conf(menu);
 375                                return;
 376                        }
 377                        /* fall through */
 378                case P_COMMENT:
 379                        prompt = menu_get_prompt(menu);
 380                        if (prompt)
 381                                printf("%*c\n%*c %s\n%*c\n",
 382                                        indent, '*',
 383                                        indent, '*', _(prompt),
 384                                        indent, '*');
 385                default:
 386                        ;
 387                }
 388        }
 389
 390        if (!sym)
 391                goto conf_childs;
 392
 393        if (sym_is_choice(sym)) {
 394                conf_choice(menu);
 395                if (sym->curr.tri != mod)
 396                        return;
 397                goto conf_childs;
 398        }
 399
 400        switch (sym->type) {
 401        case S_INT:
 402        case S_HEX:
 403        case S_STRING:
 404                conf_string(menu);
 405                break;
 406        default:
 407                conf_sym(menu);
 408                break;
 409        }
 410
 411conf_childs:
 412        if (sym)
 413                indent += 2;
 414        for (child = menu->list; child; child = child->next)
 415                conf(child);
 416        if (sym)
 417                indent -= 2;
 418}
 419
 420static void check_conf(struct menu *menu)
 421{
 422        struct symbol *sym;
 423        struct menu *child;
 424
 425        if (!menu_is_visible(menu))
 426                return;
 427
 428        sym = menu->sym;
 429        if (sym && !sym_has_value(sym)) {
 430                if (sym_is_changable(sym) ||
 431                    (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) {
 432                        if (input_mode == listnewconfig) {
 433                                if (sym->name && !sym_is_choice_value(sym)) {
 434                                        printf("%s%s\n", CONFIG_, sym->name);
 435                                }
 436                        } else if (input_mode != olddefconfig) {
 437                                if (!conf_cnt++)
 438                                        printf(_("*\n* Restart config...\n*\n"));
 439                                rootEntry = menu_get_parent_menu(menu);
 440                                conf(rootEntry);
 441                        }
 442                }
 443        }
 444
 445        for (child = menu->list; child; child = child->next)
 446                check_conf(child);
 447}
 448
 449static struct option long_opts[] = {
 450        {"oldaskconfig",    no_argument,       NULL, oldaskconfig},
 451        {"oldconfig",       no_argument,       NULL, oldconfig},
 452        {"silentoldconfig", no_argument,       NULL, silentoldconfig},
 453        {"defconfig",       optional_argument, NULL, defconfig},
 454        {"savedefconfig",   required_argument, NULL, savedefconfig},
 455        {"allnoconfig",     no_argument,       NULL, allnoconfig},
 456        {"allyesconfig",    no_argument,       NULL, allyesconfig},
 457        {"allmodconfig",    no_argument,       NULL, allmodconfig},
 458        {"alldefconfig",    no_argument,       NULL, alldefconfig},
 459        {"randconfig",      no_argument,       NULL, randconfig},
 460        {"listnewconfig",   no_argument,       NULL, listnewconfig},
 461        {"olddefconfig",    no_argument,       NULL, olddefconfig},
 462        /*
 463         * oldnoconfig is an alias of olddefconfig, because people already
 464         * are dependent on its behavior(sets new symbols to their default
 465         * value but not 'n') with the counter-intuitive name.
 466         */
 467        {"oldnoconfig",     no_argument,       NULL, olddefconfig},
 468        {NULL, 0, NULL, 0}
 469};
 470
 471static void conf_usage(const char *progname)
 472{
 473
 474        printf("Usage: %s [option] <kconfig-file>\n", progname);
 475        printf("[option] is _one_ of the following:\n");
 476        printf("  --listnewconfig         List new options\n");
 477        printf("  --oldaskconfig          Start a new configuration using a line-oriented program\n");
 478        printf("  --oldconfig             Update a configuration using a provided .config as base\n");
 479        printf("  --silentoldconfig       Same as oldconfig, but quietly, additionally update deps\n");
 480        printf("  --olddefconfig          Same as silentoldconfig but sets new symbols to their default value\n");
 481        printf("  --oldnoconfig           An alias of olddefconfig\n");
 482        printf("  --defconfig <file>      New config with default defined in <file>\n");
 483        printf("  --savedefconfig <file>  Save the minimal current configuration to <file>\n");
 484        printf("  --allnoconfig           New config where all options are answered with no\n");
 485        printf("  --allyesconfig          New config where all options are answered with yes\n");
 486        printf("  --allmodconfig          New config where all options are answered with mod\n");
 487        printf("  --alldefconfig          New config with all symbols set to default\n");
 488        printf("  --randconfig            New config with random answer to all options\n");
 489}
 490
 491int main(int ac, char **av)
 492{
 493        const char *progname = av[0];
 494        int opt;
 495        const char *name, *defconfig_file = NULL /* gcc uninit */;
 496        struct stat tmpstat;
 497
 498        setlocale(LC_ALL, "");
 499        bindtextdomain(PACKAGE, LOCALEDIR);
 500        textdomain(PACKAGE);
 501
 502        tty_stdio = isatty(0) && isatty(1) && isatty(2);
 503
 504        while ((opt = getopt_long(ac, av, "", long_opts, NULL)) != -1) {
 505                input_mode = (enum input_mode)opt;
 506                switch (opt) {
 507                case silentoldconfig:
 508                        sync_kconfig = 1;
 509                        break;
 510                case defconfig:
 511                case savedefconfig:
 512                        defconfig_file = optarg;
 513                        break;
 514                case randconfig:
 515                {
 516                        struct timeval now;
 517                        unsigned int seed;
 518                        char *seed_env;
 519
 520                        /*
 521                         * Use microseconds derived seed,
 522                         * compensate for systems where it may be zero
 523                         */
 524                        gettimeofday(&now, NULL);
 525                        seed = (unsigned int)((now.tv_sec + 1) * (now.tv_usec + 1));
 526
 527                        seed_env = getenv("KCONFIG_SEED");
 528                        if( seed_env && *seed_env ) {
 529                                char *endp;
 530                                int tmp = (int)strtol(seed_env, &endp, 10);
 531                                if (*endp == '\0') {
 532                                        seed = tmp;
 533                                }
 534                        }
 535                        srand(seed);
 536                        break;
 537                }
 538                case oldaskconfig:
 539                case oldconfig:
 540                case allnoconfig:
 541                case allyesconfig:
 542                case allmodconfig:
 543                case alldefconfig:
 544                case listnewconfig:
 545                case olddefconfig:
 546                        break;
 547                case '?':
 548                        conf_usage(progname);
 549                        exit(1);
 550                        break;
 551                }
 552        }
 553        if (ac == optind) {
 554                printf(_("%s: Kconfig file missing\n"), av[0]);
 555                conf_usage(progname);
 556                exit(1);
 557        }
 558        name = av[optind];
 559        conf_parse(name);
 560        //zconfdump(stdout);
 561        if (sync_kconfig) {
 562                name = conf_get_configname();
 563                if (stat(name, &tmpstat)) {
 564                        fprintf(stderr, _("***\n"
 565                                "*** Configuration file \"%s\" not found!\n"
 566                                "***\n"
 567                                "*** Please run some configurator (e.g. \"make oldconfig\" or\n"
 568                                "*** \"make menuconfig\" or \"make xconfig\").\n"
 569                                "***\n"), name);
 570                        exit(1);
 571                }
 572        }
 573
 574        switch (input_mode) {
 575        case defconfig:
 576                if (!defconfig_file)
 577                        defconfig_file = conf_get_default_confname();
 578                if (conf_read(defconfig_file)) {
 579                        printf(_("***\n"
 580                                "*** Can't find default configuration \"%s\"!\n"
 581                                "***\n"), defconfig_file);
 582                        exit(1);
 583                }
 584                break;
 585        case savedefconfig:
 586        case silentoldconfig:
 587        case oldaskconfig:
 588        case oldconfig:
 589        case listnewconfig:
 590        case olddefconfig:
 591                conf_read(NULL);
 592                break;
 593        case allnoconfig:
 594        case allyesconfig:
 595        case allmodconfig:
 596        case alldefconfig:
 597        case randconfig:
 598                name = getenv("KCONFIG_ALLCONFIG");
 599                if (!name)
 600                        break;
 601                if ((strcmp(name, "") != 0) && (strcmp(name, "1") != 0)) {
 602                        if (conf_read_simple(name, S_DEF_USER)) {
 603                                fprintf(stderr,
 604                                        _("*** Can't read seed configuration \"%s\"!\n"),
 605                                        name);
 606                                exit(1);
 607                        }
 608                        break;
 609                }
 610                switch (input_mode) {
 611                case allnoconfig:       name = "allno.config"; break;
 612                case allyesconfig:      name = "allyes.config"; break;
 613                case allmodconfig:      name = "allmod.config"; break;
 614                case alldefconfig:      name = "alldef.config"; break;
 615                case randconfig:        name = "allrandom.config"; break;
 616                default: break;
 617                }
 618                if (conf_read_simple(name, S_DEF_USER) &&
 619                    conf_read_simple("all.config", S_DEF_USER)) {
 620                        fprintf(stderr,
 621                                _("*** KCONFIG_ALLCONFIG set, but no \"%s\" or \"all.config\" file found\n"),
 622                                name);
 623                        exit(1);
 624                }
 625                break;
 626        default:
 627                break;
 628        }
 629
 630        if (sync_kconfig) {
 631                if (conf_get_changed()) {
 632                        name = getenv("KCONFIG_NOSILENTUPDATE");
 633                        if (name && *name) {
 634                                fprintf(stderr,
 635                                        _("\n*** The configuration requires explicit update.\n\n"));
 636                                return 1;
 637                        }
 638                }
 639                valid_stdin = tty_stdio;
 640        }
 641
 642        switch (input_mode) {
 643        case allnoconfig:
 644                conf_set_all_new_symbols(def_no);
 645                break;
 646        case allyesconfig:
 647                conf_set_all_new_symbols(def_yes);
 648                break;
 649        case allmodconfig:
 650                conf_set_all_new_symbols(def_mod);
 651                break;
 652        case alldefconfig:
 653                conf_set_all_new_symbols(def_default);
 654                break;
 655        case randconfig:
 656                conf_set_all_new_symbols(def_random);
 657                break;
 658        case defconfig:
 659                conf_set_all_new_symbols(def_default);
 660                break;
 661        case savedefconfig:
 662                break;
 663        case oldaskconfig:
 664                rootEntry = &rootmenu;
 665                conf(&rootmenu);
 666                input_mode = silentoldconfig;
 667                /* fall through */
 668        case oldconfig:
 669        case listnewconfig:
 670        case olddefconfig:
 671        case silentoldconfig:
 672                /* Update until a loop caused no more changes */
 673                do {
 674                        conf_cnt = 0;
 675                        check_conf(&rootmenu);
 676                } while (conf_cnt &&
 677                         (input_mode != listnewconfig &&
 678                          input_mode != olddefconfig));
 679                break;
 680        }
 681
 682        if (sync_kconfig) {
 683                /* silentoldconfig is used during the build so we shall update autoconf.
 684                 * All other commands are only used to generate a config.
 685                 */
 686                if (conf_get_changed() && conf_write(NULL)) {
 687                        fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n"));
 688                        exit(1);
 689                }
 690                if (conf_write_autoconf()) {
 691                        fprintf(stderr, _("\n*** Error during update of the configuration.\n\n"));
 692                        return 1;
 693                }
 694        } else if (input_mode == savedefconfig) {
 695                if (conf_write_defconfig(defconfig_file)) {
 696                        fprintf(stderr, _("n*** Error while saving defconfig to: %s\n\n"),
 697                                defconfig_file);
 698                        return 1;
 699                }
 700        } else if (input_mode != listnewconfig) {
 701                if (conf_write(NULL)) {
 702                        fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n"));
 703                        exit(1);
 704                }
 705        }
 706        return 0;
 707}
 708
 709/*
 710 * Helper function to facilitate fgets() by Jean Sacren.
 711 */
 712void xfgets(char *str, int size, FILE *in)
 713{
 714        if (fgets(str, size, in) == NULL)
 715                fprintf(stderr, "\nError in reading or end of file.\n");
 716}
 717