/*****************************************************************************
*   "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"

/*   I prefer to put the declarations of static functions just before the    */
/* function themselves, but the tables below needs them so...		     */

/* Although the type of parameters is specified (for InptPrsrTypeCheck rtn)  */
/* All the parameters to the following dispatched functions are passed by    */
/* address. There is a problem in TurboC (ANSI C?) that all the real types   */
/* are passed as double, even if the are float. As RealType may be float,    */
/* the problems is hidden by passing parameters by address...		     */

NumFuncTableType NumFuncTable[] = {
    { "ACOS",	 ARCCOS,acos,		1,	{ NUMERIC_EXPR } },
    { "ASIN",	 ARCSIN,asin,		1,	{ NUMERIC_EXPR } },
    { "ATAN2",	 ARCTAN2,atan2,		2,	{ NUMERIC_EXPR, NUMERIC_EXPR } },
    { "ATAN",	 ARCTAN,atan,		1,	{ NUMERIC_EXPR } },
    { "COS",	 COS,	cos,		1,	{ NUMERIC_EXPR } },
    { "EXP",	 EXP,	exp,		1,	{ NUMERIC_EXPR } },
    { "ABS",	 FABS,	fabs,		1,	{ NUMERIC_EXPR } },
    { "LN",	 LN,	log,		1,	{ NUMERIC_EXPR } },
    { "LOG",	 LOG,	log10,		1,	{ NUMERIC_EXPR } },
    { "SIN",	 SIN,	sin,		1,	{ NUMERIC_EXPR } },
    { "SQRT",	 SQRT,	sqrt,		1,	{ NUMERIC_EXPR } },
    { "TAN",	 TAN,	tan,		1,	{ NUMERIC_EXPR } },
    { "CPOLY",	 CPOLY,	PolyCountPolys,	1,	{ POLY_EXPR } },
    { "AREA",	 AREA,	PolyObjectArea,	1,	{ POLY_EXPR } },
    { "VOLUME",  VOLUME,PolyObjectVolume,1, 	{ POLY_EXPR } },
    { "TIME",	 TIME,	DosGetTime,	1,	{ NUMERIC_EXPR } },
    { "SIZEOF",  SIZEOF,GetObjectSize,	1,	{ OLST_EXPR | POLY_EXPR | CURVE_EXPR } },
    { "MESHSIZE",MESHSIZE,GetMeshSize,	2,	{ SURFACE_EXPR, NUMERIC_EXPR } },
    { "THISOBJ", THISOBJ,ThisObjectIs,	1,	{ STRING_EXPR } },
    { "RANDOM",  IRT_RNDM,IritRandom,	2,	{ NUMERIC_EXPR, NUMERIC_EXPR } },
    { "CLNTEXEC",CLNTEXEC,ClientExecute,1,	{ STRING_EXPR } }

};
int NumFuncTableSize = sizeof(NumFuncTable) / sizeof(NumFuncTableType);

