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