home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / IRIT / POLY3DHS.ZIP / PARSER.C < prev    next >
Encoding:
C/C++ Source or Header  |  1990-05-05  |  23.2 KB  |  612 lines

  1. /*****************************************************************************
  2. *   Module to read a graphic data file into the    given structure.         *
  3. *                                         *
  4. * Written by:  Gershon Elber                Ver 1.0, Jan. 1989   *
  5. *****************************************************************************/
  6.  
  7. /* #define DEBUG         /* Defines some helpfull printing routines. */
  8.  
  9. #ifdef __MSDOS__
  10. #include <stdlib.h>
  11. #endif /* __MSDOS__ */
  12.  
  13. #include <stdio.h>
  14. #include <ctype.h>
  15. #include <math.h>
  16. #include <string.h>
  17. #include "program.h"
  18. #include "genmat.h"
  19. #include "parser.h"
  20.  
  21. static int  GlblToken =    0,          /* Used by the parser, to unget token. */
  22.         GlblLineCount = 1,         /* Used to locate errors in input file. */
  23.         GlblParserError = 0;        /* Save last error number found. */
  24. static char GlblStringToken[UNGET_STACK_SIZE][LINE_LEN];/* Save unget tokens.*/
  25. static struct FileDescription *Descriptor;
  26.  
  27. static struct BinTree *AllocBinTree(int Entry, VoidPtr Data);
  28. static void UnGetToken(char *StringToken);
  29. static void GetStringToken(FILE *f, char *StringToken);
  30. static int GetToken(FILE *f, char *StringToken);
  31. static void GetVertexAttributes(VertexStruct *PVertex, FILE *f);
  32. static void GetPolygonAttributes(PolygonStruct *PPolygon, FILE *f);
  33. static void GetObjectAttributes(ObjectStruct *PObject, FILE *f);
  34. static void EliminateComments(FILE *f);
  35. static void ParserError(int ErrNum, char *Msg);
  36. static void InsertBinTree(BinTree **Tree, BinTree *PNewRecord);
  37. static LinearListStruct *GetNameFromFD(char *Name, FileDescription *FD,
  38.                             int EntryTypes);
  39. static VoidPtr GetLinList(FILE *f, FileDescription *FD, int EntryTypes);
  40.  
  41. #ifdef DEBUG
  42. void PrintAllBinTrees(FileDescription *FD);
  43. void PrintBinTree(BinTree *Tree);
  44. #endif DEBUG
  45.  
  46. /*****************************************************************************
  47. * Routine to read the data from    a given    file and update    the data structures  *
  48. * Descriptor (which returned) from it.                         *
  49. * If MoreFlag is on then more printed staff will be given...             *
  50. *****************************************************************************/
  51. FileDescription *GetDataFile(FILE *f)
  52. {
  53.     int    i;
  54.     char StringToken[LINE_LEN];
  55.     struct VertexStruct       *PVertex;
  56.     struct PolygonStruct   *PPolygon;
  57.     struct ObjectStruct       *PObject;
  58.     struct BinTree       *PBinTree;
  59.  
  60.     GlblToken =    0;
  61.  
  62.     Descriptor = (FileDescription *) MyMalloc(sizeof(FileDescription));
  63.     /* As all the trees    are empty set the following: */
  64.     Descriptor -> VertexPointer       =
  65.     Descriptor -> PolygonPointer   =
  66.     Descriptor -> PolylinePointer  =
  67.     Descriptor -> ObjectPointer       = (BinTree *) NULL;
  68.  
  69.     GlblLineCount = 1;                      /* Reset line counter. */
  70.     EliminateComments(f);         /* Skip all comments including '['. */
  71.     while (!feof(f)) {
  72.     GlblParserError = 0;                    /* Reset errors. */
  73.     switch (GetToken(f, StringToken)) {
  74.         case TOKEN_VERTEX:
  75.         PVertex = (VertexStruct *) MyMalloc(sizeof(VertexStruct));
  76.         PVertex -> Transform = 0; /* Flag if vertex was transformed. */
  77.         PVertex -> Internal = 0;      /* Flag if vertex is internal. */
  78.         PBinTree = AllocBinTree(VERTEX_ENTRY, (VoidPtr) PVertex);
  79.         GetToken(f, PBinTree -> Name);            /* Get the name. */
  80.         /* The following handle the optional attributes in record.   */
  81.         if (GetToken(f, StringToken) == TOKEN_OPEN_PAREN)
  82.             GetVertexAttributes(PVertex, f);      /* Get attributes. */
  83.         else UnGetToken(StringToken);
  84.         /* The following handles reading of 3 coord. of vertex. */
  85.         for (i=0; i<3    ;i++) {
  86.             GetToken(f, StringToken);
  87.             if (sscanf(StringToken, "%f", &PVertex -> Coord[i]) != 1)
  88.             ParserError(P_ERR_NumberExpected, StringToken);
  89.         }
  90.         if ((i=GetToken(f, StringToken)) != TOKEN_CLOSE_PAREN)
  91.             ParserError(P_ERR_CloseParanExpected, StringToken);
  92.         if (!GlblParserError)
  93.             InsertBinTree(&Descriptor -> VertexPointer, PBinTree);
  94.         break;
  95.         case TOKEN_POLYGON:
  96.         fprintf(stderr, "\b\b\b\b\b%5d", ++NumOfPolygons);
  97.  
  98.         PPolygon = (PolygonStruct *) MyMalloc(sizeof(PolygonStruct));
  99.         PPolygon -> Polyline = FALSE;
  100.         PBinTree = AllocBinTree(POLYGON_ENTRY, (VoidPtr) PPolygon);
  101.         GetToken(f, PBinTree -> Name);            /* Get the name. */
  102.         /* The following handle the optional attributes in record.  */
  103.         if (GetToken(f, StringToken) == TOKEN_OPEN_PAREN)
  104.             GetPolygonAttributes(PPolygon, f);
  105.         else UnGetToken(StringToken);
  106.         /* The following handles reading the members list. */
  107.         PPolygon -> PVertex = (VertexStruct *)
  108.                 GetLinList(f, Descriptor, VERTEX_ENTRY);
  109.         if (!GlblParserError)
  110.             InsertBinTree(&Descriptor -> PolygonPointer, PBinTree);
  111.         break;
  112.         case TOKEN_POLYLINE:
  113.         fprintf(stderr, "\b\b\b\b\b%5d", ++NumOfPolygons);
  114.  
  115.         PPolygon = (PolygonStruct *) MyMalloc(sizeof(PolygonStruct));
  116.         PPolygon -> Polyline = TRUE;
  117.         PBinTree = AllocBinTree(POLYGON_ENTRY, (VoidPtr) PPolygon);
  118.         GetToken(f, PBinTree -> Name);            /* Get the name. */
  119.         /* The following handle the optional attributes in record. */
  120.         if (GetToken(f, StringToken) == TOKEN_OPEN_PAREN)
  121.             GetPolygonAttributes(PPolygon, f);
  122.         else UnGetToken(StringToken);
  123.         /* The following handles reading the members list. */
  124.         PPolygon -> PVertex = (VertexStruct *)
  125.                 GetLinList(f, Descriptor, VERTEX_ENTRY);
  126.         if (!GlblParserError)
  127.             InsertBinTree(&Descriptor -> PolylinePointer, PBinTree);
  128.         break;
  129.         case TOKEN_OBJECT:
  130.         PObject = (ObjectStruct *) MyMalloc(sizeof(ObjectStruct));
  131.         PObject -> Color = DEFAULT_COLOR;
  132.         PBinTree = AllocBinTree(OBJECT_ENTRY, (VoidPtr) PObject);
  133.         GetToken(f, PBinTree -> Name);            /* Get the name. */
  134.         /* The following handle the optional attributes in record.   */
  135.         if (GetToken(f, StringToken) == TOKEN_OPEN_PAREN)
  136.             GetObjectAttributes(PObject, f);
  137.         else UnGetToken(StringToken);
  138.         /* The following handles reading the polygon list. Note      */
  139.         /* an object might be created from Polygons/Polylines only.  */
  140.         PObject -> PPolygon = (PolygonStruct *)
  141.             GetLinList(f, Descriptor, POLYGON_ENTRY | POLYLINE_ENTRY);
  142.         if (!GlblParserError)
  143.             InsertBinTree(&Descriptor -> ObjectPointer, PBinTree);
  144.         break;
  145.         default:
  146.         ParserError(P_ERR_UndefExprHeader, StringToken);
  147.         break;
  148.     } /* Of switch. */
  149.     if (!feof(f)) EliminateComments(f);  /* Skip comments including '['. */
  150.     } /* Of while !eof. */
  151.  
  152.     return Descriptor;
  153. }
  154.  
  155. /*****************************************************************************
  156. * Routine to allocate one BinTree Item:                         *
  157. *****************************************************************************/
  158. static struct BinTree *AllocBinTree(int Entry, VoidPtr Data)
  159. {
  160.     struct BinTree *PBinTree;
  161.  
  162.     PBinTree = (BinTree *) MyMalloc(sizeof(BinTree));
  163.     PBinTree -> EntryType = Entry;
  164.     PBinTree -> Data.PVoid = Data;
  165.     PBinTree -> right = PBinTree -> left = (BinTree *) NULL;
  166.  
  167.     return PBinTree;
  168. }
  169.  
  170. /*****************************************************************************
  171. * The view file    should be 4 by 4 matrix.                     *
  172. *****************************************************************************/
  173. void GetViewFile(FILE *f, int FileExists)
  174. {
  175.     int    i, j;
  176.     char StringToken[LINE_LEN];
  177.     MatrixType PerspMat, Mat;
  178.  
  179.     if (FileExists) {
  180.     for (i=0; i<4; i++)
  181.         for (j=0; j<4; j++)
  182.         if (GetToken(f, StringToken) != TOKEN_OTHER ||
  183.             sscanf(StringToken, "%lf", &GlblViewMat[i][j]) != 1) {
  184.             fprintf(stderr, "Wrong input data in view file, dies\n");
  185.             MyExit(1);
  186.         }
  187.  
  188.     if (GetToken(f, StringToken) == TOKEN_OTHER &&
  189.         sscanf(StringToken, "%lf", &PerspMat[0][0]) == 1) {
  190.         for (i=0; i<4; i++)
  191.         for (j=0; j<4; j++) {
  192.             if (i==0 && j==0) continue;       /* Already got first one. */
  193.             if (GetToken(f, StringToken) != TOKEN_OTHER ||
  194.             sscanf(StringToken, "%lf", &PerspMat[i][j]) != 1) {
  195.             fprintf(stderr, "Wrong input data in view file, dies\n");
  196.             MyExit(1);
  197.             }
  198.         }
  199.         MultTwo4by4(GlblViewMat, GlblViewMat, PerspMat);
  200.     }
  201.     }
  202.     else { /* Set default isometric view: */
  203.     /* 90 - 35.2644 = 54.7356. */
  204.     GenMatRotX1(DEG2RAD(-54.7356), Mat);
  205.     GenMatRotZ1(M_PI + M_PI / 4, GlblViewMat);
  206.     MultTwo4by4(GlblViewMat, GlblViewMat, Mat);
  207.     }
  208. }
  209.  
  210. /*****************************************************************************
  211. *   Routine to unget one token (on stack of UNGET_STACK_SIZE levels!)         *
  212. *****************************************************************************/
  213. static void UnGetToken(char *StringToken)
  214. {
  215.     if (GlblToken >= UNGET_STACK_SIZE) {
  216.      fprintf(stderr, "Parser Internal stack overflow...\n");
  217.      MyExit(1);
  218.     }
  219.  
  220.     strcpy(GlblStringToken[GlblToken], StringToken);
  221.     GlblToken++;  /* GlblToken exists - Something in it (no overflow check). */
  222. }
  223.  
  224. /*****************************************************************************
  225. *   Routine to get the next token out of the input file    f.             *
  226. * Returns the next token found,    as StringToken.                     *
  227. * Note:    StringToken must be allocated before calling this routine!         *
  228. *****************************************************************************/
  229. static void GetStringToken(FILE *f, char *StringToken)
  230. {
  231.     int    len;
  232.     char c, *LocalStringToken;
  233.  
  234.     if (GlblToken) {                   /* Get first the unget token. */
  235.     GlblToken--;
  236.     strcpy(StringToken, GlblStringToken[GlblToken]);
  237.     return;
  238.     }
  239.     /* skip white spaces: */
  240.     while ((!feof(f))
  241.      && (((c = getc(f)) == ' ') || (c == '\t') || (c == '\n')))
  242.         if (c == '\n') GlblLineCount++;         /* Count the lines. */
  243.  
  244.     LocalStringToken = StringToken;
  245.     if (c == '[')              /* Its a token by    itself so return it. */
  246.     *LocalStringToken++ = c;          /* Copy the token    into string. */
  247.     else {
  248.     if (!feof(f))
  249.          do    *LocalStringToken++ = c;      /* Copy the token    into string. */
  250.          while ((!feof(f)) &&
  251.               ((c = getc(f)) !=    ' ') &&    (c != '\t') && (c != '\n'));
  252.     if (c == '\n') ungetc(c, f);     /* Save it to be counted next time. */
  253.     }
  254.     *LocalStringToken =    NULL;                     /* Put    eos. */
  255.  
  256.     /* The following handles the spacial case were we have XXXX] - we must   */
  257.     /* split it    into two token XXXX and    ], UnGetToken(']') and return XXXX:  */
  258.     if ((StringToken[len = strlen(StringToken)-1] == ']') && (len > 0))    {
  259.     /* Return CloseParan. */
  260.     UnGetToken(&StringToken[len]);             /* Save next token. */
  261.     StringToken[len] = NULL;        /* Set end of string on    "]". */
  262.     }
  263. }
  264.  
  265. /*****************************************************************************
  266. *   Routine to get the next token out of the input file    f as token number.   *
  267. * Returns the next token number    found, with numeric result in NumericToken   *
  268. * if TokenType is TOKEN_NUMBER.                             *
  269. * Note:    StringToken must be allocated before calling this routine!         *
  270. *****************************************************************************/
  271. static int GetToken(FILE *f, char *StringToken)
  272. {
  273.     GetStringToken(f, StringToken);
  274.  
  275.     if (feof(f))                 return TOKEN_EOF;
  276.  
  277.     if (!strcmp(StringToken, "["))         return TOKEN_OPEN_PAREN;
  278.     if (!strcmp(StringToken, "]"))         return TOKEN_CLOSE_PAREN;
  279.  
  280.     if (!strcmp(StringToken, "VERTEX"))         return TOKEN_VERTEX;
  281.     if (!strcmp(StringToken, "POLYGON"))     return TOKEN_POLYGON;
  282.     if (!strcmp(StringToken, "POLYLINE"))    return TOKEN_POLYLINE;
  283.     if (!strcmp(StringToken, "OBJECT"))         return TOKEN_OBJECT;
  284.  
  285.     if (!strcmp(StringToken, "COLOR"))         return TOKEN_COLOR;
  286.     if (!strcmp(StringToken, "INTERNAL"))    return TOKEN_INTERNAL;
  287.     if (!strcmp(StringToken, "PLANE"))       return TOKEN_PLANE;
  288.  
  289.     return TOKEN_OTHER;                  /* Must be number or name. */
  290. }
  291.  
  292. /*****************************************************************************
  293. * Routine to read from input file f the    following [ATTR ...] [ATTR ...].     *
  294. * Note the '[' was allready read.                         *
  295. * Current supported attributes: [INTERNAL] - internal edge (IRIT output)     *
  296. *****************************************************************************/
  297. static void GetVertexAttributes(VertexStruct *PVertex, FILE *f)
  298. {
  299.     char StringToken[LINE_LEN];
  300.  
  301.     do {
  302.     switch (GetToken(f, StringToken)) {
  303.         case TOKEN_INTERNAL:
  304.         PVertex -> Internal = 1;
  305.         if (GetToken(f, StringToken) != TOKEN_CLOSE_PAREN)
  306.             ParserError(P_ERR_CloseParanExpected, StringToken);
  307.         break;
  308.         default:                      /* Ignore this option! */
  309.         while (GetToken(f, StringToken) != TOKEN_CLOSE_PAREN);
  310.         break;
  311.     }
  312.     }
  313.     while (GetToken(f, StringToken) == TOKEN_OPEN_PAREN);
  314.  
  315.     UnGetToken(StringToken);
  316. }
  317.  
  318. /*****************************************************************************
  319. * Routine to read from input file f the    following [ATTR ...] [ATTR ...].     *
  320. * Note the '[' was allready read.                         *
  321. * Current supported attributes: [PLANE A B C D].                 *
  322. *****************************************************************************/
  323. static void GetPolygonAttributes(PolygonStruct *PPolygon, FILE *f)
  324. {
  325.     int    i;
  326.     char StringToken[LINE_LEN];
  327.  
  328.     do {
  329.     switch (GetToken(f, StringToken)) {
  330.         case TOKEN_PLANE:
  331.         for (i=0; i<4; i++) {
  332.             GetToken(f, StringToken);
  333.             if (sscanf(StringToken, "%f", &PPolygon -> Plane[i]) != 1)
  334.             ParserError(P_ERR_NumberExpected, StringToken);
  335.         }
  336.         if (GetToken(f, StringToken) != TOKEN_CLOSE_PAREN)
  337.             ParserError(P_ERR_CloseParanExpected, StringToken);
  338.         break;
  339.         default:
  340.         while (GetToken(f, StringToken) != TOKEN_CLOSE_PAREN);
  341.         break;
  342.     }
  343.     }
  344.     while (GetToken(f, StringToken) == TOKEN_OPEN_PAREN);
  345.  
  346.     UnGetToken(StringToken);
  347. }
  348.  
  349. /*****************************************************************************
  350. * Routine to read from input file f the    following [ATTR ...] [ATTR ...].     *
  351. * Note the '[' was allready read.                         *
  352. * Current supported attributes: [COLOR C] - set color.                 *
  353. *****************************************************************************/
  354. static void GetObjectAttributes(ObjectStruct *PObject, FILE *f)
  355. {
  356.     int    i;
  357.     char StringToken[LINE_LEN];
  358.  
  359.     do {
  360.     switch (GetToken(f, StringToken)) {
  361.         case TOKEN_COLOR:
  362.         GetToken(f, StringToken);
  363.         if (sscanf(StringToken, "%d", &i) != 1)
  364.             ParserError(P_ERR_NumberExpected, StringToken);
  365.         if (GetToken(f, StringToken) != TOKEN_CLOSE_PAREN)
  366.             ParserError(P_ERR_CloseParanExpected, StringToken);
  367.         PObject -> Color = i;
  368.         break;
  369.         default:
  370.         while (GetToken(f, StringToken) != TOKEN_CLOSE_PAREN);
  371.         break;
  372.     }
  373.     }
  374.     while (GetToken(f, StringToken) == TOKEN_OPEN_PAREN);
  375.  
  376.     UnGetToken(StringToken);
  377. }
  378.  
  379. /*****************************************************************************
  380. * Routine to read the input tokens up to a '[' token - skip comments.         *
  381. * Note the routine reads the '[' token,    so next    is the expression itself.    *
  382. *****************************************************************************/
  383. static void EliminateComments(FILE *f)
  384. {
  385.     char StringToken[LINE_LEN];
  386.  
  387.     while ((!feof(f)) && (GetToken(f, StringToken) != TOKEN_OPEN_PAREN));
  388. }
  389.  
  390. /*****************************************************************************
  391. * Routine to print pasring error according to ErrNum and set GlblParserError.*
  392. *****************************************************************************/
  393. static void ParserError(int ErrNum, char *Msg)
  394. {
  395.     GlblParserError = TRUE;
  396.  
  397.     if (MoreFlag == 0) return;                  /* Dont print nothing. */
  398.  
  399.     fprintf(stderr, "\nError in line %3d : ", GlblLineCount);
  400.  
  401.     switch (ErrNum) {
  402.     case P_ERR_NumberExpected:
  403.         fprintf(stderr, "Numeric Data Expected, ");
  404.         break;
  405.     case P_ERR_CloseParanExpected:
  406.         fprintf(stderr, "] expected, ");
  407.         break;
  408.     case P_ERR_ListCompUndef:
  409.         fprintf(stderr, "List component undefined -");
  410.         break;
  411.     case P_ERR_UndefExprHeader:
  412.         fprintf(stderr, "Undefined expression header -");
  413.         break;
  414.     default:
  415.         fprintf(stderr, "Unknown error, ");
  416.         break;
  417.     }
  418.     fprintf(stderr, " found %s.\n", Msg);
  419. }
  420.  
  421. /*****************************************************************************
  422. * Routine to insert new    element    into a binary tree. If the element already   *
  423. * exists then the new one replace it.                         *
  424. *****************************************************************************/
  425. static void InsertBinTree(BinTree **Tree, BinTree *PNewRecord)
  426. {
  427.     int    Comparison;
  428.     BinTree *PBin;
  429.  
  430.     if (*Tree == (BinTree *) NULL)   /*    Only might happen if the tree empty. */
  431.     *Tree =    PNewRecord;
  432.     else {                  /* Search for the new place to put it. */
  433.     /* Test for Match - if so replace old by new: */
  434.     if ((Comparison    = strcmp((*Tree) -> Name, PNewRecord -> Name)) == 0) {
  435.         PBin = *Tree;
  436.         *Tree = PNewRecord;                     /* Replace. */
  437.         switch (PBin -> EntryType) {      /* Free the data area (union). */
  438.         case VERTEX_ENTRY:
  439.             free((char *) PBin -> Data.PVertex);
  440.             break;
  441.         case POLYGON_ENTRY:
  442.             free((char *) PBin -> Data.PPolygon);
  443.             break;
  444.         case OBJECT_ENTRY:
  445.             free((char *) PBin -> Data.PObject);
  446.             break;
  447.         default:
  448.             /* Should not be, unless was not updated here... */
  449.             break;
  450.         }
  451.         free((char *) PBin);
  452.     }
  453.     else if    (Comparison > 0)       /* Go to right side - its bigger. */
  454.         if ((*Tree) -> right !=    (BinTree *) NULL)  /* Only if exist. */
  455.             InsertBinTree(&((*Tree) -> right), PNewRecord);
  456.         else (*Tree) ->    right =    PNewRecord;  /*    Put record in place. */
  457.          else if ((*Tree) -> left != (BinTree *) NULL) /* Only if exist. */
  458.             InsertBinTree(&((*Tree) -> left), PNewRecord); /*Smaller.*/
  459.           else (*Tree) -> left = PNewRecord; /*    Put record in place. */
  460.     }
  461. }
  462.  
  463. /*****************************************************************************
  464. * Routine to Get an element from binary    tree. If the element is    found a         *
  465. * pointer to it    BinTree    record is return, NULL else...                 *
  466. *****************************************************************************/
  467. BinTree *GetBinTree(char *RecName, BinTree *Tree)
  468. {
  469.     int    Comparison;
  470.  
  471.     /* If the tree is empty - not found, return    NULL: */
  472.     if (Tree ==    (BinTree *) NULL) return (BinTree *) NULL;
  473.  
  474.     /* Test for    Match -    if so return that record: */
  475.     if ((Comparison = strcmp(Tree -> Name, RecName)) == 0)
  476.     return Tree;                   /* Found it - so return it... */
  477.     else if (Comparison    > 0)
  478.           return GetBinTree(RecName, Tree -> right);
  479.      else return GetBinTree(RecName, Tree -> left);
  480. }
  481.  
  482. /*****************************************************************************
  483. * Routine to search for    Name in    the trees, allowed by EntryTypes, of the     *
  484. * file descrition FD. NULL returned if not found. The order of search is:    *
  485. * VERTEX ,  POLYGON ,  OBJECT.                             *
  486. * Once found, if was already used (multi-reference) it is copied fresh.         *
  487. *****************************************************************************/
  488. static LinearListStruct *GetNameFromFD(char *Name, FileDescription *FD,
  489.                                 int EntryTypes)
  490. {
  491.     BinTree *PBin;
  492.     VertexStruct *PVertex;
  493.     PolygonStruct *PPolygon;
  494.     ObjectStruct *PObject;
  495.  
  496.     if (EntryTypes & VERTEX_ENTRY) {          /* Check in vertices tree. */
  497.     if ((PBin = GetBinTree(Name, FD -> VertexPointer)) != NULL) {
  498.         if (PBin -> Used) {
  499.         PVertex = (VertexStruct *) MyMalloc(sizeof(VertexStruct));
  500.         GEN_COPY(PVertex, PBin -> Data.PVertex, sizeof(VertexStruct));
  501.         return (LinearListStruct *) PVertex;
  502.         }
  503.         else {
  504.         PBin -> Used = TRUE;
  505.         return (LinearListStruct *) PBin -> Data.PVertex;
  506.         }
  507.     }
  508.     }
  509.     if (EntryTypes & POLYGON_ENTRY) {           /* Check in polygon tree. */
  510.     if ((PBin = GetBinTree(Name, FD -> PolygonPointer)) != NULL) {
  511.         if (PBin -> Used) {
  512.         PPolygon = (PolygonStruct *) MyMalloc(sizeof(PolygonStruct));
  513.         GEN_COPY(PPolygon, PBin -> Data.PPolygon, sizeof(PolygonStruct));
  514.         return (LinearListStruct *) PPolygon;
  515.         }
  516.         else {
  517.         PBin -> Used = TRUE;
  518.         return (LinearListStruct *) PBin -> Data.PPolygon;
  519.         }
  520.     }
  521.     }
  522.     if (EntryTypes & POLYLINE_ENTRY) {          /* Check in polyline tree. */
  523.     if ((PBin = GetBinTree(Name, FD -> PolylinePointer)) != NULL) {
  524.         if (PBin -> Used) {
  525.         PPolygon = (PolygonStruct *) MyMalloc(sizeof(PolygonStruct));
  526.         GEN_COPY(PPolygon, PBin -> Data.PPolyline, sizeof(PolygonStruct));
  527.         return (LinearListStruct *) PPolygon;
  528.         }
  529.         else {
  530.         PBin -> Used = TRUE;
  531.         return (LinearListStruct *) PBin -> Data.PPolyline;
  532.         }
  533.     }
  534.     }
  535.     if (EntryTypes & OBJECT_ENTRY) {            /* Check in object tree. */
  536.     if ((PBin = GetBinTree(Name, FD -> ObjectPointer)) != NULL) {
  537.         if (PBin -> Used) {
  538.         PObject = (ObjectStruct *) MyMalloc(sizeof(ObjectStruct));
  539.         GEN_COPY(PObject, PBin -> Data.PObject, sizeof(ObjectStruct));
  540.         return (LinearListStruct *) PObject;
  541.         }
  542.         else {
  543.         PBin -> Used = TRUE;
  544.         return (LinearListStruct *) PBin -> Data.PObject;
  545.         }
  546.     }
  547.     }
  548.  
  549.     return NULL;                           /* Not found. */
  550. }
  551.  
  552. /*****************************************************************************
  553. * Routine to get linear    list of    names from file    f until    ']' is detected.     *
  554. * search for that names    in file    description FD unter the trees allowed         *
  555. * according to EntryTypes (1 bit per entry, see    ?????Entry is parser.h).     *
  556. * Create a linear list of pointers to them. Return that    linear list.         *
  557. *****************************************************************************/
  558. static VoidPtr GetLinList(FILE *f, FileDescription *FD, int EntryTypes)
  559. {
  560.     char StringToken[LINE_LEN];
  561.     struct LinearListStruct *PLinHead = NULL, *PLinTail = NULL, *PItem;
  562.  
  563.     while (GetToken(f, StringToken) != TOKEN_CLOSE_PAREN) {
  564.     if ((PItem = GetNameFromFD(StringToken, FD, EntryTypes)) == NULL) {
  565.         ParserError(P_ERR_ListCompUndef, StringToken);  /* Record undef. */
  566.         continue;             /* To next component to search for. */
  567.     }
  568.     if (PLinHead ==    NULL)                /* Its first record. */
  569.         PLinHead = PLinTail    = PItem;
  570.     else {                    /* Its record in the middle. */
  571.         PLinTail ->    Pnext =    PItem;
  572.         PLinTail = PItem;
  573.     }
  574.     }
  575.     if (PLinTail != NULL) PLinTail -> Pnext = NULL;    /* Mark end of list. */
  576.  
  577.     return (VoidPtr) PLinHead;
  578. }
  579.  
  580. #ifdef    DEBUG
  581.  
  582. /*****************************************************************************
  583. * Routine to Print all the trees in the    file description:             *
  584. *****************************************************************************/
  585. void PrintAllBinTrees(FileDescription *FD)
  586. {
  587.     fprintf(stderr, "******************* Vertices ******************\n");
  588.     PrintBinTree(FD -> VertexPointer);
  589.     fprintf(stderr, "******************* Polygons ******************\n");
  590.     PrintBinTree(FD -> PolygonPointer);
  591.     fprintf(stderr, "****************** Polyliness *****************\n");
  592.     PrintBinTree(FD -> PolylinePointer);
  593.     fprintf(stderr, "******************* Objects *******************\n");
  594.     PrintBinTree(FD -> ObjectPointer);
  595. }
  596.  
  597. /*****************************************************************************
  598. * Routine to Print the Names in    tree in    lexicorgaphic order. Used only for   *
  599. * debuging - to    see trees content...                         *
  600. *****************************************************************************/
  601. void PrintBinTree(BinTree *Tree)
  602. {
  603.     /* If the tree is empty - not found, return    NULL: */
  604.     if (Tree ==    (BinTree *) NULL) return;
  605.  
  606.     PrintBinTree(Tree -> right);
  607.     fprintf(stderr, "%s\n", Tree -> Name);
  608.     PrintBinTree(Tree -> left);
  609. }
  610.  
  611. #endif  DEBUG
  612.