[comp.sources.bugs] Official patch #5 for rayshade v3.0; please apply

craig@weedeater.math.yale.edu (Craig Kolb) (04/13/90)

System: rayshade version 3.0
Patch #: 5
Priority: HIGH
Subject: Patch #5

Description:

	Rayshade assumed that a freed pointer could be safely
	dereferenced up until the next call to malloc().  It
	is now assumed that free() is destructive.

	Pointers were being freed twice in several places.

	The test for edge-on intersection with planar primitives
	was not particularly robust.  In particular, near edge-on
	intersections with textured planes caused TLOSS errors under
	certain circumstances.

	HUGE was too huge for some machines.  FAR_AWAY is used instead.

	The matrices to transform cylinders and cones to their canonical
	forms were applied as if they were user-specified.  This caused
	cylinders and cones to be always textured in "canonical"
	space.  The matrices are now stored and applied locally to the
	cylinder/cone routines.

	Simplified cone and cylinder intersection routines by making
	canonical primitives truly canonical.

	It was possible to divide by zero when rendering cones.

	The validity of colormap entires was not checked.

	times() is (void) on some SYSV systems and (long) on others.
	Removed checking of its return value altogether.

	Various pieces of lint removed throughout the code.

	Replaced outdated code in primitive tutorial.


Fix:	From rn, say "| patch -p -N -d DIR", where DIR is your top-level
	rayshade source directory.  Outside of rn, say
	"cd DIR; patch -p -N <thisarticle".
	If you don't have the patch program, apply the following by hand,
	or get patch (version 2.0, latest patchlevel).

	After patching:
		make depend
		make
		make install

	If patch indicates that patchlevel is the wrong version, you may need
	to apply one or more previous patches, or the patch may already
	have been applied.  See the patchlevel.h file to find out what has or
	has not been applied.  In any event, don't continue with the patch.

	If you are missing previous patches they can be obtained via anonymous
	ftp from weedeater.math.yale.edu (130.132.23.17).

	Craig Kolb
	kolb@yale.edu


Index: src/patchlevel.h
Prereq: 4
1c1
< #define PATCHLEVEL 4
---
> #define PATCHLEVEL 5

Index: Changes
*** Changes.old	Tue Apr 10 16:50:08 1990
--- Changes	Tue Apr 10 16:50:09 1990
***************
*** 1,3 ****
--- 1,15 ----
+ Patch #5:
+ ---------
+ Changes to reflect that free() may be destructive.
+ Fixed several other free()-related bugs.
+ Cylinders and cones were always textured in canonical cylinder/cone space.
+ Fixed divide by zero bug in cylinder code.
+ Optimizations in cylinder and cone code.
+ HUGE in bounds.c was too huge for some machines.  Replaced by FAR_AWAY.
+ Improved handling of near edge-on intersection with triangles and planes.
+ Added check for invalid colormap entries.
+ Lint removal.
+ 
  Patch #4:
  ---------
  Added gloss texture.

Index: src/bounds.c
*** src/bounds.c.old	Tue Apr 10 16:47:54 1990
--- src/bounds.c	Tue Apr 10 16:47:54 1990
***************
*** 18,26 ****
   * name of the person performing the modification, the date of modification,
   * and the reason for such modification.
   *
!  * $Id: bounds.c,v 3.0 89/10/27 02:05:46 craig Exp $
   *
   * $Log:	bounds.c,v $
   * Revision 3.0  89/10/27  02:05:46  craig
   * Baseline for first official release.
   * 
--- 18,29 ----
   * name of the person performing the modification, the date of modification,
   * and the reason for such modification.
   *
!  * $Id: bounds.c,v 3.0.1.1 90/04/04 19:03:47 craig Exp $
   *
   * $Log:	bounds.c,v $
+  * Revision 3.0.1.1  90/04/04  19:03:47  craig
+  * patch5: Substituded FAR_AWAY for HUGE in bounds initialization routines.
+  * 
   * Revision 3.0  89/10/27  02:05:46  craig
   * Baseline for first official release.
   * 
***************
*** 31,40 ****
  #include "typedefs.h"
  #include "funcdefs.h"
  
- #ifndef HUGE
- #define HUGE	1.701411e38
- #endif
- 
  /*
   * Ray-bounding box intersection test.
   */
--- 34,39 ----
***************
*** 188,195 ****
  init_bounds(bounds)
  double bounds[2][3];
  {
! 	bounds[LOW][X] = bounds[LOW][Y] = bounds[LOW][Z] = HUGE;
! 	bounds[HIGH][X] = bounds[HIGH][Y] = bounds[HIGH][Z] = -HUGE;
  }
  
  /*
--- 187,194 ----
  init_bounds(bounds)
  double bounds[2][3];
  {
! 	bounds[LOW][X] = bounds[LOW][Y] = bounds[LOW][Z] = FAR_AWAY;
! 	bounds[HIGH][X] = bounds[HIGH][Y] = bounds[HIGH][Z] = -FAR_AWAY;
  }
  
  /*

Index: src/cone.c
*** src/cone.c.old	Tue Apr 10 16:47:59 1990
--- src/cone.c	Tue Apr 10 16:48:00 1990
***************
*** 18,26 ****
   * name of the person performing the modification, the date of modification,
   * and the reason for such modification.
   *
!  * $Id: cone.c,v 3.0.1.3 90/02/12 13:20:58 craig Exp $
   *
   * $Log:	cone.c,v $
   * Revision 3.0.1.3  90/02/12  13:20:58  craig
   * patch4: Changes to avoid rotation about null axis.
   * 
--- 18,33 ----
   * name of the person performing the modification, the date of modification,
   * and the reason for such modification.
   *
!  * $Id: cone.c,v 3.0.1.5 90/04/09 14:30:08 craig Exp $
   *
   * $Log:	cone.c,v $
+  * Revision 3.0.1.5  90/04/09  14:30:08  craig
+  * patch5: Transformation information now stored locally.
+  * patch5: Canonical cone now truly canonical.
+  * 
+  * Revision 3.0.1.4  90/04/04  14:51:25  craig
+  * patch5: Fixed divide by zero problem in intcone().
+  * 
   * Revision 3.0.1.3  90/02/12  13:20:58  craig
   * patch4: Changes to avoid rotation about null axis.
   * 
***************
*** 41,56 ****
  #include "constants.h"
  
  Object *
! makcone(surf, cent, ax, br, ar, trans)
  char *surf;
  Vector *cent, *ax;
  double br, ar;
- TransInfo *trans;
  {
  	Cone *cone;
  	Primitive *prim;
  	Object *newobj;
! 	double len, dtmp;
  	Vector axis, base, tmp;
  
  	prim = mallocprim();
--- 48,62 ----
  #include "constants.h"
  
  Object *
! makcone(surf, cent, ax, br, ar)
  char *surf;
  Vector *cent, *ax;
  double br, ar;
  {
  	Cone *cone;
  	Primitive *prim;
  	Object *newobj;
! 	double tantheta, lprime, tlen, len, dtmp;
  	Vector axis, base, tmp;
  
  	prim = mallocprim();
***************
*** 61,78 ****
  	prim->objpnt.p_cone = cone;
  
  	/*
! 	 * Cones are defined by a basepoint, an apex point, and
! 	 * base and apex radii.  The cone is stored as
! 	 * the origin of the cone, the change in radius per
! 	 * unit distance from the origin of the cone, the maximum z-value
! 	 * of the cone, and "start_pos",
! 	 * the distance along the axis from the cone origin where
! 	 * the first endcap appears (where the passed "basepoint"
! 	 * appears).
  	 *
! 	 * The intcone() routine intersects a ray with a cone aligned
! 	 * along the Z axis.  Thus, we must define a transformation
! 	 * matrix which will transform an axis-aligned cone to the desired.
  	 */
  
  	/*
--- 67,78 ----
  	prim->objpnt.p_cone = cone;
  
  	/*
! 	 * To render a cone, we transform the desired cone into
! 	 * a canonical, Z-axis aligned, unit length, unit radius
! 	 * at the apex cone.
  	 *
! 	 * Here, we construct the transformation matrix to map
! 	 * from cone<-->world space.
  	 */
  
  	/*
***************
*** 93,99 ****
  		 * If the base and apex radii are equal, then we
  		 * can treat the cone as a cylinder.
  		 */
