Merge tag 'kbuild-v6.10' of git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy...
[linux-block.git] / scripts / kconfig / parser.y
CommitLineData
0c874100 1/* SPDX-License-Identifier: GPL-2.0 */
1da177e4
LT
2/*
3 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
1da177e4 4 */
0c874100 5%{
1da177e4
LT
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
7a88488b 14#include "lkc.h"
a77a05dc 15#include "internal.h"
d3d16228 16#include "preprocess.h"
7a88488b 17
1da177e4
LT
18#define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt)
19
20#define PRINTD 0x0001
21#define DEBUG_PARSE 0x0002
22
23int cdebug = PRINTD;
24
765f4cde 25static void yyerror(const char *err);
1da177e4 26static void zconfprint(const char *err, ...);
a02f0570 27static void zconf_error(const char *err, ...);
caaebb3c
MY
28static bool zconf_endtoken(const char *tokenname,
29 const char *expected_tokenname);
1da177e4 30
a77a05dc 31struct menu *current_menu, *current_entry;
1da177e4 32
700e7a8d
MY
33static bool inside_choice = false;
34
1da177e4 35%}
1da177e4
LT
36
37%union
38{
1da177e4
LT
39 char *string;
40 struct symbol *symbol;
41 struct expr *expr;
42 struct menu *menu;
3c8f317d 43 enum symbol_type type;
1175c025 44 enum variable_flavor flavor;
1da177e4
LT
45}
46
1da177e4 47%token <string> T_HELPTEXT
1da177e4
LT
48%token <string> T_WORD
49%token <string> T_WORD_QUOTE
3c8f317d 50%token T_BOOL
b3d1d9d3 51%token T_CHOICE
1da177e4 52%token T_CLOSE_PAREN
c3d22871 53%token T_COLON_EQUAL
b3d1d9d3
MY
54%token T_COMMENT
55%token T_CONFIG
3c8f317d
MY
56%token T_DEFAULT
57%token T_DEF_BOOL
58%token T_DEF_TRISTATE
b3d1d9d3
MY
59%token T_DEPENDS
60%token T_ENDCHOICE
61%token T_ENDIF
62%token T_ENDMENU
63%token T_HELP
3c8f317d 64%token T_HEX
b3d1d9d3
MY
65%token T_IF
66%token T_IMPLY
3c8f317d 67%token T_INT
b3d1d9d3
MY
68%token T_MAINMENU
69%token T_MENU
70%token T_MENUCONFIG
ce2164ab 71%token T_MODULES
b3d1d9d3 72%token T_ON
1da177e4 73%token T_OPEN_PAREN
c3d22871 74%token T_PLUS_EQUAL
b3d1d9d3
MY
75%token T_PROMPT
76%token T_RANGE
77%token T_SELECT
78%token T_SOURCE
3c8f317d
MY
79%token T_STRING
80%token T_TRISTATE
b3d1d9d3 81%token T_VISIBLE
3370f9f0 82%token T_EOL
9ced3bdd 83%token <string> T_ASSIGN_VAL
1da177e4
LT
84
85%left T_OR
86%left T_AND
87%left T_EQUAL T_UNEQUAL
31847b67 88%left T_LESS T_LESS_EQUAL T_GREATER T_GREATER_EQUAL
1da177e4
LT
89%nonassoc T_NOT
90
26e47a3c 91%type <symbol> nonconst_symbol
1da177e4 92%type <symbol> symbol
3c8f317d 93%type <type> type logic_type default
1da177e4
LT
94%type <expr> expr
95%type <expr> if_expr
caaebb3c 96%type <string> end
a02f0570 97%type <menu> if_entry menu_entry choice_entry
c83f0209 98%type <string> assign_val
c3d22871 99%type <flavor> assign_op
a02f0570
RZ
100
101%destructor {
102 fprintf(stderr, "%s:%d: missing end statement for this entry\n",
40bab83a 103 $$->filename, $$->lineno);
a02f0570
RZ
104 if (current_menu == $$)
105 menu_end_menu();
106} if_entry menu_entry choice_entry
1da177e4 107
1da177e4 108%%
cc66bca7 109input: mainmenu_stmt stmt_list | stmt_list;
0724a7c3
UM
110
111/* mainmenu entry */
112
1be6e791 113mainmenu_stmt: T_MAINMENU T_WORD_QUOTE T_EOL
0724a7c3
UM
114{
115 menu_add_prompt(P_MENU, $2, NULL);
116};
117
a02f0570
RZ
118stmt_list:
119 /* empty */
09d5873e 120 | stmt_list assignment_stmt
a02f0570 121 | stmt_list choice_stmt
09d5873e
MY
122 | stmt_list comment_stmt
123 | stmt_list config_stmt
124 | stmt_list if_stmt
a02f0570 125 | stmt_list menu_stmt
09d5873e
MY
126 | stmt_list menuconfig_stmt
127 | stmt_list source_stmt
a02f0570 128 | stmt_list T_WORD error T_EOL { zconf_error("unknown statement \"%s\"", $2); }
a02f0570 129 | stmt_list error T_EOL { zconf_error("invalid statement"); }
1da177e4
LT
130;
131
09d5873e
MY
132stmt_list_in_choice:
133 /* empty */
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 error T_EOL { zconf_error("invalid statement"); }
a02f0570
RZ
138;
139
1da177e4
LT
140/* config/menuconfig entry */
141
26e47a3c 142config_entry_start: T_CONFIG nonconst_symbol T_EOL
1da177e4 143{
26e47a3c 144 menu_add_entry($2);
1d7c4f10 145 printd(DEBUG_PARSE, "%s:%d:config %s\n", cur_filename, cur_lineno, $2->name);
1da177e4
LT
146};
147
148config_stmt: config_entry_start config_option_list
149{
700e7a8d
MY
150 if (inside_choice) {
151 if (!current_entry->prompt) {
152 fprintf(stderr, "%s:%d: error: choice member must have a prompt\n",
153 current_entry->filename, current_entry->lineno);
154 yynerrs++;
155 }
156 }
157
1d7c4f10 158 printd(DEBUG_PARSE, "%s:%d:endconfig\n", cur_filename, cur_lineno);
1da177e4
LT
159};
160
26e47a3c 161menuconfig_entry_start: T_MENUCONFIG nonconst_symbol T_EOL
1da177e4 162{
26e47a3c 163 menu_add_entry($2);
1d7c4f10 164 printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", cur_filename, cur_lineno, $2->name);
1da177e4
LT
165};
166
167menuconfig_stmt: menuconfig_entry_start config_option_list
168{
169 if (current_entry->prompt)
170 current_entry->prompt->type = P_MENU;
171 else
172 zconfprint("warning: menuconfig statement without prompt");
1d7c4f10 173 printd(DEBUG_PARSE, "%s:%d:endconfig\n", cur_filename, cur_lineno);
1da177e4
LT
174};
175
176config_option_list:
177 /* empty */
178 | config_option_list config_option
179 | config_option_list depends
180 | config_option_list help
1da177e4
LT
181;
182
3c8f317d 183config_option: type prompt_stmt_opt T_EOL
1da177e4 184{
3c8f317d 185 menu_set_type($1);
1d7c4f10 186 printd(DEBUG_PARSE, "%s:%d:type(%u)\n", cur_filename, cur_lineno, $1);
1da177e4
LT
187};
188
1be6e791 189config_option: T_PROMPT T_WORD_QUOTE if_expr T_EOL
1da177e4
LT
190{
191 menu_add_prompt(P_PROMPT, $2, $3);
1d7c4f10 192 printd(DEBUG_PARSE, "%s:%d:prompt\n", cur_filename, cur_lineno);
1da177e4
LT
193};
194
3c8f317d 195config_option: default expr if_expr T_EOL
1da177e4
LT
196{
197 menu_add_expr(P_DEFAULT, $2, $3);
3c8f317d
MY
198 if ($1 != S_UNKNOWN)
199 menu_set_type($1);
1d7c4f10 200 printd(DEBUG_PARSE, "%s:%d:default(%u)\n", cur_filename, cur_lineno,
3c8f317d 201 $1);
1da177e4
LT
202};
203
26e47a3c 204config_option: T_SELECT nonconst_symbol if_expr T_EOL
1da177e4 205{
26e47a3c 206 menu_add_symbol(P_SELECT, $2, $3);
1d7c4f10 207 printd(DEBUG_PARSE, "%s:%d:select\n", cur_filename, cur_lineno);
1da177e4
LT
208};
209
26e47a3c 210config_option: T_IMPLY nonconst_symbol if_expr T_EOL
237e3ad0 211{
26e47a3c 212 menu_add_symbol(P_IMPLY, $2, $3);
1d7c4f10 213 printd(DEBUG_PARSE, "%s:%d:imply\n", cur_filename, cur_lineno);
237e3ad0
NP
214};
215
1da177e4
LT
216config_option: T_RANGE symbol symbol if_expr T_EOL
217{
218 menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,$2, $3), $4);
1d7c4f10 219 printd(DEBUG_PARSE, "%s:%d:range\n", cur_filename, cur_lineno);
1da177e4
LT
220};
221
6dd85ff1 222config_option: T_MODULES T_EOL
ce2164ab 223{
6dd85ff1
MY
224 if (modules_sym)
225 zconf_error("symbol '%s' redefines option 'modules' already defined by symbol '%s'",
226 current_entry->sym->name, modules_sym->name);
227 modules_sym = current_entry->sym;
ce2164ab 228};
f6a88aa8 229
1da177e4
LT
230/* choice entry */
231
c83f0209 232choice: T_CHOICE T_EOL
1da177e4 233{
1da251c6 234 struct symbol *sym = sym_lookup(NULL, 0);
a7c79cf3 235
1da177e4
LT
236 menu_add_entry(sym);
237 menu_add_expr(P_CHOICE, NULL, NULL);
1d7c4f10 238 printd(DEBUG_PARSE, "%s:%d:choice\n", cur_filename, cur_lineno);
1da177e4
LT
239};
240
241choice_entry: choice choice_option_list
242{
4957515b
MY
243 if (!current_entry->prompt) {
244 fprintf(stderr, "%s:%d: error: choice must have a prompt\n",
245 current_entry->filename, current_entry->lineno);
246 yynerrs++;
247 }
248
a02f0570 249 $$ = menu_add_menu();
700e7a8d
MY
250
251 inside_choice = true;
1da177e4
LT
252};
253
254choice_end: end
255{
700e7a8d
MY
256 inside_choice = false;
257
caaebb3c 258 if (zconf_endtoken($1, "choice")) {
1da177e4 259 menu_end_menu();
1d7c4f10 260 printd(DEBUG_PARSE, "%s:%d:endchoice\n", cur_filename, cur_lineno);
1da177e4
LT
261 }
262};
263
09d5873e 264choice_stmt: choice_entry stmt_list_in_choice choice_end
a02f0570 265;
1da177e4
LT
266
267choice_option_list:
268 /* empty */
269 | choice_option_list choice_option
270 | choice_option_list depends
271 | choice_option_list help
1da177e4
LT
272;
273
1be6e791 274choice_option: T_PROMPT T_WORD_QUOTE if_expr T_EOL
1da177e4
LT
275{
276 menu_add_prompt(P_PROMPT, $2, $3);
1d7c4f10 277 printd(DEBUG_PARSE, "%s:%d:prompt\n", cur_filename, cur_lineno);
1da177e4
LT
278};
279
3c8f317d 280choice_option: logic_type prompt_stmt_opt T_EOL
1da177e4 281{
3c8f317d 282 menu_set_type($1);
1d7c4f10 283 printd(DEBUG_PARSE, "%s:%d:type(%u)\n", cur_filename, cur_lineno, $1);
1da177e4
LT
284};
285
26e47a3c 286choice_option: T_DEFAULT nonconst_symbol if_expr T_EOL
1da177e4 287{
3c8f317d 288 menu_add_symbol(P_DEFAULT, $2, $3);
1d7c4f10 289 printd(DEBUG_PARSE, "%s:%d:default\n", cur_filename, cur_lineno);
1da177e4
LT
290};
291
3c8f317d
MY
292type:
293 logic_type
294 | T_INT { $$ = S_INT; }
295 | T_HEX { $$ = S_HEX; }
296 | T_STRING { $$ = S_STRING; }
297
298logic_type:
299 T_BOOL { $$ = S_BOOLEAN; }
300 | T_TRISTATE { $$ = S_TRISTATE; }
301
302default:
303 T_DEFAULT { $$ = S_UNKNOWN; }
304 | T_DEF_BOOL { $$ = S_BOOLEAN; }
305 | T_DEF_TRISTATE { $$ = S_TRISTATE; }
306
1da177e4
LT
307/* if entry */
308
b2d00d7c 309if_entry: T_IF expr T_EOL
1da177e4 310{
1d7c4f10 311 printd(DEBUG_PARSE, "%s:%d:if\n", cur_filename, cur_lineno);
1da177e4
LT
312 menu_add_entry(NULL);
313 menu_add_dep($2);
a02f0570 314 $$ = menu_add_menu();
1da177e4
LT
315};
316
317if_end: end
318{
caaebb3c 319 if (zconf_endtoken($1, "if")) {
1da177e4 320 menu_end_menu();
1d7c4f10 321 printd(DEBUG_PARSE, "%s:%d:endif\n", cur_filename, cur_lineno);
1da177e4
LT
322 }
323};
324
4891796c 325if_stmt: if_entry stmt_list if_end
1da177e4
LT
326;
327
09d5873e
MY
328if_stmt_in_choice: if_entry stmt_list_in_choice if_end
329;
330
1da177e4
LT
331/* menu entry */
332
1be6e791 333menu: T_MENU T_WORD_QUOTE T_EOL
1da177e4
LT
334{
335 menu_add_entry(NULL);
fb7f6ff6 336 menu_add_prompt(P_MENU, $2, NULL);
1d7c4f10 337 printd(DEBUG_PARSE, "%s:%d:menu\n", cur_filename, cur_lineno);
1da177e4
LT
338};
339
1f31be9e 340menu_entry: menu menu_option_list
1da177e4 341{
a02f0570 342 $$ = menu_add_menu();
1da177e4
LT
343};
344
345menu_end: end
346{
caaebb3c 347 if (zconf_endtoken($1, "menu")) {
1da177e4 348 menu_end_menu();
1d7c4f10 349 printd(DEBUG_PARSE, "%s:%d:endmenu\n", cur_filename, cur_lineno);
1da177e4
LT
350 }
351};
352
94d4e1b6 353menu_stmt: menu_entry stmt_list menu_end
1da177e4
LT
354;
355
1f31be9e
MY
356menu_option_list:
357 /* empty */
358 | menu_option_list visible
359 | menu_option_list depends
360;
361
1be6e791 362source_stmt: T_SOURCE T_WORD_QUOTE T_EOL
1da177e4 363{
1d7c4f10 364 printd(DEBUG_PARSE, "%s:%d:source %s\n", cur_filename, cur_lineno, $2);
a02f0570 365 zconf_nextfile($2);
24161a67 366 free($2);
1da177e4
LT
367};
368
369/* comment entry */
370
1be6e791 371comment: T_COMMENT T_WORD_QUOTE T_EOL
1da177e4
LT
372{
373 menu_add_entry(NULL);
fb7f6ff6 374 menu_add_prompt(P_COMMENT, $2, NULL);
1d7c4f10 375 printd(DEBUG_PARSE, "%s:%d:comment\n", cur_filename, cur_lineno);
1da177e4
LT
376};
377
4b5ec81b
MY
378comment_stmt: comment comment_option_list
379;
380
381comment_option_list:
382 /* empty */
383 | comment_option_list depends
df60f4b9 384;
1da177e4
LT
385
386/* help option */
387
388help_start: T_HELP T_EOL
389{
1d7c4f10 390 printd(DEBUG_PARSE, "%s:%d:help\n", cur_filename, cur_lineno);
1da177e4
LT
391 zconf_starthelp();
392};
393
394help: help_start T_HELPTEXT
395{
6479f327
UM
396 if (current_entry->help) {
397 free(current_entry->help);
398 zconfprint("warning: '%s' defined with more than one help text -- only the last one will be used",
399 current_entry->sym->name ?: "<choice>");
400 }
1b9eda2e
UM
401
402 /* Is the help text empty or all whitespace? */
403 if ($2[strspn($2, " \f\n\r\t\v")] == '\0')
404 zconfprint("warning: '%s' defined with blank help text",
405 current_entry->sym->name ?: "<choice>");
406
03d29122 407 current_entry->help = $2;
1da177e4
LT
408};
409
410/* depends option */
411
1da177e4
LT
412depends: T_DEPENDS T_ON expr T_EOL
413{
414 menu_add_dep($3);
1d7c4f10 415 printd(DEBUG_PARSE, "%s:%d:depends on\n", cur_filename, cur_lineno);
1da177e4
LT
416};
417
86e187ff 418/* visibility option */
413cd19d 419visible: T_VISIBLE if_expr T_EOL
86e187ff
AL
420{
421 menu_add_visibility($2);
422};
423
1da177e4
LT
424/* prompt statement */
425
426prompt_stmt_opt:
427 /* empty */
1be6e791 428 | T_WORD_QUOTE if_expr
1da177e4 429{
fb7f6ff6 430 menu_add_prompt(P_PROMPT, $1, $2);
1da177e4
LT
431};
432
caaebb3c
MY
433end: T_ENDMENU T_EOL { $$ = "menu"; }
434 | T_ENDCHOICE T_EOL { $$ = "choice"; }
435 | T_ENDIF T_EOL { $$ = "if"; }
1da177e4
LT
436;
437
1da177e4
LT
438if_expr: /* empty */ { $$ = NULL; }
439 | T_IF expr { $$ = $2; }
440;
441
442expr: symbol { $$ = expr_alloc_symbol($1); }
31847b67
JB
443 | symbol T_LESS symbol { $$ = expr_alloc_comp(E_LTH, $1, $3); }
444 | symbol T_LESS_EQUAL symbol { $$ = expr_alloc_comp(E_LEQ, $1, $3); }
445 | symbol T_GREATER symbol { $$ = expr_alloc_comp(E_GTH, $1, $3); }
446 | symbol T_GREATER_EQUAL symbol { $$ = expr_alloc_comp(E_GEQ, $1, $3); }
1da177e4
LT
447 | symbol T_EQUAL symbol { $$ = expr_alloc_comp(E_EQUAL, $1, $3); }
448 | symbol T_UNEQUAL symbol { $$ = expr_alloc_comp(E_UNEQUAL, $1, $3); }
449 | T_OPEN_PAREN expr T_CLOSE_PAREN { $$ = $2; }
450 | T_NOT expr { $$ = expr_alloc_one(E_NOT, $2); }
451 | expr T_OR expr { $$ = expr_alloc_two(E_OR, $1, $3); }
452 | expr T_AND expr { $$ = expr_alloc_two(E_AND, $1, $3); }
453;
454
26e47a3c
UM
455/* For symbol definitions, selects, etc., where quotes are not accepted */
456nonconst_symbol: T_WORD { $$ = sym_lookup($1, 0); free($1); };
457
458symbol: nonconst_symbol
5a1aa8a1 459 | T_WORD_QUOTE { $$ = sym_lookup($1, SYMBOL_CONST); free($1); }
1da177e4
LT
460;
461
9ced3bdd
MY
462/* assignment statement */
463
171a515d 464assignment_stmt: T_WORD assign_op assign_val T_EOL { variable_add($1, $3, $2); free($1); free($3); }
c3d22871
MY
465
466assign_op:
467 T_EQUAL { $$ = VAR_RECURSIVE; }
468 | T_COLON_EQUAL { $$ = VAR_SIMPLE; }
469 | T_PLUS_EQUAL { $$ = VAR_APPEND; }
470;
9ced3bdd
MY
471
472assign_val:
473 /* empty */ { $$ = xstrdup(""); };
474 | T_ASSIGN_VAL
475;
476
1da177e4
LT
477%%
478
8a22f867
MY
479/**
480 * choice_check_sanity - check sanity of a choice member
481 *
482 * @menu: menu of the choice member
483 *
484 * Return: -1 if an error is found, 0 otherwise.
485 */
486static int choice_check_sanity(struct menu *menu)
487{
488 struct property *prop;
489 int ret = 0;
490
491 for (prop = menu->sym->prop; prop; prop = prop->next) {
492 if (prop->type == P_DEFAULT) {
493 fprintf(stderr, "%s:%d: error: %s",
494 prop->filename, prop->lineno,
495 "defaults for choice values not supported\n");
496 ret = -1;
497 }
498
499 if (prop->menu != menu && prop->type == P_PROMPT &&
500 prop->menu->parent != menu->parent) {
501 fprintf(stderr, "%s:%d: error: %s",
502 prop->filename, prop->lineno,
503 "choice value has a prompt outside its choice group\n");
504 ret = -1;
505 }
506 }
507
508 return ret;
509}
510
1da177e4
LT
511void conf_parse(const char *name)
512{
cc25cfc5 513 struct menu *menu;
1da177e4 514
526396b7
MY
515 autoconf_cmd = str_new();
516
56e634b0 517 str_printf(&autoconf_cmd, "\ndeps_config := \\\n");
526396b7 518
1da177e4
LT
519 zconf_initscan(name);
520
692d97c3 521 _menu_init();
1da177e4 522
a02f0570 523 if (getenv("ZCONF_DEBUG"))
765f4cde
MY
524 yydebug = 1;
525 yyparse();
9ced3bdd 526
d3e4a68f
MY
527 /*
528 * FIXME:
529 * cur_filename and cur_lineno are used even after yyparse();
530 * menu_finalize() calls menu_add_symbol(). This should be fixed.
531 */
532 cur_filename = "<none>";
533 cur_lineno = 0;
534
56e634b0
MY
535 str_printf(&autoconf_cmd,
536 "\n"
537 "$(autoconfig): $(deps_config)\n"
538 "$(deps_config): ;\n");
539
540 env_write_dep(&autoconf_cmd);
541
9ced3bdd
MY
542 /* Variables are expanded in the parse phase. We can free them here. */
543 variable_all_del();
544
765f4cde 545 if (yynerrs)
1da177e4 546 exit(1);
6902dccf 547 if (!modules_sym)
73a6afc5 548 modules_sym = &symbol_no;
f6ce00b8 549
96d8e48d
MY
550 if (!menu_has_prompt(&rootmenu)) {
551 current_entry = &rootmenu;
137c0118 552 menu_add_prompt(P_MENU, "Main menu", NULL);
96d8e48d 553 }
f6ce00b8 554
7e3465f6 555 menu_finalize();
cc25cfc5 556
03c4ecaa 557 menu_for_each_entry(menu) {
8a22f867
MY
558 struct menu *child;
559
cc25cfc5 560 if (menu->sym && sym_check_deps(menu->sym))
765f4cde 561 yynerrs++;
8a22f867
MY
562
563 if (menu->sym && sym_is_choice(menu->sym)) {
564 menu_for_each_sub_entry(child, menu)
565 if (child->sym && choice_check_sanity(child))
566 yynerrs++;
567 }
bb66fc67 568 }
cc25cfc5 569
765f4cde 570 if (yynerrs)
5447d34b 571 exit(1);
5ee54659 572 conf_set_changed(true);
1da177e4
LT
573}
574
caaebb3c
MY
575static bool zconf_endtoken(const char *tokenname,
576 const char *expected_tokenname)
1da177e4 577{
caaebb3c 578 if (strcmp(tokenname, expected_tokenname)) {
a02f0570 579 zconf_error("unexpected '%s' within %s block",
caaebb3c 580 tokenname, expected_tokenname);
765f4cde 581 yynerrs++;
1da177e4
LT
582 return false;
583 }
40bab83a 584 if (strcmp(current_menu->filename, cur_filename)) {
a02f0570 585 zconf_error("'%s' in different file than '%s'",
caaebb3c 586 tokenname, expected_tokenname);
a02f0570 587 fprintf(stderr, "%s:%d: location of the '%s'\n",
40bab83a 588 current_menu->filename, current_menu->lineno,
caaebb3c 589 expected_tokenname);
765f4cde 590 yynerrs++;
1da177e4
LT
591 return false;
592 }
593 return true;
594}
595
596static void zconfprint(const char *err, ...)
597{
598 va_list ap;
599
1d7c4f10 600 fprintf(stderr, "%s:%d: ", cur_filename, cur_lineno);
a02f0570
RZ
601 va_start(ap, err);
602 vfprintf(stderr, err, ap);
603 va_end(ap);
604 fprintf(stderr, "\n");
605}
606
607static void zconf_error(const char *err, ...)
608{
609 va_list ap;
610
765f4cde 611 yynerrs++;
1d7c4f10 612 fprintf(stderr, "%s:%d: ", cur_filename, cur_lineno);
1da177e4
LT
613 va_start(ap, err);
614 vfprintf(stderr, err, ap);
615 va_end(ap);
616 fprintf(stderr, "\n");
617}
618
765f4cde 619static void yyerror(const char *err)
1da177e4 620{
1d7c4f10 621 fprintf(stderr, "%s:%d: %s\n", cur_filename, cur_lineno, err);
1da177e4
LT
622}
623
65166571 624static void print_quoted_string(FILE *out, const char *str)
1da177e4
LT
625{
626 const char *p;
627 int len;
628
629 putc('"', out);
630 while ((p = strchr(str, '"'))) {
631 len = p - str;
632 if (len)
633 fprintf(out, "%.*s", len, str);
634 fputs("\\\"", out);
635 str = p + 1;
636 }
637 fputs(str, out);
638 putc('"', out);
639}
640
65166571 641static void print_symbol(FILE *out, struct menu *menu)
1da177e4
LT
642{
643 struct symbol *sym = menu->sym;
644 struct property *prop;
645
646 if (sym_is_choice(sym))
c6ccc30f 647 fprintf(out, "\nchoice\n");
1da177e4 648 else
c6ccc30f 649 fprintf(out, "\nconfig %s\n", sym->name);
1da177e4
LT
650 switch (sym->type) {
651 case S_BOOLEAN:
b92d804a 652 fputs(" bool\n", out);
1da177e4
LT
653 break;
654 case S_TRISTATE:
655 fputs(" tristate\n", out);
656 break;
657 case S_STRING:
658 fputs(" string\n", out);
659 break;
660 case S_INT:
661 fputs(" integer\n", out);
662 break;
663 case S_HEX:
664 fputs(" hex\n", out);
665 break;
666 default:
667 fputs(" ???\n", out);
668 break;
669 }
670 for (prop = sym->prop; prop; prop = prop->next) {
671 if (prop->menu != menu)
672 continue;
673 switch (prop->type) {
674 case P_PROMPT:
675 fputs(" prompt ", out);
676 print_quoted_string(out, prop->text);
677 if (!expr_is_yes(prop->visible.expr)) {
678 fputs(" if ", out);
679 expr_fprint(prop->visible.expr, out);
680 }
681 fputc('\n', out);
682 break;
683 case P_DEFAULT:
684 fputs( " default ", out);
685 expr_fprint(prop->expr, out);
686 if (!expr_is_yes(prop->visible.expr)) {
687 fputs(" if ", out);
688 expr_fprint(prop->visible.expr, out);
689 }
690 fputc('\n', out);
691 break;
692 case P_CHOICE:
693 fputs(" #choice value\n", out);
694 break;
c6ccc30f
LZ
695 case P_SELECT:
696 fputs( " select ", out);
697 expr_fprint(prop->expr, out);
698 fputc('\n', out);
699 break;
237e3ad0
NP
700 case P_IMPLY:
701 fputs( " imply ", out);
702 expr_fprint(prop->expr, out);
703 fputc('\n', out);
704 break;
c6ccc30f
LZ
705 case P_RANGE:
706 fputs( " range ", out);
707 expr_fprint(prop->expr, out);
708 fputc('\n', out);
709 break;
710 case P_MENU:
711 fputs( " menu ", out);
712 print_quoted_string(out, prop->text);
713 fputc('\n', out);
714 break;
ecd53ac2
DG
715 case P_SYMBOL:
716 fputs( " symbol ", out);
6397d96b 717 fprintf(out, "%s\n", prop->menu->sym->name);
ecd53ac2 718 break;
1da177e4
LT
719 default:
720 fprintf(out, " unknown prop %d!\n", prop->type);
721 break;
722 }
723 }
03d29122
SR
724 if (menu->help) {
725 int len = strlen(menu->help);
726 while (menu->help[--len] == '\n')
727 menu->help[len] = 0;
728 fprintf(out, " help\n%s\n", menu->help);
1da177e4 729 }
1da177e4
LT
730}
731
732void zconfdump(FILE *out)
733{
734 struct property *prop;
735 struct symbol *sym;
736 struct menu *menu;
737
738 menu = rootmenu.list;
739 while (menu) {
740 if ((sym = menu->sym))
741 print_symbol(out, menu);
742 else if ((prop = menu->prompt)) {
743 switch (prop->type) {
744 case P_COMMENT:
745 fputs("\ncomment ", out);
746 print_quoted_string(out, prop->text);
747 fputs("\n", out);
748 break;
749 case P_MENU:
750 fputs("\nmenu ", out);
751 print_quoted_string(out, prop->text);
752 fputs("\n", out);
753 break;
754 default:
755 ;
756 }
757 if (!expr_is_yes(prop->visible.expr)) {
758 fputs(" depends ", out);
759 expr_fprint(prop->visible.expr, out);
760 fputc('\n', out);
761 }
1da177e4
LT
762 }
763
764 if (menu->list)
765 menu = menu->list;
766 else if (menu->next)
767 menu = menu->next;
768 else while ((menu = menu->parent)) {
769 if (menu->prompt && menu->prompt->type == P_MENU)
770 fputs("\nendmenu\n", out);
771 if (menu->next) {
772 menu = menu->next;
773 break;
774 }
775 }
776 }
777}