/*****************************************************************************
*   "Irit" - the 3d (not only polygonal) solid modeller.		     *
*									     *
* Written by:  Gershon Elber				Ver 0.2, Mar. 1990   *
******************************************************************************
* (C) Gershon Elber, Technion, Israel Institute of Technology                *
******************************************************************************
*   General, local to module, definitions for the Input Parser module.	     *
*   Note this module actually consists of InptPrsr/InptEval/OverLoad modules.*
*****************************************************************************/

#ifndef	INPT_PRSR_LH
#define	INPT_PRSR_LH

/* #define DEBUG        Print some intermediate results (InptPrsr/InptEval). */

#define INIT_PARSER_STACK	100	     /* Depth of expression nesting. */

typedef enum {
    POLY_EXPR =     0x00000001,
    NUMERIC_EXPR =  0x00000002,
    POINT_EXPR	=   0x00000004,
    VECTOR_EXPR	=   0x00000008,
    PLANE_EXPR	=   0x00000010,
    MATRIX_EXPR	=   0x00000020,
    CURVE_EXPR =    0x00000040,
    SURFACE_EXPR =  0x00000080,
    STRING_EXPR	=   0x00000100,
    OLST_EXPR =     0x00000200,
    CTLPT_EXPR =    0x00000400,
    TRIMSRF_EXPR =  0x00000800,
    TRIVAR_EXPR =   0x00001000,

    POLY_CURVE_EXPR = POLY_EXPR | CURVE_EXPR,
    GEOM_EXPR =     POINT_EXPR | VECTOR_EXPR | POLY_EXPR | CURVE_EXPR |
		    SURFACE_EXPR | CTLPT_EXPR | TRIMSRF_EXPR | TRIVAR_EXPR,
    OLST_GEOM_EXPR = OLST_EXPR | GEOM_EXPR,
    ANY_EXPR =      POLY_EXPR | NUMERIC_EXPR | POINT_EXPR | VECTOR_EXPR |
    		    PLANE_EXPR | MATRIX_EXPR | CURVE_EXPR | SURFACE_EXPR |
		    STRING_EXPR | OLST_EXPR | CTLPT_EXPR | TRIMSRF_EXPR |
		    TRIVAR_EXPR,

    NO_EXPR =       0x10000000,
    ERROR_EXPR =    0x20000000
} IritExprType;

/*****************************************************************************
* The expression parse tree node definition:				     *
*****************************************************************************/
typedef	struct ParseTree {
    struct ParseTree *Right, *Left;
    int NodeKind;
    IPObjectStruct *PObj;
    struct UserDefinedFuncDefType *UserFunc;
} ParseTree;

/* See also IPObjectStruct structure for the different object possible: */
#define IS_POLY_NODE(Node)	((Node) -> PObj -> ObjType == IP_OBJ_POLY)
#define IS_NUM_NODE(Node)	((Node) -> PObj -> ObjType == IP_OBJ_NUMERIC)
#define IS_PT_NODE(Node)	((Node) -> PObj -> ObjType == IP_OBJ_POINT)
#define IS_VEC_NODE(Node)	((Node) -> PObj -> ObjType == IP_OBJ_VECTOR)
#define IS_PLANE_NODE(Node)	((Node) -> PObj -> ObjType == IP_OBJ_PLANE)
#define IS_CTLPT_NODE(Node)	((Node) -> PObj -> ObjType == IP_OBJ_CTLPT)
#define IS_MAT_NODE(Node)	((Node) -> PObj -> ObjType == IP_OBJ_MATRIX)
#define IS_STR_NODE(Node)	((Node) -> PObj -> ObjType == IP_OBJ_STRING)
#define IS_OLST_NODE(Node)	((Node) -> PObj -> ObjType == IP_OBJ_LIST_OBJ)
#define IS_CRV_NODE(Node)	((Node) -> PObj -> ObjType == IP_OBJ_CURVE)
#define IS_SRF_NODE(Node)	((Node) -> PObj -> ObjType == IP_OBJ_SURFACE)
#define IS_TRIMSRF_NODE(Node)	((Node) -> PObj -> ObjType == IP_OBJ_TRIMSRF)
#define IS_TRIVAR_NODE(Node)	((Node) -> PObj -> ObjType == IP_OBJ_TRIVAR)

