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