ObjFuncTableType ObjFuncTable[] = {
    { "POINT",	  POINT,	GenPTObject,		3,	{ NUMERIC_EXPR, NUMERIC_EXPR, NUMERIC_EXPR },		POINT_EXPR },
    { "VECTOR",	  VECTOR,	GenVECObject,		3,	{ NUMERIC_EXPR, NUMERIC_EXPR, NUMERIC_EXPR },		VECTOR_EXPR },
    { "PLANE",	  PLANE,	GenPLANEObject,		4,	{ NUMERIC_EXPR, NUMERIC_EXPR, NUMERIC_EXPR, NUMERIC_EXPR }, PLANE_EXPR },
    { "CTLPT",	  CTLPT,	InptEvalCtlPtFromParams, ANY_PARAM_NUM, { 0 },						CTLPT_EXPR },
    { "ROTX",	  ROTX,		GMGenMatObjectRotX,	1,	{ NUMERIC_EXPR },					MATRIX_EXPR },
    { "ROTY",	  ROTY,		GMGenMatObjectRotY,	1,	{ NUMERIC_EXPR },					MATRIX_EXPR },
    { "ROTZ",	  ROTZ,		GMGenMatObjectRotZ,	1,	{ NUMERIC_EXPR },					MATRIX_EXPR },
    { "TRANS",	  TRANS,	GMGenMatObjectTrans,	1,	{ VECTOR_EXPR },					MATRIX_EXPR },
    { "SCALE",	  SCALE,	GMGenMatObjectScale,	1,	{ VECTOR_EXPR },					MATRIX_EXPR },
    { "BOX",	  BOX,		GenBOXObject,		4,	{ VECTOR_EXPR, NUMERIC_EXPR, NUMERIC_EXPR, NUMERIC_EXPR }, POLY_EXPR },
    { "GBOX",	  GBOX,		GenGBOXObject,		4,	{ VECTOR_EXPR, VECTOR_EXPR, VECTOR_EXPR, VECTOR_EXPR }, POLY_EXPR },
    { "CONE",	  CONE,		GenCONEObject,		3,	{ VECTOR_EXPR, VECTOR_EXPR, NUMERIC_EXPR },		POLY_EXPR },
    { "CON2",	  CONE2,	GenCONE2Object,		4,	{ VECTOR_EXPR, VECTOR_EXPR, NUMERIC_EXPR, NUMERIC_EXPR }, POLY_EXPR },
    { "CYLIN",	  CYLIN,	GenCYLINObject,		3,	{ VECTOR_EXPR, VECTOR_EXPR, NUMERIC_EXPR },		POLY_EXPR },
    { "SPHERE",	  SPHERE,	GenSPHEREObject,	2,	{ VECTOR_EXPR, NUMERIC_EXPR },				POLY_EXPR },
    { "TORUS",	  TORUS,	GenTORUSObject,		4,	{ VECTOR_EXPR, VECTOR_EXPR, NUMERIC_EXPR, NUMERIC_EXPR }, POLY_EXPR },
    { "CIRCPOLY", CIRCPOLY,	GenPOLYDISKObject,	3,	{ VECTOR_EXPR, VECTOR_EXPR, NUMERIC_EXPR },		POLY_EXPR },
    { "POLY",     POLY,		GenPOLYGONObject,	2,	{ OLST_EXPR, NUMERIC_EXPR },				POLY_EXPR },
    { "CROSSEC",  CROSSEC,	GenCROSSECObject,	1,	{ POLY_CURVE_EXPR },					POLY_EXPR },
    { "SURFREV",  SURFREV,	GenSURFREVObject,	1,	{ POLY_CURVE_EXPR },					POLY_EXPR | SURFACE_EXPR },
    { "SURFPREV", SURFPREV,	GenSURFPREVObject,	1,	{ CURVE_EXPR },						SURFACE_EXPR },
    { "EXTRUDE",  EXTRUDE,	GenEXTRUDEObject,	2,	{ POLY_CURVE_EXPR, VECTOR_EXPR },			POLY_EXPR | SURFACE_EXPR },
    { "LIST",	  LIST,		InptEvalGenObjectList,	ANY_PARAM_NUM, { 0 },						OLST_EXPR },
    { "LOAD",     LOAD,		LoadObjectFromFile,	1,	{ STRING_EXPR },					ANY_EXPR },
    { "CONVEX",	  CONVEX,	ConvexPolyObjectN,	1,	{ POLY_EXPR  | OLST_EXPR },				POLY_EXPR | OLST_EXPR },
    { "SBEZIER",  SBEZIER,	GenBezierSurfaceObject, 1,	{ OLST_EXPR },						SURFACE_EXPR },
    { "CBEZIER",  CBEZIER,	GenBezierCurveObject,	1,	{ OLST_EXPR },						CURVE_EXPR },
    { "SBSPLINE", SBSPLINE,	GenBsplineSurfaceObject,4,	{ NUMERIC_EXPR, NUMERIC_EXPR, OLST_EXPR, OLST_EXPR },	SURFACE_EXPR },
    { "CBSPLINE", CBSPLINE,	GenBsplineCurveObject,	3,	{ NUMERIC_EXPR, OLST_EXPR, OLST_EXPR },			CURVE_EXPR },
    { "SEVAL",    SEVAL,	EvalSurfaceObject,	3,	{ SURFACE_EXPR, NUMERIC_EXPR, NUMERIC_EXPR },		CTLPT_EXPR },
    { "CEVAL",    CEVAL,	EvalCurveObject,	2,	{ CURVE_EXPR, NUMERIC_EXPR },				CTLPT_EXPR },
    { "STANGENT", STANGENT,	TangentSurfaceObject,	4,	{ SURFACE_EXPR, NUMERIC_EXPR, NUMERIC_EXPR, NUMERIC_EXPR }, VECTOR_EXPR },
    { "CTANGENT", CTANGENT,	TangentCurveObject,	2,	{ CURVE_EXPR, NUMERIC_EXPR },				VECTOR_EXPR },
    { "SNORMAL",  SNORMAL,	NormalSurfaceObject,	3,	{ SURFACE_EXPR, NUMERIC_EXPR, NUMERIC_EXPR },		VECTOR_EXPR },
    { "TDIVIDE",  TDIVIDE,	DivideTrivarObject,	3,	{ TRIVAR_EXPR, NUMERIC_EXPR, NUMERIC_EXPR },		OLST_EXPR },
    { "SDIVIDE",  SDIVIDE,	DivideSurfaceObject,	3,	{ SURFACE_EXPR, NUMERIC_EXPR, NUMERIC_EXPR },		OLST_EXPR },
    { "CDIVIDE",  CDIVIDE,	DivideCurveObject,	2,	{ CURVE_EXPR, NUMERIC_EXPR },				OLST_EXPR },
    { "TREGION",  TREGION,	RegionFromTrivarObject, 4,	{ TRIVAR_EXPR, NUMERIC_EXPR, NUMERIC_EXPR, NUMERIC_EXPR }, SURFACE_EXPR },
    { "SREGION",  SREGION,	RegionFromSurfaceObject,4,	{ SURFACE_EXPR, NUMERIC_EXPR, NUMERIC_EXPR, NUMERIC_EXPR }, SURFACE_EXPR },
    { "CREGION",  CREGION,	RegionFromCurveObject,	3,	{ CURVE_EXPR, NUMERIC_EXPR, NUMERIC_EXPR },		CURVE_EXPR },
    { "TREFINE",  TREFINE,	RefineTrivarObject,	4,	{ TRIVAR_EXPR, NUMERIC_EXPR, NUMERIC_EXPR, OLST_EXPR }, SURFACE_EXPR },
    { "SREFINE",  SREFINE,	RefineSurfaceObject,	4,	{ SURFACE_EXPR, NUMERIC_EXPR, NUMERIC_EXPR, OLST_EXPR }, SURFACE_EXPR },
    { "CREFINE",  CREFINE,	RefineCurveObject,	3,	{ CURVE_EXPR, NUMERIC_EXPR, OLST_EXPR },		CURVE_EXPR },
    { "SRAISE",   SRAISE,	RaiseSurfaceObject,	3,	{ SURFACE_EXPR, NUMERIC_EXPR, NUMERIC_EXPR },		SURFACE_EXPR },
    { "CRAISE",   CRAISE,	RaiseCurveObject,	2,	{ CURVE_EXPR, NUMERIC_EXPR },				CURVE_EXPR },
    { "CSURFACE", CSURFACE,	CurveFromSurface,	3,	{ SURFACE_EXPR, NUMERIC_EXPR, NUMERIC_EXPR },		CURVE_EXPR },
    { "CMESH",    CMESH,	CurveFromSrfMesh,	3,	{ SURFACE_EXPR, NUMERIC_EXPR, NUMERIC_EXPR },		CURVE_EXPR },
    { "NTH",	  NTH,		GetNthList,		2,	{ OLST_EXPR, NUMERIC_EXPR },				ANY_EXPR },
    { "GPOLYGON", GPOLYGON,	Geometry2Polygons,	2,	{ OLST_GEOM_EXPR, NUMERIC_EXPR },			POLY_EXPR },
    { "GPOLYLINE",GPOLYLINE,	Geometry2Polylines,	2,	{ OLST_GEOM_EXPR, NUMERIC_EXPR },			POLY_EXPR },
    { "CIRCLE",   CIRCLE,	GenCircleCurveObject,	2,	{ VECTOR_EXPR, NUMERIC_EXPR },				CURVE_EXPR },
    { "PCIRCLE",  PCIRCLE,	GenPCircleCurveObject,	2,	{ VECTOR_EXPR, NUMERIC_EXPR },				CURVE_EXPR },
    { "ARC",	  ARC,		GenArcCurveObject,	3,	{ VECTOR_EXPR, VECTOR_EXPR, VECTOR_EXPR },		CURVE_EXPR },
    { "RULEDSRF", RULEDSRF,	GenRuledSrfObject,	2,	{ CURVE_EXPR, CURVE_EXPR },				SURFACE_EXPR },
    { "BOOLSUM",  BOOLSUM,	GenBoolSumSrfObject,	4,	{ CURVE_EXPR, CURVE_EXPR, CURVE_EXPR, CURVE_EXPR },	SURFACE_EXPR },
    { "BOOLONE",  BOOLONE,	GenBoolOneSrfObject,	1,	{ CURVE_EXPR },						SURFACE_EXPR },
    { "SFROMCRVS", SFROMCRVS,	GenSrfFromCrvsObject,	2,	{ OLST_EXPR, NUMERIC_EXPR },				SURFACE_EXPR },
    { "SWEEPSRF", SWEEPSRF,	GenSweepSrfObject,	3,	{ CURVE_EXPR, CURVE_EXPR, CURVE_EXPR | VECTOR_EXPR | NUMERIC_EXPR },	SURFACE_EXPR },
    { "SWPSCLSRF", SWPSCLSRF,	GenSweepScaleSrfObject,	5,	{ CURVE_EXPR, CURVE_EXPR, CURVE_EXPR | NUMERIC_EXPR, CURVE_EXPR | VECTOR_EXPR | NUMERIC_EXPR, NUMERIC_EXPR },	SURFACE_EXPR },
    { "OFFSET",	  OFFSET,	GenOffsetObject,	4,	{ CURVE_EXPR | SURFACE_EXPR, NUMERIC_EXPR, NUMERIC_EXPR, NUMERIC_EXPR }, CURVE_EXPR | SURFACE_EXPR },
    { "AOFFSET",  AOFFSET,	GenAOffsetObject,	5,	{ CURVE_EXPR | SURFACE_EXPR, NUMERIC_EXPR, NUMERIC_EXPR, NUMERIC_EXPR, NUMERIC_EXPR }, CURVE_EXPR | SURFACE_EXPR | OLST_EXPR },
    { "LOFFSET",  LOFFSET,	GenLeastSqrOffsetObject,5,	{ CURVE_EXPR, NUMERIC_EXPR, NUMERIC_EXPR, NUMERIC_EXPR, NUMERIC_EXPR }, CURVE_EXPR },
    { "COERCE",   COERCE,	CoerceObjectTo,		2,	{ ANY_EXPR, NUMERIC_EXPR },				ANY_EXPR },
    { "CEDITPT",  CEDITPT,	EditCrvControlPoint,	3,	{ CURVE_EXPR, CTLPT_EXPR, NUMERIC_EXPR },		CURVE_EXPR },
    { "SEDITPT",  SEDITPT,	EditSrfControlPoint,	4,	{ SURFACE_EXPR, CTLPT_EXPR, NUMERIC_EXPR, NUMERIC_EXPR }, SURFACE_EXPR },
    { "MERGEPOLY",MERGEPOLY,	GenObjectFromPolyList,	1,	{ OLST_EXPR },						POLY_EXPR },
    { "CMORPH",   CMORPH,	TwoCrvsMorphing,	4,	{ CURVE_EXPR, CURVE_EXPR, NUMERIC_EXPR, NUMERIC_EXPR },	CURVE_EXPR | OLST_EXPR },
    { "SMORPH",   SMORPH,	TwoSrfsMorphing,	3,	{ SURFACE_EXPR, SURFACE_EXPR, NUMERIC_EXPR },		SURFACE_EXPR },
    { "BZR2BSP",  BZR2BSP,	CnvrtBezierToBspline,	1,	{ SURFACE_EXPR | CURVE_EXPR },				CURVE_EXPR | SURFACE_EXPR },
    { "BSP2BZR",  BSP2BZR,	CnvrtBsplineToBezier,	1,	{ SURFACE_EXPR | CURVE_EXPR },				CURVE_EXPR | SURFACE_EXPR },
    { "SMERGE",   SMERGE,	MergeSrfSrf,		4,	{ SURFACE_EXPR, SURFACE_EXPR, NUMERIC_EXPR, NUMERIC_EXPR }, SURFACE_EXPR },
    { "CDERIVE",  CDERIVE,	DeriveCurveObject,	1,	{ CURVE_EXPR },						CURVE_EXPR },
    { "SDERIVE",  SDERIVE,	DeriveSurfaceObject,	2,	{ SURFACE_EXPR, NUMERIC_EXPR },				SURFACE_EXPR },
    { "TDERIVE",  TDERIVE,	DeriveTrivarObject,	2,	{ TRIVAR_EXPR, NUMERIC_EXPR },				TRIVAR_EXPR },
    { "CINTEG",   CINTEG,	IntegrateCurveObject,	1,	{ CURVE_EXPR },						CURVE_EXPR },
    { "SNRMLSRF", SNRMLSRF,	SurfaceNormalObject,	1,	{ SURFACE_EXPR },					SURFACE_EXPR },
    { "SYMBPROD", SYMBPROD,	TwoCrvsSrfsProduct,	2,	{ CURVE_EXPR | SURFACE_EXPR, CURVE_EXPR | SURFACE_EXPR }, CURVE_EXPR | SURFACE_EXPR },
    { "SYMBDPROD",SYMBDPROD,	TwoCrvsSrfsDotProduct,	2,	{ CURVE_EXPR | SURFACE_EXPR, CURVE_EXPR | SURFACE_EXPR }, CURVE_EXPR | SURFACE_EXPR },
    { "SYMBCPROD",SYMBCPROD,	TwoCrvsSrfsCrossProduct,2,	{ CURVE_EXPR | SURFACE_EXPR, CURVE_EXPR | SURFACE_EXPR }, CURVE_EXPR | SURFACE_EXPR },
    { "SYMBSUM",  SYMBSUM,	TwoCrvsSrfsSum,		2,	{ CURVE_EXPR | SURFACE_EXPR, CURVE_EXPR | SURFACE_EXPR }, CURVE_EXPR | SURFACE_EXPR },
    { "SYMBDIFF", SYMBDIFF,	TwoCrvsSrfsDiff,	2,	{ CURVE_EXPR | SURFACE_EXPR, CURVE_EXPR | SURFACE_EXPR }, CURVE_EXPR | SURFACE_EXPR },
    { "HOMOMAT",  HOMOMAT,	GenMatObjectGeneric,	1,	{ OLST_EXPR },						MATRIX_EXPR },
    { "CINFLECT", CINFLECT,	CrvInflectionPts,	2,	{ CURVE_EXPR, NUMERIC_EXPR },				CURVE_EXPR | OLST_EXPR },
    { "CCRVTR",   CCRVTR,	CrvCurvaturePts,	2,	{ CURVE_EXPR, NUMERIC_EXPR },				CURVE_EXPR | OLST_EXPR },
    { "SCRVTR",   SCRVTR,	SrfCurvatureBounds,	3,	{ SURFACE_EXPR, NUMERIC_EXPR, NUMERIC_EXPR },		SURFACE_EXPR },
    { "CREPARAM", CREPARAM,	CrvReparametrization,	3,	{ CURVE_EXPR, NUMERIC_EXPR, NUMERIC_EXPR },		CURVE_EXPR },
    { "SREPARAM", SREPARAM,	SrfReparametrization,	4,	{ SURFACE_EXPR, NUMERIC_EXPR, NUMERIC_EXPR, NUMERIC_EXPR }, SURFACE_EXPR },
    { "CEVOLUTE", CEVOLUTE,	CrvEvolute,		1,	{ CURVE_EXPR },						CURVE_EXPR },
    { "CZEROS",   CZEROS,	CrvZeros,		3,	{ CURVE_EXPR, NUMERIC_EXPR, NUMERIC_EXPR },		OLST_EXPR },
    { "CEXTREMES",CEXTREMES,	CrvExtremes,		3,	{ CURVE_EXPR, NUMERIC_EXPR, NUMERIC_EXPR },		OLST_EXPR },
    { "CCINTER",  CCINTER,	CrvCrvInter,		4,	{ CURVE_EXPR, CURVE_EXPR, NUMERIC_EXPR, NUMERIC_EXPR },	SURFACE_EXPR | OLST_EXPR },
    { "NIL",      NIL,	        GetNilList,		0, 	{ 0 },							OLST_EXPR },
    { "COORD",    COORD,        GetObjectCoord,		2, 	{ ANY_EXPR, NUMERIC_EXPR },				NUMERIC_EXPR | CTLPT_EXPR | POINT_EXPR },
    { "COMPOSE",  COMPOSE,      CrvComposition,		2, 	{ CURVE_EXPR | SURFACE_EXPR, CURVE_EXPR },		CURVE_EXPR },
    { "PRISA",    PRISA,        SrfsPrisa,		5, 	{ SURFACE_EXPR, NUMERIC_EXPR, NUMERIC_EXPR, NUMERIC_EXPR, VECTOR_EXPR }, OLST_EXPR },
    { "CRVPTDST", CRVPTDIST,    CrvPointDist,		4, 	{ CURVE_EXPR, POINT_EXPR, NUMERIC_EXPR, NUMERIC_EXPR },	NUMERIC_EXPR | OLST_EXPR },
    { "CRVLNDST", CRVLNDIST,    CrvLineDist,		5, 	{ CURVE_EXPR, POINT_EXPR, VECTOR_EXPR, NUMERIC_EXPR, NUMERIC_EXPR },	  NUMERIC_EXPR | OLST_EXPR },
    { "ADAPISO",  ADAPISO,      SrfAdapIsoCurves,	5, 	{ SURFACE_EXPR, NUMERIC_EXPR, NUMERIC_EXPR, NUMERIC_EXPR, NUMERIC_EXPR }, OLST_EXPR | CURVE_EXPR },
    { "PDOMAIN",  PDOMAIN,	GetFreefromParamDomain,	1,	{ TRIVAR_EXPR | TRIMSRF_EXPR | SURFACE_EXPR | CURVE_EXPR }, OLST_EXPR },
    { "CINTERP",  CINTERP,	CrvLeastSquarePtData,	4,	{ OLST_EXPR, NUMERIC_EXPR, NUMERIC_EXPR, NUMERIC_EXPR }, CURVE_EXPR },
    { "SINTERP",  SINTERP,	SrfLeastSquarePtData,	6,	{ OLST_EXPR, NUMERIC_EXPR, NUMERIC_EXPR, NUMERIC_EXPR, NUMERIC_EXPR, NUMERIC_EXPR }, SURFACE_EXPR },
    { "CMULTIRES",CMULTIRES,	CurveMultiResDecomp,	2,	{ CURVE_EXPR, NUMERIC_EXPR },				OLST_EXPR },
    { "GETLINE",  GETLINE,	WndwInputStdinObject,	1,	{ NUMERIC_EXPR },					ANY_EXPR },
    { "FFEXTREME",FFEXTREME,	ExtremumControlPointVals,2,	{ CURVE_EXPR | SURFACE_EXPR, NUMERIC_EXPR },		CTLPT_EXPR },
    { "TRIMSRF",  TRIMSRF,      GenTrimmedSurface,      3,      { SURFACE_EXPR, CURVE_EXPR | OLST_EXPR, NUMERIC_EXPR },	TRIMSRF_EXPR },
    { "STRIMSRF", SRFTRIMSRF,   GetSrfFromTrimmedSrf,   1,      { TRIMSRF_EXPR },					SURFACE_EXPR },
    { "CTRIMSRF", CRVTRIMCRV,   GetTrimCrvsFromTrimmedSrf,2,    { TRIMSRF_EXPR, NUMERIC_EXPR },				OLST_EXPR },
    { "TBEZIER",  TBEZIER,      GenBezierTrivarObject,  1,	{ OLST_EXPR },						TRIVAR_EXPR },
    { "TBSPLINE", TBSPLINE,     GenBsplineTrivarObject, 5,	{ NUMERIC_EXPR, NUMERIC_EXPR, NUMERIC_EXPR, OLST_EXPR, OLST_EXPR },	TRIVAR_EXPR },
    { "TEVAL",    TEVAL,        EvalTrivarObject,	4,	{ TRIVAR_EXPR, NUMERIC_EXPR, NUMERIC_EXPR, NUMERIC_EXPR },		CTLPT_EXPR },
    { "STRIVAR",  STRIVAR,	SurfaceFromTrivar,	3,	{ TRIVAR_EXPR, NUMERIC_EXPR, NUMERIC_EXPR },		SURFACE_EXPR },
    { "TINTERP",  TINTERP,	InterpolateTrivar,	1,	{ TRIVAR_EXPR },					TRIVAR_EXPR },
    { "CLNTREAD", CLNTREAD,	ClientRead,		2,	{ NUMERIC_EXPR, NUMERIC_EXPR },				ANY_EXPR },
    { "MOMENT",   MOMENT,	ComputeCrvMoments,	2,	{ CURVE_EXPR, NUMERIC_EXPR },				POINT_EXPR | VECTOR_EXPR },
    { "TFROMSRFS",TFROMSRFS,	GenTVFromSrfsObject,	2,	{ OLST_EXPR, NUMERIC_EXPR },				TRIVAR_EXPR },
};
int ObjFuncTableSize = sizeof(ObjFuncTable) / sizeof(ObjFuncTableType);

