%{ #include #include #include #include "cli_val.h" extern int yy_cli_def_lineno; extern char *yy_cli_def_text; static vtw_def *parse_defp; static int parse_status; static boolean cli_def_type_only=0; /*{ if (cli_def_type_only) YYACCEPT;}*/ /* XXX: sigh, the -p flag to yacc should do this for us kkkk*/ #define yystacksize tpltstacksize #define yysslim tpltsslim /* forward prototypes */ extern int yy_cli_parse_parse(); extern int yy_cli_def_lex(); extern void yy_cli_parse_error(const char *); static void cli_deferror(const char *); extern FILE *yy_cli_def_in; #define YYDEBUG 1 #define yy_cli_parse_lex yy_cli_def_lex %} %token EOL %token MULTI %token TAG %token TYPE %token HELP %token DEFAULT %token PATTERN %token EXEC %token SYNTAX %token COMMIT %token CHECK %token DUMMY %left SEMI %token VALUE %token TYPE_DEF %token VAR %token STRING %token EX_STRING %token SYNTAX_ERROR %token ACTION %left ASSIGN %left OR %left AND %right NOT %left COMMA %nonassoc COND %token RP %token LP %type val %type exp %type val0 %type action %type action0 %union { char *strp; valstruct val; vtw_type_e type; vtw_cond_e cond; vtw_node *nodep; vtw_act_type action; } %% input: tag | EOL input | tag otherinput ; otherinput: type EOL | cause EOL | otherinput type EOL | otherinput cause EOL | otherinput EOL | EOL | syntax_error ; tag: /* empty */ | TAG EOL {parse_defp->tag = TRUE;} | MULTI EOL {parse_defp->multi = TRUE;} ; type: TYPE TYPE_DEF SEMI STRING { parse_defp->def_type = $2; parse_defp->def_type_help = $4; } ; type: TYPE TYPE_DEF { parse_defp->def_type = $2; } ; cause: help_cause | default_cause | syntax_cause | ACTION action { append(parse_defp->actions + $1, $2, 0);} | dummy_stmt ; dummy_stmt: DUMMY STRING { /* ignored */ } ; help_cause: HELP STRING { parse_defp->def_node_help = $2; /* no semantics for now */ } default_cause: DEFAULT VALUE { if ($2.val_type != parse_defp->def_type) yy_cli_parse_error((const char *)"Bad default\n"); parse_defp->def_default = $2.val; } default_cause: DEFAULT STRING { if (TEXT_TYPE != parse_defp->def_type) yy_cli_parse_error((const char *)"Bad default\n"); parse_defp->def_default = $2; } syntax_cause: SYNTAX exp {append(parse_defp->actions + syntax_act, $2, 0);} ; syntax_cause: COMMIT exp {append(parse_defp->actions + syntax_act, $2, 1);} ; action0: STRING { $$ = make_node(EXEC_OP, make_str_node($1),NULL);} ; action: action0 | action0 SEMI STRING {$$ = make_node(HELP_OP, $1, make_str_node($3));} | exp ; exp: LP exp RP {$$=$2;} | exp AND exp {$$ = make_node(AND_OP,$1,$3);} | exp OR exp {$$ = make_node(OR_OP,$1,$3);} | val COND val {$$ = make_node(COND_OP,$1,$3);$$->vtw_node_aux = $2;} | PATTERN VAR STRING { $$ = make_node(PATTERN_OP,make_var_node($2), make_str_node($3));} | EXEC STRING { $$ = make_node(EXEC_OP,make_str_node($2),NULL);} | NOT exp {$$ = make_node(NOT_OP,$2,NULL);} | exp SEMI STRING {$$ = make_node(HELP_OP, $1, make_str_node($3));} | VAR ASSIGN val {$$ = make_node(ASSIGN_OP, make_var_node($1), $3);} ; val: VAR {$$ = make_var_node($1);} | val0 {$$ = make_val_node(&($1));} | EX_STRING {$$=make_str_node0($1, B_QUOTE_OP);} ; val0: VALUE | val0 COMMA val0 { add_val(&($1), &($3)); $$=$1; } | STRING {$$ = str2val($1);} ; syntax_error: SYNTAX_ERROR { cli_deferror("syntax error"); } ; %% char *parse_path; int parse_def(vtw_def *defp, char *path, boolean type_only) { int status; yy_cli_def_lineno = 1; parse_status = 0; parse_defp = defp; cli_def_type_only = type_only; yy_cli_def_in = fopen(path, "r"); #if 0 yy_cli_parse_debug = 1; #endif if (!yy_cli_def_in) return -5; parse_path = path; status = yy_cli_parse_parse(); /* 0 is OK */ fclose(yy_cli_def_in); return status; } static void cli_deferror(const char *s) { printf("Error: %s in file [%s], line %d, last token [%s]\n",s, parse_path, yy_cli_def_lineno, yy_cli_def_text); } void yy_cli_parse_error(const char *s) { cli_deferror(s); }