3 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
4 * Released under the terms of the GNU GPL v2.0.
14 #define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt)
17 #define DEBUG_PARSE 0x0002
21 extern int zconflex(void);
22 static void zconfprint(const char *err, ...);
23 static void zconferror(const char *err);
24 static bool zconf_endtoken(int token, int starttoken, int endtoken);
26 struct symbol *symbol_hash[257];
28 #define YYERROR_VERBOSE
36 struct symbol *symbol;
50 %token <string> T_HELPTEXT
62 %token <string> T_WORD
63 %token <string> T_STRING
73 %left T_EQUAL T_UNEQUAL
84 #define LKC_DIRECT_LINK
95 | T_MAINMENU prompt nl_or_eof
96 | T_ENDMENU { zconfprint("unexpected 'endmenu' statement"); }
97 | T_ENDIF { zconfprint("unexpected 'endif' statement"); }
98 | T_ENDCHOICE { zconfprint("unexpected 'endchoice' statement"); }
99 | error nl_or_eof { zconfprint("syntax error"); yyerrok; }
113 config_entry_start: T_CONFIG T_WORD
115 struct symbol *sym = sym_lookup($2, 0);
116 sym->flags |= SYMBOL_OPTIONAL;
118 printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), $2);
121 config_stmt: config_entry_start T_EOL config_option_list
124 printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
129 | config_option_list config_option T_EOL
130 | config_option_list depends T_EOL
131 | config_option_list help
132 | config_option_list T_EOL
135 config_option: T_TRISTATE prompt_stmt_opt
137 menu_set_type(S_TRISTATE);
138 printd(DEBUG_PARSE, "%s:%d:tristate\n", zconf_curname(), zconf_lineno());
141 config_option: T_BOOLEAN prompt_stmt_opt
143 menu_set_type(S_BOOLEAN);
144 printd(DEBUG_PARSE, "%s:%d:boolean\n", zconf_curname(), zconf_lineno());
147 config_option: T_INT prompt_stmt_opt
149 menu_set_type(S_INT);
150 printd(DEBUG_PARSE, "%s:%d:int\n", zconf_curname(), zconf_lineno());
153 config_option: T_HEX prompt_stmt_opt
155 menu_set_type(S_HEX);
156 printd(DEBUG_PARSE, "%s:%d:hex\n", zconf_curname(), zconf_lineno());
159 config_option: T_STRING prompt_stmt_opt
161 menu_set_type(S_STRING);
162 printd(DEBUG_PARSE, "%s:%d:string\n", zconf_curname(), zconf_lineno());
165 config_option: T_PROMPT prompt if_expr
167 menu_add_prop(P_PROMPT, $2, NULL, $3);
168 printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
171 config_option: T_DEFAULT symbol if_expr
173 menu_add_prop(P_DEFAULT, NULL, $2, $3);
174 printd(DEBUG_PARSE, "%s:%d:default\n", zconf_curname(), zconf_lineno());
181 struct symbol *sym = sym_lookup(NULL, 0);
182 sym->flags |= SYMBOL_CHOICE;
184 menu_add_prop(P_CHOICE, NULL, NULL, NULL);
185 printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno());
188 choice_entry: choice T_EOL choice_option_list
196 if (zconf_endtoken($1, T_CHOICE, T_ENDCHOICE)) {
198 printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno());
203 choice_entry choice_block choice_end T_EOL
204 | choice_entry choice_block
206 printf("%s:%d: missing 'endchoice' for this 'choice' statement\n", current_menu->file->name, current_menu->lineno);
212 | choice_option_list choice_option T_EOL
213 | choice_option_list depends T_EOL
214 | choice_option_list help
215 | choice_option_list T_EOL
218 choice_option: T_PROMPT prompt if_expr
220 menu_add_prop(P_PROMPT, $2, NULL, $3);
221 printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
224 choice_option: T_OPTIONAL
226 current_entry->sym->flags |= SYMBOL_OPTIONAL;
227 printd(DEBUG_PARSE, "%s:%d:optional\n", zconf_curname(), zconf_lineno());
230 choice_option: T_DEFAULT symbol
232 menu_add_prop(P_DEFAULT, NULL, $2, NULL);
233 //current_choice->prop->def = $2;
234 printd(DEBUG_PARSE, "%s:%d:default\n", zconf_curname(), zconf_lineno());
239 | choice_block common_block
246 printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno());
247 menu_add_entry(NULL);
248 //current_entry->prompt = menu_add_prop(T_IF, NULL, NULL, $2);
256 if (zconf_endtoken($1, T_IF, T_ENDIF)) {
258 printd(DEBUG_PARSE, "%s:%d:endif\n", zconf_curname(), zconf_lineno());
263 if T_EOL if_block if_end T_EOL
266 printf("%s:%d: missing 'endif' for this 'if' statement\n", current_menu->file->name, current_menu->lineno);
272 | if_block common_block
274 | if_block choice_stmt
281 menu_add_entry(NULL);
282 menu_add_prop(P_MENU, $2, NULL, NULL);
283 printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno());
286 menu_entry: menu T_EOL depends_list
294 if (zconf_endtoken($1, T_MENU, T_ENDMENU)) {
296 printd(DEBUG_PARSE, "%s:%d:endmenu\n", zconf_curname(), zconf_lineno());
301 menu_entry menu_block menu_end T_EOL
302 | menu_entry menu_block
304 printf("%s:%d: missing 'endmenu' for this 'menu' statement\n", current_menu->file->name, current_menu->lineno);
310 | menu_block common_block
311 | menu_block menu_stmt
312 | menu_block choice_stmt
313 | menu_block error T_EOL { zconfprint("invalid menu option"); yyerrok; }
316 source: T_SOURCE prompt
319 printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), $2);
322 source_stmt: source T_EOL
329 comment: T_COMMENT prompt
331 menu_add_entry(NULL);
332 menu_add_prop(P_COMMENT, $2, NULL, NULL);
333 printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno());
336 comment_stmt: comment T_EOL depends_list
343 help_start: T_HELP T_EOL
345 printd(DEBUG_PARSE, "%s:%d:help\n", zconf_curname(), zconf_lineno());
349 help: help_start T_HELPTEXT
351 current_entry->sym->help = $2;
356 depends_list: /* empty */
357 | depends_list depends T_EOL
361 depends: T_DEPENDS T_ON expr
364 printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno());
369 printd(DEBUG_PARSE, "%s:%d:depends\n", zconf_curname(), zconf_lineno());
374 printd(DEBUG_PARSE, "%s:%d:requires\n", zconf_curname(), zconf_lineno());
377 /* prompt statement */
383 menu_add_prop(P_PROMPT, $1, NULL, NULL);
387 menu_add_prop(P_PROMPT, $1, NULL, $3);
394 end: T_ENDMENU { $$ = T_ENDMENU; }
395 | T_ENDCHOICE { $$ = T_ENDCHOICE; }
396 | T_ENDIF { $$ = T_ENDIF; }
402 if_expr: /* empty */ { $$ = NULL; }
403 | T_IF expr { $$ = $2; }
406 expr: symbol { $$ = expr_alloc_symbol($1); }
407 | symbol T_EQUAL symbol { $$ = expr_alloc_comp(E_EQUAL, $1, $3); }
408 | symbol T_UNEQUAL symbol { $$ = expr_alloc_comp(E_UNEQUAL, $1, $3); }
409 | T_OPEN_PAREN expr T_CLOSE_PAREN { $$ = $2; }
410 | T_NOT expr { $$ = expr_alloc_one(E_NOT, $2); }
411 | expr T_OR expr { $$ = expr_alloc_two(E_OR, $1, $3); }
412 | expr T_AND expr { $$ = expr_alloc_two(E_AND, $1, $3); }
415 symbol: T_WORD { $$ = sym_lookup($1, 0); free($1); }
416 | T_STRING { $$ = sym_lookup($1, 1); free($1); }
421 void conf_parse(const char *name)
423 zconf_initscan(name);
427 rootmenu.prompt = menu_add_prop(P_MENU, "BusyBox Configuration", NULL, NULL);
433 menu_finalize(&rootmenu);
435 modules_sym = sym_lookup("MODULES", 0);
437 sym_change_count = 1;
440 const char *zconf_tokenname(int token)
443 case T_MENU: return "menu";
444 case T_ENDMENU: return "endmenu";
445 case T_CHOICE: return "choice";
446 case T_ENDCHOICE: return "endchoice";
447 case T_IF: return "if";
448 case T_ENDIF: return "endif";
453 static bool zconf_endtoken(int token, int starttoken, int endtoken)
455 if (token != endtoken) {
456 zconfprint("unexpected '%s' within %s block", zconf_tokenname(token), zconf_tokenname(starttoken));
460 if (current_menu->file != current_file) {
461 zconfprint("'%s' in different file than '%s'", zconf_tokenname(token), zconf_tokenname(starttoken));
462 zconfprint("location of the '%s'", zconf_tokenname(starttoken));
469 static void zconfprint(const char *err, ...)
473 fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno());
475 vfprintf(stderr, err, ap);
477 fprintf(stderr, "\n");
480 static void zconferror(const char *err)
482 fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno(), err);
485 void print_quoted_string(FILE *out, const char *str)
491 while ((p = strchr(str, '"'))) {
494 fprintf(out, "%.*s", len, str);
502 void print_symbol(FILE *out, struct menu *menu)
504 struct symbol *sym = menu->sym;
505 struct property *prop;
507 //sym->flags |= SYMBOL_PRINTED;
509 if (sym_is_choice(sym))
510 fprintf(out, "choice\n");
512 fprintf(out, "config %s\n", sym->name);
515 fputs(" boolean\n", out);
518 fputs(" tristate\n", out);
521 fputs(" string\n", out);
524 fputs(" integer\n", out);
527 fputs(" hex\n", out);
530 fputs(" ???\n", out);
534 if (!expr_is_yes(sym->dep)) {
535 fputs(" depends ", out);
536 expr_fprint(sym->dep, out);
540 for (prop = sym->prop; prop; prop = prop->next) {
541 if (prop->menu != menu)
543 switch (prop->type) {
545 fputs(" prompt ", out);
546 print_quoted_string(out, prop->text);
549 if (prop->def->flags & SYMBOL_CONST)
550 print_quoted_string(out, prop->def->name);
552 fputs(prop->def->name, out);
554 if (!expr_is_yes(E_EXPR(prop->visible))) {
556 expr_fprint(E_EXPR(prop->visible), out);
561 fputs( " default ", out);
562 print_quoted_string(out, prop->def->name);
563 if (!expr_is_yes(E_EXPR(prop->visible))) {
565 expr_fprint(E_EXPR(prop->visible), out);
570 fputs(" #choice value\n", out);
573 fprintf(out, " unknown prop %d!\n", prop->type);
578 int len = strlen(sym->help);
579 while (sym->help[--len] == '\n')
581 fprintf(out, " help\n%s\n", sym->help);
586 void zconfdump(FILE *out)
589 struct property *prop;
593 menu = rootmenu.list;
595 if ((sym = menu->sym))
596 print_symbol(out, menu);
597 else if ((prop = menu->prompt)) {
598 switch (prop->type) {
600 // fputs("\nmainmenu ", out);
601 // print_quoted_string(out, prop->text);
605 fputs("\ncomment ", out);
606 print_quoted_string(out, prop->text);
610 fputs("\nmenu ", out);
611 print_quoted_string(out, prop->text);
615 // fputs("\nsource ", out);
616 // print_quoted_string(out, prop->text);
620 // fputs("\nif\n", out);
624 if (!expr_is_yes(E_EXPR(prop->visible))) {
625 fputs(" depends ", out);
626 expr_fprint(E_EXPR(prop->visible), out);
636 else while ((menu = menu->parent)) {
637 if (menu->prompt && menu->prompt->type == P_MENU)
638 fputs("\nendmenu\n", out);
647 #include "lex.zconf.c"
648 #include "confdata.c"