! 		return makcyl(surf, cent, ax, br, trans);
  	}
  	/*
  	 * Find the axis and axis length.
--- 93,99 ----
  		 * If the base and apex radii are equal, then we
  		 * can treat the cone as a cylinder.
  		 */
! 		return makcyl(surf, cent, ax, br);
  	}
  	/*
  	 * Find the axis and axis length.
***************
*** 107,135 ****
  		free((char *)newobj);
  		return (Object *)0;
  	}
- 	cone->apex_rad = ar;
  	/*
  	 * "tantheta" is the change in radius per unit length along
  	 * the cone axis.
  	 */
! 	cone->tantheta = (ar - br) / len;
  	/*
! 	 * Start pos defines the point along the axis where the first
  	 * endcap should be placed.
  	 */
! 	cone->start_pos = br / cone->tantheta;
  	/*
  	 * Find the true base (origin) of the cone.
  	 */
! 	scalar_prod(-cone->start_pos, axis, &base);
  	vecadd(base, *cent, &base);
  	/*
! 	 * The apex endcap is placed cone->len units from the cone
! 	 * origin.
  	 */
! 	cone->end_pos = cone->start_pos + len;
  	/*
! 	 * Calculate rotation matrix to map from world space to cone space.
  	 */
  	if (abs(axis.z) == 1.) {
  		tmp.x = 1;
--- 107,138 ----
  		free((char *)newobj);
  		return (Object *)0;
  	}
  	/*
  	 * "tantheta" is the change in radius per unit length along
  	 * the cone axis.
  	 */
! 	tantheta = (ar - br) / len;
  	/*
! 	 * lprime defines the distance along the axis where the first
  	 * endcap should be placed.
  	 */
! 	lprime = br / tantheta;
  	/*
  	 * Find the true base (origin) of the cone.
  	 */
! 	scalar_prod(-lprime, axis, &base);
  	vecadd(base, *cent, &base);
  	/*
! 	 * tlen is the total length of the cone.
! 	 */
! 	tlen = lprime + len;
! 	/*
! 	 * start_dist is the distance from the origin of the canonical
! 	 * cone at which the first endcap appears.
  	 */
! 	cone->start_dist = lprime / tlen;
  	/*
! 	 * Calculate transformation to map from cone space to world space.
  	 */
  	if (abs(axis.z) == 1.) {
  		tmp.x = 1;
***************
*** 139,147 ****
  		tmp.y = -axis.x;
  		tmp.z = 0.;
  	}
! 	RS_rotate(trans, &tmp, acos(axis.z));
! 	RS_translate(trans, &base);
! 	cone->tantheta *= cone->tantheta;
  
  	return newobj;
  }
--- 142,152 ----
  		tmp.y = -axis.x;
  		tmp.z = 0.;
  	}
! 	init_trans(&cone->trans.obj2world);
! 	RS_scale(&cone->trans.obj2world, ar, ar, tlen);
! 	RS_rotate(&cone->trans.obj2world, &tmp, acos(axis.z));
! 	RS_translate(&cone->trans.obj2world, &base);
! 	invert_trans(&cone->trans.world2obj, &cone->trans.obj2world);
  
  	return newobj;
  }
***************
*** 156,162 ****
  Primitive       *obj;
  {
  	double t1, t2, a, b, c, disc, zpos, et1, et2;
! 	double x, y;
  	extern unsigned long primtests[];
  	Cone *cone;
  
--- 161,170 ----
  Primitive       *obj;
  {
  	double t1, t2, a, b, c, disc, zpos, et1, et2;
! 	double x, y, distfact;
! 	Ray newray;
! 	Vector nray, npos;
! 	extern double TransformRay();
  	extern unsigned long primtests[];
  	Cone *cone;
  
***************
*** 164,183 ****
  	cone = obj->objpnt.p_cone;
  
  	/*
! 	 * Recall that 'tantheta' is really tantheta^2.
  	 */
! 	a = ray->x * ray->x + ray->y * ray->y - ray->z*ray->z*cone->tantheta;
! 	b = ray->x * pos->x + ray->y * pos->y - cone->tantheta*ray->z*pos->z;
! 	c = pos->x*pos->x + pos->y*pos->y - cone->tantheta*pos->z*pos->z;
  
  	if (equal(a, 0.)) {
  		/*
  		 * Only one intersection point...
  		 */
  		t1 = -c / b;
! 		zpos = pos->z + t1 * ray->z;
! 		if (t1 < EPSILON || zpos < cone->start_pos ||
! 		    zpos > cone->end_pos)
  			t1 = FAR_AWAY;
  		t2 = FAR_AWAY;
  	} else {
--- 172,196 ----
  	cone = obj->objpnt.p_cone;
  
  	/*
! 	 * Transform ray from world to cone space.
  	 */
! 	newray.pos = *pos;
! 	newray.dir = *ray;
! 	distfact = TransformRay(&newray, &cone->trans.world2obj);
! 	nray = newray.dir;
! 	npos = newray.pos;
  
+ 	a = nray.x * nray.x + nray.y * nray.y - nray.z*nray.z;
+ 	b = nray.x * npos.x + nray.y * npos.y - nray.z*npos.z;
+ 	c = npos.x*npos.x + npos.y*npos.y - npos.z*npos.z;
+ 
  	if (equal(a, 0.)) {
  		/*
  		 * Only one intersection point...
  		 */
  		t1 = -c / b;
! 		zpos = npos.z + t1 * nray.z;
! 		if (t1 < EPSILON || zpos < cone->start_dist || zpos > 1.)
  			t1 = FAR_AWAY;
  		t2 = FAR_AWAY;
  	} else {
***************
*** 190,220 ****
  		/*
  		 * Clip intersection points.
  		 */
! 		zpos = pos->z + t1 * ray->z;
! 		if (t1 < EPSILON || zpos < cone->start_pos ||
! 		    zpos > cone->end_pos)
  			t1 = FAR_AWAY;
! 		zpos = pos->z + t2 * ray->z;
! 		if (t2 < EPSILON || zpos < cone->start_pos ||
! 		    zpos > cone->end_pos)
  			t2 = FAR_AWAY;
  	}
  	/*
  	 * Find t for both endcaps.
  	 */
! 	et1 = (cone->start_pos - pos->z) / ray->z;
! 	x = pos->x + et1 * ray->x;
! 	y = pos->y + et1 * ray->y;
! 	if (x*x + y*y > cone->start_pos*cone->start_pos*cone->tantheta)
  		et1 = FAR_AWAY;
! 	et2 = (cone->end_pos - pos->z) / ray->z;
! 	x = pos->x + et2 * ray->x;
! 	y = pos->y + et2 * ray->y;
! 	if (x*x + y*y > cone->end_pos*cone->end_pos*cone->tantheta)
  		et2 = FAR_AWAY;
  
  	t1 = min(t1, min(t2, min(et1, et2)));
! 	return (t1 == FAR_AWAY ? 0. : t1);
  }
  
  /*
--- 203,237 ----
  		/*
  		 * Clip intersection points.
  		 */
! 		zpos = npos.z + t1 * nray.z;
! 		if (t1 < EPSILON || zpos < cone->start_dist || zpos > 1.)
  			t1 = FAR_AWAY;
! 		zpos = npos.z + t2 * nray.z;
! 		if (t2 < EPSILON || zpos < cone->start_dist || zpos > 1.)
  			t2 = FAR_AWAY;
  	}
+ 
+ 	if (equal(nray.z, 0.)) {
+ 		t1 = min(t1, t2);
+ 		return (t1 == FAR_AWAY ? 0. : t1 / distfact);
+ 	}
+ 
  	/*
  	 * Find t for both endcaps.
  	 */
! 	et1 = (cone->start_dist - npos.z) / nray.z;
! 	x = npos.x + et1 * nray.x;
! 	y = npos.y + et1 * nray.y;
! 	if (x*x + y*y > cone->start_dist*cone->start_dist)
  		et1 = FAR_AWAY;
! 	et2 = (1. - npos.z) / nray.z;
! 	x = npos.x + et2 * nray.x;
! 	y = npos.y + et2 * nray.y;
! 	if (x*x + y*y > 1.)
  		et2 = FAR_AWAY;
  
  	t1 = min(t1, min(t2, min(et1, et2)));
! 	return (t1 == FAR_AWAY ? 0. : t1 / distfact);
  }
  
  /*
***************
*** 225,237 ****
  Primitive *obj;
  {
  	Cone *cone;
  
  	cone = obj->objpnt.p_cone;
  
! 	if (equal(pos->z, cone->start_pos)) {
  		nrm->x = nrm->y = 0.;
  		nrm->z = -1.;
! 	} else if (equal(pos->z, cone->end_pos)) {
  		nrm->x = nrm->y = 0.;
  		nrm->z = 1.;
  	} else {
--- 242,261 ----
  Primitive *obj;
  {
  	Cone *cone;
+ 	Vector npos;
  
  	cone = obj->objpnt.p_cone;
  
! 	/*
! 	 * Transform intersection point to cone space.
! 	 */
! 	npos = *pos;
! 	transform_point(&npos, &cone->trans.world2obj);
! 	
! 	if (equal(npos.z, cone->start_dist)) {
  		nrm->x = nrm->y = 0.;
  		nrm->z = -1.;
! 	} else if (equal(npos.z, 1)) {
  		nrm->x = nrm->y = 0.;
  		nrm->z = 1.;
  	} else {
***************
*** 239,248 ****
  		 * The following is equal to
  		 * (pos X (0, 0, 1)) X pos
  		 */
! 		nrm->x = pos->x * pos->z;
! 		nrm->y = pos->y * pos->z;
! 		nrm->z = -pos->x * pos->x - pos->y * pos->y;
  	}
  }
  
  /*
--- 263,276 ----
  		 * The following is equal to
  		 * (pos X (0, 0, 1)) X pos
  		 */
