In regards to changes for 9508, expr2 system choking on floating point numbers, I...
authorSteve Murphy <murf@digium.com>
Thu, 5 Jul 2007 18:15:22 +0000 (18:15 +0000)
committerSteve Murphy <murf@digium.com>
Thu, 5 Jul 2007 18:15:22 +0000 (18:15 +0000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@73449 65c4cc65-6c06-0410-ace0-fbb531ad65f3

13 files changed:
UPGRADE.txt
doc/tex/channelvariables.tex
include/asterisk/ast_expr.h
main/ast_expr2.c
main/ast_expr2.fl
main/ast_expr2.h
main/ast_expr2.y
main/ast_expr2f.c
main/pbx.c
pbx/pbx_ael.c
utils/ael_main.c
utils/check_expr.c
utils/expr2.testinput

index c396e1c..f986544 100644 (file)
@@ -29,6 +29,11 @@ Core:
   Where D is a string of base-10 digits. All math is now done in "long double",
   if it is available on your compiler/architecture. This was half-way between
   a bug-fix (because the MATH func returns fp by default), and an enhancement.
+  Also, for those counting on, or needing, integer operations, a series of
+  'functions' were also added to the expr language, to allow several styles
+  of rounding/truncation, along with a set of common floating point operations,
+  like sin, cos, tan, log, pow, etc. The ability to call external functions
+  like CDR(), etc. was also added, without having to use the ${...} notation.
  
 Voicemail:
 
index 8b50d04..77fcca4 100644 (file)
@@ -207,19 +207,19 @@ with equal precedence are grouped within { } symbols.
              an empty string or zero; otherwise, returns zero.
 
      expr1 {=, >, >=, <, <=, !=} expr2
-             Return the results of integer comparison if both arguments are
-             integers; otherwise, returns the results of string comparison
+             Return the results of floating point comparison if both arguments are
+             numbers; otherwise, returns the results of string comparison
              using the locale-specific collation sequence.  The result of each
              comparison is 1 if the specified relation is true, or 0 if the
              relation is false.
 
      expr1 {+, -} expr2
-             Return the results of addition or subtraction of integer-valued
+             Return the results of addition or subtraction of floating point-valued
              arguments.
 
      expr1 {*, /, %} expr2
-             Return the results of multiplication, integer division, or
-             remainder of integer-valued arguments.
+             Return the results of multiplication, floating point division, or
+             remainder of arguments.
 
      - expr1
             Return the result of subtracting expr1 from 0.
@@ -274,7 +274,69 @@ Parentheses are used for grouping in the usual manner.
 Operator precedence is applied as one would expect in any of the C
 or C derived languages.
 
-\subsection{Examples}
+subsection{Floating Point Numbers}
+
+In 1.6 and above, we shifted the \$\[...\] expressions to be calculated
+via floating point numbers instead of integers. We use 'long double' numbers
+when possible, which provide around 16 digits of precision with 12 byte numbers. 
+
+To specify a floating point constant, the number has to have this format: D.D, where D is 
+a string of base 10 digits. So, you can say 0.10, but you can't say .10 or 20.-- we hope
+this is not an excessive restriction!
+
+Floating point numbers are turned into strings via the '%g'/'%Lg' format of the printf
+function set. This allows numbers to still 'look' like integers to those counting
+on integer behavior. If you were counting on 1/4 evaluating to 0, you need to now say
+TRUNC(1/4). For a list of all the truncation/rounding capabilities, see the next section.
+
+
+subsection{Functions}
+
+In 1.6 and above, we upgraded the $[] expressions to handle floating point numbers.
+Because of this, folks counting on integer behavior would be disrupted. To make
+the same results possible, some rounding and integer truncation functions have been
+added to the core of the Expr2 parser. Indeed, dialplan functions can be called from
+$[..] expressions without the ${...} operators. The only trouble might be in the fact that
+the arguments to these functions must be specified with a comma. If you try to call
+the MATH function, for example, and try to say 3 + MATH(7*8), the expression parser will
+evaluate 7*8 for you into 56, and the MATH function will most likely complain that its 
+input doesn't make any sense.
+
+We also provide access to most of the floating point functions in the C library. (but not all of them).
+
+While we don't expect someone to want to do Fourier analysis in the dialplan, we
+don't want to preclude it, either.
+
+Here is a list of the 'builtin' functions in Expr2. All other dialplan functions
+are available by simply calling them (read-only). In other words, you don't need to
+surround function calls in \$\[...\] expressions with \$\{...\}. Don't jump to conclusions,
+though! -- you still need to wrap variable names in curly braces!
+
+\begin{Enumerate}
+\item COS(x) x is in radians. Results vary from -1 to 1. 
+\item SIN(x) x is in radians. Results vary from -1 to 1.
+\item TAN(x) x is in radians.
+\item ACOS(x) x should be a value between -1 and 1.
+\item ASIN(x) x should be a value between -1 and 1.
+\item ATAN(x) returns the arc tangent in radians; between -PI/2 and PI/2.
+\item ATAN2(x,y) returns a result resembling y/x, except that the signs of both args are used to determine the quadrant of the result. Its result is in radians, between -PI and PI.
+\item POW(x,y) returns the value of x raised to the power of y.
+\item SQRT(x) returns the square root of x.
+\item FLOOR(x) rounds x down to the nearest integer.
+\item CEIL(x) rounds x up to the nearest integer.
+\item ROUND(x) rounds x to the nearest integer, but round halfway cases away from zero.
+\item RINT(x) rounds x to the nearest integer, rounding halfway cases to the nearest even integer.
+\item TRUNC(x) rounds x to the nearest integer not larger in absolute value.
+\item REMAINDER(x,y) computes the remainder of dividing x by y. The return value is x - n*y, where n is the value x/y, rounded to the nearest integer.
+If this quotient is 1/2, it is rounded to the nearest even number.
+\item EXP(x) returns e to the x power.
+\item EXP2(x) returns 2 to the x power.
+\item LOG(x) returns the natural logarithm of x.
+\item LOG2(x) returns the base 2 log of x.
+\item LOG10(x) returns the base 10 log of x.
+\end{Enumerate}
+
+subsection{Examples}
 
 \begin{verbatim}
  "One Thousand Five Hundred" =~ "(T[^ ]+)"
@@ -310,6 +372,55 @@ or C derived languages.
 
 (2+8)/2
        returns 5, of course.
+
+(3+8)/2
+       returns 5.5 now.
+
+TRUNC((3+8)/2)
+       returns 5.
+
+FLOOR(2.5)
+       returns 2
+
+FLOOR(-2.5)
+       returns -3
+
+CEIL(2.5)
+       returns 3.
+
+CEIL(-2.5)
+       returns -2.
+
+ROUND(2.5)
+       returns 3.
+
+ROUND(3.5)
+       returns 4.
+
+ROUND(-2.5)
+       returns -3
+
+RINT(2.5)
+       returns 2.
+
+RINT(3.5)
+       returns 4.
+
+RINT(-2.5)
+       returns -2.
+
+RINT(-3.5)
+       returns -4.
+
+TRUNC(2.5)
+       returns 2.
+
+TRUNC(3.5)
+       returns 3.
+
+TRUNC(-3.5)
+       returns -3.
+
 \begin{verbatim}
 
 Of course, all of the above examples use constants, but would work the
@@ -319,9 +430,10 @@ variable reference \${CALLERIDNUM}, for instance.
 
 \subsection{Numbers Vs. Strings}
 
-Tokens consisting only of numbers are converted to 64-bit numbers for
-most of the operators. This means that overflows can occur when the
-numbers get above 18 digits.  Warnings will appear in the logs in this
+Tokens consisting only of numbers are converted to 'long double' if possible, which
+are from 80 bits to 128 bits depending on the OS, compiler, and hardware.
+This means that overflows can occur when the
+numbers get above 18 digits (depending on the number of bits involved).  Warnings will appear in the logs in this
 case.
 
 \subsection{Conditionals}
index bc03313..6ca201f 100644 (file)
 
 #ifndef _ASTERISK_EXPR_H
 #define _ASTERISK_EXPR_H
-
+#ifndef STANDALONE
+#include "asterisk/channel.h"
+#endif
 #if defined(__cplusplus) || defined(c_plusplus)
 extern "C" {
 #endif
 
-int ast_expr(char *expr, char *buf, int length);
+int ast_expr(char *expr, char *buf, int length, struct ast_channel *chan);
 
 #if defined(__cplusplus) || defined(c_plusplus)
 }
index 1d0ee0c..2154a4d 100644 (file)
    /* Put the tokens into the symbol table, so that GDB and other debuggers
       know about them.  */
    enum yytokentype {
-     TOK_COLONCOLON = 258,
-     TOK_COND = 259,
-     TOK_OR = 260,
-     TOK_AND = 261,
-     TOK_NE = 262,
-     TOK_LE = 263,
-     TOK_GE = 264,
-     TOK_LT = 265,
-     TOK_GT = 266,
-     TOK_EQ = 267,
-     TOK_MINUS = 268,
-     TOK_PLUS = 269,
-     TOK_MOD = 270,
-     TOK_DIV = 271,
-     TOK_MULT = 272,
-     TOK_COMPL = 273,
-     TOK_EQTILDE = 274,
-     TOK_COLON = 275,
-     TOK_LP = 276,
-     TOK_RP = 277,
-     TOKEN = 278
+     TOK_COMMA = 258,
+     TOK_COLONCOLON = 259,
+     TOK_COND = 260,
+     TOK_OR = 261,
+     TOK_AND = 262,
+     TOK_NE = 263,
+     TOK_LE = 264,
+     TOK_GE = 265,
+     TOK_LT = 266,
+     TOK_GT = 267,
+     TOK_EQ = 268,
+     TOK_MINUS = 269,
+     TOK_PLUS = 270,
+     TOK_MOD = 271,
+     TOK_DIV = 272,
+     TOK_MULT = 273,
+     TOK_COMPL = 274,
+     TOK_EQTILDE = 275,
+     TOK_COLON = 276,
+     TOK_LP = 277,
+     TOK_RP = 278,
+     TOKEN = 279
    };
 #endif
 /* Tokens.  */
-#define TOK_COLONCOLON 258
-#define TOK_COND 259
-#define TOK_OR 260
-#define TOK_AND 261
-#define TOK_NE 262
-#define TOK_LE 263
-#define TOK_GE 264
-#define TOK_LT 265
-#define TOK_GT 266
-#define TOK_EQ 267
-#define TOK_MINUS 268
-#define TOK_PLUS 269
-#define TOK_MOD 270
-#define TOK_DIV 271
-#define TOK_MULT 272
-#define TOK_COMPL 273
-#define TOK_EQTILDE 274
-#define TOK_COLON 275
-#define TOK_LP 276
-#define TOK_RP 277
-#define TOKEN 278
+#define TOK_COMMA 258
+#define TOK_COLONCOLON 259
+#define TOK_COND 260
+#define TOK_OR 261
+#define TOK_AND 262
+#define TOK_NE 263
+#define TOK_LE 264
+#define TOK_GE 265
+#define TOK_LT 266
+#define TOK_GT 267
+#define TOK_EQ 268
+#define TOK_MINUS 269
+#define TOK_PLUS 270
+#define TOK_MOD 271
+#define TOK_DIV 272
+#define TOK_MULT 273
+#define TOK_COMPL 274
+#define TOK_EQTILDE 275
+#define TOK_COLON 276
+#define TOK_LP 277
+#define TOK_RP 278
+#define TOKEN 279
 
 
 
 #endif
 
 #ifdef __USE_ISOC99
-#define FP___PRINTF "%.16Lg"
+#define FP___PRINTF "%.18Lg"
 #define FP___FMOD   fmodl
 #define FP___STRTOD  strtold
 #define FP___TYPE    long double
+#define FUNC_COS     cosl
+#define FUNC_SIN     sinl
+#define FUNC_TAN     tanl
+#define FUNC_ACOS     acosl
+#define FUNC_ASIN     asinl
+#define FUNC_ATAN     atanl
+#define FUNC_ATAN2     atan2l
+#define FUNC_POW       powl
+#define FUNC_SQRT       sqrtl
+#define FUNC_FLOOR      floorl
+#define FUNC_CEIL      ceill
+#define FUNC_ROUND     roundl
+#define FUNC_RINT     rintl
+#define FUNC_TRUNC     truncl
+#define FUNC_EXP       expl
+#define FUNC_EXP2       exp2l
+#define FUNC_LOG       logl
+#define FUNC_LOG2       log2l
+#define FUNC_LOG10       log10l
+#define FUNC_REMAINDER       remainderl
 #else
-#define FP___PRINTF "%.8g"
+#define FP___PRINTF "%.16g"
 #define FP___FMOD   fmod
 #define FP___STRTOD  strtod
 #define FP___TYPE    double
+#define FUNC_COS     cos
+#define FUNC_SIN     sin
+#define FUNC_TAN     tan
+#define FUNC_ACOS     acos
+#define FUNC_ASIN     asin
+#define FUNC_ATAN     atan
+#define FUNC_ATAN2     atan2
+#define FUNC_POW       pow
+#define FUNC_SQRT       sqrt
+#define FUNC_FLOOR      floor
+#define FUNC_CEIL      ceil
+#define FUNC_ROUND     round
+#define FUNC_RINT     rint
+#define FUNC_TRUNC     trunc
+#define FUNC_EXP       exp
+#define FUNC_EXP2       exp2
+#define FUNC_LOG       log
+#define FUNC_LOG2       log2
+#define FUNC_LOG10       log10
+#define FUNC_REMAINDER       remainder
 #endif
 
 #include <stdlib.h>
 #include "asterisk.h"
 #include "asterisk/ast_expr.h"
 #include "asterisk/logger.h"
+#ifndef STANDALONE
+#include "asterisk/pbx.h"
+#endif
 
 #if defined(LONG_LONG_MIN) && !defined(QUAD_MIN)
 #define QUAD_MIN LONG_LONG_MIN
@@ -208,6 +253,19 @@ struct val {
        } u;
 } ;
 
+enum node_type {
+       AST_EXPR_NODE_COMMA, AST_EXPR_NODE_STRING, AST_EXPR_NODE_VAL
+} ;
+
+struct expr_node 
+{
+       enum node_type type;
+       struct val *val;
+       struct expr_node *left;
+       struct expr_node *right;
+};
+
+
 typedef void *yyscan_t;
 
 struct parse_io
@@ -215,6 +273,7 @@ struct parse_io
        char *string;
        struct val *val;
        yyscan_t scanner;
+       struct ast_channel *chan;
 };
  
 static int             chk_div __P((FP___TYPE, FP___TYPE));
@@ -244,8 +303,12 @@ static struct val  *op_or __P((struct val *, struct val *));
 static struct val      *op_plus __P((struct val *, struct val *));
 static struct val      *op_rem __P((struct val *, struct val *));
 static struct val      *op_times __P((struct val *, struct val *));
+static struct val   *op_func(struct val *funcname, struct expr_node *arglist, struct ast_channel *chan);
 static int             to_number __P((struct val *));
 static void            to_string __P((struct val *));
+static struct expr_node *alloc_expr_node(enum node_type);
+static void destroy_arglist(struct expr_node *arglist);
+static int is_really_num(char *str);
 
 /* uh, if I want to predeclare yylex with a YYLTYPE, I have to predeclare the yyltype... sigh */
 typedef struct yyltype
@@ -292,12 +355,13 @@ int               ast_yyerror(const char *,YYLTYPE *, struct parse_io *);
 
 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
 typedef union YYSTYPE
-#line 165 "ast_expr2.y"
+#line 226 "ast_expr2.y"
 {
        struct val *val;
+       struct expr_node *arglist;
 }
 /* Line 198 of yacc.c.  */
-#line 301 "ast_expr2.c"
+#line 365 "ast_expr2.c"
        YYSTYPE;
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
 # define YYSTYPE_IS_DECLARED 1
@@ -319,13 +383,13 @@ typedef struct YYLTYPE
 
 
 /* Copy the second part of user declarations.  */
-#line 169 "ast_expr2.y"
+#line 231 "ast_expr2.y"
 
 extern int             ast_yylex __P((YYSTYPE *, YYLTYPE *, yyscan_t));
 
 
 /* Line 221 of yacc.c.  */
-#line 329 "ast_expr2.c"
+#line 393 "ast_expr2.c"
 
 #ifdef short
 # undef short
@@ -538,22 +602,22 @@ union yyalloc
 #endif
 
 /* YYFINAL -- State number of the termination state.  */
-#define YYFINAL  10
+#define YYFINAL  11
 /* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   140
+#define YYLAST   150
 
 /* YYNTOKENS -- Number of terminals.  */
-#define YYNTOKENS  24
+#define YYNTOKENS  25
 /* YYNNTS -- Number of nonterminals.  */
-#define YYNNTS  3
+#define YYNNTS  4
 /* YYNRULES -- Number of rules.  */
-#define YYNRULES  23
+#define YYNRULES  26
 /* YYNRULES -- Number of states.  */
-#define YYNSTATES  46
+#define YYNSTATES  52
 
 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
 #define YYUNDEFTOK  2
-#define YYMAXUTOK   278
+#define YYMAXUTOK   279
 
 #define YYTRANSLATE(YYX)                                               \
   ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
@@ -588,7 +652,7 @@ static const yytype_uint8 yytranslate[] =
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
        5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
-      15,    16,    17,    18,    19,    20,    21,    22,    23
+      15,    16,    17,    18,    19,    20,    21,    22,    23,    24
 };
 
 #if YYDEBUG
