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