! 		nrm->x = npos.x * npos.z;
! 		nrm->y = npos.y * npos.z;
! 		nrm->z = -npos.x * npos.x - npos.y * npos.y;
  	}
+ 	/*
+ 	 * Transform normal back to world space.
+ 	 */
+ 	TransformNormal(nrm, &cone->trans.world2obj);
  }
  
  /*
***************
*** 256,263 ****
  
  	cone = o->objpnt.p_cone;
  
! 	bounds[LOW][X] = bounds[LOW][Y] = -cone->apex_rad;
! 	bounds[HIGH][X] = bounds[HIGH][Y] = cone->apex_rad;
! 	bounds[LOW][Z] = cone->start_pos;
! 	bounds[HIGH][Z] = cone->end_pos;
  }
--- 284,295 ----
  
  	cone = o->objpnt.p_cone;
  
! 	bounds[LOW][X] = bounds[LOW][Y] = -1;
! 	bounds[HIGH][X] = bounds[HIGH][Y] = 1;
! 	bounds[LOW][Z] = cone->start_dist;
! 	bounds[HIGH][Z] = 1;
! 	/*
! 	 * Transform bounding box to world space.
! 	 */
! 	transform_bounds(&cone->trans.obj2world, bounds);
  }

Index: src/cylinder.c
*** src/cylinder.c.old	Tue Apr 10 16:48:04 1990
--- src/cylinder.c	Tue Apr 10 16:48:05 1990
***************
*** 18,26 ****
   * name of the person performing the modification, the date of modification,
   * and the reason for such modification.
   *
!  * $Id: cylinder.c,v 3.0.1.4 90/03/07 22:43:04 craig Exp $
   *
   * $Log:	cylinder.c,v $
   * Revision 3.0.1.4  90/03/07  22:43:04  craig
   * patch4: Fixed typo in previous fix.
   * 
--- 18,30 ----
   * name of the person performing the modification, the date of modification,
   * and the reason for such modification.
   *
!  * $Id: cylinder.c,v 3.0.1.5 90/04/09 14:29:43 craig Exp $
   *
   * $Log:	cylinder.c,v $
+  * Revision 3.0.1.5  90/04/09  14:29:43  craig
+  * patch5: Transformation information now stored locally.
+  * patch5: Canonical cylinder now truly canonical.
+  * 
   * Revision 3.0.1.4  90/03/07  22:43:04  craig
   * patch4: Fixed typo in previous fix.
   * 
***************
*** 44,54 ****
  #include "constants.h"
  
  Object *
! makcyl(surf, cent, ax, r, trans)
  char *surf;
  Vector *cent, *ax;
  double r;
- TransInfo *trans;
  {
  	Cylinder *cyl;
  	Primitive *prim;
--- 48,57 ----
  #include "constants.h"
  
  Object *
! makcyl(surf, cent, ax, r)
  char *surf;
  Vector *cent, *ax;
  double r;
  {
  	Cylinder *cyl;
  	Primitive *prim;
***************
*** 80,89 ****
  		return (Object *)0;
  	}
  
- 	cyl->rad = r*r;
- 	cyl->len = len;
  	/*
! 	 * Define matrix to transform from axis-aligned to desired cylinder.
  	 */
  	if (abs(axis.z) == 1.) {
  		dir.x = 1.;
--- 83,91 ----
  		return (Object *)0;
  	}
  
  	/*
! 	 * Define matrix to transform from Z axis aligned unit cylinder
! 	 * to desired cylinder.
  	 */
  	if (abs(axis.z) == 1.) {
  		dir.x = 1.;
***************
*** 93,101 ****
  		dir.y = -axis.x;
  		dir.z = 0.;
  	}
! 	RS_rotate(trans, &dir, acos(axis.z));
! 	RS_translate(trans, cent);
! 
  	return newobj;
  }
  
--- 95,105 ----
  		dir.y = -axis.x;
  		dir.z = 0.;
  	}
! 	init_trans(&cyl->trans.obj2world);
! 	RS_scale(&cyl->trans.obj2world, r, r, len);
! 	RS_rotate(&cyl->trans.obj2world, &dir, acos(axis.z));
! 	RS_translate(&cyl->trans.obj2world, cent);
! 	invert_trans(&cyl->trans.world2obj, &cyl->trans.obj2world);
  	return newobj;
  }
  
