1 /* SPDX-License-Identifier: GPL-2.0-only */
3 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
17 #define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt)
20 #define DEBUG_PARSE 0x0002
24 static void yyerror(const char *err
);
25 static void zconfprint
(const char *err
, ...
);
26 static void zconf_error
(const char *err
, ...
);
27 static bool zconf_endtoken
(const char *tokenname
,
28 const char *expected_tokenname
);
30 struct symbol
*symbol_hash
[SYMBOL_HASHSIZE
];
32 struct menu
*current_menu
, *current_entry
;
39 struct symbol
*symbol
;
42 enum symbol_type type
;
43 enum variable_flavor flavor
;
46 %token
<string> T_HELPTEXT
47 %token
<string> T_WORD
48 %token
<string> T_WORD_QUOTE
83 %token
<string> T_ASSIGN_VAL
87 %left T_EQUAL T_UNEQUAL
88 %left T_LESS T_LESS_EQUAL T_GREATER T_GREATER_EQUAL
91 %type
<symbol
> nonconst_symbol
93 %type
<type
> type logic_type default
97 %type
<menu
> if_entry menu_entry choice_entry
98 %type
<string> word_opt assign_val
99 %type
<flavor
> assign_op
102 fprintf
(stderr
, "%s:%d: missing end statement for this entry\n",
103 $$
->file
->name
, $$
->lineno
);
104 if
(current_menu
== $$
)
106 } if_entry menu_entry choice_entry
109 input: mainmenu_stmt stmt_list | stmt_list
;
113 mainmenu_stmt: T_MAINMENU T_WORD_QUOTE T_EOL
115 menu_add_prompt
(P_MENU
, $2, NULL
);
120 | stmt_list assignment_stmt
121 | stmt_list choice_stmt
122 | stmt_list comment_stmt
123 | stmt_list config_stmt
125 | stmt_list menu_stmt
126 | stmt_list menuconfig_stmt
127 | stmt_list source_stmt
128 | stmt_list T_WORD
error T_EOL
{ zconf_error
("unknown statement \"%s\"", $2); }
129 | stmt_list
error T_EOL
{ zconf_error
("invalid statement"); }
134 | stmt_list_in_choice comment_stmt
135 | stmt_list_in_choice config_stmt
136 | stmt_list_in_choice if_stmt_in_choice
137 | stmt_list_in_choice source_stmt
138 | stmt_list_in_choice
error T_EOL
{ zconf_error
("invalid statement"); }
141 /* config/menuconfig entry */
143 config_entry_start: T_CONFIG nonconst_symbol T_EOL
145 $2->flags |
= SYMBOL_OPTIONAL
;
147 printd
(DEBUG_PARSE
, "%s:%d:config %s\n", zconf_curname
(), zconf_lineno
(), $2->name
);
150 config_stmt: config_entry_start config_option_list
152 printd
(DEBUG_PARSE
, "%s:%d:endconfig\n", zconf_curname
(), zconf_lineno
());
155 menuconfig_entry_start: T_MENUCONFIG nonconst_symbol T_EOL
157 $2->flags |
= SYMBOL_OPTIONAL
;
159 printd
(DEBUG_PARSE
, "%s:%d:menuconfig %s\n", zconf_curname
(), zconf_lineno
(), $2->name
);
162 menuconfig_stmt: menuconfig_entry_start config_option_list
164 if
(current_entry
->prompt
)
165 current_entry
->prompt
->type
= P_MENU
;
167 zconfprint
("warning: menuconfig statement without prompt");
168 printd
(DEBUG_PARSE
, "%s:%d:endconfig\n", zconf_curname
(), zconf_lineno
());
173 | config_option_list config_option
174 | config_option_list depends
175 | config_option_list help
178 config_option: type prompt_stmt_opt T_EOL
181 printd
(DEBUG_PARSE
, "%s:%d:type(%u)\n",
182 zconf_curname
(), zconf_lineno
(),
186 config_option: T_PROMPT T_WORD_QUOTE if_expr T_EOL
188 menu_add_prompt
(P_PROMPT
, $2, $3);
189 printd
(DEBUG_PARSE
, "%s:%d:prompt\n", zconf_curname
(), zconf_lineno
());
192 config_option: default expr if_expr T_EOL
194 menu_add_expr
(P_DEFAULT
, $2, $3);
197 printd
(DEBUG_PARSE
, "%s:%d:default(%u)\n",
198 zconf_curname
(), zconf_lineno
(),
202 config_option: T_SELECT nonconst_symbol if_expr T_EOL
204 menu_add_symbol
(P_SELECT
, $2, $3);
205 printd
(DEBUG_PARSE
, "%s:%d:select\n", zconf_curname
(), zconf_lineno
());
208 config_option: T_IMPLY nonconst_symbol if_expr T_EOL
210 menu_add_symbol
(P_IMPLY
, $2, $3);
211 printd
(DEBUG_PARSE
, "%s:%d:imply\n", zconf_curname
(), zconf_lineno
());
214 config_option: T_RANGE symbol symbol if_expr T_EOL
216 menu_add_expr
(P_RANGE
, expr_alloc_comp
(E_RANGE
,$2, $3), $4);
217 printd
(DEBUG_PARSE
, "%s:%d:range\n", zconf_curname
(), zconf_lineno
());
220 config_option: T_MODULES T_EOL
223 zconf_error
("symbol '%s' redefines option 'modules' already defined by symbol '%s'",
224 current_entry
->sym
->name
, modules_sym
->name
);
225 modules_sym
= current_entry
->sym
;
230 choice: T_CHOICE word_opt T_EOL
232 struct symbol
*sym
= sym_lookup
($2, SYMBOL_CHOICE
);
233 sym
->flags |
= SYMBOL_NO_WRITE
;
235 menu_add_expr
(P_CHOICE
, NULL
, NULL
);
237 printd
(DEBUG_PARSE
, "%s:%d:choice\n", zconf_curname
(), zconf_lineno
());
240 choice_entry: choice choice_option_list
242 $$
= menu_add_menu
();
247 if
(zconf_endtoken
($1, "choice")) {
249 printd
(DEBUG_PARSE
, "%s:%d:endchoice\n", zconf_curname
(), zconf_lineno
());
253 choice_stmt: choice_entry stmt_list_in_choice choice_end
258 | choice_option_list choice_option
259 | choice_option_list depends
260 | choice_option_list help
263 choice_option: T_PROMPT T_WORD_QUOTE if_expr T_EOL
265 menu_add_prompt
(P_PROMPT
, $2, $3);
266 printd
(DEBUG_PARSE
, "%s:%d:prompt\n", zconf_curname
(), zconf_lineno
());
269 choice_option: logic_type prompt_stmt_opt T_EOL
272 printd
(DEBUG_PARSE
, "%s:%d:type(%u)\n",
273 zconf_curname
(), zconf_lineno
(), $1);
276 choice_option: T_OPTIONAL T_EOL
278 current_entry
->sym
->flags |
= SYMBOL_OPTIONAL
;
279 printd
(DEBUG_PARSE
, "%s:%d:optional\n", zconf_curname
(), zconf_lineno
());
282 choice_option: T_DEFAULT nonconst_symbol if_expr T_EOL
284 menu_add_symbol
(P_DEFAULT
, $2, $3);
285 printd
(DEBUG_PARSE
, "%s:%d:default\n",
286 zconf_curname
(), zconf_lineno
());
291 | T_INT
{ $$
= S_INT
; }
292 | T_HEX
{ $$
= S_HEX
; }
293 | T_STRING
{ $$
= S_STRING
; }
296 T_BOOL
{ $$
= S_BOOLEAN
; }
297 | T_TRISTATE
{ $$
= S_TRISTATE
; }
300 T_DEFAULT
{ $$
= S_UNKNOWN
; }
301 | T_DEF_BOOL
{ $$
= S_BOOLEAN
; }
302 | T_DEF_TRISTATE
{ $$
= S_TRISTATE
; }
306 if_entry: T_IF expr T_EOL
308 printd
(DEBUG_PARSE
, "%s:%d:if\n", zconf_curname
(), zconf_lineno
());
309 menu_add_entry
(NULL
);
311 $$
= menu_add_menu
();
316 if
(zconf_endtoken
($1, "if")) {
318 printd
(DEBUG_PARSE
, "%s:%d:endif\n", zconf_curname
(), zconf_lineno
());
322 if_stmt: if_entry stmt_list if_end
325 if_stmt_in_choice: if_entry stmt_list_in_choice if_end
330 menu: T_MENU T_WORD_QUOTE T_EOL
332 menu_add_entry
(NULL
);
333 menu_add_prompt
(P_MENU
, $2, NULL
);
334 printd
(DEBUG_PARSE
, "%s:%d:menu\n", zconf_curname
(), zconf_lineno
());
337 menu_entry: menu menu_option_list
339 $$
= menu_add_menu
();
344 if
(zconf_endtoken
($1, "menu")) {
346 printd
(DEBUG_PARSE
, "%s:%d:endmenu\n", zconf_curname
(), zconf_lineno
());
350 menu_stmt: menu_entry stmt_list menu_end
355 | menu_option_list visible
356 | menu_option_list depends
359 source_stmt: T_SOURCE T_WORD_QUOTE T_EOL
361 printd
(DEBUG_PARSE
, "%s:%d:source %s\n", zconf_curname
(), zconf_lineno
(), $2);
368 comment: T_COMMENT T_WORD_QUOTE T_EOL
370 menu_add_entry
(NULL
);
371 menu_add_prompt
(P_COMMENT
, $2, NULL
);
372 printd
(DEBUG_PARSE
, "%s:%d:comment\n", zconf_curname
(), zconf_lineno
());
375 comment_stmt: comment comment_option_list
380 | comment_option_list depends
385 help_start: T_HELP T_EOL
387 printd
(DEBUG_PARSE
, "%s:%d:help\n", zconf_curname
(), zconf_lineno
());
391 help: help_start T_HELPTEXT
393 if
(current_entry
->help
) {
394 free
(current_entry
->help
);
395 zconfprint
("warning: '%s' defined with more than one help text -- only the last one will be used",
396 current_entry
->sym
->name ?
: "<choice>");
399 /* Is the help text empty or all whitespace? */
400 if
($2[strspn
($2, " \f\n\r\t\v")] == '\0')
401 zconfprint
("warning: '%s' defined with blank help text",
402 current_entry
->sym
->name ?
: "<choice>");
404 current_entry
->help
= $2;
409 depends: T_DEPENDS T_ON expr T_EOL
412 printd
(DEBUG_PARSE
, "%s:%d:depends on\n", zconf_curname
(), zconf_lineno
());
415 /* visibility option */
416 visible: T_VISIBLE if_expr T_EOL
418 menu_add_visibility
($2);
421 /* prompt statement */
425 | T_WORD_QUOTE if_expr
427 menu_add_prompt
(P_PROMPT
, $1, $2);
430 end: T_ENDMENU T_EOL
{ $$
= "menu"; }
431 | T_ENDCHOICE T_EOL
{ $$
= "choice"; }
432 | T_ENDIF T_EOL
{ $$
= "if"; }
435 if_expr: /* empty */ { $$
= NULL
; }
436 | T_IF expr
{ $$
= $2; }
439 expr: symbol
{ $$
= expr_alloc_symbol
($1); }
440 | symbol T_LESS symbol
{ $$
= expr_alloc_comp
(E_LTH
, $1, $3); }
441 | symbol T_LESS_EQUAL symbol
{ $$
= expr_alloc_comp
(E_LEQ
, $1, $3); }
442 | symbol T_GREATER symbol
{ $$
= expr_alloc_comp
(E_GTH
, $1, $3); }
443 | symbol T_GREATER_EQUAL symbol
{ $$
= expr_alloc_comp
(E_GEQ
, $1, $3); }
444 | symbol T_EQUAL symbol
{ $$
= expr_alloc_comp
(E_EQUAL
, $1, $3); }
445 | symbol T_UNEQUAL symbol
{ $$
= expr_alloc_comp
(E_UNEQUAL
, $1, $3); }
446 | T_OPEN_PAREN expr T_CLOSE_PAREN
{ $$
= $2; }
447 | T_NOT expr
{ $$
= expr_alloc_one
(E_NOT
, $2); }
448 | expr T_OR expr
{ $$
= expr_alloc_two
(E_OR
, $1, $3); }
449 | expr T_AND expr
{ $$
= expr_alloc_two
(E_AND
, $1, $3); }
452 /* For symbol definitions, selects, etc., where quotes are not accepted */
453 nonconst_symbol: T_WORD
{ $$
= sym_lookup
($1, 0); free
($1); };
455 symbol: nonconst_symbol
456 | T_WORD_QUOTE
{ $$
= sym_lookup
($1, SYMBOL_CONST
); free
($1); }
459 word_opt: /* empty */ { $$
= NULL
; }
462 /* assignment statement */
464 assignment_stmt: T_WORD assign_op assign_val T_EOL
{ variable_add
($1, $3, $2); free
($1); free
($3); }
467 T_EQUAL
{ $$
= VAR_RECURSIVE
; }
468 | T_COLON_EQUAL
{ $$
= VAR_SIMPLE
; }
469 | T_PLUS_EQUAL
{ $$
= VAR_APPEND
; }
473 /* empty */ { $$
= xstrdup
(""); };
479 void conf_parse
(const char *name
)
484 zconf_initscan
(name
);
488 if
(getenv
("ZCONF_DEBUG"))
492 /* Variables are expanded in the parse phase. We can free them here. */
498 modules_sym
= sym_find
( "n" );
500 if
(!menu_has_prompt
(&rootmenu
)) {
501 current_entry
= &rootmenu
;
502 menu_add_prompt
(P_MENU
, "Main menu", NULL
);
505 menu_finalize
(&rootmenu
);
506 for_all_symbols
(i
, sym
) {
507 if
(sym_check_deps
(sym
))
512 conf_set_changed
(true
);
515 static bool zconf_endtoken
(const char *tokenname
,
516 const char *expected_tokenname
)
518 if
(strcmp
(tokenname
, expected_tokenname
)) {
519 zconf_error
("unexpected '%s' within %s block",
520 tokenname
, expected_tokenname
);
524 if
(current_menu
->file
!= current_file
) {
525 zconf_error
("'%s' in different file than '%s'",
526 tokenname
, expected_tokenname
);
527 fprintf
(stderr
, "%s:%d: location of the '%s'\n",
528 current_menu
->file
->name
, current_menu
->lineno
,
536 static void zconfprint
(const char *err
, ...
)
540 fprintf
(stderr
, "%s:%d: ", zconf_curname
(), zconf_lineno
());
542 vfprintf
(stderr
, err
, ap
);
544 fprintf
(stderr
, "\n");
547 static void zconf_error
(const char *err
, ...
)
552 fprintf
(stderr
, "%s:%d: ", zconf_curname
(), zconf_lineno
());
554 vfprintf
(stderr
, err
, ap
);
556 fprintf
(stderr
, "\n");
559 static void yyerror(const char *err
)
561 fprintf
(stderr
, "%s:%d: %s\n", zconf_curname
(), zconf_lineno
() + 1, err
);
564 static void print_quoted_string
(FILE *out
, const char *str
)
570 while
((p
= strchr
(str
, '"'))) {
573 fprintf
(out
, "%.*s", len
, str
);
581 static void print_symbol
(FILE *out
, struct menu
*menu
)
583 struct symbol
*sym
= menu
->sym
;
584 struct property
*prop
;
586 if
(sym_is_choice
(sym
))
587 fprintf
(out
, "\nchoice\n");
589 fprintf
(out
, "\nconfig %s\n", sym
->name
);
592 fputs
(" bool\n", out
);
595 fputs
(" tristate\n", out
);
598 fputs
(" string\n", out
);
601 fputs
(" integer\n", out
);
604 fputs
(" hex\n", out
);
607 fputs
(" ???\n", out
);
610 for
(prop
= sym
->prop
; prop
; prop
= prop
->next
) {
611 if
(prop
->menu
!= menu
)
613 switch
(prop
->type
) {
615 fputs
(" prompt ", out
);
616 print_quoted_string
(out
, prop
->text
);
617 if
(!expr_is_yes
(prop
->visible.expr
)) {
619 expr_fprint
(prop
->visible.expr
, out
);
624 fputs
( " default ", out
);
625 expr_fprint
(prop
->expr
, out
);
626 if
(!expr_is_yes
(prop
->visible.expr
)) {
628 expr_fprint
(prop
->visible.expr
, out
);
633 fputs
(" #choice value\n", out
);
636 fputs
( " select ", out
);
637 expr_fprint
(prop
->expr
, out
);
641 fputs
( " imply ", out
);
642 expr_fprint
(prop
->expr
, out
);
646 fputs
( " range ", out
);
647 expr_fprint
(prop
->expr
, out
);
651 fputs
( " menu ", out
);
652 print_quoted_string
(out
, prop
->text
);
656 fputs
( " symbol ", out
);
657 fprintf
(out
, "%s\n", prop
->menu
->sym
->name
);
660 fprintf
(out
, " unknown prop %d!\n", prop
->type
);
665 int len
= strlen
(menu
->help
);
666 while
(menu
->help
[--len
] == '\n')
668 fprintf
(out
, " help\n%s\n", menu
->help
);
672 void zconfdump
(FILE *out
)
674 struct property
*prop
;
678 menu
= rootmenu.list
;
680 if
((sym
= menu
->sym
))
681 print_symbol
(out
, menu
);
682 else if
((prop
= menu
->prompt
)) {
683 switch
(prop
->type
) {
685 fputs
("\ncomment ", out
);
686 print_quoted_string
(out
, prop
->text
);
690 fputs
("\nmenu ", out
);
691 print_quoted_string
(out
, prop
->text
);
697 if
(!expr_is_yes
(prop
->visible.expr
)) {
698 fputs
(" depends ", out
);
699 expr_fprint
(prop
->visible.expr
, out
);
708 else while
((menu
= menu
->parent
)) {
709 if
(menu
->prompt
&& menu
->prompt
->type
== P_MENU
)
710 fputs
("\nendmenu\n", out
);