/*****************************************************************************
* a block of command seperated by a colon can have assignments followed by   *
* use of variables. We would like to know that when we test for validity.    *
*****************************************************************************/
#define TO_BE_ASSIGNED_TAG	   0x10
#define IS_TO_BE_ASSIGN_OBJ(Obj)   ((Obj) -> Tags & TO_BE_ASSIGNED_TAG)
#define SET_TO_BE_ASSIGN_OBJ(Obj)  ((Obj) -> Tags |= TO_BE_ASSIGNED_TAG)
#define RST_TO_BE_ASSIGN_OBJ(Obj)  ((Obj) -> Tags &= ~TO_BE_ASSIGNED_TAG))

/*****************************************************************************
* The include file stack - nesting is allowed up to FILE_STACK_SIZE.	     *
*****************************************************************************/
typedef struct FileStackStruct {
    char Name[FILE_NAME_LEN];
    FILE *f;
} FileStackStruct;

#define FILE_STACK_SIZE	10

/*****************************************************************************
* Function entry table looks like this (for table see InptPrsr.c module):    *
*****************************************************************************/
#define FUNC_NAME_LEN	31			    /* 10 + NULL terminator. */
#define FUNC_MAX_PARAM	7	       /* Update # Param cases in inptevl1.c */
#define ANY_PARAM_NUM	127

typedef struct FuncTableType {
    char FuncName[FUNC_NAME_LEN];
    int FuncToken;
    void (*Func)();
    ByteType NumOfParam;
    IritExprType ParamObjType[FUNC_MAX_PARAM];
    IritExprType RetType;
} FuncTableType;

typedef struct NumFuncTableType {
    char FuncName[FUNC_NAME_LEN];
    int FuncToken;
    double (*Func)();
    ByteType NumOfParam;
    IritExprType ParamObjType[FUNC_MAX_PARAM];
    IritExprType RetType;
} NumFuncTableType;

typedef struct ObjFuncTableType {
    char FuncName[FUNC_NAME_LEN];
    int FuncToken;
    IPObjectStruct *(*Func)();
    ByteType NumOfParam;
    IritExprType ParamObjType[FUNC_MAX_PARAM];
    IritExprType RetType;
} ObjFuncTableType;

typedef struct GenFuncTableType {
    char FuncName[FUNC_NAME_LEN];
    int FuncToken;
    void (*Func)();
    ByteType NumOfParam;
    IritExprType ParamObjType[FUNC_MAX_PARAM];
    IritExprType RetType;
} GenFuncTableType;

typedef struct ConstantTableType {
    char FuncName[FUNC_NAME_LEN];
    RealType Value;
} ConstantTableType;

typedef struct UserDefinedFuncDefType {
    struct UserDefinedFuncDefType *Pnext;
    char FuncName[FUNC_NAME_LEN];
    int IsFunction;
    int NumParams;
    IPObjectStruct *Params;
    IPObjectStruct *LocalVars;
    ParseTree *Body;
} UserDefinedFuncDefType;

/* The followings are defined in the InptEval.c module and are globals so   */
/* InptPrsr.c module will be able to access them...			    */
extern NumFuncTableType NumFuncTable[];
extern int NumFuncTableSize;
extern ObjFuncTableType ObjFuncTable[];
extern int ObjFuncTableSize;
extern GenFuncTableType GenFuncTable[];
extern int GenFuncTableSize;
extern ConstantTableType ConstantTable[];
extern int ConstantTableSize;
extern UserDefinedFuncDefType *UserDefinedFuncList;

/*****************************************************************************
* Tokens used in the expression	to tree	conversion and tree definition.	     *
*****************************************************************************/

#define	TOKENERROR  0
#define TOKEN_NONE  1

/* Warning - changing the order of these constants, needs updating the order */
/* of them, in the tables in the begining of InptPrsr.c & OverLoad.c modules.*/

typedef enum {
    USERFUNCDEF = 90,		       /* Function and procedure definition. */
    USERPROCDEF,
    USERINSTDEF
} UserDefinedFuncType;

#define USER_FUNC	0
#define IS_USER_FUNCTION(Token)		(Token >= USERFUNCDEF && \
					 Token <= USERINSTDEF)

typedef enum {				   /* Real value returned functions. */
    ARCCOS = 100,
    ARCSIN,
    ARCTAN2,
    ARCTAN,
    COS,
    EXP,
    FABS,
    FLOOR,
    FMOD,
    FPOWER,
    LN,
    LOG,
    SIN,
    SQRT,
    TAN,
    CPOLY,
    AREA,
    VOLUME,
    TIME,
    SIZEOF,
    MESHSIZE,
    THISOBJ,
    IRT_RNDM,
    CLNTEXEC,
    DSTPTLN,
    DSTPTPLN,
    DSTLNLN
} RealValueFuncType;

