home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / i / iritsm3s.zip / irit / dataprsr.c < prev    next >
C/C++ Source or Header  |  1992-02-29  |  34KB  |  1,165 lines

  1. /*****************************************************************************
  2. *   "Irit" - the 3d polygonal solid modeller.                     *
  3. *                                         *
  4. * Written by:  Gershon Elber                Ver 0.2, Mar. 1990   *
  5. ******************************************************************************
  6. * Data File Interpreter module - handle data files - to/from geom objects    *
  7. *****************************************************************************/
  8.  
  9. #ifdef USE_VARARGS
  10. #include <varargs.h>
  11. #else
  12. #include <stdarg.h>
  13. #endif /* USE_VARARGS */
  14.  
  15. #include <stdio.h>
  16. #include <ctype.h>
  17. #include <math.h>
  18. #include <string.h>
  19. #include "program.h"
  20. #include "cagd_lib.h"
  21. #include "allocate.h"
  22. #include "attribut.h"
  23. #include "dataprsr.h"                /* Visible to the other modules. */
  24. #include "geomat3d.h"
  25. #include "objects.h"
  26. #include "windows.h"
  27. #include "graphgen.h"
  28.  
  29. #define UNGET_STACK_SIZE    5             /* Internal stack size. */
  30.  
  31. typedef enum {              /* List of all possible tokens enumerated. */
  32.     TOKEN_NONE,
  33.  
  34.     TOKEN_OPEN_PAREN,
  35.     TOKEN_CLOSE_PAREN,
  36.  
  37.     TOKEN_E2,
  38.     TOKEN_P2,
  39.     TOKEN_E3,
  40.     TOKEN_P3,
  41.  
  42.     TOKEN_NUMBER,
  43.     TOKEN_STRING,
  44.     TOKEN_VECTOR,
  45.     TOKEN_MATRIX,
  46.     TOKEN_CTLPT,
  47.     TOKEN_VERTEX,
  48.     TOKEN_POLYGON,
  49.     TOKEN_POLYLINE,
  50.     TOKEN_OBJECT,
  51.     TOKEN_COLOR,
  52.     TOKEN_INTERNAL,
  53.     TOKEN_NORMAL,
  54.     TOKEN_PLANE,
  55.     TOKEN_CURVE,
  56.     TOKEN_SURFACE,
  57.  
  58.     TOKEN_OTHER    = 100,            /* Probably names & numbers. */
  59.     TOKEN_EOF = -1
  60. } TokenType;
  61.  
  62. typedef enum {             /* Possible error code during data parsing. */
  63.     DP_NO_ERR = 0,
  64.  
  65.     DP_ERR_NUMBER_EXPECTED,
  66.     DP_ERR_OPEN_PAREN_EXPECTED,
  67.     DP_ERR_CLOSE_PAREN_EXPECTED,
  68.     DP_ERR_LIST_COMP_UNDEF,
  69.     DP_ERR_UNDEF_EXPR_HEADER,
  70.     DP_ERR_PT_TYPE_EXPECTED,
  71.     DP_ERR_OBJECT_EMPTY,
  72.     DP_ERR_EMPTY_NAME,
  73.     DP_ERR_OPEN_FAILED,
  74.     DP_ERR_MIXED_TYPES,
  75.     DP_STR_NOT_IN_QUOTES,
  76.     DP_ERR_CAGD_LIB_ERR,
  77.  
  78.     DP_WRN_OBJ_NAME_TRUNC = 100
  79. } DataPrsrErrType;
  80.  
  81. static int  DPGlblLineCount = 0;     /* Used to locate errors in input file. */
  82. static DataPrsrErrType DPGlblParserError = DP_NO_ERR;   /* Last err # found. */
  83. static char DPGlblTokenError[LINE_LEN]; /* Last token where error was found. */
  84. static jmp_buf LclLongJumpBuffer;           /* Used in error traping. */
  85. static int  GlblToken =    0,          /* Used by the parser, to unget token. */
  86.         GlblLineCount = 1;         /* Used to locate errors in input file. */
  87. static char GlblStringToken[UNGET_STACK_SIZE][LINE_LEN];/* Save unget tokens.*/
  88. static FILE *OutputFile = NULL;
  89.  
  90. static void UnGetToken(char *StringToken);
  91. static void GetStringToken(FILE *f, char *StringToken);
  92. static TokenType GetToken(FILE *f, char *StringToken);
  93. static void GetVertexAttributes(VertexStruct *PVertex, FILE *f,
  94.                                   int *HasNormal);
  95. static void GetPolygonAttributes(PolygonStruct *PPolygon, FILE *f,
  96.                                 int *HasPlane);
  97. static void GetObjectAttributes(ObjectStruct *PObject, FILE *f);
  98. static void GetPointData(FILE *f, PolygonStruct *PPolygon, int IsPolyline,
  99.                             int *HasNormal);
  100. static void DPUpdatePolyPlane(PolygonStruct *PPoly);
  101. static void ParserError(DataPrsrErrType ErrNum, char *Msg);
  102. static void DataPrsrPutAllObjects(ObjectStruct *PObj, int Indent);
  103. static char *Real2Str(RealType R);
  104. static void DataPrsrGetAllObjects(FILE *f, ObjectStruct *PObjParent);
  105. static void GetCloseParenToken(FILE *f);
  106. static void GetNumericToken(FILE *f, RealType *r);
  107. static void DataPrsrGetAuxObject(FILE *f, ObjectStruct *PObj);
  108.  
  109. #ifdef USE_VARARGS
  110. static void IFprintf(int Indent, char *va_alist, ...);
  111. #else
  112. static void IFprintf(int Indent, char *Format, ...);
  113. #endif /* USE_VARARGS */
  114.  
  115. /*****************************************************************************
  116. * Routine to print the data from given object into given file FileName.         *
  117. * If FileName is NULL or empty, print to screen using WndwInputWindowPutStr. *
  118. *****************************************************************************/
  119. void DataPrsrPutObject(char *FileName, ObjectStruct *PObj)
  120. {
  121.     char *Pchar;
  122.     char FullFileName[LINE_LEN];
  123.  
  124.     DPGlblParserError = DP_NO_ERR;
  125.  
  126.     /* If the following gain control and is non zero - its from error! */
  127.     if (setjmp(LclLongJumpBuffer) != 0) {
  128.     if (OutputFile != NULL) fclose(OutputFile);
  129.     return;
  130.     }
  131.  
  132.     if (FileName && (int) strlen(FileName) > 0) {
  133.         if ((Pchar = strchr(FileName, '.')) != NULL)
  134.         *Pchar = 0;             /* Make sure no file type is given. */
  135.         if (strlen(FileName) == 0) ParserError(DP_ERR_EMPTY_NAME, "");
  136.  
  137.         strcpy(FullFileName, FileName);
  138.         strcat(FullFileName, ".dat");
  139.  
  140.         if ((OutputFile = fopen(FullFileName, "w")) == NULL)
  141.             ParserError(DP_ERR_OPEN_FAILED, FullFileName);
  142.     }
  143.     else
  144.     OutputFile = NULL;
  145.  
  146.     DataPrsrPutAllObjects(PObj, 0);
  147.  
  148.     if (OutputFile) {
  149.     fclose(OutputFile);
  150.     OutputFile = NULL;
  151.     }
  152.  
  153.     return;
  154. }
  155.  
  156. /*****************************************************************************
  157. * Routine to read the data from    a given    file.                     *
  158. *****************************************************************************/
  159. ObjectStruct *DataPrsrGetObjects(char *FileName)
  160. {
  161.     char FullFileName[LINE_LEN];
  162.     FILE
  163.     *f = NULL;
  164.     ObjectStruct *PObj, *PTmp;
  165.  
  166.     /* If the following gain control and is non zero - its from error! */
  167.     if (setjmp(LclLongJumpBuffer) != 0) {
  168.     if (f != NULL) fclose(f);
  169.     return NULL;
  170.     }
  171.  
  172.     if (strlen(FileName) == 0) ParserError(DP_ERR_EMPTY_NAME, "");
  173.  
  174.     strcpy(FullFileName, FileName);
  175.     if (strrchr(FullFileName, '.') == NULL) strcat(FullFileName, ".dat");
  176.  
  177.     if ((f = fopen(FullFileName, "r")) == NULL)
  178.     ParserError(DP_ERR_OPEN_FAILED, FullFileName);
  179.  
  180.     GlblToken =    0;             /* Used in UnGetToken token buffer. */
  181.     DPGlblParserError = DP_NO_ERR;                /* Reset errors. */
  182.     GlblLineCount = 1;                      /* Reset line counter. */
  183.  
  184.     PObj = AllocObject("", OBJ_LIST_OBJ, NULL);
  185.     DataPrsrGetAllObjects(f, PObj);
  186.  
  187.     if (PObj -> ObjType == OBJ_LIST_OBJ &&
  188.     PObj -> U.PObjList[1] == NULL)
  189.     {
  190.     /* Only one object in list - return the object instead. */
  191.     PTmp = PObj -> U.PObjList[0];
  192.     PObj -> U.PObjList[0] = NULL;
  193.     MyFree((char *) PObj, ALLOC_OBJECT);
  194.     PObj = PTmp;
  195.     }
  196.  
  197.     fclose(f);
  198.     return PObj;
  199. }
  200.  
  201. /*****************************************************************************
  202. * Same as fprintf but with indentation. Prints into global OutputFile unless *
  203. * it is NULL in which it prints to screen using WndwInputWindowPutStr         *
  204. *****************************************************************************/
  205. #ifdef USE_VARARGS
  206. static void IFprintf(int Indent, char *va_alist, ...)
  207. {
  208.     char *Format, Line[LINE_LEN_LONG];
  209.     int i;
  210.     va_list ArgPtr;
  211.  
  212.     va_start(ArgPtr);
  213.     Format = va_arg(ArgPtr, char *);
  214. #else
  215. static void IFprintf(int Indent, char *Format, ...)
  216. {
  217.     char Line[LINE_LEN_LONG];
  218.     int i;
  219.     va_list ArgPtr;
  220.  
  221.     va_start(ArgPtr, Format);
  222. #endif /* USE_VARARGS */
  223.  
  224.     for (i = 0; i < Indent; i++) Line[i] = ' ';
  225.     vsprintf(&Line[Indent], Format, ArgPtr);
  226.     va_end(ArgPtr);
  227.  
  228.     if (OutputFile != NULL)
  229.     fputs(Line, OutputFile);
  230.     else
  231.     WndwInputWindowPutStr(Line);
  232. }
  233.  
  234. /*****************************************************************************
  235. * Routine to print the data from given geometry object.                 *
  236. *****************************************************************************/
  237. static void DataPrsrPutAllObjects(ObjectStruct *PObj, int Indent)
  238. {
  239.     int i;
  240.     char
  241.     *ErrStr = NULL;
  242.     CagdRType *Coords;
  243.     PolygonStruct *PPolygon;
  244.     VertexStruct *PVertex;
  245.  
  246.     if (IS_GEOM_OBJ(PObj)) {
  247.     AttributeStruct
  248.         *Attr = &(PObj -> U.Attr);
  249.  
  250.     IFprintf(Indent, "[OBJECT [COLOR %d]", GetObjectColor(PObj));
  251.  
  252.     if (Attr -> NumStrAttribs > 0) {
  253.         IFprintf(0, "\n");
  254.         for (i = 0; i < Attr -> NumStrAttribs; i++)
  255.             IFprintf(Indent + 8,
  256.              i == Attr -> NumStrAttribs - 1 ? "[%s %s]" : "[%s %s]\n",
  257.              Attr -> StrAttrName[i], Attr -> StrAttrData[i]);
  258.         IFprintf(0, " %s\n",
  259.              strlen(PObj -> Name) ? PObj -> Name : "NONE");
  260.     }
  261.     else
  262.             IFprintf(0, " %s\n",
  263.              strlen(PObj -> Name) ? PObj -> Name : "NONE");
  264.     }
  265.     else
  266.     IFprintf(Indent, "[OBJECT %s\n",
  267.              strlen(PObj -> Name) ? PObj -> Name : "NONE");
  268.  
  269.     Indent += 4;
  270.  
  271.     switch (PObj -> ObjType) {
  272.     case POLY_OBJ:
  273.         for (PPolygon = PObj -> U.Pl.P;
  274.          PPolygon != NULL;
  275.          PPolygon = PPolygon -> Pnext) {
  276.         if (PPolygon -> V == NULL)
  277.             FatalError("Dump: Attemp to dump empty polygon, exit\n");
  278.         for (PVertex = PPolygon -> V -> Pnext, i = 1;
  279.              PVertex != PPolygon -> V && PVertex != NULL;
  280.              PVertex = PVertex -> Pnext, i++);
  281.         if (IS_POLYLINE_OBJ(PObj))
  282.             IFprintf(Indent, "[POLYLINE %d\n", i);
  283.         else
  284.             IFprintf(Indent, "[POLYGON [PLANE %s %s %s %s] %d\n",
  285.             Real2Str(PPolygon -> Plane[0]),
  286.             Real2Str(PPolygon -> Plane[1]),
  287.             Real2Str(PPolygon -> Plane[2]),
  288.             Real2Str(PPolygon -> Plane[3]), i);
  289.  
  290.         PVertex = PPolygon -> V;
  291.         do {             /* Assume at least one edge in polygon! */
  292.             if (IS_POLYLINE_OBJ(PObj))
  293.             IFprintf(Indent + 4, "[%s%s %s %s]\n",
  294.                 IS_INTERNAL_EDGE(PVertex) ? "[INTERNAL] " : "",
  295.                 Real2Str(PVertex -> Pt[0]),
  296.                 Real2Str(PVertex -> Pt[1]),
  297.                 Real2Str(PVertex -> Pt[2]));
  298.             else
  299.             IFprintf(Indent + 4, "[%s[NORMAL %s %s %s] %s %s %s]\n",
  300.                 IS_INTERNAL_EDGE(PVertex) ? "[INTERNAL] " : "",
  301.                 Real2Str(PVertex -> Normal[0]),
  302.                 Real2Str(PVertex -> Normal[1]),
  303.                 Real2Str(PVertex -> Normal[2]),
  304.                 Real2Str(PVertex -> Pt[0]),
  305.                 Real2Str(PVertex -> Pt[1]),
  306.                 Real2Str(PVertex -> Pt[2]));
  307.  
  308.             PVertex = PVertex -> Pnext;
  309.         }
  310.         while (PVertex != PPolygon -> V && PVertex != NULL);
  311.         IFprintf(Indent, "]\n");           /* Close the polygon. */
  312.         }
  313.         break;
  314.     case NUMERIC_OBJ:
  315.         IFprintf(Indent, "[NUMBER %s]\n", Real2Str(PObj -> U.R));
  316.         break;
  317.     case VECTOR_OBJ:
  318.         IFprintf(Indent, "[VECTOR %s %s %s]\n",
  319.              Real2Str(PObj -> U.Vec[0]),
  320.              Real2Str(PObj -> U.Vec[1]),
  321.              Real2Str(PObj -> U.Vec[2]));
  322.         break;
  323.     case CTLPT_OBJ:
  324.         Coords = PObj -> U.CtlPt.Coords;
  325.         switch (PObj -> U.CtlPt.PtType) {
  326.         case CAGD_PT_E2_TYPE:
  327.                 IFprintf(Indent, "[CTLPT %s %s %s]\n", "E2",
  328.                  Real2Str(Coords[1]),
  329.                  Real2Str(Coords[2]));
  330.             break;
  331.         case CAGD_PT_P2_TYPE:
  332.                 IFprintf(Indent, "[CTLPT %s %s %s %s]\n", "P2",
  333.                          Real2Str(Coords[0]),
  334.                  Real2Str(Coords[1]),
  335.                  Real2Str(Coords[2]));
  336.             break;
  337.         case CAGD_PT_E3_TYPE:
  338.             IFprintf(Indent, "[CTLPT %s %s %s %s]\n", "E3",
  339.                  Real2Str(Coords[1]),
  340.                  Real2Str(Coords[2]),
  341.                  Real2Str(Coords[3]));
  342.             break;
  343.         case CAGD_PT_P3_TYPE:
  344.                 IFprintf(Indent, "[CTLPT %s %s %s %s %s]\n", "P3",
  345.                  Real2Str(Coords[0]),
  346.                  Real2Str(Coords[1]),
  347.                  Real2Str(Coords[2]),
  348.                  Real2Str(Coords[3]));
  349.             break;
  350.         default:
  351.             WndwInputWindowPutStr("Dump: Undefined point type");
  352.             break;
  353.         }
  354.         break;
  355.     case MATRIX_OBJ:
  356.         IFprintf(Indent, "[MATRIX\n");
  357.         for (i = 0; i < 4; i++)
  358.         IFprintf(Indent + 8, "%s %s %s %s%s\n",
  359.              Real2Str(PObj -> U.Mat[i][0]),
  360.              Real2Str(PObj -> U.Mat[i][1]),
  361.              Real2Str(PObj -> U.Mat[i][2]),
  362.              Real2Str(PObj -> U.Mat[i][3]),
  363.              i == 3 ? "]" : "");
  364.         break;
  365.     case STRING_OBJ:
  366.         IFprintf(Indent, "[STRING \"%s\"]\n", PObj -> U.Str);
  367.         break;
  368.     case OBJ_LIST_OBJ:
  369.         for (i = 0; PObj -> U.PObjList[i] != NULL; i++)
  370.         DataPrsrPutAllObjects(PObj -> U.PObjList[i], Indent);
  371.         break;
  372.     case CURVE_OBJ:
  373.             CagdCrvWriteToFile2(PObj -> U.Crv.Crv, OutputFile, Indent, NULL, &ErrStr);
  374.         break;
  375.     case SURFACE_OBJ:
  376.         CagdSrfWriteToFile2(PObj -> U.Srf.Srf, OutputFile, Indent, NULL, &ErrStr);
  377.         break;
  378.     default:
  379.         WndwInputWindowPutStr(
  380.         "Dump: Attemp to dump undefine object type.");
  381.         break;
  382.     }
  383.  
  384.     Indent -= 4;
  385.     IFprintf(Indent, "]\n");                /* Close the object. */
  386.  
  387.     if (ErrStr != NULL)    ParserError(DP_ERR_CAGD_LIB_ERR, ErrStr);
  388. }
  389.  
  390. /*****************************************************************************
  391. * Convert a real number into a string.                         *
  392. * The routine maintains 6 different buffers simultanuously so up to 6 calls  *
  393. * can be issued from same printf...                         *
  394. *****************************************************************************/
  395. static char *Real2Str(RealType R)
  396. {
  397.     static int j, k,
  398.     i = 0;
  399.     static char Buffer[6][LINE_LEN_SHORT], Line[LINE_LEN];
  400.  
  401.     if (ABS(R) < EPSILON) R = 0.0;        /* Round off very small numbers. */
  402.  
  403. #   ifdef DOUBLE
  404.     sprintf(Buffer[i], "%-8.6lg", R);
  405. #   else
  406.     sprintf(Buffer[i], "%-8.6g", R);
  407. #   endif /* DOUBLE */
  408.  
  409.     for (k = 0; !isdigit(Buffer[i][k]) && k < LINE_LEN; k++);
  410.     if (k >= LINE_LEN) {
  411.     sprintf(Line, "Conversion of real number (%f) failed.\n", R);
  412.     FatalError(Line);
  413.     }
  414.  
  415.     for (j = strlen(Buffer[i]) - 1; Buffer[i][j] == ' ' && j > k; j--);
  416.     if (strchr(Buffer[i], '.') != NULL)
  417.     for (; Buffer[i][j] == '0' && j > k; j--);
  418.     Buffer[i][j+1] = 0;
  419.  
  420.     j = i;
  421.     i = (i + 1) % 6;
  422.     return Buffer[j];
  423. }
  424.  
  425. /*****************************************************************************
  426. * Routine to read the geometry data from a given file. Reads "[OBJECT ..."   *
  427. * prefixes only and invoke the auxiliary routine.                 *
  428. * Note objects may be recursively defined.                     *
  429. *****************************************************************************/
  430. static void DataPrsrGetAllObjects(FILE *f, ObjectStruct *PObjParent)
  431. {
  432.     char StringToken[LINE_LEN];
  433.     TokenType Token;
  434.     int ObjCount = 0,
  435.     Quit = FALSE;
  436.     ObjectStruct *PObj, *OldPObj;
  437.  
  438.     while (!Quit) {
  439.         while ((Token = GetToken(f, StringToken)) != TOKEN_OPEN_PAREN &&
  440.            Token != TOKEN_CLOSE_PAREN &&
  441.            Token != TOKEN_EOF);
  442.  
  443.     if (Token == TOKEN_CLOSE_PAREN || Token == TOKEN_EOF)
  444.     {
  445.         if (Token == TOKEN_CLOSE_PAREN)
  446.         UnGetToken(StringToken);
  447.         Quit = TRUE;
  448.         break;
  449.     }
  450.  
  451.     switch (GetToken(f, StringToken)) {
  452.         case TOKEN_OBJECT:
  453.             PObjParent -> ObjType = OBJ_LIST_OBJ;
  454.  
  455.         PObj = AllocObject("", UNDEF_OBJ, NULL);
  456.  
  457.         /* The following handle optional attributes in record. */
  458.         if (GetToken(f, StringToken) == TOKEN_OPEN_PAREN)
  459.             GetObjectAttributes(PObj, f);
  460.         else
  461.         {
  462.             SetObjectColor(PObj, GlblLoadColor);
  463.             UnGetToken(StringToken);
  464.         }
  465.  
  466.         if (GetToken(f, StringToken) == TOKEN_OTHER &&
  467.             strcmp(StringToken, "NONE") != 0)
  468.             strcpy(PObj -> Name, StringToken);
  469.  
  470.         DataPrsrGetAllObjects(f, PObj);
  471.  
  472.         GetCloseParenToken(f);
  473.  
  474.         if (PObj -> ObjType == UNDEF_OBJ)
  475.             ParserError(DP_ERR_OBJECT_EMPTY, "");
  476.  
  477.         PObjParent -> U.PObjList[ObjCount++] = PObj;
  478.  
  479.         if ((int) strlen(PObj -> Name) > 0) {
  480.             if ((OldPObj = GetObject(PObj -> Name)) != NULL)
  481.             DeleteObject(OldPObj, TRUE);
  482.             InsertObject(PObj);
  483.             PObj -> Count++;
  484.         }
  485.         break;
  486.         default:
  487.         UnGetToken(StringToken);
  488.         UnGetToken("[");
  489.         DataPrsrGetAuxObject(f, PObjParent);
  490.         Quit = TRUE;
  491.         break;
  492.     }
  493.     }
  494.  
  495.     if (PObjParent -> ObjType == UNDEF_OBJ)
  496.     ParserError(DP_ERR_OBJECT_EMPTY, "");
  497.     else if (PObjParent -> ObjType == OBJ_LIST_OBJ)
  498.     PObjParent -> U.PObjList[ObjCount++] = NULL;
  499. }
  500.  
  501. /*****************************************************************************
  502. * Routine to get close paren token from f.                     *
  503. *****************************************************************************/
  504. static void GetCloseParenToken(FILE *f)
  505. {
  506.     char StringToken[LINE_LEN];
  507.  
  508.     if (GetToken(f, StringToken) != TOKEN_CLOSE_PAREN)
  509.     ParserError(DP_ERR_CLOSE_PAREN_EXPECTED, StringToken);
  510. }
  511.  
  512. /*****************************************************************************
  513. * Routine to get one numeric token into r.                     *
  514. *****************************************************************************/
  515. static void GetNumericToken(FILE *f, RealType *r)
  516. {
  517.     char StringToken[LINE_LEN];
  518.  
  519.     GetToken(f, StringToken);
  520. #   ifdef DOUBLE
  521.     if (sscanf(StringToken, "%lf", r) != 1)
  522. #   else
  523.     if (sscanf(StringToken, "%f", r) != 1)
  524. #   endif /* DOUBLE */
  525.         ParserError(DP_ERR_NUMBER_EXPECTED, StringToken);
  526. }
  527.  
  528. /*****************************************************************************
  529. * Routine to read the geometry data from a given file.                 *
  530. *****************************************************************************/
  531. static void DataPrsrGetAuxObject(FILE *f, ObjectStruct *PObj)
  532. {
  533.     int    i, j, ErrLine, HasPlane, HasNormal;
  534.     char *p1, *p2, *ErrStr, StringToken[LINE_LEN];
  535.     CagdRType *Coords;
  536.     VertexStruct *PVertex;
  537.     PolygonStruct *PPolygon;
  538.     CagdCrvStruct *PCurve;
  539.     CagdSrfStruct *PSurface;
  540.  
  541.     while (GetToken(f, StringToken) == TOKEN_OPEN_PAREN) {
  542.     switch (GetToken(f, StringToken)) {
  543.         case TOKEN_POLYLINE:
  544.         switch (PObj -> ObjType) {
  545.             case POLY_OBJ:
  546.             if (!IS_POLYLINE_OBJ(PObj))
  547.                 ParserError(DP_ERR_MIXED_TYPES, "");
  548.             break;
  549.             case UNDEF_OBJ:
  550.             PObj -> ObjType = POLY_OBJ;
  551.             PObj -> U.Pl.P = NULL;
  552.             SET_POLYLINE_OBJ(PObj);
  553.             break;
  554.             default:
  555.             ParserError(DP_ERR_MIXED_TYPES, "");
  556.             break;
  557.         }
  558.  
  559.         PPolygon = AllocPolygon(0, 0, NULL, NULL);
  560.  
  561.         /* The following handle the optional attributes in struct.   */
  562.         if (GetToken(f, StringToken) == TOKEN_OPEN_PAREN)
  563.             GetPolygonAttributes(PPolygon, f, &HasPlane);
  564.         else
  565.             UnGetToken(StringToken);
  566.  
  567.         /* The following handles reading the vertices. */
  568.         GetPointData(f, PPolygon, TRUE, &HasNormal);
  569.  
  570.         PPolygon -> Pnext = PObj -> U.Pl.P;
  571.         PObj -> U.Pl.P = PPolygon;
  572.         break;
  573.         case TOKEN_POLYGON:
  574.         switch (PObj -> ObjType) {
  575.             case POLY_OBJ:
  576.             if (IS_POLYLINE_OBJ(PObj))
  577.                 ParserError(DP_ERR_MIXED_TYPES, "");
  578.             break;
  579.             case UNDEF_OBJ:
  580.             PObj -> ObjType = POLY_OBJ;
  581.             PObj -> U.Pl.P = NULL;
  582.             RST_POLYLINE_OBJ(PObj);
  583.             break;
  584.             default:
  585.             ParserError(DP_ERR_MIXED_TYPES, "");
  586.             break;
  587.         }
  588.  
  589.         PPolygon = AllocPolygon(0, 0, NULL, NULL);
  590.  
  591.         /* The following handle the optional attributes in struct.   */
  592.         HasPlane = HasNormal = FALSE;
  593.         if (GetToken(f, StringToken) == TOKEN_OPEN_PAREN)
  594.             GetPolygonAttributes(PPolygon, f, &HasPlane);
  595.         else
  596.             UnGetToken(StringToken);
  597.  
  598.         /* The following handles reading the vertices. */
  599.         GetPointData(f, PPolygon, FALSE, &HasNormal);
  600.  
  601.         if (!HasPlane) DPUpdatePolyPlane(PPolygon);
  602.         if (!HasNormal) {
  603.             /* Update all normals to be the same as plane eqn. */
  604.             PVertex = PPolygon -> V;
  605.             do {
  606.             PT_COPY(PVertex -> Normal, PPolygon -> Plane);
  607.             PVertex = PVertex -> Pnext;
  608.             }
  609.             while (PVertex != PPolygon -> V && PVertex != NULL);
  610.         }
  611.         PPolygon -> Pnext = PObj -> U.Pl.P;
  612.         PObj -> U.Pl.P = PPolygon;
  613.         break;
  614.         case TOKEN_NUMBER:
  615.         switch (PObj -> ObjType) {
  616.             case NUMERIC_OBJ:
  617.             break;
  618.             case UNDEF_OBJ:
  619.             PObj -> ObjType = NUMERIC_OBJ;
  620.             break;
  621.             default:
  622.             ParserError(DP_ERR_MIXED_TYPES, "");
  623.             break;
  624.         }
  625.         GetNumericToken(f, &PObj -> U.R);
  626.         GetCloseParenToken(f);
  627.         break;
  628.         case TOKEN_STRING:
  629.         switch (PObj -> ObjType) {
  630.             case STRING_OBJ:
  631.             break;
  632.             case UNDEF_OBJ:
  633.             PObj -> ObjType = STRING_OBJ;
  634.             break;
  635.             default:
  636.             ParserError(DP_ERR_MIXED_TYPES, "");
  637.             break;
  638.         }
  639.         GetToken(f, StringToken);
  640.         if ((p1 = strchr(StringToken, '"')) == NULL ||
  641.             (p2 = strrchr(StringToken, '"')) == p1)
  642.             ParserError(DP_STR_NOT_IN_QUOTES, StringToken);
  643.  
  644.         /* Convert the end quote to EOS and copy string. */
  645.         *p2 = 0;
  646.         strcpy(PObj -> U.Str, &p1[1]);
  647.  
  648.         GetCloseParenToken(f);
  649.         break;
  650.         case TOKEN_VECTOR:
  651.         switch (PObj -> ObjType) {
  652.             case VECTOR_OBJ:
  653.             break;
  654.             case UNDEF_OBJ:
  655.             PObj -> ObjType = VECTOR_OBJ;
  656.             break;
  657.             default:
  658.             ParserError(DP_ERR_MIXED_TYPES, "");
  659.             break;
  660.         }
  661.         for (i = 0; i < 3; i++)
  662.             GetNumericToken(f, &PObj -> U.Vec[i]);
  663.         GetCloseParenToken(f);
  664.         break;
  665.         case TOKEN_MATRIX:
  666.         switch (PObj -> ObjType) {
  667.             case MATRIX_OBJ:
  668.             break;
  669.             case UNDEF_OBJ:
  670.             PObj -> ObjType = MATRIX_OBJ;
  671.             break;
  672.             default:
  673.             ParserError(DP_ERR_MIXED_TYPES, "");
  674.             break;
  675.         }
  676.         for (i = 0; i < 4; i++)
  677.             for (j = 0; j < 4; j++)
  678.             GetNumericToken(f, &PObj -> U.Mat[i][j]);
  679.         GetCloseParenToken(f);
  680.         break;
  681.         case TOKEN_CTLPT:
  682.         switch (PObj -> ObjType) {
  683.             case CTLPT_OBJ:
  684.             break;
  685.             case UNDEF_OBJ:
  686.             PObj -> ObjType = CTLPT_OBJ;
  687.             break;
  688.             default:
  689.             ParserError(DP_ERR_MIXED_TYPES, "");
  690.             break;
  691.         }
  692.  
  693.         switch (GetToken(f, StringToken)) {
  694.             case TOKEN_E2:
  695.             PObj -> U.CtlPt.PtType = CAGD_PT_E2_TYPE;
  696.             j = 2;
  697.             i = 1;
  698.             break;
  699.             case TOKEN_P2:
  700.             PObj -> U.CtlPt.PtType = CAGD_PT_P2_TYPE;
  701.             j = 3;
  702.             i = 0;
  703.             break;
  704.             case TOKEN_E3:
  705.             PObj -> U.CtlPt.PtType = CAGD_PT_E3_TYPE;
  706.             j = 3;
  707.             i = 1;
  708.             break;
  709.             case TOKEN_P3:
  710.             PObj -> U.CtlPt.PtType = CAGD_PT_P3_TYPE;
  711.             j = 4;
  712.             i = 0;
  713.             break;
  714.             default:
  715.             WndwInputWindowPutStr("Read: Undefined point type");
  716.             break;
  717.         }
  718.  
  719.         Coords = PObj -> U.CtlPt.Coords;
  720.         for ( ; j > 0; i++, j--)
  721.             GetNumericToken(f, &Coords[i]);
  722.         GetCloseParenToken(f);
  723.         break;
  724.         case TOKEN_SURFACE:
  725.         switch (PObj -> ObjType) {
  726.             case SURFACE_OBJ:
  727.             break;
  728.             case UNDEF_OBJ:
  729.             PObj -> ObjType = SURFACE_OBJ;
  730.             PObj -> U.Srf.Srf = NULL;
  731.             PObj -> U.Srf.PLPolys = NULL;
  732.             PObj -> U.Srf.CtlMesh = NULL;
  733.             PObj -> U.Srf.Polygons = NULL;
  734.             break;
  735.             default:
  736.             ParserError(DP_ERR_MIXED_TYPES, "");
  737.             break;
  738.         }
  739.  
  740.         ErrLine = GlblLineCount;
  741.         PSurface = CagdSrfReadFromFile2(f, &ErrStr, &ErrLine);
  742.         GlblLineCount = ErrLine;
  743.         if (ErrStr != NULL) {
  744.             ParserError(DP_ERR_CAGD_LIB_ERR, ErrStr);
  745.             break;
  746.         }
  747.  
  748.         PSurface -> Pnext = PObj -> U.Srf.Srf;
  749.         PObj -> U.Srf.Srf = PSurface;
  750.         break;
  751.         case TOKEN_CURVE:
  752.         switch (PObj -> ObjType) {
  753.             case CURVE_OBJ:
  754.             break;
  755.             case UNDEF_OBJ:
  756.             PObj -> ObjType = CURVE_OBJ;
  757.             PObj -> U.Crv.Crv = NULL;
  758.             PObj -> U.Crv.PLPolys = NULL;
  759.             PObj -> U.Crv.CtlPoly = NULL;
  760.             break;
  761.             default:
  762.             ParserError(DP_ERR_MIXED_TYPES, "");
  763.             break;
  764.         }
  765.  
  766.         ErrLine = GlblLineCount;
  767.         PCurve = CagdCrvReadFromFile2(f, &ErrStr, &ErrLine);
  768.         GlblLineCount = ErrLine;
  769.         if (ErrStr != NULL) {
  770.             ParserError(DP_ERR_CAGD_LIB_ERR, ErrStr);
  771.             break;
  772.         }
  773.  
  774.         PCurve -> Pnext = PObj -> U.Crv.Crv;
  775.         PObj -> U.Crv.Crv = PCurve;
  776.         break;
  777.         default:
  778.         ParserError(DP_ERR_UNDEF_EXPR_HEADER, StringToken);
  779.         break;
  780.     } /* Of switch. */
  781.     } /* Of while. */
  782.  
  783.     UnGetToken(StringToken);
  784. }
  785.  
  786. /*****************************************************************************
  787. *   Routine to unget one token (on stack of UNGET_STACK_SIZE levels!)         *
  788. *****************************************************************************/
  789. static void UnGetToken(char *StringToken)
  790. {
  791.     if (GlblToken >= UNGET_STACK_SIZE)
  792.      FatalError("Parser Internal stack overflow...\n");
  793.  
  794.     strcpy(GlblStringToken[GlblToken], StringToken);
  795.     GlblToken++;  /* GlblToken exists - Something in it (no overflow check). */
  796. }
  797.  
  798. /*****************************************************************************
  799. *   Routine to get the next token out of the input file    f.             *
  800. * Returns the next token found,    as StringToken.                     *
  801. * Note:    StringToken must be allocated before calling this routine!         *
  802. *****************************************************************************/
  803. static void GetStringToken(FILE *f, char *StringToken)
  804. {
  805.     int    len;
  806.     char c, *LocalStringToken;
  807.  
  808.     if (GlblToken) { /*    get first the unget token */
  809.     GlblToken--;
  810.     strcpy(StringToken, GlblStringToken[GlblToken]);
  811.     return;
  812.     }
  813.     /* skip white spaces: */
  814.     while ((!feof(f))
  815.      && (((c = getc(f)) == ' ') || (c == '\t') || (c == '\n')))
  816.         if (c == '\n') GlblLineCount++;         /* Count the lines. */
  817.  
  818.     LocalStringToken = StringToken;
  819.     if (c == '[')              /* Its a token by    itself so return it. */
  820.     *LocalStringToken++ = c;          /* Copy the token    into string. */
  821.     else {
  822.     if (!feof(f))
  823.          do    *LocalStringToken++ = c;      /* Copy the token    into string. */
  824.          while ((!feof(f)) &&
  825.               ((c = getc(f)) !=    ' ') &&    (c != '\t') && (c != '\n'));
  826.     if (c == '\n') ungetc(c, f);     /* Save it to be counted next time. */
  827.     }
  828.     *LocalStringToken =    0;                     /* Put    eos. */
  829.  
  830.     /* The following handles the spacial case were we have XXXX] - we must   */
  831.     /* split it    into two token XXXX and    ], UnGetToken(']') and return XXXX:  */
  832.     if ((StringToken[len = strlen(StringToken)-1] == ']') && (len > 0))    {
  833.     /* Return CloseParan */
  834.     UnGetToken(&StringToken[len]);             /* Save next token. */
  835.     StringToken[len] = 0;            /* Set end of string on    "]". */
  836.     }
  837. }
  838.  
  839. /*****************************************************************************
  840. *   Routine to get the next token out of the input file    f as token number.   *
  841. * Note:    StringToken must be allocated before calling this routine!         *
  842. *****************************************************************************/
  843. static TokenType GetToken(FILE *f, char *StringToken)
  844. {
  845.     static int IntTokens[] = {
  846.     TOKEN_OPEN_PAREN,
  847.     TOKEN_CLOSE_PAREN,
  848.     TOKEN_VERTEX,
  849.     TOKEN_POLYGON,
  850.     TOKEN_POLYLINE,
  851.     TOKEN_OBJECT,
  852.     TOKEN_COLOR,
  853.     TOKEN_INTERNAL,
  854.     TOKEN_NORMAL,
  855.     TOKEN_PLANE,
  856.     TOKEN_CURVE,
  857.     TOKEN_SURFACE,
  858.     TOKEN_E2,
  859.     TOKEN_P2,
  860.     TOKEN_E3,
  861.     TOKEN_P3,
  862.     TOKEN_NUMBER,
  863.     TOKEN_STRING,
  864.     TOKEN_VECTOR,
  865.     TOKEN_MATRIX,
  866.     TOKEN_CTLPT,
  867.     0
  868.     };
  869.     static char *StrTokens[] = {
  870.     "[",
  871.     "]",
  872.     "VERTEX",
  873.     "POLYGON",
  874.     "POLYLINE",
  875.     "OBJECT",
  876.     "COLOR",
  877.     "INTERNAL",
  878.     "NORMAL",
  879.     "PLANE",
  880.     "CURVE",
  881.     "SURFACE",
  882.     "E2",
  883.     "P2",
  884.     "E3",
  885.     "P3",
  886.     "NUMBER",
  887.     "STRING",
  888.     "VECTOR",
  889.     "MATRIX",
  890.     "CTLPT",
  891.     NULL
  892.     };
  893.     int i;
  894.  
  895.     GetStringToken(f, StringToken);
  896.  
  897.     if (feof(f)) return TOKEN_EOF;
  898.  
  899.     for (i = 0; StrTokens[i] != NULL; i++)
  900.     if (strcmp(StringToken, StrTokens[i]) == 0) return IntTokens[i];
  901.  
  902.     return TOKEN_OTHER;                  /* Must be number or name. */
  903. }
  904.  
  905. /*****************************************************************************
  906. * Routine to read from input file f the    following [ATTR ...] [ATTR ...].     *
  907. * Note the '[' was allready read.                         *
  908. * Current supported attributes: [INTERNAL] - internal edge (IRIT output).    *
  909. *****************************************************************************/
  910. static void GetVertexAttributes(VertexStruct *PVertex, FILE *f,
  911.                                   int *HasNormal)
  912. {
  913.     int i;
  914.     char StringToken[LINE_LEN];
  915.  
  916.     do {
  917.     switch (GetToken(f, StringToken)) {
  918.         case TOKEN_INTERNAL:
  919.         if (GetToken(f, StringToken) != TOKEN_CLOSE_PAREN)
  920.             ParserError(DP_ERR_CLOSE_PAREN_EXPECTED, StringToken);
  921.         SET_INTERNAL_EDGE(PVertex);
  922.         break;
  923.         case TOKEN_NORMAL:
  924.         /* The following handles reading 3 coord. of vertex normal. */
  925.         for (i = 0; i < 3; i++)
  926.             GetNumericToken(f, &PVertex -> Normal[i]);
  927.  
  928.         GetCloseParenToken(f);
  929.         *HasNormal = TRUE;
  930.         break;
  931.         default: /* Ignore this option! */
  932.         while (GetToken(f, StringToken) != TOKEN_CLOSE_PAREN);
  933.         break;
  934.     }
  935.     }
  936.     while (GetToken(f, StringToken) == TOKEN_OPEN_PAREN);
  937.  
  938.     UnGetToken(StringToken);
  939. }
  940.  
  941. /*****************************************************************************
  942. * Routine to read from input file f the    following [ATTR ...] [ATTR ...].     *
  943. * Note the '[' was allready read.                         *
  944. * Current supported attributes: [PLANE A B C D].                 *
  945. *****************************************************************************/
  946. static void GetPolygonAttributes(PolygonStruct *PPolygon, FILE *f,
  947.                                 int *HasPlane)
  948. {
  949.     int i;
  950.     char StringToken[LINE_LEN];
  951.  
  952.     do {
  953.     switch (GetToken(f, StringToken)) {
  954.         case TOKEN_PLANE:
  955.         /* The following handles reading of 4 coord. of plane eqn.. */
  956.         for (i = 0; i < 4; i++)
  957.             GetNumericToken(f, &PPolygon -> Plane[i]);
  958.         GetCloseParenToken(f);
  959.         *HasPlane = TRUE;
  960.         break;
  961.         default:
  962.         while (GetToken(f, StringToken) != TOKEN_CLOSE_PAREN);
  963.         break;
  964.     }
  965.     }
  966.     while (GetToken(f, StringToken) == TOKEN_OPEN_PAREN);
  967.  
  968.     UnGetToken(StringToken);
  969. }
  970.  
  971. /*****************************************************************************
  972. * Routine to read from input file f the    following [ATTR ...] [ATTR ...].     *
  973. * Note the '[' was allready read.                         *
  974. * Current supported attributes: [COLOR C] - set color.                 *
  975. * All other attributes are treated as String attributes.             *
  976. *****************************************************************************/
  977. static void GetObjectAttributes(ObjectStruct *PObject, FILE *f)
  978. {
  979.     int    i;
  980.     char StringToken[LINE_LEN], Data[LINE_LEN], Name[LINE_LEN];
  981.  
  982.     do {
  983.     switch (GetToken(f, StringToken)) {
  984.         case TOKEN_COLOR:
  985.         GetToken(f, StringToken);
  986.         if (sscanf(StringToken, "%d", &i) != 1)
  987.             ParserError(DP_ERR_NUMBER_EXPECTED, StringToken);
  988.         GetCloseParenToken(f);
  989.         SetObjectColor(PObject, i);
  990.         break;
  991.         default:
  992.         strcpy(Name, StringToken);
  993.         strcpy(Data, " ");
  994.         while (GetToken(f, StringToken) != TOKEN_CLOSE_PAREN) {
  995.             strcat(Data, StringToken);
  996.             strcat(Data, " ");
  997.         }
  998.         SetObjectStrAttrib(PObject, Name, Data);
  999.         break;
  1000.     }
  1001.     }
  1002.     while (GetToken(f, StringToken) == TOKEN_OPEN_PAREN);
  1003.  
  1004.     UnGetToken(StringToken);
  1005. }
  1006.  
  1007. /*****************************************************************************
  1008. * Routine to read poly* vertex information.                     *
  1009. *****************************************************************************/
  1010. static void GetPointData(FILE *f, PolygonStruct *PPolygon, int IsPolyline,
  1011.                                int *HasNormal)
  1012. {
  1013.     int i, j, Length;
  1014.     char StringToken[LINE_LEN];
  1015.     VertexStruct *V,
  1016.     *VTail = NULL;
  1017.  
  1018.     if (GetToken(f, StringToken) != TOKEN_OTHER ||
  1019.     sscanf(StringToken, "%d", &Length) != 1)
  1020.     ParserError(DP_ERR_NUMBER_EXPECTED, StringToken);
  1021.  
  1022.     for (i = 0; i < Length; i++) {
  1023.     if (GetToken(f, StringToken) != TOKEN_OPEN_PAREN)
  1024.         ParserError(DP_ERR_OPEN_PAREN_EXPECTED, StringToken);
  1025.  
  1026.     V = AllocVertex(0, 0, NULL, NULL);
  1027.  
  1028.     /* The following handle the optional attributes in struct. */
  1029.     *HasNormal = FALSE;
  1030.     if (GetToken(f, StringToken) == TOKEN_OPEN_PAREN)
  1031.         GetVertexAttributes(V, f, HasNormal);
  1032.     else
  1033.         UnGetToken(StringToken);
  1034.  
  1035.     for (j = 0; j < 3; j++)                /* Read coordinates. */
  1036.         GetNumericToken(f, &V -> Pt[j]);
  1037.  
  1038.     GetCloseParenToken(f);
  1039.  
  1040.     if (!*HasNormal)
  1041.         PT_COPY(V -> Normal, PPolygon -> Plane);
  1042.  
  1043.     if (VTail == NULL)
  1044.         PPolygon -> V = VTail = V;
  1045.     else {
  1046.         VTail -> Pnext = V;
  1047.         VTail = V;
  1048.     }
  1049.     }
  1050.     VTail -> Pnext = IsPolyline ? NULL : PPolygon -> V;
  1051.  
  1052.     GetCloseParenToken(f);
  1053. }
  1054.  
  1055. /*****************************************************************************
  1056. *   Routine to update the Plane equation of the given polygon by the order   *
  1057. * of the first 3 vertices of that polygon.                     *
  1058. *****************************************************************************/
  1059. static void DPUpdatePolyPlane(PolygonStruct *PPoly)
  1060. {
  1061.     int i;
  1062.     VectorType V1, V2;
  1063.     RealType Len;
  1064.     VertexStruct *V;
  1065.  
  1066.     V = PPoly -> V;    PT_SUB(V1, V -> Pt, V -> Pnext -> Pt);
  1067.     V = V -> Pnext;    PT_SUB(V2, V -> Pt, V -> Pnext -> Pt);
  1068.  
  1069.     PPoly -> Plane[0] = V1[1] * V2[2] - V2[1] * V1[2];
  1070.     PPoly -> Plane[1] = V1[2] * V2[0] - V2[2] * V1[0];
  1071.     PPoly -> Plane[2] = V1[0] * V2[1] - V2[0] * V1[1];
  1072.     PPoly -> Plane[3] = (-DOT_PROD(PPoly -> Plane, PPoly -> V -> Pt));
  1073.  
  1074.     /* Normalize the plane such that the normal has length of 1: */
  1075.     Len = PT_LENGTH(PPoly -> Plane);
  1076.     for (i = 0; i < 4; i++) PPoly -> Plane[i] /= Len;
  1077. }
  1078.  
  1079. /*****************************************************************************
  1080. * Routine to print pasring error according to ErrNum and set GlblParserError.*
  1081. *****************************************************************************/
  1082. static void ParserError(DataPrsrErrType ErrNum, char *Msg)
  1083. {
  1084.     DPGlblLineCount = GlblLineCount;
  1085.     DPGlblParserError = ErrNum;
  1086.     strcpy(DPGlblTokenError, Msg);    /* Keep the message in safe place... */
  1087.  
  1088.     longjmp(LclLongJumpBuffer, 1);                   /* Jump to... */
  1089. }
  1090.  
  1091. /*****************************************************************************
  1092. * Returns TRUE if error happened, FALSE otherwise.                 *
  1093. *   If error, then ErrorMsg is updated to point on static str describing it. *
  1094. *****************************************************************************/
  1095. int DataPrsrParseError(char **ErrorMsg)
  1096. {
  1097.     DataPrsrErrType Temp;
  1098.     char TempCopy[LINE_LEN];
  1099.  
  1100.     if ((Temp = DPGlblParserError) == DP_NO_ERR) return FALSE;
  1101.  
  1102.     strcpy(TempCopy, DPGlblTokenError);
  1103.     DPGlblParserError = DP_NO_ERR;
  1104.  
  1105.     switch (Temp) {
  1106.     case DP_ERR_NUMBER_EXPECTED:
  1107.         sprintf(DPGlblTokenError, "Line %d: Numeric data expected - found %s",
  1108.         DPGlblLineCount, TempCopy);
  1109.         break;
  1110.     case DP_ERR_OPEN_PAREN_EXPECTED:
  1111.         sprintf(DPGlblTokenError, "Line %d: '[' expected - found '%s'",
  1112.         DPGlblLineCount, TempCopy);
  1113.         break;
  1114.     case DP_ERR_CLOSE_PAREN_EXPECTED:
  1115.         sprintf(DPGlblTokenError, "Line %d: ']' expected - found '%s'",
  1116.         DPGlblLineCount, TempCopy);
  1117.         break;
  1118.     case DP_ERR_LIST_COMP_UNDEF:
  1119.         sprintf(DPGlblTokenError, "Line %d: Undefined list element - \"%s\"",
  1120.         DPGlblLineCount, TempCopy);
  1121.         break;
  1122.     case DP_ERR_UNDEF_EXPR_HEADER:
  1123.         sprintf(DPGlblTokenError, "Line %d: Undefined TOKEN - \"%s\"",
  1124.         DPGlblLineCount, TempCopy);
  1125.         break;
  1126.     case DP_ERR_PT_TYPE_EXPECTED:
  1127.         sprintf(DPGlblTokenError, "Line %d: Point type expected",
  1128.         DPGlblLineCount);
  1129.         break;
  1130.     case DP_ERR_OBJECT_EMPTY:
  1131.         sprintf(DPGlblTokenError, "Line %d: Empty object found",
  1132.         DPGlblLineCount);
  1133.         break;
  1134.     case DP_ERR_EMPTY_NAME:
  1135.         sprintf(DPGlblTokenError, "Given file name is empty");
  1136.         break;
  1137.     case DP_ERR_OPEN_FAILED:
  1138.         sprintf(DPGlblTokenError, "Fail to open file - %s",    TempCopy);
  1139.         break;
  1140.     case DP_ERR_MIXED_TYPES:
  1141.         sprintf(DPGlblTokenError,
  1142.             "Line %d: Mixed data types in same object",
  1143.             DPGlblLineCount);
  1144.         break;
  1145.     case DP_STR_NOT_IN_QUOTES:
  1146.         sprintf(DPGlblTokenError,
  1147.             "Line %d: String not in quotes (%s)",
  1148.             DPGlblLineCount, TempCopy);
  1149.         break;
  1150.     case DP_ERR_CAGD_LIB_ERR:
  1151.         sprintf(DPGlblTokenError, "Line %d: %s",
  1152.             DPGlblLineCount, TempCopy);
  1153.         break;
  1154.     default:
  1155.         sprintf(DPGlblTokenError,
  1156.             "Line %d: Data file parser - undefined error",
  1157.             DPGlblLineCount);
  1158.         break;
  1159.     }
  1160.  
  1161.     *ErrorMsg = DPGlblTokenError;
  1162.  
  1163.     return TRUE;
  1164. }
  1165.