***************
*** 108,131 ****
  Primitive       *obj;
  {
  	double t1, t2, a, b, c, zpos1, zpos2, et1, et2, x, y, disc;
  	extern unsigned long primtests[];
  	Cylinder *cyl;
  
  	primtests[CYL]++;
  	cyl = obj->objpnt.p_cylinder;
  
! 	a = ray->x * ray->x + ray->y * ray->y;
! 	c = pos->x*pos->x + pos->y*pos->y - cyl->rad;
  
! 	if (a < EPSILON*EPSILON) {	/* |ray->z| == 1. */
  		if(c < EPSILON*EPSILON)	/* Within endcap */
  			/* Wrong if origin is inside cylinder. */
! 			return min(-pos->z / ray->z,
! 				  (cyl->len - pos->z) / ray->z);
  		return 0.;
  	}
  
! 	b = ray->x * pos->x + ray->y * pos->y;
  	disc = b*b - a*c;
  	if(disc < 0.)
  		return 0.;
--- 112,148 ----
  Primitive       *obj;
  {
  	double t1, t2, a, b, c, zpos1, zpos2, et1, et2, x, y, disc;
+ 	double distfact;
  	extern unsigned long primtests[];
+ 	extern double TransformRay();
+ 	Ray newray;
+ 	Vector nray, npos;
  	Cylinder *cyl;
  
  	primtests[CYL]++;
  	cyl = obj->objpnt.p_cylinder;
  
! 	/*
! 	 * Transform ray into canonical cylinder space.
! 	 */
! 	newray.dir = *ray;
! 	newray.pos = *pos;
! 	distfact = TransformRay(&newray, &cyl->trans.world2obj);
! 	nray = newray.dir;
! 	npos = newray.pos;
! 
! 	a = nray.x * nray.x + nray.y * nray.y;
! 	c = npos.x*npos.x + npos.y*npos.y - 1;
  
! 	if (a < EPSILON*EPSILON) {	/* |nray.z| == 1. */
  		if(c < EPSILON*EPSILON)	/* Within endcap */
  			/* Wrong if origin is inside cylinder. */
! 			return min(-npos.z / nray.z,
! 				  (1. - npos.z) / nray.z) / distfact;
  		return 0.;
  	}
  
! 	b = nray.x * npos.x + nray.y * npos.y;
  	disc = b*b - a*c;
  	if(disc < 0.)
  		return 0.;
***************
*** 134,142 ****
  	t2 = (-b - disc) / a;
  	if(t1 < EPSILON && t2 < EPSILON)
  		return 0.;
! 	zpos1 = pos->z + t1 * ray->z;
! 	zpos2 = pos->z + t2 * ray->z;
! 	if ((zpos1 > cyl->len && zpos2 > cyl->len) ||
  	    (zpos1 < 0. && zpos2 < 0.))
  		return 0.;
  	if (t1 < EPSILON)
--- 151,159 ----
  	t2 = (-b - disc) / a;
  	if(t1 < EPSILON && t2 < EPSILON)
  		return 0.;
! 	zpos1 = npos.z + t1 * nray.z;
! 	zpos2 = npos.z + t2 * nray.z;
! 	if ((zpos1 > 1 && zpos2 > 1) ||
  	    (zpos1 < 0. && zpos2 < 0.))
  		return 0.;
  	if (t1 < EPSILON)
***************
*** 143,176 ****
  		t1 = FAR_AWAY;
  	if (t2 < EPSILON)
  		t2 = FAR_AWAY;
- 	if (t1 == FAR_AWAY && t2 == FAR_AWAY)
- 		return 0.;
  	/*
  	 * Don't bother checking endcaps if both intersection points
  	 * are on the cylinder.
  	 */
! 	if ((zpos1 > 0. && zpos1 < cyl->len && zpos2 > 0. && zpos2 < cyl->len))
! 		return min(t1, t2);
  	/*
   	 * It's possible to get rid of the ray-disc intersection tests
  	 * (by looking at t1, t2 and zpos1, zpos), but the code gets messy.
  	 */
! 	if (zpos1 < 0. || zpos1 > cyl->len)
  		t1 = FAR_AWAY;
! 	if (zpos2 < 0. || zpos2 > cyl->len)
  		t2 = FAR_AWAY;
! 	et1 = -pos->z / ray->z;
! 	x = pos->x + et1 * ray->x;
! 	y = pos->y + et1 * ray->y;
! 	if (x*x + y*y > cyl->rad)
  		et1 = FAR_AWAY;
! 	et2 = (cyl->len - pos->z) / ray->z;
! 	x = pos->x + et2 * ray->x;
! 	y = pos->y + et2 * ray->y;
! 	if (x*x + y*y > cyl->rad)
  		et2 = FAR_AWAY;
  	t1 = min(t1, min(t2, min(et1, et2)));
! 	return (t1 == FAR_AWAY ? 0. : t1);
  }
  
  nrmcyl(pos, obj, nrm)
--- 160,191 ----
  		t1 = FAR_AWAY;
  	if (t2 < EPSILON)
  		t2 = FAR_AWAY;
  	/*
  	 * Don't bother checking endcaps if both intersection points
  	 * are on the cylinder.
  	 */
! 	if ((zpos1 > 0. && zpos1 < 1. && zpos2 > 0. && zpos2 < 1.))
! 		return min(t1, t2) / distfact;
  	/*
   	 * It's possible to get rid of the ray-disc intersection tests
  	 * (by looking at t1, t2 and zpos1, zpos), but the code gets messy.
  	 */
! 	if (zpos1 < 0. || zpos1 > 1.)
  		t1 = FAR_AWAY;
! 	if (zpos2 < 0. || zpos2 > 1.)
  		t2 = FAR_AWAY;
! 	et1 = -npos.z / nray.z;
! 	x = npos.x + et1 * nray.x;
! 	y = npos.y + et1 * nray.y;
! 	if (x*x + y*y > 1.)
  		et1 = FAR_AWAY;
! 	et2 = (1. - npos.z) / nray.z;
! 	x = npos.x + et2 * nray.x;
! 	y = npos.y + et2 * nray.y;
! 	if (x*x + y*y > 1.)
  		et2 = FAR_AWAY;
  	t1 = min(t1, min(t2, min(et1, et2)));
! 	return (t1 == FAR_AWAY ? 0. : t1 / distfact);
  }
  
  nrmcyl(pos, obj, nrm)
***************
*** 178,190 ****
  Primitive *obj;
  {
  	Cylinder *cyl;
  	double dist;
  
  	cyl = obj->objpnt.p_cylinder;
  
! 	dist = pos->x*pos->x + pos->y*pos->y;
! 	if (dist+EPSILON < cyl->rad) {
! 		if (equal(pos->z,0.)) {
  			/*
  			 * Hit on lower endcap.
  			 */
--- 193,212 ----
  Primitive *obj;
  {
  	Cylinder *cyl;
+ 	Vector npos;
  	double dist;
  
  	cyl = obj->objpnt.p_cylinder;
  
! 	/*
! 	 * Transform position into cylinder space.
! 	 */
! 	npos = *pos;
! 	transform_point(&npos, &cyl->trans.world2obj);
! 
! 	dist = npos.x*npos.x + npos.y*npos.y;
! 	if (dist+EPSILON < 1) {
! 		if (equal(npos.z,0.)) {
  			/*
  			 * Hit on lower endcap.
  			 */
***************
*** 198,208 ****
  			nrm->z = 1.;
  		}
  	} else {	/* Hit along cylinder. */
! 		nrm->x = pos->x;
! 		nrm->y = pos->y;
  		nrm->z = 0.;
  		/* Will be normalized by ShadeRay(). */
  	}
  }
  
  cylextent(o, bounds)
--- 220,235 ----
  			nrm->z = 1.;
  		}
  	} else {	/* Hit along cylinder. */
! 		nrm->x = npos.x;
! 		nrm->y = npos.y;
  		nrm->z = 0.;
  		/* Will be normalized by ShadeRay(). */
  	}
+ 
+ 	/*
+ 	 * Tranform normal back to world space.
+ 	 */
+ 	TransformNormal(nrm, &cyl->trans.world2obj);
  }
  
  cylextent(o, bounds)
***************
*** 210,221 ****
  double bounds[2][3];
  {
  	Cylinder *cyl;
! 	double r;
  	cyl = o->objpnt.p_cylinder;
  
! 	r = sqrt(cyl->rad);
! 	bounds[LOW][X] = bounds[LOW][Y] = -r;
! 	bounds[HIGH][X] = bounds[HIGH][Y] = r;
  	bounds[LOW][Z] = 0.;
! 	bounds[HIGH][Z] = cyl->len;
  }
--- 237,251 ----
  double bounds[2][3];
  {
  	Cylinder *cyl;
! 
  	cyl = o->objpnt.p_cylinder;
  
! 	bounds[LOW][X] = bounds[LOW][Y] = -1;
! 	bounds[HIGH][X] = bounds[HIGH][Y] = 1;
  	bounds[LOW][Z] = 0.;
! 	bounds[HIGH][Z] = 1;
! 	/*
! 	 * Transform bounding box to world space.
! 	 */
! 	transform_bounds(&cyl->trans.obj2world, bounds);
  }

Index: src/hf.c
*** src/hf.c.old	Tue Apr 10 16:48:12 1990
--- src/hf.c	Tue Apr 10 16:48:13 1990
***************
*** 18,26 ****
   * name of the person performing the modification, the date of modification,
   * and the reason for such modification.
   *
!  * $Id: hf.c,v 3.0.1.3 90/02/12 13:30:14 craig Exp $
   *
   * $Log:	hf.c,v $
   * Revision 3.0.1.3  90/02/12  13:30:14  craig
   * patch4: Fixed bug involving computation of hf->lsize[i]
   * 
--- 18,29 ----
   * name of the person performing the modification, the date of modification,
   * and the reason for such modification.
   *
!  * $Id: hf.c,v 3.0.1.4 90/04/04 14:52:30 craig Exp $
   *
   * $Log:	hf.c,v $
+  * Revision 3.0.1.4  90/04/04  14:52:30  craig
+  * patch5: Lint removal.
+  * 
   * Revision 3.0.1.3  90/02/12  13:30:14  craig
   * patch4: Fixed bug involving computation of hf->lsize[i]
   * 
***************
*** 118,124 ****
  	/*
  	 * Get HF size.
  	 */
! 	if (fread(&hf->size, sizeof(int), 1, fp) == 0)
  		yyerror("Cannot read height field size.");
  
  	hf->data = (float **)share_malloc(hf->size * sizeof(float *));
--- 121,127 ----
  	/*
  	 * Get HF size.
  	 */
