evalExpr.c 2.79 KB
#include <malloc.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

#include <expValue.h>
#include <tepal.h>
#include <tepal_pars.h>
#include <evalExpr.h>


/*
 * static function (internal only)
 */
static
inline
	s_expVal *
stringPlus (s_expVal * _op1, s_expVal * _op2)
{
	s_expVal * ret;
	char *     op1 = expValueString (_op1);
	char *     op2 = expValueString (_op2);
	char *     retVal = (char *) malloc (
			sizeof (char) * (strlen (op1) + strlen (op2) + 1));

	strcpy (retVal, op1);
	strcat (retVal, op2);
	ret = expValueStringNew (retVal);

	free (retVal);
	free (op2);
	free (op1);

	return ret;
}

static
inline
	s_expVal *
stringNeg (s_expVal * _op)
{
	s_expVal * ret;
	int        i;

	char *     op  = expValueString (_op);
	int        len = strlen (op) - 1;

	for (i=0; i<=(len/2); i++)
	{
		char tmp = op[i];
		op[i] = op[len-i];
		op[len-i] = tmp;
	}

	ret = expValueStringNew (op);
	free (op);
	return ret;
}

static
inline
	s_expVal *
evalIntExp (int op, s_expVal * _op1, s_expVal * _op2)
{
	long op1 = expValueInt (_op1);
	long op2 = (_op2 != NULL) ? expValueInt (_op2) : 0;

	if (op == NEG)				return expValueIntNew (- op1);

	switch (expValueGetType (_op2))
	{
		case EXP_TYP_INT:
		case EXP_TYP_FLOAT:
			switch (op)
			{
				case PLUS:		return expValueIntNew (op1 + op2);
				case MINUS:		return expValueIntNew (op1 - op2);
				case TIMES:		return expValueIntNew (op1 * op2);
				case OVER:		return expValueIntNew (op1 / op2);
				case MODULO:	return expValueIntNew (op1 % op2);
			}

		case EXP_TYP_STRING:
			if (op == PLUS)
				return stringPlus (_op1, _op2);
			exitError (ERR_STRING_OPERATOR, op);
	}
}

static
inline
	s_expVal *
evalFloatExp (int op, s_expVal * _op1, s_expVal * _op2)
{
	double op1 = expValueFloat (_op1);
	double op2 = (_op2 != NULL) ? expValueFloat (_op2) : 0.0;

	if (op == NEG)				return expValueFloatNew (- op1);

	switch (expValueGetType (_op2))
	{
		case EXP_TYP_INT:
		case EXP_TYP_FLOAT:
			switch (op)
			{
				case MODULO:	exitError (ERR_FLOAT_OPERATOR, op);
				case PLUS:		return expValueFloatNew (op1 + op2);
				case MINUS:		return expValueFloatNew (op1 - op2);
				case TIMES:		return expValueFloatNew (op1 * op2);
				case OVER:		return expValueFloatNew (op1 / op2);
			}

		case EXP_TYP_STRING:
			if (op == PLUS)
				return stringPlus (_op1, _op2);
			exitError (ERR_STRING_OPERATOR, op);
	}
}



/*
 * public functions (interface)
 */
	s_expVal *
evalExpr (int op, s_expVal * op1, s_expVal * op2)
{
	switch (expValueGetType (op1))
	{
		case EXP_TYP_INT:
			return evalIntExp (op, op1, op2);

		case EXP_TYP_FLOAT:
			if (op != MODULO)
				return evalFloatExp (op, op1, op2);
			exitError (ERR_FLOAT_OPERATOR, op);

		case EXP_TYP_STRING:
			if (op == PLUS)
				return stringPlus (op1, op2);
			if (op == NEG)
				return stringNeg (op1);
			exitError (ERR_STRING_OPERATOR, op);
	}
}