/* The cast for DosSystem below is because of the xlc compiler for the R6000 */
/* aix system complains on DosSystem as function with no arguments, so we    */
/* make it think it has one integer argument...				     */
GenFuncTableType GenFuncTable[] = {
    { "EXIT",	EXIT,		IritExit0,		0,	{ 0 } },
    { "VIEWOBJ",VIEWOBJ,	WndwViewObject,		1,	{ ANY_EXPR } },
    { "CHDIR",	CHDIR,		DosChangeDir,		1,	{ STRING_EXPR } },
    { "INCLUDE",INCLUDE,	FileInclude,		1,	{ STRING_EXPR } },
    { "SAVE",	SAVE,		SaveObjectInFile,	2,	{ STRING_EXPR, ANY_EXPR } },
    { "FREE",	FREEOBJ,	FreeObject,		1,	{ ANY_EXPR } },
    { "IF",	IFCOND, 	InptEvalIfCondition,	ANY_PARAM_NUM, { 0 } },
    { "FOR",	FORLOOP, 	InptEvalForLoop,	4,	{ NUMERIC_EXPR,	NUMERIC_EXPR, NUMERIC_EXPR, ANY_EXPR } },
    { "HELP",	PRHELP,		InptEvalPrintHelp,	1,	{ STRING_EXPR } },
    { "VARLIST", VARLIST, 	PrintObjectList,	0,	{ 0 } },
    { "SYSTEM",	SYSTEM,		DosSystem,		1,	{ STRING_EXPR } },
    { "LOGFILE",LOGFILE, 	WndwLogPrint,		1,	{ STRING_EXPR | NUMERIC_EXPR } },
    { "COLOR",	COLOR,		AttrSetObjectColor, 	2,	{ OLST_GEOM_EXPR, NUMERIC_EXPR } },
    { "SNOC",	SNOC,		SnocList,		2,	{ ANY_EXPR, OLST_EXPR } },
    { "ATTRIB",	ATTRIB,		SetObjectAttrib,	3,	{ ANY_EXPR, STRING_EXPR, ANY_EXPR } },
    { "RMATTR",	RMATTR,		RemoveObjectAttrib,	2,	{ ANY_EXPR, STRING_EXPR } },
    { "FFCOMPAT",FFCOMPAT,	MakeFreeFormCompatible,	2,	{ CURVE_EXPR | SURFACE_EXPR, CURVE_EXPR | SURFACE_EXPR } },
    { "MSLEEP",  MSLEEP,	MilisecondSleep,	1,	{ NUMERIC_EXPR } },
    { "PRINTF", IRITPRINT,	IritObjectPrintfStdout,	2,	{ STRING_EXPR, OLST_EXPR } },
    { "IRITSTATE",IRITSTATE,	SetIritState,		2,	{ STRING_EXPR, NUMERIC_EXPR | STRING_EXPR } },
    { "ERROR",  IRITERROR,      IritPrsrFatalError,	1,	{ STRING_EXPR } },
    { "CLNTWRITE",CLNTWRITE,	ClientWrite,		2,	{ NUMERIC_EXPR, ANY_EXPR } },
    { "CLNTCLOSE",CLNTCLOSE,	ClientClose,		2,	{ NUMERIC_EXPR, NUMERIC_EXPR } }
};
int GenFuncTableSize = sizeof(GenFuncTable) / sizeof(GenFuncTableType);