! 	if (fread((char *)&hf->size, sizeof(int), 1, fp) == 0)
  		yyerror("Cannot read height field size.");
  
  	hf->data = (float **)share_malloc(hf->size * sizeof(float *));
***************
*** 127,133 ****
  		/*
  		 * Read in row of HF data.
  		 */
! 		if (fread(hf->data[i],sizeof(float),hf->size,fp) != hf->size)
  			yyerror("Not enough heightfield data.");
  		for (j = 0; j < hf->size; j++) {
  			val = hf->data[i][j];
--- 130,136 ----
  		/*
  		 * Read in row of HF data.
  		 */
! 		if (fread((char *)hf->data[i],sizeof(float),hf->size,fp) != hf->size)
  			yyerror("Not enough heightfield data.");
  		for (j = 0; j < hf->size; j++) {
  			val = hf->data[i][j];
***************
*** 145,151 ****
  				hf->minz = val;
  		}
  	}
! 	fclose(fp);
  	/*
  	 * Allocate levels of grid.  hf->levels = log base BestSize of hf->size
  	 */
--- 148,154 ----
  				hf->minz = val;
  		}
  	}
! 	(void)fclose(fp);
  	/*
  	 * Allocate levels of grid.  hf->levels = log base BestSize of hf->size
  	 */
***************
*** 154,160 ****
  			;
  	hf->levels++;
  	hf->qsize = CACHESIZE;
! 	hf->q = (hfTri **)Calloc(hf->qsize, sizeof(hfTri *));
  	hf->qtail = 0;
  
  	hf->lsize = (int *)share_malloc(hf->levels * sizeof(int));
--- 157,163 ----
  			;
  	hf->levels++;
  	hf->qsize = CACHESIZE;
! 	hf->q = (hfTri **)Calloc((unsigned)hf->qsize, sizeof(hfTri *));
  	hf->qtail = 0;
  
  	hf->lsize = (int *)share_malloc(hf->levels * sizeof(int));
***************
*** 563,568 ****
--- 566,572 ----
  /*
   * Compute normal to height field.
   */
+ /*ARGSUSED*/
  nrmhf(pos, prim, nrm)
  Vector *pos, *nrm;
  Primitive *prim;

Index: src/input_yacc.y
*** src/input_yacc.y.old	Tue Apr 10 16:48:20 1990
--- src/input_yacc.y	Tue Apr 10 16:48:23 1990
***************
*** 17,23 ****
  /* name of the person performing the modification, the date of modification,*/
  /* and the reason for such modification.				    */
  /*									    */
! /* $Id: input_yacc.y,v 3.0.1.8 90/03/07 21:26:42 craig Exp $ */
  %{
  #include <stdio.h>
  #include "constants.h"
--- 17,23 ----
  /* name of the person performing the modification, the date of modification,*/
  /* and the reason for such modification.				    */
  /*									    */
! /* $Id: input_yacc.y,v 3.0.1.9 90/04/04 18:58:50 craig Exp $ */
  %{
  #include <stdio.h>
  #include "constants.h"
***************
*** 196,203 ****
  		{
  			CurObj->data->texture = CurText;
  			CurText = (Texture *)0;
  			free((char *)CurObj);
! 			CurObj = CurObj->next;
  		}
  		;
  Objectdef	: Startdef Objdefs tENDDEF
--- 196,204 ----
  		{
  			CurObj->data->texture = CurText;
  			CurText = (Texture *)0;
+ 			ListTmp = CurObj->next;
  			free((char *)CurObj);
! 			CurObj = ListTmp;
  		}
  		;
  Objectdef	: Startdef Objdefs tENDDEF

Index: src/main.c
*** src/main.c.old	Tue Apr 10 16:48:29 1990
--- src/main.c	Tue Apr 10 16:48:30 1990
***************
*** 1,5 ****
  char rcsid[] =
! 	"$Id: main.c,v 3.0.1.3 90/03/07 21:33:09 craig Exp $";
  /*
   * main.c
   *
--- 1,5 ----
  char rcsid[] =
! 	"$Id: main.c,v 3.0.1.4 90/04/04 14:50:44 craig Exp $";
  /*
   * main.c
   *
***************
*** 21,26 ****
--- 21,29 ----
   * and the reason for such modification.
   *
   * $Log:	main.c,v $
+  * Revision 3.0.1.4  90/04/04  14:50:44  craig
+  * patch5: Removed check of return value of times().
+  * 
   * Revision 3.0.1.3  90/03/07  21:33:09  craig
   * patch4: Return value of times() is now checked.
   * patch4: Workers is externed iff LINDA is defined.
***************
*** 179,188 ****
  double *usertime, *systime;
  {
  	struct tms time;
- 	long times();
  
! 	if (times(&time) < 0)
! 		RSwarning("Cannot get cpu time?!\n");
  	*usertime = (double)time.tms_utime / (double)HZ;
  	*systime = (double)time.tms_stime / (double)HZ;
  }
--- 182,189 ----
  double *usertime, *systime;
  {
  	struct tms time;
  
! 	(void)times(&time);
  	*usertime = (double)time.tms_utime / (double)HZ;
  	*systime = (double)time.tms_stime / (double)HZ;
  }

Index: src/memory.c
*** src/memory.c.old	Tue Apr 10 16:48:33 1990
--- src/memory.c	Tue Apr 10 16:48:33 1990
***************
*** 18,26 ****
   * name of the person performing the modification, the date of modification,
   * and the reason for such modification.
   *
!  * $Id: memory.c,v 3.0.1.1 89/12/06 16:33:59 craig Exp $
   *
   * $Log:	memory.c,v $
   * Revision 3.0.1.1  89/12/06  16:33:59  craig
   * patch2: Added calls to new error/warning routines.
   * 
--- 18,29 ----
   * name of the person performing the modification, the date of modification,
   * and the reason for such modification.
   *
!  * $Id: memory.c,v 3.0.1.2 90/04/04 18:56:08 craig Exp $
   *
   * $Log:	memory.c,v $
+  * Revision 3.0.1.2  90/04/04  18:56:08  craig
+  * patch5: Lint removal.
+  * 
   * Revision 3.0.1.1  89/12/06  16:33:59  craig
   * patch2: Added calls to new error/warning routines.
   * 
***************
*** 29,34 ****
--- 32,40 ----
   * 
   */
  #include <stdio.h>
+ #ifdef SYSV
+ #include <memory.h>
+ #endif
  #include "typedefs.h"
  #include "funcdefs.h"
  
***************
*** 56,64 ****
  
  	res = Malloc(nelem*elen);
  #ifdef SYSV
! 	memset(res, (char)0, nelem*elen);
  #else
! 	bzero(res, nelem*elen);
  #endif
  	return res;
  }
--- 62,70 ----
  
  	res = Malloc(nelem*elen);
  #ifdef SYSV
! 	(void)memset(res, (char)0, (int)(nelem*elen));
  #else
! 	bzero(res, (int)nelem*elen);
  #endif
  	return res;
  }

Index: src/noise.c
*** src/noise.c.old	Tue Apr 10 16:48:36 1990
--- src/noise.c	Tue Apr 10 16:48:36 1990
***************
*** 18,26 ****
   * name of the person performing the modification, the date of modification,
   * and the reason for such modification.
   *
!  * $Id: noise.c,v 3.0 89/10/27 02:05:57 craig Exp $
   *
   * $Log:	noise.c,v $
   * Revision 3.0  89/10/27  02:05:57  craig
   * Baseline for first official release.
   * 
--- 18,29 ----
   * name of the person performing the modification, the date of modification,
   * and the reason for such modification.
   *
!  * $Id: noise.c,v 3.0.1.1 90/04/04 18:59:22 craig Exp $
   *
   * $Log:	noise.c,v $
+  * Revision 3.0.1.1  90/04/04  18:59:22  craig
+  * patch5: Lint removal.
+  * 
   * Revision 3.0  89/10/27  02:05:57  craig
   * Baseline for first official release.
   * 
***************
*** 100,106 ****
  	(void)srandom(0);
  #endif
  