@@ -596,31 +660,32 @@ static const yytype_uint8 yytranslate[] =
    YYRHS.  */
 static const yytype_uint8 yyprhs[] =
 {
-       0,     0,     3,     5,     6,     8,    12,    16,    20,    24,
-      28,    32,    36,    40,    44,    48,    52,    55,    58,    62,
-      66,    70,    74,    78
+       0,     0,     3,     5,     6,     8,    12,    17,    19,    23,
+      27,    31,    35,    39,    43,    47,    51,    55,    59,    63,
+      66,    69,    73,    77,    81,    85,    89
 };
 
 /* YYRHS -- A `-1'-separated list of the rules' RHS.  */
 static const yytype_int8 yyrhs[] =
 {
-      25,     0,    -1,    26,    -1,    -1,    23,    -1,    21,    26,
-      22,    -1,    26,     5,    26,    -1,    26,     6,    26,    -1,
-      26,    12,    26,    -1,    26,    11,    26,    -1,    26,    10,
-      26,    -1,    26,     9,    26,    -1,    26,     8,    26,    -1,
-      26,     7,    26,    -1,    26,    14,    26,    -1,    26,    13,
-      26,    -1,    13,    26,    -1,    18,    26,    -1,    26,    17,
-      26,    -1,    26,    16,    26,    -1,    26,    15,    26,    -1,
-      26,    20,    26,    -1,    26,    19,    26,    -1,    26,     4,
-      26,     3,    26,    -1
+      26,     0,    -1,    28,    -1,    -1,    28,    -1,    27,     3,
+      28,    -1,    24,    22,    27,    23,    -1,    24,    -1,    22,
+      28,    23,    -1,    28,     6,    28,    -1,    28,     7,    28,
+      -1,    28,    13,    28,    -1,    28,    12,    28,    -1,    28,
+      11,    28,    -1,    28,    10,    28,    -1,    28,     9,    28,
+      -1,    28,     8,    28,    -1,    28,    15,    28,    -1,    28,
+      14,    28,    -1,    14,    28,    -1,    19,    28,    -1,    28,
+      18,    28,    -1,    28,    17,    28,    -1,    28,    16,    28,
+      -1,    28,    21,    28,    -1,    28,    20,    28,    -1,    28,
+       5,    28,     4,    28,    -1
 };
 
 /* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
 static const yytype_uint16 yyrline[] =
 {
-       0,   193,   193,   201,   208,   209,   213,   217,   221,   225,
-     229,   233,   237,   241,   245,   249,   253,   257,   261,   265,
-     269,   273,   277,   281
+       0,   257,   257,   265,   272,   273,   282,   288,   289,   293,
+     297,   301,   305,   309,   313,   317,   321,   325,   329,   333,
+     337,   341,   345,   349,   353,   357,   361
 };
 #endif
 
@@ -629,11 +694,11 @@ static const yytype_uint16 yyrline[] =
    First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
 static const char *const yytname[] =
 {
-  "$end", "error", "$undefined", "TOK_COLONCOLON", "TOK_COND", "TOK_OR",
-  "TOK_AND", "TOK_NE", "TOK_LE", "TOK_GE", "TOK_LT", "TOK_GT", "TOK_EQ",
-  "TOK_MINUS", "TOK_PLUS", "TOK_MOD", "TOK_DIV", "TOK_MULT", "TOK_COMPL",
-  "TOK_EQTILDE", "TOK_COLON", "TOK_LP", "TOK_RP", "TOKEN", "$accept",
-  "start", "expr", 0
+  "$end", "error", "$undefined", "TOK_COMMA", "TOK_COLONCOLON",
+  "TOK_COND", "TOK_OR", "TOK_AND", "TOK_NE", "TOK_LE", "TOK_GE", "TOK_LT",
+  "TOK_GT", "TOK_EQ", "TOK_MINUS", "TOK_PLUS", "TOK_MOD", "TOK_DIV",
+  "TOK_MULT", "TOK_COMPL", "TOK_EQTILDE", "TOK_COLON", "TOK_LP", "TOK_RP",
+  "TOKEN", "$accept", "start", "arglist", "expr", 0
 };
 #endif
 
@@ -644,24 +709,24 @@ static const yytype_uint16 yytoknum[] =
 {
        0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
      265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
-     275,   276,   277,   278
+     275,   276,   277,   278,   279
 };
 # endif
 
 /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
 static const yytype_uint8 yyr1[] =
 {
-       0,    24,    25,    25,    26,    26,    26,    26,    26,    26,
-      26,    26,    26,    26,    26,    26,    26,    26,    26,    26,
-      26,    26,    26,    26
+       0,    25,    26,    26,    27,    27,    28,    28,    28,    28,
+      28,    28,    28,    28,    28,    28,    28,    28,    28,    28,
+      28,    28,    28,    28,    28,    28,    28
 };
 
 /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
 static const yytype_uint8 yyr2[] =
 {
-       0,     2,     1,     0,     1,     3,     3,     3,     3,     3,
-       3,     3,     3,     3,     3,     3,     2,     2,     3,     3,
-       3,     3,     3,     5
+       0,     2,     1,     0,     1,     3,     4,     1,     3,     3,
+       3,     3,     3,     3,     3,     3,     3,     3,     3,     2,
+       2,     3,     3,     3,     3,     3,     5
 };
 
 /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
@@ -669,35 +734,37 @@ static const yytype_uint8 yyr2[] =
    means the default is an error.  */
 static const yytype_uint8 yydefact[] =
 {
-       3,     0,     0,     0,     4,     0,     2,    16,    17,     0,
-       1,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     5,     0,     6,
-       7,    13,    12,    11,    10,     9,     8,    15,    14,    20,
-      19,    18,    22,    21,     0,    23
+       3,     0,     0,     0,     7,     0,     2,    19,    20,     0,
+       0,     1,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     8,     0,
+       4,     0,     9,    10,    16,    15,    14,    13,    12,    11,
+      18,    17,    23,    22,    21,    25,    24,     0,     6,     0,
+       5,    26
 };
 
 /* YYDEFGOTO[NTERM-NUM].  */
 static const yytype_int8 yydefgoto[] =
 {
-      -1,     5,     6
+      -1,     5,    29,     6
 };
 
 /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
    STATE-NUM.  */
-#define YYPACT_NINF -13
-static const yytype_int8 yypact[] =
-{
-     109,   109,   109,   109,   -13,     6,    59,   106,   106,    22,
-     -13,   109,   109,   109,   109,   109,   109,   109,   109,   109,
-     109,   109,   109,   109,   109,   109,   109,   -13,    42,    90,
-     104,   120,   120,   120,   120,   120,   120,   -12,   -12,   106,
-     106,   106,   -13,   -13,   109,    75
+#define YYPACT_NINF -18
+static const yytype_int16 yypact[] =
+{
+     112,   112,   112,   112,   -16,     5,    62,   -17,   -17,    24,
+     112,   -18,   112,   112,   112,   112,   112,   112,   112,   112,
+     112,   112,   112,   112,   112,   112,   112,   112,   -18,     4,
+      62,    45,    93,   107,   123,   123,   123,   123,   123,   123,
+     129,   129,   -17,   -17,   -17,   -18,   -18,   112,   -18,   112,
+      62,    78
 };
 
 /* YYPGOTO[NTERM-NUM].  */
 static const yytype_int8 yypgoto[] =
 {
-     -13,   -13,    -1
+     -18,   -18,   -18,    -1
 };
 
 /* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
@@ -707,51 +774,54 @@ static const yytype_int8 yypgoto[] =
 #define YYTABLE_NINF -1
 static const yytype_uint8 yytable[] =
 {
-       7,     8,     9,    22,    23,    24,    10,    25,    26,     0,
-      28,    29,    30,    31,    32,    33,    34,    35,    36,    37,
-      38,    39,    40,    41,    42,    43,    11,    12,    13,    14,
-      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
-       0,    25,    26,    45,    27,    44,    11,    12,    13,    14,
-      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
-       0,    25,    26,    11,    12,    13,    14,    15,    16,    17,
-      18,    19,    20,    21,    22,    23,    24,     0,    25,    26,
+       7,     8,     9,    26,    27,    11,    10,    47,     0,    30,
+       0,    31,    32,    33,    34,    35,    36,    37,    38,    39,
+      40,    41,    42,    43,    44,    45,    46,    48,     0,    12,
+      13,    14,    15,    16,    17,    18,    19,    20,    21,    22,
+      23,    24,    25,     0,    26,    27,    50,    28,    51,    49,
       12,    13,    14,    15,    16,    17,    18,    19,    20,    21,
-      22,    23,    24,     0,    25,    26,    13,    14,    15,    16,
-      17,    18,    19,    20,    21,    22,    23,    24,     0,    25,
-      26,    14,    15,    16,    17,    18,    19,    20,    21,    22,
-      23,    24,     1,    25,    26,    25,    26,     2,     0,     0,
-       3,     0,     4,    20,    21,    22,    23,    24,     0,    25,
-      26
+      22,    23,    24,    25,     0,    26,    27,    12,    13,    14,
+      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
+      25,     0,    26,    27,    13,    14,    15,    16,    17,    18,
+      19,    20,    21,    22,    23,    24,    25,     0,    26,    27,
+      14,    15,    16,    17,    18,    19,    20,    21,    22,    23,
+      24,    25,     0,    26,    27,    15,    16,    17,    18,    19,
+      20,    21,    22,    23,    24,    25,     1,    26,    27,     0,
+       0,     2,     0,     0,     3,     0,     4,    21,    22,    23,
+      24,    25,     0,    26,    27,    23,    24,    25,     0,    26,
+      27
 };
 
 static const yytype_int8 yycheck[] =
 {
-       1,     2,     3,    15,    16,    17,     0,    19,    20,    -1,
-      11,    12,    13,    14,    15,    16,    17,    18,    19,    20,
-      21,    22,    23,    24,    25,    26,     4,     5,     6,     7,
-       8,     9,    10,    11,    12,    13,    14,    15,    16,    17,
-      -1,    19,    20,    44,    22,     3,     4,     5,     6,     7,
-       8,     9,    10,    11,    12,    13,    14,    15,    16,    17,
-      -1,    19,    20,     4,     5,     6,     7,     8,     9,    10,
-      11,    12,    13,    14,    15,    16,    17,    -1,    19,    20,
+       1,     2,     3,    20,    21,     0,    22,     3,    -1,    10,
+      -1,    12,    13,    14,    15,    16,    17,    18,    19,    20,
+      21,    22,    23,    24,    25,    26,    27,    23,    -1,     5,
+       6,     7,     8,     9,    10,    11,    12,    13,    14,    15,
+      16,    17,    18,    -1,    20,    21,    47,    23,    49,     4,
        5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
-      15,    16,    17,    -1,    19,    20,     6,     7,     8,     9,
-      10,    11,    12,    13,    14,    15,    16,    17,    -1,    19,
-      20,     7,     8,     9,    10,    11,    12,    13,    14,    15,
-      16,    17,    13,    19,    20,    19,    20,    18,    -1,    -1,
-      21,    -1,    23,    13,    14,    15,    16,    17,    -1,    19,
-      20
+      15,    16,    17,    18,    -1,    20,    21,     5,     6,     7,
+       8,     9,    10,    11,    12,    13,    14,    15,    16,    17,
+      18,    -1,    20,    21,     6,     7,     8,     9,    10,    11,
+      12,    13,    14,    15,    16,    17,    18,    -1,    20,    21,
+       7,     8,     9,    10,    11,    12,    13,    14,    15,    16,
+      17,    18,    -1,    20,    21,     8,     9,    10,    11,    12,
+      13,    14,    15,    16,    17,    18,    14,    20,    21,    -1,
+      -1,    19,    -1,    -1,    22,    -1,    24,    14,    15,    16,
+      17,    18,    -1,    20,    21,    16,    17,    18,    -1,    20,
+      21
 };
 
 /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
    symbol of state STATE-NUM.  */
 static const yytype_uint8 yystos[] =
 {
-       0,    13,    18,    21,    23,    25,    26,    26,    26,    26,
-       0,     4,     5,     6,     7,     8,     9,    10,    11,    12,
-      13,    14,    15,    16,    17,    19,    20,    22,    26,    26,
-      26,    26,    26,    26,    26,    26,    26,    26,    26,    26,
-      26,    26,    26,    26,     3,    26
+       0,    14,    19,    22,    24,    26,    28,    28,    28,    28,
+      22,     0,     5,     6,     7,     8,     9,    10,    11,    12,
+      13,    14,    15,    16,    17,    18,    20,    21,    23,    27,
+      28,    28,    28,    28,    28,    28,    28,    28,    28,    28,
+      28,    28,    28,    28,    28,    28,    28,     3,    23,     4,
+      28,    28
 };
 
 #define yyerrok                (yyerrstatus = 0)
@@ -1268,115 +1338,115 @@ yydestruct (yymsg, yytype, yyvaluep, yylocationp)
 
   switch (yytype)
     {
-      case 3: /* "TOK_COLONCOLON" */
-#line 187 "ast_expr2.y"
+      case 4: /* "TOK_COLONCOLON" */
+#line 251 "ast_expr2.y"
        {  free_value((yyvaluep->val)); };
-#line 1275 "ast_expr2.c"
+#line 1345 "ast_expr2.c"
        break;
-      case 4: /* "TOK_COND" */
-#line 187 "ast_expr2.y"
+      case 5: /* "TOK_COND" */
+#line 251 "ast_expr2.y"
        {  free_value((yyvaluep->val)); };
-#line 1280 "ast_expr2.c"
+#line 1350 "ast_expr2.c"
        break;
-      case 5: /* "TOK_OR" */
-#line 187 "ast_expr2.y"
+      case 6: /* "TOK_OR" */
+#line 251 "ast_expr2.y"
        {  free_value((yyvaluep->val)); };
-#line 1285 "ast_expr2.c"
+#line 1355 "ast_expr2.c"
        break;
-      case 6: /* "TOK_AND" */
-#line 187 "ast_expr2.y"
+      case 7: /* "TOK_AND" */
+#line 251 "ast_expr2.y"
        {  free_value((yyvaluep->val)); };
-#line 1290 "ast_expr2.c"
+#line 1360 "ast_expr2.c"
        break;
-      case 7: /* "TOK_NE" */
-#line 187 "ast_expr2.y"
+      case 8: /* "TOK_NE" */
+#line 251 "ast_expr2.y"
        {  free_value((yyvaluep->val)); };
-#line 1295 "ast_expr2.c"
+#line 1365 "ast_expr2.c"
        break;
-      case 8: /* "TOK_LE" */
-#line 187 "ast_expr2.y"
+      case 9: /* "TOK_LE" */
+#line 251 "ast_expr2.y"
        {  free_value((yyvaluep->val)); };
-#line 1300 "ast_expr2.c"
+#line 1370 "ast_expr2.c"
        break;
-      case 9: /* "TOK_GE" */
-#line 187 "ast_expr2.y"
+      case 10: /* "TOK_GE" */
+#line 251 "ast_expr2.y"
        {  free_value((yyvaluep->val)); };
-#line 1305 "ast_expr2.c"
+#line 1375 "ast_expr2.c"
        break;
-      case 10: /* "TOK_LT" */
-#line 187 "ast_expr2.y"
+      case 11: /* "TOK_LT" */
+#line 251 "ast_expr2.y"
        {  free_value((yyvaluep->val)); };
-#line 1310 "ast_expr2.c"
+#line 1380 "ast_expr2.c"
        break;
-      case 11: /* "TOK_GT" */
-#line 187 "ast_expr2.y"
+      case 12: /* "TOK_GT" */
+#line 251 "ast_expr2.y"
        {  free_value((yyvaluep->val)); };
-#line 1315 "ast_expr2.c"
+#line 1385 "ast_expr2.c"
        break;
-      case 12: /* "TOK_EQ" */
-#line 187 "ast_expr2.y"
+      case 13: /* "TOK_EQ" */
+#line 251 "ast_expr2.y"
        {  free_value((yyvaluep->val)); };
-#line 1320 "ast_expr2.c"
+#line 1390 "ast_expr2.c"
        break;
-      case 13: /* "TOK_MINUS" */
-#line 187 "ast_expr2.y"
+      case 14: /* "TOK_MINUS" */
+#line 251 "ast_expr2.y"
        {  free_value((yyvaluep->val)); };
-#line 1325 "ast_expr2.c"
+#line 1395 "ast_expr2.c"
        break;
-      case 14: /* "TOK_PLUS" */
-#line 187 "ast_expr2.y"
+      case 15: /* "TOK_PLUS" */
+#line 251 "ast_expr2.y"
        {  free_value((yyvaluep->val)); };
-#line 1330 "ast_expr2.c"
+#line 1400 "ast_expr2.c"
        break;
-      case 15: /* "TOK_MOD" */
-#line 187 "ast_expr2.y"
+      case 16: /* "TOK_MOD" */
+#line 251 "ast_expr2.y"
        {  free_value((yyvaluep->val)); };
-#line 1335 "ast_expr2.c"
+#line 1405 "ast_expr2.c"
        break;
-      case 16: /* "TOK_DIV" */
-#line 187 "ast_expr2.y"
+      case 17: /* "TOK_DIV" */
+#line 251 "ast_expr2.y"
        {  free_value((yyvaluep->val)); };
-#line 1340 "ast_expr2.c"
+#line 1410 "ast_expr2.c"
        break;
-      case 17: /* "TOK_MULT" */
-#line 187 "ast_expr2.y"
+      case 18: /* "TOK_MULT" */
+#line 251 "ast_expr2.y"
        {  free_value((yyvaluep->val)); };
-#line 1345 "ast_expr2.c"
+#line 1415 "ast_expr2.c"
        break;
-      case 18: /* "TOK_COMPL" */
-#line 187 "ast_expr2.y"
+      case 19: /* "TOK_COMPL" */
+#line 251 "ast_expr2.y"
        {  free_value((yyvaluep->val)); };
-#line 1350 "ast_expr2.c"
+#line 1420 "ast_expr2.c"
        break;
-      case 19: /* "TOK_EQTILDE" */
-#line 187 "ast_expr2.y"
+      case 20: /* "TOK_EQTILDE" */
+#line 251 "ast_expr2.y"
        {  free_value((yyvaluep->val)); };
-#line 1355 "ast_expr2.c"
+#line 1425 "ast_expr2.c"
        break;
-      case 20: /* "TOK_COLON" */
-#line 187 "ast_expr2.y"
+      case 21: /* "TOK_COLON" */
+#line 251 "ast_expr2.y"
        {  free_value((yyvaluep->val)); };
-#line 1360 "ast_expr2.c"
+#line 1430 "ast_expr2.c"
        break;
-      case 21: /* "TOK_LP" */
-#line 187 "ast_expr2.y"
+      case 22: /* "TOK_LP" */
+#line 251 "ast_expr2.y"
        {  free_value((yyvaluep->val)); };
-#line 1365 "ast_expr2.c"
+#line 1435 "ast_expr2.c"
        break;
-      case 22: /* "TOK_RP" */
-#line 187 "ast_expr2.y"
+      case 23: /* "TOK_RP" */
+#line 251 "ast_expr2.y"
        {  free_value((yyvaluep->val)); };
-#line 1370 "ast_expr2.c"
+#line 1440 "ast_expr2.c"
        break;
-      case 23: /* "TOKEN" */
-#line 187 "ast_expr2.y"
+      case 24: /* "TOKEN" */
+#line 251 "ast_expr2.y"
        {  free_value((yyvaluep->val)); };
-#line 1375 "ast_expr2.c"
+#line 1445 "ast_expr2.c"
        break;
-      case 26: /* "expr" */
-#line 187 "ast_expr2.y"
+      case 28: /* "expr" */
+#line 251 "ast_expr2.y"
        {  free_value((yyvaluep->val)); };
-#line 1380 "ast_expr2.c"
+#line 1450 "ast_expr2.c"
        break;
 
       default:
@@ -1699,7 +1769,7 @@ yyreduce:
   switch (yyn)
     {
         case 2:
-#line 193 "ast_expr2.y"
+#line 257 "ast_expr2.y"
     { ((struct parse_io *)parseio)->val = (struct val *)calloc(sizeof(struct val),1);
               ((struct parse_io *)parseio)->val->type = (yyvsp[(1) - (1)].val)->type;
               if( (yyvsp[(1) - (1)].val)->type == AST_EXPR_number )
@@ -1711,7 +1781,7 @@ yyreduce:
     break;
 
   case 3:
-#line 201 "ast_expr2.y"
+#line 265 "ast_expr2.y"
     {/* nothing */ ((struct parse_io *)parseio)->val = (struct val *)calloc(sizeof(struct val),1);
               ((struct parse_io *)parseio)->val->type = AST_EXPR_string;
                          ((struct parse_io *)parseio)->val->u.s = strdup(""); 
@@ -1719,156 +1789,181 @@ yyreduce:
     break;
 
   case 4:
-#line 208 "ast_expr2.y"
-    { (yyval.val)= (yyvsp[(1) - (1)].val);;}
+#line 272 "ast_expr2.y"
+    { (yyval.arglist) = alloc_expr_node(AST_EXPR_NODE_VAL); (yyval.arglist)->val = (yyvsp[(1) - (1)].val);;}
     break;
 
   case 5:
-#line 209 "ast_expr2.y"
-    { (yyval.val) = (yyvsp[(2) - (3)].val); 
+#line 273 "ast_expr2.y"
+    {struct expr_node *x = alloc_expr_node(AST_EXPR_NODE_VAL);
+                                 struct expr_node *t;
+                                                                DESTROY((yyvsp[(2) - (3)].val));
+                                 for (t=(yyvsp[(1) - (3)].arglist);t->right;t=t->right)
+                                                                 ;
+                                 (yyval.arglist) = (yyvsp[(1) - (3)].arglist); t->right = x; x->val = (yyvsp[(3) - (3)].val);;}
+    break;
+
+  case 6:
+#line 282 "ast_expr2.y"
+    { (yyval.val) = op_func((yyvsp[(1) - (4)].val),(yyvsp[(3) - (4)].arglist), ((struct parse_io *)parseio)->chan);
+                                           DESTROY((yyvsp[(2) - (4)].val));
+                                                                       DESTROY((yyvsp[(4) - (4)].val));
+                                                                       DESTROY((yyvsp[(1) - (4)].val));
+                                                                       destroy_arglist((yyvsp[(3) - (4)].arglist));
+                                  ;}
+    break;
+
+  case 7:
+#line 288 "ast_expr2.y"
+    {(yyval.val) = (yyvsp[(1) - (1)].val);;}
+    break;
+
+  case 8:
+#line 289 "ast_expr2.y"
+    { (yyval.val) = (yyvsp[(2) - (3)].val);
                               (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column; 
                                                   (yyloc).first_line=0; (yyloc).last_line=0;
                                                        DESTROY((yyvsp[(1) - (3)].val)); DESTROY((yyvsp[(3) - (3)].val)); ;}
     break;
 
-  case 6:
-#line 213 "ast_expr2.y"
+  case 9:
+#line 293 "ast_expr2.y"
     { (yyval.val) = op_or ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val));
                                                DESTROY((yyvsp[(2) - (3)].val));        
                          (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column; 
                                                 (yyloc).first_line=0; (yyloc).last_line=0;;}
     break;
 
-  case 7:
-#line 217 "ast_expr2.y"
+  case 10:
+#line 297 "ast_expr2.y"
     { (yyval.val) = op_and ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val)); 
                                                DESTROY((yyvsp[(2) - (3)].val));        
                              (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column; 
                           (yyloc).first_line=0; (yyloc).last_line=0;;}
     break;
 
-  case 8:
-#line 221 "ast_expr2.y"
+  case 11:
+#line 301 "ast_expr2.y"
     { (yyval.val) = op_eq ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val));
                                                DESTROY((yyvsp[(2) - (3)].val));        
                             (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column;
                                                 (yyloc).first_line=0; (yyloc).last_line=0;;}
     break;
 
-  case 9:
-#line 225 "ast_expr2.y"
+  case 12:
+#line 305 "ast_expr2.y"
     { (yyval.val) = op_gt ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val));
                                                DESTROY((yyvsp[(2) - (3)].val));        
                          (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column;
                                                 (yyloc).first_line=0; (yyloc).last_line=0;;}
     break;
 
-  case 10:
-#line 229 "ast_expr2.y"
+  case 13:
+#line 309 "ast_expr2.y"
     { (yyval.val) = op_lt ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val)); 
                                                DESTROY((yyvsp[(2) - (3)].val));        
                             (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column; 
                                                 (yyloc).first_line=0; (yyloc).last_line=0;;}
     break;
 
-  case 11:
-#line 233 "ast_expr2.y"
+  case 14:
+#line 313 "ast_expr2.y"
     { (yyval.val) = op_ge ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val)); 
                                                DESTROY((yyvsp[(2) - (3)].val));        
                              (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column; 
                                                  (yyloc).first_line=0; (yyloc).last_line=0;;}
     break;
 
-  case 12:
-#line 237 "ast_expr2.y"
+  case 15:
+#line 317 "ast_expr2.y"
     { (yyval.val) = op_le ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val)); 
                                                DESTROY((yyvsp[(2) - (3)].val));        
                              (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column; 
                                                  (yyloc).first_line=0; (yyloc).last_line=0;;}
     break;
 