ConstantTableType ConstantTable[] = {
    { "PI",	M_PI },

    { "ON",	1.0 },
    { "TRUE",	1.0 },
    { "OFF",	0.0 },
    { "FALSE",	0.0 },

    { "COL",    (double) CAGD_CONST_U_DIR },
    { "ROW",    (double) CAGD_CONST_V_DIR },
    { "DEPTH",  (double) TRIV_CONST_W_DIR },

    { "KV_OPEN", (double) KV_UNIFORM_OPEN },
    { "KV_FLOAT", (double) KV_UNIFORM_FLOAT },
    { "KV_PERIODIC", (double) KV_UNIFORM_PERIODIC },

    { "PARAM_CHORD", (double) CAGD_CHORD_LEN_PARAM },
    { "PARAM_CENTRIP", (double) CAGD_CENTRIPETAL_PARAM },
    { "PARAM_UNIFORM", (double) CAGD_UNIFORM_PARAM },

    { "E1", (double) CAGD_PT_E1_TYPE },
    { "E2", (double) CAGD_PT_E2_TYPE },
    { "E3", (double) CAGD_PT_E3_TYPE },
    { "E4", (double) CAGD_PT_E4_TYPE },
    { "E5", (double) CAGD_PT_E5_TYPE },

    { "P1", (double) CAGD_PT_P1_TYPE },
    { "P2", (double) CAGD_PT_P2_TYPE },
    { "P3", (double) CAGD_PT_P3_TYPE },
    { "P4", (double) CAGD_PT_P4_TYPE },
    { "P5", (double) CAGD_PT_P5_TYPE },

    { "UNDEF_TYPE",   (double) IP_OBJ_UNDEF },
    { "POLY_TYPE",    (double) IP_OBJ_POLY },
    { "NUMERIC_TYPE", (double) IP_OBJ_NUMERIC },
    { "POINT_TYPE",   (double) IP_OBJ_POINT },
    { "VECTOR_TYPE",  (double) IP_OBJ_VECTOR },
    { "PLANE_TYPE",   (double) IP_OBJ_PLANE },
    { "MATRIX_TYPE",  (double) IP_OBJ_MATRIX },
    { "CURVE_TYPE",   (double) IP_OBJ_CURVE },
    { "SURFACE_TYPE", (double) IP_OBJ_SURFACE },
    { "STRING_TYPE",  (double) IP_OBJ_STRING },
    { "CTLPT_TYPE",   (double) IP_OBJ_CTLPT },
    { "LIST_TYPE",    (double) IP_OBJ_LIST_OBJ },
    { "TRIVAR_TYPE",  (double) IP_OBJ_TRIVAR },
    { "TRIMSRF_TYPE", (double) IP_OBJ_TRIMSRF },

    { "BLACK",  (double) IG_IRIT_BLACK },
    { "BLUE",	(double) IG_IRIT_BLUE },
    { "GREEN",	(double) IG_IRIT_GREEN },
    { "CYAN",	(double) IG_IRIT_CYAN },
    { "RED",	(double) IG_IRIT_RED },
    { "MAGENTA",(double) IG_IRIT_MAGENTA },
    { "YELLOW", (double) IG_IRIT_YELLOW },
    { "WHITE",  (double) IG_IRIT_WHITE },

    { "MSDOS",  (double) MACHINE_MSDOS },
    { "SGI",    (double) MACHINE_SGI },
    { "HP",     (double) MACHINE_HP },
    { "SUN",    (double) MACHINE_SUN },
    { "APOLLO", (double) MACHINE_APOLLO },
    { "UNIX",   (double) MACHINE_UNIX },
    { "IBMOS2", (double) MACHINE_IBMOS2 },
    { "IBMNT",  (double) MACHINE_IBMNT },
    { "AMIGA",  (double) MACHINE_AMIGA },
};
int ConstantTableSize = sizeof(ConstantTable) / sizeof(ConstantTableType);

