home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************************
- * "Irit" - the 3d 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... *
- *****************************************************************************/
-
- #ifdef __MSDOS__
- #include <alloc.h>
- #include <dir.h>
- #endif /* __MSDOS__ */
-
- #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 "dataprsr.h"
- #include "dosintr.h"
- #include "freeform.h"
- #include "geomat3d.h"
- #include "geomvals.h"
- #include "graphgen.h"
- #include "inptprsg.h"
- #include "inptprsl.h"
- #include "matherr.h"
- #include "objects.h"
- #include "overload.h"
- #include "primitiv.h"
- #include "viewobj.h"
- #include "windows.h"
-
- InptPrsrEvalErrType IPGlblEvalError = IPE_NO_ERR;/* Global used by EvalTree. */
- extern char IPGlblCharData[LINE_LEN_LONG]; /* Used for both parse & eval. */
-
- /* I prefer to put the declarations of static functions just before the */
- /* function themselves, but the tables below needs them so... */
- static int FetchParameters(ParseTree *Root, int NumParams, int Level,
- ParseTree *Params[]);
- static void PrintHelp(char *HelpHeader);
- static void IfCondition(ParseTree *Left, ParseTree *Cond, ParseTree *Right,
- ParseTree *PBody);
- static void ForLoop(ParseTree *PStart, ParseTree *PInc, ParseTree *PEnd,
- ParseTree *PBody);
- static ObjectStruct *GenObjectList(ParseTree *PObjParams);
- static ObjectStruct *CtlPtFromParams(ParseTree *PObjParams);
- static int CountNumExpressions(ParseTree *Root);
- static ParseTree *FetchExpression(ParseTree *Root, int i, int n);
- static int RetrieveMathError(void);
- static int CountNumParameters(ParseTree *Root);
- static ParseTree *FetchParameter(ParseTree *Root, int i, int n);
- static int FuncParamMismatch(ParseTree *Root);
- static void LocalPrintTree(ParseTree *Root, int Level, char *Str);
- static void RebindVariable(ParseTree *Root, ObjectStruct *PObj);
- static int RetrieveMathError(void);
-
- /* 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 } },
- };
- int NumFuncTableSize = sizeof(NumFuncTable) / sizeof(NumFuncTableType);
-
- ObjFuncTableType ObjFuncTable[] = {
- { "VECTOR", VECTOR, GenVecObject, 3, { NUMERIC_EXPR, NUMERIC_EXPR, NUMERIC_EXPR } },
- { "CTLPT", CTLPT, CtlPtFromParams, ANY_PARAM_NUM, { 0 } },
- { "ROTX", ROTX, GenMatObjectRotX, 1, { NUMERIC_EXPR } },
- { "ROTY", ROTY, GenMatObjectRotY, 1, { NUMERIC_EXPR } },
- { "ROTZ", ROTZ, GenMatObjectRotZ, 1, { NUMERIC_EXPR } },
- { "TRANS", TRANS, GenMatObjectTrans, 1, { VECTOR_EXPR } },
- { "SCALE", SCALE, GenMatObjectScale, 1, { VECTOR_EXPR } },
- { "BOX", BOX, GenBOXObject, 4, { VECTOR_EXPR, NUMERIC_EXPR, NUMERIC_EXPR, NUMERIC_EXPR } },
- { "GBOX", GBOX, GenGBOXObject, 4, { VECTOR_EXPR, VECTOR_EXPR, VECTOR_EXPR, VECTOR_EXPR } },
- { "CONE", CONE, GenCONEObject, 3, { VECTOR_EXPR, VECTOR_EXPR, NUMERIC_EXPR } },
- { "CON2", CONE2, GenCONE2Object, 4, { VECTOR_EXPR, VECTOR_EXPR, NUMERIC_EXPR, NUMERIC_EXPR } },
- { "CYLIN", CYLIN, GenCYLINObject, 3, { VECTOR_EXPR, VECTOR_EXPR, NUMERIC_EXPR } },
- { "SPHERE", SPHERE, GenSPHEREObject, 2, { VECTOR_EXPR, NUMERIC_EXPR } },
- { "TORUS", TORUS, GenTORUSObject, 4, { VECTOR_EXPR, VECTOR_EXPR, NUMERIC_EXPR, NUMERIC_EXPR } },
- { "CIRCPOLY", CIRCPOLY, GenPLANEObject, 3, { VECTOR_EXPR, VECTOR_EXPR, NUMERIC_EXPR } },
- { "POLY", POLY, GenPOLYGONObject, 1, { OLST_EXPR } },
- { "CROSSEC", CROSSEC, GenCROSSECObject, 1, { POLY_CURVE_EXPR } },
- { "SURFREV", SURFREV, GenSURFREVObject, 1, { POLY_CURVE_EXPR } },
- { "EXTRUDE", EXTRUDE, GenEXTRUDEObject, 2, { POLY_CURVE_EXPR, VECTOR_EXPR } },
- { "LIST", LIST, GenObjectList, ANY_PARAM_NUM, { 0 } },
- { "LOAD", LOAD, DataPrsrGetObjects, 1, { STRING_EXPR } },
- { "CONVEX", CONVEX, ConvexPolyObjectN, 1, { POLY_EXPR } },
- { "SBEZIER", SBEZIER, GenBezierSurfaceObject, 1, { OLST_EXPR } },
- { "CBEZIER", CBEZIER, GenBezierCurveObject, 1, { OLST_EXPR } },
- { "SBSPLINE", SBSPLINE, GenBsplineSurfaceObject, 4, { NUMERIC_EXPR, NUMERIC_EXPR, OLST_EXPR, OLST_EXPR } },
- { "CBSPLINE", CBSPLINE, GenBsplineCurveObject, 3, { NUMERIC_EXPR, OLST_EXPR, OLST_EXPR } },
- { "SEVAL", SEVAL, EvalSurfaceObject, 3, { SURFACE_EXPR, NUMERIC_EXPR, NUMERIC_EXPR } },
- { "CEVAL", CEVAL, EvalCurveObject, 2, { CURVE_EXPR, NUMERIC_EXPR } },
- { "STANGENT", STANGENT, TangentSurfaceObject, 4, { SURFACE_EXPR, NUMERIC_EXPR, NUMERIC_EXPR, NUMERIC_EXPR } },
- { "CTANGENT", CTANGENT, TangentCurveObject, 2, { CURVE_EXPR, NUMERIC_EXPR } },
- { "SNORMAL", SNORMAL, NormalSurfaceObject, 3, { SURFACE_EXPR, NUMERIC_EXPR, NUMERIC_EXPR } },
- { "SDIVIDE", SDIVIDE, DivideSurfaceObject, 3, { SURFACE_EXPR, NUMERIC_EXPR, NUMERIC_EXPR } },
- { "CDIVIDE", CDIVIDE, DivideCurveObject, 2, { CURVE_EXPR, NUMERIC_EXPR } },
- { "SREGION", SREGION, RegionFromSurfaceObject, 4, { SURFACE_EXPR, NUMERIC_EXPR, NUMERIC_EXPR, NUMERIC_EXPR } },
- { "CREGION", CREGION, RegionFromCurveObject, 3, { CURVE_EXPR, NUMERIC_EXPR, NUMERIC_EXPR } },
- { "SREFINE", SREFINE, RefineSurfaceObject, 4, { SURFACE_EXPR, NUMERIC_OBJ, NUMERIC_OBJ, OLST_EXPR } },
- { "CREFINE", CREFINE, RefineCurveObject, 3, { CURVE_EXPR, NUMERIC_OBJ, OLST_EXPR } },
- { "SRAISE", SRAISE, RaiseSurfaceObject, 3, { SURFACE_EXPR, NUMERIC_OBJ, NUMERIC_OBJ } },
- { "CRAISE", CRAISE, RaiseCurveObject, 2, { CURVE_EXPR, NUMERIC_OBJ } },
- { "CSURFACE", CSURFACE, CurveFromSurface, 3, { SURFACE_EXPR, NUMERIC_OBJ, NUMERIC_OBJ } },
- { "CMESH", CMESH, CurveFromSrfMesh, 3, { SURFACE_EXPR, NUMERIC_OBJ, NUMERIC_OBJ } },
- { "NTH", NTH, GetNthList, 2, { OLST_EXPR, NUMERIC_EXPR } },
- { "GPOLYGON", GPOLYGON, Geometry2Polygons, 1, { OLST_GEOM_EXPR } },
- { "GPOLYLINE", GPOLYLINE, Geometry2Polylines, 1, { OLST_GEOM_EXPR } },
- { "CIRCLE", CIRCLE, GenCircleCurveObject, 2, { VECTOR_EXPR, NUMERIC_EXPR } },
- { "ARC", ARC, GenArcCurveObject, 3, { VECTOR_EXPR, VECTOR_EXPR, VECTOR_EXPR } },
- { "RULEDSRF", RULEDSRF, GenRuledSrfObject, 2, { CURVE_EXPR, CURVE_EXPR } },
- { "BOOLSUM", BOOLSUM, GenBoolSumSrfObject, 4, { CURVE_EXPR, CURVE_EXPR, CURVE_EXPR, CURVE_EXPR } },
- { "SFROMCRVS", SFROMCRVS, GenSrfFromCrvsObject, 1, { OLST_EXPR } },
- { "SWEEPSRF", SWEEPSRF, GenSweepSrfObject, 3, { CURVE_EXPR, CURVE_EXPR, CURVE_EXPR | NUMERIC_EXPR } },
- { "OFFSET", OFFSET, GenOffsetObject, 2, { CURVE_EXPR | SURFACE_EXPR, NUMERIC_EXPR } },
- { "CEDITPT", CEDITPT, EditCrvControlPoint, 3, { CURVE_EXPR, CTLPT_EXPR, NUMERIC_EXPR } },
- { "SEDITPT", SEDITPT, EditSrfControlPoint, 4, { SURFACE_EXPR, CTLPT_EXPR, NUMERIC_EXPR, NUMERIC_EXPR } },
- { "MERGEPOLY",MERGEPOLY, GenObjectFromPolyList, 1, { OLST_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... */
- typedef void (*VoidFuncIntPtr)(int);
- GenFuncTableType GenFuncTable[] = {
- { "EXIT", EXIT, MyExit, 0, { 0 } },
- { "VIEW", VIEW, WndwViewGeomObject, 2, { OLST_GEOM_EXPR, NUMERIC_EXPR } },
- { "DIR", DIR, DosPrintDir, 1, { STRING_EXPR } },
- { "CHDIR", CHDIR, DosChangeDir, 1, { STRING_EXPR } },
- { "NORMAL", NORMAL, ViewSetNormals, 3, { NUMERIC_EXPR, NUMERIC_EXPR, NUMERIC_EXPR } },
- { "INCLUDE", INCLUDE, FileInclude, 1, { STRING_EXPR } },
- { "SAVE", SAVE, DataPrsrPutObject, 2, { STRING_EXPR, ANY_EXPR } },
- { "FREE", FREEOBJ, FreeObject, 1, { ANY_EXPR } },
- { "INTERACT", INTERACT, InteractPolyObject, 2, { OLST_GEOM_EXPR, NUMERIC_EXPR } },
- { "PAUSE", PAUSE, WndwPause, 1, { NUMERIC_EXPR } },
- { "IF", IFCOND, IfCondition, 4, { NUMERIC_EXPR, STRING_EXPR, NUMERIC_EXPR, ANY_EXPR } },
- { "FOR", FORLOOP, ForLoop, 4, { NUMERIC_EXPR, NUMERIC_EXPR, NUMERIC_EXPR, ANY_EXPR } },
- { "HELP", PRHELP, PrintHelp, 1, { STRING_EXPR } },
- { "VARLIST", VARLIST, PrintObjectList, 0, { 0 } },
- { "ALIAS", ALIAS, AliasEdit, 2, { STRING_EXPR, STRING_EXPR } },
- { "BEEP", BEEP, GGTone, 2, { NUMERIC_EXPR, NUMERIC_EXPR } },
- { "EDIT", EDIT, DosEditFile, 1, { STRING_EXPR } },
- { "SYSTEM", SYSTEM, (VoidFuncIntPtr) DosSystem, 0, { 0 } },
- { "LOGFILE", LOGFILE, WndwLogPrint, 1, { NUMERIC_EXPR } },
- { "COLOR", COLOR, SetObjectColor, 2, { GEOM_EXPR, NUMERIC_EXPR } },
- { "SNOC", SNOC, SnocList, 2, { ANY_EXPR, OLST_EXPR } },
- { "ATTRIB", ATTRIB, SetObjectStrAttrib, 3, { GEOM_EXPR, STRING_EXPR, STRING_EXPR } },
- { "CLOSED", CLOSED, ViewSetClosed, 1, { 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 },
-
- { "KV_OPEN", (double) KV_UNIFORM_OPEN },
- { "KV_FLOAT", (double) KV_UNIFORM_FLOAT },
-
- { "E2", (double) CAGD_PT_E2_TYPE },
- { "E3", (double) CAGD_PT_E3_TYPE },
- { "P2", (double) CAGD_PT_P2_TYPE },
- { "P3", (double) CAGD_PT_P3_TYPE },
-
- { "BLACK", (double) BLACK },
- { "BLUE", (double) BLUE },
- { "GREEN", (double) GREEN },
- { "CYAN", (double) CYAN },
- { "RED", (double) RED },
- { "MAGENTA", (double) MAGENTA },
- { "YELLOW", (double) YELLOW },
- { "WHITE", (double) 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 },
- };
- int ConstantTableSize = sizeof(ConstantTable) / sizeof(ConstantTableType);
-
- /*****************************************************************************
- * Routine to do type checking to the given tree - return type if found one *
- * or returns ERROR_EXPR if error in types was detected. *
- *****************************************************************************/
- IritExprType InptPrsrTypeCheck(ParseTree *Root, int Level)
- {
- IritExprType Right, Left, Result;
-
- if (Level == 0 &&
- Root->NodeKind != PARAMETER && /* What is allowed on top level. */
- Root->NodeKind != EQUAL &&
- !IS_GEN_FUNCTION(Root->NodeKind)) {
- IPGlblEvalError = IE_ERR_NO_ASSIGNMENT;
- strcpy(IPGlblCharData, "");
- return ERROR_EXPR;
- }
-
- if (IS_NUM_FUNCTION(Root->NodeKind)) { /* Funcs which returns Real Type: */
- if (FuncParamMismatch(Root)) return ERROR_EXPR;
- return NUMERIC_EXPR;
- }
-
- if (IS_GEN_FUNCTION(Root->NodeKind)) { /* Funcs which returns nothing: */
- if (Level == 0) {
- if (FuncParamMismatch(Root)) return ERROR_EXPR;
- return NO_EXPR;
- }
- else {
- IPGlblEvalError = IE_ERR_TYPE_MISMATCH;
- UpdateCharError("Procedure ", Root->NodeKind);
- return ERROR_EXPR;
- }
- }
-
- switch (Root->NodeKind) {
- case VECTOR: /* Object functions which returns Vector Type: */
- case STANGENT:
- case CTANGENT:
- case SNORMAL:
- if (FuncParamMismatch(Root)) return ERROR_EXPR;
- return VECTOR_EXPR;
- case CTLPT: /* Object functions which returns Ctl Pt Type: */
- case CEVAL:
- case SEVAL:
- if (FuncParamMismatch(Root)) return ERROR_EXPR;
- return CTLPT_EXPR;
- case ROTX:
- case ROTY:
- case ROTZ:
- case TRANS:
- case SCALE:
- if (FuncParamMismatch(Root)) return ERROR_EXPR;
- return MATRIX_EXPR;
- case BOX:
- case GBOX:
- case CONE:
- case CONE2:
- case CYLIN:
- case SPHERE:
- case TORUS:
- case CIRCPOLY:
- case POLY:
- case CROSSEC:
- case CONVEX:
- case GPOLYGON:
- case GPOLYLINE:
- case MERGEPOLY:
- if (FuncParamMismatch(Root)) return ERROR_EXPR;
- return POLY_EXPR;
- case CBEZIER:
- case CBSPLINE:
- case CREFINE:
- case CRAISE:
- case CSURFACE:
- case CMESH:
- case CIRCLE:
- case ARC:
- case CREGION:
- case CEDITPT:
- if (FuncParamMismatch(Root)) return ERROR_EXPR;
- return CURVE_EXPR;
- case SBEZIER:
- case SBSPLINE:
- case SREFINE:
- case SRAISE:
- case RULEDSRF:
- case BOOLSUM:
- case SWEEPSRF:
- case SREGION:
- case SFROMCRVS:
- case SEDITPT:
- if (FuncParamMismatch(Root)) return ERROR_EXPR;
- return SURFACE_EXPR;
- case LOAD:
- case NTH:
- if (FuncParamMismatch(Root)) return ERROR_EXPR;
- return ANY_EXPR;
- case OFFSET:
- if (FuncParamMismatch(Root)) return ERROR_EXPR;
- return SURFACE_EXPR | CURVE_EXPR;
- case SURFREV:
- case EXTRUDE:
- if (FuncParamMismatch(Root)) return ERROR_EXPR;
- return SURFACE_EXPR | POLY_EXPR;
- case LIST:
- case SDIVIDE:
- case CDIVIDE:
- if (FuncParamMismatch(Root)) return ERROR_EXPR;
- return OLST_EXPR;
- 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);
- 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);
- 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;
- }
- return Right;
- case NUMBER:
- return NUMERIC_EXPR;
- case PARAMETER:
- switch (Root->U.PObj->ObjType) {
- case POLY_OBJ:
- return POLY_EXPR;
- case NUMERIC_OBJ:
- return NUMERIC_EXPR;
- case VECTOR_OBJ:
- return VECTOR_EXPR;
- case CTLPT_OBJ:
- return CTLPT_EXPR;
- case MATRIX_OBJ:
- return MATRIX_EXPR;
- case STRING_OBJ:
- return STRING_EXPR;
- case OBJ_LIST_OBJ:
- return OLST_EXPR;
- case CURVE_OBJ:
- return CURVE_EXPR;
- case SURFACE_OBJ:
- return SURFACE_EXPR;
- case UNDEF_OBJ:
- IPGlblEvalError = IE_ERR_UNDEF_OBJECT;
- strcpy(IPGlblCharData, Root->U.PObj->Name);
- return ERROR_EXPR;
- }
- IPGlblEvalError = IE_ERR_FATAL_ERROR;
- sprintf(IPGlblCharData, "Object = %s, Type %d",
- Root->U.PObj->Name, Root->U.PObj->ObjType);
- return ERROR_EXPR;
- case STRING:
- return STRING_EXPR;
- default: /* Should never happen. */
- IPGlblEvalError = IE_ERR_FATAL_ERROR;
- UpdateCharError("Token ", Root->NodeKind);
- return ERROR_EXPR;
- }
- }
-
- /* Disable the function with no prototype warning on Borland's compilers. */
- #ifdef __BORLANDC__
- #pragma warn -pro
- #endif /* __BORLANDC__ */
-
- /*****************************************************************************
- * Routine to evaluate a value of a given tree root and parameter. *
- * Note we change the tree itself during the evaluation process. *
- * Also note we assume the tree is type checked (via InptPrsrTypeCheck rtn). *
- *****************************************************************************/
- ParseTree *InptPrsrEvalTree(ParseTree *Root, int Level)
- {
- char *ErrorMsg;
- RealType R;
- ParseTree *TempL, *TempR, *Params[5];
- PolygonStruct *PPoly;
- ObjectStruct *PObj;
-
- 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 (!FetchParameters(Root, 1, Level, Params)) return NULL;
- /* Use table entries to call the function directly. */
- Root->U.R = (NumFuncTable[Root->NodeKind-NUM_FUNC_OFFSET].Func)
- (Params[0]->U.R);
- Root->ObjType = NUMERIC_OBJ;
- if (RetrieveMathError()) return NULL;
- return Root;
-
- case CPOLY:
- case AREA:
- case VOLUME:
- if (!FetchParameters(Root, 1, Level, Params)) return NULL;
- /* Use table entries to call the function directly. */
- Root->U.R = (NumFuncTable[Root->NodeKind-NUM_FUNC_OFFSET].Func)
- (Params[0]->U.PObj);
- Root->ObjType = NUMERIC_OBJ;
- if (RetrieveMathError()) return NULL;
- return Root;
-
- case ARCTAN2: /* Real return functions with two real parameters. */
- if (!FetchParameters(Root, 2, Level, Params)) return NULL;
- /* Use table entries to call the function directly. */
- Root->U.R = (NumFuncTable[Root->NodeKind-NUM_FUNC_OFFSET].Func)
- (Params[0]->U.R, Params[1]->U.R);
- Root->ObjType = NUMERIC_OBJ;
- if (RetrieveMathError()) return NULL;
- return Root;
-
- case VECTOR: /* Object return functions with three real parameters. */
- if (!FetchParameters(Root, 3, Level, Params)) return NULL;
- /* Use table entries to call the function directly. */
- Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
- ("", &Params[0]->U.R, &Params[1]->U.R, &Params[2]->U.R, NULL);
- Root->ObjType = Root -> U.PObj -> ObjType;
- return Root;
-
- case CTLPT:
- case LIST:
- /* Use table entries to call the function directly. */
- Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
- (Root -> Right);
- if (Root->U.PObj == NULL) return NULL;
- Root->ObjType = Root -> U.PObj -> ObjType;
- return Root;
-
- case ROTX:
- case ROTY:
- case ROTZ:
- if (!FetchParameters(Root, 1, Level, Params)) return NULL;
- /* Use table entries to call the function directly. */
- Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
- (&Params[0]->U.R);
- if (RetrieveMathError()) return NULL;
- Root->ObjType = Root -> U.PObj -> ObjType;
- return Root;
-
- case TRANS:
- case SCALE:
- if (!FetchParameters(Root, 1, Level, Params)) return NULL;
- /* Use table entries to call the function directly. */
- Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
- (Params[0]->U.PObj->U.Vec);
- if (RetrieveMathError()) return NULL;
- Root->ObjType = Root -> U.PObj -> ObjType;
- return Root;
-
- case BOX:
- if (!FetchParameters(Root, 4, Level, Params)) return NULL;
- /* Use table entries to call the function directly. */
- Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
- (Params[0]->U.PObj->U.Vec, &Params[1]->U.R, &Params[2]->U.R,
- &Params[3]->U.R);
- Root->ObjType = Root -> U.PObj -> ObjType;
- return Root;
-
- case GBOX:
- if (!FetchParameters(Root, 4, Level, Params)) return NULL;
- /* Use table entries to call the function directly. */
- Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
- (Params[0]->U.PObj->U.Vec, Params[1]->U.PObj ->U.Vec,
- Params[2]->U.PObj->U.Vec, Params[3]->U.PObj ->U.Vec);
- Root->ObjType = Root -> U.PObj -> ObjType;
- return Root;
-
- case CONE:
- case CYLIN:
- case CIRCPOLY:
- if (!FetchParameters(Root, 3, Level, Params)) return NULL;
- /* Use table entries to call the function directly. */
- Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
- (Params[0]->U.PObj->U.Vec, Params[1]->U.PObj->U.Vec,
- &Params[2]->U.R);
- Root->ObjType = Root -> U.PObj -> ObjType;
- return Root;
-
- case SPHERE:
- case CIRCLE:
- if (!FetchParameters(Root, 2, Level, Params)) return NULL;
- /* Use table entries to call the function directly. */
- Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
- (Params[0]->U.PObj->U.Vec, &Params[1]->U.R);
- Root->ObjType = Root -> U.PObj -> ObjType;
- return Root;
-
- case TORUS:
- case CONE2:
- if (!FetchParameters(Root, 4, Level, Params)) return NULL;
- /* Use table entries to call the function directly. */
- Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
- (Params[0]->U.PObj->U.Vec, Params[1]->U.PObj->U.Vec,
- &Params[2]->U.R, &Params[3]->U.R);
- Root->ObjType = Root -> U.PObj -> ObjType;
- return Root;
-
- case SEVAL:
- case SNORMAL:
- if (!FetchParameters(Root, 3, Level, Params)) return NULL;
- /* Use table entries to call the function directly. */
- Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
- (Params[0]->U.PObj, &Params[1]->U.R, &Params[2]->U.R);
- if (Root->U.PObj == NULL) return NULL;
- Root->ObjType = Root -> U.PObj -> ObjType;
- return Root;
-
- case STANGENT:
- case SREGION:
- if (!FetchParameters(Root, 4, Level, Params)) return NULL;
- /* Use table entries to call the function directly. */
- Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
- (Params[0]->U.PObj, &Params[1]->U.R,
- &Params[2]->U.R, &Params[3]->U.R);
- if (Root->U.PObj == NULL) return NULL;
- Root->ObjType = Root -> U.PObj -> ObjType;
- return Root;
-
- case CDIVIDE:
- case CEVAL:
- case CTANGENT:
- case CRAISE:
- case OFFSET:
- if (!FetchParameters(Root, 2, Level, Params)) return NULL;
- /* Use table entries to call the function directly. */
- Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
- (Params[0]->U.PObj, &Params[1]->U.R);
- if (Root->U.PObj == NULL) return NULL;
- Root->ObjType = Root -> U.PObj -> ObjType;
- return Root;
-
- case SREFINE:
- if (!FetchParameters(Root, 4, Level, Params)) return NULL;
- /* Use table entries to call the function directly. */
- Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
- (Params[0]->U.PObj, &Params[1]->U.R,
- &Params[2]->U.R, Params[3]->U.PObj);
- if (Root->U.PObj == NULL) return NULL;
- Root->ObjType = Root -> U.PObj -> ObjType;
- return Root;
-
- case CREFINE:
- if (!FetchParameters(Root, 3, Level, Params)) return NULL;
- /* Use table entries to call the function directly. */
- Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
- (Params[0]->U.PObj, &Params[1]->U.R, Params[2]->U.PObj);
- if (Root->U.PObj == NULL) return NULL;
- Root->ObjType = Root -> U.PObj -> ObjType;
- return Root;
-
- case SDIVIDE:
- case SRAISE:
- case CSURFACE:
- case CREGION:
- if (!FetchParameters(Root, 3, Level, Params)) return NULL;
- /* Use table entries to call the function directly. */
- Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
- (Params[0]->U.PObj, &Params[1]->U.R, &Params[2]->U.R);
- if (Root->U.PObj == NULL) return NULL;
- Root->ObjType = Root -> U.PObj -> ObjType;
- return Root;
-
- case CMESH:
- if (!FetchParameters(Root, 3, Level, Params)) return NULL;
- /* Use table entries to call the function directly. */
- Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
- (Params[0]->U.PObj,
- &Params[1]->U.R, &Params[2]->U.R);
- if (Root->U.PObj == NULL) return NULL;
- Root->ObjType = Root -> U.PObj -> ObjType;
- return Root;
-
- case NTH:
- if (!FetchParameters(Root, 2, Level, Params)) return NULL;
- /* Use table entries to call the function directly. */
- Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
- (Params[0]->U.PObj, &Params[1]->U.R);
- if (Root->U.PObj == NULL) return NULL;
-
- if (IS_NUM_OBJ(Root->U.PObj)) {
- Root->ObjType = NUMERIC_OBJ;
- MyFree((char *) Root->U.PObj, ALLOC_OBJECT);
- Root->U.R = Root->U.PObj->U.R;
- Root->NodeKind = NUMBER; /* Disconnect the var. binding. */
- return Root;
- }
- else {
- Root->ObjType = Root->U.PObj->ObjType;
- /* Since at this point, no one is pointing on it: */
- Root->U.PObj->Count = 0;
- return Root;
- }
-
- case POLY:
- case SBEZIER:
- case CBEZIER:
- case SURFREV:
- case CONVEX:
- case GPOLYGON:
- case GPOLYLINE:
- case SFROMCRVS:
- case MERGEPOLY:
- if (!FetchParameters(Root, 1, Level, Params)) return NULL;
- /* Use table entries to call the function directly. */
- Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
- (Params[0]->U.PObj);
- if (Root->U.PObj == NULL) return NULL;
- Root->ObjType = Root -> U.PObj -> ObjType;
- return Root;
-
- case CBSPLINE:
- if (!FetchParameters(Root, 3, Level, Params)) return NULL;
- /* Use table entries to call the function directly. */
- Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
- (&Params[0]->U.R, Params[1]->U.PObj, Params[2]->U.PObj);
- if (Root->U.PObj == NULL) return NULL;
- Root->ObjType = Root -> U.PObj -> ObjType;
- return Root;
-
- case SBSPLINE:
- if (!FetchParameters(Root, 4, Level, Params)) return NULL;
- /* Use table entries to call the function directly. */
- Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
- (&Params[0]->U.R, &Params[1]->U.R,
- Params[2]->U.PObj, Params[3]->U.PObj);
- if (Root->U.PObj == NULL) return NULL;
- Root->ObjType = Root -> U.PObj -> ObjType;
- return Root;
-
- case CROSSEC:
- if (!FetchParameters(Root, 1, Level, Params)) return NULL;
- Root->ObjType = POLY_OBJ;
- /* Use table entries to call the function directly. */
- if (IS_POLY_OBJ(Params[0] -> U.PObj))
- Root->U.PObj =
- (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
- (Params[0]->U.PObj);
- else
- Root->U.PObj =
- (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)(NULL);
- if (Root->U.PObj == NULL) return NULL;
- return Root;
-
- case EXTRUDE:
- if (!FetchParameters(Root, 2, Level, Params)) return NULL;
- /* Use table entries to call the function directly. */
- Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
- (Params[0]->U.PObj, Params[1]->U.PObj->U.Vec);
- if (Root->U.PObj == NULL) return NULL;
- Root->ObjType = Root -> U.PObj -> ObjType;
- return Root;
-
- case RULEDSRF:
- if (!FetchParameters(Root, 2, Level, Params)) return NULL;
- /* Use table entries to call the function directly. */
- Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
- (Params[0]->U.PObj, Params[1]->U.PObj);
- if (Root->U.PObj == NULL) return NULL;
- Root->ObjType = Root -> U.PObj -> ObjType;
- return Root;
-
- case BOOLSUM:
- if (!FetchParameters(Root, 4, Level, Params)) return NULL;
- /* Use table entries to call the function directly. */
- Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
- (Params[0]->U.PObj, Params[1]->U.PObj,
- Params[2]->U.PObj, Params[3]->U.PObj);
- if (Root->U.PObj == NULL) return NULL;
- Root->ObjType = Root -> U.PObj -> ObjType;
- return Root;
-
- case CEDITPT:
- if (!FetchParameters(Root, 3, Level, Params)) return NULL;
- /* Use table entries to call the function directly. */
- Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
- (Params[0]->U.PObj, Params[1]->U.PObj,
- &Params[2]->U.R);
- if (Root->U.PObj == NULL) return NULL;
- Root->ObjType = Root -> U.PObj -> ObjType;
- return Root;
-
- case SEDITPT:
- if (!FetchParameters(Root, 4, Level, Params)) return NULL;
- /* Use table entries to call the function directly. */
- Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
- (Params[0]->U.PObj, Params[1]->U.PObj,
- &Params[2]->U.R, &Params[3]->U.R);
- if (Root->U.PObj == NULL) return NULL;
- Root->ObjType = Root -> U.PObj -> ObjType;
- return Root;
-
- case ARC:
- if (!FetchParameters(Root, 3, Level, Params)) return NULL;
- /* Use table entries to call the function directly. */
- Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
- (Params[0]->U.PObj->U.Vec, Params[1]->U.PObj->U.Vec,
- Params[2]->U.PObj->U.Vec);
- if (Root->U.PObj == NULL) return NULL;
- Root->ObjType = Root -> U.PObj -> ObjType;
- return Root;
-
- case SWEEPSRF:
- if (!FetchParameters(Root, 3, Level, Params)) return NULL;
- /* Use table entries to call the function directly. */
- if (IS_NUM_NODE(Params[2])) {
- Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
- (Params[0]->U.PObj, Params[1]->U.PObj, NULL,
- &Params[2]->U.R);
- }
- else {
- R = 1.0;
- Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
- (Params[0]->U.PObj, Params[1]->U.PObj, Params[2]->U.PObj,
- &R);
- }
- if (Root->U.PObj == NULL) return NULL;
- Root->ObjType = Root -> U.PObj -> ObjType;
- return Root;
-
- case LOAD:
- if (!FetchParameters(Root, 1, Level, Params)) return NULL;
- /* Use table entries to call the function directly. */
- Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
- (Params[0]->U.PObj->U.Str, "");
- if (Root->U.PObj == NULL) {
- DataPrsrParseError(&ErrorMsg);
- IPGlblEvalError = IE_ERR_DATA_PRSR_ERROR;
- strcpy(IPGlblCharData, ErrorMsg);
- return NULL;
- }
- Root->ObjType = Root -> U.PObj -> ObjType;
- return Root;
-
- case SNOC:
- if (!FetchParameters(Root, 2, Level, Params)) return NULL;
-
- if (Params[0]->ObjType == NUMERIC_OBJ) {
- PObj = GenNumObject("", &Params[0]->U.R, NULL);
- /* Use table entries to call the function directly. */
- (GenFuncTable[Root->NodeKind-GEN_FUNC_OFFSET].Func)
- (PObj, Params[1]->U.PObj);
- MyFree((char *) PObj, ALLOC_OBJECT);
- }
- else {
- /* Use table entries to call the function directly. */
- (GenFuncTable[Root->NodeKind-GEN_FUNC_OFFSET].Func)
- (Params[0]->U.PObj, Params[1]->U.PObj);
- }
- Root->ObjType = UNDEF_OBJ;
- return Root;
-
- case VIEW:
- case INTERACT:
- if (!FetchParameters(Root, 2, Level, Params)) return NULL;
- Root->ObjType = UNDEF_OBJ;
- /* Use table entries to call the function directly. */
- (GenFuncTable[Root->NodeKind-GEN_FUNC_OFFSET].Func)
- (Params[0]->U.PObj, &Params[1]->U.R);
- return Root;
-
- case COLOR:
- if (!FetchParameters(Root, 2, Level, Params)) return NULL;
- Root->ObjType = UNDEF_OBJ;
- /* Use table entries to call the function directly. */
- (GenFuncTable[Root->NodeKind-GEN_FUNC_OFFSET].Func)
- (Params[0]->U.PObj, REAL_TO_INT(Params[1]->U.R));
- return Root;
-
- case EXIT:
- /* Yes - we finished for today... */
- (GenFuncTable[Root->NodeKind-GEN_FUNC_OFFSET].Func)(0);
-
- case PAUSE:
- case LOGFILE:
- case CLOSED:
- if (!FetchParameters(Root, 1, Level, Params)) return NULL;
- /* Use table entries to call the function directly. */
- (GenFuncTable[Root->NodeKind-GEN_FUNC_OFFSET].Func)
- (&Params[0] -> U.R);
- Root->ObjType = UNDEF_OBJ;
- return Root;
-
- case VARLIST:
- case SYSTEM:
- /* Use table entries to call the function directly. */
- (GenFuncTable[Root->NodeKind-GEN_FUNC_OFFSET].Func)(GlblObjList);
- Root->ObjType = UNDEF_OBJ;
- return Root;
-
- case DIR:
- case CHDIR:
- case INCLUDE:
- case PRHELP:
- case EDIT:
- if (!FetchParameters(Root, 1, Level, Params)) return NULL;
- /* Use table entries to call the function directly. */
- (GenFuncTable[Root->NodeKind-GEN_FUNC_OFFSET].Func)
- (Params[0]->U.PObj->U.Str);
- Root->ObjType = UNDEF_OBJ;
- return Root;
-
- case SAVE:
- if (!FetchParameters(Root, 2, Level, Params)) return NULL;
- if (Params[1]->ObjType == NUMERIC_OBJ) {
- PObj = GenNumObject("", &Params[1]->U.R, NULL);
- /* Use table entries to call the function directly. */
- (GenFuncTable[Root->NodeKind-GEN_FUNC_OFFSET].Func)
- (Params[0]->U.PObj->U.Str, PObj);
- MyFree((char *) PObj, ALLOC_OBJECT);
- }
- else {
- /* Use table entries to call the function directly. */
- (GenFuncTable[Root->NodeKind-GEN_FUNC_OFFSET].Func)
- (Params[0]->U.PObj->U.Str, Params[1]->U.PObj);
- }
-
- if (DataPrsrParseError(&ErrorMsg) != 0) {
- IPGlblEvalError = IE_ERR_DATA_PRSR_ERROR;
- strcpy(IPGlblCharData, ErrorMsg);
- return NULL;
- }
- Root->ObjType = UNDEF_OBJ;
- return Root;
-
- case BEEP:
- if (!FetchParameters(Root, 2, Level, Params)) return NULL;
- /* Use table entries to call the function directly. */
- (GenFuncTable[Root->NodeKind-GEN_FUNC_OFFSET].Func)
- (REAL_TO_INT(Params[0]->U.R), REAL_TO_INT(Params[1]->U.R));
- Root->ObjType = UNDEF_OBJ;
- return Root;
-
- case ALIAS:
- if (!FetchParameters(Root, 2, Level, Params)) return NULL;
- /* Use table entries to call the function directly. */
- (GenFuncTable[Root->NodeKind-GEN_FUNC_OFFSET].Func)
- (Params[0]->U.PObj->U.Str, Params[1]->U.PObj->U.Str);
- Root->ObjType = UNDEF_OBJ;
- return Root;
-
- case ATTRIB:
- if (!FetchParameters(Root, 3, Level, Params)) return NULL;
- /* Use table entries to call the function directly. */
- (GenFuncTable[Root->NodeKind-GEN_FUNC_OFFSET].Func)
- (Params[0]->U.PObj,
- Params[1]->U.PObj->U.Str, Params[2]->U.PObj->U.Str);
- Root->ObjType = UNDEF_OBJ;
- return Root;
-
- case FREEOBJ:
- if (!FetchParameters(Root, 1, Level, Params)) return NULL;
- if ((TempR = InptPrsrEvalTree(Root->Right, Level+1)) == NULL)
- return NULL;
- if (TempR->ObjType == NUMERIC_OBJ) {
- IPGlblEvalError = IE_ERR_TYPE_MISMATCH;
- strcpy(IPGlblCharData, "Func FREE, parameter 1");
- return Root;
- }
- if (strlen(TempR->U.PObj->Name) == 0) {
- IPGlblEvalError = IE_ERR_FREE_SIMPLE;
- UpdateCharError("Procedure ", FREEOBJ);
- return Root;
- }
- /* Use table entries to call the function directly. */
- (GenFuncTable[Root->NodeKind-GEN_FUNC_OFFSET].Func)
- (TempR->U.PObj);
- Root->ObjType = UNDEF_OBJ;
- TempR->U.PObj = NULL; /* Make sure its disconnected... */
- return Root;
-
- case NORMAL:
- if (!FetchParameters(Root, 3, Level, Params)) return NULL;
- /* Use table entries to call the function directly. */
- (GenFuncTable[Root->NodeKind-GEN_FUNC_OFFSET].Func)
- (&Params[0]->U.R, &Params[1]->U.R, &Params[2]->U.R);
- Root->ObjType = UNDEF_OBJ;
- return Root;
-
- case IFCOND:
- IfCondition(FetchParameter(Root->Right, 0, 4),
- FetchParameter(Root->Right, 1, 4),
- FetchParameter(Root->Right, 2, 4),
- FetchParameter(Root->Right, 3, 4));
- Root->ObjType = UNDEF_OBJ;
- return Root;
-
- case FORLOOP:
- ForLoop(FetchParameter(Root->Right, 0, 4),
- FetchParameter(Root->Right, 1, 4),
- FetchParameter(Root->Right, 2, 4),
- FetchParameter(Root->Right, 3, 4));
- Root->ObjType = UNDEF_OBJ;
- return Root;
-
- 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))
- return NULL;
- TempR = OverLoadEvalOper(Root, TempR, TempL,
- &IPGlblEvalError, IPGlblCharData);
- if (RetrieveMathError())
- return NULL;
- else
- return TempR;
-
- case UNARMINUS:
- if ((TempR = InptPrsrEvalTree(Root->Right, Level+1)) == NULL)
- return NULL;
- TempR = OverLoadEvalOper(Root, TempR, NULL,
- &IPGlblEvalError, IPGlblCharData);
- if (RetrieveMathError())
- return NULL;
- else
- return TempR;
-
- case NUMBER:
- Root->ObjType = NUMERIC_OBJ;
- return Root;
-
- case PARAMETER:
- if (Level == 0) { /* If only object - print its content. */
- Root->U.PObj->Count--; /* Remove reference from this tree. */
- PrintObject(Root->U.PObj);
- Root->U.PObj->Count++; /* Add reference back. */
- Root->ObjType = Root->U.PObj->ObjType;
- return Root;
- }
- if (IS_NUM_OBJ(Root->U.PObj)) {
- Root->ObjType = NUMERIC_OBJ;
- Root->U.PObj->Count--;
- Root->U.R = Root->U.PObj->U.R;
- Root->NodeKind = NUMBER; /* Disconnect the var. binding. */
- return Root;
- }
- else {
- Root->ObjType = Root->U.PObj->ObjType;
- return Root;
- }
-
- case STRING:
- Root->ObjType = STRING_OBJ;
- return Root;
-
- case EQUAL:
- if ((TempR = InptPrsrEvalTree(Root->Right, Level+1)) == NULL)
- return NULL;
- TempL = Root->Left;
- PPoly = NULL;
- if (IS_UNDEF_OBJ(TempL->U.PObj)) /* Its new object. */
- InsertObject(TempL->U.PObj); /* Insert to global vars. */
- else if (IS_POLY_OBJ(TempL->U.PObj)) /* If old var. was poly. */
- PPoly = TempL->U.PObj->U.Pl.P;
-
- if (IS_NUM_NODE(TempR)) {
- TempL->ObjType = TempL->U.PObj->ObjType = NUMERIC_OBJ;
- TempL->U.PObj->U.R = TempR->U.R;
- }
- else {
- if (TempL -> U.PObj == TempR -> U.PObj) return TempR;/* A=A. */
- TempL->ObjType = TempR->ObjType;
- CopyObject(TempL->U.PObj, TempR->U.PObj, FALSE);
- }
- if (PPoly != NULL) MyFree((char *) (PPoly), ALLOC_POLYGON);
-
- Root->ObjType = UNDEF_OBJ;
- return TempR;
- }
- return NULL; /* Makes warning silent. */
- }
-
- /* Restore the function with no prototype warning on Borland's compilers. */
- #ifdef __BORLANDC__
- #pragma warn .pro
- #endif /* __BORLANDC__ */
-
- /*****************************************************************************
- * Routine to print help on the given subject HelpHeader. *
- * Note a match is if the HelpHeader in prefix of help file line. *
- *****************************************************************************/
- static void PrintHelp(char *HelpHeader)
- {
- int i;
- char *Path, s[LINE_LEN];
- FILE *f;
-
- Path = searchpath(GlblHelpFileName);
-
- if (strlen(HelpHeader) == 0)
- HelpHeader = "Commands"; /* Print a list of all commands. */
-
- if ((f = fopen(Path, "r")) == NULL) {
- sprintf(s, "Cannot open help file \"%s\".\n", GlblHelpFileName);
- WndwInputWindowPutStr(s);
- return;
- }
-
- for (i = 0; i < (int) strlen(HelpHeader); i++)
- if (islower(HelpHeader[i])) HelpHeader[i] = toupper(HelpHeader[i]);
-
- while (fgets(s, LINE_LEN-1, f) != NULL) {
- if (strncmp(HelpHeader, s, strlen(HelpHeader)) == 0) {
- /* Found match - print it. */
- while (fgets(s, LINE_LEN-1, f) != NULL && s[0] != '$') {
- WndwInputWindowPutStr(&s[1]); /* Skip char 1. */
- }
- fclose(f);
- return;
- }
- }
-
- fclose(f);
-
- sprintf(s, "No help on %s\n", HelpHeader);
- WndwInputWindowPutStr(s);
- }
-
- /*****************************************************************************
- * Routine to execute the IF structure. *
- *****************************************************************************/
- static void IfCondition(ParseTree *Left, ParseTree *Cond, ParseTree *Right,
- ParseTree *PBody)
- {
- int i, NumOfExpr;
- RealType L, R;
- char *Str;
-
- Left = InptPrsrEvalTree(Left, 1);
- Cond = InptPrsrEvalTree(Cond, 1);
- Right = InptPrsrEvalTree(Right, 1);
-
- L = Left->U.R;
- Str = Cond->U.PObj->U.Str;
- R = Right->U.R;
-
- if ((strcmp(Str, "=") == 0 && L == R) ||
- (strcmp(Str, "<>") == 0 && L != R) ||
- (strcmp(Str, "<=") == 0 && L <= R) ||
- (strcmp(Str, ">=") == 0 && L >= R) ||
- (strcmp(Str, ">") == 0 && L > R) ||
- (strcmp(Str, "<") == 0 && L < R)) {
- /* If we are here, then the condition holds: */
- for (i = 0; i < (NumOfExpr = CountNumExpressions(PBody)); i++) {
- InptPrsrEvalTree(FetchExpression(PBody, i, NumOfExpr), 0);
- if (GlblWasCtrlBrk || /* async. break send from the user. */
- IPGlblEvalError) break;
- }
- }
- }
-
- /*****************************************************************************
- * Routine to execute the FOR structure loop. *
- * Note that as InptPrsrEvalTree routine is destructive on its input tree, *
- * we must make a copy of the body before executing it! *
- * We wish we could access the loop variable directly, but the user might *
- * be stupid and free it in the loop - so me must access it by name. *
- *****************************************************************************/
- static void ForLoop(ParseTree *PStart, ParseTree *PInc, ParseTree *PEnd,
- ParseTree *PBody)
- {
- int i, NumOfExpr, LoopCount;
- char *LoopVarName = NULL;
- RealType LoopVar, StartVal, Increment, EndVal;
- ParseTree *PTemp;
- ObjectStruct *PLoopVar;
-
- /* Find the only two cases where loop variable is allowed - when then */
- /* given starting value is a parameter, or assignment to parameter... */
- if (PStart -> NodeKind == PARAMETER)
- LoopVarName = PStart -> U.PObj -> Name;
- else if (PStart -> NodeKind == EQUAL &&
- PStart -> Left -> NodeKind == PARAMETER) {
- LoopVarName = PStart -> Left -> U.PObj -> Name;
- /* Rebind the iteration variable to body - it might be new: */
- RebindVariable(PBody, PStart -> Left -> U.PObj);
- if (GetObject(LoopVarName) == NULL) /* It is really new. */
- PStart -> Left -> U.PObj -> Count++;
- }
-
- PStart = InptPrsrEvalTree(PStart, 1); /* Evaluate starting value. */
- PInc = InptPrsrEvalTree(PInc, 1); /* Evaluate increment value. */
- PEnd = InptPrsrEvalTree(PEnd, 1); /* Evaluate end value. */
- if (IPGlblEvalError ||
- PStart == NULL || PInc == NULL || PEnd == NULL) return;
- StartVal = PStart -> U.R;
- Increment = PInc -> U.R;
- EndVal = PEnd -> U.R;
-
- NumOfExpr = CountNumExpressions(PBody); /* Num. of expr. in the body. */
- for (LoopVar = StartVal, LoopCount = 0;
- APX_EQ(LoopVar, EndVal) ||
- (Increment > 0 ? LoopVar <= EndVal : LoopVar >= EndVal);
- LoopVar += Increment, LoopCount++) {
- if (GlblWasCtrlBrk || /* Async. break send from the user. */
- IPGlblEvalError || GlblFatalError) return;
- if (LoopVarName != NULL) {
- if ((PLoopVar = GetObject(LoopVarName)) != NULL &&
- IS_NUM_OBJ(PLoopVar))
- PLoopVar -> U.R = LoopVar; /* Update loop var. */
- else {
- IPGlblEvalError = IE_ERR_MODIF_ITER_VAR;
- strcpy(IPGlblCharData, LoopVarName);
- }
- }
-
- for (i = 0; i < NumOfExpr; i++) {
- PTemp = FetchExpression(PBody, i, NumOfExpr);
- if (LoopCount == 0 && InptPrsrTypeCheck(PTemp, 0) == ERROR_EXPR)
- return;
- else {
- if (LoopVar == EndVal) {
- /* Use the original tree. Note we must evaluate the */
- /* original tree at least once as ObjType's are updated. */
- InptPrsrEvalTree(PTemp, 0); /* Eval as its top level... */
- }
- else {
- PTemp = InptPrsrCopyTree(PTemp);
- InptPrsrEvalTree(PTemp, 0); /* Eval as its top level... */
- InptPrsrFreeTree(PTemp); /* Not needed any more. */
- }
- }
- }
- }
- }
-
- /*****************************************************************************
- * Routine to create an OBJECT LIST object out of all parameters. *
- *****************************************************************************/
- static ObjectStruct *GenObjectList(ParseTree *PObjParams)
- {
- int i, NumOfParams;
- ParseTree *Param;
- ObjectStruct *PObj;
-
- NumOfParams = CountNumParameters(PObjParams);
- if (NumOfParams > MAX_OBJ_LIST) {
- IPGlblEvalError = IE_ERR_LIST_TOO_LONG;
- return NULL;
- }
-
- PObj = AllocObject("", OBJ_LIST_OBJ, NULL);
-
- for (i = 0; i < NumOfParams; i++) {
- if ((Param = InptPrsrEvalTree(FetchParameter(PObjParams, i,
- NumOfParams),
- 1)) == NULL) {
- MyFree((char *) PObj, ALLOC_OBJECT);
- return NULL;
- }
- if (Param -> NodeKind == NUMBER ||
- (Param -> NodeKind == UNARMINUS &&
- Param -> ObjType == NUMERIC_OBJ)) {
- /* This is a special case in which the data is saved in parse */
- /* tree instead of as an underneath object - make an object! */
- PObj -> U.PObjList[i] = AllocObject("", NUMERIC_OBJ, NULL);
- PObj -> U.PObjList[i] -> U.R = Param -> U.R;
- }
- else {
- if (Param -> U.PObj -> ObjType == UNDEF_OBJ) {
- IPGlblEvalError = IE_ERR_UNDEF_OBJECT;
- strcpy(IPGlblCharData, Param -> U.PObj -> Name);
- PObj -> U.PObjList[i] = NULL;
- MyFree((char *) PObj, ALLOC_OBJECT);
- return NULL;
- }
-
- PObj -> U.PObjList[i] = Param -> U.PObj;
- Param -> U.PObj -> Count++; /* Increase number of references. */
- }
- }
-
- if (NumOfParams < MAX_OBJ_LIST) PObj -> U.PObjList[NumOfParams] = NULL;
- return PObj;
- }
-
- /*****************************************************************************
- * Routine to create an Control Point Object out of all parameters. *
- *****************************************************************************/
- static ObjectStruct *CtlPtFromParams(ParseTree *PObjParams)
- {
- int i, NumPts, NumOfParams, PtType,
- CoordCount = 0;
- ParseTree *Param;
- ObjectStruct *PObj;
-
- NumOfParams = CountNumParameters(PObjParams);
-
- PObj = AllocObject("", CTLPT_OBJ, NULL);
-
- for (i = 0; i < NumOfParams; i++) {
- if ((Param = InptPrsrEvalTree(FetchParameter(PObjParams, i,
- NumOfParams),
- 1)) == NULL) {
- MyFree((char *) PObj, ALLOC_OBJECT);
- return NULL;
- }
- if (Param -> ObjType != NUMERIC_OBJ) {
- IPGlblEvalError = IE_ERR_TYPE_MISMATCH;
- strcpy(IPGlblCharData, "Numeric data expected");
- MyFree((char *) PObj, ALLOC_OBJECT);
- return NULL;
- }
-
- if (i == 0) {
- PtType = PObj -> U.CtlPt.PtType = (CagdPointType) Param -> U.R;
- switch (PtType) {
- case CAGD_PT_E2_TYPE:
- NumPts = 2;
- CoordCount = 1;
- break;
- case CAGD_PT_E3_TYPE:
- NumPts = 3;
- CoordCount = 1;
- break;
- case CAGD_PT_P2_TYPE:
- NumPts = 3;
- break;
- case CAGD_PT_P3_TYPE:
- NumPts = 4;
- break;
- default:
- IPGlblEvalError = IE_ERR_TYPE_MISMATCH;
- strcpy(IPGlblCharData, "E2, E3, P2, P3 expected");
- MyFree((char *) PObj, ALLOC_OBJECT);
- return NULL;
- }
- if (NumOfParams - 1 != NumPts) {
- IPGlblEvalError = IE_ERR_NUM_PRM_MISMATCH;
- sprintf(IPGlblCharData, "%d expected", NumPts);
- MyFree((char *) PObj, ALLOC_OBJECT);
- return NULL;
- }
- }
- else
- PObj -> U.CtlPt.Coords[CoordCount++] = Param -> U.R;
- }
-
- return PObj;
- }
-
- /*****************************************************************************
- * Routine to count number of expressions seperated by a COLON are given *
- * in the tree ROOT. This routine is similar to CountNumParameters below. *
- *****************************************************************************/
- static int CountNumExpressions(ParseTree *Root)
- {
- int i=1;
-
- while (Root->NodeKind == COLON) {
- i++;
- Root = Root->Right;
- }
- return i;
- }
-
- /*****************************************************************************
- * Routine to fetch the i expression out of a tree represent n expressions *
- * (0 <= i < n) seperated by colonc. Similar to FetchParameter routine below. *
- *****************************************************************************/
- static ParseTree *FetchExpression(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;
- }
-
- /*****************************************************************************
- * Routine to retrieve math error if was one. return TRUE if was error. *
- *****************************************************************************/
- static int RetrieveMathError(void)
- {
- int Error;
- char *FuncName, *p;
-
- #ifdef __MSDOS__
- if ((Error = MathError(&FuncName)) != 0) {
- switch (Error) {
- case DOMAIN:
- p = "DOMAIN";
- break;
- case SING:
- p = "SING";
- break;
- case OVERFLOW:
- p = "O.F.";
- break;
- case UNDERFLOW:
- p = "U.F.";
- break;
- case TLOSS:
- p = "TLOSS";
- break;
- default:
- p = "Undef.";
- break;
- }
- strcpy(IPGlblCharData, p);
- strcat(IPGlblCharData, " error - func. ");
- strcat(IPGlblCharData, FuncName);
- IPGlblEvalError = IE_ERR_FP_ERROR;
- return TRUE;
- }
- #endif /* __MSDOS__ */
-
- return FALSE;
- }
-
- /*****************************************************************************
- * Routine to count number of parameters where given: parameters are defined *
- * as subtrees seperated by commas, i.e.: the infix form 1, 2, 3, 4 is *
- * represented as [1, [2, [3, 4]]] in the tree supplied to this function and *
- * 4 (number of parameters) is returned. *
- *****************************************************************************/
- static int CountNumParameters(ParseTree *Root)
- {
- int i = 1;
-
- if (Root == NULL) return 0;
-
- while (Root->NodeKind == COMMA) {
- i++;
- Root = Root->Right;
- }
- return i;
- }
-
- /*****************************************************************************
- * Routine to fetch the i paramter out of a tree represent n parameters *
- * (0 <= i < n). See CountNumParameters for more description of structure. *
- * Note it is assumed the tree HAS n parameters and 0<=i<n (No input error). *
- *****************************************************************************/
- static ParseTree *FetchParameter(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;
- }
-
- /*****************************************************************************
- * Routine to fetch the parameters from the parsed tree. *
- * Returns TRUE iff fetching was succesfull. *
- *****************************************************************************/
- static int FetchParameters(ParseTree *Root, int NumParams, int Level,
- ParseTree *Params[])
- {
- int i;
-
- Level++;
- for (i = 0; i < NumParams; i++)
- if ((Params[i] = InptPrsrEvalTree(FetchParameter(Root->Right, i,
- NumParams),
- Level)) == NULL)
- return FALSE;
-
- return TRUE;
- }
-
- /*****************************************************************************
- * Routine to test number of parameters and type of them against what is *
- * defined in its global tables Num/Obj/GenFuncTable. return TRUE if mismatch *
- * was detected: *
- *****************************************************************************/
- static int FuncParamMismatch(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_FUNC: /* 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);
- return TRUE;
- }
-
- if (FuncTable[FuncOffset].NumOfParam == ANY_PARAM_NUM)
- return FALSE;
-
- /* See if number of parameters is ok: */
- if ((Count = CountNumParameters(Root->Right)) !=
- 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 is consistent: */
- for (i = 0; i < Count; i++) {
- if (FuncTable[FuncOffset].ParamObjType[i] != ANY_EXPR &&
- !(FuncTable[FuncOffset].ParamObjType[i] &
- InptPrsrTypeCheck(FetchParameter(Root->Right, i, Count), 1))) {
- sprintf(IPGlblCharData, "Func %s,%sparameter %d",
- FuncTable[FuncOffset].FuncName,
- IPGlblEvalError == IE_ERR_UNDEF_OBJECT ? " undefined " : " ",
- i+1);
- IPGlblEvalError = IE_ERR_TYPE_MISMATCH;
- return TRUE;
- }
- }
- return FALSE;
- }
-
- /*****************************************************************************
- * Routine to free a tree - release all memory allocated by it. *
- *****************************************************************************/
- void InptPrsrFreeTree(ParseTree *Root)
- {
- char s[LINE_LEN];
- int ValidObject;
-
- if (!Root) return;
-
- ValidObject = Root->ObjType != NUMERIC_OBJ && Root->ObjType != UNDEF_OBJ;
-
- if (IS_FUNCTION(Root -> NodeKind)) {
- if (IS_NO_PARAM_FUNC(Root -> NodeKind))
- MyExprFree(Root);
- else {
- InptPrsrFreeTree(Root->Right);
- if (ValidObject && strlen(Root->U.PObj->Name) == 0)
- MyFree((char *) Root->U.PObj, ALLOC_OBJECT); /* Its temp.*/
- MyExprFree(Root);
- }
- return;
- }
-
- switch (Root -> NodeKind) {
- case DIV:
- case MINUS:
- case MULT:
- case PLUS:
- case POWER:
- InptPrsrFreeTree(Root->Right);
- InptPrsrFreeTree(Root->Left);
- if (ValidObject && strlen(Root->U.PObj->Name) == 0)
- MyFree((char *) Root->U.PObj, ALLOC_OBJECT);/* Its temporary.*/
- MyExprFree(Root);
- break;
-
- case UNARMINUS:
- InptPrsrFreeTree(Root->Right);
- if (ValidObject && strlen(Root->U.PObj->Name) == 0)
- MyFree((char *) Root->U.PObj, ALLOC_OBJECT);/* Its temporary.*/
- MyExprFree(Root);
- break;
-
- case COMMA:
- case COLON:
- case EQUAL:
- InptPrsrFreeTree(Root->Right);
- InptPrsrFreeTree(Root->Left);
- MyExprFree(Root);
- break;
-
- case NUMBER:
- MyExprFree(Root);
- break;
-
- case PARAMETER:
- if (Root->U.PObj) {
- /* No assign took place - Its temporary. */
- if ((Root->U.PObj->ObjType == UNDEF_OBJ ||
- strlen(Root->U.PObj->Name) == 0))
- MyFree((char *) Root->U.PObj, ALLOC_OBJECT);
- else
- Root->U.PObj->Count--;
- }
- MyExprFree(Root);
- break;
-
- case STRING:
- MyFree((char *) Root->U.PObj, ALLOC_OBJECT);/* The string object.*/
- MyExprFree(Root);
- break;
-
- case TOKENSTART:
- MyExprFree(Root);
- break;
-
- case OPENPARA:
- case CLOSPARA:
- MyExprFree(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) {
- MyExprFree(Root);
- }
- else {
- sprintf(s, "%s (%d).\n",
- "InptPrsrFreeTree: Undefined ParseTree type to free",
- Root -> NodeKind);
- FatalError(s);
- }
- break;
- }
- }
-
- /*****************************************************************************
- * Routine to print a content of ROOT (using inorder traversal): *
- * level holds: 0 for lowest level +/-, 1 for *, /, 2 for ^ operations. *
- * If *str = NULL print on stderr, else on given string Str. *
- *****************************************************************************/
- 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. */
- }
- }
-
- /*****************************************************************************
- * Routine to print a content of ROOT (using inorder traversal): *
- * level holds: 0 for lowest level +/-, 1 for *, /, 2 for ^ operations. *
- * It is assumed Str has at list LINE_LEN_LONG places to write the expression.*
- *****************************************************************************/
- static void LocalPrintTree(ParseTree *Root, int Level, char *Str)
- {
- int CloseFlag = FALSE, Len, i;
-
- if (!Root) return;
- i = Root->NodeKind / 100;
-
- if ((Len = strlen(Str)) > LINE_LEN_LONG * 2 / 3)/* Prevent from overflow.*/
- if (Str[Len-1] == '.')
- return; /* "..." was allready concatenated. */
- else {
- strcat(Str, "...");
- return;
- }
-
- # ifdef DEBUG
- strcat(Str, "["); /* Usefull to see ALL nestings - no preceedings. */
- # endif /* DEBUG */
-
- switch (i * 100) {
- case NUM_FUNC:
- Level = 0;
- CloseFlag = TRUE;
- strcat(Str, NumFuncTable[Root->NodeKind-NUM_FUNC_OFFSET].FuncName);
- strcat(Str, "(");
- break;
-
- case OBJ_FUNC:
- 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 NUMBER:
- sprintf(&Str[strlen(Str)], "%lg", Root->U.R);
- break;
-
- case PARAMETER:
- sprintf(&Str[strlen(Str)], "%s", Root->U.PObj->Name);
- break;
-
- case STRING:
- sprintf(&Str[strlen(Str)], "\"%s\"", Root->U.PObj->U.Str);
- break;
-
- case OPENPARA:
- strcat(Str, "(");
- break;
-
- case CLOSPARA:
- strcat(Str, ")");
- break;
-
- case TOKENSTART:
- break;
-
- default:
- FatalError("LocalPrintTree: Undefined ParseTree type to print, exit");
- }
- break;
-
- default:
- FatalError("LocalPrintTree: Undefined ParseTree type to print, exit");
- }
- LocalPrintTree(Root->Right, Level, Str);
- if (CloseFlag) strcat(Str, ")");
-
- # ifdef DEBUG
- strcat(Str, "]"); /* Usefull to see ALL nestings - no preceedings. */
- # endif /* DEBUG */
- }
-
- /*****************************************************************************
- * Routine to copy a parse tree - Generate brand new ParseTree structure *
- * but bind to non-temp variables if they are exists - their Name is not NULL *
- * This means that updating these objects in the copied tree, will affect *
- * these objects in the original tree. *
- *****************************************************************************/
- ParseTree *InptPrsrCopyTree(ParseTree *Root)
- {
- ParseTree *NewRoot;
-
- if (Root == NULL) return NULL;
-
- NewRoot = MyExprMalloc();
-
- if (IS_FUNCTION(Root->NodeKind)) { /* All the functions. */
- NewRoot -> NodeKind = Root -> NodeKind;
- NewRoot -> ObjType = Root -> ObjType;
- NewRoot -> Right = InptPrsrCopyTree(Root -> Right);
- return NewRoot;
- }
-
- switch (Root->NodeKind) {
- case DIV:
- case MINUS:
- case MULT:
- case PLUS:
- case POWER:
-
- case COMMA:
- case COLON:
- case EQUAL:
- NewRoot -> NodeKind = Root -> NodeKind;
- NewRoot -> ObjType = Root -> ObjType;
- NewRoot -> Right = InptPrsrCopyTree(Root -> Right);
- NewRoot -> Left = InptPrsrCopyTree(Root -> Left);
- return NewRoot;
-
- case NUMBER:
- NewRoot -> NodeKind = Root -> NodeKind;
- NewRoot -> ObjType = Root -> ObjType;
- NewRoot -> U.R = Root -> U.R;
- return NewRoot;
-
- case PARAMETER:
- case STRING:
- NewRoot -> NodeKind = Root -> NodeKind;
- NewRoot -> ObjType = Root -> ObjType;
- NewRoot -> U.PObj = Root -> U.PObj; /* Point on SAME object. */
- NewRoot -> U.PObj -> Count++; /* But increase its ref. count. */
- return NewRoot;
-
- case TOKENSTART:
- NewRoot -> NodeKind = Root -> NodeKind;
- NewRoot -> ObjType = Root -> ObjType;
- return NewRoot;
-
- default:
- FatalError("InptPrsrCopyTree: Undefined ParseTree type to copy, exit\n");
- }
- return NULL; /* Makes warning silent. */
- }
-
- /*****************************************************************************
- * Routine to rebind a variable - given a tree, scan it and update each *
- * occurance of that variable to point to PObj. *
- *****************************************************************************/
- static void RebindVariable(ParseTree *Root, ObjectStruct *PObj)
- {
- if (Root == NULL) return;
-
- if (IS_FUNCTION(Root->NodeKind)) { /* All the functions. */
- RebindVariable(Root -> Right, PObj);
- return;
- }
-
- switch (Root->NodeKind) {
- case UNARMINUS:
- RebindVariable(Root -> Right, PObj);
- return;
-
- case DIV:
- case MINUS:
- case MULT:
- case PLUS:
- case POWER:
-
- case COMMA:
- case COLON:
- case EQUAL:
- RebindVariable(Root -> Right, PObj);
- RebindVariable(Root -> Left, PObj);
- return;
-
- case NUMBER:
- return;
-
- case PARAMETER:
- case STRING:
- if (strcmp(Root -> U.PObj -> Name, PObj -> Name) == 0) {
- /* I wish I could free that, but nesting loops might try */
- /* to free the same place n times... We will loose this */
- /* variable place if it defined for the first time. Fix */
- /* it if you really care... */
- /*
- if (IS_UNDEF_OBJ(Root -> U.PObj))
- MyFree((char *) Root->U.PObj, ALLOC_OBJECT);
- */
- Root -> U.PObj = PObj;
- }
- return;
-
- case TOKENSTART:
- return;
-
- default:
- FatalError("RebindVariable: Undefined ParseTree type, exit\n");
- }
- }
-
- /*****************************************************************************
- * Routine to return evaluation error if happen one, zero elsewhere *
- *****************************************************************************/
- InptPrsrEvalErrType InptPrsrEvalError(char **Message)
- {
- InptPrsrEvalErrType Temp;
-
- *Message = IPGlblCharData;
- Temp = IPGlblEvalError;
- IPGlblEvalError = IPE_NO_ERR;
-
- return Temp;
- }
-