Merge "stasis_bridges: Remove silly usage of RAII_VAR."
[asterisk/asterisk.git] / main / ast_expr2.y
1 %{
2 /* Written by Pace Willisson (pace@blitz.com)
3  * and placed in the public domain.
4  *
5  * Largely rewritten by J.T. Conklin (jtc@wimsey.com)
6  *
7  * And then overhauled twice by Steve Murphy (murf@digium.com)
8  * to add double-quoted strings, allow mult. spaces, improve
9  * error messages, and then to fold in a flex scanner for the
10  * yylex operation.
11  *
12  * $FreeBSD: src/bin/expr/expr.y,v 1.16 2000/07/22 10:59:36 se Exp $
13  */
14
15 #define ASTMM_LIBC ASTMM_REDIRECT
16 #include "asterisk.h"
17
18 #include <sys/cdefs.h>
19 #include <sys/types.h>
20 #include <stdio.h>
21
22 #if defined(STANDALONE) || defined(STANDALONE2)
23 #ifndef __USE_ISOC99
24 #define __USE_ISOC99 1
25 #endif
26 #endif
27
28 #ifdef __USE_ISOC99
29 #define FP___PRINTF "%.18Lg"
30 #define FP___TYPE    long double
31 #else
32 #define FP___PRINTF "%.16g"
33 #define FP___TYPE    double
34 #endif
35
36 #ifdef HAVE_COSL
37 #define FUNC_COS   cosl
38 #elif defined(HAVE_COS)
39 #define FUNC_COS        (long double)cos
40 #endif
41
42 #ifdef HAVE_SINL
43 #define FUNC_SIN   sinl
44 #elif defined(HAVE_SIN)
45 #define FUNC_SIN        (long double)sin
46 #endif
47
48 #ifdef HAVE_TANL
49 #define FUNC_TAN   tanl
50 #elif defined(HAVE_TAN)
51 #define FUNC_TAN        (long double)tan
52 #endif
53
54 #ifdef HAVE_ACOSL
55 #define FUNC_ACOS   acosl
56 #elif defined(HAVE_ACOS)
57 #define FUNC_ACOS       (long double)acos
58 #endif
59
60 #ifdef HAVE_ASINL
61 #define FUNC_ASIN   asinl
62 #elif defined(HAVE_ASIN)
63 #define FUNC_ASIN       (long double)asin
64 #endif
65
66 #ifdef HAVE_ATANL
67 #define FUNC_ATAN   atanl
68 #elif defined(HAVE_ATAN)
69 #define FUNC_ATAN       (long double)atan
70 #endif
71
72 #ifdef HAVE_ATAN2L
73 #define FUNC_ATAN2   atan2l
74 #elif defined(HAVE_ATAN2)
75 #define FUNC_ATAN2      (long double)atan2
76 #endif
77
78 #ifdef HAVE_POWL
79 #define FUNC_POW   powl
80 #elif defined(HAVE_POW)
81 #define FUNC_POW        (long double)pow
82 #endif
83
84 #ifdef HAVE_SQRTL
85 #define FUNC_SQRT   sqrtl
86 #elif defined(HAVE_SQRT)
87 #define FUNC_SQRT       (long double)sqrt
88 #endif
89
90 #ifdef HAVE_RINTL
91 #define FUNC_RINT   rintl
92 #elif defined(HAVE_RINT)
93 #define FUNC_RINT       (long double)rint
94 #endif
95
96 #ifdef HAVE_EXPL
97 #define FUNC_EXP   expl
98 #elif defined(HAVE_EXP)
99 #define FUNC_EXP        (long double)exp
100 #endif
101
102 #ifdef HAVE_LOGL
103 #define FUNC_LOG   logl
104 #elif defined(HAVE_LOG)
105 #define FUNC_LOG        (long double)log
106 #endif
107
108 #ifdef HAVE_REMAINDERL
109 #define FUNC_REMAINDER   remainderl
110 #elif defined(HAVE_REMAINDER)
111 #define FUNC_REMAINDER  (long double)remainder
112 #endif
113
114 #ifdef HAVE_FMODL
115 #define FUNC_FMOD   fmodl
116 #elif defined(HAVE_FMOD)
117 #define FUNC_FMOD       (long double)fmod
118 #endif
119
120 #ifdef HAVE_STRTOLD
121 #define FUNC_STRTOD  strtold
122 #elif defined(HAVE_STRTOD)
123 #define FUNC_STRTOD  (long double)strtod
124 #endif
125
126 #ifdef HAVE_FLOORL
127 #define FUNC_FLOOR      floorl
128 #elif defined(HAVE_FLOOR)
129 #define FUNC_FLOOR      (long double)floor
130 #endif
131
132 #ifdef HAVE_CEILL
133 #define FUNC_CEIL      ceill
134 #elif defined(HAVE_CEIL)
135 #define FUNC_CEIL       (long double)ceil
136 #endif
137
138 #ifdef HAVE_ROUNDL
139 #define FUNC_ROUND     roundl
140 #elif defined(HAVE_ROUND)
141 #define FUNC_ROUND     (long double)round
142 #endif
143
144 #ifdef HAVE_TRUNCL
145 #define FUNC_TRUNC     truncl
146 #elif defined(HAVE_TRUNC)
147 #define FUNC_TRUNC     (long double)trunc
148 #endif
149
150 /*! \note
151  * Oddly enough, some platforms have some ISO C99 functions, but not others, so
152  * we define the missing functions in terms of their mathematical identities.
153  */
154 #ifdef HAVE_EXP2L
155 #define FUNC_EXP2       exp2l
156 #elif (defined(HAVE_EXPL) && defined(HAVE_LOGL))
157 #define FUNC_EXP2(x)    expl((x) * logl(2.0))
158 #elif (defined(HAVE_EXP) && defined(HAVE_LOG))
159 #define FUNC_EXP2(x)    (long double)exp((x) * log(2.0))
160 #endif
161
162 #ifdef HAVE_EXP10L
163 #define FUNC_EXP10       exp10l
164 #elif (defined(HAVE_EXPL) && defined(HAVE_LOGL))
165 #define FUNC_EXP10(x)   expl((x) * logl(10.0))
166 #elif (defined(HAVE_EXP) && defined(HAVE_LOG))
167 #define FUNC_EXP10(x)   (long double)exp((x) * log(10.0))
168 #endif
169
170 #ifdef HAVE_LOG2L
171 #define FUNC_LOG2       log2l
172 #elif defined(HAVE_LOGL)
173 #define FUNC_LOG2(x)    (logl(x) / logl(2.0))
174 #elif defined(HAVE_LOG10L)
175 #define FUNC_LOG2(x)    (log10l(x) / log10l(2.0))
176 #elif defined(HAVE_LOG2)
177 #define FUNC_LOG2       (long double)log2
178 #elif defined(HAVE_LOG)
179 #define FUNC_LOG2(x)    ((long double)log(x) / log(2.0))
180 #endif
181
182 #ifdef HAVE_LOG10L
183 #define FUNC_LOG10       log10l
184 #elif defined(HAVE_LOGL)
185 #define FUNC_LOG10(x)   (logl(x) / logl(10.0))
186 #elif defined(HAVE_LOG2L)
187 #define FUNC_LOG10(x)   (log2l(x) / log2l(10.0))
188 #elif defined(HAVE_LOG10)
189 #define FUNC_LOG10(x)   (long double)log10(x)
190 #elif defined(HAVE_LOG)
191 #define FUNC_LOG10(x)   ((long double)log(x) / log(10.0))
192 #endif
193
194
195 #include <stdlib.h>
196 #ifndef _GNU_SOURCE
197 #define _GNU_SOURCE
198 #endif
199 #include <string.h>
200 #include <math.h>
201 #include <locale.h>
202 #include <unistd.h>
203 #include <ctype.h>
204 #if !defined(SOLARIS) && !defined(__CYGWIN__)
205         /* #include <err.h> */
206 #else
207 #define quad_t int64_t
208 #endif
209 #include <errno.h>
210 #include <regex.h>
211 #include <limits.h>
212
213 #include "asterisk/ast_expr.h"
214 #include "asterisk/logger.h"
215 #if !defined(STANDALONE) && !defined(STANDALONE2)
216 #include "asterisk/pbx.h"
217 #endif
218
219 #if defined(LONG_LONG_MIN) && !defined(QUAD_MIN)
220 #define QUAD_MIN LONG_LONG_MIN
221 #endif
222 #if defined(LONG_LONG_MAX) && !defined(QUAD_MAX)
223 #define QUAD_MAX LONG_LONG_MAX
224 #endif
225
226 #  if ! defined(QUAD_MIN)
227 #   define QUAD_MIN     (-0x7fffffffffffffffLL-1)
228 #  endif
229 #  if ! defined(QUAD_MAX)
230 #   define QUAD_MAX     (0x7fffffffffffffffLL)
231 #  endif
232 #define YYENABLE_NLS 0
233 #define YYPARSE_PARAM parseio
234 #define YYLEX_PARAM ((struct parse_io *)parseio)->scanner
235 #define YYERROR_VERBOSE 1
236 extern char extra_error_message[4095];
237 extern int extra_error_message_supplied;
238
239 enum valtype {
240         AST_EXPR_number, AST_EXPR_numeric_string, AST_EXPR_string
241 } ;
242
243 #if defined(STANDALONE) || defined(STANDALONE2)
244 void ast_log(int level, const char *file, int line, const char *function, const char *fmt, ...) __attribute__ ((format (printf,5,6)));
245 #endif
246
247 struct val {
248         enum valtype type;
249         union {
250                 char *s;
251                 FP___TYPE i; /* either long double, or just double, on a bad day */
252         } u;
253 } ;
254
255 enum node_type {
256         AST_EXPR_NODE_COMMA, AST_EXPR_NODE_STRING, AST_EXPR_NODE_VAL
257 } ;
258
259 struct expr_node
260 {
261         enum node_type type;
262         struct val *val;
263         struct expr_node *left;
264         struct expr_node *right;
265 };
266
267
268 typedef void *yyscan_t;
269
270 struct parse_io
271 {
272         char *string;
273         struct val *val;
274         yyscan_t scanner;
275         struct ast_channel *chan;
276 };
277
278 static int              chk_div __P((FP___TYPE, FP___TYPE));
279 static int              chk_minus __P((FP___TYPE, FP___TYPE, FP___TYPE));
280 static int              chk_plus __P((FP___TYPE, FP___TYPE, FP___TYPE));
281 static int              chk_times __P((FP___TYPE, FP___TYPE, FP___TYPE));
282 static void             free_value __P((struct val *));
283 static int              is_zero_or_null __P((struct val *));
284 static int              isstring __P((struct val *));
285 static struct val       *make_number __P((FP___TYPE));
286 static struct val       *make_str __P((const char *));
287 static struct val       *op_and __P((struct val *, struct val *));
288 static struct val       *op_colon __P((struct val *, struct val *));
289 static struct val       *op_eqtilde __P((struct val *, struct val *));
290 static struct val       *op_tildetilde __P((struct val *, struct val *));
291 static struct val       *op_div __P((struct val *, struct val *));
292 static struct val       *op_eq __P((struct val *, struct val *));
293 static struct val       *op_ge __P((struct val *, struct val *));
294 static struct val       *op_gt __P((struct val *, struct val *));
295 static struct val       *op_le __P((struct val *, struct val *));
296 static struct val       *op_lt __P((struct val *, struct val *));
297 static struct val       *op_cond __P((struct val *, struct val *, struct val *));
298 static struct val       *op_minus __P((struct val *, struct val *));
299 static struct val       *op_negate __P((struct val *));
300 static struct val       *op_compl __P((struct val *));
301 static struct val       *op_ne __P((struct val *, struct val *));
302 static struct val       *op_or __P((struct val *, struct val *));
303 static struct val       *op_plus __P((struct val *, struct val *));
304 static struct val       *op_rem __P((struct val *, struct val *));
305 static struct val       *op_times __P((struct val *, struct val *));
306 static struct val   *op_func(struct val *funcname, struct expr_node *arglist, struct ast_channel *chan);
307 static int              to_number __P((struct val *));
308 static void             to_string __P((struct val *));
309 static struct expr_node *alloc_expr_node(enum node_type);
310 static void destroy_arglist(struct expr_node *arglist);
311
312 /* uh, if I want to predeclare yylex with a YYLTYPE, I have to predeclare the yyltype... sigh */
313 typedef struct yyltype
314 {
315   int first_line;
316   int first_column;
317
318   int last_line;
319   int last_column;
320 } yyltype;
321
322 # define YYLTYPE yyltype
323 # define YYLTYPE_IS_TRIVIAL 1
324
325 /* we will get warning about no prototype for yylex! But we can't
326    define it here, we have no definition yet for YYSTYPE. */
327
328 int             ast_yyerror(const char *,YYLTYPE *, struct parse_io *);
329
330 /* I wanted to add args to the yyerror routine, so I could print out
331    some useful info about the error. Not as easy as it looks, but it
332    is possible. */
333 #define ast_yyerror(x) ast_yyerror(x,&yyloc,parseio)
334 #define DESTROY(x) {if((x)->type == AST_EXPR_numeric_string || (x)->type == AST_EXPR_string) free((x)->u.s); (x)->u.s = 0; free(x);}
335 %}
336
337 %pure-parser
338 %locations
339 /* %debug  for when you are having big problems */
340
341 /* %name-prefix="ast_yy" */
342
343 %union
344 {
345         struct val *val;
346         struct expr_node *arglist;
347 }
348
349 %{
350 extern int              ast_yylex __P((YYSTYPE *, YYLTYPE *, yyscan_t));
351 %}
352 %left <val> TOK_COMMA
353 %left <val> TOK_COND TOK_COLONCOLON
354 %left <val> TOK_OR
355 %left <val> TOK_AND
356 %left <val> TOK_EQ TOK_GT TOK_LT TOK_GE TOK_LE TOK_NE
357 %left <val> TOK_PLUS TOK_MINUS
358 %left <val> TOK_MULT TOK_DIV TOK_MOD
359 %right <val> TOK_COMPL
360 %left <val> TOK_COLON TOK_EQTILDE TOK_TILDETILDE
361 %left <val> TOK_RP TOK_LP
362
363 %token <val> TOKEN
364 %type <arglist> arglist
365 %type <val> start expr
366
367 %destructor {  free_value($$); }  expr TOKEN TOK_COND TOK_COLONCOLON TOK_OR TOK_AND TOK_EQ
368                                  TOK_GT TOK_LT TOK_GE TOK_LE TOK_NE TOK_PLUS TOK_MINUS TOK_MULT TOK_DIV TOK_MOD TOK_COMPL TOK_COLON TOK_EQTILDE
369                                  TOK_RP TOK_LP TOK_TILDETILDE
370
371 %%
372
373 start: expr { ((struct parse_io *)parseio)->val = (struct val *)calloc(sizeof(struct val),1);
374               ((struct parse_io *)parseio)->val->type = $1->type;
375               if( $1->type == AST_EXPR_number )
376                                   ((struct parse_io *)parseio)->val->u.i = $1->u.i;
377               else
378                                   ((struct parse_io *)parseio)->val->u.s = $1->u.s;
379                           free($1);
380                         }
381         | {/* nothing */ ((struct parse_io *)parseio)->val = (struct val *)calloc(sizeof(struct val),1);
382               ((struct parse_io *)parseio)->val->type = AST_EXPR_string;
383                           ((struct parse_io *)parseio)->val->u.s = strdup("");
384                         }
385
386         ;
387
388 arglist: expr { $$ = alloc_expr_node(AST_EXPR_NODE_VAL); $$->val = $1;}
389        | arglist TOK_COMMA expr %prec TOK_RP {struct expr_node *x = alloc_expr_node(AST_EXPR_NODE_VAL);
390                                  struct expr_node *t;
391                                                                  DESTROY($2);
392                                  for (t=$1;t->right;t=t->right)
393                                                                   ;
394                                  $$ = $1; t->right = x; x->val = $3;}
395        | arglist TOK_COMMA %prec TOK_RP {struct expr_node *x = alloc_expr_node(AST_EXPR_NODE_VAL);
396                                  struct expr_node *t;  /* NULL args should OK */
397                                                                  DESTROY($2);
398                                  for (t=$1;t->right;t=t->right)
399                                                                   ;
400                                  $$ = $1; t->right = x; x->val = make_str("");}
401        ;
402
403 expr:
404       TOKEN TOK_LP arglist TOK_RP { $$ = op_func($1,$3, ((struct parse_io *)parseio)->chan);
405                                             DESTROY($2);
406                                                                         DESTROY($4);
407                                                                         DESTROY($1);
408                                                                         destroy_arglist($3);
409                                   }
410     | TOKEN {$$ = $1;}
411         | TOK_LP expr TOK_RP { $$ = $2;
412                                @$.first_column = @1.first_column; @$.last_column = @3.last_column;
413                                                    @$.first_line=0; @$.last_line=0;
414                                                         DESTROY($1); DESTROY($3); }
415         | expr TOK_OR expr { $$ = op_or ($1, $3);
416                                                 DESTROY($2);
417                          @$.first_column = @1.first_column; @$.last_column = @3.last_column;
418                                                  @$.first_line=0; @$.last_line=0;}
419         | expr TOK_AND expr { $$ = op_and ($1, $3);
420                                                 DESTROY($2);
421                               @$.first_column = @1.first_column; @$.last_column = @3.last_column;
422                           @$.first_line=0; @$.last_line=0;}
423         | expr TOK_EQ expr { $$ = op_eq ($1, $3);
424                                                 DESTROY($2);
425                              @$.first_column = @1.first_column; @$.last_column = @3.last_column;
426                                                  @$.first_line=0; @$.last_line=0;}
427         | expr TOK_GT expr { $$ = op_gt ($1, $3);
428                                                 DESTROY($2);
429                          @$.first_column = @1.first_column; @$.last_column = @3.last_column;
430                                                  @$.first_line=0; @$.last_line=0;}
431         | expr TOK_LT expr { $$ = op_lt ($1, $3);
432                                                 DESTROY($2);
433                              @$.first_column = @1.first_column; @$.last_column = @3.last_column;
434                                                  @$.first_line=0; @$.last_line=0;}
435         | expr TOK_GE expr  { $$ = op_ge ($1, $3);
436                                                 DESTROY($2);
437                               @$.first_column = @1.first_column; @$.last_column = @3.last_column;
438                                                   @$.first_line=0; @$.last_line=0;}
439         | expr TOK_LE expr  { $$ = op_le ($1, $3);
440                                                 DESTROY($2);
441                               @$.first_column = @1.first_column; @$.last_column = @3.last_column;
442                                                   @$.first_line=0; @$.last_line=0;}
443         | expr TOK_NE expr  { $$ = op_ne ($1, $3);
444                                                 DESTROY($2);
445                               @$.first_column = @1.first_column; @$.last_column = @3.last_column;
446                                                   @$.first_line=0; @$.last_line=0;}
447         | expr TOK_PLUS expr { $$ = op_plus ($1, $3);
448                                                 DESTROY($2);
449                                @$.first_column = @1.first_column; @$.last_column = @3.last_column;
450                                                    @$.first_line=0; @$.last_line=0;}
451         | expr TOK_MINUS expr { $$ = op_minus ($1, $3);
452                                                 DESTROY($2);
453                                 @$.first_column = @1.first_column; @$.last_column = @3.last_column;
454                                                         @$.first_line=0; @$.last_line=0;}
455         | TOK_MINUS expr %prec TOK_COMPL { $$ = op_negate ($2);
456                                                 DESTROY($1);
457                                 @$.first_column = @1.first_column; @$.last_column = @2.last_column;
458                                                         @$.first_line=0; @$.last_line=0;}
459         | TOK_COMPL expr   { $$ = op_compl ($2);
460                                                 DESTROY($1);
461                                 @$.first_column = @1.first_column; @$.last_column = @2.last_column;
462                                                         @$.first_line=0; @$.last_line=0;}
463         | expr TOK_MULT expr { $$ = op_times ($1, $3);
464                                                 DESTROY($2);
465                                @$.first_column = @1.first_column; @$.last_column = @3.last_column;
466                                                    @$.first_line=0; @$.last_line=0;}
467         | expr TOK_DIV expr { $$ = op_div ($1, $3);
468                                                 DESTROY($2);
469                               @$.first_column = @1.first_column; @$.last_column = @3.last_column;
470                                                   @$.first_line=0; @$.last_line=0;}
471         | expr TOK_MOD expr { $$ = op_rem ($1, $3);
472                                                 DESTROY($2);
473                               @$.first_column = @1.first_column; @$.last_column = @3.last_column;
474                                                   @$.first_line=0; @$.last_line=0;}
475         | expr TOK_COLON expr { $$ = op_colon ($1, $3);
476                                                 DESTROY($2);
477                                 @$.first_column = @1.first_column; @$.last_column = @3.last_column;
478                                                         @$.first_line=0; @$.last_line=0;}
479         | expr TOK_EQTILDE expr { $$ = op_eqtilde ($1, $3);
480                                                 DESTROY($2);
481                                 @$.first_column = @1.first_column; @$.last_column = @3.last_column;
482                                                         @$.first_line=0; @$.last_line=0;}
483         | expr TOK_COND expr TOK_COLONCOLON expr  { $$ = op_cond ($1, $3, $5);
484                                                 DESTROY($2);
485                                                 DESTROY($4);
486                                 @$.first_column = @1.first_column; @$.last_column = @3.last_column;
487                                                         @$.first_line=0; @$.last_line=0;}
488         | expr TOK_TILDETILDE expr { $$ = op_tildetilde ($1, $3);
489                                                 DESTROY($2);
490                                 @$.first_column = @1.first_column; @$.last_column = @3.last_column;
491                                                         @$.first_line=0; @$.last_line=0;}
492         ;
493
494 %%
495
496 static struct expr_node *alloc_expr_node(enum node_type nt)
497 {
498         struct expr_node *x = calloc(1,sizeof(struct expr_node));
499         if (!x) {
500                 ast_log(LOG_ERROR, "Allocation for expr_node FAILED!!\n");
501                 return 0;
502         }
503         x->type = nt;
504         return x;
505 }
506
507
508
509 static struct val *
510 make_number (FP___TYPE i)
511 {
512         struct val *vp;
513
514         vp = (struct val *) malloc (sizeof (*vp));
515         if (vp == NULL) {
516                 ast_log(LOG_WARNING, "malloc() failed\n");
517                 return(NULL);
518         }
519
520         vp->type = AST_EXPR_number;
521         vp->u.i  = i;
522         return vp;
523 }
524
525 static struct val *
526 make_str (const char *s)
527 {
528         struct val *vp;
529         size_t i;
530         int isint; /* this started out being a test for an integer, but then ended up being a test for a float */
531
532         vp = (struct val *) malloc (sizeof (*vp));
533         if (vp == NULL || ((vp->u.s = strdup (s)) == NULL)) {
534                 if (vp) {
535                         free(vp);
536                 }
537                 ast_log(LOG_WARNING,"malloc() failed\n");
538                 return(NULL);
539         }
540
541         for (i = 0, isint = (isdigit(s[0]) || s[0] == '-' || s[0]=='.'); isint && i < strlen(s); i++)
542         {
543                 if (!isdigit(s[i]) && s[i] != '.') {
544                         isint = 0;
545                         break;
546                 }
547         }
548         if (isint)
549                 vp->type = AST_EXPR_numeric_string;
550         else
551                 vp->type = AST_EXPR_string;
552
553         return vp;
554 }
555
556
557 static void
558 free_value (struct val *vp)
559 {
560         if (vp==NULL) {
561                 return;
562         }
563         if (vp->type == AST_EXPR_string || vp->type == AST_EXPR_numeric_string)
564                 free (vp->u.s);
565         free(vp);
566 }
567
568
569 static int
570 to_number (struct val *vp)
571 {
572         FP___TYPE i;
573
574         if (vp == NULL) {
575                 ast_log(LOG_WARNING,"vp==NULL in to_number()\n");
576                 return(0);
577         }
578
579         if (vp->type == AST_EXPR_number)
580                 return 1;
581
582         if (vp->type == AST_EXPR_string)
583                 return 0;
584
585         /* vp->type == AST_EXPR_numeric_string, make it numeric */
586         errno = 0;
587         i  = FUNC_STRTOD(vp->u.s, (char**)0); /* either strtod, or strtold on a good day */
588         if (errno != 0) {
589                 ast_log(LOG_WARNING,"Conversion of %s to number under/overflowed!\n", vp->u.s);
590                 free(vp->u.s);
591                 vp->u.s = 0;
592                 return(0);
593         }
594         free (vp->u.s);
595         vp->u.i = i;
596         vp->type = AST_EXPR_number;
597         return 1;
598 }
599
600 static void
601 strip_quotes(struct val *vp)
602 {
603         if (vp->type != AST_EXPR_string && vp->type != AST_EXPR_numeric_string)
604                 return;
605
606         if( vp->u.s[0] == '"' && vp->u.s[strlen(vp->u.s)-1] == '"' )
607         {
608                 char *f, *t;
609                 f = vp->u.s;
610                 t = vp->u.s;
611
612                 while( *f )
613                 {
614                         if( *f  && *f != '"' )
615                                 *t++ = *f++;
616                         else
617                                 f++;
618                 }
619                 *t = *f;
620         }
621 }
622
623 static void
624 to_string (struct val *vp)
625 {
626         char *tmp;
627
628         if (vp->type == AST_EXPR_string || vp->type == AST_EXPR_numeric_string)
629                 return;
630
631         if (asprintf(&tmp, FP___PRINTF, vp->u.i) == -1) {
632                 ast_log(LOG_WARNING, "asprintf() failed\n");
633                 return;
634         }
635
636         vp->type = AST_EXPR_string;
637         vp->u.s  = tmp;
638 }
639
640
641 static int
642 isstring (struct val *vp)
643 {
644         /* only TRUE if this string is not a valid number */
645         return (vp->type == AST_EXPR_string);
646 }
647
648
649 static int
650 is_zero_or_null (struct val *vp)
651 {
652         if (vp->type == AST_EXPR_number) {
653                 return (vp->u.i == 0);
654         } else {
655                 return (*vp->u.s == 0 || (to_number(vp) && vp->u.i == 0));
656         }
657         /* NOTREACHED */
658 }
659
660 #ifdef STANDALONE2
661
662 void ast_log(int level, const char *file, int line, const char *function, const char *fmt, ...)
663 {
664         va_list vars;
665         va_start(vars,fmt);
666
667         printf("LOG: lev:%d file:%s  line:%d func: %s  ",
668                    level, file, line, function);
669         vprintf(fmt, vars);
670         fflush(stdout);
671         va_end(vars);
672 }
673
674
675 int main(int argc,char **argv) {
676         char s[4096];
677         char out[4096];
678         FILE *infile;
679
680         if( !argv[1] )
681                 exit(20);
682
683         if( access(argv[1],F_OK)== 0 )
684         {
685                 int ret;
686
687                 infile = fopen(argv[1],"r");
688                 if( !infile )
689                 {
690                         printf("Sorry, couldn't open %s for reading!\n", argv[1]);
691                         exit(10);
692                 }
693                 while( fgets(s,sizeof(s),infile) )
694                 {
695                         if( s[strlen(s)-1] == '\n' )
696                                 s[strlen(s)-1] = 0;
697
698                         ret = ast_expr(s, out, sizeof(out), NULL);
699                         printf("Expression: %s    Result: [%d] '%s'\n",
700                                    s, ret, out);
701                 }
702                 fclose(infile);
703         }
704         else
705         {
706                 if (ast_expr(argv[1], s, sizeof(s), NULL))
707                         printf("=====%s======\n",s);
708                 else
709                         printf("No result\n");
710         }
711         return 0;
712 }
713
714 #endif
715
716 #undef ast_yyerror
717 #define ast_yyerror(x) ast_yyerror(x, YYLTYPE *yylloc, struct parse_io *parseio)
718
719 /* I put the ast_yyerror func in the flex input file,
720    because it refers to the buffer state. Best to
721    let it access the BUFFER stuff there and not trying
722    define all the structs, macros etc. in this file! */
723
724 static void destroy_arglist(struct expr_node *arglist)
725 {
726         struct expr_node *arglist_next;
727
728         while (arglist)
729         {
730                 arglist_next = arglist->right;
731                 if (arglist->val)
732                         free_value(arglist->val);
733                 arglist->val = 0;
734                 arglist->right = 0;
735                 free(arglist);
736                 arglist = arglist_next;
737         }
738 }
739
740 #if !defined(STANDALONE) && !defined(STANDALONE2)
741 static char *compose_func_args(struct expr_node *arglist)
742 {
743         struct expr_node *t = arglist;
744         char *argbuf;
745         int total_len = 0;
746
747         while (t) {
748                 if (t != arglist)
749                         total_len += 1; /* for the sep */
750                 if (t->val) {
751                         if (t->val->type == AST_EXPR_number)
752                                 total_len += 25; /* worst case */
753                         else
754                                 total_len += strlen(t->val->u.s);
755                 }
756
757                 t = t->right;
758         }
759         total_len++; /* for the null */
760         ast_log(LOG_NOTICE,"argbuf allocated %d bytes;\n", total_len);
761         argbuf = malloc(total_len);
762         argbuf[0] = 0;
763         t = arglist;
764         while (t) {
765                 char numbuf[30];
766
767                 if (t != arglist)
768                         strcat(argbuf,",");
769
770                 if (t->val) {
771                         if (t->val->type == AST_EXPR_number) {
772                                 sprintf(numbuf,FP___PRINTF,t->val->u.i);
773                                 strcat(argbuf,numbuf);
774                         } else
775                                 strcat(argbuf,t->val->u.s);
776                 }
777                 t = t->right;
778         }
779         ast_log(LOG_NOTICE,"argbuf uses %d bytes;\n", (int) strlen(argbuf));
780         return argbuf;
781 }
782
783 static int is_really_num(char *str)
784 {
785         if ( strspn(str,"-0123456789.   ") == strlen(str))
786                 return 1;
787         else
788                 return 0;
789 }
790 #endif
791
792 static struct val *op_func(struct val *funcname, struct expr_node *arglist, struct ast_channel *chan)
793 {
794         if (strspn(funcname->u.s,"ABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789") == strlen(funcname->u.s))
795         {
796                 struct val *result;
797                 if (0) {
798 #ifdef FUNC_COS
799                 } else if (strcmp(funcname->u.s,"COS") == 0) {
800                         if (arglist && !arglist->right && arglist->val){
801                                 to_number(arglist->val);
802                                 result = make_number(FUNC_COS(arglist->val->u.i));
803                                 return result;
804                         } else {
805                                 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
806                                 return make_number(0.0);
807                         }
808 #endif
809 #ifdef FUNC_SIN
810                 } else if (strcmp(funcname->u.s,"SIN") == 0) {
811                         if (arglist && !arglist->right && arglist->val){
812                                 to_number(arglist->val);
813                                 result = make_number(FUNC_SIN(arglist->val->u.i));
814                                 return result;
815                         } else {
816                                 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
817                                 return make_number(0.0);
818                         }
819 #endif
820 #ifdef FUNC_TAN
821                 } else if (strcmp(funcname->u.s,"TAN") == 0) {
822                         if (arglist && !arglist->right && arglist->val){
823                                 to_number(arglist->val);
824                                 result = make_number(FUNC_TAN(arglist->val->u.i));
825                                 return result;
826                         } else {
827                                 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
828                                 return make_number(0.0);
829                         }
830 #endif
831 #ifdef FUNC_ACOS
832                 } else if (strcmp(funcname->u.s,"ACOS") == 0) {
833                         if (arglist && !arglist->right && arglist->val){
834                                 to_number(arglist->val);
835                                 result = make_number(FUNC_ACOS(arglist->val->u.i));
836                                 return result;
837                         } else {
838                                 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
839                                 return make_number(0.0);
840                         }
841 #endif
842 #ifdef FUNC_ASIN
843                 } else if (strcmp(funcname->u.s,"ASIN") == 0) {
844                         if (arglist && !arglist->right && arglist->val){
845                                 to_number(arglist->val);
846                                 result = make_number(FUNC_ASIN(arglist->val->u.i));
847                                 return result;
848                         } else {
849                                 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
850                                 return make_number(0.0);
851                         }
852 #endif
853 #ifdef FUNC_ATAN
854                 } else if (strcmp(funcname->u.s,"ATAN") == 0) {
855                         if (arglist && !arglist->right && arglist->val){
856                                 to_number(arglist->val);
857                                 result = make_number(FUNC_ATAN(arglist->val->u.i));
858                                 return result;
859                         } else {
860                                 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
861                                 return make_number(0.0);
862                         }
863 #endif
864 #ifdef FUNC_ATAN2
865                 } else if (strcmp(funcname->u.s,"ATAN2") == 0) {
866                         if (arglist && arglist->right && !arglist->right->right && arglist->val && arglist->right->val){
867                                 to_number(arglist->val);
868                                 to_number(arglist->right->val);
869                                 result = make_number(FUNC_ATAN2(arglist->val->u.i, arglist->right->val->u.i));
870                                 return result;
871                         } else {
872                                 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
873                                 return make_number(0.0);
874                         }
875 #endif
876 #ifdef FUNC_POW
877                 } else if (strcmp(funcname->u.s,"POW") == 0) {
878                         if (arglist && arglist->right && !arglist->right->right && arglist->val && arglist->right->val){
879                                 to_number(arglist->val);
880                                 to_number(arglist->right->val);
881                                 result = make_number(FUNC_POW(arglist->val->u.i, arglist->right->val->u.i));
882                                 return result;
883                         } else {
884                                 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
885                                 return make_number(0.0);
886                         }
887 #endif
888 #ifdef FUNC_SQRT
889                 } else if (strcmp(funcname->u.s,"SQRT") == 0) {
890                         if (arglist && !arglist->right && arglist->val){
891                                 to_number(arglist->val);
892                                 result = make_number(FUNC_SQRT(arglist->val->u.i));
893                                 return result;
894                         } else {
895                                 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
896                                 return make_number(0.0);
897                         }
898 #endif
899 #ifdef FUNC_FLOOR
900                 } else if (strcmp(funcname->u.s,"FLOOR") == 0) {
901                         if (arglist && !arglist->right && arglist->val){
902                                 to_number(arglist->val);
903                                 result = make_number(FUNC_FLOOR(arglist->val->u.i));
904                                 return result;
905                         } else {
906                                 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
907                                 return make_number(0.0);
908                         }
909 #endif
910 #ifdef FUNC_CEIL
911                 } else if (strcmp(funcname->u.s,"CEIL") == 0) {
912                         if (arglist && !arglist->right && arglist->val){
913                                 to_number(arglist->val);
914                                 result = make_number(FUNC_CEIL(arglist->val->u.i));
915                                 return result;
916                         } else {
917                                 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
918                                 return make_number(0.0);
919                         }
920 #endif
921 #ifdef FUNC_ROUND
922                 } else if (strcmp(funcname->u.s,"ROUND") == 0) {
923                         if (arglist && !arglist->right && arglist->val){
924                                 to_number(arglist->val);
925                                 result = make_number(FUNC_ROUND(arglist->val->u.i));
926                                 return result;
927                         } else {
928                                 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
929                                 return make_number(0.0);
930                         }
931 #endif /* defined(FUNC_ROUND) */
932 #ifdef FUNC_RINT
933                 } else if (strcmp(funcname->u.s,"RINT") == 0) {
934                         if (arglist && !arglist->right && arglist->val){
935                                 to_number(arglist->val);
936                                 result = make_number(FUNC_RINT(arglist->val->u.i));
937                                 return result;
938                         } else {
939                                 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
940                                 return make_number(0.0);
941                         }
942 #endif
943 #ifdef FUNC_TRUNC
944                 } else if (strcmp(funcname->u.s,"TRUNC") == 0) {
945                         if (arglist && !arglist->right && arglist->val){
946                                 to_number(arglist->val);
947                                 result = make_number(FUNC_TRUNC(arglist->val->u.i));
948                                 return result;
949                         } else {
950                                 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
951                                 return make_number(0.0);
952                         }
953 #endif /* defined(FUNC_TRUNC) */
954 #ifdef FUNC_EXP
955                 } else if (strcmp(funcname->u.s,"EXP") == 0) {
956                         if (arglist && !arglist->right && arglist->val){
957                                 to_number(arglist->val);
958                                 result = make_number(FUNC_EXP(arglist->val->u.i));
959                                 return result;
960                         } else {
961                                 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
962                                 return make_number(0.0);
963                         }
964 #endif
965 #ifdef FUNC_EXP2
966                 } else if (strcmp(funcname->u.s,"EXP2") == 0) {
967                         if (arglist && !arglist->right && arglist->val){
968                                 to_number(arglist->val);
969                                 result = make_number(FUNC_EXP2(arglist->val->u.i));
970                                 return result;
971                         } else {
972                                 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
973                                 return make_number(0.0);
974                         }
975 #endif
976 #ifdef FUNC_EXP10
977                 } else if (strcmp(funcname->u.s,"EXP10") == 0) {
978                         if (arglist && !arglist->right && arglist->val){
979                                 to_number(arglist->val);
980                                 result = make_number(FUNC_EXP10(arglist->val->u.i));
981                                 return result;
982                         } else {
983                                 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
984                                 return make_number(0.0);
985                         }
986 #endif
987 #ifdef FUNC_LOG
988                 } else if (strcmp(funcname->u.s,"LOG") == 0) {
989                         if (arglist && !arglist->right && arglist->val){
990                                 to_number(arglist->val);
991                                 result = make_number(FUNC_LOG(arglist->val->u.i));
992                                 return result;
993                         } else {
994                                 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
995                                 return make_number(0.0);
996                         }
997 #endif
998 #ifdef FUNC_LOG2
999                 } else if (strcmp(funcname->u.s,"LOG2") == 0) {
1000                         if (arglist && !arglist->right && arglist->val){
1001                                 to_number(arglist->val);
1002                                 result = make_number(FUNC_LOG2(arglist->val->u.i));
1003                                 return result;
1004                         } else {
1005                                 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
1006                                 return make_number(0.0);
1007                         }
1008 #endif
1009 #ifdef FUNC_LOG10
1010                 } else if (strcmp(funcname->u.s,"LOG10") == 0) {
1011                         if (arglist && !arglist->right && arglist->val){
1012                                 to_number(arglist->val);
1013                                 result = make_number(FUNC_LOG10(arglist->val->u.i));
1014                                 return result;
1015                         } else {
1016                                 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
1017                                 return make_number(0.0);
1018                         }
1019 #endif
1020 #ifdef FUNC_REMAINDER
1021                 } else if (strcmp(funcname->u.s,"REMAINDER") == 0) {
1022                         if (arglist && arglist->right && !arglist->right->right && arglist->val && arglist->right->val){
1023                                 to_number(arglist->val);
1024                                 to_number(arglist->right->val);
1025                                 result = make_number(FUNC_REMAINDER(arglist->val->u.i, arglist->right->val->u.i));
1026                                 return result;
1027                         } else {
1028                                 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
1029                                 return make_number(0.0);
1030                         }
1031 #endif
1032                 } else if (strcmp(funcname->u.s, "ABS") == 0) {
1033                         if (arglist && !arglist->right && arglist->val) {
1034                                 to_number(arglist->val);
1035                                 result = make_number(arglist->val->u.i < 0 ? arglist->val->u.i * -1 : arglist->val->u.i);
1036                                 return result;
1037                         } else {
1038                                 ast_log(LOG_WARNING, "Wrong args to %s() function\n", funcname->u.s);
1039                                 return make_number(0.0);
1040                         }
1041                 } else {
1042                         /* is this a custom function we should execute and collect the results of? */
1043 #if !defined(STANDALONE) && !defined(STANDALONE2)
1044                         struct ast_custom_function *f = ast_custom_function_find(funcname->u.s);
1045                         if (!chan)
1046                                 ast_log(LOG_WARNING,"Hey! chan is NULL.\n");
1047                         if (!f)
1048                                 ast_log(LOG_WARNING,"Hey! could not find func %s.\n", funcname->u.s);
1049
1050                         if (f && chan) {
1051                                 if (f->read) {
1052                                         char workspace[512];
1053                                         char *argbuf = compose_func_args(arglist);
1054                                         f->read(chan, funcname->u.s, argbuf, workspace, sizeof(workspace));
1055                                         free(argbuf);
1056                                         if (is_really_num(workspace))
1057                                                 return make_number(FUNC_STRTOD(workspace,(char **)NULL));
1058                                         else
1059                                                 return make_str(workspace);
1060                                 } else {
1061                                         ast_log(LOG_ERROR,"Error! Function '%s' cannot be read!\n", funcname->u.s);
1062                                         return (make_number ((FP___TYPE)0.0));
1063                                 }
1064
1065                         } else {
1066                                 ast_log(LOG_ERROR, "Error! '%s' doesn't appear to be an available function!\n", funcname->u.s);
1067                                 return (make_number ((FP___TYPE)0.0));
1068                         }
1069 #else
1070                         ast_log(LOG_ERROR, "Error! '%s' is not available in the standalone version!\n", funcname->u.s);
1071                         return (make_number ((FP___TYPE)0.0));
1072 #endif
1073                 }
1074         }
1075         else
1076         {
1077                 ast_log(LOG_ERROR, "Error! '%s' is not possibly a function name!\n", funcname->u.s);
1078                 return (make_number ((FP___TYPE)0.0));
1079         }
1080         return (make_number ((FP___TYPE)0.0));
1081 }
1082
1083
1084 static struct val *
1085 op_or (struct val *a, struct val *b)
1086 {
1087         if (is_zero_or_null (a)) {
1088                 free_value (a);
1089                 return (b);
1090         } else {
1091                 free_value (b);
1092                 return (a);
1093         }
1094 }
1095
1096 static struct val *
1097 op_and (struct val *a, struct val *b)
1098 {
1099         if (is_zero_or_null (a) || is_zero_or_null (b)) {
1100                 free_value (a);
1101                 free_value (b);
1102                 return (make_number ((FP___TYPE)0.0));
1103         } else {
1104                 free_value (b);
1105                 return (a);
1106         }
1107 }
1108
1109 static struct val *
1110 op_eq (struct val *a, struct val *b)
1111 {
1112         struct val *r;
1113
1114         if (isstring (a) || isstring (b)) {
1115                 to_string (a);
1116                 to_string (b);
1117                 r = make_number ((FP___TYPE)(strcoll (a->u.s, b->u.s) == 0));
1118         } else {
1119 #ifdef DEBUG_FOR_CONVERSIONS
1120                 char buffer[2000];
1121                 sprintf(buffer,"Converting '%s' and '%s' ", a->u.s, b->u.s);
1122 #endif
1123                 (void)to_number(a);
1124                 (void)to_number(b);
1125 #ifdef DEBUG_FOR_CONVERSIONS
1126                 ast_log(LOG_WARNING,"%s to '%lld' and '%lld'\n", buffer, a->u.i, b->u.i);
1127 #endif
1128                 r = make_number ((FP___TYPE)(a->u.i == b->u.i));
1129         }
1130
1131         free_value (a);
1132         free_value (b);
1133         return r;
1134 }
1135
1136 static struct val *
1137 op_gt (struct val *a, struct val *b)
1138 {
1139         struct val *r;
1140
1141         if (isstring (a) || isstring (b)) {
1142                 to_string (a);
1143                 to_string (b);
1144                 r = make_number ((FP___TYPE)(strcoll (a->u.s, b->u.s) > 0));
1145         } else {
1146                 (void)to_number(a);
1147                 (void)to_number(b);
1148                 r = make_number ((FP___TYPE)(a->u.i > b->u.i));
1149         }
1150
1151         free_value (a);
1152         free_value (b);
1153         return r;
1154 }
1155
1156 static struct val *
1157 op_lt (struct val *a, struct val *b)
1158 {
1159         struct val *r;
1160
1161         if (isstring (a) || isstring (b)) {
1162                 to_string (a);
1163                 to_string (b);
1164                 r = make_number ((FP___TYPE)(strcoll (a->u.s, b->u.s) < 0));
1165         } else {
1166                 (void)to_number(a);
1167                 (void)to_number(b);
1168                 r = make_number ((FP___TYPE)(a->u.i < b->u.i));
1169         }
1170
1171         free_value (a);
1172         free_value (b);
1173         return r;
1174 }
1175
1176 static struct val *
1177 op_ge (struct val *a, struct val *b)
1178 {
1179         struct val *r;
1180
1181         if (isstring (a) || isstring (b)) {
1182                 to_string (a);
1183                 to_string (b);
1184                 r = make_number ((FP___TYPE)(strcoll (a->u.s, b->u.s) >= 0));
1185         } else {
1186                 (void)to_number(a);
1187                 (void)to_number(b);
1188                 r = make_number ((FP___TYPE)(a->u.i >= b->u.i));
1189         }
1190
1191         free_value (a);
1192         free_value (b);
1193         return r;
1194 }
1195
1196 static struct val *
1197 op_le (struct val *a, struct val *b)
1198 {
1199         struct val *r;
1200
1201         if (isstring (a) || isstring (b)) {
1202                 to_string (a);
1203                 to_string (b);
1204                 r = make_number ((FP___TYPE)(strcoll (a->u.s, b->u.s) <= 0));
1205         } else {
1206                 (void)to_number(a);
1207                 (void)to_number(b);
1208                 r = make_number ((FP___TYPE)(a->u.i <= b->u.i));
1209         }
1210
1211         free_value (a);
1212         free_value (b);
1213         return r;
1214 }
1215
1216 static struct val *
1217 op_cond (struct val *a, struct val *b, struct val *c)
1218 {
1219         struct val *r;
1220
1221         if( isstring(a) )
1222         {
1223                 if( strlen(a->u.s) && strcmp(a->u.s, "\"\"") != 0 && strcmp(a->u.s,"0") != 0 )
1224                 {
1225                         free_value(a);
1226                         free_value(c);
1227                         r = b;
1228                 }
1229                 else
1230                 {
1231                         free_value(a);
1232                         free_value(b);
1233                         r = c;
1234                 }
1235         }
1236         else
1237         {
1238                 (void)to_number(a);
1239                 if( a->u.i )
1240                 {
1241                         free_value(a);
1242                         free_value(c);
1243                         r = b;
1244                 }
1245                 else
1246                 {
1247                         free_value(a);
1248                         free_value(b);
1249                         r = c;
1250                 }
1251         }
1252         return r;
1253 }
1254
1255 static struct val *
1256 op_ne (struct val *a, struct val *b)
1257 {
1258         struct val *r;
1259
1260         if (isstring (a) || isstring (b)) {
1261                 to_string (a);
1262                 to_string (b);
1263                 r = make_number ((FP___TYPE)(strcoll (a->u.s, b->u.s) != 0));
1264         } else {
1265                 (void)to_number(a);
1266                 (void)to_number(b);
1267                 r = make_number ((FP___TYPE)(a->u.i != b->u.i));
1268         }
1269
1270         free_value (a);
1271         free_value (b);
1272         return r;
1273 }
1274
1275 static int
1276 chk_plus (FP___TYPE a, FP___TYPE b, FP___TYPE r)
1277 {
1278         /* sum of two positive numbers must be positive */
1279         if (a > 0 && b > 0 && r <= 0)
1280                 return 1;
1281         /* sum of two negative numbers must be negative */
1282         if (a < 0 && b < 0 && r >= 0)
1283                 return 1;
1284         /* all other cases are OK */
1285         return 0;
1286 }
1287
1288 static struct val *
1289 op_plus (struct val *a, struct val *b)
1290 {
1291         struct val *r;
1292
1293         if (!to_number (a)) {
1294                 if( !extra_error_message_supplied )
1295                         ast_log(LOG_WARNING,"non-numeric argument\n");
1296                 if (!to_number (b)) {
1297                         free_value(a);
1298                         free_value(b);
1299                         return make_number(0);
1300                 } else {
1301                         free_value(a);
1302                         return (b);
1303                 }
1304         } else if (!to_number(b)) {
1305                 free_value(b);
1306                 return (a);
1307         }
1308
1309         r = make_number (a->u.i + b->u.i);
1310         if (chk_plus (a->u.i, b->u.i, r->u.i)) {
1311                 ast_log(LOG_WARNING,"overflow\n");
1312         }
1313         free_value (a);
1314         free_value (b);
1315         return r;
1316 }
1317
1318 static int
1319 chk_minus (FP___TYPE a, FP___TYPE b, FP___TYPE r)
1320 {
1321         /* special case subtraction of QUAD_MIN */
1322         if (b == QUAD_MIN) {
1323                 if (a >= 0)
1324                         return 1;
1325                 else
1326                         return 0;
1327         }
1328         /* this is allowed for b != QUAD_MIN */
1329         return chk_plus (a, -b, r);
1330 }
1331
1332 static struct val *
1333 op_minus (struct val *a, struct val *b)
1334 {
1335         struct val *r;
1336
1337         if (!to_number (a)) {
1338                 if( !extra_error_message_supplied )
1339                         ast_log(LOG_WARNING, "non-numeric argument\n");
1340                 if (!to_number (b)) {
1341                         free_value(a);
1342                         free_value(b);
1343                         return make_number(0);
1344                 } else {
1345                         r = make_number(0 - b->u.i);
1346                         free_value(a);
1347                         free_value(b);
1348                         return (r);
1349                 }
1350         } else if (!to_number(b)) {
1351                 if( !extra_error_message_supplied )
1352                         ast_log(LOG_WARNING, "non-numeric argument\n");
1353                 free_value(b);
1354                 return (a);
1355         }
1356
1357         r = make_number (a->u.i - b->u.i);
1358         if (chk_minus (a->u.i, b->u.i, r->u.i)) {
1359                 ast_log(LOG_WARNING, "overflow\n");
1360         }
1361         free_value (a);
1362         free_value (b);
1363         return r;
1364 }
1365
1366 static struct val *
1367 op_negate (struct val *a)
1368 {
1369         struct val *r;
1370
1371         if (!to_number (a) ) {
1372                 free_value(a);
1373                 if( !extra_error_message_supplied )
1374                         ast_log(LOG_WARNING, "non-numeric argument\n");
1375                 return make_number(0);
1376         }
1377
1378         r = make_number (- a->u.i);
1379         if (chk_minus (0, a->u.i, r->u.i)) {
1380                 ast_log(LOG_WARNING, "overflow\n");
1381         }
1382         free_value (a);
1383         return r;
1384 }
1385
1386 static struct val *
1387 op_compl (struct val *a)
1388 {
1389         int v1 = 1;
1390         struct val *r;
1391
1392         if( !a )
1393         {
1394                 v1 = 0;
1395         }
1396         else
1397         {
1398                 switch( a->type )
1399                 {
1400                 case AST_EXPR_number:
1401                         if( a->u.i == 0 )
1402                                 v1 = 0;
1403                         break;
1404
1405                 case AST_EXPR_string:
1406                         if( a->u.s == 0 )
1407                                 v1 = 0;
1408                         else
1409                         {
1410                                 if( a->u.s[0] == 0 )
1411                                         v1 = 0;
1412                                 else if (strlen(a->u.s) == 1 && a->u.s[0] == '0' )
1413                                         v1 = 0;
1414                                 else
1415                                         v1 = atoi(a->u.s);
1416                         }
1417                         break;
1418
1419                 case AST_EXPR_numeric_string:
1420                         if( a->u.s == 0 )
1421                                 v1 = 0;
1422                         else
1423                         {
1424                                 if( a->u.s[0] == 0 )
1425                                         v1 = 0;
1426                                 else if (strlen(a->u.s) == 1 && a->u.s[0] == '0' )
1427                                         v1 = 0;
1428                                 else
1429                                         v1 = atoi(a->u.s);
1430                         }
1431                         break;
1432                 }
1433         }
1434
1435         r = make_number (!v1);
1436         free_value (a);
1437         return r;
1438 }
1439
1440 static int
1441 chk_times (FP___TYPE a, FP___TYPE b, FP___TYPE r)
1442 {
1443         /* special case: first operand is 0, no overflow possible */
1444         if (a == 0)
1445                 return 0;
1446         /* cerify that result of division matches second operand */
1447         if (r / a != b)
1448                 return 1;
1449         return 0;
1450 }
1451
1452 static struct val *
1453 op_times (struct val *a, struct val *b)
1454 {
1455         struct val *r;
1456
1457         if (!to_number (a) || !to_number (b)) {
1458                 free_value(a);
1459                 free_value(b);
1460                 if( !extra_error_message_supplied )
1461                         ast_log(LOG_WARNING, "non-numeric argument\n");
1462                 return(make_number(0));
1463         }
1464
1465         r = make_number (a->u.i * b->u.i);
1466         if (chk_times (a->u.i, b->u.i, r->u.i)) {
1467                 ast_log(LOG_WARNING, "overflow\n");
1468         }
1469         free_value (a);
1470         free_value (b);
1471         return (r);
1472 }
1473
1474 static int
1475 chk_div (FP___TYPE a, FP___TYPE b)
1476 {
1477         /* div by zero has been taken care of before */
1478         /* only QUAD_MIN / -1 causes overflow */
1479         if (a == QUAD_MIN && b == -1)
1480                 return 1;
1481         /* everything else is OK */
1482         return 0;
1483 }
1484
1485 static struct val *
1486 op_div (struct val *a, struct val *b)
1487 {
1488         struct val *r;
1489
1490         if (!to_number (a)) {
1491                 free_value(a);
1492                 free_value(b);
1493                 if( !extra_error_message_supplied )
1494                         ast_log(LOG_WARNING, "non-numeric argument\n");
1495                 return make_number(0);
1496         } else if (!to_number (b)) {
1497                 free_value(a);
1498                 free_value(b);
1499                 if( !extra_error_message_supplied )
1500                         ast_log(LOG_WARNING, "non-numeric argument\n");
1501                 return make_number(INT_MAX);
1502         }
1503
1504         if (b->u.i == 0) {
1505                 ast_log(LOG_WARNING, "division by zero\n");
1506                 free_value(a);
1507                 free_value(b);
1508                 return make_number(INT_MAX);
1509         }
1510
1511         r = make_number (a->u.i / b->u.i);
1512         if (chk_div (a->u.i, b->u.i)) {
1513                 ast_log(LOG_WARNING, "overflow\n");
1514         }
1515         free_value (a);
1516         free_value (b);
1517         return r;
1518 }
1519
1520 static struct val *
1521 op_rem (struct val *a, struct val *b)
1522 {
1523         struct val *r;
1524
1525         if (!to_number (a) || !to_number (b)) {
1526                 if( !extra_error_message_supplied )
1527                         ast_log(LOG_WARNING, "non-numeric argument\n");
1528                 free_value(a);
1529                 free_value(b);
1530                 return make_number(0);
1531         }
1532
1533         if (b->u.i == 0) {
1534                 ast_log(LOG_WARNING, "div by zero\n");
1535                 free_value(a);
1536                 return(b);
1537         }
1538
1539         r = make_number (FUNC_FMOD(a->u.i, b->u.i)); /* either fmod or fmodl if FP___TYPE is available */
1540         /* chk_rem necessary ??? */
1541         free_value (a);
1542         free_value (b);
1543         return r;
1544 }
1545
1546
1547 static struct val *
1548 op_colon (struct val *a, struct val *b)
1549 {
1550         regex_t rp;
1551         regmatch_t rm[2];
1552         char errbuf[256];
1553         int eval;
1554         struct val *v;
1555
1556         /* coerce to both arguments to strings */
1557         to_string(a);
1558         to_string(b);
1559         /* strip double quotes from both -- they'll screw up the pattern, and the search string starting at ^ */
1560         strip_quotes(a);
1561         strip_quotes(b);
1562         /* compile regular expression */
1563         if ((eval = regcomp (&rp, b->u.s, REG_EXTENDED)) != 0) {
1564                 regerror (eval, &rp, errbuf, sizeof(errbuf));
1565                 ast_log(LOG_WARNING, "regcomp() error : %s\n", errbuf);
1566                 free_value(a);
1567                 free_value(b);
1568                 return make_str("");
1569         }
1570
1571         /* compare string against pattern */
1572         /* remember that patterns are anchored to the beginning of the line */
1573         if (regexec(&rp, a->u.s, (size_t)2, rm, 0) == 0 && rm[0].rm_so == 0) {
1574                 if (rm[1].rm_so >= 0) {
1575                         *(a->u.s + rm[1].rm_eo) = '\0';
1576                         v = make_str (a->u.s + rm[1].rm_so);
1577
1578                 } else {
1579                         v = make_number ((FP___TYPE)(rm[0].rm_eo - rm[0].rm_so));
1580                 }
1581         } else {
1582                 if (rp.re_nsub == 0) {
1583                         v = make_number ((FP___TYPE)0);
1584                 } else {
1585                         v = make_str ("");
1586                 }
1587         }
1588
1589         /* free arguments and pattern buffer */
1590         free_value (a);
1591         free_value (b);
1592         regfree (&rp);
1593
1594         return v;
1595 }
1596
1597
1598 static struct val *
1599 op_eqtilde (struct val *a, struct val *b)
1600 {
1601         regex_t rp;
1602         regmatch_t rm[2];
1603         char errbuf[256];
1604         int eval;
1605         struct val *v;
1606
1607         /* coerce to both arguments to strings */
1608         to_string(a);
1609         to_string(b);
1610         /* strip double quotes from both -- they'll screw up the pattern, and the search string starting at ^ */
1611         strip_quotes(a);
1612         strip_quotes(b);
1613         /* compile regular expression */
1614         if ((eval = regcomp (&rp, b->u.s, REG_EXTENDED)) != 0) {
1615                 regerror (eval, &rp, errbuf, sizeof(errbuf));
1616                 ast_log(LOG_WARNING, "regcomp() error : %s\n", errbuf);
1617                 free_value(a);
1618                 free_value(b);
1619                 return make_str("");
1620         }
1621
1622         /* compare string against pattern */
1623         /* remember that patterns are anchored to the beginning of the line */
1624         if (regexec(&rp, a->u.s, (size_t)2, rm, 0) == 0 ) {
1625                 if (rm[1].rm_so >= 0) {
1626                         *(a->u.s + rm[1].rm_eo) = '\0';
1627                         v = make_str (a->u.s + rm[1].rm_so);
1628
1629                 } else {
1630                         v = make_number ((FP___TYPE)(rm[0].rm_eo - rm[0].rm_so));
1631                 }
1632         } else {
1633                 if (rp.re_nsub == 0) {
1634                         v = make_number ((FP___TYPE)0.0);
1635                 } else {
1636                         v = make_str ("");
1637                 }
1638         }
1639
1640         /* free arguments and pattern buffer */
1641         free_value (a);
1642         free_value (b);
1643         regfree (&rp);
1644
1645         return v;
1646 }
1647
1648 static struct val *  /* this is a string concat operator */
1649 op_tildetilde (struct val *a, struct val *b)
1650 {
1651         struct val *v;
1652         char *vs;
1653
1654         /* coerce to both arguments to strings */
1655         to_string(a);
1656         to_string(b);
1657         /* strip double quotes from both -- */
1658         strip_quotes(a);
1659         strip_quotes(b);
1660
1661         vs = malloc(strlen(a->u.s)+strlen(b->u.s)+1);
1662         if (vs == NULL) {
1663                 ast_log(LOG_WARNING, "malloc() failed\n");
1664                 free_value(a);
1665                 free_value(b);
1666                 return NULL;
1667         }
1668
1669         strcpy(vs,a->u.s);
1670         strcat(vs,b->u.s);
1671
1672         v = make_str(vs);
1673
1674         free(vs);
1675
1676         /* free arguments */
1677         free_value(a);
1678         free_value(b);
1679
1680         return v;
1681 }