mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-05 20:20:07 +00:00
add conditional operator to expression parser, and various cleanups (bug #4459)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@5997 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
10
ast_expr2.fl
10
ast_expr2.fl
@@ -67,7 +67,9 @@ struct parse_io
|
|||||||
\* { SET_COLUMNS; SET_STRING; return TOK_MULT;}
|
\* { SET_COLUMNS; SET_STRING; return TOK_MULT;}
|
||||||
\/ { SET_COLUMNS; SET_STRING; return TOK_DIV;}
|
\/ { SET_COLUMNS; SET_STRING; return TOK_DIV;}
|
||||||
\% { SET_COLUMNS; SET_STRING; return TOK_MOD;}
|
\% { SET_COLUMNS; SET_STRING; return TOK_MOD;}
|
||||||
|
\? { SET_COLUMNS; SET_STRING; return TOK_COND;}
|
||||||
\: { SET_COLUMNS; SET_STRING; return TOK_COLON;}
|
\: { SET_COLUMNS; SET_STRING; return TOK_COLON;}
|
||||||
|
\:\: { SET_COLUMNS; SET_STRING; return TOK_COLONCOLON;}
|
||||||
\( { SET_COLUMNS; SET_STRING; return TOK_LP;}
|
\( { SET_COLUMNS; SET_STRING; return TOK_LP;}
|
||||||
\) { SET_COLUMNS; SET_STRING; return TOK_RP;}
|
\) { SET_COLUMNS; SET_STRING; return TOK_RP;}
|
||||||
|
|
||||||
@@ -78,7 +80,7 @@ struct parse_io
|
|||||||
[0-9]+ { SET_COLUMNS; /* the original behavior of the expression parser was to bring in numbers as a numeric string */
|
[0-9]+ { SET_COLUMNS; /* the original behavior of the expression parser was to bring in numbers as a numeric string */
|
||||||
SET_NUMERIC_STRING;
|
SET_NUMERIC_STRING;
|
||||||
return TOKEN;}
|
return TOKEN;}
|
||||||
[a-zA-Z0-9,.?';{}\\_^%$#@!]+ {SET_COLUMNS; SET_STRING; return TOKEN;}
|
[a-zA-Z0-9,.';{}\\_^%$#@!]+ {SET_COLUMNS; SET_STRING; return TOKEN;}
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
||||||
@@ -157,14 +159,16 @@ int ast_yyerror (const char *s, yyltype *loc, struct parse_io *parseio )
|
|||||||
spacebuf2[i++]='^';
|
spacebuf2[i++]='^';
|
||||||
spacebuf2[i]= 0;
|
spacebuf2[i]= 0;
|
||||||
|
|
||||||
#ifdef STANDALONE
|
#ifdef STANDALONE3
|
||||||
/* easier to read in the standalone version */
|
/* easier to read in the standalone version */
|
||||||
printf("ast_yyerror(): syntax error: %s; Input:\n%s\n%s\n",
|
printf("ast_yyerror(): syntax error: %s; Input:\n%s\n%s\n",
|
||||||
s, parseio->string,spacebuf2);
|
s, parseio->string,spacebuf2);
|
||||||
#else
|
#else
|
||||||
ast_log(LOG_WARNING,"ast_yyerror(): syntax error: %s; Input:\n%s\n%s\n",
|
ast_log(LOG_WARNING,"ast_yyerror(): syntax error: %s; Input:\n%s\n%s\n",
|
||||||
s, parseio->string,spacebuf2);
|
s, parseio->string,spacebuf2);
|
||||||
ast_log(LOG_WARNING,"If you have questions, please refer to doc/README.variables2 in the asterisk source.\n");
|
#endif
|
||||||
|
#ifndef STANDALONE
|
||||||
|
ast_log(LOG_WARNING,"If you have questions, please refer to doc/README.variables in the asterisk source.\n");
|
||||||
#endif
|
#endif
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
88
ast_expr2.y
88
ast_expr2.y
@@ -37,23 +37,24 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
# if ! defined(QUAD_MIN)
|
# if ! defined(QUAD_MIN)
|
||||||
# define QUAD_MIN (-0x7fffffffffffffffL-1)
|
# define QUAD_MIN (-0x7fffffffffffffffLL-1)
|
||||||
# endif
|
# endif
|
||||||
# if ! defined(QUAD_MAX)
|
# if ! defined(QUAD_MAX)
|
||||||
# define QUAD_MAX (0x7fffffffffffffffL)
|
# define QUAD_MAX (0x7fffffffffffffffLL)
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
#define YYPARSE_PARAM parseio
|
#define YYPARSE_PARAM parseio
|
||||||
#define YYLEX_PARAM ((struct parse_io *)parseio)->scanner
|
#define YYLEX_PARAM ((struct parse_io *)parseio)->scanner
|
||||||
#define YYERROR_VERBOSE 1
|
#define YYERROR_VERBOSE 1
|
||||||
|
|
||||||
/* #define ast_log fprintf
|
|
||||||
#define LOG_WARNING stderr */
|
|
||||||
|
|
||||||
enum valtype {
|
enum valtype {
|
||||||
AST_EXPR_integer, AST_EXPR_numeric_string, AST_EXPR_string
|
AST_EXPR_integer, AST_EXPR_numeric_string, AST_EXPR_string
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
#ifdef STANDALONE
|
||||||
|
void ast_log(int level, const char *file, int line, const char *function, const char *fmt, ...) __attribute__ ((format (printf,5,6)));
|
||||||
|
#endif
|
||||||
|
|
||||||
struct val {
|
struct val {
|
||||||
enum valtype type;
|
enum valtype type;
|
||||||
union {
|
union {
|
||||||
@@ -89,6 +90,7 @@ static struct val *op_ge __P((struct val *, struct val *));
|
|||||||
static struct val *op_gt __P((struct val *, struct val *));
|
static struct val *op_gt __P((struct val *, struct val *));
|
||||||
static struct val *op_le __P((struct val *, struct val *));
|
static struct val *op_le __P((struct val *, struct val *));
|
||||||
static struct val *op_lt __P((struct val *, struct val *));
|
static struct val *op_lt __P((struct val *, struct val *));
|
||||||
|
static struct val *op_cond __P((struct val *, struct val *, struct val *));
|
||||||
static struct val *op_minus __P((struct val *, struct val *));
|
static struct val *op_minus __P((struct val *, struct val *));
|
||||||
static struct val *op_negate __P((struct val *));
|
static struct val *op_negate __P((struct val *));
|
||||||
static struct val *op_compl __P((struct val *));
|
static struct val *op_compl __P((struct val *));
|
||||||
@@ -136,22 +138,20 @@ int ast_yyerror(const char *,YYLTYPE *, struct parse_io *);
|
|||||||
struct val *val;
|
struct val *val;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* IN_ANOTHER_LIFE
|
|
||||||
%{
|
%{
|
||||||
static int ast_yylex __P((YYSTYPE *, YYLTYPE *, yyscan_t));
|
extern int ast_yylex __P((YYSTYPE *, YYLTYPE *, yyscan_t));
|
||||||
%}
|
%}
|
||||||
*/
|
%left <val> TOK_COND TOK_COLONCOLON
|
||||||
|
|
||||||
%left <val> TOK_OR
|
%left <val> TOK_OR
|
||||||
%left <val> TOK_AND
|
%left <val> TOK_AND
|
||||||
%left <val> TOK_EQ TOK_GT TOK_LT TOK_GE TOK_LE TOK_NE
|
%left <val> TOK_EQ TOK_GT TOK_LT TOK_GE TOK_LE TOK_NE
|
||||||
%left <val> TOK_PLUS TOK_MINUS
|
%left <val> TOK_PLUS TOK_MINUS
|
||||||
%left <val> TOK_MULT TOK_DIV TOK_MOD
|
%left <val> TOK_MULT TOK_DIV TOK_MOD
|
||||||
%left <val> TOK_COMPL TOK_EQTILDE
|
%right <val> TOK_COMPL
|
||||||
%left UMINUS
|
%left <val> TOK_COLON TOK_EQTILDE
|
||||||
%left <val> TOK_COLON
|
|
||||||
%left <val> TOK_RP TOK_LP
|
%left <val> TOK_RP TOK_LP
|
||||||
|
|
||||||
|
|
||||||
%token <val> TOKEN
|
%token <val> TOKEN
|
||||||
%type <val> start expr
|
%type <val> start expr
|
||||||
|
|
||||||
@@ -172,11 +172,11 @@ expr: TOKEN { $$= $1;}
|
|||||||
| expr TOK_AND expr { $$ = op_and ($1, $3);
|
| expr TOK_AND expr { $$ = op_and ($1, $3);
|
||||||
@$.first_column = @1.first_column; @$.last_column = @3.last_column;
|
@$.first_column = @1.first_column; @$.last_column = @3.last_column;
|
||||||
@$.first_line=0; @$.last_line=0;}
|
@$.first_line=0; @$.last_line=0;}
|
||||||
| expr TOK_EQ expr { $$ = op_eq ($1, $3);
|
| expr TOK_EQ expr { $$ = op_eq ($1, $3);
|
||||||
@$.first_column = @1.first_column; @$.last_column = @3.last_column;
|
@$.first_column = @1.first_column; @$.last_column = @3.last_column;
|
||||||
@$.first_line=0; @$.last_line=0;}
|
@$.first_line=0; @$.last_line=0;}
|
||||||
| expr TOK_GT expr { $$ = op_gt ($1, $3);
|
| expr TOK_GT expr { $$ = op_gt ($1, $3);
|
||||||
@$.first_column = @1.first_column; @$.last_column = @3.last_column;
|
@$.first_column = @1.first_column; @$.last_column = @3.last_column;
|
||||||
@$.first_line=0; @$.last_line=0;}
|
@$.first_line=0; @$.last_line=0;}
|
||||||
| expr TOK_LT expr { $$ = op_lt ($1, $3);
|
| expr TOK_LT expr { $$ = op_lt ($1, $3);
|
||||||
@$.first_column = @1.first_column; @$.last_column = @3.last_column;
|
@$.first_column = @1.first_column; @$.last_column = @3.last_column;
|
||||||
@@ -196,10 +196,10 @@ expr: TOKEN { $$= $1;}
|
|||||||
| expr TOK_MINUS expr { $$ = op_minus ($1, $3);
|
| expr TOK_MINUS expr { $$ = op_minus ($1, $3);
|
||||||
@$.first_column = @1.first_column; @$.last_column = @3.last_column;
|
@$.first_column = @1.first_column; @$.last_column = @3.last_column;
|
||||||
@$.first_line=0; @$.last_line=0;}
|
@$.first_line=0; @$.last_line=0;}
|
||||||
| TOK_MINUS expr %prec UMINUS { $$ = op_negate ($2);
|
| TOK_MINUS expr %prec TOK_COMPL { $$ = op_negate ($2);
|
||||||
@$.first_column = @1.first_column; @$.last_column = @2.last_column;
|
@$.first_column = @1.first_column; @$.last_column = @2.last_column;
|
||||||
@$.first_line=0; @$.last_line=0;}
|
@$.first_line=0; @$.last_line=0;}
|
||||||
| TOK_COMPL expr %prec UMINUS { $$ = op_compl ($2);
|
| TOK_COMPL expr { $$ = op_compl ($2);
|
||||||
@$.first_column = @1.first_column; @$.last_column = @2.last_column;
|
@$.first_column = @1.first_column; @$.last_column = @2.last_column;
|
||||||
@$.first_line=0; @$.last_line=0;}
|
@$.first_line=0; @$.last_line=0;}
|
||||||
| expr TOK_MULT expr { $$ = op_times ($1, $3);
|
| expr TOK_MULT expr { $$ = op_times ($1, $3);
|
||||||
@@ -217,6 +217,9 @@ expr: TOKEN { $$= $1;}
|
|||||||
| expr TOK_EQTILDE expr { $$ = op_eqtilde ($1, $3);
|
| expr TOK_EQTILDE expr { $$ = op_eqtilde ($1, $3);
|
||||||
@$.first_column = @1.first_column; @$.last_column = @3.last_column;
|
@$.first_column = @1.first_column; @$.last_column = @3.last_column;
|
||||||
@$.first_line=0; @$.last_line=0;}
|
@$.first_line=0; @$.last_line=0;}
|
||||||
|
| expr TOK_COND expr TOK_COLONCOLON expr { $$ = op_cond ($1, $3, $5);
|
||||||
|
@$.first_column = @1.first_column; @$.last_column = @3.last_column;
|
||||||
|
@$.first_line=0; @$.last_line=0;}
|
||||||
;
|
;
|
||||||
|
|
||||||
%%
|
%%
|
||||||
@@ -282,7 +285,7 @@ static quad_t
|
|||||||
to_integer (struct val *vp)
|
to_integer (struct val *vp)
|
||||||
{
|
{
|
||||||
quad_t i;
|
quad_t i;
|
||||||
|
|
||||||
if (vp == NULL) {
|
if (vp == NULL) {
|
||||||
ast_log(LOG_WARNING,"vp==NULL in to_integer()\n");
|
ast_log(LOG_WARNING,"vp==NULL in to_integer()\n");
|
||||||
return(0);
|
return(0);
|
||||||
@@ -375,11 +378,17 @@ is_zero_or_null (struct val *vp)
|
|||||||
|
|
||||||
void ast_log(int level, const char *file, int line, const char *function, const char *fmt, ...)
|
void ast_log(int level, const char *file, int line, const char *function, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
printf("LOG: lev:%d file:%s line:%d func: %s fmt:%s\n",
|
va_list vars;
|
||||||
level, file, line, function, fmt);
|
va_start(vars,fmt);
|
||||||
|
|
||||||
|
printf("LOG: lev:%d file:%s line:%d func: %s ",
|
||||||
|
level, file, line, function);
|
||||||
|
vprintf(fmt, vars);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
va_end(vars);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int main(int argc,char **argv) {
|
int main(int argc,char **argv) {
|
||||||
char *s;
|
char *s;
|
||||||
|
|
||||||
@@ -531,6 +540,45 @@ op_le (struct val *a, struct val *b)
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct val *
|
||||||
|
op_cond (struct val *a, struct val *b, struct val *c)
|
||||||
|
{
|
||||||
|
struct val *r;
|
||||||
|
|
||||||
|
if( isstring(a) )
|
||||||
|
{
|
||||||
|
if( strlen(a->u.s) && strcmp(a->u.s, "\"\"") != 0 && strcmp(a->u.s,"0") != 0 )
|
||||||
|
{
|
||||||
|
free_value(a);
|
||||||
|
free_value(c);
|
||||||
|
r = b;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
free_value(a);
|
||||||
|
free_value(b);
|
||||||
|
r = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
(void)to_integer(a);
|
||||||
|
if( a->u.i )
|
||||||
|
{
|
||||||
|
free_value(a);
|
||||||
|
free_value(c);
|
||||||
|
r = b;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
free_value(a);
|
||||||
|
free_value(b);
|
||||||
|
r = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
static struct val *
|
static struct val *
|
||||||
op_ne (struct val *a, struct val *b)
|
op_ne (struct val *a, struct val *b)
|
||||||
{
|
{
|
||||||
|
@@ -518,6 +518,12 @@ of possible concern with "legacy" extension.conf files:
|
|||||||
** match anywhere in the string. The only diff with the ':' is that
|
** match anywhere in the string. The only diff with the ':' is that
|
||||||
** match doesn't have to be anchored to the beginning of the string.
|
** match doesn't have to be anchored to the beginning of the string.
|
||||||
|
|
||||||
|
**9. Added the conditional operator 'expr1 ? true_expr :: false_expr'
|
||||||
|
** First, all 3 exprs are evaluated, and if expr1 is false, the 'false_expr'
|
||||||
|
** is returned as the result. See above for details.
|
||||||
|
|
||||||
|
**10. Unary operators '-' and '!' were made right associative.
|
||||||
|
|
||||||
--------------------------------------------------------
|
--------------------------------------------------------
|
||||||
DEBUGGING HINTS FOR $[ ] EXPRESSIONS
|
DEBUGGING HINTS FOR $[ ] EXPRESSIONS
|
||||||
--------------------------------------------------------
|
--------------------------------------------------------
|
||||||
|
Reference in New Issue
Block a user