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