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