Ejemplo n.º 1
0
void proto_init(struct bot *b) {
	bot = b;
	Link *invite_link = hashmap_get("INVITE", b->handlers);
	if (!invite_link) {
		invite_link = calloc(1, sizeof(Link));
		hashmap_set("INVITE", invite_link, b->handlers);
	}

	push_val(invite_link, (void*)irc_invite);

	Link *chanjoin_link = hashmap_get("332", b->handlers);
	if (!chanjoin_link) {
		chanjoin_link = calloc(1, sizeof(Link));
		hashmap_set("332", chanjoin_link, b->handlers);
	}

	push_val(chanjoin_link, (void*)irc_chan_join);

	Link *privmsg_link = hashmap_get("PRIVMSG", b->handlers);
	if (!privmsg_link) {
		privmsg_link = calloc(1, sizeof(Link));
		hashmap_set("PRIVMSG", privmsg_link, b->handlers);
	}

	push_val(privmsg_link, (void*)irc_privmsg);
}
Ejemplo n.º 2
0
static  int do_expr( void )
{
    long arg1;
    long arg2;
    int op;

    if( not_ok == pop_op( &op ) ) {
        return( not_ok );
    }

    if( not_ok == pop_val( &arg1 ) ) {
        return( not_ok );
    }

    pop_val( &arg2 );

    switch( op ) {
    case '+':
        push_val( arg2 + arg1 );
        break;

    case '-':
        push_val( arg2 - arg1 );
        break;

    case '*':
        push_val( arg2 * arg1 );
        break;

    case '/':
        if( 0 == arg1 ) {
            return( not_ok );
        }
        push_val( arg2 / arg1 );
        break;

    case '(':
        cvalue += 2;
        break;

    default:
        return( not_ok );
    }

    if( 1 > cvalue ) {
        return( not_ok );
    } else {
        return( op );
    }
}
Ejemplo n.º 3
0
void init(struct bot *bot) {
	mkfifo("status", 0644);
	if (!isfifo("status")) {
		printf("[fifo\tfail] Error initializing status FIFO: %s\n", strerror(errno));
	} else {
		push_val(bot->tick_functions, fifo_tick);
	}
}
Ejemplo n.º 4
0
static char * get_exp( char * str )
{
    char *ptr  = str;
    char *tptr = tokbuf;
    struct operator *op;

    while( *ptr ) {
        if( *ptr == ' ' ) {
            if( ignore_blanks ) {
                ptr++;
                continue;
            } else {
                break;
            }
        }
        op = get_op( ptr );
        if (NULL != op ) {
            if( ('-' == *ptr)  || ('+' == *ptr) ) {
                if( ('-' == *(ptr+1))  || ('+' == *(ptr+1)) ) {
                    return( NULL );
                }
                if( str != ptr )
                    break;
                if( str == ptr && !isdigit( ptr[1] ) && '.' != *(ptr+1) ) {
                    push_val(0);
                    *tptr++ = *ptr++;
                    break;
                }
            } else if (str == ptr) {
                *tptr++ = *ptr++;
                break;
            } else
                break;
        }

        *tptr++ = *ptr++;
    }
    *tptr = NULC;

    return tokbuf;
}
Ejemplo n.º 5
0
static  int evaluate( char * * line, long *val )
{
    long        arg;
    char    *   ptr;
    char    *   str;
    char    *   endptr;
    int         ercode;
    operator *  op;
    int         expr_oper;              // looking for term or operator

    expr_oper = 0;
    coper     = 0;
    cvalue    = 0;
    nparens   = 0;
    ptr       = *line;

    while( *ptr ) {
        if( *ptr == ' ' ) {
            if( ignore_blanks ) {
                ptr++;
                continue;
            } else {
                break;
            }
        }
        switch( expr_oper ) {
        case 0:                         // look for term
            str = get_exp( ptr );

            if( str == NULL ) {         // nothing is error
                return( not_ok );
            }

            op = get_op( str );
            if( *(str +1) == NULC ) {
                if( NULL != op ) {
                    push_op( op->operc );
                    ptr++;
                    break;
                }

                if( (*str == '-' ) || (*str == '+' ) ) {
                    push_op(*str);
                    ++ptr;
                    break;
                }
            }

            arg = strtol( str, &endptr, 10 );
            if( (((arg == LONG_MIN) || (arg == LONG_MAX)) && errno == ERANGE)
                 || (str == endptr) ) {
                 return( not_ok );
            }

            push_val( arg );

            ptr += endptr - str;        // to the next unprocessed char

            expr_oper = 1;              // look for operator next
            break;

        case 1:                         // look for operator
            op = get_op( ptr );
            if( NULL == op ) {
                return( not_ok );
            }
            if( ')' == *ptr ) {
                ercode = do_paren();
                if( ok > ercode ) {
                    return( ercode );
                }
            } else {
                while( coper && op->priority <= get_prio_m1() ) {
                    do_expr();
                }
                push_op( op->operc );
                expr_oper = 0;      // look for term next
            }
            ptr++;
            break;
        }
    }

    while( 1 < cvalue ) {
        ercode = do_expr();
        if( ok > ercode )
             return ercode;
    }
    if( !coper ) {
        *line = ptr;                    // next scan position
        return( pop_val( val ) );       // no operations left return result
    } else {
        return( not_ok );
    }
}
Ejemplo n.º 6
0
int
evaluate(int *ip, char last_char)
{
	int end, level;
	int op, type;
	int arg;
	int i;
	unsigned char c;

	end = 0;
	level = 0;
	undef = 0;
	op_idx = 0;
	val_idx = 0;
	value = 0;
	val_stack[0] = 0;
	need_operator = 0;
	expr_lablptr = NULL;
	expr_lablcnt = 0;
	op = OP_START;
	func_idx = 0;

	/* array index to pointer */
	expr = &prlnbuf[*ip];

	/* skip spaces */
cont:
	while (isspace(*expr))
		expr++;

	/* search for a continuation char */
	if (*expr == '\\') {
		/* skip spaces */
		i = 1;
		while (isspace(expr[i]))
			i++;

		/* check if end of line */
		if (expr[i] == ';' || expr[i] == '\0') {
			/* output */
			if (!continued_line) {
				/* replace '\' with three dots */
				strcpy(expr, "...");

				/* store the current line */
				strcpy(tmplnbuf, prlnbuf);
			}

			/* ok */
			continued_line++;

			/* read a new line */
			if (readline() == -1)
				return (0);

			/* rewind line pointer and continue */
			expr = &prlnbuf[SFIELD];
			goto cont;
		}
	}

	/* parser main loop */
	while (!end) {
		c = *expr;

		/* number */
		if (isdigit(c)) {
			if (need_operator)
				goto error;
			if (!push_val(T_DECIMAL))
				return (0);
		}

		/* symbol */
		else
		if (isalpha(c) || c == '_' || c == '.') {
			if (need_operator)
				goto error;
			if (!push_val(T_SYMBOL))
				return (0);
		}

		/* operators */
		else {
			switch (c) {
			/* function arg */
			case '\\':
				if (func_idx == 0) {
					error("Syntax error in expression!");
					return (0);
				}
				expr++;
				c = *expr++;
				if (c < '1' || c > '9') {
					error("Invalid function argument index!");
					return (0);
				}
				arg = c - '1';
				expr_stack[func_idx++] = expr;
				expr = func_arg[func_idx - 2][arg];
				break;

			/* hexa prefix */
			case '$':
				if (need_operator)
					goto error;
				if (!push_val(T_HEXA))
					return (0);
				break;

			/* character prefix */
			case '\'':
				if (need_operator)
					goto error;
				if (!push_val(T_CHAR))
					return (0);
				break;

			/* round brackets */
			case '(':
				if (need_operator)
					goto error;
				if (!push_op(OP_OPEN))
					return (0);
				level++;
				expr++;
				break;
			case ')':
				if (!need_operator)
					goto error;
				if (level == 0)
					goto error;
				while (op_stack[op_idx] != OP_OPEN) {
					if (!do_op())
						return (0);
				}
				op_idx--;
				level--;
				expr++;
				break;

			/* not equal, left shift, lower, lower or equal */
			case '<':
				if (!need_operator)
					goto error;
				expr++;
				switch (*expr) {
				case '>':
					op = OP_NOT_EQUAL;
					expr++;
					break;
				case '<':
					op = OP_SHL;
					expr++;
					break;
				case '=':
					op = OP_LOWER_EQUAL;
					expr++;
					break;
				default:
					op = OP_LOWER;
					break;
				}
				if (!push_op(op))
					return (0);
				break;

			/* right shift, higher, higher or equal */
			case '>':
				if (!need_operator)
					goto error;
				expr++;
				switch (*expr) {
				case '>':
					op = OP_SHR;
					expr++;
					break;
				case '=':
					op = OP_HIGHER_EQUAL;
					expr++;
					break;
				default:
					op = OP_HIGHER;
					break;
				}
				if (!push_op(op))
					return (0);
				break;

			/* equal */
			case '=':
				if (!need_operator)
					goto error;
				if (!push_op(OP_EQUAL))
					return (0);
				expr++;
				break;

			/* one complement */
			case '~':
				if (need_operator)
					goto error;
				if (!push_op(OP_COM))
					return (0);
				expr++;
				break;

			/* sub, neg */
			case '-':
				if (need_operator)
					op = OP_SUB;
				else
					op = OP_NEG;
				if (!push_op(op))
					return (0);
				expr++;
				break;

			/* not, not equal */
			case '!':
				if (!need_operator)
					op = OP_NOT;
				else {
					op = OP_NOT_EQUAL;
					expr++;
					if (*expr != '=')
						goto error;
				}
				if (!push_op(op))
					return (0);
				expr++;
				break;

			/* binary prefix, current PC */
			case '%':
			case '*':
				if (!need_operator) {
					if (c == '%')
						type = T_BINARY;
					else
						type = T_PC;
					if (!push_val(type))
						return (0);
					break;
				}

			/* modulo, mul, add, div, and, xor, or */
			case '+':
			case '/':
			case '&':
			case '^':
			case '|':
				if (!need_operator)
					goto error;
				switch (c) {
				case '%': op = OP_MOD; break;
				case '*': op = OP_MUL; break;
				case '+': op = OP_ADD; break;
				case '/': op = OP_DIV; break;
				case '&': op = OP_AND; break;
				case '^': op = OP_XOR; break;
				case '|': op = OP_OR;  break;
				}
				if (!push_op(op))
					return (0);
				expr++;
				break;

			/* skip immediate operand prefix if in macro */
			case '#':
				if (expand_macro)
					expr++;
				else
					end = 3;
				break;

			/* space or tab */
			case ' ':
			case '\t':
				expr++;
				break;

			/* end of line */
			case '\0':
				if (func_idx) {
					func_idx--;
					expr = expr_stack[func_idx];
					break;
				}
			case ';':
				end = 1;
				break;
			case ',':
				end = 2;
				break;
			default:
				end = 3;
				break;
			}
		}
	}

	if (!need_operator)
		goto error;
	if (level != 0)
		goto error;
	while (op_stack[op_idx] != OP_START) {
		if (!do_op())
			return (0);
	}

	/* get the expression value */
	value = val_stack[val_idx];

	/* any undefined symbols? trap that if in the last pass */
	if (undef) {
		if (pass == LAST_PASS)
			error("Undefined symbol in operand field!");
	}

	/* check if the last char is what the user asked for */
	switch (last_char) {
	case ';':
		if (end != 1)
			goto error;
		expr++;
		break;
	case ',':
		if (end != 2) {
			error("Argument missing!");
			return (0);
		}
		expr++;
		break;
	}

	/* convert back the pointer to an array index */
	*ip = expr - prlnbuf;

	/* ok */
	return (1);

	/* syntax error */
error:
	error("Syntax error in expression!");
	return (0);
}
Ejemplo n.º 7
0
LFUNC bool duel_eval_sbin(tnode *n,tvalue *v)
{
   tval_list *vl = &n->eval.vlist ;
   tvalue y,*v1= &n->eval.v1, *v2= &n->eval.v2 ;
   tnode *kid0 = n->kids[0], *kid1 = n->kids[1] ;
   int vi ;
   bool ok ;
#define lev n->eval.level

   duel_assert(n->node_kind==NK_OP && n->op_kind==OPK_SBIN);
   switch(n->op) {
   case OP_DECL:
           duel_assert(kid0->node_kind==NK_NAME && kid1->node_kind==NK_CTYPE);
           if(kid1->ctype->size<=0) duel_gen_error("illegal type size",0);
           v->val_kind=VK_LVALUE ;
           v->ctype=kid1->ctype ;
           v->u.lvalue=duel_alloc_target_space(kid1->ctype->size);
           strcpy(v->symb_val,kid0->name);
           duel_set_alias(kid0->name,v);
   break ;
   case OP_DEF:
           if(kid0->node_kind!=NK_NAME) 
                duel_gen_error("left side of := must be a simple var",0);
           if(!duel_eval(kid1,v)) return FALSE ;
           duel_set_alias(kid0->name,v);
           return TRUE ;
   case ',':
         if(lev==1 && duel_eval(kid0,v)) return TRUE ;
         lev=2 ;
         return duel_eval(kid1,v);
   case ';':  
         /*note: (x;) is not allowed in syntax, but is allowed here and 
          *means eval x, return nothing. used by parser, e.g. terminating ';'
          *produces no side effects 
          */

         if(lev==1) while(duel_eval(kid0,v)) ; /* eval all left size */
         lev=2 ;
         return duel_eval(kid1,v); 
   break ;
   case OP_IMP:  /* a=>b  for each _=eval(a) return eval(b) (with _ set) */
             if(lev>1) goto im2 ;
             for(;;) {
                  if(!duel_eval(kid0,v1)) return FALSE ;
                  lev=2 ;
             im2: push_dot_stack(v1,0);
                  ok=duel_eval(kid1,v);
                  pop_dot_stack();
                  if(ok) return TRUE ;
             }
   case OP_IF:  /* if(a) b  return eval(b) for each eval(a)!=0 */
             if(lev>1) goto if2 ;
             for(;;) {
                  if(!duel_eval(kid0,v)) return FALSE ;
                  if(!duel_mk_logical(v,"if(x)y")) continue ;
                  lev=2 ;
             if2: if(duel_eval(kid1,v)) return TRUE ;
             }
   case OP_OR:  /* a||b normal 'C' logical or */
             if(lev>1) goto or2 ;
             for(;;) {
                  if(!duel_eval(kid0,v)) return FALSE ;
                  if(duel_mk_logical(v,"x||y")) {lev=1 ; return TRUE ;}
             or2: if(duel_eval(kid1,v)) {
                    lev=2 ;
                    duel_mk_logical(v,"y||x");
                    return TRUE ;
                  }
             }
   case OP_AND:  /* a&&b normal 'C' logical and */
             if(lev>1) goto an2 ;
             for(;;) {
                  if(!duel_eval(kid0,v)) return FALSE ;
                  if(!duel_mk_logical(v,"x&&y")) {lev=1 ; return TRUE ;}
             an2: if(duel_eval(kid1,v)) {
                    lev=2 ;
                    duel_mk_logical(v,"y&&x");
                    return TRUE ;
                  }
             }
   case '.':  
             if(lev>1) goto dt2 ;
             for(;;) {
                  if(!duel_eval(kid0,v1)) return FALSE ;
                  *v2 = * v1 ;  /* copy value for the lookup */
                  if(ctype_kind_func_ptr_like(v1->ctype))  /* func.x */ 
                      duel_find_func_frame(v2,"x.y");
                  else
                  if(v1->val_kind!=VK_FVALUE)  /* type check frame or struct*/
                      duel_get_struct_val(v1,"x.y");
                  lev=2 ;
             dt2: if(!eval_dot(kid1,v,".",v1,v2)) continue ;
                  if(v->ctype!=v1->ctype || v->val_kind!=v1->val_kind ||
		     v->u.lvalue != v1->u.lvalue || 
                     strcmp(v->symb_val,v1->symb_val)!=0) /* check for x._ */
                      duel_set_symb_val(v,"%s.%s",v1,v);
                  return TRUE ;
             }
   case OP_ARR:
             if(lev>1) goto ar2 ;
             for(;;) {
                  if(!duel_eval(kid0,v1)) return FALSE ;
                  *v2 = *v1 ;           /* copy value for dereferencing */
                  duel_get_struct_ptr_val(v2,"x->y");
                  lev=2 ;
             ar2: if(!eval_dot(kid1,v,"->",v1,v2)) continue ;
                  if(v->ctype!=v1->ctype || v->val_kind!=v1->val_kind ||
		     v->u.lvalue != v1->u.lvalue || 
                     strcmp(v->symb_val,v1->symb_val)!=0) /* check for x->_ */
                      duel_set_symb_val(v,"%s->%s",v1,v);
                  return TRUE ;
             }
   case OP_TO:  /* a..b  Is it legal to have 1..(5,6) sure! */
         if(lev>1) goto to2 ;
         do {
             if(kid0 && !duel_eval(kid0,v1)) break ;
             do {
               if(kid1 && !duel_eval(kid1,v2)) break ;
         to2:  if(duel_do_op_to(kid0? v1:0,kid1? v2:0,++lev-2,v)) return TRUE;
             } while(kid1);
         } while(kid0) ;  /* either one (kid0 null) or infinite iterations*/
   break ;
   case OP_SEL:          /* x[[y]] */
           if(lev==1) { lev=2 ; n->eval.counter= -1 ; }
           if(!duel_eval(kid1,v1)) {
               stop_eval(kid0);
               return FALSE ;
           }
           vi=duel_get_posint_val(v1,"y[[x]]");
           if(vi<=n->eval.counter) {
                   /* v is smaller than previous v value, so reset x and
                    * start over. Example: \x[1,5,3] after \x[1],
                    * we continue to get [5]. but to get [3] we reset
                    * Alternatively, we could have kept a list of old
                    * generated values.
                    */
               stop_eval(kid0) ;
               n->eval.counter= -1 ;
           }
           for( ; n->eval.counter<vi ; n->eval.counter++) 
               if(!duel_eval(kid0,v)) 
                   duel_op_error("operator x of y[[x]] too large",0,v1,0);
           return TRUE ; /* value is the last (v) computed */
   break ;
   case '@':             /* x@y - generate x stops when y true */
           if(!duel_eval(kid0,v)) return FALSE ;
           if(kid1->node_kind==NK_CONST) {      /* special case y constant */
               *v2=kid1->cnst ;
               *v1= *v ;        /* because 'apply_bin_op' destroy its args */
               duel_apply_bin_op(OP_EQ,v1,v2,&y);
               if(y.u.rval_int) { stop_eval(kid0); return FALSE ; }
               return TRUE ;
           }
           *v1 = *v ;           /* allow fields in y of x@y for x struct ptr */
           if(ctype_kind_ptr_like(v->ctype) && 
              ctype_kind_struct_like(v->ctype->u.kid))
               duel_get_struct_ptr_val(v1,"x@y");

           while(eval_dot(kid1,v2,"@",v,v1)) /* check &&/y */
               if(!duel_mk_logical(v2,"y@x")) {  /* y==0, so dont stop x */
                   stop_eval(kid1);
                   return TRUE ;
               }
           stop_eval(kid0); 
    break ;
    case '#':            /* x#i define variable i as counter for gen. x*/
       if(kid1->node_kind!=NK_NAME) 
               duel_gen_error("x#y 2rd operand must be a name",0);
       if(!duel_eval(kid0,v)) return FALSE ;
       if(lev==1) { lev=2 ; n->eval.counter= -1 ; } /* first time */
       y.val_kind=VK_RVALUE ;
       y.ctype=ctype_int ;
       y.u.rval_int= ++n->eval.counter ;
       sprintf(y.symb_val,"%d",n->eval.counter);
       duel_set_alias(kid1->name,&y);
       return TRUE ;
   break ;
   case OP_DFS:          /* x-->y */
       if(lev>1) goto df2 ;
       for(;;) {
            if(!duel_eval(kid0,v)) return FALSE ;
            duel_free_val_list(vl);
            push_val(vl,v);
            lev=2 ;
       df2: if(get_next_dfs_val(vl,kid1,v)) return TRUE ;
       }
   break ;
   case OP_WHILE:       /* while(a) b  */
             if(lev==2) goto wh2 ;
             for(;;) {
                  while(duel_eval(kid0,v)) /* check &&/a */
                    if(!duel_mk_logical(v,"while(x)y")) {
                       stop_eval(kid0);
                       return FALSE ;
                    }
                  lev=2 ;
             wh2: if(duel_eval(kid1,v)) return TRUE ;
             }
   default: duel_assert(0);
   }
   return FALSE ;
#undef lev
}
Ejemplo n.º 8
0
/* Calcola e restituisce il risultato di un'espressione in forma infissa */
double EvalInfix(const char *strExpression, char * strError)
{
    Token tok;
    Token tok_temp;
    double left, right;
    double dblRet;

    strcpy(strError, "");

    tok_temp.Type = EOL;
    tok_temp.str[0] = '@';
    tok_temp.str[1] = '\0';
    push_op(tok_temp, strError);
    if ( strError[0] != '\0' )
        return 0.0;

    left = right = 0.0;
    while ( (PreviousTokenType = GetNextToken(strExpression, &tok, TRUE)) != EOL )
    {
        if ( tok.Type == UNKNOWN )
        {
            sprintf(strError, "Error: invalid token: %s\n", tok.str);
            return 0.0;
        }
        else if ( tok.Type == VALUE )
        {
            push_val(tok.Value, strError);
            if ( strError[0] != '\0' )
                return 0.0;
        }
        else if ( tok.Type == OPAREN || tok.Type == UMINUS || tok.Type == UPLUS )
        {
            push_op(tok, strError);
            if ( strError[0] != '\0' )
                return 0.0;
        }
        else if ( tok.Type == CPAREN )
        {
            while ( top_op(strError).Type != OPAREN )
            {
                if ( strError[0] != '\0' )
                    return 0.0;

                tok_temp = pop_op(strError);
                if ( strError[0] != '\0' )
                    return 0.0;

                if ( (tok_temp.Type == EOL) || (is_empty_op()) )
                {
                    sprintf(strError, "Error: unbalanced brackets.\n");
                    return 0.0;
                }

                right = pop_val(strError);
                if ( strError[0] != '\0' )
                    return 0.0;

                if ( tok_temp.Type != UMINUS )
                {
                    left = pop_val(strError);
                    if ( strError[0] != '\0' )
                        return 0.0;

                    dblRet = BinaryOperation(left, right, tok_temp.str[0], strError);
                    if ( strError[0] != '\0' )
                        return 0.0;

                    push_val(dblRet, strError);
                    if ( strError[0] != '\0' )
                        return 0.0;
                }
                else
                {
                    push_val( -1 * right, strError );
                    if ( strError[0] != '\0' )
                        return 0.0;
                }
            }
            pop_op(strError);
            if ( strError[0] != '\0' )
                return 0.0;
        }
        else
        {
            while ( PREC_TABLE[ top_op(strError).Type ].topOfStack >= PREC_TABLE[ tok.Type ].inputSymbol )
            {
                if ( strError[0] != '\0' )
                    return 0.0;

                if ( top_op(strError).Type != UMINUS && top_op(strError).Type != UPLUS )
                {
                    if ( strError[0] != '\0' )
                        return 0.0;

                    right = pop_val(strError);
                    if ( strError[0] != '\0' )
                        return 0.0;

                    left = pop_val(strError);
                    if ( strError[0] != '\0' )
                        return 0.0;

                    tok_temp = pop_op(strError);
                    if ( strError[0] != '\0' )
                        return 0.0;

                    dblRet = BinaryOperation(left, right, tok_temp.str[0], strError);
                    if ( strError[0] != '\0' )
                        return 0.0;

                    push_val(dblRet, strError);
                    if ( strError[0] != '\0' )
                        return 0.0;
                }
                else
                {
                    if ( top_op(strError).Type == UMINUS )
                    {
                        if ( strError[0] != '\0' )
                            return 0.0;

                        right = pop_val(strError);
                        if ( strError[0] != '\0' )
                            return 0.0;

                        pop_op(strError);
                        if ( strError[0] != '\0' )
                            return 0.0;

                        push_val(-1 * right, strError);
                        if ( strError[0] != '\0' )
                            return 0.0;
                    }
                    else
                    {
                        pop_op(strError);
                        if ( strError[0] != '\0' )
                            return 0.0;
                    }
                }
            }

            if ( tok.Type != EOL )
            {
                push_op(tok, strError);
                if ( strError[0] != '\0' )
                    return 0.0;
            }
        }
    }

    while ( 1 )
    {
        tok_temp = pop_op(strError);
        if ( strError[0] != '\0' )
            return 0.0;

        if ( tok_temp.Type == EOL )
            break;

        if ( tok_temp.Type != UPLUS )
        {
            right = pop_val(strError);
            if ( strError[0] != '\0' )
                return 0.0;
        }

        if ( tok_temp.Type != UMINUS && tok_temp.Type != UPLUS )
        {
            left = pop_val(strError);
            if ( strError[0] != '\0' )
                return 0.0;

            dblRet = BinaryOperation(left, right, tok_temp.str[0], strError);
            if ( strError[0] != '\0' )
                return 0.0;

            push_val(dblRet, strError);
            if ( strError[0] != '\0' )
                return 0.0;
        }
        else
        {
            push_val( -1 * right, strError );
            if ( strError[0] != '\0' )
                return 0.0;
        }
    }

    dblRet = pop_val(strError);
    if ( strError[0] != '\0' )
        return 0.0;

    if ( is_empty_val() )
    {
        return dblRet;
    }
    else
    {
        sprintf(strError, "Error: malformed expression.\n");
        return 0.0;
    }
}