Skip to content
Snippets Groups Projects
ast_expr2.c 95.8 KiB
Newer Older
  • Learn to ignore specific revisions
  •   YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen);
    
    #line 374 "ast_expr2.y"
    
        { ((struct parse_io *)parseio)->val = (struct val *)calloc(sizeof(struct val),1);
    
                  ((struct parse_io *)parseio)->val->type = (yyvsp[(1) - (1)].val)->type;
    
                  if( (yyvsp[(1) - (1)].val)->type == AST_EXPR_number )
    
    				  ((struct parse_io *)parseio)->val->u.i = (yyvsp[(1) - (1)].val)->u.i;
    
    				  ((struct parse_io *)parseio)->val->u.s = (yyvsp[(1) - (1)].val)->u.s; 
    			  free((yyvsp[(1) - (1)].val));
    
    #line 382 "ast_expr2.y"
    
        {/* nothing */ ((struct parse_io *)parseio)->val = (struct val *)calloc(sizeof(struct val),1);
                  ((struct parse_io *)parseio)->val->type = AST_EXPR_string;
    			  ((struct parse_io *)parseio)->val->u.s = strdup(""); 
    
    #line 389 "ast_expr2.y"
    
        { (yyval.arglist) = alloc_expr_node(AST_EXPR_NODE_VAL); (yyval.arglist)->val = (yyvsp[(1) - (1)].val);;}
    
    #line 390 "ast_expr2.y"
    
        {struct expr_node *x = alloc_expr_node(AST_EXPR_NODE_VAL);
                                     struct expr_node *t;
    								 DESTROY((yyvsp[(2) - (3)].val));
                                     for (t=(yyvsp[(1) - (3)].arglist);t->right;t=t->right)
    						         	  ;
    
                                     (yyval.arglist) = (yyvsp[(1) - (3)].arglist); t->right = x; x->val = (yyvsp[(3) - (3)].val);;}
    
    #line 396 "ast_expr2.y"
    
        {struct expr_node *x = alloc_expr_node(AST_EXPR_NODE_VAL);
                                     struct expr_node *t;  /* NULL args should OK */
    								 DESTROY((yyvsp[(2) - (2)].val));
                                     for (t=(yyvsp[(1) - (2)].arglist);t->right;t=t->right)
    						         	  ;
    
                                     (yyval.arglist) = (yyvsp[(1) - (2)].arglist); t->right = x; x->val = make_str("");;}
    
    #line 405 "ast_expr2.y"
    
        { (yyval.val) = op_func((yyvsp[(1) - (4)].val),(yyvsp[(3) - (4)].arglist), ((struct parse_io *)parseio)->chan);
    		                            DESTROY((yyvsp[(2) - (4)].val));
    									DESTROY((yyvsp[(4) - (4)].val));
    									DESTROY((yyvsp[(1) - (4)].val));
    									destroy_arglist((yyvsp[(3) - (4)].arglist));
    
    #line 411 "ast_expr2.y"
    
        {(yyval.val) = (yyvsp[(1) - (1)].val);;}
    
    #line 412 "ast_expr2.y"
    
        { (yyval.val) = (yyvsp[(2) - (3)].val);
    
    	                       (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column; 
    						   (yyloc).first_line=0; (yyloc).last_line=0;
    
    							DESTROY((yyvsp[(1) - (3)].val)); DESTROY((yyvsp[(3) - (3)].val)); ;}
    
    #line 416 "ast_expr2.y"
    
        { (yyval.val) = op_or ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val));
    						DESTROY((yyvsp[(2) - (3)].val));	
                             (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column; 
    
    						 (yyloc).first_line=0; (yyloc).last_line=0;;}
    
    #line 420 "ast_expr2.y"
    
        { (yyval.val) = op_and ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val)); 
    						DESTROY((yyvsp[(2) - (3)].val));	
    	                      (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column; 
    
                              (yyloc).first_line=0; (yyloc).last_line=0;;}
    
    #line 424 "ast_expr2.y"
    
        { (yyval.val) = op_eq ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val));
    						DESTROY((yyvsp[(2) - (3)].val));	
    	                     (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column;
    
    						 (yyloc).first_line=0; (yyloc).last_line=0;;}
    
    #line 428 "ast_expr2.y"
    
        { (yyval.val) = op_gt ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val));
    						DESTROY((yyvsp[(2) - (3)].val));	
                             (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column;
    
    						 (yyloc).first_line=0; (yyloc).last_line=0;;}
    
    #line 432 "ast_expr2.y"
    
        { (yyval.val) = op_lt ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val)); 
    						DESTROY((yyvsp[(2) - (3)].val));	
    	                     (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column; 
    
    						 (yyloc).first_line=0; (yyloc).last_line=0;;}
    
    #line 436 "ast_expr2.y"
    
        { (yyval.val) = op_ge ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val)); 
    						DESTROY((yyvsp[(2) - (3)].val));	
    	                      (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column; 
    
    						  (yyloc).first_line=0; (yyloc).last_line=0;;}
    
    #line 440 "ast_expr2.y"
    
        { (yyval.val) = op_le ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val)); 
    						DESTROY((yyvsp[(2) - (3)].val));	
    	                      (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column; 
    
    						  (yyloc).first_line=0; (yyloc).last_line=0;;}
    
    #line 444 "ast_expr2.y"
    
        { (yyval.val) = op_ne ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val)); 
    						DESTROY((yyvsp[(2) - (3)].val));	
    	                      (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column; 
    
    						  (yyloc).first_line=0; (yyloc).last_line=0;;}
    
    #line 448 "ast_expr2.y"
    
        { (yyval.val) = op_plus ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val)); 
    						DESTROY((yyvsp[(2) - (3)].val));	
    	                       (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column; 
    
    						   (yyloc).first_line=0; (yyloc).last_line=0;;}
    
    #line 452 "ast_expr2.y"
    
        { (yyval.val) = op_minus ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val)); 
    						DESTROY((yyvsp[(2) - (3)].val));	
    	                        (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column; 
    
    							(yyloc).first_line=0; (yyloc).last_line=0;;}
    
    #line 456 "ast_expr2.y"
    
        { (yyval.val) = op_negate ((yyvsp[(2) - (2)].val)); 
    						DESTROY((yyvsp[(1) - (2)].val));	
    	                        (yyloc).first_column = (yylsp[(1) - (2)]).first_column; (yyloc).last_column = (yylsp[(2) - (2)]).last_column; 
    
    							(yyloc).first_line=0; (yyloc).last_line=0;;}
    
    #line 460 "ast_expr2.y"
    
        { (yyval.val) = op_compl ((yyvsp[(2) - (2)].val)); 
    						DESTROY((yyvsp[(1) - (2)].val));	
    	                        (yyloc).first_column = (yylsp[(1) - (2)]).first_column; (yyloc).last_column = (yylsp[(2) - (2)]).last_column; 
    
    							(yyloc).first_line=0; (yyloc).last_line=0;;}
    
    #line 464 "ast_expr2.y"
    
        { (yyval.val) = op_times ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val)); 
    						DESTROY((yyvsp[(2) - (3)].val));	
    	                       (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column; 
    
    						   (yyloc).first_line=0; (yyloc).last_line=0;;}
    
    #line 468 "ast_expr2.y"
    
        { (yyval.val) = op_div ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val)); 
    						DESTROY((yyvsp[(2) - (3)].val));	
    	                      (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column; 
    
    						  (yyloc).first_line=0; (yyloc).last_line=0;;}
    
    #line 472 "ast_expr2.y"
    
        { (yyval.val) = op_rem ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val)); 
    						DESTROY((yyvsp[(2) - (3)].val));	
    	                      (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column; 
    
    						  (yyloc).first_line=0; (yyloc).last_line=0;;}
    
    #line 476 "ast_expr2.y"
    
        { (yyval.val) = op_colon ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val)); 
    						DESTROY((yyvsp[(2) - (3)].val));	
    	                        (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column; 
    
    							(yyloc).first_line=0; (yyloc).last_line=0;;}
    
    #line 480 "ast_expr2.y"
    
        { (yyval.val) = op_eqtilde ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val)); 
    						DESTROY((yyvsp[(2) - (3)].val));	
    	                        (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column; 
    
    							(yyloc).first_line=0; (yyloc).last_line=0;;}
    
    #line 484 "ast_expr2.y"
    
        { (yyval.val) = op_cond ((yyvsp[(1) - (5)].val), (yyvsp[(3) - (5)].val), (yyvsp[(5) - (5)].val)); 
    						DESTROY((yyvsp[(2) - (5)].val));	
    						DESTROY((yyvsp[(4) - (5)].val));	
    	                        (yyloc).first_column = (yylsp[(1) - (5)]).first_column; (yyloc).last_column = (yylsp[(3) - (5)]).last_column; 
    
    							(yyloc).first_line=0; (yyloc).last_line=0;;}
    
    #line 489 "ast_expr2.y"
    
    Steve Murphy's avatar
    Steve Murphy committed
        { (yyval.val) = op_tildetilde ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val)); 
    						DESTROY((yyvsp[(2) - (3)].val));	
    	                        (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column; 
    
    							(yyloc).first_line=0; (yyloc).last_line=0;;}
    
    Steve Murphy's avatar
    Steve Murphy committed
        break;
    
    
    /* Line 1455 of yacc.c  */
    #line 2283 "ast_expr2.c"
    
          default: break;
    
      YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
    
      YY_STACK_PRINT (yyss, yyssp);
    
      *++yyvsp = yyval;
      *++yylsp = yyloc;
    
      /* Now `shift' the result of the reduction.  Determine what state
         that goes to, based on the state we popped back to and the rule
         number reduced by.  */
    
      yyn = yyr1[yyn];
    
      yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
      if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
        yystate = yytable[yystate];
      else
        yystate = yydefgoto[yyn - YYNTOKENS];
    
      goto yynewstate;
    
    
    /*------------------------------------.
    | yyerrlab -- here on detecting error |
    `------------------------------------*/
    yyerrlab:
      /* If not already recovering from an error, report this error.  */
      if (!yyerrstatus)
        {
          ++yynerrs;
    
    #if ! YYERROR_VERBOSE
          yyerror (YY_("syntax error"));
    #else
          {
    
    	YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
    	if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
    	  {
    	    YYSIZE_T yyalloc = 2 * yysize;
    	    if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
    	      yyalloc = YYSTACK_ALLOC_MAXIMUM;
    	    if (yymsg != yymsgbuf)
    	      YYSTACK_FREE (yymsg);
    	    yymsg = (char *) YYSTACK_ALLOC (yyalloc);
    	    if (yymsg)
    	      yymsg_alloc = yyalloc;
    	    else
    	      {
    		yymsg = yymsgbuf;
    		yymsg_alloc = sizeof yymsgbuf;
    	      }
    	  }
    
    	if (0 < yysize && yysize <= yymsg_alloc)
    	  {
    	    (void) yysyntax_error (yymsg, yystate, yychar);
    	    yyerror (yymsg);
    	  }
    	else
    	  {
    	    yyerror (YY_("syntax error"));
    	    if (yysize != 0)
    	      goto yyexhaustedlab;
    	  }
    
          /* If just tried and failed to reuse lookahead token after an
    
    	  /* Return failure if at end of input.  */
    
    	  yydestruct ("Error: discarding",
    		      yytoken, &yylval, &yylloc);
    
      /* Else will try to reuse lookahead token after shifting the error
    
    /*---------------------------------------------------.
    | yyerrorlab -- error raised explicitly by YYERROR.  |
    `---------------------------------------------------*/
    yyerrorlab:
    
      /* Pacify compilers like GCC when the user code never invokes
         YYERROR and the label yyerrorlab therefore never appears in user
         code.  */
    
      yyerror_range[0] = yylsp[1-yylen];
    
      /* Do not reclaim the symbols of the rule which action triggered
         this YYERROR.  */
      YYPOPSTACK (yylen);
      yylen = 0;
      YY_STACK_PRINT (yyss, yyssp);
    
    /*-------------------------------------------------------------.
    | yyerrlab1 -- common code for both syntax error and YYERROR.  |
    `-------------------------------------------------------------*/
    yyerrlab1:
    
      yyerrstatus = 3;	/* Each real token shifted decrements this.  */
    
      for (;;)
        {
          yyn = yypact[yystate];
    
    	{
    	  yyn += YYTERROR;
    	  if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
    	    {
    	      yyn = yytable[yyn];
    	      if (0 < yyn)
    		break;
    	    }
    	}
    
          /* Pop the current state because it cannot handle the error token.  */
          if (yyssp == yyss)
    	YYABORT;
    
    
          yydestruct ("Error: popping",
    		  yystos[yystate], yyvsp, yylsp);
          YYPOPSTACK (1);
    
          YY_STACK_PRINT (yyss, yyssp);
        }
    
      *++yyvsp = yylval;
    
    Tilghman Lesher's avatar
     
    Tilghman Lesher committed
    
    
    Tilghman Lesher's avatar
     
    Tilghman Lesher committed
      /* Using YYLLOC is tempting, but would change the location of
    
         the lookahead.  YYLOC is available though.  */
    
      YYLLOC_DEFAULT (yyloc, (yyerror_range - 1), 2);
    
    Tilghman Lesher's avatar
     
    Tilghman Lesher committed
      YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
    
    
      yystate = yyn;
      goto yynewstate;
    
    
    /*-------------------------------------.
    | yyacceptlab -- YYACCEPT comes here.  |
    `-------------------------------------*/
    yyacceptlab:
      yyresult = 0;
      goto yyreturn;
    
    /*-----------------------------------.
    | yyabortlab -- YYABORT comes here.  |
    `-----------------------------------*/
    yyabortlab:
      yyresult = 1;
      goto yyreturn;
    
    
    #if !defined(yyoverflow) || YYERROR_VERBOSE
    
    /*-------------------------------------------------.
    | yyexhaustedlab -- memory exhaustion comes here.  |
    `-------------------------------------------------*/
    yyexhaustedlab:
      yyerror (YY_("memory exhausted"));
    
      if (yychar != YYEMPTY)
    
         yydestruct ("Cleanup: discarding lookahead",
    		 yytoken, &yylval, &yylloc);
    
      /* Do not reclaim the symbols of the rule which action triggered
         this YYABORT or YYACCEPT.  */
      YYPOPSTACK (yylen);
      YY_STACK_PRINT (yyss, yyssp);
    
      while (yyssp != yyss)
        {
          yydestruct ("Cleanup: popping",
    		  yystos[*yyssp], yyvsp, yylsp);
    
    #ifndef yyoverflow
      if (yyss != yyssa)
        YYSTACK_FREE (yyss);
    
    #endif
    #if YYERROR_VERBOSE
      if (yymsg != yymsgbuf)
        YYSTACK_FREE (yymsg);
    
    Steve Murphy's avatar
    Steve Murphy committed
      /* Make sure YYID is used.  */
      return YYID (yyresult);
    
    #line 495 "ast_expr2.y"
    
    
    
    static struct expr_node *alloc_expr_node(enum node_type nt)
    {
    	struct expr_node *x = calloc(1,sizeof(struct expr_node));
    	if (!x) {
    		ast_log(LOG_ERROR, "Allocation for expr_node FAILED!!\n");
    		return 0;
    	}
    	x->type = nt;
    	return x;
    }
    
    
    make_number (FP___TYPE i)
    
    {
    	struct val *vp;
    
    	vp = (struct val *) malloc (sizeof (*vp));
    	if (vp == NULL) {
    		ast_log(LOG_WARNING, "malloc() failed\n");
    		return(NULL);
    	}
    
    
    	vp->type = AST_EXPR_number;
    
    	vp->u.i  = i;
    	return vp; 
    }
    
    static struct val *
    make_str (const char *s)
    {
    	struct val *vp;
    	size_t i;
    
    	int isint; /* this started out being a test for an integer, but then ended up being a test for a float */
    
    
    	vp = (struct val *) malloc (sizeof (*vp));
    	if (vp == NULL || ((vp->u.s = strdup (s)) == NULL)) {
    
    		if (vp) {
    			free(vp);
    		}
    
    		ast_log(LOG_WARNING,"malloc() failed\n");
    		return(NULL);
    	}
    
    
    	for (i = 0, isint = (isdigit(s[0]) || s[0] == '-' || s[0]=='.'); isint && i < strlen(s); i++)
    
    		if (!isdigit(s[i]) && s[i] != '.') {
    			isint = 0;
    			break;
    		}
    
    	}
    	if (isint)
    		vp->type = AST_EXPR_numeric_string;
    	else	
    		vp->type = AST_EXPR_string;
    
    	return vp;
    }
    
    
    static void
    free_value (struct val *vp)
    {	
    	if (vp==NULL) {
    		return;
    	}
    	if (vp->type == AST_EXPR_string || vp->type == AST_EXPR_numeric_string)
    		free (vp->u.s);	
    
    Tilghman Lesher's avatar
     
    Tilghman Lesher committed
    	free(vp);
    
    static int
    to_number (struct val *vp)
    
    		ast_log(LOG_WARNING,"vp==NULL in to_number()\n");
    
    	if (vp->type == AST_EXPR_number)
    
    		return 1;
    
    	if (vp->type == AST_EXPR_string)
    		return 0;
    
    	/* vp->type == AST_EXPR_numeric_string, make it numeric */
    	errno = 0;
    
    	i  = FUNC_STRTOD(vp->u.s, (char**)0); /* either strtod, or strtold on a good day */
    
    		ast_log(LOG_WARNING,"Conversion of %s to number under/overflowed!\n", vp->u.s);
    
    		free(vp->u.s);
    		vp->u.s = 0;
    		return(0);
    	}
    	free (vp->u.s);
    	vp->u.i = i;
    
    	vp->type = AST_EXPR_number;
    
    	return 1;
    }
    
    static void
    strip_quotes(struct val *vp)
    {
    	if (vp->type != AST_EXPR_string && vp->type != AST_EXPR_numeric_string)
    		return;
    	
    	if( vp->u.s[0] == '"' && vp->u.s[strlen(vp->u.s)-1] == '"' )
    	{
    		char *f, *t;
    		f = vp->u.s;
    		t = vp->u.s;
    		
    		while( *f )
    		{
    			if( *f  && *f != '"' )
    				*t++ = *f++;
    			else
    				f++;
    		}
    		*t = *f;
    	}
    }
    
    static void
    to_string (struct val *vp)
    {
    	char *tmp;
    
    	if (vp->type == AST_EXPR_string || vp->type == AST_EXPR_numeric_string)
    		return;
    
    
    	if (asprintf(&tmp, FP___PRINTF, vp->u.i) == -1) {
    		ast_log(LOG_WARNING, "asprintf() failed\n");
    
    		return;
    	}
    
    	vp->type = AST_EXPR_string;
    	vp->u.s  = tmp;
    }
    
    
    static int
    isstring (struct val *vp)
    {
    
    	/* only TRUE if this string is not a valid number */
    
    	return (vp->type == AST_EXPR_string);
    }
    
    
    static int
    is_zero_or_null (struct val *vp)
    {
    
    	if (vp->type == AST_EXPR_number) {
    
    		return (*vp->u.s == 0 || (to_number(vp) && vp->u.i == 0));
    
    #ifdef STANDALONE2
    
    void ast_log(int level, const char *file, int line, const char *function, const char *fmt, ...)
    {
    	va_list vars;
    	va_start(vars,fmt);
    	
            printf("LOG: lev:%d file:%s  line:%d func: %s  ",
                       level, file, line, function);
    	vprintf(fmt, vars);
    	fflush(stdout);
    	va_end(vars);
    }
    
    
    int main(int argc,char **argv) {
    	char s[4096];
    	char out[4096];
    	FILE *infile;
    	
    	if( !argv[1] )
    		exit(20);
    	
    	if( access(argv[1],F_OK)== 0 )
    	{
    		int ret;
    		
    		infile = fopen(argv[1],"r");
    		if( !infile )
    		{
    			printf("Sorry, couldn't open %s for reading!\n", argv[1]);
    			exit(10);
    		}
    		while( fgets(s,sizeof(s),infile) )
    		{
    			if( s[strlen(s)-1] == '\n' )
    				s[strlen(s)-1] = 0;
    			
    			ret = ast_expr(s, out, sizeof(out), NULL);
    			printf("Expression: %s    Result: [%d] '%s'\n",
    				   s, ret, out);
    		}
    		fclose(infile);
    	}
    	else
    	{
    		if (ast_expr(argv[1], s, sizeof(s), NULL))
    			printf("=====%s======\n",s);
    		else
    			printf("No result\n");
    	}
    	return 0;
    }
    
    #endif
    
    
    #undef ast_yyerror
    #define ast_yyerror(x) ast_yyerror(x, YYLTYPE *yylloc, struct parse_io *parseio)
    
    /* I put the ast_yyerror func in the flex input file,
       because it refers to the buffer state. Best to
       let it access the BUFFER stuff there and not trying
       define all the structs, macros etc. in this file! */
    
    
    static void destroy_arglist(struct expr_node *arglist)
    {
    	struct expr_node *arglist_next;
    	
    	while (arglist)
    	{
    		arglist_next = arglist->right;
    		if (arglist->val)
    			free_value(arglist->val);
    		arglist->val = 0;
    		arglist->right = 0;
    		free(arglist);
    		arglist = arglist_next;
    	}
    }
    
    
    #if !defined(STANDALONE) && !defined(STANDALONE2)
    
    static char *compose_func_args(struct expr_node *arglist)
    {
    	struct expr_node *t = arglist;
    	char *argbuf;
    	int total_len = 0;
    	
    	while (t) {
    		if (t != arglist)
    			total_len += 1; /* for the sep */
    		if (t->val) {
    			if (t->val->type == AST_EXPR_number)
    				total_len += 25; /* worst case */
    			else
    				total_len += strlen(t->val->u.s);
    		}
    		
    		t = t->right;
    	}
    	total_len++; /* for the null */
    	ast_log(LOG_NOTICE,"argbuf allocated %d bytes;\n", total_len);
    	argbuf = malloc(total_len);
    	argbuf[0] = 0;
    	t = arglist;
    	while (t) {
    		char numbuf[30];
    		
    		if (t != arglist)
    
    		
    		if (t->val) {
    			if (t->val->type == AST_EXPR_number) {
    				sprintf(numbuf,FP___PRINTF,t->val->u.i);
    				strcat(argbuf,numbuf);
    			} else
    				strcat(argbuf,t->val->u.s);
    		}
    		t = t->right;
    	}
    
    	ast_log(LOG_NOTICE,"argbuf uses %d bytes;\n", (int) strlen(argbuf));
    
    	return argbuf;
    }
    
    static int is_really_num(char *str)
    {
    	if ( strspn(str,"-0123456789. 	") == strlen(str))
    		return 1;
    	else
    		return 0;
    }
    
    
    static struct val *op_func(struct val *funcname, struct expr_node *arglist, struct ast_channel *chan)
    {
    	if (strspn(funcname->u.s,"ABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789") == strlen(funcname->u.s))
    	{
    		struct val *result;
    
    		if (0) {
    #ifdef FUNC_COS
    		} else if (strcmp(funcname->u.s,"COS") == 0) {
    
    			if (arglist && !arglist->right && arglist->val){
    				to_number(arglist->val);
    				result = make_number(FUNC_COS(arglist->val->u.i));
    				return result;
    			} else {
    				ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
    				return make_number(0.0);
    			}
    
    		} else if (strcmp(funcname->u.s,"SIN") == 0) {
    			if (arglist && !arglist->right && arglist->val){
    				to_number(arglist->val);
    				result = make_number(FUNC_SIN(arglist->val->u.i));
    				return result;
    			} else {
    				ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
    				return make_number(0.0);
    			}
    
    		} else if (strcmp(funcname->u.s,"TAN") == 0) {
    			if (arglist && !arglist->right && arglist->val){
    				to_number(arglist->val);
    				result = make_number(FUNC_TAN(arglist->val->u.i));
    				return result;
    			} else {
    				ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
    				return make_number(0.0);
    			}
    
    		} else if (strcmp(funcname->u.s,"ACOS") == 0) {
    			if (arglist && !arglist->right && arglist->val){
    				to_number(arglist->val);
    				result = make_number(FUNC_ACOS(arglist->val->u.i));
    				return result;
    			} else {
    				ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
    				return make_number(0.0);
    			}
    
    		} else if (strcmp(funcname->u.s,"ASIN") == 0) {
    			if (arglist && !arglist->right && arglist->val){
    				to_number(arglist->val);
    				result = make_number(FUNC_ASIN(arglist->val->u.i));
    				return result;
    			} else {
    				ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
    				return make_number(0.0);
    			}
    
    		} else if (strcmp(funcname->u.s,"ATAN") == 0) {
    			if (arglist && !arglist->right && arglist->val){
    				to_number(arglist->val);
    				result = make_number(FUNC_ATAN(arglist->val->u.i));
    				return result;
    			} else {
    				ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
    				return make_number(0.0);
    			}
    
    		} else if (strcmp(funcname->u.s,"ATAN2") == 0) {
    			if (arglist && arglist->right && !arglist->right->right && arglist->val && arglist->right->val){
    				to_number(arglist->val);
    				to_number(arglist->right->val);
    				result = make_number(FUNC_ATAN2(arglist->val->u.i, arglist->right->val->u.i));
    				return result;
    			} else {
    				ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
    				return make_number(0.0);
    			}
    
    		} else if (strcmp(funcname->u.s,"POW") == 0) {
    			if (arglist && arglist->right && !arglist->right->right && arglist->val && arglist->right->val){
    				to_number(arglist->val);
    				to_number(arglist->right->val);
    				result = make_number(FUNC_POW(arglist->val->u.i, arglist->right->val->u.i));
    				return result;
    			} else {
    				ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
    				return make_number(0.0);
    			}
    
    		} else if (strcmp(funcname->u.s,"SQRT") == 0) {
    			if (arglist && !arglist->right && arglist->val){
    				to_number(arglist->val);
    				result = make_number(FUNC_SQRT(arglist->val->u.i));
    				return result;
    			} else {
    				ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
    				return make_number(0.0);
    			}
    
    		} else if (strcmp(funcname->u.s,"FLOOR") == 0) {
    			if (arglist && !arglist->right && arglist->val){
    				to_number(arglist->val);
    				result = make_number(FUNC_FLOOR(arglist->val->u.i));
    				return result;
    			} else {
    				ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
    				return make_number(0.0);
    			}
    
    		} else if (strcmp(funcname->u.s,"CEIL") == 0) {
    			if (arglist && !arglist->right && arglist->val){
    				to_number(arglist->val);
    				result = make_number(FUNC_CEIL(arglist->val->u.i));
    				return result;
    			} else {
    				ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
    				return make_number(0.0);
    			}
    
    		} else if (strcmp(funcname->u.s,"ROUND") == 0) {
    			if (arglist && !arglist->right && arglist->val){
    				to_number(arglist->val);
    				result = make_number(FUNC_ROUND(arglist->val->u.i));
    				return result;
    			} else {
    				ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
    				return make_number(0.0);
    			}
    
    		} else if (strcmp(funcname->u.s,"RINT") == 0) {
    			if (arglist && !arglist->right && arglist->val){
    				to_number(arglist->val);
    				result = make_number(FUNC_RINT(arglist->val->u.i));
    				return result;
    			} else {
    				ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
    				return make_number(0.0);
    			}
    
    		} else if (strcmp(funcname->u.s,"TRUNC") == 0) {
    			if (arglist && !arglist->right && arglist->val){
    				to_number(arglist->val);
    				result = make_number(FUNC_TRUNC(arglist->val->u.i));
    				return result;
    			} else {
    				ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
    				return make_number(0.0);
    			}
    
    		} else if (strcmp(funcname->u.s,"EXP") == 0) {
    			if (arglist && !arglist->right && arglist->val){
    				to_number(arglist->val);
    				result = make_number(FUNC_EXP(arglist->val->u.i));
    				return result;
    			} else {
    				ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
    				return make_number(0.0);
    			}
    
    		} else if (strcmp(funcname->u.s,"EXP2") == 0) {
    			if (arglist && !arglist->right && arglist->val){
    				to_number(arglist->val);
    				result = make_number(FUNC_EXP2(arglist->val->u.i));
    				return result;
    			} else {
    				ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
    				return make_number(0.0);
    			}
    
    		} else if (strcmp(funcname->u.s,"EXP10") == 0) {
    			if (arglist && !arglist->right && arglist->val){
    				to_number(arglist->val);
    				result = make_number(FUNC_EXP10(arglist->val->u.i));
    				return result;
    			} else {
    				ast_log(LOG_WARNING,"Wrong args to %s() function\n",funcname->u.s);
    				return make_number(0.0);
    			}
    
    		} else if (strcmp(funcname->u.s,"LOG") == 0) {
    			if (arglist && !arglist->right && arglist->val){
    				to_number(arglist->val);
    				result = make_number(FUNC_LOG(arglist->val->u.i));