UserDefinedFuncDefType
    *UserDefinedFuncList = NULL;

/*****************************************************************************
* DESCRIPTION:                                                               M
* Do type checking to the given parsed tree - return type if found one       M
* or returns ERROR_EXPR if error in types was detected.			     M
*                                                                            *
* PARAMETERS:                                                                M
*   Root:      Of parse tree to verify.                                      M
*   Level:     Of recursion. Used to identify top level (Level == 0).        M
*                                                                            *
* RETURN VALUE:                                                              M
*   IritExprType:  ERROR_EXPR if found error, or expression type otherwise.  M
*                                                                            *
* KEYWORDS:                                                                  M
*   InptPrsrTypeCheck                                                        M
*****************************************************************************/
IritExprType InptPrsrTypeCheck(ParseTree *Root, int Level)
{
    IritExprType Right, Left, Result;

    if (IS_NUM_FUNCTION(Root -> NodeKind)) {   /* Funcs returning Real Type: */
	if (IritEvalFuncParamMismatch(Root))
	    return ERROR_EXPR;
	return NUMERIC_EXPR;
    }

    if (IS_GEN_FUNCTION(Root -> NodeKind)) {     /* Funcs returning nothing: */
	if (Level == 0) {
	    if (IritEvalFuncParamMismatch(Root))
		return ERROR_EXPR;
	    return NO_EXPR;
	}
	else {
	    IPGlblEvalError = IE_ERR_TYPE_MISMATCH;
	    UpdateCharError("Procedure ", Root -> NodeKind, Root);
	    return ERROR_EXPR;
	}
    }

    if (IS_OBJ_FUNCTION(Root -> NodeKind)) {     /* Funcs returning objects: */
	if (IritEvalFuncParamMismatch(Root))
	    return ERROR_EXPR;
	return ObjFuncTable[Root -> NodeKind - OBJ_FUNC_OFFSET].RetType;
    }

    switch (Root -> NodeKind) {
	case PLUS:
	case MINUS:
	case MULT:
	case DIV:
	case POWER:
	    Right = InptPrsrTypeCheck(Root -> Right, Level + 1);
	    Left  = InptPrsrTypeCheck(Root -> Left,  Level + 1);
	    if (Right == ERROR_EXPR || Left == ERROR_EXPR)
		return ERROR_EXPR;
	    if (!OverLoadTypeCheck(Root -> NodeKind, Right, Left, &Result)) {
		IPGlblEvalError = IE_ERR_TYPE_MISMATCH;
                UpdateCharError("Operator ", Root -> NodeKind, Root);
		return ERROR_EXPR;
	    }
	    else
		return Result;
	case UNARMINUS:
	    if ((Right = InptPrsrTypeCheck(Root -> Right, Level + 1))
							== ERROR_EXPR)
		return ERROR_EXPR;
	    else if (!OverLoadTypeCheck(Root -> NodeKind, Right, NO_EXPR,
								&Result)) {
		IPGlblEvalError = IE_ERR_TYPE_MISMATCH;
                UpdateCharError("Operator ", Root -> NodeKind, Root);
		return ERROR_EXPR;
	    }
	    else
		return Result;
	case EQUAL:
	    if ((Right = InptPrsrTypeCheck(Root -> Right, Level + 1))
							== ERROR_EXPR)
		return ERROR_EXPR;
	    if (Root -> Left -> NodeKind != PARAMETER) {
		IPGlblEvalError = IE_ERR_ASSIGN_LEFT_OP;
		InptPrsrPrintTree(Root -> Left, IPGlblCharData);
		return ERROR_EXPR;
	    }
	    else if (Root -> Left -> PObj -> ObjType == IP_OBJ_UNDEF)
		SET_TO_BE_ASSIGN_OBJ(Root -> Left -> PObj);
	    return Right;
	case BOOL_AND:
	case BOOL_OR:
	    if (InptPrsrTypeCheck(Root -> Right, Level + 1) != NUMERIC_EXPR ||
		InptPrsrTypeCheck(Root -> Left,  Level + 1) != NUMERIC_EXPR)
		return ERROR_EXPR;
	    return NUMERIC_EXPR;
	case BOOL_NOT:
	    if (InptPrsrTypeCheck(Root -> Right, Level + 1) != NUMERIC_EXPR)
		return ERROR_EXPR;
	    return NUMERIC_EXPR;
	case CMP_EQUAL:
	case CMP_NOTEQUAL:
	case CMP_LSEQUAL:
	case CMP_GTEQUAL:
	case CMP_LESS:
	case CMP_GREAT:
	    Right = InptPrsrTypeCheck(Root -> Right, Level + 1);
	    Left  = InptPrsrTypeCheck(Root -> Left,  Level + 1);
	    if (Right == ERROR_EXPR || Left == ERROR_EXPR)
		return ERROR_EXPR;
	    return NUMERIC_EXPR;
	case NUMBER:
	    return NUMERIC_EXPR;
	case PARAMETER:
	    switch (Root -> PObj -> ObjType) {
                case IP_OBJ_POLY:
                    return POLY_EXPR;
		case IP_OBJ_NUMERIC:
		    return NUMERIC_EXPR;
		case IP_OBJ_POINT:
		    return POINT_EXPR;
		case IP_OBJ_VECTOR:
		    return VECTOR_EXPR;
		case IP_OBJ_PLANE:
		    return PLANE_EXPR;
		case IP_OBJ_CTLPT:
		    return CTLPT_EXPR;
		case IP_OBJ_MATRIX:
		    return MATRIX_EXPR;
		case IP_OBJ_STRING:
		    return STRING_EXPR;
		case IP_OBJ_LIST_OBJ:
		    return OLST_EXPR;
		case IP_OBJ_CURVE:
		    return CURVE_EXPR;
		case IP_OBJ_SURFACE:
		    return SURFACE_EXPR;
		default:
		    if (IS_TO_BE_ASSIGN_OBJ(Root -> PObj)) {
			/* A block of expressions seperated by colons has  */
			/* an assignment followed by usage herein. No idea */
			/* of the type forces us to allow anything and     */
			/* hope for the best.				   */
			return ANY_EXPR;
		    }
		    else {
			IPGlblEvalError = IE_ERR_IP_OBJ_UNDEFINED;
			sprintf(IPGlblCharData, "Object = %s, Type %d",
				Root -> PObj -> Name, Root -> PObj -> ObjType);
			return ERROR_EXPR;
		    }
	    }
	case STRING:
	    return STRING_EXPR;
	case USERFUNCDEF:
	    return ANY_EXPR;
	case USERPROCDEF:
	    return NO_EXPR;
	case USERINSTDEF:
	    return ANY_EXPR;
	case COLON:
	    if (Root -> Left &&
		Root -> Left -> NodeKind == EQUAL &&
		Root -> Left -> Right &&
		(Root -> Left-> Right -> NodeKind == USERPROCDEF ||
		 Root -> Left-> Right -> NodeKind == USERFUNCDEF)) {
		ParseTree *Body;

		/* A special form of function/procedure definition. */
		for (Body = Root;
		     Body -> NodeKind == COLON;
		     Body = Body -> Right);
		if (Root -> Left -> Left -> NodeKind != PARAMETER ||
		    Body == NULL ||
		    Body == Root)
		    return ERROR_EXPR;		    
	    }
	    else {
		Left  = InptPrsrTypeCheck(Root -> Left,  0);
		Right = InptPrsrTypeCheck(Root -> Right, 0);
		if (Right == ERROR_EXPR || Left == ERROR_EXPR)
		    return ERROR_EXPR;
	    }
	    return NO_EXPR;
	default:				     /* Should never happen. */
	    IPGlblEvalError = IE_ERR_FATAL_ERROR;
            UpdateCharError("Token ", Root -> NodeKind, Root);
	    return ERROR_EXPR;
    }
}

