xref: /linux-6.15/scripts/kconfig/parser.y (revision 6971f719)
1769a1c02SMasahiro Yamada /* SPDX-License-Identifier: GPL-2.0 */
2769a1c02SMasahiro Yamada /*
3769a1c02SMasahiro Yamada  * Copyright (C) 2002 Roman Zippel <[email protected]>
4769a1c02SMasahiro Yamada  */
5769a1c02SMasahiro Yamada %{
6769a1c02SMasahiro Yamada 
7769a1c02SMasahiro Yamada #include <ctype.h>
8769a1c02SMasahiro Yamada #include <stdarg.h>
9769a1c02SMasahiro Yamada #include <stdio.h>
10769a1c02SMasahiro Yamada #include <stdlib.h>
11769a1c02SMasahiro Yamada #include <string.h>
12769a1c02SMasahiro Yamada #include <stdbool.h>
13769a1c02SMasahiro Yamada 
14a9d83d74SMasahiro Yamada #include <xalloc.h>
15769a1c02SMasahiro Yamada #include "lkc.h"
16a77a05dcSMasahiro Yamada #include "internal.h"
17d3d16228SMasahiro Yamada #include "preprocess.h"
18769a1c02SMasahiro Yamada 
19769a1c02SMasahiro Yamada #define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt)
20769a1c02SMasahiro Yamada 
21769a1c02SMasahiro Yamada #define PRINTD		0x0001
22769a1c02SMasahiro Yamada #define DEBUG_PARSE	0x0002
23769a1c02SMasahiro Yamada 
24769a1c02SMasahiro Yamada int cdebug = PRINTD;
25769a1c02SMasahiro Yamada 
26769a1c02SMasahiro Yamada static void yyerror(const char *err);
27769a1c02SMasahiro Yamada static void zconf_error(const char *err, ...);
28769a1c02SMasahiro Yamada static bool zconf_endtoken(const char *tokenname,
29769a1c02SMasahiro Yamada 			   const char *expected_tokenname);
30769a1c02SMasahiro Yamada 
319b114520SMasahiro Yamada struct menu *current_menu, *current_entry, *current_choice;
32700e7a8dSMasahiro Yamada 
33769a1c02SMasahiro Yamada %}
34769a1c02SMasahiro Yamada 
35769a1c02SMasahiro Yamada %union
36769a1c02SMasahiro Yamada {
37769a1c02SMasahiro Yamada 	char *string;
38769a1c02SMasahiro Yamada 	struct symbol *symbol;
39769a1c02SMasahiro Yamada 	struct expr *expr;
40769a1c02SMasahiro Yamada 	struct menu *menu;
41769a1c02SMasahiro Yamada 	enum symbol_type type;
42769a1c02SMasahiro Yamada 	enum variable_flavor flavor;
43769a1c02SMasahiro Yamada }
44769a1c02SMasahiro Yamada 
45769a1c02SMasahiro Yamada %token <string> T_HELPTEXT
46769a1c02SMasahiro Yamada %token <string> T_WORD
47769a1c02SMasahiro Yamada %token <string> T_WORD_QUOTE
48769a1c02SMasahiro Yamada %token T_BOOL
49769a1c02SMasahiro Yamada %token T_CHOICE
50769a1c02SMasahiro Yamada %token T_CLOSE_PAREN
51769a1c02SMasahiro Yamada %token T_COLON_EQUAL
52769a1c02SMasahiro Yamada %token T_COMMENT
53769a1c02SMasahiro Yamada %token T_CONFIG
54769a1c02SMasahiro Yamada %token T_DEFAULT
55769a1c02SMasahiro Yamada %token T_DEF_BOOL
56769a1c02SMasahiro Yamada %token T_DEF_TRISTATE
57769a1c02SMasahiro Yamada %token T_DEPENDS
58769a1c02SMasahiro Yamada %token T_ENDCHOICE
59769a1c02SMasahiro Yamada %token T_ENDIF
60769a1c02SMasahiro Yamada %token T_ENDMENU
61769a1c02SMasahiro Yamada %token T_HELP
62769a1c02SMasahiro Yamada %token T_HEX
63769a1c02SMasahiro Yamada %token T_IF
64769a1c02SMasahiro Yamada %token T_IMPLY
65769a1c02SMasahiro Yamada %token T_INT
66769a1c02SMasahiro Yamada %token T_MAINMENU
67769a1c02SMasahiro Yamada %token T_MENU
68769a1c02SMasahiro Yamada %token T_MENUCONFIG
69769a1c02SMasahiro Yamada %token T_MODULES
70769a1c02SMasahiro Yamada %token T_ON
71769a1c02SMasahiro Yamada %token T_OPEN_PAREN
72769a1c02SMasahiro Yamada %token T_PLUS_EQUAL
73769a1c02SMasahiro Yamada %token T_PROMPT
74769a1c02SMasahiro Yamada %token T_RANGE
75769a1c02SMasahiro Yamada %token T_SELECT
76769a1c02SMasahiro Yamada %token T_SOURCE
77769a1c02SMasahiro Yamada %token T_STRING
78769a1c02SMasahiro Yamada %token T_TRISTATE
79769a1c02SMasahiro Yamada %token T_VISIBLE
80769a1c02SMasahiro Yamada %token T_EOL
81769a1c02SMasahiro Yamada %token <string> T_ASSIGN_VAL
82769a1c02SMasahiro Yamada 
83769a1c02SMasahiro Yamada %left T_OR
84769a1c02SMasahiro Yamada %left T_AND
85769a1c02SMasahiro Yamada %left T_EQUAL T_UNEQUAL
86769a1c02SMasahiro Yamada %left T_LESS T_LESS_EQUAL T_GREATER T_GREATER_EQUAL
87769a1c02SMasahiro Yamada %nonassoc T_NOT
88769a1c02SMasahiro Yamada 
89769a1c02SMasahiro Yamada %type <symbol> nonconst_symbol
90769a1c02SMasahiro Yamada %type <symbol> symbol
91fde19251SMasahiro Yamada %type <type> type default
92769a1c02SMasahiro Yamada %type <expr> expr
93769a1c02SMasahiro Yamada %type <expr> if_expr
94769a1c02SMasahiro Yamada %type <string> end
95769a1c02SMasahiro Yamada %type <menu> if_entry menu_entry choice_entry
96c83f0209SMasahiro Yamada %type <string> assign_val
97769a1c02SMasahiro Yamada %type <flavor> assign_op
98769a1c02SMasahiro Yamada 
99769a1c02SMasahiro Yamada %destructor {
100769a1c02SMasahiro Yamada 	fprintf(stderr, "%s:%d: missing end statement for this entry\n",
10140bab83aSMasahiro Yamada 		$$->filename, $$->lineno);
102769a1c02SMasahiro Yamada 	if (current_menu == $$)
103769a1c02SMasahiro Yamada 		menu_end_menu();
104769a1c02SMasahiro Yamada } if_entry menu_entry choice_entry
105769a1c02SMasahiro Yamada 
106769a1c02SMasahiro Yamada %%
107769a1c02SMasahiro Yamada input: mainmenu_stmt stmt_list | stmt_list;
108769a1c02SMasahiro Yamada 
109769a1c02SMasahiro Yamada /* mainmenu entry */
110769a1c02SMasahiro Yamada 
1111be6e791SMasahiro Yamada mainmenu_stmt: T_MAINMENU T_WORD_QUOTE T_EOL
112769a1c02SMasahiro Yamada {
113769a1c02SMasahiro Yamada 	menu_add_prompt(P_MENU, $2, NULL);
114769a1c02SMasahiro Yamada };
115769a1c02SMasahiro Yamada 
116769a1c02SMasahiro Yamada stmt_list:
117769a1c02SMasahiro Yamada 	  /* empty */
11809d5873eSMasahiro Yamada 	| stmt_list assignment_stmt
119769a1c02SMasahiro Yamada 	| stmt_list choice_stmt
12009d5873eSMasahiro Yamada 	| stmt_list comment_stmt
12109d5873eSMasahiro Yamada 	| stmt_list config_stmt
12209d5873eSMasahiro Yamada 	| stmt_list if_stmt
123769a1c02SMasahiro Yamada 	| stmt_list menu_stmt
12409d5873eSMasahiro Yamada 	| stmt_list menuconfig_stmt
12509d5873eSMasahiro Yamada 	| stmt_list source_stmt
126769a1c02SMasahiro Yamada 	| stmt_list T_WORD error T_EOL	{ zconf_error("unknown statement \"%s\"", $2); }
127769a1c02SMasahiro Yamada 	| stmt_list error T_EOL		{ zconf_error("invalid statement"); }
128769a1c02SMasahiro Yamada ;
129769a1c02SMasahiro Yamada 
13009d5873eSMasahiro Yamada stmt_list_in_choice:
13109d5873eSMasahiro Yamada 	  /* empty */
13209d5873eSMasahiro Yamada 	| stmt_list_in_choice comment_stmt
13309d5873eSMasahiro Yamada 	| stmt_list_in_choice config_stmt
13409d5873eSMasahiro Yamada 	| stmt_list_in_choice if_stmt_in_choice
13509d5873eSMasahiro Yamada 	| stmt_list_in_choice error T_EOL	{ zconf_error("invalid statement"); }
136769a1c02SMasahiro Yamada ;
137769a1c02SMasahiro Yamada 
138769a1c02SMasahiro Yamada /* config/menuconfig entry */
139769a1c02SMasahiro Yamada 
140769a1c02SMasahiro Yamada config_entry_start: T_CONFIG nonconst_symbol T_EOL
141769a1c02SMasahiro Yamada {
142769a1c02SMasahiro Yamada 	menu_add_entry($2);
1431d7c4f10SMasahiro Yamada 	printd(DEBUG_PARSE, "%s:%d:config %s\n", cur_filename, cur_lineno, $2->name);
144769a1c02SMasahiro Yamada };
145769a1c02SMasahiro Yamada 
146769a1c02SMasahiro Yamada config_stmt: config_entry_start config_option_list
147769a1c02SMasahiro Yamada {
1489b114520SMasahiro Yamada 	if (current_choice) {
149700e7a8dSMasahiro Yamada 		if (!current_entry->prompt) {
150700e7a8dSMasahiro Yamada 			fprintf(stderr, "%s:%d: error: choice member must have a prompt\n",
151700e7a8dSMasahiro Yamada 				current_entry->filename, current_entry->lineno);
152700e7a8dSMasahiro Yamada 			yynerrs++;
153700e7a8dSMasahiro Yamada 		}
154fde19251SMasahiro Yamada 
155fde19251SMasahiro Yamada 		if (current_entry->sym->type != S_BOOLEAN) {
156fde19251SMasahiro Yamada 			fprintf(stderr, "%s:%d: error: choice member must be bool\n",
157fde19251SMasahiro Yamada 				current_entry->filename, current_entry->lineno);
158fde19251SMasahiro Yamada 			yynerrs++;
159fde19251SMasahiro Yamada 		}
160f79dc03fSMasahiro Yamada 
1614d46b5b6SMasahiro Yamada 		/*
1624d46b5b6SMasahiro Yamada 		 * If the same symbol appears twice in a choice block, the list
1634d46b5b6SMasahiro Yamada 		 * node would be added twice, leading to a broken linked list.
1644d46b5b6SMasahiro Yamada 		 * list_empty() ensures that this symbol has not yet added.
1654d46b5b6SMasahiro Yamada 		 */
1664d46b5b6SMasahiro Yamada 		if (list_empty(&current_entry->sym->choice_link))
167f79dc03fSMasahiro Yamada 			list_add_tail(&current_entry->sym->choice_link,
168f79dc03fSMasahiro Yamada 				      &current_choice->choice_members);
169700e7a8dSMasahiro Yamada 	}
170700e7a8dSMasahiro Yamada 
1711d7c4f10SMasahiro Yamada 	printd(DEBUG_PARSE, "%s:%d:endconfig\n", cur_filename, cur_lineno);
172769a1c02SMasahiro Yamada };
173769a1c02SMasahiro Yamada 
174769a1c02SMasahiro Yamada menuconfig_entry_start: T_MENUCONFIG nonconst_symbol T_EOL
175769a1c02SMasahiro Yamada {
176769a1c02SMasahiro Yamada 	menu_add_entry($2);
1771d7c4f10SMasahiro Yamada 	printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", cur_filename, cur_lineno, $2->name);
178769a1c02SMasahiro Yamada };
179769a1c02SMasahiro Yamada 
180769a1c02SMasahiro Yamada menuconfig_stmt: menuconfig_entry_start config_option_list
181769a1c02SMasahiro Yamada {
182769a1c02SMasahiro Yamada 	if (current_entry->prompt)
183769a1c02SMasahiro Yamada 		current_entry->prompt->type = P_MENU;
184769a1c02SMasahiro Yamada 	else
185*6971f719SMasahiro Yamada 		zconf_error("menuconfig statement without prompt");
1861d7c4f10SMasahiro Yamada 	printd(DEBUG_PARSE, "%s:%d:endconfig\n", cur_filename, cur_lineno);
187769a1c02SMasahiro Yamada };
188769a1c02SMasahiro Yamada 
189769a1c02SMasahiro Yamada config_option_list:
190769a1c02SMasahiro Yamada 	  /* empty */
191769a1c02SMasahiro Yamada 	| config_option_list config_option
192769a1c02SMasahiro Yamada 	| config_option_list depends
193769a1c02SMasahiro Yamada 	| config_option_list help
194769a1c02SMasahiro Yamada ;
195769a1c02SMasahiro Yamada 
196769a1c02SMasahiro Yamada config_option: type prompt_stmt_opt T_EOL
197769a1c02SMasahiro Yamada {
198769a1c02SMasahiro Yamada 	menu_set_type($1);
1991d7c4f10SMasahiro Yamada 	printd(DEBUG_PARSE, "%s:%d:type(%u)\n", cur_filename, cur_lineno, $1);
200769a1c02SMasahiro Yamada };
201769a1c02SMasahiro Yamada 
2021be6e791SMasahiro Yamada config_option: T_PROMPT T_WORD_QUOTE if_expr T_EOL
203769a1c02SMasahiro Yamada {
204769a1c02SMasahiro Yamada 	menu_add_prompt(P_PROMPT, $2, $3);
2051d7c4f10SMasahiro Yamada 	printd(DEBUG_PARSE, "%s:%d:prompt\n", cur_filename, cur_lineno);
206769a1c02SMasahiro Yamada };
207769a1c02SMasahiro Yamada 
208769a1c02SMasahiro Yamada config_option: default expr if_expr T_EOL
209769a1c02SMasahiro Yamada {
210769a1c02SMasahiro Yamada 	menu_add_expr(P_DEFAULT, $2, $3);
211769a1c02SMasahiro Yamada 	if ($1 != S_UNKNOWN)
212769a1c02SMasahiro Yamada 		menu_set_type($1);
2131d7c4f10SMasahiro Yamada 	printd(DEBUG_PARSE, "%s:%d:default(%u)\n", cur_filename, cur_lineno,
214769a1c02SMasahiro Yamada 		$1);
215769a1c02SMasahiro Yamada };
216769a1c02SMasahiro Yamada 
217769a1c02SMasahiro Yamada config_option: T_SELECT nonconst_symbol if_expr T_EOL
218769a1c02SMasahiro Yamada {
219769a1c02SMasahiro Yamada 	menu_add_symbol(P_SELECT, $2, $3);
2201d7c4f10SMasahiro Yamada 	printd(DEBUG_PARSE, "%s:%d:select\n", cur_filename, cur_lineno);
221769a1c02SMasahiro Yamada };
222769a1c02SMasahiro Yamada 
223769a1c02SMasahiro Yamada config_option: T_IMPLY nonconst_symbol if_expr T_EOL
224769a1c02SMasahiro Yamada {
225769a1c02SMasahiro Yamada 	menu_add_symbol(P_IMPLY, $2, $3);
2261d7c4f10SMasahiro Yamada 	printd(DEBUG_PARSE, "%s:%d:imply\n", cur_filename, cur_lineno);
227769a1c02SMasahiro Yamada };
228769a1c02SMasahiro Yamada 
229769a1c02SMasahiro Yamada config_option: T_RANGE symbol symbol if_expr T_EOL
230769a1c02SMasahiro Yamada {
231769a1c02SMasahiro Yamada 	menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,$2, $3), $4);
2321d7c4f10SMasahiro Yamada 	printd(DEBUG_PARSE, "%s:%d:range\n", cur_filename, cur_lineno);
233769a1c02SMasahiro Yamada };
234769a1c02SMasahiro Yamada 
2356dd85ff1SMasahiro Yamada config_option: T_MODULES T_EOL
236769a1c02SMasahiro Yamada {
2376dd85ff1SMasahiro Yamada 	if (modules_sym)
2386dd85ff1SMasahiro Yamada 		zconf_error("symbol '%s' redefines option 'modules' already defined by symbol '%s'",
2396dd85ff1SMasahiro Yamada 			    current_entry->sym->name, modules_sym->name);
2406dd85ff1SMasahiro Yamada 	modules_sym = current_entry->sym;
241769a1c02SMasahiro Yamada };
242769a1c02SMasahiro Yamada 
243769a1c02SMasahiro Yamada /* choice entry */
244769a1c02SMasahiro Yamada 
245c83f0209SMasahiro Yamada choice: T_CHOICE T_EOL
246769a1c02SMasahiro Yamada {
2471da251c6SMasahiro Yamada 	struct symbol *sym = sym_lookup(NULL, 0);
248a7c79cf3SMasahiro Yamada 
249769a1c02SMasahiro Yamada 	menu_add_entry(sym);
250fde19251SMasahiro Yamada 	menu_set_type(S_BOOLEAN);
251f79dc03fSMasahiro Yamada 	INIT_LIST_HEAD(&current_entry->choice_members);
252fde19251SMasahiro Yamada 
2531d7c4f10SMasahiro Yamada 	printd(DEBUG_PARSE, "%s:%d:choice\n", cur_filename, cur_lineno);
254769a1c02SMasahiro Yamada };
255769a1c02SMasahiro Yamada 
256769a1c02SMasahiro Yamada choice_entry: choice choice_option_list
257769a1c02SMasahiro Yamada {
2584957515bSMasahiro Yamada 	if (!current_entry->prompt) {
2594957515bSMasahiro Yamada 		fprintf(stderr, "%s:%d: error: choice must have a prompt\n",
2604957515bSMasahiro Yamada 			current_entry->filename, current_entry->lineno);
2614957515bSMasahiro Yamada 		yynerrs++;
2624957515bSMasahiro Yamada 	}
2634957515bSMasahiro Yamada 
264769a1c02SMasahiro Yamada 	$$ = menu_add_menu();
265700e7a8dSMasahiro Yamada 
2669b114520SMasahiro Yamada 	current_choice = current_entry;
267769a1c02SMasahiro Yamada };
268769a1c02SMasahiro Yamada 
269769a1c02SMasahiro Yamada choice_end: end
270769a1c02SMasahiro Yamada {
2719b114520SMasahiro Yamada 	current_choice = NULL;
272700e7a8dSMasahiro Yamada 
273769a1c02SMasahiro Yamada 	if (zconf_endtoken($1, "choice")) {
274769a1c02SMasahiro Yamada 		menu_end_menu();
2751d7c4f10SMasahiro Yamada 		printd(DEBUG_PARSE, "%s:%d:endchoice\n", cur_filename, cur_lineno);
276769a1c02SMasahiro Yamada 	}
277769a1c02SMasahiro Yamada };
278769a1c02SMasahiro Yamada 
27909d5873eSMasahiro Yamada choice_stmt: choice_entry stmt_list_in_choice choice_end
280769a1c02SMasahiro Yamada ;
281769a1c02SMasahiro Yamada 
282769a1c02SMasahiro Yamada choice_option_list:
283769a1c02SMasahiro Yamada 	  /* empty */
284769a1c02SMasahiro Yamada 	| choice_option_list choice_option
285769a1c02SMasahiro Yamada 	| choice_option_list depends
286769a1c02SMasahiro Yamada 	| choice_option_list help
287769a1c02SMasahiro Yamada ;
288769a1c02SMasahiro Yamada 
2891be6e791SMasahiro Yamada choice_option: T_PROMPT T_WORD_QUOTE if_expr T_EOL
290769a1c02SMasahiro Yamada {
291769a1c02SMasahiro Yamada 	menu_add_prompt(P_PROMPT, $2, $3);
2921d7c4f10SMasahiro Yamada 	printd(DEBUG_PARSE, "%s:%d:prompt\n", cur_filename, cur_lineno);
293769a1c02SMasahiro Yamada };
294769a1c02SMasahiro Yamada 
295769a1c02SMasahiro Yamada choice_option: T_DEFAULT nonconst_symbol if_expr T_EOL
296769a1c02SMasahiro Yamada {
297769a1c02SMasahiro Yamada 	menu_add_symbol(P_DEFAULT, $2, $3);
2981d7c4f10SMasahiro Yamada 	printd(DEBUG_PARSE, "%s:%d:default\n", cur_filename, cur_lineno);
299769a1c02SMasahiro Yamada };
300769a1c02SMasahiro Yamada 
301769a1c02SMasahiro Yamada type:
302fde19251SMasahiro Yamada 	  T_BOOL		{ $$ = S_BOOLEAN; }
303fde19251SMasahiro Yamada 	| T_TRISTATE		{ $$ = S_TRISTATE; }
304769a1c02SMasahiro Yamada 	| T_INT			{ $$ = S_INT; }
305769a1c02SMasahiro Yamada 	| T_HEX			{ $$ = S_HEX; }
306769a1c02SMasahiro Yamada 	| T_STRING		{ $$ = S_STRING; }
307769a1c02SMasahiro Yamada 
308769a1c02SMasahiro Yamada default:
309769a1c02SMasahiro Yamada 	  T_DEFAULT		{ $$ = S_UNKNOWN; }
310769a1c02SMasahiro Yamada 	| T_DEF_BOOL		{ $$ = S_BOOLEAN; }
311769a1c02SMasahiro Yamada 	| T_DEF_TRISTATE	{ $$ = S_TRISTATE; }
312769a1c02SMasahiro Yamada 
313769a1c02SMasahiro Yamada /* if entry */
314769a1c02SMasahiro Yamada 
315769a1c02SMasahiro Yamada if_entry: T_IF expr T_EOL
316769a1c02SMasahiro Yamada {
3171d7c4f10SMasahiro Yamada 	printd(DEBUG_PARSE, "%s:%d:if\n", cur_filename, cur_lineno);
318769a1c02SMasahiro Yamada 	menu_add_entry(NULL);
319769a1c02SMasahiro Yamada 	menu_add_dep($2);
320769a1c02SMasahiro Yamada 	$$ = menu_add_menu();
321769a1c02SMasahiro Yamada };
322769a1c02SMasahiro Yamada 
323769a1c02SMasahiro Yamada if_end: end
324769a1c02SMasahiro Yamada {
325769a1c02SMasahiro Yamada 	if (zconf_endtoken($1, "if")) {
326769a1c02SMasahiro Yamada 		menu_end_menu();
3271d7c4f10SMasahiro Yamada 		printd(DEBUG_PARSE, "%s:%d:endif\n", cur_filename, cur_lineno);
328769a1c02SMasahiro Yamada 	}
329769a1c02SMasahiro Yamada };
330769a1c02SMasahiro Yamada 
331769a1c02SMasahiro Yamada if_stmt: if_entry stmt_list if_end
332769a1c02SMasahiro Yamada ;
333769a1c02SMasahiro Yamada 
33409d5873eSMasahiro Yamada if_stmt_in_choice: if_entry stmt_list_in_choice if_end
33509d5873eSMasahiro Yamada ;
33609d5873eSMasahiro Yamada 
337769a1c02SMasahiro Yamada /* menu entry */
338769a1c02SMasahiro Yamada 
3391be6e791SMasahiro Yamada menu: T_MENU T_WORD_QUOTE T_EOL
340769a1c02SMasahiro Yamada {
341769a1c02SMasahiro Yamada 	menu_add_entry(NULL);
342769a1c02SMasahiro Yamada 	menu_add_prompt(P_MENU, $2, NULL);
3431d7c4f10SMasahiro Yamada 	printd(DEBUG_PARSE, "%s:%d:menu\n", cur_filename, cur_lineno);
344769a1c02SMasahiro Yamada };
345769a1c02SMasahiro Yamada 
346769a1c02SMasahiro Yamada menu_entry: menu menu_option_list
347769a1c02SMasahiro Yamada {
348769a1c02SMasahiro Yamada 	$$ = menu_add_menu();
349769a1c02SMasahiro Yamada };
350769a1c02SMasahiro Yamada 
351769a1c02SMasahiro Yamada menu_end: end
352769a1c02SMasahiro Yamada {
353769a1c02SMasahiro Yamada 	if (zconf_endtoken($1, "menu")) {
354769a1c02SMasahiro Yamada 		menu_end_menu();
3551d7c4f10SMasahiro Yamada 		printd(DEBUG_PARSE, "%s:%d:endmenu\n", cur_filename, cur_lineno);
356769a1c02SMasahiro Yamada 	}
357769a1c02SMasahiro Yamada };
358769a1c02SMasahiro Yamada 
359769a1c02SMasahiro Yamada menu_stmt: menu_entry stmt_list menu_end
360769a1c02SMasahiro Yamada ;
361769a1c02SMasahiro Yamada 
362769a1c02SMasahiro Yamada menu_option_list:
363769a1c02SMasahiro Yamada 	  /* empty */
364769a1c02SMasahiro Yamada 	| menu_option_list visible
365769a1c02SMasahiro Yamada 	| menu_option_list depends
366769a1c02SMasahiro Yamada ;
367769a1c02SMasahiro Yamada 
3681be6e791SMasahiro Yamada source_stmt: T_SOURCE T_WORD_QUOTE T_EOL
369769a1c02SMasahiro Yamada {
3701d7c4f10SMasahiro Yamada 	printd(DEBUG_PARSE, "%s:%d:source %s\n", cur_filename, cur_lineno, $2);
371769a1c02SMasahiro Yamada 	zconf_nextfile($2);
372769a1c02SMasahiro Yamada 	free($2);
373769a1c02SMasahiro Yamada };
374769a1c02SMasahiro Yamada 
375769a1c02SMasahiro Yamada /* comment entry */
376769a1c02SMasahiro Yamada 
3771be6e791SMasahiro Yamada comment: T_COMMENT T_WORD_QUOTE T_EOL
378769a1c02SMasahiro Yamada {
379769a1c02SMasahiro Yamada 	menu_add_entry(NULL);
380769a1c02SMasahiro Yamada 	menu_add_prompt(P_COMMENT, $2, NULL);
3811d7c4f10SMasahiro Yamada 	printd(DEBUG_PARSE, "%s:%d:comment\n", cur_filename, cur_lineno);
382769a1c02SMasahiro Yamada };
383769a1c02SMasahiro Yamada 
384769a1c02SMasahiro Yamada comment_stmt: comment comment_option_list
385769a1c02SMasahiro Yamada ;
386769a1c02SMasahiro Yamada 
387769a1c02SMasahiro Yamada comment_option_list:
388769a1c02SMasahiro Yamada 	  /* empty */
389769a1c02SMasahiro Yamada 	| comment_option_list depends
390769a1c02SMasahiro Yamada ;
391769a1c02SMasahiro Yamada 
392769a1c02SMasahiro Yamada /* help option */
393769a1c02SMasahiro Yamada 
394769a1c02SMasahiro Yamada help_start: T_HELP T_EOL
395769a1c02SMasahiro Yamada {
3961d7c4f10SMasahiro Yamada 	printd(DEBUG_PARSE, "%s:%d:help\n", cur_filename, cur_lineno);
397769a1c02SMasahiro Yamada 	zconf_starthelp();
398769a1c02SMasahiro Yamada };
399769a1c02SMasahiro Yamada 
400769a1c02SMasahiro Yamada help: help_start T_HELPTEXT
401769a1c02SMasahiro Yamada {
402769a1c02SMasahiro Yamada 	if (current_entry->help) {
403769a1c02SMasahiro Yamada 		free(current_entry->help);
404*6971f719SMasahiro Yamada 		zconf_error("'%s' defined with more than one help text",
405769a1c02SMasahiro Yamada 			    current_entry->sym->name ?: "<choice>");
406769a1c02SMasahiro Yamada 	}
407769a1c02SMasahiro Yamada 
408769a1c02SMasahiro Yamada 	/* Is the help text empty or all whitespace? */
409769a1c02SMasahiro Yamada 	if ($2[strspn($2, " \f\n\r\t\v")] == '\0')
410*6971f719SMasahiro Yamada 		zconf_error("'%s' defined with blank help text",
411769a1c02SMasahiro Yamada 			    current_entry->sym->name ?: "<choice>");
412769a1c02SMasahiro Yamada 
413769a1c02SMasahiro Yamada 	current_entry->help = $2;
414769a1c02SMasahiro Yamada };
415769a1c02SMasahiro Yamada 
416769a1c02SMasahiro Yamada /* depends option */
417769a1c02SMasahiro Yamada 
418769a1c02SMasahiro Yamada depends: T_DEPENDS T_ON expr T_EOL
419769a1c02SMasahiro Yamada {
420769a1c02SMasahiro Yamada 	menu_add_dep($3);
4211d7c4f10SMasahiro Yamada 	printd(DEBUG_PARSE, "%s:%d:depends on\n", cur_filename, cur_lineno);
422769a1c02SMasahiro Yamada };
423769a1c02SMasahiro Yamada 
424769a1c02SMasahiro Yamada /* visibility option */
425769a1c02SMasahiro Yamada visible: T_VISIBLE if_expr T_EOL
426769a1c02SMasahiro Yamada {
427769a1c02SMasahiro Yamada 	menu_add_visibility($2);
428769a1c02SMasahiro Yamada };
429769a1c02SMasahiro Yamada 
430769a1c02SMasahiro Yamada /* prompt statement */
431769a1c02SMasahiro Yamada 
432769a1c02SMasahiro Yamada prompt_stmt_opt:
433769a1c02SMasahiro Yamada 	  /* empty */
4341be6e791SMasahiro Yamada 	| T_WORD_QUOTE if_expr
435769a1c02SMasahiro Yamada {
436769a1c02SMasahiro Yamada 	menu_add_prompt(P_PROMPT, $1, $2);
437769a1c02SMasahiro Yamada };
438769a1c02SMasahiro Yamada 
439769a1c02SMasahiro Yamada end:	  T_ENDMENU T_EOL	{ $$ = "menu"; }
440769a1c02SMasahiro Yamada 	| T_ENDCHOICE T_EOL	{ $$ = "choice"; }
441769a1c02SMasahiro Yamada 	| T_ENDIF T_EOL		{ $$ = "if"; }
442769a1c02SMasahiro Yamada ;
443769a1c02SMasahiro Yamada 
444769a1c02SMasahiro Yamada if_expr:  /* empty */			{ $$ = NULL; }
445769a1c02SMasahiro Yamada 	| T_IF expr			{ $$ = $2; }
446769a1c02SMasahiro Yamada ;
447769a1c02SMasahiro Yamada 
448769a1c02SMasahiro Yamada expr:	  symbol				{ $$ = expr_alloc_symbol($1); }
449769a1c02SMasahiro Yamada 	| symbol T_LESS symbol			{ $$ = expr_alloc_comp(E_LTH, $1, $3); }
450769a1c02SMasahiro Yamada 	| symbol T_LESS_EQUAL symbol		{ $$ = expr_alloc_comp(E_LEQ, $1, $3); }
451769a1c02SMasahiro Yamada 	| symbol T_GREATER symbol		{ $$ = expr_alloc_comp(E_GTH, $1, $3); }
452769a1c02SMasahiro Yamada 	| symbol T_GREATER_EQUAL symbol		{ $$ = expr_alloc_comp(E_GEQ, $1, $3); }
453769a1c02SMasahiro Yamada 	| symbol T_EQUAL symbol			{ $$ = expr_alloc_comp(E_EQUAL, $1, $3); }
454769a1c02SMasahiro Yamada 	| symbol T_UNEQUAL symbol		{ $$ = expr_alloc_comp(E_UNEQUAL, $1, $3); }
455769a1c02SMasahiro Yamada 	| T_OPEN_PAREN expr T_CLOSE_PAREN	{ $$ = $2; }
456769a1c02SMasahiro Yamada 	| T_NOT expr				{ $$ = expr_alloc_one(E_NOT, $2); }
457769a1c02SMasahiro Yamada 	| expr T_OR expr			{ $$ = expr_alloc_two(E_OR, $1, $3); }
458769a1c02SMasahiro Yamada 	| expr T_AND expr			{ $$ = expr_alloc_two(E_AND, $1, $3); }
459769a1c02SMasahiro Yamada ;
460769a1c02SMasahiro Yamada 
461769a1c02SMasahiro Yamada /* For symbol definitions, selects, etc., where quotes are not accepted */
462769a1c02SMasahiro Yamada nonconst_symbol: T_WORD { $$ = sym_lookup($1, 0); free($1); };
463769a1c02SMasahiro Yamada 
464769a1c02SMasahiro Yamada symbol:	  nonconst_symbol
465769a1c02SMasahiro Yamada 	| T_WORD_QUOTE	{ $$ = sym_lookup($1, SYMBOL_CONST); free($1); }
466769a1c02SMasahiro Yamada ;
467769a1c02SMasahiro Yamada 
468769a1c02SMasahiro Yamada /* assignment statement */
469769a1c02SMasahiro Yamada 
470769a1c02SMasahiro Yamada assignment_stmt:  T_WORD assign_op assign_val T_EOL	{ variable_add($1, $3, $2); free($1); free($3); }
471769a1c02SMasahiro Yamada 
472769a1c02SMasahiro Yamada assign_op:
473769a1c02SMasahiro Yamada 	  T_EQUAL	{ $$ = VAR_RECURSIVE; }
474769a1c02SMasahiro Yamada 	| T_COLON_EQUAL	{ $$ = VAR_SIMPLE; }
475769a1c02SMasahiro Yamada 	| T_PLUS_EQUAL	{ $$ = VAR_APPEND; }
476769a1c02SMasahiro Yamada ;
477769a1c02SMasahiro Yamada 
478769a1c02SMasahiro Yamada assign_val:
479769a1c02SMasahiro Yamada 	/* empty */		{ $$ = xstrdup(""); };
480769a1c02SMasahiro Yamada 	| T_ASSIGN_VAL
481769a1c02SMasahiro Yamada ;
482769a1c02SMasahiro Yamada 
483769a1c02SMasahiro Yamada %%
484769a1c02SMasahiro Yamada 
4858a22f867SMasahiro Yamada /**
4868a22f867SMasahiro Yamada  * choice_check_sanity - check sanity of a choice member
4878a22f867SMasahiro Yamada  *
4888a22f867SMasahiro Yamada  * @menu: menu of the choice member
4898a22f867SMasahiro Yamada  *
4908a22f867SMasahiro Yamada  * Return: -1 if an error is found, 0 otherwise.
4918a22f867SMasahiro Yamada  */
4926425e3b2SMasahiro Yamada static int choice_check_sanity(const struct menu *menu)
4938a22f867SMasahiro Yamada {
4948a22f867SMasahiro Yamada 	struct property *prop;
4958a22f867SMasahiro Yamada 	int ret = 0;
4968a22f867SMasahiro Yamada 
4978a22f867SMasahiro Yamada 	for (prop = menu->sym->prop; prop; prop = prop->next) {
4988a22f867SMasahiro Yamada 		if (prop->type == P_DEFAULT) {
4998a22f867SMasahiro Yamada 			fprintf(stderr, "%s:%d: error: %s",
5008a22f867SMasahiro Yamada 				prop->filename, prop->lineno,
5018a22f867SMasahiro Yamada 				"defaults for choice values not supported\n");
5028a22f867SMasahiro Yamada 			ret = -1;
5038a22f867SMasahiro Yamada 		}
5048a22f867SMasahiro Yamada 
5058a22f867SMasahiro Yamada 		if (prop->menu != menu && prop->type == P_PROMPT &&
5068a22f867SMasahiro Yamada 		    prop->menu->parent != menu->parent) {
5078a22f867SMasahiro Yamada 			fprintf(stderr, "%s:%d: error: %s",
5088a22f867SMasahiro Yamada 				prop->filename, prop->lineno,
5098a22f867SMasahiro Yamada 				"choice value has a prompt outside its choice group\n");
5108a22f867SMasahiro Yamada 			ret = -1;
5118a22f867SMasahiro Yamada 		}
5128a22f867SMasahiro Yamada 	}
5138a22f867SMasahiro Yamada 
5148a22f867SMasahiro Yamada 	return ret;
5158a22f867SMasahiro Yamada }
5168a22f867SMasahiro Yamada 
conf_parse(const char * name)517769a1c02SMasahiro Yamada void conf_parse(const char *name)
518769a1c02SMasahiro Yamada {
519cc25cfc5SMasahiro Yamada 	struct menu *menu;
520769a1c02SMasahiro Yamada 
521526396b7SMasahiro Yamada 	autoconf_cmd = str_new();
522526396b7SMasahiro Yamada 
52356e634b0SMasahiro Yamada 	str_printf(&autoconf_cmd, "\ndeps_config := \\\n");
524526396b7SMasahiro Yamada 
525769a1c02SMasahiro Yamada 	zconf_initscan(name);
526769a1c02SMasahiro Yamada 
527769a1c02SMasahiro Yamada 	_menu_init();
528769a1c02SMasahiro Yamada 
529769a1c02SMasahiro Yamada 	if (getenv("ZCONF_DEBUG"))
530769a1c02SMasahiro Yamada 		yydebug = 1;
531769a1c02SMasahiro Yamada 	yyparse();
532769a1c02SMasahiro Yamada 
53356e634b0SMasahiro Yamada 	str_printf(&autoconf_cmd,
53456e634b0SMasahiro Yamada 		   "\n"
53556e634b0SMasahiro Yamada 		   "$(autoconfig): $(deps_config)\n"
53656e634b0SMasahiro Yamada 		   "$(deps_config): ;\n");
53756e634b0SMasahiro Yamada 
53856e634b0SMasahiro Yamada 	env_write_dep(&autoconf_cmd);
53956e634b0SMasahiro Yamada 
540769a1c02SMasahiro Yamada 	/* Variables are expanded in the parse phase. We can free them here. */
541769a1c02SMasahiro Yamada 	variable_all_del();
542769a1c02SMasahiro Yamada 
543769a1c02SMasahiro Yamada 	if (yynerrs)
544769a1c02SMasahiro Yamada 		exit(1);
545769a1c02SMasahiro Yamada 	if (!modules_sym)
54673a6afc5SMasahiro Yamada 		modules_sym = &symbol_no;
547769a1c02SMasahiro Yamada 
548769a1c02SMasahiro Yamada 	if (!menu_has_prompt(&rootmenu)) {
549769a1c02SMasahiro Yamada 		current_entry = &rootmenu;
550769a1c02SMasahiro Yamada 		menu_add_prompt(P_MENU, "Main menu", NULL);
551769a1c02SMasahiro Yamada 	}
552769a1c02SMasahiro Yamada 
5537e3465f6SMasahiro Yamada 	menu_finalize();
554cc25cfc5SMasahiro Yamada 
55503c4ecaaSMasahiro Yamada 	menu_for_each_entry(menu) {
5568a22f867SMasahiro Yamada 		struct menu *child;
5578a22f867SMasahiro Yamada 
558cc25cfc5SMasahiro Yamada 		if (menu->sym && sym_check_deps(menu->sym))
559769a1c02SMasahiro Yamada 			yynerrs++;
5608a22f867SMasahiro Yamada 
5618a22f867SMasahiro Yamada 		if (menu->sym && sym_is_choice(menu->sym)) {
5628a22f867SMasahiro Yamada 			menu_for_each_sub_entry(child, menu)
5638a22f867SMasahiro Yamada 				if (child->sym && choice_check_sanity(child))
5648a22f867SMasahiro Yamada 					yynerrs++;
5658a22f867SMasahiro Yamada 		}
566cc25cfc5SMasahiro Yamada 	}
567cc25cfc5SMasahiro Yamada 
568769a1c02SMasahiro Yamada 	if (yynerrs)
569769a1c02SMasahiro Yamada 		exit(1);
5705ee54659SMasahiro Yamada 	conf_set_changed(true);
571769a1c02SMasahiro Yamada }
572769a1c02SMasahiro Yamada 
zconf_endtoken(const char * tokenname,const char * expected_tokenname)573769a1c02SMasahiro Yamada static bool zconf_endtoken(const char *tokenname,
574769a1c02SMasahiro Yamada 			   const char *expected_tokenname)
575769a1c02SMasahiro Yamada {
576769a1c02SMasahiro Yamada 	if (strcmp(tokenname, expected_tokenname)) {
577769a1c02SMasahiro Yamada 		zconf_error("unexpected '%s' within %s block",
578769a1c02SMasahiro Yamada 			    tokenname, expected_tokenname);
579769a1c02SMasahiro Yamada 		yynerrs++;
580769a1c02SMasahiro Yamada 		return false;
581769a1c02SMasahiro Yamada 	}
58240bab83aSMasahiro Yamada 	if (strcmp(current_menu->filename, cur_filename)) {
583769a1c02SMasahiro Yamada 		zconf_error("'%s' in different file than '%s'",
584769a1c02SMasahiro Yamada 			    tokenname, expected_tokenname);
585769a1c02SMasahiro Yamada 		fprintf(stderr, "%s:%d: location of the '%s'\n",
58640bab83aSMasahiro Yamada 			current_menu->filename, current_menu->lineno,
587769a1c02SMasahiro Yamada 			expected_tokenname);
588769a1c02SMasahiro Yamada 		yynerrs++;
589769a1c02SMasahiro Yamada 		return false;
590769a1c02SMasahiro Yamada 	}
591769a1c02SMasahiro Yamada 	return true;
592769a1c02SMasahiro Yamada }
593769a1c02SMasahiro Yamada 
zconf_error(const char * err,...)594769a1c02SMasahiro Yamada static void zconf_error(const char *err, ...)
595769a1c02SMasahiro Yamada {
596769a1c02SMasahiro Yamada 	va_list ap;
597769a1c02SMasahiro Yamada 
598769a1c02SMasahiro Yamada 	yynerrs++;
5991d7c4f10SMasahiro Yamada 	fprintf(stderr, "%s:%d: ", cur_filename, cur_lineno);
600769a1c02SMasahiro Yamada 	va_start(ap, err);
601769a1c02SMasahiro Yamada 	vfprintf(stderr, err, ap);
602769a1c02SMasahiro Yamada 	va_end(ap);
603769a1c02SMasahiro Yamada 	fprintf(stderr, "\n");
604769a1c02SMasahiro Yamada }
605769a1c02SMasahiro Yamada 
yyerror(const char * err)606769a1c02SMasahiro Yamada static void yyerror(const char *err)
607769a1c02SMasahiro Yamada {
6081d7c4f10SMasahiro Yamada 	fprintf(stderr, "%s:%d: %s\n", cur_filename, cur_lineno, err);
609769a1c02SMasahiro Yamada }
610769a1c02SMasahiro Yamada 
print_quoted_string(FILE * out,const char * str)611769a1c02SMasahiro Yamada static void print_quoted_string(FILE *out, const char *str)
612769a1c02SMasahiro Yamada {
613769a1c02SMasahiro Yamada 	const char *p;
614769a1c02SMasahiro Yamada 	int len;
615769a1c02SMasahiro Yamada 
616769a1c02SMasahiro Yamada 	putc('"', out);
617769a1c02SMasahiro Yamada 	while ((p = strchr(str, '"'))) {
618769a1c02SMasahiro Yamada 		len = p - str;
619769a1c02SMasahiro Yamada 		if (len)
620769a1c02SMasahiro Yamada 			fprintf(out, "%.*s", len, str);
621769a1c02SMasahiro Yamada 		fputs("\\\"", out);
622769a1c02SMasahiro Yamada 		str = p + 1;
623769a1c02SMasahiro Yamada 	}
624769a1c02SMasahiro Yamada 	fputs(str, out);
625769a1c02SMasahiro Yamada 	putc('"', out);
626769a1c02SMasahiro Yamada }
627769a1c02SMasahiro Yamada 
print_symbol(FILE * out,const struct menu * menu)6286425e3b2SMasahiro Yamada static void print_symbol(FILE *out, const struct menu *menu)
629769a1c02SMasahiro Yamada {
630769a1c02SMasahiro Yamada 	struct symbol *sym = menu->sym;
631769a1c02SMasahiro Yamada 	struct property *prop;
632769a1c02SMasahiro Yamada 
633769a1c02SMasahiro Yamada 	if (sym_is_choice(sym))
634769a1c02SMasahiro Yamada 		fprintf(out, "\nchoice\n");
635769a1c02SMasahiro Yamada 	else
636769a1c02SMasahiro Yamada 		fprintf(out, "\nconfig %s\n", sym->name);
637769a1c02SMasahiro Yamada 	switch (sym->type) {
638769a1c02SMasahiro Yamada 	case S_BOOLEAN:
639769a1c02SMasahiro Yamada 		fputs("  bool\n", out);
640769a1c02SMasahiro Yamada 		break;
641769a1c02SMasahiro Yamada 	case S_TRISTATE:
642769a1c02SMasahiro Yamada 		fputs("  tristate\n", out);
643769a1c02SMasahiro Yamada 		break;
644769a1c02SMasahiro Yamada 	case S_STRING:
645769a1c02SMasahiro Yamada 		fputs("  string\n", out);
646769a1c02SMasahiro Yamada 		break;
647769a1c02SMasahiro Yamada 	case S_INT:
648769a1c02SMasahiro Yamada 		fputs("  integer\n", out);
649769a1c02SMasahiro Yamada 		break;
650769a1c02SMasahiro Yamada 	case S_HEX:
651769a1c02SMasahiro Yamada 		fputs("  hex\n", out);
652769a1c02SMasahiro Yamada 		break;
653769a1c02SMasahiro Yamada 	default:
654769a1c02SMasahiro Yamada 		fputs("  ???\n", out);
655769a1c02SMasahiro Yamada 		break;
656769a1c02SMasahiro Yamada 	}
657769a1c02SMasahiro Yamada 	for (prop = sym->prop; prop; prop = prop->next) {
658769a1c02SMasahiro Yamada 		if (prop->menu != menu)
659769a1c02SMasahiro Yamada 			continue;
660769a1c02SMasahiro Yamada 		switch (prop->type) {
661769a1c02SMasahiro Yamada 		case P_PROMPT:
662769a1c02SMasahiro Yamada 			fputs("  prompt ", out);
663769a1c02SMasahiro Yamada 			print_quoted_string(out, prop->text);
664769a1c02SMasahiro Yamada 			if (!expr_is_yes(prop->visible.expr)) {
665769a1c02SMasahiro Yamada 				fputs(" if ", out);
666769a1c02SMasahiro Yamada 				expr_fprint(prop->visible.expr, out);
667769a1c02SMasahiro Yamada 			}
668769a1c02SMasahiro Yamada 			fputc('\n', out);
669769a1c02SMasahiro Yamada 			break;
670769a1c02SMasahiro Yamada 		case P_DEFAULT:
671769a1c02SMasahiro Yamada 			fputs( "  default ", out);
672769a1c02SMasahiro Yamada 			expr_fprint(prop->expr, out);
673769a1c02SMasahiro Yamada 			if (!expr_is_yes(prop->visible.expr)) {
674769a1c02SMasahiro Yamada 				fputs(" if ", out);
675769a1c02SMasahiro Yamada 				expr_fprint(prop->visible.expr, out);
676769a1c02SMasahiro Yamada 			}
677769a1c02SMasahiro Yamada 			fputc('\n', out);
678769a1c02SMasahiro Yamada 			break;
679769a1c02SMasahiro Yamada 		case P_SELECT:
680769a1c02SMasahiro Yamada 			fputs( "  select ", out);
681769a1c02SMasahiro Yamada 			expr_fprint(prop->expr, out);
682769a1c02SMasahiro Yamada 			fputc('\n', out);
683769a1c02SMasahiro Yamada 			break;
684769a1c02SMasahiro Yamada 		case P_IMPLY:
685769a1c02SMasahiro Yamada 			fputs( "  imply ", out);
686769a1c02SMasahiro Yamada 			expr_fprint(prop->expr, out);
687769a1c02SMasahiro Yamada 			fputc('\n', out);
688769a1c02SMasahiro Yamada 			break;
689769a1c02SMasahiro Yamada 		case P_RANGE:
690769a1c02SMasahiro Yamada 			fputs( "  range ", out);
691769a1c02SMasahiro Yamada 			expr_fprint(prop->expr, out);
692769a1c02SMasahiro Yamada 			fputc('\n', out);
693769a1c02SMasahiro Yamada 			break;
694769a1c02SMasahiro Yamada 		case P_MENU:
695769a1c02SMasahiro Yamada 			fputs( "  menu ", out);
696769a1c02SMasahiro Yamada 			print_quoted_string(out, prop->text);
697769a1c02SMasahiro Yamada 			fputc('\n', out);
698769a1c02SMasahiro Yamada 			break;
699769a1c02SMasahiro Yamada 		default:
700769a1c02SMasahiro Yamada 			fprintf(out, "  unknown prop %d!\n", prop->type);
701769a1c02SMasahiro Yamada 			break;
702769a1c02SMasahiro Yamada 		}
703769a1c02SMasahiro Yamada 	}
704769a1c02SMasahiro Yamada 	if (menu->help) {
705769a1c02SMasahiro Yamada 		int len = strlen(menu->help);
706769a1c02SMasahiro Yamada 		while (menu->help[--len] == '\n')
707769a1c02SMasahiro Yamada 			menu->help[len] = 0;
708769a1c02SMasahiro Yamada 		fprintf(out, "  help\n%s\n", menu->help);
709769a1c02SMasahiro Yamada 	}
710769a1c02SMasahiro Yamada }
711769a1c02SMasahiro Yamada 
zconfdump(FILE * out)712769a1c02SMasahiro Yamada void zconfdump(FILE *out)
713769a1c02SMasahiro Yamada {
714769a1c02SMasahiro Yamada 	struct property *prop;
715769a1c02SMasahiro Yamada 	struct symbol *sym;
716769a1c02SMasahiro Yamada 	struct menu *menu;
717769a1c02SMasahiro Yamada 
718769a1c02SMasahiro Yamada 	menu = rootmenu.list;
719769a1c02SMasahiro Yamada 	while (menu) {
720769a1c02SMasahiro Yamada 		if ((sym = menu->sym))
721769a1c02SMasahiro Yamada 			print_symbol(out, menu);
722769a1c02SMasahiro Yamada 		else if ((prop = menu->prompt)) {
723769a1c02SMasahiro Yamada 			switch (prop->type) {
724769a1c02SMasahiro Yamada 			case P_COMMENT:
725769a1c02SMasahiro Yamada 				fputs("\ncomment ", out);
726769a1c02SMasahiro Yamada 				print_quoted_string(out, prop->text);
727769a1c02SMasahiro Yamada 				fputs("\n", out);
728769a1c02SMasahiro Yamada 				break;
729769a1c02SMasahiro Yamada 			case P_MENU:
730769a1c02SMasahiro Yamada 				fputs("\nmenu ", out);
731769a1c02SMasahiro Yamada 				print_quoted_string(out, prop->text);
732769a1c02SMasahiro Yamada 				fputs("\n", out);
733769a1c02SMasahiro Yamada 				break;
734769a1c02SMasahiro Yamada 			default:
735769a1c02SMasahiro Yamada 				;
736769a1c02SMasahiro Yamada 			}
737769a1c02SMasahiro Yamada 			if (!expr_is_yes(prop->visible.expr)) {
738769a1c02SMasahiro Yamada 				fputs("  depends ", out);
739769a1c02SMasahiro Yamada 				expr_fprint(prop->visible.expr, out);
740769a1c02SMasahiro Yamada 				fputc('\n', out);
741769a1c02SMasahiro Yamada 			}
742769a1c02SMasahiro Yamada 		}
743769a1c02SMasahiro Yamada 
744769a1c02SMasahiro Yamada 		if (menu->list)
745769a1c02SMasahiro Yamada 			menu = menu->list;
746769a1c02SMasahiro Yamada 		else if (menu->next)
747769a1c02SMasahiro Yamada 			menu = menu->next;
748769a1c02SMasahiro Yamada 		else while ((menu = menu->parent)) {
749769a1c02SMasahiro Yamada 			if (menu->prompt && menu->prompt->type == P_MENU)
750769a1c02SMasahiro Yamada 				fputs("\nendmenu\n", out);
751769a1c02SMasahiro Yamada 			if (menu->next) {
752769a1c02SMasahiro Yamada 				menu = menu->next;
753769a1c02SMasahiro Yamada 				break;
754769a1c02SMasahiro Yamada 			}
755769a1c02SMasahiro Yamada 		}
756769a1c02SMasahiro Yamada 	}
757769a1c02SMasahiro Yamada }
758