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