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