! 	hashTable = (short int *) malloc(4096*sizeof(short int));
  	for (i = 0; i < 4096; i++)
  		hashTable[i] = i;
  	for (i = 4095; i > 0; i--) {
--- 103,109 ----
  	(void)srandom(0);
  #endif
  
! 	hashTable = (short *) Malloc(4096*sizeof(short int));
  	for (i = 0; i < 4096; i++)
  		hashTable[i] = i;
  	for (i = 4095; i > 0; i--) {

Index: src/outputp.c
*** src/outputp.c.old	Tue Apr 10 16:48:40 1990
--- src/outputp.c	Tue Apr 10 16:48:40 1990
***************
*** 18,26 ****
   * name of the person performing the modification, the date of modification,
   * and the reason for such modification.
   *
!  * $Id: outputp.c,v 3.0.1.2 90/02/12 16:09:05 craig Exp $
   *
   * $Log:	outputp.c,v $
   * Revision 3.0.1.2  90/02/12  16:09:05  craig
   * patch4: Fixed bug with duplicate headers in mtv files when Appending.
   * 
--- 18,29 ----
   * name of the person performing the modification, the date of modification,
   * and the reason for such modification.
   *
!  * $Id: outputp.c,v 3.0.1.3 90/04/04 14:53:04 craig Exp $
   *
   * $Log:	outputp.c,v $
+  * Revision 3.0.1.3  90/04/04  14:53:04  craig
+  * patch5: Lint removal.
+  * 
   * Revision 3.0.1.2  90/02/12  16:09:05  craig
   * patch4: Fixed bug with duplicate headers in mtv files when Appending.
   * 
***************
*** 101,107 ****
  	buffer[1]=(unsigned char *)Malloc(sizeof(unsigned char)*(unsigned)Xres);
  	buffer[2]=(unsigned char *)Malloc(sizeof(unsigned char)*(unsigned)Xres);
  	if (Appending)
! 		fseek(imgfile, 0L, 2);		/* Go to end of file */
  }
  
  
--- 104,110 ----
  	buffer[1]=(unsigned char *)Malloc(sizeof(unsigned char)*(unsigned)Xres);
  	buffer[2]=(unsigned char *)Malloc(sizeof(unsigned char)*(unsigned)Xres);
  	if (Appending)
! 		(void)fseek(imgfile, 0L, 2);	/* Go to end of file */
  }
  
  
***************
*** 134,140 ****
  endpic()
  {
  	sv_puteof(&sv_globals);
! 	fclose(imgfile);
  }
  
  #else /* NORLE */
--- 137,143 ----
  endpic()
  {
  	sv_puteof(&sv_globals);
! 	(void)fclose(imgfile);
  }
  
  #else /* NORLE */
***************
*** 166,174 ****
  	extern int Xres;
  
  	for (i = 0; i < Xres; i++) {
! 		fputc(correct(255.*buf[i].r), imgfile);
! 		fputc(correct(255.*buf[i].g), imgfile);
! 		fputc(correct(255.*buf[i].b), imgfile);
  	}
  	fflush(imgfile);
  }
--- 169,177 ----
  	extern int Xres;
  
  	for (i = 0; i < Xres; i++) {
! 		(void)fputc(correct(255.*buf[i].r), imgfile);
! 		(void)fputc(correct(255.*buf[i].g), imgfile);
! 		(void)fputc(correct(255.*buf[i].b), imgfile);
  	}
  	fflush(imgfile);
  }
***************
*** 175,181 ****
  
  endpic()
  {
! 	fclose(imgfile);
  }
  #endif /* NORLE */
  
--- 178,184 ----
  
  endpic()
  {
! 	(void)fclose(imgfile);
  }
  #endif /* NORLE */
  

Index: src/plane.c
*** src/plane.c.old	Tue Apr 10 16:48:43 1990
--- src/plane.c	Tue Apr 10 16:48:44 1990
***************
*** 18,26 ****
   * name of the person performing the modification, the date of modification,
   * and the reason for such modification.
   *
!  * $Id: plane.c,v 3.0.1.1 89/12/06 16:34:03 craig Exp $
   *
   * $Log:	plane.c,v $
   * Revision 3.0.1.1  89/12/06  16:34:03  craig
   * patch2: Added calls to new error/warning routines.
   * 
--- 18,29 ----
   * name of the person performing the modification, the date of modification,
   * and the reason for such modification.
   *
!  * $Id: plane.c,v 3.0.1.2 90/04/04 19:02:42 craig Exp $
   *
   * $Log:	plane.c,v $
+  * Revision 3.0.1.2  90/04/04  19:02:42  craig
+  * patch5: Test for edge-on intersection more robust.
+  * 
   * Revision 3.0.1.1  89/12/06  16:34:03  craig
   * patch2: Added calls to new error/warning routines.
   * 
***************
*** 77,83 ****
  	plane = obj->objpnt.p_plane;
  
  	denom = dotp(&plane->norm, ray);
! 	if (denom == 0.)
  		return 0.;
  	dist = (plane->d - dotp(&plane->norm, pos)) / denom;
  	return (dist > FAR_AWAY ? 0. : dist);
--- 80,86 ----
  	plane = obj->objpnt.p_plane;
  
  	denom = dotp(&plane->norm, ray);
! 	if (equal(denom, 0.))
  		return 0.;
  	dist = (plane->d - dotp(&plane->norm, pos)) / denom;
  	return (dist > FAR_AWAY ? 0. : dist);

Index: src/poly.c
*** src/poly.c.old	Tue Apr 10 16:48:47 1990
--- src/poly.c	Tue Apr 10 16:48:47 1990
***************
*** 18,26 ****
   * name of the person performing the modification, the date of modification,
   * and the reason for such modification.
   *
!  * $Id: poly.c,v 3.0.1.1 89/12/06 16:33:38 craig Exp $
   *
   * $Log:	poly.c,v $
   * Revision 3.0.1.1  89/12/06  16:33:38  craig
   * patch2: Added calls to new error/warning routines.
   * 
--- 18,29 ----
   * name of the person performing the modification, the date of modification,
   * and the reason for such modification.
   *
!  * $Id: poly.c,v 3.0.1.2 90/04/04 19:01:19 craig Exp $
   *
   * $Log:	poly.c,v $
+  * Revision 3.0.1.2  90/04/04  19:01:19  craig
+  * patch5: Corrected free()-related problems.
+  * 
   * Revision 3.0.1.1  89/12/06  16:33:38  craig
   * patch2: Added calls to new error/warning routines.
   * 
***************
*** 49,55 ****
  	Object *newobj;
  	double indexval;
  	Vector edge1, edge2, anorm;
! 	PointList *cur;
  	int i;
  	extern int TrashBadPoly;
  
--- 52,58 ----
  	Object *newobj;
  	double indexval;
  	Vector edge1, edge2, anorm;
! 	PointList *cur, *pltmp;
  	int i;
  	extern int TrashBadPoly;
  
***************
*** 71,81 ****
  	 * to worry about doing so.
  	 */
  	i = npoints -1;
! 	for(cur = plist;cur;cur = cur->next) {
  		poly->points[i--] = cur->vec;
  		free((char *)cur);
  	}
- 	free((char *)plist);
  
  	/*
  	 * Find normal to polygon.  Check all edges before giving
--- 74,84 ----
  	 * to worry about doing so.
  	 */
  	i = npoints -1;
