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