/*****************************************************************************
*   "Irit" - the 3d (not only polygonal) solid modeller.		     *
*									     *
* Written by:  Gershon Elber				Ver 0.2, Mar. 1990   *
******************************************************************************
*   Module to evaluate the binary tree generated by the InptPrsr module.     *
*   All the objects are handled the same but the numerical one, which is     *
* moved as a RealType and not as an object (only internally within this	     *
* module) as it is frequently used and consumes much less memory this way.   *
*   Note this module is par of InptPrsr module and was splited only because  *
* of text file sizes problems...					     *
*****************************************************************************/

#include <stdio.h>
#include <ctype.h>
#include <math.h>
#include <string.h>
#include "program.h"
#include "allocate.h"
#include "attribut.h"
#include "convex.h"
#include "ctrl-brk.h"
#include "dosintr.h"
#include "freeform.h"
#include "geomat3d.h"
#include "geomvals.h"
#include "inptprsg.h"
#include "inptprsl.h"
#include "objects.h"
#include "overload.h"
#include "primitiv.h"
#include "windows.h"
#include "iritgrap.h"

InptPrsrEvalErrType
    IPGlblEvalError = IPE_NO_ERR;		 /* Global used by EvalTree. */

static void LocalPrintTree(ParseTree *Root, int Level, char *Str);