! 	for(cur = plist; cur != (PointList *)0; cur = pltmp) {
  		poly->points[i--] = cur->vec;
+ 		pltmp = cur->next;
  		free((char *)cur);
  	}
  
  	/*
  	 * Find normal to polygon.  Check all edges before giving

Index: src/primobj.h
*** src/primobj.h.old	Tue Apr 10 16:48:50 1990
--- src/primobj.h	Tue Apr 10 16:48:50 1990
***************
*** 18,26 ****
   * name of the person performing the modification, the date of modification,
   * and the reason for such modification.
   *
!  * $Id: primobj.h,v 3.0 89/10/27 02:06:00 craig Exp $
   *
   * $Log:	primobj.h,v $
   * Revision 3.0  89/10/27  02:06:00  craig
   * Baseline for first official release.
   * 
--- 18,29 ----
   * name of the person performing the modification, the date of modification,
   * and the reason for such modification.
   *
!  * $Id: primobj.h,v 3.0.1.1 90/04/09 13:39:59 craig Exp $
   *
   * $Log:	primobj.h,v $
+  * Revision 3.0.1.1  90/04/09  13:39:59  craig
+  * patch5: New Cylinder and Cone types.
+  * 
   * Revision 3.0  89/10/27  02:06:00  craig
   * Baseline for first official release.
   * 
***************
*** 30,41 ****
   * Cylinder
   */
  typedef struct cylinder	{
! 	double rad, len;		/* Radius and length. */
  } Cylinder;
  
  typedef struct cone {
! 	double start_pos, end_pos, apex_rad;	/* End cap Z positions */
! 	double tantheta;			/* "slope" */
  } Cone;
  
  /*
--- 33,44 ----
   * Cylinder
   */
  typedef struct cylinder	{
! 	Trans trans;
  } Cylinder;
  
  typedef struct cone {
! 	double start_dist;
! 	Trans trans;
  } Cone;
  
  /*

Index: src/setup.c
*** src/setup.c.old	Tue Apr 10 16:48:55 1990
--- src/setup.c	Tue Apr 10 16:48:56 1990
***************
*** 18,26 ****
   * name of the person performing the modification, the date of modification,
   * and the reason for such modification.
   *
!  * $Id: setup.c,v 3.0.1.2 90/02/12 13:26:49 craig Exp $
   *
   * $Log:	setup.c,v $
   * Revision 3.0.1.2  90/02/12  13:26:49  craig
   * patch4: Added calls to new error/warning routines.
   * patch4: Attempting to render empty scene now results in an error message.
--- 18,29 ----
   * name of the person performing the modification, the date of modification,
   * and the reason for such modification.
   *
!  * $Id: setup.c,v 3.0.1.3 90/04/04 19:00:19 craig Exp $
   *
   * $Log:	setup.c,v $
+  * Revision 3.0.1.3  90/04/04  19:00:19  craig
+  * patch5: Lint removal.
+  * 
   * Revision 3.0.1.2  90/02/12  13:26:49  craig
   * patch4: Added calls to new error/warning routines.
   * patch4: Attempting to render empty scene now results in an error message.
***************
*** 178,184 ****
  	 * transformation.
  	 */
  	for (i = 0; i < nlight; i++) {
! 		light[i].cache = (Primitive **)Calloc(maxlevel+1,
  					sizeof(Primitive *));
  		light[i].trans = (TransInfo *)Malloc((maxlevel+1)*
  					sizeof(TransInfo));
--- 181,187 ----
  	 * transformation.
  	 */
  	for (i = 0; i < nlight; i++) {
! 		light[i].cache = (Primitive **)Calloc((unsigned)maxlevel+1,
  					sizeof(Primitive *));
  		light[i].trans = (TransInfo *)Malloc((maxlevel+1)*
  					sizeof(TransInfo));

Index: src/shade.c
*** src/shade.c.old	Tue Apr 10 16:49:00 1990
--- src/shade.c	Tue Apr 10 16:49:02 1990
***************
*** 18,26 ****
   * name of the person performing the modification, the date of modification,
   * and the reason for such modification.
   *
!  * $Id: shade.c,v 3.0.1.2 90/03/07 21:31:21 craig Exp $
   *
   * $Log:	shade.c,v $
   * Revision 3.0.1.2  90/03/07  21:31:21  craig
   * patch4: Replaced call to LightCoordSys() with call to VectCoordSys().
   * 
--- 18,29 ----
   * name of the person performing the modification, the date of modification,
   * and the reason for such modification.
   *
!  * $Id: shade.c,v 3.0.1.3 90/04/04 19:04:19 craig Exp $
   *
   * $Log:	shade.c,v $
+  * Revision 3.0.1.3  90/04/04  19:04:19  craig
+  * patch5: Corrected free()-related problems.
+  * 
   * Revision 3.0.1.2  90/03/07  21:31:21  craig
   * patch4: Replaced call to LightCoordSys() with call to VectCoordSys().
   * 
***************
*** 180,186 ****
  				 * of two refracting surfaces. Skip it.
  				 */
  				return;
- 			free((char *)NewRay.media);
  			NewRay.media = NewRay.media->next;
  			if (refract(&NewRay.dir, surf->kref,
  			    NewRay.media ? NewRay.media->surf->kref :
--- 183,188 ----

Index: src/texture.c
*** src/texture.c.old	Tue Apr 10 16:49:06 1990
--- src/texture.c	Tue Apr 10 16:49:08 1990
***************
*** 18,26 ****
   * name of the person performing the modification, the date of modification,
   * and the reason for such modification.
   *
!  * $Id: texture.c,v 3.0.1.3 90/03/07 21:30:22 craig Exp $
   *
   * $Log:	texture.c,v $
   * Revision 3.0.1.3  90/03/07  21:30:22  craig
   * patch4: Fixed thresholding bug in fBmText().
   * patch4: Colormap is now set to NULL in new_texture().
--- 18,29 ----
   * name of the person performing the modification, the date of modification,
   * and the reason for such modification.
   *
!  * $Id: texture.c,v 3.0.1.4 90/04/04 17:22:39 craig Exp $
   *
   * $Log:	texture.c,v $
+  * Revision 3.0.1.4  90/04/04  17:22:39  craig
+  * patch5: Added checking for invalid colormap entries.
+  * 
   * Revision 3.0.1.3  90/03/07  21:30:22  craig
   * patch4: Fixed thresholding bug in fBmText().
   * patch4: Colormap is now set to NULL in new_texture().
***************
*** 114,119 ****
--- 117,123 ----
  	return text;
  }
  
+ /*ARGSUSED*/
  WoodText(text, pos, norm, surf)
  Texture *text;
  Vector *pos, *norm;
***************
*** 120,126 ****
  Surface *surf;
  {
  	double red, grn, blu;
! 	double chaos, midBrown, brownLayer, greenLayer;
  	double perturb, brownPerturb, greenPerturb, grnPerturb;
  	double t;
  
--- 124,130 ----
  Surface *surf;
  {
  	double red, grn, blu;
! 	double chaos, brownLayer, greenLayer;
  	double perturb, brownPerturb, greenPerturb, grnPerturb;
  	double t;
  
***************
*** 265,270 ****
--- 269,275 ----
  /*
   * Apply "blotch" texture.
   */
+ /*ARGSUSED*/
  BlotchText(text, pos, norm, surf)
  Texture *text;
  Vector *pos, *norm;
***************
*** 282,287 ****
--- 287,293 ----
  	}
  }
  
+ /*ARGSUSED*/
  fBmText(text, pos, norm, surf)
  Texture *text;
  Vector *pos, *norm;
***************
*** 314,319 ****
--- 320,326 ----
  /*
   * Apply a "checker" texture.
   */
+ /*ARGSUSED*/
  CheckerText(text, pos, norm, surf)
  Texture *text;
  Vector *pos, *norm;
***************
*** 330,335 ****
--- 337,343 ----
  	/* else surface stays the same. */
  }
  
+ /*ARGSUSED*/
  fBmBumpText(text, pos, norm, surf)
  Texture *text;
  Vector *pos, *norm;
***************
*** 348,353 ****
--- 356,362 ----
  /*
   * Apply a "bump" texture.
   */
+ /*ARGSUSED*/
  BumpText(text, pos, norm, surf)
  Texture *text;
  Vector *pos, *norm;
***************
*** 362,367 ****
--- 371,377 ----
  	(void)normalize(norm);
  }
  
+ /*ARGSUSED*/
  MarbleText(text, pos, norm, surf)
  Texture *text;
  Vector *pos, *norm;
***************
*** 385,390 ****
--- 395,401 ----
  	}
  }
  
+ /*ARGSUSED*/
  GlossText(text, pos, norm, surf)
  Texture *text;
  Vector *pos, *norm;
***************
*** 420,426 ****
  	FILE *fp;
  	Color *map;
  	char buf[BUFSIZ];
! 	int i;
  
  	fp = fopen(filename, "r");
  	if (fp == (FILE *)NULL)
--- 431,437 ----
  	FILE *fp;
  	Color *map;
  	char buf[BUFSIZ];
! 	int i, num;
  
  	fp = fopen(filename, "r");
  	if (fp == (FILE *)NULL)
***************
*** 429,436 ****
  	map = (Color *)Calloc(256, sizeof(Color));
  
  	for (i = 0; fgets(buf,BUFSIZ,fp) != NULL && i < 256; i++) {
! 		sscanf(buf,"%lf %lf %lf",&map[i].r, &map[i].g, &map[i].b);
  		ScaleColor(1. / 255., map[i], &map[i]);
  	}
  	return map;
  }
