home *** CD-ROM | disk | FTP | other *** search
/ Amiga Elysian Archive / AmigaElysianArchive.iso / prog / source / dkbsrc.lzh / PARSE.C < prev    next >
C/C++ Source or Header  |  1990-08-03  |  66KB  |  2,282 lines

  1. /*****************************************************************************
  2. *
  3. *                                    parse.c
  4. *
  5. *   from DKBTrace (c) 1990  David Buck
  6. *
  7. *  This module implements a parser for the scene description files.
  8. *
  9. * This software is freely distributable. The source and/or object code may be
  10. * copied or uploaded to communications services so long as this notice remains
  11. * at the top of each file.  If any changes are made to the program, you must
  12. * clearly indicate in the documentation and in the programs startup message
  13. * who it was who made the changes. The documentation should also describe what
  14. * those changes were. This software may not be included in whole or in
  15. * part into any commercial package without the express written consent of the
  16. * author.  It may, however, be included in other public domain or freely
  17. * distributed software so long as the proper credit for the software is given.
  18. *
  19. * This software is provided as is without any guarantees or warranty. Although
  20. * the author has attempted to find and correct any bugs in the software, he
  21. * is not responsible for any damage caused by the use of the software.  The
  22. * author is under no obligation to provide service, corrections, or upgrades
  23. * to this package.
  24. *
  25. * Despite all the legal stuff above, if you do find bugs, I would like to hear
  26. * about them.  Also, if you have any comments or questions, you may contact me
  27. * at the following address:
  28. *
  29. *     David Buck
  30. *     22C Sonnet Cres.
  31. *     Nepean Ontario
  32. *     Canada, K2H 8W7
  33. *
  34. *  I can also be reached on the following bulleton boards:
  35. *
  36. *     ATX              (613) 526-4141
  37. *     OMX              (613) 731-3419
  38. *     Mystic           (613) 731-0088 or (613) 731-6698
  39. *
  40. *  Fidonet:   1:163/109.9
  41. *  Internet:  David_Buck@Carleton.CA
  42. *
  43. *  IBM Port by Aaron A. Collins. Aaron may be reached on the following BBS'es:
  44. *
  45. *     Lattice BBS                      (708) 916-1200
  46. *     The Information Exchange BBS     (708) 945-5575
  47. *     Stillwaters BBS                  (708) 403-2826
  48. *
  49. *****************************************************************************/
  50.  
  51. #include "frame.h"
  52. #include "vector.h"
  53. #include "dkbproto.h"
  54.  
  55. /* This file implements a simple recursive-descent parser for reading the
  56. input file.  */
  57.  
  58. extern FILE *Token_File;
  59. FRAME *Parsing_Frame_Ptr;
  60. char Current_File_Name[20];
  61.  
  62. extern METHODS Composite_Methods;
  63. extern METHODS Basic_Object_Methods;
  64. extern METHODS Sphere_Methods;
  65. extern METHODS Quadric_Methods;
  66. extern METHODS Viewpoint_Methods;
  67. extern METHODS Plane_Methods;
  68. extern METHODS Triangle_Methods;
  69. extern METHODS Smooth_Triangle_Methods;
  70. extern METHODS CSG_Union_Methods;
  71. extern METHODS CSG_Intersection_Methods;
  72.  
  73. extern struct Reserved_Word_Struct Reserved_Words [];
  74. extern DBL Antialias_Threshold;
  75.  
  76. struct Token_Struct Token;
  77.  
  78. #define MAX_CONSTANTS 250
  79. struct Constant_Struct Constants[MAX_CONSTANTS];
  80. int Number_Of_Constants;
  81. TEXTURE *Default_Texture;
  82. int Degenerate_Triangles;
  83.  
  84. /* Here we create out own little language for doing the parsing.  It
  85. makes the code easier to read. */
  86.  
  87. #define EXPECT { int Exit_Flag; Exit_Flag = FALSE; \
  88.  while (!Exit_Flag) {Get_Token();  switch (Token.Token_Id) {
  89. #define CASE(x) case x:
  90. #define CASE2(x, y) case x: case y:
  91. #define CASE3(x, y, z) case x: case y: case z:
  92. #define CASE4(w, x, y, z) case w: case x: case y: case z:
  93. #define CASE5(v, w, x, y, z) case v: case w: case x: case y: case z:
  94. #define END_CASE break;
  95. #define EXIT Exit_Flag = TRUE;
  96. #define OTHERWISE default:
  97. #define END_EXPECT } } }
  98. #define GET(x) Get_Token(); if (Token.Token_Id != x) Parse_Error (x)
  99. #define UNGET Unget_Token();
  100.  
  101. /* Parse the file into the given frame. */
  102. void Parse (File, Frame_Ptr)
  103.   FILE *File;
  104.   FRAME *Frame_Ptr;
  105.   {
  106.   Token_File = File;
  107.   Parsing_Frame_Ptr = Frame_Ptr;
  108.  
  109.   Degenerate_Triangles = FALSE;
  110.   Token_Init ();
  111.   Frame_Init ();
  112.   Parse_Frame ();
  113.   if (Degenerate_Triangles) {
  114.      printf ("Cannot continue due to degenerate triangles.\n");
  115.      exit(1);
  116.      }
  117.   }
  118.  
  119. void Token_Init ()
  120.   {
  121.   Token.Unget_Token = FALSE;
  122.   Token.End_Of_File = FALSE;
  123.   Number_Of_Constants = 0;
  124.   }
  125.  
  126. /* Read a token from the input file and store it in the Token variable.
  127. If the token is an INCLUDE token, then set the include file name and
  128. read another token. */
  129.  
  130. int Get_Token ()
  131.   {
  132.   char *str_ptr;
  133.   int Token_Id;
  134.  
  135.   if (Token.Unget_Token)
  136.     {
  137.     Token.Unget_Token = FALSE;
  138.     return (TRUE);
  139.     }
  140.  
  141.   if (Token.End_Of_File)
  142.     {
  143.     return (FALSE);
  144.     }
  145.   
  146.   if (fscanf (Token_File, "%d %d", &Token_Id, &Token.Token_Line_No)
  147.        != 2)
  148.     {
  149.     Token.End_Of_File = TRUE;
  150.     Token.Token_Id    = END_OF_FILE_TOKEN;
  151.     return (TRUE);
  152.     }
  153.  
  154.   Token.Token_Id = Token_Id;
  155.  
  156.   getc(Token_File);
  157.   if (fgets (Token.Token_String, FILE_NAME_LENGTH, Token_File) == NULL)
  158.     {
  159.     Token.End_Of_File = TRUE;
  160.     Token.Token_Id    = END_OF_FILE_TOKEN;
  161.     return (TRUE);
  162.     }
  163.  
  164.   if ((str_ptr = strchr(Token.Token_String, '\n')) != NULL)
  165.      *str_ptr = '\0';
  166.  
  167.   if (Token.Token_Id == FLOAT_TOKEN)
  168.     if (sscanf (Token.Token_String, DBL_FORMAT_STRING, &(Token.Token_Float)) != 1)
  169.       {
  170.       printf ("Premature end of file in token file\n");
  171.       printf ("Could not read float: %s\n", Token.Token_String);
  172.       Token.End_Of_File = TRUE;
  173.       Token.Token_Id    = END_OF_FILE_TOKEN;
  174.       return (TRUE);
  175.       }
  176.  
  177.   if (Token.Token_Id == INCLUDE_TOKEN) {
  178.      strcpy (Current_File_Name, Token.Token_String);
  179.      return (Get_Token());
  180.      }
  181.  
  182.   if (Token.Token_Id > LAST_TOKEN)
  183.     {
  184.     Token.Identifier_Number = (int) Token.Token_Id - (int) LAST_TOKEN;
  185.     Token.Token_Id = IDENTIFIER_TOKEN;
  186.     }
  187.  
  188.   return (TRUE);
  189.   }
  190.  
  191.  
  192. /* Mark that the token has been put back into the input stream.  The next
  193. call to Get_Token will return the last-read token instead of reading a
  194. new one from the file. */
  195.  
  196. void Unget_Token ()
  197.   {
  198.   Token.Unget_Token = TRUE;
  199.   }
  200.  
  201. /* Set up the fields in the frame to default values. */
  202. void Frame_Init ()
  203.   {
  204.   Default_Texture = Get_Texture();
  205.   Init_Viewpoint(&(Parsing_Frame_Ptr -> View_Point));
  206.   Parsing_Frame_Ptr -> Light_Sources = NULL;
  207.   Parsing_Frame_Ptr -> Objects = NULL;
  208.   Parsing_Frame_Ptr -> Atmosphere_IOR = 1.0;
  209.   Parsing_Frame_Ptr -> Antialias_Threshold = Antialias_Threshold;
  210.   Parsing_Frame_Ptr -> Fog_Distance = 0.0;
  211.   Make_Colour (&(Parsing_Frame_Ptr->Fog_Colour), 0.0, 0.0, 0.0);
  212.   }
  213.  
  214. /* Allocate and initialize a composite object. */
  215. COMPOSITE *Get_Composite_Object()
  216.   {
  217.   COMPOSITE *New_Composite;
  218.  
  219.   if ((New_Composite = (COMPOSITE *) malloc (sizeof (COMPOSITE)))
  220.         == NULL)
  221.     Error ("Cannot allocate object");
  222.  
  223.   New_Composite -> Objects = NULL;
  224.   New_Composite -> Next_Object = NULL;
  225.   New_Composite -> Next_Light_Source = NULL;
  226.   New_Composite -> Bounding_Shapes = NULL;
  227.   New_Composite -> Type = COMPOSITE_TYPE;
  228.   New_Composite -> Methods = &Composite_Methods;
  229.   return (New_Composite);
  230.   }
  231.  
  232. /* Allocate and initialize a sphere. */
  233. SPHERE *Get_Sphere_Shape()
  234.   {
  235.   SPHERE *New_Shape;
  236.  
  237.   if ((New_Shape = (SPHERE *) malloc (sizeof (SPHERE))) == NULL)
  238.     Error ("Cannot allocate shape");
  239.  
  240.   Make_Vector (&(New_Shape -> Center), 0.0, 0.0, 0.0);
  241.   New_Shape->Radius = 1.0;
  242.   New_Shape->Radius_Squared = 1.0;
  243.   New_Shape->Inverse_Radius = 1.0;
  244.   New_Shape -> Type = SPHERE_TYPE;
  245.   New_Shape -> Next_Object = NULL;
  246.   New_Shape -> Methods = &Sphere_Methods;
  247.   New_Shape -> VPCached = FALSE;
  248.   New_Shape -> Inverted = FALSE;
  249.   return (New_Shape);
  250.   }
  251.  
  252. /* Allocate and initialize a quadric surface. */
  253. QUADRIC *Get_Quadric_Shape()
  254.   {
  255.   QUADRIC *New_Shape;
  256.  
  257.   if ((New_Shape = (QUADRIC *) malloc (sizeof (QUADRIC))) == NULL)
  258.     Error ("Cannot allocate shape");
  259.  
  260.   Make_Vector (&(New_Shape -> Object_2_Terms), 1.0, 1.0, 1.0);
  261.   Make_Vector (&(New_Shape -> Object_Mixed_Terms), 0.0, 0.0, 0.0);
  262.   Make_Vector (&(New_Shape -> Object_Terms), 0.0, 0.0, 0.0);
  263.   New_Shape -> Object_Constant = 1.0;
  264.   New_Shape -> Object_VP_Constant = HUGE_VAL;
  265.   New_Shape -> Constant_Cached = FALSE;
  266.   New_Shape -> Non_Zero_Square_Term = FALSE;
  267.   New_Shape -> Type = QUADRIC_TYPE;
  268.   New_Shape -> Next_Object = NULL;
  269.   New_Shape -> Methods = &Quadric_Methods;
  270.   return (New_Shape);
  271.   }
  272.  
  273. /* Allocate and initialize a plane. */
  274. PLANE *Get_Plane_Shape()
  275.   {
  276.   PLANE *New_Shape;
  277.  
  278.   if ((New_Shape = (PLANE *) malloc (sizeof (PLANE))) == NULL)
  279.     Error ("Cannot allocate shape");
  280.  
  281.   Make_Vector (&(New_Shape -> Normal_Vector), 0.0, 1.0, 0.0);
  282.   New_Shape->Distance = 0.0;
  283.   New_Shape -> Type = PLANE_TYPE;
  284.   New_Shape -> Next_Object = NULL;
  285.   New_Shape -> Methods = &Plane_Methods;
  286.   New_Shape -> VPCached = 0;
  287.   return (New_Shape);
  288.   }
  289.  
  290. /* Allocate and initialize a triangle. */
  291. TRIANGLE *Get_Triangle_Shape()
  292.   {
  293.   TRIANGLE *New_Shape;
  294.  
  295.   if ((New_Shape = (TRIANGLE *) malloc (sizeof (TRIANGLE))) == NULL)
  296.     Error ("Cannot allocate shape");
  297.  
  298.   Make_Vector (&(New_Shape -> Normal_Vector), 0.0, 1.0, 0.0);
  299.   Make_Vector (&(New_Shape -> P1), 0.0, 0.0, 0.0);
  300.   Make_Vector (&(New_Shape -> P2), 1.0, 0.0, 0.0);
  301.   Make_Vector (&(New_Shape -> P3), 0.0, 1.0, 0.0);
  302.   New_Shape->Distance = 0.0;
  303.   New_Shape->Inverted = FALSE;
  304.   New_Shape -> Type = TRIANGLE_TYPE;
  305.   New_Shape -> Next_Object = NULL;
  306.   New_Shape -> Methods = &Triangle_Methods;
  307.   New_Shape -> VPCached = FALSE;
  308.   return (New_Shape);
  309.   }
  310.  
  311. /* Allocate and initialize a smooth triangle. */
  312. SMOOTH_TRIANGLE *Get_Smooth_Triangle_Shape()
  313.   {
  314.   SMOOTH_TRIANGLE *New_Shape;
  315.  
  316.   if ((New_Shape = (SMOOTH_TRIANGLE *) malloc (sizeof (SMOOTH_TRIANGLE))) == NULL)
  317.     Error ("Cannot allocate shape");
  318.  
  319.   Make_Vector (&(New_Shape -> Normal_Vector), 0.0, 1.0, 0.0);
  320.   Make_Vector (&(New_Shape -> P1), 0.0, 0.0, 0.0);
  321.   Make_Vector (&(New_Shape -> P2), 1.0, 0.0, 0.0);
  322.   Make_Vector (&(New_Shape -> P3), 0.0, 1.0, 0.0);
  323.   Make_Vector (&(New_Shape -> N1), 0.0, 1.0, 0.0);
  324.   Make_Vector (&(New_Shape -> DN12), 0.0, 1.0, 0.0);
  325.   Make_Vector (&(New_Shape -> DN13), 0.0, 1.0, 0.0);
  326.   New_Shape->Distance = 0.0;
  327.   New_Shape -> Type = SMOOTH_TRIANGLE_TYPE;
  328.   New_Shape->Inverted = FALSE;
  329.   New_Shape -> Next_Object = NULL;
  330.   New_Shape -> Methods = &Smooth_Triangle_Methods;
  331.   New_Shape -> VPCached = 0;
  332.   return (New_Shape);
  333.   }
  334.  
  335. CSG_SHAPE *Get_CSG_Shape()
  336.   {
  337.   CSG_SHAPE *New_Shape;
  338.  
  339.   if ((New_Shape = (CSG_SHAPE *) malloc (sizeof (CSG_SHAPE))) == NULL)
  340.     Error ("Cannot allocate shape");
  341.  
  342.   New_Shape -> Parent_Object = NULL;
  343.   New_Shape -> Next_Object = NULL;
  344.   New_Shape -> Shapes = NULL;
  345.   return (New_Shape);
  346.   }
  347.  
  348. CSG_SHAPE *Get_CSG_Union()
  349.   {
  350.   CSG_SHAPE *New_Shape;
  351.  
  352.   New_Shape = Get_CSG_Shape();
  353.   New_Shape -> Methods = &CSG_Union_Methods;
  354.   New_Shape -> Type = CSG_UNION_TYPE;
  355.   return (New_Shape);
  356.   }
  357.  
  358. CSG_SHAPE *Get_CSG_Intersection()
  359.   {
  360.   CSG_SHAPE *New_Shape;
  361.  
  362.   New_Shape = Get_CSG_Shape();
  363.   New_Shape -> Methods = &CSG_Intersection_Methods;
  364.   New_Shape -> Type = CSG_INTERSECTION_TYPE;
  365.   return (New_Shape);
  366.   }
  367.  
  368. OBJECT *Get_Object ()
  369.   {
  370.   OBJECT *New_Object;
  371.  
  372.   if ((New_Object = (OBJECT *) malloc (sizeof (OBJECT))) == NULL)
  373.     Error ("Cannot allocate object");
  374.  
  375.   Make_Vector (&(New_Object -> Object_Center), 0.0, 0.0, 0.0);
  376.  
  377.   New_Object -> Next_Object = NULL;
  378.   New_Object -> Next_Light_Source = NULL;
  379.   New_Object -> Shape = NULL;
  380.   New_Object -> Bounding_Shapes = NULL;
  381.   New_Object -> Object_Texture = Default_Texture;
  382.  
  383.   Make_Colour (&New_Object->Object_Colour, 0.0, 0.0, 0.0);
  384.  
  385.   New_Object -> Light_Source_Flag = FALSE;
  386.   New_Object -> Transparency = FALSE;
  387.   New_Object -> Type = OBJECT_TYPE;
  388.   New_Object -> Methods = &Basic_Object_Methods;
  389.   return (New_Object);
  390.   }
  391.  
  392. TEXTURE *Get_Texture ()
  393.    {
  394.    TEXTURE *New_Texture;
  395.  
  396.    if ((New_Texture = (TEXTURE *) malloc (sizeof (TEXTURE))) == NULL)
  397.      Error ("Cannot allocate object");
  398.  
  399.    New_Texture -> Object_Reflection = 0.0;
  400.    New_Texture -> Object_Ambient = 0.3;
  401.    New_Texture -> Object_Diffuse = 0.7;
  402.    New_Texture -> Object_Brilliance = 1.0;
  403.    New_Texture -> Object_Specular = 0.0;
  404.    New_Texture -> Object_Roughness = 0.05;
  405.    New_Texture -> Object_Phong = 0.0;
  406.    New_Texture -> Object_PhongSize = 40;
  407.  
  408.    New_Texture -> Texture_Randomness= 0.0;
  409.    New_Texture -> Bump_Amount = 0.0;
  410.    New_Texture -> Phase = 0.0;
  411.    New_Texture -> Frequency = 1.0;
  412.    New_Texture -> Texture_Number = 0;
  413.    New_Texture -> Texture_Transformation = NULL;
  414.    New_Texture -> Bump_Number = NO_BUMPS;
  415.    New_Texture -> Turbulence = 0.0;
  416.    New_Texture -> Colour_Map = NULL;
  417.    New_Texture -> Once_Flag = FALSE;
  418.    Make_Colour (&New_Texture -> Colour1, 0.0, 0.0, 0.0);
  419.    Make_Colour (&New_Texture -> Colour2, 0.0, 0.0, 0.0);
  420.    Make_Vector (&New_Texture->Texture_Gradient, 0.0, 0.0, 0.0);
  421.  
  422.    New_Texture -> Object_Index_Of_Refraction = 1.0;
  423.    New_Texture -> Object_Refraction = 0.0;
  424.  
  425.    return (New_Texture);
  426.    }
  427.  
  428. VIEWPOINT *Get_Viewpoint ()
  429.   {
  430.   VIEWPOINT *New_Viewpoint;
  431.  
  432.   if ((New_Viewpoint = (VIEWPOINT *)malloc (sizeof (VIEWPOINT)))
  433.         == NULL)
  434.     Error ("Cannot allocate viewpoint");
  435.  
  436.   Init_Viewpoint (New_Viewpoint);
  437.   return (New_Viewpoint);
  438.   }
  439.  
  440. COLOUR *Get_Colour ()
  441.   {
  442.   COLOUR *New_Colour;
  443.  
  444.   if ((New_Colour = (COLOUR *) malloc (sizeof (COLOUR))) == NULL)
  445.     Error ("Cannot allocate colour");
  446.  
  447.   Make_Colour (New_Colour, 0.0, 0.0, 0.0);
  448.   return (New_Colour);
  449.   }
  450.  
  451. VECTOR *Get_Vector ()
  452.   {
  453.   VECTOR *New_Vector;
  454.  
  455.   if ((New_Vector = (VECTOR *) malloc (sizeof (VECTOR))) == NULL)
  456.     Error ("Cannot allocate vector");
  457.  
  458.   New_Vector -> x = 0.0;
  459.   New_Vector -> y = 0.0;
  460.   New_Vector -> z = 0.0;
  461.   return (New_Vector);
  462.   }
  463.  
  464. DBL *Get_Float ()
  465.   {
  466.   DBL *New_Float;
  467.  
  468.   if ((New_Float = (DBL *) malloc (sizeof (DBL))) == NULL)
  469.     Error ("Cannot allocate float");
  470.  
  471.   *New_Float = 0.0;
  472.   return (New_Float);
  473.   }
  474.  
  475. TRANSFORMATION *Get_Transformation()
  476.   {
  477.   TRANSFORMATION *New_Transformation;
  478.  
  479.   if ((New_Transformation =
  480.         (TRANSFORMATION *) malloc (sizeof (TRANSFORMATION))) == NULL)
  481.     Error ("Cannot allocate transformation");
  482.  
  483.   MIdentity ((MATRIX *) &(New_Transformation -> matrix[0][0]));
  484.   MIdentity ((MATRIX *) &(New_Transformation -> inverse[0][0]));
  485.   return (New_Transformation);
  486.   }
  487.  
  488. /* Parse a float.  Doesn't handle exponentiation. */
  489. DBL Parse_Float ()
  490.   {
  491.   DBL Local_Float = 0.0;
  492.   CONSTANT Constant_Id;
  493.   register int Negative, Sign_Parsed;
  494.  
  495.   Negative = FALSE;
  496.   Sign_Parsed = FALSE;
  497.  
  498.   EXPECT
  499.     CASE (IDENTIFIER_TOKEN)
  500.       if ((Constant_Id = Find_Constant()) != -1)
  501.         if (Constants[(int)Constant_Id].Constant_Type == FLOAT_CONSTANT)
  502.           {
  503.           Local_Float = *((DBL *) Constants[(int)Constant_Id].Constant_Data);
  504.           if (Negative)
  505.             Local_Float *= -1.0;
  506.           }
  507.         else
  508.           Type_Error ();
  509.       else
  510.         Undeclared ();
  511.       EXIT
  512.     END_CASE
  513.  
  514.     CASE (PLUS_TOKEN)
  515.       if (Sign_Parsed)
  516.         Parse_Error (FLOAT_TOKEN);
  517.       Sign_Parsed = TRUE;
  518.     END_CASE
  519.  
  520.     CASE (DASH_TOKEN)
  521.       if (Sign_Parsed)
  522.         Parse_Error (FLOAT_TOKEN);
  523.       Negative = TRUE;
  524.       Sign_Parsed = TRUE;
  525.     END_CASE
  526.  
  527.     CASE (FLOAT_TOKEN)
  528.       Local_Float = Token.Token_Float;
  529.       if (Negative)
  530.         Local_Float *= -1.0;
  531.       EXIT
  532.     END_CASE
  533.  
  534.     OTHERWISE
  535.       Parse_Error (FLOAT_TOKEN);
  536.     END_CASE
  537.   END_EXPECT
  538.  
  539.   return (Local_Float);
  540.   }
  541.  
  542. void Parse_Vector (Given_Vector)
  543.   VECTOR *Given_Vector;
  544.   {
  545.   CONSTANT Constant_Id;
  546.  
  547.   EXPECT
  548.     CASE (IDENTIFIER_TOKEN)
  549.       if ((Constant_Id = Find_Constant()) != -1)
  550.         if (Constants[(int)Constant_Id].Constant_Type == VECTOR_CONSTANT)
  551.           *Given_Vector = *((VECTOR *) Constants[(int)Constant_Id].Constant_Data);
  552.         else
  553.           Type_Error ();
  554.       else
  555.         Undeclared ();
  556.       EXIT
  557.     END_CASE
  558.  
  559.     CASE (LEFT_ANGLE_TOKEN)
  560.       (Given_Vector -> x) = Parse_Float();
  561.       (Given_Vector -> y) = Parse_Float();
  562.       (Given_Vector -> z) = Parse_Float();
  563.       GET (RIGHT_ANGLE_TOKEN);
  564.       EXIT
  565.     END_CASE
  566.  
  567.     OTHERWISE 
  568.       Parse_Error (LEFT_ANGLE_TOKEN);
  569.     END_CASE
  570.   END_EXPECT
  571.   }
  572.  
  573. void Parse_Colour (Given_Colour)
  574.   COLOUR *Given_Colour;
  575.   {
  576.   CONSTANT Constant_Id;
  577.  
  578.   Make_Colour (Given_Colour, 0.0, 0.0, 0.0);
  579.   EXPECT
  580.     CASE (IDENTIFIER_TOKEN)
  581.       if ((Constant_Id = Find_Constant()) != -1)
  582.         if (Constants[(int)Constant_Id].Constant_Type == COLOUR_CONSTANT)
  583.           *Given_Colour = *((COLOUR *) Constants[(int)Constant_Id].Constant_Data);
  584.         else
  585.           Type_Error ();
  586.       else
  587.         Undeclared ();
  588.     END_CASE
  589.  
  590.     CASE (RED_TOKEN)
  591.       (Given_Colour -> Red) = Parse_Float();
  592.     END_CASE
  593.  
  594.     CASE (GREEN_TOKEN)
  595.       (Given_Colour -> Green) = Parse_Float();
  596.     END_CASE
  597.  
  598.     CASE (BLUE_TOKEN)
  599.       (Given_Colour -> Blue) = Parse_Float();
  600.     END_CASE
  601.  
  602.     CASE (ALPHA_TOKEN)
  603.       (Given_Colour -> Alpha) = Parse_Float();
  604.     END_CASE
  605.  
  606.     OTHERWISE
  607.       UNGET
  608.       EXIT
  609.     END_CASE
  610.   END_EXPECT
  611.   }
  612.  
  613. COLOUR_MAP *Parse_Colour_Map ()
  614.    {
  615. #define MAX_ENTRIES 20
  616.    COLOUR_MAP *New_Colour_Map;
  617.    register int i;
  618.  
  619.    if ((New_Colour_Map = (COLOUR_MAP *) malloc (sizeof (COLOUR_MAP))) == NULL)
  620.       Error ("Not enough memory for colour map");
  621.  
  622.    if ((New_Colour_Map -> Colour_Map_Entries = (COLOUR_MAP_ENTRY *)
  623.                   malloc(MAX_ENTRIES * sizeof (COLOUR_MAP_ENTRY))) == NULL)
  624.       Error ("Not enough memory for colour map");
  625.  
  626.    i = 0;
  627.    EXPECT
  628.       CASE (LEFT_SQUARE_TOKEN)
  629.          New_Colour_Map -> Colour_Map_Entries [i].start = Parse_Float();
  630.          New_Colour_Map -> Colour_Map_Entries [i].end = Parse_Float();
  631.          GET (COLOUR_TOKEN);
  632.          Parse_Colour (&(New_Colour_Map->Colour_Map_Entries[i].Start_Colour));
  633.          GET (COLOUR_TOKEN);
  634.          Parse_Colour (&(New_Colour_Map->Colour_Map_Entries[i].End_Colour));
  635.          i++;
  636.          if (i > MAX_ENTRIES)
  637.             Error ("Colour_Map too long");
  638.          GET (RIGHT_SQUARE_TOKEN);
  639.       END_CASE
  640.  
  641.       CASE2 (END_COLOUR_MAP_TOKEN, END_COLOR_MAP_TOKEN)
  642.           New_Colour_Map -> Number_Of_Entries = i;
  643.           EXIT
  644.       END_CASE
  645.  
  646.       OTHERWISE
  647.          Parse_Error (END_COLOUR_MAP_TOKEN);
  648.       END_CASE
  649.    END_EXPECT
  650.    return (New_Colour_Map);
  651.    }
  652.  
  653. TEXTURE *Copy_Texture (Texture)
  654.    TEXTURE *Texture;
  655.    {
  656.    TEXTURE *New_Texture;
  657.    New_Texture = Get_Texture();
  658.    *New_Texture = *Texture;
  659.    if (New_Texture->Texture_Transformation) {
  660.       if ((New_Texture->Texture_Transformation = (TRANSFORMATION *) malloc (sizeof (TRANSFORMATION))) == NULL)
  661.      Error("Cannot allocate texture transformation");
  662.       *New_Texture->Texture_Transformation = *Texture->Texture_Transformation;
  663.       }
  664.    return (New_Texture);
  665.    }
  666.  
  667. TEXTURE *Parse_Texture (Old_Texture)
  668.    TEXTURE *Old_Texture;
  669.    {
  670.    VECTOR Local_Vector;
  671.    TRANSFORMATION Local_Transformation;
  672.    CONSTANT Constant_Id;
  673.    TEXTURE *Texture;
  674.    int Texture_Constant;
  675.  
  676.    Texture = Old_Texture;
  677.    Texture_Constant = TRUE;
  678.  
  679.    EXPECT
  680.       CASE (IDENTIFIER_TOKEN)
  681.          if ((Constant_Id = Find_Constant()) != -1)
  682.             if (Constants[(int)Constant_Id].Constant_Type == TEXTURE_CONSTANT) {
  683.                Texture = ((TEXTURE *) Constants[(int)Constant_Id].Constant_Data);
  684.                Texture_Constant = TRUE;
  685.                }
  686.             else
  687.                Type_Error ();
  688.          else
  689.             Undeclared ();
  690.       END_CASE
  691.  
  692.       CASE (FLOAT_TOKEN)
  693.          UNGET
  694.          if (Texture_Constant) {
  695.             Texture = Copy_Texture(Texture);
  696.             Texture_Constant = FALSE;
  697.             }
  698.          Texture -> Texture_Randomness = Parse_Float();
  699.       END_CASE
  700.  
  701.       CASE (ONCE_TOKEN)
  702.          if (Texture_Constant) {
  703.             Texture = Copy_Texture(Texture);
  704.             Texture_Constant = FALSE;
  705.             }
  706.          Texture->Once_Flag = TRUE;
  707.       END_CASE
  708.  
  709.       CASE (TURBULENCE_TOKEN)
  710.          if (Texture_Constant) {
  711.             Texture = Copy_Texture(Texture);
  712.             Texture_Constant = FALSE;
  713.             }
  714.           Texture -> Turbulence = Parse_Float();
  715.       END_CASE
  716.  
  717.       CASE (BOZO_TOKEN)
  718.          if (Texture_Constant) {
  719.             Texture_Constant = FALSE;
  720.             Texture = Copy_Texture (Texture);
  721.             }
  722.          Texture -> Texture_Number = BOZO_TEXTURE;
  723.       END_CASE
  724.  
  725.       CASE (CHECKER_TOKEN)
  726.          if (Texture_Constant) {
  727.             Texture_Constant = FALSE;
  728.             Texture = Copy_Texture (Texture);
  729.             }
  730.          Texture -> Texture_Number = CHECKER_TEXTURE;
  731.          EXPECT
  732.             CASE (COLOUR_TOKEN)
  733.                Parse_Colour (&(Texture -> Colour1));
  734.                GET (COLOUR_TOKEN);
  735.                Parse_Colour (&(Texture -> Colour2));
  736.             END_CASE
  737.  
  738.             OTHERWISE
  739.                UNGET
  740.                EXIT
  741.             END_CASE
  742.          END_EXPECT
  743.       END_CASE
  744.  
  745.       CASE (MARBLE_TOKEN)
  746.          if (Texture_Constant) {
  747.             Texture_Constant = FALSE;
  748.             Texture = Copy_Texture (Texture);
  749.             }
  750.          Texture -> Texture_Number = MARBLE_TEXTURE;
  751.       END_CASE
  752.  
  753.       CASE (WOOD_TOKEN)
  754.          if (Texture_Constant) {
  755.             Texture_Constant = FALSE;
  756.             Texture = Copy_Texture (Texture);
  757.             }
  758.          Texture -> Texture_Number = WOOD_TEXTURE;
  759.       END_CASE
  760.  
  761.       CASE (SPOTTED_TOKEN)
  762.          if (Texture_Constant) {
  763.             Texture_Constant = FALSE;
  764.             Texture = Copy_Texture (Texture);
  765.             }
  766.          Texture -> Texture_Number = SPOTTED_TEXTURE;
  767.       END_CASE
  768.  
  769.       CASE (AGATE_TOKEN)
  770.          if (Texture_Constant) {
  771.             Texture_Constant = FALSE;
  772.             Texture = Copy_Texture (Texture);
  773.             }
  774.          Texture -> Texture_Number = AGATE_TEXTURE;
  775.       END_CASE
  776.  
  777.       CASE (GRANITE_TOKEN)
  778.          if (Texture_Constant) {
  779.             Texture_Constant = FALSE;
  780.             Texture = Copy_Texture (Texture);
  781.             }
  782.          Texture -> Texture_Number = GRANITE_TEXTURE;
  783.       END_CASE
  784.  
  785.        CASE (GRADIENT_TOKEN)
  786.          if (Texture_Constant) {
  787.             Texture_Constant = FALSE;
  788.             Texture = Copy_Texture (Texture);
  789.             }
  790.      Texture -> Texture_Number = GRADIENT_TEXTURE;
  791.      Parse_Vector (&(Texture -> Texture_Gradient));
  792.        END_CASE
  793.  
  794.       CASE (AMBIENT_TOKEN)
  795.          if (Texture_Constant) {
  796.             Texture_Constant = FALSE;
  797.             Texture = Copy_Texture (Texture);
  798.             }
  799.          (Texture -> Object_Ambient) = Parse_Float ();
  800.       END_CASE
  801.  
  802.       CASE (BRILLIANCE_TOKEN)
  803.          if (Texture_Constant) {
  804.             Texture_Constant = FALSE;
  805.             Texture = Copy_Texture (Texture);
  806.             }
  807.          (Texture -> Object_Brilliance) = Parse_Float ();
  808.       END_CASE
  809.  
  810.       CASE (ROUGHNESS_TOKEN)
  811.          if (Texture_Constant) {
  812.             Texture_Constant = FALSE;
  813.             Texture = Copy_Texture (Texture);
  814.             }
  815.          (Texture -> Object_Roughness) = Parse_Float ();
  816.          if (Texture -> Object_Roughness > 1.0)
  817.             Texture -> Object_Roughness = 1.0;
  818.          if (Texture -> Object_Roughness < 0.001)
  819.             Texture -> Object_Roughness = 0.001;
  820.       END_CASE
  821.  
  822.       CASE (PHONGSIZE_TOKEN)
  823.          if (Texture_Constant) {
  824.             Texture_Constant = FALSE;
  825.             Texture = Copy_Texture (Texture);
  826.             }
  827.          (Texture -> Object_PhongSize) = Parse_Float ();
  828.          if (Texture -> Object_PhongSize < 1.0)
  829.             Texture -> Object_PhongSize = 1.0;
  830.          if (Texture -> Object_PhongSize > 100)
  831.             Texture -> Object_PhongSize = 100;
  832.       END_CASE
  833.  
  834.       CASE (DIFFUSE_TOKEN)
  835.          if (Texture_Constant) {
  836.             Texture_Constant = FALSE;
  837.             Texture = Copy_Texture (Texture);
  838.             }
  839.          (Texture -> Object_Diffuse) = Parse_Float ();
  840.       END_CASE
  841.  
  842.       CASE (SPECULAR_TOKEN)
  843.          if (Texture_Constant) {
  844.             Texture_Constant = FALSE;
  845.             Texture = Copy_Texture (Texture);
  846.             }
  847.          (Texture -> Object_Specular) = Parse_Float ();
  848.       END_CASE
  849.  
  850.       CASE (PHONG_TOKEN)
  851.          if (Texture_Constant) {
  852.             Texture_Constant = FALSE;
  853.             Texture = Copy_Texture (Texture);
  854.             }
  855.          (Texture -> Object_Phong) = Parse_Float ();
  856.       END_CASE
  857.  
  858.       CASE (IOR_TOKEN)
  859.          if (Texture_Constant) {
  860.             Texture_Constant = FALSE;
  861.             Texture = Copy_Texture (Texture);
  862.             }
  863.          (Texture -> Object_Index_Of_Refraction) = Parse_Float ();
  864.       END_CASE
  865.  
  866.       CASE (REFRACTION_TOKEN)
  867.          if (Texture_Constant) {
  868.             Texture_Constant = FALSE;
  869.             Texture = Copy_Texture (Texture);
  870.             }
  871.          (Texture -> Object_Refraction) = Parse_Float ();
  872.       END_CASE
  873.  
  874.       CASE (REFLECTION_TOKEN)
  875.          if (Texture_Constant) {
  876.             Texture_Constant = FALSE;
  877.             Texture = Copy_Texture (Texture);
  878.             }
  879.          (Texture -> Object_Reflection) = Parse_Float ();
  880.       END_CASE
  881.  
  882.       CASE (IMAGEMAP_TOKEN)
  883.          if (Texture_Constant) {
  884.             Texture_Constant = FALSE;
  885.             Texture = Copy_Texture (Texture);
  886.             }
  887.          Texture -> Texture_Number = IMAGEMAP_TEXTURE;
  888.          if ((Texture->Image = (IMAGE *)malloc(sizeof(IMAGE))) == NULL)
  889.          Error("Cannot allocate imagemap texture");
  890.          Make_Vector (&Texture->Texture_Gradient, 1.0, -1.0, 0.0);
  891.          EXPECT
  892.             CASE (LEFT_ANGLE_TOKEN)
  893.                  UNGET
  894.                  Parse_Vector (&(Texture -> Texture_Gradient));
  895.             END_CASE
  896.  
  897.             CASE (IFF_TOKEN)
  898.                GET (STRING_TOKEN);
  899.                read_iff_image(Texture->Image, Token.Token_String);
  900.                EXIT
  901.             END_CASE
  902.  
  903.             CASE (GIF_TOKEN)
  904.                GET (STRING_TOKEN);
  905.                read_gif_image(Texture->Image, Token.Token_String);
  906.                EXIT
  907.             END_CASE
  908.  
  909.             CASE (RAW_TOKEN)
  910.                GET (STRING_TOKEN);
  911.                read_raw_image(Texture->Image, Token.Token_String);
  912.                EXIT
  913.             END_CASE
  914.  
  915.             OTHERWISE
  916.                Parse_Error (RAW_TOKEN);
  917.             END_CASE
  918.          END_EXPECT
  919.       END_CASE
  920.  
  921.       CASE (WAVES_TOKEN)
  922.          if (Texture_Constant) {
  923.             Texture_Constant = FALSE;
  924.             Texture = Copy_Texture (Texture);
  925.             }
  926.          Texture -> Bump_Number = WAVES;
  927.          Texture -> Bump_Amount = Parse_Float ();
  928.          EXPECT
  929.             CASE (PHASE_TOKEN)
  930.                Texture -> Phase = Parse_Float();
  931.                EXIT
  932.             END_CASE
  933.  
  934.             OTHERWISE
  935.                UNGET
  936.                EXIT
  937.             END_CASE
  938.          END_EXPECT
  939.       END_CASE
  940.  
  941.       CASE (FREQUENCY_TOKEN)
  942.          if (Texture_Constant) {
  943.             Texture_Constant = FALSE;
  944.             Texture = Copy_Texture (Texture);
  945.             }
  946.          Texture -> Frequency = Parse_Float();
  947.       END_CASE
  948.  
  949.       CASE (PHASE_TOKEN)
  950.          if (Texture_Constant) {
  951.             Texture_Constant = FALSE;
  952.             Texture = Copy_Texture (Texture);
  953.             }
  954.          Texture -> Phase = Parse_Float();
  955.       END_CASE
  956.  
  957.       CASE (RIPPLES_TOKEN)
  958.          if (Texture_Constant) {
  959.             Texture_Constant = FALSE;
  960.             Texture = Copy_Texture (Texture);
  961.             }
  962.          Texture -> Bump_Number = RIPPLES;
  963.          Texture -> Bump_Amount = Parse_Float ();
  964.       END_CASE
  965.  
  966.       CASE (WRINKLES_TOKEN)
  967.          if (Texture_Constant) {
  968.             Texture_Constant = FALSE;
  969.             Texture = Copy_Texture (Texture);
  970.             }
  971.          Texture -> Bump_Number = WRINKLES;
  972.          Texture -> Bump_Amount = Parse_Float ();
  973.       END_CASE
  974.  
  975.       CASE (BUMPS_TOKEN)
  976.          if (Texture_Constant) {
  977.             Texture_Constant = FALSE;
  978.             Texture = Copy_Texture (Texture);
  979.             }
  980.          Texture -> Bump_Number = BUMPS;
  981.          Texture -> Bump_Amount = Parse_Float ();
  982.       END_CASE
  983.  
  984.       CASE (DENTS_TOKEN)
  985.          if (Texture_Constant) {
  986.             Texture_Constant = FALSE;
  987.             Texture = Copy_Texture (Texture);
  988.             }
  989.          Texture -> Bump_Number = DENTS;
  990.          Texture -> Bump_Amount = Parse_Float ();
  991.       END_CASE
  992.  
  993.       CASE (TRANSLATE_TOKEN)
  994.          if (Texture_Constant) {
  995.             Texture_Constant = FALSE;
  996.             Texture = Copy_Texture (Texture);
  997.             }
  998.          Parse_Vector (&Local_Vector);
  999.          if (!Texture -> Texture_Transformation)
  1000.             Texture -> Texture_Transformation = Get_Transformation ();
  1001.          Get_Translation_Transformation (&Local_Transformation,
  1002.                                          &Local_Vector);
  1003.          Compose_Transformations (Texture -> Texture_Transformation,
  1004.                                   &Local_Transformation);
  1005.       END_CASE
  1006.  
  1007.       CASE (ROTATE_TOKEN)
  1008.          if (Texture_Constant) {
  1009.             Texture_Constant = FALSE;
  1010.             Texture = Copy_Texture (Texture);
  1011.             }
  1012.          Parse_Vector (&Local_Vector);
  1013.          if (!Texture -> Texture_Transformation)
  1014.             Texture -> Texture_Transformation = Get_Transformation ();
  1015.          Get_Rotation_Transformation (&Local_Transformation,
  1016.                                       &Local_Vector);
  1017.          Compose_Transformations (Texture -> Texture_Transformation,
  1018.                                   &Local_Transformation);
  1019.       END_CASE
  1020.  
  1021.       CASE (SCALE_TOKEN)
  1022.          if (Texture_Constant) {
  1023.             Texture_Constant = FALSE;
  1024.             Texture = Copy_Texture (Texture);
  1025.             }
  1026.          Parse_Vector (&Local_Vector);
  1027.          if (!Texture -> Texture_Transformation)
  1028.              Texture -> Texture_Transformation = Get_Transformation ();
  1029.          Get_Scaling_Transformation (&Local_Transformation,
  1030.                                      &Local_Vector);
  1031.          Compose_Transformations (Texture -> Texture_Transformation,
  1032.                                   &Local_Transformation);
  1033.       END_CASE
  1034.  
  1035.       CASE2 (COLOUR_MAP_TOKEN, COLOR_MAP_TOKEN)
  1036.          if (Texture_Constant) {
  1037.             Texture_Constant = FALSE;
  1038.             Texture = Copy_Texture (Texture);
  1039.             }
  1040.          Texture -> Colour_Map = Parse_Colour_Map();
  1041.       END_CASE
  1042.  
  1043.       CASE (END_TEXTURE_TOKEN)
  1044.          EXIT
  1045.       END_CASE
  1046.  
  1047.       OTHERWISE
  1048.          Parse_Error (END_TEXTURE_TOKEN);
  1049.       END_CASE
  1050.    END_EXPECT
  1051.    return (Texture);
  1052.    }
  1053.  
  1054. SHAPE *Parse_Sphere ()
  1055.   {
  1056.   SPHERE *Local_Shape;
  1057.   CONSTANT Constant_Id;
  1058.   VECTOR Local_Vector;
  1059.  
  1060.   Local_Shape = NULL;
  1061.  
  1062.   EXPECT
  1063.      CASE (LEFT_ANGLE_TOKEN)
  1064.        UNGET
  1065.        Local_Shape = Get_Sphere_Shape();
  1066.        Parse_Vector(&(Local_Shape -> Center));
  1067.        Local_Shape -> Radius = Parse_Float();
  1068.        Local_Shape -> Radius_Squared = Local_Shape -> Radius * Local_Shape -> Radius;
  1069.        Local_Shape -> Inverse_Radius = 1.0 / Local_Shape -> Radius;
  1070.        EXIT
  1071.      END_CASE
  1072.  
  1073.      CASE (IDENTIFIER_TOKEN)
  1074.        if ((Constant_Id = Find_Constant()) != -1)
  1075.          if (Constants[(int)Constant_Id].Constant_Type == SPHERE_CONSTANT)
  1076.            Local_Shape = (SPHERE *)Copy((OBJECT *) Constants[(int)Constant_Id].Constant_Data);
  1077.          else
  1078.            Type_Error ();
  1079.        else
  1080.          Undeclared ();
  1081.        EXIT
  1082.      END_CASE
  1083.  
  1084.      OTHERWISE
  1085.         Parse_Error (LEFT_ANGLE_TOKEN);
  1086.      END_CASE
  1087.   END_EXPECT
  1088.  
  1089.   EXPECT
  1090.      CASE (END_SPHERE_TOKEN)
  1091.         EXIT
  1092.      END_CASE
  1093.  
  1094.      CASE (TRANSLATE_TOKEN)
  1095.         Parse_Vector (&Local_Vector);
  1096.         Translate ((OBJECT *) Local_Shape, &Local_Vector);
  1097.      END_CASE
  1098.  
  1099.      CASE (ROTATE_TOKEN)
  1100.         Parse_Vector (&Local_Vector);
  1101.         Rotate ((OBJECT *) Local_Shape, &Local_Vector);
  1102.      END_CASE
  1103.  
  1104.      CASE (SCALE_TOKEN)
  1105.         Parse_Vector (&Local_Vector);
  1106.         Scale ((OBJECT *) Local_Shape, &Local_Vector);
  1107.      END_CASE
  1108.  
  1109.      CASE (INVERSE_TOKEN)
  1110.         Invert ((OBJECT *) Local_Shape);
  1111.      END_CASE
  1112.  
  1113.      OTHERWISE
  1114.         Parse_Error (END_SPHERE_TOKEN);
  1115.      END_CASE
  1116.   END_EXPECT
  1117.  
  1118.   return ((SHAPE *) Local_Shape);
  1119.   }
  1120.  
  1121. SHAPE *Parse_Plane ()
  1122.   {
  1123.   PLANE *Local_Shape;
  1124.   CONSTANT Constant_Id;
  1125.   VECTOR Local_Vector;
  1126.  
  1127.   Local_Shape = NULL;
  1128.  
  1129.   EXPECT
  1130.      CASE (LEFT_ANGLE_TOKEN)
  1131.        UNGET
  1132.        Local_Shape = Get_Plane_Shape();
  1133.        Parse_Vector(&(Local_Shape -> Normal_Vector));
  1134.        Local_Shape->Distance = Parse_Float();
  1135.        Local_Shape->Distance *= -1.0;
  1136.        EXIT
  1137.      END_CASE
  1138.  
  1139.      CASE (IDENTIFIER_TOKEN)
  1140.        if ((Constant_Id = Find_Constant()) != -1)
  1141.          if (Constants[(int)Constant_Id].Constant_Type == PLANE_CONSTANT)
  1142.            Local_Shape = (PLANE *)Copy((OBJECT *) Constants[(int)Constant_Id].Constant_Data);
  1143.          else
  1144.            Type_Error ();
  1145.        else
  1146.          Undeclared ();
  1147.        EXIT
  1148.      END_CASE
  1149.  
  1150.      OTHERWISE
  1151.         Parse_Error (LEFT_ANGLE_TOKEN);
  1152.      END_CASE
  1153.   END_EXPECT
  1154.  
  1155.   EXPECT
  1156.      CASE (END_PLANE_TOKEN)
  1157.         EXIT
  1158.      END_CASE
  1159.  
  1160.      CASE (TRANSLATE_TOKEN)
  1161.         Parse_Vector (&Local_Vector);
  1162.         Translate ((OBJECT *) Local_Shape, &Local_Vector);
  1163.      END_CASE
  1164.  
  1165.      CASE (ROTATE_TOKEN)
  1166.         Parse_Vector (&Local_Vector);
  1167.         Rotate ((OBJECT *) Local_Shape, &Local_Vector);
  1168.      END_CASE
  1169.  
  1170.      CASE (SCALE_TOKEN)
  1171.         Parse_Vector (&Local_Vector);
  1172.         Scale ((OBJECT *) Local_Shape, &Local_Vector);
  1173.      END_CASE
  1174.  
  1175.      CASE (INVERSE_TOKEN)
  1176.         Invert ((OBJECT *) Local_Shape);
  1177.      END_CASE
  1178.  
  1179.      OTHERWISE
  1180.         Parse_Error (END_PLANE_TOKEN);
  1181.      END_CASE
  1182.   END_EXPECT
  1183.  
  1184.   return ((SHAPE *) Local_Shape);
  1185.   }
  1186.  
  1187. SHAPE *Parse_Triangle ()
  1188.   {
  1189.   TRIANGLE *Local_Shape;
  1190.   CONSTANT Constant_Id;
  1191.   VECTOR Local_Vector;
  1192.  
  1193.   Local_Shape = NULL;
  1194.  
  1195.   EXPECT
  1196.      CASE (LEFT_ANGLE_TOKEN)
  1197.        UNGET
  1198.        Local_Shape = Get_Triangle_Shape();
  1199.        Parse_Vector (&Local_Shape->P1);
  1200.        Parse_Vector (&Local_Shape->P2);
  1201.        Parse_Vector (&Local_Shape->P3);
  1202.        if (!Compute_Triangle (Local_Shape)) {
  1203.           printf ("Degenerate triangle on line %d.  Please remove.\n",
  1204.                   Token.Token_Line_No);
  1205.           Degenerate_Triangles = TRUE;
  1206.           }
  1207.        EXIT
  1208.      END_CASE
  1209.  
  1210.      CASE (IDENTIFIER_TOKEN)
  1211.        if ((Constant_Id = Find_Constant()) != -1)
  1212.          if (Constants[(int)Constant_Id].Constant_Type == TRIANGLE_CONSTANT)
  1213.            Local_Shape = (TRIANGLE *)Copy((OBJECT *) Constants[(int)Constant_Id].Constant_Data);
  1214.          else
  1215.            Type_Error ();
  1216.        else
  1217.          Undeclared ();
  1218.        EXIT
  1219.      END_CASE
  1220.  
  1221.      OTHERWISE
  1222.         Parse_Error (LEFT_ANGLE_TOKEN);
  1223.      END_CASE
  1224.   END_EXPECT
  1225.  
  1226.   EXPECT
  1227.      CASE (END_TRIANGLE_TOKEN)
  1228.         EXIT
  1229.      END_CASE
  1230.  
  1231.      CASE (TRANSLATE_TOKEN)
  1232.         Parse_Vector (&Local_Vector);
  1233.         Translate ((OBJECT *) Local_Shape, &Local_Vector);
  1234.      END_CASE
  1235.  
  1236.      CASE (ROTATE_TOKEN)
  1237.         Parse_Vector (&Local_Vector);
  1238.         Rotate ((OBJECT *) Local_Shape, &Local_Vector);
  1239.      END_CASE
  1240.  
  1241.      CASE (SCALE_TOKEN)
  1242.         Parse_Vector (&Local_Vector);
  1243.         Scale ((OBJECT *) Local_Shape, &Local_Vector);
  1244.      END_CASE
  1245.  
  1246.      CASE (INVERSE_TOKEN)
  1247.         Invert ((OBJECT *) Local_Shape);
  1248.      END_CASE
  1249.  
  1250.      OTHERWISE
  1251.         Parse_Error (END_TRIANGLE_TOKEN);
  1252.      END_CASE
  1253.   END_EXPECT
  1254.  
  1255.   return ((SHAPE *) Local_Shape);
  1256.   }
  1257.  
  1258. SHAPE *Parse_Smooth_Triangle ()
  1259.   {
  1260.   SMOOTH_TRIANGLE *Local_Shape;
  1261.   CONSTANT Constant_Id;
  1262.   VECTOR Local_Vector;
  1263.  
  1264.   Local_Shape = NULL;
  1265.  
  1266.   EXPECT
  1267.      CASE (LEFT_ANGLE_TOKEN)
  1268.        UNGET
  1269.        Local_Shape = (SMOOTH_TRIANGLE *) Get_Smooth_Triangle_Shape();
  1270.        Parse_Vector (&Local_Shape->P1);
  1271.        Parse_Vector (&Local_Shape->N1);
  1272.        Parse_Vector (&Local_Shape->P2);
  1273.        Parse_Vector (&Local_Vector);
  1274.        VSub (Local_Shape->DN12, Local_Vector, Local_Shape->N1);
  1275.        Parse_Vector (&Local_Shape->P3);
  1276.        Parse_Vector (&Local_Vector);
  1277.        VSub (Local_Shape->DN13, Local_Vector, Local_Shape->N1);
  1278.        if (!Compute_Triangle ((TRIANGLE *) Local_Shape)) {
  1279.           printf ("Degenerate triangle on line %d.  Please remove.\n",
  1280.                   Token.Token_Line_No);
  1281.           Degenerate_Triangles = TRUE;
  1282.           }
  1283.        EXIT
  1284.      END_CASE
  1285.  
  1286.      CASE (IDENTIFIER_TOKEN)
  1287.        if ((Constant_Id = Find_Constant()) != -1)
  1288.          if (Constants[(int)Constant_Id].Constant_Type == SMOOTH_TRIANGLE_CONSTANT)
  1289.            Local_Shape = (SMOOTH_TRIANGLE *)Copy((OBJECT *) Constants[(int)Constant_Id].Constant_Data);
  1290.          else
  1291.            Type_Error ();
  1292.        else
  1293.          Undeclared ();
  1294.        EXIT
  1295.      END_CASE
  1296.  
  1297.      CASE (TRANSLATE_TOKEN)
  1298.         Parse_Vector (&Local_Vector);
  1299.         Translate ((OBJECT *) Local_Shape, &Local_Vector);
  1300.      END_CASE
  1301.  
  1302.      CASE (ROTATE_TOKEN)
  1303.         Parse_Vector (&Local_Vector);
  1304.         Rotate ((OBJECT *) Local_Shape, &Local_Vector);
  1305.      END_CASE
  1306.  
  1307.      CASE (SCALE_TOKEN)
  1308.         Parse_Vector (&Local_Vector);
  1309.         Scale ((OBJECT *) Local_Shape, &Local_Vector);
  1310.      END_CASE
  1311.  
  1312.      CASE (INVERSE_TOKEN)
  1313.         Invert ((OBJECT *) Local_Shape);
  1314.      END_CASE
  1315.  
  1316.      OTHERWISE
  1317.         Parse_Error (LEFT_ANGLE_TOKEN);
  1318.      END_CASE
  1319.   END_EXPECT
  1320.  
  1321.   EXPECT
  1322.      CASE (END_TRIANGLE_TOKEN)
  1323.         EXIT
  1324.      END_CASE
  1325.  
  1326.      OTHERWISE
  1327.         Parse_Error (END_TRIANGLE_TOKEN);
  1328.      END_CASE
  1329.   END_EXPECT
  1330.  
  1331.   return ((SHAPE *) Local_Shape);
  1332.   }
  1333.  
  1334. SHAPE *Parse_Quadric ()
  1335.   {
  1336.   QUADRIC *Local_Shape;
  1337.   VECTOR Local_Vector;
  1338.   CONSTANT Constant_Id;
  1339.  
  1340.   Local_Shape = NULL;
  1341.  
  1342.   EXPECT
  1343.      CASE (LEFT_ANGLE_TOKEN)
  1344.        UNGET
  1345.        Local_Shape = Get_Quadric_Shape();
  1346.        Parse_Vector(&(Local_Shape -> Object_2_Terms));
  1347.        Parse_Vector(&(Local_Shape -> Object_Mixed_Terms));
  1348.        Parse_Vector(&(Local_Shape -> Object_Terms));
  1349.        (Local_Shape -> Object_Constant) = Parse_Float();
  1350.        Local_Shape -> Non_Zero_Square_Term = 
  1351.          !((Local_Shape -> Object_2_Terms.x == 0.0)
  1352.           && (Local_Shape -> Object_2_Terms.y == 0.0)
  1353.           && (Local_Shape -> Object_2_Terms.z == 0.0)
  1354.           && (Local_Shape -> Object_Mixed_Terms.x == 0.0)
  1355.           && (Local_Shape -> Object_Mixed_Terms.y == 0.0)
  1356.           && (Local_Shape -> Object_Mixed_Terms.z == 0.0));
  1357.        EXIT
  1358.      END_CASE
  1359.  
  1360.      CASE (IDENTIFIER_TOKEN)
  1361.        if ((Constant_Id = Find_Constant()) != -1)
  1362.          if (Constants[(int)Constant_Id].Constant_Type == QUADRIC_CONSTANT)
  1363.            Local_Shape = (QUADRIC *)Copy((OBJECT *) Constants[(int)Constant_Id].Constant_Data);
  1364.          else
  1365.            Type_Error ();
  1366.        else
  1367.          Undeclared ();
  1368.        EXIT
  1369.      END_CASE
  1370.  
  1371.      OTHERWISE
  1372.         Parse_Error (LEFT_ANGLE_TOKEN);
  1373.      END_CASE
  1374.   END_EXPECT
  1375.  
  1376.   EXPECT
  1377.      CASE (END_QUADRIC_TOKEN)
  1378.         EXIT
  1379.      END_CASE
  1380.  
  1381.      CASE (TRANSLATE_TOKEN)
  1382.         Parse_Vector (&Local_Vector);
  1383.         Translate ((OBJECT *) Local_Shape, &Local_Vector);
  1384.      END_CASE
  1385.  
  1386.      CASE (ROTATE_TOKEN)
  1387.         Parse_Vector (&Local_Vector);
  1388.         Rotate ((OBJECT *) Local_Shape, &Local_Vector);
  1389.      END_CASE
  1390.  
  1391.      CASE (SCALE_TOKEN)
  1392.         Parse_Vector (&Local_Vector);
  1393.         Scale ((OBJECT *) Local_Shape, &Local_Vector);
  1394.      END_CASE
  1395.  
  1396.      CASE (INVERSE_TOKEN)
  1397.         Invert ((OBJECT *) Local_Shape);
  1398.      END_CASE
  1399.  
  1400.      OTHERWISE
  1401.         Parse_Error (END_QUADRIC_TOKEN);
  1402.      END_CASE
  1403.   END_EXPECT
  1404.  
  1405.   return ((SHAPE *) Local_Shape);
  1406.   }
  1407.  
  1408. CSG_SHAPE *Parse_CSG (type, Parent_Object)
  1409.   int type;
  1410.   OBJECT *Parent_Object;
  1411.   {
  1412.   CSG_SHAPE *Container = NULL;
  1413.   SHAPE *Local_Shape;
  1414.   VECTOR Local_Vector;
  1415.   CONSTANT Constant_Id;
  1416.   int First_Shape_Parsed = FALSE;
  1417.  
  1418.   if (type == CSG_UNION_TYPE)
  1419.     Container = Get_CSG_Union ();
  1420.  
  1421.   else if ((type == CSG_INTERSECTION_TYPE) || (type == CSG_DIFFERENCE_TYPE))
  1422.     Container = Get_CSG_Intersection ();
  1423.  
  1424.   Container -> Parent_Object = Parent_Object;
  1425.  
  1426.   EXPECT
  1427.      CASE (IDENTIFIER_TOKEN)
  1428.        if ((Constant_Id = Find_Constant()) != -1)
  1429.          if ((Constants[(int)Constant_Id].Constant_Type == CSG_INTERSECTION_CONSTANT)
  1430.              || (Constants[(int)Constant_Id].Constant_Type == CSG_UNION_CONSTANT)
  1431.              || (Constants[(int)Constant_Id].Constant_Type == CSG_DIFFERENCE_CONSTANT)) {
  1432.            free (Container);
  1433.            Container = (CSG_SHAPE *) Copy ((OBJECT *) Constants[(int)Constant_Id].Constant_Data);
  1434.            Set_CSG_Parents(Container, Parent_Object);
  1435.            }
  1436.          else
  1437.            Type_Error ();
  1438.        else
  1439.          Undeclared ();
  1440.      END_CASE
  1441.  
  1442.      CASE (SPHERE_TOKEN)
  1443.        Local_Shape = Parse_Sphere ();
  1444.        Local_Shape -> Parent_Object = Parent_Object;
  1445.        if ((type == CSG_DIFFERENCE_TYPE) && First_Shape_Parsed)
  1446.           Invert ((OBJECT *) Local_Shape);
  1447.        First_Shape_Parsed = TRUE;
  1448.        Link((OBJECT *) Local_Shape, (OBJECT **) &(Local_Shape -> Next_Object),
  1449.                (OBJECT **) &(Container -> Shapes));
  1450.      END_CASE
  1451.  
  1452.      CASE (PLANE_TOKEN)
  1453.        Local_Shape = Parse_Plane ();
  1454.        Local_Shape -> Parent_Object = Parent_Object;
  1455.        if ((type == CSG_DIFFERENCE_TYPE) && First_Shape_Parsed)
  1456.           Invert ((OBJECT *) Local_Shape);
  1457.        First_Shape_Parsed = TRUE;
  1458.        Link((OBJECT *) Local_Shape, (OBJECT **) &(Local_Shape -> Next_Object),
  1459.                (OBJECT **) &(Container -> Shapes));
  1460.      END_CASE
  1461.  
  1462.      CASE (TRIANGLE_TOKEN)
  1463.        Local_Shape = Parse_Triangle ();
  1464.        Local_Shape -> Parent_Object = Parent_Object;
  1465.        if ((type == CSG_DIFFERENCE_TYPE) && First_Shape_Parsed)
  1466.           Invert ((OBJECT *) Local_Shape);
  1467.        First_Shape_Parsed = TRUE;
  1468.        Link((OBJECT *) Local_Shape, (OBJECT **) &(Local_Shape -> Next_Object),
  1469.                (OBJECT **) &(Container -> Shapes));
  1470.      END_CASE
  1471.  
  1472.      CASE (SMOOTH_TRIANGLE_TOKEN)
  1473.        Local_Shape = Parse_Smooth_Triangle ();
  1474.        Local_Shape -> Parent_Object = Parent_Object;
  1475.        if ((type == CSG_DIFFERENCE_TYPE) && First_Shape_Parsed)
  1476.           Invert ((OBJECT *) Local_Shape);
  1477.        First_Shape_Parsed = TRUE;
  1478.        Link((OBJECT *) Local_Shape, (OBJECT **) &(Local_Shape -> Next_Object),
  1479.                (OBJECT **) &(Container -> Shapes));
  1480.      END_CASE
  1481.  
  1482.      CASE (QUADRIC_TOKEN)
  1483.        Local_Shape = Parse_Quadric ();
  1484.        Local_Shape -> Parent_Object = Parent_Object;
  1485.        if ((type == CSG_DIFFERENCE_TYPE) && First_Shape_Parsed)
  1486.           Invert ((OBJECT *) Local_Shape);
  1487.        First_Shape_Parsed = TRUE;
  1488.        Link((OBJECT *) Local_Shape, (OBJECT **) &(Local_Shape -> Next_Object),
  1489.                (OBJECT **) &(Container -> Shapes));
  1490.      END_CASE
  1491.  
  1492.      CASE (UNION_TOKEN)
  1493.        Local_Shape = (SHAPE *) Parse_CSG (CSG_UNION_TYPE, Parent_Object);
  1494.        if ((type == CSG_DIFFERENCE_TYPE) && First_Shape_Parsed)
  1495.           Invert ((OBJECT *) Local_Shape);
  1496.        First_Shape_Parsed = TRUE;
  1497.        Link((OBJECT *) Local_Shape, (OBJECT **) &(Local_Shape -> Next_Object),
  1498.                (OBJECT **) &(Container -> Shapes));
  1499.      END_CASE
  1500.  
  1501.      CASE (INTERSECTION_TOKEN)
  1502.        Local_Shape = (SHAPE *) Parse_CSG (CSG_INTERSECTION_TYPE, Parent_Object);
  1503.        if ((type == CSG_DIFFERENCE_TYPE) && First_Shape_Parsed)
  1504.           Invert ((OBJECT *) Local_Shape);
  1505.        First_Shape_Parsed = TRUE;
  1506.        Link((OBJECT *) Local_Shape, (OBJECT **) &(Local_Shape -> Next_Object),
  1507.                (OBJECT **) &(Container -> Shapes));
  1508.      END_CASE
  1509.  
  1510.      CASE (DIFFERENCE_TOKEN)
  1511.        Local_Shape = (SHAPE *) Parse_CSG (CSG_DIFFERENCE_TYPE, Parent_Object);
  1512.        if ((type == CSG_DIFFERENCE_TYPE) && First_Shape_Parsed)
  1513.           Invert ((OBJECT *) Local_Shape);
  1514.        First_Shape_Parsed = TRUE;
  1515.        Link((OBJECT *) Local_Shape, (OBJECT **) &(Local_Shape -> Next_Object),
  1516.                (OBJECT **) &(Container -> Shapes));
  1517.      END_CASE
  1518.  
  1519.      OTHERWISE
  1520.         UNGET
  1521.         EXIT
  1522.      END_CASE
  1523.   END_EXPECT
  1524.  
  1525.   EXPECT
  1526.      CASE3 (END_UNION_TOKEN, END_INTERSECTION_TOKEN, END_DIFFERENCE_TOKEN)
  1527.         EXIT
  1528.      END_CASE
  1529.  
  1530.      CASE (TRANSLATE_TOKEN)
  1531.         Parse_Vector (&Local_Vector);
  1532.         Translate((OBJECT *) Container, &Local_Vector);
  1533.      END_CASE
  1534.  
  1535.      CASE (ROTATE_TOKEN)
  1536.         Parse_Vector (&Local_Vector);
  1537.         Rotate ((OBJECT *) Container, &Local_Vector);
  1538.      END_CASE
  1539.  
  1540.      CASE (SCALE_TOKEN)
  1541.         Parse_Vector (&Local_Vector);
  1542.         Scale ((OBJECT *) Container, &Local_Vector);
  1543.      END_CASE
  1544.  
  1545.      CASE (INVERSE_TOKEN)
  1546.         Invert ((OBJECT *) Container);
  1547.      END_CASE
  1548.  
  1549.      OTHERWISE
  1550.         Parse_Error (END_QUADRIC_TOKEN);
  1551.      END_CASE
  1552.   END_EXPECT
  1553.  
  1554.   return ((CSG_SHAPE *) Container);
  1555.   }
  1556.  
  1557. SHAPE *Parse_Shape (Object)
  1558.   OBJECT *Object;
  1559.   {
  1560.   SHAPE *Local_Shape = NULL;
  1561.  
  1562.   EXPECT
  1563.     CASE (SPHERE_TOKEN)
  1564.       Local_Shape = Parse_Sphere ();
  1565.       Local_Shape -> Parent_Object = Object;
  1566.       EXIT
  1567.     END_CASE
  1568.  
  1569.     CASE (PLANE_TOKEN)
  1570.       Local_Shape = Parse_Plane ();
  1571.       Local_Shape -> Parent_Object = Object;
  1572.       EXIT
  1573.     END_CASE
  1574.  
  1575.     CASE (TRIANGLE_TOKEN)
  1576.       Local_Shape = Parse_Triangle ();
  1577.       Local_Shape -> Parent_Object = Object;
  1578.       EXIT
  1579.     END_CASE
  1580.  
  1581.     CASE (SMOOTH_TRIANGLE_TOKEN)
  1582.       Local_Shape = Parse_Smooth_Triangle ();
  1583.       Local_Shape -> Parent_Object = Object;
  1584.       EXIT
  1585.     END_CASE
  1586.  
  1587.     CASE (QUADRIC_TOKEN)
  1588.       Local_Shape = Parse_Quadric ();
  1589.       Local_Shape -> Parent_Object = Object;
  1590.       EXIT
  1591.     END_CASE
  1592.  
  1593.     CASE (UNION_TOKEN)
  1594.       Local_Shape = (SHAPE *) Parse_CSG (CSG_UNION_TYPE, Object);
  1595.       EXIT
  1596.     END_CASE
  1597.  
  1598.     CASE (INTERSECTION_TOKEN)
  1599.       Local_Shape = (SHAPE *) Parse_CSG (CSG_INTERSECTION_TYPE, Object);
  1600.       EXIT
  1601.     END_CASE
  1602.  
  1603.     CASE (DIFFERENCE_TOKEN)
  1604.       Local_Shape = (SHAPE *) Parse_CSG (CSG_DIFFERENCE_TYPE, Object);
  1605.       EXIT
  1606.     END_CASE
  1607.  
  1608.     OTHERWISE
  1609.        Parse_Error (QUADRIC_TOKEN);
  1610.     END_CASE
  1611.   END_EXPECT
  1612.   return (Local_Shape);
  1613.   }
  1614.  
  1615. OBJECT *Parse_Object ()
  1616.   {
  1617.   OBJECT *Object;
  1618.   SHAPE *Local_Shape;
  1619.   VECTOR Local_Vector;
  1620.   CONSTANT Constant_Id;
  1621.   int i;
  1622.  
  1623.   Object = NULL;
  1624.  
  1625.   EXPECT
  1626.     CASE (IDENTIFIER_TOKEN)
  1627.       if ((Constant_Id = Find_Constant()) != -1)
  1628.         if (Constants[(int)Constant_Id].Constant_Type == OBJECT_CONSTANT)
  1629.           Object = (OBJECT *) Copy((OBJECT *) Constants[(int)Constant_Id].Constant_Data);
  1630.         else
  1631.           Type_Error ();
  1632.       else
  1633.         Undeclared ();
  1634.       EXIT
  1635.     END_CASE
  1636.  
  1637.     CASE5 (SPHERE_TOKEN, QUADRIC_TOKEN, UNION_TOKEN,
  1638.            INTERSECTION_TOKEN, DIFFERENCE_TOKEN)
  1639.     CASE3 (TRIANGLE_TOKEN, SMOOTH_TRIANGLE_TOKEN, PLANE_TOKEN)
  1640.         UNGET
  1641.         if (Object == NULL)
  1642.            Object = Get_Object();
  1643.  
  1644.         Local_Shape = Parse_Shape(Object);
  1645.         Link((OBJECT *)Local_Shape, (OBJECT **) &(Local_Shape -> Next_Object),
  1646.                 (OBJECT **) &(Object -> Shape));
  1647.         EXIT
  1648.     END_CASE
  1649.  
  1650.     OTHERWISE
  1651.         Parse_Error (QUADRIC_TOKEN);
  1652.         EXIT
  1653.     END_CASE
  1654.   END_EXPECT
  1655.  
  1656.   EXPECT
  1657.     CASE (BOUNDED_TOKEN)
  1658.        EXPECT
  1659.           CASE (END_BOUNDED_TOKEN)
  1660.              EXIT
  1661.           END_CASE
  1662.  
  1663.           OTHERWISE
  1664.              UNGET
  1665.              Local_Shape = Parse_Shape(Object);
  1666.              Link((OBJECT *) Local_Shape,
  1667.                   (OBJECT **) &(Local_Shape -> Next_Object),
  1668.                   (OBJECT **) &(Object -> Bounding_Shapes));
  1669.           END_CASE
  1670.        END_EXPECT       
  1671.     END_CASE
  1672.  
  1673.     CASE2 (COLOR_TOKEN, COLOUR_TOKEN)
  1674.        Parse_Colour (&(Object -> Object_Colour));
  1675.        if (Object->Object_Colour.Alpha != 0.0)
  1676.           Object->Transparency = TRUE;
  1677.     END_CASE
  1678.  
  1679.     CASE (TEXTURE_TOKEN)
  1680.       Object -> Object_Texture = Parse_Texture (Object->Object_Texture);
  1681.       if ((Object->Object_Texture->Colour1.Alpha != 0.0) ||
  1682.           (Object->Object_Texture->Colour2.Alpha != 0.0))
  1683.          Object->Transparency = TRUE;
  1684.       else
  1685.          if (Object->Object_Texture->Colour_Map != NULL)
  1686.             for (i = 0 ; i < Object->Object_Texture->Colour_Map->Number_Of_Entries ; i++)
  1687.                if ((Object->Object_Texture->Colour_Map->Colour_Map_Entries[i].Start_Colour.Alpha != 0.0) ||
  1688.                    (Object->Object_Texture->Colour_Map->Colour_Map_Entries[i].Start_Colour.Alpha != 0.0)) {
  1689.                   Object->Transparency = TRUE;
  1690.                   break;
  1691.                   }
  1692.     END_CASE
  1693.  
  1694.     CASE (LIGHT_SOURCE_TOKEN)
  1695.       Object -> Light_Source_Flag = TRUE;
  1696.     END_CASE
  1697.  
  1698.     CASE (TRANSLATE_TOKEN)
  1699.        Parse_Vector (&Local_Vector);
  1700.        Translate (Object, &Local_Vector);
  1701.     END_CASE
  1702.  
  1703.     CASE (ROTATE_TOKEN)
  1704.        Parse_Vector (&Local_Vector);
  1705.        Rotate (Object, &Local_Vector);
  1706.     END_CASE
  1707.  
  1708.     CASE (SCALE_TOKEN)
  1709.        Parse_Vector (&Local_Vector);
  1710.        Scale (Object, &Local_Vector);
  1711.     END_CASE
  1712.  
  1713.     CASE (INVERSE_TOKEN)
  1714.        Invert (Object);
  1715.     END_CASE
  1716.  
  1717.     CASE (AMBIENT_TOKEN)
  1718.       if (Object -> Object_Texture == Default_Texture)
  1719.          Object -> Object_Texture = Get_Texture();
  1720.  
  1721.       (Object -> Object_Texture -> Object_Ambient) = Parse_Float ();
  1722.     END_CASE
  1723.  
  1724.     CASE (BRILLIANCE_TOKEN)
  1725.       if (Object -> Object_Texture == Default_Texture)
  1726.          Object -> Object_Texture = Get_Texture();
  1727.  
  1728.       (Object -> Object_Texture -> Object_Brilliance) = Parse_Float ();
  1729.     END_CASE
  1730.  
  1731.     CASE (ROUGHNESS_TOKEN)
  1732.       if (Object -> Object_Texture == Default_Texture)
  1733.          Object -> Object_Texture = Get_Texture();
  1734.  
  1735.       (Object -> Object_Texture -> Object_Roughness) = Parse_Float ();
  1736.       if (Object -> Object_Texture -> Object_Roughness > 1.0)
  1737.          Object -> Object_Texture -> Object_Roughness = 1.0;
  1738.       if (Object -> Object_Texture -> Object_Roughness < 0.001)
  1739.          Object -> Object_Texture -> Object_Roughness = 0.001;
  1740.     END_CASE
  1741.  
  1742.     CASE (PHONGSIZE_TOKEN)
  1743.       if (Object -> Object_Texture == Default_Texture)
  1744.          Object -> Object_Texture = Get_Texture();
  1745.  
  1746.       (Object -> Object_Texture -> Object_PhongSize) = Parse_Float ();
  1747.       if (Object -> Object_Texture -> Object_PhongSize < 1.0)
  1748.          Object -> Object_Texture -> Object_PhongSize = 1.0;
  1749.       if (Object -> Object_Texture -> Object_PhongSize > 100)
  1750.          Object -> Object_Texture -> Object_PhongSize = 100;
  1751.     END_CASE
  1752.  
  1753.     CASE (DIFFUSE_TOKEN)
  1754.       if (Object -> Object_Texture == Default_Texture)
  1755.          Object -> Object_Texture = Get_Texture();
  1756.  
  1757.       (Object -> Object_Texture -> Object_Diffuse) = Parse_Float ();
  1758.     END_CASE
  1759.  
  1760.     CASE (SPECULAR_TOKEN)
  1761.       if (Object -> Object_Texture == Default_Texture)
  1762.          Object -> Object_Texture = Get_Texture();
  1763.  
  1764.       (Object -> Object_Texture -> Object_Specular) = Parse_Float ();
  1765.     END_CASE
  1766.  
  1767.     CASE (PHONG_TOKEN)
  1768.       if (Object -> Object_Texture == Default_Texture)
  1769.          Object -> Object_Texture = Get_Texture();
  1770.  
  1771.       (Object -> Object_Texture -> Object_Phong) = Parse_Float ();
  1772.     END_CASE
  1773.  
  1774.     CASE (IOR_TOKEN)
  1775.       if (Object -> Object_Texture == Default_Texture)
  1776.          Object -> Object_Texture = Get_Texture();
  1777.  
  1778.       (Object -> Object_Texture -> Object_Index_Of_Refraction) = Parse_Float ();
  1779.     END_CASE
  1780.  
  1781.     CASE (REFRACTION_TOKEN)
  1782.       if (Object -> Object_Texture == Default_Texture)
  1783.          Object -> Object_Texture = Get_Texture();
  1784.  
  1785.       (Object -> Object_Texture -> Object_Refraction) = Parse_Float ();
  1786.     END_CASE
  1787.  
  1788.     CASE (REFLECTION_TOKEN)
  1789.       if (Object -> Object_Texture == Default_Texture)
  1790.          Object -> Object_Texture = Get_Texture();
  1791.  
  1792.       (Object -> Object_Texture -> Object_Reflection) = Parse_Float ();
  1793.     END_CASE
  1794.  
  1795.     CASE (END_OBJECT_TOKEN)
  1796.       EXIT
  1797.     END_CASE
  1798.  
  1799.     OTHERWISE
  1800.       Parse_Error (END_OBJECT_TOKEN);
  1801.     END_CASE
  1802.  
  1803.   END_EXPECT
  1804.  
  1805.   return (Object);
  1806.   }
  1807.  
  1808. OBJECT *Parse_Composite ()
  1809.   {
  1810.   COMPOSITE *Local_Composite;
  1811.   OBJECT *Local_Object;
  1812.   SHAPE *Local_Shape;
  1813.   CONSTANT Constant_Id;
  1814.   VECTOR Local_Vector;
  1815.  
  1816.   Local_Composite = NULL;
  1817.  
  1818.   EXPECT
  1819.     CASE (IDENTIFIER_TOKEN)
  1820.       if ((Constant_Id = Find_Constant()) != -1)
  1821.         if (Constants[(int)Constant_Id].Constant_Type == COMPOSITE_CONSTANT)
  1822.           Local_Composite = (COMPOSITE *)Copy((OBJECT *) Constants[(int)Constant_Id].Constant_Data);
  1823.         else          
  1824.           Type_Error ();
  1825.       else
  1826.         Undeclared ();
  1827.     END_CASE
  1828.  
  1829.     CASE (COMPOSITE_TOKEN)
  1830.       if (Local_Composite == NULL)       
  1831.            Local_Composite = Get_Composite_Object();
  1832.  
  1833.       Local_Object = Parse_Composite();
  1834.       Link((OBJECT *) Local_Object,(OBJECT **) &(Local_Object -> Next_Object),
  1835.               (OBJECT **) &(Local_Composite -> Objects));
  1836.     END_CASE
  1837.  
  1838.     CASE (OBJECT_TOKEN)
  1839.       if (Local_Composite == NULL)       
  1840.            Local_Composite = Get_Composite_Object();
  1841.  
  1842.       Local_Object = Parse_Object();
  1843.       Link(Local_Object, &(Local_Object -> Next_Object),
  1844.                &(Local_Composite -> Objects));
  1845.  
  1846.       if (Local_Object -> Light_Source_Flag)
  1847.          Link(Local_Object, &(Local_Object -> Next_Light_Source),
  1848.                &(Parsing_Frame_Ptr -> Light_Sources));
  1849.     END_CASE
  1850.  
  1851.     CASE (END_COMPOSITE_TOKEN)
  1852.       UNGET
  1853.       if (Local_Composite == NULL)       
  1854.         Local_Composite = Get_Composite_Object();
  1855.  
  1856.       EXIT
  1857.     END_CASE
  1858.  
  1859.     OTHERWISE
  1860.        UNGET
  1861.        EXIT
  1862.     END_CASE
  1863.   END_EXPECT
  1864.  
  1865.   EXPECT
  1866.     CASE (END_COMPOSITE_TOKEN)
  1867.        EXIT
  1868.     END_CASE
  1869.  
  1870.     CASE (BOUNDED_TOKEN)
  1871.        EXPECT
  1872.           CASE (END_BOUNDED_TOKEN)
  1873.              EXIT
  1874.           END_CASE
  1875.  
  1876.           OTHERWISE
  1877.              UNGET
  1878.              Local_Shape = Parse_Shape((OBJECT *) Local_Composite);
  1879.              Link((OBJECT *) Local_Shape,
  1880.                   (OBJECT **) &(Local_Shape -> Next_Object),
  1881.                   (OBJECT **) &(Local_Composite -> Bounding_Shapes));
  1882.           END_CASE
  1883.        END_EXPECT       
  1884.     END_CASE
  1885.  
  1886.     CASE (TRANSLATE_TOKEN)
  1887.        Parse_Vector (&Local_Vector);
  1888.        Translate ((OBJECT *) Local_Composite, &Local_Vector);
  1889.     END_CASE
  1890.  
  1891.     CASE (ROTATE_TOKEN)
  1892.        Parse_Vector (&Local_Vector);
  1893.        Rotate ((OBJECT *) Local_Composite, &Local_Vector);
  1894.     END_CASE
  1895.  
  1896.     CASE (SCALE_TOKEN)
  1897.        Parse_Vector (&Local_Vector);
  1898.        Scale ((OBJECT *) Local_Composite, &Local_Vector);
  1899.     END_CASE
  1900.  
  1901.      CASE (INVERSE_TOKEN)
  1902.         Invert ((OBJECT *) Local_Composite);
  1903.      END_CASE
  1904.  
  1905.     OTHERWISE
  1906.        Parse_Error (END_COMPOSITE_TOKEN);
  1907.     END_CASE
  1908.   END_EXPECT
  1909.  
  1910.   return ((OBJECT *) Local_Composite);
  1911.   }
  1912.  
  1913. void Parse_Fog ()
  1914.    {
  1915.    EXPECT
  1916.       CASE (COLOUR_TOKEN)
  1917.          Parse_Colour (&Parsing_Frame_Ptr->Fog_Colour);
  1918.       END_CASE
  1919.  
  1920.       CASE (FLOAT_TOKEN)
  1921.          Parsing_Frame_Ptr->Fog_Distance = Token.Token_Float;
  1922.       END_CASE
  1923.  
  1924.       CASE (END_FOG_TOKEN)
  1925.          EXIT
  1926.       END_CASE
  1927.  
  1928.       OTHERWISE
  1929.          Parse_Error (END_FOG_TOKEN);
  1930.       END_CASE
  1931.    END_EXPECT
  1932.    }
  1933.  
  1934. void Parse_Frame ()
  1935.   {
  1936.   OBJECT *Local_Object;
  1937.  
  1938.   EXPECT
  1939.     CASE (FOG_TOKEN)
  1940.        Parse_Fog();
  1941.     END_CASE
  1942.  
  1943.     CASE (OBJECT_TOKEN)
  1944.       Local_Object = Parse_Object();
  1945.       Link(Local_Object, &(Local_Object -> Next_Object),
  1946.              &(Parsing_Frame_Ptr -> Objects));
  1947.  
  1948.       if (Local_Object -> Light_Source_Flag)
  1949.          Link(Local_Object, &(Local_Object -> Next_Light_Source),
  1950.                &(Parsing_Frame_Ptr -> Light_Sources));
  1951.     END_CASE
  1952.  
  1953.     CASE (COMPOSITE_TOKEN)
  1954.       Local_Object = Parse_Composite();
  1955.       Link(Local_Object, &(Local_Object -> Next_Object),
  1956.             &(Parsing_Frame_Ptr -> Objects));
  1957.     END_CASE
  1958.  
  1959.     CASE (VIEW_POINT_TOKEN)
  1960.       Parse_Viewpoint(&(Parsing_Frame_Ptr -> View_Point));
  1961.     END_CASE
  1962.  
  1963.     CASE (DECLARE_TOKEN)
  1964.       Parse_Declare ();
  1965.     END_CASE
  1966.  
  1967.     CASE (END_OF_FILE_TOKEN)
  1968.       EXIT
  1969.     END_CASE
  1970.  
  1971.     OTHERWISE 
  1972.       Parse_Error (OBJECT_TOKEN);
  1973.     END_CASE
  1974.   END_EXPECT
  1975.   }
  1976.  
  1977. void Parse_Viewpoint (Given_Vp)
  1978.   VIEWPOINT *Given_Vp;
  1979.   {
  1980.   CONSTANT Constant_Id;
  1981.   VECTOR Local_Vector, Temp_Vector;
  1982.   DBL Direction_Length, Up_Length, Right_Length, Handedness;
  1983.  
  1984.   Init_Viewpoint (Given_Vp);
  1985.  
  1986.   EXPECT
  1987.     CASE (IDENTIFIER_TOKEN)
  1988.       if ((Constant_Id = Find_Constant()) != -1)
  1989.         if (Constants[(int)Constant_Id].Constant_Type == VIEW_POINT_CONSTANT)
  1990.           *Given_Vp = 
  1991.              *((VIEWPOINT*) Constants[(int)Constant_Id].Constant_Data);
  1992.         else
  1993.           Type_Error ();
  1994.       else
  1995.         Undeclared ();
  1996.     END_CASE
  1997.  
  1998.     CASE (LOCATION_TOKEN)
  1999.       Parse_Vector(&(Given_Vp -> Location));
  2000.     END_CASE
  2001.  
  2002.     CASE (DIRECTION_TOKEN)
  2003.       Parse_Vector(&(Given_Vp -> Direction));
  2004.     END_CASE
  2005.  
  2006.     CASE (UP_TOKEN)
  2007.       Parse_Vector(&(Given_Vp -> Up));
  2008.     END_CASE
  2009.  
  2010.     CASE (RIGHT_TOKEN)
  2011.       Parse_Vector(&(Given_Vp -> Right));
  2012.     END_CASE
  2013.  
  2014.     CASE (SKY_TOKEN)
  2015.       Parse_Vector(&(Given_Vp -> Sky));
  2016.     END_CASE
  2017.  
  2018.     CASE (LOOK_AT_TOKEN)
  2019.        VLength (Direction_Length, Given_Vp->Direction);
  2020.        VLength (Up_Length, Given_Vp->Up);
  2021.        VLength (Right_Length, Given_Vp->Right);
  2022.        VCross (Temp_Vector, Given_Vp->Direction, Given_Vp->Up);
  2023.        VDot (Handedness, Temp_Vector, Given_Vp->Right);
  2024.        Parse_Vector(&Given_Vp->Direction);
  2025.  
  2026.        VSub (Given_Vp->Direction, Given_Vp->Direction, Given_Vp->Location);
  2027.        VNormalize (Given_Vp->Direction, Given_Vp->Direction);
  2028.        VCross(Given_Vp->Right, Given_Vp->Direction, Given_Vp->Sky);
  2029.        VNormalize (Given_Vp->Right, Given_Vp->Right);
  2030.        VCross (Given_Vp->Up, Given_Vp->Right, Given_Vp->Direction);
  2031.        VScale (Given_Vp->Direction, Given_Vp->Direction, Direction_Length);
  2032.        if (Handedness >= 0.0) {
  2033.           VScale (Given_Vp->Right, Given_Vp->Right, Right_Length);
  2034.           }
  2035.        else {
  2036.           VScale (Given_Vp->Right, Given_Vp->Right, -Right_Length);
  2037.           }
  2038.  
  2039.        VScale (Given_Vp->Up, Given_Vp->Up, Up_Length);       
  2040.     END_CASE
  2041.  
  2042.     CASE (TRANSLATE_TOKEN)
  2043.        Parse_Vector (&Local_Vector);
  2044.        Translate ((OBJECT *) Given_Vp, &Local_Vector);
  2045.     END_CASE
  2046.  
  2047.     CASE (ROTATE_TOKEN)
  2048.        Parse_Vector (&Local_Vector);
  2049.        Rotate ((OBJECT *) Given_Vp, &Local_Vector);
  2050.     END_CASE
  2051.  
  2052.     CASE (SCALE_TOKEN)
  2053.        Parse_Vector (&Local_Vector);
  2054.        Scale ((OBJECT *) Given_Vp, &Local_Vector);
  2055.     END_CASE
  2056.  
  2057.     CASE (END_VIEW_POINT_TOKEN)
  2058.       EXIT
  2059.     END_CASE
  2060.  
  2061.     OTHERWISE
  2062.       Parse_Error (END_VIEW_POINT_TOKEN);
  2063.     END_CASE
  2064.   END_EXPECT
  2065.   }
  2066.  
  2067. void Parse_Declare ()
  2068.   {
  2069.   CONSTANT Constant_Id;
  2070.  
  2071.   struct Constant_Struct *Constant_Ptr;
  2072.  
  2073.   GET (IDENTIFIER_TOKEN);
  2074.   if ((Constant_Id = Find_Constant()) == -1)
  2075.     if (++Number_Of_Constants >= MAX_CONSTANTS)
  2076.       Error ("Too many constants");
  2077.     else
  2078.       Constant_Id = Number_Of_Constants;
  2079.  
  2080.   Constant_Ptr = &(Constants[(int)Constant_Id]);
  2081.   GET (EQUALS_TOKEN);
  2082.  
  2083.   EXPECT
  2084.     CASE (OBJECT_TOKEN)
  2085.       Constant_Ptr -> Identifier_Number = Token.Identifier_Number;
  2086.       Constant_Ptr -> Constant_Data = (char *) Parse_Object();
  2087.       Constant_Ptr -> Constant_Type = OBJECT_CONSTANT;
  2088.       EXIT
  2089.     END_CASE
  2090.  
  2091.     CASE (SPHERE_TOKEN)
  2092.       Constant_Ptr -> Identifier_Number = Token.Identifier_Number;
  2093.       Constant_Ptr -> Constant_Data = (char *) Parse_Sphere ();
  2094.       Constant_Ptr -> Constant_Type = SPHERE_CONSTANT;
  2095.       EXIT
  2096.     END_CASE
  2097.  
  2098.     CASE (PLANE_TOKEN)
  2099.       Constant_Ptr -> Identifier_Number = Token.Identifier_Number;
  2100.       Constant_Ptr -> Constant_Data = (char *) Parse_Plane ();
  2101.       Constant_Ptr -> Constant_Type = PLANE_CONSTANT;
  2102.       EXIT
  2103.     END_CASE
  2104.  
  2105.     CASE (TRIANGLE_TOKEN)
  2106.       Constant_Ptr -> Identifier_Number = Token.Identifier_Number;
  2107.       Constant_Ptr -> Constant_Data = (char *) Parse_Triangle ();
  2108.       Constant_Ptr -> Constant_Type = TRIANGLE_CONSTANT;
  2109.       EXIT
  2110.     END_CASE
  2111.  
  2112.     CASE (SMOOTH_TRIANGLE_TOKEN)
  2113.       Constant_Ptr -> Identifier_Number = Token.Identifier_Number;
  2114.       Constant_Ptr -> Constant_Data = (char *) Parse_Smooth_Triangle ();
  2115.       Constant_Ptr -> Constant_Type = SMOOTH_TRIANGLE_CONSTANT;
  2116.       EXIT
  2117.     END_CASE
  2118.  
  2119.     CASE (QUADRIC_TOKEN)
  2120.       Constant_Ptr -> Identifier_Number = Token.Identifier_Number;
  2121.       Constant_Ptr -> Constant_Data = (char *) Parse_Quadric ();
  2122.       Constant_Ptr -> Constant_Type = QUADRIC_CONSTANT;
  2123.       EXIT
  2124.     END_CASE
  2125.  
  2126.     CASE (INTERSECTION_TOKEN)
  2127.       Constant_Ptr -> Identifier_Number = Token.Identifier_Number;
  2128.       Constant_Ptr -> Constant_Data = (char *) Parse_CSG(CSG_INTERSECTION_TYPE, NULL);
  2129.       Constant_Ptr -> Constant_Type = CSG_INTERSECTION_CONSTANT;
  2130.       EXIT
  2131.     END_CASE
  2132.  
  2133.     CASE (UNION_TOKEN)
  2134.       Constant_Ptr -> Identifier_Number = Token.Identifier_Number;
  2135.       Constant_Ptr -> Constant_Data = (char *) Parse_CSG(CSG_UNION_TYPE, NULL);
  2136.       Constant_Ptr -> Constant_Type = CSG_UNION_CONSTANT;
  2137.       EXIT
  2138.     END_CASE
  2139.  
  2140.     CASE (DIFFERENCE_TOKEN)
  2141.       Constant_Ptr -> Identifier_Number = Token.Identifier_Number;
  2142.       Constant_Ptr -> Constant_Data = (char *) Parse_CSG(CSG_DIFFERENCE_TYPE, NULL);
  2143.       Constant_Ptr -> Constant_Type = CSG_DIFFERENCE_CONSTANT;
  2144.       EXIT
  2145.     END_CASE
  2146.  
  2147.     CASE (COMPOSITE_TOKEN)
  2148.       Constant_Ptr -> Identifier_Number = Token.Identifier_Number;
  2149.       Constant_Ptr -> Constant_Data = (char *) Parse_Composite();
  2150.       Constant_Ptr -> Constant_Type = COMPOSITE_CONSTANT;
  2151.       EXIT
  2152.     END_CASE
  2153.  
  2154.     CASE (TEXTURE_TOKEN)
  2155.       Constant_Ptr -> Identifier_Number = Token.Identifier_Number;
  2156.       Constant_Ptr -> Constant_Data = (char *) Parse_Texture(Default_Texture);
  2157.       Constant_Ptr -> Constant_Type = TEXTURE_CONSTANT;
  2158.       EXIT
  2159.     END_CASE
  2160.  
  2161.     CASE (VIEW_POINT_TOKEN)
  2162.       Constant_Ptr -> Identifier_Number = Token.Identifier_Number;
  2163.       Constant_Ptr -> Constant_Data = (char *) Get_Viewpoint();
  2164.       Constant_Ptr -> Constant_Type = VIEW_POINT_CONSTANT;
  2165.       Parse_Viewpoint((VIEWPOINT *) Constant_Ptr -> Constant_Data);
  2166.       EXIT
  2167.     END_CASE
  2168.  
  2169.     CASE2 (COLOR_TOKEN, COLOUR_TOKEN)
  2170.       Constant_Ptr -> Identifier_Number = Token.Identifier_Number;
  2171.       Constant_Ptr -> Constant_Data = (char *) Get_Colour();
  2172.       Constant_Ptr -> Constant_Type = COLOUR_CONSTANT;
  2173.       Parse_Colour ((COLOUR *) Constant_Ptr -> Constant_Data);
  2174.       EXIT
  2175.     END_CASE
  2176.  
  2177.     CASE (LEFT_ANGLE_TOKEN)
  2178.       UNGET
  2179.       Constant_Ptr -> Identifier_Number = Token.Identifier_Number;
  2180.       Constant_Ptr -> Constant_Data = (char *) Get_Vector();
  2181.       Constant_Ptr -> Constant_Type = VECTOR_CONSTANT;
  2182.       Parse_Vector((VECTOR *) Constant_Ptr -> Constant_Data);
  2183.       EXIT
  2184.     END_CASE
  2185.  
  2186.     CASE3 (DASH_TOKEN, PLUS_TOKEN, FLOAT_TOKEN)
  2187.       UNGET
  2188.       Constant_Ptr -> Identifier_Number = Token.Identifier_Number;
  2189.       Constant_Ptr -> Constant_Data = (char *) Get_Float();
  2190.       Constant_Ptr -> Constant_Type = FLOAT_CONSTANT;
  2191.       *(Constant_Ptr -> Constant_Data) = Parse_Float();
  2192.       EXIT
  2193.     END_CASE
  2194.  
  2195.     OTHERWISE
  2196.       Parse_Error (OBJECT_TOKEN);
  2197.     END_CASE
  2198.   END_EXPECT
  2199.   }
  2200.  
  2201. void Init_Viewpoint (vp)
  2202.   VIEWPOINT *vp;
  2203.   {
  2204.   vp -> Methods = (void *) &Viewpoint_Methods;
  2205.   vp -> Type = VIEWPOINT_TYPE;
  2206.   Make_Vector (&vp->Location, 0.0, 0.0, 0.0);
  2207.   Make_Vector (&vp->Direction, 0.0, 0.0, 1.0);
  2208.   Make_Vector (&vp->Up, 0.0, 1.0, 0.0);
  2209.   Make_Vector (&vp->Right, 1.0, 0.0, 0.0);
  2210.   Make_Vector (&vp->Sky, 0.0, 1.0, 0.0);
  2211.   }
  2212.  
  2213. void Link (New_Object, Field, Old_Object_List)
  2214.   OBJECT *New_Object, **Field, **Old_Object_List;
  2215.   {
  2216.   *Field = *Old_Object_List;
  2217.   *Old_Object_List = New_Object;
  2218.   }
  2219.  
  2220. CONSTANT Find_Constant()
  2221.   {
  2222.   register int i;
  2223.  
  2224.   for (i = 1 ; i <= Number_Of_Constants ; i++)
  2225.     if (Constants [i].Identifier_Number == Token.Identifier_Number)
  2226.       return (i);
  2227.  
  2228.   return (-1);
  2229.   }
  2230.  
  2231.  
  2232. char *Get_Token_String (Token_Id)
  2233.   TOKEN Token_Id;
  2234.   {
  2235.   register int i;
  2236.  
  2237.   for (i = 0 ; i < LAST_TOKEN ; i++)
  2238.      if (Reserved_Words[i].Token_Number == Token_Id)
  2239.         return (Reserved_Words[i].Token_Name);
  2240.   return ("");
  2241.   }
  2242.  
  2243. void Parse_Error (Token_Id)
  2244.   TOKEN Token_Id;
  2245.   {
  2246.   char *expected, *found;
  2247.  
  2248.   fprintf (stderr, "Error in file %s line %d\n", Current_File_Name,
  2249.                                                  Token.Token_Line_No);
  2250.   expected = Get_Token_String (Token_Id);
  2251.   found = Get_Token_String (Token.Token_Id);
  2252.   fprintf (stderr, "%s expected but %s found instead\n", expected, found);
  2253.   exit(0);
  2254.   }
  2255.  
  2256. void Type_Error ()
  2257.   {
  2258.   fprintf (stderr, "Error in file %s line %d\n", Current_File_Name,
  2259.                                                  Token.Token_Line_No);
  2260.   fprintf (stderr, "Identifier %s is the wrong type\n",
  2261.             &Token.Token_String[0]);
  2262.   exit (0);
  2263.   }
  2264.  
  2265. void Undeclared ()
  2266.   {
  2267.   fprintf (stderr, "Error in file %s line %d\n", Current_File_Name,
  2268.                                                  Token.Token_Line_No);
  2269.   fprintf (stderr, "Undeclared identifier %s\n", &Token.Token_String[0]);
  2270.   exit (0);
  2271.   }
  2272.  
  2273. void Error (str)
  2274.   char *str;
  2275.   {
  2276.   fprintf (stderr, "Error in file %s line %d\n", Current_File_Name,
  2277.                                                  Token.Token_Line_No);
  2278.   fputs (str, stderr);
  2279.   exit (0);
  2280.   }
  2281.  
  2282.