#define NUM_FUNC	100
#define NUM_FUNC_OFFSET	100
#define IS_NUM_FUNCTION(Token)		(Token >= 100 && Token < 200)

typedef enum {				       /* Object returned Functions. */
    POINT = 200,
    VECTOR,
    PLANE,
    CTLPT,
    ROTX,
    ROTY,
    ROTZ,
    ROTVEC,
    ROTZ2V2,
    ROTZ2V,
    TRANS,
    SCALE,
    BOX,
    GBOX,
    CONE,
    CONE2,
    CYLIN,
    SPHERE,
    TORUS,
    CIRCPOLY,
    POLY,
    CROSSEC,
    SURFREV,
    SURFPREV,
    EXTRUDE,
    LIST,
    LOAD,
    CONVEX,
    SBEZIER,
    CBEZIER,
    SBSPLINE,
    CBSPLINE,
    SEVAL,
    CEVAL,
    STANGENT,
    CTANGENT,
    SNORMAL,
    CNORMAL,
    TDIVIDE,
    SDIVIDE,
    CDIVIDE,
    TREGION,
    SREGION,
    CREGION,
    TREFINE,
    SREFINE,
    CREFINE,
    SRAISE,
    CRAISE,
    CSURFACE,
    CMESH,
    NTH,
    GPOLYGON,
    GPOLYLINE,
    CIRCLE,
    PCIRCLE,
    ARC,
    RULEDSRF,
    BOOLSUM,
    BOOLONE,
    SFROMCRVS,
    SWEEPSRF,
    SWPSCLSRF,
    OFFSET,
    AOFFSET,
    LOFFSET,
    MOFFSET,
    COERCE,
    CEDITPT,
    SEDITPT,
    MERGEPOLY,
    CMORPH,
    SMORPH,
    BZR2BSP,
    BSP2BZR,
    SMERGE,
    CDERIVE,
    SDERIVE,
    TDERIVE,
    CINTEG,
    SNRMLSRF,
    CNRMLCRV,
    SYMBPROD,
    SYMBDPROD,
    SYMBCPROD,
    SYMBSUM,
    SYMBDIFF,
    HOMOMAT,
    CINFLECT,
    CCRVTR,
    SCRVTR,
    SGAUSS,
    SMEANSQR,
    CREPARAM,
    SREPARAM,
    EVOLUTE,
    CZEROS,
    CEXTREMES,
    CCINTER,
    NIL,
    COORD,
    COMPOSE,
    PRISA,
    CRVPTDIST,
    CRVLNDIST,
    ADAPISO,
    PDOMAIN,
    CINTERP,
    SINTERP,
    CMULTIRES,
    GETLINE,
    FFEXTREME,
    TRIMSRF,
    SRFTRIMSRF,
    CRVTRIMCRV,
    TBEZIER,
    TBSPLINE,
    TEVAL,
    TEXTGEOM,
    STRIVAR,
    TINTERP,
    CLNTREAD,
    MOMENT,
    TFROMSRFS,
    SFOCAL,
    HERMITE,
    FFMATCH,
    CONTOUR,
    SRINTER,
    PLN3PTS,
    PTPTLN,
    PTLNPLN,
    PTSLNLN,
    PT3BARY,
    FFSPLIT,
    FFMERGE,
    FFPTTYPE
} ObjValueFuncType;

#define OBJ_FUNC1	200
#define OBJ_FUNC2	300
#define OBJ_FUNC_OFFSET	200
#define IS_OBJ_FUNCTION(Token)		(Token >= 200 && Token < 400)

typedef enum {		   /* General Functions/No value returned functions. */
    EXIT = 400,
    VIEWOBJ,
    CHDIR,
    INCLUDE,
    SAVE,
    FREEOBJ,
    IFCOND,
    FORLOOP,
    WHILELOOP,
    PRHELP,
    VARLIST,
    SYSTEM,
    LOGFILE,
    COLOR,
    AWIDTH,
    ADWIDTH,
    SNOC,
    ATTRIB,
    RMATTR,
    FFCOMPAT,
    MSLEEP,
    IRITPRINT,
    IRITSTATE,
    IRITERROR,
    CLNTWRITE,
    CLNTCLOSE,
    COMMENT = 499
} GenValueFuncType;

