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