-  case 13:
-#line 241 "ast_expr2.y"
+  case 16:
+#line 321 "ast_expr2.y"
     { (yyval.val) = op_ne ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val)); 
                                                DESTROY((yyvsp[(2) - (3)].val));        
                              (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column; 
                                                  (yyloc).first_line=0; (yyloc).last_line=0;;}
     break;
 
-  case 14:
-#line 245 "ast_expr2.y"
+  case 17:
+#line 325 "ast_expr2.y"
     { (yyval.val) = op_plus ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val)); 
                                                DESTROY((yyvsp[(2) - (3)].val));        
                               (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column; 
                                                   (yyloc).first_line=0; (yyloc).last_line=0;;}
     break;
 
-  case 15:
-#line 249 "ast_expr2.y"
+  case 18:
+#line 329 "ast_expr2.y"
     { (yyval.val) = op_minus ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val)); 
                                                DESTROY((yyvsp[(2) - (3)].val));        
                                (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column; 
                                                        (yyloc).first_line=0; (yyloc).last_line=0;;}
     break;
 
-  case 16:
-#line 253 "ast_expr2.y"
+  case 19:
+#line 333 "ast_expr2.y"
     { (yyval.val) = op_negate ((yyvsp[(2) - (2)].val)); 
                                                DESTROY((yyvsp[(1) - (2)].val));        
                                (yyloc).first_column = (yylsp[(1) - (2)]).first_column; (yyloc).last_column = (yylsp[(2) - (2)]).last_column; 
                                                        (yyloc).first_line=0; (yyloc).last_line=0;;}
     break;
 
-  case 17:
-#line 257 "ast_expr2.y"
+  case 20:
+#line 337 "ast_expr2.y"
     { (yyval.val) = op_compl ((yyvsp[(2) - (2)].val)); 
                                                DESTROY((yyvsp[(1) - (2)].val));        
                                (yyloc).first_column = (yylsp[(1) - (2)]).first_column; (yyloc).last_column = (yylsp[(2) - (2)]).last_column; 
                                                        (yyloc).first_line=0; (yyloc).last_line=0;;}
     break;
 
-  case 18:
-#line 261 "ast_expr2.y"
+  case 21:
+#line 341 "ast_expr2.y"
     { (yyval.val) = op_times ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val)); 
                                                DESTROY((yyvsp[(2) - (3)].val));        
                               (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column; 
                                                   (yyloc).first_line=0; (yyloc).last_line=0;;}
     break;
 
-  case 19:
-#line 265 "ast_expr2.y"
+  case 22:
+#line 345 "ast_expr2.y"
     { (yyval.val) = op_div ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val)); 
                                                DESTROY((yyvsp[(2) - (3)].val));        
                              (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column; 
                                                  (yyloc).first_line=0; (yyloc).last_line=0;;}
     break;
 
-  case 20:
-#line 269 "ast_expr2.y"
+  case 23:
+#line 349 "ast_expr2.y"
     { (yyval.val) = op_rem ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val)); 
                                                DESTROY((yyvsp[(2) - (3)].val));        
                              (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column; 
                                                  (yyloc).first_line=0; (yyloc).last_line=0;;}
     break;
 
-  case 21:
-#line 273 "ast_expr2.y"
+  case 24:
+#line 353 "ast_expr2.y"
     { (yyval.val) = op_colon ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val)); 
                                                DESTROY((yyvsp[(2) - (3)].val));        
                                (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column; 
                                                        (yyloc).first_line=0; (yyloc).last_line=0;;}
     break;
 
-  case 22:
-#line 277 "ast_expr2.y"
+  case 25:
+#line 357 "ast_expr2.y"
     { (yyval.val) = op_eqtilde ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val)); 
                                                DESTROY((yyvsp[(2) - (3)].val));        
                                (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column; 
                                                        (yyloc).first_line=0; (yyloc).last_line=0;;}
     break;
 
-  case 23:
-#line 281 "ast_expr2.y"
+  case 26:
+#line 361 "ast_expr2.y"
     { (yyval.val) = op_cond ((yyvsp[(1) - (5)].val), (yyvsp[(3) - (5)].val), (yyvsp[(5) - (5)].val)); 
                                                DESTROY((yyvsp[(2) - (5)].val));        
                                                DESTROY((yyvsp[(4) - (5)].val));        
@@ -1878,7 +1973,7 @@ yyreduce:
 
 
 /* Line 1270 of yacc.c.  */
-#line 1882 "ast_expr2.c"
+#line 1977 "ast_expr2.c"
       default: break;
     }
   YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
@@ -2097,7 +2192,20 @@ yyreturn:
 }
 
 
-#line 288 "ast_expr2.y"
+#line 368 "ast_expr2.y"
+
+
+static struct expr_node *alloc_expr_node(enum node_type nt)
+{
+       struct expr_node *x = calloc(1,sizeof(struct expr_node));
+       if (!x) {
+               ast_log(LOG_ERROR, "Allocation for expr_node FAILED!!\n");
+               return 0;
+       }
+       x->type = nt;
+       return x;
+}
+
 
 
 static struct val *
@@ -2288,7 +2396,7 @@ int main(int argc,char **argv) {
                        if( s[strlen(s)-1] == '\n' )
                                s[strlen(s)-1] = 0;
                        
-                       ret = ast_expr(s, out, sizeof(out));
+                       ret = ast_expr(s, out, sizeof(out),NULL);
                        printf("Expression: %s    Result: [%d] '%s'\n",
                                   s, ret, out);
                }
