/***************************************************************************** * Generic parser for the "Irit" solid modeller. * * * * Written by: Gershon Elber Ver 0.2, Sep. 1991 * *****************************************************************************/ #ifdef __MSDOS__ #include #endif /* __MSDOS__ */ #include #include #include #include #include #include "irit_sm.h" #include "iritprsr.h" #define LOAD_COLOR 14 /* Index color 1 by default. */ #define UNGET_STACK_SIZE 5 /* Internal stack size. */ typedef enum { /* List of all possible tokens enumerated. */ TOKEN_NONE, TOKEN_OPEN_PAREN, TOKEN_CLOSE_PAREN, TOKEN_E2, TOKEN_P2, TOKEN_E3, TOKEN_P3, TOKEN_NUMBER, TOKEN_STRING, TOKEN_VECTOR, TOKEN_MATRIX, TOKEN_CTLPT, TOKEN_VERTEX, TOKEN_POLYGON, TOKEN_POLYLINE, TOKEN_POINTLIST, TOKEN_OBJECT, TOKEN_COLOR, TOKEN_RGB, TOKEN_INTERNAL, TOKEN_NORMAL, TOKEN_PLANE, TOKEN_CURVE, TOKEN_SURFACE, TOKEN_OTHER = 100, /* Probably names & numbers. */ TOKEN_EOF = -1 } TokenType; typedef enum { /* Possible error code during data parsing. */ IP_NO_ERR = 0, IP_ERR_NUMBER_EXPECTED, IP_ERR_OPEN_PAREN_EXPECTED, IP_ERR_CLOSE_PAREN_EXPECTED, IP_ERR_LIST_COMP_UNDEF, IP_ERR_UNDEF_EXPR_HEADER, IP_ERR_PT_TYPE_EXPECTED, IP_ERR_OBJECT_EMPTY, IP_ERR_MIXED_TYPES, IP_STR_NOT_IN_QUOTES, IP_ERR_OBJECT_EXPECTED, IP_ERR_CAGD_LIB_ERR, IP_ERR_STACK_OVERFLOW, IP_ERR_DEGEN_POLYGON, IP_WRN_OBJ_NAME_TRUNC = 100 } IritPrsrErrType; static int IPGlblLineCount = 0; /* Used to locate errors in input file. */ static IritPrsrErrType IPGlblParserError = IP_NO_ERR; /* Last err # found. */ static char IPGlblTokenError[LINE_LEN_LONG]; /* Last token error was found. */ static jmp_buf LclLongJumpBuffer; /* Used in error traping. */ static int GlblToken = 0, /* Used by the parser, to unget token. */ GlblLineCount = 1; /* Used to locate errors in input file. */ static char GlblStringToken[UNGET_STACK_SIZE][LINE_LEN_LONG];/* Unget tokens.*/ static IPObjectStruct *AllSrfs = NULL; static IPObjectStruct *AllCrvs = NULL; static IPObjectStruct *AllPolys = NULL; int IritPrsrPolyListCirc = TRUE; int IritPrsrWasViewMat = FALSE, IritPrsrWasPrspMat = FALSE; MatrixType IritPrsrViewMat = { /* Isometric view, by default. */ { -0.707107, -0.408248, 0.577350, 0.000000 }, { 0.707107, -0.408248, 0.577350, 0.000000 }, { 0.000000, 0.816496, 0.577350, 0.000000 }, { 0.000000, 0.000000, 0.000000, 1.000000 } }; MatrixType IritPrsrPrspMat = { { 1, 0, 0, 0 }, { 0, 1, 0, 0 }, { 0, 0, 0.1, -0.35 }, { 0, 0, 0.35, 1.0 } }; static void UnGetToken(char *StringToken); static void GetStringToken(FILE *f, char *StringToken); static TokenType GetToken(FILE *f, char *StringToken); static void GetVertexAttributes(IPVertexStruct *PVertex, FILE *f); static void GetPolygonAttributes(IPPolygonStruct *PPolygon, FILE *f); static void GetObjectAttributes(IPObjectStruct *PObject, FILE *f); static void GetPointData(FILE *f, IPPolygonStruct *PPolygon); static void IPUpdatePolyPlane(IPPolygonStruct *PPoly); static void ParserError(IritPrsrErrType ErrNum, char *Msg); static void IritPrsrGetAllObjects(FILE *f, IPObjectStruct *PObjParent); static void GetCloseParenToken(FILE *f); static void SkipToCloseParenToken(FILE *f); static void GetNumericToken(FILE *f, RealType *r); static void IritPrsrGetAuxObject(FILE *f, IPObjectStruct *PObj); /***************************************************************************** * Routine to read the data from a given file. * *****************************************************************************/ IPObjectStruct *IritPrsrGetObjects(FILE *f) { IPObjectStruct *PObjs, *PTmp; AllSrfs = NULL; AllCrvs = NULL; AllPolys = NULL; /* If the following gain control and is non zero - its from error! */ if (setjmp(LclLongJumpBuffer) != 0) { if (f != NULL) fclose(f); return NULL; } GlblToken = 0; /* Used in UnGetToken token buffer. */ IPGlblParserError = IP_NO_ERR; /* Reset errors. */ GlblLineCount = 1; /* Reset line counter. */ PTmp = IritPrsrNewObjectStruct(); IritPrsrGetAllObjects(f, PTmp); if (AllCrvs != NULL || AllSrfs != NULL) { if ((PObjs = IritPrsrProcessFreeForm(AllCrvs, AllSrfs)) != NULL) { for (PTmp = PObjs; PTmp -> Pnext != NULL; PTmp = PTmp -> Pnext) { if (!IP_HAS_OBJ_COLOR(PTmp)) { PTmp -> Color = LOAD_COLOR; IP_SET_OBJ_COLOR(PTmp); } } PTmp -> Pnext = AllPolys; AllPolys = PObjs; } } fclose(f); return AllPolys; } /***************************************************************************** * Routine to read the geometry data from a given file. Reads "[OBJECT ..." * * prefixes only and invoke the auxiliary routine. * * Note objects may be recursively defined. * *****************************************************************************/ static void IritPrsrGetAllObjects(FILE *f, IPObjectStruct *PObjParent) { char StringToken[LINE_LEN_LONG]; TokenType Token; int WasObjectToken = FALSE, Quit = FALSE; IPObjectStruct *PObj; while (!Quit) { while ((Token = GetToken(f, StringToken)) != TOKEN_OPEN_PAREN && Token != TOKEN_CLOSE_PAREN && Token != TOKEN_EOF); if (Token == TOKEN_CLOSE_PAREN || Token == TOKEN_EOF) { if (Token == TOKEN_CLOSE_PAREN) UnGetToken(StringToken); Quit = TRUE; break; } switch (GetToken(f, StringToken)) { case TOKEN_OBJECT: WasObjectToken = TRUE; PObj = IritPrsrNewObjectStruct(); /* The following handle optional attributes in record. */ if (GetToken(f, StringToken) == TOKEN_OPEN_PAREN) GetObjectAttributes(PObj, f); else { UnGetToken(StringToken); } if (!IP_HAS_OBJ_COLOR(PObj)) { PObj -> Color = LOAD_COLOR; IP_SET_OBJ_COLOR(PObj); } if (GetToken(f, StringToken) == TOKEN_OTHER && strcmp(StringToken, "NONE") != 0) strcpy(PObj -> Name, StringToken); IritPrsrGetAllObjects(f, PObj); GetCloseParenToken(f); if (PObjParent) { /* This object contains other object - delete it since */ /* we are flattening the structure here. */ free((VoidPtr) PObjParent); PObjParent = NULL; } break; default: if (WasObjectToken) { ParserError(IP_ERR_OBJECT_EXPECTED, StringToken); } UnGetToken(StringToken); UnGetToken("["); IritPrsrGetAuxObject(f, PObjParent); Quit = TRUE; break; } } } /***************************************************************************** * Routine to get close paren token from f. * *****************************************************************************/ static void GetCloseParenToken(FILE *f) { char StringToken[LINE_LEN_LONG]; if (GetToken(f, StringToken) != TOKEN_CLOSE_PAREN) ParserError(IP_ERR_CLOSE_PAREN_EXPECTED, StringToken); } /***************************************************************************** * Routine to get close paren token from f. * *****************************************************************************/ static void SkipToCloseParenToken(FILE *f) { char StringToken[LINE_LEN_LONG]; while (!feof(f) && GetToken(f, StringToken) != TOKEN_CLOSE_PAREN); } /***************************************************************************** * Routine to get one numeric token into r. * *****************************************************************************/ static void GetNumericToken(FILE *f, RealType *r) { char StringToken[LINE_LEN_LONG]; GetToken(f, StringToken); # ifdef DOUBLE if (sscanf(StringToken, "%lf", r) != 1) # else if (sscanf(StringToken, "%f", r) != 1) # endif /* DOUBLE */ ParserError(IP_ERR_NUMBER_EXPECTED, StringToken); } /***************************************************************************** * Routine to read the content of a single object. Return TRUE if data is * * useful for this parser, FALSE if data should be purged. * *****************************************************************************/ static void IritPrsrGetAuxObject(FILE *f, IPObjectStruct *PObj) { int i, j, ErrLine; TokenType Token; char *ErrStr, StringToken[LINE_LEN_LONG]; IPPolygonStruct *PPolygon; CagdCrvStruct *PCurve; CagdSrfStruct *PSurface; PObj -> Type = IP_OBJ_UNDEF; while (GetToken(f, StringToken) == TOKEN_OPEN_PAREN) { switch (Token = GetToken(f, StringToken)) { case TOKEN_POLYGON: case TOKEN_POLYLINE: case TOKEN_POINTLIST: PPolygon = IritPrsrNewPolygonStruct(); switch (Token) { case TOKEN_POLYGON: PPolygon -> Type = IP_POLYGON; break; case TOKEN_POLYLINE: PPolygon -> Type = IP_POLYLINE; break; case TOKEN_POINTLIST: PPolygon -> Type = IP_POINTLIST; break; } /* The following handle the optional attributes in struct. */ if (GetToken(f, StringToken) == TOKEN_OPEN_PAREN) GetPolygonAttributes(PPolygon, f); else UnGetToken(StringToken); /* The following handles reading the vertices. */ GetPointData(f, PPolygon); if (PPolygon -> Type == IP_POLYGON && !IP_HAS_POLY_PLANE(PPolygon)) IPUpdatePolyPlane(PPolygon); PPolygon -> Pnext = PObj -> U.PPolygon; PObj -> U.PPolygon = PPolygon; PObj -> Type = IP_OBJ_POLY; break; case TOKEN_MATRIX: if (strcmp(PObj -> Name, "VIEW_MAT") == 0) { IritPrsrWasViewMat = TRUE; for (i = 0; i < 4; i++) for (j = 0; j < 4; j++) GetNumericToken(f, &IritPrsrViewMat[i][j]); GetCloseParenToken(f); } else if (strcmp(PObj -> Name, "PRSP_MAT") == 0) { IritPrsrWasPrspMat = TRUE; for (i = 0; i < 4; i++) for (j = 0; j < 4; j++) GetNumericToken(f, &IritPrsrPrspMat[i][j]); GetCloseParenToken(f); } else SkipToCloseParenToken(f); break; case TOKEN_SURFACE: ErrLine = GlblLineCount; PSurface = CagdSrfReadFromFile2(f, &ErrStr, &ErrLine); GlblLineCount = ErrLine; if (ErrStr != NULL) { ParserError(IP_ERR_CAGD_LIB_ERR, ErrStr); break; } if (PSurface != NULL) { PSurface -> Pnext = PObj -> U.PSrfs; PObj -> U.PSrfs = PSurface; } PObj -> Type = IP_OBJ_SURFACE; break; case TOKEN_CURVE: ErrLine = GlblLineCount; PCurve = CagdCrvReadFromFile2(f, &ErrStr, &ErrLine); GlblLineCount = ErrLine; if (ErrStr != NULL) { ParserError(IP_ERR_CAGD_LIB_ERR, ErrStr); break; } if (PCurve != NULL) { PCurve -> Pnext = PObj -> U.PCrvs; PObj -> U.PCrvs = PCurve; } PObj -> Type = IP_OBJ_CURVE; break; case TOKEN_NUMBER: case TOKEN_STRING: case TOKEN_VECTOR: case TOKEN_CTLPT: SkipToCloseParenToken(f); break; default: ParserError(IP_ERR_UNDEF_EXPR_HEADER, StringToken); break; } /* Of switch. */ } /* Of while. */ switch (Token) { case TOKEN_POLYGON: case TOKEN_POLYLINE: case TOKEN_POINTLIST: PObj -> Pnext = AllPolys; AllPolys = PObj; break; case TOKEN_SURFACE: PObj -> Pnext = AllSrfs; AllSrfs = PObj; break; case TOKEN_CURVE: PObj -> Pnext = AllCrvs; AllCrvs = PObj; break; default: free((VoidPtr) PObj); break; } UnGetToken(StringToken); } /***************************************************************************** * Routine to unget one token (on stack of UNGET_STACK_SIZE levels!) * *****************************************************************************/ static void UnGetToken(char *StringToken) { if (GlblToken >= UNGET_STACK_SIZE) ParserError(IP_ERR_STACK_OVERFLOW, ""); strcpy(GlblStringToken[GlblToken], StringToken); GlblToken++; /* GlblToken exists - Something in it (no overflow check). */ } /***************************************************************************** * Routine to get the next token out of the input file f. * * Returns the next token found, as StringToken. * * Note: StringToken must be allocated before calling this routine! * *****************************************************************************/ static void GetStringToken(FILE *f, char *StringToken) { int len; char c, *LocalStringToken; if (GlblToken) { /* get first the unget token */ GlblToken--; strcpy(StringToken, GlblStringToken[GlblToken]); return; } /* skip white spaces: */ while ((!feof(f)) && (((c = getc(f)) == ' ') || (c == '\t') || (c == '\n'))) if (c == '\n') GlblLineCount++; /* Count the lines. */ LocalStringToken = StringToken; if (c == '[') /* Its a token by itself so return it. */ *LocalStringToken++ = c; /* Copy the token into string. */ else { if (!feof(f)) do *LocalStringToken++ = c; /* Copy the token into string. */ while ((!feof(f)) && ((c = getc(f)) != ' ') && (c != '\t') && (c != '\n')); if (c == '\n') ungetc(c, f); /* Save it to be counted next time. */ } *LocalStringToken = 0; /* Put eos. */ /* The following handles the spacial case were we have XXXX] - we must */ /* split it into two token XXXX and ], UnGetToken(']') and return XXXX: */ if ((StringToken[len = strlen(StringToken)-1] == ']') && (len > 0)) { /* Return CloseParan */ UnGetToken(&StringToken[len]); /* Save next token. */ StringToken[len] = 0; /* Set end of string on "]". */ } } /***************************************************************************** * Routine to get the next token out of the input file f as token number. * * Note: StringToken must be allocated before calling this routine! * *****************************************************************************/ static TokenType GetToken(FILE *f, char *StringToken) { static int IntTokens[] = { TOKEN_OPEN_PAREN, TOKEN_CLOSE_PAREN, TOKEN_VERTEX, TOKEN_POLYGON, TOKEN_POLYLINE, TOKEN_POINTLIST, TOKEN_OBJECT, TOKEN_COLOR, TOKEN_RGB, TOKEN_INTERNAL, TOKEN_NORMAL, TOKEN_PLANE, TOKEN_CURVE, TOKEN_SURFACE, TOKEN_E2, TOKEN_P2, TOKEN_E3, TOKEN_P3, TOKEN_NUMBER, TOKEN_STRING, TOKEN_VECTOR, TOKEN_MATRIX, TOKEN_CTLPT, 0 }; static char *StrTokens[] = { "[", "]", "VERTEX", "POLYGON", "POLYLINE", "POINTLIST", "OBJECT", "COLOR", "RGB", "INTERNAL", "NORMAL", "PLANE", "CURVE", "SURFACE", "E2", "P2", "E3", "P3", "NUMBER", "STRING", "VECTOR", "MATRIX", "CTLPT", NULL }; int i; GetStringToken(f, StringToken); if (feof(f)) return TOKEN_EOF; for (i = 0; StrTokens[i] != NULL; i++) if (strcmp(StringToken, StrTokens[i]) == 0) return IntTokens[i]; return TOKEN_OTHER; /* Must be number or name. */ } /***************************************************************************** * Routine to read from input file f the following [ATTR ...] [ATTR ...]. * * Note the '[' was allready read. * *****************************************************************************/ static void GetVertexAttributes(IPVertexStruct *PVertex, FILE *f) { int i; RealType Len; char StringToken[LINE_LEN_LONG]; do { switch (GetToken(f, StringToken)) { case TOKEN_INTERNAL: GetCloseParenToken(f); IP_SET_VRTX_INTERNAL(PVertex); break; case TOKEN_NORMAL: /* The following handles reading 3 coord. of vertex normal. */ for (i = 0; i < 3; i++) GetNumericToken(f, &PVertex -> Normal[i]); /* Make sure it is normalized. */ Len = PT_LENGTH(PVertex -> Normal); for (i = 0; i < 3; i++) PVertex -> Normal[i] /= Len; GetCloseParenToken(f); IP_SET_VRTX_NORMAL(PVertex); break; default: /* Ignore this option! */ SkipToCloseParenToken(f); break; } } while (GetToken(f, StringToken) == TOKEN_OPEN_PAREN); UnGetToken(StringToken); } /***************************************************************************** * Routine to read from input file f the following [ATTR ...] [ATTR ...]. * * Note the '[' was allready read. * *****************************************************************************/ static void GetPolygonAttributes(IPPolygonStruct *PPolygon, FILE *f) { int i; RealType Len; char StringToken[LINE_LEN_LONG]; do { switch (GetToken(f, StringToken)) { case TOKEN_PLANE: /* The following handles reading of 4 coord. of plane eqn.. */ for (i = 0; i < 4; i++) GetNumericToken(f, &PPolygon -> Plane[i]); /* Make sure it is normalized. */ Len = PT_LENGTH(PPolygon -> Plane); for (i = 0; i < 4; i++) PPolygon -> Plane[i] /= Len; GetCloseParenToken(f); IP_SET_POLY_PLANE(PPolygon); break; default: SkipToCloseParenToken(f); break; } } while (GetToken(f, StringToken) == TOKEN_OPEN_PAREN); UnGetToken(StringToken); } /***************************************************************************** * Routine to read from input file f the following [ATTR ...] [ATTR ...]. * * Note the '[' was allready read. * *****************************************************************************/ static void GetObjectAttributes(IPObjectStruct *PObject, FILE *f) { int i, j; char StringToken[LINE_LEN_LONG]; do { switch (GetToken(f, StringToken)) { case TOKEN_RGB: /* The following handles reading of 3 coord. of rgb. */ for (i = 0; i < 3; i++) { GetToken(f, StringToken); if (sscanf(StringToken, "%d", &j) != 1) ParserError(IP_ERR_NUMBER_EXPECTED, StringToken); PObject -> RGB[i] = (unsigned char) j; } GetCloseParenToken(f); IP_SET_OBJ_RGB(PObject); break; case TOKEN_COLOR: GetToken(f, StringToken); if (sscanf(StringToken, "%d", &i) != 1) ParserError(IP_ERR_NUMBER_EXPECTED, StringToken); GetCloseParenToken(f); PObject -> Color = i; IP_SET_OBJ_COLOR(PObject); break; default: if ((i = PObject -> Attrs.NumStrAttribs) < MAX_NUM_ATTRS) { PObject -> Attrs.StrAttrName[i] = strdup(StringToken); if (GetToken(f, StringToken) == TOKEN_CLOSE_PAREN) { UnGetToken(StringToken); PObject -> Attrs.StrAttrData[i] = ""; } else { PObject -> Attrs.StrAttrData[i] = strdup(StringToken); } PObject -> Attrs.NumStrAttribs++; } SkipToCloseParenToken(f); break; } } while (GetToken(f, StringToken) == TOKEN_OPEN_PAREN); if (!IP_HAS_OBJ_COLOR(PObject)) { PObject -> Color = LOAD_COLOR; IP_SET_OBJ_COLOR(PObject); } UnGetToken(StringToken); } /***************************************************************************** * Routine to read poly* vertex information. * *****************************************************************************/ static void GetPointData(FILE *f, IPPolygonStruct *PPolygon) { int i, j, Length; char StringToken[LINE_LEN_LONG]; IPVertexStruct *V, *VTail = NULL; if (GetToken(f, StringToken) != TOKEN_OTHER || sscanf(StringToken, "%d", &Length) != 1) ParserError(IP_ERR_NUMBER_EXPECTED, StringToken); for (i = 0; i < Length; i++) { if (GetToken(f, StringToken) != TOKEN_OPEN_PAREN) ParserError(IP_ERR_OPEN_PAREN_EXPECTED, StringToken); V = IritPrsrNewVertexStruct(); /* The following handle the optional attributes in struct. */ if (GetToken(f, StringToken) == TOKEN_OPEN_PAREN) GetVertexAttributes(V, f); else UnGetToken(StringToken); for (j = 0; j < 3; j++) /* Read coordinates. */ GetNumericToken(f, &V -> Coord[j]); GetCloseParenToken(f); if (!IP_HAS_VRTX_NORMAL(V)) PT_COPY(V -> Normal, PPolygon -> Plane); if (VTail == NULL) PPolygon -> PVertex = VTail = V; else { VTail -> Pnext = V; VTail = V; } } if (IritPrsrPolyListCirc && PPolygon -> Type == IP_POLYGON) VTail -> Pnext = PPolygon -> PVertex; GetCloseParenToken(f); } /***************************************************************************** * Routine to update the Plane equation of the given polygon by the order * * of the first 3 vertices of that polygon. * *****************************************************************************/ static void IPUpdatePolyPlane(IPPolygonStruct *PPoly) { int i; RealType Len, V1[3], V2[3]; IPVertexStruct *V = PPoly -> PVertex; if (V == NULL || V -> Pnext == NULL || V -> Pnext -> Pnext == NULL) ParserError(IP_ERR_DEGEN_POLYGON, ""); PT_SUB(V1, V -> Coord, V -> Pnext -> Coord); V = V -> Pnext; PT_SUB(V2, V -> Coord, V -> Pnext -> Coord); PPoly -> Plane[0] = V1[1] * V2[2] - V2[1] * V1[2]; PPoly -> Plane[1] = V1[2] * V2[0] - V2[2] * V1[0]; PPoly -> Plane[2] = V1[0] * V2[1] - V2[0] * V1[1]; PPoly -> Plane[3] = (-DOT_PROD(PPoly -> Plane, PPoly -> PVertex -> Coord)); /* Normalize the plane such that the normal has length of 1: */ Len = PT_LENGTH(PPoly -> Plane); for (i = 0; i < 4; i++) PPoly -> Plane[i] /= Len; } /***************************************************************************** * Routine to set a string attribute. A string attribute consists of an * * attribute name (string) and data (also string). * * If Data = "", the attribute with name Name is been freed. * * If attribute by the given name already exists, it is replaced. * *****************************************************************************/ void IritPrsrSetStrAttrib(IPObjectStruct *PObj, char *Name, char *Data) { int i; IPAttributeStruct *Attr = &PObj -> Attrs; for (i = 0; i < Attr -> NumStrAttribs; i++) { if (strcmp(Name, Attr -> StrAttrName[i]) == 0) { /* If Data is an empty string, remove this entry. */ if (strlen(Data) == 0) { free((VoidPtr) Attr -> StrAttrName[i]); free((VoidPtr) Attr -> StrAttrData[i]); for ( ; i < (int) Attr -> NumStrAttribs - 2; i++) { Attr -> StrAttrName[i] = Attr -> StrAttrName[i + 1]; Attr -> StrAttrData[i] = Attr -> StrAttrData[i + 1]; } Attr -> NumStrAttribs--; } else { free((VoidPtr) Attr -> StrAttrData[i]); Attr -> StrAttrData[i] = strdup(Data); } return; } } /* O.k. it is a new attribute. */ if (Attr -> NumStrAttribs >= MAX_NUM_ATTRS) { return; } Attr -> StrAttrName[Attr -> NumStrAttribs] = strdup(Name); Attr -> StrAttrData[Attr -> NumStrAttribs++] = strdup(Data); } /***************************************************************************** * Routine to get a string attribute. A string attribute consists of an * * attribute name (string) and data (also string). * * Returns a pointer to data if string name is found, NULL otherwise. * *****************************************************************************/ char *IritPrsrGetStrAttrib(IPObjectStruct *PObj, char *Name) { int i; IPAttributeStruct *Attr = &PObj -> Attrs; /* If Name is an empty string - print all attributes. */ if (Name == NULL || strlen(Name) == 0) return NULL; for (i = 0; i < Attr -> NumStrAttribs; i++) if (strcmp(Name, Attr -> StrAttrName[i]) == 0) return Attr -> StrAttrData[i]; return NULL; } /***************************************************************************** * Routine to allocate a new VertexStruct. * *****************************************************************************/ IPVertexStruct *IritPrsrNewVertexStruct(void) { IPVertexStruct *V = (IPVertexStruct *) malloc(sizeof(IPVertexStruct)); V -> Pnext = NULL; V -> VAux = NULL; V -> VTags = 0; return V; } /***************************************************************************** * Routine to allocate a new PolygonStruct. * *****************************************************************************/ IPPolygonStruct *IritPrsrNewPolygonStruct(void) { IPPolygonStruct *P = (IPPolygonStruct *) malloc(sizeof(IPPolygonStruct)); P -> Pnext = NULL; P -> PVertex = NULL; P -> PAux = NULL; P -> PTags = 0; return P; } /***************************************************************************** * Routine to allocate a new ObjectStruct. * *****************************************************************************/ IPObjectStruct *IritPrsrNewObjectStruct(void) { IPObjectStruct *O = (IPObjectStruct *) malloc(sizeof(IPObjectStruct)); O -> Pnext = NULL; O -> U.PPolygon = NULL; O -> OAux = NULL; O -> Attrs.NumStrAttribs = 0; O -> OTags = 0; O -> Name[0] = 0; O -> Color = LOAD_COLOR; O -> FFPolylines = O -> FFPolygons = NULL; return O; } /***************************************************************************** * Routine to print pasring error according to ErrNum and set GlblParserError.* *****************************************************************************/ static void ParserError(IritPrsrErrType ErrNum, char *Msg) { IPGlblLineCount = GlblLineCount; IPGlblParserError = ErrNum; strcpy(IPGlblTokenError, Msg); /* Keep the message in safe place... */ longjmp(LclLongJumpBuffer, 1); /* Jump to... */ } /***************************************************************************** * Returns TRUE if error happened, FALSE otherwise. * * If error, then ErrorMsg is updated to point on static str describing it. * *****************************************************************************/ int IritPrsrParseError(char **ErrorMsg) { IritPrsrErrType Temp; char TempCopy[LINE_LEN_LONG]; if ((Temp = IPGlblParserError) == IP_NO_ERR) return FALSE; strcpy(TempCopy, IPGlblTokenError); IPGlblParserError = IP_NO_ERR; switch (Temp) { case IP_ERR_NUMBER_EXPECTED: sprintf(IPGlblTokenError, "Line %d: Numeric data expected - found %s", IPGlblLineCount, TempCopy); break; case IP_ERR_OPEN_PAREN_EXPECTED: sprintf(IPGlblTokenError, "Line %d: '[' expected - found '%s'", IPGlblLineCount, TempCopy); break; case IP_ERR_CLOSE_PAREN_EXPECTED: sprintf(IPGlblTokenError, "Line %d: ']' expected - found '%s'", IPGlblLineCount, TempCopy); break; case IP_ERR_LIST_COMP_UNDEF: sprintf(IPGlblTokenError, "Line %d: Undefined list element - \"%s\"", IPGlblLineCount, TempCopy); break; case IP_ERR_UNDEF_EXPR_HEADER: sprintf(IPGlblTokenError, "Line %d: Undefined TOKEN - \"%s\"", IPGlblLineCount, TempCopy); break; case IP_ERR_PT_TYPE_EXPECTED: sprintf(IPGlblTokenError, "Line %d: Point type expected", IPGlblLineCount); break; case IP_ERR_OBJECT_EMPTY: sprintf(IPGlblTokenError, "Line %d: Empty object found", IPGlblLineCount); break; case IP_ERR_MIXED_TYPES: sprintf(IPGlblTokenError, "Line %d: Mixed data types in same object", IPGlblLineCount); break; case IP_STR_NOT_IN_QUOTES: sprintf(IPGlblTokenError, "Line %d: String not in quotes (%s)", IPGlblLineCount, TempCopy); break; case IP_ERR_OBJECT_EXPECTED: sprintf(IPGlblTokenError, "Line %d: 'OBJECT' expected, found '%s'", IPGlblLineCount, TempCopy); break; case IP_ERR_CAGD_LIB_ERR: sprintf(IPGlblTokenError, "Line %d: %s", IPGlblLineCount, TempCopy); break; case IP_ERR_STACK_OVERFLOW: sprintf(IPGlblTokenError, "Line %d: Parser Stack overflow", IPGlblLineCount); break; default: sprintf(IPGlblTokenError, "Line %d: Data file parser - undefined error", IPGlblLineCount); break; } *ErrorMsg = IPGlblTokenError; return TRUE; }