f516291f9c3ef7af0a366524bc127ba1ec51a1dd
[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         tmp = malloc ((size_t)25);
632         if (tmp == NULL) {
633                 ast_log(LOG_WARNING,"malloc() failed\n");
634                 return;
635         }
636
637         sprintf(tmp, FP___PRINTF, vp->u.i);
638         vp->type = AST_EXPR_string;
639         vp->u.s  = tmp;
640 }
641
642
643 static int
644 isstring (struct val *vp)
645 {
646         /* only TRUE if this string is not a valid number */
647         return (vp->type == AST_EXPR_string);
648 }
649
650
651 static int
652 is_zero_or_null (struct val *vp)
653 {
654         if (vp->type == AST_EXPR_number) {
655                 return (vp->u.i == 0);
656         } else {
657                 return (*vp->u.s == 0 || (to_number(vp) && vp->u.i == 0));
658         }
659         /* NOTREACHED */
660 }
661
662 #ifdef STANDALONE2
663
664 void ast_log(int level, const char *file, int line, const char *function, const char *fmt, ...)
665 {
666         va_list vars;
667         va_start(vars,fmt);
668         
669         printf("LOG: lev:%d file:%s  line:%d func: %s  ",
670                    level, file, line, function);
671         vprintf(fmt, vars);
672         fflush(stdout);
673         va_end(vars);
674 }
675
676
677 int main(int argc,char **argv) {
678         char s[4096];
679         char out[4096];
680         FILE *infile;
681         
682         if( !argv[1] )
683                 exit(20);
684         
685         if( access(argv[1],F_OK)== 0 )
686         {
687                 int ret;
688                 
689                 infile = fopen(argv[1],"r");
690                 if( !infile )
691                 {
692                         printf("Sorry, couldn't open %s for reading!\n", argv[1]);
693                         exit(10);
694                 }
695                 while( fgets(s,sizeof(s),infile) )
696                 {
697                         if( s[strlen(s)-1] == '\n' )
698                                 s[strlen(s)-1] = 0;
699                         
700                         ret = ast_expr(s, out, sizeof(out), NULL);
701                         printf("Expression: %s    Result: [%d] '%s'\n",
702                                    s, ret, out);
703                 }
704                 fclose(infile);
705         }
706         else
707         {
708                 if (ast_expr(argv[1], s, sizeof(s), NULL))
709                         printf("=====%s======\n",s);
710                 else
711                         printf("No result\n");
712         }
713         return 0;
714 }
715
716 #endif
717
718 #undef ast_yyerror
719 #define ast_yyerror(x) ast_yyerror(x, YYLTYPE *yylloc, struct parse_io *parseio)
720
721 /* I put the ast_yyerror func in the flex input file,
722    because it refers to the buffer state. Best to
723    let it access the BUFFER stuff there and not trying
724    define all the structs, macros etc. in this file! */
725
726 static void destroy_arglist(struct expr_node *arglist)
727 {
728         struct expr_node *arglist_next;
729         
730         while (arglist)
731         {
732                 arglist_next = arglist->right;
733                 if (arglist->val)
734                         free_value(arglist->val);
735                 arglist->val = 0;
736                 arglist->right = 0;
737                 free(arglist);
738                 arglist = arglist_next;
739         }
740 }
741
742 #if !defined(STANDALONE) && !defined(STANDALONE2)
743 static char *compose_func_args(struct expr_node *arglist)
744 {
745         struct expr_node *t = arglist;
746         char *argbuf;
747         int total_len = 0;
748         
749         while (t) {
750                 if (t != arglist)
751                         total_len += 1; /* for the sep */
752                 if (t->val) {
753                         if (t->val->type == AST_EXPR_number)
754                                 total_len += 25; /* worst case */
755                         else
756                                 total_len += strlen(t->val->u.s);
757                 }
758                 
759                 t = t->right;
760         }
761         total_len++; /* for the null */
762         ast_log(LOG_NOTICE,"argbuf allocated %d bytes;\n", total_len);
763         argbuf = malloc(total_len);
764         argbuf[0] = 0;
765         t = arglist;
766         while (t) {
767                 char numbuf[30];
768                 
769                 if (t != arglist)
770                         strcat(argbuf,",");
771                 
772                 if (t->val) {
773                         if (t->val->type == AST_EXPR_number) {
774                                 sprintf(numbuf,FP___PRINTF,t->val->u.i);
775                                 strcat(argbuf,numbuf);
776                         } else
777                                 strcat(argbuf,t->val->u.s);
778                 }
779                 t = t->right;
780         }
781         ast_log(LOG_NOTICE,"argbuf uses %d bytes;\n", (int) strlen(argbuf));
782         return argbuf;
783 }
784
785 static int is_really_num(char *str)
786 {
787         if ( strspn(str,"-0123456789.   ") == strlen(str))
788                 return 1;
789         else
790                 return 0;
791 }
792 #endif
793
794 static struct val *op_func(struct val *funcname, struct expr_node *arglist, struct ast_channel *chan)
795 {
796         if (strspn(funcname->u.s,"ABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789") == strlen(funcname->u.s))
797         {
798                 struct val *result;
799                 if (0) {
800 #ifdef FUNC_COS
801                 } else if (strcmp(funcname->u.s,"COS") == 0) {
802                         if (arglist && !arglist->right && arglist->val){
803                                 to_number(arglist->val);
804                                 result = make_number(FUNC_COS(arglist->val->u.i));
805                                 return result;
806                         } else {
807                                 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
808                                 return make_number(0.0);
809                         }
810 #endif
811 #ifdef FUNC_SIN
812                 } else if (strcmp(funcname->u.s,"SIN") == 0) {
813                         if (arglist && !arglist->right && arglist->val){
814                                 to_number(arglist->val);
815                                 result = make_number(FUNC_SIN(arglist->val->u.i));
816                                 return result;
817                         } else {
818                                 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
819                                 return make_number(0.0);
820                         }
821 #endif
822 #ifdef FUNC_TAN
823                 } else if (strcmp(funcname->u.s,"TAN") == 0) {
824                         if (arglist && !arglist->right && arglist->val){
825                                 to_number(arglist->val);
826                                 result = make_number(FUNC_TAN(arglist->val->u.i));
827                                 return result;
828                         } else {
829                                 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
830                                 return make_number(0.0);
831                         }
832 #endif
833 #ifdef FUNC_ACOS
834                 } else if (strcmp(funcname->u.s,"ACOS") == 0) {
835                         if (arglist && !arglist->right && arglist->val){
836                                 to_number(arglist->val);
837                                 result = make_number(FUNC_ACOS(arglist->val->u.i));
838                                 return result;
839                         } else {
840                                 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
841                                 return make_number(0.0);
842                         }
843 #endif
844 #ifdef FUNC_ASIN
845                 } else if (strcmp(funcname->u.s,"ASIN") == 0) {
846                         if (arglist && !arglist->right && arglist->val){
847                                 to_number(arglist->val);
848                                 result = make_number(FUNC_ASIN(arglist->val->u.i));
849                                 return result;
850                         } else {
851                                 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
852                                 return make_number(0.0);
853                         }
854 #endif
855 #ifdef FUNC_ATAN
856                 } else if (strcmp(funcname->u.s,"ATAN") == 0) {
857                         if (arglist && !arglist->right && arglist->val){
858                                 to_number(arglist->val);
859                                 result = make_number(FUNC_ATAN(arglist->val->u.i));
860                                 return result;
861                         } else {
862                                 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
863                                 return make_number(0.0);
864                         }
865 #endif
866 #ifdef FUNC_ATAN2
867                 } else if (strcmp(funcname->u.s,"ATAN2") == 0) {
868                         if (arglist && arglist->right && !arglist->right->right && arglist->val && arglist->right->val){
869                                 to_number(arglist->val);
870                                 to_number(arglist->right->val);
871                                 result = make_number(FUNC_ATAN2(arglist->val->u.i, arglist->right->val->u.i));
872                                 return result;
873                         } else {
874                                 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
875                                 return make_number(0.0);
876                         }
877 #endif
878 #ifdef FUNC_POW
879                 } else if (strcmp(funcname->u.s,"POW") == 0) {
880                         if (arglist && arglist->right && !arglist->right->right && arglist->val && arglist->right->val){
881                                 to_number(arglist->val);
882                                 to_number(arglist->right->val);
883                                 result = make_number(FUNC_POW(arglist->val->u.i, arglist->right->val->u.i));
884                                 return result;
885                         } else {
886                                 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
887                                 return make_number(0.0);
888                         }
889 #endif
890 #ifdef FUNC_SQRT
891                 } else if (strcmp(funcname->u.s,"SQRT") == 0) {
892                         if (arglist && !arglist->right && arglist->val){
893                                 to_number(arglist->val);
894                                 result = make_number(FUNC_SQRT(arglist->val->u.i));
895                                 return result;
896                         } else {
897                                 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
898                                 return make_number(0.0);
899                         }
900 #endif
901 #ifdef FUNC_FLOOR
902                 } else if (strcmp(funcname->u.s,"FLOOR") == 0) {
903                         if (arglist && !arglist->right && arglist->val){
904                                 to_number(arglist->val);
905                                 result = make_number(FUNC_FLOOR(arglist->val->u.i));
906                                 return result;
907                         } else {
908                                 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
909                                 return make_number(0.0);
910                         }
911 #endif
912 #ifdef FUNC_CEIL
913                 } else if (strcmp(funcname->u.s,"CEIL") == 0) {
914                         if (arglist && !arglist->right && arglist->val){
915                                 to_number(arglist->val);
916                                 result = make_number(FUNC_CEIL(arglist->val->u.i));
917                                 return result;
918                         } else {
919                                 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
920                                 return make_number(0.0);
921                         }
922 #endif
923 #ifdef FUNC_ROUND
924                 } else if (strcmp(funcname->u.s,"ROUND") == 0) {
925                         if (arglist && !arglist->right && arglist->val){
926                                 to_number(arglist->val);
927                                 result = make_number(FUNC_ROUND(arglist->val->u.i));
928                                 return result;
929                         } else {
930                                 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
931                                 return make_number(0.0);
932                         }
933 #endif /* defined(FUNC_ROUND) */
934 #ifdef FUNC_RINT
935                 } else if (strcmp(funcname->u.s,"RINT") == 0) {
936                         if (arglist && !arglist->right && arglist->val){
937                                 to_number(arglist->val);
938                                 result = make_number(FUNC_RINT(arglist->val->u.i));
939                                 return result;
940                         } else {
941                                 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
942                                 return make_number(0.0);
943                         }
944 #endif
945 #ifdef FUNC_TRUNC
946                 } else if (strcmp(funcname->u.s,"TRUNC") == 0) {
947                         if (arglist && !arglist->right && arglist->val){
948                                 to_number(arglist->val);
949                                 result = make_number(FUNC_TRUNC(arglist->val->u.i));
950                                 return result;
951                         } else {
952                                 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
953                                 return make_number(0.0);
954                         }
955 #endif /* defined(FUNC_TRUNC) */
956 #ifdef FUNC_EXP
957                 } else if (strcmp(funcname->u.s,"EXP") == 0) {
958                         if (arglist && !arglist->right && arglist->val){
959                                 to_number(arglist->val);
960                                 result = make_number(FUNC_EXP(arglist->val->u.i));
961                                 return result;
962                         } else {
963                                 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
964                                 return make_number(0.0);
965                         }
966 #endif
967 #ifdef FUNC_EXP2
968                 } else if (strcmp(funcname->u.s,"EXP2") == 0) {
969                         if (arglist && !arglist->right && arglist->val){
970                                 to_number(arglist->val);
971                                 result = make_number(FUNC_EXP2(arglist->val->u.i));
972                                 return result;
973                         } else {
974                                 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
975                                 return make_number(0.0);
976                         }
977 #endif
978 #ifdef FUNC_EXP10
979                 } else if (strcmp(funcname->u.s,"EXP10") == 0) {
980                         if (arglist && !arglist->right && arglist->val){
981                                 to_number(arglist->val);
982                                 result = make_number(FUNC_EXP10(arglist->val->u.i));
983                                 return result;
984                         } else {
985                                 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
986                                 return make_number(0.0);
987                         }
988 #endif
989 #ifdef FUNC_LOG
990                 } else if (strcmp(funcname->u.s,"LOG") == 0) {
991                         if (arglist && !arglist->right && arglist->val){
992                                 to_number(arglist->val);
993                                 result = make_number(FUNC_LOG(arglist->val->u.i));
994                                 return result;
995                         } else {
996                                 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
997                                 return make_number(0.0);
998                         }
999 #endif
1000 #ifdef FUNC_LOG2
1001                 } else if (strcmp(funcname->u.s,"LOG2") == 0) {
1002                         if (arglist && !arglist->right && arglist->val){
1003                                 to_number(arglist->val);
1004                                 result = make_number(FUNC_LOG2(arglist->val->u.i));
1005                                 return result;
1006                         } else {
1007                                 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
1008                                 return make_number(0.0);
1009                         }
1010 #endif
1011 #ifdef FUNC_LOG10
1012                 } else if (strcmp(funcname->u.s,"LOG10") == 0) {
1013                         if (arglist && !arglist->right && arglist->val){
1014                                 to_number(arglist->val);
1015                                 result = make_number(FUNC_LOG10(arglist->val->u.i));
1016                                 return result;
1017                         } else {
1018                                 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
1019                                 return make_number(0.0);
1020                         }
1021 #endif
1022 #ifdef FUNC_REMAINDER
1023                 } else if (strcmp(funcname->u.s,"REMAINDER") == 0) {
1024                         if (arglist && arglist->right && !arglist->right->right && arglist->val && arglist->right->val){
1025                                 to_number(arglist->val);
1026                                 to_number(arglist->right->val);
1027                                 result = make_number(FUNC_REMAINDER(arglist->val->u.i, arglist->right->val->u.i));
1028                                 return result;
1029                         } else {
1030                                 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
1031                                 return make_number(0.0);
1032                         }
1033 #endif
1034                 } else if (strcmp(funcname->u.s, "ABS") == 0) {
1035                         if (arglist && !arglist->right && arglist->val) {
1036                                 to_number(arglist->val);
1037                                 result = make_number(arglist->val->u.i < 0 ? arglist->val->u.i * -1 : arglist->val->u.i);
1038                                 return result;
1039                         } else {
1040                                 ast_log(LOG_WARNING, "Wrong args to %s() function\n", funcname->u.s);
1041                                 return make_number(0.0);
1042                         }
1043                 } else {
1044                         /* is this a custom function we should execute and collect the results of? */
1045 #if !defined(STANDALONE) && !defined(STANDALONE2)
1046                         struct ast_custom_function *f = ast_custom_function_find(funcname->u.s);
1047                         if (!chan)
1048                                 ast_log(LOG_WARNING,"Hey! chan is NULL.\n");
1049                         if (!f)
1050                                 ast_log(LOG_WARNING,"Hey! could not find func %s.\n", funcname->u.s);
1051                         
1052                         if (f && chan) {
1053                                 if (f->read) {
1054                                         char workspace[512];
1055                                         char *argbuf = compose_func_args(arglist);
1056                                         f->read(chan, funcname->u.s, argbuf, workspace, sizeof(workspace));
1057                                         free(argbuf);
1058                                         if (is_really_num(workspace))
1059                                                 return make_number(FUNC_STRTOD(workspace,(char **)NULL));
1060                                         else
1061                                                 return make_str(workspace);
1062                                 } else {
1063                                         ast_log(LOG_ERROR,"Error! Function '%s' cannot be read!\n", funcname->u.s);
1064                                         return (make_number ((FP___TYPE)0.0));
1065                                 }
1066                                 
1067                         } else {
1068                                 ast_log(LOG_ERROR, "Error! '%s' doesn't appear to be an available function!\n", funcname->u.s);
1069                                 return (make_number ((FP___TYPE)0.0));
1070                         }
1071 #else
1072                         ast_log(LOG_ERROR, "Error! '%s' is not available in the standalone version!\n", funcname->u.s);
1073                         return (make_number ((FP___TYPE)0.0));
1074 #endif
1075                 }
1076         }
1077         else
1078         {
1079                 ast_log(LOG_ERROR, "Error! '%s' is not possibly a function name!\n", funcname->u.s);
1080                 return (make_number ((FP___TYPE)0.0));
1081         }
1082         return (make_number ((FP___TYPE)0.0));
1083 }
1084
1085
1086 static struct val *
1087 op_or (struct val *a, struct val *b)
1088 {
1089         if (is_zero_or_null (a)) {
1090                 free_value (a);
1091                 return (b);
1092         } else {
1093                 free_value (b);
1094                 return (a);
1095         }
1096 }
1097                 
1098 static struct val *
1099 op_and (struct val *a, struct val *b)
1100 {
1101         if (is_zero_or_null (a) || is_zero_or_null (b)) {
1102                 free_value (a);
1103                 free_value (b);
1104                 return (make_number ((FP___TYPE)0.0));
1105         } else {
1106                 free_value (b);
1107                 return (a);
1108         }
1109 }
1110
1111 static struct val *
1112 op_eq (struct val *a, struct val *b)
1113 {
1114         struct val *r; 
1115
1116         if (isstring (a) || isstring (b)) {
1117                 to_string (a);
1118                 to_string (b);  
1119                 r = make_number ((FP___TYPE)(strcoll (a->u.s, b->u.s) == 0));
1120         } else {
1121 #ifdef DEBUG_FOR_CONVERSIONS
1122                 char buffer[2000];
1123                 sprintf(buffer,"Converting '%s' and '%s' ", a->u.s, b->u.s);
1124 #endif
1125                 (void)to_number(a);
1126                 (void)to_number(b);
1127 #ifdef DEBUG_FOR_CONVERSIONS
1128                 ast_log(LOG_WARNING,"%s to '%lld' and '%lld'\n", buffer, a->u.i, b->u.i);
1129 #endif
1130                 r = make_number ((FP___TYPE)(a->u.i == b->u.i));
1131         }
1132
1133         free_value (a);
1134         free_value (b);
1135         return r;
1136 }
1137
1138 static struct val *
1139 op_gt (struct val *a, struct val *b)
1140 {
1141         struct val *r;
1142
1143         if (isstring (a) || isstring (b)) {
1144                 to_string (a);
1145                 to_string (b);
1146                 r = make_number ((FP___TYPE)(strcoll (a->u.s, b->u.s) > 0));
1147         } else {
1148                 (void)to_number(a);
1149                 (void)to_number(b);
1150                 r = make_number ((FP___TYPE)(a->u.i > b->u.i));
1151         }
1152
1153         free_value (a);
1154         free_value (b);
1155         return r;
1156 }
1157
1158 static struct val *
1159 op_lt (struct val *a, struct val *b)
1160 {
1161         struct val *r;
1162
1163         if (isstring (a) || isstring (b)) {
1164                 to_string (a);
1165                 to_string (b);
1166                 r = make_number ((FP___TYPE)(strcoll (a->u.s, b->u.s) < 0));
1167         } else {
1168                 (void)to_number(a);
1169                 (void)to_number(b);
1170                 r = make_number ((FP___TYPE)(a->u.i < b->u.i));
1171         }
1172
1173         free_value (a);
1174         free_value (b);
1175         return r;
1176 }
1177
1178 static struct val *
1179 op_ge (struct val *a, struct val *b)
1180 {
1181         struct val *r;
1182
1183         if (isstring (a) || isstring (b)) {
1184                 to_string (a);
1185                 to_string (b);
1186                 r = make_number ((FP___TYPE)(strcoll (a->u.s, b->u.s) >= 0));
1187         } else {
1188                 (void)to_number(a);
1189                 (void)to_number(b);
1190                 r = make_number ((FP___TYPE)(a->u.i >= b->u.i));
1191         }
1192
1193         free_value (a);
1194         free_value (b);
1195         return r;
1196 }
1197
1198 static struct val *
1199 op_le (struct val *a, struct val *b)
1200 {
1201         struct val *r;
1202
1203         if (isstring (a) || isstring (b)) {
1204                 to_string (a);
1205                 to_string (b);
1206                 r = make_number ((FP___TYPE)(strcoll (a->u.s, b->u.s) <= 0));
1207         } else {
1208                 (void)to_number(a);
1209                 (void)to_number(b);
1210                 r = make_number ((FP___TYPE)(a->u.i <= b->u.i));
1211         }
1212
1213         free_value (a);
1214         free_value (b);
1215         return r;
1216 }
1217
1218 static struct val *
1219 op_cond (struct val *a, struct val *b, struct val *c)
1220 {
1221         struct val *r;
1222
1223         if( isstring(a) )
1224         {
1225                 if( strlen(a->u.s) && strcmp(a->u.s, "\"\"") != 0 && strcmp(a->u.s,"0") != 0 )
1226                 {
1227                         free_value(a);
1228                         free_value(c);
1229                         r = b;
1230                 }
1231                 else
1232                 {
1233                         free_value(a);
1234                         free_value(b);
1235                         r = c;
1236                 }
1237         }
1238         else
1239         {
1240                 (void)to_number(a);
1241                 if( a->u.i )
1242                 {
1243                         free_value(a);
1244                         free_value(c);
1245                         r = b;
1246                 }
1247                 else
1248                 {
1249                         free_value(a);
1250                         free_value(b);
1251                         r = c;
1252                 }
1253         }
1254         return r;
1255 }
1256
1257 static struct val *
1258 op_ne (struct val *a, struct val *b)
1259 {
1260         struct val *r;
1261
1262         if (isstring (a) || isstring (b)) {
1263                 to_string (a);
1264                 to_string (b);
1265                 r = make_number ((FP___TYPE)(strcoll (a->u.s, b->u.s) != 0));
1266         } else {
1267                 (void)to_number(a);
1268                 (void)to_number(b);
1269                 r = make_number ((FP___TYPE)(a->u.i != b->u.i));
1270         }
1271
1272         free_value (a);
1273         free_value (b);
1274         return r;
1275 }
1276
1277 static int
1278 chk_plus (FP___TYPE a, FP___TYPE b, FP___TYPE r)
1279 {
1280         /* sum of two positive numbers must be positive */
1281         if (a > 0 && b > 0 && r <= 0)
1282                 return 1;
1283         /* sum of two negative numbers must be negative */
1284         if (a < 0 && b < 0 && r >= 0)
1285                 return 1;
1286         /* all other cases are OK */
1287         return 0;
1288 }
1289
1290 static struct val *
1291 op_plus (struct val *a, struct val *b)
1292 {
1293         struct val *r;
1294
1295         if (!to_number (a)) {
1296                 if( !extra_error_message_supplied )
1297                         ast_log(LOG_WARNING,"non-numeric argument\n");
1298                 if (!to_number (b)) {
1299                         free_value(a);
1300                         free_value(b);
1301                         return make_number(0);
1302                 } else {
1303                         free_value(a);
1304                         return (b);
1305                 }
1306         } else if (!to_number(b)) {
1307                 free_value(b);
1308                 return (a);
1309         }
1310
1311         r = make_number (a->u.i + b->u.i);
1312         if (chk_plus (a->u.i, b->u.i, r->u.i)) {
1313                 ast_log(LOG_WARNING,"overflow\n");
1314         }
1315         free_value (a);
1316         free_value (b);
1317         return r;
1318 }
1319
1320 static int
1321 chk_minus (FP___TYPE a, FP___TYPE b, FP___TYPE r)
1322 {
1323         /* special case subtraction of QUAD_MIN */
1324         if (b == QUAD_MIN) {
1325                 if (a >= 0)
1326                         return 1;
1327                 else
1328                         return 0;
1329         }
1330         /* this is allowed for b != QUAD_MIN */
1331         return chk_plus (a, -b, r);
1332 }
1333
1334 static struct val *
1335 op_minus (struct val *a, struct val *b)
1336 {
1337         struct val *r;
1338
1339         if (!to_number (a)) {
1340                 if( !extra_error_message_supplied )
1341                         ast_log(LOG_WARNING, "non-numeric argument\n");
1342                 if (!to_number (b)) {
1343                         free_value(a);
1344                         free_value(b);
1345                         return make_number(0);
1346                 } else {
1347                         r = make_number(0 - b->u.i);
1348                         free_value(a);
1349                         free_value(b);
1350                         return (r);
1351                 }
1352         } else if (!to_number(b)) {
1353                 if( !extra_error_message_supplied )
1354                         ast_log(LOG_WARNING, "non-numeric argument\n");
1355                 free_value(b);
1356                 return (a);
1357         }
1358
1359         r = make_number (a->u.i - b->u.i);
1360         if (chk_minus (a->u.i, b->u.i, r->u.i)) {
1361                 ast_log(LOG_WARNING, "overflow\n");
1362         }
1363         free_value (a);
1364         free_value (b);
1365         return r;
1366 }
1367
1368 static struct val *
1369 op_negate (struct val *a)
1370 {
1371         struct val *r;
1372
1373         if (!to_number (a) ) {
1374                 free_value(a);
1375                 if( !extra_error_message_supplied )
1376                         ast_log(LOG_WARNING, "non-numeric argument\n");
1377                 return make_number(0);
1378         }
1379
1380         r = make_number (- a->u.i);
1381         if (chk_minus (0, a->u.i, r->u.i)) {
1382                 ast_log(LOG_WARNING, "overflow\n");
1383         }
1384         free_value (a);
1385         return r;
1386 }
1387
1388 static struct val *
1389 op_compl (struct val *a)
1390 {
1391         int v1 = 1;
1392         struct val *r;
1393         
1394         if( !a )
1395         {
1396                 v1 = 0;
1397         }
1398         else
1399         {
1400                 switch( a->type )
1401                 {
1402                 case AST_EXPR_number:
1403                         if( a->u.i == 0 )
1404                                 v1 = 0;
1405                         break;
1406                         
1407                 case AST_EXPR_string:
1408                         if( a->u.s == 0 )
1409                                 v1 = 0;
1410                         else
1411                         {
1412                                 if( a->u.s[0] == 0 )
1413                                         v1 = 0;
1414                                 else if (strlen(a->u.s) == 1 && a->u.s[0] == '0' )
1415                                         v1 = 0;
1416                                 else
1417                                         v1 = atoi(a->u.s);
1418                         }
1419                         break;
1420                         
1421                 case AST_EXPR_numeric_string:
1422                         if( a->u.s == 0 )
1423                                 v1 = 0;
1424                         else
1425                         {
1426                                 if( a->u.s[0] == 0 )
1427                                         v1 = 0;
1428                                 else if (strlen(a->u.s) == 1 && a->u.s[0] == '0' )
1429                                         v1 = 0;
1430                                 else
1431                                         v1 = atoi(a->u.s);
1432                         }
1433                         break;
1434                 }
1435         }
1436         
1437         r = make_number (!v1);
1438         free_value (a);
1439         return r;
1440 }
1441
1442 static int
1443 chk_times (FP___TYPE a, FP___TYPE b, FP___TYPE r)
1444 {
1445         /* special case: first operand is 0, no overflow possible */
1446         if (a == 0)
1447                 return 0;
1448         /* cerify that result of division matches second operand */
1449         if (r / a != b)
1450                 return 1;
1451         return 0;
1452 }
1453
1454 static struct val *
1455 op_times (struct val *a, struct val *b)
1456 {
1457         struct val *r;
1458
1459         if (!to_number (a) || !to_number (b)) {
1460                 free_value(a);
1461                 free_value(b);
1462                 if( !extra_error_message_supplied )
1463                         ast_log(LOG_WARNING, "non-numeric argument\n");
1464                 return(make_number(0));
1465         }
1466
1467         r = make_number (a->u.i * b->u.i);
1468         if (chk_times (a->u.i, b->u.i, r->u.i)) {
1469                 ast_log(LOG_WARNING, "overflow\n");
1470         }
1471         free_value (a);
1472         free_value (b);
1473         return (r);
1474 }
1475
1476 static int
1477 chk_div (FP___TYPE a, FP___TYPE b)
1478 {
1479         /* div by zero has been taken care of before */
1480         /* only QUAD_MIN / -1 causes overflow */
1481         if (a == QUAD_MIN && b == -1)
1482                 return 1;
1483         /* everything else is OK */
1484         return 0;
1485 }
1486
1487 static struct val *
1488 op_div (struct val *a, struct val *b)
1489 {
1490         struct val *r;
1491
1492         if (!to_number (a)) {
1493                 free_value(a);
1494                 free_value(b);
1495                 if( !extra_error_message_supplied )
1496                         ast_log(LOG_WARNING, "non-numeric argument\n");
1497                 return make_number(0);
1498         } else if (!to_number (b)) {
1499                 free_value(a);
1500                 free_value(b);
1501                 if( !extra_error_message_supplied )
1502                         ast_log(LOG_WARNING, "non-numeric argument\n");
1503                 return make_number(INT_MAX);
1504         }
1505
1506         if (b->u.i == 0) {
1507                 ast_log(LOG_WARNING, "division by zero\n");             
1508                 free_value(a);
1509                 free_value(b);
1510                 return make_number(INT_MAX);
1511         }
1512
1513         r = make_number (a->u.i / b->u.i);
1514         if (chk_div (a->u.i, b->u.i)) {
1515                 ast_log(LOG_WARNING, "overflow\n");
1516         }
1517         free_value (a);
1518         free_value (b);
1519         return r;
1520 }
1521         
1522 static struct val *
1523 op_rem (struct val *a, struct val *b)
1524 {
1525         struct val *r;
1526
1527         if (!to_number (a) || !to_number (b)) {
1528                 if( !extra_error_message_supplied )
1529                         ast_log(LOG_WARNING, "non-numeric argument\n");
1530                 free_value(a);
1531                 free_value(b);
1532                 return make_number(0);
1533         }
1534
1535         if (b->u.i == 0) {
1536                 ast_log(LOG_WARNING, "div by zero\n");
1537                 free_value(a);
1538                 return(b);
1539         }
1540
1541         r = make_number (FUNC_FMOD(a->u.i, b->u.i)); /* either fmod or fmodl if FP___TYPE is available */
1542         /* chk_rem necessary ??? */
1543         free_value (a);
1544         free_value (b);
1545         return r;
1546 }
1547         
1548
1549 static struct val *
1550 op_colon (struct val *a, struct val *b)
1551 {
1552         regex_t rp;
1553         regmatch_t rm[2];
1554         char errbuf[256];
1555         int eval;
1556         struct val *v;
1557
1558         /* coerce to both arguments to strings */
1559         to_string(a);
1560         to_string(b);
1561         /* strip double quotes from both -- they'll screw up the pattern, and the search string starting at ^ */
1562         strip_quotes(a);
1563         strip_quotes(b);
1564         /* compile regular expression */
1565         if ((eval = regcomp (&rp, b->u.s, REG_EXTENDED)) != 0) {
1566                 regerror (eval, &rp, errbuf, sizeof(errbuf));
1567                 ast_log(LOG_WARNING, "regcomp() error : %s\n", errbuf);
1568                 free_value(a);
1569                 free_value(b);
1570                 return make_str("");            
1571         }
1572
1573         /* compare string against pattern */
1574         /* remember that patterns are anchored to the beginning of the line */
1575         if (regexec(&rp, a->u.s, (size_t)2, rm, 0) == 0 && rm[0].rm_so == 0) {
1576                 if (rm[1].rm_so >= 0) {
1577                         *(a->u.s + rm[1].rm_eo) = '\0';
1578                         v = make_str (a->u.s + rm[1].rm_so);
1579
1580                 } else {
1581                         v = make_number ((FP___TYPE)(rm[0].rm_eo - rm[0].rm_so));
1582                 }
1583         } else {
1584                 if (rp.re_nsub == 0) {
1585                         v = make_number ((FP___TYPE)0);
1586                 } else {
1587                         v = make_str ("");
1588                 }
1589         }
1590
1591         /* free arguments and pattern buffer */
1592         free_value (a);
1593         free_value (b);
1594         regfree (&rp);
1595
1596         return v;
1597 }
1598         
1599
1600 static struct val *
1601 op_eqtilde (struct val *a, struct val *b)
1602 {
1603         regex_t rp;
1604         regmatch_t rm[2];
1605         char errbuf[256];
1606         int eval;
1607         struct val *v;
1608
1609         /* coerce to both arguments to strings */
1610         to_string(a);
1611         to_string(b);
1612         /* strip double quotes from both -- they'll screw up the pattern, and the search string starting at ^ */
1613         strip_quotes(a);
1614         strip_quotes(b);
1615         /* compile regular expression */
1616         if ((eval = regcomp (&rp, b->u.s, REG_EXTENDED)) != 0) {
1617                 regerror (eval, &rp, errbuf, sizeof(errbuf));
1618                 ast_log(LOG_WARNING, "regcomp() error : %s\n", errbuf);
1619                 free_value(a);
1620                 free_value(b);
1621                 return make_str("");            
1622         }
1623
1624         /* compare string against pattern */
1625         /* remember that patterns are anchored to the beginning of the line */
1626         if (regexec(&rp, a->u.s, (size_t)2, rm, 0) == 0 ) {
1627                 if (rm[1].rm_so >= 0) {
1628                         *(a->u.s + rm[1].rm_eo) = '\0';
1629                         v = make_str (a->u.s + rm[1].rm_so);
1630
1631                 } else {
1632                         v = make_number ((FP___TYPE)(rm[0].rm_eo - rm[0].rm_so));
1633                 }
1634         } else {
1635                 if (rp.re_nsub == 0) {
1636                         v = make_number ((FP___TYPE)0.0);
1637                 } else {
1638                         v = make_str ("");
1639                 }
1640         }
1641
1642         /* free arguments and pattern buffer */
1643         free_value (a);
1644         free_value (b);
1645         regfree (&rp);
1646
1647         return v;
1648 }
1649
1650 static struct val *  /* this is a string concat operator */
1651 op_tildetilde (struct val *a, struct val *b)
1652 {
1653         struct val *v;
1654         char *vs;
1655
1656         /* coerce to both arguments to strings */
1657         to_string(a);
1658         to_string(b);
1659         /* strip double quotes from both -- */
1660         strip_quotes(a);
1661         strip_quotes(b);
1662
1663         vs = malloc(strlen(a->u.s)+strlen(b->u.s)+1);
1664         if (vs == NULL) {
1665                 ast_log(LOG_WARNING, "malloc() failed\n");
1666                 free_value(a);
1667                 free_value(b);
1668                 return NULL;
1669         }
1670
1671         strcpy(vs,a->u.s);
1672         strcat(vs,b->u.s);
1673
1674         v = make_str(vs);
1675
1676         free(vs);
1677
1678         /* free arguments */
1679         free_value(a);
1680         free_value(b);
1681
1682         return v;
1683 }