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