--- 440,452 ----
  	map = (Color *)Calloc(256, sizeof(Color));
  
  	for (i = 0; fgets(buf,BUFSIZ,fp) != NULL && i < 256; i++) {
! 		num = sscanf(buf,"%lf %lf %lf",&map[i].r, &map[i].g, &map[i].b);
! 		if (num != 3) {
! 			RSerror("%s, line %d:  Bad color specification.\n",
! 				filename, i+1);
! 		}
  		ScaleColor(1. / 255., map[i], &map[i]);
  	}
+ 	(void)fclose(fp);
  	return map;
  }

Index: src/triangle.c
*** src/triangle.c.old	Tue Apr 10 16:49:11 1990
--- src/triangle.c	Tue Apr 10 16:49:13 1990
***************
*** 18,26 ****
   * name of the person performing the modification, the date of modification,
   * and the reason for such modification.
   *
!  * $Id: triangle.c,v 3.0.1.1 89/12/06 16:33:32 craig Exp $
   *
   * $Log:	triangle.c,v $
   * Revision 3.0.1.1  89/12/06  16:33:32  craig
   * patch2: Added calls to new error/warning routines.
   * 
--- 18,30 ----
   * name of the person performing the modification, the date of modification,
   * and the reason for such modification.
   *
!  * $Id: triangle.c,v 3.0.1.2 90/04/04 18:55:45 craig Exp $
   *
   * $Log:	triangle.c,v $
+  * Revision 3.0.1.2  90/04/04  18:55:45  craig
+  * patch5: Test for edge-on intersection is more robust.
+  * patch5: Lint removal.
+  * 
   * Revision 3.0.1.1  89/12/06  16:33:32  craig
   * patch2: Added calls to new error/warning routines.
   * 
***************
*** 146,152 ****
  	 * Plane intersection.
  	 */
  	k = dotp(&triangle->nrm, ray);
! 	if (k == 0.)
  		return 0.;
  	s = (triangle->d - dotp(&triangle->nrm, pos)) / k;
  	if (s <= 0.)
--- 150,156 ----
  	 * Plane intersection.
  	 */
  	k = dotp(&triangle->nrm, ray);
! 	if (equal(k, 0.))
  		return 0.;
  	s = (triangle->d - dotp(&triangle->nrm, pos)) / k;
  	if (s <= 0.)
***************
*** 211,216 ****
--- 215,221 ----
  	return s;
  }
  
+ /*ARGSUSED*/
  nrmtri(pos, obj, nrm)
  Vector           *pos, *nrm;
  Primitive       *obj;

Index: src/viewing.c
*** src/viewing.c.old	Tue Apr 10 16:49:17 1990
--- src/viewing.c	Tue Apr 10 16:49:17 1990
***************
*** 18,26 ****
   * name of the person performing the modification, the date of modification,
   * and the reason for such modification.
   *
!  * $Id: viewing.c,v 3.0.1.3 89/12/02 14:38:37 craig Exp $
   *
   * $Log:	viewing.c,v $
   * Revision 3.0.1.3  89/12/02  14:38:37  craig
   * patch2: Added depth of field code, courtesy of Rodney G. Bogart.
   * 
--- 18,29 ----
   * name of the person performing the modification, the date of modification,
   * and the reason for such modification.
   *
!  * $Id: viewing.c,v 3.0.1.4 90/04/04 18:59:54 craig Exp $
   *
   * $Log:	viewing.c,v $
+  * Revision 3.0.1.4  90/04/04  18:59:54  craig
+  * patch5: Lint removal.
+  * 
   * Revision 3.0.1.3  89/12/02  14:38:37  craig
   * patch2: Added depth of field code, courtesy of Rodney G. Bogart.
   * 
***************
*** 126,132 ****
  	vecadd(aperture_inc, eyep, &(ray->pos));
  	scalar_prod(focaldist, ray->dir, &(ray->dir));
  	vecsub(ray->dir, aperture_inc, &(ray->dir));
! 	normalize(&ray->dir);
  }
  
  /*
--- 129,135 ----
  	vecadd(aperture_inc, eyep, &(ray->pos));
  	scalar_prod(focaldist, ray->dir, &(ray->dir));
  	vecsub(ray->dir, aperture_inc, &(ray->dir));
! 	(void)normalize(&ray->dir);
  }
  
  /*

Index: src/voxels.c
*** src/voxels.c.old	Tue Apr 10 16:49:21 1990
--- src/voxels.c	Tue Apr 10 16:49:21 1990
***************
*** 18,26 ****
   * name of the person performing the modification, the date of modification,
   * and the reason for such modification.
   *
!  * $Id: voxels.c,v 3.0.1.2 90/02/12 13:19:50 craig Exp $
   *
   * $Log:	voxels.c,v $
   * Revision 3.0.1.2  90/02/12  13:19:50  craig
   * patch4: Added reporting of total number of primitives.
   * 
--- 18,29 ----
   * name of the person performing the modification, the date of modification,
   * and the reason for such modification.
   *
!  * $Id: voxels.c,v 3.0.1.3 90/04/04 19:05:23 craig Exp $
   *
   * $Log:	voxels.c,v $
+  * Revision 3.0.1.3  90/04/04  19:05:23  craig
+  * patch5: Changes to reflect that free() may be destructive.
+  * 
   * Revision 3.0.1.2  90/02/12  13:19:50  craig
   * patch4: Added reporting of total number of primitives.
   * 
***************
*** 152,158 ****
  {
  	Grid *grid;
  	Object *otmp;
! 	ObjList *ltmp;
  	int x, y, i;
  	extern ObjList *find_bounds();
  
--- 155,161 ----
  {
  	Grid *grid;
  	Object *otmp;
! 	ObjList *ltmp, *nltmp;
  	int x, y, i;
  	extern ObjList *find_bounds();
  
***************
*** 190,199 ****
  	/*
  	 * obj->data now holds a linked list of bounded objects.
  	 */
! 	for(ltmp = (ObjList *)obj->data; ltmp; ltmp = ltmp->next) {
  		otmp = ltmp->data;
  		engrid(otmp, grid);
! 		free(ltmp);
  	}
  	obj->type = GRID;
  	obj->data = (char *)grid;
--- 193,203 ----
  	/*
  	 * obj->data now holds a linked list of bounded objects.
  	 */
! 	for(ltmp = (ObjList *)obj->data; ltmp != (ObjList *)0; ltmp = nltmp) {
  		otmp = ltmp->data;
  		engrid(otmp, grid);
! 		nltmp = ltmp->next;
! 		free((char *)ltmp);
  	}
  	obj->type = GRID;
  	obj->data = (char *)grid;

Index: doc/primitive.ms
*** doc/primitive.ms.old	Tue Apr 10 17:22:56 1990
--- doc/primitive.ms	Tue Apr 10 17:22:57 1990
***************
*** 3,11 ****
  .\" Brief tutorial on adding new primitives to rayshade.
  .\" Craig Kolb 10/89
  .\"
! .\" $Id: primitive.ms,v 3.0 89/10/24 18:07:30 craig Exp $
  .\"
  .\" $Log:	primitive.ms,v $
  .\" Revision 3.0  89/10/24  18:07:30  craig
  .\" Baseline for first official release.
  .\" 
--- 3,14 ----
  .\" Brief tutorial on adding new primitives to rayshade.
  .\" Craig Kolb 10/89
  .\"
! .\" $Id: primitive.ms,v 3.0.1.1 90/04/10 17:22:36 craig Exp $
  .\"
  .\" $Log:	primitive.ms,v $
+ .\" Revision 3.0.1.1  90/04/10  17:22:36  craig
+ .\" patch5: addscaledvec() no longer returns a structure...
+ .\" 
  .\" Revision 3.0  89/10/24  18:07:30  craig
  .\" Baseline for first official release.
  .\" 
***************
*** 505,511 ****
          /*
           *  Find difference between point of intersection and center of disc.
           */
!         vecsub(addscaledvec(*pos, dist, *ray), disc->center, &hit);
          /*
           * If hit point is <= disc->radius from center, we've hit the disc.
           */
--- 508,515 ----
          /*
           *  Find difference between point of intersection and center of disc.
           */
!         addscaledvec(*pos, dist, *ray, &hit);
!         vecsub(hit, disc->center, &hit);
          /*
           * If hit point is <= disc->radius from center, we've hit the disc.
           */