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