@@ -2296,7 +2404,7 @@ int main(int argc,char **argv) {
        }
        else
        {
-               if (ast_expr(argv[1], s, sizeof(s)))
+               if (ast_expr(argv[1], s, sizeof(s), NULL))
                        printf("=====%s======\n",s);
                else
                        printf("No result\n");
@@ -2313,6 +2421,304 @@ int main(int argc,char **argv) {
    let it access the BUFFER stuff there and not trying
    define all the structs, macros etc. in this file! */
 
+static void destroy_arglist(struct expr_node *arglist)
+{
+       struct expr_node *arglist_next;
+       
+       while (arglist)
+       {
+               arglist_next = arglist->right;
+               if (arglist->val)
+                       free_value(arglist->val);
+               arglist->val = 0;
+               arglist->right = 0;
+               free(arglist);
+               arglist = arglist_next;
+       }
+}
+
+static char *compose_func_args(struct expr_node *arglist)
+{
+       struct expr_node *t = arglist;
+       char *argbuf;
+       int total_len = 0;
+       
+       while (t) {
+               if (t != arglist)
+                       total_len += 1; /* for the sep */
+               if (t->val) {
+                       if (t->val->type == AST_EXPR_number)
+                               total_len += 25; /* worst case */
+                       else
+                               total_len += strlen(t->val->u.s);
+               }
+               
+               t = t->right;
+       }
+       total_len++; /* for the null */
+       ast_log(LOG_NOTICE,"argbuf allocated %d bytes;\n", total_len);
+       argbuf = malloc(total_len);
+       argbuf[0] = 0;
+       t = arglist;
+       while (t) {
+               char numbuf[30];
+               
+               if (t != arglist)
+                       strcat(argbuf,"|");
+               
+               if (t->val) {
+                       if (t->val->type == AST_EXPR_number) {
+                               sprintf(numbuf,FP___PRINTF,t->val->u.i);
+                               strcat(argbuf,numbuf);
+                       } else
+                               strcat(argbuf,t->val->u.s);
+               }
+               t = t->right;
+       }
+       ast_log(LOG_NOTICE,"argbuf uses %d bytes;\n", strlen(argbuf));
+       return argbuf;
+}
+
+static int is_really_num(char *str)
+{
+       if ( strspn(str,"-0123456789.   ") == strlen(str))
+               return 1;
+       else
+               return 0;
+}
+
+
+static struct val *op_func(struct val *funcname, struct expr_node *arglist, struct ast_channel *chan)
+{
+       if (strspn(funcname->u.s,"ABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789") == strlen(funcname->u.s))
+       {
+               struct val *result;
+               
+               if (strcmp(funcname->u.s,"COS") == 0) {
+                       if (arglist && !arglist->right && arglist->val){
+                               to_number(arglist->val);
+                               result = make_number(FUNC_COS(arglist->val->u.i));
+                               return result;
+                       } else {
+                               ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
+                               return make_number(0.0);
+                       }
+               } else if (strcmp(funcname->u.s,"SIN") == 0) {
+                       if (arglist && !arglist->right && arglist->val){
+                               to_number(arglist->val);
+                               result = make_number(FUNC_SIN(arglist->val->u.i));
+                               return result;
+                       } else {
+                               ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
+                               return make_number(0.0);
+                       }
+               } else if (strcmp(funcname->u.s,"TAN") == 0) {
+                       if (arglist && !arglist->right && arglist->val){
+                               to_number(arglist->val);
+                               result = make_number(FUNC_TAN(arglist->val->u.i));
+                               return result;
+                       } else {
+                               ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
+                               return make_number(0.0);
+                       }
+               } else if (strcmp(funcname->u.s,"ACOS") == 0) {
+                       if (arglist && !arglist->right && arglist->val){
+                               to_number(arglist->val);
+                               result = make_number(FUNC_ACOS(arglist->val->u.i));
+                               return result;
+                       } else {
+                               ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
+                               return make_number(0.0);
+                       }
+               } else if (strcmp(funcname->u.s,"ASIN") == 0) {
+                       if (arglist && !arglist->right && arglist->val){
+                               to_number(arglist->val);
+                               result = make_number(FUNC_ASIN(arglist->val->u.i));
+                               return result;
+                       } else {
+                               ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
+                               return make_number(0.0);
+                       }
+               } else if (strcmp(funcname->u.s,"ATAN") == 0) {
+                       if (arglist && !arglist->right && arglist->val){
+                               to_number(arglist->val);
+                               result = make_number(FUNC_ATAN(arglist->val->u.i));
+                               return result;
+                       } else {
+                               ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
+                               return make_number(0.0);
+                       }
+               } else if (strcmp(funcname->u.s,"ATAN2") == 0) {
+                       if (arglist && arglist->right && !arglist->right->right && arglist->val && arglist->right->val){
+                               to_number(arglist->val);
+                               to_number(arglist->right->val);
+                               result = make_number(FUNC_ATAN2(arglist->val->u.i, arglist->right->val->u.i));
+                               return result;
+                       } else {
+                               ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
+                               return make_number(0.0);
+                       }
+               } else if (strcmp(funcname->u.s,"POW") == 0) {
+                       if (arglist && arglist->right && !arglist->right->right && arglist->val && arglist->right->val){
+                               to_number(arglist->val);
+                               to_number(arglist->right->val);
+                               result = make_number(FUNC_POW(arglist->val->u.i, arglist->right->val->u.i));
+                               return result;
+                       } else {
+                               ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
+                               return make_number(0.0);
+                       }
+               } else if (strcmp(funcname->u.s,"SQRT") == 0) {
+                       if (arglist && !arglist->right && arglist->val){
+                               to_number(arglist->val);
+                               result = make_number(FUNC_SQRT(arglist->val->u.i));
+                               return result;
+                       } else {
+                               ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
+                               return make_number(0.0);
+                       }
+               } else if (strcmp(funcname->u.s,"FLOOR") == 0) {
+                       if (arglist && !arglist->right && arglist->val){
+                               to_number(arglist->val);
+                               result = make_number(FUNC_FLOOR(arglist->val->u.i));
+                               return result;
+                       } else {
+                               ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
+                               return make_number(0.0);
+                       }
+               } else if (strcmp(funcname->u.s,"CEIL") == 0) {
+                       if (arglist && !arglist->right && arglist->val){
+                               to_number(arglist->val);
+                               result = make_number(FUNC_CEIL(arglist->val->u.i));
+                               return result;
+                       } else {
+                               ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
+                               return make_number(0.0);
+                       }
+               } else if (strcmp(funcname->u.s,"ROUND") == 0) {
+                       if (arglist && !arglist->right && arglist->val){
+                               to_number(arglist->val);
+                               result = make_number(FUNC_ROUND(arglist->val->u.i));
+                               return result;
+                       } else {
+                               ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
+                               return make_number(0.0);
+                       }
+               } else if (strcmp(funcname->u.s,"RINT") == 0) {
+                       if (arglist && !arglist->right && arglist->val){
+                               to_number(arglist->val);
+                               result = make_number(FUNC_RINT(arglist->val->u.i));
+                               return result;
+                       } else {
+                               ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
+                               return make_number(0.0);
+                       }
+               } else if (strcmp(funcname->u.s,"TRUNC") == 0) {
+                       if (arglist && !arglist->right && arglist->val){
+                               to_number(arglist->val);
+                               result = make_number(FUNC_TRUNC(arglist->val->u.i));
+                               return result;
+                       } else {
+                               ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
+                               return make_number(0.0);
+                       }
+               } else if (strcmp(funcname->u.s,"EXP") == 0) {
+                       if (arglist && !arglist->right && arglist->val){
+                               to_number(arglist->val);
+                               result = make_number(FUNC_EXP(arglist->val->u.i));
+                               return result;
+                       } else {
+                               ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
+                               return make_number(0.0);
+                       }
+               } else if (strcmp(funcname->u.s,"EXP2") == 0) {
+                       if (arglist && !arglist->right && arglist->val){
+                               to_number(arglist->val);
+                               result = make_number(FUNC_EXP2(arglist->val->u.i));
+                               return result;
+                       } else {
+                               ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
+                               return make_number(0.0);
+                       }
+               } else if (strcmp(funcname->u.s,"LOG") == 0) {
+                       if (arglist && !arglist->right && arglist->val){
+                               to_number(arglist->val);
+                               result = make_number(FUNC_LOG(arglist->val->u.i));
+                               return result;
+                       } else {
+                               ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
+                               return make_number(0.0);
+                       }
+               } else if (strcmp(funcname->u.s,"LOG2") == 0) {
+                       if (arglist && !arglist->right && arglist->val){
+                               to_number(arglist->val);
+                               result = make_number(FUNC_LOG2(arglist->val->u.i));
+                               return result;
+                       } else {
+                               ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
+                               return make_number(0.0);
+                       }
+               } else if (strcmp(funcname->u.s,"LOG10") == 0) {
+                       if (arglist && !arglist->right && arglist->val){
+                               to_number(arglist->val);
+                               result = make_number(FUNC_LOG10(arglist->val->u.i));
+                               return result;
+                       } else {
+                               ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
+                               return make_number(0.0);
+                       }
+               } else if (strcmp(funcname->u.s,"REMAINDER") == 0) {
+                       if (arglist && arglist->right && !arglist->right->right && arglist->val && arglist->right->val){
+                               to_number(arglist->val);
+                               to_number(arglist->right->val);
+                               result = make_number(FUNC_REMAINDER(arglist->val->u.i, arglist->right->val->u.i));
+                               return result;
+                       } else {
+                               ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
+                               return make_number(0.0);
+                       }
+               } else {
+                       /* is this a custom function we should execute and collect the results of? */
+#ifndef STANDALONE
+                       struct ast_custom_function *f = ast_custom_function_find(funcname->u.s);
+                       if (!chan)
+                               ast_log(LOG_WARNING,"Hey! chan is NULL.\n");
+                       if (!f)
+                               ast_log(LOG_WARNING,"Hey! could not find func %s.\n", funcname->u.s);
+                       
+                       if (f && chan) {
+                               if (f->read) {
+                                       char workspace[512];
+                                       char *argbuf = compose_func_args(arglist);
+                                       f->read(chan, funcname->u.s, argbuf, workspace, sizeof(workspace));
+                                       free(argbuf);
+                                       if (is_really_num(workspace))
+                                               return make_number(FP___STRTOD(workspace,(char **)NULL));
+                                       else
+                                               return make_str(workspace);
+                               } else {
+                                       ast_log(LOG_ERROR,"Error! Function '%s' cannot be read!\n", funcname->u.s);
+                                       return (make_number ((FP___TYPE)0.0));
+                               }
+                               
+                       } else {
+                               ast_log(LOG_ERROR,"Error! '%s' doesn't appear to be an available function!", funcname->u.s);
+                               return (make_number ((FP___TYPE)0.0));
+                       }
+#else
+                       ast_log(LOG_ERROR,"Error! '%s' is not available in the standalone version!", funcname->u.s);
+                       return (make_number ((FP___TYPE)0.0));
+#endif
+               }
+       }
+       else
+       {
+               ast_log(LOG_ERROR,"Error! '%s' is not possibly a function name!", funcname->u.s);
+               return (make_number ((FP___TYPE)0.0));
+       }
+       return (make_number ((FP___TYPE)0.0));
+}
+
 
 static struct val *
 op_or (struct val *a, struct val *b)
@@ -2332,7 +2738,7 @@ op_and (struct val *a, struct val *b)
        if (is_zero_or_null (a) || is_zero_or_null (b)) {
                free_value (a);
                free_value (b);
-               return (make_number ((double)0.0));
+               return (make_number ((FP___TYPE)0.0));
        } else {
                free_value (b);
                return (a);
index 49c051b..7252053 100644 (file)
@@ -36,12 +36,12 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #endif
 
 #ifdef __USE_ISOC99
-#define FP___PRINTF "%.16Lg"
+#define FP___PRINTF "%.18Lg"
 #define FP___FMOD   fmodl
 #define FP___STRTOD  strtold
 #define FP___TYPE    long double
 #else
-#define FP___PRINTF "%.8g"
+#define FP___PRINTF "%.16g"
 #define FP___FMOD   fmod
 #define FP___STRTOD  strtod
 #define FP___TYPE    double
@@ -62,7 +62,10 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
 #include "asterisk/ast_expr.h"
 #include "asterisk/logger.h"
+#ifndef STANDALONE
 #include "asterisk/strings.h"
+#include "asterisk/channel.h"
+#endif
 
 enum valtype {
        AST_EXPR_number, AST_EXPR_numeric_string, AST_EXPR_string
@@ -101,6 +104,7 @@ struct parse_io
        char *string;
        struct val *val;
        yyscan_t scanner;
+       struct ast_channel *chan;
 };
  
 void ast_yyset_column(int column_no, yyscan_t yyscanner);
@@ -133,6 +137,7 @@ static char *expr2_token_subst(char *mess);
 \<\=   { SET_COLUMNS; SET_STRING; return TOK_LE;}
 \!\=   { SET_COLUMNS; SET_STRING; return TOK_NE;}
 \+     { SET_COLUMNS; SET_STRING; return TOK_PLUS;}
+\,     { SET_COLUMNS; SET_STRING; return TOK_COMMA;}
 \-     { SET_COLUMNS; SET_STRING; return TOK_MINUS;}
 \*     { SET_COLUMNS; SET_STRING; return TOK_MULT;}
 \/     { SET_COLUMNS; SET_STRING; return TOK_DIV;}
@@ -166,7 +171,7 @@ static char *expr2_token_subst(char *mess);
                return TOKEN;
        }
 
-[a-zA-Z0-9,.';\\_^$#@]+        {
+[a-zA-Z0-9\.';\\_^$#@]+        {
                SET_COLUMNS;
                SET_STRING;
                return TOKEN;
@@ -230,13 +235,14 @@ static char *expr2_token_subst(char *mess);
 int ast_yyparse(void *); /* need to/should define this prototype for the call to yyparse */
 int ast_yyerror(const char *, YYLTYPE *, struct parse_io *); /* likewise */
 
-int ast_expr(char *expr, char *buf, int length)
+int ast_expr(char *expr, char *buf, int length, struct ast_channel *chan)
 {
        struct parse_io io;
        int return_value = 0;
        
        memset(&io, 0, sizeof(io));
        io.string = expr;  /* to pass to the error routine */
+       io.chan = chan;
        
        ast_yylex_init(&io.scanner);
        
@@ -310,6 +316,7 @@ static char *expr2_token_equivs1[] =
        "TOK_COMPL",
        "TOK_COLON",
        "TOK_EQTILDE",
+       "TOK_COMMA",
        "TOK_RP",
        "TOK_LP"
 };
@@ -335,6 +342,7 @@ static char *expr2_token_equivs2[] =
        "!",
        ":",
        "=~",
+       ",",
        ")",
        "("
 };
index 4bff4d8..517402c 100644 (file)
    /* Put the tokens into the symbol table, so that GDB and other debuggers
       know about them.  */
    enum yytokentype {
-     TOK_COLONCOLON = 258,
-     TOK_COND = 259,
-     TOK_OR = 260,
-     TOK_AND = 261,
-     TOK_NE = 262,
-     TOK_LE = 263,
-     TOK_GE = 264,
-     TOK_LT = 265,
-     TOK_GT = 266,
-     TOK_EQ = 267,
-     TOK_MINUS = 268,
-     TOK_PLUS = 269,
-     TOK_MOD = 270,
-     TOK_DIV = 271,
-     TOK_MULT = 272,
-     TOK_COMPL = 273,
-     TOK_EQTILDE = 274,
-     TOK_COLON = 275,
-     TOK_LP = 276,
-     TOK_RP = 277,
-     TOKEN = 278
+     TOK_COMMA = 258,
+     TOK_COLONCOLON = 259,
+     TOK_COND = 260,
+     TOK_OR = 261,
+     TOK_AND = 262,
+     TOK_NE = 263,
+     TOK_LE = 264,
+     TOK_GE = 265,
+     TOK_LT = 266,
+     TOK_GT = 267,
+     TOK_EQ = 268,
+     TOK_MINUS = 269,
+     TOK_PLUS = 270,
+     TOK_MOD = 271,
+     TOK_DIV = 272,
+     TOK_MULT = 273,
+     TOK_COMPL = 274,
+     TOK_EQTILDE = 275,
+     TOK_COLON = 276,
+     TOK_LP = 277,
+     TOK_RP = 278,
+     TOKEN = 279
    };
 #endif
 /* Tokens.  */
-#define TOK_COLONCOLON 258
-#define TOK_COND 259
-#define TOK_OR 260
-#define TOK_AND 261
-#define TOK_NE 262
-#define TOK_LE 263
-#define TOK_GE 264
-#define TOK_LT 265
-#define TOK_GT 266
-#define TOK_EQ 267
-#define TOK_MINUS 268
-#define TOK_PLUS 269
-#define TOK_MOD 270
-#define TOK_DIV 271
-#define TOK_MULT 272
-#define TOK_COMPL 273
-#define TOK_EQTILDE 274
-#define TOK_COLON 275
-#define TOK_LP 276
-#define TOK_RP 277
-#define TOKEN 278
+#define TOK_COMMA 258
+#define TOK_COLONCOLON 259
+#define TOK_COND 260
+#define TOK_OR 261
+#define TOK_AND 262
+#define TOK_NE 263
+#define TOK_LE 264
+#define TOK_GE 265
+#define TOK_LT 266
+#define TOK_GT 267
+#define TOK_EQ 268
+#define TOK_MINUS 269
+#define TOK_PLUS 270
+#define TOK_MOD 271
+#define TOK_DIV 272
+#define TOK_MULT 273
+#define TOK_COMPL 274
+#define TOK_EQTILDE 275
+#define TOK_COLON 276
+#define TOK_LP 277
+#define TOK_RP 278
+#define TOKEN 279
 
 
 
 
 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
 typedef union YYSTYPE
-#line 165 "ast_expr2.y"
+#line 226 "ast_expr2.y"
 {
        struct val *val;
+       struct expr_node *arglist;
 }
 /* Line 1536 of yacc.c.  */
-#line 89 "ast_expr2.h"
+#line 92 "ast_expr2.h"
        YYSTYPE;
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
 # define YYSTYPE_IS_DECLARED 1
index 8b43223..d6c5e8e 100644 (file)
 #endif
 
 #ifdef __USE_ISOC99
-#define FP___PRINTF "%.16Lg"
+#define FP___PRINTF "%.18Lg"
 #define FP___FMOD   fmodl
 #define FP___STRTOD  strtold
 #define FP___TYPE    long double
+#define FUNC_COS     cosl
+#define FUNC_SIN     sinl
+#define FUNC_TAN     tanl
+#define FUNC_ACOS     acosl
+#define FUNC_ASIN     asinl
+#define FUNC_ATAN     atanl
+#define FUNC_ATAN2     atan2l
+#define FUNC_POW       powl
+#define FUNC_SQRT       sqrtl
+#define FUNC_FLOOR      floorl
+#define FUNC_CEIL      ceill
+#define FUNC_ROUND     roundl
+#define FUNC_RINT     rintl
+#define FUNC_TRUNC     truncl
+#define FUNC_EXP       expl
+#define FUNC_EXP2       exp2l
+#define FUNC_LOG       logl
+#define FUNC_LOG2       log2l
+#define FUNC_LOG10       log10l
+#define FUNC_REMAINDER       remainderl
 #else
-#define FP___PRINTF "%.8g"
+#define FP___PRINTF "%.16g"
 #define FP___FMOD   fmod
 #define FP___STRTOD  strtod
 #define FP___TYPE    double
+#define FUNC_COS     cos
+#define FUNC_SIN     sin
+#define FUNC_TAN     tan
+#define FUNC_ACOS     acos
+#define FUNC_ASIN     asin
+#define FUNC_ATAN     atan
+#define FUNC_ATAN2     atan2
+#define FUNC_POW       pow
+#define FUNC_SQRT       sqrt
+#define FUNC_FLOOR      floor
+#define FUNC_CEIL      ceil
+#define FUNC_ROUND     round
+#define FUNC_RINT     rint
+#define FUNC_TRUNC     trunc
+#define FUNC_EXP       exp
+#define FUNC_EXP2       exp2
+#define FUNC_LOG       log
+#define FUNC_LOG2       log2
+#define FUNC_LOG10       log10
+#define FUNC_REMAINDER       remainder
 #endif
 
 #include <stdlib.h>
@@ -54,6 +94,9 @@
 #include "asterisk.h"
 #include "asterisk/ast_expr.h"
 #include "asterisk/logger.h"
+#ifndef STANDALONE
+#include "asterisk/pbx.h"
+#endif
 
 #if defined(LONG_LONG_MIN) && !defined(QUAD_MIN)
 #define QUAD_MIN LONG_LONG_MIN
@@ -91,6 +134,19 @@ struct val {
        } u;
 } ;
 
+enum node_type {
+       AST_EXPR_NODE_COMMA, AST_EXPR_NODE_STRING, AST_EXPR_NODE_VAL
+} ;
+
+struct expr_node 
+{
+       enum node_type type;
+       struct val *val;
+       struct expr_node *left;
+       struct expr_node *right;
+};
+
+
 typedef void *yyscan_t;
 
 struct parse_io
@@ -98,6 +154,7 @@ struct parse_io
        char *string;
        struct val *val;
        yyscan_t scanner;
+       struct ast_channel *chan;
 };
  
 static int             chk_div __P((FP___TYPE, FP___TYPE));
@@ -127,8 +184,12 @@ static struct val  *op_or __P((struct val *, struct val *));
 static struct val      *op_plus __P((struct val *, struct val *));
 static struct val      *op_rem __P((struct val *, struct val *));
 static struct val      *op_times __P((struct val *, struct val *));
+static struct val   *op_func(struct val *funcname, struct expr_node *arglist, struct ast_channel *chan);
 static int             to_number __P((struct val *));
 static void            to_string __P((struct val *));
+static struct expr_node *alloc_expr_node(enum node_type);
+static void destroy_arglist(struct expr_node *arglist);
+static int is_really_num(char *str);
 
 /* uh, if I want to predeclare yylex with a YYLTYPE, I have to predeclare the yyltype... sigh */
 typedef struct yyltype
@@ -164,23 +225,26 @@ int               ast_yyerror(const char *,YYLTYPE *, struct parse_io *);
 %union
 {
        struct val *val;
+       struct expr_node *arglist;
 }
 
 %{
 extern int             ast_yylex __P((YYSTYPE *, YYLTYPE *, yyscan_t));
 %}
+%left <val> TOK_COMMA
 %left <val> TOK_COND TOK_COLONCOLON
 %left <val> TOK_OR
 %left <val> TOK_AND
 %left <val> TOK_EQ TOK_GT TOK_LT TOK_GE TOK_LE TOK_NE
 %left <val> TOK_PLUS TOK_MINUS
-%left <val> TOK_MULT TOK_DIV TOK_MOD
+%left <val> TOK_MULT TOK_DIV TOK_MOD 
 %right <val> TOK_COMPL
 %left <val> TOK_COLON TOK_EQTILDE
 %left <val> TOK_RP TOK_LP
 
 
 %token <val> TOKEN
+%type <arglist> arglist
 %type <val> start expr
 
 
@@ -205,8 +269,24 @@ start: expr { ((struct parse_io *)parseio)->val = (struct val *)calloc(sizeof(st
 
        ;
 
-expr:  TOKEN   { $$= $1;}
-       | TOK_LP expr TOK_RP { $$ = $2; 
+arglist: expr { $$ = alloc_expr_node(AST_EXPR_NODE_VAL); $$->val = $1;}
+       | arglist TOK_COMMA expr %prec TOK_RP{struct expr_node *x = alloc_expr_node(AST_EXPR_NODE_VAL);
+                                 struct expr_node *t;
+                                                                DESTROY($2);
+                                 for (t=$1;t->right;t=t->right)
+                                                                 ;
+                                 $$ = $1; t->right = x; x->val = $3;}
+       ;
+
+expr: 
+      TOKEN TOK_LP arglist TOK_RP { $$ = op_func($1,$3, ((struct parse_io *)parseio)->chan);
+                                           DESTROY($2);
+                                                                       DESTROY($4);
+                                                                       DESTROY($1);
+                                                                       destroy_arglist($3);
+                                  }
+    | TOKEN {$$ = $1;}
+       | TOK_LP expr TOK_RP { $$ = $2;
                               @$.first_column = @1.first_column; @$.last_column = @3.last_column; 
                                                   @$.first_line=0; @$.last_line=0;
                                                        DESTROY($1); DESTROY($3); }
@@ -287,6 +367,19 @@ expr:      TOKEN   { $$= $1;}
 
 %%
 
+static struct expr_node *alloc_expr_node(enum node_type nt)
+{
+       struct expr_node *x = calloc(1,sizeof(struct expr_node));
+       if (!x) {
+               ast_log(LOG_ERROR, "Allocation for expr_node FAILED!!\n");
+               return 0;
+       }
+       x->type = nt;
+       return x;
+}
+
+
+
 static struct val *
 make_number (FP___TYPE i)
 {
@@ -475,7 +568,7 @@ int main(int argc,char **argv) {
                        if( s[strlen(s)-1] == '\n' )
                                s[strlen(s)-1] = 0;
                        
-                       ret = ast_expr(s, out, sizeof(out));
+                       ret = ast_expr(s, out, sizeof(out),NULL);
                        printf("Expression: %s    Result: [%d] '%s'\n",
                                   s, ret, out);
                }
@@ -483,7 +576,7 @@ int main(int argc,char **argv) {
        }
        else
        {
-               if (ast_expr(argv[1], s, sizeof(s)))
+               if (ast_expr(argv[1], s, sizeof(s), NULL))
                        printf("=====%s======\n",s);
                else
                        printf("No result\n");
@@ -500,6 +593,304 @@ int main(int argc,char **argv) {
    let it access the BUFFER stuff there and not trying
    define all the structs, macros etc. in this file! */
 
+static void destroy_arglist(struct expr_node *arglist)
+{
+       struct expr_node *arglist_next;
+       
+       while (arglist)
+       {
+               arglist_next = arglist->right;
+               if (arglist->val)
+                       free_value(arglist->val);
+               arglist->val = 0;
+               arglist->right = 0;
+               free(arglist);
+               arglist = arglist_next;
+       }
+}
+
+static char *compose_func_args(struct expr_node *arglist)
+{
+       struct expr_node *t = arglist;
+       char *argbuf;
+       int total_len = 0;
+       
+       while (t) {
+               if (t != arglist)
+                       total_len += 1; /* for the sep */
+               if (t->val) {
+                       if (t->val->type == AST_EXPR_number)
+                               total_len += 25; /* worst case */
+                       else
+                               total_len += strlen(t->val->u.s);
+               }
+               
+               t = t->right;
+       }
+       total_len++; /* for the null */
+       ast_log(LOG_NOTICE,"argbuf allocated %d bytes;\n", total_len);
+       argbuf = malloc(total_len);
+       argbuf[0] = 0;
+       t = arglist;
+       while (t) {
+               char numbuf[30];
+               
+               if (t != arglist)
+                       strcat(argbuf,"|");
+               
+               if (t->val) {
+                       if (t->val->type == AST_EXPR_number) {
+                               sprintf(numbuf,FP___PRINTF,t->val->u.i);
+                               strcat(argbuf,numbuf);
+                       } else
+                               strcat(argbuf,t->val->u.s);
+               }
+               t = t->right;
+       }
+       ast_log(LOG_NOTICE,"argbuf uses %d bytes;\n", strlen(argbuf));
+       return argbuf;
+}
+
+static int is_really_num(char *str)
+{
+       if ( strspn(str,"-0123456789.   ") == strlen(str))
+               return 1;
+       else
+               return 0;
+}
+
+
+static struct val *op_func(struct val *funcname, struct expr_node *arglist, struct ast_channel *chan)
+{
+       if (strspn(funcname->u.s,"ABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789") == strlen(funcname->u.s))
+       {
+               struct val *result;
+               
+               if (strcmp(funcname->u.s,"COS") == 0) {
+                       if (arglist && !arglist->right && arglist->val){
+                               to_number(arglist->val);
+                               result = make_number(FUNC_COS(arglist->val->u.i));
+                               return result;
+                       } else {
+                               ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
+                               return make_number(0.0);
+                       }
+               } else if (strcmp(funcname->u.s,"SIN") == 0) {
+                       if (arglist && !arglist->right && arglist->val){
+                               to_number(arglist->val);
+                               result = make_number(FUNC_SIN(arglist->val->u.i));
+                               return result;
+                       } else {
+                               ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
+                               return make_number(0.0);
+                       }
+               } else if (strcmp(funcname->u.s,"TAN") == 0) {
+                       if (arglist && !arglist->right && arglist->val){
+                               to_number(arglist->val);
+                               result = make_number(FUNC_TAN(arglist->val->u.i));
+                               return result;
+                       } else {
+                               ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
+                               return make_number(0.0);
+                       }
+               } else if (strcmp(funcname->u.s,"ACOS") == 0) {
+                       if (arglist && !arglist->right && arglist->val){
+                               to_number(arglist->val);
+                               result = make_number(FUNC_ACOS(arglist->val->u.i));
+                               return result;
+                       } else {
+                               ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
+                               return make_number(0.0);
+                       }
+               } else if (strcmp(funcname->u.s,"ASIN") == 0) {
+                       if (arglist && !arglist->right && arglist->val){
+                               to_number(arglist->val);
+                               result = make_number(FUNC_ASIN(arglist->val->u.i));
+                               return result;
+                       } else {
+                               ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
+                               return make_number(0.0);
+                       }
+               } else if (strcmp(funcname->u.s,"ATAN") == 0) {
+                       if (arglist && !arglist->right && arglist->val){
+                               to_number(arglist->val);
+                               result = make_number(FUNC_ATAN(arglist->val->u.i));
+                               return result;
+                       } else {
+                               ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
+                               return make_number(0.0);
+                       }
+               } else if (strcmp(funcname->u.s,"ATAN2") == 0) {
+                       if (arglist && arglist->right && !arglist->right->right && arglist->val && arglist->right->val){
+                               to_number(arglist->val);
+                               to_number(arglist->right->val);
+                               result = make_number(FUNC_ATAN2(arglist->val->u.i, arglist->right->val->u.i));
+                               return result;
+                       } else {
+                               ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
+                               return make_number(0.0);
+                       }
+               } else if (strcmp(funcname->u.s,"POW") == 0) {
+                       if (arglist && arglist->right && !arglist->right->right && arglist->val && arglist->right->val){
+                               to_number(arglist->val);
+                               to_number(arglist->right->val);
+                               result = make_number(FUNC_POW(arglist->val->u.i, arglist->right->val->u.i));
+                               return result;
+                       } else {
+                               ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
+                               return make_number(0.0);
+                       }
+               } else if (strcmp(funcname->u.s,"SQRT") == 0) {
+                       if (arglist && !arglist->right && arglist->val){
+                               to_number(arglist->val);
+                               result = make_number(FUNC_SQRT(arglist->val->u.i));
+                               return result;
+                       } else {
+                               ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
+                               return make_number(0.0);
+                       }
+               } else if (strcmp(funcname->u.s,"FLOOR") == 0) {
+                       if (arglist && !arglist->right && arglist->val){
+                               to_number(arglist->val);
+                               result = make_number(FUNC_FLOOR(arglist->val->u.i));
+                               return result;
+                       } else {
+                               ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
+                               return make_number(0.0);
+                       }
+               } else if (strcmp(funcname->u.s,"CEIL") == 0) {
+                       if (arglist && !arglist->right && arglist->val){
+                               to_number(arglist->val);
+                               result = make_number(FUNC_CEIL(arglist->val->u.i));
+                               return result;
+                       } else {
+                               ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
+                               return make_number(0.0);
+                       }
+               } else if (strcmp(funcname->u.s,"ROUND") == 0) {
+                       if (arglist && !arglist->right && arglist->val){
+                               to_number(arglist->val);
+                               result = make_number(FUNC_ROUND(arglist->val->u.i));
+                               return result;
+                       } else {
+                               ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
+                               return make_number(0.0);
+                       }
+               } else if (strcmp(funcname->u.s,"RINT") == 0) {
+                       if (arglist && !arglist->right && arglist->val){
+                               to_number(arglist->val);
+                               result = make_number(FUNC_RINT(arglist->val->u.i));
+                               return result;
+                       } else {
+                               ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
+                               return make_number(0.0);
+                       }
+               } else if (strcmp(funcname->u.s,"TRUNC") == 0) {
+                       if (arglist && !arglist->right && arglist->val){
+                               to_number(arglist->val);
+                               result = make_number(FUNC_TRUNC(arglist->val->u.i));
+                               return result;
+                       } else {
+                               ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
+                               return make_number(0.0);
+                       }
+               } else if (strcmp(funcname->u.s,"EXP") == 0) {
+                       if (arglist && !arglist->right && arglist->val){
+                               to_number(arglist->val);
+                               result = make_number(FUNC_EXP(arglist->val->u.i));
+                               return result;
+                       } else {
+                               ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
+                               return make_number(0.0);
+                       }
+               } else if (strcmp(funcname->u.s,"EXP2") == 0) {
+                       if (arglist && !arglist->right && arglist->val){
+                               to_number(arglist->val);
+                               result = make_number(FUNC_EXP2(arglist->val->u.i));
+                               return result;
+                       } else {
+                               ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
+                               return make_number(0.0);
+                       }
+               } else if (strcmp(funcname->u.s,"LOG") == 0) {
+                       if (arglist && !arglist->right && arglist->val){
+                               to_number(arglist->val);
+                               result = make_number(FUNC_LOG(arglist->val->u.i));
+                               return result;
+                       } else {
+                               ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
+                               return make_number(0.0);
+                       }
+               } else if (strcmp(funcname->u.s,"LOG2") == 0) {
+                       if (arglist && !arglist->right && arglist->val){
+                               to_number(arglist->val);
+                               result = make_number(FUNC_LOG2(arglist->val->u.i));
+                               return result;
+                       } else {
+                               ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
+                               return make_number(0.0);
+                       }
+               } else if (strcmp(funcname->u.s,"LOG10") == 0) {
+                       if (arglist && !arglist->right && arglist->val){
+                               to_number(arglist->val);
+                               result = make_number(FUNC_LOG10(arglist->val->u.i));
+                               return result;
+                       } else {
+                               ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
+                               return make_number(0.0);
+                       }
+               } else if (strcmp(funcname->u.s,"REMAINDER") == 0) {
+                       if (arglist && arglist->right && !arglist->right->right && arglist->val && arglist->right->val){
+                               to_number(arglist->val);
+                               to_number(arglist->right->val);
+                               result = make_number(FUNC_REMAINDER(arglist->val->u.i, arglist->right->val->u.i));
+                               return result;
+                       } else {
+                               ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
+                               return make_number(0.0);
+                       }
+               } else {
+                       /* is this a custom function we should execute and collect the results of? */
+#ifndef STANDALONE
+                       struct ast_custom_function *f = ast_custom_function_find(funcname->u.s);
+                       if (!chan)
+                               ast_log(LOG_WARNING,"Hey! chan is NULL.\n");
+                       if (!f)
+                               ast_log(LOG_WARNING,"Hey! could not find func %s.\n", funcname->u.s);
+                       
+                       if (f && chan) {
+                               if (f->read) {
+                                       char workspace[512];
+                                       char *argbuf = compose_func_args(arglist);
+                                       f->read(chan, funcname->u.s, argbuf, workspace, sizeof(workspace));
+                                       free(argbuf);
+                                       if (is_really_num(workspace))
+                                               return make_number(FP___STRTOD(workspace,(char **)NULL));
+                                       else
+                                               return make_str(workspace);
+                               } else {
+                                       ast_log(LOG_ERROR,"Error! Function '%s' cannot be read!\n", funcname->u.s);
+                                       return (make_number ((FP___TYPE)0.0));
+                               }
+                               
+                       } else {
+                               ast_log(LOG_ERROR,"Error! '%s' doesn't appear to be an available function!", funcname->u.s);
+                               return (make_number ((FP___TYPE)0.0));
+                       }
+#else
+                       ast_log(LOG_ERROR,"Error! '%s' is not available in the standalone version!", funcname->u.s);
+                       return (make_number ((FP___TYPE)0.0));
+#endif
+               }
+       }
+       else
+       {
+               ast_log(LOG_ERROR,"Error! '%s' is not possibly a function name!", funcname->u.s);
+               return (make_number ((FP___TYPE)0.0));
+       }
+       return (make_number ((FP___TYPE)0.0));
+}
+
 
 static struct val *
 op_or (struct val *a, struct val *b)
@@ -519,7 +910,7 @@ op_and (struct val *a, struct val *b)
        if (is_zero_or_null (a) || is_zero_or_null (b)) {
                free_value (a);
                free_value (b);
-               return (make_number ((double)0.0));
+               return (make_number ((FP___TYPE)0.0));
        } else {
                free_value (b);
                return (a);
index aa84e2b..7888a59 100644 (file)
@@ -351,16 +351,16 @@ static yyconst flex_int16_t yy_nxt[][128] =
        10,    8,    8,    9,    8,    8,    8,    8,    8,    8,
         8,    8,    8,    8,    8,    8,    8,    8,    8,    8,
         8,    8,    9,   11,   12,   13,   14,   15,   16,   13,
-       17,   18,   19,   20,   13,   21,   13,   22,   23,   23,
-       23,   23,   23,   23,   23,   23,   23,   23,   24,   13,
-       25,   26,   27,   28,   13,   13,   13,   13,   13,   13,
+       17,   18,   19,   20,   21,   22,   13,   23,   24,   24,
+       24,   24,   24,   24,   24,   24,   24,   24,   25,   13,
+       26,   27,   28,   29,   13,   13,   13,   13,   13,   13,
 
        13,   13,   13,   13,   13,   13,   13,   13,   13,   13,
        13,   13,   13,   13,   13,   13,   13,   13,   13,   13,
        13,    8,   13,    8,   13,   13,    8,   13,   13,   13,
        13,   13,   13,   13,   13,   13,   13,   13,   13,   13,
        13,   13,   13,   13,   13,   13,   13,   13,   13,   13,
-       13,   13,   13,    8,   29,    8,    8,    8
+       13,   13,   13,    8,   30,    8,    8,    8
     },
 
     {
@@ -369,85 +369,85 @@ static yyconst flex_int16_t yy_nxt[][128] =
         8,    8,    8,    8,    8,    8,    8,    8,    8,    8,
         8,    8,    9,   11,   12,   13,   14,   15,   16,   13,
 
-       17,   18,   19,   20,   13,   21,   13,   22,   23,   23,
-       23,   23,   23,   23,   23,   23,   23,   23,   24,   13,
-       25,   26,   27,   28,   13,   13,   13,   13,   13,   13,
+       17,   18,   19,   20,   21,   22,   13,   23,   24,   24,
+       24,   24,   24,   24,   24,   24,   24,   24,   25,   13,
+       26,   27,   28,   29,   13,   13,   13,   13,   13,   13,
        13,   13,   13,   13,   13,   13,   13,   13,   13,   13,
        13,   13,   13,   13,   13,   13,   13,   13,   13,   13,
        13,    8,   13,    8,   13,   13,    8,   13,   13,   13,
        13,   13,   13,   13,   13,   13,   13,   13,   13,   13,
        13,   13,   13,   13,   13,   13,   13,   13,   13,   13,
-       13,   13,   13,    8,   29,    8,    8,    8
+       13,   13,   13,    8,   30,    8,    8,    8
     },
 
     {
-        7,   30,   30,   30,   30,   30,   30,   30,   30,   30,
-
-       30,   30,   30,   30,   30,   30,   30,   30,   30,   30,
-       30,   30,   30,   30,   30,   30,   30,   30,   30,   30,
-       30,   30,   30,   30,   30,   30,   30,   30,   30,   30,
-       30,   30,   30,   30,   30,   30,   30,   30,   30,   30,
-       30,   30,   30,   30,   30,   30,   30,   30,   30,   30,
-       30,   30,   30,   30,   30,   30,   30,   30,   30,   30,
-       30,   30,   30,   30,   30,   30,   30,   30,   30,   30,
-       30,   30,   30,   30,   30,   30,   30,   30,   30,   30,
-       30,   30,   30,   30,   30,   30,   30,   30,   30,   30,
-       30,   30,   30,   30,   30,   30,   30,   30,   30,   30,
-
-       30,   30,   30,   30,   30,   30,   30,   30,   30,   30,
-       30,   30,   30,   31,   30,   32,   30,   30
+        7,   31,   31,   31,   31,   31,   31,   31,   31,   31,
+
+       31,   31,   31,   31,   31,   31,   31,   31,   31,   31,
+       31,   31,   31,   31,   31,   31,   31,   31,   31,   31,
+       31,   31,   31,   31,   31,   31,   31,   31,   31,   31,
+       31,   31,   31,   31,   31,   31,   31,   31,   31,   31,
+       31,   31,   31,   31,   31,   31,   31,   31,   31,   31,
+       31,   31,   31,   31,   31,   31,   31,   31,   31,   31,
+       31,   31,   31,   31,   31,   31,   31,   31,   31,   31,
+       31,   31,   31,   31,   31,   31,   31,   31,   31,   31,
+       31,   31,   31,   31,   31,   31,   31,   31,   31,   31,
+       31,   31,   31,   31,   31,   31,   31,   31,   31,   31,
+
+       31,   31,   31,   31,   31,   31,   31,   31,   31,   31,
+       31,   31,   31,   32,   31,   33,   31,   31
     },
 
     {
-        7,   30,   30,   30,   30,   30,   30,   30,   30,   30,
-       30,   30,   30,   30,   30,   30,   30,   30,   30,   30,
-       30,   30,   30,   30,   30,   30,   30,   30,   30,   30,
-       30,   30,   30,   30,   30,   30,   30,   30,   30,   30,
-       30,   30,   30,   30,   30,   30,   30,   30,   30,   30,
-       30,   30,   30,   30,   30,   30,   30,   30,   30,   30,
-       30,   30,   30,   30,   30,   30,   30,   30,   30,   30,
-       30,   30,   30,   30,   30,   30,   30,   30,   30,   30,
-
-       30,   30,   30,   30,   30,   30,   30,   30,   30,   30,
-       30,   30,   30,   30,   30,   30,   30,   30,   30,   30,
-       30,   30,   30,   30,   30,   30,   30,   30,   30,   30,
-       30,   30,   30,   30,   30,   30,   30,   30,   30,   30,
-       30,   30,   30,   31,   30,   32,   30,   30
+        7,   31,   31,   31,   31,   31,   31,   31,   31,   31,
+       31,   31,   31,   31,   31,   31,   31,   31,   31,   31,
+       31,   31,   31,   31,   31,   31,   31,   31,   31,   31,
+       31,   31,   31,   31,   31,   31,   31,   31,   31,   31,
+       31,   31,   31,   31,   31,   31,   31,   31,   31,   31,
+       31,   31,   31,   31,   31,   31,   31,   31,   31,   31,
+       31,   31,   31,   31,   31,   31,   31,   31,   31,   31,
+       31,   31,   31,   31,   31,   31,   31,   31,   31,   31,
+
+       31,   31,   31,   31,   31,   31,   31,   31,   31,   31,
+       31,   31,   31,   31,   31,   31,   31,   31,   31,   31,
+       31,   31,   31,   31,   31,   31,   31,   31,   31,   31,
+       31,   31,   31,   31,   31,   31,   31,   31,   31,   31,
+       31,   31,   31,   32,   31,   33,   31,   31
     },
 
     {
-        7,   33,   33,   33,   33,   33,   33,   33,   33,   34,
-       34,   33,   33,   34,   33,   33,   33,   33,   33,   33,
-       33,   33,   33,   33,   33,   33,   33,   33,   33,   33,
-       33,   33,   34,   34,   33,   33,   35,   34,   34,   33,
-       34,   34,   34,   34,   33,   34,   33,   34,   33,   33,
-
-       33,   33,   33,   33,   33,   33,   33,   33,   34,   33,
-       34,   34,   34,   34,   33,   33,   33,   33,   33,   33,
-       33,   33,   33,   33,   33,   33,   33,   33,   33,   33,
-       33,   33,   33,   33,   33,   33,   33,   33,   33,   33,
-       33,   33,   33,   33,   33,   33,   33,   33,   33,   33,
-       33,   33,   33,   33,   33,   33,   33,   33,   33,   33,
-       33,   33,   33,   33,   33,   33,   33,   33,   33,   33,
-       33,   33,   33,   33,   34,   33,   33,   33
+        7,   34,   34,   34,   34,   34,   34,   34,   34,   35,
+       35,   34,   34,   35,   34,   34,   34,   34,   34,   34,
+       34,   34,   34,   34,   34,   34,   34,   34,   34,   34,
+       34,   34,   35,   35,   34,   34,   36,   35,   35,   34,
+       35,   35,   35,   35,   34,   35,   34,   35,   34,   34,
+
+       34,   34,   34,   34,   34,   34,   34,   34,   35,   34,
+       35,   35,   35,   35,   34,   34,   34,   34,   34,   34,
+       34,   34,   34,   34,   34,   34,   34,   34,   34,   34,
+       34,   34,   34,   34,   34,   34,   34,   34,   34,   34,
+       34,   34,   34,   34,   34,   34,   34,   34,   34,   34,
+       34,   34,   34,   34,   34,   34,   34,   34,   34,   34,
+       34,   34,   34,   34,   34,   34,   34,   34,   34,   34,
+       34,   34,   34,   34,   35,   34,   34,   34
     },
 
     {
-        7,   33,   33,   33,   33,   33,   33,   33,   33,   34,
-       34,   33,   33,   34,   33,   33,   33,   33,   33,   33,
-
-       33,   33,   33,   33,   33,   33,   33,   33,   33,   33,
-       33,   33,   34,   34,   33,   33,   35,   34,   34,   33,
-       34,   34,   34,   34,   33,   34,   33,   34,   33,   33,
-       33,   33,   33,   33,   33,   33,   33,   33,   34,   33,
-       34,   34,   34,   34,   33,   33,   33,   33,   33,   33,
-       33,   33,   33,   33,   33,   33,   33,   33,   33,   33,
-       33,   33,   33,   33,   33,   33,   33,   33,   33,   33,
-       33,   33,   33,   33,   33,   33,   33,   33,   33,   33,
-       33,   33,   33,   33,   33,   33,   33,   33,   33,   33,
-       33,   33,   33,   33,   33,   33,   33,   33,   33,   33,
-
-       33,   33,   33,   33,   34,   33,   33,   33
+        7,   34,   34,   34,   34,   34,   34,   34,   34,   35,
+       35,   34,   34,   35,   34,   34,   34,   34,   34,   34,
+
+       34,   34,   34,   34,   34,   34,   34,   34,   34,   34,
+       34,   34,   35,   35,   34,   34,   36,   35,   35,   34,
+       35,   35,   35,   35,   34,   35,   34,   35,   34,   34,
+       34,   34,   34,   34,   34,   34,   34,   34,   35,   34,
+       35,   35,   35,   35,   34,   34,   34,   34,   34,   34,
+       34,   34,   34,   34,   34,   34,   34,   34,   34,   34,
+       34,   34,   34,   34,   34,   34,   34,   34,   34,   34,
+       34,   34,   34,   34,   34,   34,   34,   34,   34,   34,
+       34,   34,   34,   34,   34,   34,   34,   34,   34,   34,
+       34,   34,   34,   34,   34,   34,   34,   34,   34,   34,
+
+       34,   34,   34,   34,   35,   34,   34,   34
     },
 
     {
@@ -526,7 +526,7 @@ static yyconst flex_int16_t yy_nxt[][128] =
       -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,
       -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,
       -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,
-      -11,   36,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,
+      -11,   37,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,
 
       -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,
       -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,  -11,
@@ -537,20 +537,20 @@ static yyconst flex_int16_t yy_nxt[][128] =
     },
 
     {
-        7,   37,   37,   37,   37,   37,   37,   37,   37,   37,
-       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
-       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
-       37,   37,   37,   37,   38,   37,   37,   37,   37,   37,
-
-       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
-       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
-       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
-       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
-       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
-       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
-       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
-       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
-       37,   37,   37,   37,   37,   37,   37,   37
+        7,   38,   38,   38,   38,   38,   38,   38,   38,   38,
+       38,   38,   38,   38,   38,   38,   38,   38,   38,   38,
+       38,   38,   38,   38,   38,   38,   38,   38,   38,   38,
+       38,   38,   38,   38,   39,   38,   38,   38,   38,   38,
+
+       38,   38,   38,   38,   38,   38,   38,   38,   38,   38,
+       38,   38,   38,   38,   38,   38,   38,   38,   38,   38,
+       38,   38,   38,   38,   38,   38,   38,   38,   38,   38,
+       38,   38,   38,   38,   38,   38,   38,   38,   38,   38,
+       38,   38,   38,   38,   38,   38,   38,   38,   38,   38,
+       38,   38,   38,   38,   38,   38,   38,   38,   38,   38,
+       38,   38,   38,   38,   38,   38,   38,   38,   38,   38,
+       38,   38,   38,   38,   38,   38,   38,   38,   38,   38,
+       38,   38,   38,   38,   38,   38,   38,   38
     },
 
     {
@@ -558,34 +558,34 @@ static yyconst flex_int16_t yy_nxt[][128] =
 
       -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,
       -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,  -13,
-      -13,  -13,  -13,  -13,  -13,   39,   39,  -13,  -13,   39,
-      -13,  -13,  -13,  -13,   39,  -13,   39,  -13,   39,   39,
-       39,   39,   39,   39,   39,   39,   39,   39,  -13,   39,
-      -13,  -13,  -13,  -13,   39,   39,   39,   39,   39,   39,
-       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
-       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
-       39,  -13,   39,  -13,   39,   39,  -13,   39,   39,   39,
-       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
-
-       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
-       39,   39,   39,  -13,  -13,  -13,  -13,  -13
+      -13,  -13,  -13,  -13,  -13,   40,   40,  -13,  -13,   40,
+      -13,  -13,  -13,  -13,  -13,  -13,   40,  -13,   40,   40,
+       40,   40,   40,   40,   40,   40,   40,   40,  -13,   40,
+      -13,  -13,  -13,  -13,   40,   40,   40,   40,   40,   40,
+       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+       40,  -13,   40,  -13,   40,   40,  -13,   40,   40,   40,
+       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+
+       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+       40,   40,   40,  -13,  -13,  -13,  -13,  -13
     },
 
     {
         7,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,
       -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,
       -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,  -14,
-      -14,  -14,  -14,  -14,  -14,   39,   39,  -14,  -14,   39,
-      -14,  -14,  -14,  -14,   39,  -14,   39,  -14,   39,   39,
-       39,   39,   39,   39,   39,   39,   39,   39,  -14,   39,
-      -14,  -14,  -14,  -14,   39,   39,   39,   39,   39,   39,
-       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
-
-       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
-       39,  -14,   39,  -14,   39,   39,  -14,   39,   39,   39,
-       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
-       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
-       39,   39,   39,   40,  -14,  -14,  -14,  -14
+      -14,  -14,  -14,  -14,  -14,   40,   40,  -14,  -14,   40,
+      -14,  -14,  -14,  -14,  -14,  -14,   40,  -14,   40,   40,
+       40,   40,   40,   40,   40,   40,   40,   40,  -14,   40,
+      -14,  -14,  -14,  -14,   40,   40,   40,   40,   40,   40,
+       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+
+       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+       40,  -14,   40,  -14,   40,   40,  -14,   40,   40,   40,
+       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+       40,   40,   40,   41,  -14,  -14,  -14,  -14
     },
 
     {
@@ -610,7 +610,7 @@ static yyconst flex_int16_t yy_nxt[][128] =
       -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
 
       -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
-      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,   41,  -16,
+      -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,   42,  -16,
       -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
       -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
       -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,  -16,
@@ -731,34 +731,34 @@ static yyconst flex_int16_t yy_nxt[][128] =
 
       -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
       -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
-      -23,  -23,  -23,  -23,  -23,   39,   39,  -23,  -23,   39,
-      -23,  -23,  -23,  -23,   39,  -23,   42,  -23,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,  -23,   39,
-      -23,  -23,  -23,  -23,   39,   39,   39,   39,   39,   39,
-       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
-       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
-       39,  -23,   39,  -23,   39,   39,  -23,   39,   39,   39,
-       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
-
-       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
-       39,   39,   39,  -23,  -23,  -23,  -23,  -23
+      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
+      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
+      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
+      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
+      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
+      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
+      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
+      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
+
+      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23,
+      -23,  -23,  -23,  -23,  -23,  -23,  -23,  -23
     },
 
     {
         7,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,
       -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,
       -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,
-      -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,
-      -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,
-      -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,   44,  -24,
-      -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,
-      -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,
-
-      -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,
-      -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,
-      -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,
-      -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24,
-      -24,  -24,  -24,  -24,  -24,  -24,  -24,  -24
+      -24,  -24,  -24,  -24,  -24,   40,   40,  -24,  -24,   40,
+      -24,  -24,  -24,  -24,  -24,  -24,   43,  -24,   44,   44,
+       44,   44,   44,   44,   44,   44,   44,   44,  -24,   40,
+      -24,  -24,  -24,  -24,   40,   40,   40,   40,   40,   40,
+       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+
+       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+       40,  -24,   40,  -24,   40,   40,  -24,   40,   40,   40,
+       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+       40,   40,   40,  -24,  -24,  -24,  -24,  -24
     },
 
     {
@@ -768,8 +768,8 @@ static yyconst flex_int16_t yy_nxt[][128] =
       -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,
       -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,
 
+      -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,   45,  -25,
       -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,
-      -25,   45,  -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,
       -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,
       -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,
       -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,  -25,
@@ -793,7 +793,7 @@ static yyconst flex_int16_t yy_nxt[][128] =
       -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,
       -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26,
 
-      -26,  -26,  -26,  -26,  -26,  -26,   47,  -26
+      -26,  -26,  -26,  -26,  -26,  -26,  -26,  -26
     },
 
     {
@@ -803,14 +803,14 @@ static yyconst flex_int16_t yy_nxt[][128] =
       -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,
       -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,
       -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,
-      -27,   48,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,
+      -27,   47,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,
       -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,
       -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,
 
       -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,
       -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,
       -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27,
-      -27,  -27,  -27,  -27,  -27,  -27,  -27,  -27
+      -27,  -27,  -27,  -27,  -27,  -27,   48,  -27
     },
 
     {
@@ -821,7 +821,7 @@ static yyconst flex_int16_t yy_nxt[][128] =
       -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,
       -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,
 
-      -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,
+      -28,   49,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,
       -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,
       -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,
       -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,  -28,
@@ -844,42 +844,42 @@ static yyconst flex_int16_t yy_nxt[][128] =
       -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,
       -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,
       -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29,
-      -29,  -29,  -29,  -29,   49,  -29,  -29,  -29
+      -29,  -29,  -29,  -29,  -29,  -29,  -29,  -29
 
     },
 
     {
-        7,   50,   50,   50,   50,   50,   50,   50,   50,   50,
-       50,   50,   50,   50,   50,   50,   50,   50,   50,   50,
-       50,   50,   50,   50,   50,   50,   50,   50,   50,   50,
-       50,   50,   50,   50,   50,   50,   50,   50,   50,   50,
-       50,   50,   50,   50,   50,   50,   50,   50,   50,   50,
-       50,   50,   50,   50,   50,   50,   50,   50,   50,   50,
-       50,   50,   50,   50,   50,   50,   50,   50,   50,   50,
-       50,   50,   50,   50,   50,   50,   50,   50,   50,   50,
-       50,   50,   50,   50,   50,   50,   50,   50,   50,   50,
-       50,   50,   50,   50,   50,   50,   50,   50,   50,   50,
-
-       50,   50,   50,   50,   50,   50,   50,   50,   50,   50,
-       50,   50,   50,   50,   50,   50,   50,   50,   50,   50,
-       50,   50,   50,   51,   50,   52,   50,   50
+        7,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
+      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
+      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
+      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
+      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
+      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
+      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
+      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
+      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
+      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
+
+      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
+      -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,  -30,
+      -30,  -30,  -30,  -30,   50,  -30,  -30,  -30
     },
 
     {
-        7,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
-      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
-      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
-      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
-      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
-      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
-      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
-
-      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
-      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
-      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
-      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
-      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31,
-      -31,  -31,  -31,  -31,  -31,  -31,  -31,  -31
+        7,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+       51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+       51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+       51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+       51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+       51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+       51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+
+       51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+       51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+       51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+       51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+       51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+       51,   51,   51,   52,   51,   53,   51,   51
     },
 
     {
@@ -900,38 +900,38 @@ static yyconst flex_int16_t yy_nxt[][128] =
     },
 
     {
-        7,   53,   53,   53,   53,   53,   53,   53,   53,  -33,
-
-      -33,   53,   53,  -33,   53,   53,   53,   53,   53,   53,
-       53,   53,   53,   53,   53,   53,   53,   53,   53,   53,
-       53,   53,  -33,  -33,   53,   53,  -33,  -33,  -33,   53,
-      -33,  -33,  -33,  -33,   53,  -33,   53,  -33,   53,   53,
-       53,   53,   53,   53,   53,   53,   53,   53,  -33,   53,
-      -33,  -33,  -33,  -33,   53,   53,   53,   53,   53,   53,
-       53,   53,   53,   53,   53,   53,   53,   53,   53,   53,
-       53,   53,   53,   53,   53,   53,   53,   53,   53,   53,
-       53,   53,   53,   53,   53,   53,   53,   53,   53,   53,
-       53,   53,   53,   53,   53,   53,   53,   53,   53,   53,
-
-       53,   53,   53,   53,   53,   53,   53,   53,   53,   53,
-       53,   53,   53,   53,  -33,   53,   53,   53
+        7,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+
+      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+
+      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33,
+      -33,  -33,  -33,  -33,  -33,  -33,  -33,  -33
     },
 
     {
-        7,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34,
-      -34,  -34,  -34,  -34,  -34,  -34,  -34,  -34
+        7,   54,   54,   54,   54,   54,   54,   54,   54,  -34,
+      -34,   54,   54,  -34,   54,   54,   54,   54,   54,   54,
+       54,   54,   54,   54,   54,   54,   54,   54,   54,   54,
+       54,   54,  -34,  -34,   54,   54,  -34,  -34,  -34,   54,
+      -34,  -34,  -34,  -34,   54,  -34,   54,  -34,   54,   54,
+       54,   54,   54,   54,   54,   54,   54,   54,  -34,   54,
+      -34,  -34,  -34,  -34,   54,   54,   54,   54,   54,   54,
+       54,   54,   54,   54,   54,   54,   54,   54,   54,   54,
+
+       54,   54,   54,   54,   54,   54,   54,   54,   54,   54,
+       54,   54,   54,   54,   54,   54,   54,   54,   54,   54,
+       54,   54,   54,   54,   54,   54,   54,   54,   54,   54,
+       54,   54,   54,   54,   54,   54,   54,   54,   54,   54,
+       54,   54,   54,   54,  -34,   54,   54,   54
     },
 
     {
@@ -948,7 +948,7 @@ static yyconst flex_int16_t yy_nxt[][128] =
       -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
       -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
       -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35,
-      -35,  -35,  -35,   54,  -35,  -35,  -35,  -35
+      -35,  -35,  -35,  -35,  -35,  -35,  -35,  -35
     },
 
     {
@@ -966,41 +966,41 @@ static yyconst flex_int16_t yy_nxt[][128] =
       -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
       -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36,
 
-      -36,  -36,  -36,  -36,  -36,  -36,  -36,  -36
+      -36,  -36,  -36,   55,  -36,  -36,  -36,  -36
     },
 
     {
-        7,   37,   37,   37,   37,   37,   37,   37,   37,   37,
-       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
-       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
-       37,   37,   37,   37,   38,   37,   37,   37,   37,   37,
-       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
-       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
-       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
-       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
-       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
-
-       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
-       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
-       37,   37,   37,   37,   37,   37,   37,   37,   37,   37,
-       37,   37,   37,   37,   37,   37,   37,   37
+        7,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37,
+      -37,  -37,  -37,  -37,  -37,  -37,  -37,  -37
     },
 
     {
-        7,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
-      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
-      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
-      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
-      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
-      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
-
-      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
-      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
-      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
-      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
-      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
-      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38,
-      -38,  -38,  -38,  -38,  -38,  -38,  -38,  -38
+        7,   38,   38,   38,   38,   38,   38,   38,   38,   38,
+       38,   38,   38,   38,   38,   38,   38,   38,   38,   38,
+       38,   38,   38,   38,   38,   38,   38,   38,   38,   38,
+       38,   38,   38,   38,   39,   38,   38,   38,   38,   38,
+       38,   38,   38,   38,   38,   38,   38,   38,   38,   38,
+       38,   38,   38,   38,   38,   38,   38,   38,   38,   38,
+
+       38,   38,   38,   38,   38,   38,   38,   38,   38,   38,
+       38,   38,   38,   38,   38,   38,   38,   38,   38,   38,
+       38,   38,   38,   38,   38,   38,   38,   38,   38,   38,
+       38,   38,   38,   38,   38,   38,   38,   38,   38,   38,
+       38,   38,   38,   38,   38,   38,   38,   38,   38,   38,
+       38,   38,   38,   38,   38,   38,   38,   38,   38,   38,
+       38,   38,   38,   38,   38,   38,   38,   38
     },
 
     {
@@ -1008,16 +1008,16 @@ static yyconst flex_int16_t yy_nxt[][128] =
       -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
       -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
 
-      -39,  -39,  -39,  -39,  -39,   39,   39,  -39,  -39,   39,
-      -39,  -39,  -39,  -39,   39,  -39,   39,  -39,   39,   39,
-       39,   39,   39,   39,   39,   39,   39,   39,  -39,   39,
-      -39,  -39,  -39,  -39,   39,   39,   39,   39,   39,   39,
-       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
-       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
-       39,  -39,   39,  -39,   39,   39,  -39,   39,   39,   39,
-       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
-       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
-       39,   39,   39,  -39,  -39,  -39,  -39,  -39
+      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
+      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
+      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
+      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
+      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
+      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
+      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
+      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
+      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39,
+      -39,  -39,  -39,  -39,  -39,  -39,  -39,  -39
 
     },
 
@@ -1025,17 +1025,17 @@ static yyconst flex_int16_t yy_nxt[][128] =
         7,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
       -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
       -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
-      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
-      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
-      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
-      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
-      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
-      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
-      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
-
-      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
-      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40,
-      -40,  -40,  -40,  -40,  -40,  -40,  -40,  -40
+      -40,  -40,  -40,  -40,  -40,   40,   40,  -40,  -40,   40,
+      -40,  -40,  -40,  -40,  -40,  -40,   40,  -40,   40,   40,
+       40,   40,   40,   40,   40,   40,   40,   40,  -40,   40,
+      -40,  -40,  -40,  -40,   40,   40,   40,   40,   40,   40,
+       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+       40,  -40,   40,  -40,   40,   40,  -40,   40,   40,   40,
+
+       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+       40,   40,   40,  -40,  -40,  -40,  -40,  -40
     },
 
     {
@@ -1059,17 +1059,17 @@ static yyconst flex_int16_t yy_nxt[][128] =
         7,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
       -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
       -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
-      -42,  -42,  -42,  -42,  -42,   39,   39,  -42,  -42,   39,
-
-      -42,  -42,  -42,  -42,   39,  -42,   39,  -42,   55,   55,
-       55,   55,   55,   55,   55,   55,   55,   55,  -42,   39,
-      -42,  -42,  -42,  -42,   39,   39,   39,   39,   39,   39,
-       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
-       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
-       39,  -42,   39,  -42,   39,   39,  -42,   39,   39,   39,
-       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
-       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
-       39,   39,   39,  -42,  -42,  -42,  -42,  -42
+      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
+
+      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
+      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
+      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
+      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
+      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
+      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
+      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
+      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42,
+      -42,  -42,  -42,  -42,  -42,  -42,  -42,  -42
     },
 
     {
@@ -1077,34 +1077,34 @@ static yyconst flex_int16_t yy_nxt[][128] =
 
       -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
       -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,  -43,
-      -43,  -43,  -43,  -43,  -43,   39,   39,  -43,  -43,   39,
-      -43,  -43,  -43,  -43,   39,  -43,   42,  -43,   43,   43,
-       43,   43,   43,   43,   43,   43,   43,   43,  -43,   39,
-      -43,  -43,  -43,  -43,   39,   39,   39,   39,   39,   39,
-       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
-       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
-       39,  -43,   39,  -43,   39,   39,  -43,   39,   39,   39,
-       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
-
-       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
-       39,   39,   39,  -43,  -43,  -43,  -43,  -43
+      -43,  -43,  -43,  -43,  -43,   40,   40,  -43,  -43,   40,
+      -43,  -43,  -43,  -43,  -43,  -43,   40,  -43,   56,   56,
+       56,   56,   56,   56,   56,   56,   56,   56,  -43,   40,
+      -43,  -43,  -43,  -43,   40,   40,   40,   40,   40,   40,
+       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+       40,  -43,   40,  -43,   40,   40,  -43,   40,   40,   40,
+       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+
+       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+       40,   40,   40,  -43,  -43,  -43,  -43,  -43
     },
 
     {
         7,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
       -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
       -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
-      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
-      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
-      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
-      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
-      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
-
-      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
-      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
-      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
-      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44,
-      -44,  -44,  -44,  -44,  -44,  -44,  -44,  -44
+      -44,  -44,  -44,  -44,  -44,   40,   40,  -44,  -44,   40,
+      -44,  -44,  -44,  -44,  -44,  -44,   43,  -44,   44,   44,
+       44,   44,   44,   44,   44,   44,   44,   44,  -44,   40,
+      -44,  -44,  -44,  -44,   40,   40,   40,   40,   40,   40,
+       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+
+       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+       40,  -44,   40,  -44,   40,   40,  -44,   40,   40,   40,
+       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+       40,   40,   40,  -44,  -44,  -44,  -44,  -44
     },
 
     {
@@ -1195,37 +1195,37 @@ static yyconst flex_int16_t yy_nxt[][128] =
     },
 
     {
-        7,   50,   50,   50,   50,   50,   50,   50,   50,   50,
-       50,   50,   50,   50,   50,   50,   50,   50,   50,   50,
-       50,   50,   50,   50,   50,   50,   50,   50,   50,   50,
-       50,   50,   50,   50,   50,   50,   50,   50,   50,   50,
-       50,   50,   50,   50,   50,   50,   50,   50,   50,   50,
-       50,   50,   50,   50,   50,   50,   50,   50,   50,   50,
-       50,   50,   50,   50,   50,   50,   50,   50,   50,   50,
-       50,   50,   50,   50,   50,   50,   50,   50,   50,   50,
-       50,   50,   50,   50,   50,   50,   50,   50,   50,   50,
-       50,   50,   50,   50,   50,   50,   50,   50,   50,   50,
-
-       50,   50,   50,   50,   50,   50,   50,   50,   50,   50,
-       50,   50,   50,   50,   50,   50,   50,   50,   50,   50,
-       50,   50,   50,   51,   50,   52,   50,   50
+        7,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
+      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
+      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
+      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
+      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
+      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
+      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
+      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
+      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
+      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
+
+      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
+      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50,
+      -50,  -50,  -50,  -50,  -50,  -50,  -50,  -50
     },
 
     {
-        7,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51,
-      -51,  -51,  -51,  -51,  -51,  -51,  -51,  -51
+        7,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+       51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+       51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+       51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+       51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+       51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+       51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+
+       51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+       51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+       51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+       51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+       51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+       51,   51,   51,   52,   51,   53,   51,   51
     },
 
     {
@@ -1246,55 +1246,73 @@ static yyconst flex_int16_t yy_nxt[][128] =
     },
 
     {
-        7,   53,   53,   53,   53,   53,   53,   53,   53,  -53,
-
-      -53,   53,   53,  -53,   53,   53,   53,   53,   53,   53,
-       53,   53,   53,   53,   53,   53,   53,   53,   53,   53,
-       53,   53,  -53,  -53,   53,   53,  -53,  -53,  -53,   53,
-      -53,  -53,  -53,  -53,   53,  -53,   53,  -53,   53,   53,
-       53,   53,   53,   53,   53,   53,   53,   53,  -53,   53,
-      -53,  -53,  -53,  -53,   53,   53,   53,   53,   53,   53,
-       53,   53,   53,   53,   53,   53,   53,   53,   53,   53,
-       53,   53,   53,   53,   53,   53,   53,   53,   53,   53,
-       53,   53,   53,   53,   53,   53,   53,   53,   53,   53,
-       53,   53,   53,   53,   53,   53,   53,   53,   53,   53,
-
-       53,   53,   53,   53,   53,   53,   53,   53,   53,   53,
-       53,   53,   53,   53,  -53,   53,   53,   53
+        7,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53,
+      -53,  -53,  -53,  -53,  -53,  -53,  -53,  -53
     },
 
     {
-        7,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
-      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
-      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
-      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
-      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
-      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
-      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
-      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
-
-      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
-      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
-      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
-      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54,
-      -54,  -54,  -54,  -54,  -54,  -54,  -54,  -54
+        7,   54,   54,   54,   54,   54,   54,   54,   54,  -54,
+      -54,   54,   54,  -54,   54,   54,   54,   54,   54,   54,
+       54,   54,   54,   54,   54,   54,   54,   54,   54,   54,
+       54,   54,  -54,  -54,   54,   54,  -54,  -54,  -54,   54,
+      -54,  -54,  -54,  -54,   54,  -54,   54,  -54,   54,   54,
+       54,   54,   54,   54,   54,   54,   54,   54,  -54,   54,
+      -54,  -54,  -54,  -54,   54,   54,   54,   54,   54,   54,
+       54,   54,   54,   54,   54,   54,   54,   54,   54,   54,
+
+       54,   54,   54,   54,   54,   54,   54,   54,   54,   54,
+       54,   54,   54,   54,   54,   54,   54,   54,   54,   54,
+       54,   54,   54,   54,   54,   54,   54,   54,   54,   54,
+       54,   54,   54,   54,   54,   54,   54,   54,   54,   54,
+       54,   54,   54,   54,  -54,   54,   54,   54
     },
 
     {
         7,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
       -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
       -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
-      -55,  -55,  -55,  -55,  -55,   39,   39,  -55,  -55,   39,
-      -55,  -55,  -55,  -55,   39,  -55,   39,  -55,   55,   55,
-
-       55,   55,   55,   55,   55,   55,   55,   55,  -55,   39,
-      -55,  -55,  -55,  -55,   39,   39,   39,   39,   39,   39,
-       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
-       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
-       39,  -55,   39,  -55,   39,   39,  -55,   39,   39,   39,
-       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
-       39,   39,   39,   39,   39,   39,   39,   39,   39,   39,
-       39,   39,   39,  -55,  -55,  -55,  -55,  -55
+      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
+      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
+
+      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
+      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
+      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
+      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
+      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
+      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
+      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55,
+      -55,  -55,  -55,  -55,  -55,  -55,  -55,  -55
+    },
+
+    {
+        7,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
+      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
+
+      -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,  -56,
+      -56,  -56,  -56,  -56,  -56,   40,   40,  -56,  -56,   40,
+      -56,  -56,  -56,  -56,  -56,  -56,   40,  -56,   56,   56,
+       56,   56,   56,   56,   56,   56,   56,   56,  -56,   40,
+      -56,  -56,  -56,  -56,   40,   40,   40,   40,   40,   40,
+       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+       40,  -56,   40,  -56,   40,   40,  -56,   40,   40,   40,
+       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+
+       40,   40,   40,  -56,  -56,  -56,  -56,  -56
     },
 
     } ;
@@ -1315,8 +1333,8 @@ static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner );
        *yy_cp = '\0'; \
        yyg->yy_c_buf_p = yy_cp;
 
-#define YY_NUM_RULES 35
-#define YY_END_OF_BUFFER 36
+#define YY_NUM_RULES 36
+#define YY_END_OF_BUFFER 37
 /* This struct is not used in this scanner,
    but its presence is necessary. */
 struct yy_trans_info
@@ -1324,24 +1342,24 @@ struct yy_trans_info
        flex_int32_t yy_verify;
        flex_int32_t yy_nxt;
        };
-static yyconst flex_int16_t yy_accept[56] =
+static yyconst flex_int16_t yy_accept[57] =
     {   0,
-        0,    0,    0,    0,   32,   32,   36,   35,   25,   27,
-       19,   35,   29,   29,   17,    2,   22,   23,   15,   13,
-       14,   16,   28,   20,    9,    3,    8,   18,    1,   35,
-       31,   30,   32,   33,   33,   12,    0,   26,   29,   24,
-        5,   29,   28,   21,   11,    6,    7,   10,    4,    0,
-       31,   30,   32,   34,   28
+        0,    0,    0,    0,   33,   33,   37,   36,   26,   28,
+       20,   36,   30,   30,   18,    2,   23,   24,   16,   13,
+       14,   15,   17,   29,   21,    9,    3,    8,   19,    1,
+       36,   32,   31,   33,   34,   34,   12,    0,   27,   30,
+       25,    5,   30,   29,   22,   11,    6,    7,   10,    4,
+        0,   32,   31,   33,   35,   29
     } ;
 
-static yyconst yy_state_type yy_NUL_trans[56] =
+static yyconst yy_state_type yy_NUL_trans[57] =
     {   0,
-        8,    8,   30,   30,   33,   33,    0,    0,    0,    0,
-        0,   37,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,   50,
-        0,    0,   53,    0,    0,    0,   37,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,   50,
-        0,    0,   53,    0,    0
+        8,    8,   31,   31,   34,   34,    0,    0,    0,    0,
+        0,   38,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+       51,    0,    0,   54,    0,    0,    0,   38,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+       51,    0,    0,   54,    0,    0
     } ;
 
 /* The intent behind this definition is that it'll catch
@@ -1390,12 +1408,12 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #endif
 
 #ifdef __USE_ISOC99
-#define FP___PRINTF "%.16Lg"
+#define FP___PRINTF "%.18Lg"
 #define FP___FMOD   fmodl
 #define FP___STRTOD  strtold
 #define FP___TYPE    long double
 #else
-#define FP___PRINTF "%.8g"
+#define FP___PRINTF "%.16g"
 #define FP___FMOD   fmod
 #define FP___STRTOD  strtod
 #define FP___TYPE    double
@@ -1416,7 +1434,10 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
 #include "asterisk/ast_expr.h"
 #include "asterisk/logger.h"
+#ifndef STANDALONE
 #include "asterisk/strings.h"
+#include "asterisk/channel.h"
+#endif
 
 enum valtype {
        AST_EXPR_number, AST_EXPR_numeric_string, AST_EXPR_string
@@ -1455,6 +1476,7 @@ struct parse_io
        char *string;
        struct val *val;
        yyscan_t scanner;
+       struct ast_channel *chan;
 };
  
 void ast_yyset_column(int column_no, yyscan_t yyscanner);
@@ -1462,7 +1484,7 @@ int ast_yyget_column(yyscan_t yyscanner);
 static int curlycount = 0;
 static char *expr2_token_subst(char *mess);
 
-#line 1466 "ast_expr2f.c"
+#line 1488 "ast_expr2f.c"
 
 #define INITIAL 0
 #define var 1
@@ -1685,10 +1707,10 @@ YY_DECL
        register int yy_act;
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
 
-#line 121 "ast_expr2.fl"
+#line 125 "ast_expr2.fl"
 
 
-#line 1692 "ast_expr2f.c"
+#line 1714 "ast_expr2f.c"
 
     yylval = yylval_param;
 
@@ -1771,122 +1793,127 @@ do_action:    /* This label is used only to access EOF actions. */
 
 case 1:
 YY_RULE_SETUP
-#line 123 "ast_expr2.fl"
+#line 127 "ast_expr2.fl"
 { SET_COLUMNS; SET_STRING; return TOK_OR;}
        YY_BREAK
 case 2:
 YY_RULE_SETUP
-#line 124 "ast_expr2.fl"
+#line 128 "ast_expr2.fl"
 { SET_COLUMNS; SET_STRING; return TOK_AND;}
        YY_BREAK
 case 3:
 YY_RULE_SETUP
-#line 125 "ast_expr2.fl"
+#line 129 "ast_expr2.fl"
 { SET_COLUMNS; SET_STRING; return TOK_EQ;}
        YY_BREAK
 case 4:
 YY_RULE_SETUP
-#line 126 "ast_expr2.fl"
+#line 130 "ast_expr2.fl"
 { SET_COLUMNS; SET_STRING; return TOK_OR;}
        YY_BREAK
 case 5:
 YY_RULE_SETUP
-#line 127 "ast_expr2.fl"
+#line 131 "ast_expr2.fl"
 { SET_COLUMNS; SET_STRING; return TOK_AND;}
        YY_BREAK
 case 6:
 YY_RULE_SETUP
-#line 128 "ast_expr2.fl"
+#line 132 "ast_expr2.fl"
 { SET_COLUMNS; SET_STRING; return TOK_EQ;}
        YY_BREAK
 case 7:
 YY_RULE_SETUP
-#line 129 "ast_expr2.fl"
+#line 133 "ast_expr2.fl"
 { SET_COLUMNS; SET_STRING; return TOK_EQTILDE;}
        YY_BREAK
 case 8:
 YY_RULE_SETUP
-#line 130 "ast_expr2.fl"
+#line 134 "ast_expr2.fl"
 { SET_COLUMNS; SET_STRING; return TOK_GT;}
        YY_BREAK
 case 9:
 YY_RULE_SETUP
-#line 131 "ast_expr2.fl"
+#line 135 "ast_expr2.fl"
 { SET_COLUMNS; SET_STRING; return TOK_LT;}
        YY_BREAK
 case 10:
 YY_RULE_SETUP
-#line 132 "ast_expr2.fl"
+#line 136 "ast_expr2.fl"
 { SET_COLUMNS; SET_STRING; return TOK_GE;}
        YY_BREAK
 case 11:
 YY_RULE_SETUP
-#line 133 "ast_expr2.fl"
+#line 137 "ast_expr2.fl"
 { SET_COLUMNS; SET_STRING; return TOK_LE;}
        YY_BREAK
 case 12:
 YY_RULE_SETUP
-#line 134 "ast_expr2.fl"
+#line 138 "ast_expr2.fl"
 { SET_COLUMNS; SET_STRING; return TOK_NE;}
        YY_BREAK
 case 13:
 YY_RULE_SETUP
-#line 135 "ast_expr2.fl"
+#line 139 "ast_expr2.fl"
 { SET_COLUMNS; SET_STRING; return TOK_PLUS;}
        YY_BREAK
 case 14:
 YY_RULE_SETUP
-#line 136 "ast_expr2.fl"
-{ SET_COLUMNS; SET_STRING; return TOK_MINUS;}
+#line 140 "ast_expr2.fl"
+{ SET_COLUMNS; SET_STRING; return TOK_COMMA;}
        YY_BREAK
 case 15:
 YY_RULE_SETUP
-#line 137 "ast_expr2.fl"
-{ SET_COLUMNS; SET_STRING; return TOK_MULT;}
+#line 141 "ast_expr2.fl"
+{ SET_COLUMNS; SET_STRING; return TOK_MINUS;}
        YY_BREAK
 case 16:
 YY_RULE_SETUP
-#line 138 "ast_expr2.fl"
-{ SET_COLUMNS; SET_STRING; return TOK_DIV;}
+#line 142 "ast_expr2.fl"
+{ SET_COLUMNS; SET_STRING; return TOK_MULT;}
        YY_BREAK
 case 17:
 YY_RULE_SETUP
-#line 139 "ast_expr2.fl"
-{ SET_COLUMNS; SET_STRING; return TOK_MOD;}
+#line 143 "ast_expr2.fl"
+{ SET_COLUMNS; SET_STRING; return TOK_DIV;}
        YY_BREAK
 case 18:
 YY_RULE_SETUP
-#line 140 "ast_expr2.fl"
-{ SET_COLUMNS; SET_STRING; return TOK_COND;}
+#line 144 "ast_expr2.fl"
+{ SET_COLUMNS; SET_STRING; return TOK_MOD;}
        YY_BREAK
 case 19:
 YY_RULE_SETUP
-#line 141 "ast_expr2.fl"
-{ SET_COLUMNS; SET_STRING; return TOK_COMPL;}
+#line 145 "ast_expr2.fl"
+{ SET_COLUMNS; SET_STRING; return TOK_COND;}
        YY_BREAK
 case 20:
 YY_RULE_SETUP
-#line 142 "ast_expr2.fl"
-{ SET_COLUMNS; SET_STRING; return TOK_COLON;}
+#line 146 "ast_expr2.fl"
+{ SET_COLUMNS; SET_STRING; return TOK_COMPL;}
        YY_BREAK
 case 21:
 YY_RULE_SETUP
-#line 143 "ast_expr2.fl"
-{ SET_COLUMNS; SET_STRING; return TOK_COLONCOLON;}
+#line 147 "ast_expr2.fl"
+{ SET_COLUMNS; SET_STRING; return TOK_COLON;}
        YY_BREAK
 case 22:
 YY_RULE_SETUP
-#line 144 "ast_expr2.fl"
-{ SET_COLUMNS; SET_STRING; return TOK_LP;}
+#line 148 "ast_expr2.fl"
+{ SET_COLUMNS; SET_STRING; return TOK_COLONCOLON;}
        YY_BREAK
 case 23:
 YY_RULE_SETUP
-#line 145 "ast_expr2.fl"
-{ SET_COLUMNS; SET_STRING; return TOK_RP;}
+#line 149 "ast_expr2.fl"
+{ SET_COLUMNS; SET_STRING; return TOK_LP;}
        YY_BREAK
 case 24:
 YY_RULE_SETUP
-#line 146 "ast_expr2.fl"
+#line 150 "ast_expr2.fl"
+{ SET_COLUMNS; SET_STRING; return TOK_RP;}
+       YY_BREAK
+case 25:
+YY_RULE_SETUP
+#line 151 "ast_expr2.fl"
 {
                /* gather the contents of ${} expressions, with trailing stuff,
                 * into a single TOKEN.
@@ -1897,26 +1924,26 @@ YY_RULE_SETUP
                yymore();
        }
        YY_BREAK
-case 25:
+case 26:
 YY_RULE_SETUP
-#line 156 "ast_expr2.fl"
+#line 161 "ast_expr2.fl"
 {}
        YY_BREAK
-case 26:
-/* rule 26 can match eol */
+case 27:
+/* rule 27 can match eol */
 YY_RULE_SETUP
-#line 157 "ast_expr2.fl"
+#line 162 "ast_expr2.fl"
 {SET_COLUMNS; SET_STRING; return TOKEN;}
        YY_BREAK
-case 27:
-/* rule 27 can match eol */
+case 28:
+/* rule 28 can match eol */
 YY_RULE_SETUP
-#line 159 "ast_expr2.fl"
+#line 164 "ast_expr2.fl"
 {/* what to do with eol */}
        YY_BREAK
-case 28:
+case 29:
 YY_RULE_SETUP
-#line 160 "ast_expr2.fl"
+#line 165 "ast_expr2.fl"
 {
                SET_COLUMNS;
                /* the original behavior of the expression parser was
@@ -1926,19 +1953,19 @@ YY_RULE_SETUP
                return TOKEN;
        }
        YY_BREAK
-case 29:
+case 30:
 YY_RULE_SETUP
-#line 169 "ast_expr2.fl"
+#line 174 "ast_expr2.fl"
 {
                SET_COLUMNS;
                SET_STRING;
                return TOKEN;
        }
        YY_BREAK
-case 30:
-/* rule 30 can match eol */
+case 31:
+/* rule 31 can match eol */
 YY_RULE_SETUP
-#line 176 "ast_expr2.fl"
+#line 181 "ast_expr2.fl"
 {
                curlycount--;
                if (curlycount < 0) {
@@ -1949,18 +1976,18 @@ YY_RULE_SETUP
                }
        }
        YY_BREAK
-case 31:
-/* rule 31 can match eol */
+case 32:
+/* rule 32 can match eol */
 YY_RULE_SETUP
-#line 186 "ast_expr2.fl"
+#line 191 "ast_expr2.fl"
 {
                curlycount++;
                yymore();
        }
        YY_BREAK
-case 32:
+case 33:
 YY_RULE_SETUP
-#line 192 "ast_expr2.fl"
+#line 197 "ast_expr2.fl"
 {
                BEGIN(0);
                SET_COLUMNS;
@@ -1968,10 +1995,10 @@ YY_RULE_SETUP
                return TOKEN;
        }
        YY_BREAK
-case 33:
-/* rule 33 can match eol */
+case 34:
+/* rule 34 can match eol */
 YY_RULE_SETUP
-#line 199 "ast_expr2.fl"
+#line 204 "ast_expr2.fl"
 {
                char c = yytext[yyleng-1];
                BEGIN(0);
@@ -1981,9 +2008,9 @@ YY_RULE_SETUP
                return TOKEN;
        }
        YY_BREAK
-case 34:
+case 35:
 YY_RULE_SETUP
-#line 208 "ast_expr2.fl"
+#line 213 "ast_expr2.fl"
 {
                curlycount = 0;
                BEGIN(var);
@@ -1991,7 +2018,7 @@ YY_RULE_SETUP
        }
        YY_BREAK
 case YY_STATE_EOF(trail):
-#line 214 "ast_expr2.fl"
+#line 219 "ast_expr2.fl"
 {
                BEGIN(0);
                SET_COLUMNS;
@@ -2000,12 +2027,12 @@ case YY_STATE_EOF(trail):
                /*actually, if an expr is only a variable ref, this could happen a LOT */
        }
        YY_BREAK
-case 35:
+case 36:
 YY_RULE_SETUP
-#line 222 "ast_expr2.fl"
+#line 227 "ast_expr2.fl"
 ECHO;
        YY_BREAK
-#line 2009 "ast_expr2f.c"
+#line 2036 "ast_expr2f.c"
 case YY_STATE_EOF(INITIAL):
 case YY_STATE_EOF(var):
        yyterminate();
@@ -3138,7 +3165,7 @@ void ast_yyfree (void * ptr , yyscan_t yyscanner)
 #undef YY_DECL_IS_OURS
 #undef YY_DECL
 #endif
-#line 222 "ast_expr2.fl"
+#line 227 "ast_expr2.fl"
 
 
 
@@ -3151,13 +3178,14 @@ void ast_yyfree (void * ptr , yyscan_t yyscanner)
 int ast_yyparse(void *); /* need to/should define this prototype for the call to yyparse */
 int ast_yyerror(const char *, YYLTYPE *, struct parse_io *); /* likewise */
 
-int ast_expr(char *expr, char *buf, int length)
+int ast_expr(char *expr, char *buf, int length, struct ast_channel *chan)
 {
        struct parse_io io;
        int return_value = 0;
        
        memset(&io, 0, sizeof(io));
        io.string = expr;  /* to pass to the error routine */
+       io.chan = chan;
        
        ast_yylex_init(&io.scanner);
        
@@ -3231,6 +3259,7 @@ static char *expr2_token_equivs1[] =
        "TOK_COMPL",
        "TOK_COLON",
        "TOK_EQTILDE",
+       "TOK_COMMA",
        "TOK_RP",
        "TOK_LP"
 };
@@ -3256,6 +3285,7 @@ static char *expr2_token_equivs2[] =
        "!",
        ":",
        "=~",
+       ",",
        ")",
        "("
 };
index 440e584..44f507a 100644 (file)
@@ -1677,7 +1677,7 @@ static void pbx_substitute_variables_helper_full(struct ast_channel *c, struct v
                                vars = var;
                        }
 
-                       length = ast_expr(vars, cp2, count);
+                       length = ast_expr(vars, cp2, count, c);
 
                        if (length) {
                                ast_debug(1, "Expression result is '%s'\n", cp2);
index d5d58b3..243193e 100644 (file)
@@ -90,7 +90,7 @@ void check_pval_item(pval *item, struct argapp *apps, int in_globals);
 void check_switch_expr(pval *item, struct argapp *apps);
 void ast_expr_register_extra_error_info(char *errmsg);
 void ast_expr_clear_extra_error_info(void);
-int  ast_expr(char *expr, char *buf, int length);
+int  ast_expr(char *expr, char *buf, int length,struct ast_channel *chan);
 struct pval *find_macro(char *name);
 struct pval *find_context(char *name);
 struct pval *find_context(char *name);
@@ -2640,7 +2640,7 @@ void check_pval_item(pval *item, struct argapp *apps, int in_globals)
                if( !in_globals ) { /* don't check stuff inside the globals context; no wrapping in $[ ] there... */
                        snprintf(errmsg,sizeof(errmsg), "file %s, line %d, columns %d-%d, variable declaration expr '%s':", config, item->startline, item->startcol, item->endcol, item->u2.val);
                        ast_expr_register_extra_error_info(errmsg);
-                       ast_expr(item->u2.val, expr_output, sizeof(expr_output));
+                       ast_expr(item->u2.val, expr_output, sizeof(expr_output),NULL);
                        ast_expr_clear_extra_error_info();
                        if ( strpbrk(item->u2.val,"~!-+<>=*/&^") && !strstr(item->u2.val,"${") ) {
                                ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: expression %s has operators, but no variables. Interesting...\n",
@@ -2686,12 +2686,12 @@ void check_pval_item(pval *item, struct argapp *apps, int in_globals)
 
                strp = strchr(item->u1.for_init, '=');
                if (strp) {
-                       ast_expr(strp+1, expr_output, sizeof(expr_output));
+                       ast_expr(strp+1, expr_output, sizeof(expr_output),NULL);
                }
-               ast_expr(item->u2.for_test, expr_output, sizeof(expr_output));
+               ast_expr(item->u2.for_test, expr_output, sizeof(expr_output),NULL);
                strp = strchr(item->u3.for_inc, '=');
                if (strp) {
-                       ast_expr(strp+1, expr_output, sizeof(expr_output));
+                       ast_expr(strp+1, expr_output, sizeof(expr_output),NULL);
                }
                if ( strpbrk(item->u2.for_test,"~!-+<>=*/&^") && !strstr(item->u2.for_test,"${") ) {
                        ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: expression %s has operators, but no variables. Interesting...\n",
@@ -2717,7 +2717,7 @@ void check_pval_item(pval *item, struct argapp *apps, int in_globals)
                */
                snprintf(errmsg,sizeof(errmsg),"file %s, line %d, columns %d-%d, while expr '%s':", config, item->startline, item->startcol, item->endcol, item->u1.str);
                ast_expr_register_extra_error_info(errmsg);
-               ast_expr(item->u1.str, expr_output, sizeof(expr_output));
+               ast_expr(item->u1.str, expr_output, sizeof(expr_output),NULL);
                ast_expr_clear_extra_error_info();
                if ( strpbrk(item->u1.str,"~!-+<>=*/&^") && !strstr(item->u1.str,"${") ) {
                        ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: expression %s has operators, but no variables. Interesting...\n",
@@ -2754,7 +2754,7 @@ void check_pval_item(pval *item, struct argapp *apps, int in_globals)
                */
                snprintf(errmsg,sizeof(errmsg),"file %s, line %d, columns %d-%d, random expr '%s':", config, item->startline, item->startcol, item->endcol, item->u1.str);
                ast_expr_register_extra_error_info(errmsg);
-               ast_expr(item->u1.str, expr_output, sizeof(expr_output));
+               ast_expr(item->u1.str, expr_output, sizeof(expr_output),NULL);
                ast_expr_clear_extra_error_info();
                if ( strpbrk(item->u1.str,"~!-+<>=*/&^") && !strstr(item->u1.str,"${") ) {
                        ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: random expression '%s' has operators, but no variables. Interesting...\n",
@@ -2797,7 +2797,7 @@ void check_pval_item(pval *item, struct argapp *apps, int in_globals)
                */
                snprintf(errmsg,sizeof(errmsg),"file %s, line %d, columns %d-%d, if expr '%s':", config, item->startline, item->startcol, item->endcol, item->u1.str);
                ast_expr_register_extra_error_info(errmsg);
-               ast_expr(item->u1.str, expr_output, sizeof(expr_output));
+               ast_expr(item->u1.str, expr_output, sizeof(expr_output),NULL);
                ast_expr_clear_extra_error_info();
                if ( strpbrk(item->u1.str,"~!-+<>=*/&^") && !strstr(item->u1.str,"${") ) {
                        ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: expression '%s' has operators, but no variables. Interesting...\n",
index f32e0b5..9cd0bfd 100644 (file)
@@ -110,6 +110,15 @@ struct ast_app *pbx_findapp(const char *app)
        return (struct ast_app*)1; /* so as not to trigger an error */
 }
 
+struct ast_custom_function *ast_custom_function_find(const char *name);
+
+
+struct ast_custom_function *ast_custom_function_find(const char *name)
+{
+       return 0; /* in "standalone" mode, functions are just not avail */
+}
+
+
 void ast_add_profile(void)
 {
        if (!no_comp)
index df74b71..7f0378b 100644 (file)
@@ -161,6 +161,13 @@ unsigned int check_expr(char* buffer, char* error_report)
        return warn_found;
 }
 
+struct ast_custom_function *ast_custom_function_find(const char *name);
+
+struct ast_custom_function *ast_custom_function_find(const char *name)
+{
+       return 0;
+}
+
 int check_eval(char *buffer, char *error_report)
 {
        char *cp, *ep;
@@ -221,7 +228,7 @@ int check_eval(char *buffer, char *error_report)
        *ep++ = 0;
 
        /* now, run the test */
-       result = ast_expr(evalbuf, s, sizeof(s));
+       result = ast_expr(evalbuf, s, sizeof(s),NULL);
        if (result) {
                sprintf(error_report,"line %d, evaluation of $[ %s ] result: %s\n", global_lineno, evalbuf, s);
                return 1;
index 0dfc862..9e1532b 100644 (file)
@@ -93,4 +93,34 @@ something
 2.1+4.2
 1.500003+1.4999999999999898989898989898989898989889898
 1/4
-
+2.3 + COS(3.141592653)
+REMAINDER(13,3)
+2.3 + SIN(3.1415823)
+TAN(45) + 2.3
+POW(10.0,4.0)
+SQRT(4)
+SQRT(2)
+FLOOR(2.4)
+FLOOR(2.6)
+CEIL(2.4)
+CEIL(2.6)
+ROUND(2.4)
+ROUND(2.5)
+ROUND(2.6)
+RINT(2.4)
+RINT(2.5)
+RINT(2.6)
+TRUNC(2.4)
+TRUNC(2.5)
+TRUNC(2.6)
+EXP(1.0)
+EXP2(1.0)
+LOG(10)
+LOG2(10)
+LOG10(10)
+ATAN2(4,5)
+ACOS(12)
+ASIN(1)
+ATAN(10)
+SQRT(2)*SQRT(2)
+MATH(3*9)