/*****************************************************************************
* DESCRIPTION:                                                               M
* Returns a string representing the given type.				     M
*                                                                            *
* PARAMETERS:                                                                M
*   Type:     Type to get a string representation for.                       M
*                                                                            *
* RETURN VALUE:                                                              M
*   char *:   A string describing type Type.                                 M
*                                                                            *
* KEYWORDS:                                                                  M
*   InptPrsrTypeToStr                                                        M
*****************************************************************************/
char *InptPrsrTypeToStr(IritExprType Type)
{
    switch (Type) {
	case POLY_EXPR:
	    return "Poly";
	case NUMERIC_EXPR:
	    return "Numeric";
	case POINT_EXPR:
	    return "Point";
	case VECTOR_EXPR:
	    return "Vector";
	case PLANE_EXPR:
	    return "Plane";
	case CTLPT_EXPR:
	    return "Control Point";
	case MATRIX_EXPR:
	    return "Matrix";
	case STRING_EXPR:
	    return "String";
	case OLST_EXPR:
	    return "List Object";
	case CURVE_EXPR:
	    return "Curve";
	case SURFACE_EXPR:
	    return "Surface";
	default:
	    return "Undefined";
    }

}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Counts the number of parameters in Root. Parameters are defined as         M
* subtrees seperated by commas, i.e.: the infix form 1, 2, 3, 4 is 	     M
* represented as [1, [2, [3, 4]]] in the tree supplied to this function and  M
* 4 (number of parameters) is returned.					     M
*                                                                            *
* PARAMETERS:                                                                M
*   Root:      To count the number of its parameters.                        M
*                                                                            *
* RETURN VALUE:                                                              M
*   int:       Number of parameters encountered.                             M
*                                                                            *
* KEYWORDS:                                                                  M
*   InptEvalCountNumParameters                                               M
*****************************************************************************/
int InptEvalCountNumParameters(ParseTree *Root)
{
    int i = 1;

    if (Root == NULL)
	return 0;

    while (Root -> NodeKind == COMMA) {
	i++;
	Root = Root -> Right;
    }
    return i;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Fetches the i'th paramter out of a tree represent n parameters             M
* (0 <= i < n). See InptEvalCountNumParameters for more description of	     M
* structure.								     M
* Note it is assumed the tree HAS n parameters and 0<=i<n (No input error).  M
*                                                                            *
* PARAMETERS:                                                                M
*   Root:     To fetch its i'th parameter.                                   M
*   i:        The parameter wanted.                                          M
*   n:        Total number of parameters in Root.                            M
*                                                                            *
* RETURN VALUE:                                                              M
*   ParseTree *:    The requested parameter.                                 M
*                                                                            *
* KEYWORDS:                                                                  M
*   InptEvalFetchParameter                                                   M
*****************************************************************************/
ParseTree *InptEvalFetchParameter(ParseTree *Root, int i, int n)
{
    int j;

    for (j = 0; j < i; j++)
	Root = Root -> Right;

    if (i == n - 1)
	return Root;
    else
	return Root -> Left;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Fetches the parameters of a function from the parsed tree.		     M
* Returns TRUE iff fetching was succesfull.				     M
*                                                                            *
* PARAMETERS:                                                                M
*   Root:          Where the parameters should be searched for.              M
*   FuncTable:     The table's entry of the function we deal with.           M
*   NumParams:     Number of parameters of function.                         M
*   Level:         Level of recursion. To identify top levels.               M
*   Params:        Where to put the parameters as ParseTree.                 M
*   ParamPtrs:     And as pointers to RealType/PointType/VectorType etc.     M
*                                                                            *
* RETURN VALUE:                                                              M
*   int:           If everything matches.                                    M
*                                                                            *
* KEYWORDS:                                                                  M
*   InptEvalFetchParameters                                                  M
*****************************************************************************/
int InptEvalFetchParameters(ParseTree *Root,
			    FuncTableType *FuncTable,
			    int NumParams,
			    int Level,
			    ParseTree *Params[],
			    VoidPtr ParamPtrs[])
{
    int i;

    Level++;
    for (i = 0; i < NumParams; i++) {
	if ((Params[i] = InptPrsrEvalTree(InptEvalFetchParameter(Root -> Right,
								 i, NumParams),
					  Level)) == NULL)
	    return i;

	if (FuncTable != NULL) {
	    if (FuncTable -> ParamObjType[i] == NUMERIC_EXPR)
		ParamPtrs[i] = &Params[i] -> PObj -> U.R;
	    else if (FuncTable -> ParamObjType[i] == POINT_EXPR)
		ParamPtrs[i] = Params[i] -> PObj -> U.Pt;
	    else if (FuncTable -> ParamObjType[i] == VECTOR_EXPR)
		ParamPtrs[i] = Params[i] -> PObj -> U.Vec;
	    else if (FuncTable -> ParamObjType[i] == CTLPT_EXPR)
		ParamPtrs[i] = &Params[i] -> PObj -> U.CtlPt;
	    else if (FuncTable -> ParamObjType[i] == PLANE_EXPR)
		ParamPtrs[i] = Params[i] -> PObj -> U.Plane;
	    else if (FuncTable -> ParamObjType[i] == STRING_EXPR)
		ParamPtrs[i] = Params[i] -> PObj -> U.Str;
	    else
		ParamPtrs[i] = Params[i] -> PObj;
	}
    }

    return i;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Tests number of parameters and type of them against what is defined in the M
* global tables Num/Obj/GenFuncTable. return TRUE if mismatch was detected.  M
*                                                                            *
* PARAMETERS:                                                                M
*   Root:     The function entry node.                                       M
*                                                                            *
* RETURN VALUE:                                                              M
*   int:      TRUE if a mismatch wasdetected, FALSE of o.k.		     N
*                                                                            *
* KEYWORDS:                                                                  M
*   IritEvalFuncParamMismatch                                                M
*****************************************************************************/
int IritEvalFuncParamMismatch(ParseTree *Root)
{
    int FuncOffset, Count,
	i = Root -> NodeKind / 100;
    FuncTableType *FuncTable;

    switch (i * 100) {
	case NUM_FUNC:		       /* Numeric (real returned) functions. */
	    FuncOffset = Root -> NodeKind - NUM_FUNC_OFFSET;
	    FuncTable = (FuncTableType *) NumFuncTable;
	    break;
	case OBJ_FUNC1:			     /* Object (returned) functions. */
	case OBJ_FUNC2:			     /* Object (returned) functions. */
	    FuncOffset = Root -> NodeKind - OBJ_FUNC_OFFSET;
	    FuncTable = (FuncTableType *) ObjFuncTable;
	    break;
	case GEN_FUNC:
	    FuncOffset = Root -> NodeKind - GEN_FUNC_OFFSET;
	    FuncTable = (FuncTableType *) GenFuncTable;
	    break;
	default:
	    IPGlblEvalError = IE_ERR_FATAL_ERROR;
	    UpdateCharError("Undefined function - ", Root -> NodeKind, Root);
	    return TRUE;
    }

    Count = InptEvalCountNumParameters(Root -> Right);

    if (FuncTable[FuncOffset].NumOfParam == ANY_PARAM_NUM) {
	for (i = 0; i < Count; i++) {
	    IritExprType EType;

	    /* Special cases - FORLOOP and IF - top level considerations. */
	    if ((Root -> NodeKind == FORLOOP && i == 3) ||
		(Root -> NodeKind == IFCOND && i > 0))
		EType = InptPrsrTypeCheck(InptEvalFetchParameter(Root -> Right,
								 i, Count), 0);
	    else
		EType = InptPrsrTypeCheck(InptEvalFetchParameter(Root -> Right,
								 i, Count), 1);

	    /* Check only for consistency of input. */
	    if (EType == ERROR_EXPR)
		return TRUE;
	}
	return FALSE;
    }
    else { /* Number of parameter is well known and is in Count. */
	/* See if number of parameters is ok: */
	if (Count != FuncTable[FuncOffset].NumOfParam) {
	    IPGlblEvalError = IE_ERR_NUM_PRM_MISMATCH;
	    sprintf(IPGlblCharData, "Func %s - %d expected, %d found",
		    FuncTable[FuncOffset].FuncName,
		    FuncTable[FuncOffset].NumOfParam,
		    Count);
	    return TRUE;
	}

	/* See if type of parameters are consistent: */
	for (i = 0; i < Count; i++) {
	    IritExprType EType;

	    /* Special cases - FORLOOP and IF - top level considerations. */
	    if ((Root -> NodeKind == FORLOOP && i == 3) ||
		(Root -> NodeKind == IFCOND && i > 0))
		EType = InptPrsrTypeCheck(InptEvalFetchParameter(Root -> Right,
								 i, Count), 0);
	    else
		EType = InptPrsrTypeCheck(InptEvalFetchParameter(Root -> Right,
								 i, Count), 1);

	    if (EType == ERROR_EXPR)
		return TRUE;
	    if (FuncTable[FuncOffset].ParamObjType[i] != ANY_EXPR &&
		!(FuncTable[FuncOffset].ParamObjType[i] & EType)) {
		sprintf(IPGlblCharData, "Func %s,%sparameter %d",
			FuncTable[FuncOffset].FuncName,
			IPGlblEvalError == IE_ERR_IP_OBJ_UNDEFINED ?
						" undefined " : " ", i + 1);
		IPGlblEvalError = IE_ERR_TYPE_MISMATCH;
		return TRUE;
	    }
	}
	return FALSE;
    }
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Deallocates a parsed tree - release all memory allocated by it.	     M
*                                                                            *
* PARAMETERS:                                                                M
*   Root:      Of tree to release.                                           M
*                                                                            *
* RETURN VALUE:                                                              M
*   void                                                                     M
*                                                                            *
* KEYWORDS:                                                                  M
*   InptPrsrFreeTree                                                         M
*****************************************************************************/
void InptPrsrFreeTree(ParseTree *Root)
{
    char s[LINE_LEN];

    if (!Root)
	return;

    if (IS_FUNCTION(Root -> NodeKind)) {
	if (IS_NO_PARAM_FUNC(Root -> NodeKind))
	    ExprFree(Root);
	else {
	    InptPrsrFreeTree(Root -> Right);
	    if (Root -> PObj != NULL && strlen(Root -> PObj -> Name) == 0)
		IPFreeObject(Root -> PObj);			 /* Its temp.*/
	    ExprFree(Root);
        }
	return;
    }

    switch (Root -> NodeKind) {
	case DIV:
	case MINUS:
	case MULT:
	case PLUS:
	case POWER:
	    InptPrsrFreeTree(Root -> Right);
	    InptPrsrFreeTree(Root -> Left);
	    if (Root -> PObj != NULL && strlen(Root -> PObj -> Name) == 0)
		IPFreeObject(Root -> PObj);			 /* Its tmp. */
	    ExprFree(Root);
	    break;

	case UNARMINUS:
	case BOOL_NOT:
	    InptPrsrFreeTree(Root -> Right);
	    if (Root -> PObj != NULL && strlen(Root -> PObj -> Name) == 0)
		IPFreeObject(Root -> PObj);			 /* Its tmp. */
	    ExprFree(Root);
	    break;

	case COMMA:
	case COLON:
	case EQUAL:
	case CMP_EQUAL:
	case CMP_NOTEQUAL:
	case CMP_LSEQUAL:
	case CMP_GTEQUAL:
	case CMP_LESS:
	case CMP_GREAT:
	case BOOL_OR:
	case BOOL_AND:
  	    InptPrsrFreeTree(Root -> Right);
	    InptPrsrFreeTree(Root -> Left);
	    ExprFree(Root);
	    break;

	case PARAMETER:
	    if (Root -> PObj) {
		/* If object is not part of global variable list - remove it.*/
		if (strlen(Root -> PObj -> Name) == 0)
		    IPFreeObject(Root -> PObj);
		else
		    Root -> PObj -> Count--;
	    }
	    ExprFree(Root);
	    break;

	case NUMBER:
	case STRING:
	    if (Root -> PObj)
		IPFreeObject(Root -> PObj);
	    ExprFree(Root);
	    break;

	case TOKENSTART:
	    ExprFree(Root);
	    break;

	case OPENPARA:
	case CLOSPARA:
	    ExprFree(Root);
	    break;

	default:
	    /*   We might free partially build (by InptPrsr) tree when error */
	    /* is detected, and such tree may have nodes with NodeKind>=1000.*/
	    if (Root -> NodeKind >= 1000) {
		ExprFree(Root);
	    }
	    else {
		sprintf(s, "%s (%d).\n",
		    "InptPrsrFreeTree: Undefined ParseTree type to free",
		    Root -> NodeKind);
		IritFatalError(s);
	    }
	    break;
    }
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Prints the content of ROOT (using inorder traversal).			     M
* If *Str = NULL prints on stderr, else on given string Str.		     *
*                                                                            *
* PARAMETERS:                                                                M
*   Root:      Of tree to print.                                             M
*   Str:       String to write on the inorder of Root, or stderr if NULL.    M
*                                                                            *
* RETURN VALUE:                                                              M
*   void                                                                     M
*                                                                            *
* KEYWORDS:                                                                  M
*   InptPrsrPrintTree                                                        M
*****************************************************************************/
void InptPrsrPrintTree(ParseTree *Root, char *Str)
{
    strcpy(IPGlblCharData, "");			   /* Make the string empty. */

    if (Str == NULL) {
	strcpy(IPGlblCharData, "");		   /* Make the string empty. */
	LocalPrintTree(Root, 0, IPGlblCharData);       /* Copy to local str. */
	fprintf(stderr, IPGlblCharData);		     /* and print... */
    }
    else {
	strcpy(Str, "");			   /* Make the string empty. */
	LocalPrintTree(Root, 0, Str); /* Dont print to stderr - copy to str. */
    }
}

/*****************************************************************************
* DESCRIPTION:                                                               *
* Auxiliary function of InptPrsrPrintTree.				     *
*  It is assumed Str has at least INPUT_LINE_LEN places to write the	     *
* expression.								     *
*                                                                            *
* PARAMETERS:                                                                *
*   Root:      Of tree to print.                                             *
*   Level:     Of recursion.                                                 *
*   Str:       String to write on the inorder of Root, or stderr if NULL.    *
*                                                                            *
* RETURN VALUE:                                                              *
*   void                                                                     *
*****************************************************************************/
static void LocalPrintTree(ParseTree *Root, int Level, char *Str)
{
    int Len, i,
	CloseFlag = FALSE;

    if (!Root)
	return;
    i = Root -> NodeKind / 100;

    if ((Len = strlen(Str)) > INPUT_LINE_LEN + 100)     /* Prevent overflow. */
	if (Str[Len - 1] == '.')
	    return;			 /* "..." was allready concatenated. */
	else {
	    strcat(Str, "...");
	    return;
	}

#   ifdef DEBUG1
	strcat(Str, "[");   /* Usefull to see ALL nestings - no preceedings. */
#   endif /* DEBUG1 */

    switch (i * 100) {
	case USER_FUNC:
	    switch (Root -> NodeKind) {
		case USERFUNCDEF:
		    Level = 0;
		    CloseFlag = TRUE;
		    strcat(Str, "function(");
		    break;
		case USERPROCDEF:
		    Level = 0;
		    CloseFlag = TRUE;
		    strcat(Str, "procedure(");
		    break;
		case USERINSTDEF:
		    Level = 0;
		    CloseFlag = TRUE;
		    strcat(Str, Root -> UserFunc -> FuncName);
		    strcat(Str, "(");
		    break;
	    }
	    break;

	case NUM_FUNC:
	    Level = 0;
	    CloseFlag = TRUE;
            strcat(Str,
		   NumFuncTable[Root -> NodeKind - NUM_FUNC_OFFSET].FuncName);
	    strcat(Str, "(");
	    break;

	case OBJ_FUNC1:
	case OBJ_FUNC2:
	    Level = 0;
	    CloseFlag = TRUE;
            strcat(Str,
		   ObjFuncTable[Root -> NodeKind - OBJ_FUNC_OFFSET].FuncName);
	    strcat(Str, "(");
	    break;

	case GEN_FUNC:
	    Level = 0;
	    CloseFlag = TRUE;
            strcat(Str,
		   GenFuncTable[Root -> NodeKind - GEN_FUNC_OFFSET].FuncName);
	    strcat(Str, "(");
	    break;

	case OPERATORS:
	    switch (Root -> NodeKind) {
		case DIV:
		    if (Level > 1) {
			strcat(Str, "(");
		        CloseFlag = TRUE;
		    }
		    Level = 1;				       /* Div Level. */
		    LocalPrintTree(Root -> Left, Level, Str);
		    strcat(Str, "/");
		    break;

		case MINUS:
		    if (Level > 0) {
			strcat(Str, "(");
	        	CloseFlag = TRUE;
		    }
		    Level = 0;				     /* Minus Level. */
		    LocalPrintTree(Root -> Left, Level, Str);
		    strcat(Str, "-");
		    break;

		case MULT:
		    if (Level > 1) {
			strcat(Str, "(");
		        CloseFlag = TRUE;
		    }
		    Level = 1;				       /* Mul Level. */
		    LocalPrintTree(Root -> Left, Level, Str);
		    strcat(Str, "*");
		    break;

		case PLUS:
		    if (Level > 0) {
			strcat(Str, "(");
	        	CloseFlag = TRUE;
		    }
		    Level = 0;				      /* Plus Level. */
		    LocalPrintTree(Root -> Left, Level, Str);
		    strcat(Str, "+");
		    break;

		case POWER:
		    Level = 2;				     /* Power Level. */
		    LocalPrintTree(Root -> Left, Level, Str);
		    strcat(Str, "^");
		    break;

		case UNARMINUS:
		    strcat(Str, "(-");
		    Level = 0;
		    CloseFlag = TRUE;
		    break;

		case COMMA:
		    LocalPrintTree(Root -> Left, Level, Str);
		    strcat(Str, ",");
		    break;

		case COLON:
		    LocalPrintTree(Root -> Left, Level, Str);
		    strcat(Str, ":");
		    break;

		case EQUAL:
		    LocalPrintTree(Root -> Left, Level, Str);
		    strcat(Str, "=");
		    break;

		case CMP_EQUAL:
		    LocalPrintTree(Root -> Left, Level, Str);
		    strcat(Str, "==");
		    break;

		case CMP_NOTEQUAL:
		    LocalPrintTree(Root -> Left, Level, Str);
		    strcat(Str, "!=");
		    break;

		case CMP_LSEQUAL:
		    LocalPrintTree(Root -> Left, Level, Str);
		    strcat(Str, "<=");
		    break;

		case CMP_GTEQUAL:
		    LocalPrintTree(Root -> Left, Level, Str);
		    strcat(Str, ">=");
		    break;

		case CMP_LESS:
		    LocalPrintTree(Root -> Left, Level, Str);
		    strcat(Str, "<");
		    break;

		case CMP_GREAT:
		    LocalPrintTree(Root -> Left, Level, Str);
		    strcat(Str, ">");
		    break;

		case BOOL_OR:
		    LocalPrintTree(Root -> Left, Level, Str);
		    strcat(Str, "||");
		    break;

		case BOOL_AND:
		    LocalPrintTree(Root -> Left, Level, Str);
		    strcat(Str, "&&");
		    break;

		case BOOL_NOT:
		    LocalPrintTree(Root -> Left, Level, Str);
		    strcat(Str, "!");
		    break;

		case NUMBER:
		    sprintf(&Str[strlen(Str)], "%g", Root -> PObj -> U.R);
		    break;

		case PARAMETER:
		    sprintf(&Str[strlen(Str)], "%s", Root -> PObj -> Name);
		    break;

		case STRING:
		    sprintf(&Str[strlen(Str)], "\"%s\"",
			    Root -> PObj -> U.Str);
		    break;

		case OPENPARA:
		    strcat(Str, "(");
		    break;

		case CLOSPARA:
		    strcat(Str, ")");
		    break;

		case TOKENSTART:
		    break;

		default:
		    IritFatalError("LocalPrintTree: Undefined ParseTree type to print, exit");
            }
            break;

	default:
	    IritFatalError("LocalPrintTree: Undefined ParseTree type to print, exit");
    }
    LocalPrintTree(Root -> Right, Level, Str);
    if (CloseFlag)
	strcat(Str, ")");

#   ifdef DEBUG1
	strcat(Str, "]");   /* Usefull to see ALL nestings - no preceedings. */
#   endif /* DEBUG1 */
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Duplicates a parse tree - Generates brand new ParseTree structure but      M
* binds to non-temp variables if they are exists - their Name is not NULL.   M
*   This means that updating these objects in the copied tree, will affect   M
* these objects in the original tree.					     M
*                                                                            *
* PARAMETERS:                                                                M
*   Root:     To duplicate.                                                  M
*                                                                            *
* RETURN VALUE:                                                              M
*   ParseTree *:   Duplicated parse tree                                     M
*                                                                            *
* KEYWORDS:                                                                  M
*   InptPrsrCopyTree                                                         M
*****************************************************************************/
ParseTree *InptPrsrCopyTree(ParseTree *Root)
{
    ParseTree *NewRoot;

    if (Root == NULL)
	return NULL;

    NewRoot = ExprMalloc();

    if (IS_FUNCTION(Root -> NodeKind)) {	       /* All the functions. */
	NewRoot -> NodeKind = Root -> NodeKind;
	NewRoot -> Right = InptPrsrCopyTree(Root -> Right);
	if (IS_USER_FUNCTION(Root -> NodeKind))
	    NewRoot -> UserFunc = Root -> UserFunc;
	return NewRoot;
    }

    switch (Root -> NodeKind) {
	case DIV:
	case MINUS:
	case MULT:
	case PLUS:
	case POWER:

	case COMMA:
	case COLON:
	case EQUAL:
	case CMP_EQUAL:
	case CMP_NOTEQUAL:
	case CMP_LSEQUAL:
	case CMP_GTEQUAL:
	case CMP_LESS:
	case CMP_GREAT:
        case BOOL_OR:
        case BOOL_AND:
	    NewRoot -> NodeKind = Root -> NodeKind;
	    NewRoot -> Right = InptPrsrCopyTree(Root -> Right);
	    NewRoot -> Left  = InptPrsrCopyTree(Root -> Left);
	    return NewRoot;

	case UNARMINUS:
        case BOOL_NOT:
	    NewRoot -> NodeKind = Root -> NodeKind;
	    NewRoot -> Right = InptPrsrCopyTree(Root -> Right);
	    NewRoot -> Left  = NULL;
	    return NewRoot;

	case NUMBER:
	case PARAMETER:
	case STRING:
	    NewRoot -> NodeKind = Root -> NodeKind;
	    NewRoot -> PObj = Root -> PObj;	    /* Point on SAME object. */
	    NewRoot -> PObj -> Count++;      /* But increase its ref. count. */
	    return NewRoot;

	case TOKENSTART:
	    NewRoot -> NodeKind = Root -> NodeKind;
	    return NewRoot;

	default:
	    IritFatalError("InptPrsrCopyTree: Undefined ParseTree type to copy, exit");
    }
    return NULL;				    /* Makes warning silent. */
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Routine to return evaluation error if happen one, zero elsewhere	     M
*                                                                            *
* PARAMETERS:                                                                M
*   Message:    Place here a message describing an error, if was one.        M
*                                                                            *
* RETURN VALUE:                                                              M
*   InptPrsrEvalErrType:  Type of evaluation error.                          M
*                                                                            *
* KEYWORDS:                                                                  M
*   InptPrsrEvalError                                                        M
*****************************************************************************/
InptPrsrEvalErrType InptPrsrEvalError(char **Message)
{
    InptPrsrEvalErrType Temp;

    *Message = IPGlblCharData;
    Temp = IPGlblEvalError;
    IPGlblEvalError = IPE_NO_ERR;

    return Temp;
}
