source: MondoRescue/branches/2.2.5/mindi-busybox/scripts/kconfig/zconf.y @ 1765

Last change on this file since 1765 was 1765, checked in by Bruno Cornec, 13 years ago

Update to busybox 1.7.2

File size: 13.9 KB
Line 
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, "Busybox 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"
Note: See TracBrowser for help on using the repository browser.