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