Index: ast_expr2.fl =================================================================== --- ast_expr2.fl (revision 8106) +++ ast_expr2.fl (working copy) @@ -1,4 +1,9 @@ %{ +/*! \file + * + * \brief Dialplan Expression Parser + */ + #include #include #include @@ -44,7 +49,7 @@ void ast_yyset_column(int column_no, yyscan_t yyscanner); int ast_yyget_column(yyscan_t yyscanner); - +static int curlycount = 0; %} %option prefix="ast_yy" @@ -54,6 +59,7 @@ %option bison-bridge %option bison-locations %option noyywrap +%x var trail %% @@ -75,6 +81,8 @@ \:\: { SET_COLUMNS; SET_STRING; return TOK_COLONCOLON;} \( { SET_COLUMNS; SET_STRING; return TOK_LP;} \) { SET_COLUMNS; SET_STRING; return TOK_RP;} +\$\{ {/* gather the contents of ${} expressions, with trailing stuff, into a single TOKEN. They are much more complex now than they used to be */ + curlycount = 0; BEGIN(var); yymore();} [ \r] {} \"[^"]*\" {SET_COLUMNS; SET_STRING; return TOKEN;} @@ -83,8 +91,15 @@ [0-9]+ { SET_COLUMNS; /* the original behavior of the expression parser was to bring in numbers as a numeric string */ SET_NUMERIC_STRING; return TOKEN;} -[a-zA-Z0-9,.';{}\\_^%$#@!]+ {SET_COLUMNS; SET_STRING; return TOKEN;} +[a-zA-Z0-9,.';\\_^%$#@!]+ {SET_COLUMNS; SET_STRING; return TOKEN;} +[^{}]*\} {curlycount--; if(curlycount < 0){ BEGIN(trail); yymore();} else { yymore();}} +[^{}]*\{ {curlycount++; yymore(); } +[^-\t\r \n$():?%/+=*<>!|&]* {BEGIN(0); SET_COLUMNS; SET_STRING; return TOKEN;} +[-\t\r \n$():?%/+=*<>!|&] {char c = yytext[yyleng-1]; BEGIN(0); unput(c); SET_COLUMNS; SET_STRING; return TOKEN;} +\$\{ {curlycount = 0; BEGIN(var); yymore(); } +<> {BEGIN(0); SET_COLUMNS; SET_STRING; return TOKEN; /* actually, if an expr is only a variable ref, this could happen a LOT */} + %% /* I'm putting the interface routine to the whole parse here in the flexer input file @@ -130,6 +145,7 @@ ast_copy_string(buf, io.val->u.s, length); #endif /* STANDALONE */ return_value = strlen(buf); + free(io.val->u.s); } free(io.val); } @@ -144,15 +160,6 @@ int i=0; spacebuf[0] = 0; -#ifdef WHEN_LOC_MEANS_SOMETHING - if( loc->first_column > 7990 ) /* if things get out of whack, why crash? */ - loc->first_column = 7990; - if( loc->last_column > 7990 ) - loc->last_column = 7990; - for(i=0;ifirst_column;i++) spacebuf[i] = ' '; - for( ;ilast_column;i++) spacebuf[i] = '^'; - spacebuf[i] = 0; -#endif for(i=0;i< (int)(yytext - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf);i++) spacebuf2[i] = ' '; /* uh... assuming yyg is defined, then I can use the yycolumn macro, which is the same thing as... get this: yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]->yy_bs_column Index: ast_expr2.y =================================================================== --- ast_expr2.y (revision 8106) +++ ast_expr2.y (working copy) @@ -124,7 +124,12 @@ some useful info about the error. Not as easy as it looks, but it is possible. */ #define ast_yyerror(x) ast_yyerror(x,&yyloc,parseio) - +#define DESTROY(x) { \ +if ((x)->type == AST_EXPR_numeric_string || (x)->type == AST_EXPR_string) \ + free((x)->u.s); \ + (x)->u.s = 0; \ + free(x); \ +} %} %pure-parser @@ -158,69 +163,91 @@ %% start: expr { ((struct parse_io *)parseio)->val = (struct val *)calloc(sizeof(struct val),1); - ((struct parse_io *)parseio)->val->type = $$->type; - if( $$->type == AST_EXPR_integer ) - ((struct parse_io *)parseio)->val->u.i = $$->u.i; + ((struct parse_io *)parseio)->val->type = $1->type; + if( $1->type == AST_EXPR_integer ) + ((struct parse_io *)parseio)->val->u.i = $1->u.i; else - ((struct parse_io *)parseio)->val->u.s = $$->u.s; } + ((struct parse_io *)parseio)->val->u.s = $1->u.s; + free($1); + } ; expr: TOKEN { $$= $1;} | TOK_LP expr TOK_RP { $$ = $2; @$.first_column = @1.first_column; @$.last_column = @3.last_column; - @$.first_line=0; @$.last_line=0;} + @$.first_line=0; @$.last_line=0; + DESTROY($1); DESTROY($3); } | expr TOK_OR expr { $$ = op_or ($1, $3); + DESTROY($2); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;} | expr TOK_AND expr { $$ = op_and ($1, $3); + DESTROY($2); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;} | expr TOK_EQ expr { $$ = op_eq ($1, $3); + DESTROY($2); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;} | expr TOK_GT expr { $$ = op_gt ($1, $3); + DESTROY($2); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;} | expr TOK_LT expr { $$ = op_lt ($1, $3); + DESTROY($2); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;} | expr TOK_GE expr { $$ = op_ge ($1, $3); + DESTROY($2); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;} | expr TOK_LE expr { $$ = op_le ($1, $3); + DESTROY($2); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;} | expr TOK_NE expr { $$ = op_ne ($1, $3); + DESTROY($2); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;} | expr TOK_PLUS expr { $$ = op_plus ($1, $3); + DESTROY($2); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;} | expr TOK_MINUS expr { $$ = op_minus ($1, $3); + DESTROY($2); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;} | TOK_MINUS expr %prec TOK_COMPL { $$ = op_negate ($2); + DESTROY($1); @$.first_column = @1.first_column; @$.last_column = @2.last_column; @$.first_line=0; @$.last_line=0;} | TOK_COMPL expr { $$ = op_compl ($2); + DESTROY($1); @$.first_column = @1.first_column; @$.last_column = @2.last_column; @$.first_line=0; @$.last_line=0;} | expr TOK_MULT expr { $$ = op_times ($1, $3); + DESTROY($2); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;} | expr TOK_DIV expr { $$ = op_div ($1, $3); + DESTROY($2); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;} | expr TOK_MOD expr { $$ = op_rem ($1, $3); + DESTROY($2); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;} | expr TOK_COLON expr { $$ = op_colon ($1, $3); + DESTROY($2); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;} | expr TOK_EQTILDE expr { $$ = op_eqtilde ($1, $3); + DESTROY($2); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;} | expr TOK_COND expr TOK_COLONCOLON expr { $$ = op_cond ($1, $3, $5); + DESTROY($2); + DESTROY($4); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;} ; @@ -281,6 +308,7 @@ } if (vp->type == AST_EXPR_string || vp->type == AST_EXPR_numeric_string) free (vp->u.s); + free(vp); }