2 /* Written by Pace Willisson (pace@blitz.com)
3 * and placed in the public domain.
5 * Largely rewritten by J.T. Conklin (jtc@wimsey.com)
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
12 * $FreeBSD: src/bin/expr/expr.y,v 1.16 2000/07/22 10:59:36 se Exp $
17 #include <sys/types.h>
20 #if !defined(STANDALONE) && !defined(STANDALONE2) \
22 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
25 #define __USE_ISOC99 1
30 #define FP___PRINTF "%.18Lg"
31 #define FP___TYPE long double
33 #define FP___PRINTF "%.16g"
34 #define FP___TYPE double
39 #elif defined(HAVE_COS)
40 #define FUNC_COS (long double)cos
45 #elif defined(HAVE_SIN)
46 #define FUNC_SIN (long double)sin
51 #elif defined(HAVE_TAN)
52 #define FUNC_TAN (long double)tan
56 #define FUNC_ACOS acosl
57 #elif defined(HAVE_ACOS)
58 #define FUNC_ACOS (long double)acos
62 #define FUNC_ASIN asinl
63 #elif defined(HAVE_ASIN)
64 #define FUNC_ASIN (long double)asin
68 #define FUNC_ATAN atanl
69 #elif defined(HAVE_ATAN)
70 #define FUNC_ATAN (long double)atan
74 #define FUNC_ATAN2 atan2l
75 #elif defined(HAVE_ATAN2)
76 #define FUNC_ATAN2 (long double)atan2
81 #elif defined(HAVE_POW)
82 #define FUNC_POW (long double)pow
86 #define FUNC_SQRT sqrtl
87 #elif defined(HAVE_SQRT)
88 #define FUNC_SQRT (long double)sqrt
92 #define FUNC_RINT rintl
93 #elif defined(HAVE_RINT)
94 #define FUNC_RINT (long double)rint
99 #elif defined(HAVE_EXP)
100 #define FUNC_EXP (long double)exp
104 #define FUNC_LOG logl
105 #elif defined(HAVE_LOG)
106 #define FUNC_LOG (long double)log
109 #ifdef HAVE_REMAINDERL
110 #define FUNC_REMAINDER remainderl
111 #elif defined(HAVE_REMAINDER)
112 #define FUNC_REMAINDER (long double)remainder
116 #define FUNC_FMOD fmodl
117 #elif defined(HAVE_FMOD)
118 #define FUNC_FMOD (long double)fmod
122 #define FUNC_STRTOD strtold
123 #elif defined(HAVE_STRTOD)
124 #define FUNC_STRTOD (long double)strtod
128 #define FUNC_FLOOR floorl
129 #elif defined(HAVE_FLOOR)
130 #define FUNC_FLOOR (long double)floor
134 #define FUNC_CEIL ceill
135 #elif defined(HAVE_CEIL)
136 #define FUNC_CEIL (long double)ceil
140 #define FUNC_ROUND roundl
141 #elif defined(HAVE_ROUND)
142 #define FUNC_ROUND (long double)round
146 #define FUNC_TRUNC truncl
147 #elif defined(HAVE_TRUNC)
148 #define FUNC_TRUNC (long double)trunc
152 * Oddly enough, some platforms have some ISO C99 functions, but not others, so
153 * we define the missing functions in terms of their mathematical identities.
156 #define FUNC_EXP2 exp2l
157 #elif (defined(HAVE_EXPL) && defined(HAVE_LOGL))
158 #define FUNC_EXP2(x) expl((x) * logl(2.0))
159 #elif (defined(HAVE_EXP) && defined(HAVE_LOG))
160 #define FUNC_EXP2(x) (long double)exp((x) * log(2.0))
164 #define FUNC_EXP10 exp10l
165 #elif (defined(HAVE_EXPL) && defined(HAVE_LOGL))
166 #define FUNC_EXP10(x) expl((x) * logl(10.0))
167 #elif (defined(HAVE_EXP) && defined(HAVE_LOG))
168 #define FUNC_EXP10(x) (long double)exp((x) * log(10.0))
172 #define FUNC_LOG2 log2l
173 #elif defined(HAVE_LOGL)
174 #define FUNC_LOG2(x) (logl(x) / logl(2.0))
175 #elif defined(HAVE_LOG10L)
176 #define FUNC_LOG2(x) (log10l(x) / log10l(2.0))
177 #elif defined(HAVE_LOG2)
178 #define FUNC_LOG2 (long double)log2
179 #elif defined(HAVE_LOG)
180 #define FUNC_LOG2(x) ((long double)log(x) / log(2.0))
184 #define FUNC_LOG10 log10l
185 #elif defined(HAVE_LOGL)
186 #define FUNC_LOG10(x) (logl(x) / logl(10.0))
187 #elif defined(HAVE_LOG2L)
188 #define FUNC_LOG10(x) (log2l(x) / log2l(10.0))
189 #elif defined(HAVE_LOG10)
190 #define FUNC_LOG10(x) (long double)log10(x)
191 #elif defined(HAVE_LOG)
192 #define FUNC_LOG10(x) ((long double)log(x) / log(10.0))
205 #if !defined(SOLARIS) && !defined(__CYGWIN__)
206 /* #include <err.h> */
208 #define quad_t int64_t
214 #include "asterisk/ast_expr.h"
215 #include "asterisk/logger.h"
216 #if !defined(STANDALONE) && !defined(STANDALONE2)
217 #include "asterisk/pbx.h"
220 #if defined(LONG_LONG_MIN) && !defined(QUAD_MIN)
221 #define QUAD_MIN LONG_LONG_MIN
223 #if defined(LONG_LONG_MAX) && !defined(QUAD_MAX)
224 #define QUAD_MAX LONG_LONG_MAX
227 # if ! defined(QUAD_MIN)
228 # define QUAD_MIN (-0x7fffffffffffffffLL-1)
230 # if ! defined(QUAD_MAX)
231 # define QUAD_MAX (0x7fffffffffffffffLL)
233 #define YYENABLE_NLS 0
234 #define YYPARSE_PARAM parseio
235 #define YYLEX_PARAM ((struct parse_io *)parseio)->scanner
236 #define YYERROR_VERBOSE 1
237 extern char extra_error_message[4095];
238 extern int extra_error_message_supplied;
241 AST_EXPR_number, AST_EXPR_numeric_string, AST_EXPR_string
244 #if defined(STANDALONE) || defined(STANDALONE2)
245 void ast_log(int level, const char *file, int line, const char *function, const char *fmt, ...) __attribute__ ((format (printf,5,6)));
252 FP___TYPE i; /* either long double, or just double, on a bad day */
257 AST_EXPR_NODE_COMMA, AST_EXPR_NODE_STRING, AST_EXPR_NODE_VAL
264 struct expr_node *left;
265 struct expr_node *right;
269 typedef void *yyscan_t;
276 struct ast_channel *chan;
279 static int chk_div __P((FP___TYPE, FP___TYPE));
280 static int chk_minus __P((FP___TYPE, FP___TYPE, FP___TYPE));
281 static int chk_plus __P((FP___TYPE, FP___TYPE, FP___TYPE));
282 static int chk_times __P((FP___TYPE, FP___TYPE, FP___TYPE));
283 static void free_value __P((struct val *));
284 static int is_zero_or_null __P((struct val *));
285 static int isstring __P((struct val *));
286 static struct val *make_number __P((FP___TYPE));
287 static struct val *make_str __P((const char *));
288 static struct val *op_and __P((struct val *, struct val *));
289 static struct val *op_colon __P((struct val *, struct val *));
290 static struct val *op_eqtilde __P((struct val *, struct val *));
291 static struct val *op_tildetilde __P((struct val *, struct val *));
292 static struct val *op_div __P((struct val *, struct val *));
293 static struct val *op_eq __P((struct val *, struct val *));
294 static struct val *op_ge __P((struct val *, struct val *));
295 static struct val *op_gt __P((struct val *, struct val *));
296 static struct val *op_le __P((struct val *, struct val *));
297 static struct val *op_lt __P((struct val *, struct val *));
298 static struct val *op_cond __P((struct val *, struct val *, struct val *));
299 static struct val *op_minus __P((struct val *, struct val *));
300 static struct val *op_negate __P((struct val *));
301 static struct val *op_compl __P((struct val *));
302 static struct val *op_ne __P((struct val *, struct val *));
303 static struct val *op_or __P((struct val *, struct val *));
304 static struct val *op_plus __P((struct val *, struct val *));
305 static struct val *op_rem __P((struct val *, struct val *));
306 static struct val *op_times __P((struct val *, struct val *));
307 static struct val *op_func(struct val *funcname, struct expr_node *arglist, struct ast_channel *chan);
308 static int to_number __P((struct val *));
309 static void to_string __P((struct val *));
310 static struct expr_node *alloc_expr_node(enum node_type);
311 static void destroy_arglist(struct expr_node *arglist);
313 /* uh, if I want to predeclare yylex with a YYLTYPE, I have to predeclare the yyltype... sigh */
314 typedef struct yyltype
323 # define YYLTYPE yyltype
324 # define YYLTYPE_IS_TRIVIAL 1
326 /* we will get warning about no prototype for yylex! But we can't
327 define it here, we have no definition yet for YYSTYPE. */
329 int ast_yyerror(const char *,YYLTYPE *, struct parse_io *);
331 /* I wanted to add args to the yyerror routine, so I could print out
332 some useful info about the error. Not as easy as it looks, but it
334 #define ast_yyerror(x) ast_yyerror(x,&yyloc,parseio)
335 #define DESTROY(x) {if((x)->type == AST_EXPR_numeric_string || (x)->type == AST_EXPR_string) free((x)->u.s); (x)->u.s = 0; free(x);}
340 /* %debug for when you are having big problems */
342 /* %name-prefix="ast_yy" */
347 struct expr_node *arglist;
351 extern int ast_yylex __P((YYSTYPE *, YYLTYPE *, yyscan_t));
353 %left <val> TOK_COMMA
354 %left <val> TOK_COND TOK_COLONCOLON
357 %left <val> TOK_EQ TOK_GT TOK_LT TOK_GE TOK_LE TOK_NE
358 %left <val> TOK_PLUS TOK_MINUS
359 %left <val> TOK_MULT TOK_DIV TOK_MOD
360 %right <val> TOK_COMPL
361 %left <val> TOK_COLON TOK_EQTILDE TOK_TILDETILDE
362 %left <val> TOK_RP TOK_LP
365 %type <arglist> arglist
366 %type <val> start expr
368 %destructor { free_value($$); } expr TOKEN TOK_COND TOK_COLONCOLON TOK_OR TOK_AND TOK_EQ
369 TOK_GT TOK_LT TOK_GE TOK_LE TOK_NE TOK_PLUS TOK_MINUS TOK_MULT TOK_DIV TOK_MOD TOK_COMPL TOK_COLON TOK_EQTILDE
370 TOK_RP TOK_LP TOK_TILDETILDE
374 start: expr { ((struct parse_io *)parseio)->val = (struct val *)calloc(sizeof(struct val),1);
375 ((struct parse_io *)parseio)->val->type = $1->type;
376 if( $1->type == AST_EXPR_number )
377 ((struct parse_io *)parseio)->val->u.i = $1->u.i;
379 ((struct parse_io *)parseio)->val->u.s = $1->u.s;
382 | {/* nothing */ ((struct parse_io *)parseio)->val = (struct val *)calloc(sizeof(struct val),1);
383 ((struct parse_io *)parseio)->val->type = AST_EXPR_string;
384 ((struct parse_io *)parseio)->val->u.s = strdup("");
389 arglist: expr { $$ = alloc_expr_node(AST_EXPR_NODE_VAL); $$->val = $1;}
390 | arglist TOK_COMMA expr %prec TOK_RP {struct expr_node *x = alloc_expr_node(AST_EXPR_NODE_VAL);
393 for (t=$1;t->right;t=t->right)
395 $$ = $1; t->right = x; x->val = $3;}
396 | arglist TOK_COMMA %prec TOK_RP {struct expr_node *x = alloc_expr_node(AST_EXPR_NODE_VAL);
397 struct expr_node *t; /* NULL args should OK */
399 for (t=$1;t->right;t=t->right)
401 $$ = $1; t->right = x; x->val = make_str("");}
405 TOKEN TOK_LP arglist TOK_RP { $$ = op_func($1,$3, ((struct parse_io *)parseio)->chan);
412 | TOK_LP expr TOK_RP { $$ = $2;
413 @$.first_column = @1.first_column; @$.last_column = @3.last_column;
414 @$.first_line=0; @$.last_line=0;
415 DESTROY($1); DESTROY($3); }
416 | expr TOK_OR expr { $$ = op_or ($1, $3);
418 @$.first_column = @1.first_column; @$.last_column = @3.last_column;
419 @$.first_line=0; @$.last_line=0;}
420 | expr TOK_AND expr { $$ = op_and ($1, $3);
422 @$.first_column = @1.first_column; @$.last_column = @3.last_column;
423 @$.first_line=0; @$.last_line=0;}
424 | expr TOK_EQ expr { $$ = op_eq ($1, $3);
426 @$.first_column = @1.first_column; @$.last_column = @3.last_column;
427 @$.first_line=0; @$.last_line=0;}
428 | expr TOK_GT expr { $$ = op_gt ($1, $3);
430 @$.first_column = @1.first_column; @$.last_column = @3.last_column;
431 @$.first_line=0; @$.last_line=0;}
432 | expr TOK_LT expr { $$ = op_lt ($1, $3);
434 @$.first_column = @1.first_column; @$.last_column = @3.last_column;
435 @$.first_line=0; @$.last_line=0;}
436 | expr TOK_GE expr { $$ = op_ge ($1, $3);
438 @$.first_column = @1.first_column; @$.last_column = @3.last_column;
439 @$.first_line=0; @$.last_line=0;}
440 | expr TOK_LE expr { $$ = op_le ($1, $3);
442 @$.first_column = @1.first_column; @$.last_column = @3.last_column;
443 @$.first_line=0; @$.last_line=0;}
444 | expr TOK_NE expr { $$ = op_ne ($1, $3);
446 @$.first_column = @1.first_column; @$.last_column = @3.last_column;
447 @$.first_line=0; @$.last_line=0;}
448 | expr TOK_PLUS expr { $$ = op_plus ($1, $3);
450 @$.first_column = @1.first_column; @$.last_column = @3.last_column;
451 @$.first_line=0; @$.last_line=0;}
452 | expr TOK_MINUS expr { $$ = op_minus ($1, $3);
454 @$.first_column = @1.first_column; @$.last_column = @3.last_column;
455 @$.first_line=0; @$.last_line=0;}
456 | TOK_MINUS expr %prec TOK_COMPL { $$ = op_negate ($2);
458 @$.first_column = @1.first_column; @$.last_column = @2.last_column;
459 @$.first_line=0; @$.last_line=0;}
460 | TOK_COMPL expr { $$ = op_compl ($2);
462 @$.first_column = @1.first_column; @$.last_column = @2.last_column;
463 @$.first_line=0; @$.last_line=0;}
464 | expr TOK_MULT expr { $$ = op_times ($1, $3);
466 @$.first_column = @1.first_column; @$.last_column = @3.last_column;
467 @$.first_line=0; @$.last_line=0;}
468 | expr TOK_DIV expr { $$ = op_div ($1, $3);
470 @$.first_column = @1.first_column; @$.last_column = @3.last_column;
471 @$.first_line=0; @$.last_line=0;}
472 | expr TOK_MOD expr { $$ = op_rem ($1, $3);
474 @$.first_column = @1.first_column; @$.last_column = @3.last_column;
475 @$.first_line=0; @$.last_line=0;}
476 | expr TOK_COLON expr { $$ = op_colon ($1, $3);
478 @$.first_column = @1.first_column; @$.last_column = @3.last_column;
479 @$.first_line=0; @$.last_line=0;}
480 | expr TOK_EQTILDE expr { $$ = op_eqtilde ($1, $3);
482 @$.first_column = @1.first_column; @$.last_column = @3.last_column;
483 @$.first_line=0; @$.last_line=0;}
484 | expr TOK_COND expr TOK_COLONCOLON expr { $$ = op_cond ($1, $3, $5);
487 @$.first_column = @1.first_column; @$.last_column = @3.last_column;
488 @$.first_line=0; @$.last_line=0;}
489 | expr TOK_TILDETILDE expr { $$ = op_tildetilde ($1, $3);
491 @$.first_column = @1.first_column; @$.last_column = @3.last_column;
492 @$.first_line=0; @$.last_line=0;}
497 static struct expr_node *alloc_expr_node(enum node_type nt)
499 struct expr_node *x = calloc(1,sizeof(struct expr_node));
501 ast_log(LOG_ERROR, "Allocation for expr_node FAILED!!\n");
511 make_number (FP___TYPE i)
515 vp = (struct val *) malloc (sizeof (*vp));
517 ast_log(LOG_WARNING, "malloc() failed\n");
521 vp->type = AST_EXPR_number;
527 make_str (const char *s)
531 int isint; /* this started out being a test for an integer, but then ended up being a test for a float */
533 vp = (struct val *) malloc (sizeof (*vp));
534 if (vp == NULL || ((vp->u.s = strdup (s)) == NULL)) {
535 ast_log(LOG_WARNING,"malloc() failed\n");
539 for (i = 0, isint = (isdigit(s[0]) || s[0] == '-' || s[0]=='.'); isint && i < strlen(s); i++)
541 if (!isdigit(s[i]) && s[i] != '.') {
547 vp->type = AST_EXPR_numeric_string;
549 vp->type = AST_EXPR_string;
556 free_value (struct val *vp)
561 if (vp->type == AST_EXPR_string || vp->type == AST_EXPR_numeric_string)
568 to_number (struct val *vp)
573 ast_log(LOG_WARNING,"vp==NULL in to_number()\n");
577 if (vp->type == AST_EXPR_number)
580 if (vp->type == AST_EXPR_string)
583 /* vp->type == AST_EXPR_numeric_string, make it numeric */
585 i = FUNC_STRTOD(vp->u.s, (char**)0); /* either strtod, or strtold on a good day */
587 ast_log(LOG_WARNING,"Conversion of %s to number under/overflowed!\n", vp->u.s);
594 vp->type = AST_EXPR_number;
599 strip_quotes(struct val *vp)
601 if (vp->type != AST_EXPR_string && vp->type != AST_EXPR_numeric_string)
604 if( vp->u.s[0] == '"' && vp->u.s[strlen(vp->u.s)-1] == '"' )
612 if( *f && *f != '"' )
622 to_string (struct val *vp)
626 if (vp->type == AST_EXPR_string || vp->type == AST_EXPR_numeric_string)
629 tmp = malloc ((size_t)25);
631 ast_log(LOG_WARNING,"malloc() failed\n");
635 sprintf(tmp, FP___PRINTF, vp->u.i);
636 vp->type = AST_EXPR_string;
642 isstring (struct val *vp)
644 /* only TRUE if this string is not a valid number */
645 return (vp->type == AST_EXPR_string);
650 is_zero_or_null (struct val *vp)
652 if (vp->type == AST_EXPR_number) {
653 return (vp->u.i == 0);
655 return (*vp->u.s == 0 || (to_number(vp) && vp->u.i == 0));
662 void ast_log(int level, const char *file, int line, const char *function, const char *fmt, ...)
667 printf("LOG: lev:%d file:%s line:%d func: %s ",
668 level, file, line, function);
675 int main(int argc,char **argv) {
683 if( access(argv[1],F_OK)== 0 )
687 infile = fopen(argv[1],"r");
690 printf("Sorry, couldn't open %s for reading!\n", argv[1]);
693 while( fgets(s,sizeof(s),infile) )
695 if( s[strlen(s)-1] == '\n' )
698 ret = ast_expr(s, out, sizeof(out), NULL);
699 printf("Expression: %s Result: [%d] '%s'\n",
706 if (ast_expr(argv[1], s, sizeof(s), NULL))
707 printf("=====%s======\n",s);
709 printf("No result\n");
717 #define ast_yyerror(x) ast_yyerror(x, YYLTYPE *yylloc, struct parse_io *parseio)
719 /* I put the ast_yyerror func in the flex input file,
720 because it refers to the buffer state. Best to
721 let it access the BUFFER stuff there and not trying
722 define all the structs, macros etc. in this file! */
724 static void destroy_arglist(struct expr_node *arglist)
726 struct expr_node *arglist_next;
730 arglist_next = arglist->right;
732 free_value(arglist->val);
736 arglist = arglist_next;
740 #if !defined(STANDALONE) && !defined(STANDALONE2)
741 static char *compose_func_args(struct expr_node *arglist)
743 struct expr_node *t = arglist;
749 total_len += 1; /* for the sep */
751 if (t->val->type == AST_EXPR_number)
752 total_len += 25; /* worst case */
754 total_len += strlen(t->val->u.s);
759 total_len++; /* for the null */
760 ast_log(LOG_NOTICE,"argbuf allocated %d bytes;\n", total_len);
761 argbuf = malloc(total_len);
771 if (t->val->type == AST_EXPR_number) {
772 sprintf(numbuf,FP___PRINTF,t->val->u.i);
773 strcat(argbuf,numbuf);
775 strcat(argbuf,t->val->u.s);
779 ast_log(LOG_NOTICE,"argbuf uses %d bytes;\n", (int) strlen(argbuf));
783 static int is_really_num(char *str)
785 if ( strspn(str,"-0123456789. ") == strlen(str))
792 static struct val *op_func(struct val *funcname, struct expr_node *arglist, struct ast_channel *chan)
794 if (strspn(funcname->u.s,"ABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789") == strlen(funcname->u.s))
799 } else if (strcmp(funcname->u.s,"COS") == 0) {
800 if (arglist && !arglist->right && arglist->val){
801 to_number(arglist->val);
802 result = make_number(FUNC_COS(arglist->val->u.i));
805 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
806 return make_number(0.0);
810 } else if (strcmp(funcname->u.s,"SIN") == 0) {
811 if (arglist && !arglist->right && arglist->val){
812 to_number(arglist->val);
813 result = make_number(FUNC_SIN(arglist->val->u.i));
816 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
817 return make_number(0.0);
821 } else if (strcmp(funcname->u.s,"TAN") == 0) {
822 if (arglist && !arglist->right && arglist->val){
823 to_number(arglist->val);
824 result = make_number(FUNC_TAN(arglist->val->u.i));
827 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
828 return make_number(0.0);
832 } else if (strcmp(funcname->u.s,"ACOS") == 0) {
833 if (arglist && !arglist->right && arglist->val){
834 to_number(arglist->val);
835 result = make_number(FUNC_ACOS(arglist->val->u.i));
838 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
839 return make_number(0.0);
843 } else if (strcmp(funcname->u.s,"ASIN") == 0) {
844 if (arglist && !arglist->right && arglist->val){
845 to_number(arglist->val);
846 result = make_number(FUNC_ASIN(arglist->val->u.i));
849 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
850 return make_number(0.0);
854 } else if (strcmp(funcname->u.s,"ATAN") == 0) {
855 if (arglist && !arglist->right && arglist->val){
856 to_number(arglist->val);
857 result = make_number(FUNC_ATAN(arglist->val->u.i));
860 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
861 return make_number(0.0);
865 } else if (strcmp(funcname->u.s,"ATAN2") == 0) {
866 if (arglist && arglist->right && !arglist->right->right && arglist->val && arglist->right->val){
867 to_number(arglist->val);
868 to_number(arglist->right->val);
869 result = make_number(FUNC_ATAN2(arglist->val->u.i, arglist->right->val->u.i));
872 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
873 return make_number(0.0);
877 } else if (strcmp(funcname->u.s,"POW") == 0) {
878 if (arglist && arglist->right && !arglist->right->right && arglist->val && arglist->right->val){
879 to_number(arglist->val);
880 to_number(arglist->right->val);
881 result = make_number(FUNC_POW(arglist->val->u.i, arglist->right->val->u.i));
884 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
885 return make_number(0.0);
889 } else if (strcmp(funcname->u.s,"SQRT") == 0) {
890 if (arglist && !arglist->right && arglist->val){
891 to_number(arglist->val);
892 result = make_number(FUNC_SQRT(arglist->val->u.i));
895 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
896 return make_number(0.0);
900 } else if (strcmp(funcname->u.s,"FLOOR") == 0) {
901 if (arglist && !arglist->right && arglist->val){
902 to_number(arglist->val);
903 result = make_number(FUNC_FLOOR(arglist->val->u.i));
906 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
907 return make_number(0.0);
911 } else if (strcmp(funcname->u.s,"CEIL") == 0) {
912 if (arglist && !arglist->right && arglist->val){
913 to_number(arglist->val);
914 result = make_number(FUNC_CEIL(arglist->val->u.i));
917 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
918 return make_number(0.0);
922 } else if (strcmp(funcname->u.s,"ROUND") == 0) {
923 if (arglist && !arglist->right && arglist->val){
924 to_number(arglist->val);
925 result = make_number(FUNC_ROUND(arglist->val->u.i));
928 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
929 return make_number(0.0);
931 #endif /* defined(FUNC_ROUND) */
933 } else if (strcmp(funcname->u.s,"RINT") == 0) {
934 if (arglist && !arglist->right && arglist->val){
935 to_number(arglist->val);
936 result = make_number(FUNC_RINT(arglist->val->u.i));
939 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
940 return make_number(0.0);
944 } else if (strcmp(funcname->u.s,"TRUNC") == 0) {
945 if (arglist && !arglist->right && arglist->val){
946 to_number(arglist->val);
947 result = make_number(FUNC_TRUNC(arglist->val->u.i));
950 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
951 return make_number(0.0);
953 #endif /* defined(FUNC_TRUNC) */
955 } else if (strcmp(funcname->u.s,"EXP") == 0) {
956 if (arglist && !arglist->right && arglist->val){
957 to_number(arglist->val);
958 result = make_number(FUNC_EXP(arglist->val->u.i));
961 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
962 return make_number(0.0);
966 } else if (strcmp(funcname->u.s,"EXP2") == 0) {
967 if (arglist && !arglist->right && arglist->val){
968 to_number(arglist->val);
969 result = make_number(FUNC_EXP2(arglist->val->u.i));
972 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
973 return make_number(0.0);
977 } else if (strcmp(funcname->u.s,"EXP10") == 0) {
978 if (arglist && !arglist->right && arglist->val){
979 to_number(arglist->val);
980 result = make_number(FUNC_EXP10(arglist->val->u.i));
983 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
984 return make_number(0.0);
988 } else if (strcmp(funcname->u.s,"LOG") == 0) {
989 if (arglist && !arglist->right && arglist->val){
990 to_number(arglist->val);
991 result = make_number(FUNC_LOG(arglist->val->u.i));
994 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
995 return make_number(0.0);
999 } else if (strcmp(funcname->u.s,"LOG2") == 0) {
1000 if (arglist && !arglist->right && arglist->val){
1001 to_number(arglist->val);
1002 result = make_number(FUNC_LOG2(arglist->val->u.i));
1005 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
1006 return make_number(0.0);
1010 } else if (strcmp(funcname->u.s,"LOG10") == 0) {
1011 if (arglist && !arglist->right && arglist->val){
1012 to_number(arglist->val);
1013 result = make_number(FUNC_LOG10(arglist->val->u.i));
1016 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
1017 return make_number(0.0);
1020 #ifdef FUNC_REMAINDER
1021 } else if (strcmp(funcname->u.s,"REMAINDER") == 0) {
1022 if (arglist && arglist->right && !arglist->right->right && arglist->val && arglist->right->val){
1023 to_number(arglist->val);
1024 to_number(arglist->right->val);
1025 result = make_number(FUNC_REMAINDER(arglist->val->u.i, arglist->right->val->u.i));
1028 ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
1029 return make_number(0.0);
1033 /* is this a custom function we should execute and collect the results of? */
1034 #if !defined(STANDALONE) && !defined(STANDALONE2)
1035 struct ast_custom_function *f = ast_custom_function_find(funcname->u.s);
1037 ast_log(LOG_WARNING,"Hey! chan is NULL.\n");
1039 ast_log(LOG_WARNING,"Hey! could not find func %s.\n", funcname->u.s);
1043 char workspace[512];
1044 char *argbuf = compose_func_args(arglist);
1045 f->read(chan, funcname->u.s, argbuf, workspace, sizeof(workspace));
1047 if (is_really_num(workspace))
1048 return make_number(FUNC_STRTOD(workspace,(char **)NULL));
1050 return make_str(workspace);
1052 ast_log(LOG_ERROR,"Error! Function '%s' cannot be read!\n", funcname->u.s);
1053 return (make_number ((FP___TYPE)0.0));
1057 ast_log(LOG_ERROR,"Error! '%s' doesn't appear to be an available function!", funcname->u.s);
1058 return (make_number ((FP___TYPE)0.0));
1061 ast_log(LOG_ERROR,"Error! '%s' is not available in the standalone version!", funcname->u.s);
1062 return (make_number ((FP___TYPE)0.0));
1068 ast_log(LOG_ERROR,"Error! '%s' is not possibly a function name!", funcname->u.s);
1069 return (make_number ((FP___TYPE)0.0));
1071 return (make_number ((FP___TYPE)0.0));
1076 op_or (struct val *a, struct val *b)
1078 if (is_zero_or_null (a)) {
1088 op_and (struct val *a, struct val *b)
1090 if (is_zero_or_null (a) || is_zero_or_null (b)) {
1093 return (make_number ((FP___TYPE)0.0));
1101 op_eq (struct val *a, struct val *b)
1105 if (isstring (a) || isstring (b)) {
1108 r = make_number ((FP___TYPE)(strcoll (a->u.s, b->u.s) == 0));
1110 #ifdef DEBUG_FOR_CONVERSIONS
1112 sprintf(buffer,"Converting '%s' and '%s' ", a->u.s, b->u.s);
1116 #ifdef DEBUG_FOR_CONVERSIONS
1117 ast_log(LOG_WARNING,"%s to '%lld' and '%lld'\n", buffer, a->u.i, b->u.i);
1119 r = make_number ((FP___TYPE)(a->u.i == b->u.i));
1128 op_gt (struct val *a, struct val *b)
1132 if (isstring (a) || isstring (b)) {
1135 r = make_number ((FP___TYPE)(strcoll (a->u.s, b->u.s) > 0));
1139 r = make_number ((FP___TYPE)(a->u.i > b->u.i));
1148 op_lt (struct val *a, struct val *b)
1152 if (isstring (a) || isstring (b)) {
1155 r = make_number ((FP___TYPE)(strcoll (a->u.s, b->u.s) < 0));
1159 r = make_number ((FP___TYPE)(a->u.i < b->u.i));
1168 op_ge (struct val *a, struct val *b)
1172 if (isstring (a) || isstring (b)) {
1175 r = make_number ((FP___TYPE)(strcoll (a->u.s, b->u.s) >= 0));
1179 r = make_number ((FP___TYPE)(a->u.i >= b->u.i));
1188 op_le (struct val *a, struct val *b)
1192 if (isstring (a) || isstring (b)) {
1195 r = make_number ((FP___TYPE)(strcoll (a->u.s, b->u.s) <= 0));
1199 r = make_number ((FP___TYPE)(a->u.i <= b->u.i));
1208 op_cond (struct val *a, struct val *b, struct val *c)
1214 if( strlen(a->u.s) && strcmp(a->u.s, "\"\"") != 0 && strcmp(a->u.s,"0") != 0 )
1247 op_ne (struct val *a, struct val *b)
1251 if (isstring (a) || isstring (b)) {
1254 r = make_number ((FP___TYPE)(strcoll (a->u.s, b->u.s) != 0));
1258 r = make_number ((FP___TYPE)(a->u.i != b->u.i));
1267 chk_plus (FP___TYPE a, FP___TYPE b, FP___TYPE r)
1269 /* sum of two positive numbers must be positive */
1270 if (a > 0 && b > 0 && r <= 0)
1272 /* sum of two negative numbers must be negative */
1273 if (a < 0 && b < 0 && r >= 0)
1275 /* all other cases are OK */
1280 op_plus (struct val *a, struct val *b)
1284 if (!to_number (a)) {
1285 if( !extra_error_message_supplied )
1286 ast_log(LOG_WARNING,"non-numeric argument\n");
1287 if (!to_number (b)) {
1290 return make_number(0);
1295 } else if (!to_number(b)) {
1300 r = make_number (a->u.i + b->u.i);
1301 if (chk_plus (a->u.i, b->u.i, r->u.i)) {
1302 ast_log(LOG_WARNING,"overflow\n");
1310 chk_minus (FP___TYPE a, FP___TYPE b, FP___TYPE r)
1312 /* special case subtraction of QUAD_MIN */
1313 if (b == QUAD_MIN) {
1319 /* this is allowed for b != QUAD_MIN */
1320 return chk_plus (a, -b, r);
1324 op_minus (struct val *a, struct val *b)
1328 if (!to_number (a)) {
1329 if( !extra_error_message_supplied )
1330 ast_log(LOG_WARNING, "non-numeric argument\n");
1331 if (!to_number (b)) {
1334 return make_number(0);
1336 r = make_number(0 - b->u.i);
1341 } else if (!to_number(b)) {
1342 if( !extra_error_message_supplied )
1343 ast_log(LOG_WARNING, "non-numeric argument\n");
1348 r = make_number (a->u.i - b->u.i);
1349 if (chk_minus (a->u.i, b->u.i, r->u.i)) {
1350 ast_log(LOG_WARNING, "overflow\n");
1358 op_negate (struct val *a)
1362 if (!to_number (a) ) {
1364 if( !extra_error_message_supplied )
1365 ast_log(LOG_WARNING, "non-numeric argument\n");
1366 return make_number(0);
1369 r = make_number (- a->u.i);
1370 if (chk_minus (0, a->u.i, r->u.i)) {
1371 ast_log(LOG_WARNING, "overflow\n");
1378 op_compl (struct val *a)
1391 case AST_EXPR_number:
1396 case AST_EXPR_string:
1401 if( a->u.s[0] == 0 )
1403 else if (strlen(a->u.s) == 1 && a->u.s[0] == '0' )
1408 case AST_EXPR_numeric_string:
1413 if( a->u.s[0] == 0 )
1415 else if (strlen(a->u.s) == 1 && a->u.s[0] == '0' )
1422 r = make_number (!v1);
1428 chk_times (FP___TYPE a, FP___TYPE b, FP___TYPE r)
1430 /* special case: first operand is 0, no overflow possible */
1433 /* cerify that result of division matches second operand */
1440 op_times (struct val *a, struct val *b)
1444 if (!to_number (a) || !to_number (b)) {
1447 if( !extra_error_message_supplied )
1448 ast_log(LOG_WARNING, "non-numeric argument\n");
1449 return(make_number(0));
1452 r = make_number (a->u.i * b->u.i);
1453 if (chk_times (a->u.i, b->u.i, r->u.i)) {
1454 ast_log(LOG_WARNING, "overflow\n");
1462 chk_div (FP___TYPE a, FP___TYPE b)
1464 /* div by zero has been taken care of before */
1465 /* only QUAD_MIN / -1 causes overflow */
1466 if (a == QUAD_MIN && b == -1)
1468 /* everything else is OK */
1473 op_div (struct val *a, struct val *b)
1477 if (!to_number (a)) {
1480 if( !extra_error_message_supplied )
1481 ast_log(LOG_WARNING, "non-numeric argument\n");
1482 return make_number(0);
1483 } else if (!to_number (b)) {
1486 if( !extra_error_message_supplied )
1487 ast_log(LOG_WARNING, "non-numeric argument\n");
1488 return make_number(INT_MAX);
1492 ast_log(LOG_WARNING, "division by zero\n");
1495 return make_number(INT_MAX);
1498 r = make_number (a->u.i / b->u.i);
1499 if (chk_div (a->u.i, b->u.i)) {
1500 ast_log(LOG_WARNING, "overflow\n");
1508 op_rem (struct val *a, struct val *b)
1512 if (!to_number (a) || !to_number (b)) {
1513 if( !extra_error_message_supplied )
1514 ast_log(LOG_WARNING, "non-numeric argument\n");
1517 return make_number(0);
1521 ast_log(LOG_WARNING, "div by zero\n");
1526 r = make_number (FUNC_FMOD(a->u.i, b->u.i)); /* either fmod or fmodl if FP___TYPE is available */
1527 /* chk_rem necessary ??? */
1535 op_colon (struct val *a, struct val *b)
1543 /* coerce to both arguments to strings */
1546 /* strip double quotes from both -- they'll screw up the pattern, and the search string starting at ^ */
1549 /* compile regular expression */
1550 if ((eval = regcomp (&rp, b->u.s, REG_EXTENDED)) != 0) {
1551 regerror (eval, &rp, errbuf, sizeof(errbuf));
1552 ast_log(LOG_WARNING,"regcomp() error : %s",errbuf);
1555 return make_str("");
1558 /* compare string against pattern */
1559 /* remember that patterns are anchored to the beginning of the line */
1560 if (regexec(&rp, a->u.s, (size_t)2, rm, 0) == 0 && rm[0].rm_so == 0) {
1561 if (rm[1].rm_so >= 0) {
1562 *(a->u.s + rm[1].rm_eo) = '\0';
1563 v = make_str (a->u.s + rm[1].rm_so);
1566 v = make_number ((FP___TYPE)(rm[0].rm_eo - rm[0].rm_so));
1569 if (rp.re_nsub == 0) {
1570 v = make_number ((FP___TYPE)0);
1576 /* free arguments and pattern buffer */
1586 op_eqtilde (struct val *a, struct val *b)
1594 /* coerce to both arguments to strings */
1597 /* strip double quotes from both -- they'll screw up the pattern, and the search string starting at ^ */
1600 /* compile regular expression */
1601 if ((eval = regcomp (&rp, b->u.s, REG_EXTENDED)) != 0) {
1602 regerror (eval, &rp, errbuf, sizeof(errbuf));
1603 ast_log(LOG_WARNING,"regcomp() error : %s",errbuf);
1606 return make_str("");
1609 /* compare string against pattern */
1610 /* remember that patterns are anchored to the beginning of the line */
1611 if (regexec(&rp, a->u.s, (size_t)2, rm, 0) == 0 ) {
1612 if (rm[1].rm_so >= 0) {
1613 *(a->u.s + rm[1].rm_eo) = '\0';
1614 v = make_str (a->u.s + rm[1].rm_so);
1617 v = make_number ((FP___TYPE)(rm[0].rm_eo - rm[0].rm_so));
1620 if (rp.re_nsub == 0) {
1621 v = make_number ((FP___TYPE)0.0);
1627 /* free arguments and pattern buffer */
1635 static struct val * /* this is a string concat operator */
1636 op_tildetilde (struct val *a, struct val *b)
1641 /* coerce to both arguments to strings */
1644 /* strip double quotes from both -- */
1648 vs = malloc(strlen(a->u.s)+strlen(b->u.s)+1);
1654 /* free arguments */