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