coreboot-v3/util/kconfig/zconf.y
<<
>>
Prefs
   1%{
   2/*
   3 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
   4 * Released under the terms of the GNU GPL v2.0.
   5 */
   6
   7#include <ctype.h>
   8#include <stdarg.h>
   9#include <stdio.h>
  10#include <stdlib.h>
  11#include <string.h>
  12#include <stdbool.h>
  13
  14#define LKC_DIRECT_LINK
  15#include "lkc.h"
  16
  17#include "zconf.hash.c"
  18
  19#define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt)
  20
  21#define PRINTD          0x0001
  22#define DEBUG_PARSE     0x0002
  23
  24int cdebug = PRINTD;
  25
  26extern int zconflex(void);
  27static void zconfprint(const char *err, ...);
  28static void zconf_error(const char *err, ...);
  29static void zconferror(const char *err);
  30static bool zconf_endtoken(struct kconf_id *id, int starttoken, int endtoken);
  31
  32struct symbol *symbol_hash[257];
  33
  34static struct menu *current_menu, *current_entry;
  35
  36#define YYDEBUG 0
  37#if YYDEBUG
  38#define YYERROR_VERBOSE
  39#endif
  40%}
  41%expect 26
  42
  43%union
  44{
  45        char *string;
  46        struct file *file;
  47        struct symbol *symbol;
  48        struct expr *expr;
  49        struct menu *menu;
  50        struct kconf_id *id;
  51}
  52
  53%token <id>T_MAINMENU
  54%token <id>T_MENU
  55%token <id>T_ENDMENU
  56%token <id>T_SOURCE
  57%token <id>T_CHOICE
  58%token <id>T_ENDCHOICE
  59%token <id>T_COMMENT
  60%token <id>T_CONFIG
  61%token <id>T_MENUCONFIG
  62%token <id>T_HELP
  63%token <string> T_HELPTEXT
  64%token <id>T_IF
  65%token <id>T_ENDIF
  66%token <id>T_DEPENDS
  67%token <id>T_REQUIRES
  68%token <id>T_OPTIONAL
  69%token <id>T_PROMPT
  70%token <id>T_TYPE
  71%token <id>T_DEFAULT
  72%token <id>T_SELECT
  73%token <id>T_RANGE
  74%token <id>T_ON
  75%token <string> T_WORD
  76%token <string> T_WORD_QUOTE
  77%token T_UNEQUAL
  78%token T_CLOSE_PAREN
  79%token T_OPEN_PAREN
  80%token T_EOL
  81
  82%left T_OR
  83%left T_AND
  84%left T_EQUAL T_UNEQUAL
  85%nonassoc T_NOT
  86
  87%type <string> prompt
  88%type <symbol> symbol
  89%type <expr> expr
  90%type <expr> if_expr
  91%type <id> end
  92%type <id> option_name
  93%type <menu> if_entry menu_entry choice_entry
  94
  95%destructor {
  96        fprintf(stderr, "%s:%d: missing end statement for this entry\n",
  97                $$->file->name, $$->lineno);
  98        if (current_menu == $$)
  99                menu_end_menu();
 100} if_entry menu_entry choice_entry
 101
 102%%
 103input: stmt_list;
 104
 105stmt_list:
 106          /* empty */
 107        | stmt_list common_stmt
 108        | stmt_list choice_stmt
 109        | stmt_list menu_stmt
 110        | stmt_list T_MAINMENU prompt nl
 111        | stmt_list end                 { zconf_error("unexpected end statement"); }
 112        | stmt_list T_WORD error T_EOL  { zconf_error("unknown statement \"%s\"", $2); }
 113        | stmt_list option_name error T_EOL
 114{
 115        zconf_error("unexpected option \"%s\"", kconf_id_strings + $2->name);
 116}
 117        | stmt_list error T_EOL         { zconf_error("invalid statement"); }
 118;
 119
 120option_name:
 121        T_DEPENDS | T_PROMPT | T_TYPE | T_SELECT | T_OPTIONAL | T_RANGE | T_DEFAULT
 122;
 123
 124common_stmt:
 125          T_EOL
 126        | if_stmt
 127        | comment_stmt
 128        | config_stmt
 129        | menuconfig_stmt
 130        | source_stmt
 131;
 132
 133option_error:
 134          T_WORD error T_EOL            { zconf_error("unknown option \"%s\"", $1); }
 135        | error T_EOL                   { zconf_error("invalid option"); }
 136;
 137
 138
 139/* config/menuconfig entry */
 140
 141config_entry_start: T_CONFIG T_WORD T_EOL
 142{
 143        struct symbol *sym = sym_lookup($2, 0);
 144        sym->flags |= SYMBOL_OPTIONAL;
 145        menu_add_entry(sym);
 146        printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), $2);
 147};
 148
 149config_stmt: config_entry_start config_option_list
 150{
 151        menu_end_entry();
 152        printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
 153};
 154
 155menuconfig_entry_start: T_MENUCONFIG T_WORD T_EOL
 156{
 157        struct symbol *sym = sym_lookup($2, 0);
 158        sym->flags |= SYMBOL_OPTIONAL;
 159        menu_add_entry(sym);
 160        printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), $2);
 161};
 162
 163menuconfig_stmt: menuconfig_entry_start config_option_list
 164{
 165        if (current_entry->prompt)
 166                current_entry->prompt->type = P_MENU;
 167        else
 168                zconfprint("warning: menuconfig statement without prompt");
 169        menu_end_entry();
 170        printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
 171};
 172
 173config_option_list:
 174          /* empty */
 175        | config_option_list config_option
 176        | config_option_list depends
 177        | config_option_list help
 178        | config_option_list option_error
 179        | config_option_list T_EOL
 180;
 181
 182config_option: T_TYPE prompt_stmt_opt T_EOL
 183{
 184        menu_set_type($1->stype);
 185        printd(DEBUG_PARSE, "%s:%d:type(%u)\n",
 186                zconf_curname(), zconf_lineno(),
 187                $1->stype);
 188};
 189
 190config_option: T_PROMPT prompt if_expr T_EOL
 191{
 192        menu_add_prompt(P_PROMPT, $2, $3);
 193        printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
 194};
 195
 196config_option: T_DEFAULT expr if_expr T_EOL
 197{
 198        menu_add_expr(P_DEFAULT, $2, $3);
 199        if ($1->stype != S_UNKNOWN)
 200                menu_set_type($1->stype);
 201        printd(DEBUG_PARSE, "%s:%d:default(%u)\n",
 202                zconf_curname(), zconf_lineno(),
 203                $1->stype);
 204};
 205
 206config_option: T_SELECT T_WORD if_expr T_EOL
 207{
 208        menu_add_symbol(P_SELECT, sym_lookup($2, 0), $3);
 209        printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno());
 210};
 211
 212config_option: T_RANGE symbol symbol if_expr T_EOL
 213{
 214        menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,$2, $3), $4);
 215        printd(DEBUG_PARSE, "%s:%d:range\n", zconf_curname(), zconf_lineno());
 216};
 217
 218/* choice entry */
 219
 220choice: T_CHOICE T_EOL
 221{
 222        struct symbol *sym = sym_lookup(NULL, 0);
 223        sym->flags |= SYMBOL_CHOICE;
 224        menu_add_entry(sym);
 225        menu_add_expr(P_CHOICE, NULL, NULL);
 226        printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno());
 227};
 228
 229choice_entry: choice choice_option_list
 230{
 231        $$ = menu_add_menu();
 232};
 233
 234choice_end: end
 235{
 236        if (zconf_endtoken($1, T_CHOICE, T_ENDCHOICE)) {
 237                menu_end_menu();
 238                printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno());
 239        }
 240};
 241
 242choice_stmt: choice_entry choice_block choice_end
 243;
 244
 245choice_option_list:
 246          /* empty */
 247        | choice_option_list choice_option
 248        | choice_option_list depends
 249        | choice_option_list help
 250        | choice_option_list T_EOL
 251        | choice_option_list option_error
 252;
 253
 254choice_option: T_PROMPT prompt if_expr T_EOL
 255{
 256        menu_add_prompt(P_PROMPT, $2, $3);
 257        printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
 258};
 259
 260choice_option: T_TYPE prompt_stmt_opt T_EOL
 261{
 262        if ($1->stype == S_BOOLEAN || $1->stype == S_TRISTATE) {
 263                menu_set_type($1->stype);
 264                printd(DEBUG_PARSE, "%s:%d:type(%u)\n",
 265                        zconf_curname(), zconf_lineno(),
 266                        $1->stype);
 267        } else
 268                YYERROR;
 269};
 270
 271choice_option: T_OPTIONAL T_EOL
 272{
 273        current_entry->sym->flags |= SYMBOL_OPTIONAL;
 274        printd(DEBUG_PARSE, "%s:%d:optional\n", zconf_curname(), zconf_lineno());
 275};
 276
 277choice_option: T_DEFAULT T_WORD if_expr T_EOL
 278{
 279        if ($1->stype == S_UNKNOWN) {
 280                menu_add_symbol(P_DEFAULT, sym_lookup($2, 0), $3);
 281                printd(DEBUG_PARSE, "%s:%d:default\n",
 282                        zconf_curname(), zconf_lineno());
 283        } else
 284                YYERROR;
 285};
 286
 287choice_block:
 288          /* empty */
 289        | choice_block common_stmt
 290;
 291
 292/* if entry */
 293
 294if_entry: T_IF expr nl
 295{
 296        printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno());
 297        menu_add_entry(NULL);
 298        menu_add_dep($2);
 299        $$ = menu_add_menu();
 300};
 301
 302if_end: end
 303{
 304        if (zconf_endtoken($1, T_IF, T_ENDIF)) {
 305                menu_end_menu();
 306                printd(DEBUG_PARSE, "%s:%d:endif\n", zconf_curname(), zconf_lineno());
 307        }
 308};
 309
 310if_stmt: if_entry if_block if_end
 311;
 312
 313if_block:
 314          /* empty */
 315        | if_block common_stmt
 316        | if_block menu_stmt
 317        | if_block choice_stmt
 318;
 319
 320/* menu entry */
 321
 322menu: T_MENU prompt T_EOL
 323{
 324        menu_add_entry(NULL);
 325        menu_add_prompt(P_MENU, $2, NULL);
 326        printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno());
 327};
 328
 329menu_entry: menu depends_list
 330{
 331        $$ = menu_add_menu();
 332};
 333
 334menu_end: end
 335{
 336        if (zconf_endtoken($1, T_MENU, T_ENDMENU)) {
 337                menu_end_menu();
 338                printd(DEBUG_PARSE, "%s:%d:endmenu\n", zconf_curname(), zconf_lineno());
 339        }
 340};
 341
 342menu_stmt: menu_entry menu_block menu_end
 343;
 344
 345menu_block:
 346          /* empty */
 347        | menu_block common_stmt
 348        | menu_block menu_stmt
 349        | menu_block choice_stmt
 350;
 351
 352source_stmt: T_SOURCE prompt T_EOL
 353{
 354        printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), $2);
 355        zconf_nextfile($2);
 356};
 357
 358/* comment entry */
 359
 360comment: T_COMMENT prompt T_EOL
 361{
 362        menu_add_entry(NULL);
 363        menu_add_prompt(P_COMMENT, $2, NULL);
 364        printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno());
 365};
 366
 367comment_stmt: comment depends_list
 368{
 369        menu_end_entry();
 370};
 371
 372/* help option */
 373
 374help_start: T_HELP T_EOL
 375{
 376        printd(DEBUG_PARSE, "%s:%d:help\n", zconf_curname(), zconf_lineno());
 377        zconf_starthelp();
 378};
 379
 380help: help_start T_HELPTEXT
 381{
 382        current_entry->sym->help = $2;
 383};
 384
 385/* depends option */
 386
 387depends_list:
 388          /* empty */
 389        | depends_list depends
 390        | depends_list T_EOL
 391        | depends_list option_error
 392;
 393
 394depends: T_DEPENDS T_ON expr T_EOL
 395{
 396        menu_add_dep($3);
 397        printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno());
 398}
 399        | T_DEPENDS expr T_EOL
 400{
 401        menu_add_dep($2);
 402        printd(DEBUG_PARSE, "%s:%d:depends\n", zconf_curname(), zconf_lineno());
 403}
 404        | T_REQUIRES expr T_EOL
 405{
 406        menu_add_dep($2);
 407        printd(DEBUG_PARSE, "%s:%d:requires\n", zconf_curname(), zconf_lineno());
 408};
 409
 410/* prompt statement */
 411
 412prompt_stmt_opt:
 413          /* empty */
 414        | prompt if_expr
 415{
 416        menu_add_prompt(P_PROMPT, $1, $2);
 417};
 418
 419prompt:   T_WORD
 420        | T_WORD_QUOTE
 421;
 422
 423end:      T_ENDMENU T_EOL       { $$ = $1; }
 424        | T_ENDCHOICE T_EOL     { $$ = $1; }
 425        | T_ENDIF T_EOL         { $$ = $1; }
 426;
 427
 428nl:
 429          T_EOL
 430        | nl T_EOL
 431;
 432
 433if_expr:  /* empty */                   { $$ = NULL; }
 434        | T_IF expr                     { $$ = $2; }
 435;
 436
 437expr:     symbol                                { $$ = expr_alloc_symbol($1); }
 438        | symbol T_EQUAL symbol                 { $$ = expr_alloc_comp(E_EQUAL, $1, $3); }
 439        | symbol T_UNEQUAL symbol               { $$ = expr_alloc_comp(E_UNEQUAL, $1, $3); }
 440        | T_OPEN_PAREN expr T_CLOSE_PAREN       { $$ = $2; }
 441        | T_NOT expr                            { $$ = expr_alloc_one(E_NOT, $2); }
 442        | expr T_OR expr                        { $$ = expr_alloc_two(E_OR, $1, $3); }
 443        | expr T_AND expr                       { $$ = expr_alloc_two(E_AND, $1, $3); }
 444;
 445
 446symbol:   T_WORD        { $$ = sym_lookup($1, 0); free($1); }
 447        | T_WORD_QUOTE  { $$ = sym_lookup($1, 1); free($1); }
 448;
 449
 450%%
 451
 452void conf_parse(const char *name)
 453{
 454        struct symbol *sym;
 455        int i;
 456
 457        zconf_initscan(name);
 458
 459        sym_init();
 460        menu_init();
 461        modules_sym = sym_lookup("MODULES", 0);
 462        rootmenu.prompt = menu_add_prompt(P_MENU, "coreboot configuration", NULL);
 463
 464#if YYDEBUG
 465        if (getenv("ZCONF_DEBUG"))
 466                zconfdebug = 1;
 467#endif
 468        zconfparse();
 469        if (zconfnerrs)
 470                exit(1);
 471        menu_finalize(&rootmenu);
 472        for_all_symbols(i, sym) {
 473                sym_check_deps(sym);
 474        }
 475
 476        sym_change_count = 1;
 477}
 478
 479const char *zconf_tokenname(int token)
 480{
 481        switch (token) {
 482        case T_MENU:            return "menu";
 483        case T_ENDMENU:         return "endmenu";
 484        case T_CHOICE:          return "choice";
 485        case T_ENDCHOICE:       return "endchoice";
 486        case T_IF:              return "if";
 487        case T_ENDIF:           return "endif";
 488        case T_DEPENDS:         return "depends";
 489        }
 490        return "<token>";
 491}
 492
 493static bool zconf_endtoken(struct kconf_id *id, int starttoken, int endtoken)
 494{
 495        if (id->token != endtoken) {
 496                zconf_error("unexpected '%s' within %s block",
 497                        kconf_id_strings + id->name, zconf_tokenname(starttoken));
 498                zconfnerrs++;
 499                return false;
 500        }
 501        if (current_menu->file != current_file) {
 502                zconf_error("'%s' in different file than '%s'",
 503                        kconf_id_strings + id->name, zconf_tokenname(starttoken));
 504                fprintf(stderr, "%s:%d: location of the '%s'\n",
 505                        current_menu->file->name, current_menu->lineno,
 506                        zconf_tokenname(starttoken));
 507                zconfnerrs++;
 508                return false;
 509        }
 510        return true;
 511}
 512
 513static void zconfprint(const char *err, ...)
 514{
 515        va_list ap;
 516
 517        fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno());
 518        va_start(ap, err);
 519        vfprintf(stderr, err, ap);
 520        va_end(ap);
 521        fprintf(stderr, "\n");
 522}
 523
 524static void zconf_error(const char *err, ...)
 525{
 526        va_list ap;
 527
 528        zconfnerrs++;
 529        fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno());
 530        va_start(ap, err);
 531        vfprintf(stderr, err, ap);
 532        va_end(ap);
 533        fprintf(stderr, "\n");
 534}
 535
 536static void zconferror(const char *err)
 537{
 538#if YYDEBUG
 539        fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err);
 540#endif
 541}
 542
 543void print_quoted_string(FILE *out, const char *str)
 544{
 545        const char *p;
 546        int len;
 547
 548        putc('"', out);
 549        while ((p = strchr(str, '"'))) {
 550                len = p - str;
 551                if (len)
 552                        fprintf(out, "%.*s", len, str);
 553                fputs("\\\"", out);
 554                str = p + 1;
 555        }
 556        fputs(str, out);
 557        putc('"', out);
 558}
 559
 560void print_symbol(FILE *out, struct menu *menu)
 561{
 562        struct symbol *sym = menu->sym;
 563        struct property *prop;
 564
 565        if (sym_is_choice(sym))
 566                fprintf(out, "choice\n");
 567        else
 568                fprintf(out, "config %s\n", sym->name);
 569        switch (sym->type) {
 570        case S_BOOLEAN:
 571                fputs("  boolean\n", out);
 572                break;
 573        case S_TRISTATE:
 574                fputs("  tristate\n", out);
 575                break;
 576        case S_STRING:
 577                fputs("  string\n", out);
 578                break;
 579        case S_INT:
 580                fputs("  integer\n", out);
 581                break;
 582        case S_HEX:
 583                fputs("  hex\n", out);
 584                break;
 585        default:
 586                fputs("  ???\n", out);
 587                break;
 588        }
 589        for (prop = sym->prop; prop; prop = prop->next) {
 590                if (prop->menu != menu)
 591                        continue;
 592                switch (prop->type) {
 593                case P_PROMPT:
 594                        fputs("  prompt ", out);
 595                        print_quoted_string(out, prop->text);
 596                        if (!expr_is_yes(prop->visible.expr)) {
 597                                fputs(" if ", out);
 598                                expr_fprint(prop->visible.expr, out);
 599                        }
 600                        fputc('\n', out);
 601                        break;
 602                case P_DEFAULT:
 603                        fputs( "  default ", out);
 604                        expr_fprint(prop->expr, out);
 605                        if (!expr_is_yes(prop->visible.expr)) {
 606                                fputs(" if ", out);
 607                                expr_fprint(prop->visible.expr, out);
 608                        }
 609                        fputc('\n', out);
 610                        break;
 611                case P_CHOICE:
 612                        fputs("  #choice value\n", out);
 613                        break;
 614                default:
 615                        fprintf(out, "  unknown prop %d!\n", prop->type);
 616                        break;
 617                }
 618        }
 619        if (sym->help) {
 620                int len = strlen(sym->help);
 621                while (sym->help[--len] == '\n')
 622                        sym->help[len] = 0;
 623                fprintf(out, "  help\n%s\n", sym->help);
 624        }
 625        fputc('\n', out);
 626}
 627
 628void zconfdump(FILE *out)
 629{
 630        struct property *prop;
 631        struct symbol *sym;
 632        struct menu *menu;
 633
 634        menu = rootmenu.list;
 635        while (menu) {
 636                if ((sym = menu->sym))
 637                        print_symbol(out, menu);
 638                else if ((prop = menu->prompt)) {
 639                        switch (prop->type) {
 640                        case P_COMMENT:
 641                                fputs("\ncomment ", out);
 642                                print_quoted_string(out, prop->text);
 643                                fputs("\n", out);
 644                                break;
 645                        case P_MENU:
 646                                fputs("\nmenu ", out);
 647                                print_quoted_string(out, prop->text);
 648                                fputs("\n", out);
 649                                break;
 650                        default:
 651                                ;
 652                        }
 653                        if (!expr_is_yes(prop->visible.expr)) {
 654                                fputs("  depends ", out);
 655                                expr_fprint(prop->visible.expr, out);
 656                                fputc('\n', out);
 657                        }
 658                        fputs("\n", out);
 659                }
 660
 661                if (menu->list)
 662                        menu = menu->list;
 663                else if (menu->next)
 664                        menu = menu->next;
 665                else while ((menu = menu->parent)) {
 666                        if (menu->prompt && menu->prompt->type == P_MENU)
 667                                fputs("\nendmenu\n", out);
 668                        if (menu->next) {
 669                                menu = menu->next;
 670                                break;
 671                        }
 672                }
 673        }
 674}
 675
 676#include "lex.zconf.c"
 677#include "util.c"
 678#include "confdata.c"
 679#include "expr.c"
 680#include "symbol.c"
 681#include "menu.c"
 682
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.