[comp.sources.amiga] v90i257: DKBTrace 2.01 - DKBtrace Ray-Tracer, Part09/10

amiga-request@abcfd20.larc.nasa.gov (Amiga Sources/Binaries Moderator) (09/04/90)

Submitted-by: David Schanen <mtv@milton.u.washington.edu>
Posting-number: Volume 90, Issue 257
Archive-name: applications/dkbtrace-2.01/part09

#!/bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 9 (of 10)."
# Contents:  src/parse.c
# Wrapped by tadguy@abcfd20 on Mon Sep  3 19:21:22 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'src/parse.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/parse.c'\"
else
echo shar: Extracting \"'src/parse.c'\" \(63678 characters\)
sed "s/^X//" >'src/parse.c' <<'END_OF_FILE'
X/*****************************************************************************
X*
X*                                    parse.c
X*
X*   from DKBTrace (c) 1990  David Buck
X*
X*  This module implements a parser for the scene description files.
X*
X* This software is freely distributable. The source and/or object code may be
X* copied or uploaded to communications services so long as this notice remains
X* at the top of each file.  If any changes are made to the program, you must
X* clearly indicate in the documentation and in the programs startup message
X* who it was who made the changes. The documentation should also describe what
X* those changes were. This software may not be included in whole or in
X* part into any commercial package without the express written consent of the
X* author.  It may, however, be included in other public domain or freely
X* distributed software so long as the proper credit for the software is given.
X*
X* This software is provided as is without any guarantees or warranty. Although
X* the author has attempted to find and correct any bugs in the software, he
X* is not responsible for any damage caused by the use of the software.  The
X* author is under no obligation to provide service, corrections, or upgrades
X* to this package.
X*
X* Despite all the legal stuff above, if you do find bugs, I would like to hear
X* about them.  Also, if you have any comments or questions, you may contact me
X* at the following address:
X*
X*     David Buck
X*     22C Sonnet Cres.
X*     Nepean Ontario
X*     Canada, K2H 8W7
X*
X*  I can also be reached on the following bulleton boards:
X*
X*     ATX              (613) 526-4141
X*     OMX              (613) 731-3419
X*     Mystic           (613) 731-0088 or (613) 731-6698
X*
X*  Fidonet:   1:163/109.9
X*  Internet:  David_Buck@Carleton.CA
X*
X*  IBM Port by Aaron A. Collins. Aaron may be reached on the following BBS'es:
X*
X*     Lattice BBS                      (708) 916-1200
X*     The Information Exchange BBS     (708) 945-5575
X*     Stillwaters BBS                  (708) 403-2826
X*
X*****************************************************************************/
X
X#include "frame.h"
X#include "vector.h"
X#include "dkbproto.h"
X
X/* This file implements a simple recursive-descent parser for reading the
Xinput file.  */
X
Xextern FILE *Token_File;
XFRAME *Parsing_Frame_Ptr;
Xchar Current_File_Name[20];
X
Xextern METHODS Composite_Methods;
Xextern METHODS Basic_Object_Methods;
Xextern METHODS Sphere_Methods;
Xextern METHODS Quadric_Methods;
Xextern METHODS Viewpoint_Methods;
Xextern METHODS Plane_Methods;
Xextern METHODS Triangle_Methods;
Xextern METHODS Smooth_Triangle_Methods;
Xextern METHODS CSG_Union_Methods;
Xextern METHODS CSG_Intersection_Methods;
X
Xextern struct Reserved_Word_Struct Reserved_Words [];
Xextern DBL Antialias_Threshold;
X
Xstruct Token_Struct Token;
X
X#define MAX_CONSTANTS 100
Xstruct Constant_Struct Constants[MAX_CONSTANTS];
Xint Number_Of_Constants;
XTEXTURE *Default_Texture;
Xint Degenerate_Triangles;
X
X/* Here we create out own little language for doing the parsing.  It
Xmakes the code easier to read. */
X
X#define EXPECT { int Exit_Flag; Exit_Flag = FALSE; \
X while (!Exit_Flag) {Get_Token();  switch (Token.Token_Id) {
X#define CASE(x) case x:
X#define CASE2(x, y) case x: case y:
X#define CASE3(x, y, z) case x: case y: case z:
X#define CASE4(w, x, y, z) case w: case x: case y: case z:
X#define CASE5(v, w, x, y, z) case v: case w: case x: case y: case z:
X#define END_CASE break;
X#define EXIT Exit_Flag = TRUE;
X#define OTHERWISE default:
X#define END_EXPECT } } }
X#define GET(x) Get_Token(); if (Token.Token_Id != x) Parse_Error (x)
X#define UNGET Unget_Token();
X
X/* Parse the file into the given frame. */
Xvoid Parse (File, Frame_Ptr)
X  FILE *File;
X  FRAME *Frame_Ptr;
X  {
X  Token_File = File;
X  Parsing_Frame_Ptr = Frame_Ptr;
X
X  Degenerate_Triangles = FALSE;
X  Token_Init ();
X  Frame_Init ();
X  Parse_Frame ();
X  if (Degenerate_Triangles) {
X     printf ("Cannot continue due to degenerate triangles.\n");
X     exit(1);
X     }
X  }
X
Xvoid Token_Init ()
X  {
X  Token.Unget_Token = FALSE;
X  Token.End_Of_File = FALSE;
X  Number_Of_Constants = 0;
X  }
X
X/* Read a token from the input file and store it in the Token variable.
XIf the token is an INCLUDE token, then set the include file name and
Xread another token. */
X
Xint Get_Token ()
X  {
X  char *str_ptr;
X  int Token_Id;
X
X  if (Token.Unget_Token)
X    {
X    Token.Unget_Token = FALSE;
X    return (TRUE);
X    }
X
X  if (Token.End_Of_File)
X    {
X    return (FALSE);
X    }
X  
X  if (fscanf (Token_File, "%d %d", &Token_Id, &Token.Token_Line_No)
X       != 2)
X    {
X    Token.End_Of_File = TRUE;
X    Token.Token_Id    = END_OF_FILE_TOKEN;
X    return (TRUE);
X    }
X
X  Token.Token_Id = Token_Id;
X
X  getc(Token_File);
X  if (fgets (Token.Token_String, FILE_NAME_LENGTH, Token_File) == NULL)
X    {
X    Token.End_Of_File = TRUE;
X    Token.Token_Id    = END_OF_FILE_TOKEN;
X    return (TRUE);
X    }
X
X  if ((str_ptr = strchr(Token.Token_String, '\n')) != NULL)
X     *str_ptr = '\0';
X
X  if (Token.Token_Id == FLOAT_TOKEN)
X    if (sscanf (Token.Token_String, DBL_FORMAT_STRING, &(Token.Token_Float)) != 1)
X      {
X      printf ("Premature end of file in token file\n");
X      printf ("Could not read float: %s\n", Token.Token_String);
X      Token.End_Of_File = TRUE;
X      Token.Token_Id    = END_OF_FILE_TOKEN;
X      return (TRUE);
X      }
X
X  if (Token.Token_Id == INCLUDE_TOKEN) {
X     strcpy (Current_File_Name, Token.Token_String);
X     return (Get_Token());
X     }
X
X  if (Token.Token_Id > LAST_TOKEN)
X    {
X    Token.Identifier_Number = (int) Token.Token_Id - (int) LAST_TOKEN;
X    Token.Token_Id = IDENTIFIER_TOKEN;
X    }
X
X  return (TRUE);
X  }
X
X
X/* Mark that the token has been put back into the input stream.  The next
Xcall to Get_Token will return the last-read token instead of reading a
Xnew one from the file. */
X
Xvoid Unget_Token ()
X  {
X  Token.Unget_Token = TRUE;
X  }
X
X/* Set up the fields in the frame to default values. */
Xvoid Frame_Init ()
X  {
X  Default_Texture = Get_Texture();
X  Init_Viewpoint(&(Parsing_Frame_Ptr -> View_Point));
X  Parsing_Frame_Ptr -> Light_Sources = NULL;
X  Parsing_Frame_Ptr -> Objects = NULL;
X  Parsing_Frame_Ptr -> Atmosphere_IOR = 1.0;
X  Parsing_Frame_Ptr -> Antialias_Threshold = Antialias_Threshold;
X  Parsing_Frame_Ptr -> Fog_Distance = 0.0;
X  Make_Colour (&(Parsing_Frame_Ptr->Fog_Colour), 0.0, 0.0, 0.0);
X  }
X
X/* Allocate and initialize a composite object. */
XCOMPOSITE *Get_Composite_Object()
X  {
X  COMPOSITE *New_Composite;
X
X  if ((New_Composite = (COMPOSITE *) malloc (sizeof (COMPOSITE)))
X        == NULL)
X    Error ("Cannot allocate object");
X
X  New_Composite -> Objects = NULL;
X  New_Composite -> Next_Object = NULL;
X  New_Composite -> Next_Light_Source = NULL;
X  New_Composite -> Bounding_Shapes = NULL;
X  New_Composite -> Type = COMPOSITE_TYPE;
X  New_Composite -> Methods = &Composite_Methods;
X  return (New_Composite);
X  }
X
X/* Allocate and initialize a sphere. */
XSPHERE *Get_Sphere_Shape()
X  {
X  SPHERE *New_Shape;
X
X  if ((New_Shape = (SPHERE *) malloc (sizeof (SPHERE))) == NULL)
X    Error ("Cannot allocate shape");
X
X  Make_Vector (&(New_Shape -> Center), 0.0, 0.0, 0.0);
X  New_Shape->Radius = 1.0;
X  New_Shape->Radius_Squared = 1.0;
X  New_Shape->Inverse_Radius = 1.0;
X  New_Shape -> Type = SPHERE_TYPE;
X  New_Shape -> Next_Object = NULL;
X  New_Shape -> Methods = &Sphere_Methods;
X  New_Shape -> VPCached = FALSE;
X  New_Shape -> Inverted = FALSE;
X  return (New_Shape);
X  }
X
X/* Allocate and initialize a quadric surface. */
XQUADRIC *Get_Quadric_Shape()
X  {
X  QUADRIC *New_Shape;
X
X  if ((New_Shape = (QUADRIC *) malloc (sizeof (QUADRIC))) == NULL)
X    Error ("Cannot allocate shape");
X
X  Make_Vector (&(New_Shape -> Object_2_Terms), 1.0, 1.0, 1.0);
X  Make_Vector (&(New_Shape -> Object_Mixed_Terms), 0.0, 0.0, 0.0);
X  Make_Vector (&(New_Shape -> Object_Terms), 0.0, 0.0, 0.0);
X  New_Shape -> Object_Constant = 1.0;
X  New_Shape -> Object_VP_Constant = HUGE_VAL;
X  New_Shape -> Constant_Cached = FALSE;
X  New_Shape -> Non_Zero_Square_Term = FALSE;
X  New_Shape -> Type = QUADRIC_TYPE;
X  New_Shape -> Next_Object = NULL;
X  New_Shape -> Methods = &Quadric_Methods;
X  return (New_Shape);
X  }
X
X/* Allocate and initialize a plane. */
XPLANE *Get_Plane_Shape()
X  {
X  PLANE *New_Shape;
X
X  if ((New_Shape = (PLANE *) malloc (sizeof (PLANE))) == NULL)
X    Error ("Cannot allocate shape");
X
X  Make_Vector (&(New_Shape -> Normal_Vector), 0.0, 1.0, 0.0);
X  New_Shape->Distance = 0.0;
X  New_Shape -> Type = PLANE_TYPE;
X  New_Shape -> Next_Object = NULL;
X  New_Shape -> Methods = &Plane_Methods;
X  New_Shape -> VPCached = 0;
X  return (New_Shape);
X  }
X
X/* Allocate and initialize a triangle. */
XTRIANGLE *Get_Triangle_Shape()
X  {
X  TRIANGLE *New_Shape;
X
X  if ((New_Shape = (TRIANGLE *) malloc (sizeof (TRIANGLE))) == NULL)
X    Error ("Cannot allocate shape");
X
X  Make_Vector (&(New_Shape -> Normal_Vector), 0.0, 1.0, 0.0);
X  Make_Vector (&(New_Shape -> P1), 0.0, 0.0, 0.0);
X  Make_Vector (&(New_Shape -> P2), 1.0, 0.0, 0.0);
X  Make_Vector (&(New_Shape -> P3), 0.0, 1.0, 0.0);
X  New_Shape->Distance = 0.0;
X  New_Shape->Inverted = FALSE;
X  New_Shape -> Type = TRIANGLE_TYPE;
X  New_Shape -> Next_Object = NULL;
X  New_Shape -> Methods = &Triangle_Methods;
X  New_Shape -> VPCached = FALSE;
X  return (New_Shape);
X  }
X
X/* Allocate and initialize a smooth triangle. */
XSMOOTH_TRIANGLE *Get_Smooth_Triangle_Shape()
X  {
X  SMOOTH_TRIANGLE *New_Shape;
X
X  if ((New_Shape = (SMOOTH_TRIANGLE *) malloc (sizeof (SMOOTH_TRIANGLE))) == NULL)
X    Error ("Cannot allocate shape");
X
X  Make_Vector (&(New_Shape -> Normal_Vector), 0.0, 1.0, 0.0);
X  Make_Vector (&(New_Shape -> P1), 0.0, 0.0, 0.0);
X  Make_Vector (&(New_Shape -> P2), 1.0, 0.0, 0.0);
X  Make_Vector (&(New_Shape -> P3), 0.0, 1.0, 0.0);
X  Make_Vector (&(New_Shape -> N1), 0.0, 1.0, 0.0);
X  Make_Vector (&(New_Shape -> DN12), 0.0, 1.0, 0.0);
X  Make_Vector (&(New_Shape -> DN13), 0.0, 1.0, 0.0);
X  New_Shape->Distance = 0.0;
X  New_Shape -> Type = SMOOTH_TRIANGLE_TYPE;
X  New_Shape->Inverted = FALSE;
X  New_Shape -> Next_Object = NULL;
X  New_Shape -> Methods = &Smooth_Triangle_Methods;
X  New_Shape -> VPCached = 0;
X  return (New_Shape);
X  }
X
XCSG_SHAPE *Get_CSG_Shape()
X  {
X  CSG_SHAPE *New_Shape;
X
X  if ((New_Shape = (CSG_SHAPE *) malloc (sizeof (CSG_SHAPE))) == NULL)
X    Error ("Cannot allocate shape");
X
X  New_Shape -> Parent_Object = NULL;
X  New_Shape -> Next_Object = NULL;
X  New_Shape -> Shapes = NULL;
X  return (New_Shape);
X  }
X
XCSG_SHAPE *Get_CSG_Union()
X  {
X  CSG_SHAPE *New_Shape;
X
X  New_Shape = Get_CSG_Shape();
X  New_Shape -> Methods = &CSG_Union_Methods;
X  New_Shape -> Type = CSG_UNION_TYPE;
X  return (New_Shape);
X  }
X
XCSG_SHAPE *Get_CSG_Intersection()
X  {
X  CSG_SHAPE *New_Shape;
X
X  New_Shape = Get_CSG_Shape();
X  New_Shape -> Methods = &CSG_Intersection_Methods;
X  New_Shape -> Type = CSG_INTERSECTION_TYPE;
X  return (New_Shape);
X  }
X
XOBJECT *Get_Object ()
X  {
X  OBJECT *New_Object;
X
X  if ((New_Object = (OBJECT *) malloc (sizeof (OBJECT))) == NULL)
X    Error ("Cannot allocate object");
X
X  Make_Vector (&(New_Object -> Object_Center), 0.0, 0.0, 0.0);
X
X  New_Object -> Next_Object = NULL;
X  New_Object -> Next_Light_Source = NULL;
X  New_Object -> Shape = NULL;
X  New_Object -> Bounding_Shapes = NULL;
X  New_Object -> Object_Texture = Default_Texture;
X
X  Make_Colour (&New_Object->Object_Colour, 0.0, 0.0, 0.0);
X
X  New_Object -> Light_Source_Flag = FALSE;
X  New_Object -> Transparency = FALSE;
X  New_Object -> Type = OBJECT_TYPE;
X  New_Object -> Methods = &Basic_Object_Methods;
X  return (New_Object);
X  }
X
XTEXTURE *Get_Texture ()
X   {
X   TEXTURE *New_Texture;
X
X   if ((New_Texture = (TEXTURE *) malloc (sizeof (TEXTURE))) == NULL)
X     Error ("Cannot allocate object");
X
X   New_Texture -> Object_Reflection = 0.0;
X   New_Texture -> Object_Ambient = 0.3;
X   New_Texture -> Object_Diffuse = 0.7;
X   New_Texture -> Object_Brilliance = 1.0;
X   New_Texture -> Object_Specular = 0.0;
X   New_Texture -> Object_Roughness = 0.05;
X   New_Texture -> Object_Phong = 0.0;
X   New_Texture -> Object_PhongSize = 40;
X
X   New_Texture -> Texture_Randomness= 0.0;
X   New_Texture -> Bump_Amount = 0.0;
X   New_Texture -> Phase = 0.0;
X   New_Texture -> Frequency = 1.0;
X   New_Texture -> Texture_Number = 0;
X   New_Texture -> Texture_Transformation = NULL;
X   New_Texture -> Bump_Number = NO_BUMPS;
X   New_Texture -> Turbulence = 0.0;
X   New_Texture -> Colour_Map = NULL;
X   New_Texture -> Once_Flag = FALSE;
X   Make_Colour (&New_Texture -> Colour1, 0.0, 0.0, 0.0);
X   Make_Colour (&New_Texture -> Colour2, 0.0, 0.0, 0.0);
X   Make_Vector (&New_Texture->Texture_Gradient, 0.0, 0.0, 0.0);
X
X   New_Texture -> Object_Index_Of_Refraction = 1.0;
X   New_Texture -> Object_Refraction = 0.0;
X
X   return (New_Texture);
X   }
X
XVIEWPOINT *Get_Viewpoint ()
X  {
X  VIEWPOINT *New_Viewpoint;
X
X  if ((New_Viewpoint = (VIEWPOINT *)malloc (sizeof (VIEWPOINT)))
X        == NULL)
X    Error ("Cannot allocate viewpoint");
X
X  Init_Viewpoint (New_Viewpoint);
X  return (New_Viewpoint);
X  }
X
XCOLOUR *Get_Colour ()
X  {
X  COLOUR *New_Colour;
X
X  if ((New_Colour = (COLOUR *) malloc (sizeof (COLOUR))) == NULL)
X    Error ("Cannot allocate colour");
X
X  Make_Colour (New_Colour, 0.0, 0.0, 0.0);
X  return (New_Colour);
X  }
X
XVECTOR *Get_Vector ()
X  {
X  VECTOR *New_Vector;
X
X  if ((New_Vector = (VECTOR *) malloc (sizeof (VECTOR))) == NULL)
X    Error ("Cannot allocate vector");
X
X  New_Vector -> x = 0.0;
X  New_Vector -> y = 0.0;
X  New_Vector -> z = 0.0;
X  return (New_Vector);
X  }
X
XDBL *Get_Float ()
X  {
X  DBL *New_Float;
X
X  if ((New_Float = (DBL *) malloc (sizeof (DBL))) == NULL)
X    Error ("Cannot allocate float");
X
X  *New_Float = 0.0;
X  return (New_Float);
X  }
X
XTRANSFORMATION *Get_Transformation()
X  {
X  TRANSFORMATION *New_Transformation;
X
X  if ((New_Transformation =
X        (TRANSFORMATION *) malloc (sizeof (TRANSFORMATION))) == NULL)
X    Error ("Cannot allocate transformation");
X
X  MIdentity ((MATRIX *) &(New_Transformation -> matrix[0][0]));
X  MIdentity ((MATRIX *) &(New_Transformation -> inverse[0][0]));
X  return (New_Transformation);
X  }
X
X/* Parse a float.  Doesn't handle exponentiation. */
XDBL Parse_Float ()
X  {
X  DBL Local_Float;
X  CONSTANT Constant_Id;
X  register int Negative, Sign_Parsed;
X
X  Negative = FALSE;
X  Sign_Parsed = FALSE;
X
X  EXPECT
X    CASE (IDENTIFIER_TOKEN)
X      if ((Constant_Id = Find_Constant()) != -1)
X        if (Constants[(int)Constant_Id].Constant_Type == FLOAT_CONSTANT)
X          {
X          Local_Float = *((DBL *) Constants[(int)Constant_Id].Constant_Data);
X          if (Negative)
X            Local_Float *= -1.0;
X          }
X        else
X          Type_Error ();
X      else
X        Undeclared ();
X      EXIT
X    END_CASE
X
X    CASE (PLUS_TOKEN)
X      if (Sign_Parsed)
X        Parse_Error (FLOAT_TOKEN);
X      Sign_Parsed = TRUE;
X    END_CASE
X
X    CASE (DASH_TOKEN)
X      if (Sign_Parsed)
X        Parse_Error (FLOAT_TOKEN);
X      Negative = TRUE;
X      Sign_Parsed = TRUE;
X    END_CASE
X
X    CASE (FLOAT_TOKEN)
X      Local_Float = Token.Token_Float;
X      if (Negative)
X        Local_Float *= -1.0;
X      EXIT
X    END_CASE
X
X    OTHERWISE
X      Parse_Error (FLOAT_TOKEN);
X    END_CASE
X  END_EXPECT
X
X  return (Local_Float);
X  }
X
Xvoid Parse_Vector (Given_Vector)
X  VECTOR *Given_Vector;
X  {
X  CONSTANT Constant_Id;
X
X  EXPECT
X    CASE (IDENTIFIER_TOKEN)
X      if ((Constant_Id = Find_Constant()) != -1)
X        if (Constants[(int)Constant_Id].Constant_Type == VECTOR_CONSTANT)
X          *Given_Vector = *((VECTOR *) Constants[(int)Constant_Id].Constant_Data);
X        else
X          Type_Error ();
X      else
X        Undeclared ();
X      EXIT
X    END_CASE
X
X    CASE (LEFT_ANGLE_TOKEN)
X      (Given_Vector -> x) = Parse_Float();
X      (Given_Vector -> y) = Parse_Float();
X      (Given_Vector -> z) = Parse_Float();
X      GET (RIGHT_ANGLE_TOKEN);
X      EXIT
X    END_CASE
X
X    OTHERWISE 
X      Parse_Error (LEFT_ANGLE_TOKEN);
X    END_CASE
X  END_EXPECT
X  }
X
Xvoid Parse_Colour (Given_Colour)
X  COLOUR *Given_Colour;
X  {
X  CONSTANT Constant_Id;
X
X  Make_Colour (Given_Colour, 0.0, 0.0, 0.0);
X  EXPECT
X    CASE (IDENTIFIER_TOKEN)
X      if ((Constant_Id = Find_Constant()) != -1)
X        if (Constants[(int)Constant_Id].Constant_Type == COLOUR_CONSTANT)
X          *Given_Colour = *((COLOUR *) Constants[(int)Constant_Id].Constant_Data);
X        else
X          Type_Error ();
X      else
X        Undeclared ();
X    END_CASE
X
X    CASE (RED_TOKEN)
X      (Given_Colour -> Red) = Parse_Float();
X    END_CASE
X
X    CASE (GREEN_TOKEN)
X      (Given_Colour -> Green) = Parse_Float();
X    END_CASE
X
X    CASE (BLUE_TOKEN)
X      (Given_Colour -> Blue) = Parse_Float();
X    END_CASE
X
X    CASE (ALPHA_TOKEN)
X      (Given_Colour -> Alpha) = Parse_Float();
X    END_CASE
X
X    OTHERWISE
X      UNGET
X      EXIT
X    END_CASE
X  END_EXPECT
X  }
X
XCOLOUR_MAP *Parse_Colour_Map ()
X   {
X#define MAX_ENTRIES 20
X   COLOUR_MAP *New_Colour_Map;
X   register int i;
X
X   New_Colour_Map = (COLOUR_MAP *)
X                        malloc (sizeof (COLOUR_MAP));
X
X   if (New_Colour_Map == NULL)
X      Error ("Not enough memory for colour map");
X
X   New_Colour_Map -> Colour_Map_Entries = (COLOUR_MAP_ENTRY *)
X                  malloc(MAX_ENTRIES * sizeof (COLOUR_MAP_ENTRY));
X
X   if (New_Colour_Map -> Colour_Map_Entries == NULL)
X      Error ("Not enough memory for colour map");
X
X   i = 0;
X   EXPECT
X      CASE (LEFT_SQUARE_TOKEN)
X         New_Colour_Map -> Colour_Map_Entries [i].start = Parse_Float();
X         New_Colour_Map -> Colour_Map_Entries [i].end = Parse_Float();
X         GET (COLOUR_TOKEN);
X         Parse_Colour (&(New_Colour_Map->Colour_Map_Entries[i].Start_Colour));
X         GET (COLOUR_TOKEN);
X         Parse_Colour (&(New_Colour_Map->Colour_Map_Entries[i].End_Colour));
X         i++;
X         if (i > MAX_ENTRIES)
X            Error ("Colour_Map too long");
X         GET (RIGHT_SQUARE_TOKEN);
X      END_CASE
X
X      CASE2 (END_COLOUR_MAP_TOKEN, END_COLOR_MAP_TOKEN)
X          New_Colour_Map -> Number_Of_Entries = i;
X          EXIT
X      END_CASE
X
X      OTHERWISE
X         Parse_Error (END_COLOUR_MAP_TOKEN);
X      END_CASE
X   END_EXPECT
X   return (New_Colour_Map);
X   }
X
XTEXTURE *Copy_Texture (Texture)
X   TEXTURE *Texture;
X   {
X   TEXTURE *New_Texture;
X   New_Texture = Get_Texture();
X   *New_Texture = *Texture;
X   if (New_Texture->Texture_Transformation) {
X      New_Texture->Texture_Transformation = (TRANSFORMATION *) malloc (sizeof (TRANSFORMATION));
X      *New_Texture->Texture_Transformation = *Texture->Texture_Transformation;
X      }
X   return (New_Texture);
X   }
X
XTEXTURE *Parse_Texture (Old_Texture)
X   TEXTURE *Old_Texture;
X   {
X   VECTOR Local_Vector;
X   TRANSFORMATION Local_Transformation;
X   CONSTANT Constant_Id;
X   TEXTURE *Texture;
X   int Texture_Constant;
X
X   Texture = Old_Texture;
X   Texture_Constant = TRUE;
X
X   EXPECT
X      CASE (IDENTIFIER_TOKEN)
X         if ((Constant_Id = Find_Constant()) != -1)
X            if (Constants[(int)Constant_Id].Constant_Type == TEXTURE_CONSTANT) {
X               Texture = ((TEXTURE *) Constants[(int)Constant_Id].Constant_Data);
X               Texture_Constant = TRUE;
X               }
X            else
X               Type_Error ();
X         else
X            Undeclared ();
X      END_CASE
X
X      CASE (FLOAT_TOKEN)
X         UNGET
X         if (Texture_Constant) {
X            Texture = Copy_Texture(Texture);
X            Texture_Constant = FALSE;
X            }
X         Texture -> Texture_Randomness = Parse_Float();
X      END_CASE
X
X      CASE (ONCE_TOKEN)
X         if (Texture_Constant) {
X            Texture = Copy_Texture(Texture);
X            Texture_Constant = FALSE;
X            }
X         Texture->Once_Flag = TRUE;
X      END_CASE
X
X      CASE (TURBULENCE_TOKEN)
X         if (Texture_Constant) {
X            Texture = Copy_Texture(Texture);
X            Texture_Constant = FALSE;
X            }
X          Texture -> Turbulence = Parse_Float();
X      END_CASE
X 
X      CASE (BOZO_TOKEN)
X         if (Texture_Constant) {
X            Texture_Constant = FALSE;
X            Texture = Copy_Texture (Texture);
X            }
X         Texture -> Texture_Number = BOZO_TEXTURE;
X      END_CASE
X
X      CASE (CHECKER_TOKEN)
X         if (Texture_Constant) {
X            Texture_Constant = FALSE;
X            Texture = Copy_Texture (Texture);
X            }
X         Texture -> Texture_Number = CHECKER_TEXTURE;
X         EXPECT
X            CASE (COLOUR_TOKEN)
X               Parse_Colour (&(Texture -> Colour1));
X               GET (COLOUR_TOKEN);
X               Parse_Colour (&(Texture -> Colour2));
X            END_CASE
X
X            OTHERWISE
X               UNGET
X               EXIT
X            END_CASE
X         END_EXPECT
X      END_CASE
X
X      CASE (MARBLE_TOKEN)
X         if (Texture_Constant) {
X            Texture_Constant = FALSE;
X            Texture = Copy_Texture (Texture);
X            }
X         Texture -> Texture_Number = MARBLE_TEXTURE;
X      END_CASE
X
X      CASE (WOOD_TOKEN)
X         if (Texture_Constant) {
X            Texture_Constant = FALSE;
X            Texture = Copy_Texture (Texture);
X            }
X         Texture -> Texture_Number = WOOD_TEXTURE;
X      END_CASE
X
X      CASE (SPOTTED_TOKEN)
X         if (Texture_Constant) {
X            Texture_Constant = FALSE;
X            Texture = Copy_Texture (Texture);
X            }
X         Texture -> Texture_Number = SPOTTED_TEXTURE;
X      END_CASE
X
X      CASE (AGATE_TOKEN)
X         if (Texture_Constant) {
X            Texture_Constant = FALSE;
X            Texture = Copy_Texture (Texture);
X            }
X         Texture -> Texture_Number = AGATE_TEXTURE;
X      END_CASE
X
X      CASE (GRANITE_TOKEN)
X         if (Texture_Constant) {
X            Texture_Constant = FALSE;
X            Texture = Copy_Texture (Texture);
X            }
X         Texture -> Texture_Number = GRANITE_TEXTURE;
X      END_CASE
X
X       CASE (GRADIENT_TOKEN)
X         if (Texture_Constant) {
X            Texture_Constant = FALSE;
X            Texture = Copy_Texture (Texture);
X            }
X	 Texture -> Texture_Number = GRADIENT_TEXTURE;
X	 Parse_Vector (&(Texture -> Texture_Gradient));
X       END_CASE
X 
X      CASE (AMBIENT_TOKEN)
X         if (Texture_Constant) {
X            Texture_Constant = FALSE;
X            Texture = Copy_Texture (Texture);
X            }
X         (Texture -> Object_Ambient) = Parse_Float ();
X      END_CASE
X
X      CASE (BRILLIANCE_TOKEN)
X         if (Texture_Constant) {
X            Texture_Constant = FALSE;
X            Texture = Copy_Texture (Texture);
X            }
X         (Texture -> Object_Brilliance) = Parse_Float ();
X      END_CASE
X
X      CASE (ROUGHNESS_TOKEN)
X         if (Texture_Constant) {
X            Texture_Constant = FALSE;
X            Texture = Copy_Texture (Texture);
X            }
X         (Texture -> Object_Roughness) = Parse_Float ();
X         if (Texture -> Object_Roughness > 1.0)
X            Texture -> Object_Roughness = 1.0;
X         if (Texture -> Object_Roughness < 0.001)
X            Texture -> Object_Roughness = 0.001;
X      END_CASE
X
X      CASE (PHONGSIZE_TOKEN)
X         if (Texture_Constant) {
X            Texture_Constant = FALSE;
X            Texture = Copy_Texture (Texture);
X            }
X         (Texture -> Object_PhongSize) = Parse_Float ();
X         if (Texture -> Object_PhongSize < 1.0)
X            Texture -> Object_PhongSize = 1.0;
X         if (Texture -> Object_PhongSize > 100)
X            Texture -> Object_PhongSize = 100;
X      END_CASE
X
X      CASE (DIFFUSE_TOKEN)
X         if (Texture_Constant) {
X            Texture_Constant = FALSE;
X            Texture = Copy_Texture (Texture);
X            }
X         (Texture -> Object_Diffuse) = Parse_Float ();
X      END_CASE
X
X      CASE (SPECULAR_TOKEN)
X         if (Texture_Constant) {
X            Texture_Constant = FALSE;
X            Texture = Copy_Texture (Texture);
X            }
X         (Texture -> Object_Specular) = Parse_Float ();
X      END_CASE
X
X      CASE (PHONG_TOKEN)
X         if (Texture_Constant) {
X            Texture_Constant = FALSE;
X            Texture = Copy_Texture (Texture);
X            }
X         (Texture -> Object_Phong) = Parse_Float ();
X      END_CASE
X
X      CASE (IOR_TOKEN)
X         if (Texture_Constant) {
X            Texture_Constant = FALSE;
X            Texture = Copy_Texture (Texture);
X            }
X         (Texture -> Object_Index_Of_Refraction) = Parse_Float ();
X      END_CASE
X
X      CASE (REFRACTION_TOKEN)
X         if (Texture_Constant) {
X            Texture_Constant = FALSE;
X            Texture = Copy_Texture (Texture);
X            }
X         (Texture -> Object_Refraction) = Parse_Float ();
X      END_CASE
X
X      CASE (REFLECTION_TOKEN)
X         if (Texture_Constant) {
X            Texture_Constant = FALSE;
X            Texture = Copy_Texture (Texture);
X            }
X         (Texture -> Object_Reflection) = Parse_Float ();
X      END_CASE
X
X      CASE (IMAGEMAP_TOKEN)
X         if (Texture_Constant) {
X            Texture_Constant = FALSE;
X            Texture = Copy_Texture (Texture);
X            }
X         Texture -> Texture_Number = IMAGEMAP_TEXTURE;
X         Texture->Image = (IMAGE *)malloc(sizeof(IMAGE));
X         Make_Vector (&Texture->Texture_Gradient, 1.0, -1.0, 0.0);
X         EXPECT
X            CASE (LEFT_ANGLE_TOKEN)
X                 UNGET
X            	 Parse_Vector (&(Texture -> Texture_Gradient));
X            END_CASE
X
X            CASE (IFF_TOKEN)
X               GET (STRING_TOKEN);
X               read_iff_image(Texture->Image, Token.Token_String);
X               EXIT
X            END_CASE
X
X            CASE (GIF_TOKEN)
X               GET (STRING_TOKEN);
X               read_gif_image(Texture->Image, Token.Token_String);
X               EXIT
X            END_CASE
X
X            CASE (RAW_TOKEN)
X               GET (STRING_TOKEN);
X               read_raw_image(Texture->Image, Token.Token_String);
X               EXIT
X            END_CASE
X
X            OTHERWISE
X               Parse_Error (RAW_TOKEN);
X            END_CASE
X         END_EXPECT
X      END_CASE
X
X      CASE (WAVES_TOKEN)
X         if (Texture_Constant) {
X            Texture_Constant = FALSE;
X            Texture = Copy_Texture (Texture);
X            }
X         Texture -> Bump_Number = WAVES;
X         Texture -> Bump_Amount = Parse_Float ();
X         EXPECT
X            CASE (PHASE_TOKEN)
X               Texture -> Phase = Parse_Float();
X               EXIT
X            END_CASE
X
X            OTHERWISE
X               UNGET
X               EXIT
X            END_CASE
X         END_EXPECT
X      END_CASE
X
X      CASE (FREQUENCY_TOKEN)
X         if (Texture_Constant) {
X            Texture_Constant = FALSE;
X            Texture = Copy_Texture (Texture);
X            }
X         Texture -> Frequency = Parse_Float();
X      END_CASE
X
X      CASE (PHASE_TOKEN)
X         if (Texture_Constant) {
X            Texture_Constant = FALSE;
X            Texture = Copy_Texture (Texture);
X            }
X         Texture -> Phase = Parse_Float();
X      END_CASE
X
X      CASE (RIPPLES_TOKEN)
X         if (Texture_Constant) {
X            Texture_Constant = FALSE;
X            Texture = Copy_Texture (Texture);
X            }
X         Texture -> Bump_Number = RIPPLES;
X         Texture -> Bump_Amount = Parse_Float ();
X      END_CASE
X
X      CASE (WRINKLES_TOKEN)
X         if (Texture_Constant) {
X            Texture_Constant = FALSE;
X            Texture = Copy_Texture (Texture);
X            }
X         Texture -> Bump_Number = WRINKLES;
X         Texture -> Bump_Amount = Parse_Float ();
X      END_CASE
X
X      CASE (BUMPS_TOKEN)
X         if (Texture_Constant) {
X            Texture_Constant = FALSE;
X            Texture = Copy_Texture (Texture);
X            }
X         Texture -> Bump_Number = BUMPS;
X         Texture -> Bump_Amount = Parse_Float ();
X      END_CASE
X
X      CASE (DENTS_TOKEN)
X         if (Texture_Constant) {
X            Texture_Constant = FALSE;
X            Texture = Copy_Texture (Texture);
X            }
X         Texture -> Bump_Number = DENTS;
X         Texture -> Bump_Amount = Parse_Float ();
X      END_CASE
X
X      CASE (TRANSLATE_TOKEN)
X         if (Texture_Constant) {
X            Texture_Constant = FALSE;
X            Texture = Copy_Texture (Texture);
X            }
X         Parse_Vector (&Local_Vector);
X         if (!Texture -> Texture_Transformation)
X            Texture -> Texture_Transformation = Get_Transformation ();
X         Get_Translation_Transformation (&Local_Transformation,
X                                         &Local_Vector);
X         Compose_Transformations (Texture -> Texture_Transformation,
X                                  &Local_Transformation);
X      END_CASE
X
X      CASE (ROTATE_TOKEN)
X         if (Texture_Constant) {
X            Texture_Constant = FALSE;
X            Texture = Copy_Texture (Texture);
X            }
X         Parse_Vector (&Local_Vector);
X         if (!Texture -> Texture_Transformation)
X            Texture -> Texture_Transformation = Get_Transformation ();
X         Get_Rotation_Transformation (&Local_Transformation,
X                                      &Local_Vector);
X         Compose_Transformations (Texture -> Texture_Transformation,
X                                  &Local_Transformation);
X      END_CASE
X
X      CASE (SCALE_TOKEN)
X         if (Texture_Constant) {
X            Texture_Constant = FALSE;
X            Texture = Copy_Texture (Texture);
X            }
X         Parse_Vector (&Local_Vector);
X         if (!Texture -> Texture_Transformation)
X             Texture -> Texture_Transformation = Get_Transformation ();
X         Get_Scaling_Transformation (&Local_Transformation,
X                                     &Local_Vector);
X         Compose_Transformations (Texture -> Texture_Transformation,
X                                  &Local_Transformation);
X      END_CASE
X
X      CASE2 (COLOUR_MAP_TOKEN, COLOR_MAP_TOKEN)
X         if (Texture_Constant) {
X            Texture_Constant = FALSE;
X            Texture = Copy_Texture (Texture);
X            }
X         Texture -> Colour_Map = Parse_Colour_Map();
X      END_CASE
X
X      CASE (END_TEXTURE_TOKEN)
X         EXIT
X      END_CASE
X
X      OTHERWISE
X         Parse_Error (END_TEXTURE_TOKEN);
X      END_CASE
X   END_EXPECT
X   return (Texture);
X   }
X
XSHAPE *Parse_Sphere ()
X  {
X  SPHERE *Local_Shape;
X  CONSTANT Constant_Id;
X  VECTOR Local_Vector;
X
X  Local_Shape = NULL;
X
X  EXPECT
X     CASE (LEFT_ANGLE_TOKEN)
X       UNGET
X       Local_Shape = Get_Sphere_Shape();
X       Parse_Vector(&(Local_Shape -> Center));
X       Local_Shape -> Radius = Parse_Float();
X       Local_Shape -> Radius_Squared = Local_Shape -> Radius * Local_Shape -> Radius;
X       Local_Shape -> Inverse_Radius = 1.0 / Local_Shape -> Radius;
X       EXIT
X     END_CASE
X
X     CASE (IDENTIFIER_TOKEN)
X       if ((Constant_Id = Find_Constant()) != -1)
X         if (Constants[(int)Constant_Id].Constant_Type == SPHERE_CONSTANT)
X           Local_Shape = (SPHERE *)Copy((OBJECT *) Constants[(int)Constant_Id].Constant_Data);
X         else
X           Type_Error ();
X       else
X         Undeclared ();
X       EXIT
X     END_CASE
X
X     OTHERWISE
X        Parse_Error (LEFT_ANGLE_TOKEN);
X     END_CASE
X  END_EXPECT
X
X  EXPECT
X     CASE (END_SPHERE_TOKEN)
X        EXIT
X     END_CASE
X
X     CASE (TRANSLATE_TOKEN)
X        Parse_Vector (&Local_Vector);
X        Translate ((OBJECT *) Local_Shape, &Local_Vector);
X     END_CASE
X
X     CASE (ROTATE_TOKEN)
X        Parse_Vector (&Local_Vector);
X        Rotate ((OBJECT *) Local_Shape, &Local_Vector);
X     END_CASE
X
X     CASE (SCALE_TOKEN)
X        Parse_Vector (&Local_Vector);
X        Scale ((OBJECT *) Local_Shape, &Local_Vector);
X     END_CASE
X
X     CASE (INVERSE_TOKEN)
X        Invert ((OBJECT *) Local_Shape);
X     END_CASE
X
X     OTHERWISE
X        Parse_Error (END_SPHERE_TOKEN);
X     END_CASE
X  END_EXPECT
X
X  return ((SHAPE *) Local_Shape);
X  }
X
XSHAPE *Parse_Plane ()
X  {
X  PLANE *Local_Shape;
X  CONSTANT Constant_Id;
X  VECTOR Local_Vector;
X
X  Local_Shape = NULL;
X
X  EXPECT
X     CASE (LEFT_ANGLE_TOKEN)
X       UNGET
X       Local_Shape = Get_Plane_Shape();
X       Parse_Vector(&(Local_Shape -> Normal_Vector));
X       Local_Shape->Distance = Parse_Float();
X       Local_Shape->Distance *= -1.0;
X       EXIT
X     END_CASE
X
X     CASE (IDENTIFIER_TOKEN)
X       if ((Constant_Id = Find_Constant()) != -1)
X         if (Constants[(int)Constant_Id].Constant_Type == PLANE_CONSTANT)
X           Local_Shape = (PLANE *)Copy((OBJECT *) Constants[(int)Constant_Id].Constant_Data);
X         else
X           Type_Error ();
X       else
X         Undeclared ();
X       EXIT
X     END_CASE
X
X     OTHERWISE
X        Parse_Error (LEFT_ANGLE_TOKEN);
X     END_CASE
X  END_EXPECT
X
X  EXPECT
X     CASE (END_PLANE_TOKEN)
X        EXIT
X     END_CASE
X
X     CASE (TRANSLATE_TOKEN)
X        Parse_Vector (&Local_Vector);
X        Translate ((OBJECT *) Local_Shape, &Local_Vector);
X     END_CASE
X
X     CASE (ROTATE_TOKEN)
X        Parse_Vector (&Local_Vector);
X        Rotate ((OBJECT *) Local_Shape, &Local_Vector);
X     END_CASE
X
X     CASE (SCALE_TOKEN)
X        Parse_Vector (&Local_Vector);
X        Scale ((OBJECT *) Local_Shape, &Local_Vector);
X     END_CASE
X
X     CASE (INVERSE_TOKEN)
X        Invert ((OBJECT *) Local_Shape);
X     END_CASE
X
X     OTHERWISE
X        Parse_Error (END_PLANE_TOKEN);
X     END_CASE
X  END_EXPECT
X
X  return ((SHAPE *) Local_Shape);
X  }
X
XSHAPE *Parse_Triangle ()
X  {
X  TRIANGLE *Local_Shape;
X  CONSTANT Constant_Id;
X  VECTOR Local_Vector;
X
X  Local_Shape = NULL;
X
X  EXPECT
X     CASE (LEFT_ANGLE_TOKEN)
X       UNGET
X       Local_Shape = Get_Triangle_Shape();
X       Parse_Vector (&Local_Shape->P1);
X       Parse_Vector (&Local_Shape->P2);
X       Parse_Vector (&Local_Shape->P3);
X       if (!Compute_Triangle (Local_Shape)) {
X          printf ("Degenerate triangle on line %d.  Please remove.\n",
X                  Token.Token_Line_No);
X          Degenerate_Triangles = TRUE;
X          }
X       EXIT
X     END_CASE
X
X     CASE (IDENTIFIER_TOKEN)
X       if ((Constant_Id = Find_Constant()) != -1)
X         if (Constants[(int)Constant_Id].Constant_Type == TRIANGLE_CONSTANT)
X           Local_Shape = (TRIANGLE *)Copy((OBJECT *) Constants[(int)Constant_Id].Constant_Data);
X         else
X           Type_Error ();
X       else
X         Undeclared ();
X       EXIT
X     END_CASE
X
X     OTHERWISE
X        Parse_Error (LEFT_ANGLE_TOKEN);
X     END_CASE
X  END_EXPECT
X
X  EXPECT
X     CASE (END_TRIANGLE_TOKEN)
X        EXIT
X     END_CASE
X
X     CASE (TRANSLATE_TOKEN)
X        Parse_Vector (&Local_Vector);
X        Translate ((OBJECT *) Local_Shape, &Local_Vector);
X     END_CASE
X
X     CASE (ROTATE_TOKEN)
X        Parse_Vector (&Local_Vector);
X        Rotate ((OBJECT *) Local_Shape, &Local_Vector);
X     END_CASE
X
X     CASE (SCALE_TOKEN)
X        Parse_Vector (&Local_Vector);
X        Scale ((OBJECT *) Local_Shape, &Local_Vector);
X     END_CASE
X
X     CASE (INVERSE_TOKEN)
X        Invert ((OBJECT *) Local_Shape);
X     END_CASE
X
X     OTHERWISE
X        Parse_Error (END_TRIANGLE_TOKEN);
X     END_CASE
X  END_EXPECT
X
X  return ((SHAPE *) Local_Shape);
X  }
X
XSHAPE *Parse_Smooth_Triangle ()
X  {
X  SMOOTH_TRIANGLE *Local_Shape;
X  CONSTANT Constant_Id;
X  VECTOR Local_Vector;
X
X  Local_Shape = NULL;
X
X  EXPECT
X     CASE (LEFT_ANGLE_TOKEN)
X       UNGET
X       Local_Shape = (SMOOTH_TRIANGLE *) Get_Smooth_Triangle_Shape();
X       Parse_Vector (&Local_Shape->P1);
X       Parse_Vector (&Local_Shape->N1);
X       Parse_Vector (&Local_Shape->P2);
X       Parse_Vector (&Local_Vector);
X       VSub (Local_Shape->DN12, Local_Vector, Local_Shape->N1);
X       Parse_Vector (&Local_Shape->P3);
X       Parse_Vector (&Local_Vector);
X       VSub (Local_Shape->DN13, Local_Vector, Local_Shape->N1);
X       if (!Compute_Triangle ((TRIANGLE *) Local_Shape)) {
X          printf ("Degenerate triangle on line %d.  Please remove.\n",
X                  Token.Token_Line_No);
X          Degenerate_Triangles = TRUE;
X          }
X       EXIT
X     END_CASE
X
X     CASE (IDENTIFIER_TOKEN)
X       if ((Constant_Id = Find_Constant()) != -1)
X         if (Constants[(int)Constant_Id].Constant_Type == SMOOTH_TRIANGLE_CONSTANT)
X           Local_Shape = (SMOOTH_TRIANGLE *)Copy((OBJECT *) Constants[(int)Constant_Id].Constant_Data);
X         else
X           Type_Error ();
X       else
X         Undeclared ();
X       EXIT
X     END_CASE
X
X     CASE (TRANSLATE_TOKEN)
X        Parse_Vector (&Local_Vector);
X        Translate ((OBJECT *) Local_Shape, &Local_Vector);
X     END_CASE
X
X     CASE (ROTATE_TOKEN)
X        Parse_Vector (&Local_Vector);
X        Rotate ((OBJECT *) Local_Shape, &Local_Vector);
X     END_CASE
X
X     CASE (SCALE_TOKEN)
X        Parse_Vector (&Local_Vector);
X        Scale ((OBJECT *) Local_Shape, &Local_Vector);
X     END_CASE
X
X     CASE (INVERSE_TOKEN)
X        Invert ((OBJECT *) Local_Shape);
X     END_CASE
X
X     OTHERWISE
X        Parse_Error (LEFT_ANGLE_TOKEN);
X     END_CASE
X  END_EXPECT
X
X  EXPECT
X     CASE (END_TRIANGLE_TOKEN)
X        EXIT
X     END_CASE
X
X     OTHERWISE
X        Parse_Error (END_TRIANGLE_TOKEN);
X     END_CASE
X  END_EXPECT
X
X  return ((SHAPE *) Local_Shape);
X  }
X
XSHAPE *Parse_Quadric ()
X  {
X  QUADRIC *Local_Shape;
X  VECTOR Local_Vector;
X  CONSTANT Constant_Id;
X
X  Local_Shape = NULL;
X
X  EXPECT
X     CASE (LEFT_ANGLE_TOKEN)
X       UNGET
X       Local_Shape = Get_Quadric_Shape();
X       Parse_Vector(&(Local_Shape -> Object_2_Terms));
X       Parse_Vector(&(Local_Shape -> Object_Mixed_Terms));
X       Parse_Vector(&(Local_Shape -> Object_Terms));
X       (Local_Shape -> Object_Constant) = Parse_Float();
X       Local_Shape -> Non_Zero_Square_Term = 
X         !((Local_Shape -> Object_2_Terms.x == 0.0)
X          && (Local_Shape -> Object_2_Terms.y == 0.0)
X          && (Local_Shape -> Object_2_Terms.z == 0.0)
X          && (Local_Shape -> Object_Mixed_Terms.x == 0.0)
X          && (Local_Shape -> Object_Mixed_Terms.y == 0.0)
X          && (Local_Shape -> Object_Mixed_Terms.z == 0.0));
X       EXIT
X     END_CASE
X
X     CASE (IDENTIFIER_TOKEN)
X       if ((Constant_Id = Find_Constant()) != -1)
X         if (Constants[(int)Constant_Id].Constant_Type == QUADRIC_CONSTANT)
X           Local_Shape = (QUADRIC *)Copy((OBJECT *) Constants[(int)Constant_Id].Constant_Data);
X         else
X           Type_Error ();
X       else
X         Undeclared ();
X       EXIT
X     END_CASE
X
X     OTHERWISE
X        Parse_Error (LEFT_ANGLE_TOKEN);
X     END_CASE
X  END_EXPECT
X
X  EXPECT
X     CASE (END_QUADRIC_TOKEN)
X        EXIT
X     END_CASE
X
X     CASE (TRANSLATE_TOKEN)
X        Parse_Vector (&Local_Vector);
X        Translate ((OBJECT *) Local_Shape, &Local_Vector);
X     END_CASE
X
X     CASE (ROTATE_TOKEN)
X        Parse_Vector (&Local_Vector);
X        Rotate ((OBJECT *) Local_Shape, &Local_Vector);
X     END_CASE
X
X     CASE (SCALE_TOKEN)
X        Parse_Vector (&Local_Vector);
X        Scale ((OBJECT *) Local_Shape, &Local_Vector);
X     END_CASE
X
X     CASE (INVERSE_TOKEN)
X        Invert ((OBJECT *) Local_Shape);
X     END_CASE
X
X     OTHERWISE
X        Parse_Error (END_QUADRIC_TOKEN);
X     END_CASE
X  END_EXPECT
X
X  return ((SHAPE *) Local_Shape);
X  }
X
XCSG_SHAPE *Parse_CSG (type, Parent_Object)
X  int type;
X  OBJECT *Parent_Object;
X  {
X  CSG_SHAPE *Container;
X  SHAPE *Local_Shape;
X  VECTOR Local_Vector;
X  CONSTANT Constant_Id;
X  int First_Shape_Parsed = FALSE;
X
X  if (type == CSG_UNION_TYPE)
X    Container = Get_CSG_Union ();
X
X  else if ((type == CSG_INTERSECTION_TYPE) || (type == CSG_DIFFERENCE_TYPE))
X    Container = Get_CSG_Intersection ();
X
X  Container -> Parent_Object = Parent_Object;
X
X  EXPECT
X     CASE (IDENTIFIER_TOKEN)
X       if ((Constant_Id = Find_Constant()) != -1)
X         if ((Constants[(int)Constant_Id].Constant_Type == CSG_INTERSECTION_CONSTANT)
X             || (Constants[(int)Constant_Id].Constant_Type == CSG_UNION_CONSTANT)
X             || (Constants[(int)Constant_Id].Constant_Type == CSG_DIFFERENCE_CONSTANT)) {
X           free (Container);
X           Container = (CSG_SHAPE *) Copy ((OBJECT *) Constants[(int)Constant_Id].Constant_Data);
X           Set_CSG_Parents(Container, Parent_Object);
X           }
X         else
X           Type_Error ();
X       else
X         Undeclared ();
X     END_CASE
X
X     CASE (SPHERE_TOKEN)
X       Local_Shape = Parse_Sphere ();
X       Local_Shape -> Parent_Object = Parent_Object;
X       if ((type == CSG_DIFFERENCE_TYPE) && First_Shape_Parsed)
X          Invert ((OBJECT *) Local_Shape);
X       First_Shape_Parsed = TRUE;
X       Link((OBJECT *) Local_Shape, (OBJECT **) &(Local_Shape -> Next_Object),
X               (OBJECT **) &(Container -> Shapes));
X     END_CASE
X
X     CASE (PLANE_TOKEN)
X       Local_Shape = Parse_Plane ();
X       Local_Shape -> Parent_Object = Parent_Object;
X       if ((type == CSG_DIFFERENCE_TYPE) && First_Shape_Parsed)
X          Invert ((OBJECT *) Local_Shape);
X       First_Shape_Parsed = TRUE;
X       Link((OBJECT *) Local_Shape, (OBJECT **) &(Local_Shape -> Next_Object),
X               (OBJECT **) &(Container -> Shapes));
X     END_CASE
X
X     CASE (TRIANGLE_TOKEN)
X       Local_Shape = Parse_Triangle ();
X       Local_Shape -> Parent_Object = Parent_Object;
X       if ((type == CSG_DIFFERENCE_TYPE) && First_Shape_Parsed)
X          Invert ((OBJECT *) Local_Shape);
X       First_Shape_Parsed = TRUE;
X       Link((OBJECT *) Local_Shape, (OBJECT **) &(Local_Shape -> Next_Object),
X               (OBJECT **) &(Container -> Shapes));
X     END_CASE
X
X     CASE (SMOOTH_TRIANGLE_TOKEN)
X       Local_Shape = Parse_Smooth_Triangle ();
X       Local_Shape -> Parent_Object = Parent_Object;
X       if ((type == CSG_DIFFERENCE_TYPE) && First_Shape_Parsed)
X          Invert ((OBJECT *) Local_Shape);
X       First_Shape_Parsed = TRUE;
X       Link((OBJECT *) Local_Shape, (OBJECT **) &(Local_Shape -> Next_Object),
X               (OBJECT **) &(Container -> Shapes));
X     END_CASE
X
X     CASE (QUADRIC_TOKEN)
X       Local_Shape = Parse_Quadric ();
X       Local_Shape -> Parent_Object = Parent_Object;
X       if ((type == CSG_DIFFERENCE_TYPE) && First_Shape_Parsed)
X          Invert ((OBJECT *) Local_Shape);
X       First_Shape_Parsed = TRUE;
X       Link((OBJECT *) Local_Shape, (OBJECT **) &(Local_Shape -> Next_Object),
X               (OBJECT **) &(Container -> Shapes));
X     END_CASE
X
X     CASE (UNION_TOKEN)
X       Local_Shape = (SHAPE *) Parse_CSG (CSG_UNION_TYPE, Parent_Object);
X       if ((type == CSG_DIFFERENCE_TYPE) && First_Shape_Parsed)
X          Invert ((OBJECT *) Local_Shape);
X       First_Shape_Parsed = TRUE;
X       Link((OBJECT *) Local_Shape, (OBJECT **) &(Local_Shape -> Next_Object),
X               (OBJECT **) &(Container -> Shapes));
X     END_CASE
X
X     CASE (INTERSECTION_TOKEN)
X       Local_Shape = (SHAPE *) Parse_CSG (CSG_INTERSECTION_TYPE, Parent_Object);
X       if ((type == CSG_DIFFERENCE_TYPE) && First_Shape_Parsed)
X          Invert ((OBJECT *) Local_Shape);
X       First_Shape_Parsed = TRUE;
X       Link((OBJECT *) Local_Shape, (OBJECT **) &(Local_Shape -> Next_Object),
X               (OBJECT **) &(Container -> Shapes));
X     END_CASE
X
X     CASE (DIFFERENCE_TOKEN)
X       Local_Shape = (SHAPE *) Parse_CSG (CSG_DIFFERENCE_TYPE, Parent_Object);
X       if ((type == CSG_DIFFERENCE_TYPE) && First_Shape_Parsed)
X          Invert ((OBJECT *) Local_Shape);
X       First_Shape_Parsed = TRUE;
X       Link((OBJECT *) Local_Shape, (OBJECT **) &(Local_Shape -> Next_Object),
X               (OBJECT **) &(Container -> Shapes));
X     END_CASE
X
X     OTHERWISE
X        UNGET
X        EXIT
X     END_CASE
X  END_EXPECT
X
X  EXPECT
X     CASE3 (END_UNION_TOKEN, END_INTERSECTION_TOKEN, END_DIFFERENCE_TOKEN)
X        EXIT
X     END_CASE
X
X     CASE (TRANSLATE_TOKEN)
X        Parse_Vector (&Local_Vector);
X        Translate((OBJECT *) Container, &Local_Vector);
X     END_CASE
X
X     CASE (ROTATE_TOKEN)
X        Parse_Vector (&Local_Vector);
X        Rotate ((OBJECT *) Container, &Local_Vector);
X     END_CASE
X
X     CASE (SCALE_TOKEN)
X        Parse_Vector (&Local_Vector);
X        Scale ((OBJECT *) Container, &Local_Vector);
X     END_CASE
X
X     CASE (INVERSE_TOKEN)
X        Invert ((OBJECT *) Container);
X     END_CASE
X
X     OTHERWISE
X        Parse_Error (END_QUADRIC_TOKEN);
X     END_CASE
X  END_EXPECT
X
X  return ((CSG_SHAPE *) Container);
X  }
X
XSHAPE *Parse_Shape (Object)
X  OBJECT *Object;
X  {
X  SHAPE *Local_Shape;
X
X  EXPECT
X    CASE (SPHERE_TOKEN)
X      Local_Shape = Parse_Sphere ();
X      Local_Shape -> Parent_Object = Object;
X      EXIT
X    END_CASE
X
X    CASE (PLANE_TOKEN)
X      Local_Shape = Parse_Plane ();
X      Local_Shape -> Parent_Object = Object;
X      EXIT
X    END_CASE
X
X    CASE (TRIANGLE_TOKEN)
X      Local_Shape = Parse_Triangle ();
X      Local_Shape -> Parent_Object = Object;
X      EXIT
X    END_CASE
X
X    CASE (SMOOTH_TRIANGLE_TOKEN)
X      Local_Shape = Parse_Smooth_Triangle ();
X      Local_Shape -> Parent_Object = Object;
X      EXIT
X    END_CASE
X
X    CASE (QUADRIC_TOKEN)
X      Local_Shape = Parse_Quadric ();
X      Local_Shape -> Parent_Object = Object;
X      EXIT
X    END_CASE
X
X    CASE (UNION_TOKEN)
X      Local_Shape = (SHAPE *) Parse_CSG (CSG_UNION_TYPE, Object);
X      EXIT
X    END_CASE
X
X    CASE (INTERSECTION_TOKEN)
X      Local_Shape = (SHAPE *) Parse_CSG (CSG_INTERSECTION_TYPE, Object);
X      EXIT
X    END_CASE
X
X    CASE (DIFFERENCE_TOKEN)
X      Local_Shape = (SHAPE *) Parse_CSG (CSG_DIFFERENCE_TYPE, Object);
X      EXIT
X    END_CASE
X
X    OTHERWISE
X       Parse_Error (QUADRIC_TOKEN);
X    END_CASE
X  END_EXPECT
X  return (Local_Shape);
X  }
X
XOBJECT *Parse_Object ()
X  {
X  OBJECT *Object;
X  SHAPE *Local_Shape;
X  VECTOR Local_Vector;
X  CONSTANT Constant_Id;
X  int i;
X
X  Object = NULL;
X
X  EXPECT
X    CASE (IDENTIFIER_TOKEN)
X      if ((Constant_Id = Find_Constant()) != -1)
X        if (Constants[(int)Constant_Id].Constant_Type == OBJECT_CONSTANT)
X          Object = (OBJECT *) Copy((OBJECT *) Constants[(int)Constant_Id].Constant_Data);
X        else
X          Type_Error ();
X      else
X        Undeclared ();
X      EXIT
X    END_CASE
X
X    CASE5 (SPHERE_TOKEN, QUADRIC_TOKEN, UNION_TOKEN,
X           INTERSECTION_TOKEN, DIFFERENCE_TOKEN)
X    CASE3 (TRIANGLE_TOKEN, SMOOTH_TRIANGLE_TOKEN, PLANE_TOKEN)
X        UNGET
X        if (Object == NULL)
X           Object = Get_Object();
X
X        Local_Shape = Parse_Shape(Object);
X        Link((OBJECT *)Local_Shape, (OBJECT **) &(Local_Shape -> Next_Object),
X                (OBJECT **) &(Object -> Shape));
X        EXIT
X    END_CASE
X
X    OTHERWISE
X        Parse_Error (QUADRIC_TOKEN);
X        EXIT
X    END_CASE
X  END_EXPECT
X
X  EXPECT
X    CASE (BOUNDED_TOKEN)
X       EXPECT
X          CASE (END_BOUNDED_TOKEN)
X             EXIT
X          END_CASE
X
X          OTHERWISE
X             UNGET
X             Local_Shape = Parse_Shape(Object);
X             Link((OBJECT *) Local_Shape,
X                  (OBJECT **) &(Local_Shape -> Next_Object),
X                  (OBJECT **) &(Object -> Bounding_Shapes));
X          END_CASE
X       END_EXPECT       
X    END_CASE
X
X    CASE2 (COLOR_TOKEN, COLOUR_TOKEN)
X       Parse_Colour (&(Object -> Object_Colour));
X       if (Object->Object_Colour.Alpha != 0.0)
X          Object->Transparency = TRUE;
X    END_CASE
X
X    CASE (TEXTURE_TOKEN)
X      Object -> Object_Texture = Parse_Texture (Object->Object_Texture);
X      if ((Object->Object_Texture->Colour1.Alpha != 0.0) ||
X          (Object->Object_Texture->Colour2.Alpha != 0.0))
X         Object->Transparency = TRUE;
X      else
X         if (Object->Object_Texture->Colour_Map != NULL)
X            for (i = 0 ; i < Object->Object_Texture->Colour_Map->Number_Of_Entries ; i++)
X               if ((Object->Object_Texture->Colour_Map->Colour_Map_Entries[i].Start_Colour.Alpha != 0.0) ||
X                   (Object->Object_Texture->Colour_Map->Colour_Map_Entries[i].Start_Colour.Alpha != 0.0)) {
X                  Object->Transparency = TRUE;
X                  break;
X                  }
X    END_CASE
X
X    CASE (LIGHT_SOURCE_TOKEN)
X      Object -> Light_Source_Flag = TRUE;
X    END_CASE
X
X    CASE (TRANSLATE_TOKEN)
X       Parse_Vector (&Local_Vector);
X       Translate (Object, &Local_Vector);
X    END_CASE
X
X    CASE (ROTATE_TOKEN)
X       Parse_Vector (&Local_Vector);
X       Rotate (Object, &Local_Vector);
X    END_CASE
X
X    CASE (SCALE_TOKEN)
X       Parse_Vector (&Local_Vector);
X       Scale (Object, &Local_Vector);
X    END_CASE
X
X    CASE (INVERSE_TOKEN)
X       Invert (Object);
X    END_CASE
X
X    CASE (AMBIENT_TOKEN)
X      if (Object -> Object_Texture == Default_Texture)
X         Object -> Object_Texture = Get_Texture();
X
X      (Object -> Object_Texture -> Object_Ambient) = Parse_Float ();
X    END_CASE
X
X    CASE (BRILLIANCE_TOKEN)
X      if (Object -> Object_Texture == Default_Texture)
X         Object -> Object_Texture = Get_Texture();
X
X      (Object -> Object_Texture -> Object_Brilliance) = Parse_Float ();
X    END_CASE
X
X    CASE (ROUGHNESS_TOKEN)
X      if (Object -> Object_Texture == Default_Texture)
X         Object -> Object_Texture = Get_Texture();
X
X      (Object -> Object_Texture -> Object_Roughness) = Parse_Float ();
X      if (Object -> Object_Texture -> Object_Roughness > 1.0)
X         Object -> Object_Texture -> Object_Roughness = 1.0;
X      if (Object -> Object_Texture -> Object_Roughness < 0.001)
X         Object -> Object_Texture -> Object_Roughness = 0.001;
X    END_CASE
X
X    CASE (PHONGSIZE_TOKEN)
X      if (Object -> Object_Texture == Default_Texture)
X         Object -> Object_Texture = Get_Texture();
X
X      (Object -> Object_Texture -> Object_PhongSize) = Parse_Float ();
X      if (Object -> Object_Texture -> Object_PhongSize < 1.0)
X         Object -> Object_Texture -> Object_PhongSize = 1.0;
X      if (Object -> Object_Texture -> Object_PhongSize > 100)
X         Object -> Object_Texture -> Object_PhongSize = 100;
X    END_CASE
X
X    CASE (DIFFUSE_TOKEN)
X      if (Object -> Object_Texture == Default_Texture)
X         Object -> Object_Texture = Get_Texture();
X
X      (Object -> Object_Texture -> Object_Diffuse) = Parse_Float ();
X    END_CASE
X
X    CASE (SPECULAR_TOKEN)
X      if (Object -> Object_Texture == Default_Texture)
X         Object -> Object_Texture = Get_Texture();
X
X      (Object -> Object_Texture -> Object_Specular) = Parse_Float ();
X    END_CASE
X
X    CASE (PHONG_TOKEN)
X      if (Object -> Object_Texture == Default_Texture)
X         Object -> Object_Texture = Get_Texture();
X
X      (Object -> Object_Texture -> Object_Phong) = Parse_Float ();
X    END_CASE
X
X    CASE (IOR_TOKEN)
X      if (Object -> Object_Texture == Default_Texture)
X         Object -> Object_Texture = Get_Texture();
X
X      (Object -> Object_Texture -> Object_Index_Of_Refraction) = Parse_Float ();
X    END_CASE
X
X    CASE (REFRACTION_TOKEN)
X      if (Object -> Object_Texture == Default_Texture)
X         Object -> Object_Texture = Get_Texture();
X
X      (Object -> Object_Texture -> Object_Refraction) = Parse_Float ();
X    END_CASE
X
X    CASE (REFLECTION_TOKEN)
X      if (Object -> Object_Texture == Default_Texture)
X         Object -> Object_Texture = Get_Texture();
X
X      (Object -> Object_Texture -> Object_Reflection) = Parse_Float ();
X    END_CASE
X
X    CASE (END_OBJECT_TOKEN)
X      EXIT
X    END_CASE
X
X    OTHERWISE
X      Parse_Error (END_OBJECT_TOKEN);
X    END_CASE
X
X  END_EXPECT
X
X  return (Object);
X  }
X
XOBJECT *Parse_Composite ()
X  {
X  COMPOSITE *Local_Composite;
X  OBJECT *Local_Object;
X  SHAPE *Local_Shape;
X  CONSTANT Constant_Id;
X  VECTOR Local_Vector;
X
X  Local_Composite = NULL;
X
X  EXPECT
X    CASE (IDENTIFIER_TOKEN)
X      if ((Constant_Id = Find_Constant()) != -1)
X        if (Constants[(int)Constant_Id].Constant_Type == COMPOSITE_CONSTANT)
X          Local_Composite = (COMPOSITE *)Copy((OBJECT *) Constants[(int)Constant_Id].Constant_Data);
X        else          
X          Type_Error ();
X      else
X        Undeclared ();
X    END_CASE
X
X    CASE (COMPOSITE_TOKEN)
X      if (Local_Composite == NULL)       
X           Local_Composite = Get_Composite_Object();
X
X      Local_Object = Parse_Composite();
X      Link((OBJECT *) Local_Object,(OBJECT **) &(Local_Object -> Next_Object),
X              (OBJECT **) &(Local_Composite -> Objects));
X    END_CASE
X
X    CASE (OBJECT_TOKEN)
X      if (Local_Composite == NULL)       
X           Local_Composite = Get_Composite_Object();
X
X      Local_Object = Parse_Object();
X      Link(Local_Object, &(Local_Object -> Next_Object),
X               &(Local_Composite -> Objects));
X
X      if (Local_Object -> Light_Source_Flag)
X         Link(Local_Object, &(Local_Object -> Next_Light_Source),
X               &(Parsing_Frame_Ptr -> Light_Sources));
X    END_CASE
X
X    CASE (END_COMPOSITE_TOKEN)
X      UNGET
X      if (Local_Composite == NULL)       
X        Local_Composite = Get_Composite_Object();
X
X      EXIT
X    END_CASE
X
X    OTHERWISE
X       UNGET
X       EXIT
X    END_CASE
X  END_EXPECT
X
X  EXPECT
X    CASE (END_COMPOSITE_TOKEN)
X       EXIT
X    END_CASE
X
X    CASE (BOUNDED_TOKEN)
X       EXPECT
X          CASE (END_BOUNDED_TOKEN)
X             EXIT
X          END_CASE
X
X          OTHERWISE
X             UNGET
X             Local_Shape = Parse_Shape((OBJECT *) Local_Composite);
X             Link((OBJECT *) Local_Shape,
X                  (OBJECT **) &(Local_Shape -> Next_Object),
X                  (OBJECT **) &(Local_Composite -> Bounding_Shapes));
X          END_CASE
X       END_EXPECT       
X    END_CASE
X
X    CASE (TRANSLATE_TOKEN)
X       Parse_Vector (&Local_Vector);
X       Translate ((OBJECT *) Local_Composite, &Local_Vector);
X    END_CASE
X
X    CASE (ROTATE_TOKEN)
X       Parse_Vector (&Local_Vector);
X       Rotate ((OBJECT *) Local_Composite, &Local_Vector);
X    END_CASE
X
X    CASE (SCALE_TOKEN)
X       Parse_Vector (&Local_Vector);
X       Scale ((OBJECT *) Local_Composite, &Local_Vector);
X    END_CASE
X
X     CASE (INVERSE_TOKEN)
X        Invert ((OBJECT *) Local_Composite);
X     END_CASE
X
X    OTHERWISE
X       Parse_Error (END_COMPOSITE_TOKEN);
X    END_CASE
X  END_EXPECT
X
X  return ((OBJECT *) Local_Composite);
X  }
X
Xvoid Parse_Fog ()
X   {
X   EXPECT
X      CASE (COLOUR_TOKEN)
X         Parse_Colour (&Parsing_Frame_Ptr->Fog_Colour);
X      END_CASE
X
X      CASE (FLOAT_TOKEN)
X         Parsing_Frame_Ptr->Fog_Distance = Token.Token_Float;
X      END_CASE
X
X      CASE (END_FOG_TOKEN)
X         EXIT
X      END_CASE
X
X      OTHERWISE
X         Parse_Error (END_FOG_TOKEN);
X      END_CASE
X   END_EXPECT
X   }
X
Xvoid Parse_Frame ()
X  {
X  OBJECT *Local_Object;
X
X  EXPECT
X    CASE (FOG_TOKEN)
X       Parse_Fog();
X    END_CASE
X
X    CASE (OBJECT_TOKEN)
X      Local_Object = Parse_Object();
X      Link(Local_Object, &(Local_Object -> Next_Object),
X             &(Parsing_Frame_Ptr -> Objects));
X
X      if (Local_Object -> Light_Source_Flag)
X         Link(Local_Object, &(Local_Object -> Next_Light_Source),
X               &(Parsing_Frame_Ptr -> Light_Sources));
X    END_CASE
X
X    CASE (COMPOSITE_TOKEN)
X      Local_Object = Parse_Composite();
X      Link(Local_Object, &(Local_Object -> Next_Object),
X            &(Parsing_Frame_Ptr -> Objects));
X    END_CASE
X
X    CASE (VIEW_POINT_TOKEN)
X      Parse_Viewpoint(&(Parsing_Frame_Ptr -> View_Point));
X    END_CASE
X
X    CASE (DECLARE_TOKEN)
X      Parse_Declare ();
X    END_CASE
X
X    CASE (END_OF_FILE_TOKEN)
X      EXIT
X    END_CASE
X
X    OTHERWISE 
X      Parse_Error (OBJECT_TOKEN);
X    END_CASE
X  END_EXPECT
X  }
X
Xvoid Parse_Viewpoint (Given_Vp)
X  VIEWPOINT *Given_Vp;
X  {
X  CONSTANT Constant_Id;
X  VECTOR Local_Vector, Temp_Vector;
X  DBL Direction_Length, Up_Length, Right_Length, Handedness;
X
X  Init_Viewpoint (Given_Vp);
X
X  EXPECT
X    CASE (IDENTIFIER_TOKEN)
X      if ((Constant_Id = Find_Constant()) != -1)
X        if (Constants[(int)Constant_Id].Constant_Type == VIEW_POINT_CONSTANT)
X          *Given_Vp = 
X             *((VIEWPOINT*) Constants[(int)Constant_Id].Constant_Data);
X        else
X          Type_Error ();
X      else
X        Undeclared ();
X    END_CASE
X
X    CASE (LOCATION_TOKEN)
X      Parse_Vector(&(Given_Vp -> Location));
X    END_CASE
X
X    CASE (DIRECTION_TOKEN)
X      Parse_Vector(&(Given_Vp -> Direction));
X    END_CASE
X
X    CASE (UP_TOKEN)
X      Parse_Vector(&(Given_Vp -> Up));
X    END_CASE
X
X    CASE (RIGHT_TOKEN)
X      Parse_Vector(&(Given_Vp -> Right));
X    END_CASE
X
X    CASE (SKY_TOKEN)
X      Parse_Vector(&(Given_Vp -> Sky));
X    END_CASE
X
X    CASE (LOOK_AT_TOKEN)
X       VLength (Direction_Length, Given_Vp->Direction);
X       VLength (Up_Length, Given_Vp->Up);
X       VLength (Right_Length, Given_Vp->Right);
X       VCross (Temp_Vector, Given_Vp->Direction, Given_Vp->Up);
X       VDot (Handedness, Temp_Vector, Given_Vp->Right);
X       Parse_Vector(&Given_Vp->Direction);
X
X       VSub (Given_Vp->Direction, Given_Vp->Direction, Given_Vp->Location);
X       VNormalize (Given_Vp->Direction, Given_Vp->Direction);
X       VCross(Given_Vp->Right, Given_Vp->Direction, Given_Vp->Sky);
X       VNormalize (Given_Vp->Right, Given_Vp->Right);
X       VCross (Given_Vp->Up, Given_Vp->Right, Given_Vp->Direction);
X       VScale (Given_Vp->Direction, Given_Vp->Direction, Direction_Length);
X       if (Handedness >= 0.0) {
X          VScale (Given_Vp->Right, Given_Vp->Right, Right_Length);
X          }
X       else {
X          VScale (Given_Vp->Right, Given_Vp->Right, -Right_Length);
X          }
X
X       VScale (Given_Vp->Up, Given_Vp->Up, Up_Length);       
X    END_CASE
X
X    CASE (TRANSLATE_TOKEN)
X       Parse_Vector (&Local_Vector);
X       Translate ((OBJECT *) Given_Vp, &Local_Vector);
X    END_CASE
X
X    CASE (ROTATE_TOKEN)
X       Parse_Vector (&Local_Vector);
X       Rotate ((OBJECT *) Given_Vp, &Local_Vector);
X    END_CASE
X
X    CASE (SCALE_TOKEN)
X       Parse_Vector (&Local_Vector);
X       Scale ((OBJECT *) Given_Vp, &Local_Vector);
X    END_CASE
X
X    CASE (END_VIEW_POINT_TOKEN)
X      EXIT
X    END_CASE
X
X    OTHERWISE
X      Parse_Error (END_VIEW_POINT_TOKEN);
X    END_CASE
X  END_EXPECT
X  }
X
Xvoid Parse_Declare ()
X  {
X  CONSTANT Constant_Id;
X
X  struct Constant_Struct *Constant_Ptr;
X
X  GET (IDENTIFIER_TOKEN);
X  if ((Constant_Id = Find_Constant()) == -1)
X    if (++Number_Of_Constants >= MAX_CONSTANTS)
X      Error ("Too many constants");
X    else
X      Constant_Id = Number_Of_Constants;
X
X  Constant_Ptr = &(Constants[(int)Constant_Id]);
X  GET (EQUALS_TOKEN);
X
X  EXPECT
X    CASE (OBJECT_TOKEN)
X      Constant_Ptr -> Identifier_Number = Token.Identifier_Number;
X      Constant_Ptr -> Constant_Data = (char *) Parse_Object();
X      Constant_Ptr -> Constant_Type = OBJECT_CONSTANT;
X      EXIT
X    END_CASE
X
X    CASE (SPHERE_TOKEN)
X      Constant_Ptr -> Identifier_Number = Token.Identifier_Number;
X      Constant_Ptr -> Constant_Data = (char *) Parse_Sphere ();
X      Constant_Ptr -> Constant_Type = SPHERE_CONSTANT;
X      EXIT
X    END_CASE
X
X    CASE (PLANE_TOKEN)
X      Constant_Ptr -> Identifier_Number = Token.Identifier_Number;
X      Constant_Ptr -> Constant_Data = (char *) Parse_Plane ();
X      Constant_Ptr -> Constant_Type = PLANE_CONSTANT;
X      EXIT
X    END_CASE
X
X    CASE (TRIANGLE_TOKEN)
X      Constant_Ptr -> Identifier_Number = Token.Identifier_Number;
X      Constant_Ptr -> Constant_Data = (char *) Parse_Triangle ();
X      Constant_Ptr -> Constant_Type = TRIANGLE_CONSTANT;
X      EXIT
X    END_CASE
X
X    CASE (SMOOTH_TRIANGLE_TOKEN)
X      Constant_Ptr -> Identifier_Number = Token.Identifier_Number;
X      Constant_Ptr -> Constant_Data = (char *) Parse_Smooth_Triangle ();
X      Constant_Ptr -> Constant_Type = SMOOTH_TRIANGLE_CONSTANT;
X      EXIT
X    END_CASE
X
X    CASE (QUADRIC_TOKEN)
X      Constant_Ptr -> Identifier_Number = Token.Identifier_Number;
X      Constant_Ptr -> Constant_Data = (char *) Parse_Quadric ();
X      Constant_Ptr -> Constant_Type = QUADRIC_CONSTANT;
X      EXIT
X    END_CASE
X
X    CASE (INTERSECTION_TOKEN)
X      Constant_Ptr -> Identifier_Number = Token.Identifier_Number;
X      Constant_Ptr -> Constant_Data = (char *) Parse_CSG(CSG_INTERSECTION_TYPE, NULL);
X      Constant_Ptr -> Constant_Type = CSG_INTERSECTION_CONSTANT;
X      EXIT
X    END_CASE
X
X    CASE (UNION_TOKEN)
X      Constant_Ptr -> Identifier_Number = Token.Identifier_Number;
X      Constant_Ptr -> Constant_Data = (char *) Parse_CSG(CSG_UNION_TYPE, NULL);
X      Constant_Ptr -> Constant_Type = CSG_UNION_CONSTANT;
X      EXIT
X    END_CASE
X
X    CASE (DIFFERENCE_TOKEN)
X      Constant_Ptr -> Identifier_Number = Token.Identifier_Number;
X      Constant_Ptr -> Constant_Data = (char *) Parse_CSG(CSG_DIFFERENCE_TYPE, NULL);
X      Constant_Ptr -> Constant_Type = CSG_DIFFERENCE_CONSTANT;
X      EXIT
X    END_CASE
X
X    CASE (COMPOSITE_TOKEN)
X      Constant_Ptr -> Identifier_Number = Token.Identifier_Number;
X      Constant_Ptr -> Constant_Data = (char *) Parse_Composite();
X      Constant_Ptr -> Constant_Type = COMPOSITE_CONSTANT;
X      EXIT
X    END_CASE
X
X    CASE (TEXTURE_TOKEN)
X      Constant_Ptr -> Identifier_Number = Token.Identifier_Number;
X      Constant_Ptr -> Constant_Data = (char *) Parse_Texture(Default_Texture);
X      Constant_Ptr -> Constant_Type = TEXTURE_CONSTANT;
X      EXIT
X    END_CASE
X
X    CASE (VIEW_POINT_TOKEN)
X      Constant_Ptr -> Identifier_Number = Token.Identifier_Number;
X      Constant_Ptr -> Constant_Data = (char *) Get_Viewpoint();
X      Constant_Ptr -> Constant_Type = VIEW_POINT_CONSTANT;
X      Parse_Viewpoint((VIEWPOINT *) Constant_Ptr -> Constant_Data);
X      EXIT
X    END_CASE
X
X    CASE2 (COLOR_TOKEN, COLOUR_TOKEN)
X      Constant_Ptr -> Identifier_Number = Token.Identifier_Number;
X      Constant_Ptr -> Constant_Data = (char *) Get_Colour();
X      Constant_Ptr -> Constant_Type = COLOUR_CONSTANT;
X      Parse_Colour ((COLOUR *) Constant_Ptr -> Constant_Data);
X      EXIT
X    END_CASE
X
X    CASE (LEFT_ANGLE_TOKEN)
X      UNGET
X      Constant_Ptr -> Identifier_Number = Token.Identifier_Number;
X      Constant_Ptr -> Constant_Data = (char *) Get_Vector();
X      Constant_Ptr -> Constant_Type = VECTOR_CONSTANT;
X      Parse_Vector((VECTOR *) Constant_Ptr -> Constant_Data);
X      EXIT
X    END_CASE
X
X    CASE3 (DASH_TOKEN, PLUS_TOKEN, FLOAT_TOKEN)
X      UNGET
X      Constant_Ptr -> Identifier_Number = Token.Identifier_Number;
X      Constant_Ptr -> Constant_Data = (char *) Get_Float();
X      Constant_Ptr -> Constant_Type = FLOAT_CONSTANT;
X      *(Constant_Ptr -> Constant_Data) = Parse_Float();
X      EXIT
X    END_CASE
X
X    OTHERWISE
X      Parse_Error (OBJECT_TOKEN);
X    END_CASE
X  END_EXPECT
X  }
X
Xvoid Init_Viewpoint (vp)
X  VIEWPOINT *vp;
X  {
X  vp -> Methods = (void *) &Viewpoint_Methods;
X  vp -> Type = VIEWPOINT_TYPE;
X  Make_Vector (&vp->Location, 0.0, 0.0, 0.0);
X  Make_Vector (&vp->Direction, 0.0, 0.0, 1.0);
X  Make_Vector (&vp->Up, 0.0, 1.0, 0.0);
X  Make_Vector (&vp->Right, 1.0, 0.0, 0.0);
X  Make_Vector (&vp->Sky, 0.0, 1.0, 0.0);
X  }
X
Xvoid Link (New_Object, Field, Old_Object_List)
X  OBJECT *New_Object, **Field, **Old_Object_List;
X  {
X  *Field = *Old_Object_List;
X  *Old_Object_List = New_Object;
X  }
X
XCONSTANT Find_Constant()
X  {
X  register int i;
X
X  for (i = 1 ; i <= Number_Of_Constants ; i++)
X    if (Constants [i].Identifier_Number == Token.Identifier_Number)
X      return (i);
X
X  return (-1);
X  }
X
X
Xchar *Get_Token_String (Token_Id)
X  TOKEN Token_Id;
X  {
X  register int i;
X
X  for (i = 0 ; i < LAST_TOKEN ; i++)
X     if (Reserved_Words[i].Token_Number == Token_Id)
X        return (Reserved_Words[i].Token_Name);
X  return ("");
X  }
X
Xvoid Parse_Error (Token_Id)
X  TOKEN Token_Id;
X  {
X  char *expected, *found;
X
X  fprintf (stderr, "Error in file %s line %d\n", Current_File_Name,
X                                                 Token.Token_Line_No);
X  expected = Get_Token_String (Token_Id);
X  found = Get_Token_String (Token.Token_Id);
X  fprintf (stderr, "%s expected but %s found instead\n", expected, found);
X  exit(0);
X  }
X
Xvoid Type_Error ()
X  {
X  fprintf (stderr, "Error in file %s line %d\n", Current_File_Name,
X                                                 Token.Token_Line_No);
X  fprintf (stderr, "Identifier %s is the wrong type\n",
X            &Token.Token_String[0]);
X  exit (0);
X  }
X
Xvoid Undeclared ()
X  {
X  fprintf (stderr, "Error in file %s line %d\n", Current_File_Name,
X                                                 Token.Token_Line_No);
X  fprintf (stderr, "Undeclared identifier %s\n", &Token.Token_String[0]);
X  exit (0);
X  }
X
Xvoid Error (str)
X  char *str;
X  {
X  fprintf (stderr, "Error in file %s line %d\n", Current_File_Name,
X                                                 Token.Token_Line_No);
X  fputs (str, stderr);
X  exit (0);
X  }
X
END_OF_FILE
if test 63678 -ne `wc -c <'src/parse.c'`; then
    echo shar: \"'src/parse.c'\" unpacked with wrong size!
fi
# end of 'src/parse.c'
fi
echo shar: End of archive 9 \(of 10\).
cp /dev/null ark9isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 10 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
-- 
Mail submissions (sources or binaries) to <amiga@uunet.uu.net>.
Mail comments to the moderator at <amiga-request@uunet.uu.net>.
Post requests for sources, and general discussion to comp.sys.amiga.