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