Add ABS() absolute value function to the expression parser.
[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 #include "asterisk.h"
16
17 #include <sys/types.h>
18 #include <stdio.h>
19
20 #if !defined(STANDALONE) && !defined(STANDALONE2)       \
21         
22 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
23 #else
24 #ifndef __USE_ISOC99
25 #define __USE_ISOC99 1
26 #endif
27 #endif
28
29 #ifdef __USE_ISOC99
30 #define FP___PRINTF "%.18Lg"
31 #define FP___TYPE    long double
32 #else
33 #define FP___PRINTF "%.16g"
34 #define FP___TYPE    double
35 #endif
36
37 #ifdef HAVE_COSL
38 #define FUNC_COS   cosl
39 #elif defined(HAVE_COS)
40 #define FUNC_COS        (long double)cos
41 #endif
42
43 #ifdef HAVE_SINL
44 #define FUNC_SIN   sinl
45 #elif defined(HAVE_SIN)
46 #define FUNC_SIN        (long double)sin
47 #endif
48
49 #ifdef HAVE_TANL
50 #define FUNC_TAN   tanl
51 #elif defined(HAVE_TAN)
52 #define FUNC_TAN        (long double)tan
53 #endif
54
55 #ifdef HAVE_ACOSL
56 #define FUNC_ACOS   acosl
57 #elif defined(HAVE_ACOS)
58 #define FUNC_ACOS       (long double)acos
59 #endif
60
61 #ifdef HAVE_ASINL
62 #define FUNC_ASIN   asinl
63 #elif defined(HAVE_ASIN)
64 #define FUNC_ASIN       (long double)asin
65 #endif
66
67 #ifdef HAVE_ATANL
68 #define FUNC_ATAN   atanl
69 #elif defined(HAVE_ATAN)
70 #define FUNC_ATAN       (long double)atan
71 #endif
72
73 #ifdef HAVE_ATAN2L
74 #define FUNC_ATAN2   atan2l
75 #elif defined(HAVE_ATAN2)
76 #define FUNC_ATAN2      (long double)atan2
77 #endif
78
79 #ifdef HAVE_POWL
80 #define FUNC_POW   powl
81 #elif defined(HAVE_POW)
82 #define FUNC_POW        (long double)pow
83 #endif
84
85 #ifdef HAVE_SQRTL
86 #define FUNC_SQRT   sqrtl
87 #elif defined(HAVE_SQRT)
88 #define FUNC_SQRT       (long double)sqrt
89 #endif
90
91 #ifdef HAVE_RINTL
92 #define FUNC_RINT   rintl
93 #elif defined(HAVE_RINT)
94 #define FUNC_RINT       (long double)rint
95 #endif
96
97 #ifdef HAVE_EXPL
98 #define FUNC_EXP   expl
99 #elif defined(HAVE_EXP)
100 #define FUNC_EXP        (long double)exp
101 #endif
102
103 #ifdef HAVE_LOGL
104 #define FUNC_LOG   logl
105 #elif defined(HAVE_LOG)
106 #define FUNC_LOG        (long double)log
107 #endif
108
109 #ifdef HAVE_REMAINDERL
110 #define FUNC_REMAINDER   remainderl
111 #elif defined(HAVE_REMAINDER)
112 #define FUNC_REMAINDER  (long double)remainder
113 #endif
114
115 #ifdef HAVE_FMODL
116 #define FUNC_FMOD   fmodl
117 #elif defined(HAVE_FMOD)
118 #define FUNC_FMOD       (long double)fmod
119 #endif
120
121 #ifdef HAVE_STRTOLD
122 #define FUNC_STRTOD  strtold
123 #elif defined(HAVE_STRTOD)
124 #define FUNC_STRTOD  (long double)strtod
125 #endif
126
127 #ifdef HAVE_FLOORL
128 #define FUNC_FLOOR      floorl
129 #elif defined(HAVE_FLOOR)
130 #define FUNC_FLOOR      (long double)floor
131 #endif
132
133 #ifdef HAVE_CEILL
134 #define FUNC_CEIL      ceill
135 #elif defined(HAVE_CEIL)
136 #define FUNC_CEIL       (long double)ceil
137 #endif
138
139 #ifdef HAVE_ROUNDL
140 #define FUNC_ROUND     roundl
141 #elif defined(HAVE_ROUND)
142 #define FUNC_ROUND     (long double)round
143 #endif
144
145 #ifdef HAVE_TRUNCL
146 #define FUNC_TRUNC     truncl
147 #elif defined(HAVE_TRUNC)
148 #define FUNC_TRUNC     (long double)trunc
149 #endif
150
151 /*! \note
152  * Oddly enough, some platforms have some ISO C99 functions, but not others, so
153  * we define the missing functions in terms of their mathematical identities.
154  */
155 #ifdef HAVE_EXP2L
156 #define FUNC_EXP2       exp2l
157 #elif (defined(HAVE_EXPL) && defined(HAVE_LOGL))
158 #define FUNC_EXP2(x)    expl((x) * logl(2.0))
159 #elif (defined(HAVE_EXP) && defined(HAVE_LOG))
160 #define FUNC_EXP2(x)    (long double)exp((x) * log(2.0))
161 #endif
162
163 #ifdef HAVE_EXP10L
164 #define FUNC_EXP10       exp10l
165 #elif (defined(HAVE_EXPL) && defined(HAVE_LOGL))
166 #define FUNC_EXP10(x)   expl((x) * logl(10.0))
167 #elif (defined(HAVE_EXP) && defined(HAVE_LOG))
168 #define FUNC_EXP10(x)   (long double)exp((x) * log(10.0))
169 #endif
170
171 #ifdef HAVE_LOG2L
172 #define FUNC_LOG2       log2l
173 #elif defined(HAVE_LOGL)
174 #define FUNC_LOG2(x)    (logl(x) / logl(2.0))
175 #elif defined(HAVE_LOG10L)
176 #define FUNC_LOG2(x)    (log10l(x) / log10l(2.0))
177 #elif defined(HAVE_LOG2)
178 #define FUNC_LOG2       (long double)log2
179 #elif defined(HAVE_LOG)
180 #define FUNC_LOG2(x)    ((long double)log(x) / log(2.0))
181 #endif
182
183 #ifdef HAVE_LOG10L
184 #define FUNC_LOG10       log10l
185 #elif defined(HAVE_LOGL)
186 #define FUNC_LOG10(x)   (logl(x) / logl(10.0))
187 #elif defined(HAVE_LOG2L)
188 #define FUNC_LOG10(x)   (log2l(x) / log2l(10.0))
189 #elif defined(HAVE_LOG10)
190 #define FUNC_LOG10(x)   (long double)log10(x)
191 #elif defined(HAVE_LOG)
192 #define FUNC_LOG10(x)   ((long double)log(x) / log(10.0))
193 #endif
194
195
196 #include <stdlib.h>
197 #ifndef _GNU_SOURCE
198 #define _GNU_SOURCE
199 #endif
200 #include <string.h>
201 #include <math.h>
202 #include <locale.h>
203 #include <unistd.h>
204 #include <ctype.h>
205 #if !defined(SOLARIS) && !defined(__CYGWIN__)
206         /* #include <err.h> */
207 #else
208 #define quad_t int64_t
209 #endif
210 #include <errno.h>
211 #include <regex.h>
212 #include <limits.h>
213
214 #include "asterisk/ast_expr.h"
215 #include "asterisk/logger.h"
216 #if !defined(STANDALONE) && !defined(STANDALONE2)
217 #include "asterisk/pbx.h"
218 #endif
219
220 #if defined(LONG_LONG_MIN) && !defined(QUAD_MIN)
221 #define QUAD_MIN LONG_LONG_MIN
222 #endif
223 #if defined(LONG_LONG_MAX) && !defined(QUAD_MAX)
224 #define QUAD_MAX LONG_LONG_MAX
225 #endif
226
227 #  if ! defined(QUAD_MIN)
228 #   define QUAD_MIN     (-0x7fffffffffffffffLL-1)
229 #  endif
230 #  if ! defined(QUAD_MAX)
231 #   define QUAD_MAX     (0x7fffffffffffffffLL)
232 #  endif
233 #define YYENABLE_NLS 0
234 #define YYPARSE_PARAM parseio
235 #define YYLEX_PARAM ((struct parse_io *)parseio)->scanner
236 #define YYERROR_VERBOSE 1
237 extern char extra_error_message[4095];
238 extern int extra_error_message_supplied;
239
240 enum valtype {
241         AST_EXPR_number, AST_EXPR_numeric_string, AST_EXPR_string
242 } ;
243
244 #if defined(STANDALONE) || defined(STANDALONE2)
245 void ast_log(int level, const char *file, int line, const char *function, const char *fmt, ...) __attribute__ ((format (printf,5,6)));
246 #endif
247
248 struct val {
249         enum valtype type;
250         union {
251                 char *s;
252                 FP___TYPE i; /* either long double, or just double, on a bad day */
253         } u;
254 } ;
255
256 enum node_type {
257         AST_EXPR_NODE_COMMA, AST_EXPR_NODE_STRING, AST_EXPR_NODE_VAL
258 } ;
259
260 struct expr_node 
261 {
262         enum node_type type;
263         struct val *val;
264         struct expr_node *left;
265         struct expr_node *right;
266 };
267
268
269 typedef void *yyscan_t;
270
271 struct parse_io
272 {
273         char *string;
274         struct val *val;
275         yyscan_t scanner;
276         struct ast_channel *chan;
277 };
278  
279 static int              chk_div __P((FP___TYPE, FP___TYPE));
280 static int              chk_minus __P((FP___TYPE, FP___TYPE, FP___TYPE));
281 static int              chk_plus __P((FP___TYPE, FP___TYPE, FP___TYPE));
282 static int              chk_times __P((FP___TYPE, FP___TYPE, FP___TYPE));
283 static void             free_value __P((struct val *));
284 static int              is_zero_or_null __P((struct val *));
285 static int              isstring __P((struct val *));
286 static struct val       *make_number __P((FP___TYPE));
287 static struct val       *make_str __P((const char *));
288 static struct val       *op_and __P((struct val *, struct val *));
289 static struct val       *op_colon __P((struct val *, struct val *));
290 static struct val       *op_eqtilde __P((struct val *, struct val *));
291 static struct val       *op_tildetilde __P((struct val *, struct val *));
292 static struct val       *op_div __P((struct val *, struct val *));
293 static struct val       *op_eq __P((struct val *, struct val *));
294 static struct val       *op_ge __P((struct val *, struct val *));
295 static struct val       *op_gt __P((struct val *, struct val *));
296 static struct val       *op_le __P((struct val *, struct val *));
297 static struct val       *op_lt __P((struct val *, struct val *));
298 static struct val       *op_cond __P((struct val *, struct val *, struct val *));
299 static struct val       *op_minus __P((struct val *, struct val *));
300 static struct val       *op_negate __P((struct val *));
301 static struct val       *op_compl __P((struct val *));
302 static struct val       *op_ne __P((struct val *, struct val *));
303 static struct val       *op_or __P((struct val *, struct val *));
304 static struct val       *op_plus __P((struct val *, struct val *));
305 static struct val       *op_rem __P((struct val *, struct val *));
306 static struct val       *op_times __P((struct val *, struct val *));
307 static struct val   *op_func(struct val *funcname, struct expr_node *arglist, struct ast_channel *chan);
308 static int              to_number __P((struct val *));
309 static void             to_string __P((struct val *));
310 static struct expr_node *alloc_expr_node(enum node_type);
311 static void destroy_arglist(struct expr_node *arglist);
312
313 /* uh, if I want to predeclare yylex with a YYLTYPE, I have to predeclare the yyltype... sigh */
314 typedef struct yyltype
315 {
316   int first_line;
317   int first_column;
318
319   int last_line;
320   int last_column;
321 } yyltype;
322
323 # define YYLTYPE yyltype
324 # define YYLTYPE_IS_TRIVIAL 1
325
326 /* we will get warning about no prototype for yylex! But we can't
327    define it here, we have no definition yet for YYSTYPE. */
328
329 int             ast_yyerror(const char *,YYLTYPE *, struct parse_io *);
330  
331 /* I wanted to add args to the yyerror routine, so I could print out
332    some useful info about the error. Not as easy as it looks, but it
333    is possible. */
334 #define ast_yyerror(x) ast_yyerror(x,&yyloc,parseio)
335 #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);}
336 %}
337  
338 %pure-parser
339 %locations
340 /* %debug  for when you are having big problems */
341
342 /* %name-prefix="ast_yy" */
343
344 %union
345 {
346         struct val *val;
347         struct expr_node *arglist;
348 }
349
350 %{
351 extern int              ast_yylex __P((YYSTYPE *, YYLTYPE *, yyscan_t));
352 %}
353 %left <val> TOK_COMMA
354 %left <val> TOK_COND TOK_COLONCOLON
355 %left <val> TOK_OR
356 %left <val> TOK_AND
357 %left <val> TOK_EQ TOK_GT TOK_LT TOK_GE TOK_LE TOK_NE
358 %left <val> TOK_PLUS TOK_MINUS
359 %left <val> TOK_MULT TOK_DIV TOK_MOD 
360 %right <val> TOK_COMPL
361 %left <val> TOK_COLON TOK_EQTILDE TOK_TILDETILDE
362 %left <val> TOK_RP TOK_LP
363
364 %token <val> TOKEN
365 %type <arglist> arglist
366 %type <val> start expr
367
368 %destructor {  free_value($$); }  expr TOKEN TOK_COND TOK_COLONCOLON TOK_OR TOK_AND TOK_EQ 
369                                  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 
370                                  TOK_RP TOK_LP TOK_TILDETILDE
371
372 %%
373
374 start: expr { ((struct parse_io *)parseio)->val = (struct val *)calloc(sizeof(struct val),1);
375               ((struct parse_io *)parseio)->val->type = $1->type;
376               if( $1->type == AST_EXPR_number )
377                                   ((struct parse_io *)parseio)->val->u.i = $1->u.i;
378               else
379                                   ((struct parse_io *)parseio)->val->u.s = $1->u.s; 
380                           free($1);
381                         }
382         | {/* nothing */ ((struct parse_io *)parseio)->val = (struct val *)calloc(sizeof(struct val),1);
383               ((struct parse_io *)parseio)->val->type = AST_EXPR_string;
384                           ((struct parse_io *)parseio)->val->u.s = strdup(""); 
385                         }
386
387         ;
388
389 arglist: expr { $$ = alloc_expr_node(AST_EXPR_NODE_VAL); $$->val = $1;}
390        | arglist TOK_COMMA expr %prec TOK_RP {struct expr_node *x = alloc_expr_node(AST_EXPR_NODE_VAL);
391                                  struct expr_node *t;
392                                                                  DESTROY($2);
393                                  for (t=$1;t->right;t=t->right)
394                                                                   ;
395                                  $$ = $1; t->right = x; x->val = $3;}
396        | arglist TOK_COMMA %prec TOK_RP {struct expr_node *x = alloc_expr_node(AST_EXPR_NODE_VAL);
397                                  struct expr_node *t;  /* NULL args should OK */
398                                                                  DESTROY($2);
399                                  for (t=$1;t->right;t=t->right)
400                                                                   ;
401                                  $$ = $1; t->right = x; x->val = make_str("");}
402        ;
403
404 expr: 
405       TOKEN TOK_LP arglist TOK_RP { $$ = op_func($1,$3, ((struct parse_io *)parseio)->chan);
406                                             DESTROY($2);
407                                                                         DESTROY($4);
408                                                                         DESTROY($1);
409                                                                         destroy_arglist($3);
410                                   }
411     | TOKEN {$$ = $1;}
412         | TOK_LP expr TOK_RP { $$ = $2;
413                                @$.first_column = @1.first_column; @$.last_column = @3.last_column; 
414                                                    @$.first_line=0; @$.last_line=0;
415                                                         DESTROY($1); DESTROY($3); }
416         | expr TOK_OR expr { $$ = op_or ($1, $3);
417                                                 DESTROY($2);    
418                          @$.first_column = @1.first_column; @$.last_column = @3.last_column; 
419                                                  @$.first_line=0; @$.last_line=0;}
420         | expr TOK_AND expr { $$ = op_and ($1, $3); 
421                                                 DESTROY($2);    
422                               @$.first_column = @1.first_column; @$.last_column = @3.last_column; 
423                           @$.first_line=0; @$.last_line=0;}
424         | expr TOK_EQ expr { $$ = op_eq ($1, $3);
425                                                 DESTROY($2);    
426                              @$.first_column = @1.first_column; @$.last_column = @3.last_column;
427                                                  @$.first_line=0; @$.last_line=0;}
428         | expr TOK_GT expr { $$ = op_gt ($1, $3);
429                                                 DESTROY($2);    
430                          @$.first_column = @1.first_column; @$.last_column = @3.last_column;
431                                                  @$.first_line=0; @$.last_line=0;}
432         | expr TOK_LT expr { $$ = op_lt ($1, $3); 
433                                                 DESTROY($2);    
434                              @$.first_column = @1.first_column; @$.last_column = @3.last_column; 
435                                                  @$.first_line=0; @$.last_line=0;}
436         | expr TOK_GE expr  { $$ = op_ge ($1, $3); 
437                                                 DESTROY($2);    
438                               @$.first_column = @1.first_column; @$.last_column = @3.last_column; 
439                                                   @$.first_line=0; @$.last_line=0;}
440         | expr TOK_LE expr  { $$ = op_le ($1, $3); 
441                                                 DESTROY($2);    
442                               @$.first_column = @1.first_column; @$.last_column = @3.last_column; 
443                                                   @$.first_line=0; @$.last_line=0;}
444         | expr TOK_NE expr  { $$ = op_ne ($1, $3); 
445                                                 DESTROY($2);    
446                               @$.first_column = @1.first_column; @$.last_column = @3.last_column; 
447                                                   @$.first_line=0; @$.last_line=0;}
448         | expr TOK_PLUS expr { $$ = op_plus ($1, $3); 
449                                                 DESTROY($2);    
450                                @$.first_column = @1.first_column; @$.last_column = @3.last_column; 
451                                                    @$.first_line=0; @$.last_line=0;}
452         | expr TOK_MINUS expr { $$ = op_minus ($1, $3); 
453                                                 DESTROY($2);    
454                                 @$.first_column = @1.first_column; @$.last_column = @3.last_column; 
455                                                         @$.first_line=0; @$.last_line=0;}
456         | TOK_MINUS expr %prec TOK_COMPL { $$ = op_negate ($2); 
457                                                 DESTROY($1);    
458                                 @$.first_column = @1.first_column; @$.last_column = @2.last_column; 
459                                                         @$.first_line=0; @$.last_line=0;}
460         | TOK_COMPL expr   { $$ = op_compl ($2); 
461                                                 DESTROY($1);    
462                                 @$.first_column = @1.first_column; @$.last_column = @2.last_column; 
463                                                         @$.first_line=0; @$.last_line=0;}
464         | expr TOK_MULT expr { $$ = op_times ($1, $3); 
465                                                 DESTROY($2);    
466                                @$.first_column = @1.first_column; @$.last_column = @3.last_column; 
467                                                    @$.first_line=0; @$.last_line=0;}
468         | expr TOK_DIV expr { $$ = op_div ($1, $3); 
469                                                 DESTROY($2);    
470                               @$.first_column = @1.first_column; @$.last_column = @3.last_column; 
471                                                   @$.first_line=0; @$.last_line=0;}
472         | expr TOK_MOD expr { $$ = op_rem ($1, $3); 
473                                                 DESTROY($2);    
474                               @$.first_column = @1.first_column; @$.last_column = @3.last_column; 
475                                                   @$.first_line=0; @$.last_line=0;}
476         | expr TOK_COLON expr { $$ = op_colon ($1, $3); 
477                                                 DESTROY($2);    
478                                 @$.first_column = @1.first_column; @$.last_column = @3.last_column; 
479                                                         @$.first_line=0; @$.last_line=0;}
480         | expr TOK_EQTILDE expr { $$ = op_eqtilde ($1, $3); 
481                                                 DESTROY($2);    
482                                 @$.first_column = @1.first_column; @$.last_column = @3.last_column; 
483                                                         @$.first_line=0; @$.last_line=0;}
484         | expr TOK_COND expr TOK_COLONCOLON expr  { $$ = op_cond ($1, $3, $5); 
485                                                 DESTROY($2);    
486                                                 DESTROY($4);    
487                                 @$.first_column = @1.first_column; @$.last_column = @3.last_column; 
488                                                         @$.first_line=0; @$.last_line=0;}
489         | expr TOK_TILDETILDE expr { $$ = op_tildetilde ($1, $3); 
490                                                 DESTROY($2);    
491                                 @$.first_column = @1.first_column; @$.last_column = @3.last_column; 
492                                                         @$.first_line=0; @$.last_line=0;}
493         ;
494
495 %%
496
497 static struct expr_node *alloc_expr_node(enum node_type nt)
498 {
499         struct expr_node *x = calloc(1,sizeof(struct expr_node));
500         if (!x) {
501                 ast_log(LOG_ERROR, "Allocation for expr_node FAILED!!\n");
502                 return 0;
503         }
504         x->type = nt;
505         return x;
506 }
507
508
509
510 static struct val *
511 make_number (FP___TYPE i)
512 {
513         struct val *vp;
514
515         vp = (struct val *) malloc (sizeof (*vp));
516         if (vp == NULL) {
517                 ast_log(LOG_WARNING, "malloc() failed\n");
518                 return(NULL);
519         }
520
521         vp->type = AST_EXPR_number;
522         vp->u.i  = i;
523         return vp; 
524 }
525
526 static struct val *
527 make_str (const char *s)
528 {
529         struct val *vp;
530         size_t i;
531         int isint; /* this started out being a test for an integer, but then ended up being a test for a float */
532
533         vp = (struct val *) malloc (sizeof (*vp));
534         if (vp == NULL || ((vp->u.s = strdup (s)) == NULL)) {
535                 ast_log(LOG_WARNING,"malloc() failed\n");
536                 return(NULL);
537         }
538
539         for (i = 0, isint = (isdigit(s[0]) || s[0] == '-' || s[0]=='.'); isint && i < strlen(s); i++)
540         {
541                 if (!isdigit(s[i]) && s[i] != '.') {
542                         isint = 0;
543                         break;
544                 }
545         }
546         if (isint)
547                 vp->type = AST_EXPR_numeric_string;
548         else    
549                 vp->type = AST_EXPR_string;
550
551         return vp;
552 }
553
554
555 static void
556 free_value (struct val *vp)
557 {       
558         if (vp==NULL) {
559                 return;
560         }
561         if (vp->type == AST_EXPR_string || vp->type == AST_EXPR_numeric_string)
562                 free (vp->u.s); 
563         free(vp);
564 }
565
566
567 static int
568 to_number (struct val *vp)
569 {
570         FP___TYPE i;
571         
572         if (vp == NULL) {
573                 ast_log(LOG_WARNING,"vp==NULL in to_number()\n");
574                 return(0);
575         }
576
577         if (vp->type == AST_EXPR_number)
578                 return 1;
579
580         if (vp->type == AST_EXPR_string)
581                 return 0;
582
583         /* vp->type == AST_EXPR_numeric_string, make it numeric */
584         errno = 0;
585         i  = FUNC_STRTOD(vp->u.s, (char**)0); /* either strtod, or strtold on a good day */
586         if (errno != 0) {
587                 ast_log(LOG_WARNING,"Conversion of %s to number under/overflowed!\n", vp->u.s);
588                 free(vp->u.s);
589                 vp->u.s = 0;
590                 return(0);
591         }
592         free (vp->u.s);
593         vp->u.i = i;
594         vp->type = AST_EXPR_number;
595         return 1;
596 }
597
598 static void
599 strip_quotes(struct val *vp)
600 {
601         if (vp->type != AST_EXPR_string && vp->type != AST_EXPR_numeric_string)
602                 return;
603         
604         if( vp->u.s[0] == '"' && vp->u.s[strlen(vp->u.s)-1] == '"' )
605         {
606                 char *f, *t;
607                 f = vp->u.s;
608                 t = vp->u.s;
609                 
610                 while( *f )
611                 {
612                         if( *f  && *f != '"' )
613                                 *t++ = *f++;
614                         else
615                                 f++;
616                 }
617                 *t = *f;
618         }
619 }
620
621 static void
622 to_string (struct val *vp)
623 {
624         char *tmp;
625
626         if (vp->type == AST_EXPR_string || vp->type == AST_EXPR_numeric_string)
627                 return;
628
629         tmp = malloc ((size_t)25);
630         if (tmp == NULL) {
631                 ast_log(LOG_WARNING,"malloc() failed\n");
632                 return;
633         }
634
635         sprintf(tmp, FP___PRINTF, vp->u.i);
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         strcpy(vs,a->u.s);
1663         strcat(vs,b->u.s);
1664
1665         v = make_str(vs);
1666
1667         /* free arguments */
1668         free_value(a);
1669         free_value(b);
1670
1671         return v;
1672 }