#define GEN_FUNC	400
#define GEN_FUNC_OFFSET	400
#define IS_GEN_FUNCTION(Token)		((Token) >= 400 && (Token) < 500)

#define IS_FUNCTION(Token)              ((Token) >= 90 && (Token) < 500)
#define IS_NO_PARAM_FUNC(Token)		((Token) == EXIT || \
					 (Token) == VARLIST || \
					 (Token) == NIL)

typedef enum {						       /* Operators. */
    PLUS = 500,
    MINUS,
    MULT,
    DIV,
    POWER,
    UNARMINUS,
    EQUAL,
    COMMA,
    COLON,
    SEMICOLON,
    CMP_EQUAL,
    CMP_NOTEQUAL,
    CMP_LSEQUAL,
    CMP_GTEQUAL,
    CMP_LESS,
    CMP_GREAT,
    BOOL_AND,
    BOOL_OR,
    BOOL_NOT,
    LASTOPER = BOOL_NOT,

    OPENPARA = 530,					     /* Paranthesis. */
    CLOSPARA,

    NUMBER = 550,					    /* Numeric Data. */
    PARAMETER,					 /* Point on new/old object. */
    STRING,		     /* Sequence of characters within double quotes. */

    TOKENSTART = 590,
    TOKENEND
} GenericTokenType;

#define OPERATORS		500
#define OPERATORS_OFFSET	500
#define IS_AN_OPERATOR(Token)		((Token) >= 500 && (Token) <= LASTOPER)

extern char IPGlblCharData[INPUT_LINE_LEN];   /* Used for both parse & eval. */
extern InptPrsrEvalErrType IPGlblEvalError;	 /* Global used by EvalTree. */

/*****************************************************************************
*   The local function (static) prototypes:				     *
*   Note that if DEBUG is defined for the preprocessor, few more function    *
* become available:							     *
*   Also note that some of the routines are defined globals as both the      *
* InptPrsr.c and InptEval.c modules needs them.				     *
*****************************************************************************/

ParseTree *ExprMalloc(void);
void ExprFree(ParseTree *Ptr);
void UpdateCharError(char *StrMsg, int Token, ParseTree *Node);
void FileInclude(char *FileName);
IritExprType InptPrsrTypeCheck(ParseTree *Root, int Level);   /* Type check. */
ParseTree *InptPrsrEvalTree(ParseTree *Root, int Level);   /* Evaluate tree. */
void InptPrsrFreeTree(ParseTree *Root);			   /* Free all tree. */
void InptPrsrPrintTree(ParseTree *Root, char *str);	      /* print it... */
ParseTree *InptPrsrCopyTree(ParseTree *Root);			 /* Copy it. */
ParseTree *InptEvalFetchParameter(ParseTree *Root, int i, int n);
int InptEvalCountNumParameters(ParseTree *Root);

char *InptPrsrTypeToStr(IritExprType Type);
void InptEvalPrintHelp(char *HelpHeader);
ParseTree *InptEvalCompareObject(ParseTree *Root,
				 ParseTree *Left,
			         ParseTree *Right,
				 InptPrsrEvalErrType *IError,
    				 char *CError);
void InptEvalIfCondition(ParseTree *Cond,
			 ParseTree *CondTrue,
			 ParseTree *CondFalse);
void InptEvalForLoop(ParseTree *PStart,
		     ParseTree *PInc,
		     ParseTree *PEnd,
		     ParseTree *PBody);
void InptEvalWhileLoop(ParseTree *PCond, ParseTree *PBody);
void IritPrsrMarkToBeAssigned(ParseTree *Root);
IPObjectStruct *InptEvalGenObjectList(ParseTree *PObjParams);
IPObjectStruct *InptEvalCtlPtFromParams(ParseTree *PObjParams);
void InptEvalDefineFunc(ParseTree *FuncDef);
ParseTree *InptEvalUserFunc(ParseTree *Root, ParseTree *Params[]);
int InptEvalFetchParameters(ParseTree *Root,
			    FuncTableType *FuncTable,
			    int NumParams,
			    int Level,
			    ParseTree *Params[],
			    VoidPtr ParamPtrs[]);
int IritEvalFuncParamMismatch(ParseTree *Root);

#endif	/* INPT_PRSR_LH */