/* Disable the function with no prototype warning on Borland's compilers. */
#ifdef __BORLANDC__
#pragma warn -pro
#endif /* __BORLANDC__ */

/*****************************************************************************
* DESCRIPTION:                                                               M
* Evaluates the given parsed and verified tree (via InptPrsrTypeCheck rtn).  M
*    The tree is modified, in place, during the evaluation process.	     M
*                                                                            *
* PARAMETERS:                                                                M
*   Root:      Parsed tree to evaluate.                                      M
*   Level:     Of recursion. Used to identify top level (Level == 0).        M
*                                                                            *
* RETURN VALUE:                                                              M
*   ParseTree *:   Result of evaluation.                                     M
*                                                                            *
* KEYWORDS:                                                                  M
*   InptPrsrEvalTree                                                         M
*****************************************************************************/
ParseTree *InptPrsrEvalTree(ParseTree *Root, int Level)
{
    int Index, NumOfParam,
	PrintIt = (Level == 0 && Root -> NodeKind != EQUAL);
    char *ErrorMsg, *p, Name[LINE_LEN];
    ParseTree *TempL, *TempR, *Params[FUNC_MAX_PARAM],
	*RetVal = NULL;
    VoidPtr ParamPtrs[FUNC_MAX_PARAM];

    if (IS_NUM_FUNCTION(Root -> NodeKind)) {/* Funcs which return Real Type: */
	Index = Root -> NodeKind - NUM_FUNC_OFFSET;
	NumOfParam = NumFuncTable[Index].NumOfParam;

	switch(Root -> NodeKind) {
	    case ARCSIN:   /* Real return functions with one real parameter. */
	    case ARCCOS:
	    case ARCTAN:
	    case COS:
	    case EXP:
	    case FABS:
	    case LN:
	    case LOG:
	    case SIN:
	    case SQRT:
	    case TAN:
	    case TIME:
		if (InptEvalFetchParameters(Root, NULL, 1, Level,
					    Params, ParamPtrs) != 1)
		    break;
		/* Use table entries to call the function directly. */
		Root -> PObj =
		    GenNUMValObject((NumFuncTable[Index].Func)
				        (Params[0] -> PObj -> U.R));
		RetVal = Root;
		break;

	    case ARCTAN2:
	    case IRT_RNDM:
		if (InptEvalFetchParameters(Root, NULL, 2, Level,
					    Params, ParamPtrs) != 2)
		    break;
		/* Use table entries to call the function directly. */
		Root -> PObj =
		    GenNUMValObject((NumFuncTable[Index].Func)
				        (Params[0] -> PObj -> U.R,
					 Params[1] -> PObj -> U.R));
		RetVal = Root;
		break;

	    default:
		if (InptEvalFetchParameters(Root,
			(FuncTableType *) &NumFuncTable[Index],
			NumOfParam, Level, Params, ParamPtrs) != NumOfParam)
		    break;

		/* Use table entries to call the function directly. */
		switch (NumFuncTable[Index].NumOfParam) {
		    case 0:
		        Root -> PObj =
			    GenNUMValObject((NumFuncTable[Index].Func)());
			break;
		    case 1:
		        Root -> PObj =
			    GenNUMValObject((NumFuncTable[Index].Func)
					        (ParamPtrs[0]));
			break;
		    case 2:
			Root -> PObj =
			    GenNUMValObject((NumFuncTable[Index].Func)
					        (ParamPtrs[0], ParamPtrs[1]));
			break;
		    case 3:
			Root -> PObj =
			    GenNUMValObject((NumFuncTable[Index].Func)
					        (ParamPtrs[0], ParamPtrs[1],
						 ParamPtrs[2]));
			break;
		    case 4:
			Root -> PObj =
			    GenNUMValObject((NumFuncTable[Index].Func)
					        (ParamPtrs[0], ParamPtrs[1],
						 ParamPtrs[2], ParamPtrs[3]));
		        break;
		    case 5:
		        Root -> PObj =
			    GenNUMValObject((NumFuncTable[Index].Func)
					        (ParamPtrs[0], ParamPtrs[1],
						 ParamPtrs[2], ParamPtrs[3],
						 ParamPtrs[4]));
		        break;
		    case 6:
		        Root -> PObj =
			    GenNUMValObject((NumFuncTable[Index].Func)
					        (ParamPtrs[0], ParamPtrs[1],
						 ParamPtrs[2], ParamPtrs[3],
						 ParamPtrs[4], ParamPtrs[5]));
		        break;
		}

		RetVal = Root;
		break;
	}
    }
    else if (IS_OBJ_FUNCTION(Root -> NodeKind)) {/* Funcs returning objects: */
	Index = Root -> NodeKind - OBJ_FUNC_OFFSET;
	NumOfParam = ObjFuncTable[Index].NumOfParam;

	switch (Root -> NodeKind) {
	    case COORD:
	        if (InptEvalFetchParameters(Root, NULL, 2, Level,
					    Params, ParamPtrs) != 2)
		    break;
	        /* Use table entries to call the function directly. */
		Root -> PObj =
		    (ObjFuncTable[Index].Func)
		        (Params[0] -> PObj, &Params[1] -> PObj -> U.R);
		if (Root -> PObj == NULL)
		    break;

		RetVal = Root;
		break;

	    case NTH:
		if (InptEvalFetchParameters(Root, NULL, 2,
					    Level, Params, ParamPtrs) != 2)
		    break;
		/* Use table entries to call the function directly. */
		Root -> PObj =
		    (ObjFuncTable[Index].Func)
		        (Params[0] -> PObj, &Params[1] -> PObj -> U.R);
		if (Root -> PObj == NULL)
		    break;

		RetVal = Root;
		break;

	    case LOAD:
		if (InptEvalFetchParameters(Root, NULL, 1,
					    Level, Params, ParamPtrs) != 1)
		    break;
		/* Use table entries to call the function directly. */
		Root -> PObj =
		    (ObjFuncTable[Index].Func)(Params[0] -> PObj -> U.Str, "");
		if (Root -> PObj == NULL) {
	            LoadSaveObjectParseError(&ErrorMsg);
		    IPGlblEvalError = IE_ERR_DATA_PRSR_ERROR;
		    strcpy(IPGlblCharData, ErrorMsg);
		    break;
		}
		RetVal = Root;
		break;

	    case CTLPT:
	    case LIST:
		/* Use table entries to call the function directly. */
		Root -> PObj = (ObjFuncTable[Index].Func)(Root -> Right);
		if (Root -> PObj == NULL)
		    break;
		RetVal = Root;
		break;

	    default:
		if (InptEvalFetchParameters(Root,
			(FuncTableType *) &ObjFuncTable[Index],
			NumOfParam, Level, Params, ParamPtrs) != NumOfParam)
		    break;

		/* Use table entries to call the function directly. */
		switch (ObjFuncTable[Index].NumOfParam) {
		    case 0:
			Root -> PObj = (ObjFuncTable[Index].Func)();
			break;
		    case 1:
			Root -> PObj = (ObjFuncTable[Index].Func)
				(ParamPtrs[0]);
			break;
		    case 2:
			Root -> PObj = (ObjFuncTable[Index].Func)
				(ParamPtrs[0], ParamPtrs[1]);
			break;
		    case 3:
			Root -> PObj = (ObjFuncTable[Index].Func)
				(ParamPtrs[0], ParamPtrs[1], ParamPtrs[2]);
			break;
		    case 4:
			Root -> PObj = (ObjFuncTable[Index].Func)
				(ParamPtrs[0], ParamPtrs[1], ParamPtrs[2],
				 ParamPtrs[3]);
			break;
		    case 5:
			Root -> PObj = (ObjFuncTable[Index].Func)
				(ParamPtrs[0], ParamPtrs[1], ParamPtrs[2],
				 ParamPtrs[3], ParamPtrs[4]);
			break;
		    case 6:
			Root -> PObj = (ObjFuncTable[Index].Func)
				(ParamPtrs[0], ParamPtrs[1], ParamPtrs[2],
				 ParamPtrs[3], ParamPtrs[4], ParamPtrs[5]);
			break;
		}
		if (Root -> PObj == NULL)
		    break;
		RetVal = Root;
		break;
	}
    }
    else if (IS_GEN_FUNCTION(Root -> NodeKind)) {/* Funcs returning nothing: */
	Index = Root -> NodeKind - GEN_FUNC_OFFSET;
	NumOfParam = GenFuncTable[Index].NumOfParam;

	switch (Root -> NodeKind) {
	    case COLOR:
		if (InptEvalFetchParameters(Root, NULL, 2, Level,
					    Params, ParamPtrs) != 2)
		    break;

		(GenFuncTable[Index].Func)
			 (Params[0] -> PObj,
			  REAL_TO_INT(Params[1] -> PObj -> U.R));
		break;
	
	    case VARLIST:
	        (GenFuncTable[Index].Func)(GlblObjList);
		break;

	    case SAVE:
		if (InptEvalFetchParameters(Root, NULL, 2, Level,
					    Params, ParamPtrs) != 2)
		    break;

		/* Use table entries to call the function directly. */
		(GenFuncTable[Index].Func)(Params[0] -> PObj -> U.Str,
					   Params[1] -> PObj);

		/* Save the matrix. */
		strncpy(Name, Params[0] -> PObj -> U.Str, LINE_LEN - 5);
		if ((p = strstr(Name, ".dat")) != NULL ||
		    (p = strstr(Name, ".DAT")) != NULL)
		    *p = 0;
		strcat(Name, ".mat");
		WndwViewSaveMatrix(Name);

	        if (LoadSaveObjectParseError(&ErrorMsg) != 0) {
		    IPGlblEvalError = IE_ERR_DATA_PRSR_ERROR;
		    strcpy(IPGlblCharData, ErrorMsg);
		    break;
	        }
		break;

	    case FREEOBJ:
		if (InptEvalFetchParameters(Root, NULL, 1, Level, Params,
					    ParamPtrs) != 1 ||
	            (TempR = InptPrsrEvalTree(Root -> Right, Level + 1))
								   == NULL)
		    break;

	        if (strlen(TempR -> PObj -> Name) == 0) {
		    IPGlblEvalError = IE_ERR_FREE_SIMPLE;
                    UpdateCharError("Procedure ", FREEOBJ, NULL);
		    RetVal = Root;
		    break;
	        }
	        /* Use table entries to call the function directly. */
	        (GenFuncTable[Index].Func)(TempR -> PObj);
	        TempR -> PObj = NULL;	    /* Make sure its disconnected... */
		break;

	    case IFCOND:
		switch (NumOfParam =
			          InptEvalCountNumParameters(Root -> Right)) {
		    case 2:
			InptEvalIfCondition(
			    InptEvalFetchParameter(Root -> Right, 0, 2),
			    InptEvalFetchParameter(Root -> Right, 1, 2),
			    NULL);
			break;
		    case 3:
			InptEvalIfCondition(
			    InptEvalFetchParameter(Root -> Right, 0, 3),
			    InptEvalFetchParameter(Root -> Right, 1, 3),
			    InptEvalFetchParameter(Root -> Right, 2, 3));
			break;
		    default:
			IPGlblEvalError = IE_ERR_NUM_PRM_MISMATCH;
			sprintf(IPGlblCharData,
				"IF clause (2 or 3 expected, found %d)",
				NumOfParam);
			break;
		}
		break;

	    case FORLOOP:
		InptEvalForLoop(InptEvalFetchParameter(Root -> Right, 0, 4),
				InptEvalFetchParameter(Root -> Right, 1, 4),
				InptEvalFetchParameter(Root -> Right, 2, 4),
				InptEvalFetchParameter(Root -> Right, 3, 4));
		break;

	    default:
		if (InptEvalFetchParameters(Root,
			(FuncTableType *) &GenFuncTable[Index],
			NumOfParam, Level, Params, ParamPtrs) != NumOfParam)
		    break;

		/* Use table entries to call the function directly. */
		switch (GenFuncTable[Index].NumOfParam) {
		    case 0:
			(GenFuncTable[Index].Func)();
			break;
		    case 1:
			(GenFuncTable[Index].Func)
				(ParamPtrs[0]);
			break;
		    case 2:
			(GenFuncTable[Index].Func)
				(ParamPtrs[0], ParamPtrs[1]);
			break;
		    case 3:
			(GenFuncTable[Index].Func)
				(ParamPtrs[0], ParamPtrs[1], ParamPtrs[2]);
			break;
		    case 4:
			(GenFuncTable[Index].Func)
				(ParamPtrs[0], ParamPtrs[1], ParamPtrs[2],
				 ParamPtrs[3]);
			break;
		    case 5:
			(GenFuncTable[Index].Func)
				(ParamPtrs[0], ParamPtrs[1], ParamPtrs[2],
				 ParamPtrs[3], ParamPtrs[4]);
			break;
		    case 6:
			(GenFuncTable[Index].Func)
				(ParamPtrs[0], ParamPtrs[1], ParamPtrs[2],
				 ParamPtrs[3], ParamPtrs[4], ParamPtrs[5]);
			break;
		}
		break;
	}
	RetVal = Root;
	if (Root -> PObj)
	    Root -> PObj -> ObjType = IP_OBJ_UNDEF;
	else
	    Root -> PObj = IPAllocObject("", IP_OBJ_UNDEF, NULL);
    }
    else {
        switch (Root -> NodeKind) {		  /* The rest of the world. */
	    case PLUS:
	    case MINUS:
	    case MULT:
	    case DIV:
	    case POWER:
	        if (((TempR = InptPrsrEvalTree(Root -> Right, Level + 1))
								== NULL) ||
		    ((TempL = InptPrsrEvalTree(Root -> Left,  Level + 1))
								== NULL))
		    break;
		TempR = OverLoadEvalOper(Root, TempR, TempL,
					 &IPGlblEvalError, IPGlblCharData);
		RetVal = TempR;
		break;

	    case UNARMINUS:
		if ((TempR = InptPrsrEvalTree(Root -> Right, Level + 1))
								      == NULL)
		    break;
		TempR = OverLoadEvalOper(Root, TempR, NULL,
					 &IPGlblEvalError, IPGlblCharData);
		RetVal = TempR;
		break;

	    case COLON:
		if (Root -> Left &&
		    Root -> Left -> NodeKind == EQUAL &&
		    Root -> Left -> Right &&
		    (Root -> Left-> Right -> NodeKind == USERPROCDEF ||
		     Root -> Left-> Right -> NodeKind == USERFUNCDEF)) {
		    /* A special form of function/procedure definition. */
		    InptEvalDefineFunc(Root);
		}
		else {
		    InptPrsrEvalTree(Root -> Left, 0);
		    InptPrsrEvalTree(Root -> Right, 0);
		}
		break;

	    case NUMBER:
		RetVal = Root;
		break;

	    case PARAMETER:
		RetVal = Root;
		break;

	    case STRING:
		RetVal = Root;
		break;

	    case EQUAL:
		if ((TempR = InptPrsrEvalTree(Root -> Right, Level + 1))
								== NULL)
		    break;
		TempL = Root -> Left;

		if (TempL -> PObj == TempR -> PObj) {
		    RetVal = TempR; /* A = A. */
		    break;
		}
		else if (TempL -> PObj == NULL)
		    TempL -> PObj = IPAllocObject("", IP_OBJ_UNDEF, NULL);
		else if (ListObjectFind(TempR -> PObj, TempL -> PObj)) {
		    /* Object is in the list. To prevent a loop in the list */
		    /* structure, create a new object to hold the result.   */
		    strcpy(Name, TempL -> PObj -> Name);
		    DeleteObject(TempL -> PObj, FALSE);
		    TempL -> PObj -> Count -= 2;
		    TempL -> PObj -> Name[0] = 0;

		    TempL -> PObj = IPAllocObject(Name, IP_OBJ_UNDEF, NULL);
		    InsertObject(TempL -> PObj);
		    TempL -> PObj -> Count++;
		}
		CopyObject(TempL -> PObj, TempR -> PObj, FALSE);

		RetVal = TempR;
		break;

	    case BOOL_AND:
	        if (((TempR = InptPrsrEvalTree(Root -> Right, Level + 1))
								== NULL) ||
		    ((TempL = InptPrsrEvalTree(Root -> Left,  Level + 1))
								== NULL))
		    break;
		if (Root -> PObj)
		    Root -> PObj -> ObjType = IP_OBJ_NUMERIC;
		else
		    Root -> PObj = IPAllocObject("", IP_OBJ_NUMERIC, NULL);
		Root -> PObj -> ObjType = IP_OBJ_NUMERIC;
		Root -> PObj -> U.R = (!APX_EQ(TempR -> PObj -> U.R, 0.0) &&
				       !APX_EQ(TempL -> PObj -> U.R, 0.0));
		RetVal = Root;
		break;

	    case BOOL_OR:
	        if (((TempR = InptPrsrEvalTree(Root -> Right, Level + 1))
								== NULL) ||
		    ((TempL = InptPrsrEvalTree(Root -> Left,  Level + 1))
								== NULL))
		    break;
		if (Root -> PObj)
		    Root -> PObj -> ObjType = IP_OBJ_NUMERIC;
		else
		    Root -> PObj = IPAllocObject("", IP_OBJ_NUMERIC, NULL);
		Root -> PObj -> U.R = (!APX_EQ(TempR -> PObj -> U.R, 0.0) ||
				       !APX_EQ(TempL -> PObj -> U.R, 0.0));
		RetVal = Root;
		break;

	    case BOOL_NOT:
		if ((TempR = InptPrsrEvalTree(Root -> Right, Level + 1))
								      == NULL)
		    break;
		if (Root -> PObj)
		    Root -> PObj -> ObjType = IP_OBJ_NUMERIC;
		else
		    Root -> PObj = IPAllocObject("", IP_OBJ_NUMERIC, NULL);
		Root -> PObj -> U.R = APX_EQ(TempR -> PObj -> U.R, 0.0);
		RetVal = Root;
		break;

	    case CMP_EQUAL:
	    case CMP_NOTEQUAL:
	    case CMP_LSEQUAL:
	    case CMP_GTEQUAL:
	    case CMP_LESS:
	    case CMP_GREAT:
	        if (((TempR = InptPrsrEvalTree(Root -> Right, Level + 1))
								== NULL) ||
		    ((TempL = InptPrsrEvalTree(Root -> Left,  Level + 1))
								== NULL))
		    break;
		RetVal = InptEvalCompareObject(Root, TempL, TempR,
					   &IPGlblEvalError, IPGlblCharData);
		break;

	    case USERINSTDEF:
		if (InptEvalCountNumParameters(Root -> Right) !=
		    Root -> UserFunc -> NumParams) {
		    IPGlblEvalError = IE_ERR_NUM_PRM_MISMATCH;
		    strcpy(IPGlblCharData, Root -> UserFunc -> FuncName);
		    break;
		}
		if (InptEvalFetchParameters(Root, NULL,
			Root -> UserFunc -> NumParams,
			Level, Params, ParamPtrs) !=
		    Root -> UserFunc -> NumParams)
		    break;

		RetVal = InptEvalUserFunc(Root, Params);
		break;
	}
    }

    if (PrintIt &&
	RetVal &&
	RetVal -> PObj &&
	RetVal -> PObj -> ObjType != IP_OBJ_UNDEF) {
	RetVal -> PObj -> Count--;	       /* Remove ref from this tree. */
	PrintObject(RetVal -> PObj);
	RetVal -> PObj -> Count++;		      /* Add reference back. */
    }

    return RetVal;
}

/* Restore the function with no prototype warning on Borland's compilers. */
#ifdef __BORLANDC__
#pragma warn .pro
#endif /* __BORLANDC__ */
