162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci%{ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#include <ctype.h> 862306a36Sopenharmony_ci#include <stdarg.h> 962306a36Sopenharmony_ci#include <stdio.h> 1062306a36Sopenharmony_ci#include <stdlib.h> 1162306a36Sopenharmony_ci#include <string.h> 1262306a36Sopenharmony_ci#include <stdbool.h> 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#include "lkc.h" 1562306a36Sopenharmony_ci#include "internal.h" 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt) 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#define PRINTD 0x0001 2062306a36Sopenharmony_ci#define DEBUG_PARSE 0x0002 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ciint cdebug = PRINTD; 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_cistatic void yyerror(const char *err); 2562306a36Sopenharmony_cistatic void zconfprint(const char *err, ...); 2662306a36Sopenharmony_cistatic void zconf_error(const char *err, ...); 2762306a36Sopenharmony_cistatic bool zconf_endtoken(const char *tokenname, 2862306a36Sopenharmony_ci const char *expected_tokenname); 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_cistruct symbol *symbol_hash[SYMBOL_HASHSIZE]; 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_cistruct menu *current_menu, *current_entry; 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci%} 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci%union 3762306a36Sopenharmony_ci{ 3862306a36Sopenharmony_ci char *string; 3962306a36Sopenharmony_ci struct symbol *symbol; 4062306a36Sopenharmony_ci struct expr *expr; 4162306a36Sopenharmony_ci struct menu *menu; 4262306a36Sopenharmony_ci enum symbol_type type; 4362306a36Sopenharmony_ci enum variable_flavor flavor; 4462306a36Sopenharmony_ci} 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci%token <string> T_HELPTEXT 4762306a36Sopenharmony_ci%token <string> T_WORD 4862306a36Sopenharmony_ci%token <string> T_WORD_QUOTE 4962306a36Sopenharmony_ci%token T_BOOL 5062306a36Sopenharmony_ci%token T_CHOICE 5162306a36Sopenharmony_ci%token T_CLOSE_PAREN 5262306a36Sopenharmony_ci%token T_COLON_EQUAL 5362306a36Sopenharmony_ci%token T_COMMENT 5462306a36Sopenharmony_ci%token T_CONFIG 5562306a36Sopenharmony_ci%token T_DEFAULT 5662306a36Sopenharmony_ci%token T_DEF_BOOL 5762306a36Sopenharmony_ci%token T_DEF_TRISTATE 5862306a36Sopenharmony_ci%token T_DEPENDS 5962306a36Sopenharmony_ci%token T_ENDCHOICE 6062306a36Sopenharmony_ci%token T_ENDIF 6162306a36Sopenharmony_ci%token T_ENDMENU 6262306a36Sopenharmony_ci%token T_HELP 6362306a36Sopenharmony_ci%token T_HEX 6462306a36Sopenharmony_ci%token T_IF 6562306a36Sopenharmony_ci%token T_IMPLY 6662306a36Sopenharmony_ci%token T_INT 6762306a36Sopenharmony_ci%token T_MAINMENU 6862306a36Sopenharmony_ci%token T_MENU 6962306a36Sopenharmony_ci%token T_MENUCONFIG 7062306a36Sopenharmony_ci%token T_MODULES 7162306a36Sopenharmony_ci%token T_ON 7262306a36Sopenharmony_ci%token T_OPEN_PAREN 7362306a36Sopenharmony_ci%token T_OPTIONAL 7462306a36Sopenharmony_ci%token T_PLUS_EQUAL 7562306a36Sopenharmony_ci%token T_PROMPT 7662306a36Sopenharmony_ci%token T_RANGE 7762306a36Sopenharmony_ci%token T_SELECT 7862306a36Sopenharmony_ci%token T_SOURCE 7962306a36Sopenharmony_ci%token T_STRING 8062306a36Sopenharmony_ci%token T_TRISTATE 8162306a36Sopenharmony_ci%token T_VISIBLE 8262306a36Sopenharmony_ci%token T_EOL 8362306a36Sopenharmony_ci%token <string> T_ASSIGN_VAL 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci%left T_OR 8662306a36Sopenharmony_ci%left T_AND 8762306a36Sopenharmony_ci%left T_EQUAL T_UNEQUAL 8862306a36Sopenharmony_ci%left T_LESS T_LESS_EQUAL T_GREATER T_GREATER_EQUAL 8962306a36Sopenharmony_ci%nonassoc T_NOT 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci%type <symbol> nonconst_symbol 9262306a36Sopenharmony_ci%type <symbol> symbol 9362306a36Sopenharmony_ci%type <type> type logic_type default 9462306a36Sopenharmony_ci%type <expr> expr 9562306a36Sopenharmony_ci%type <expr> if_expr 9662306a36Sopenharmony_ci%type <string> end 9762306a36Sopenharmony_ci%type <menu> if_entry menu_entry choice_entry 9862306a36Sopenharmony_ci%type <string> word_opt assign_val 9962306a36Sopenharmony_ci%type <flavor> assign_op 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci%destructor { 10262306a36Sopenharmony_ci fprintf(stderr, "%s:%d: missing end statement for this entry\n", 10362306a36Sopenharmony_ci $$->file->name, $$->lineno); 10462306a36Sopenharmony_ci if (current_menu == $$) 10562306a36Sopenharmony_ci menu_end_menu(); 10662306a36Sopenharmony_ci} if_entry menu_entry choice_entry 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci%% 10962306a36Sopenharmony_ciinput: mainmenu_stmt stmt_list | stmt_list; 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci/* mainmenu entry */ 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_cimainmenu_stmt: T_MAINMENU T_WORD_QUOTE T_EOL 11462306a36Sopenharmony_ci{ 11562306a36Sopenharmony_ci menu_add_prompt(P_MENU, $2, NULL); 11662306a36Sopenharmony_ci}; 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_cistmt_list: 11962306a36Sopenharmony_ci /* empty */ 12062306a36Sopenharmony_ci | stmt_list assignment_stmt 12162306a36Sopenharmony_ci | stmt_list choice_stmt 12262306a36Sopenharmony_ci | stmt_list comment_stmt 12362306a36Sopenharmony_ci | stmt_list config_stmt 12462306a36Sopenharmony_ci | stmt_list if_stmt 12562306a36Sopenharmony_ci | stmt_list menu_stmt 12662306a36Sopenharmony_ci | stmt_list menuconfig_stmt 12762306a36Sopenharmony_ci | stmt_list source_stmt 12862306a36Sopenharmony_ci | stmt_list T_WORD error T_EOL { zconf_error("unknown statement \"%s\"", $2); } 12962306a36Sopenharmony_ci | stmt_list error T_EOL { zconf_error("invalid statement"); } 13062306a36Sopenharmony_ci; 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_cistmt_list_in_choice: 13362306a36Sopenharmony_ci /* empty */ 13462306a36Sopenharmony_ci | stmt_list_in_choice comment_stmt 13562306a36Sopenharmony_ci | stmt_list_in_choice config_stmt 13662306a36Sopenharmony_ci | stmt_list_in_choice if_stmt_in_choice 13762306a36Sopenharmony_ci | stmt_list_in_choice error T_EOL { zconf_error("invalid statement"); } 13862306a36Sopenharmony_ci; 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci/* config/menuconfig entry */ 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ciconfig_entry_start: T_CONFIG nonconst_symbol T_EOL 14362306a36Sopenharmony_ci{ 14462306a36Sopenharmony_ci $2->flags |= SYMBOL_OPTIONAL; 14562306a36Sopenharmony_ci menu_add_entry($2); 14662306a36Sopenharmony_ci printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), $2->name); 14762306a36Sopenharmony_ci}; 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ciconfig_stmt: config_entry_start config_option_list 15062306a36Sopenharmony_ci{ 15162306a36Sopenharmony_ci printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno()); 15262306a36Sopenharmony_ci}; 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_cimenuconfig_entry_start: T_MENUCONFIG nonconst_symbol T_EOL 15562306a36Sopenharmony_ci{ 15662306a36Sopenharmony_ci $2->flags |= SYMBOL_OPTIONAL; 15762306a36Sopenharmony_ci menu_add_entry($2); 15862306a36Sopenharmony_ci printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), $2->name); 15962306a36Sopenharmony_ci}; 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_cimenuconfig_stmt: menuconfig_entry_start config_option_list 16262306a36Sopenharmony_ci{ 16362306a36Sopenharmony_ci if (current_entry->prompt) 16462306a36Sopenharmony_ci current_entry->prompt->type = P_MENU; 16562306a36Sopenharmony_ci else 16662306a36Sopenharmony_ci zconfprint("warning: menuconfig statement without prompt"); 16762306a36Sopenharmony_ci printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno()); 16862306a36Sopenharmony_ci}; 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ciconfig_option_list: 17162306a36Sopenharmony_ci /* empty */ 17262306a36Sopenharmony_ci | config_option_list config_option 17362306a36Sopenharmony_ci | config_option_list depends 17462306a36Sopenharmony_ci | config_option_list help 17562306a36Sopenharmony_ci; 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ciconfig_option: type prompt_stmt_opt T_EOL 17862306a36Sopenharmony_ci{ 17962306a36Sopenharmony_ci menu_set_type($1); 18062306a36Sopenharmony_ci printd(DEBUG_PARSE, "%s:%d:type(%u)\n", 18162306a36Sopenharmony_ci zconf_curname(), zconf_lineno(), 18262306a36Sopenharmony_ci $1); 18362306a36Sopenharmony_ci}; 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ciconfig_option: T_PROMPT T_WORD_QUOTE if_expr T_EOL 18662306a36Sopenharmony_ci{ 18762306a36Sopenharmony_ci menu_add_prompt(P_PROMPT, $2, $3); 18862306a36Sopenharmony_ci printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno()); 18962306a36Sopenharmony_ci}; 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ciconfig_option: default expr if_expr T_EOL 19262306a36Sopenharmony_ci{ 19362306a36Sopenharmony_ci menu_add_expr(P_DEFAULT, $2, $3); 19462306a36Sopenharmony_ci if ($1 != S_UNKNOWN) 19562306a36Sopenharmony_ci menu_set_type($1); 19662306a36Sopenharmony_ci printd(DEBUG_PARSE, "%s:%d:default(%u)\n", 19762306a36Sopenharmony_ci zconf_curname(), zconf_lineno(), 19862306a36Sopenharmony_ci $1); 19962306a36Sopenharmony_ci}; 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ciconfig_option: T_SELECT nonconst_symbol if_expr T_EOL 20262306a36Sopenharmony_ci{ 20362306a36Sopenharmony_ci menu_add_symbol(P_SELECT, $2, $3); 20462306a36Sopenharmony_ci printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno()); 20562306a36Sopenharmony_ci}; 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ciconfig_option: T_IMPLY nonconst_symbol if_expr T_EOL 20862306a36Sopenharmony_ci{ 20962306a36Sopenharmony_ci menu_add_symbol(P_IMPLY, $2, $3); 21062306a36Sopenharmony_ci printd(DEBUG_PARSE, "%s:%d:imply\n", zconf_curname(), zconf_lineno()); 21162306a36Sopenharmony_ci}; 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ciconfig_option: T_RANGE symbol symbol if_expr T_EOL 21462306a36Sopenharmony_ci{ 21562306a36Sopenharmony_ci menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,$2, $3), $4); 21662306a36Sopenharmony_ci printd(DEBUG_PARSE, "%s:%d:range\n", zconf_curname(), zconf_lineno()); 21762306a36Sopenharmony_ci}; 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ciconfig_option: T_MODULES T_EOL 22062306a36Sopenharmony_ci{ 22162306a36Sopenharmony_ci if (modules_sym) 22262306a36Sopenharmony_ci zconf_error("symbol '%s' redefines option 'modules' already defined by symbol '%s'", 22362306a36Sopenharmony_ci current_entry->sym->name, modules_sym->name); 22462306a36Sopenharmony_ci modules_sym = current_entry->sym; 22562306a36Sopenharmony_ci}; 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci/* choice entry */ 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_cichoice: T_CHOICE word_opt T_EOL 23062306a36Sopenharmony_ci{ 23162306a36Sopenharmony_ci struct symbol *sym = sym_lookup($2, SYMBOL_CHOICE); 23262306a36Sopenharmony_ci sym->flags |= SYMBOL_NO_WRITE; 23362306a36Sopenharmony_ci menu_add_entry(sym); 23462306a36Sopenharmony_ci menu_add_expr(P_CHOICE, NULL, NULL); 23562306a36Sopenharmony_ci free($2); 23662306a36Sopenharmony_ci printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno()); 23762306a36Sopenharmony_ci}; 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_cichoice_entry: choice choice_option_list 24062306a36Sopenharmony_ci{ 24162306a36Sopenharmony_ci $$ = menu_add_menu(); 24262306a36Sopenharmony_ci}; 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_cichoice_end: end 24562306a36Sopenharmony_ci{ 24662306a36Sopenharmony_ci if (zconf_endtoken($1, "choice")) { 24762306a36Sopenharmony_ci menu_end_menu(); 24862306a36Sopenharmony_ci printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno()); 24962306a36Sopenharmony_ci } 25062306a36Sopenharmony_ci}; 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_cichoice_stmt: choice_entry stmt_list_in_choice choice_end 25362306a36Sopenharmony_ci; 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_cichoice_option_list: 25662306a36Sopenharmony_ci /* empty */ 25762306a36Sopenharmony_ci | choice_option_list choice_option 25862306a36Sopenharmony_ci | choice_option_list depends 25962306a36Sopenharmony_ci | choice_option_list help 26062306a36Sopenharmony_ci; 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_cichoice_option: T_PROMPT T_WORD_QUOTE if_expr T_EOL 26362306a36Sopenharmony_ci{ 26462306a36Sopenharmony_ci menu_add_prompt(P_PROMPT, $2, $3); 26562306a36Sopenharmony_ci printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno()); 26662306a36Sopenharmony_ci}; 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_cichoice_option: logic_type prompt_stmt_opt T_EOL 26962306a36Sopenharmony_ci{ 27062306a36Sopenharmony_ci menu_set_type($1); 27162306a36Sopenharmony_ci printd(DEBUG_PARSE, "%s:%d:type(%u)\n", 27262306a36Sopenharmony_ci zconf_curname(), zconf_lineno(), $1); 27362306a36Sopenharmony_ci}; 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_cichoice_option: T_OPTIONAL T_EOL 27662306a36Sopenharmony_ci{ 27762306a36Sopenharmony_ci current_entry->sym->flags |= SYMBOL_OPTIONAL; 27862306a36Sopenharmony_ci printd(DEBUG_PARSE, "%s:%d:optional\n", zconf_curname(), zconf_lineno()); 27962306a36Sopenharmony_ci}; 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_cichoice_option: T_DEFAULT nonconst_symbol if_expr T_EOL 28262306a36Sopenharmony_ci{ 28362306a36Sopenharmony_ci menu_add_symbol(P_DEFAULT, $2, $3); 28462306a36Sopenharmony_ci printd(DEBUG_PARSE, "%s:%d:default\n", 28562306a36Sopenharmony_ci zconf_curname(), zconf_lineno()); 28662306a36Sopenharmony_ci}; 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_citype: 28962306a36Sopenharmony_ci logic_type 29062306a36Sopenharmony_ci | T_INT { $$ = S_INT; } 29162306a36Sopenharmony_ci | T_HEX { $$ = S_HEX; } 29262306a36Sopenharmony_ci | T_STRING { $$ = S_STRING; } 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_cilogic_type: 29562306a36Sopenharmony_ci T_BOOL { $$ = S_BOOLEAN; } 29662306a36Sopenharmony_ci | T_TRISTATE { $$ = S_TRISTATE; } 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_cidefault: 29962306a36Sopenharmony_ci T_DEFAULT { $$ = S_UNKNOWN; } 30062306a36Sopenharmony_ci | T_DEF_BOOL { $$ = S_BOOLEAN; } 30162306a36Sopenharmony_ci | T_DEF_TRISTATE { $$ = S_TRISTATE; } 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci/* if entry */ 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ciif_entry: T_IF expr T_EOL 30662306a36Sopenharmony_ci{ 30762306a36Sopenharmony_ci printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno()); 30862306a36Sopenharmony_ci menu_add_entry(NULL); 30962306a36Sopenharmony_ci menu_add_dep($2); 31062306a36Sopenharmony_ci $$ = menu_add_menu(); 31162306a36Sopenharmony_ci}; 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ciif_end: end 31462306a36Sopenharmony_ci{ 31562306a36Sopenharmony_ci if (zconf_endtoken($1, "if")) { 31662306a36Sopenharmony_ci menu_end_menu(); 31762306a36Sopenharmony_ci printd(DEBUG_PARSE, "%s:%d:endif\n", zconf_curname(), zconf_lineno()); 31862306a36Sopenharmony_ci } 31962306a36Sopenharmony_ci}; 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ciif_stmt: if_entry stmt_list if_end 32262306a36Sopenharmony_ci; 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ciif_stmt_in_choice: if_entry stmt_list_in_choice if_end 32562306a36Sopenharmony_ci; 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci/* menu entry */ 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_cimenu: T_MENU T_WORD_QUOTE T_EOL 33062306a36Sopenharmony_ci{ 33162306a36Sopenharmony_ci menu_add_entry(NULL); 33262306a36Sopenharmony_ci menu_add_prompt(P_MENU, $2, NULL); 33362306a36Sopenharmony_ci printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno()); 33462306a36Sopenharmony_ci}; 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_cimenu_entry: menu menu_option_list 33762306a36Sopenharmony_ci{ 33862306a36Sopenharmony_ci $$ = menu_add_menu(); 33962306a36Sopenharmony_ci}; 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_cimenu_end: end 34262306a36Sopenharmony_ci{ 34362306a36Sopenharmony_ci if (zconf_endtoken($1, "menu")) { 34462306a36Sopenharmony_ci menu_end_menu(); 34562306a36Sopenharmony_ci printd(DEBUG_PARSE, "%s:%d:endmenu\n", zconf_curname(), zconf_lineno()); 34662306a36Sopenharmony_ci } 34762306a36Sopenharmony_ci}; 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_cimenu_stmt: menu_entry stmt_list menu_end 35062306a36Sopenharmony_ci; 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_cimenu_option_list: 35362306a36Sopenharmony_ci /* empty */ 35462306a36Sopenharmony_ci | menu_option_list visible 35562306a36Sopenharmony_ci | menu_option_list depends 35662306a36Sopenharmony_ci; 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_cisource_stmt: T_SOURCE T_WORD_QUOTE T_EOL 35962306a36Sopenharmony_ci{ 36062306a36Sopenharmony_ci printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), $2); 36162306a36Sopenharmony_ci zconf_nextfile($2); 36262306a36Sopenharmony_ci free($2); 36362306a36Sopenharmony_ci}; 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci/* comment entry */ 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_cicomment: T_COMMENT T_WORD_QUOTE T_EOL 36862306a36Sopenharmony_ci{ 36962306a36Sopenharmony_ci menu_add_entry(NULL); 37062306a36Sopenharmony_ci menu_add_prompt(P_COMMENT, $2, NULL); 37162306a36Sopenharmony_ci printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno()); 37262306a36Sopenharmony_ci}; 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_cicomment_stmt: comment comment_option_list 37562306a36Sopenharmony_ci; 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_cicomment_option_list: 37862306a36Sopenharmony_ci /* empty */ 37962306a36Sopenharmony_ci | comment_option_list depends 38062306a36Sopenharmony_ci; 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci/* help option */ 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_cihelp_start: T_HELP T_EOL 38562306a36Sopenharmony_ci{ 38662306a36Sopenharmony_ci printd(DEBUG_PARSE, "%s:%d:help\n", zconf_curname(), zconf_lineno()); 38762306a36Sopenharmony_ci zconf_starthelp(); 38862306a36Sopenharmony_ci}; 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_cihelp: help_start T_HELPTEXT 39162306a36Sopenharmony_ci{ 39262306a36Sopenharmony_ci if (current_entry->help) { 39362306a36Sopenharmony_ci free(current_entry->help); 39462306a36Sopenharmony_ci zconfprint("warning: '%s' defined with more than one help text -- only the last one will be used", 39562306a36Sopenharmony_ci current_entry->sym->name ?: "<choice>"); 39662306a36Sopenharmony_ci } 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_ci /* Is the help text empty or all whitespace? */ 39962306a36Sopenharmony_ci if ($2[strspn($2, " \f\n\r\t\v")] == '\0') 40062306a36Sopenharmony_ci zconfprint("warning: '%s' defined with blank help text", 40162306a36Sopenharmony_ci current_entry->sym->name ?: "<choice>"); 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_ci current_entry->help = $2; 40462306a36Sopenharmony_ci}; 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_ci/* depends option */ 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_cidepends: T_DEPENDS T_ON expr T_EOL 40962306a36Sopenharmony_ci{ 41062306a36Sopenharmony_ci menu_add_dep($3); 41162306a36Sopenharmony_ci printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno()); 41262306a36Sopenharmony_ci}; 41362306a36Sopenharmony_ci 41462306a36Sopenharmony_ci/* visibility option */ 41562306a36Sopenharmony_civisible: T_VISIBLE if_expr T_EOL 41662306a36Sopenharmony_ci{ 41762306a36Sopenharmony_ci menu_add_visibility($2); 41862306a36Sopenharmony_ci}; 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_ci/* prompt statement */ 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ciprompt_stmt_opt: 42362306a36Sopenharmony_ci /* empty */ 42462306a36Sopenharmony_ci | T_WORD_QUOTE if_expr 42562306a36Sopenharmony_ci{ 42662306a36Sopenharmony_ci menu_add_prompt(P_PROMPT, $1, $2); 42762306a36Sopenharmony_ci}; 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_ciend: T_ENDMENU T_EOL { $$ = "menu"; } 43062306a36Sopenharmony_ci | T_ENDCHOICE T_EOL { $$ = "choice"; } 43162306a36Sopenharmony_ci | T_ENDIF T_EOL { $$ = "if"; } 43262306a36Sopenharmony_ci; 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_ciif_expr: /* empty */ { $$ = NULL; } 43562306a36Sopenharmony_ci | T_IF expr { $$ = $2; } 43662306a36Sopenharmony_ci; 43762306a36Sopenharmony_ci 43862306a36Sopenharmony_ciexpr: symbol { $$ = expr_alloc_symbol($1); } 43962306a36Sopenharmony_ci | symbol T_LESS symbol { $$ = expr_alloc_comp(E_LTH, $1, $3); } 44062306a36Sopenharmony_ci | symbol T_LESS_EQUAL symbol { $$ = expr_alloc_comp(E_LEQ, $1, $3); } 44162306a36Sopenharmony_ci | symbol T_GREATER symbol { $$ = expr_alloc_comp(E_GTH, $1, $3); } 44262306a36Sopenharmony_ci | symbol T_GREATER_EQUAL symbol { $$ = expr_alloc_comp(E_GEQ, $1, $3); } 44362306a36Sopenharmony_ci | symbol T_EQUAL symbol { $$ = expr_alloc_comp(E_EQUAL, $1, $3); } 44462306a36Sopenharmony_ci | symbol T_UNEQUAL symbol { $$ = expr_alloc_comp(E_UNEQUAL, $1, $3); } 44562306a36Sopenharmony_ci | T_OPEN_PAREN expr T_CLOSE_PAREN { $$ = $2; } 44662306a36Sopenharmony_ci | T_NOT expr { $$ = expr_alloc_one(E_NOT, $2); } 44762306a36Sopenharmony_ci | expr T_OR expr { $$ = expr_alloc_two(E_OR, $1, $3); } 44862306a36Sopenharmony_ci | expr T_AND expr { $$ = expr_alloc_two(E_AND, $1, $3); } 44962306a36Sopenharmony_ci; 45062306a36Sopenharmony_ci 45162306a36Sopenharmony_ci/* For symbol definitions, selects, etc., where quotes are not accepted */ 45262306a36Sopenharmony_cinonconst_symbol: T_WORD { $$ = sym_lookup($1, 0); free($1); }; 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_cisymbol: nonconst_symbol 45562306a36Sopenharmony_ci | T_WORD_QUOTE { $$ = sym_lookup($1, SYMBOL_CONST); free($1); } 45662306a36Sopenharmony_ci; 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_ciword_opt: /* empty */ { $$ = NULL; } 45962306a36Sopenharmony_ci | T_WORD 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_ci/* assignment statement */ 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ciassignment_stmt: T_WORD assign_op assign_val T_EOL { variable_add($1, $3, $2); free($1); free($3); } 46462306a36Sopenharmony_ci 46562306a36Sopenharmony_ciassign_op: 46662306a36Sopenharmony_ci T_EQUAL { $$ = VAR_RECURSIVE; } 46762306a36Sopenharmony_ci | T_COLON_EQUAL { $$ = VAR_SIMPLE; } 46862306a36Sopenharmony_ci | T_PLUS_EQUAL { $$ = VAR_APPEND; } 46962306a36Sopenharmony_ci; 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_ciassign_val: 47262306a36Sopenharmony_ci /* empty */ { $$ = xstrdup(""); }; 47362306a36Sopenharmony_ci | T_ASSIGN_VAL 47462306a36Sopenharmony_ci; 47562306a36Sopenharmony_ci 47662306a36Sopenharmony_ci%% 47762306a36Sopenharmony_ci 47862306a36Sopenharmony_civoid conf_parse(const char *name) 47962306a36Sopenharmony_ci{ 48062306a36Sopenharmony_ci struct symbol *sym; 48162306a36Sopenharmony_ci int i; 48262306a36Sopenharmony_ci 48362306a36Sopenharmony_ci zconf_initscan(name); 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_ci _menu_init(); 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_ci if (getenv("ZCONF_DEBUG")) 48862306a36Sopenharmony_ci yydebug = 1; 48962306a36Sopenharmony_ci yyparse(); 49062306a36Sopenharmony_ci 49162306a36Sopenharmony_ci /* Variables are expanded in the parse phase. We can free them here. */ 49262306a36Sopenharmony_ci variable_all_del(); 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_ci if (yynerrs) 49562306a36Sopenharmony_ci exit(1); 49662306a36Sopenharmony_ci if (!modules_sym) 49762306a36Sopenharmony_ci modules_sym = sym_find( "n" ); 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_ci if (!menu_has_prompt(&rootmenu)) { 50062306a36Sopenharmony_ci current_entry = &rootmenu; 50162306a36Sopenharmony_ci menu_add_prompt(P_MENU, "Main menu", NULL); 50262306a36Sopenharmony_ci } 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci menu_finalize(&rootmenu); 50562306a36Sopenharmony_ci for_all_symbols(i, sym) { 50662306a36Sopenharmony_ci if (sym_check_deps(sym)) 50762306a36Sopenharmony_ci yynerrs++; 50862306a36Sopenharmony_ci } 50962306a36Sopenharmony_ci if (yynerrs) 51062306a36Sopenharmony_ci exit(1); 51162306a36Sopenharmony_ci conf_set_changed(true); 51262306a36Sopenharmony_ci} 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_cistatic bool zconf_endtoken(const char *tokenname, 51562306a36Sopenharmony_ci const char *expected_tokenname) 51662306a36Sopenharmony_ci{ 51762306a36Sopenharmony_ci if (strcmp(tokenname, expected_tokenname)) { 51862306a36Sopenharmony_ci zconf_error("unexpected '%s' within %s block", 51962306a36Sopenharmony_ci tokenname, expected_tokenname); 52062306a36Sopenharmony_ci yynerrs++; 52162306a36Sopenharmony_ci return false; 52262306a36Sopenharmony_ci } 52362306a36Sopenharmony_ci if (current_menu->file != current_file) { 52462306a36Sopenharmony_ci zconf_error("'%s' in different file than '%s'", 52562306a36Sopenharmony_ci tokenname, expected_tokenname); 52662306a36Sopenharmony_ci fprintf(stderr, "%s:%d: location of the '%s'\n", 52762306a36Sopenharmony_ci current_menu->file->name, current_menu->lineno, 52862306a36Sopenharmony_ci expected_tokenname); 52962306a36Sopenharmony_ci yynerrs++; 53062306a36Sopenharmony_ci return false; 53162306a36Sopenharmony_ci } 53262306a36Sopenharmony_ci return true; 53362306a36Sopenharmony_ci} 53462306a36Sopenharmony_ci 53562306a36Sopenharmony_cistatic void zconfprint(const char *err, ...) 53662306a36Sopenharmony_ci{ 53762306a36Sopenharmony_ci va_list ap; 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ci fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno()); 54062306a36Sopenharmony_ci va_start(ap, err); 54162306a36Sopenharmony_ci vfprintf(stderr, err, ap); 54262306a36Sopenharmony_ci va_end(ap); 54362306a36Sopenharmony_ci fprintf(stderr, "\n"); 54462306a36Sopenharmony_ci} 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_cistatic void zconf_error(const char *err, ...) 54762306a36Sopenharmony_ci{ 54862306a36Sopenharmony_ci va_list ap; 54962306a36Sopenharmony_ci 55062306a36Sopenharmony_ci yynerrs++; 55162306a36Sopenharmony_ci fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno()); 55262306a36Sopenharmony_ci va_start(ap, err); 55362306a36Sopenharmony_ci vfprintf(stderr, err, ap); 55462306a36Sopenharmony_ci va_end(ap); 55562306a36Sopenharmony_ci fprintf(stderr, "\n"); 55662306a36Sopenharmony_ci} 55762306a36Sopenharmony_ci 55862306a36Sopenharmony_cistatic void yyerror(const char *err) 55962306a36Sopenharmony_ci{ 56062306a36Sopenharmony_ci fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err); 56162306a36Sopenharmony_ci} 56262306a36Sopenharmony_ci 56362306a36Sopenharmony_cistatic void print_quoted_string(FILE *out, const char *str) 56462306a36Sopenharmony_ci{ 56562306a36Sopenharmony_ci const char *p; 56662306a36Sopenharmony_ci int len; 56762306a36Sopenharmony_ci 56862306a36Sopenharmony_ci putc('"', out); 56962306a36Sopenharmony_ci while ((p = strchr(str, '"'))) { 57062306a36Sopenharmony_ci len = p - str; 57162306a36Sopenharmony_ci if (len) 57262306a36Sopenharmony_ci fprintf(out, "%.*s", len, str); 57362306a36Sopenharmony_ci fputs("\\\"", out); 57462306a36Sopenharmony_ci str = p + 1; 57562306a36Sopenharmony_ci } 57662306a36Sopenharmony_ci fputs(str, out); 57762306a36Sopenharmony_ci putc('"', out); 57862306a36Sopenharmony_ci} 57962306a36Sopenharmony_ci 58062306a36Sopenharmony_cistatic void print_symbol(FILE *out, struct menu *menu) 58162306a36Sopenharmony_ci{ 58262306a36Sopenharmony_ci struct symbol *sym = menu->sym; 58362306a36Sopenharmony_ci struct property *prop; 58462306a36Sopenharmony_ci 58562306a36Sopenharmony_ci if (sym_is_choice(sym)) 58662306a36Sopenharmony_ci fprintf(out, "\nchoice\n"); 58762306a36Sopenharmony_ci else 58862306a36Sopenharmony_ci fprintf(out, "\nconfig %s\n", sym->name); 58962306a36Sopenharmony_ci switch (sym->type) { 59062306a36Sopenharmony_ci case S_BOOLEAN: 59162306a36Sopenharmony_ci fputs(" bool\n", out); 59262306a36Sopenharmony_ci break; 59362306a36Sopenharmony_ci case S_TRISTATE: 59462306a36Sopenharmony_ci fputs(" tristate\n", out); 59562306a36Sopenharmony_ci break; 59662306a36Sopenharmony_ci case S_STRING: 59762306a36Sopenharmony_ci fputs(" string\n", out); 59862306a36Sopenharmony_ci break; 59962306a36Sopenharmony_ci case S_INT: 60062306a36Sopenharmony_ci fputs(" integer\n", out); 60162306a36Sopenharmony_ci break; 60262306a36Sopenharmony_ci case S_HEX: 60362306a36Sopenharmony_ci fputs(" hex\n", out); 60462306a36Sopenharmony_ci break; 60562306a36Sopenharmony_ci default: 60662306a36Sopenharmony_ci fputs(" ???\n", out); 60762306a36Sopenharmony_ci break; 60862306a36Sopenharmony_ci } 60962306a36Sopenharmony_ci for (prop = sym->prop; prop; prop = prop->next) { 61062306a36Sopenharmony_ci if (prop->menu != menu) 61162306a36Sopenharmony_ci continue; 61262306a36Sopenharmony_ci switch (prop->type) { 61362306a36Sopenharmony_ci case P_PROMPT: 61462306a36Sopenharmony_ci fputs(" prompt ", out); 61562306a36Sopenharmony_ci print_quoted_string(out, prop->text); 61662306a36Sopenharmony_ci if (!expr_is_yes(prop->visible.expr)) { 61762306a36Sopenharmony_ci fputs(" if ", out); 61862306a36Sopenharmony_ci expr_fprint(prop->visible.expr, out); 61962306a36Sopenharmony_ci } 62062306a36Sopenharmony_ci fputc('\n', out); 62162306a36Sopenharmony_ci break; 62262306a36Sopenharmony_ci case P_DEFAULT: 62362306a36Sopenharmony_ci fputs( " default ", out); 62462306a36Sopenharmony_ci expr_fprint(prop->expr, out); 62562306a36Sopenharmony_ci if (!expr_is_yes(prop->visible.expr)) { 62662306a36Sopenharmony_ci fputs(" if ", out); 62762306a36Sopenharmony_ci expr_fprint(prop->visible.expr, out); 62862306a36Sopenharmony_ci } 62962306a36Sopenharmony_ci fputc('\n', out); 63062306a36Sopenharmony_ci break; 63162306a36Sopenharmony_ci case P_CHOICE: 63262306a36Sopenharmony_ci fputs(" #choice value\n", out); 63362306a36Sopenharmony_ci break; 63462306a36Sopenharmony_ci case P_SELECT: 63562306a36Sopenharmony_ci fputs( " select ", out); 63662306a36Sopenharmony_ci expr_fprint(prop->expr, out); 63762306a36Sopenharmony_ci fputc('\n', out); 63862306a36Sopenharmony_ci break; 63962306a36Sopenharmony_ci case P_IMPLY: 64062306a36Sopenharmony_ci fputs( " imply ", out); 64162306a36Sopenharmony_ci expr_fprint(prop->expr, out); 64262306a36Sopenharmony_ci fputc('\n', out); 64362306a36Sopenharmony_ci break; 64462306a36Sopenharmony_ci case P_RANGE: 64562306a36Sopenharmony_ci fputs( " range ", out); 64662306a36Sopenharmony_ci expr_fprint(prop->expr, out); 64762306a36Sopenharmony_ci fputc('\n', out); 64862306a36Sopenharmony_ci break; 64962306a36Sopenharmony_ci case P_MENU: 65062306a36Sopenharmony_ci fputs( " menu ", out); 65162306a36Sopenharmony_ci print_quoted_string(out, prop->text); 65262306a36Sopenharmony_ci fputc('\n', out); 65362306a36Sopenharmony_ci break; 65462306a36Sopenharmony_ci case P_SYMBOL: 65562306a36Sopenharmony_ci fputs( " symbol ", out); 65662306a36Sopenharmony_ci fprintf(out, "%s\n", prop->menu->sym->name); 65762306a36Sopenharmony_ci break; 65862306a36Sopenharmony_ci default: 65962306a36Sopenharmony_ci fprintf(out, " unknown prop %d!\n", prop->type); 66062306a36Sopenharmony_ci break; 66162306a36Sopenharmony_ci } 66262306a36Sopenharmony_ci } 66362306a36Sopenharmony_ci if (menu->help) { 66462306a36Sopenharmony_ci int len = strlen(menu->help); 66562306a36Sopenharmony_ci while (menu->help[--len] == '\n') 66662306a36Sopenharmony_ci menu->help[len] = 0; 66762306a36Sopenharmony_ci fprintf(out, " help\n%s\n", menu->help); 66862306a36Sopenharmony_ci } 66962306a36Sopenharmony_ci} 67062306a36Sopenharmony_ci 67162306a36Sopenharmony_civoid zconfdump(FILE *out) 67262306a36Sopenharmony_ci{ 67362306a36Sopenharmony_ci struct property *prop; 67462306a36Sopenharmony_ci struct symbol *sym; 67562306a36Sopenharmony_ci struct menu *menu; 67662306a36Sopenharmony_ci 67762306a36Sopenharmony_ci menu = rootmenu.list; 67862306a36Sopenharmony_ci while (menu) { 67962306a36Sopenharmony_ci if ((sym = menu->sym)) 68062306a36Sopenharmony_ci print_symbol(out, menu); 68162306a36Sopenharmony_ci else if ((prop = menu->prompt)) { 68262306a36Sopenharmony_ci switch (prop->type) { 68362306a36Sopenharmony_ci case P_COMMENT: 68462306a36Sopenharmony_ci fputs("\ncomment ", out); 68562306a36Sopenharmony_ci print_quoted_string(out, prop->text); 68662306a36Sopenharmony_ci fputs("\n", out); 68762306a36Sopenharmony_ci break; 68862306a36Sopenharmony_ci case P_MENU: 68962306a36Sopenharmony_ci fputs("\nmenu ", out); 69062306a36Sopenharmony_ci print_quoted_string(out, prop->text); 69162306a36Sopenharmony_ci fputs("\n", out); 69262306a36Sopenharmony_ci break; 69362306a36Sopenharmony_ci default: 69462306a36Sopenharmony_ci ; 69562306a36Sopenharmony_ci } 69662306a36Sopenharmony_ci if (!expr_is_yes(prop->visible.expr)) { 69762306a36Sopenharmony_ci fputs(" depends ", out); 69862306a36Sopenharmony_ci expr_fprint(prop->visible.expr, out); 69962306a36Sopenharmony_ci fputc('\n', out); 70062306a36Sopenharmony_ci } 70162306a36Sopenharmony_ci } 70262306a36Sopenharmony_ci 70362306a36Sopenharmony_ci if (menu->list) 70462306a36Sopenharmony_ci menu = menu->list; 70562306a36Sopenharmony_ci else if (menu->next) 70662306a36Sopenharmony_ci menu = menu->next; 70762306a36Sopenharmony_ci else while ((menu = menu->parent)) { 70862306a36Sopenharmony_ci if (menu->prompt && menu->prompt->type == P_MENU) 70962306a36Sopenharmony_ci fputs("\nendmenu\n", out); 71062306a36Sopenharmony_ci if (menu->next) { 71162306a36Sopenharmony_ci menu = menu->next; 71262306a36Sopenharmony_ci break; 71362306a36Sopenharmony_ci } 71462306a36Sopenharmony_ci } 71562306a36Sopenharmony_ci } 71662306a36Sopenharmony_ci} 717