Skip to content
Snippets Groups Projects
ast_expr2.c 58.7 KiB
Newer Older
  • Learn to ignore specific revisions
  •   short int yyssa[YYINITDEPTH];
      short int *yyss = yyssa;
      register short int *yyssp;
    
    
      /* The semantic value stack.  */
      YYSTYPE yyvsa[YYINITDEPTH];
      YYSTYPE *yyvs = yyvsa;
      register YYSTYPE *yyvsp;
    
      /* The location stack.  */
      YYLTYPE yylsa[YYINITDEPTH];
      YYLTYPE *yyls = yylsa;
      YYLTYPE *yylsp;
      YYLTYPE *yylerrsp;
    
    #define YYPOPSTACK   (yyvsp--, yyssp--, yylsp--)
    
      YYSIZE_T yystacksize = YYINITDEPTH;
    
      /* The variables used to return semantic value and location from the
         action routines.  */
      YYSTYPE yyval;
      YYLTYPE yyloc;
    
      /* When reducing, the number of symbols on the RHS of the reduced
         rule.  */
      int yylen;
    
      YYDPRINTF ((stderr, "Starting parse\n"));
    
      yystate = 0;
      yyerrstatus = 0;
      yynerrs = 0;
      yychar = YYEMPTY;		/* Cause a token to be read.  */
    
      /* Initialize stack pointers.
         Waste one element of value and location stack
         so that they stay on the same level as the state stack.
         The wasted elements are never initialized.  */
    
      yyssp = yyss;
      yyvsp = yyvs;
      yylsp = yyls;
    
      goto yysetstate;
    
    /*------------------------------------------------------------.
    | yynewstate -- Push a new state, which is found in yystate.  |
    `------------------------------------------------------------*/
     yynewstate:
      /* In all cases, when you get here, the value and location stacks
         have just been pushed. so pushing a state here evens the stacks.
         */
      yyssp++;
    
     yysetstate:
      *yyssp = yystate;
    
      if (yyss + yystacksize - 1 <= yyssp)
        {
          /* Get the current used size of the three stacks, in elements.  */
          YYSIZE_T yysize = yyssp - yyss + 1;
    
    #ifdef yyoverflow
          {
    	/* Give user a chance to reallocate the stack. Use copies of
    	   these so that the &'s don't force the real ones into
    	   memory.  */
    	YYSTYPE *yyvs1 = yyvs;
    
    	YYLTYPE *yyls1 = yyls;
    
    	/* Each stack pointer address is followed by the size of the
    	   data in use in that stack, in bytes.  This used to be a
    	   conditional around just the two extra args, but that might
    	   be undefined if yyoverflow is a macro.  */
    	yyoverflow ("parser stack overflow",
    		    &yyss1, yysize * sizeof (*yyssp),
    		    &yyvs1, yysize * sizeof (*yyvsp),
    		    &yyls1, yysize * sizeof (*yylsp),
    		    &yystacksize);
    	yyls = yyls1;
    	yyss = yyss1;
    	yyvs = yyvs1;
          }
    #else /* no yyoverflow */
    # ifndef YYSTACK_RELOCATE
          goto yyoverflowlab;
    # else
          /* Extend the stack our own way.  */
          if (YYMAXDEPTH <= yystacksize)
    	goto yyoverflowlab;
          yystacksize *= 2;
          if (YYMAXDEPTH < yystacksize)
    	yystacksize = YYMAXDEPTH;
    
          {
    
    	union yyalloc *yyptr =
    	  (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
    	if (! yyptr)
    	  goto yyoverflowlab;
    	YYSTACK_RELOCATE (yyss);
    	YYSTACK_RELOCATE (yyvs);
    	YYSTACK_RELOCATE (yyls);
    #  undef YYSTACK_RELOCATE
    	if (yyss1 != yyssa)
    	  YYSTACK_FREE (yyss1);
          }
    # endif
    #endif /* no yyoverflow */
    
          yyssp = yyss + yysize - 1;
          yyvsp = yyvs + yysize - 1;
          yylsp = yyls + yysize - 1;
    
          YYDPRINTF ((stderr, "Stack size increased to %lu\n",
    		  (unsigned long int) yystacksize));
    
          if (yyss + yystacksize - 1 <= yyssp)
    	YYABORT;
        }
    
      YYDPRINTF ((stderr, "Entering state %d\n", yystate));
    
      goto yybackup;
    
    /*-----------.
    | yybackup.  |
    `-----------*/
    yybackup:
    
    /* Do appropriate processing given the current state.  */
    /* Read a lookahead token if we need one and don't already have one.  */
    /* yyresume: */
    
      /* First try to decide what to do without reference to lookahead token.  */
    
      yyn = yypact[yystate];
      if (yyn == YYPACT_NINF)
        goto yydefault;
    
      /* Not known => get a lookahead token if don't already have one.  */
    
      /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol.  */
      if (yychar == YYEMPTY)
        {
          YYDPRINTF ((stderr, "Reading a token: "));
          yychar = YYLEX;
        }
    
      if (yychar <= YYEOF)
        {
          yychar = yytoken = YYEOF;
          YYDPRINTF ((stderr, "Now at end of input.\n"));
        }
      else
        {
          yytoken = YYTRANSLATE (yychar);
          YYDSYMPRINTF ("Next token is", yytoken, &yylval, &yylloc);
        }
    
      /* If the proper action on seeing token YYTOKEN is to reduce or to
         detect an error, take that action.  */
      yyn += yytoken;
      if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
        goto yydefault;
      yyn = yytable[yyn];
      if (yyn <= 0)
        {
          if (yyn == 0 || yyn == YYTABLE_NINF)
    	goto yyerrlab;
          yyn = -yyn;
          goto yyreduce;
        }
    
      if (yyn == YYFINAL)
        YYACCEPT;
    
      /* Shift the lookahead token.  */
      YYDPRINTF ((stderr, "Shifting token %s, ", yytname[yytoken]));
    
      /* Discard the token being shifted unless it is eof.  */
      if (yychar != YYEOF)
        yychar = YYEMPTY;
    
      *++yyvsp = yylval;
      *++yylsp = yylloc;
    
      /* Count tokens shifted since error; after three, turn off error
         status.  */
      if (yyerrstatus)
        yyerrstatus--;
    
      yystate = yyn;
      goto yynewstate;
    
    
    /*-----------------------------------------------------------.
    | yydefault -- do the default action for the current state.  |
    `-----------------------------------------------------------*/
    yydefault:
      yyn = yydefact[yystate];
      if (yyn == 0)
        goto yyerrlab;
      goto yyreduce;
    
    
    /*-----------------------------.
    | yyreduce -- Do a reduction.  |
    `-----------------------------*/
    yyreduce:
      /* yyn is the number of a rule to reduce with.  */
      yylen = yyr2[yyn];
    
      /* If YYLEN is nonzero, implement the default value of the action:
         `$$ = $1'.
    
         Otherwise, the following line sets YYVAL to garbage.
         This behavior is undocumented and Bison
         users should not rely upon it.  Assigning to YYVAL
         unconditionally makes the parser a bit smaller, and it avoids a
         GCC warning that YYVAL may be used uninitialized.  */
      yyval = yyvsp[1-yylen];
    
      /* Default location. */
    
      YYLLOC_DEFAULT (yyloc, yylsp - yylen, yylen);
    
      YY_REDUCE_PRINT (yyn);
      switch (yyn)
        {
            case 2:
    #line 160 "ast_expr2.y"
        { ((struct parse_io *)parseio)->val = (struct val *)calloc(sizeof(struct val),1);
                  ((struct parse_io *)parseio)->val->type = yyval.val->type;
    
                  if( yyval.val->type == AST_EXPR_integer )
    		((struct parse_io *)parseio)->val->u.i = yyval.val->u.i;
                  else
                    ((struct parse_io *)parseio)->val->u.s = yyval.val->u.s; ;}
    
    #line 168 "ast_expr2.y"
    
    #line 169 "ast_expr2.y"
    
        { yyval.val = yyvsp[-1].val; 
    	                       yyloc.first_column = yylsp[-2].first_column; yyloc.last_column = yylsp[0].last_column; 
    						   yyloc.first_line=0; yyloc.last_line=0;;}
        break;
    
      case 5:
    
    #line 172 "ast_expr2.y"
    
        { yyval.val = op_or (yyvsp[-2].val, yyvsp[0].val);
                             yyloc.first_column = yylsp[-2].first_column; yyloc.last_column = yylsp[0].last_column; 
    						 yyloc.first_line=0; yyloc.last_line=0;;}
        break;
    
      case 6:
    
    #line 175 "ast_expr2.y"
    
        { yyval.val = op_and (yyvsp[-2].val, yyvsp[0].val); 
    	                      yyloc.first_column = yylsp[-2].first_column; yyloc.last_column = yylsp[0].last_column; 
                              yyloc.first_line=0; yyloc.last_line=0;;}
        break;
    
      case 7:
    
    #line 178 "ast_expr2.y"
    
        { yyval.val = op_eq (yyvsp[-2].val, yyvsp[0].val);
    	                     yyloc.first_column = yylsp[-2].first_column; yyloc.last_column = yylsp[0].last_column;
    						 yyloc.first_line=0; yyloc.last_line=0;;}
        break;
    
      case 8:
    
    #line 181 "ast_expr2.y"
    
        { yyval.val = op_gt (yyvsp[-2].val, yyvsp[0].val);
                             yyloc.first_column = yylsp[-2].first_column; yyloc.last_column = yylsp[0].last_column;
    						 yyloc.first_line=0; yyloc.last_line=0;;}
        break;
    
      case 9:
    
    #line 184 "ast_expr2.y"
    
        { yyval.val = op_lt (yyvsp[-2].val, yyvsp[0].val); 
    	                     yyloc.first_column = yylsp[-2].first_column; yyloc.last_column = yylsp[0].last_column; 
    						 yyloc.first_line=0; yyloc.last_line=0;;}
        break;
    
      case 10:
    
    #line 187 "ast_expr2.y"
    
        { yyval.val = op_ge (yyvsp[-2].val, yyvsp[0].val); 
    	                      yyloc.first_column = yylsp[-2].first_column; yyloc.last_column = yylsp[0].last_column; 
    						  yyloc.first_line=0; yyloc.last_line=0;;}
        break;
    
      case 11:
    
    #line 190 "ast_expr2.y"
    
        { yyval.val = op_le (yyvsp[-2].val, yyvsp[0].val); 
    	                      yyloc.first_column = yylsp[-2].first_column; yyloc.last_column = yylsp[0].last_column; 
    						  yyloc.first_line=0; yyloc.last_line=0;;}
        break;
    
      case 12:
    
    #line 193 "ast_expr2.y"
    
        { yyval.val = op_ne (yyvsp[-2].val, yyvsp[0].val); 
    	                      yyloc.first_column = yylsp[-2].first_column; yyloc.last_column = yylsp[0].last_column; 
    						  yyloc.first_line=0; yyloc.last_line=0;;}
        break;
    
      case 13:
    
    #line 196 "ast_expr2.y"
    
        { yyval.val = op_plus (yyvsp[-2].val, yyvsp[0].val); 
    	                       yyloc.first_column = yylsp[-2].first_column; yyloc.last_column = yylsp[0].last_column; 
    						   yyloc.first_line=0; yyloc.last_line=0;;}
        break;
    
      case 14:
    
    #line 199 "ast_expr2.y"
    
        { yyval.val = op_minus (yyvsp[-2].val, yyvsp[0].val); 
    	                        yyloc.first_column = yylsp[-2].first_column; yyloc.last_column = yylsp[0].last_column; 
    							yyloc.first_line=0; yyloc.last_line=0;;}
        break;
    
      case 15:
    
    #line 202 "ast_expr2.y"
    
        { yyval.val = op_negate (yyvsp[0].val); 
    	                        yyloc.first_column = yylsp[-1].first_column; yyloc.last_column = yylsp[0].last_column; 
    							yyloc.first_line=0; yyloc.last_line=0;;}
        break;
    
      case 16:
    
    #line 205 "ast_expr2.y"
    
        { yyval.val = op_compl (yyvsp[0].val); 
    	                        yyloc.first_column = yylsp[-1].first_column; yyloc.last_column = yylsp[0].last_column; 
    							yyloc.first_line=0; yyloc.last_line=0;;}
        break;
    
      case 17:
    
    #line 208 "ast_expr2.y"
    
        { yyval.val = op_times (yyvsp[-2].val, yyvsp[0].val); 
    	                       yyloc.first_column = yylsp[-2].first_column; yyloc.last_column = yylsp[0].last_column; 
    						   yyloc.first_line=0; yyloc.last_line=0;;}
        break;
    
      case 18:
    
    #line 211 "ast_expr2.y"
    
        { yyval.val = op_div (yyvsp[-2].val, yyvsp[0].val); 
    	                      yyloc.first_column = yylsp[-2].first_column; yyloc.last_column = yylsp[0].last_column; 
    						  yyloc.first_line=0; yyloc.last_line=0;;}
        break;
    
      case 19:
    
    #line 214 "ast_expr2.y"
    
        { yyval.val = op_rem (yyvsp[-2].val, yyvsp[0].val); 
    	                      yyloc.first_column = yylsp[-2].first_column; yyloc.last_column = yylsp[0].last_column; 
    						  yyloc.first_line=0; yyloc.last_line=0;;}
        break;
    
      case 20:
    
    #line 217 "ast_expr2.y"
    
        { yyval.val = op_colon (yyvsp[-2].val, yyvsp[0].val); 
    	                        yyloc.first_column = yylsp[-2].first_column; yyloc.last_column = yylsp[0].last_column; 
    							yyloc.first_line=0; yyloc.last_line=0;;}
        break;
    
      case 21:
    
    #line 220 "ast_expr2.y"
    
        { yyval.val = op_eqtilde (yyvsp[-2].val, yyvsp[0].val); 
    	                        yyloc.first_column = yylsp[-2].first_column; yyloc.last_column = yylsp[0].last_column; 
    							yyloc.first_line=0; yyloc.last_line=0;;}
        break;
    
      case 22:
    
    #line 223 "ast_expr2.y"
    
        { yyval.val = op_cond (yyvsp[-4].val, yyvsp[-2].val, yyvsp[0].val); 
    	                        yyloc.first_column = yylsp[-4].first_column; yyloc.last_column = yylsp[-2].last_column; 
    							yyloc.first_line=0; yyloc.last_line=0;;}
        break;
    
    
        }
    
    
    #line 1384 "ast_expr2.c"
    
    
      yyvsp -= yylen;
      yyssp -= yylen;
      yylsp -= yylen;
    
      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
          yyn = yypact[yystate];
    
          if (YYPACT_NINF < yyn && yyn < YYLAST)
    	{
    	  YYSIZE_T yysize = 0;
    	  int yytype = YYTRANSLATE (yychar);
    
    
    	  /* Start YYX at -YYN if negative to avoid negative indexes in
    	     YYCHECK.  */
    
    	  int yyxbegin = yyn < 0 ? -yyn : 0;
    
    	  /* Stay within bounds of both yycheck and yytname.  */
    	  int yychecklim = YYLAST - yyn;
    	  int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
    	  int yycount = 0;
    
    	  yyprefix = ", expecting ";
    	  for (yyx = yyxbegin; yyx < yyxend; ++yyx)
    
    	    if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
    
    	      {
    		yysize += yystrlen (yyprefix) + yystrlen (yytname [yyx]);
    		yycount += 1;
    		if (yycount == 5)
    		  {
    		    yysize = 0;
    		    break;
    		  }
    	      }
    	  yysize += (sizeof ("syntax error, unexpected ")
    		     + yystrlen (yytname[yytype]));
    
    	  yymsg = (char *) YYSTACK_ALLOC (yysize);
    	  if (yymsg != 0)
    	    {
    	      char *yyp = yystpcpy (yymsg, "syntax error, unexpected ");
    	      yyp = yystpcpy (yyp, yytname[yytype]);
    
    	      if (yycount < 5)
    		{
    
    		  yyprefix = ", expecting ";
    		  for (yyx = yyxbegin; yyx < yyxend; ++yyx)
    
    		    if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
    		      {
    
    			yyp = yystpcpy (yyp, yytname[yyx]);
    
    		      }
    		}
    	      yyerror (yymsg);
    	      YYSTACK_FREE (yymsg);
    	    }
    	  else
    	    yyerror ("syntax error; also virtual memory exhausted");
    	}
          else
    #endif /* YYERROR_VERBOSE */
    	yyerror ("syntax error");
        }
    
      yylerrsp = yylsp;
    
      if (yyerrstatus == 3)
        {
          /* If just tried and failed to reuse lookahead token after an
    	 error, discard it.  */
    
    
              /* If at end of input, pop the error token,
    	     then the rest of the stack, then return failure.  */
    	  if (yychar == YYEOF)
    	     for (;;)
    	       {
    		 YYPOPSTACK;
    		 if (yyssp == yyss)
    		   YYABORT;
    		 YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
    		 yydestruct (yystos[*yyssp], yyvsp, yylsp);
    	       }
    
          else
    	{
    	  YYDSYMPRINTF ("Error: discarding", yytoken, &yylval, &yylloc);
    	  yydestruct (yytoken, &yylval, &yylloc);
    	  yychar = YYEMPTY;
    	  *++yylerrsp = yylloc;
    	}
    
        }
    
      /* Else will try to reuse lookahead token after shifting the error
         token.  */
    
    /*---------------------------------------------------.
    | yyerrorlab -- error raised explicitly by YYERROR.  |
    `---------------------------------------------------*/
    yyerrorlab:
    
    #ifdef __GNUC__
      /* Pacify GCC when the user code never invokes YYERROR and the label
         yyerrorlab therefore never appears in user code.  */
      if (0)
         goto yyerrorlab;
    
      yyvsp -= yylen;
      yyssp -= yylen;
      yystate = *yyssp;
    
      yylerrsp = yylsp;
      *++yylerrsp = yyloc;
    
    /*-------------------------------------------------------------.
    | yyerrlab1 -- common code for both syntax error and YYERROR.  |
    `-------------------------------------------------------------*/
    yyerrlab1:
    
      yyerrstatus = 3;	/* Each real token shifted decrements this.  */
    
      for (;;)
        {
          yyn = yypact[yystate];
          if (yyn != YYPACT_NINF)
    	{
    	  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;
    
          YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
          yydestruct (yystos[yystate], yyvsp, yylsp);
    
          YY_STACK_PRINT (yyss, yyssp);
        }
    
      if (yyn == YYFINAL)
        YYACCEPT;
    
      YYDPRINTF ((stderr, "Shifting error token, "));
    
      *++yyvsp = yylval;
    
      YYLLOC_DEFAULT (yyloc, yylsp, yylerrsp - yylsp);
    
      *++yylsp = yyloc;
    
      yystate = yyn;
      goto yynewstate;
    
    
    /*-------------------------------------.
    | yyacceptlab -- YYACCEPT comes here.  |
    `-------------------------------------*/
    yyacceptlab:
      yyresult = 0;
      goto yyreturn;
    
    /*-----------------------------------.
    | yyabortlab -- YYABORT comes here.  |
    `-----------------------------------*/
    yyabortlab:
      yyresult = 1;
      goto yyreturn;
    
    #ifndef yyoverflow
    /*----------------------------------------------.
    | yyoverflowlab -- parser overflow comes here.  |
    `----------------------------------------------*/
    yyoverflowlab:
      yyerror ("parser stack overflow");
      yyresult = 2;
      /* Fall through.  */
    #endif
    
    yyreturn:
    #ifndef yyoverflow
      if (yyss != yyssa)
        YYSTACK_FREE (yyss);
    #endif
      return yyresult;
    }
    
    
    
    #line 228 "ast_expr2.y"
    
    
    
    static struct val *
    make_integer (quad_t 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_integer;
    	vp->u.i  = i;
    	return vp; 
    }
    
    static struct val *
    make_str (const char *s)
    {
    	struct val *vp;
    	size_t i;
    	int isint;
    
    	vp = (struct val *) malloc (sizeof (*vp));
    	if (vp == NULL || ((vp->u.s = strdup (s)) == NULL)) {
    		ast_log(LOG_WARNING,"malloc() failed\n");
    		return(NULL);
    	}
    
    	for(i = 1, isint = isdigit(s[0]) || s[0] == '-';
    	    isint && i < strlen(s);
    	    i++)
    	{
    		if(!isdigit(s[i]))
    			 isint = 0;
    	}
    
    	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);	
    }
    
    
    static quad_t
    to_integer (struct val *vp)
    {
    	quad_t i;
    	
    	if (vp == NULL) {
    		ast_log(LOG_WARNING,"vp==NULL in to_integer()\n");
    		return(0);
    	}
    
    	if (vp->type == AST_EXPR_integer)
    		return 1;
    
    	if (vp->type == AST_EXPR_string)
    		return 0;
    
    	/* vp->type == AST_EXPR_numeric_string, make it numeric */
    	errno = 0;
    	i  = strtoll(vp->u.s, (char**)NULL, 10);
    	if (errno != 0) {
    		ast_log(LOG_WARNING,"Conversion of %s to integer 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_integer;
    	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;
    
    	tmp = malloc ((size_t)25);
    	if (tmp == NULL) {
    		ast_log(LOG_WARNING,"malloc() failed\n");
    		return;
    	}
    
    
    	sprintf(tmp, "%ld", (long int) vp->u.i);
    
    	vp->type = AST_EXPR_string;
    	vp->u.s  = tmp;
    }
    
    
    static int
    isstring (struct val *vp)
    {
    	/* only TRUE if this string is not a valid integer */
    	return (vp->type == AST_EXPR_string);
    }
    
    
    static int
    is_zero_or_null (struct val *vp)
    {
    	if (vp->type == AST_EXPR_integer) {
    		return (vp->u.i == 0);
    	} else {
    		return (*vp->u.s == 0 || (to_integer (vp) && vp->u.i == 0));
    	}
    	/* NOTREACHED */
    }
    
    #ifdef STANDALONE
    
    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];
    	
    	if (ast_expr(argv[1], s, sizeof(s)))
    		printf("=====%s======\n",s);
    	else
    		printf("No result\n");
    
    }
    
    #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 struct val *
    op_or (struct val *a, struct val *b)
    {
    	if (is_zero_or_null (a)) {
    		free_value (a);
    		return (b);
    	} else {
    		free_value (b);
    		return (a);
    	}
    }
    		
    static struct val *
    op_and (struct val *a, struct val *b)
    {
    	if (is_zero_or_null (a) || is_zero_or_null (b)) {
    		free_value (a);
    		free_value (b);
    		return (make_integer ((quad_t)0));
    	} else {
    		free_value (b);
    		return (a);
    	}
    }
    
    static struct val *
    op_eq (struct val *a, struct val *b)
    {
    	struct val *r; 
    
    	if (isstring (a) || isstring (b)) {
    		to_string (a);
    		to_string (b);	
    		r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) == 0));
    	} else {
    #ifdef DEBUG_FOR_CONVERSIONS
    		char buffer[2000];
    		sprintf(buffer,"Converting '%s' and '%s' ", a->u.s, b->u.s);
    #endif
    		(void)to_integer(a);
    		(void)to_integer(b);
    #ifdef DEBUG_FOR_CONVERSIONS
    		ast_log(LOG_WARNING,"%s to '%lld' and '%lld'\n", buffer, a->u.i, b->u.i);
    #endif
    		r = make_integer ((quad_t)(a->u.i == b->u.i));
    	}
    
    	free_value (a);
    	free_value (b);
    	return r;
    }
    
    static struct val *
    op_gt (struct val *a, struct val *b)
    {
    	struct val *r;
    
    	if (isstring (a) || isstring (b)) {
    		to_string (a);
    		to_string (b);
    		r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) > 0));
    	} else {
    		(void)to_integer(a);
    		(void)to_integer(b);
    		r = make_integer ((quad_t)(a->u.i > b->u.i));
    	}
    
    	free_value (a);
    	free_value (b);
    	return r;
    }
    
    static struct val *
    op_lt (struct val *a, struct val *b)
    {
    	struct val *r;
    
    	if (isstring (a) || isstring (b)) {
    		to_string (a);
    		to_string (b);
    		r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) < 0));
    	} else {
    		(void)to_integer(a);
    		(void)to_integer(b);
    		r = make_integer ((quad_t)(a->u.i < b->u.i));
    	}
    
    	free_value (a);
    	free_value (b);
    	return r;
    }
    
    static struct val *
    op_ge (struct val *a, struct val *b)
    {
    	struct val *r;
    
    	if (isstring (a) || isstring (b)) {
    		to_string (a);
    		to_string (b);
    		r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) >= 0));
    	} else {
    		(void)to_integer(a);
    		(void)to_integer(b);
    		r = make_integer ((quad_t)(a->u.i >= b->u.i));
    	}
    
    	free_value (a);
    	free_value (b);
    	return r;
    }
    
    static struct val *
    op_le (struct val *a, struct val *b)
    {
    	struct val *r;
    
    	if (isstring (a) || isstring (b)) {
    		to_string (a);
    		to_string (b);
    		r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) <= 0));
    	} else {
    		(void)to_integer(a);
    		(void)to_integer(b);
    		r = make_integer ((quad_t)(a->u.i <= b->u.i));
    	}
    
    	free_value (a);
    	free_value (b);
    	return r;
    }
    
    static struct val *
    op_cond (struct val *a, struct val *b, struct val *c)
    {
    	struct val *r;
    
    	if( isstring(a) )
    	{
    		if( strlen(a->u.s) && strcmp(a->u.s, "\"\"") != 0 && strcmp(a->u.s,"0") != 0 )
    		{
    			free_value(a);
    			free_value(c);
    			r = b;
    		}
    		else
    		{
    			free_value(a);
    			free_value(b);
    			r = c;
    		}
    	}
    	else
    	{
    		(void)to_integer(a);
    		if( a->u.i )
    		{
    			free_value(a);
    			free_value(c);
    			r = b;
    		}
    		else
    		{
    			free_value(a);
    			free_value(b);
    			r = c;
    		}
    	}
    	return r;
    }
    
    static struct val *
    op_ne (struct val *a, struct val *b)
    {
    	struct val *r;
    
    	if (isstring (a) || isstring (b)) {
    		to_string (a);
    		to_string (b);
    		r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) != 0));
    	} else {
    		(void)to_integer(a);
    		(void)to_integer(b);
    		r = make_integer ((quad_t)(a->u.i != b->u.i));
    	}
    
    	free_value (a);
    	free_value (b);
    	return r;
    }
    
    static int
    chk_plus (quad_t a, quad_t b, quad_t r)
    {
    	/* sum of two positive numbers must be positive */
    	if (a > 0 && b > 0 && r <= 0)
    		return 1;
    	/* sum of two negative numbers must be negative */
    	if (a < 0 && b < 0 && r >= 0)
    		return 1;
    	/* all other cases are OK */