home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************************
- * "Irit" - the 3d polygonal solid modeller. *
- * *
- * Written by: Gershon Elber Ver 0.2, Mar. 1990 *
- ******************************************************************************
- * Data File Interpreter module - handle data files - to/from geom objects *
- *****************************************************************************/
-
- #ifdef USE_VARARGS
- #include <varargs.h>
- #else
- #include <stdarg.h>
- #endif /* USE_VARARGS */
-
- #include <stdio.h>
- #include <ctype.h>
- #include <math.h>
- #include <string.h>
- #include "program.h"
- #include "cagd_lib.h"
- #include "allocate.h"
- #include "attribut.h"
- #include "dataprsr.h" /* Visible to the other modules. */
- #include "geomat3d.h"
- #include "objects.h"
- #include "windows.h"
- #include "graphgen.h"
-
- #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_OBJECT,
- TOKEN_COLOR,
- 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. */
- DP_NO_ERR = 0,
-
- DP_ERR_NUMBER_EXPECTED,
- DP_ERR_OPEN_PAREN_EXPECTED,
- DP_ERR_CLOSE_PAREN_EXPECTED,
- DP_ERR_LIST_COMP_UNDEF,
- DP_ERR_UNDEF_EXPR_HEADER,
- DP_ERR_PT_TYPE_EXPECTED,
- DP_ERR_OBJECT_EMPTY,
- DP_ERR_EMPTY_NAME,
- DP_ERR_OPEN_FAILED,
- DP_ERR_MIXED_TYPES,
- DP_STR_NOT_IN_QUOTES,
- DP_ERR_CAGD_LIB_ERR,
-
- DP_WRN_OBJ_NAME_TRUNC = 100
- } DataPrsrErrType;
-
- static int DPGlblLineCount = 0; /* Used to locate errors in input file. */
- static DataPrsrErrType DPGlblParserError = DP_NO_ERR; /* Last err # found. */
- static char DPGlblTokenError[LINE_LEN]; /* Last token where 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];/* Save unget tokens.*/
- static FILE *OutputFile = NULL;
-
- static void UnGetToken(char *StringToken);
- static void GetStringToken(FILE *f, char *StringToken);
- static TokenType GetToken(FILE *f, char *StringToken);
- static void GetVertexAttributes(VertexStruct *PVertex, FILE *f,
- int *HasNormal);
- static void GetPolygonAttributes(PolygonStruct *PPolygon, FILE *f,
- int *HasPlane);
- static void GetObjectAttributes(ObjectStruct *PObject, FILE *f);
- static void GetPointData(FILE *f, PolygonStruct *PPolygon, int IsPolyline,
- int *HasNormal);
- static void DPUpdatePolyPlane(PolygonStruct *PPoly);
- static void ParserError(DataPrsrErrType ErrNum, char *Msg);
- static void DataPrsrPutAllObjects(ObjectStruct *PObj, int Indent);
- static char *Real2Str(RealType R);
- static void DataPrsrGetAllObjects(FILE *f, ObjectStruct *PObjParent);
- static void GetCloseParenToken(FILE *f);
- static void GetNumericToken(FILE *f, RealType *r);
- static void DataPrsrGetAuxObject(FILE *f, ObjectStruct *PObj);
-
- #ifdef USE_VARARGS
- static void IFprintf(int Indent, char *va_alist, ...);
- #else
- static void IFprintf(int Indent, char *Format, ...);
- #endif /* USE_VARARGS */
-
- /*****************************************************************************
- * Routine to print the data from given object into given file FileName. *
- * If FileName is NULL or empty, print to screen using WndwInputWindowPutStr. *
- *****************************************************************************/
- void DataPrsrPutObject(char *FileName, ObjectStruct *PObj)
- {
- char *Pchar;
- char FullFileName[LINE_LEN];
-
- DPGlblParserError = DP_NO_ERR;
-
- /* If the following gain control and is non zero - its from error! */
- if (setjmp(LclLongJumpBuffer) != 0) {
- if (OutputFile != NULL) fclose(OutputFile);
- return;
- }
-
- if (FileName && (int) strlen(FileName) > 0) {
- if ((Pchar = strchr(FileName, '.')) != NULL)
- *Pchar = 0; /* Make sure no file type is given. */
- if (strlen(FileName) == 0) ParserError(DP_ERR_EMPTY_NAME, "");
-
- strcpy(FullFileName, FileName);
- strcat(FullFileName, ".dat");
-
- if ((OutputFile = fopen(FullFileName, "w")) == NULL)
- ParserError(DP_ERR_OPEN_FAILED, FullFileName);
- }
- else
- OutputFile = NULL;
-
- DataPrsrPutAllObjects(PObj, 0);
-
- if (OutputFile) {
- fclose(OutputFile);
- OutputFile = NULL;
- }
-
- return;
- }
-
- /*****************************************************************************
- * Routine to read the data from a given file. *
- *****************************************************************************/
- ObjectStruct *DataPrsrGetObjects(char *FileName)
- {
- char FullFileName[LINE_LEN];
- FILE
- *f = NULL;
- ObjectStruct *PObj, *PTmp;
-
- /* If the following gain control and is non zero - its from error! */
- if (setjmp(LclLongJumpBuffer) != 0) {
- if (f != NULL) fclose(f);
- return NULL;
- }
-
- if (strlen(FileName) == 0) ParserError(DP_ERR_EMPTY_NAME, "");
-
- strcpy(FullFileName, FileName);
- if (strrchr(FullFileName, '.') == NULL) strcat(FullFileName, ".dat");
-
- if ((f = fopen(FullFileName, "r")) == NULL)
- ParserError(DP_ERR_OPEN_FAILED, FullFileName);
-
- GlblToken = 0; /* Used in UnGetToken token buffer. */
- DPGlblParserError = DP_NO_ERR; /* Reset errors. */
- GlblLineCount = 1; /* Reset line counter. */
-
- PObj = AllocObject("", OBJ_LIST_OBJ, NULL);
- DataPrsrGetAllObjects(f, PObj);
-
- if (PObj -> ObjType == OBJ_LIST_OBJ &&
- PObj -> U.PObjList[1] == NULL)
- {
- /* Only one object in list - return the object instead. */
- PTmp = PObj -> U.PObjList[0];
- PObj -> U.PObjList[0] = NULL;
- MyFree((char *) PObj, ALLOC_OBJECT);
- PObj = PTmp;
- }
-
- fclose(f);
- return PObj;
- }
-
- /*****************************************************************************
- * Same as fprintf but with indentation. Prints into global OutputFile unless *
- * it is NULL in which it prints to screen using WndwInputWindowPutStr *
- *****************************************************************************/
- #ifdef USE_VARARGS
- static void IFprintf(int Indent, char *va_alist, ...)
- {
- char *Format, Line[LINE_LEN_LONG];
- int i;
- va_list ArgPtr;
-
- va_start(ArgPtr);
- Format = va_arg(ArgPtr, char *);
- #else
- static void IFprintf(int Indent, char *Format, ...)
- {
- char Line[LINE_LEN_LONG];
- int i;
- va_list ArgPtr;
-
- va_start(ArgPtr, Format);
- #endif /* USE_VARARGS */
-
- for (i = 0; i < Indent; i++) Line[i] = ' ';
- vsprintf(&Line[Indent], Format, ArgPtr);
- va_end(ArgPtr);
-
- if (OutputFile != NULL)
- fputs(Line, OutputFile);
- else
- WndwInputWindowPutStr(Line);
- }
-
- /*****************************************************************************
- * Routine to print the data from given geometry object. *
- *****************************************************************************/
- static void DataPrsrPutAllObjects(ObjectStruct *PObj, int Indent)
- {
- int i;
- char
- *ErrStr = NULL;
- CagdRType *Coords;
- PolygonStruct *PPolygon;
- VertexStruct *PVertex;
-
- if (IS_GEOM_OBJ(PObj)) {
- AttributeStruct
- *Attr = &(PObj -> U.Attr);
-
- IFprintf(Indent, "[OBJECT [COLOR %d]", GetObjectColor(PObj));
-
- if (Attr -> NumStrAttribs > 0) {
- IFprintf(0, "\n");
- for (i = 0; i < Attr -> NumStrAttribs; i++)
- IFprintf(Indent + 8,
- i == Attr -> NumStrAttribs - 1 ? "[%s %s]" : "[%s %s]\n",
- Attr -> StrAttrName[i], Attr -> StrAttrData[i]);
- IFprintf(0, " %s\n",
- strlen(PObj -> Name) ? PObj -> Name : "NONE");
- }
- else
- IFprintf(0, " %s\n",
- strlen(PObj -> Name) ? PObj -> Name : "NONE");
- }
- else
- IFprintf(Indent, "[OBJECT %s\n",
- strlen(PObj -> Name) ? PObj -> Name : "NONE");
-
- Indent += 4;
-
- switch (PObj -> ObjType) {
- case POLY_OBJ:
- for (PPolygon = PObj -> U.Pl.P;
- PPolygon != NULL;
- PPolygon = PPolygon -> Pnext) {
- if (PPolygon -> V == NULL)
- FatalError("Dump: Attemp to dump empty polygon, exit\n");
- for (PVertex = PPolygon -> V -> Pnext, i = 1;
- PVertex != PPolygon -> V && PVertex != NULL;
- PVertex = PVertex -> Pnext, i++);
- if (IS_POLYLINE_OBJ(PObj))
- IFprintf(Indent, "[POLYLINE %d\n", i);
- else
- IFprintf(Indent, "[POLYGON [PLANE %s %s %s %s] %d\n",
- Real2Str(PPolygon -> Plane[0]),
- Real2Str(PPolygon -> Plane[1]),
- Real2Str(PPolygon -> Plane[2]),
- Real2Str(PPolygon -> Plane[3]), i);
-
- PVertex = PPolygon -> V;
- do { /* Assume at least one edge in polygon! */
- if (IS_POLYLINE_OBJ(PObj))
- IFprintf(Indent + 4, "[%s%s %s %s]\n",
- IS_INTERNAL_EDGE(PVertex) ? "[INTERNAL] " : "",
- Real2Str(PVertex -> Pt[0]),
- Real2Str(PVertex -> Pt[1]),
- Real2Str(PVertex -> Pt[2]));
- else
- IFprintf(Indent + 4, "[%s[NORMAL %s %s %s] %s %s %s]\n",
- IS_INTERNAL_EDGE(PVertex) ? "[INTERNAL] " : "",
- Real2Str(PVertex -> Normal[0]),
- Real2Str(PVertex -> Normal[1]),
- Real2Str(PVertex -> Normal[2]),
- Real2Str(PVertex -> Pt[0]),
- Real2Str(PVertex -> Pt[1]),
- Real2Str(PVertex -> Pt[2]));
-
- PVertex = PVertex -> Pnext;
- }
- while (PVertex != PPolygon -> V && PVertex != NULL);
- IFprintf(Indent, "]\n"); /* Close the polygon. */
- }
- break;
- case NUMERIC_OBJ:
- IFprintf(Indent, "[NUMBER %s]\n", Real2Str(PObj -> U.R));
- break;
- case VECTOR_OBJ:
- IFprintf(Indent, "[VECTOR %s %s %s]\n",
- Real2Str(PObj -> U.Vec[0]),
- Real2Str(PObj -> U.Vec[1]),
- Real2Str(PObj -> U.Vec[2]));
- break;
- case CTLPT_OBJ:
- Coords = PObj -> U.CtlPt.Coords;
- switch (PObj -> U.CtlPt.PtType) {
- case CAGD_PT_E2_TYPE:
- IFprintf(Indent, "[CTLPT %s %s %s]\n", "E2",
- Real2Str(Coords[1]),
- Real2Str(Coords[2]));
- break;
- case CAGD_PT_P2_TYPE:
- IFprintf(Indent, "[CTLPT %s %s %s %s]\n", "P2",
- Real2Str(Coords[0]),
- Real2Str(Coords[1]),
- Real2Str(Coords[2]));
- break;
- case CAGD_PT_E3_TYPE:
- IFprintf(Indent, "[CTLPT %s %s %s %s]\n", "E3",
- Real2Str(Coords[1]),
- Real2Str(Coords[2]),
- Real2Str(Coords[3]));
- break;
- case CAGD_PT_P3_TYPE:
- IFprintf(Indent, "[CTLPT %s %s %s %s %s]\n", "P3",
- Real2Str(Coords[0]),
- Real2Str(Coords[1]),
- Real2Str(Coords[2]),
- Real2Str(Coords[3]));
- break;
- default:
- WndwInputWindowPutStr("Dump: Undefined point type");
- break;
- }
- break;
- case MATRIX_OBJ:
- IFprintf(Indent, "[MATRIX\n");
- for (i = 0; i < 4; i++)
- IFprintf(Indent + 8, "%s %s %s %s%s\n",
- Real2Str(PObj -> U.Mat[i][0]),
- Real2Str(PObj -> U.Mat[i][1]),
- Real2Str(PObj -> U.Mat[i][2]),
- Real2Str(PObj -> U.Mat[i][3]),
- i == 3 ? "]" : "");
- break;
- case STRING_OBJ:
- IFprintf(Indent, "[STRING \"%s\"]\n", PObj -> U.Str);
- break;
- case OBJ_LIST_OBJ:
- for (i = 0; PObj -> U.PObjList[i] != NULL; i++)
- DataPrsrPutAllObjects(PObj -> U.PObjList[i], Indent);
- break;
- case CURVE_OBJ:
- CagdCrvWriteToFile2(PObj -> U.Crv.Crv, OutputFile, Indent, NULL, &ErrStr);
- break;
- case SURFACE_OBJ:
- CagdSrfWriteToFile2(PObj -> U.Srf.Srf, OutputFile, Indent, NULL, &ErrStr);
- break;
- default:
- WndwInputWindowPutStr(
- "Dump: Attemp to dump undefine object type.");
- break;
- }
-
- Indent -= 4;
- IFprintf(Indent, "]\n"); /* Close the object. */
-
- if (ErrStr != NULL) ParserError(DP_ERR_CAGD_LIB_ERR, ErrStr);
- }
-
- /*****************************************************************************
- * Convert a real number into a string. *
- * The routine maintains 6 different buffers simultanuously so up to 6 calls *
- * can be issued from same printf... *
- *****************************************************************************/
- static char *Real2Str(RealType R)
- {
- static int j, k,
- i = 0;
- static char Buffer[6][LINE_LEN_SHORT], Line[LINE_LEN];
-
- if (ABS(R) < EPSILON) R = 0.0; /* Round off very small numbers. */
-
- # ifdef DOUBLE
- sprintf(Buffer[i], "%-8.6lg", R);
- # else
- sprintf(Buffer[i], "%-8.6g", R);
- # endif /* DOUBLE */
-
- for (k = 0; !isdigit(Buffer[i][k]) && k < LINE_LEN; k++);
- if (k >= LINE_LEN) {
- sprintf(Line, "Conversion of real number (%f) failed.\n", R);
- FatalError(Line);
- }
-
- for (j = strlen(Buffer[i]) - 1; Buffer[i][j] == ' ' && j > k; j--);
- if (strchr(Buffer[i], '.') != NULL)
- for (; Buffer[i][j] == '0' && j > k; j--);
- Buffer[i][j+1] = 0;
-
- j = i;
- i = (i + 1) % 6;
- return Buffer[j];
- }
-
- /*****************************************************************************
- * 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 DataPrsrGetAllObjects(FILE *f, ObjectStruct *PObjParent)
- {
- char StringToken[LINE_LEN];
- TokenType Token;
- int ObjCount = 0,
- Quit = FALSE;
- ObjectStruct *PObj, *OldPObj;
-
- 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:
- PObjParent -> ObjType = OBJ_LIST_OBJ;
-
- PObj = AllocObject("", UNDEF_OBJ, NULL);
-
- /* The following handle optional attributes in record. */
- if (GetToken(f, StringToken) == TOKEN_OPEN_PAREN)
- GetObjectAttributes(PObj, f);
- else
- {
- SetObjectColor(PObj, GlblLoadColor);
- UnGetToken(StringToken);
- }
-
- if (GetToken(f, StringToken) == TOKEN_OTHER &&
- strcmp(StringToken, "NONE") != 0)
- strcpy(PObj -> Name, StringToken);
-
- DataPrsrGetAllObjects(f, PObj);
-
- GetCloseParenToken(f);
-
- if (PObj -> ObjType == UNDEF_OBJ)
- ParserError(DP_ERR_OBJECT_EMPTY, "");
-
- PObjParent -> U.PObjList[ObjCount++] = PObj;
-
- if ((int) strlen(PObj -> Name) > 0) {
- if ((OldPObj = GetObject(PObj -> Name)) != NULL)
- DeleteObject(OldPObj, TRUE);
- InsertObject(PObj);
- PObj -> Count++;
- }
- break;
- default:
- UnGetToken(StringToken);
- UnGetToken("[");
- DataPrsrGetAuxObject(f, PObjParent);
- Quit = TRUE;
- break;
- }
- }
-
- if (PObjParent -> ObjType == UNDEF_OBJ)
- ParserError(DP_ERR_OBJECT_EMPTY, "");
- else if (PObjParent -> ObjType == OBJ_LIST_OBJ)
- PObjParent -> U.PObjList[ObjCount++] = NULL;
- }
-
- /*****************************************************************************
- * Routine to get close paren token from f. *
- *****************************************************************************/
- static void GetCloseParenToken(FILE *f)
- {
- char StringToken[LINE_LEN];
-
- if (GetToken(f, StringToken) != TOKEN_CLOSE_PAREN)
- ParserError(DP_ERR_CLOSE_PAREN_EXPECTED, StringToken);
- }
-
- /*****************************************************************************
- * Routine to get one numeric token into r. *
- *****************************************************************************/
- static void GetNumericToken(FILE *f, RealType *r)
- {
- char StringToken[LINE_LEN];
-
- GetToken(f, StringToken);
- # ifdef DOUBLE
- if (sscanf(StringToken, "%lf", r) != 1)
- # else
- if (sscanf(StringToken, "%f", r) != 1)
- # endif /* DOUBLE */
- ParserError(DP_ERR_NUMBER_EXPECTED, StringToken);
- }
-
- /*****************************************************************************
- * Routine to read the geometry data from a given file. *
- *****************************************************************************/
- static void DataPrsrGetAuxObject(FILE *f, ObjectStruct *PObj)
- {
- int i, j, ErrLine, HasPlane, HasNormal;
- char *p1, *p2, *ErrStr, StringToken[LINE_LEN];
- CagdRType *Coords;
- VertexStruct *PVertex;
- PolygonStruct *PPolygon;
- CagdCrvStruct *PCurve;
- CagdSrfStruct *PSurface;
-
- while (GetToken(f, StringToken) == TOKEN_OPEN_PAREN) {
- switch (GetToken(f, StringToken)) {
- case TOKEN_POLYLINE:
- switch (PObj -> ObjType) {
- case POLY_OBJ:
- if (!IS_POLYLINE_OBJ(PObj))
- ParserError(DP_ERR_MIXED_TYPES, "");
- break;
- case UNDEF_OBJ:
- PObj -> ObjType = POLY_OBJ;
- PObj -> U.Pl.P = NULL;
- SET_POLYLINE_OBJ(PObj);
- break;
- default:
- ParserError(DP_ERR_MIXED_TYPES, "");
- break;
- }
-
- PPolygon = AllocPolygon(0, 0, NULL, NULL);
-
- /* The following handle the optional attributes in struct. */
- if (GetToken(f, StringToken) == TOKEN_OPEN_PAREN)
- GetPolygonAttributes(PPolygon, f, &HasPlane);
- else
- UnGetToken(StringToken);
-
- /* The following handles reading the vertices. */
- GetPointData(f, PPolygon, TRUE, &HasNormal);
-
- PPolygon -> Pnext = PObj -> U.Pl.P;
- PObj -> U.Pl.P = PPolygon;
- break;
- case TOKEN_POLYGON:
- switch (PObj -> ObjType) {
- case POLY_OBJ:
- if (IS_POLYLINE_OBJ(PObj))
- ParserError(DP_ERR_MIXED_TYPES, "");
- break;
- case UNDEF_OBJ:
- PObj -> ObjType = POLY_OBJ;
- PObj -> U.Pl.P = NULL;
- RST_POLYLINE_OBJ(PObj);
- break;
- default:
- ParserError(DP_ERR_MIXED_TYPES, "");
- break;
- }
-
- PPolygon = AllocPolygon(0, 0, NULL, NULL);
-
- /* The following handle the optional attributes in struct. */
- HasPlane = HasNormal = FALSE;
- if (GetToken(f, StringToken) == TOKEN_OPEN_PAREN)
- GetPolygonAttributes(PPolygon, f, &HasPlane);
- else
- UnGetToken(StringToken);
-
- /* The following handles reading the vertices. */
- GetPointData(f, PPolygon, FALSE, &HasNormal);
-
- if (!HasPlane) DPUpdatePolyPlane(PPolygon);
- if (!HasNormal) {
- /* Update all normals to be the same as plane eqn. */
- PVertex = PPolygon -> V;
- do {
- PT_COPY(PVertex -> Normal, PPolygon -> Plane);
- PVertex = PVertex -> Pnext;
- }
- while (PVertex != PPolygon -> V && PVertex != NULL);
- }
- PPolygon -> Pnext = PObj -> U.Pl.P;
- PObj -> U.Pl.P = PPolygon;
- break;
- case TOKEN_NUMBER:
- switch (PObj -> ObjType) {
- case NUMERIC_OBJ:
- break;
- case UNDEF_OBJ:
- PObj -> ObjType = NUMERIC_OBJ;
- break;
- default:
- ParserError(DP_ERR_MIXED_TYPES, "");
- break;
- }
- GetNumericToken(f, &PObj -> U.R);
- GetCloseParenToken(f);
- break;
- case TOKEN_STRING:
- switch (PObj -> ObjType) {
- case STRING_OBJ:
- break;
- case UNDEF_OBJ:
- PObj -> ObjType = STRING_OBJ;
- break;
- default:
- ParserError(DP_ERR_MIXED_TYPES, "");
- break;
- }
- GetToken(f, StringToken);
- if ((p1 = strchr(StringToken, '"')) == NULL ||
- (p2 = strrchr(StringToken, '"')) == p1)
- ParserError(DP_STR_NOT_IN_QUOTES, StringToken);
-
- /* Convert the end quote to EOS and copy string. */
- *p2 = 0;
- strcpy(PObj -> U.Str, &p1[1]);
-
- GetCloseParenToken(f);
- break;
- case TOKEN_VECTOR:
- switch (PObj -> ObjType) {
- case VECTOR_OBJ:
- break;
- case UNDEF_OBJ:
- PObj -> ObjType = VECTOR_OBJ;
- break;
- default:
- ParserError(DP_ERR_MIXED_TYPES, "");
- break;
- }
- for (i = 0; i < 3; i++)
- GetNumericToken(f, &PObj -> U.Vec[i]);
- GetCloseParenToken(f);
- break;
- case TOKEN_MATRIX:
- switch (PObj -> ObjType) {
- case MATRIX_OBJ:
- break;
- case UNDEF_OBJ:
- PObj -> ObjType = MATRIX_OBJ;
- break;
- default:
- ParserError(DP_ERR_MIXED_TYPES, "");
- break;
- }
- for (i = 0; i < 4; i++)
- for (j = 0; j < 4; j++)
- GetNumericToken(f, &PObj -> U.Mat[i][j]);
- GetCloseParenToken(f);
- break;
- case TOKEN_CTLPT:
- switch (PObj -> ObjType) {
- case CTLPT_OBJ:
- break;
- case UNDEF_OBJ:
- PObj -> ObjType = CTLPT_OBJ;
- break;
- default:
- ParserError(DP_ERR_MIXED_TYPES, "");
- break;
- }
-
- switch (GetToken(f, StringToken)) {
- case TOKEN_E2:
- PObj -> U.CtlPt.PtType = CAGD_PT_E2_TYPE;
- j = 2;
- i = 1;
- break;
- case TOKEN_P2:
- PObj -> U.CtlPt.PtType = CAGD_PT_P2_TYPE;
- j = 3;
- i = 0;
- break;
- case TOKEN_E3:
- PObj -> U.CtlPt.PtType = CAGD_PT_E3_TYPE;
- j = 3;
- i = 1;
- break;
- case TOKEN_P3:
- PObj -> U.CtlPt.PtType = CAGD_PT_P3_TYPE;
- j = 4;
- i = 0;
- break;
- default:
- WndwInputWindowPutStr("Read: Undefined point type");
- break;
- }
-
- Coords = PObj -> U.CtlPt.Coords;
- for ( ; j > 0; i++, j--)
- GetNumericToken(f, &Coords[i]);
- GetCloseParenToken(f);
- break;
- case TOKEN_SURFACE:
- switch (PObj -> ObjType) {
- case SURFACE_OBJ:
- break;
- case UNDEF_OBJ:
- PObj -> ObjType = SURFACE_OBJ;
- PObj -> U.Srf.Srf = NULL;
- PObj -> U.Srf.PLPolys = NULL;
- PObj -> U.Srf.CtlMesh = NULL;
- PObj -> U.Srf.Polygons = NULL;
- break;
- default:
- ParserError(DP_ERR_MIXED_TYPES, "");
- break;
- }
-
- ErrLine = GlblLineCount;
- PSurface = CagdSrfReadFromFile2(f, &ErrStr, &ErrLine);
- GlblLineCount = ErrLine;
- if (ErrStr != NULL) {
- ParserError(DP_ERR_CAGD_LIB_ERR, ErrStr);
- break;
- }
-
- PSurface -> Pnext = PObj -> U.Srf.Srf;
- PObj -> U.Srf.Srf = PSurface;
- break;
- case TOKEN_CURVE:
- switch (PObj -> ObjType) {
- case CURVE_OBJ:
- break;
- case UNDEF_OBJ:
- PObj -> ObjType = CURVE_OBJ;
- PObj -> U.Crv.Crv = NULL;
- PObj -> U.Crv.PLPolys = NULL;
- PObj -> U.Crv.CtlPoly = NULL;
- break;
- default:
- ParserError(DP_ERR_MIXED_TYPES, "");
- break;
- }
-
- ErrLine = GlblLineCount;
- PCurve = CagdCrvReadFromFile2(f, &ErrStr, &ErrLine);
- GlblLineCount = ErrLine;
- if (ErrStr != NULL) {
- ParserError(DP_ERR_CAGD_LIB_ERR, ErrStr);
- break;
- }
-
- PCurve -> Pnext = PObj -> U.Crv.Crv;
- PObj -> U.Crv.Crv = PCurve;
- break;
- default:
- ParserError(DP_ERR_UNDEF_EXPR_HEADER, StringToken);
- break;
- } /* Of switch. */
- } /* Of while. */
-
- UnGetToken(StringToken);
- }
-
- /*****************************************************************************
- * Routine to unget one token (on stack of UNGET_STACK_SIZE levels!) *
- *****************************************************************************/
- static void UnGetToken(char *StringToken)
- {
- if (GlblToken >= UNGET_STACK_SIZE)
- FatalError("Parser Internal stack overflow...\n");
-
- 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_OBJECT,
- TOKEN_COLOR,
- 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",
- "OBJECT",
- "COLOR",
- "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. *
- * Current supported attributes: [INTERNAL] - internal edge (IRIT output). *
- *****************************************************************************/
- static void GetVertexAttributes(VertexStruct *PVertex, FILE *f,
- int *HasNormal)
- {
- int i;
- char StringToken[LINE_LEN];
-
- do {
- switch (GetToken(f, StringToken)) {
- case TOKEN_INTERNAL:
- if (GetToken(f, StringToken) != TOKEN_CLOSE_PAREN)
- ParserError(DP_ERR_CLOSE_PAREN_EXPECTED, StringToken);
- SET_INTERNAL_EDGE(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]);
-
- GetCloseParenToken(f);
- *HasNormal = TRUE;
- break;
- default: /* Ignore this option! */
- while (GetToken(f, StringToken) != TOKEN_CLOSE_PAREN);
- 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. *
- * Current supported attributes: [PLANE A B C D]. *
- *****************************************************************************/
- static void GetPolygonAttributes(PolygonStruct *PPolygon, FILE *f,
- int *HasPlane)
- {
- int i;
- char StringToken[LINE_LEN];
-
- 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]);
- GetCloseParenToken(f);
- *HasPlane = TRUE;
- break;
- default:
- while (GetToken(f, StringToken) != TOKEN_CLOSE_PAREN);
- 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. *
- * Current supported attributes: [COLOR C] - set color. *
- * All other attributes are treated as String attributes. *
- *****************************************************************************/
- static void GetObjectAttributes(ObjectStruct *PObject, FILE *f)
- {
- int i;
- char StringToken[LINE_LEN], Data[LINE_LEN], Name[LINE_LEN];
-
- do {
- switch (GetToken(f, StringToken)) {
- case TOKEN_COLOR:
- GetToken(f, StringToken);
- if (sscanf(StringToken, "%d", &i) != 1)
- ParserError(DP_ERR_NUMBER_EXPECTED, StringToken);
- GetCloseParenToken(f);
- SetObjectColor(PObject, i);
- break;
- default:
- strcpy(Name, StringToken);
- strcpy(Data, " ");
- while (GetToken(f, StringToken) != TOKEN_CLOSE_PAREN) {
- strcat(Data, StringToken);
- strcat(Data, " ");
- }
- SetObjectStrAttrib(PObject, Name, Data);
- break;
- }
- }
- while (GetToken(f, StringToken) == TOKEN_OPEN_PAREN);
-
- UnGetToken(StringToken);
- }
-
- /*****************************************************************************
- * Routine to read poly* vertex information. *
- *****************************************************************************/
- static void GetPointData(FILE *f, PolygonStruct *PPolygon, int IsPolyline,
- int *HasNormal)
- {
- int i, j, Length;
- char StringToken[LINE_LEN];
- VertexStruct *V,
- *VTail = NULL;
-
- if (GetToken(f, StringToken) != TOKEN_OTHER ||
- sscanf(StringToken, "%d", &Length) != 1)
- ParserError(DP_ERR_NUMBER_EXPECTED, StringToken);
-
- for (i = 0; i < Length; i++) {
- if (GetToken(f, StringToken) != TOKEN_OPEN_PAREN)
- ParserError(DP_ERR_OPEN_PAREN_EXPECTED, StringToken);
-
- V = AllocVertex(0, 0, NULL, NULL);
-
- /* The following handle the optional attributes in struct. */
- *HasNormal = FALSE;
- if (GetToken(f, StringToken) == TOKEN_OPEN_PAREN)
- GetVertexAttributes(V, f, HasNormal);
- else
- UnGetToken(StringToken);
-
- for (j = 0; j < 3; j++) /* Read coordinates. */
- GetNumericToken(f, &V -> Pt[j]);
-
- GetCloseParenToken(f);
-
- if (!*HasNormal)
- PT_COPY(V -> Normal, PPolygon -> Plane);
-
- if (VTail == NULL)
- PPolygon -> V = VTail = V;
- else {
- VTail -> Pnext = V;
- VTail = V;
- }
- }
- VTail -> Pnext = IsPolyline ? NULL : PPolygon -> V;
-
- 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 DPUpdatePolyPlane(PolygonStruct *PPoly)
- {
- int i;
- VectorType V1, V2;
- RealType Len;
- VertexStruct *V;
-
- V = PPoly -> V; PT_SUB(V1, V -> Pt, V -> Pnext -> Pt);
- V = V -> Pnext; PT_SUB(V2, V -> Pt, V -> Pnext -> Pt);
-
- 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 -> V -> Pt));
-
- /* 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 print pasring error according to ErrNum and set GlblParserError.*
- *****************************************************************************/
- static void ParserError(DataPrsrErrType ErrNum, char *Msg)
- {
- DPGlblLineCount = GlblLineCount;
- DPGlblParserError = ErrNum;
- strcpy(DPGlblTokenError, 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 DataPrsrParseError(char **ErrorMsg)
- {
- DataPrsrErrType Temp;
- char TempCopy[LINE_LEN];
-
- if ((Temp = DPGlblParserError) == DP_NO_ERR) return FALSE;
-
- strcpy(TempCopy, DPGlblTokenError);
- DPGlblParserError = DP_NO_ERR;
-
- switch (Temp) {
- case DP_ERR_NUMBER_EXPECTED:
- sprintf(DPGlblTokenError, "Line %d: Numeric data expected - found %s",
- DPGlblLineCount, TempCopy);
- break;
- case DP_ERR_OPEN_PAREN_EXPECTED:
- sprintf(DPGlblTokenError, "Line %d: '[' expected - found '%s'",
- DPGlblLineCount, TempCopy);
- break;
- case DP_ERR_CLOSE_PAREN_EXPECTED:
- sprintf(DPGlblTokenError, "Line %d: ']' expected - found '%s'",
- DPGlblLineCount, TempCopy);
- break;
- case DP_ERR_LIST_COMP_UNDEF:
- sprintf(DPGlblTokenError, "Line %d: Undefined list element - \"%s\"",
- DPGlblLineCount, TempCopy);
- break;
- case DP_ERR_UNDEF_EXPR_HEADER:
- sprintf(DPGlblTokenError, "Line %d: Undefined TOKEN - \"%s\"",
- DPGlblLineCount, TempCopy);
- break;
- case DP_ERR_PT_TYPE_EXPECTED:
- sprintf(DPGlblTokenError, "Line %d: Point type expected",
- DPGlblLineCount);
- break;
- case DP_ERR_OBJECT_EMPTY:
- sprintf(DPGlblTokenError, "Line %d: Empty object found",
- DPGlblLineCount);
- break;
- case DP_ERR_EMPTY_NAME:
- sprintf(DPGlblTokenError, "Given file name is empty");
- break;
- case DP_ERR_OPEN_FAILED:
- sprintf(DPGlblTokenError, "Fail to open file - %s", TempCopy);
- break;
- case DP_ERR_MIXED_TYPES:
- sprintf(DPGlblTokenError,
- "Line %d: Mixed data types in same object",
- DPGlblLineCount);
- break;
- case DP_STR_NOT_IN_QUOTES:
- sprintf(DPGlblTokenError,
- "Line %d: String not in quotes (%s)",
- DPGlblLineCount, TempCopy);
- break;
- case DP_ERR_CAGD_LIB_ERR:
- sprintf(DPGlblTokenError, "Line %d: %s",
- DPGlblLineCount, TempCopy);
- break;
- default:
- sprintf(DPGlblTokenError,
- "Line %d: Data file parser - undefined error",
- DPGlblLineCount);
- break;
- }
-
- *ErrorMsg = DPGlblTokenError;
-
- return TRUE;
- }
-