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