#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#	dms
# This archive created: Mon Aug  6 14:48:53 2007
export PATH; PATH=/bin:/usr/bin:$PATH
if test ! -d 'dms'
then
	echo shar: "creating directory 'dms'"
	mkdir 'dms'
fi
echo shar: "entering directory 'dms'"
cd 'dms'
echo shar: "extracting 'atoms.h'" '(2427 characters)'
if test -f 'atoms.h'
then
	echo shar: "will not over-write existing file 'atoms.h'"
else
sed 's/^	X//' << \SHAR_EOF > 'atoms.h'
	X/*
	X
	XCopyright (c) <2002> The Regents of the University of California.
	XAll rights reserved.
	X
	XRedistribution and use in source and binary forms, with or without
	Xmodification, are permitted provided that the following conditions
	Xare met:
	X  1. Redistributions of source code must retain the above copyright
	X     notice, this list of conditions, and the following disclaimer.
	X  2. Redistributions in binary form must reproduce the above
	X     copyright notice, this list of conditions, and the following
	X     disclaimer in the documentation and/or other materials provided
	X     with the distribution.
	X  3. Redistributions must acknowledge that this software was
	X     originally developed by the UCSF Computer Graphics Laboratory
	X     under support by the NIH National Center for Research Resources,
	X     grant P41-RR01081.
	X
	XTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
	XEXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
	XIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
	XPURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS BE LIABLE
	XFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
	XCONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
	XOF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
	XBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
	XWHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
	XOR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
	XEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
	X
	X */
	X#ifndef	__ATOM__
	X#define	__ATOM__
	X
	X#define	TREENTRANT	0
	X#define	SREENTRANT	1
	X#define	CONTACT		2
	X
	Xtypedef struct point_def	{
	X	double	coord[3];
	X}	POINT;
	X
	Xtypedef struct surface_def	{
	X	struct surface_def	*next;
	X	int			npoint;
	X	POINT			*position;
	X	POINT			*normal;
	X	double			area;
	X	int			type;
	X}	SURFACE;
	X
	X#define	AN_LEN	6
	X#define	RN_LEN	9
	X#define	RT_LEN	6
	X
	Xtypedef struct atom_def	{
	X	struct atom_def	*next;
	X	double		coord[3];
	X	char		atname[AN_LEN];
	X	char		resseq[RN_LEN];
	X	char		restype[RT_LEN];
	X	double		radius;
	X	int		wanted, resindex;
	X	SURFACE		*surface;
	X}	ATOM;
	X
	Xtypedef int	AINDEX;
	X
	Xtypedef struct neighbor_def	{
	X	int	nneighbor;
	X	AINDEX	*neighbor;
	X}	NEIGHBOR;
	X
	Xtypedef struct probe_def	{
	X	struct probe_def	*next;
	X	AINDEX			atom[3];
	X	double			coord[3];
	X	int			real;
	X}	PROBE;
	X
	X#define	ATOM_IS(ap,aname,rname)	\
	X	(strcmp((ap)->atname, aname) == 0 && strcmp((ap)->resseq, rname) == 0)
	X
	X#endif
SHAR_EOF
if test 2427 -ne "`wc -c < 'atoms.h'`"
then
	echo shar: "error transmitting 'atoms.h'" '(should have been 2427 characters)'
fi
fi
echo shar: "extracting 'compute.c'" '(30786 characters)'
if test -f 'compute.c'
then
	echo shar: "will not over-write existing file 'compute.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'compute.c'
	X/*
	X
	XCopyright (c) <2002> The Regents of the University of California.
	XAll rights reserved.
	X
	XRedistribution and use in source and binary forms, with or without
	Xmodification, are permitted provided that the following conditions
	Xare met:
	X  1. Redistributions of source code must retain the above copyright
	X     notice, this list of conditions, and the following disclaimer.
	X  2. Redistributions in binary form must reproduce the above
	X     copyright notice, this list of conditions, and the following
	X     disclaimer in the documentation and/or other materials provided
	X     with the distribution.
	X  3. Redistributions must acknowledge that this software was
	X     originally developed by the UCSF Computer Graphics Laboratory
	X     under support by the NIH National Center for Research Resources,
	X     grant P41-RR01081.
	X
	XTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
	XEXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
	XIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
	XPURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS BE LIABLE
	XFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
	XCONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
	XOF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
	XBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
	XWHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
	XOR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
	XEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
	X
	X */
	X#include <stdio.h>
	X#include <string.h>
	X#include <ctype.h>
	X#include <errno.h>
	X#include <netdb.h>
	X#include <sys/types.h>
	X#ifndef FD_SET
	X#ifndef linux
	X#include <sys/select.h>
	X#endif
	X#endif
	X#include <sys/socket.h>
	X#include <netinet/in.h>
	X#include <sys/time.h>
	X#include <sys/uio.h>
	X#include "dms_param.h"
	X#include "atoms.h"
	X#include "wanted.h"
	X#include "protocol.h"
	X
	Xextern void	*emalloc();
	X
	X#ifndef	FD_SET
	X#define	FD_SET(n, p)	((p)->fds_bits[0] |= (1 << (n)))
	X#define	FD_CLR(n, p)	((p)->fds_bits[0] &= ~(1 << (n)))
	X#define	FD_ISSET(n, p)	((p)->fds_bits[0] & (1 << n))
	X#define	FD_ZERO(p)	((p)->fds_bits[0] = 0)
	X#define	FD_ISZERO(p)	((p)->fds_bits[0] == 0)
	X#endif
	X
	X#ifndef	DEBUG
	X#define STATIC static
	X#else
	X#define	STATIC
	X#endif
	X
	X#ifndef	TRUE
	X#define	TRUE	1
	X#define	FALSE	0
	X#endif
	X
	Xtypedef struct server_def	{
	X	struct server_def	*next;
	X	char			*host;
	X	FILE			*in_fd, *out_fd;
	X	int			state;
	X	void			(*reply)();
	X	void			(*retry)();
	X	int			arg1, arg2;
	X	int			nrequest;
	X}	SERVER;
	X
	X#define	EXECUTING	0
	X#define	AVAILABLE	1
	X#define	DEAD		2
	X#define	IDLE		3
	X#define	STOPPED		4
	X
	XSTATIC NEIGHBOR	*neighbor;
	XSTATIC PROBE	*probe;
	XSTATIC SERVER	*server;
	XSTATIC ATOM	**alist;
	XSTATIC int	natom;
	X
	XSTATIC void	read_radii();
	XSTATIC void	assign_radius();
	XSTATIC void	print_astat();
	XSTATIC int	compute_comp();
	XSTATIC void	start_servers();
	XSTATIC int	try_host();
	XSTATIC void	stop_servers();
	XSTATIC SERVER	*get_server();
	XSTATIC void	wait_for_server();
	XSTATIC void	print_sstat();
	XSTATIC void	param_info();
	XSTATIC void	pi_reply();
	XSTATIC void	atom_info();
	XSTATIC void	ai_reply();
	XSTATIC void	ni_reply();
	XSTATIC void	probe_info();
	XSTATIC void	pri_reply();
	XSTATIC void	neighbors();
	XSTATIC void	c_reply();
	XSTATIC void	probes();
	XSTATIC void	p_reply();
	XSTATIC void	contact_surface();
	XSTATIC void	torus_surface();
	XSTATIC void	probe_surface();
	XSTATIC void	surface_reply();
	XSTATIC void	collapse_probes();
	XSTATIC void	cross();
	X
	Xextern char	(*resseqs)[RN_LEN];
	Xextern int	numresseq;
	X
	X/*
	X * neighbor_info:
	X *	Send neighbor information to all servers
	X */
	Xvoid neighbor_info(nlist, natom)
	XNEIGHBOR	*nlist;
	Xint		natom;
	X{
	X	register SERVER		*sp;
	X	register NEIGHBOR	*np, *endnp;
	X	register struct iovec	*ip;
	X	register int		n;
	X	struct iovec		*countv, *datav;
	X	char			buf[BUFSIZ];
	X
	X	endnp = nlist + natom;
	X	n = 0;
	X	countv = (struct iovec *) emalloc(natom * sizeof (struct iovec));
	X	for (np = nlist, ip = countv; np < endnp; np++, ip++) {
	X		ip->iov_base = (caddr_t) &np->nneighbor;
	X		ip->iov_len = sizeof (int);
	X		if (np->nneighbor > 0)
	X			n++;
	X	}
	X	if (n > 0) {
	X		datav = (struct iovec *) emalloc(n * sizeof (struct iovec));
	X		ip = datav;
	X		for (np = nlist; np < endnp; np++) {
	X			if (np->nneighbor <= 0)
	X				continue;
	X			ip->iov_base = (caddr_t) np->neighbor;
	X			ip->iov_len = np->nneighbor * sizeof (AINDEX);
	X			ip++;
	X		}
	X	}
	X	(void) sprintf(buf, NI_COMMAND, natom);
	X	for (sp = server; sp != NULL; sp = sp->next) {
	X		if (sp->state == DEAD)
	X			continue;
	X		fputs(buf, sp->out_fd);
	X		fwritev(sp->out_fd, countv, natom);
	X		if (n > 0)
	X			fwritev(sp->out_fd, datav, n);
	X		(void) fflush(sp->out_fd);
	X		sp->state = EXECUTING;
	X		sp->reply = ni_reply;
	X		sp->retry = NULL;
	X	}
	X	wait_for_server();
	X	(void) free((char *) countv);
	X	if (n > 0)
	X		(void) free((char *) datav);
	X}
	X
	X/*
	X * compute_ms:
	X *	Compute the molecular surface
	X */
	Xvoid compute_ms(aarray, nat, radius, density, want_normal, verbose)
	XATOM	**aarray;
	Xint	nat;
	Xdouble	radius, density;
	Xint	want_normal;
	Xint	verbose;
	X{
	X	register ATOM		**app, **endap;
	X	register PROBE		*pp;
	X	register int		i, j, k;
	X
	X	/*
	X	 * Store the parameters so reply() routines can get at them
	X	 */
	X	alist = aarray;
	X	natom = nat;
	X	endap = alist + natom;
	X
	X	/*
	X	 * Assign a radius for each atom
	X	 */
	X	read_radii();
	X	for (app = alist; app < endap; app++) {
	X		assign_radius(*app);
	X		(*app)->surface = NULL;
	X	}
	X	if (verbose)
	X		print_astat();
	X
	X	/*
	X	 * Sort the atoms by coordinate so we can look just at slices
	X	 * instead of all atoms when looking for neighbors
	X	 */
	X	qsort((char *) alist, natom, sizeof (ATOM *), compute_comp);
	X
	X	/*
	X	 * Start up servers on all the machines that we can reach
	X	 * and hand them the necessary parameters as well as atomic
	X	 * coordinates
	X	 */
	X	start_servers();
	X	param_info(radius, density, want_normal);
	X	atom_info(alist, natom);
	X	if (verbose)
	X		fputs("Servers initialized\n", stderr);
	X
	X	/*
	X	 * Loop through the atom list and assign selected atoms to
	X	 * available servers (this should give us a list of neighbors).
	X	 * We then pass out the neighbor information to all the compute
	X	 * servers in preparation for surface computation.
	X	 */
	X	neighbor = (NEIGHBOR *) emalloc(natom * sizeof (NEIGHBOR));
	X	for (app = alist; app < endap; app++)
	X		neighbors(app - alist);
	X	wait_for_server();
	X	neighbor_info(neighbor, natom);
	X	if (verbose)
	X		fputs("Neighbors computed\n", stderr);
	X
	X	/*
	X	 * Loop through the neighbor list and ask for probes which
	X	 * contact both neighbor simultaneously.  We then pass the
	X	 * probe information to all the compute servers as well.
	X	 */
	X	for (i = 0; i < natom; i++)
	X		for (j = 0; j < neighbor[i].nneighbor; j++)
	X			if (neighbor[i].neighbor[j] > i)
	X				probes(i, neighbor[i].neighbor[j]);
	X	wait_for_server();
	X	probe_info(probe);
	X	if (verbose)
	X		fputs("Probes computed\n", stderr);
	X
	X	/*
	X	 * Now we clean up the neighbor info and send it out again
	X	 */
	X	for (i = 0; i < natom; i++) {
	X		for (j = 0, k = 0; j < neighbor[i].nneighbor; j++)
	X			if (neighbor[i].neighbor[j] >= 0)
	X				neighbor[i].neighbor[k++] =
	X					neighbor[i].neighbor[j];
	X		neighbor[i].nneighbor = k;
	X	}
	X#ifdef RETRANS_NB
	X	neighbor_info(neighbor, natom);
	X	if (verbose)
	X		fputs("Neighbors sent\n", stderr);
	X#endif
	X
	X	/*
	X	 * Generate surface points
	X	 * First the contact, then the toroid reentrant,
	X	 * and finally spherical reentrant
	X	 */
	X	for (app = alist; app < endap; app++)
	X		if ((*app)->wanted)
	X			contact_surface(app - alist);
	X	for (i = 0; i < natom; i++)
	X		for (j = 0; j < neighbor[i].nneighbor; j++)
	X			if (neighbor[i].neighbor[j] > i) {
	X				if (!alist[i]->wanted
	X				&& !alist[neighbor[i].neighbor[j]]->wanted)
	X					continue;
	X				torus_surface(i, neighbor[i].neighbor[j]);
	X			}
	X
	X	/*
	X	 * Collapse near-coincident probes and then compute surface area
	X	 */
	X	collapse_probes();
	X	for (pp = probe, i = 0; pp != NULL; pp = pp->next, i++) {
	X		if (!alist[pp->atom[0]]->wanted
	X		&&  !alist[pp->atom[1]]->wanted
	X		&&  !alist[pp->atom[2]]->wanted)
	X			continue;
	X		if (pp->real)
	X			probe_surface(i);
	X	}
	X	wait_for_server();
	X	if (verbose)
	X		fputs("Surface computed\n", stderr);
	X
	X	/*
	X	 * Ah...we're done.  Terminate the servers and return
	X	 */
	X	if (verbose)
	X		print_sstat();
	X	stop_servers();
	X}
	X
	Xtypedef struct radius_def	{
	X	struct radius_def	*next;
	X	char			*name;
	X	char			namelen;
	X	double			radius;
	X	int			natom;
	X}	RADIUS;
	X
	Xstatic RADIUS	*radius, *def_radius;
	X
	X/*
	X * read_radii:
	X *	Get radii from radii file
	X */
	XSTATIC
	Xvoid
	Xread_radii()
	X{
	X	register RADIUS	*rp;
	X	register FILE	*fp;
	X	char		buf[BUFSIZ], name[10];
	X	double		length;
	X
	X	if ((fp = fopen(RADII_FILE, "r")) == NULL) {
	X		if ((fp = fopen(DEF_RADII_FILE, "r")) == NULL) {
	X			perror(DEF_RADII_FILE);
	X			exit(1);
	X		}
	X	}
	X	while (fgets(buf, sizeof buf, fp) != NULL) {
	X		if (buf[0] == '#')
	X			continue;
	X		if (sscanf(buf, "%s%lf", name, &length) != 2) {
	X			fputs("Syntax error in radii file\n", stderr);
	X			fputs(buf, stderr);
	X			continue;
	X		}
	X		if (strcmp(name, "default") == 0) {
	X			def_radius = (RADIUS *) emalloc(sizeof (RADIUS));
	X			def_radius->next = NULL;
	X			def_radius->name = NULL;
	X			def_radius->namelen = 0;
	X			def_radius->radius = length;
	X			def_radius->natom = 0;
	X		}
	X		else {
	X			rp = (RADIUS *) emalloc(sizeof (RADIUS));
	X			rp->next = radius;
	X			rp->namelen = strlen(name);
	X			rp->name = emalloc(rp->namelen + 1);
	X			(void) strcpy(rp->name, name);
	X			rp->radius = length;
	X			rp->natom = 0;
	X			radius = rp;
	X		}
	X	}
	X	(void) fclose(fp);
	X}
	X
	X/*
	X * assign_radius:
	X *	Assign a van der Waals radius to this atom
	X */
	XSTATIC
	Xvoid
	Xassign_radius(ap)
	XATOM	*ap;
	X{
	X	register RADIUS	*rp;
	X
	X	for (rp = radius; rp != NULL; rp = rp->next)
	X		if (strncmp(rp->name, ap->atname, rp->namelen) == 0)
	X			break;
	X	if (rp == NULL) {
	X		if (def_radius == NULL) {
	X			fprintf(stderr, "Unknown atom type %s\n", ap->atname);
	X			exit(1);
	X		}
	X		else
	X			rp = def_radius;
	X	}
	X	ap->radius = rp->radius;
	X	rp->natom++;
	X}
	X
	X/*
	X * print_astat:
	X *	Print atom type statistics
	X */
	XSTATIC
	Xvoid
	Xprint_astat()
	X{
	X	register struct radius_def	*rp;
	X
	X	for (rp = radius; rp != NULL; rp = rp->next)
	X		if (rp->natom > 0)
	X			fprintf(stderr, "\t%s\t%d\n", rp->name, rp->natom);
	X	/*
	X	 * The last entry is the default
	X	 */
	X	if (def_radius != NULL && def_radius->natom > 0)
	X		fprintf(stderr, "\t???\t%d\n", def_radius->natom);
	X}
	X
	X/*
	X * compute_comp:
	X *	Compare atoms based on coordinates
	X */
	XSTATIC
	Xint
	Xcompute_comp(a1, a2)
	XATOM	**a1, **a2;
	X{
	X	register ATOM	*t1, *t2;
	X
	X	t1 = *a1;
	X	t2 = *a2;
	X	if (t1->coord[0] < t2->coord[0])
	X		return -1;
	X	else if (t1->coord[0] > t2->coord[0])
	X		return 1;
	X	if (t1->coord[1] < t2->coord[1])
	X		return -1;
	X	else if (t1->coord[1] > t2->coord[1])
	X		return 1;
	X	if (t1->coord[2] < t2->coord[2])
	X		return -1;
	X	else if (t1->coord[2] > t2->coord[2])
	X		return 1;
	X	return 0;
	X}
	X
	X/*
	X * start_servers:
	X *	Start up servers on all available machines
	X *	For the first pass implementation, we will try to contact
	X *	known hosts only once and just use that set.  If hosts die,
	X *	they get marked as down and are no longer used.  No attempts
	X *	at retrying to connect to any host will be made.
	X */
	XSTATIC
	Xvoid
	Xstart_servers()
	X{
	X	struct servent	*servp;
	X
	X	if ((servp = getservbyname("dms", "tcp")) == NULL) {
	X		/* service entry not found, run in standalone mode */
	X		int     pid, toserver[2], fromserver[2];
	X
	X		server = (SERVER *) emalloc(sizeof (SERVER));
	X		server->nrequest = 0;
	X		server->retry = NULL;
	X		server->host = "localhost";
	X		if (pipe(toserver) < 0 || pipe(fromserver) < 0) {
	X			perror("Cannot create pipe");
	X			exit(1);
	X		}
	X		if ((pid = fork()) < 0) {
	X			perror("Cannot fork");
	X			exit(1);
	X		}
	X		if (pid == 0) {
	X			close(0);
	X			close(1);
	X			dup2(toserver[0], 0);
	X			dup2(fromserver[1], 1);
	X			close(toserver[0]);
	X			close(toserver[1]);
	X			close(fromserver[0]);
	X			close(fromserver[1]);
	X			execl(SERVER_PATH, "dmsd", NULL);
	X			perror("execl");
	X			exit(1);
	X		}
	X		server->in_fd = fdopen(fromserver[0], "r");
	X		server->out_fd = fdopen(toserver[1], "w");
	X		close(fromserver[1]);
	X		close(toserver[0]);
	X		if (server->in_fd == NULL || server->out_fd == NULL) {
	X			fprintf(stderr, "Cannot open file descriptor.\n");
	X			exit(1);
	X		}
	X		setlinebuf(server->out_fd);
	X		server->state = AVAILABLE;
	X		server->next = NULL;
	X	} else {
	X		/* service entry found, run in distributed processing mode */
	X		register SERVER	*sp;
	X		register FILE	*fp;
	X		register char	*cp;
	X		char		buf[BUFSIZ];
	X
	X		if ((fp = fopen(SERVER_FILE, "r")) == NULL) {
	X			if ((fp = fopen(DEF_SERVER_FILE, "r")) == NULL) {
	X				perror(DEF_SERVER_FILE);
	X				exit(1);
	X			}
	X		}
	X		sethostent(TRUE);
	X		while (fgets(buf, sizeof buf, fp) != NULL) {
	X			if ((cp = strchr(buf, '\n')) != NULL)
	X				*cp = '\0';
	X			sp = (SERVER *) emalloc(sizeof (SERVER));
	X			sp->host = emalloc(strlen(buf) + 1);
	X			sp->nrequest = 0;
	X			sp->retry = NULL;
	X			(void) strcpy(sp->host, buf);
	X			if (try_host(buf, sp, servp->s_port) < 0)
	X				(void) free((char *) sp);
	X			else {
	X				sp->next = server;
	X				server = sp;
	X			}
	X		}
	X		endhostent();
	X		(void) fclose(fp);
	X	}
	X}
	X
	X/*
	X * try_host:
	X *	Try to contact a host.
	X */
	XSTATIC
	Xint
	Xtry_host(host, sp, port)
	Xchar	*host;
	XSERVER	*sp;
	Xint	port;
	X{
	X	struct hostent		*hostp;
	X	struct sockaddr_in	addr;
	X	int			fd;
	X	int			newfd;
	X	extern int		errno;
	X
	X	if ((hostp = gethostbyname(host)) == NULL) {
	X		fprintf(stderr, "%s: no such host\n", host);
	X		return -1;
	X	}
	X	if ((fd = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
	X		perror("socket");
	X		return -1;
	X	}
	X	addr.sin_family = PF_INET;
	X	addr.sin_addr = *((struct in_addr *) hostp->h_addr);
	X	addr.sin_port = port;
	X	if (connect(fd, (struct sockaddr *) &addr, sizeof addr) < 0) {
	X		perror(host);
	X		if (errno != ETIMEDOUT) {
	X			(void) close(fd);
	X			return -1;
	X		}
	X		else {
	X			(void) close(fd);
	X			sp->state = DEAD;
	X			return 0;
	X		}
	X	}
	X
	X	if ((sp->in_fd = fdopen(fd, "r")) == NULL) {
	X		perror("fdopen");
	X		(void) close(fd);
	X		sp->state = DEAD;
	X		return 0;
	X	}
	X
	X#ifdef BSD
	X	newfd = fd;
	X#else
	X	newfd = dup(fd);
	X#endif
	X	if ((sp->out_fd = fdopen(newfd, "w")) == NULL) {
	X		perror("fdopen");
	X		(void) close(fd);
	X		sp->state = DEAD;
	X		return 0;
	X	}
	X
	X	sp->state = AVAILABLE;
	X	return 0;
	X}
	X
	X/*
	X * stop_servers:
	X *	Terminate all servers that are currently active
	X */
	XSTATIC
	Xvoid
	Xstop_servers()
	X{
	X	register SERVER	*sp, *nextsp;
	X
	X	for (sp = server; sp != NULL; sp = nextsp) {
	X		nextsp = sp->next;
	X		if (sp->state != DEAD) {
	X			(void) fclose(sp->in_fd);
	X			(void) fclose(sp->out_fd);
	X		}
	X		(void) free((char *) sp);
	X	}
	X}
	X
	X/*
	X * get_server:
	X *	Get an available server.  Bomb out if all servers are dead.
	X */
	XSTATIC
	XSERVER *
	Xget_server()
	X{
	X	register SERVER	*sp;
	X	register int	max_fd, any_live, n;
	X	fd_set		mask, save_mask;
	X
	X	max_fd = 0;	/* In case _file is declared unsigned */
	X	any_live = FALSE;
	X	FD_ZERO(&save_mask);
	X	n = 0;
	X
	X	/*
	X	 * If there is an available server, return it.  Otherwise,
	X	 * keep track of the list of currently executing servers
	X	 */
	X	for (sp = server; sp != NULL; sp = sp->next) {
	X		switch (sp->state) {
	X		  case AVAILABLE:
	X			sp->nrequest++;
	X			return sp;
	X		  case EXECUTING:
	X		  case STOPPED:
	X			FD_SET(fileno(sp->in_fd), &save_mask);
	X			n++;
	X			if (fileno(sp->in_fd) > max_fd)
	X				max_fd = fileno(sp->in_fd);
	X			any_live = TRUE;
	X			break;
	X		  case IDLE:
	X			any_live = TRUE;
	X			break;
	X		  case DEAD:
	X			break;
	X		}
	X	}
	X
	X	if (!any_live) {
	X		fputs("All servers died!\n", stderr);
	X		exit(1);
	X	}
	X	if (n <= 0)
	X		return NULL;
	X	max_fd++;
	X
	Xagain:
	X	mask = save_mask;
	X	/*
	X	 * Wait for a server to come back (either respond or die)
	X	 */
	X	if (select(max_fd, &mask, (fd_set *) NULL, (fd_set *) NULL,
	X	(struct timeval *) NULL) <= 0) {
	X		perror("select");
	X		exit(1);
	X	}
	X	for (sp = server; sp != NULL; sp = sp->next) {
	X		if (sp->state != EXECUTING && sp->state != STOPPED)
	X			continue;
	X		if (!FD_ISSET(fileno(sp->in_fd), &mask))
	X			continue;
	X		(*sp->reply)(sp);
	X		switch (sp->state) {
	X		  case AVAILABLE:
	X			sp->nrequest++;
	X			return sp;
	X		  case EXECUTING:
	X		  case STOPPED:
	X			break;
	X		  default:
	X			FD_CLR(fileno(sp->in_fd), &save_mask);
	X			n--;
	X			break;
	X		}
	X	}
	X	if (n <= 0) {
	X		fputs("All servers died!\n", stderr);
	X		exit(1);
	X	}
	X	goto again;
	X}
	X
	X/*
	X * wait_for_server:
	X *	Wait for all servers to become idle.
	X *	If there are servers that died while handling requests that
	X *	need to be retried, handle that as well.  Since servers normally
	X *	do not die, we are willing to take a performance penalty to handle
	X *	the special case.
	X */
	XSTATIC
	Xvoid
	Xwait_for_server()
	X{
	X	register SERVER	*sp;
	X	register int	n;
	X
	Xagain:
	X	/*
	X	 * Wait for all active servers to finish
	X	 */
	X	while ((sp = get_server()) != NULL) {
	X		sp->state = IDLE;
	X		continue;
	X	}
	X	for (sp = server; sp != NULL; sp = sp->next)
	X		if (sp->state == IDLE)
	X			sp->state = AVAILABLE;
	X
	X	/*
	X	 * Check for servers that died in action.  If they need to
	X	 * be retried, start them up and go back to the waiting stage
	X	 */
	X	n = 0;
	X	for (sp = server; sp != NULL; sp = sp->next)
	X		if (sp->state == DEAD && sp->retry != NULL) {
	X			(*sp->retry)(sp->arg1, sp->arg2);
	X			sp->retry = NULL;
	X#ifdef DEBUG
	X			fprintf(stderr, "Retrying after %s died\n", sp->host);
	X#endif
	X			n++;
	X		}
	X	if (n > 0)
	X		goto again;
	X}
	X
	X/*
	X * print_sstat:
	X *	Print server statistics
	X */
	XSTATIC
	Xvoid
	Xprint_sstat()
	X{
	X	register SERVER	*sp;
	X
	X	fputs("Server request count:\n", stderr);
	X	for (sp = server; sp != NULL; sp = sp->next)
	X		fprintf(stderr, "\t%-8s\t%d\n", sp->host, sp->nrequest);
	X}
	X
	X/*
	X * wanted:
	X *	Determine whether the given atom is in the "wanted list"
	X *	We "know" we are called with non-null arguments
	X */
	Xint
	Xwanted(ATOM *ap, WANTED *wlist)
	X{
	X	register WANTED	*wp;
	X	int		from, to, at;
	X
	X	at = ap->resindex;
	X	for (wp = wlist; wp != NULL; wp = wp->next)
	X		switch (wp->type) {
	X		  case W_RANGE:
	X			from = wp->startres;
	X			to = wp->w.endres;
	X			if (from < 0 || to < 0)
	X				continue;
	X			if (from <= at && at <= to)
	X				return TRUE;
	X			break;
	X		  case W_ANY:
	X			if (at == wp->startres)
	X				return TRUE;
	X			break;
	X		  case W_ATOM:
	X			if (at != wp->startres)
	X				continue;
	X			if (strcmp(ap->atname, wp->w.atom) == 0)
	X				return TRUE;
	X			break;
	X		}
	X	return FALSE;
	X}
	X
	X/*
	X * locres:
	X *	return the numeric index of the given resseq in the array of
	X *	all resseqs (which should be in the same order as the PDB file).
	X *	Returns -1 if not found.
	X */
	Xint
	Xlocres(seq)
	Xchar	*seq;
	X{
	X	register int	i;
	X	int		index;
	X
	X	index = -1;
	X	for (i = 0; i < numresseq; i++) {
	X		if (strcmp(resseqs[i], seq) == 0) {
	X			index = i;
	X			break;
	X		}
	X	}
	X	return index;
	X}
	X
	X/*
	X * param_info:
	X *	Pass parameter (probe radius and whether we need normals)
	X *	to servers
	X */
	XSTATIC
	Xvoid
	Xparam_info(radius, density, want_normal)
	Xdouble	radius, density;
	Xint	want_normal;
	X{
	X	register SERVER	*sp;
	X	char		buf[BUFSIZ];
	X
	X	(void) sprintf(buf, PI_COMMAND, radius, density, want_normal);
	X	for (sp = server; sp != NULL; sp = sp->next) {
	X		if (sp->state == DEAD)
	X			continue;
	X		fputs(buf, sp->out_fd);
	X		(void) fflush(sp->out_fd);
	X		sp->state = EXECUTING;
	X		sp->reply = pi_reply;
	X		sp->retry = NULL;
	X	}
	X	wait_for_server();
	X}
	X
	X/*
	X * pi_reply:
	X *	Wait for response to param info command
	X */
	XSTATIC
	Xvoid
	Xpi_reply(sp)
	XSERVER	*sp;
	X{
	X	char		buf[BUFSIZ];
	X
	X	if (fgets(buf, sizeof buf, sp->in_fd) == NULL) {
	X		fputs("server died\n", stderr);
	X		sp->state = DEAD;
	X		(void) fclose(sp->in_fd);
	X		(void) fclose(sp->out_fd);
	X		return;
	X	}
	X	if (strcmp(buf, PI_RESPONSE) != 0) {
	X		fputs("pi_reply: unexpected response from server\n", stderr);
	X		fputs(buf, stderr);
	X		sp->state = DEAD;
	X		(void) fclose(sp->in_fd);
	X		(void) fclose(sp->out_fd);
	X		return;
	X	}
	X	sp->state = AVAILABLE;
	X}
	X
	X/*
	X * atom_info:
	X *	Pass atom information out to all servers
	X */
	XSTATIC
	Xvoid
	Xatom_info(alist, natom)
	XATOM	**alist;
	Xint	natom;
	X{
	X	register SERVER	*sp;
	X	register ATOM	**app;
	X	struct iovec	*iov, *ip, *endip;
	X	char		buf[BUFSIZ];
	X
	X	iov = (struct iovec *) emalloc(natom * sizeof (struct iovec));
	X	endip = iov + natom;
	X	app = alist;
	X	for (ip = iov; ip < endip; ip++) {
	X		ip->iov_base = (caddr_t) *app++;
	X		ip->iov_len = sizeof (ATOM);
	X	}
	X	(void) sprintf(buf, AI_COMMAND, natom);
	X	for (sp = server; sp != NULL; sp = sp->next) {
	X		if (sp->state == DEAD)
	X			continue;
	X		(void) fputs(buf, sp->out_fd);
	X		fwritev(sp->out_fd, iov, natom);
	X		(void) fflush(sp->out_fd);
	X		sp->state = EXECUTING;
	X		sp->reply = ai_reply;
	X		sp->retry = NULL;
	X	}
	X	wait_for_server();
	X	(void) free((char *) iov);
	X}
	X
	X/*
	X * ai_reply:
	X *	Read a reply from a server that just received atom info
	X */
	XSTATIC
	Xvoid
	Xai_reply(sp)
	XSERVER	*sp;
	X{
	X	char		buf[BUFSIZ];
	X
	X	if (fgets(buf, sizeof buf, sp->in_fd) == NULL) {
	X		fputs("ai_reply: server died\n", stderr);
	X		goto bad;
	X	}
	X	if (strcmp(buf, AI_RESPONSE) != 0) {
	X		fputs("ai_reply: unexpected response from server\n", stderr);
	X		fputs(buf, stderr);
	X		goto bad;
	X	}
	X	sp->state = AVAILABLE;
	X	return;
	Xbad:
	X	sp->state = DEAD;
	X	(void) fclose(sp->in_fd);
	X	(void) fclose(sp->out_fd);
	X	return;
	X}
	X
	X/*
	X * ni_reply:
	X *	Read a reply from a server that just received neighbor info
	X */
	XSTATIC
	Xvoid
	Xni_reply(sp)
	XSERVER	*sp;
	X{
	X	char		buf[BUFSIZ];
	X
	X	if (fgets(buf, sizeof buf, sp->in_fd) == NULL) {
	X		fputs("ni_reply: server died\n", stderr);
	X		goto bad;
	X	}
	X	if (strcmp(buf, NI_RESPONSE) != 0) {
	X		fputs("ni_reply: unexpected response from server\n", stderr);
	X		fputs(buf, stderr);
	X		goto bad;
	X	}
	X	sp->state = AVAILABLE;
	X	return;
	Xbad:
	X	sp->state = DEAD;
	X	(void) fclose(sp->in_fd);
	X	(void) fclose(sp->out_fd);
	X	return;
	X}
	X
	X
	X/*
	X * probe_info:
	X *	Send probe information to all servers
	X */
	XSTATIC
	Xvoid
	Xprobe_info(plist)
	XPROBE	*plist;
	X{
	X	register SERVER		*sp;
	X	register PROBE		*pp;
	X	register int		n;
	X	register struct iovec	*ip;
	X	struct iovec		*iov, *endip;
	X	char			buf[BUFSIZ];
	X
	X	/*
	X	 * Count up the number of probes and allocate
	X	 * data structure for sending it down the line
	X	 */
	X	n = 0;
	X	for (pp = probe; pp != NULL; pp = pp->next)
	X		n++;
	X	if (n > 0) {
	X		iov = (struct iovec *) emalloc(n * sizeof (struct iovec));
	X		endip = iov + n;
	X		for (ip = iov, pp = plist; ip < endip; ip++, pp = pp->next) {
	X			ip->iov_base = (caddr_t) pp;
	X			ip->iov_len = sizeof (PROBE);
	X		}
	X	}
	X
	X	(void) sprintf(buf, PRI_COMMAND, n);
	X	for (sp = server; sp != NULL; sp = sp->next) {
	X		if (sp->state == DEAD)
	X			continue;
	X		fputs(buf, sp->out_fd);
	X		if (n > 0)
	X			fwritev(sp->out_fd, iov, n);
	X		(void) fflush(sp->out_fd);
	X		sp->state = EXECUTING;
	X		sp->reply = pri_reply;
	X		sp->retry = NULL;
	X	}
	X	wait_for_server();
	X	if (n > 0)
	X		(void) free((char *) iov);
	X}
	X
	X/*
	X * pri_reply:
	X *	Read a reply from a server that just received probe info
	X */
	XSTATIC
	Xvoid
	Xpri_reply(sp)
	XSERVER	*sp;
	X{
	X	char		buf[BUFSIZ];
	X
	X	if (fgets(buf, sizeof buf, sp->in_fd) == NULL) {
	X		fputs("pri_reply: server died\n", stderr);
	X		goto bad;
	X	}
	X	if (strcmp(buf, PRI_RESPONSE) != 0) {
	X		fputs("pri_reply: unexpected response from server\n", stderr);
	X		fputs(buf, stderr);
	X		goto bad;
	X	}
	X	sp->state = AVAILABLE;
	X	return;
	Xbad:
	X	sp->state = DEAD;
	X	(void) fclose(sp->in_fd);
	X	(void) fclose(sp->out_fd);
	X	return;
	X}
	X
	X/*
	X * neighbors:
	X *	Send contact computation request for atom "n" in "alist"
	X *	out to an available server.  If none is available, wait for one.
	X */
	XSTATIC
	Xvoid
	Xneighbors(n)
	Xint	n;
	X{
	X	register SERVER	*sp;
	X
	X	if ((sp = get_server()) == NULL) {
	X		fputs("neighbors: servers idling!\n", stderr);
	X		exit(1);
	X	}
	X	fprintf(sp->out_fd, C_COMMAND, n);
	X	(void) fflush(sp->out_fd);
	X	sp->state = EXECUTING;
	X	sp->reply = c_reply;
	X	sp->retry = neighbors;
	X	sp->arg1 = n;
	X}
	X
	X/*
	X * c_reply:
	X *	Read the output of a server which completed a contact
	X *	computation.  Reset the server state when we are done.
	X */
	XSTATIC
	Xvoid
	Xc_reply(sp)
	XSERVER	*sp;
	X{
	X	char		buf[BUFSIZ];
	X	int		n, nn;
	X
	X	/*
	X	 * Read the computed neighbors
	X	 */
	X	if (fgets(buf, sizeof buf, sp->in_fd) == NULL) {
	X		fputs("c_reply: server died\n", stderr);
	X		goto bad;
	X	}
	X	if (sscanf(buf, C_RESPONSE, &n, &nn) != 2) {
	X		fputs("c_reply: unexpected response from server\n", stderr);
	X		fputs(buf, stderr);
	X		goto bad;
	X	}
	X	neighbor[n].nneighbor = nn;
	X	if (nn > 0) {
	X		neighbor[n].neighbor = (AINDEX *) emalloc(nn * sizeof (AINDEX));
	X		if (fread((char *) neighbor[n].neighbor, sizeof (AINDEX), nn,
	X		sp->in_fd) != nn) {
	X			fputs("c_reply: unexpected EOF from server\n", stderr);
	X			goto bad;
	X		}
	X	}
	X	else
	X		neighbor[n].neighbor = NULL;
	X
	X	/*
	X	 * Reset the server state and return
	X	 */
	X	sp->state = AVAILABLE;
	X	return;
	X
	Xbad:
	X	/*
	X	 * Mark the server as dead and return
	X	 */
	X	sp->state = DEAD;
	X	(void) fclose(sp->in_fd);
	X	(void) fclose(sp->out_fd);
	X	return;
	X}
	X
	X/*
	X * probes:
	X *	Send contact computation request for atom "n" in "alist"
	X *	out to an available server.  If none is available, wait for one.
	X */
	XSTATIC
	Xvoid
	Xprobes(n, m)
	Xint	n;
	XAINDEX	m;
	X{
	X	register SERVER	*sp;
	X
	X	if ((sp = get_server()) == NULL) {
	X		fputs("neighbors: servers idling!\n", stderr);
	X		exit(1);
	X	}
	X	fprintf(sp->out_fd, P_COMMAND, n, m);
	X	(void) fflush(sp->out_fd);
	X	sp->state = EXECUTING;
	X	sp->reply = p_reply;
	X	sp->retry = probes;
	X	sp->arg1 = n;
	X	sp->arg2 = m;
	X}
	X
	X/*
	X * p_reply:
	X *	Read the output of a server which completed a probe
	X *	computation.  Reset the server state when we are done.
	X */
	XSTATIC
	Xvoid
	Xp_reply(sp)
	XSERVER	*sp;
	X{
	X	register int	i;
	X	register PROBE	*pp;
	X	char		buf[BUFSIZ];
	X	int		n, m, np;
	X
	X	for (;;) {
	X		if (fgets(buf, sizeof buf, sp->in_fd) == NULL) {
	X			fputs("p_reply: server died\n", stderr);
	X			goto bad;
	X		}
	X		if (sscanf(buf, P_BADNB, &n, &m) != 2)
	X			break;
	X		/*
	X		 * These atoms are not real neighbors!  We should go and
	X		 * remove the neighbor markings on them.
	X		 */
	X		for (i = 0; i < neighbor[n].nneighbor; i++)
	X			if (neighbor[n].neighbor[i] == m)
	X				neighbor[n].neighbor[i] = -1;
	X		for (i = 0; i < neighbor[m].nneighbor; i++)
	X			if (neighbor[m].neighbor[i] == n)
	X				neighbor[m].neighbor[i] = -1;
	X	}
	X	if (sscanf(buf, P_RESPONSE, &np) != 1) {
	X		fputs("p_reply: unexpected response from server\n",
	X			stderr);
	X		fputs(buf, stderr);
	X		goto bad;
	X	}
	X	if (np > 0) {
	X		pp = (PROBE *) emalloc(np * sizeof (PROBE));
	X		if (fread((char *) pp, sizeof (PROBE), np, sp->in_fd) != np) {
	X			fputs("p_reply: unexpected EOF from server\n", stderr);
	X			goto bad;
	X		}
	X		for (i = 1; i < np; i++)
	X			pp[i - 1].next = &pp[i];
	X		pp[np - 1].next = probe;
	X		probe = pp;
	X	}
	X
	X	/*
	X	 * Reset the server state and return
	X	 */
	X	sp->state = AVAILABLE;
	X	return;
	X
	Xbad:
	X	/*
	X	 * Mark the server as dead and return
	X	 */
	X	sp->state = DEAD;
	X	(void) fclose(sp->in_fd);
	X	(void) fclose(sp->out_fd);
	X	return;
	X}
	X
	X/*
	X * contact_surface:
	X *	Start a server on computing the contact surface for atom `n'
	X */
	XSTATIC
	Xvoid
	Xcontact_surface(n)
	Xint	n;
	X{
	X	register SERVER	*sp;
	X
	X	if ((sp = get_server()) == NULL) {
	X		fputs("contact_surface: servers idling!\n", stderr);
	X		exit(1);
	X	}
	X	fprintf(sp->out_fd, CS_COMMAND, n);
	X	(void) fflush(sp->out_fd);
	X	sp->state = EXECUTING;
	X	sp->reply = surface_reply;
	X	sp->retry = contact_surface;
	X	sp->arg1 = n;
	X}
	X
	X/*
	X * torus_surface:
	X *	Start a server on computing the toroid reentrant surface between
	X *	atoms `n' and `m'
	X */
	XSTATIC
	Xvoid
	Xtorus_surface(n, m)
	Xint	n, m;
	X{
	X	register SERVER	*sp;
	X
	X	if ((sp = get_server()) == NULL) {
	X		fputs("torus_surface: servers idling!\n", stderr);
	X		exit(1);
	X	}
	X	fprintf(sp->out_fd, TS_COMMAND, n, m);
	X	(void) fflush(sp->out_fd);
	X	sp->state = EXECUTING;
	X	sp->reply = surface_reply;
	X	sp->retry = torus_surface;
	X	sp->arg1 = n;
	X	sp->arg2 = m;
	X}
	X
	X/*
	X * probe_surface:
	X *	Start a server on computing the probe reentrant surface
	X *	for probe `pp'
	X */
	XSTATIC
	Xvoid
	Xprobe_surface(n)
	Xint	n;
	X{
	X	register SERVER	*sp;
	X
	X	if ((sp = get_server()) == NULL) {
	X		fputs("probe_surface: servers idling!\n", stderr);
	X		exit(1);
	X	}
	X	fprintf(sp->out_fd, PS_COMMAND, n);
	X	(void) fflush(sp->out_fd);
	X	sp->state = EXECUTING;
	X	sp->reply = surface_reply;
	X	sp->retry = probe_surface;
	X	sp->arg1 = n;
	X}
	X
	X/*
	X * surface_reply:
	X *	This routine is used by all surface computation requests.
	X *	We read surface data until we get an "END" message
	X */
	XSTATIC
	Xvoid
	Xsurface_reply(sp)
	XSERVER	*sp;
	X{
	X	register SURFACE	*surfp;
	X	register int		cc;
	X	char			buf[BUFSIZ];
	X	int			n, nn, type, have_normal;
	X	double			area;
	X
	X	for (;;) {
	X		if (fgets(buf, sizeof buf, sp->in_fd) == NULL) {
	X			fputs("surface_reply: server died\n", stderr);
	X			goto bad;
	X		}
	X		if (strcmp(buf, SURFACE_END) == 0)
	X			break;
	X		if (sscanf(buf, SURFACE_RESPONSE, &n, &nn, &type, &area,
	X		&have_normal) != 5) {
	X			fputs("surface_reply: bad response from server\n",
	X				stderr);
	X			fputs(buf, stderr);
	X			goto bad;
	X		}
	X		if (nn <= 0)
	X			continue;
	X		surfp = (SURFACE *) emalloc(sizeof (SURFACE));
	X		surfp->next = alist[n]->surface;
	X		alist[n]->surface = surfp;
	X		surfp->type = type;
	X		surfp->area = area;
	X		surfp->npoint = nn;
	X		surfp->position = (POINT *) emalloc(nn * sizeof (POINT));
	X		if ((cc = fread((char *) surfp->position, sizeof (POINT), nn,
	X		sp->in_fd)) != nn) {
	X			fprintf(stderr,
	X				"surface_reply: Read %d points, wanted %d\n",
	X				cc, nn);
	X			surfp->npoint = 0;
	X			goto bad;
	X		}
	X		if (!have_normal) {
	X			surfp->normal = NULL;
	X			continue;
	X		}
	X		surfp->normal = (POINT *) emalloc(nn * sizeof (POINT));
	X		if (fread((char *) surfp->normal, sizeof (POINT), nn,
	X		sp->in_fd) != nn) {
	X			fputs("surface_reply: EOF from server\n", stderr);
	X			surfp->npoint = 0;
	X			goto bad;
	X		}
	X	}
	X
	X	/*
	X	 * Got all data, just reset state and return
	X	 */
	X	sp->state = AVAILABLE;
	X	return;
	X
	Xbad:
	X	/*
	X	 * Mark the server as dead and return
	X	 */
	X	sp->state = DEAD;
	X	(void) fclose(sp->in_fd);
	X	(void) fclose(sp->out_fd);
	X	return;
	X}
	X
	X/*
	X * collapse_probes:
	X *	Check for near-coincident probes and remove redundant
	X *	surface coverage
	X */
	XSTATIC
	Xvoid
	Xcollapse_probes()
	X{
	X	int	i, j;
	X	PROBE	*pp, *npp;
	X	double	delta, distsq;
	X	ATOM	*shared[3];
	X	int	nshared;
	X	double	plane[4];
	X	double	v1[3], v2[3];
	X	double	pside, npside;
	X#define	EPSILON	1e-8
	X
	X	for (pp = probe; pp != NULL; pp = pp->next) {
	X		if (!pp->real)
	X			continue;
	X		for (npp = pp->next; npp != NULL; npp = npp->next) {
	X			distsq = 0;
	X			for (i = 0; i < 3; i++) {
	X				delta = pp->coord[i] - npp->coord[i];
	X				distsq += delta * delta;
	X			}
	X			if (distsq > EPSILON)
	X				continue;
	X			nshared = 0;
	X			for (i = 0; i < 3; i++)
	X				for (j = 0; j < 3; j++)
	X					if (pp->atom[i] == npp->atom[j]) {
	X						shared[nshared++] =
	X							alist[pp->atom[i]];
	X						break;
	X					}
	X			if (nshared != 2)
	X				continue;
	X			for (i = 0; i < 3; i++) {
	X				v1[i] = shared[0]->coord[i] - pp->coord[i];
	X				v2[i] = shared[1]->coord[i] - pp->coord[i];
	X			}
	X			cross(v1, v2, plane);
	X			plane[3] = 0;
	X			for (i = 0; i < 3; i++)
	X				plane[3] -= plane[i] * pp->coord[i];
	X			for (i = 0; i < 3; i++) {
	X				if (alist[pp->atom[i]] != shared[0]
	X				&& alist[pp->atom[i]] != shared[1]) {
	X					pside = plane[3];
	X					for (j = 0; j < 3; j++)
	X						pside += alist[pp->atom[i]]
	X							->coord[j] * plane[j];
	X				}
	X				if (alist[npp->atom[i]] != shared[0]
	X				&& alist[npp->atom[i]] != shared[1]) {
	X					npside = plane[3];
	X					for (j = 0; j < 3; j++)
	X						npside += alist[npp->atom[i]]
	X							->coord[j] * plane[j];
	X				}
	X			}
	X			if ((npside < 0 && pside < 0)
	X			|| (npside > 0 && pside > 0))
	X				npp->real = 0;
	X		}
	X	}
	X}
	X
	X/*
	X * cross:
	X *	Take cross product of a and b
	X */
	XSTATIC
	Xvoid
	Xcross(a, b, result)
	Xdouble a[3];
	Xdouble b[3];
	Xdouble result[3];
	X{
	X	result[0] = a[1] * b[2] - b[1] * a[2];
	X	result[1] = a[2] * b[0] - b[2] * a[0];
	X	result[2] = a[0] * b[1] - b[0] * a[1];
	X}
SHAR_EOF
if test 30786 -ne "`wc -c < 'compute.c'`"
then
	echo shar: "error transmitting 'compute.c'" '(should have been 30786 characters)'
fi
fi
echo shar: "extracting 'dms.1'" '(7133 characters)'
if test -f 'dms.1'
then
	echo shar: "will not over-write existing file 'dms.1'"
else
sed 's/^	X//' << \SHAR_EOF > 'dms.1'
	X.TH DMS 1 "" "\fBAPPENDIX 6\fP" "\fBUCSF MidasPlus\fP"
	X.iX zd start
	X.SH NAME
	Xdms \- calculate a solvent-accessible molecular surface
	X.SH SYNOPSIS
	X.B dms
	X\fIfile\fR [
	X.B \-a
	X] [
	X.B \-d
	X\fIdensity\fR] [
	X.B \-g
	X\fIfile\fR] [
	X.B \-i
	X\fIfile\fR] [\fB\-n\fR] [\fB\-w
	X\fIradius\fR] [\fB\-v\fR] \fB\-o\fI file\fR
	X.SH DESCRIPTION
	X.I Dms
	Xcalculates the molecular surface of a molecule.
	XThe molecular surface resembles the van der Waals
	Xsurface of a molecule,
	Xexcept that crevices between atoms are smoothed over
	Xand interstices too small
	Xto accommodate the probe are eliminated.
	XThe surface includes cavities in the interior
	Xof the molecule,
	Xeven if they are not accessible to a solvent molecule
	Xcoming from the outside.
	X.LP
	XThe molecular surface
	Xcalculated is that defined by
	XF. M. Richards (1977,
	X.I "Ann. Rev. Biophys. Bioeng."
	X).
	XIn particular,
	Xthe calculated molecular surface is that traced out by the \fIsurface\fP
	Xof the probe sphere rather that the probe sphere's \fIcenter\fP.
	XAccording to Richards' definition
	Xthe molecular surface consists of two parts:
	X.I "contact surface"
	Xand
	X.I "reentrant surface."
	XThe contact surface is
	Xmade up of
	X``those parts of the molecular van der Waals
	Xsurface that can actually be in contact
	Xwith the surface of the probe.''
	XThe reentrant surface is defined by
	X``the interior-facing part of the probe
	Xwhen it is simultaneously
	Xin contact with more than one atom.''
	X.I Dms
	Xreports the amounts of contact and reentrant surface area,
	Xand the combined total surface area on the standard error output
	X(see the \fB\-g\fP flag below).
	X.LP
	X.I File
	Xis an input file of coordinates.
	XThe input file must be in the Protein Data Bank format.
	XThe first letter or first two letters
	Xof the atom name is used
	Xto determine the element type.
	XBy default, implicit hydrogens are
	Xincluded for carbon,
	Xnitrogen and oxygen atoms,
	Xthus aromatic carbons
	Xand nitrogens
	Xwill have van der Waals radii
	Xthat are somewhat too big.
	XNote that
	Xonly amino acid and nucleic acid residues
	Xwill be included unless \fB\-a\fR is also specified.
	X.LP
	X.SL
	X.I Dms
	Xcan be set up to run on multiple machines
	Xsimultaneously for increased performance.
	XBy default, it only runs on the local host.
	XThe
	X.SM UCSF
	XMidasPlus Installation Guide
	Xthat came with the MidasPlus
	X.SM CD-ROM
	Xcontains instructions
	Xon how to configure
	X.I dms
	Xto use multiple machines.
	X.EL
	X.LP
	X.SL
	XIf it is desired to simply visualize a small molecular surface
	Xfrom within 
	X.SM MIDAS\c
	X, it may be easier to use the \fImakems\fP(1) delegate,
	Xrather than run \fIdms\fP directly.
	XConsult the \fImakems\fP manual page for further details.
	X.EL
	X.SH OPTIONS
	XThe flags may be in any order.
	XThe meanings of the flags are described below:
	X.IP \fB\-a\fR
	XInclude all atoms,
	Xnot just those in amino acid and nucleic acid residues.
	X.IP \fB\-d\fR
	XChange the density of points on the surface.
	X.I Density
	Xis a factor affecting
	Xthe density of points on the surface;
	Xthe default of 1.0 produces about 5 points
	Xper square angstrom.
	XOnly values between 0.1 and 10.0 are permitted.
	XFor large proteins,
	Xa density of 0.5 is recommended.
	X.IP \fB\-g\fR
	XWrite all the informative messages to
	X.I file,
	Xinstead of the standard error output.
	XGenuine errors still go to the standard error output.
	XThis file is not rewound at any time,
	Xso messages from several runs may be accumulated.
	X.IP \fB\-i\fR
	X.iX 36
	XCalculate the molecular surface
	Xonly for those residues and atoms
	Xspecified in
	X.I file,
	Xbut keeping the rest of the molecule
	Xfor collision checks.
	XThe file consists of a series of lines
	Xsuch as the following:
	X.nf
	XASP  205 CA
	XTYR   13 *
	XGLY  116 FRM
	XHIS  178 TO
	X.fi
	X.IP
	XThe asterisk means all atoms of the residue
	Xand the ``FRM'' and ``TO'' mean all residues
	Xfrom 116 to 178 inclusive.
	XThe sequence number may contain letters,
	Xand if the
	X.SM PDB
	Xinput file contains chain identifiers,
	Xthen those should be appended on the right of the sequence number.
	XResidue insertion codes (if any) should be placed between
	Xthe sequence number and any chain identifier.
	XResidues contained in \fCHETATM\fP records should have
	Xan asterisk appended to the end of the residue identifier.
	XThe surface generated using the \fB\-i\fR flag
	Xis not always the same as the surface
	Xgenerated by running the entire molecule
	Xand afterwards selecting out the desired atoms.
	XThe first surface will not include
	Xreentrant surface lying between
	Xan atom in the \fB\-i\fR file and atoms not in the file.
	X.iX bd
	XThe
	X.IR pdb2site (1)
	Xutility may be useful for generating site files.
	XConsult the
	X.I pdb2site
	Xmanual page for further details.
	X.IP \fB\-n\fR
	XInclude the unit normals
	Xto the surface with
	Xeach surface point record.
	X.IP \fB\-v\fR
	XProduce more verbose output.
	X.I Dms
	Xwill announce each computation phase as it is entered
	Xas well as a count of the atom types in the molecule
	Xand the number of computation requests handled by each
	Xhost that participated in the
	X.I dms
	Xcalculation.
	X.IP \fB\-o\fR
	XThe output is written to
	X.I file.
	XThis flag is not optional.
	X.IP \fB\-w\fR
	XChange the water probe radius from the default
	Xradius of 1.4 angstroms.
	XThis parameter must be between
	X1.0 and 201.0.
	X.LP
	XThe output consists of
	Xa series of atom and surface point records,
	Xwith the same format for the
	Xfirst six fields.
	XEach atom is followed by
	Xthe surface points (if any)
	Xwhich belong to it.
	XThese first six fields
	Xare in the following format:
	Xresidue name,
	Xsequence number,
	Xatom name,
	Xx coordinate,
	Xy coordinate,
	Xz coordinate.
	XFor an atom record,
	Xthe seventh field is ``A.''
	XFor a surface point record,
	Xthe seventh field begins
	Xwith an ``S,''
	Xfollowed by a ``C,'' ``R,'' or ``S''
	Xaccording to whether
	Xthe point is part of
	Xcontact, reentrant, or ``saddle'' surface
	X(``saddle'' is a type of reentrant surface
	Xwhere the probe is in contact with exactly
	Xtwo atoms).
	XThis is followed a digit
	Xused for depicting
	Xdifferent density levels.
	XThe eighth field is the
	Xmolecular surface area associated
	Xwith the point in
	Xsquare angstroms.
	XIf the \fB\-n\fR flag is specified,
	Xthe next three fields are
	Xthe unit normal vector
	Xpointing outward from the surface.
	XInformative messages and errors are
	Xwritten to the standard error output
	Xunless a \fB\-g\fR file is specified.
	X.LP
	X.iX 27 start
	XThe chemical elements and radii
	Xthat the program handles are detailed
	Xin the table below.
	XThe program gets these values from the file
	X.IR /usr/local/midas/resource/dms/radii .
	XIf there is a file in the current directory called
	X.IR radii ,
	Xthen
	X.I dms
	Xwill use that file instead.
	XSo in order to add uncommon elements or
	Xuse different radii, one should copy the
	Xdefault file and modify it.
	XThe file format is documented in the file itself.
	X.sp
	X.RS 1i
	X.TS
	Xbox;
	Xc c
	Xa n.
	XElement	Radius
	X_	_
	XH	1.20
	XC	1.90
	XN	1.50
	XO	1.40
	XF	1.35
	XP	1.90
	XS	1.85
	XCl	1.8
	XFe	0.64
	XCu	1.28
	XZn	1.38
	XBr	1.95
	XI	2.15
	XOther	1.90
	X.TE
	X.RE
	X.SH "SEE ALSO"
	X.SL
	Xpdb2site(1),
	XThe UCSF MidasPlus Installation Guide
	X.EL
	X.SH "AUTHOR"
	XConrad Huang
	X.br
	XUniversity of California, San Francisco
	X.SH FILES
	X/usr/local/midas/resource/dms/radii        default atomic radii
	X.iX 27 stop
	X.br
	X.SH DIAGNOSTICS
	XMany and varied.
	X.iX 37
	XBe sure to examine the \fB\-g\fR file before you leave
	Xa background job running overnight.
	X.iX zd stop
SHAR_EOF
if test 7133 -ne "`wc -c < 'dms.1'`"
then
	echo shar: "error transmitting 'dms.1'" '(should have been 7133 characters)'
fi
fi
if test ! -d 'dmsd'
then
	echo shar: "creating directory 'dmsd'"
	mkdir 'dmsd'
fi
echo shar: "entering directory 'dmsd'"
cd 'dmsd'
echo shar: "extracting 'emalloc.c'" '(2367 characters)'
if test -f 'emalloc.c'
then
	echo shar: "will not over-write existing file 'emalloc.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'emalloc.c'
	X/*
	X
	XCopyright (c) <2002> The Regents of the University of California.
	XAll rights reserved.
	X
	XRedistribution and use in source and binary forms, with or without
	Xmodification, are permitted provided that the following conditions
	Xare met:
	X  1. Redistributions of source code must retain the above copyright
	X     notice, this list of conditions, and the following disclaimer.
	X  2. Redistributions in binary form must reproduce the above
	X     copyright notice, this list of conditions, and the following
	X     disclaimer in the documentation and/or other materials provided
	X     with the distribution.
	X  3. Redistributions must acknowledge that this software was
	X     originally developed by the UCSF Computer Graphics Laboratory
	X     under support by the NIH National Center for Research Resources,
	X     grant P41-RR01081.
	X
	XTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
	XEXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
	XIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
	XPURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS BE LIABLE
	XFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
	XCONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
	XOF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
	XBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
	XWHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
	XOR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
	XEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
	X
	X */
	X#include <stdio.h>
	X#include <stdlib.h>
	X
	X/*
	X * emalloc:
	X *	Same as malloc but exits when failure occurs
	X */
	Xchar *
	Xemalloc(size)
	Xunsigned	size;
	X{
	X	register char	*cp;
	X
	X	if ((cp = malloc(size)) == NULL) {
	X		fprintf(stderr, "emalloc(%u) failed\n", size);
	X		exit(1);
	X	}
	X	return cp;
	X}
	X
	X/*
	X * erealloc:
	X *	Same as realloc but exits when failure occurs
	X */
	Xchar *
	Xerealloc(ptr, size)
	Xchar		*ptr;
	Xunsigned	size;
	X{
	X	register char	*cp;
	X
	X	if ((cp = realloc(ptr, size)) == NULL) {
	X		fprintf(stderr, "erealloc(ptr, %u) failed\n", size);
	X		exit(1);
	X	}
	X	return cp;
	X}
	X
	X/*
	X * ecalloc:
	X *	Same as calloc but exits when failure occurs
	X */
	Xchar *
	Xecalloc(nelem, elsize)
	Xunsigned nelem, elsize;
	X{
	X	register char	*cp;
	X
	X	if ((cp = calloc(nelem, elsize)) == NULL) {
	X		fprintf(stderr, "calloc(%u, %u) failed\n", nelem, elsize);
	X		exit(1);
	X	}
	X	return cp;
	X}
SHAR_EOF
if test 2367 -ne "`wc -c < 'emalloc.c'`"
then
	echo shar: "error transmitting 'emalloc.c'" '(should have been 2367 characters)'
fi
fi
echo shar: "extracting 'freadv.c'" '(1924 characters)'
if test -f 'freadv.c'
then
	echo shar: "will not over-write existing file 'freadv.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'freadv.c'
	X/*
	X
	XCopyright (c) <2002> The Regents of the University of California.
	XAll rights reserved.
	X
	XRedistribution and use in source and binary forms, with or without
	Xmodification, are permitted provided that the following conditions
	Xare met:
	X  1. Redistributions of source code must retain the above copyright
	X     notice, this list of conditions, and the following disclaimer.
	X  2. Redistributions in binary form must reproduce the above
	X     copyright notice, this list of conditions, and the following
	X     disclaimer in the documentation and/or other materials provided
	X     with the distribution.
	X  3. Redistributions must acknowledge that this software was
	X     originally developed by the UCSF Computer Graphics Laboratory
	X     under support by the NIH National Center for Research Resources,
	X     grant P41-RR01081.
	X
	XTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
	XEXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
	XIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
	XPURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS BE LIABLE
	XFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
	XCONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
	XOF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
	XBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
	XWHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
	XOR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
	XEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
	X
	X */
	X#include <stdio.h>
	X#include <sys/types.h>
	X#include <sys/uio.h>
	X
	X/*
	X * freadv:
	X *	Like readv system call except we use stdio library
	X */
	Xfreadv(fp, iov, n)
	XFILE		*fp;
	Xstruct iovec	*iov;
	Xint		n;
	X{
	X	register struct iovec	*ip, *endip;
	X	register int		cc;
	X
	X	cc = 0;
	X	endip = iov + n;
	X	for (ip = iov; ip < endip; ip++)
	X		cc += fread(ip->iov_base, sizeof (char), ip->iov_len, fp);
	X	return cc;
	X}
SHAR_EOF
if test 1924 -ne "`wc -c < 'freadv.c'`"
then
	echo shar: "error transmitting 'freadv.c'" '(should have been 1924 characters)'
fi
fi
echo shar: "extracting 'GNUmakefile'" '(593 characters)'
if test -f 'GNUmakefile'
then
	echo shar: "will not over-write existing file 'GNUmakefile'"
else
sed 's/^	X//' << \SHAR_EOF > 'GNUmakefile'
	Xifeq ($(shell test -e /bin/cygwin1.dll && echo found),found)
	XPROG	= dmsd.exe
	Xelse
	XPROG	= dmsd
	Xendif
	X
	XDESTLIB	= ${LIBDIR}/dms
	X
	XDEFS	= -DDESTLIB=\"${DESTLIB}\"
	X
	XOBJS	= server.o viewat.o lookat.o freadv.o emalloc.o
	XOPT	= -g
	XCFLAGS	= -I.. ${DEFS} ${OPT}
	X
	X${PROG}: ${OBJS}
	X	${CC} -o ${PROG} ${OBJS} -lm
	X
	Xbeforeinstall:
	X	-mkdir ${DESTLIB}
	X
	Xafterinstall:
	X	cp ../dms_servers.proto ${DESTLIB}/dms_servers.proto
	X
	Xinstall: ${PROG} afterinstall
	Xafterinstall: realinstall
	Xrealinstall: beforeinstall
	X	cp ${PROG} ${DESTLIB}
	X	-strip ${DESTLIB}/${PROG}
	X
	Xclean:
	X	rm -f ${OBJS}
	X
	Xspotless:
	X	rm -f ${OBJS} ${PROG}
SHAR_EOF
if test 593 -ne "`wc -c < 'GNUmakefile'`"
then
	echo shar: "error transmitting 'GNUmakefile'" '(should have been 593 characters)'
fi
fi
echo shar: "extracting 'lookat.c'" '(3157 characters)'
if test -f 'lookat.c'
then
	echo shar: "will not over-write existing file 'lookat.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'lookat.c'
	X/*
	X
	XCopyright (c) <2002> The Regents of the University of California.
	XAll rights reserved.
	X
	XRedistribution and use in source and binary forms, with or without
	Xmodification, are permitted provided that the following conditions
	Xare met:
	X  1. Redistributions of source code must retain the above copyright
	X     notice, this list of conditions, and the following disclaimer.
	X  2. Redistributions in binary form must reproduce the above
	X     copyright notice, this list of conditions, and the following
	X     disclaimer in the documentation and/or other materials provided
	X     with the distribution.
	X  3. Redistributions must acknowledge that this software was
	X     originally developed by the UCSF Computer Graphics Laboratory
	X     under support by the NIH National Center for Research Resources,
	X     grant P41-RR01081.
	X
	XTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
	XEXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
	XIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
	XPURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS BE LIABLE
	XFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
	XCONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
	XOF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
	XBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
	XWHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
	XOR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
	XEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
	X
	X */
	X#include <stdio.h>
	X#include <math.h>
	X
	X/*
	X * This function is like the one from the E & S library which produces
	X * a matrix to rotate a vector to the Z axis.
	X *
	X * This version is much enhanced over the Pic Sys original, in that
	X * you give it both ends of the bond to be rotated about and it
	X * returns both the "m_lookat" tensor and its inverse.
	X *
	X * Martin Pensak:  1977
	X *
	X * Stolen and hacked for the PS300 by Conrad Huang 24feb84
	X */
	Xlookat(array, arrayinv, x, y)
	Xdouble	array[4][4];		/* the output array */
	Xdouble	arrayinv[4][4];		/* output array for the inverse of
	X				 * the main output */
	Xdouble	x[3], y[3];		/* the vectors */
	X{
	X	register int	j, k;
	X	double		a, b, c, l, d;
	X	double		m[4][4];
	X
	X	a = y[0] - x[0];
	X	b = y[1] - x[1];
	X	c = y[2] - x[2];
	X	l = sqrt(a*a + c*c);
	X	d = sqrt(l*l + b*b);
	X	if (d == 0.0) {
	X		fprintf(stderr, "Illegal value passed to m_lookat\n");
	X		return;
	X	}
	X
	X	m[0][0] = (l != 0) ? (c / l) : 1;
	X	m[0][1] = (l != 0) ? (-(a * b)/(l * d)) : 0;
	X	m[0][2] = a / d;
	X	m[0][3] = 0;
	X	m[1][0] = 0;
	X	m[1][1] = l / d;
	X	m[1][2] = b / d;
	X	m[1][3] = 0;
	X	m[2][0] = (l != 0) ? ( - a / l) : 0;
	X	m[2][1] = (l != 0) ? ( -(b * c)/(l * d)) : 1;
	X	m[2][2] = c / d;
	X	m[2][3] = 0;
	X	m[3][0] = m[3][1] = m[3][2] = 0;
	X	m[3][3] = 1;
	X
	X	for (j = 0; j < 4; j++)
	X		for (k = 0; k < 4; k++)
	X			array[j][k] = arrayinv[k][j] = m[j][k];
	X
	X	/* now set up the translations */
	X	a = x[0];
	X	b = x[1];
	X	c = x[2];
	X	arrayinv[3][0] = a;
	X	arrayinv[3][1] = b;
	X	arrayinv[3][2] = c;
	X
	X	array[3][0] = -(a*m[0][0] + b*m[1][0] + c*m[2][0]);
	X	array[3][1] = -(a*m[0][1] + b*m[1][1] + c*m[2][1]);
	X	array[3][2] = -(a*m[0][2] + b*m[1][2] + c*m[2][2]);
	X}
SHAR_EOF
if test 3157 -ne "`wc -c < 'lookat.c'`"
then
	echo shar: "error transmitting 'lookat.c'" '(should have been 3157 characters)'
fi
fi
echo shar: "extracting 'server.c'" '(42201 characters)'
if test -f 'server.c'
then
	echo shar: "will not over-write existing file 'server.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'server.c'
	X/*
	X
	XCopyright (c) <2002> The Regents of the University of California.
	XAll rights reserved.
	X
	XRedistribution and use in source and binary forms, with or without
	Xmodification, are permitted provided that the following conditions
	Xare met:
	X  1. Redistributions of source code must retain the above copyright
	X     notice, this list of conditions, and the following disclaimer.
	X  2. Redistributions in binary form must reproduce the above
	X     copyright notice, this list of conditions, and the following
	X     disclaimer in the documentation and/or other materials provided
	X     with the distribution.
	X  3. Redistributions must acknowledge that this software was
	X     originally developed by the UCSF Computer Graphics Laboratory
	X     under support by the NIH National Center for Research Resources,
	X     grant P41-RR01081.
	X
	XTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
	XEXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
	XIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
	XPURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS BE LIABLE
	XFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
	XCONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
	XOF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
	XBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
	XWHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
	XOR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
	XEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
	X
	X */
	X#include <stdio.h>
	X#include <math.h>
	X#include <sys/types.h>
	X#include <sys/uio.h>
	X#include <sys/file.h>
	X#include <sys/time.h>
	X#include <sys/resource.h>
	X#include "dms_param.h"
	X#include "atoms.h"
	X#include "protocol.h"
	X
	X#ifndef	TRUE
	X#define	TRUE	1
	X#define	FALSE	0
	X#endif
	X
	X#ifndef	PI
	X#define	PI	3.141592
	X#endif
	X
	X#define	ROUND(x)	((int) ((x) + 0.5))
	X#define	ABS(x)		((x) < 0 ? -(x) : (x))
	X
	X#define LOG		/* Log input and output */
	X
	X#ifndef	DEBUG
	X#undef	LOG
	X#endif
	X
	Xstatic void	execute(char *cp);
	Xstatic void	paramdata(double f1, double f2, int n);
	Xstatic void	atomdata(int n);
	Xstatic void	neighbordata(int n);
	Xstatic void	probedata(int n);
	Xstatic void	contacts(int n);
	Xstatic void	s_probes(int n, int m);
	Xstatic void	csurface(int n);
	Xstatic void	tsurface(int n, int m);
	Xstatic void	psurface(int n);
	X
	Xextern char	*sbrk(unsigned long);
	Xextern char	*emalloc(unsigned int);
	X
	X/*
	X * SERVER:
	X *	Compute server for MS.
	X *	This server is started via inetd so the input comes from stdin
	X *	and output goes to stdout.
	X */
	Xmain()
	X{
	X	char		buf[BUFSIZ];
	X	int		lockfd;
	X
	X	(void) chdir("/tmp");
	X#ifdef DEBUG
	X	(void) freopen("/tmp/dmsdlog", "w", stderr);
	X#ifdef BSD
	X	(void) setlinebuf(stderr);
	X#endif
	X	fprintf(stderr, "server started\n");
	X#endif
	X
	X	/*
	X	 * Try locking the lock file.  If we fail, another dms
	X	 * server is already running so we just exit.  If the file
	X	 * doesn't exist, then we just assume that it's okay to run.
	X	 */
	X	lockfd = open(LOCK_FILE, 0);
	X	if (lockfd >= 0 && flock(lockfd, LOCK_EX) < 0) {
	X		printf("Go away, I'm busy.\n");
	X		exit(0);
	X	}
	X
	X	/*
	X	 * Now we nice ourselves down to background priority so
	X	 * normal jobs will still get the CPU
	X	 */
	X#ifdef BSD
	X	(void) setpriority(PRIO_PROCESS, 0, NICE_PRIORITY);
	X#else
	X	(void) nice(NICE_PRIORITY);
	X#endif
	X
	X	/*
	X	 * Read commands and execute them until we reach EOF
	X	 */
	X	while (fgets(buf, sizeof buf, stdin) != NULL) {
	X#ifdef LOG
	X		fprintf(stderr, "<-- %s", buf);
	X#endif
	X		execute(buf);
	X		(void) fflush(stdout);
	X	}
	X
	X	/*
	X	 * Cleanup and exit
	X	 */
	X#ifdef DEBUG
	X	fprintf(stderr, "Memory high water mark: %d\n", sbrk(0));
	X#endif
	X	exit(0);
	X}
	X
	Xtypedef struct	keyword_def	{
	X	char	*string;
	X	int	length;
	X	int	type;
	X}	KEYWORD;
	X
	X#define	C_PARAM		0
	X#define	C_ATOM		1
	X#define	C_NEIGHBOR	2
	X#define	C_PROBEDATA	3
	X#define	C_CONTACT	4
	X#define	C_PROBE		5
	X#define	C_CSURF		6
	X#define	C_TSURF		7
	X#define	C_PSURF		8
	X
	Xstatic KEYWORD	keyword[] = {
	X	{	"paramdata",	9,	C_PARAM,	},
	X	{	"atomdata",	8,	C_ATOM,		},
	X	{	"neighbordata",	12,	C_NEIGHBOR,	},
	X	{	"probedata",	9,	C_PROBEDATA,	},
	X	{	"contacts",	8,	C_CONTACT,	},
	X	{	"probes",	6,	C_PROBE,	},
	X	{	"csurface",	8,	C_CSURF,	},
	X	{	"tsurface",	8,	C_TSURF,	},
	X	{	"psurface",	8,	C_PSURF,	},
	X};
	X#define	NKEY	(sizeof keyword / sizeof (KEYWORD))
	X
	X/*
	X * execute:
	X *	Parse the given command and call the appropriate handler
	X */
	Xstatic
	Xvoid
	Xexecute(char *cp)
	X{
	X	register KEYWORD	*kp, *endkp;
	X	int			n, m;
	X	double			f1, f2;
	X
	X	endkp = &keyword[NKEY];
	X	for (kp = keyword; kp < endkp; kp++)
	X		if (strncmp(cp, kp->string, kp->length) == 0)
	X			break;
	X	if (kp >= endkp) {
	X		printf("Unknown command: %s", cp);
	X#ifdef DEBUG
	X		fprintf(stderr, "Unknown command: %s", cp);
	X#endif
	X		return;
	X	}
	X	switch (kp->type) {
	X	  case C_PARAM:
	X		if (sscanf(cp, PI_COMMAND, &f1, &f2, &n) != 3)
	X			goto bad;
	X		paramdata(f1, f2, n);
	X		break;
	X	  case C_ATOM:
	X		if (sscanf(cp, AI_COMMAND, &n) != 1)
	X			goto bad;
	X		atomdata(n);
	X		break;
	X	  case C_NEIGHBOR:
	X		if (sscanf(cp, NI_COMMAND, &n) != 1)
	X			goto bad;
	X		neighbordata(n);
	X		break;
	X	  case C_PROBEDATA:
	X		if (sscanf(cp, PRI_COMMAND, &n) != 1)
	X			goto bad;
	X		probedata(n);
	X		break;
	X	  case C_CONTACT:
	X		if (sscanf(cp, C_COMMAND, &n) != 1)
	X			goto bad;
	X		contacts(n);
	X		break;
	X	  case C_PROBE:
	X		if (sscanf(cp, P_COMMAND, &n, &m) != 2)
	X			goto bad;
	X		s_probes(n, m);
	X		break;
	X	  case C_CSURF:
	X		if (sscanf(cp, CS_COMMAND, &n) != 1)
	X			goto bad;
	X		csurface(n);
	X		break;
	X	  case C_TSURF:
	X		if (sscanf(cp, TS_COMMAND, &n, &m) != 2)
	X			goto bad;
	X		tsurface(n, m);
	X		break;
	X	  case C_PSURF:
	X		if (sscanf(cp, PS_COMMAND, &n) != 1)
	X			goto bad;
	X		psurface(n);
	X		break;
	X	}
	X	return;
	Xbad:
	X	printf("Malformed command: %s", cp);
	X#ifdef DEBUG
	X	fprintf(stderr, "Malformed command: %s", cp);
	X#endif
	X	return;
	X}
	X
	X/*
	X * The remainder of this file consists of routines that correspond to
	X * commands.  All necessary types and global variables are declared here.
	X */
	X
	Xtypedef struct satom_def	{
	X	struct satom_def	*next;		/* Pointer to next neighbor */
	X	ATOM			atom;		/* Atom information */
	X	int			nnb;		/* Number of neighbors */
	X	AINDEX			*nb;		/* Neighbor list */
	X	int			nprobe;		/* Number of probes */
	X	int			*probe;		/* Probe list */
	X	int			nused;
	X#ifdef SORTED_NB
	X	double			dist;
	X#endif
	X}	SATOM;
	X
	Xtypedef struct sphere_def	{
	X	struct sphere_def	*next;		/* Pointer to next sphere */
	X	double			radius;		/* Radius */
	X	double			area;		/* Area per point */
	X	int			npoint;		/* Number of points */
	X	POINT			*point;		/* Point list */
	X}	SPHERE;
	X
	Xtypedef struct snb_def	{
	X	double	*coord;				/* Coordinate of neighbor */
	X	double	dist;				/* Distance between atoms */
	X	double	clip;				/* Clipping distance */
	X}	SNB;
	X
	Xtypedef struct sangle_def	{
	X	struct sangle_def	*next;		/* Pointer to next angle */
	X	double			angle;		/* Probe angle */
	X	int			start;		/* Starting or ending? */
	X	int			real;		/* This section truly exist */
	X}	SANGLE;
	X
	Xdouble	radius, density;	/* Probe and surface parameters */
	Xdouble	arclength;		/* Approximate arc length between points */
	Xdouble	root3;			/* Square root of 3 */
	Xint	want_normal;		/* Whether we should report normals */
	Xint	natom;			/* Number of atoms */
	XSATOM	*atom;			/* Atom list */
	Xint	nprobe;			/* Number of probes */
	XPROBE	*probe;			/* Probe list */
	Xdouble	maxrad;			/* Maximum atomic radius */
	XSPHERE	*sphere;		/* List of prototype spheres */
	Xint	maxsurf;		/* Size of surface list */
	XPOINT	*surface;		/* Surface points list */
	XPOINT	*normal;		/* Normal list (same size as surface) */
	X
	Xstatic SATOM	*find_satom(double x);
	Xstatic int	touches(SATOM *s1, SATOM *s2, double *dp);
	Xstatic int	probe_position(SATOM *a0, SATOM *a1, SATOM *a2,
	X		double ppos[2][3], int check_only);
	Xstatic int	hidden(SATOM *s0, SATOM *s1, SATOM *s2, double coord[3]);
	Xstatic int	occlude(SATOM *sap, double pos[3]);
	Xstatic SPHERE	*get_sphere(double r);
	Xstatic int	clipped(double coord[3], SNB *nlist, SNB *endsnp);
	Xstatic SANGLE	*compute_angles(SATOM *s1, SATOM *s2, double mat[4][4],
	X		int *na);
	Xstatic void	draw_tsections(double invmat[4][4], double tradius,
	X		double clip[2], int n, int m, SANGLE *alist);
	Xstatic int	torus_data(ATOM *a1, ATOM *a2, double tcenter[3],
	X		double *tradius, double clip[2]);
	Xstatic SANGLE	*probe_angle(int pnum, double mat[4][4], int n, int m);
	Xstatic SANGLE	*insert_angle(SANGLE *head, SANGLE *new);
	Xstatic void	tsection(double invmat[4][4], double tradius, double clip[2],
	X		double start, double end, int n, int m, int check);
	Xstatic void	send_points(POINT *plist, int np, AINDEX aindex, double area,
	X		int type, POINT *nlist);
	Xstatic void	check_point(PROBE *prp, int at, int up, int side, int npoint,
	X		POINT point[], short keep[]);
	X
	X/*
	X * paramdata:
	X *	Take the parameter data and put them in the right places
	X */
	Xstatic
	Xvoid
	Xparamdata(double f1, double f2, int n)
	X{
	X	radius = f1;
	X	density = f2 * 2.75;
	X	want_normal = n;
	X	root3 = sqrt(3.0);
	X
	X	/*
	X	 * The approximation
	X	 *	arclength = sqrt( sqrt(3) / (3 * density) )
	X	 * came from Eric Pettersen who approximated a sphere with a
	X	 * plane (an infinite sphere, you know).
	X	 */
	X	arclength = 1.0 / sqrt(root3 * density);
	X
	X	fputs(PI_RESPONSE, stdout);
	X#ifdef LOG
	X	fputs(PI_RESPONSE, stderr);
	X#endif
	X}
	X
	X/*
	X * atomdata:
	X *	Read in atomic data
	X */
	Xstatic
	Xvoid
	Xatomdata(int n)
	X{
	X	register int		cc;
	X	register SATOM		*sap, *endsap;
	X	register struct iovec	*ip;
	X	struct iovec		*iov, *endip;
	X
	X	/*
	X	 * Update global variables
	X	 */
	X	natom = n;
	X	atom = (SATOM *) emalloc(n * sizeof (SATOM));
	X#ifdef DEBUG
	X	fprintf(stderr, "Atom data = %d bytes\n", n * sizeof (SATOM));
	X#endif
	X
	X	/*
	X	 * Read in the data
	X	 */
	X	iov = (struct iovec *) emalloc(n * sizeof (struct iovec));
	X	endip = iov + n;
	X	for (ip = iov, sap = atom; ip < endip; ip++, sap++) {
	X		ip->iov_base = (caddr_t) &sap->atom;
	X		ip->iov_len = sizeof (ATOM);
	X	}
	X	if ((cc = freadv(stdin, iov, n)) != n * sizeof (ATOM)) {
	X		printf("atomdata: got %d bytes instead of %d.\n",
	X			cc, n * sizeof (ATOM));
	X#ifdef DEBUG
	X		fprintf(stderr, "atomdata: got %d bytes instead of %d.\n",
	X			cc, n * sizeof (ATOM));
	X#endif
	X		return;
	X	}
	X
	X	/*
	X	 * Initialize data regarding spheres
	X	 */
	X	maxrad = 0;
	X	endsap = atom + n;
	X	for (sap = atom; sap < endsap; sap++) {
	X		if (sap->atom.radius > maxrad)
	X			maxrad = sap->atom.radius;
	X		sap->nb = NULL;
	X	}
	X
	X	/*
	X	 * Cleanup and let caller know we've read things okay
	X	 */
	X	(void) free((char *) iov);
	X	fputs(AI_RESPONSE, stdout);
	X#ifdef LOG
	X	fputs(AI_RESPONSE, stderr);
	X#endif
	X}
	X
	X/*
	X * neighbordata:
	X *	Read in neighbor data
	X */
	Xstatic
	Xvoid
	Xneighbordata(int n)
	X{
	X	register int		cc, size, total;
	X	register SATOM		*sap, *endsap;
	X	register struct iovec	*ip;
	X	struct iovec		*iov;
	X
	X	/*
	X	 * Check for consistency
	X	 */
	X	if (n != natom) {
	X		printf("neighbordata: ncount(%d) != acount(%d)\n", n, natom);
	X#ifdef DEBUG
	X		fprintf(stderr, "neighbordata: ncount(%d) != acount(%d)\n",
	X			n, natom);
	X#endif
	X		return;
	X	}
	X	endsap = atom + natom;
	X
	X	/*
	X	 * Read in the neighbor count for each atom
	X	 */
	X	iov = (struct iovec *) emalloc(natom * sizeof (struct iovec));
	X	for (sap = atom, ip = iov; sap < endsap; sap++, ip++) {
	X		ip->iov_base = (caddr_t) &sap->nnb;
	X		ip->iov_len = sizeof (int);
	X	}
	X	if ((cc = freadv(stdin, iov, n)) != n * sizeof (int)) {
	X		printf("neighbordata: read %d bytes instead of %d.\n", cc,
	X			n * sizeof (int));
	X#ifdef DEBUG
	X		fprintf(stderr, "neighbordata: read %d bytes instead of %d.\n",
	X			cc, n * sizeof (int));
	X#endif
	X		return;
	X	}
	X
	X	/*
	X	 * Read in the actual data for each atom
	X	 */
	X	total = 0;
	X	n = 0;
	X	ip = iov;
	X	for (sap = atom; sap < endsap; sap++) {
	X		if (sap->nnb <= 0)
	X			continue;
	X		size = sap->nnb * sizeof (AINDEX);
	X		if (sap->nb == NULL)
	X			sap->nb = (AINDEX *) emalloc(size);
	X		ip->iov_base = (caddr_t) sap->nb;
	X		ip->iov_len = size;
	X		total += size;
	X		n++;
	X		ip++;
	X	}
	X	if (n > 0 && (cc = freadv(stdin, iov, n)) != total) {
	X		printf("neighbordata: read %d bytes instead of %d.\n", cc,
	X			total);
	X#ifdef DEBUG
	X		fprintf(stderr, "neighbordata: read %d bytes instead of %d.\n",
	X			cc, total);
	X#endif
	X		return;
	X	}
	X#ifdef DEBUG
	X	fprintf(stderr, "Neighbor data = %d bytes\n", total + n * sizeof (int));
	X#endif
	X
	X	/*
	X	 * Cleanup and let caller know we've read things okay
	X	 */
	X	(void) free((char *) iov);
	X	fputs(NI_RESPONSE, stdout);
	X#ifdef LOG
	X	fputs(NI_RESPONSE, stderr);
	X#endif
	X}
	X
	X/*
	X * probedata:
	X *	Read in probe and update atom information regarding probes
	X */
	Xstatic
	Xvoid
	Xprobedata(int n)
	X{
	X	register int		i;
	X	register SATOM		*sap, *endsap;
	X	register PROBE		*pp, *endpp;
	X	register int		cc, size;
	X
	X	/*
	X	 * Update global variables
	X	 */
	X	nprobe = n;
	X	if (n <= 0) {
	X		fputs(PRI_RESPONSE, stdout);
	X#ifdef LOG
	X		fputs(PRI_RESPONSE, stderr);
	X#endif
	X		return;
	X	}
	X	size = n * sizeof (PROBE);
	X	probe = (PROBE *) emalloc(size);
	X#ifdef DEBUG
	X	fprintf(stderr, "Probe data = %d bytes\n", size);
	X#endif
	X
	X	/*
	X	 * Read in the data
	X	 */
	X	if ((cc = fread((char *) probe, sizeof (PROBE), n, stdin)) != n) {
	X		printf("probedata: got %d probes instead of %d.\n", cc, n);
	X#ifdef DEBUG
	X		fprintf(stderr, "probedata: got %d bytes instead of %d.\n",
	X			cc, size);
	X#endif
	X		return;
	X	}
	X
	X	/*
	X	 * Now we update the atom data
	X	 */
	X	endsap = atom + natom;
	X	for (sap = atom; sap < endsap; sap++)
	X		sap->nprobe = sap->nused = 0;
	X	endpp = probe + nprobe;
	X	for (pp = probe; pp < endpp; pp++)
	X		for (i = 0; i < 3; i++)
	X			atom[pp->atom[i]].nprobe++;
	X	for (sap = atom; sap < endsap; sap++)
	X		if (sap->nprobe > 0)
	X			sap->probe = (int *) emalloc(sap->nprobe *
	X				sizeof (int));
	X		else
	X			sap->probe = NULL;
	X	for (pp = probe; pp < endpp; pp++)
	X		for (i = 0; i < 3; i++) {
	X			sap = &atom[pp->atom[i]];
	X			sap->probe[sap->nused++] = pp - probe;
	X		}
	X
	X	/*
	X	 * Cleanup and let caller know we've read things okay
	X	 */
	X	fputs(PRI_RESPONSE, stdout);
	X#ifdef LOG
	X	fputs(PRI_RESPONSE, stderr);
	X#endif
	X}
	X
	X/*
	X * contacts:
	X *	Compute the contacts for atom `n'
	X */
	Xstatic
	Xvoid
	Xcontacts(int n)
	X{
	X	register int	i, nn;
	X	register SATOM	*sp, *prevsp;
	X	register SATOM	*sap, *me, *nlist;
	X	register SATOM	*min, *max;
	X	AINDEX		*narray;
	X	double		distsq;
	X
	X	/*
	X	 * Initialize local variables
	X	 */
	X	me = &atom[n];
	X
	X	/*
	X	 * Locate set of atoms within `maxrad' of the given atom in
	X	 * the X direction.  This gives us a set of atoms which is
	X	 * guaranteed to include all neighbors but is still smaller
	X	 * than the set of ALL atoms.  There are more efficient ways
	X	 * to locate smaller sets but this one is easy.
	X	 */
	X	min = find_satom(me->atom.coord[0] - me->atom.radius
	X		- 2 * radius - maxrad);
	X	max = find_satom(me->atom.coord[0] + me->atom.radius
	X		+ 2 * radius + maxrad) + 1;
	X
	X	/*
	X	 * Loop through the set of atoms and locate neighbors
	X	 */
	X	nlist = NULL;
	X	nn = 0;
	X	for (sap = min; sap < max; sap++) {
	X		if (sap == me || !touches(me, sap, &distsq))
	X			continue;
	X		nn++;
	X#ifdef SORTED_NB
	X		sap->dist = distsq;
	X		prevsp = NULL;
	X		for (sp = nlist; sp != NULL; sp = sp->next) {
	X			if (sp->dist > distsq)
	X				break;
	X			prevsp = sp;
	X		}
	X		if (prevsp == NULL) {
	X			sap->next = nlist;
	X			nlist = sap;
	X		}
	X		else {
	X			sap->next = prevsp->next;
	X			prevsp->next = sap;
	X		}
	X#else
	X		sap->next = nlist;
	X		nlist = sap;
	X#endif
	X	}
	X
	X	/*
	X	 * Report the neighbor list
	X	 */
	X	printf(C_RESPONSE, n, nn);
	X#ifdef LOG
	X	fprintf(stderr, C_RESPONSE, n, nn);
	X#endif
	X	if (nn > 0) {
	X		narray = (AINDEX *) emalloc(nn * sizeof (AINDEX));
	X		for (sap = nlist, i = 0; sap != NULL; sap = sap->next, i++)
	X			narray[i] = sap - atom;
	X		(void) fwrite((char *) narray, sizeof (AINDEX), nn, stdout);
	X		(void) free((char *) narray);
	X	}
	X}
	X
	X/*
	X * find_satom:
	X *	When given an X coordinate, find the first atom whose
	X *	X coordinate is greater than or equal to the given one.
	X *	Note that the atoms are sorted by X already so we can
	X *	use a binary search.
	X */
	Xstatic
	XSATOM *
	Xfind_satom(double x)
	X{
	X	register int	hi, lo, mid;
	X
	X	hi = natom;
	X	lo = 0;
	X	mid = (hi + lo) / 2;
	X	while (mid > lo) {
	X		if (atom[mid].atom.coord[0] < x)
	X			lo = mid;
	X		else
	X			hi = mid;
	X		mid = (hi + lo) / 2;
	X	}
	X	return &atom[mid];
	X}
	X
	X/*
	X * touches:
	X *	When given two atoms, determine whether they are neighbors
	X *	(i.e. a probe will NOT fit between them).
	X */
	Xstatic
	Xint
	Xtouches(SATOM *s1, SATOM *s2, double *dp)
	X{
	X	register int	i;
	X	double		distsq, delta;
	X	double		maxdistsq;
	X
	X	/*
	X	 * Compute the maximum distance between these two atoms and
	X	 * still remain neighbors
	X	 */
	X	delta = s1->atom.radius + s2->atom.radius + 2 * radius;
	X	maxdistsq = delta * delta;
	X
	X	/*
	X	 * We determine the square of the distance between the two
	X	 * atoms and compare against `maxdistsq'.  Note that we
	X	 * compute the distance in the order Z, Y, X since we know
	X	 * that X is probably okay and Z and Y will give quicker
	X	 * failure if there is one.
	X	 */
	X	distsq = 0;
	X	for (i = 2; i >= 0; i--) {
	X		delta = s1->atom.coord[i] - s2->atom.coord[i];
	X		distsq += delta * delta;
	X		if (distsq >= maxdistsq)
	X			return FALSE;
	X	}
	X	*dp = distsq;
	X	return TRUE;
	X}
	X
	X/*
	X * s_probes:
	X *	Compute the probes that are adjacent to both given atoms
	X */
	Xstatic
	Xvoid
	Xs_probes(int n, int m)
	X{
	X	register int	i, j, k;
	X	register SATOM	*s0, *s1, *s2;
	X	register PROBE	*plist, *pp;
	X	register int	np;
	X	double		ppos[2][3];
	X	int		wanted;
	X
	X	/*
	X	 * Initialize local variables
	X	 */
	X	s0 = &atom[n];
	X	s1 = &atom[m];
	X	wanted = s0->atom.wanted || s1->atom.wanted;
	X
	X	/*
	X	 * Locate probes that may be in contact with the given
	X	 * atoms.  We need not report any probe that involves any
	X	 * atom whose index is less than `m' because it will already
	X	 * have been computed
	X	 */
	X	plist = NULL;
	X	np = 0;
	X	for (i = 0; i < s0->nnb; i++)
	X		for (j = 0; j < s1->nnb; j++) {
	X			if (s0->nb[i] != s1->nb[j])
	X				continue;
	X			s2 = &atom[s0->nb[i]];
	X			if (!wanted && !s2->atom.wanted)
	X				continue;
	X			k = probe_position(s0, s1, s2, ppos, s0->nb[i] <= m);
	X			if (k < 0) {
	X				/*
	X				 * s2 is between s0 and s1.  Just report that
	X				 * n and m cannot be neighbors and quit
	X				 */
	X				printf(P_BADNB, n, m);
	X#ifdef LOG
	X				fprintf(stderr, P_BADNB, n, m);
	X#endif
	X				goto bad;
	X			}
	X			if (k == 0)
	X				break;
	X			for (k = 0; k < 2; k++) {
	X#ifdef KEEP_REAL
	X				if (hidden(s0, s1, s2, ppos[k]))
	X					continue;
	X#endif
	X				np++;
	X				pp = (PROBE *) emalloc(sizeof (PROBE));
	X				pp->next = plist;
	X				plist = pp;
	X				pp->coord[0] = ppos[k][0];
	X				pp->coord[1] = ppos[k][1];
	X				pp->coord[2] = ppos[k][2];
	X				pp->atom[0] = n;
	X				pp->atom[1] = m;
	X				pp->atom[2] = s0->nb[i];
	X#ifdef KEEP_REAL
	X				pp->real = TRUE;
	X#else
	X				pp->real = !hidden(s0, s1, s2, ppos[k]);
	X#endif
	X			}
	X			break;
	X		}
	X
	X	/*
	X	 * Report data back to user
	X	 */
	X	printf(P_RESPONSE, np);
	X#ifdef LOG
	X	fprintf(stderr, P_RESPONSE, np);
	X#endif
	X
	X	/*
	X	 * Send the data, clean up and go home
	X	 */
	X	for (pp = plist; pp != NULL; pp = plist) {
	X		(void) fwrite((char *) pp, sizeof (PROBE), 1, stdout);
	X		plist = pp->next;
	X		free((char *) pp);
	X	}
	X	return;
	X
	Xbad:
	X	/*
	X	 * We get here when we "know" that there can be no probes
	X	 * sitting against bot given atoms.  Just report a zero
	X	 * and release data structures.
	X	 */
	X	printf(P_RESPONSE, 0);
	X#ifdef LOG
	X	fprintf(stderr, P_RESPONSE, 0);
	X#endif
	X	for (pp = plist; pp != NULL; pp = plist) {
	X		plist = pp->next;
	X		free((char *) pp);
	X	}
	X}
	X
	X/*
	X * probe_position:
	X *	When given three atoms, find the two possible probe positions.
	X *	First we transform the coordinates such that a0 is at the origin,
	X *	a1 is on the z axis, and a2 is in the y-z plane.  This arrangement
	X *	constrains the two probe positions of have the same y and z coordinates
	X *	and complementary x coordinates.
	X *	The three equations constraining distances are:
	X *		sq(x) + sq(y) + sq(z) = sq(R0 + Rp)
	X *		sq(x) + sq(y) + sq(z - z1) = sq(R1 + Rp)
	X *		sq(x) + sq(y - y2) + sq(z - z2) = sq(R2 + Rp)
	X *	from which we can solve for z, then y in terms of z, then x in
	X *	terms of y and z.
	X *
	X *	probe_position returns one of three values:
	X *		 1 - where both probe positions have been found
	X *		 0 - where no probe position is found but a0 and a1
	X *		     can still be neighbors
	X *		-1 - where a0 and a1 cannot be neighbors because a2 is
	X *		     in the way
	X */
	Xstatic
	Xint
	Xprobe_position(SATOM *a0, SATOM *a1, SATOM *a2, double ppos[2][3], int check_only)
	X{
	X	register int	i, j;
	X	double		mat[4][4], invmat[4][4];
	X	double		r0, r1, r2, dz1, dz2;
	X	double		z1, y2, z2, t;
	X	double		dy, dz;
	X	double		c[3];
	X
	X	/*
	X	 * Convert to simple coordinate system
	X	 */
	X	viewat(mat, invmat, a0->atom.coord, a1->atom.coord, a2->atom.coord);
	X	z1 = a1->atom.coord[0] * mat[0][2] + a1->atom.coord[1] * mat[1][2] +
	X		a1->atom.coord[2] * mat[2][2] + mat[3][2];
	X	y2 = a2->atom.coord[0] * mat[0][1] + a2->atom.coord[1] * mat[1][1] +
	X		a2->atom.coord[2] * mat[2][1] + mat[3][1];
	X	z2 = a2->atom.coord[0] * mat[0][2] + a2->atom.coord[1] * mat[1][2] +
	X		a2->atom.coord[2] * mat[2][2] + mat[3][2];
	X
	X	/*
	X	 * Solve in simple coordinate system.
	X	 */
	X	r0 = a0->atom.radius + radius;
	X	r1 = a1->atom.radius + radius;
	X	c[2] = (r0 * r0 - r1 * r1 + z1 * z1) / (2 * z1);
	X	r2 = a2->atom.radius + radius;
	X	dz1 = c[2] - z1;
	X	dz2 = c[2] - z2;
	X	c[1] = (r1 * r1 - r2 * r2 - dz1 * dz1 + dz2 * dz2 + y2 * y2) / (2 * y2);
	X	t = r0 * r0 - c[1] * c[1] - c[2] * c[2];
	X
	X	/*
	X	 * Now check whether the probe position is in "real" space.  If
	X	 * not determine which atom is in between the others.
	X	 */
	X	if (t <= 0) {
	X		c[1] = -sqrt(r0 * r0 - c[2] * c[2]);
	X		dy = y2 - c[1];
	X		dz = z2 - c[2];
	X		if (dy * dy + dz * dz <= r2 * r2)
	X			return -1;
	X		return 0;
	X	}
	X
	X	/*
	X	 * Probe positions are valid, convert back to original
	X	 * coordinate system and return
	X	 */
	X	if (check_only)
	X		return 0;
	X	c[0] = sqrt(t);
	X	for (i = 0; i < 3; i++) {
	X		ppos[0][i] = invmat[3][i];
	X		for (j = 0; j < 3; j++)
	X			ppos[0][i] += c[j] * invmat[j][i];
	X	}
	X	c[0] = -c[0];
	X	for (i = 0; i < 3; i++) {
	X		ppos[1][i] = invmat[3][i];
	X		for (j = 0; j < 3; j++)
	X			ppos[1][i] += c[j] * invmat[j][i];
	X	}
	X	return 1;
	X}
	X
	X/*
	X * hidden:
	X *	Determine whether the given coordinates is occluded by
	X *	any of the neighbors of the given atoms
	X */
	Xstatic
	Xint
	Xhidden(SATOM *s0, SATOM *s1, SATOM *s2, double coord[3])
	X{
	X	register int	i;
	X
	X	/*
	X	 * First we unmark all the atoms that need work.
	X	 * Then we mark the three that, by definition, cannot occlude
	X	 * the probe position.
	X	 */
	X	for (i = 0; i < s0->nnb; i++)
	X		atom[s0->nb[i]].nused = 0;
	X	for (i = 0; i < s1->nnb; i++)
	X		atom[s1->nb[i]].nused = 0;
	X	for (i = 0; i < s2->nnb; i++)
	X		atom[s2->nb[i]].nused = 0;
	X	s0->nused = s1->nused = s2->nused = 1;
	X
	X	/*
	X	 * Now we loop through all the atoms and check
	X	 */
	X	for (i = 0; i < s0->nnb; i++)
	X		if (atom[s0->nb[i]].nused++ == 0)
	X			if (occlude(&atom[s0->nb[i]], coord))
	X				return TRUE;
	X	for (i = 0; i < s1->nnb; i++)
	X		if (atom[s1->nb[i]].nused++ == 0)
	X			if (occlude(&atom[s1->nb[i]], coord))
	X				return TRUE;
	X	for (i = 0; i < s2->nnb; i++)
	X		if (atom[s2->nb[i]].nused++ == 0)
	X			if (occlude(&atom[s2->nb[i]], coord))
	X				return TRUE;
	X
	X	/*
	X	 * Nobody blocked it.  I guess it's okay
	X	 */
	X	return FALSE;
	X}
	X
	X/*
	X * occlude:
	X *	Determine whether the given atom precludes placing a sphere
	X *	at the given position
	X */
	Xstatic
	Xint
	Xocclude(SATOM *sap, double pos[3])
	X{
	X	register int	i;
	X	double		delta, distsq;
	X#ifndef ONE_OCCLUDE
	X	double		minds;
	X#endif
	X#define	EPSILON	1e-12
	X
	X#ifndef ONE_OCCLUDE
	X	delta = sap->atom.radius + radius;
	X	minds = delta * delta;
	X#endif
	X	distsq = EPSILON;
	X	for (i = 0; i < 3; i++) {
	X		delta = sap->atom.coord[i] - pos[i];
	X		distsq += delta * delta;
	X#ifndef ONE_OCCLUDE
	X		if (distsq > minds)
	X			return FALSE;
	X#endif
	X	}
	X#ifdef ONE_OCCLUDE
	X	delta = sap->atom.radius + radius;
	X	if (distsq > delta * delta)
	X		return FALSE;
	X#endif
	X	return TRUE;
	X}
	X
	X/*
	X * csurface:
	X *	Compute the contact surface of the given atom
	X */
	Xstatic
	Xvoid
	Xcsurface(int n)
	X{
	X	register POINT	*pp, *endpp;
	X	register SATOM	*sap, *me;
	X	register int	i, j;
	X	register SNB	*nlist, *snp, *endsnp;
	X	register SPHERE	*sp;
	X	register POINT	*savepp, *savenp;
	X	double		delta, distsq, len, t;
	X	double		r1p, r1psq, r2psq, r1sq;
	X	double		coord[3];
	X
	X	/*
	X	 * Initialize local variables
	X	 */
	X	me = &atom[n];
	X	if (me->nnb > 0) {
	X		nlist = (SNB *) emalloc(me->nnb * sizeof (SNB));
	X		endsnp = nlist + me->nnb;
	X	}
	X	else
	X		nlist = NULL;
	X
	X	/*
	X	 * Compute clipping distance for each neighbor
	X	 */
	X	r1p = me->atom.radius + radius;
	X	r1psq = r1p * r1p;
	X	r1sq = me->atom.radius * me->atom.radius;
	X	for (i = 0; i < me->nnb; i++) {
	X		sap = &atom[me->nb[i]];
	X		snp = &nlist[i];
	X		snp->coord = sap->atom.coord;
	X		distsq = 0;
	X		for (j = 0; j < 3; j++) {
	X			delta = me->atom.coord[j] - sap->atom.coord[j];
	X			distsq += delta * delta;
	X		}
	X		snp->dist = sqrt(distsq);
	X		delta = sap->atom.radius + radius;
	X		r2psq = delta * delta;
	X		len = (r1psq - r2psq + distsq) / (2 * snp->dist);
	X		t = len * me->atom.radius / r1p;
	X		snp->clip = r1sq + distsq - 2 * snp->dist * t;
	X	}
	X
	X	/*
	X	 * Now get a sphere and find all points which are not clipped
	X	 * by any of the neighbors.
	X	 */
	X	sp = get_sphere(me->atom.radius);
	X	endpp = sp->point + sp->npoint;
	X	if (sp->npoint > maxsurf) {
	X		if (surface != NULL) {
	X			(void) free((char *) surface);
	X			if (want_normal)
	X				(void) free((char *) normal);
	X		}
	X		maxsurf = sp->npoint;
	X		surface = (POINT *) emalloc(maxsurf * sizeof (POINT));
	X		if (want_normal)
	X			normal = (POINT *) emalloc(maxsurf * sizeof (POINT));
	X	}
	X	savepp = surface;
	X	savenp = normal;
	X	for (pp = sp->point; pp < endpp; pp++) {
	X		for (i = 0; i < 3; i++)
	X			coord[i] = me->atom.coord[i] + pp->coord[i];
	X		if (nlist != NULL && clipped(coord, nlist, endsnp))
	X			continue;
	X		for (i = 0; i < 3; i++)
	X			savepp->coord[i] = coord[i];
	X		savepp++;
	X		if (want_normal) {
	X			for (i = 0; i < 3; i++)
	X				savenp->coord[i] = pp->coord[i] / sp->radius;
	X			savenp++;
	X		}
	X	}
	X
	X	/*
	X	 * Now that we have the points, just send them back to caller
	X	 * and release the neighbor list
	X	 */
	X	i = savepp - surface;
	X	printf(SURFACE_RESPONSE, n, i, CONTACT, sp->area, want_normal);
	X#ifdef LOG
	X	fprintf(stderr, SURFACE_RESPONSE, n, i, CONTACT, sp->area, want_normal);
	X#endif
	X	if (i > 0) {
	X		(void) fwrite((char *) surface, sizeof (POINT), i, stdout);
	X		if (want_normal) {
	X			(void) fwrite((char *) normal, sizeof (POINT), i,
	X				stdout);
	X		}
	X	}
	X	fputs(SURFACE_END, stdout);
	X#ifdef LOG
	X	fputs(SURFACE_END, stderr);
	X#endif
	X
	X	if (nlist != NULL)
	X		(void) free((char *) nlist);
	X}
	X
	X/*
	X * get_sphere:
	X *	Return a prototype sphere of the given radius
	X */
	Xstatic
	XSPHERE *
	Xget_sphere(double r)
	X{
	X	register SPHERE	*sp;
	X	register int	i, j;
	X	register POINT	*pp;
	X	register int	nlayer, npoint;
	X	double		dphi, dtheta;
	X	double		phi, theta, z, rsinphi;
	X
	X	/*
	X	 * Look for one already on the list
	X	 */
	X	for (sp = sphere; sp != NULL; sp = sp->next)
	X		if (sp->radius == r)
	X			return sp;
	X
	X	/*
	X	 * Okay, it doesn't exist yet.  Let's make one.
	X	 */
	X	sp = (SPHERE *) emalloc(sizeof (SPHERE));
	X	sp->next = sphere;
	X	sphere = sp;
	X	sp->radius = r;
	X
	X	/*
	X	 * Easy part is done.  Now figure out how many points there
	X	 * should be on the sphere.
	X	 */
	X	dphi = arclength / r;
	X	nlayer = ROUND(PI / dphi) + 1;
	X	dphi = PI / nlayer;
	X	sp->npoint = 0;
	X	phi = 0;
	X	for (i = 0; i < nlayer; i++) {
	X		dtheta = (phi == 0) ? PI * 2 : arclength / (r * sin(phi));
	X		npoint = ROUND(PI * 2 / dtheta);
	X		if (npoint <= 0)
	X			npoint = 1;
	X		sp->npoint += npoint;
	X		phi += dphi;
	X	}
	X	sp->area = (4 * PI * r * r) / sp->npoint;
	X
	X	/*
	X	 * Allocate space for the points and, possibly, angles
	X	 */
	X	sp->point = (POINT *) emalloc(sp->npoint * sizeof (POINT));
	X
	X	/*
	X	 * Now we actually generate the points
	X	 */
	X	pp = sp->point;
	X	phi = 0;
	X	for (i = 0; i < nlayer; i++) {
	X		rsinphi = r * sin(phi);
	X		z = r * cos(phi);
	X		dtheta = (rsinphi == 0) ? PI * 2 : arclength / rsinphi;
	X		npoint = ROUND(PI * 2 / dtheta);
	X		if (npoint <= 0)
	X			npoint = 1;
	X		dtheta = PI * 2 / npoint;
	X		theta = (i % 2) ? 0 : PI;
	X		for (j = 0; j < npoint; j++) {
	X			pp->coord[0] = rsinphi * cos(theta);
	X			pp->coord[1] = rsinphi * sin(theta);
	X			pp->coord[2] = z;
	X			pp++;
	X			theta += dtheta;
	X			if (theta > PI * 2)
	X				theta -= PI * 2;
	X		}
	X		phi += dphi;
	X	}
	X
	X	return sp;
	X}
	X
	X/*
	X * clipped:
	X *	Determine if the given coordinate is clipped by any
	X *	of the given neighbors
	X */
	Xstatic
	Xint
	Xclipped(double coord[3], SNB *nlist, SNB *endsnp)
	X{
	X	register SNB	*snp;
	X	register int	i;
	X	double		delta, distsq;
	X
	X	for (snp = nlist; snp < endsnp; snp++) {
	X		distsq = 0;
	X		for (i = 0; i < 3; i++) {
	X			delta = snp->coord[i] - coord[i];
	X			distsq += delta * delta;
	X		}
	X		if (distsq < snp->clip)
	X			return TRUE;
	X	}
	X	return FALSE;
	X}
	X
	X/*
	X * tsurface:
	X *	Compute torus surface for neighbor pair
	X */
	Xstatic
	Xvoid
	Xtsurface(int n, int m)
	X{
	X	register int	i, j;
	X	register SATOM	*s1, *s2;
	X	register SANGLE	*ap, *anext;
	X	register SANGLE	*alist;
	X	double		tcenter[3], tradius, clip[2], coord[3];
	X	double		mat[4][4], invmat[4][4];
	X	int		na;
	X
	X	/*
	X	 * Initialize local variables
	X	 */
	X	s1 = &atom[n];
	X	s2 = &atom[m];
	X	if (!torus_data(&s1->atom, &s2->atom, tcenter, &tradius, clip)) {
	X		fputs(SURFACE_END, stdout);
	X#ifdef LOG
	X		fputs(SURFACE_END, stderr);
	X#endif
	X		return;
	X	}
	X	if (clip[0] > 0)
	X		lookat(mat, invmat, tcenter, s1->atom.coord);
	X	else {
	X		/* Note that we get the coordinates from s2 since clip[0]
	X		 * may be zero which would result in division by zero if
	X		 * we use coordinates from s1 */
	X		for (i = 0; i < 3; i++)
	X			coord[i] = tcenter[i] +
	X				(tcenter[i] - s2->atom.coord[i]);
	X		lookat(mat, invmat, tcenter, coord);
	X	}
	X
	X	alist = compute_angles(s1, s2, mat, &na);
	X	if (alist == NULL) {
	X#ifdef KEEP_REAL
	X		na = 0;
	X		for (i = 0; i < s1->nnb; i++)
	X			for (j = 0; j < s2->nnb; j++) {
	X				if (s1->nb[i] != s2->nb[j])
	X					continue;
	X				na++;
	X				break;
	X			}
	X#endif
	X		if (na == 0) {
	X			tsection(invmat, tradius, clip, 0.0, PI * 2,
	X				n, m, TRUE);
	X		}
	X	}
	X	else
	X		draw_tsections(invmat, tradius, clip, n, m, alist);
	X
	X	/*
	X	 * Release the angle list and return to caller
	X	 */
	X	for (ap = alist; ap != NULL; ap = anext) {
	X		anext = ap->next;
	X		(void) free((char *) ap);
	X	}
	X	fputs(SURFACE_END, stdout);
	X#ifdef LOG
	X	fputs(SURFACE_END, stderr);
	X#endif
	X}
	X
	X/*
	X * compute_angles:
	X *	Loop through the probe list for each atom and find those
	X *	probes which are on both list.
	X */
	X#ifdef KEEP_REAL
	X/*ARGSUSED*/
	X#endif
	Xstatic
	XSANGLE *
	Xcompute_angles(SATOM *s1, SATOM *s2, double mat[4][4], int *na)
	X{
	X	register int	i, j;
	X	register PROBE	*pp;
	X	register SANGLE	*alist, *ap;
	X
	X	alist = NULL;
	X	j = s2 - atom;
	X#ifndef KEEP_REAL
	X	*na = 0;
	X#endif
	X	for (i = 0; i < s1->nprobe; i++) {
	X		pp = &probe[s1->probe[i]];
	X		if (pp->atom[0] != j && pp->atom[1] != j && pp->atom[2] != j)
	X			continue;
	X#ifndef KEEP_REAL
	X		(*na)++;
	X#endif
	X		ap = probe_angle(s1->probe[i], mat, s1 - atom, j);
	X		ap->real = pp->real;
	X		alist = insert_angle(alist, ap);
	X	}
	X	return alist;
	X}
	X
	X/*
	X * draw_tsections:
	X *	Loop through the angle list and draw torus sections
	X */
	Xstatic
	Xvoid
	Xdraw_tsections(double invmat[4][4], double tradius, double clip[2], int n, int m, SANGLE *alist)
	X{
	X	register SANGLE	*ap, *anext;
	X
	X	for (ap = alist; ap != NULL; ap = ap->next) {
	X		if (!ap->start || !ap->real)
	X			continue;
	X		anext = (ap->next == NULL) ? alist : ap->next;
	X		tsection(invmat, tradius, clip, ap->angle,
	X			anext->angle, n, m, TRUE);
	X	}
	X}
	X
	X/*
	X * torus_data:
	X *	Compute data regarding the torus (e.g. center, radius, etc.)
	X */
	Xstatic
	Xint
	Xtorus_data(ATOM *a1, ATOM *a2, double tcenter[3], double *tradius, double clip[2])
	X{
	X	register int	i;
	X	double		distsq, dist;
	X	double		r1p, r2p;
	X	double		r1psq, r2psq, len;
	X	double		lsq;
	X
	X	/*
	X	 * Compute distance between atoms
	X	 */
	X	distsq = 0;
	X	for (i = 0; i < 3; i++) {
	X		dist = a1->coord[i] - a2->coord[i];
	X		distsq += dist * dist;
	X	}
	X	dist = sqrt(distsq);
	X
	X	/*
	X	 * Compute torus center and radius
	X	 */
	X	r1p = a1->radius + radius;
	X	r1psq = r1p * r1p;
	X	r2p = a2->radius + radius;
	X	r2psq = r2p * r2p;
	X	len = (r1psq - r2psq + distsq) / (2 * dist);
	X	lsq = r1psq - len * len;
	X	if (lsq <= 0)
	X		return 0;
	X	*tradius = sqrt(lsq);
	X	for (i = 0; i < 3; i++)
	X		tcenter[i] = a1->coord[i] +
	X			(a2->coord[i] - a1->coord[i]) * len / dist;
	X
	X	/*
	X	 * Now compute the clipping distance for the torus
	X	 */
	X	clip[0] = len * (1.0 - a1->radius / r1p);
	X	clip[1] = (dist - len) * (1.0 - a2->radius / r2p);
	X	return 1;
	X}
	X
	X/*
	X * probe_angle:
	X *	Determine the angle that the probe lies at
	X */
	Xstatic
	XSANGLE *
	Xprobe_angle(int pnum, double mat[4][4], int n, int m)
	X{
	X	register int	i, j;
	X	register PROBE	*pp;
	X	register SANGLE	*sp;
	X	register ATOM	*ap;
	X	double		angle;
	X	double		coord[3];
	X
	X	/*
	X	 * Allocate space for angle structure
	X	 */
	X	sp = (SANGLE *) emalloc(sizeof (SANGLE));
	X	sp->next = NULL;
	X	pp = &probe[pnum];
	X
	X	/*
	X	 * Compute the polar coordinates of the probe
	X	 */
	X	for (i = 0; i < 3; i++) {
	X		coord[i] = mat[3][i];
	X		for (j = 0; j < 3; j++)
	X			coord[i] += pp->coord[j] * mat[j][i];
	X	}
	X	sp->angle = atan2(coord[1], coord[0]);
	X
	X	/*
	X	 * Compute the polar coordinates of the atom which
	X	 * is adjacent to both given atoms
	X	 */
	X	for (i = 0; i < 3; i++)
	X		if (pp->atom[i] != n && pp->atom[i] != m)
	X			break;
	X	ap = &atom[pp->atom[i]].atom;
	X	for (i = 0; i < 3; i++) {
	X		coord[i] = mat[3][i];
	X		for (j = 0; j < 3; j++)
	X			coord[i] += ap->coord[j] * mat[j][i];
	X	}
	X	angle = atan2(coord[1], coord[0]);
	X
	X	/*
	X	 * Now determine whether the torus section should start or
	X	 * end here
	X	 */
	X	angle = angle - sp->angle;
	X	while (angle < 0)
	X		angle += PI * 2;
	X	sp->start = (angle >= PI);
	X	if (sp->angle < 0)
	X		sp->angle += PI * 2;
	X
	X	return sp;
	X}
	X
	X/*
	X * insert_angle:
	X *	Insert an angle into a list and return the head of the list.
	X *	If there are two identical angles, we put the start before the end
	X *	to eliminate the surface since this mostly occurs near rings.
	X */
	Xstatic
	XSANGLE *
	Xinsert_angle(SANGLE *head, SANGLE *new)
	X{
	X	register SANGLE	*ap;
	X
	X	/*
	X	 * See if the new angle should be at the beginning
	X	 */
	X	if (head == NULL || new->angle < head->angle
	X	|| (new->angle == head->angle && !head->start)) {
	X		new->next = head;
	X		return new;
	X	}
	X
	X	/*
	X	 * Find the angle whose successor is greater than the new angle.
	X	 * Add the angle after this one and return the original head
	X	 * of the list.
	X	 */
	X	for (ap = head; ap->next != NULL; ap = ap->next) {
	X		if (ap->next->angle > new->angle
	X		|| (ap->next->angle == new->angle && !ap->next->start))
	X			break;
	X	}
	X	new->next = ap->next;
	X	ap->next = new;
	X	return head;
	X}
	X
	X/*
	X * tsection:
	X *	Generate a section of a torus
	X *
	X *	The area of described by an arc swept through an angle is:
	X *		A = (integral) (integral) (r de) ds
	X *	where
	X *		 r = Rt - Rs cos a
	X *		ds = Rs da
	X *	so
	X *		A = (i) (i) (Rt - Rs cos a) Rs da de
	X *		  = e a Rt Rs - e Rs Rs (integral) cos a da
	X *		  = e Rt a Rs - e Rs Rs sin a
	X *	Symbols are:
	X *		Rs = radius of arc
	X *		Rt = arc displacement from origin
	X *		 a = angle of arc
	X *		 e = angle swept through
	X */
	Xstatic
	Xvoid
	Xtsection(double invmat[4][4], double tradius, double clip[2], double start, double end, int n, int m, int check)
	X{
	X	register int	i, j;
	X	register int	npoint;
	X	register POINT	*pp, *np;
	X	register int	na, ne;
	X	POINT		*plist, *nlist;
	X	double		area;
	X	double		mina, maxa;
	X	double		aincr, eincr;
	X	double		arange, erange;
	X	double		e, a, mida;
	X	double		nclip[2];
	X	int		eoffset;
	X	int		startm;
	X	double		coord[3], xy;
	X	double		cose, sine;
	X	double		normal[3];
	X
	X	/*
	X	 * First see whether the torus is really a torus.
	X	 * If the probe extends below the center line between
	X	 * the two atoms, only the portion which is above the center
	X	 * line should be used for sweeping out the torus.
	X	 */
	X	if (check && tradius < radius) {
	X		xy = sqrt(radius * radius - tradius * tradius);
	X		clip[1] = -clip[1];
	X		if (clip[1] < -xy && -xy < clip[0]) {
	X			nclip[0] = -xy;
	X			nclip[1] = -clip[1];
	X			tsection(invmat, tradius, nclip, start, end,
	X				n, m, FALSE);
	X		}
	X		if (clip[1] < xy && xy < clip[0]) {
	X			nclip[0] = clip[0];
	X			nclip[1] = -xy;
	X			tsection(invmat, tradius, nclip, start, end,
	X				n, m, FALSE);
	X		}
	X		return;
	X	}
	X
	X	/*
	X	 * Figure out basic parameters
	X	 */
	X	maxa = -acos(clip[0] / radius);
	X	mina = -acos(-clip[1] / radius);
	X	arange = maxa - mina;
	X	if (end < start)
	X		end += PI * 2;
	X	erange = end - start;
	X	area = erange * tradius * arange * radius -
	X		erange * radius * radius *
	X		(sin(maxa + PI / 2) + sin(-PI / 2  - mina));
	X
	X	/*
	X	 * Now figure out the maximum number of points there might be
	X	 * and allocate space for them
	X	 */
	X	ne = ROUND(erange * tradius / arclength);
	X	if (ne <= 0)
	X		return;
	X	na = ROUND(arange * radius / (arclength * root3 / 2));
	X	if (na <= 0)
	X		return;
	X	npoint = na * ne;
	X	plist = (POINT *) emalloc(npoint * sizeof (POINT));
	X	if (want_normal)
	X		nlist = (POINT *) emalloc(npoint * sizeof (POINT));
	X	else
	X		nlist = NULL;
	X
	X	/*
	X	 * Now loop through a and e and generate the points
	X	 */
	X	pp = plist;
	X	np = nlist;
	X	eoffset = 0;
	X	mida = (mina + maxa) / 2;
	X	aincr = arange / na;
	X	a = mina + aincr / 2;
	X	startm = 0;
	X	while (na-- > 0) {
	X		/*
	X		 * Compute things that only depend on a
	X		 */
	X		coord[2] = radius * cos(a);
	X		if (want_normal)
	X			normal[2] = -coord[2] / radius;
	X		xy = radius * sin(a) + tradius;
	X
	X		/*
	X		 * Loop through e and generate points
	X		 */
	X		ne = ROUND(erange * xy / arclength);
	X		if (ne > 0) {
	X			eincr = erange / ne;
	X			e = start + eincr / 2 * (eoffset + 1);
	X			eoffset = 1 - eoffset;
	X		}
	X		while (ne-- > 0) {
	X#ifdef DEBUG
	X			if (pp >= plist + npoint) {
	X				fprintf(stderr, "Point buffer overflow\n");
	X				abort();
	X			}
	X#endif
	X			cose = cos(e);
	X			sine = sin(e);
	X			coord[0] = xy * cose;
	X			coord[1] = xy * sine;
	X			for (i = 0; i < 3; i++) {
	X				pp->coord[i] = invmat[3][i];
	X				for (j = 0; j < 3; j++)
	X					pp->coord[i] += coord[j] * invmat[j][i];
	X			}
	X			pp++;
	X			e += eincr;
	X			if (!want_normal)
	X				continue;
	X			normal[0] = (tradius * cose - coord[0]) / radius;
	X			normal[1] = (tradius * sine - coord[1]) / radius;
	X			for (i = 0; i < 3; i++) {
	X				np->coord[i] = 0;	/* Just rotation */
	X				for (j = 0; j < 3; j++)
	X					np->coord[i] += normal[j] *
	X						invmat[j][i];
	X			}
	X			np++;
	X		}
	X
	X		/*
	X		 * Increment a.  If we pass the -PI/2 threshold, we will
	X		 * start generating points on atom m.
	X		 */
	X		a += aincr;
	X		if (a > mida && startm == 0)
	X			startm = pp - plist;
	X	}
	X
	X	/*
	X	 * Send point data back to the caller and clean up
	X	 */
	X	npoint = pp - plist;
	X	if (npoint > 0) {
	X		area = area / npoint;
	X		send_points(plist, startm, m, area, TREENTRANT, nlist);
	X		send_points(plist + startm, npoint - startm, n,
	X			area, TREENTRANT, nlist + startm);
	X	}
	X	(void) free((char *) plist);
	X	if (nlist != NULL)
	X		(void) free((char *) nlist);
	X}
	X
	X/*
	X * send_points:
	X *	Send points back to caller
	X */
	Xstatic
	Xvoid
	Xsend_points(POINT *plist, int np, AINDEX aindex, double area, int type, POINT *nlist)
	X{
	X	if (np <= 0)
	X		return;
	X	printf(SURFACE_RESPONSE, aindex, np, type, area, want_normal);
	X#ifdef LOG
	X	fprintf(stderr, SURFACE_RESPONSE, aindex, np, type, area,
	X		want_normal);
	X#endif
	X	(void) fwrite((char *) plist, sizeof (POINT), np, stdout);
	X	if (want_normal)
	X		(void) fwrite((char *) nlist, sizeof (POINT), np, stdout);
	X}
	X
	X/*
	X * psurface:
	X *	Generate surface associated with a probe
	X */
	Xstatic
	Xvoid
	Xpsurface(int n)
	X{
	X	register int	i, j, k;
	X	register POINT	*pp;
	X	register PROBE	*prp;
	X	register SATOM	*sap;
	X	register SPHERE	*sp;
	X	int		which;
	X	double		minr, r, delta;
	X	POINT		*point, *plist[3], *normal, *nlist[3];
	X	short		*keep, np[3];
	X
	X	/*
	X	 * Initialize local variables and allocate space
	X	 */
	X	prp = &probe[n];
	X	sp = get_sphere(radius);
	X	for (i = 0; i < 3; i++) {
	X		np[i] = 0;
	X		plist[i] = (POINT *) emalloc(sp->npoint * sizeof (POINT));
	X	}
	X	point = (POINT *) emalloc(sp->npoint * sizeof (POINT));
	X	keep = (short *) emalloc(sp->npoint * sizeof (short));
	X	for (i = 0; i < sp->npoint; i++) {
	X		keep[i] = TRUE;
	X		pp = &point[i];
	X		for (j = 0; j < 3; j++)
	X			pp->coord[j] = sp->point[i].coord[j] + prp->coord[j];
	X	}
	X	if (want_normal) {
	X		normal = (POINT *) emalloc(sp->npoint * sizeof (POINT));
	X		for (i = 0; i < sp->npoint; i++) {
	X			pp = &normal[i];
	X			for (j = 0; j < 3; j++)
	X				pp->coord[j] = -sp->point[i].coord[j] / radius;
	X		}
	X		for (i = 0; i < 3; i++)
	X			nlist[i] = (POINT *) emalloc(sp->npoint *
	X				sizeof (POINT));
	X	}
	X	else {
	X		normal = NULL;
	X		nlist[0] = nlist[1] = nlist[2] = NULL;
	X	}
	X
	X	/*
	X	 * Now we eliminate those points which do not fall within the
	X	 * spherical triangle formed by the three specified atoms.
	X	 * The way we do this is by defining a plane for each pair of
	X	 * atoms and the probe center.  The plane divides space into two
	X	 * half-spaces, one of which contains the third atom not used in
	X	 * defining the plane.  If a point does not fall in the same
	X	 * half-space as the third atom, then it is eliminated.  Only
	X	 * the wanted points will remain after all three planes have been
	X	 * used.
	X	 */
	X	for (i = 0; i < 3; i++)
	X		for (j = i + 1; j < 3; j++)
	X			check_point(prp, i, j, 3 - i - j,
	X				sp->npoint, point, keep);
	X
	X	/*
	X	 * Now we divide the points up among the three atoms.
	X	 */
	X	for (i = 0; i < sp->npoint; i++) {
	X		if (!keep[i])
	X			continue;
	X		pp = &point[i];
	X		which = -1;
	X#ifdef lint
	X		minr = 0;
	X#endif
	X		for (j = 0; j < 3; j++) {
	X			sap = &atom[prp->atom[j]];
	X			r = 0;
	X			for (k = 0; k < 3; k++) {
	X				delta = pp->coord[k] - sap->atom.coord[k];
	X				r += delta * delta;
	X			}
	X			if (which == -1 || r < minr) {
	X				minr = r;
	X				which = j;
	X			}
	X		}
	X		if (want_normal)
	X			nlist[which][np[which]] = normal[i];
	X		plist[which][np[which]++] = *pp;
	X	}
	X
	X	/*
	X	 * Send the points back to caller and clean up
	X	 */
	X	for (i = 0; i < 3; i++) {
	X		send_points(plist[i], np[i], prp->atom[i], sp->area,
	X			SREENTRANT, nlist[i]);
	X		(void) free((char *) plist[i]);
	X		if (want_normal)
	X			(void) free((char *) nlist[i]);
	X	}
	X	fputs(SURFACE_END, stdout);
	X#ifdef LOG
	X	fputs(SURFACE_END, stderr);
	X#endif
	X	(void) free((char *) point);
	X	(void) free((char *) keep);
	X	if (want_normal)
	X		(void) free((char *) normal);
	X}
	X
	X/*
	X * check_point:
	X *	Determine which of the given points should be kept
	X */
	Xstatic
	Xvoid
	Xcheck_point(PROBE *prp, int at, int up, int side, int npoint, POINT point[], short keep[])
	X{
	X	register int	i, sign;
	X	double		mat[4][4], invmat[4][4];
	X	double		x;
	X	double		*dp;
	X	double		*fp;
	X
	X	/*
	X	 * Construct a matrix which transforms the probe center to
	X	 * the origin, the at atom to the z-axis, and the up atom
	X	 * into the y-z plane.  Then transform the side atom to determine
	X	 * the sign of the x-component of the half-space to keep.
	X	 */
	X	viewat(mat, invmat, prp->coord, atom[prp->atom[at]].atom.coord,
	X		atom[prp->atom[up]].atom.coord);
	X	dp = atom[prp->atom[side]].atom.coord;
	X	x = dp[0] * mat[0][0] + dp[1] * mat[1][0] + dp[2] * mat[2][0]
	X		+ mat[3][0];
	X	sign = (x < 0) ? -1 : 1;
	X
	X	/*
	X	 * Now we loop through the points and check each one
	X	 */
	X	for (i = 0; i < npoint; i++) {
	X		if (!keep[i])
	X			continue;
	X		fp = point[i].coord;
	X		x = fp[0] * mat[0][0] + fp[1] * mat[1][0] + fp[2] * mat[2][0]
	X			+ mat[3][0];
	X		if ((sign < 0 && x > 0) || (sign > 0 && x < 0))
	X			keep[i] = FALSE;
	X	}
	X}
SHAR_EOF
if test 42201 -ne "`wc -c < 'server.c'`"
then
	echo shar: "error transmitting 'server.c'" '(should have been 42201 characters)'
fi
fi
echo shar: "extracting 'test.pdb'" '(518 characters)'
if test -f 'test.pdb'
then
	echo shar: "will not over-write existing file 'test.pdb'"
else
sed 's/^	X//' << \SHAR_EOF > 'test.pdb'
	XUSER  PDBRUN  6
	XUSER  EYEPOS    25.740    21.520   200.737
	XUSER  ATPOS     25.740    21.520    10.132
	XUSER  WINDOW   -29.271    29.271   -39.849    39.849   162.687   221.229
	XUSER  FOCUS    190.606
	XUSER  VIEWPORT     0.000   523.000     0.000   712.000
	XUSER  BGCOLOR 0.000 0.000 0.000
	XUSER  FILE    0 1gcn
	XUSER  COLOR 1.000 1.000 1.000 0
	XUSER  RADIUS   1.400
	XATOM      2  OX1 CYX     1       2.114  20.456  22.080  1.00 16.00
	XUSER  RADIUS   1.800
	XATOM      1  CX2 CYX     1       1.819  20.541  22.411  1.00 25.00
	XEND
SHAR_EOF
if test 518 -ne "`wc -c < 'test.pdb'`"
then
	echo shar: "error transmitting 'test.pdb'" '(should have been 518 characters)'
fi
fi
echo shar: "extracting 'viewat.c'" '(3017 characters)'
if test -f 'viewat.c'
then
	echo shar: "will not over-write existing file 'viewat.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'viewat.c'
	X/*
	X
	XCopyright (c) <2002> The Regents of the University of California.
	XAll rights reserved.
	X
	XRedistribution and use in source and binary forms, with or without
	Xmodification, are permitted provided that the following conditions
	Xare met:
	X  1. Redistributions of source code must retain the above copyright
	X     notice, this list of conditions, and the following disclaimer.
	X  2. Redistributions in binary form must reproduce the above
	X     copyright notice, this list of conditions, and the following
	X     disclaimer in the documentation and/or other materials provided
	X     with the distribution.
	X  3. Redistributions must acknowledge that this software was
	X     originally developed by the UCSF Computer Graphics Laboratory
	X     under support by the NIH National Center for Research Resources,
	X     grant P41-RR01081.
	X
	XTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
	XEXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
	XIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
	XPURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS BE LIABLE
	XFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
	XCONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
	XOF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
	XBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
	XWHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
	XOR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
	XEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
	X
	X */
	X#include <stdio.h>
	X#include <math.h>
	X
	Xstatic void	nmcrosprod();
	X
	Xvoid viewat(M, invM, P1, P2, P3)
	Xdouble	M[4][4], invM[4][4];
	Xdouble	P1[3], P2[3], P3[3];
	X{
	X	double	d12;
	X	double	P12X, P12Y, P12Z, P13X, P13Y, P13Z;
	X	double	lm[3][3];
	X	register int	i, j;
	X
	X	P12X = P2[0] - P1[0];
	X	P12Y = P2[1] - P1[1];
	X	P12Z = P2[2] - P1[2];
	X	P13X = P3[0] - P1[0];
	X	P13Y = P3[1] - P1[1];
	X	P13Z = P3[2] - P1[2];
	X
	X	d12 = sqrt((P12X)*(P12X) + (P12Y)*(P12Y) + (P12Z)*(P12Z));
	X	lm[0][2] = (P12X) / d12;
	X	lm[1][2] = (P12Y) / d12;
	X	lm[2][2] = (P12Z) / d12;
	X	nmcrosprod(P13X, P13Y, P13Z, P12X, P12Y, P12Z,
	X		&lm[0][0], &lm[1][0], &lm[2][0]);
	X	nmcrosprod(lm[0][2], lm[1][2], lm[2][2],
	X		lm[0][0], lm[1][0], lm[2][0], 
	X		&lm[0][1], &lm[1][1], &lm[2][1]);
	X
	X	for (i = 0; i < 3; i++) {
	X		invM[3][i] = P1[i];
	X		M[i][3] = invM[i][3] = 0;
	X		for (j = 0; j < 3; j++) {
	X			M[i][j] = lm[i][j];
	X			invM[j][i] = M[i][j];
	X		}
	X	}
	X	M[3][0] = -P1[0]*M[0][0] - P1[1]*M[1][0] - P1[2]*M[2][0];
	X	M[3][1] = -P1[0]*M[0][1] - P1[1]*M[1][1] - P1[2]*M[2][1];
	X	M[3][2] = -P1[0]*M[0][2] - P1[1]*M[1][2] - P1[2]*M[2][2];
	X	M[3][3] = invM[3][3] = 1;
	X}
	X
	Xstatic
	Xvoid
	Xnmcrosprod(x1, y1, z1, x2, y2, z2, x3, y3, z3)
	Xdouble	x1, y1, z1, x2, y2, z2;			/* r1 cross r2 */
	Xdouble	*x3, *y3, *z3;				/* Normalized crossproduct */
	X{
	X	double	dis;	/* length of crossproduct vector r1 x r2 */
	X	double	x,y,z;
	X
	X	x = y1*z2 - y2*z1;
	X	y = z1*x2 - z2*x1;
	X	z = x1*y2 - x2*y1;
	X
	X	dis = sqrt((x*x) + (y*y) + (z*z));
	X
	X	*x3 = x / dis;
	X	*y3 = y / dis;
	X	*z3 = z / dis;
	X}
SHAR_EOF
if test 3017 -ne "`wc -c < 'viewat.c'`"
then
	echo shar: "error transmitting 'viewat.c'" '(should have been 3017 characters)'
fi
fi
echo shar: "done with directory 'dmsd'"
cd ..
echo shar: "extracting 'dms_param.h'" '(2619 characters)'
if test -f 'dms_param.h'
then
	echo shar: "will not over-write existing file 'dms_param.h'"
else
sed 's/^	X//' << \SHAR_EOF > 'dms_param.h'
	X/*
	X
	XCopyright (c) <2002> The Regents of the University of California.
	XAll rights reserved.
	X
	XRedistribution and use in source and binary forms, with or without
	Xmodification, are permitted provided that the following conditions
	Xare met:
	X  1. Redistributions of source code must retain the above copyright
	X     notice, this list of conditions, and the following disclaimer.
	X  2. Redistributions in binary form must reproduce the above
	X     copyright notice, this list of conditions, and the following
	X     disclaimer in the documentation and/or other materials provided
	X     with the distribution.
	X  3. Redistributions must acknowledge that this software was
	X     originally developed by the UCSF Computer Graphics Laboratory
	X     under support by the NIH National Center for Research Resources,
	X     grant P41-RR01081.
	X
	XTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
	XEXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
	XIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
	XPURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS BE LIABLE
	XFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
	XCONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
	XOF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
	XBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
	XWHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
	XOR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
	XEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
	X
	X */
	X
	X#define	DEF_DIR(x)	DESTLIB#x
	X
	X/*
	X * SERVER_FILE contains a list of hosts that run dms servers (and are
	X * binary-compatible with the host running dms)
	X */
	X#define	SERVER_FILE	"dms_servers"
	X#define	DEF_SERVER_FILE	DEF_DIR(dms_servers)
	X
	X/*
	X * RADII_FILE contains a list of radii
	X */
	X#define	RADII_FILE	"radii"
	X#define	DEF_RADII_FILE	DEF_DIR(radii)
	X
	X/*
	X * LOCK_FILE is the name of the file that a dms server tries to lock.
	X * If the file exists and the lock fails, then the server will exit.
	X */
	X#define	LOCK_FILE	DEF_DIR(lockfile)
	X
	X/*
	X * NICE_PRIORITY is the priority that a dms server sets itself to.
	X */
	X#define	NICE_PRIORITY	15
	X
	X/* 
	X * The following #defines are for possible code options.  The best
	X * combination for running on Suns is currently selected.  Your mileage
	X * may vary with other (e.g. vectorizing) compilers.
	X */
	X#define SORTED_NB	/* Neighbor list sorted by distance */
	X#undef	ONE_OCCLUDE	/* Only check occlusion after summing components */
	X#define KEEP_REAL	/* Keep only non-hidden probes */
	X#define RETRANS_NB	/* Retransmit shortened neighbor list to servers */
SHAR_EOF
if test 2619 -ne "`wc -c < 'dms_param.h'`"
then
	echo shar: "error transmitting 'dms_param.h'" '(should have been 2619 characters)'
fi
fi
echo shar: "extracting 'dms_servers.proto'" '(10 characters)'
if test -f 'dms_servers.proto'
then
	echo shar: "will not over-write existing file 'dms_servers.proto'"
else
sed 's/^	X//' << \SHAR_EOF > 'dms_servers.proto'
	Xlocalhost
SHAR_EOF
if test 10 -ne "`wc -c < 'dms_servers.proto'`"
then
	echo shar: "error transmitting 'dms_servers.proto'" '(should have been 10 characters)'
fi
fi
echo shar: "extracting 'emalloc.c'" '(2367 characters)'
if test -f 'emalloc.c'
then
	echo shar: "will not over-write existing file 'emalloc.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'emalloc.c'
	X/*
	X
	XCopyright (c) <2002> The Regents of the University of California.
	XAll rights reserved.
	X
	XRedistribution and use in source and binary forms, with or without
	Xmodification, are permitted provided that the following conditions
	Xare met:
	X  1. Redistributions of source code must retain the above copyright
	X     notice, this list of conditions, and the following disclaimer.
	X  2. Redistributions in binary form must reproduce the above
	X     copyright notice, this list of conditions, and the following
	X     disclaimer in the documentation and/or other materials provided
	X     with the distribution.
	X  3. Redistributions must acknowledge that this software was
	X     originally developed by the UCSF Computer Graphics Laboratory
	X     under support by the NIH National Center for Research Resources,
	X     grant P41-RR01081.
	X
	XTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
	XEXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
	XIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
	XPURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS BE LIABLE
	XFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
	XCONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
	XOF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
	XBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
	XWHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
	XOR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
	XEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
	X
	X */
	X#include <stdio.h>
	X#include <stdlib.h>
	X
	X/*
	X * emalloc:
	X *	Same as malloc but exits when failure occurs
	X */
	Xchar *
	Xemalloc(size)
	Xunsigned	size;
	X{
	X	register char	*cp;
	X
	X	if ((cp = malloc(size)) == NULL) {
	X		fprintf(stderr, "emalloc(%u) failed\n", size);
	X		exit(1);
	X	}
	X	return cp;
	X}
	X
	X/*
	X * erealloc:
	X *	Same as realloc but exits when failure occurs
	X */
	Xchar *
	Xerealloc(ptr, size)
	Xchar		*ptr;
	Xunsigned	size;
	X{
	X	register char	*cp;
	X
	X	if ((cp = realloc(ptr, size)) == NULL) {
	X		fprintf(stderr, "erealloc(ptr, %u) failed\n", size);
	X		exit(1);
	X	}
	X	return cp;
	X}
	X
	X/*
	X * ecalloc:
	X *	Same as calloc but exits when failure occurs
	X */
	Xchar *
	Xecalloc(nelem, elsize)
	Xunsigned nelem, elsize;
	X{
	X	register char	*cp;
	X
	X	if ((cp = calloc(nelem, elsize)) == NULL) {
	X		fprintf(stderr, "calloc(%u, %u) failed\n", nelem, elsize);
	X		exit(1);
	X	}
	X	return cp;
	X}
SHAR_EOF
if test 2367 -ne "`wc -c < 'emalloc.c'`"
then
	echo shar: "error transmitting 'emalloc.c'" '(should have been 2367 characters)'
fi
fi
echo shar: "extracting 'fwritev.c'" '(1906 characters)'
if test -f 'fwritev.c'
then
	echo shar: "will not over-write existing file 'fwritev.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'fwritev.c'
	X/*
	X
	XCopyright (c) <2002> The Regents of the University of California.
	XAll rights reserved.
	X
	XRedistribution and use in source and binary forms, with or without
	Xmodification, are permitted provided that the following conditions
	Xare met:
	X  1. Redistributions of source code must retain the above copyright
	X     notice, this list of conditions, and the following disclaimer.
	X  2. Redistributions in binary form must reproduce the above
	X     copyright notice, this list of conditions, and the following
	X     disclaimer in the documentation and/or other materials provided
	X     with the distribution.
	X  3. Redistributions must acknowledge that this software was
	X     originally developed by the UCSF Computer Graphics Laboratory
	X     under support by the NIH National Center for Research Resources,
	X     grant P41-RR01081.
	X
	XTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
	XEXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
	XIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
	XPURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS BE LIABLE
	XFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
	XCONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
	XOF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
	XBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
	XWHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
	XOR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
	XEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
	X
	X */
	X#include <stdio.h>
	X#include <sys/types.h>
	X#include <sys/uio.h>
	X
	X/*
	X * fwritev:
	X *	Like writev system call except we use stdio library
	X */
	Xvoid fwritev(fp, iov, n)
	XFILE		*fp;
	Xstruct iovec	*iov;
	Xint		n;
	X{
	X	register struct iovec	*ip, *endip;
	X
	X	endip = iov + n;
	X	for (ip = iov; ip < endip; ip++)
	X		(void) fwrite((char *) ip->iov_base, sizeof (char),
	X			ip->iov_len, fp);
	X}
SHAR_EOF
if test 1906 -ne "`wc -c < 'fwritev.c'`"
then
	echo shar: "error transmitting 'fwritev.c'" '(should have been 1906 characters)'
fi
fi
echo shar: "extracting 'GNUmakefile'" '(1805 characters)'
if test -f 'GNUmakefile'
then
	echo shar: "will not over-write existing file 'GNUmakefile'"
else
sed 's/^	X//' << \SHAR_EOF > 'GNUmakefile'
	X# LIBDIR is the directory where a 'dms' subdirectory will be created,
	X# in which the server binary (dmsd) and various support files will be installed
	XLIBDIR  = /usr/local/lib
	X
	X# BINDIR is the directory where the dms binary will be installed
	XBINDIR  = /usr/local/bin
	X
	X# PDBINC is the directory where the 'pdb.h' file from the UCSF PDB-reading
	X# library got installed.  'pdb.h' is not installed by default by that
	X# distribution, so you will have to install it by hand into PDBINC
	XPDBINC  = libpdb
	X
	X# PDBLIB is the directory where libpdb.a from the UCSF PDB-reading library 
	X# got installed.
	XPDBLIB  = libpdb
	X
	X# MANDIR is the directory where the dms.1 manual page will be installed
	XMANDIR  = /usr/local/man/man1
	X
	Xifeq ($(shell test -e /bin/cygwin1.dll && echo found),found)
	X	PROG	= dms.exe
	Xelse
	X	PROG	= dms
	Xendif
	X
	X# you should not need to modify any of the following
	XDESTLIB	= ${LIBDIR}/dms/
	XSERVER	= ${DESTLIB}dmsd
	XDEFS	= -DDESTLIB=\"${DESTLIB}\" -DSERVER_PATH=\"$(SERVER)\"
	XOPT	= -O
	XCFLAGS  = ${DEFS} -I${PDBINC} ${OPT}
	X
	XOBJS	= compute.o fwritev.o input.o ms.o output.o emalloc.o tokenize.o
	X
	Xall:	${PROG}
	X	cd dmsd ; ${MAKE} LIBDIR=${LIBDIR} OPT="${OPT}"
	X
	X${PROG}: pdb ${OBJS}
	X	${CC} -L${PDBLIB} -o ${PROG} ${OBJS} -lpdb
	X
	Xpdb:
	X	cd libpdb ; ${MAKE} OPT="${OPT}"
	X
	Xinstall: ${PROG} maninstall afterinstall
	Xafterinstall: realinstall
	Xrealinstall: beforeinstall
	X	cp ${PROG} ${BINDIR}
	X	-strip ${BINDIR}/${PROG}
	X
	Xmaninstall:
	X	-rm -f ${MANDIR}/dms.1
	X	cp dms.1 ${MANDIR}
	X
	Xbeforeinstall:
	X	if [ -d ${DESTLIB} ]; then true ; else mkdir ${DESTLIB}; fi
	X	cd dmsd ; ${MAKE} LIBDIR=${LIBDIR} install
	X
	Xafterinstall:
	X	cp radii.proto ${DESTLIB}radii
	X
	Xclean:
	X	/bin/rm -f ${OBJS}
	X	cd libpdb ; ${MAKE} clean
	X	cd dmsd ; ${MAKE} clean
	X
	Xspotless:
	X	/bin/rm -f ${OBJS} ${PROG}
	X	cd libpdb ; ${MAKE} spotless
	X	cd dmsd ; ${MAKE} spotless
SHAR_EOF
if test 1805 -ne "`wc -c < 'GNUmakefile'`"
then
	echo shar: "error transmitting 'GNUmakefile'" '(should have been 1805 characters)'
fi
fi
echo shar: "extracting 'input.c'" '(7789 characters)'
if test -f 'input.c'
then
	echo shar: "will not over-write existing file 'input.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'input.c'
	X/*
	X
	XCopyright (c) <2002> The Regents of the University of California.
	XAll rights reserved.
	X
	XRedistribution and use in source and binary forms, with or without
	Xmodification, are permitted provided that the following conditions
	Xare met:
	X  1. Redistributions of source code must retain the above copyright
	X     notice, this list of conditions, and the following disclaimer.
	X  2. Redistributions in binary form must reproduce the above
	X     copyright notice, this list of conditions, and the following
	X     disclaimer in the documentation and/or other materials provided
	X     with the distribution.
	X  3. Redistributions must acknowledge that this software was
	X     originally developed by the UCSF Computer Graphics Laboratory
	X     under support by the NIH National Center for Research Resources,
	X     grant P41-RR01081.
	X
	XTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
	XEXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
	XIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
	XPURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS BE LIABLE
	XFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
	XCONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
	XOF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
	XBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
	XWHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
	XOR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
	XEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
	X
	X */
	X#include <stdio.h>
	X#include <ctype.h>
	X#include <math.h>
	X#include <strings.h>
	X#include <pdb.h>
	X#include "dms_param.h"
	X#include "atoms.h"
	X#include "wanted.h"
	X
	X#ifndef	DEBUG
	X#define	STATIC	static
	X#else
	X#define	STATIC
	X#endif
	X
	X#ifndef	TRUE
	X#define	TRUE	1
	X#define	FALSE	0
	X#endif
	X
	XSTATIC int	is_aa();
	Xvoid scopy(char*, char*, int);
	Xchar		(*resseqs)[RN_LEN];
	Xint		numresseq;
	X
	X/*
	X * read_pdb:
	X *	Read the given pdb file and put all the atoms into a list.
	X */
	XATOM *
	Xread_pdb(file, all)
	Xchar	*file;
	Xint	all;
	X{
	X	register ATOM		*cp;
	X	FILE			*fp;
	X	ATOM			*alist, *ap;
	X	pdb_record		r;
	X	struct pdb_atom		*atp;
	X	pdb_residue		*resp;
	X	extern char		*emalloc();
	X	char			prevresseq[RN_LEN];
	X	int			index;
	X
	X	if ((fp = fopen(file, "r")) == NULL) {
	X		perror(file);
	X		return NULL;
	X	}
	X	alist = NULL;
	X	prevresseq[0] = '\0';
	X	numresseq = 0;
	X	do {
	X		r = pdb_read_record(fp);
	X		switch(r.record_type) {
	X		  case PDB_END:
	X		  case PDB_UNKNOWN:
	X		  case PDB_TER:
	X			break;
	X		  case PDB_HETATM:
	X			if (!all)
	X				break;
	X			/* FALLTHROUGH */
	X		  case PDB_ATOM:
	X			atp = &r.pdb.atom;
	X			resp = &atp->residue;
	X			if (!all && !is_aa(resp->name))
	X				break;
	X			cp = (ATOM *) emalloc(sizeof (ATOM));
	X			cp->coord[0] = r.pdb.atom.x;
	X			cp->coord[1] = r.pdb.atom.y;
	X			cp->coord[2] = r.pdb.atom.z;
	X			scopy(cp->atname, atp->name, sizeof (atp->name));
	X			scopy(cp->restype, resp->name, sizeof (resp->name));
	X			/*
	X			 * The residue sequence is composed of the
	X			 * sequence number concatenated with the insertion
	X			 * code and chain identifier (if they exist)
	X			 */
	X			(void) sprintf(cp->resseq, "%d", resp->seq_num);
	X			if (isalnum(resp->insert_code))
	X				(void) strncat(cp->resseq,
	X					&resp->insert_code, 1);
	X			if (isalnum(resp->chain_id))
	X				(void) strncat(cp->resseq,
	X					&resp->chain_id, 1);
	X			if (r.record_type == PDB_HETATM)
	X				(void) strncat(cp->resseq, "*", 1);
	X			if (strcmp(cp->resseq, prevresseq) != 0) {
	X				strcpy(prevresseq, cp->resseq);
	X				numresseq++;
	X			}
	X			cp->resindex = numresseq-1;
	X			cp->next = NULL;
	X			if (alist == NULL)
	X				alist = cp;
	X			else
	X				ap->next = cp;
	X			ap = cp;
	X			break;
	X		  default:
	X			break;
	X		}
	X	} while (r.record_type != PDB_END);
	X	(void) fclose(fp);
	X	if (alist == NULL)
	X		return alist;
	X	resseqs = (char (*)[RN_LEN]) emalloc(numresseq * RN_LEN);
	X	strcpy(resseqs[0], alist->resseq);
	X	index = 0;
	X	for (ap = alist->next; ap != NULL; ap = ap->next) {
	X		if (strcmp(ap->resseq, resseqs[index]) != 0) {
	X			index++;
	X			strcpy(resseqs[index], ap->resseq);
	X		}
	X	}
	X	if (index+1 != numresseq) {
	X		fprintf(stderr,
	X		  "Internal error: residue ID numbering mismatch.\n");
	X		exit(1);
	X	}
	X	return alist;
	X}
	X
	X/*
	X * scopy:
	X *	Copy strings without copying blanks
	X */
	Xvoid scopy(to, from, max)
	Xregister char	*to, *from;
	Xregister int	max;
	X{
	X	while (max-- > 0 && *from != '\0')
	X		if (!isspace(*from))
	X			*to++ = *from++;
	X		else
	X			from++;
	X	*to = '\0';
	X}
	X
	X/*
	X * read_kraut:
	X *	Read the given kraut format file into an atom list
	X */
	X/* ARGSUSED */
	XATOM *
	Xread_kraut(file, all)
	Xchar	*file;
	Xint	all;
	X{
	X	/*
	X	 * Not implemented yet (maybe never).  Just fake as if
	X	 * we had not seen any atoms.
	X	 */
	X	fputs("-k is unimplemented\n", stderr);
	X	return NULL;
	X}
	X
	X/*
	X * read_midas:
	X *	Read the given midas format file into an atom list
	X */
	X/* ARGSUSED */
	XATOM *
	Xread_midas(file, all)
	Xchar	*file;
	Xint	all;
	X{
	X	/*
	X	 * Not implemented yet (maybe never).  Just fake as if
	X	 * we had not seen any atoms.
	X	 */
	X	fputs("-m is unimplemented\n", stderr);
	X	return NULL;
	X}
	X
	Xstatic char	*aa[] = {
	X	"  A", "  C", "  G", "  T", "  U",
	X	"ALA", "ARG", "ASN", "ASP", "CPR", "CYS", "CYX", "CYZ", "GLN",
	X	"GLU", "GLY", "HIS", "ILE", "LEU", "LYS", "MET", "PHE", "PRO",
	X	"SER", "THR", "TRP", "TYR", "VAL",
	X	(char *) NULL
	X};
	X
	X/*
	X * is_aa:
	X *	Decide whether the given residue type is an amino acid
	X *	or nucleic acid.
	X */
	XSTATIC
	Xint
	Xis_aa(type)
	Xchar	*type;
	X{
	X	register int	n;
	X	register char	**aap;
	X
	X	for (aap = aa; *aap != NULL; aap++) {
	X		n = strcmp(type, *aap);
	X		if (n == 0)
	X			return TRUE;
	X		else if (n < 0)
	X			break;
	X	}
	X	return FALSE;
	X}
	X
	X/*
	X * read_wanted:
	X *	Read the "wanted list" of atoms from the given file
	X */
	XWANTED *
	Xread_wanted(fp)
	XFILE	*fp;
	X{
	X	register WANTED	*cp, *wp;
	X	char		buf[BUFSIZ], atname[AN_LEN];
	X	char		orig[BUFSIZ], orig2[BUFSIZ], *fields[4];
	X	int		numfields;
	X	extern char	*emalloc();
	X	static char	*errmsg = "Residues with chain IDs and/or insertion codes should have those appended\n\twith no spaces, e.g. residue 55 of chain E with insertion code A\n\twould be identified as 55AE.\n";
	X	static char	*errmsg2 = "Could not find residue '%s' in PDB file.\nThe residue was mentioned in site file line:\n%s\n";
	X
	X	if (fp == NULL)
	X		return NULL;
	X
	X	wp = NULL;
	X	while (fgets(buf, sizeof buf, fp) != NULL) {
	X		strcpy(orig, buf);
	X		if ((numfields = tokenize(buf, fields, 4)) != 3) {
	X			if (numfields == 0)
	X				/* don't penalize blank lines */
	X				continue;
	X			fputs("Illegal line in -i file:\n", stderr);
	X			fputs(orig, stderr);
	X			if (numfields > 3) {
	X				fputs(errmsg, stderr);
	X			}
	X			exit(1);
	X		}
	X		strcpy(atname, fields[2]);
	X		cp = (WANTED *) emalloc(sizeof (WANTED));
	X		cp->startres = locres(fields[1]);
	X		if (cp->startres < 0) {
	X			/* no such residue */
	X			fprintf(stderr, errmsg2, fields[1], orig);
	X			exit(1);
	X		}
	X		if (strcmp(atname, "*") == 0) {
	X			cp->type = W_ANY;
	X		}
	X		else if (strcmp(atname, "FRM") == 0) {
	X			cp->type = W_RANGE;
	X			if (fgets(buf, sizeof buf, fp) == NULL) {
	X				fputs("Unexpected EOF in -i file\n", stderr);
	X				(void) free((char *) cp);
	X				break;
	X			}
	X			strcpy(orig2, buf);
	X			numfields = tokenize(buf, fields, 4);
	X			if (numfields == 0
	X			  || strcmp(fields[numfields-1], "TO") != 0) {
	X				fputs("No TO after FRM in -i file\n", stderr);
	X				fprintf(stderr, "FRM line was: %s\n", orig);
	X				(void) free((char *) cp);
	X				exit(1);
	X			}
	X			if (numfields > 3) {
	X				fputs(errmsg, stderr);
	X				exit(1);
	X			}
	X			cp->w.endres = locres(fields[1]);
	X			if (cp->w.endres < 0) {
	X				fprintf(stderr, errmsg2, fields[1], orig2);
	X				exit(1);
	X			}
	X			if (cp->w.endres < cp->startres) {
	X				fprintf(stderr,
	X				  "End of FRM/TO range before begining!\n");
	X				fprintf(stderr, "FRM/TO lines were:%s%s\n",
	X				  orig, orig2);
	X				exit(1);
	X			}
	X		}
	X		else {
	X			cp->type = W_ATOM;
	X			(void) strcpy(cp->w.atom, atname);
	X		}
	X		cp->next = wp;
	X		wp = cp;
	X	}
	X	return wp;
	X}
SHAR_EOF
if test 7789 -ne "`wc -c < 'input.c'`"
then
	echo shar: "error transmitting 'input.c'" '(should have been 7789 characters)'
fi
fi
if test ! -d 'libpdb'
then
	echo shar: "creating directory 'libpdb'"
	mkdir 'libpdb'
fi
echo shar: "entering directory 'libpdb'"
cd 'libpdb'
echo shar: "extracting 'GNUmakefile'" '(671 characters)'
if test -f 'GNUmakefile'
then
	echo shar: "will not over-write existing file 'GNUmakefile'"
else
sed 's/^	X//' << \SHAR_EOF > 'GNUmakefile'
	XSHELL		= /bin/sh
	Xifeq ($(shell test -e /usr/bin/ranlib && echo found),found)
	X	RANLIB		= ranlib
	Xelse
	X	RANLIB		= :
	Xendif
	X
	XOPT		= -g
	XDEBUG		=
	XCFLAGS		= $(OPT) $(DEBUG)
	XLIBRARY		= pdb
	X
	XLIBDIR		= /usr/local/lib
	XLIBARCH		= lib$(LIBRARY).a
	XOBJS		= pdb_read.o pdb_sprntf.o pdb_sscanf.o pdb_write.o pdbrun.o ms.o
	XSRCS		= pdb_read.c pdb_sprntf.c pdb_sscanf.c pdb_write.c pdbrun.c ms.c
	X
	Xall:		$(LIBARCH)
	X
	X$(LIBARCH):     $(OBJS)
	X		ar cru $(LIBARCH) $(OBJS)
	X		$(RANLIB) $(LIBARCH)
	X
	Xinstall:	$(LIBARCH)
	X		cp $(LIBARCH) $(LIBDIR)
	X		$(RANLIB) $(LIBDIR)/$(LIBARCH)
	X
	Xclean:
	X		rm -f $(OBJS)
	X
	Xspotless:
	X		rm -f $(OBJS) $(LIBARCH)
	X
	Xtags:           $(HDRS) $(SRCS); @ctags -w $(HDRS) $(SRCS)
SHAR_EOF
if test 671 -ne "`wc -c < 'GNUmakefile'`"
then
	echo shar: "error transmitting 'GNUmakefile'" '(should have been 671 characters)'
fi
fi
echo shar: "extracting 'ms.3'" '(2081 characters)'
if test -f 'ms.3'
then
	echo shar: "will not over-write existing file 'ms.3'"
else
sed 's/^	X//' << \SHAR_EOF > 'ms.3'
	X.\" Copyright (c) 1984,1989 by the Regents of the University of California.
	X.\" All Rights Reserved.
	X.\" $Id: ms.3,v 1.1 94/11/02 13:10:21 gregc Exp $
	X.TH MS 3 "14 Sept 1989"
	X.SH NAME
	Xms_read_record, ms_parse, ms_write_record \- read and write Molecular Surface (ms) records
	X.SH SYNOPSIS
	X.nf
	X.B #include <ms.h>
	X.PP
	X.B ms_record ms_read_record(f)
	X.B FILE *f;
	X.PP
	X.B ms_record ms_parse(line_buffer)
	X.B char *line_buffer;
	X.PP
	X.B void ms_write_record(f, m)
	X.B FILE *f;
	X.B ms_record *m;
	X.fi
	X.SH DESCRIPTION
	XThe routines listed above
	Xare subroutines for Molecular Surface record I/O
	Xand are available in the pdb library, typically
	X.IR "-L/usr/local/lib/midas -lpdb" .
	X.PP
	XAlthough the header file is too long to reproduce here, it should be
	Xperused before using any of the above routines.
	XIt is typically found in
	X.IR /usr/local/midas/include .
	X.PP
	X\fBms_read_record\fP reads the next line of input from the file \fBf\fP,
	Xand returns the contents parsed into a C structure.
	X\fBms_parse\fP parses the contents of the line buffer
	Xand returns a C structure.
	X\fBms_write_record\fP writes the contents of the MS record (\fB*m\fP) to 
	Xthe file \fBf\fP.
	X.SH "SEE ALSO"
	Xdms(1)
	X.SH DIAGNOSTICS
	XUpon reaching the end of the file, \fBms_read_record\fP will return
	Xa record with MS_END as its type.
	X.SH COPYRIGHT
	XCopyright \(co 1992 The Regents of the University of California.
	XAll rights reserved.
	X.PP
	XRedistribution and use in source and binary forms are permitted
	Xprovided that the above copyright notice and this paragraph are
	Xduplicated in all such forms and that any documentation,
	Xadvertising materials, and other materials related to such
	Xdistribution and use acknowledge that the software was developed
	Xby the University of California, San Francisco.  The name of the
	XUniversity may not be used to endorse or promote products derived
	Xfrom this software without specific prior written permission.
	XTHIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
	XIMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
	XWARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
SHAR_EOF
if test 2081 -ne "`wc -c < 'ms.3'`"
then
	echo shar: "error transmitting 'ms.3'" '(should have been 2081 characters)'
fi
fi
echo shar: "extracting 'ms.c'" '(6563 characters)'
if test -f 'ms.c'
then
	echo shar: "will not over-write existing file 'ms.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'ms.c'
	X/*
	X *	Copyright (c) 1989 The Regents of the University of California.
	X *	All rights reserved.
	X *
	X *	Redistribution and use in source and binary forms are permitted
	X *	provided that the above copyright notice and this paragraph are
	X *	duplicated in all such forms and that any documentation,
	X *	advertising materials, and other materials related to such
	X *	distribution and use acknowledge that the software was developed
	X *	by the University of California, San Francisco.  The name of the
	X *	University may not be used to endorse or promote products derived
	X *	from this software without specific prior written permission.
	X *	THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
	X *	IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
	X *	WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
	X *
	X *	$Id: ms.c,v 2.4 94/05/19 16:01:16 conrad Exp $
	X */
	X
	X#include <stdio.h>
	X#include <ctype.h>
	X#include <string.h>
	X#include <math.h>
	X#include "pdb_int.h"
	X#include "ms.h"
	X
	X#ifndef TRUE
	X#define	TRUE	1
	X#define	FALSE	0
	X#endif
	X
	X/*
	X * ms_read_record:
	X *	Read an ms record from a file and return the corresponding
	X *	data structure
	X */
	Xms_record
	X#ifdef __STDC__
	Xms_read_record(FILE *fp)
	X#else
	Xms_read_record(fp)
	X	FILE	*fp;
	X#endif
	X{
	X	char		buf[MS_BUFSIZ];
	X	char		*cp;
	X	int		c;
	X	ms_record	record;
	X
	X	/*
	X	 * If at end of file, just set the record type and return
	X	 */
	X	if (fgets(buf, sizeof buf, fp) == NULL) {
	X		record.record_type = MS_END;
	X		return record;
	X	}
	X
	X	cp = strchr(buf, '\n');
	X	if (cp != NULL)
	X		*cp = '\0';
	X	else
	X		/* discard extra characters since line too long */
	X		while ((c = getc(fp)) != '\n' && c != EOF)
	X			continue;
	X
	X	return ms_read_string(buf);
	X}
	X
	X#ifdef __STDC__
	X	static void	crunch(char *);
	X#else
	X	static void	crunch();
	X#endif
	X
	X/*
	X * ms_read_string
	X *	Construct the data structure corresponding to the given line
	X */
	Xms_record
	X#ifdef __STDC__
	Xms_read_string(const char *buf)
	X#else
	Xms_read_string(buf)
	X	char	*buf;
	X#endif
	X{
	X	int		i;
	X	const char	*cp;
	X	char		*sp;
	X	int		nfield;
	X	double		area, extra;
	X	double		coord[3], normal[3];
	X	ms_record	record;
	X	ms_atom		*map;
	X	ms_surface	*msp;
	X	char		type;
	X	const char	*atom_fmt, *surf_fmt;
	X
	X	/*
	X	 * If the head of the string is "user" (case-independently),
	X	 * we copy the buffer into the string and return
	X	 */
	X	if (strncasecmp(buf, "user", 4) == 0) {
	X		record.record_type = MS_USER;
	X		for (cp = buf + 4; isspace(*cp); cp++)
	X			continue;
	X		sp = record.ms.user.string;
	X		while (*cp != '\0' && *cp != '\n')
	X			*sp++ = *cp++;
	X		*sp = '\0';
	X		return record;
	X	}
	X
	X	/*
	X	 * This is either an atom line, surface line, or an error
	X	 */
	X	if (strlen(buf) < 41) {
	X		record.record_type = MS_UNKNOWN;
	X		(void) strcpy(record.ms.unknown.string, buf);
	X		return record;
	X	}
	X	type = buf[40];
	X	atom_fmt = "%3s %4s %4s%8f %8f %8f A";
	X	surf_fmt = "%3s %4s %4s%8f %8f %8f S%c%c %6f %6f %6f %6f %6f";
	X	if (isspace(type)) {
	X		type = buf[41];
	X		atom_fmt = "%3s %5s %4s%8f %8f %8f A";
	X		surf_fmt = "%3s %5s %4s%8f %8f %8f S%c%c %6f %6f %6f %6f %6f";
	X	}
	X	switch (type) {
	X	  case 'A':
	X		record.record_type = MS_ATOM;
	X		map = &record.ms.atom;
	X		nfield = pdb_sscanf(buf, atom_fmt,
	X			map->residue_type, map->residue_sequence,
	X			map->atom_name, &coord[0], &coord[1], &coord[2]);
	X		if (nfield == 6) {
	X			for (i = 0; i < 3; i++)
	X				map->coord[i] = coord[i];
	X			crunch(map->residue_type);
	X			crunch(map->residue_sequence);
	X			crunch(map->atom_name);
	X			return record;
	X		}
	X		break;
	X	  case 'S':
	X		record.record_type = MS_SURFACE;
	X		msp = &record.ms.surface;
	X		nfield = pdb_sscanf(buf, surf_fmt,
	X			msp->residue_type, msp->residue_sequence,
	X			msp->atom_name, &coord[0], &coord[1], &coord[2],
	X			&msp->type, &msp->level, &area,
	X			&normal[0], &normal[1], &normal[2], &extra);
	X		switch (nfield) {
	X		  case 9:
	X			normal[0] = 0;
	X			/* FALLTHROUGH */
	X		  case 10:
	X			msp->has_normal = FALSE;
	X			for (i = 0; i < 3; i++)
	X				msp->coord[i] = coord[i];
	X			msp->area = area;
	X			msp->extra = normal[0];
	X			crunch(msp->residue_type);
	X			crunch(msp->residue_sequence);
	X			crunch(msp->atom_name);
	X			return record;
	X		  case 12:
	X			extra = 0;
	X			/* FALLTHROUGH */
	X		  case 13:
	X			msp->has_normal = TRUE;
	X			for (i = 0; i < 3; i++) {
	X				msp->coord[i] = coord[i];
	X				msp->normal[i] = normal[i];
	X			}
	X			msp->area = area;
	X			msp->extra = extra;
	X			crunch(msp->residue_type);
	X			crunch(msp->residue_sequence);
	X			crunch(msp->atom_name);
	X			return record;
	X		}
	X		break;
	X	}
	X
	X	/*
	X	 * Okay.  We must not have recognized the record.  Set the
	X	 * record type, copy the string into the string and return
	X	 */
	X	record.record_type = MS_UNKNOWN;
	X	(void) strcpy(record.ms.unknown.string, buf);
	X	return record;
	X}
	X
	X/*
	X * crunch:
	X *	Remove blanks from a string
	X */
	Xstatic
	Xvoid
	X#ifdef __STDC__
	Xcrunch(char *s)
	X#else
	Xcrunch(s)
	X	char	*s;
	X#endif
	X{
	X	char	*last;
	X
	X	for (last = s; *s != '\0'; s++)
	X		if (!isspace(*s))
	X			*last++ = *s;
	X	*last = '\0';
	X}
	X
	X/*
	X * ms_write_record:
	X *	Write an ms record to a file from the corresponding
	X *	data structure
	X */
	Xvoid
	X#ifdef __STDC__
	Xms_write_record(FILE *fp, const ms_record *mp)
	X#else
	Xms_write_record(fp, mp)
	X	FILE		*fp;
	X	ms_record	*mp;
	X#endif
	X{
	X	char	buffer[MS_RECLEN];
	X
	X	ms_write_string(buffer, mp);
	X	fprintf(fp, "%s\n", buffer);
	X}
	X
	X/*
	X * ms_write_string:
	X *	Write an ms record to a string from the corresponding
	X *	data structure
	X */
	Xvoid
	X#ifdef __STDC__
	Xms_write_string(char *buffer, const ms_record *mp)
	X#else
	Xms_write_string(buffer, mp)
	X	char		*buffer;
	X	ms_record	*mp;
	X#endif
	X{
	X	const ms_atom		*map;
	X	const ms_surface	*msp;
	X	char			*cp;
	X
	X	switch (mp->record_type) {
	X	  case MS_ATOM:
	X		map = &mp->ms.atom;
	X		(void) sprintf(buffer, "%-3s %4s %4s %7.3f  %7.3f  %7.3f A",
	X			map->residue_type, map->residue_sequence,
	X			map->atom_name, map->coord[0], map->coord[1],
	X			map->coord[2]);
	X		break;
	X	  case MS_SURFACE:
	X		msp = &mp->ms.surface;
	X		(void) sprintf(buffer,
	X			"%-3s %4s %4s %7.3f  %7.3f  %7.3f S%c%c %6.3f",
	X			msp->residue_type, msp->residue_sequence,
	X			msp->atom_name, msp->coord[0], msp->coord[1],
	X			msp->coord[2], msp->type, msp->level, msp->area);
	X		cp = strchr(buffer, '\0');
	X		if (msp->has_normal) {
	X			(void) sprintf(cp, " %6.3f %6.3f %6.3f",
	X				msp->normal[0], msp->normal[1], msp->normal[2]);
	X			cp = strchr(cp, '\0');
	X		}
	X		if (msp->extra != 0) {
	X			if (msp->extra >= 1000 || msp->extra <= -100)
	X				(void) sprintf(cp, " %6.1f", msp->extra);
	X			else if (msp->extra >= 100 || msp->extra <= -10)
	X				(void) sprintf(cp, " %6.2f", msp->extra);
	X			else
	X				(void) sprintf(cp, " %6.3f", msp->extra);
	X		}
	X		break;
	X	  case MS_USER:
	X		(void) sprintf(buffer, "USER %s\n", mp->ms.user.string);
	X		break;
	X	}
	X}
SHAR_EOF
if test 6563 -ne "`wc -c < 'ms.c'`"
then
	echo shar: "error transmitting 'ms.c'" '(should have been 6563 characters)'
fi
fi
echo shar: "extracting 'ms.h'" '(2307 characters)'
if test -f 'ms.h'
then
	echo shar: "will not over-write existing file 'ms.h'"
else
sed 's/^	X//' << \SHAR_EOF > 'ms.h'
	X/*
	X *	Copyright (c) 1989 The Regents of the University of California.
	X *	All rights reserved.
	X *
	X *	Redistribution and use in source and binary forms are permitted
	X *	provided that the above copyright notice and this paragraph are
	X *	duplicated in all such forms and that any documentation,
	X *	advertising materials, and other materials related to such
	X *	distribution and use acknowledge that the software was developed
	X *	by the University of California, San Francisco.  The name of the
	X *	University may not be used to endorse or promote products derived
	X *	from this software without specific prior written permission.
	X *	THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
	X *	IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
	X *	WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
	X *
	X *	$Id: ms.h,v 2.2 94/01/27 12:41:26 gregc Exp $
	X */
	X
	X#ifndef MS_H
	X#define	MS_H
	X
	X#include <stdio.h>
	X
	X#ifdef __cplusplus
	Xextern "C" {
	X#endif
	X
	X#define	MS_RECLEN	128
	X#define	MS_BUFSIZ	(MS_RECLEN + 2)
	X
	X#define	MS_MAX_RESTYPE	8
	X#define	MS_MAX_RESSEQ	8
	X#define	MS_MAX_ATNAME	8
	X
	X#define	MS_UNKNOWN	0
	X#define	MS_END		1
	X#define	MS_ATOM		2
	X#define	MS_SURFACE	3
	X#define	MS_USER		4
	X
	X#define	MS_NUM_R	5
	X
	Xtypedef struct ms_atom	{
	X	char	residue_type[MS_MAX_RESTYPE];
	X	char	residue_sequence[MS_MAX_RESSEQ];
	X	char	atom_name[MS_MAX_ATNAME];
	X	float	coord[3];
	X}	ms_atom;
	X
	Xtypedef struct ms_surf	{
	X	char	residue_type[MS_MAX_RESTYPE];
	X	char	residue_sequence[MS_MAX_RESSEQ];
	X	char	atom_name[MS_MAX_ATNAME];
	X	float	coord[3];
	X	float	normal[3];
	X	float	area;
	X	float	extra;
	X	char	has_normal;
	X	char	type;
	X	char	level;
	X}	ms_surface;
	X
	Xtypedef struct ms_user	{
	X	char	string[MS_BUFSIZ];
	X}	ms_user;
	X
	X#define	ms_unknown	ms_user
	X
	Xtypedef struct ms_record	{
	X	int	record_type;
	X	union	{
	X		ms_unknown	unknown;
	X		ms_atom		atom;
	X		ms_surface	surface;
	X		ms_user		user;
	X	}	ms;
	X}	ms_record;
	X
	X#if defined(__STDC__) || defined(__cplusplus)
	Xextern ms_record	ms_read_record(FILE *);
	Xextern ms_record	ms_read_string(const char *);
	Xextern void		ms_write_record(FILE *, const ms_record *);
	Xextern void		ms_write_string(char *, const ms_record *);
	X#else
	Xextern ms_record	ms_read_record();
	Xextern ms_record	ms_read_string();
	Xextern void		ms_write_record();
	Xextern void		ms_write_string();
	X#endif
	X
	X#ifdef __cplusplus
	X}
	X#endif
	X#endif
SHAR_EOF
if test 2307 -ne "`wc -c < 'ms.h'`"
then
	echo shar: "error transmitting 'ms.h'" '(should have been 2307 characters)'
fi
fi
echo shar: "extracting 'pdb.3'" '(3650 characters)'
if test -f 'pdb.3'
then
	echo shar: "will not over-write existing file 'pdb.3'"
else
sed 's/^	X//' << \SHAR_EOF > 'pdb.3'
	X.\" Copyright (c) 1984,1989 by the Regents of the University of California.
	X.\" All Rights Reserved.
	X.\" $Id: pdb.3,v 1.16 94/11/06 19:55:29 gregc Exp $
	X.TH PDB 3 "14 Sept 1989"
	X.SH NAME
	Xpdb_read_record, pdb_parse, pdb_write_record \- read and write Brookhaven Protein DataBank records
	X.SH SYNOPSIS
	X.nf
	X.B #include <pdb.h>
	X.PP
	X.B pdb_record pdb_read_record(f)
	X.B FILE *f;
	X.PP
	X.B pdb_record pdb_parse(line_buffer)
	X.B char *line_buffer;
	X.PP
	X.B "void pdb_write_record(f, r, name, line_num)"
	X.B FILE *f;
	X.B pdb_record *r;
	X.B char *name;
	X.B int line_num;
	X.fi
	X.SH DESCRIPTION
	XThe routines listed above
	Xare subroutines for Brookhaven Protein Data Bank record I/O
	Xand are available in the pdb library, typically
	X.IR "-L/usr/local/lib/midas -lpdb" .
	X.PP
	XAlthough the header file is too long to reproduce here, it should be
	Xperused before using any of the above routines.
	XIt is typically found in
	X.IR /usr/local/midas/include .
	X\fBpdb_read_record\fP reads the next line of input from the file \fBf\fP,
	Xand returns the contents parsed into a C structure.
	X\fBpdb_parse\fP parses the contents of the line buffer
	Xand returns a C structure.
	X\fBpdb_write_record\fP writes the contents of the PDB record (\fB*r\fP) to 
	Xthe file \fBf\fP.  If the \fBname\fP is non-null, then it and the line
	Xnumber given (\fBline_num\fP) are placed in columns 72 through 80 on the
	Xline in standard PDB format.
	X.PP
	X\fBpdb_read_record\fP and \fBpdb_write_record\fP automatically
	Xhandle versions 5 and 6 of the UCSFCGL's PDB scene annotation records.
	XThe version number is automatically changed when a USER  PDBRUN record is read
	Xor written.
	XAny other version number turns off the parsing of scene annotation records.
	X.SH "SEE ALSO"
	X``Protein Data Bank Atomic Coordinate and Bibliographic Entry Format Description,'' Febuary 1992,
	XBrookhaven National Laboratory
	X(URL: ftp://ftp.pdb.bnl.gov/pub/format_desc.ps),
	Xthe January 1993 Protein Data Bank Quarterly Newsletter,
	Xand Couch, \fIet. al\fP, ``Annotating PDB Files with Scene Information'',
	X(in press)
	X(URL: http://cgl.ucsf.edu/????).
	X.SH DIAGNOSTICS
	XUpon reaching the end of the file, \fBpdb_read_record\fP will return
	Xa record with PDB_END as its type.
	X.SH NOTES
	XThe subtype field of USERxx structure tells what the \fIxx\fP part was.
	XThe rest of the line, up to the card sequence portion, is the text field.
	X.PP
	XDue to the way Brookhaven encodes their files,
	Xatom names usually have leading blanks and sometimes have embedded blanks.
	XResidue names occasionally have leading blanks too.
	XTo be entirely consistent with the PDB format, the programmer should put those
	Xblanks in before using \fBpdb_write_record\fP.
	X.SH BUGS
	XDoesn't allow exact duplication of the PDB card image sorting field
	X(columns 73 through 80).
	X.PP
	XRoutines are needed to convert to and from PDB typesetting conventions
	Xin COMPND, SOURCE, AUTHOR, and JRNL records.
	X.SH COPYRIGHT
	XCopyright \(co 1989 The Regents of the University of California.
	XAll rights reserved.
	X.PP
	XRedistribution and use in source and binary forms are permitted
	Xprovided that the above copyright notice and this paragraph are
	Xduplicated in all such forms and that any documentation,
	Xadvertising materials, and other materials related to such
	Xdistribution and use acknowledge that the software was developed
	Xby the University of California, San Francisco.  The name of the
	XUniversity may not be used to endorse or promote products derived
	Xfrom this software without specific prior written permission.
	XTHIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
	XIMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
	XWARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
SHAR_EOF
if test 3650 -ne "`wc -c < 'pdb.3'`"
then
	echo shar: "error transmitting 'pdb.3'" '(should have been 3650 characters)'
fi
fi
echo shar: "extracting 'pdb.h'" '(12494 characters)'
if test -f 'pdb.h'
then
	echo shar: "will not over-write existing file 'pdb.h'"
else
sed 's/^	X//' << \SHAR_EOF > 'pdb.h'
	X/*
	X *	Copyright (c) 1989 The Regents of the University of California.
	X *	All rights reserved.
	X *
	X *	Redistribution and use in source and binary forms are permitted
	X *	provided that the above copyright notice and this paragraph are
	X *	duplicated in all such forms and that any documentation,
	X *	advertising materials, and other materials related to such
	X *	distribution and use acknowledge that the software was developed
	X *	by the University of California, San Francisco.  The name of the
	X *	University may not be used to endorse or promote products derived
	X *	from this software without specific prior written permission.
	X *	THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
	X *	IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
	X *	WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
	X *
	X *	$Id: pdb.h,v 2.11 1995/01/20 01:20:36 gregc Exp $
	X *
	X *	Based on Brookhaven National Laboratory Protein Data Bank, March 1989
	X *
	X *	C structure declarations
	X */
	X
	X#ifndef PDB_H
	X# define	PDB_H
	X
	X# include	<stdio.h>
	X
	X# ifdef __cplusplus
	Xextern "C" {
	X# endif
	X
	X# define	PDB_RECLEN	80		/* PDB record length */
	X# define	PDB_BUFSIZ	PDB_RECLEN + 2	/* + '\n' + '\0' */		
	X
	X# define	PDB_PDBRUN_VERSION	6
	X
	X# define	PDB_UNKNOWN	0
	X
	X/* records originally in alphabetical order */
	X
	X# define	PDB_ANISOU	1
	X# define	PDB_ATOM	2
	X# define	PDB_AUTHOR	3
	X# define	PDB_COMPND	4
	X# define	PDB_CONECT	5
	X# define	PDB_CRYST1	6
	X# define	PDB_END		7
	X# define	PDB_FORMUL	8
	X# define	PDB_FTNOTE	9
	X# define	PDB_HEADER	10
	X# define	PDB_HELIX	11
	X# define	PDB_HET		12
	X# define	PDB_HETATM	13
	X# define	PDB_JRNL	14
	X# define	PDB_MASTER	15
	X# define	PDB_MTRIX	16
	X# define	PDB_OBSLTE	17
	X# define	PDB_ORIGX	18
	X# define	PDB_REMARK	19
	X# define	PDB_REVDAT	20
	X# define	PDB_SCALE	21
	X# define	PDB_SEQRES	22
	X# define	PDB_SHEET	23
	X# define	PDB_SIGATM	24
	X# define	PDB_SIGUIJ	25
	X# define	PDB_SITE	26
	X# define	PDB_SOURCE	27
	X# define	PDB_SPRSDE	28
	X# define	PDB_SSBOND	29
	X# define	PDB_TER		30
	X# define	PDB_TURN	31
	X# define	PDB_TVECT	32
	X# define	PDB_USER	33
	X# define	PDB_MODEL	34
	X# define	PDB_ENDMDL	35
	X# define	PDB_EXPDTA	36
	X# define	PDB_SYMDES	37
	X# define	PDB_SYMOP	38
	X# define	PDB_MTXDES	39
	X# define	PDB_CMPDES	40
	X# define	PDB_CMPONT	41
	X# define	PDB_TRNSFM	42
	X# define	PDB_AGRDES	43
	X# define	PDB_AGGRGT	44
	X
	X# define	PDB_NUM_R	45
	X
	X# define	PDB_USER_PDBRUN		0x100
	X# define	PDB_USER_EYEPOS		0x101
	X# define	PDB_USER_ATPOS		0x102
	X# define	PDB_USER_WINDOW		0x103
	X# define	PDB_USER_FOCUS		0x104
	X# define	PDB_USER_VIEWPORT	0x105
	X# define	PDB_USER_BGCOLOR	0x106
	X# define	PDB_USER_ANGLE		0x107
	X# define	PDB_USER_DISTANCE	0x108
	X# define	PDB_USER_FILE		0x109
	X# define	PDB_USER_MARKNAME	0x10a
	X# define	PDB_USER_MARK		0x10b
	X# define	PDB_USER_CNAME		0x10c
	X# define	PDB_USER_COLOR		0x10d
	X# define	PDB_USER_RADIUS		0x10e
	X# define	PDB_USER_OBJECT		0x10f
	X# define	PDB_USER_ENDOBJ		0x110
	X# define	PDB_USER_CHAIN		0x111
	X# define	PDB_USER_GFX_BEGIN	0x112
	X# define	PDB_USER_GFX_END	0x113
	X# define	PDB_USER_GFX_COLOR	0x114
	X# define	PDB_USER_GFX_NORMAL	0x115
	X# define	PDB_USER_GFX_VERTEX	0x116
	X# define	PDB_USER_GFX_FONT	0x117
	X# define	PDB_USER_GFX_TEXTPOS	0x118
	X# define	PDB_USER_GFX_LABEL	0x119
	X# define	PDB_USER_GFX_MOVE	0x11a	/* obsolete */
	X# define	PDB_USER_GFX_DRAW	0x11b	/* obsolete */
	X# define	PDB_USER_GFX_MARKER	0x11c	/* obsolete */
	X# define	PDB_USER_GFX_POINT	0x11d	/* obsolete */
	X
	X# define	PDB_NUM_USER_R		(PDB_USER_GFX_POINT-PDB_USER_PDBRUN+1)
	X
	X# define	PDB_GFX_UNKNOWN		0x0
	X# define	PDB_GFX_POINTS		0x1
	X# define	PDB_GFX_MARKERS		0x2
	X# define	PDB_GFX_LINES		0x3
	X# define	PDB_GFX_LINE_STRIP	0x4
	X# define	PDB_GFX_LINE_LOOP	0x5
	X# define	PDB_GFX_TRIANGLES	0x6
	X# define	PDB_GFX_TRIANGLE_STRIP	0x7
	X# define	PDB_GFX_TRIANGLE_FAN	0x8
	X# define	PDB_GFX_QUADS		0x9
	X# define	PDB_GFX_QUAD_STRIP	0xa
	X# define	PDB_GFX_POLYGON		0xb
	X
	Xtypedef char	pdb_date[10];
	Xtypedef char	pdb_aname[5];		/* atom name - NO2* */
	Xtypedef char	pdb_rname[5];		/* residue name - ALA */
	Xtypedef char	pdb_pname[5];		/* pdb name - 9lyz */
	Xtypedef char	pdb_id[4];		/* generic short id field */
	Xtypedef double	pdb_float;		/* size of floating point */
	X
	Xtypedef struct {			/* residue info */
	X	pdb_rname	name;
	X	char		chain_id;
	X	int		seq_num;
	X	char		insert_code;
	X} pdb_residue;
	X
	X/*
	X *	structures declarations for each record type
	X */
	X
	Xstruct pdb_unknown {
	X	char	junk[81];
	X};
	Xstruct pdb_aggrgt {
	X	int	serial_num;
	X	int	num_components;
	X	int	cmpont_serial_nums[14];
	X};
	X# define	pdb_agrdes	pdb_ftnote
	Xstruct pdb_anisou {
	X	int		serial_num;
	X	pdb_aname	name;
	X	char		alt_loc;
	X	pdb_residue	residue;
	X	int		u[6];
	X};
	Xstruct pdb_atom {
	X	int		serial_num;
	X	pdb_aname	name;
	X	char		alt_loc;
	X	pdb_residue	residue;
	X	pdb_float	x, y, z;
	X	pdb_float	occupancy, temp_factor;
	X	int		ftnote_num;
	X};
	Xstruct pdb_author {
	X	char	data[61];
	X	char	continuation;
	X};
	X# define	pdb_cmpdes	pdb_ftnote
	Xstruct pdb_cmpont {
	X	int		seq_num;
	X	pdb_residue	residues[2];
	X};
	X# define	pdb_compnd	pdb_author
	Xstruct pdb_conect {
	X	int	serial_num;
	X	int	covalent[4];
	X	struct {
	X		int	hydrogen[2];
	X		int	salt;
	X	} bonds[2];
	X};
	Xstruct pdb_cryst1 {
	X	pdb_float	a, b, c;
	X	pdb_float	alpha, beta, gamma;
	X	char		space_grp[12];
	X	int		z;
	X};
	X/* no structure for PDB_END */
	X/* no structure for PDB_ENDMDL */
	X# define	pdb_expdta	pdb_author
	Xstruct pdb_formul {
	X	int		component;
	X	pdb_rname	het_id;
	X	int		continuation;
	X	char		exclude;	/* * to exclude */
	X	char		formula[52];
	X};
	Xstruct pdb_ftnote {
	X	int	num;
	X	char	text[60];
	X};
	Xstruct pdb_header {
	X	char		class[41];
	X	pdb_date	date;
	X	pdb_pname	id;
	X	char		type;
	X};
	Xstruct pdb_helix {
	X	int		serial_num;
	X	pdb_id		id;
	X	pdb_residue	residues[2];
	X	int		class;
	X	char		comment[31];
	X};
	Xstruct pdb_het {
	X	pdb_residue	het_grp;
	X	int		num_atoms;
	X	char		text[41];
	X};
	X# define	pdb_hetatm	pdb_atom
	X# define	pdb_jrnl	pdb_author
	Xstruct pdb_master {
	X	int	num_remark;
	X	int	num_ftnote;
	X	int	num_het;
	X	int	num_helix;
	X	int	num_sheet;
	X	int	num_turn;
	X	int	num_site;
	X	int	num_transform;
	X	int	num_coordinate;
	X	int	num_ter;
	X	int	num_conect;
	X	int	num_seqres;
	X};
	Xstruct pdb_model {
	X	int	num;
	X};
	Xstruct pdb_mtrix {
	X	int		row_num;
	X	int		serial_num;
	X	pdb_float	m1, m2, m3, v;
	X	int		given;
	X};
	X# define	pdb_mtxdes	pdb_ftnote
	Xstruct pdb_obslte {
	X	int		continuation;
	X	pdb_date	date;
	X	pdb_pname	old_id;
	X	pdb_pname	id_map[8];
	X};
	Xstruct pdb_origx {
	X	int		row_num;
	X	pdb_float	o1, o2, o3, t;
	X};
	X# define	pdb_remark	pdb_ftnote
	Xstruct pdb_revdat {
	X	int		modification;
	X	int		continuation;
	X	pdb_date	date;
	X	char		id[8];
	X	char		mod_type;
	X	char		corrections[31];
	X};
	Xstruct pdb_scale {
	X	int		row_num;
	X	pdb_float	s1, s2, s3, u;
	X};
	Xstruct pdb_seqres {
	X	int		serial_num;
	X	char		chain_id;
	X	int		count;
	X	pdb_rname	names[13];
	X};
	Xstruct pdb_sheet {
	X	int		strand_num;
	X	pdb_id		id;
	X	int		count;
	X	pdb_residue	residues[2];
	X	int		sense;
	X	struct {
	X		pdb_aname	name;
	X		pdb_residue	residue;
	X	} atoms[2];
	X};
	X# define	pdb_sigatm	pdb_atom
	X# define	pdb_siguij	pdb_anisou
	Xstruct pdb_site {
	X	int		seq_num;
	X	pdb_id		id;
	X	int		count;
	X	pdb_residue	residues[4];
	X};
	X# define	pdb_source	pdb_author
	Xstruct pdb_sprsde {
	X	int		continuation;
	X	pdb_date	date;
	X	pdb_pname	id;
	X	pdb_pname	supersede[8];
	X};
	Xstruct pdb_ssbond {
	X	int		seq_num;
	X	pdb_residue	residues[2];
	X	char		comment[31];
	X};
	X# define	pdb_symdes	pdb_ftnote
	Xstruct pdb_symop {
	X	int		row_num;
	X	int		serial_num;
	X	pdb_float	s1, s2, s3, t;
	X};
	Xstruct pdb_ter {
	X	int		serial_num;
	X	pdb_residue	residue;
	X};
	Xstruct pdb_trnsfm {
	X	int		result_serial_num;
	X	int		apply_serial_num;
	X	int		source_serial_num;
	X};
	Xstruct pdb_turn {
	X	int		seq_num;
	X	pdb_id		id;
	X	pdb_residue	residues[2];
	X	char		comment[31];
	X};
	Xstruct pdb_tvect {
	X	int		serial_num;
	X	pdb_float	t1, t2, t3;
	X	char		comment[31];
	X};
	Xstruct pdb_user {
	X	char	subtype[3];
	X	char	text[67];
	X};
	Xstruct pdb_user_pdbrun {
	X	int	version;
	X};
	Xstruct pdb_user_eyepos {
	X	pdb_float	xyz[3];
	X};
	X# define	pdb_user_atpos	pdb_user_eyepos
	Xstruct pdb_user_window {
	X	pdb_float	left, right, bottom, top, hither, yon;
	X};
	Xstruct pdb_user_focus {
	X	pdb_float	focus;
	X};
	Xstruct pdb_user_viewport {
	X	pdb_float	xmin, xmax, ymin, ymax;
	X};
	Xstruct pdb_user_bgcolor {
	X	pdb_float	rgb[3];
	X};
	Xstruct pdb_user_angle {
	X	int		atom0, atom1, atom2, atom3;
	X	pdb_float	angle;
	X	int		which;			/* version 5 -- obsolete */
	X};
	Xstruct pdb_user_distance {
	X	int		atom0, atom1;
	X	pdb_float	distance;
	X	int		which;			/* version 5 -- obsolete */
	X};
	Xstruct pdb_user_file {
	X	char		filename[62];		/* 57 in version 6 */
	X	int		model;			/* not in version 5 */
	X};
	Xstruct pdb_user_markname {
	X	char		markname[58];
	X};
	X# define	pdb_user_mark	pdb_user_markname
	Xstruct pdb_user_cname {
	X	pdb_float	rgb[3];
	X	char		name[39];
	X};
	Xstruct pdb_user_color {
	X	pdb_float	rgb[3];
	X	char		spec[39];
	X};
	Xstruct pdb_user_radius {
	X	pdb_float	radius;
	X};
	Xstruct pdb_user_object {
	X	int		model;			/* version 5 -- obsolete */
	X};
	Xstruct pdb_user_endobj {
	X	int		model;			/* version 5 -- obsolete */
	X};
	Xstruct pdb_user_chain {
	X	int		atom0, atom1;
	X};
	Xstruct pdb_user_gfx_begin {			/* not in version 5 */
	X	int		primitive;
	X	char		unknown[33];
	X};
	X/* no structure for USER  GFX END */
	X# define	pdb_user_gfx_color	pdb_user_color
	Xstruct pdb_user_gfx_normal {
	X	pdb_float	xyz[3];
	X};
	X# define	pdb_user_gfx_vertex	pdb_user_gfx_normal
	Xstruct pdb_user_gfx_font {
	X	int	size;
	X	char	name[54];
	X};
	Xstruct pdb_user_gfx_textpos {			/* not in version 5 */
	X	pdb_float	xyz[3];
	X};
	Xstruct pdb_user_gfx_label {
	X	pdb_float	xyz[3];			/* version 5 -- obsolete */
	X	char		text[57];		/* 27 in version 5 */
	X};
	Xstruct pdb_user_gfx_move {			/* version 5 -- obsolete */
	X	pdb_float	xyz[3];
	X};
	X# define	pdb_user_gfx_draw	pdb_user_gfx_move	/* version 5 -- obsolete */
	X# define	pdb_user_gfx_marker	pdb_user_gfx_move	/* "" */
	X# define	pdb_user_gfx_point	pdb_user_gfx_move	/* "" */
	X
	Xtypedef struct pdb_record {
	X	int	record_type;
	X	union	{
	X		struct pdb_unknown	unknown;
	X		struct pdb_agrdes	agrdes;
	X		struct pdb_aggrgt	aggrgt;
	X		struct pdb_anisou	anisou;
	X		struct pdb_atom		atom;
	X		struct pdb_author	author;
	X		struct pdb_cmpdes	cmpdes;
	X		struct pdb_cmpont	cmpont;
	X		struct pdb_compnd	compnd;
	X		struct pdb_conect	conect;
	X		struct pdb_cryst1	cryst1;
	X		/* no pdb_end structure */
	X		/* no pdb_endmdl structure */
	X		struct pdb_expdta	expdta;
	X		struct pdb_formul	formul;
	X		struct pdb_ftnote	ftnote;
	X		struct pdb_header	header;
	X		struct pdb_helix	helix;
	X		struct pdb_het		het;
	X		struct pdb_hetatm	hetatm;
	X		struct pdb_jrnl		jrnl;
	X		struct pdb_master	master;
	X		struct pdb_model	model;
	X		struct pdb_mtrix	mtrix;
	X		struct pdb_mtxdes	mtxdes;
	X		struct pdb_obslte	obslte;
	X		struct pdb_origx	origx;
	X		struct pdb_remark	remark;
	X		struct pdb_revdat	revdat;
	X		struct pdb_scale	scale;
	X		struct pdb_seqres	seqres;
	X		struct pdb_sheet	sheet;
	X		struct pdb_sigatm	sigatm;
	X		struct pdb_siguij	siguij;
	X		struct pdb_site		site;
	X		struct pdb_source	source;
	X		struct pdb_sprsde	sprsde;
	X		struct pdb_ssbond	ssbond;
	X		struct pdb_symdes	symdes;
	X		struct pdb_symop	symop;
	X		struct pdb_ter		ter;
	X		struct pdb_trnsfm	trnsfm;
	X		struct pdb_turn		turn;
	X		struct pdb_tvect	tvect;
	X		struct pdb_user		user;
	X		struct pdb_user_pdbrun	user_pdbrun;
	X		struct pdb_user_eyepos	user_eyepos;
	X		struct pdb_user_atpos	user_atpos;
	X		struct pdb_user_window	user_window;
	X		struct pdb_user_focus	user_focus;
	X		struct pdb_user_viewport	user_viewport;
	X		struct pdb_user_bgcolor	user_bgcolor;
	X		struct pdb_user_angle	user_angle;
	X		struct pdb_user_distance	user_distance;
	X		struct pdb_user_file	user_file;
	X		struct pdb_user_markname	user_markname;
	X		struct pdb_user_mark	user_mark;
	X		struct pdb_user_cname	user_cname;
	X		struct pdb_user_color	user_color;
	X		struct pdb_user_radius	user_radius;
	X		struct pdb_user_object	user_object;
	X		struct pdb_user_endobj	user_endobj;
	X		struct pdb_user_chain	user_chain;
	X		struct pdb_user_gfx_begin	user_gfx_begin;
	X		struct pdb_user_gfx_color	user_gfx_color;
	X		struct pdb_user_gfx_normal	user_gfx_normal;
	X		struct pdb_user_gfx_vertex	user_gfx_vertex;
	X		struct pdb_user_gfx_font	user_gfx_font;
	X		struct pdb_user_gfx_textpos	user_gfx_textpos;
	X		struct pdb_user_gfx_label	user_gfx_label;
	X		struct pdb_user_gfx_move	user_gfx_move;
	X		struct pdb_user_gfx_draw	user_gfx_draw;
	X		struct pdb_user_gfx_marker	user_gfx_marker;
	X		struct pdb_user_gfx_point	user_gfx_point;
	X	} pdb;
	X} pdb_record;
	X
	X# if defined(__STDC__) || defined(__cplusplus)
	Xextern pdb_record	pdb_read_record(FILE *);
	Xextern pdb_record	pdb_read_string(const char *);
	Xextern void		pdb_write_record(FILE *, const pdb_record *, const char *, int);
	Xextern void		pdb_write_string(char *, const pdb_record *);
	X# else
	Xextern pdb_record	pdb_read_record();
	Xextern pdb_record	pdb_read_string();
	Xextern void		pdb_write_record();
	Xextern void		pdb_write_string();
	X# endif
	X
	X# ifdef __cplusplus
	X}
	X# endif
	X#endif /* PDB_H */
SHAR_EOF
if test 12494 -ne "`wc -c < 'pdb.h'`"
then
	echo shar: "error transmitting 'pdb.h'" '(should have been 12494 characters)'
fi
fi
echo shar: "extracting 'pdbrun.c'" '(2700 characters)'
if test -f 'pdbrun.c'
then
	echo shar: "will not over-write existing file 'pdbrun.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'pdbrun.c'
	X/*
	X *	Copyright (c) 1994 The Regents of the University of California.
	X *	All rights reserved.
	X *
	X *	Redistribution and use in source and binary forms are permitted
	X *	provided that the above copyright notice and this paragraph are
	X *	duplicated in all such forms and that any documentation,
	X *	advertising materials, and other materials related to such
	X *	distribution and use acknowledge that the software was developed
	X *	by the University of California, San Francisco.  The name of the
	X *	University may not be used to endorse or promote products derived
	X *	from this software without specific prior written permission.
	X *	THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
	X *	IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
	X *	WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
	X *
	X *	$Id: pdbrun.c,v 1.4 1994/11/18 01:00:57 gregc Exp $
	X *
	X *	subroutine for reading PDB format files
	X *
	X */
	X
	X/* LINTLIBRARY */
	X
	X# include	"pdb_int.h"
	X# include	<string.h>
	X
	Xint	pdb_pdbrun_version = PDB_PDBRUN_VERSION;
	X
	X#ifdef __STDC__
	Xconst char *
	Xpdb_gfx_string(int i)
	X#else
	Xchar *
	Xpdb_gfx_string(i)
	X	int	i;
	X#endif
	X{
	X	switch (i) {
	X	default:			return "UNKNOWN";
	X	case PDB_GFX_POINTS:		return "POINTS";
	X	case PDB_GFX_MARKERS:		return "MARKERS";
	X	case PDB_GFX_LINES:		return "LINES";
	X	case PDB_GFX_LINE_STRIP:	return "LINE-STRIP";
	X	case PDB_GFX_LINE_LOOP:		return "LINE-LOOP";
	X	case PDB_GFX_TRIANGLES:		return "TRIANGLES";
	X	case PDB_GFX_TRIANGLE_STRIP:	return "TRIANGLE-STRIP";
	X	case PDB_GFX_TRIANGLE_FAN:	return "TRIANGLE-FAN";
	X	case PDB_GFX_QUADS:		return "QUADS";
	X	case PDB_GFX_QUAD_STRIP:	return "QUAD-STRIP";
	X	case PDB_GFX_POLYGON:		return "POLYGON";
	X	}
	X}
	X
	X#ifdef __STDC__
	Xint
	Xpdb_gfx_type(const char *type)
	X#else
	Xint
	Xpdb_gfx_type(type)
	X	char	*type;
	X#endif
	X{
	X	switch (type[0]) {
	X	case 'L':
	X		if (strcmp(type + 1, "INE-LOOP") == 0)
	X			return PDB_GFX_LINE_LOOP;
	X		if (strcmp(type + 1, "INE-STRIP") == 0)
	X			return PDB_GFX_LINE_STRIP;
	X		if (strcmp(type + 1, "INES") == 0)
	X			return PDB_GFX_LINES;
	X		break;
	X	case 'M':
	X		if (strcmp(type + 1, "ARKERS") == 0)
	X			return PDB_GFX_MARKERS;
	X		break;
	X	case 'P':
	X		if (strcmp(type + 1, "OINTS") == 0)
	X			return PDB_GFX_POINTS;
	X		if (strcmp(type + 1, "OLYGON") == 0)
	X			return PDB_GFX_POLYGON;
	X		break;
	X	case 'Q':
	X		if (strcmp(type + 1, "UAD-STRIP") == 0)
	X			return PDB_GFX_QUAD_STRIP;
	X		if (strcmp(type + 1, "UADS") == 0)
	X			return PDB_GFX_QUADS;
	X		break;
	X	case 'T':
	X		if (strcmp(type + 1, "RIANGLE-FAN") == 0)
	X			return PDB_GFX_TRIANGLE_FAN;
	X		if (strcmp(type + 1, "RIANGLE-STRIP") == 0)
	X			return PDB_GFX_TRIANGLE_STRIP;
	X		if (strcmp(type + 1, "RIANGLES") == 0)
	X			return PDB_GFX_TRIANGLES;
	X		break;
	X	}
	X	return PDB_GFX_UNKNOWN;
	X}
SHAR_EOF
if test 2700 -ne "`wc -c < 'pdbrun.c'`"
then
	echo shar: "error transmitting 'pdbrun.c'" '(should have been 2700 characters)'
fi
fi
echo shar: "extracting 'pdbrun5_read.i'" '(1873 characters)'
if test -f 'pdbrun5_read.i'
then
	echo shar: "will not over-write existing file 'pdbrun5_read.i'"
else
sed 's/^	X//' << \SHAR_EOF > 'pdbrun5_read.i'
	X/*
	X *	Copyright (c) 1994 The Regents of the University of California.
	X *	All rights reserved.
	X *
	X *	Redistribution and use in source and binary forms are permitted
	X *	provided that the above copyright notice and this paragraph are
	X *	duplicated in all such forms and that any documentation,
	X *	advertising materials, and other materials related to such
	X *	distribution and use acknowledge that the software was developed
	X *	by the University of California, San Francisco.  The name of the
	X *	University may not be used to endorse or promote products derived
	X *	from this software without specific prior written permission.
	X *	THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
	X *	IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
	X *	WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
	X *
	X *	$Id: pdbrun5_read.i,v 1.4 1994/11/16 22:09:29 gregc Exp $
	X */
	X/* PDBRUN */	"%12  %2d",
	X/* EYEPOS */	"%12  %9f %9f %9f",
	X/* ATPOS */	"%11   %9f %9f %9f",
	X/* WINDOW */	"%12  %9f %9f %9f %9f %9f %9f",
	X/* FOCUS */	"%11  %9f",
	X/* VIEWPORT */	"%14  %9f %9f %9f %9f",
	X/* BGCOLOR */	"USER  BGCOLOR %lf %lf %lf",
	X/* ANGLE */	"%11  %2d %6d %6d %6d %6d %8f",
	X/* DISTANCE */	"%14  %2d %6d %6d %8f",
	X/* FILE */	"%10  %61s",
	X/* MARKNAME */	NULL,
	X/* MARK */	NULL,
	X/* CNAME */	"USER  CNAME %s %lf %lf %lf",
	X/* COLOR */	"USER  COLOR %s %lf %lf %lf",
	X/* RADIUS */	"%12  %7f",
	X/* OBJECT */	"%12  %3d",
	X/* ENDOBJ */	"%12  %3d",
	X/* CHAIN */	"USER  CHAIN %d %d",
	X/* GFX BEGIN */	NULL,
	X/* GFX END */	NULL,
	X/* GFX COLOR */	"USER  GFX COLOR %s %lf %lf %lf",
	X/* GFX NORMAL */	NULL,
	X/* GFX VERTEX */	NULL,
	X/* GFX FONT */	"USER  GFX FONT %s %d",
	X/* GFX TEXTPOS */	NULL,
	X/* GFX LABEL */	"USER  GFX LABEL %lf %lf %lf %26[^\n]",
	X/* GFX MOVE */	"%14  %9f %9f %9f",
	X/* GFX DRAW */	"%14  %9f %9f %9f",
	X/* GFX MARKER */	"%16  %9f %9f %9f",
	X/* GFX POINT */	"%15  %9f %9f %9f",
SHAR_EOF
if test 1873 -ne "`wc -c < 'pdbrun5_read.i'`"
then
	echo shar: "error transmitting 'pdbrun5_read.i'" '(should have been 1873 characters)'
fi
fi
echo shar: "extracting 'pdbrun5_write.i'" '(1843 characters)'
if test -f 'pdbrun5_write.i'
then
	echo shar: "will not over-write existing file 'pdbrun5_write.i'"
else
sed 's/^	X//' << \SHAR_EOF > 'pdbrun5_write.i'
	X/*
	X *	Copyright (c) 1994 The Regents of the University of California.
	X *	All rights reserved.
	X *
	X *	Redistribution and use in source and binary forms are permitted
	X *	provided that the above copyright notice and this paragraph are
	X *	duplicated in all such forms and that any documentation,
	X *	advertising materials, and other materials related to such
	X *	distribution and use acknowledge that the software was developed
	X *	by the University of California, San Francisco.  The name of the
	X *	University may not be used to endorse or promote products derived
	X *	from this software without specific prior written permission.
	X *	THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
	X *	IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
	X *	WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
	X *
	X *	$Id: pdbrun5_write.i,v 1.2 1994/11/16 22:09:29 gregc Exp $
	X */
	X"USER  PDBRUN %2d",
	X"USER  EYEPOS %9.3f %9.3f %9.3f",
	X"USER  ATPOS  %9.3f %9.3f %9.3f",
	X"USER  WINDOW %9.3f %9.3f %9.3f %9.3f %9.3f %9.3f",
	X"USER  FOCUS %9.3f",
	X"USER  VIEWPORT %9.3f %9.3f %9.3f %9.3f",
	X"USER  BGCOLOR %.3f %.3f %.3f",
	X"USER  ANGLE %2d %6d %6d %6d %6d %8.3f",
	X"USER  DISTANCE %2d %6d %6d %8.3f",
	X"USER  FILE %-61s",
	XNULL,	/* USER  MARKNAME */
	XNULL,	/* USER  MARK */
	X"USER  CNAME %-.38s %.3f %.3f %.3f",
	X"USER  COLOR %-.38s %5.3f %5.3f %5.3f",
	X"USER  RADIUS %7.3f",
	X"USER  OBJECT %3d",
	X"USER  ENDOBJ %3d",
	X"USER  CHAIN %d %d",
	XNULL,	/* USER  GFX BEGIN */
	XNULL,	/* USER  GFX END */
	X"USER  GFX COLOR %-.38s %.3f %.3f %.3f",
	XNULL,	/* USER  GFX NORMAL */
	XNULL,	/* USER  GFX VERTEX */
	X"USER  GFX FONT %-.53s %d",
	XNULL,	/* USER  GFX TEXTPOS */
	X"USER  GFX LABEL %9.3f %9.3f %9.3f \"%-.24s\"",
	X"USER  GFX MOVE %9.3f %9.3f %9.3f",
	X"USER  GFX DRAW %9.3f %9.3f %9.3f",
	X"USER  GFX MARKER %9.3f %9.3f %9.3f",
	X"USER  GFX POINT %9.3f %9.3f %9.3f",
SHAR_EOF
if test 1843 -ne "`wc -c < 'pdbrun5_write.i'`"
then
	echo shar: "error transmitting 'pdbrun5_write.i'" '(should have been 1843 characters)'
fi
fi
echo shar: "extracting 'pdbrun6_read.i'" '(1804 characters)'
if test -f 'pdbrun6_read.i'
then
	echo shar: "will not over-write existing file 'pdbrun6_read.i'"
else
sed 's/^	X//' << \SHAR_EOF > 'pdbrun6_read.i'
	X/*
	X *	Copyright (c) 1994 The Regents of the University of California.
	X *	All rights reserved.
	X *
	X *	Redistribution and use in source and binary forms are permitted
	X *	provided that the above copyright notice and this paragraph are
	X *	duplicated in all such forms and that any documentation,
	X *	advertising materials, and other materials related to such
	X *	distribution and use acknowledge that the software was developed
	X *	by the University of California, San Francisco.  The name of the
	X *	University may not be used to endorse or promote products derived
	X *	from this software without specific prior written permission.
	X *	THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
	X *	IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
	X *	WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
	X *
	X *	$Id: pdbrun6_read.i,v 1.3 1995/01/20 01:20:36 gregc Exp $
	X */
	X/* PDBRUN */	"%12  %2d",
	X/* EYEPOS */	"%12  %9f %9f %9f",
	X/* ATPOS */	"%11   %9f %9f %9f",
	X/* WINDOW */	"%12  %9f %9f %9f %9f %9f %9f",
	X/* FOCUS */	"%11   %9f",
	X/* VIEWPORT */	"%14  %9f %9f %9f %9f",
	X/* BGCOLOR */	"%13  %5f %5f %5f",
	X/* ANGLE */	"%11  %6d %6d %6d %6d %9f",
	X/* DISTANCE */	"%14  %6d %6d %9f",
	X/* FILE */	"%10  %4d %56s",
	X/* MARKNAME */	"%14  %57s",
	X/* MARK */	"%10  %57s",
	X/* CNAME */	"%11  %5f %5f %5f %38s",
	X/* COLOR */	"%11  %5f %5f %5f %38s",
	X/* RADIUS */	"%12  %7f",
	X/* OBJECT */	"%12 ",
	X/* ENDOBJ */	"%12 ",
	X/* CHAIN */	"%11  %6d %6d",
	X/* GFX BEGIN */	"%15  %32s",
	X/* GFX END */	"%13 ",
	X/* GFX COLOR */	"%15  %5f %5f %5f %38s",
	X/* GFX NORMAL */	"%16  %9f %9f %9f",
	X/* GFX VERTEX */	"%16  %9f %9f %9f",
	X/* GFX FONT */	"%14  %3d %53s",
	X/* GFX TEXTPOS */	"%17  %9f %9f %9f",
	X/* GFX LABEL */	"%15  %56s",
	X/* GFX MOVE */	NULL,
	X/* GFX DRAW */	NULL,
	X/* GFX MARKER */	NULL,
	X/* GFX POINT */	NULL,
SHAR_EOF
if test 1804 -ne "`wc -c < 'pdbrun6_read.i'`"
then
	echo shar: "error transmitting 'pdbrun6_read.i'" '(should have been 1804 characters)'
fi
fi
echo shar: "extracting 'pdbrun6_write.i'" '(1787 characters)'
if test -f 'pdbrun6_write.i'
then
	echo shar: "will not over-write existing file 'pdbrun6_write.i'"
else
sed 's/^	X//' << \SHAR_EOF > 'pdbrun6_write.i'
	X/*
	X *	Copyright (c) 1994 The Regents of the University of California.
	X *	All rights reserved.
	X *
	X *	Redistribution and use in source and binary forms are permitted
	X *	provided that the above copyright notice and this paragraph are
	X *	duplicated in all such forms and that any documentation,
	X *	advertising materials, and other materials related to such
	X *	distribution and use acknowledge that the software was developed
	X *	by the University of California, San Francisco.  The name of the
	X *	University may not be used to endorse or promote products derived
	X *	from this software without specific prior written permission.
	X *	THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
	X *	IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
	X *	WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
	X *
	X *	$Id: pdbrun6_write.i,v 1.3 1995/01/20 01:20:36 gregc Exp $
	X */
	X"USER  PDBRUN %2d",
	X"USER  EYEPOS %9.3f %9.3f %9.3f",
	X"USER  ATPOS  %9.3f %9.3f %9.3f",
	X"USER  WINDOW %9.3f %9.3f %9.3f %9.3f %9.3f %9.3f",
	X"USER  FOCUS  %9.3f",
	X"USER  VIEWPORT %9.3f %9.3f %9.3f %9.3f",
	X"USER  BGCOLOR %5.3f %5.3f %5.3f",
	X"USER  ANGLE %6d %6d %6d %6d %9.3f",
	X"USER  DISTANCE %6d %6d %9.3f",
	X"USER  FILE %4d %-56s",
	X"USER  MARKNAME %-57s",
	X"USER  MARK %-57s",
	X"USER  CNAME %5.3f %5.3f %5.3f %-42s",
	X"USER  COLOR %5.3f %5.3f %5.3f %-42s",
	X"USER  RADIUS %7.3f",
	X"USER  OBJECT",
	X"USER  ENDOBJ",
	X"USER  CHAIN %6d %6d",
	X"USER  GFX BEGIN %-32s",
	X"USER  GFX END",
	X"USER  GFX COLOR %5.3f %5.3f %5.3f %s",
	X"USER  GFX NORMAL %9.3f %9.3f %9.3f",
	X"USER  GFX VERTEX %9.3f %9.3f %9.3f",
	X"USER  GFX FONT %3d %-53s",
	X"USER  GFX TEXTPOS %9.3f %9.3f %9.3f",
	X"USER  GFX LABEL %-56s",
	XNULL,	/* USER  GFX MOVE */
	XNULL,	/* USER  GFX DRAW */
	XNULL,	/* USER  GFX MARKER */
	XNULL,	/* USER  GFX POINT */
SHAR_EOF
if test 1787 -ne "`wc -c < 'pdbrun6_write.i'`"
then
	echo shar: "error transmitting 'pdbrun6_write.i'" '(should have been 1787 characters)'
fi
fi
echo shar: "extracting 'pdb_int.h'" '(1312 characters)'
if test -f 'pdb_int.h'
then
	echo shar: "will not over-write existing file 'pdb_int.h'"
else
sed 's/^	X//' << \SHAR_EOF > 'pdb_int.h'
	X/*
	X *	Copyright (c) 1989 The Regents of the University of California.
	X *	All rights reserved.
	X *
	X *	Redistribution and use in source and binary forms are permitted
	X *	provided that the above copyright notice and this paragraph are
	X *	duplicated in all such forms and that any documentation,
	X *	advertising materials, and other materials related to such
	X *	distribution and use acknowledge that the software was developed
	X *	by the University of California, San Francisco.  The name of the
	X *	University may not be used to endorse or promote products derived
	X *	from this software without specific prior written permission.
	X *	THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
	X *	IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
	X *	WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
	X *
	X *	$Id: pdb_int.h,v 2.4 1994/11/17 00:58:58 gregc Exp $
	X */
	X
	X#include	"pdb.h"
	X
	X#ifndef __STDC__
	X# define	const
	X#endif
	X
	Xextern int	pdb_pdbrun_version;
	X
	X#ifdef __STDC__
	Xextern int	pdb_sscanf(const char *, const char *, ...);
	Xextern void	pdb_sprintf(char *, const char *, ...);
	Xextern const char	*pdb_gfx_string(int i);
	Xextern int	pdb_gfx_type(const char *type);
	X#else
	Xextern int	pdb_sscanf();
	Xextern void	pdb_sprintf();
	Xextern char	*pdb_gfx_string();
	Xextern int	pdb_gfx_type();
	X#endif
SHAR_EOF
if test 1312 -ne "`wc -c < 'pdb_int.h'`"
then
	echo shar: "error transmitting 'pdb_int.h'" '(should have been 1312 characters)'
fi
fi
echo shar: "extracting 'pdb_read.c'" '(30391 characters)'
if test -f 'pdb_read.c'
then
	echo shar: "will not over-write existing file 'pdb_read.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'pdb_read.c'
	X/*
	X *	Copyright (c) 1989 The Regents of the University of California.
	X *	All rights reserved.
	X *
	X *	Redistribution and use in source and binary forms are permitted
	X *	provided that the above copyright notice and this paragraph are
	X *	duplicated in all such forms and that any documentation,
	X *	advertising materials, and other materials related to such
	X *	distribution and use acknowledge that the software was developed
	X *	by the University of California, San Francisco.  The name of the
	X *	University may not be used to endorse or promote products derived
	X *	from this software without specific prior written permission.
	X *	THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
	X *	IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
	X *	WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
	X *
	X *	$Id: pdb_read.c,v 2.20 1995/07/22 02:03:18 gregc Exp $
	X *
	X *	subroutine for reading PDB format files
	X *
	X */
	X
	X/* LINTLIBRARY */
	X
	X# include	<stdio.h>
	X# include	<ctype.h>
	X# include	<string.h>
	X# include	"pdb_int.h"
	X
	X# ifndef _tolower
	X# define	_tolower	tolower
	X# endif
	X
	X# define	STREQN(a,b,n)	(strncmp(a, b, n) == 0)
	X
	Xstatic const char * const pdb_record_format[PDB_NUM_R] = {
	X#include "read_format.i"
	X};
	X
	Xstatic char const * const pdbrun5[] = {
	X#include "pdbrun5_read.i"
	X};
	X
	Xstatic char const * const pdbrun6[] = {
	X#include "pdbrun6_read.i"
	X};
	X
	X/*
	X *	for each pdb record type there is a format reading in the
	X *	record values and for printing them out.
	X *
	X *	The actual format of a line written, is the print format
	X *	followed by blank padding to 72 characters, followed by
	X *	8 characters of file and line information.
	X */
	X
	Xpdb_record
	X# ifdef __STDC__
	Xpdb_read_record(FILE *f)
	X# else
	Xpdb_read_record(f)
	X	FILE		*f;
	X# endif
	X{
	X
	X	char			buffer[PDB_BUFSIZ];
	X	char			*cp;
	X	int			c;
	X	static pdb_record	r_end = { PDB_END };
	X
	X	if (fgets(buffer, PDB_BUFSIZ, f) == NULL) {
	X		/* at eof or error - default to eof */
	X		return r_end;
	X	}
	X
	X	cp = strchr(buffer, '\n');
	X	if (cp != NULL)
	X		*cp = '\0';
	X	else
	X		/* discard extra characters since line too long */
	X		while ((c = getc(f)) != '\n' && c != EOF)
	X			continue;
	X
	X	return pdb_read_string(buffer);
	X}
	X
	Xstatic int
	X#ifdef __STDC__
	Xpdbrun5_type(const char *buf)
	X#else
	Xpdbrun5_type(buf)
	X	char	*buf;
	X#endif
	X{
	X	switch (buf[0]) {
	X	case 'A': case 'a':
	X		if (strncasecmp(buf + 1, "NGLE ", 5) == 0)
	X			return PDB_USER_ANGLE;
	X		if (strncasecmp(buf + 1, "TPOS ", 5) == 0)
	X			return PDB_USER_ATPOS;
	X		break;
	X	case 'B': case 'b':
	X		if (strncasecmp(buf + 1, "GCOLOR ", 7) == 0)
	X			return PDB_USER_BGCOLOR;
	X		break;
	X	case 'C': case 'c':
	X		if (strncasecmp(buf + 1, "HAIN ", 5) == 0)
	X			return PDB_USER_CHAIN;
	X		if (strncasecmp(buf + 1, "NAME ", 5) == 0)
	X			return PDB_USER_CNAME;
	X		if (strncasecmp(buf + 1, "OLOR ", 5) == 0)
	X			return PDB_USER_COLOR;
	X		break;
	X	case 'D': case 'd':
	X		if (strncasecmp(buf + 1, "ISTANCE ", 8) == 0)
	X			return PDB_USER_DISTANCE;
	X		break;
	X	case 'E': case 'e':
	X		if (strncasecmp(buf + 1, "NDOBJ ", 6) == 0)
	X			return PDB_USER_ENDOBJ;
	X		if (strncasecmp(buf + 1, "YEPOS ", 6) == 0)
	X			return PDB_USER_EYEPOS;
	X		break;
	X	case 'F': case 'f':
	X		if (strncasecmp(buf + 1, "ILE ", 4) == 0)
	X			return PDB_USER_FILE;
	X		if (strncasecmp(buf + 1, "OCUS ", 5) == 0)
	X			return PDB_USER_FOCUS;
	X		break;
	X	case 'G': case 'g':
	X		if (strncasecmp(buf + 1, "FX ", 3) != 0)
	X			break;
	X		if (strncasecmp(buf + 4, "COLOR ", 6) == 0)
	X			return PDB_USER_GFX_COLOR;
	X		if (strncasecmp(buf + 4, "DRAW ", 5) == 0)
	X			return PDB_USER_GFX_DRAW;
	X		if (strncasecmp(buf + 4, "FONT ", 5) == 0)
	X			return PDB_USER_GFX_FONT;
	X		if (strncasecmp(buf + 4, "LABEL ", 6) == 0)
	X			return PDB_USER_GFX_LABEL;
	X		if (strncasecmp(buf + 4, "MARKER ", 7) == 0)
	X			return PDB_USER_GFX_MARKER;
	X		if (strncasecmp(buf + 4, "MOVE ", 5) == 0)
	X			return PDB_USER_GFX_MOVE;
	X		if (strncasecmp(buf + 4, "POINT ", 6) == 0)
	X			return PDB_USER_GFX_POINT;
	X		break;
	X	case 'O': case 'o':
	X		if (strncasecmp(buf + 1, "BJECT ", 6) == 0)
	X			return PDB_USER_OBJECT;
	X		break;
	X	case 'P': case 'p':
	X		if (strncasecmp(buf + 1, "DBRUN ", 6) == 0)
	X			return PDB_USER_PDBRUN;
	X		break;
	X	case 'R': case 'r':
	X		if (strncasecmp(buf + 1, "ADIUS ", 6) == 0)
	X			return PDB_USER_RADIUS;
	X		break;
	X	case 'V': case 'v':
	X		if (strncasecmp(buf + 1, "IEWPORT ", 8) == 0)
	X			return PDB_USER_VIEWPORT;
	X		break;
	X	case 'W': case 'w':
	X		if (strncasecmp(buf + 1, "INDOW ", 6) == 0)
	X			return PDB_USER_WINDOW;
	X		break;
	X	}
	X	return PDB_USER;
	X}
	X
	Xstatic int
	X#ifdef __STDC__
	Xpdbrun6_type(const char *buf)
	X#else
	Xpdbrun6_type(buf)
	X	char	*buf;
	X#endif
	X{
	X	switch (buf[0]) {
	X	case 'A': case 'a':
	X		if (strncasecmp(buf + 1, "NGLE ", 5) == 0)
	X			return PDB_USER_ANGLE;
	X		if (strncasecmp(buf + 1, "TPOS ", 5) == 0)
	X			return PDB_USER_ATPOS;
	X		break;
	X	case 'B': case 'b':
	X		if (strncasecmp(buf + 1, "GCOLOR ", 7) == 0)
	X			return PDB_USER_BGCOLOR;
	X		break;
	X	case 'C': case 'c':
	X		if (strncasecmp(buf + 1, "HAIN ", 5) == 0)
	X			return PDB_USER_CHAIN;
	X		if (strncasecmp(buf + 1, "NAME ", 5) == 0)
	X			return PDB_USER_CNAME;
	X		if (strncasecmp(buf + 1, "OLOR ", 5) == 0)
	X			return PDB_USER_COLOR;
	X		break;
	X	case 'D': case 'd':
	X		if (strncasecmp(buf + 1, "ISTANCE ", 8) == 0)
	X			return PDB_USER_DISTANCE;
	X		break;
	X	case 'E': case 'e':
	X		if (strncasecmp(buf + 1, "NDOBJ", 5) == 0
	X		&& (buf[6] == '\0' || buf[6] == '\n' || buf[6] == ' '))
	X			return PDB_USER_ENDOBJ;
	X		if (strncasecmp(buf + 1, "YEPOS ", 6) == 0)
	X			return PDB_USER_EYEPOS;
	X		break;
	X	case 'F': case 'f':
	X		if (strncasecmp(buf + 1, "ILE ", 4) == 0)
	X			return PDB_USER_FILE;
	X		if (strncasecmp(buf + 1, "OCUS ", 5) == 0)
	X			return PDB_USER_FOCUS;
	X		break;
	X	case 'G': case 'g':
	X		if (buf[1] != 'F' || buf[2] != 'X' || buf[3] != ' ')
	X			break;
	X		switch (buf[4]) {
	X		case 'B': case 'b':
	X			if (strncasecmp(buf + 5, "EGIN ", 5) == 0)
	X				return PDB_USER_GFX_BEGIN;
	X			break;
	X		case 'C': case 'c':
	X			if (strncasecmp(buf + 5, "OLOR ", 5) == 0)
	X				return PDB_USER_GFX_COLOR;
	X			break;
	X		case 'E': case 'e':
	X			if (buf[5] == 'N' && buf[6] == 'D'
	X			&& (buf[7] == '\0' || buf[7] == '\n' || buf[7] == ' '))
	X				return PDB_USER_GFX_END;
	X			break;
	X		case 'F': case 'f':
	X			if (strncasecmp(buf + 5, "ONT ", 4) == 0)
	X				return PDB_USER_GFX_FONT;
	X			break;
	X		case 'L': case 'l':
	X			if (strncasecmp(buf + 5, "ABEL ", 5) == 0)
	X				return PDB_USER_GFX_LABEL;
	X			break;
	X		case 'N': case 'n':
	X			if (strncasecmp(buf + 5, "ORMAL ", 6) == 0)
	X				return PDB_USER_GFX_NORMAL;
	X			break;
	X		case 'T': case 't':
	X			if (strncasecmp(buf + 5, "EXTPOS ", 7) == 0)
	X				return PDB_USER_GFX_TEXTPOS;
	X			break;
	X		case 'V': case 'v':
	X			if (strncasecmp(buf + 5, "ERTEX ", 6) == 0)
	X				return PDB_USER_GFX_VERTEX;
	X			break;
	X		}
	X		break;
	X	case 'M': case 'm':
	X		if (strncasecmp(buf + 1, "ARK ", 4) == 0)
	X			return PDB_USER_MARK;
	X		if (strncasecmp(buf + 1, "ARKNAME ", 6) == 0)
	X			return PDB_USER_MARKNAME;
	X		break;
	X	case 'O': case 'o':
	X		if (strncasecmp(buf + 1, "BJECT", 5) == 0
	X		&& (buf[6] == '\0' || buf[6] == '\n' || buf[6] == ' '))
	X			return PDB_USER_OBJECT;
	X		break;
	X	case 'P': case 'p':
	X		if (strncasecmp(buf + 1, "DBRUN ", 6) == 0)
	X			return PDB_USER_PDBRUN;
	X		break;
	X	case 'R': case 'r':
	X		if (strncasecmp(buf + 1, "ADIUS ", 6) == 0)
	X			return PDB_USER_RADIUS;
	X		break;
	X	case 'V': case 'v':
	X		if (strncasecmp(buf + 1, "IEWPORT ", 6) == 0)
	X			return PDB_USER_VIEWPORT;
	X		break;
	X	case 'W': case 'w':
	X		if (strncasecmp(buf + 1, "INDOW ", 6) == 0)
	X			return PDB_USER_WINDOW;
	X		break;
	X	}
	X	return PDB_USER;
	X}
	X
	Xpdb_record
	X# ifdef __STDC__
	Xpdb_read_string(const char *buffer)
	X# else
	Xpdb_read_string(buffer)
	X	char	*buffer;
	X# endif
	X{
	X
	X	pdb_record		r;
	X	const char		*fmt;
	X	struct pdb_sheet	*sh;
	X	pdb_residue		*sha0, *sha1;
	X	char			record_type[4];
	X	int			i;
	X	char			new_buffer[PDB_BUFSIZ];
	X
	X# if defined(__STDC__) || defined(vms)
	X	(void) memset(&r, 0, sizeof r);
	X# else
	X	bzero((char *) &r, sizeof r);
	X# endif
	X
	X# ifdef DEBUG
	X	printf("%s", buffer);
	X# endif /* DEBUG */
	X
	X	/* convert pdb record to C structure */
	X
	X	for (i = 0; buffer[i] != '\0' && buffer[i] != '\n' && i < 4; i += 1) {
	X		if (isupper(buffer[i]))
	X			record_type[i] = _tolower(buffer[i]);
	X		else
	X			record_type[i] = buffer[i];
	X	}
	X	if (i < 4)
	X		for (; i < 4; i += 1)
	X			record_type[i] = ' ';
	X
	X	r.record_type = PDB_UNKNOWN;
	X	switch (record_type[0]) {
	X
	X	case 'a':
	X		if (STREQN(record_type + 1, "tom", 3))
	X			r.record_type = PDB_ATOM;
	X		else if (STREQN(record_type + 1, "uth", 3))
	X			r.record_type = PDB_AUTHOR;
	X		else if (STREQN(record_type + 1, "nis", 3))
	X			r.record_type = PDB_ANISOU;
	X		else if (STREQN(record_type + 1, "grd", 3))
	X			r.record_type = PDB_AGRDES;
	X		else if (STREQN(record_type + 1, "ggr", 3))
	X			r.record_type = PDB_AGGRGT;
	X		break;
	X
	X	case 'c':
	X		if (STREQN(record_type + 1, "omp", 3))
	X			r.record_type = PDB_COMPND;
	X		else if (STREQN(record_type + 1, "rys", 3))
	X			r.record_type = PDB_CRYST1;
	X		else if (STREQN(record_type + 1, "one", 3))
	X			r.record_type = PDB_CONECT;
	X		else if (STREQN(record_type + 1, "mpd", 3))
	X			r.record_type = PDB_CMPDES;
	X		else if (STREQN(record_type + 1, "mpo", 3))
	X			r.record_type = PDB_CMPONT;
	X		break;
	X
	X	case 'e':
	X		if (STREQN(record_type + 1, "nd ", 3))
	X			r.record_type = PDB_END;
	X		else if (STREQN(record_type + 1, "ndm", 3))
	X			r.record_type = PDB_ENDMDL;
	X		else if (STREQN(record_type + 1, "xpd", 3))
	X			r.record_type = PDB_EXPDTA;
	X		break;
	X
	X	case 'f':
	X		if (STREQN(record_type + 1, "tno", 3))
	X			r.record_type = PDB_FTNOTE;
	X		else if (STREQN(record_type + 1, "orm", 3))
	X			r.record_type = PDB_FORMUL;
	X		break;
	X
	X	case 'h':
	X		if (STREQN(record_type + 1, "eta", 3))
	X			r.record_type = PDB_HETATM;
	X		else if (STREQN(record_type + 1, "ead", 3))
	X			r.record_type = PDB_HEADER;
	X		else if (STREQN(record_type + 1, "et ", 3))
	X			r.record_type = PDB_HET;
	X		else if (STREQN(record_type + 1, "eli", 3))
	X			r.record_type = PDB_HELIX;
	X		break;
	X
	X	case 'j':
	X		if (STREQN(record_type + 1, "rnl", 3))
	X			r.record_type = PDB_JRNL;
	X		break;
	X
	X	case 'm':
	X		if (STREQN(record_type + 1, "tri", 3))
	X			r.record_type = PDB_MTRIX;
	X		else if (STREQN(record_type + 1, "ast", 3))
	X			r.record_type = PDB_MASTER;
	X		else if (STREQN(record_type + 1, "ode", 3))
	X			r.record_type = PDB_MODEL;
	X		else if (STREQN(record_type + 1, "txd", 3))
	X			r.record_type = PDB_MTXDES;
	X		break;
	X
	X	case 'o':
	X		if (STREQN(record_type + 1, "bsl", 3))
	X			r.record_type = PDB_OBSLTE;
	X		else if (STREQN(record_type + 1, "rig", 3))
	X			r.record_type = PDB_ORIGX;
	X		break;
	X
	X	case 'r':
	X		if (STREQN(record_type + 1, "ema", 3))
	X			r.record_type = PDB_REMARK;
	X		else if (STREQN(record_type + 1, "evd", 3))
	X			r.record_type = PDB_REVDAT;
	X		break;
	X
	X	case 's':
	X		switch (record_type[1]) {
	X
	X		case 'c':
	X			if (STREQN(record_type + 2, "al", 2))
	X				r.record_type = PDB_SCALE;
	X			break;
	X
	X		case 'e':
	X			if (STREQN(record_type + 2, "qr", 2))
	X				r.record_type = PDB_SEQRES;
	X			break;
	X
	X		case 'h':
	X			if (STREQN(record_type + 2, "ee", 2))
	X				r.record_type = PDB_SHEET;
	X			break;
	X
	X		case 'i':
	X			if (STREQN(record_type + 2, "te", 2))
	X				r.record_type = PDB_SITE;
	X			else if (STREQN(record_type + 2, "ga", 2))
	X				r.record_type = PDB_SIGATM;
	X			else if (STREQN(record_type + 2, "gu", 2))
	X				r.record_type = PDB_SIGUIJ;
	X			break;
	X
	X		case 'o':
	X			if (STREQN(record_type + 2, "ur", 2))
	X				r.record_type = PDB_SOURCE;
	X			break;
	X
	X		case 'p':
	X			if (STREQN(record_type + 2, "rs", 2))
	X				r.record_type = PDB_SPRSDE;
	X			break;
	X
	X		case 's':
	X			if (STREQN(record_type + 2, "bo", 2))
	X				r.record_type = PDB_SSBOND;
	X			break;
	X
	X		case 'y':
	X			if (STREQN(record_type + 2, "md", 2))
	X				r.record_type = PDB_SYMDES;
	X			else if (STREQN(record_type + 2, "mo", 2))
	X				r.record_type = PDB_SYMOP;
	X			break;
	X		}
	X		break;
	X
	X	case 't':
	X		if (STREQN(record_type + 1, "urn", 3))
	X			r.record_type = PDB_TURN;
	X		else if (STREQN(record_type + 1, "vec", 3))
	X			r.record_type = PDB_TVECT;
	X		else if (STREQN(record_type + 1, "er ", 3))
	X			r.record_type = PDB_TER;
	X		else if (STREQN(record_type + 1, "rns", 3))
	X			r.record_type = PDB_TRNSFM;
	X		break;
	X
	X	case 'u':
	X		if (STREQN(record_type + 1, "ser", 3)) {
	X			r.record_type = PDB_USER;
	X			switch (pdb_pdbrun_version) {
	X			case 1: case 2: case 3: case 4: case 5:
	X				r.record_type = pdbrun5_type(buffer + 6);
	X				break;
	X			case 6:
	X				r.record_type = pdbrun6_type(buffer + 6);
	X				break;
	X			default:
	X				if (strncasecmp(buffer + 6, "PDBRUN ", 7) == 0)
	X					r.record_type = PDB_USER_PDBRUN;
	X				break;
	X			}
	X		}
	X		break;
	X	}
	X
	X	if (r.record_type < PDB_USER_PDBRUN)
	X		fmt = pdb_record_format[r.record_type];
	X	else if (pdb_pdbrun_version < 6)
	X		fmt = pdbrun5[r.record_type - PDB_USER_PDBRUN];
	X	else
	X		fmt = pdbrun6[r.record_type - PDB_USER_PDBRUN];
	X	switch (r.record_type) {
	X
	X	default:
	X	case PDB_UNKNOWN:
	Xunknown:
	X		r.record_type = PDB_UNKNOWN;		/* in case of goto */
	X		(void) pdb_sscanf(buffer, "%72s", r.pdb.unknown.junk);
	X		break;
	X
	X	case PDB_AGGRGT:
	X		if (0 > pdb_sscanf(buffer, fmt, &r.pdb.aggrgt.serial_num,
	X				&r.pdb.aggrgt.num_components,
	X				&r.pdb.aggrgt.cmpont_serial_nums[0],
	X				&r.pdb.aggrgt.cmpont_serial_nums[1],
	X				&r.pdb.aggrgt.cmpont_serial_nums[2],
	X				&r.pdb.aggrgt.cmpont_serial_nums[3],
	X				&r.pdb.aggrgt.cmpont_serial_nums[4],
	X				&r.pdb.aggrgt.cmpont_serial_nums[5],
	X				&r.pdb.aggrgt.cmpont_serial_nums[6],
	X				&r.pdb.aggrgt.cmpont_serial_nums[7],
	X				&r.pdb.aggrgt.cmpont_serial_nums[8],
	X				&r.pdb.aggrgt.cmpont_serial_nums[9],
	X				&r.pdb.aggrgt.cmpont_serial_nums[10],
	X				&r.pdb.aggrgt.cmpont_serial_nums[11],
	X				&r.pdb.aggrgt.cmpont_serial_nums[12],
	X				&r.pdb.aggrgt.cmpont_serial_nums[13]))
	X			goto unknown;
	X		break;
	X	case PDB_ANISOU:
	X	case PDB_SIGUIJ:
	X		if (0 > pdb_sscanf(buffer, fmt, &r.pdb.anisou.serial_num,
	X				r.pdb.anisou.name, &r.pdb.anisou.alt_loc,
	X				r.pdb.anisou.residue.name,
	X				&r.pdb.anisou.residue.chain_id,
	X				&r.pdb.anisou.residue.seq_num,
	X				&r.pdb.anisou.residue.insert_code,
	X				&r.pdb.anisou.u[0], &r.pdb.anisou.u[1],
	X				&r.pdb.anisou.u[2], &r.pdb.anisou.u[3],
	X				&r.pdb.anisou.u[4], &r.pdb.anisou.u[5]))
	X			goto unknown;
	X		break;
	X
	X	case PDB_ATOM:
	X	case PDB_HETATM:
	X	case PDB_SIGATM:
	X		if (0 <= pdb_sscanf(buffer, fmt, &r.pdb.atom.serial_num,
	X				r.pdb.atom.name, &r.pdb.atom.alt_loc,
	X				r.pdb.atom.residue.name,
	X				&r.pdb.atom.residue.chain_id,
	X				&r.pdb.atom.residue.seq_num,
	X				&r.pdb.atom.residue.insert_code,
	X				&r.pdb.atom.x, &r.pdb.atom.y, &r.pdb.atom.z,
	X				&r.pdb.atom.occupancy, &r.pdb.atom.temp_factor,
	X				&r.pdb.atom.ftnote_num))
	X			break;
	X		/* handle atom serial number overflows */
	X		if (strncmp(&buffer[6], "*****", 5) != 0)
	X			goto unknown;
	X		strncpy(new_buffer, buffer, PDB_BUFSIZ);
	X		strncpy(&new_buffer[6], "00000", 5);
	X		if (0 <= pdb_sscanf(new_buffer, fmt, &r.pdb.atom.serial_num,
	X				r.pdb.atom.name, &r.pdb.atom.alt_loc,
	X				r.pdb.atom.residue.name,
	X				&r.pdb.atom.residue.chain_id,
	X				&r.pdb.atom.residue.seq_num,
	X				&r.pdb.atom.residue.insert_code,
	X				&r.pdb.atom.x, &r.pdb.atom.y, &r.pdb.atom.z,
	X				&r.pdb.atom.occupancy, &r.pdb.atom.temp_factor,
	X				&r.pdb.atom.ftnote_num)) {
	X			static int atom_serial_number = 10000;
	X			r.pdb.atom.serial_num = atom_serial_number++;
	X			break;
	X		}
	X		goto unknown;
	X
	X	case PDB_AUTHOR:
	X	case PDB_COMPND:
	X	case PDB_JRNL:
	X	case PDB_SOURCE:
	X	case PDB_EXPDTA:
	X		if (0 > pdb_sscanf(buffer, fmt, &r.pdb.author.continuation,
	X				r.pdb.author.data))
	X			goto unknown;
	X		break;
	X
	X	case PDB_CMPONT:
	X		if (0 > pdb_sscanf(buffer, fmt, &r.pdb.cmpont.seq_num,
	X				r.pdb.cmpont.residues[0].name,
	X				&r.pdb.cmpont.residues[0].chain_id,
	X				&r.pdb.cmpont.residues[0].seq_num,
	X				&r.pdb.cmpont.residues[0].insert_code,
	X				r.pdb.cmpont.residues[1].name,
	X				&r.pdb.cmpont.residues[1].chain_id,
	X				&r.pdb.cmpont.residues[1].seq_num,
	X				&r.pdb.cmpont.residues[1].insert_code))
	X			goto unknown;
	X		break;
	X
	X	case PDB_CONECT:
	X		if (0 > pdb_sscanf(buffer, fmt, &r.pdb.conect.serial_num,
	X				&r.pdb.conect.covalent[0],
	X				&r.pdb.conect.covalent[1],
	X				&r.pdb.conect.covalent[2],
	X				&r.pdb.conect.covalent[3],
	X				&r.pdb.conect.bonds[0].hydrogen[0],
	X				&r.pdb.conect.bonds[0].hydrogen[1],
	X				&r.pdb.conect.bonds[0].salt,
	X				&r.pdb.conect.bonds[1].hydrogen[0],
	X				&r.pdb.conect.bonds[1].hydrogen[1],
	X				&r.pdb.conect.bonds[1].salt))
	X			goto unknown;
	X		break;
	X
	X	case PDB_CRYST1:
	X		if (0 > pdb_sscanf(buffer, fmt, &r.pdb.cryst1.a,
	X				&r.pdb.cryst1.b, &r.pdb.cryst1.c,
	X				&r.pdb.cryst1.alpha, &r.pdb.cryst1.beta,
	X				&r.pdb.cryst1.gamma, r.pdb.cryst1.space_grp,
	X				&r.pdb.cryst1.z))
	X			goto unknown;
	X		break;
	X
	X	case PDB_END:
	X	case PDB_ENDMDL:
	X		break;
	X
	X	case PDB_FORMUL:
	X		if (0 > pdb_sscanf(buffer, fmt, &r.pdb.formul.component,
	X				r.pdb.formul.het_id, &r.pdb.formul.continuation,
	X				&r.pdb.formul.exclude, r.pdb.formul.formula))
	X			goto unknown;
	X		break;
	X
	X	case PDB_FTNOTE:
	X	case PDB_REMARK:
	X	case PDB_SYMDES:
	X	case PDB_MTXDES:
	X	case PDB_CMPDES:
	X	case PDB_AGRDES:
	X		if (0 > pdb_sscanf(buffer, fmt, &r.pdb.ftnote.num,
	X				r.pdb.ftnote.text))
	X			goto unknown;
	X		break;
	X
	X	case PDB_HEADER:
	X		if (0 > pdb_sscanf(buffer, fmt, r.pdb.header.class,
	X				r.pdb.header.date, &r.pdb.header.type,
	X				r.pdb.header.id))
	X			goto unknown;
	X		break;
	X
	X	case PDB_HELIX:
	X		if (0 > pdb_sscanf(buffer, fmt, &r.pdb.helix.serial_num,
	X				r.pdb.helix.id,
	X				r.pdb.helix.residues[0].name,
	X				&r.pdb.helix.residues[0].chain_id,
	X				&r.pdb.helix.residues[0].seq_num,
	X				&r.pdb.helix.residues[0].insert_code,
	X				r.pdb.helix.residues[1].name,
	X				&r.pdb.helix.residues[1].chain_id,
	X				&r.pdb.helix.residues[1].seq_num,
	X				&r.pdb.helix.residues[1].insert_code,
	X				&r.pdb.helix.class, r.pdb.helix.comment))
	X			goto unknown;
	X		break;
	X
	X	case PDB_HET:
	X		if (0 > pdb_sscanf(buffer, fmt, r.pdb.het.het_grp.name,
	X				&r.pdb.het.het_grp.chain_id,
	X				&r.pdb.het.het_grp.seq_num,
	X				&r.pdb.het.het_grp.insert_code,
	X				&r.pdb.het.num_atoms, r.pdb.het.text))
	X			goto unknown;
	X		break;
	X
	X	case PDB_MASTER:
	X		if (0 > pdb_sscanf(buffer, fmt, &r.pdb.master.num_remark,
	X				&r.pdb.master.num_ftnote,
	X				&r.pdb.master.num_het, &r.pdb.master.num_helix,
	X				&r.pdb.master.num_sheet, &r.pdb.master.num_turn,
	X				&r.pdb.master.num_site,
	X				&r.pdb.master.num_transform,
	X				&r.pdb.master.num_coordinate,
	X				&r.pdb.master.num_ter, &r.pdb.master.num_conect,
	X				&r.pdb.master.num_seqres))
	X			goto unknown;
	X		break;
	X
	X	case PDB_MODEL:
	X		if (0 > pdb_sscanf(buffer, fmt, &r.pdb.model.num))
	X			goto unknown;
	X		break;
	X
	X	case PDB_MTRIX:
	X		if (0 > pdb_sscanf(buffer, fmt, &r.pdb.mtrix.row_num,
	X				&r.pdb.mtrix.serial_num, &r.pdb.mtrix.m1,
	X				&r.pdb.mtrix.m2, &r.pdb.mtrix.m3,
	X				&r.pdb.mtrix.v, &r.pdb.mtrix.given))
	X			goto unknown;
	X		break;
	X
	X	case PDB_OBSLTE:
	X		if (0 > pdb_sscanf(buffer, fmt, &r.pdb.obslte.continuation,
	X				r.pdb.obslte.date, r.pdb.obslte.old_id,
	X				r.pdb.obslte.id_map[0], r.pdb.obslte.id_map[1],
	X				r.pdb.obslte.id_map[2], r.pdb.obslte.id_map[3],
	X				r.pdb.obslte.id_map[4], r.pdb.obslte.id_map[2],
	X				r.pdb.obslte.id_map[6], r.pdb.obslte.id_map[7]))
	X			goto unknown;
	X		break;
	X
	X	case PDB_ORIGX:
	X		if (0 > pdb_sscanf(buffer, fmt, &r.pdb.origx.row_num,
	X				&r.pdb.origx.o1, &r.pdb.origx.o2,
	X				&r.pdb.origx.o3, &r.pdb.origx.t))
	X			goto unknown;
	X		break;
	X
	X	case PDB_REVDAT:
	X		if (0 > pdb_sscanf(buffer, fmt, &r.pdb.revdat.modification,
	X				&r.pdb.revdat.continuation, r.pdb.revdat.date,
	X				r.pdb.revdat.id, &r.pdb.revdat.mod_type,
	X				r.pdb.revdat.corrections))
	X			goto unknown;
	X		break;
	X
	X	case PDB_SCALE:
	X		if (0 > pdb_sscanf(buffer, fmt, &r.pdb.scale.row_num,
	X				&r.pdb.scale.s1, &r.pdb.scale.s2,
	X				&r.pdb.scale.s3, &r.pdb.scale.u))
	X			goto unknown;
	X		break;
	X
	X	case PDB_SEQRES:
	X		if (0 > pdb_sscanf(buffer, fmt, &r.pdb.seqres.serial_num,
	X				&r.pdb.seqres.chain_id, &r.pdb.seqres.count,
	X				r.pdb.seqres.names[0], r.pdb.seqres.names[1],
	X				r.pdb.seqres.names[2], r.pdb.seqres.names[3],
	X				r.pdb.seqres.names[4], r.pdb.seqres.names[5],
	X				r.pdb.seqres.names[6], r.pdb.seqres.names[7],
	X				r.pdb.seqres.names[8], r.pdb.seqres.names[9],
	X				r.pdb.seqres.names[10], r.pdb.seqres.names[11],
	X				r.pdb.seqres.names[12]))
	X			goto unknown;
	X		break;
	X
	X	case PDB_SHEET:
	X		sh = &r.pdb.sheet;
	X		sha0 = &sh->atoms[0].residue;
	X		sha1 = &sh->atoms[1].residue;
	X		if (0 > pdb_sscanf(buffer, fmt, &r.pdb.sheet.strand_num,
	X				sh->id, &r.pdb.sheet.count,
	X				sh->residues[0].name, &sh->residues[0].chain_id,
	X				&sh->residues[0].seq_num,
	X				&sh->residues[0].insert_code,
	X				sh->residues[1].name, &sh->residues[1].chain_id,
	X				&sh->residues[1].seq_num,
	X				&sh->residues[1].insert_code, &sh->sense,
	X				sh->atoms[0].name, sha0->name, &sha0->chain_id,
	X				&sha0->seq_num, &sha0->insert_code,
	X				sh->atoms[1].name, sha1->name,
	X				&sha1->chain_id, &sha1->seq_num,
	X				&sha1->insert_code))
	X			goto unknown;
	X		break;
	X
	X	case PDB_SITE:
	X		if (0 > pdb_sscanf(buffer, fmt, &r.pdb.site.seq_num,
	X				r.pdb.site.id, &r.pdb.site.count,
	X				r.pdb.site.residues[0].name,
	X				&r.pdb.site.residues[0].chain_id,
	X				&r.pdb.site.residues[0].seq_num,
	X				&r.pdb.site.residues[0].insert_code,
	X				r.pdb.site.residues[1].name,
	X				&r.pdb.site.residues[1].chain_id,
	X				&r.pdb.site.residues[1].seq_num,
	X				&r.pdb.site.residues[1].insert_code,
	X				r.pdb.site.residues[2].name,
	X				&r.pdb.site.residues[2].chain_id,
	X				&r.pdb.site.residues[2].seq_num,
	X				&r.pdb.site.residues[2].insert_code,
	X				r.pdb.site.residues[3].name,
	X				&r.pdb.site.residues[3].chain_id,
	X				&r.pdb.site.residues[3].seq_num,
	X				&r.pdb.site.residues[3].insert_code))
	X			goto unknown;
	X		break;
	X
	X	case PDB_SPRSDE:
	X		if (0 > pdb_sscanf(buffer, fmt, &r.pdb.sprsde.continuation,
	X				r.pdb.sprsde.date, r.pdb.sprsde.id,
	X				r.pdb.sprsde.supersede[0],
	X				r.pdb.sprsde.supersede[1],
	X				r.pdb.sprsde.supersede[2],
	X				r.pdb.sprsde.supersede[3],
	X				r.pdb.sprsde.supersede[4],
	X				r.pdb.sprsde.supersede[5],
	X				r.pdb.sprsde.supersede[6],
	X				r.pdb.sprsde.supersede[7]))
	X			goto unknown;
	X		break;
	X
	X	case PDB_SSBOND:
	X		if (0 > pdb_sscanf(buffer, fmt, &r.pdb.ssbond.seq_num,
	X				r.pdb.ssbond.residues[0].name,
	X				&r.pdb.ssbond.residues[0].chain_id,
	X				&r.pdb.ssbond.residues[0].seq_num,
	X				&r.pdb.ssbond.residues[0].insert_code,
	X				r.pdb.ssbond.residues[1].name,
	X				&r.pdb.ssbond.residues[1].chain_id,
	X				&r.pdb.ssbond.residues[1].seq_num,
	X				&r.pdb.ssbond.residues[1].insert_code,
	X				r.pdb.ssbond.comment))
	X			goto unknown;
	X		break;
	X
	X	case PDB_SYMOP:
	X		if (0 > pdb_sscanf(buffer, fmt, &r.pdb.symop.row_num,
	X				&r.pdb.symop.serial_num, &r.pdb.symop.s1,
	X				&r.pdb.symop.s2, &r.pdb.symop.s3,
	X				&r.pdb.symop.t))
	X			goto unknown;
	X		break;
	X
	X	case PDB_TER:
	X		if (0 > pdb_sscanf(buffer, fmt, &r.pdb.ter.serial_num,
	X				r.pdb.ter.residue.name,
	X				&r.pdb.ter.residue.chain_id,
	X				&r.pdb.ter.residue.seq_num,
	X				&r.pdb.ter.residue.insert_code))
	X			goto unknown;
	X		break;
	X
	X	case PDB_TRNSFM:
	X		if (0 > pdb_sscanf(buffer, fmt, &r.pdb.trnsfm.result_serial_num,
	X				&r.pdb.trnsfm.apply_serial_num,
	X				&r.pdb.trnsfm.source_serial_num))
	X			goto unknown;
	X		break;
	X
	X	case PDB_TURN:
	X		if (0 > pdb_sscanf(buffer, fmt, &r.pdb.turn.seq_num,
	X				r.pdb.turn.id, r.pdb.turn.residues[0].name,
	X				&r.pdb.turn.residues[0].chain_id,
	X				&r.pdb.turn.residues[0].seq_num,
	X				&r.pdb.turn.residues[0].insert_code,
	X				r.pdb.turn.residues[1].name,
	X				&r.pdb.turn.residues[1].chain_id,
	X				&r.pdb.turn.residues[1].seq_num,
	X				&r.pdb.turn.residues[1].insert_code,
	X				r.pdb.turn.comment))
	X			goto unknown;
	X		break;
	X
	X	case PDB_TVECT:
	X		if (0 > pdb_sscanf(buffer, fmt, &r.pdb.tvect.serial_num,
	X				&r.pdb.tvect.t1, &r.pdb.tvect.t2,
	X				&r.pdb.tvect.t3, r.pdb.tvect.comment))
	X			goto unknown;
	X		break;
	X
	Xuser:
	X		r.record_type = PDB_USER;
	X		fmt = pdb_record_format[r.record_type];
	X	case PDB_USER:
	X		if (0 > pdb_sscanf(buffer, fmt, r.pdb.user.subtype,
	X				r.pdb.user.text))
	X			goto unknown;
	X		break;
	X
	X	case PDB_USER_PDBRUN:
	X		if (0 > pdb_sscanf(buffer, fmt, &r.pdb.user_pdbrun.version))
	X			goto user;
	X		pdb_pdbrun_version = r.pdb.user_pdbrun.version;
	X		break;
	X
	X	case PDB_USER_EYEPOS:
	X		if (0 > pdb_sscanf(buffer, fmt, &r.pdb.user_eyepos.xyz[0],
	X				&r.pdb.user_eyepos.xyz[1],
	X				&r.pdb.user_eyepos.xyz[2]))
	X			goto user;
	X		break;
	X
	X	case PDB_USER_ATPOS:
	X		if (0 > pdb_sscanf(buffer, fmt, &r.pdb.user_atpos.xyz[0],
	X				&r.pdb.user_atpos.xyz[1],
	X				&r.pdb.user_atpos.xyz[2]))
	X			goto user;
	X		break;
	X
	X	case PDB_USER_WINDOW:
	X		if (0 > pdb_sscanf(buffer, fmt, &r.pdb.user_window.left,
	X				&r.pdb.user_window.right,
	X				&r.pdb.user_window.bottom,
	X				&r.pdb.user_window.top,
	X				&r.pdb.user_window.hither,
	X				&r.pdb.user_window.yon))
	X			goto user;
	X		break;
	X
	X	case PDB_USER_FOCUS:
	X		if (0 > pdb_sscanf(buffer, fmt, &r.pdb.user_focus.focus))
	X			goto user;
	X		break;
	X
	X	case PDB_USER_VIEWPORT:
	X		if (0 > pdb_sscanf(buffer, fmt, &r.pdb.user_viewport.xmin,
	X				&r.pdb.user_viewport.xmax,
	X				&r.pdb.user_viewport.ymin,
	X				&r.pdb.user_viewport.ymax))
	X			goto user;
	X		break;
	X
	X	case PDB_USER_BGCOLOR:
	X		if (pdb_pdbrun_version < 6) {
	X			if (0 > sscanf(buffer, fmt, &r.pdb.user_bgcolor.rgb[0],
	X					&r.pdb.user_bgcolor.rgb[1],
	X					&r.pdb.user_bgcolor.rgb[2]))
	X				goto user;
	X		} else if (0 > pdb_sscanf(buffer, fmt,
	X				&r.pdb.user_bgcolor.rgb[0],
	X				&r.pdb.user_bgcolor.rgb[1],
	X				&r.pdb.user_bgcolor.rgb[2]))
	X			goto user;
	X		break;
	X
	X	case PDB_USER_ANGLE:
	X		if (pdb_pdbrun_version < 6) {
	X			if (0 > pdb_sscanf(buffer, fmt, &r.pdb.user_angle.which,
	X					&r.pdb.user_angle.atom0,
	X					&r.pdb.user_angle.atom1,
	X					&r.pdb.user_angle.atom2,
	X					&r.pdb.user_angle.atom3,
	X					&r.pdb.user_angle.angle))
	X				goto user;
	X		} else if (0 > pdb_sscanf(buffer, fmt, &r.pdb.user_angle.atom0,
	X				&r.pdb.user_angle.atom1,
	X				&r.pdb.user_angle.atom2,
	X				&r.pdb.user_angle.atom3,
	X				&r.pdb.user_angle.angle))
	X			goto user;
	X		break;
	X
	X	case PDB_USER_DISTANCE:
	X		if (pdb_pdbrun_version < 6) {
	X			if (0 > pdb_sscanf(buffer, fmt,
	X					&r.pdb.user_distance.which,
	X					&r.pdb.user_distance.atom0,
	X					&r.pdb.user_distance.atom1,
	X					&r.pdb.user_distance.distance))
	X				goto user;
	X		} else if (0 > pdb_sscanf(buffer, fmt,
	X				&r.pdb.user_distance.atom0,
	X				&r.pdb.user_distance.atom1,
	X				&r.pdb.user_distance.distance))
	X			goto user;
	X		break;
	X
	X	case PDB_USER_FILE:
	X		if (pdb_pdbrun_version < 6) {
	X			if (0 > pdb_sscanf(buffer, fmt,
	X						r.pdb.user_file.filename))
	X				goto user;
	X		} else if (0 > pdb_sscanf(buffer, fmt, &r.pdb.user_file.model,
	X						r.pdb.user_file.filename))
	X			goto user;
	X		break;
	X
	X	case PDB_USER_MARKNAME:
	X		if (0 > pdb_sscanf(buffer, fmt, r.pdb.user_markname.markname))
	X			goto user;
	X		break;
	X
	X	case PDB_USER_MARK:
	X		if (0 > pdb_sscanf(buffer, fmt, r.pdb.user_mark.markname))
	X			goto user;
	X		break;
	X
	X	case PDB_USER_CNAME:
	X		if (pdb_pdbrun_version < 6) {
	X			if (0 > sscanf(buffer, fmt, r.pdb.user_cname.name,
	X					&r.pdb.user_cname.rgb[0],
	X					&r.pdb.user_cname.rgb[1],
	X					&r.pdb.user_cname.rgb[2]))
	X				goto user;
	X		} else if (0 > pdb_sscanf(buffer, fmt, &r.pdb.user_cname.rgb[0],
	X				&r.pdb.user_cname.rgb[1],
	X				&r.pdb.user_cname.rgb[2],
	X				r.pdb.user_cname.name))
	X			goto user;
	X		break;
	X
	X	case PDB_USER_COLOR:
	X		if (pdb_pdbrun_version < 6) {
	X			if (0 > sscanf(buffer, fmt, r.pdb.user_color.spec,
	X					&r.pdb.user_color.rgb[0],
	X					&r.pdb.user_color.rgb[1],
	X					&r.pdb.user_color.rgb[2]))
	X				goto user;
	X		} else if (0 > pdb_sscanf(buffer, fmt, &r.pdb.user_color.rgb[0],
	X				&r.pdb.user_color.rgb[1],
	X				&r.pdb.user_color.rgb[2],
	X				r.pdb.user_color.spec))
	X			goto user;
	X		break;
	X
	X	case PDB_USER_RADIUS:
	X		if (0 > pdb_sscanf(buffer, fmt, &r.pdb.user_radius.radius))
	X			goto user;
	X		break;
	X
	X	case PDB_USER_OBJECT:
	X		if (pdb_pdbrun_version < 6) {
	X			if (0 > pdb_sscanf(buffer, fmt,
	X					&r.pdb.user_object.model))
	X				goto user;
	X		}
	X		break;
	X
	X	case PDB_USER_ENDOBJ:
	X		if (pdb_pdbrun_version < 6) {
	X			if (0 > pdb_sscanf(buffer, fmt,
	X					&r.pdb.user_endobj.model))
	X				goto user;
	X		}
	X		break;
	X
	X	case PDB_USER_CHAIN:
	X		if (pdb_pdbrun_version < 6) {
	X			if (0 > sscanf(buffer, fmt, &r.pdb.user_chain.atom0,
	X					&r.pdb.user_chain.atom1))
	X				goto user;
	X		} else if (0 > pdb_sscanf(buffer, fmt, &r.pdb.user_chain.atom0,
	X				&r.pdb.user_chain.atom1))
	X			goto user;
	X		break;
	X
	X	case PDB_USER_GFX_BEGIN:
	X		if (0 > pdb_sscanf(buffer, fmt, r.pdb.user_gfx_begin.unknown))
	X			goto user;
	X		r.pdb.user_gfx_begin.primitive
	X			= pdb_gfx_type(r.pdb.user_gfx_begin.unknown);
	X		break;
	X
	X	case PDB_USER_GFX_END:
	X		break;
	X
	X	case PDB_USER_GFX_COLOR:
	X		if (pdb_pdbrun_version < 6) {
	X			if (0 > sscanf(buffer, fmt, r.pdb.user_gfx_color.spec,
	X					&r.pdb.user_gfx_color.rgb[0],
	X					&r.pdb.user_gfx_color.rgb[1],
	X					&r.pdb.user_gfx_color.rgb[2]))
	X				goto user;
	X		} else if (0 > pdb_sscanf(buffer, fmt,
	X				&r.pdb.user_gfx_color.rgb[0],
	X				&r.pdb.user_gfx_color.rgb[1],
	X				&r.pdb.user_gfx_color.rgb[2],
	X				r.pdb.user_gfx_color.spec))
	X			goto user;
	X		break;
	X
	X	case PDB_USER_GFX_NORMAL:
	X		if (0 > pdb_sscanf(buffer, fmt, &r.pdb.user_gfx_normal.xyz[0],
	X				&r.pdb.user_gfx_normal.xyz[1],
	X				&r.pdb.user_gfx_normal.xyz[2]))
	X			goto user;
	X		break;
	X
	X	case PDB_USER_GFX_VERTEX:
	X		if (0 > pdb_sscanf(buffer, fmt, &r.pdb.user_gfx_vertex.xyz[0],
	X				&r.pdb.user_gfx_vertex.xyz[1],
	X				&r.pdb.user_gfx_vertex.xyz[2]))
	X			goto user;
	X		break;
	X
	X	case PDB_USER_GFX_FONT:
	X		if (pdb_pdbrun_version < 6) {
	X			if (0 > sscanf(buffer, fmt, r.pdb.user_gfx_font.name,
	X					&r.pdb.user_gfx_font.size))
	X				goto user;
	X		} else if (0 > pdb_sscanf(buffer, fmt,
	X				&r.pdb.user_gfx_font.size,
	X				r.pdb.user_gfx_font.name))
	X			goto user;
	X		break;
	X
	X	case PDB_USER_GFX_TEXTPOS:
	X		if (0 > pdb_sscanf(buffer, fmt, &r.pdb.user_gfx_textpos.xyz[0],
	X				&r.pdb.user_gfx_textpos.xyz[1],
	X				&r.pdb.user_gfx_textpos.xyz[2]))
	X			goto user;
	X		break;
	X
	X	case PDB_USER_GFX_LABEL:
	X		if (pdb_pdbrun_version < 6) {
	X			if (0 > sscanf(buffer, fmt,
	X					&r.pdb.user_gfx_label.xyz[0],
	X					&r.pdb.user_gfx_label.xyz[1],
	X					&r.pdb.user_gfx_label.xyz[2],
	X					r.pdb.user_gfx_label.text))
	X				goto user;
	X		} else if (0 > pdb_sscanf(buffer, fmt,
	X				r.pdb.user_gfx_label.text))
	X			goto user;
	X		/* TODO: process text? */
	X		break;
	X
	X	case PDB_USER_GFX_MOVE:
	X		if (0 > pdb_sscanf(buffer, fmt, &r.pdb.user_gfx_move.xyz[0],
	X				&r.pdb.user_gfx_move.xyz[1],
	X				&r.pdb.user_gfx_move.xyz[2]))
	X			goto user;
	X		break;
	X
	X	case PDB_USER_GFX_DRAW:
	X		if (0 > pdb_sscanf(buffer, fmt, &r.pdb.user_gfx_draw.xyz[0],
	X				&r.pdb.user_gfx_draw.xyz[1],
	X				&r.pdb.user_gfx_draw.xyz[2]))
	X			goto user;
	X		break;
	X
	X	case PDB_USER_GFX_MARKER:
	X		if (0 > pdb_sscanf(buffer, fmt, &r.pdb.user_gfx_marker.xyz[0],
	X				&r.pdb.user_gfx_marker.xyz[1],
	X				&r.pdb.user_gfx_marker.xyz[2]))
	X			goto user;
	X		break;
	X
	X	case PDB_USER_GFX_POINT:
	X		if (0 > pdb_sscanf(buffer, fmt, &r.pdb.user_gfx_point.xyz[0],
	X				&r.pdb.user_gfx_point.xyz[1],
	X				&r.pdb.user_gfx_point.xyz[2]))
	X			goto user;
	X		break;
	X	}
	X	
	X	return r;
	X}
	X
	X# ifdef vms
	Xpdb_read_dummy()
	X{
	X	pdb_fmt_dummy();
	X}
	X# endif
SHAR_EOF
if test 30391 -ne "`wc -c < 'pdb_read.c'`"
then
	echo shar: "error transmitting 'pdb_read.c'" '(should have been 30391 characters)'
fi
fi
echo shar: "extracting 'pdb_sprntf.c'" '(10000 characters)'
if test -f 'pdb_sprntf.c'
then
	echo shar: "will not over-write existing file 'pdb_sprntf.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'pdb_sprntf.c'
	X/*
	X *	Copyright (c) 1989 The Regents of the University of California.
	X *	All rights reserved.
	X *
	X *	Redistribution and use in source and binary forms are permitted
	X *	provided that the above copyright notice and this paragraph are
	X *	duplicated in all such forms and that any documentation,
	X *	advertising materials, and other materials related to such
	X *	distribution and use acknowledge that the software was developed
	X *	by the University of California, San Francisco.  The name of the
	X *	University may not be used to endorse or promote products derived
	X *	from this software without specific prior written permission.
	X *	THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
	X *	IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
	X *	WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
	X *
	X *	$Id: pdb_sprntf.c,v 2.4 1994/04/15 22:34:24 gregc Exp $
	X */
	X
	X/* LINTLIBRARY */
	X
	X# include	<stdio.h>
	X# include	<ctype.h>
	X# include	<string.h>
	X# ifdef __STDC__
	X# include	<stdarg.h>
	X# else
	X# include	<varargs.h>
	X# endif
	X
	Xstatic char	scratch[BUFSIZ];
	X
	X# define	OVERFLOW_CHAR	'*'
	X
	X# ifdef __STDC__
	Xstatic char	*outint(int, int, int, char, char, int, char *, char);
	Xstatic char	*outunsigned(unsigned int, int, char, int, char *);
	Xstatic char	*outstr(char *, int, int, char, int, char *);
	Xstatic char	*outfloat(double, int, int, char, int, char *);
	Xstatic char	*outexp(double, int, int, char, int, char *);
	Xstatic char	*e_out(int, char *);
	X# else
	Xstatic char	*outint(), *outunsigned(), *outstr(), *outfloat(), *outexp();
	Xstatic char	*e_out();
	X# endif
	X
	X# ifdef __STDC__
	Xvoid
	Xpdb_sprintf(char *outbuf, const char *fmt, ...)
	X# else
	X/*VARARGS2*/
	Xvoid
	Xpdb_sprintf(outbuf, fmt, va_alist)
	Xchar	*outbuf;
	Xchar	*fmt;
	Xva_dcl
	X# endif
	X{
	X	va_list		argv;
	X	char		*p;
	X	const char	*f;
	X	int		field1, field2;
	X	char		c, fill_char;
	X	int		inum;
	X	unsigned 	unum;
	X	double		fnum;
	X	int		left_justify;
	X
	X# ifdef __STDC__
	X	va_start(argv, fmt);
	X# else
	X	va_start(argv);
	X# endif
	X	f = fmt;
	X	p = outbuf;
	X	while (*f) {
	X		if (*f == '%') {
	X			f++;
	X			if (*f == '-')
	X				left_justify = 1, f++;
	X			else
	X				left_justify = 0;
	X
	X			if (*f == '0')
	X				fill_char = '0', f++;
	X			else
	X				fill_char = ' ';
	X
	X			if (isdigit(*f)) {
	X				field1 = *f++ - '0';
	X				while (isdigit(*f))
	X					field1 = field1 * 10 + *f++ - '0';
	X			}
	X			else
	X				field1 = -1;
	X
	X			if (*f == '.') {
	X				f++;
	X				field2 = 0;
	X				while (isdigit(*f))
	X					field2 = field2 * 10 + *f++ - '0';
	X			}
	X			else
	X				field2 = -1;
	X
	X			if (*f == 'l' || *f == 'h')
	X				f++;
	X
	X			while (isspace(*f))
	X				f++;
	X			switch (*f) {
	X			  case 'c':
	X				c = (char) va_arg(argv, int);
	X				if (c == '\0')
	X					c = ' ';
	X				if (left_justify)
	X					*p++ = c;
	X				while (--field1 > 0)
	X					*p++ = fill_char;
	X				if (!left_justify)
	X					*p++ = c;
	X				break;
	X			  case 'd':
	X			  case 'D':
	X				inum = va_arg(argv, int);
	X				p = outint(inum, field1, 10, fill_char, 'a',
	X					left_justify, p, (*f == 'D') ? ' ':'0');
	X				break;
	X			  case 'e':
	X				fnum = va_arg(argv, double);
	X				if (field2 < 0)
	X					field2 = 6;
	X				p = outexp(fnum, field1, field2, fill_char,
	X					left_justify, p);
	X				break;
	X			  case 'f':
	X				fnum = va_arg(argv, double);
	X				if (field2 < 0)
	X					field2 = 6;
	X				p = outfloat(fnum, field1, field2, fill_char,
	X					left_justify, p);
	X				break;
	X			  case 'o':
	X				inum = va_arg(argv, int);
	X				p = outint(inum, field1, 8, fill_char, 'a',
	X					left_justify, p, '0');
	X				break;
	X			  case 's':
	X				p = outstr(va_arg(argv, char *), field1, field2,
	X					fill_char, left_justify, p);
	X				break;
	X			  case 'u':
	X				unum = va_arg(argv, unsigned);
	X				p = outunsigned(unum, field1, fill_char,
	X					left_justify, p);
	X				break;
	X			  case 'x':
	X				inum = va_arg(argv, int);
	X				p = outint(inum, field1, 16, fill_char, 'a',
	X					left_justify, p, '0');
	X				break;
	X			  case 'X':
	X				inum = va_arg(argv, int);
	X				p = outint(inum, field1, 16, fill_char, 'A',
	X					left_justify, p, '0');
	X				break;
	X			  default:
	X				if (left_justify)
	X					*p++ = *f;
	X				while (--field1 > 0)
	X					*p++ = fill_char;
	X				if (!left_justify)
	X					*p++ = *f;
	X				break;
	X			}
	X			f++;
	X		}
	X		else if (*f == '\\') {		/* Special character */
	X			switch (*++f) {
	X			  case 'n':
	X				*p++ = '\n';
	X				break;
	X			  case 'r':
	X				*p++ = '\r';
	X				break;
	X			  case 'b':
	X				*p++ = '\b';
	X				break;
	X			  case 't':
	X				*p++ = '\t';
	X				break;
	X			  case 'f':
	X				*p++ = '\f';
	X				break;
	X			  case '0': case '1': case '2': case '3':
	X			  case '4': case '5': case '6': case '7':
	X				inum = *f++ - '0';
	X				if (*f >= '0' && *f <= '7') {
	X					inum = inum * 8 + *f++ - '0';
	X					if (*f >= '0' && *f <= '7')
	X						inum = inum * 8 + *f++ - '0';
	X				}
	X				f--;
	X				*p++ = (char) inum;
	X				break;
	X			  default:
	X				*p++ = *f;
	X			}
	X			f++;
	X		}
	X		else				/* Normal character */
	X			*p++ = *f++;
	X	}
	X	*p = '\0';
	X	va_end(argv);
	X}
	X
	Xstatic char *
	X# ifdef __STDC__
	Xe_out(int width, char *where)
	X# else
	Xe_out(width, where)
	X	int	width;
	X	char	*where;
	X# endif
	X{
	X	while (width-- > 0)
	X		*where++ = OVERFLOW_CHAR;
	X	return where;
	X}
	X
	Xstatic char *
	X# ifdef __STDC__
	Xoutint(int value, int width, int radix, char fill_char, char hex,
	X					int left_justify, char *p, char zero)
	X# else
	Xoutint(value, width, radix, fill_char, hex, left_justify, p, zero)
	X	int	value, width;
	X	int	radix;
	X	char	fill_char;
	X	char	hex;
	X	int	left_justify;
	X	char	*p;
	X	char	zero;
	X# endif
	X{
	X	char	*s;
	X	int	n;
	X	int	negative;
	X
	X	if (value < 0)
	X		negative = 1, value = -value, width--;
	X	else
	X		negative = 0;
	X	s = scratch;
	X	if (value)
	X		do {
	X			n = value % radix;
	X			*s++ = n < 10 ? '0' + n : hex + n - 10;
	X			value /= radix;
	X		} while (value);
	X	else
	X		*s++ = zero;
	X	n = s - scratch;
	X	if (width != -1 && n > width)
	X		return e_out(width + negative, p);
	X
	X	if (negative && fill_char == '0')
	X		*p++ = '-';
	X	if (!left_justify)
	X		while (width-- > n)
	X			*p++ = fill_char;
	X	if (negative && fill_char == ' ')
	X		*p++ = '-';
	X	while (--s >= scratch)
	X		*p++ = *s;
	X	if (left_justify)
	X		while (width-- > n)
	X			*p++ = fill_char;
	X	return p;
	X}
	X
	Xstatic char *
	X# ifdef __STDC__
	Xoutunsigned(unsigned int value, int width, char fill_char, int left_justify,
	X									char *p)
	X# else
	Xoutunsigned(value, width, fill_char, left_justify, p)
	X	unsigned int	value;
	X	int		width;
	X	char		fill_char;
	X	int		left_justify;
	X	char		*p;
	X# endif
	X{
	X	char	*s;
	X	int	n;
	X
	X	s = scratch;
	X	while (value) {
	X		*s++ = value % 10 + '0';
	X		value /= 10;
	X	}
	X	n = s - scratch;
	X	if (n == 0)
	X		*s++ = '0', n = 1;
	X	if (width != -1 && n > width)
	X		return e_out(width, p);
	X
	X	if (!left_justify)
	X		while (width-- > n)
	X			*p++ = fill_char;
	X	while (--s >= scratch)
	X		*p++ = *s;
	X	if (left_justify)
	X		while (width-- > n)
	X			*p++ = fill_char;
	X	return p;
	X}
	X
	Xstatic char *
	X# ifdef __STDC__
	Xoutstr(char *s, int width, int maxstr, char fill_char, int left_justify, char *p)
	X# else
	Xoutstr(s, width, maxstr, fill_char, left_justify, p)
	X	char	*s;
	X	int	width;
	X	int	maxstr;
	X	char	fill_char;
	X	int	left_justify;
	X	char	*p;
	X# endif
	X{
	X	int	len;
	X
	X	len = strlen(s);
	X	if (maxstr >= 0 && len > maxstr)
	X		len = maxstr;
	X	if (width != -1 && len > width)
	X		return e_out(width, p);
	X
	X	if (!left_justify)
	X		while (width-- > len)
	X			*p++ = fill_char;
	X	else
	X		width -= len;
	X	while (len--)
	X		*p++ = *s++;
	X	if (left_justify)
	X		while (width-- > 0)
	X			*p++ = fill_char;
	X	return p;
	X}
	X
	Xstatic char *
	X# ifdef __STDC__
	Xoutfloat(double value, int width, int nplace, char fill_char, int left_justify,
	X									char *p)
	X# else
	Xoutfloat(value, width, nplace, fill_char, left_justify, p)
	X	double	value;
	X	int	width, nplace;
	X	char	fill_char;
	X	int	left_justify;
	X	char	*p;
	X# endif
	X{
	X	int	i, intval;
	X	char	*place, *to, *from;
	X	int	negative;
	X
	X	negative = value < 0.0 ? 1 : 0;
	X		
	X	if (negative)
	X		value = -value;
	X
	X	for (i = 0; i < nplace; i++)
	X		value *= 10.0;
	X
	X	intval = value + 0.5;
	X
	X	if (width == -1)
	X		width = nplace + 4;		/* TODO: fix */
	X	else if (nplace + (nplace == 0 ? 1 : 2) > width)
	X		return e_out(width, p);
	X
	X	for (place = p + width - 1; place >= p + width - nplace; place--) {
	X		*place = '0' + intval % 10;
	X		intval /= 10;
	X	}
	X
	X	if (nplace > 0)
	X		*place-- = '.';
	X
	X	if (intval == 0)
	X		*place-- = '0';
	X
	X	for (; place >= p; place--) {
	X		if (intval == 0)
	X			break;
	X		else {
	X			*place = '0' + intval % 10;
	X			intval /= 10;
	X		}
	X	}
	X
	X	if (intval != 0)
	X		return e_out(width, p);
	X
	X	if (place < p && negative)
	X		return e_out(width, p);
	X
	X	if (left_justify) {
	X		for (from = place + 1, to = (negative ? p + 1 : p);
	X						from < p + width; from++, to++)
	X			*to = *from;
	X		for (; to < p + width; to++)
	X			*to = fill_char;
	X		if (negative)
	X			*p = '-';
	X	} else {
	X		for (to = place; to >= p; to--)
	X			*to = fill_char;
	X		if (negative)
	X			if (fill_char == ' ')
	X				*place = '-';
	X			else
	X				*p = '-';
	X	}
	X
	X	return p + width;
	X}
	X
	Xstatic char *
	X# ifdef __STDC__
	Xoutexp(double value, int width, int nplace, char fill_char, int left_justify,
	X									char *p)
	X# else
	Xoutexp(value, width, nplace, fill_char, left_justify, p)
	X	double	value;
	X	int	width, nplace;
	X	char	*p;
	X	char	fill_char;
	X	int	left_justify;
	X# endif
	X{
	X	int	n;
	X	char	*s;
	X	int	negative;
	X	double	fraction;
	X
	X	if (value < 0)
	X		negative = 1, value = -value, width--;
	X	else
	X		negative = 0;
	X
	X	n = 0;
	X	while (value > 10)
	X		n++, value /= 10;
	X	if (value)
	X		while (value < 1)
	X			n--, value *= 10;
	X
	X	s = scratch;
	X	if (n < 0) {
	X		n = -n;
	X		*s++ = n % 10 + '0';
	X		*s++ = n / 10 + '0';
	X		*s++ = '-';
	X	}
	X	else {
	X		*s++ = n % 10 + '0';
	X		*s++ = n / 10 + '0';
	X		*s++ = '+';
	X	}
	X	*s = 'e';
	X
	X	s = scratch + nplace + 4;	/* 4 == strlen("e+00") */
	X	fraction = value - (int) value;
	X	for (n = 0; n < nplace; n++) {
	X		fraction *= 10.0;
	X		*--s = '0' + (int) fraction;
	X		fraction -= (int) fraction;
	X	}
	X
	X	s = scratch + nplace + 4;
	X	if (nplace)
	X		*s++ = '.';
	X	n = (int) value;
	X	if (n)
	X		*s++ = n % 10 + '0';
	X	else
	X		*s++ = '0';
	X	n = s - scratch;
	X	if (width != -1 && n > width)
	X		return e_out(width + negative, p);
	X
	X	if (negative && fill_char == '0')
	X		*p++ = '-';
	X	if (!left_justify)
	X		while (width-- > n)
	X			*p++ = fill_char;
	X	if (negative && fill_char == ' ')
	X		*p++ = '-';
	X	while (--s >= scratch)
	X		*p++ = *s;
	X	if (left_justify)
	X		while (width-- > n)
	X			*p++ = fill_char;
	X	return p;
	X}
SHAR_EOF
if test 10000 -ne "`wc -c < 'pdb_sprntf.c'`"
then
	echo shar: "error transmitting 'pdb_sprntf.c'" '(should have been 10000 characters)'
fi
fi
echo shar: "extracting 'pdb_sscanf.c'" '(5183 characters)'
if test -f 'pdb_sscanf.c'
then
	echo shar: "will not over-write existing file 'pdb_sscanf.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'pdb_sscanf.c'
	X/*
	X *	Copyright (c) 1989 The Regents of the University of California.
	X *	All rights reserved.
	X *
	X *	Redistribution and use in source and binary forms are permitted
	X *	provided that the above copyright notice and this paragraph are
	X *	duplicated in all such forms and that any documentation,
	X *	advertising materials, and other materials related to such
	X *	distribution and use acknowledge that the software was developed
	X *	by the University of California, San Francisco.  The name of the
	X *	University may not be used to endorse or promote products derived
	X *	from this software without specific prior written permission.
	X *	THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
	X *	IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
	X *	WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
	X *
	X *	$Id: pdb_sscanf.c,v 2.8 1994/04/15 22:34:24 gregc Exp $
	X */
	X
	X/* LINTLIBRARY */
	X
	X# include	<stdio.h>
	X# include	<ctype.h>
	X# ifdef __STDC__
	X# include	<stdarg.h>
	X# include	<stdlib.h>
	X# else
	X# include	<varargs.h>
	X
	Xextern int	atoi();
	Xextern double	atof();
	X# endif
	X
	X/*
	X *	pdb_sscanf performs similarly to sscanf, execept that fields are of
	X *	fixed length and a complete line is always consumed.  The field
	X *	width defaults to one.  If the line is shorter than expected then
	X *	the default is returned.
	X *
	X *		d	get an integer.  Default:  0.
	X *		f	get a floating point number (C double).  Default:  0.0.
	X *		(space) ignore characters within field
	X *		s	get a C string, leading and trailing spaces are
	X *			stripped; the field width is used as a limit on
	X *			the string length, the null character is appended
	X *			to the end of the string.  Default:  empty string.
	X *		c	get a character(s); no stripping of spaces, nor is
	X *			a null character appended.  Default:  space(s).
	X */
	X
	X# define	MAXFIELDSIZE	64
	X
	Xint
	X# ifdef __STDC__
	Xpdb_sscanf(const char *buffer, const char *fmt, ...)
	X# else
	X/*VARARGS2*/
	Xpdb_sscanf(buffer, fmt, va_alist)
	X	char	*buffer;
	X	char	*fmt;
	X	va_dcl
	X# endif
	X{
	X	va_list	ap;
	X	int	i, field_width;
	X	int	nmatch;
	X	char	*s, *t;
	X	char	tmp[MAXFIELDSIZE];
	X
	X# ifdef __STDC__
	X	va_start(ap, fmt);
	X# else
	X	va_start(ap);
	X# endif
	X	nmatch = 0;
	X	for (; *fmt != '\0'; fmt++) {
	X		if (*fmt != '%') {
	X			if (*buffer == *fmt)
	X				buffer++;
	X			else if (*buffer != '\0' && *buffer != '\n')
	X				return -1;
	X			continue;
	X		}
	X
	X		/* calculate field_width */
	X		field_width = 0;
	X		for (++fmt; isdigit(*fmt); fmt++)
	X			field_width = field_width * 10 + *fmt - '0';
	X		if (field_width == 0)
	X			field_width = 1;	/* default */
	X		if (*buffer != '\0' && *buffer != '\n')
	X			nmatch++;
	X
	X		switch (*fmt) {
	X
	X		case 'd':			/* integer */
	X			/* if we've already seen the end of the buffer, don't
	X			   try to get anymore characters */
	X			if (*buffer == '\0' || *buffer == '\n') {
	X				*(va_arg(ap, int *)) = 0;
	X				break;
	X			}
	X
	X			s = tmp;
	X			for (i = 0; i < field_width; i++) {
	X				if (*buffer == '\0' || *buffer == '\n')
	X					break;
	X				*s++ = *buffer++;
	X			}
	X			*s = '\0';
	X#ifndef __STDC__
	X			*(va_arg(ap, int *)) = atoi(tmp);
	X#else
	X			/* remove trailing spaces */
	X			while (s > tmp && isspace(*(s - 1)))
	X				*--s = '\0';
	X			*(va_arg(ap, int *)) = (int) strtol(tmp, &t, 10);
	X			if (t != s)
	X				return -1;
	X#endif
	X			break;
	X
	X		case 'f':			/* floating point */
	X			/* if we've already seen the end of the buffer, don't
	X			   try to get anymore characters */
	X			if (*buffer == '\0' || *buffer == '\n') {
	X				*(va_arg(ap, double *)) = 0.0;
	X				break;
	X			}
	X
	X			s = tmp;
	X			for (i = 0; i < field_width; i++) {
	X				if (*buffer == '\0' || *buffer == '\n')
	X					break;
	X				*s++ = *buffer++;
	X			}
	X			*s = '\0';
	X#ifndef __STDC__
	X			*(va_arg(ap, double *)) = atof(tmp);
	X#else
	X			/* remove trailing spaces */
	X			while (s > tmp && isspace(*(s - 1)))
	X				*--s = '\0';
	X			*(va_arg(ap, double *)) = strtod(tmp, &t);
	X			if (t != s)
	X				return -1;
	X#endif
	X			break;
	X
	X		case 's':			/* string */
	X			/* if we've already seen the end of the buffer, don't
	X			   try to get anymore characters */
	X			if (*buffer == '\0' || *buffer == '\n') {
	X				*(va_arg(ap, char *)) = '\0';
	X				break;
	X			}
	X
	X			s = t = va_arg(ap, char *);
	X			for (i = 0; i < field_width; i++) {
	X				if (*buffer == '\0' || *buffer == '\n')
	X					break;
	X				*s++ = *buffer++;
	X			}
	X			*s = '\0';
	X			/* remove trailing spaces */
	X			while (s > t && isspace(*--s))
	X				*s = '\0';
	X			break;
	X
	X		case 'c':			/* character(s) */
	X			s = va_arg(ap, char *);
	X			for (i = 0; i < field_width; i++)
	X				s[i] = ' ';	/* default */
	X
	X			/* if we've already seen the end of the buffer, don't
	X			   try to get anymore characters */
	X			if (*buffer == '\0' || *buffer == '\n')
	X				break;
	X
	X			for (i = 0; i < field_width; i++) {
	X				if (*buffer == '\0' || *buffer == '\n')
	X					break;
	X				*s++ = *buffer++;
	X			}
	X			break;
	X
	X		case ' ':			/* space (ignore) */
	X			/* if we've already seen the end of the buffer, don't
	X			   try to get anymore characters */
	X			if (*buffer == '\0' || *buffer == '\n')
	X				break;
	X
	X			for (i = 0; i < field_width; i++, buffer++)
	X				if (*buffer == '\0' || *buffer == '\n')
	X					break;
	X			break;
	X
	X		default:
	X			fprintf(stderr, "bad format '%c' in pdb_sscanf\n",
	X									*fmt);
	X			va_end(ap);
	X			return -1;
	X		}
	X	}
	X	va_end(ap);
	X	return nmatch;
	X}
SHAR_EOF
if test 5183 -ne "`wc -c < 'pdb_sscanf.c'`"
then
	echo shar: "error transmitting 'pdb_sscanf.c'" '(should have been 5183 characters)'
fi
fi
echo shar: "extracting 'pdb_write.c'" '(18051 characters)'
if test -f 'pdb_write.c'
then
	echo shar: "will not over-write existing file 'pdb_write.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'pdb_write.c'
	X/*
	X *	Copyright (c) 1989 The Regents of the University of California.
	X *	All rights reserved.
	X *
	X *	Redistribution and use in source and binary forms are permitted
	X *	provided that the above copyright notice and this paragraph are
	X *	duplicated in all such forms and that any documentation,
	X *	advertising materials, and other materials related to such
	X *	distribution and use acknowledge that the software was developed
	X *	by the University of California, San Francisco.  The name of the
	X *	University may not be used to endorse or promote products derived
	X *	from this software without specific prior written permission.
	X *	THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
	X *	IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
	X *	WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
	X *
	X *	$Id: pdb_write.c,v 2.11 1995/01/20 01:20:36 gregc Exp $
	X *
	X *	subroutine for writing PDB format files
	X *
	X */
	X
	X/* LINTLIBRARY */
	X
	X# include	<stdio.h>
	X# include	<ctype.h>
	X# include	"pdb_int.h"
	X
	Xstatic const char * const pdb_record_format[PDB_NUM_R] = {
	X#include "write_format.i"
	X};
	X
	Xstatic char const * const pdbrun5[] = {
	X#include "pdbrun5_write.i"
	X};
	X
	Xstatic char const * const pdbrun6[] = {
	X#include "pdbrun6_write.i"
	X};
	X
	X/*
	X *	for each pdb record type there is a format reading in the
	X *	record values and for printing them out.
	X *
	X *	The actual format of a line written, is the print format
	X *	followed by blank padding to 72 characters, followed by
	X *	8 characters of file and line information.
	X */
	X
	Xvoid
	X# ifdef __STDC__
	Xpdb_write_record(FILE *f, const pdb_record *r, const char *name, int line_num)
	X# else
	Xpdb_write_record(f, r, name, line_num)
	X	FILE		*f;
	X	pdb_record	*r;
	X	char		*name;		/* if NULL, don't print */
	X	int		line_num;	/* if name == NULL, don't print */
	X# endif
	X{
	X	char	buffer[PDB_BUFSIZ];
	X
	X	pdb_write_string(buffer, r);
	X	if (name == NULL)
	X		(void) fprintf(f, "%s\n", buffer);
	X	else if (line_num >= 10000)
	X		(void) fprintf(f, "%-72.72s%-4.4s%04d\n", buffer, name,
	X							line_num % 10000);
	X	else
	X		(void) fprintf(f, "%-72.72s%-4.4s%4d\n", buffer, name,
	X								line_num);
	X}
	X
	Xvoid
	X# ifdef __STDC__
	Xpdb_write_string(char *buffer, const pdb_record *r)
	X# else
	Xpdb_write_string(buffer, r)
	X	char		*buffer;
	X	pdb_record	*r;
	X# endif
	X{
	X	const char		*fmt;
	X	const struct pdb_sheet	*sh;
	X	const pdb_residue	*shr0, *shr1, *sha0, *sha1;
	X	char			*s, *t;
	X
	X	/* convert C structure to pdb record */
	X
	X
	X	if (r->record_type < PDB_USER_PDBRUN)
	X		fmt = pdb_record_format[r->record_type];
	X	else if (pdb_pdbrun_version < 6)
	X		fmt = pdbrun5[r->record_type - PDB_USER_PDBRUN];
	X	else
	X		fmt = pdbrun6[r->record_type - PDB_USER_PDBRUN];
	X	switch (r->record_type) {
	X
	X	case PDB_UNKNOWN:
	X		pdb_sprintf(buffer, fmt, r->pdb.unknown.junk);
	X		break;
	X
	X	case PDB_AGGRGT:
	X		pdb_sprintf(buffer, fmt, r->pdb.aggrgt.serial_num,
	X			r->pdb.aggrgt.num_components,
	X			r->pdb.aggrgt.cmpont_serial_nums[0],
	X			r->pdb.aggrgt.cmpont_serial_nums[1],
	X			r->pdb.aggrgt.cmpont_serial_nums[2],
	X			r->pdb.aggrgt.cmpont_serial_nums[3],
	X			r->pdb.aggrgt.cmpont_serial_nums[4],
	X			r->pdb.aggrgt.cmpont_serial_nums[5],
	X			r->pdb.aggrgt.cmpont_serial_nums[6],
	X			r->pdb.aggrgt.cmpont_serial_nums[7],
	X			r->pdb.aggrgt.cmpont_serial_nums[8],
	X			r->pdb.aggrgt.cmpont_serial_nums[9],
	X			r->pdb.aggrgt.cmpont_serial_nums[10],
	X			r->pdb.aggrgt.cmpont_serial_nums[11],
	X			r->pdb.aggrgt.cmpont_serial_nums[12],
	X			r->pdb.aggrgt.cmpont_serial_nums[13]);
	X		break;
	X
	X	case PDB_ANISOU:
	X	case PDB_SIGUIJ:
	X		pdb_sprintf(buffer, fmt, r->pdb.anisou.serial_num,
	X			r->pdb.anisou.name, r->pdb.anisou.alt_loc,
	X			r->pdb.anisou.residue.name,
	X			r->pdb.anisou.residue.chain_id,
	X			r->pdb.anisou.residue.seq_num,
	X			r->pdb.anisou.residue.insert_code,
	X			r->pdb.anisou.u[0], r->pdb.anisou.u[1],
	X			r->pdb.anisou.u[2], r->pdb.anisou.u[3],
	X			r->pdb.anisou.u[4], r->pdb.anisou.u[5]);
	X		break;
	X
	X	case PDB_ATOM:
	X	case PDB_HETATM:
	X	case PDB_SIGATM:
	X		pdb_sprintf(buffer, fmt, r->pdb.atom.serial_num,
	X			r->pdb.atom.name, r->pdb.atom.alt_loc,
	X			r->pdb.atom.residue.name,
	X			r->pdb.atom.residue.chain_id,
	X			r->pdb.atom.residue.seq_num,
	X			r->pdb.atom.residue.insert_code,
	X			r->pdb.atom.x, r->pdb.atom.y, r->pdb.atom.z,
	X			r->pdb.atom.occupancy, r->pdb.atom.temp_factor,
	X			r->pdb.atom.ftnote_num);
	X		break;
	X
	X	case PDB_AUTHOR:
	X	case PDB_COMPND:
	X	case PDB_JRNL:
	X	case PDB_SOURCE:
	X	case PDB_EXPDTA:
	X		pdb_sprintf(buffer, fmt, r->pdb.author.continuation,
	X			r->pdb.author.data);
	X		break;
	X
	X	case PDB_CONECT:
	X		pdb_sprintf(buffer, fmt, r->pdb.conect.serial_num,
	X			r->pdb.conect.covalent[0], r->pdb.conect.covalent[1],
	X			r->pdb.conect.covalent[2], r->pdb.conect.covalent[3],
	X			r->pdb.conect.bonds[0].hydrogen[0],
	X			r->pdb.conect.bonds[0].hydrogen[1],
	X			r->pdb.conect.bonds[0].salt,
	X			r->pdb.conect.bonds[1].hydrogen[0],
	X			r->pdb.conect.bonds[1].hydrogen[1],
	X			r->pdb.conect.bonds[1].salt);
	X		break;
	X
	X	case PDB_CMPONT:
	X		pdb_sprintf(buffer, fmt, r->pdb.cmpont.seq_num,
	X			r->pdb.cmpont.residues[0].name,
	X			r->pdb.cmpont.residues[0].chain_id,
	X			r->pdb.cmpont.residues[0].seq_num,
	X			r->pdb.cmpont.residues[0].insert_code,
	X			r->pdb.cmpont.residues[1].name,
	X			r->pdb.cmpont.residues[1].chain_id,
	X			r->pdb.cmpont.residues[1].seq_num,
	X			r->pdb.cmpont.residues[1].insert_code);
	X		break;
	X
	X	case PDB_CRYST1:
	X		pdb_sprintf(buffer, fmt, r->pdb.cryst1.a, r->pdb.cryst1.b,
	X			r->pdb.cryst1.c, r->pdb.cryst1.alpha,
	X			r->pdb.cryst1.beta, r->pdb.cryst1.gamma,
	X			r->pdb.cryst1.space_grp, r->pdb.cryst1.z);
	X		break;
	X
	X	case PDB_END:
	X	case PDB_ENDMDL:
	X		pdb_sprintf(buffer, fmt);
	X		break;
	X
	X	case PDB_FORMUL:
	X		pdb_sprintf(buffer, fmt, r->pdb.formul.component,
	X			r->pdb.formul.het_id, r->pdb.formul.continuation,
	X			r->pdb.formul.exclude, r->pdb.formul.formula);
	X		break;
	X
	X	case PDB_FTNOTE:
	X	case PDB_REMARK:
	X	case PDB_SYMDES:
	X	case PDB_MTXDES:
	X	case PDB_CMPDES:
	X	case PDB_AGRDES:
	X		pdb_sprintf(buffer, fmt, r->pdb.ftnote.num, r->pdb.ftnote.text);
	X		break;
	X
	X	case PDB_HEADER:
	X		pdb_sprintf(buffer, fmt, r->pdb.header.class,
	X			r->pdb.header.date, r->pdb.header.type,
	X			r->pdb.header.id);
	X		break;
	X
	X	case PDB_HELIX:
	X		pdb_sprintf(buffer, fmt, r->pdb.helix.serial_num,
	X			r->pdb.helix.id,
	X			r->pdb.helix.residues[0].name,
	X			r->pdb.helix.residues[0].chain_id,
	X			r->pdb.helix.residues[0].seq_num,
	X			r->pdb.helix.residues[0].insert_code,
	X			r->pdb.helix.residues[1].name,
	X			r->pdb.helix.residues[1].chain_id,
	X			r->pdb.helix.residues[1].seq_num,
	X			r->pdb.helix.residues[1].insert_code,
	X			r->pdb.helix.class, r->pdb.helix.comment);
	X		break;
	X
	X	case PDB_HET:
	X		pdb_sprintf(buffer, fmt, r->pdb.het.het_grp.name,
	X			r->pdb.het.het_grp.chain_id, r->pdb.het.het_grp.seq_num,
	X			r->pdb.het.het_grp.insert_code, r->pdb.het.num_atoms,
	X			r->pdb.het.text);
	X		break;
	X
	X	case PDB_MASTER:
	X		pdb_sprintf(buffer, fmt, r->pdb.master.num_remark,
	X			r->pdb.master.num_ftnote, r->pdb.master.num_het,
	X			r->pdb.master.num_helix, r->pdb.master.num_sheet,
	X			r->pdb.master.num_turn, r->pdb.master.num_site,
	X			r->pdb.master.num_transform,
	X			r->pdb.master.num_coordinate, r->pdb.master.num_ter,
	X			r->pdb.master.num_conect, r->pdb.master.num_seqres);
	X		break;
	X
	X	case PDB_MODEL:
	X		pdb_sprintf(buffer, fmt, r->pdb.model.num);
	X		break;
	X
	X	case PDB_MTRIX:
	X		pdb_sprintf(buffer, fmt, r->pdb.mtrix.row_num,
	X			r->pdb.mtrix.serial_num, r->pdb.mtrix.m1,
	X			r->pdb.mtrix.m2, r->pdb.mtrix.m3, r->pdb.mtrix.v,
	X			r->pdb.mtrix.given);
	X		break;
	X
	X	case PDB_OBSLTE:
	X		pdb_sprintf(buffer, fmt, r->pdb.obslte.continuation,
	X			r->pdb.obslte.date, r->pdb.obslte.old_id,
	X			r->pdb.obslte.id_map[0], r->pdb.obslte.id_map[1],
	X			r->pdb.obslte.id_map[2], r->pdb.obslte.id_map[3],
	X			r->pdb.obslte.id_map[4], r->pdb.obslte.id_map[2],
	X			r->pdb.obslte.id_map[6], r->pdb.obslte.id_map[7]);
	X		break;
	X
	X	case PDB_ORIGX:
	X		pdb_sprintf(buffer, fmt, r->pdb.origx.row_num, r->pdb.origx.o1,
	X			r->pdb.origx.o2, r->pdb.origx.o3, r->pdb.origx.t);
	X		break;
	X
	X	case PDB_REVDAT:
	X		pdb_sprintf(buffer, fmt, r->pdb.revdat.modification,
	X			r->pdb.revdat.continuation, r->pdb.revdat.date,
	X			r->pdb.revdat.id, r->pdb.revdat.mod_type,
	X			r->pdb.revdat.corrections);
	X		break;
	X
	X	case PDB_SCALE:
	X		pdb_sprintf(buffer, fmt, r->pdb.scale.row_num, r->pdb.scale.s1,
	X			r->pdb.scale.s2, r->pdb.scale.s3, r->pdb.scale.u);
	X		break;
	X
	X	case PDB_SEQRES:
	X		pdb_sprintf(buffer, fmt, r->pdb.seqres.serial_num,
	X			r->pdb.seqres.chain_id, r->pdb.seqres.count,
	X			r->pdb.seqres.names[0], r->pdb.seqres.names[1],
	X			r->pdb.seqres.names[2], r->pdb.seqres.names[3],
	X			r->pdb.seqres.names[4], r->pdb.seqres.names[5],
	X			r->pdb.seqres.names[6], r->pdb.seqres.names[7],
	X			r->pdb.seqres.names[8], r->pdb.seqres.names[9],
	X			r->pdb.seqres.names[10], r->pdb.seqres.names[11],
	X			r->pdb.seqres.names[12]);
	X		break;
	X
	X	case PDB_SHEET:
	X		sh = &r->pdb.sheet;
	X		shr0 = &sh->residues[0];
	X		shr1 = &sh->residues[1];
	X		sha0 = &sh->atoms[0].residue;
	X		sha1 = &sh->atoms[1].residue;
	X		pdb_sprintf(buffer, fmt, sh->strand_num,
	X			sh->id, sh->count,
	X			shr0->name, shr0->chain_id, shr0->seq_num,
	X			shr0->insert_code,
	X			shr1->name, shr1->chain_id, shr1->seq_num,
	X			shr1->insert_code,
	X			sh->sense,
	X			sh->atoms[0].name,
	X			sha0->name, sha0->chain_id, sha0->seq_num,
	X			sha0->insert_code,
	X			sh->atoms[1].name,
	X			sha1->name, sha1->chain_id, sha1->seq_num,
	X			sha1->insert_code);
	X		break;
	X
	X	case PDB_SITE:
	X		shr0 = &r->pdb.site.residues[0];
	X		shr1 = &r->pdb.site.residues[1];
	X		sha0 = &r->pdb.site.residues[2];
	X		sha1 = &r->pdb.site.residues[3];
	X		pdb_sprintf(buffer, fmt, r->pdb.site.seq_num,
	X			r->pdb.site.id, r->pdb.site.count,
	X			shr0->name, shr0->chain_id, shr0->seq_num,
	X			shr0->insert_code,
	X			shr1->name, shr1->chain_id, shr1->seq_num,
	X			shr1->insert_code,
	X			sha0->name, sha0->chain_id, sha0->seq_num,
	X			sha0->insert_code,
	X			sha1->name, sha1->chain_id, sha1->seq_num,
	X			sha1->insert_code);
	X		break;
	X
	X	case PDB_SPRSDE:
	X		pdb_sprintf(buffer, fmt, r->pdb.sprsde.continuation,
	X			r->pdb.sprsde.date, r->pdb.sprsde.id,
	X			r->pdb.sprsde.supersede[0], r->pdb.sprsde.supersede[1],
	X			r->pdb.sprsde.supersede[2], r->pdb.sprsde.supersede[3],
	X			r->pdb.sprsde.supersede[4], r->pdb.sprsde.supersede[5],
	X			r->pdb.sprsde.supersede[6], r->pdb.sprsde.supersede[7]);
	X		break;
	X
	X	case PDB_SSBOND:
	X		pdb_sprintf(buffer, fmt, r->pdb.ssbond.seq_num,
	X			r->pdb.ssbond.residues[0].name,
	X			r->pdb.ssbond.residues[0].chain_id,
	X			r->pdb.ssbond.residues[0].seq_num,
	X			r->pdb.ssbond.residues[0].insert_code,
	X			r->pdb.ssbond.residues[1].name,
	X			r->pdb.ssbond.residues[1].chain_id,
	X			r->pdb.ssbond.residues[1].seq_num,
	X			r->pdb.ssbond.residues[1].insert_code,
	X			r->pdb.ssbond.comment);
	X		break;
	X
	X	case PDB_SYMOP:
	X		pdb_sprintf(buffer, fmt, r->pdb.symop.row_num,
	X			r->pdb.symop.serial_num, r->pdb.symop.s1,
	X			r->pdb.symop.s2, r->pdb.symop.s3, r->pdb.symop.t);
	X		break;
	X
	X	case PDB_TER:
	X		pdb_sprintf(buffer, fmt, r->pdb.ter.serial_num,
	X			r->pdb.ter.residue.name, r->pdb.ter.residue.chain_id,
	X			r->pdb.ter.residue.seq_num,
	X			r->pdb.ter.residue.insert_code);
	X		break;
	X
	X	case PDB_TRNSFM:
	X		pdb_sprintf(buffer, fmt, r->pdb.trnsfm.result_serial_num,
	X			r->pdb.trnsfm.apply_serial_num,
	X			r->pdb.trnsfm.source_serial_num);
	X		break;
	X
	X	case PDB_TURN:
	X		pdb_sprintf(buffer, fmt, r->pdb.turn.seq_num,
	X			r->pdb.turn.id,
	X			r->pdb.turn.residues[0].name,
	X			r->pdb.turn.residues[0].chain_id,
	X			r->pdb.turn.residues[0].seq_num,
	X			r->pdb.turn.residues[0].insert_code,
	X			r->pdb.turn.residues[1].name,
	X			r->pdb.turn.residues[1].chain_id,
	X			r->pdb.turn.residues[1].seq_num,
	X			r->pdb.turn.residues[1].insert_code,
	X			r->pdb.turn.comment);
	X		break;
	X
	X	case PDB_TVECT:
	X		pdb_sprintf(buffer, fmt, r->pdb.tvect.serial_num,
	X			r->pdb.tvect.t1, r->pdb.tvect.t2, r->pdb.tvect.t3,
	X			r->pdb.tvect.comment);
	X		break;
	X
	X	case PDB_USER:
	X		pdb_sprintf(buffer, fmt, r->pdb.user.subtype, r->pdb.user.text);
	X		break;
	X
	X	case PDB_USER_PDBRUN:
	X		pdb_sprintf(buffer, fmt, r->pdb.user_pdbrun.version);
	X		pdb_pdbrun_version = r->pdb.user_pdbrun.version;
	X		break;
	X
	X	case PDB_USER_EYEPOS:
	X		pdb_sprintf(buffer, fmt, r->pdb.user_eyepos.xyz[0],
	X			r->pdb.user_eyepos.xyz[1], r->pdb.user_eyepos.xyz[2]);
	X		break;
	X
	X	case PDB_USER_ATPOS:
	X		pdb_sprintf(buffer, fmt, r->pdb.user_atpos.xyz[0],
	X			r->pdb.user_atpos.xyz[1], r->pdb.user_atpos.xyz[2]);
	X		break;
	X
	X	case PDB_USER_WINDOW:
	X		pdb_sprintf(buffer, fmt, r->pdb.user_window.left,
	X			r->pdb.user_window.right, r->pdb.user_window.bottom,
	X			r->pdb.user_window.top, r->pdb.user_window.hither,
	X			r->pdb.user_window.yon);
	X		break;
	X
	X	case PDB_USER_FOCUS:
	X		pdb_sprintf(buffer, fmt, r->pdb.user_focus.focus);
	X		break;
	X
	X	case PDB_USER_VIEWPORT:
	X		pdb_sprintf(buffer, fmt, r->pdb.user_viewport.xmin,
	X			r->pdb.user_viewport.xmax, r->pdb.user_viewport.ymin,
	X			r->pdb.user_viewport.ymax);
	X		break;
	X
	X	case PDB_USER_BGCOLOR:
	X		if (pdb_pdbrun_version < 6)
	X			sprintf(buffer, fmt, r->pdb.user_bgcolor.rgb[0],
	X				r->pdb.user_bgcolor.rgb[1],
	X				r->pdb.user_bgcolor.rgb[2]);
	X		else
	X			pdb_sprintf(buffer, fmt, r->pdb.user_bgcolor.rgb[0],
	X				r->pdb.user_bgcolor.rgb[1],
	X				r->pdb.user_bgcolor.rgb[2]);
	X		break;
	X
	X	case PDB_USER_ANGLE:
	X		if (pdb_pdbrun_version < 6)
	X			pdb_sprintf(buffer, fmt, r->pdb.user_angle.which,
	X				r->pdb.user_angle.atom0,
	X				r->pdb.user_angle.atom1,
	X				r->pdb.user_angle.atom2,
	X				r->pdb.user_angle.atom3,
	X				r->pdb.user_angle.angle);
	X		else
	X			pdb_sprintf(buffer, fmt, r->pdb.user_angle.atom0,
	X				r->pdb.user_angle.atom1,
	X				r->pdb.user_angle.atom2,
	X				r->pdb.user_angle.atom3,
	X				r->pdb.user_angle.angle);
	X		break;
	X
	X	case PDB_USER_DISTANCE:
	X		if (pdb_pdbrun_version < 6)
	X			pdb_sprintf(buffer, fmt, r->pdb.user_distance.which,
	X				r->pdb.user_distance.atom0,
	X				r->pdb.user_distance.atom1,
	X				r->pdb.user_distance.distance);
	X		else
	X			pdb_sprintf(buffer, fmt, r->pdb.user_distance.atom0,
	X				r->pdb.user_distance.atom1,
	X				r->pdb.user_distance.distance);
	X		break;
	X
	X	case PDB_USER_FILE:
	X		if (pdb_pdbrun_version < 6)
	X			pdb_sprintf(buffer, fmt, r->pdb.user_file.filename);
	X		else
	X			pdb_sprintf(buffer, fmt, r->pdb.user_file.model,
	X						r->pdb.user_file.filename);
	X		break;
	X
	X	case PDB_USER_MARKNAME:
	X		pdb_sprintf(buffer, fmt, r->pdb.user_markname.markname);
	X		break;
	X
	X	case PDB_USER_MARK:
	X		pdb_sprintf(buffer, fmt, r->pdb.user_mark.markname);
	X		break;
	X
	X	case PDB_USER_CNAME:
	X		if (pdb_pdbrun_version < 6)
	X			sprintf(buffer, fmt, r->pdb.user_cname.name,
	X				r->pdb.user_cname.rgb[0],
	X				r->pdb.user_cname.rgb[1],
	X				r->pdb.user_cname.rgb[2]);
	X		else
	X			pdb_sprintf(buffer, fmt, r->pdb.user_cname.rgb[0],
	X				r->pdb.user_cname.rgb[1],
	X				r->pdb.user_cname.rgb[2],
	X				r->pdb.user_cname.name);
	X		break;
	X
	X	case PDB_USER_COLOR:
	X		if (pdb_pdbrun_version < 6)
	X			sprintf(buffer, fmt, r->pdb.user_color.spec,
	X				r->pdb.user_color.rgb[0],
	X				r->pdb.user_color.rgb[1],
	X				r->pdb.user_color.rgb[2]);
	X		else
	X			pdb_sprintf(buffer, fmt, r->pdb.user_color.rgb[0],
	X				r->pdb.user_color.rgb[1],
	X				r->pdb.user_color.rgb[2],
	X				r->pdb.user_color.spec);
	X		break;
	X
	X	case PDB_USER_RADIUS:
	X		pdb_sprintf(buffer, fmt, r->pdb.user_radius.radius);
	X		break;
	X
	X	case PDB_USER_OBJECT:
	X		pdb_sprintf(buffer, fmt, r->pdb.user_object.model);
	X		break;
	X
	X	case PDB_USER_ENDOBJ:
	X		pdb_sprintf(buffer, fmt, r->pdb.user_endobj.model);
	X		break;
	X
	X	case PDB_USER_CHAIN:
	X		if (pdb_pdbrun_version < 6)
	X			sprintf(buffer, fmt, r->pdb.user_chain.atom0,
	X				r->pdb.user_chain.atom1);
	X		else
	X			pdb_sprintf(buffer, fmt, r->pdb.user_chain.atom0,
	X				r->pdb.user_chain.atom1);
	X		break;
	X
	X	case PDB_USER_GFX_BEGIN:
	X		if (r->pdb.user_gfx_begin.primitive == PDB_GFX_UNKNOWN)
	X			pdb_sprintf(buffer, fmt, r->pdb.user_gfx_begin.unknown);
	X		else
	X			pdb_sprintf(buffer, fmt, pdb_gfx_string(
	X					r->pdb.user_gfx_begin.primitive));
	X		break;
	X
	X	case PDB_USER_GFX_END:
	X		pdb_sprintf(buffer, fmt);
	X		break;
	X
	X	case PDB_USER_GFX_COLOR:
	X		if (pdb_pdbrun_version < 6)
	X			sprintf(buffer, fmt, r->pdb.user_gfx_color.spec,
	X				r->pdb.user_gfx_color.rgb[0],
	X				r->pdb.user_gfx_color.rgb[1],
	X				r->pdb.user_gfx_color.rgb[2]);
	X		else
	X			pdb_sprintf(buffer, fmt, r->pdb.user_gfx_color.rgb[0],
	X				r->pdb.user_gfx_color.rgb[1],
	X				r->pdb.user_gfx_color.rgb[2],
	X				r->pdb.user_gfx_color.spec);
	X		break;
	X
	X	case PDB_USER_GFX_NORMAL:
	X		pdb_sprintf(buffer, fmt, r->pdb.user_gfx_normal.xyz[0],
	X			r->pdb.user_gfx_normal.xyz[1],
	X			r->pdb.user_gfx_normal.xyz[2]);
	X		break;
	X
	X	case PDB_USER_GFX_VERTEX:
	X		pdb_sprintf(buffer, fmt, r->pdb.user_gfx_vertex.xyz[0],
	X			r->pdb.user_gfx_vertex.xyz[1],
	X			r->pdb.user_gfx_vertex.xyz[2]);
	X		break;
	X
	X	case PDB_USER_GFX_FONT:
	X		if (pdb_pdbrun_version < 6)
	X			sprintf(buffer, fmt, r->pdb.user_gfx_font.name,
	X				r->pdb.user_gfx_font.size);
	X		else
	X			pdb_sprintf(buffer, fmt, r->pdb.user_gfx_font.size,
	X				r->pdb.user_gfx_font.name);
	X		break;
	X
	X	case PDB_USER_GFX_TEXTPOS:
	X		pdb_sprintf(buffer, fmt, r->pdb.user_gfx_textpos.xyz[0],
	X			r->pdb.user_gfx_textpos.xyz[1],
	X			r->pdb.user_gfx_textpos.xyz[2]);
	X		break;
	X
	X	case PDB_USER_GFX_LABEL:
	X		if (pdb_pdbrun_version < 6)
	X			sprintf(buffer, fmt, r->pdb.user_gfx_label.xyz[0],
	X				r->pdb.user_gfx_label.xyz[1],
	X				r->pdb.user_gfx_label.xyz[2],
	X				r->pdb.user_gfx_label.text);
	X		else
	X			pdb_sprintf(buffer, fmt, r->pdb.user_gfx_label.text);
	X		break;
	X
	X	case PDB_USER_GFX_MOVE:
	X		pdb_sprintf(buffer, fmt, r->pdb.user_gfx_move.xyz[0],
	X			r->pdb.user_gfx_move.xyz[1],
	X			r->pdb.user_gfx_move.xyz[2]);
	X		break;
	X
	X	case PDB_USER_GFX_DRAW:
	X		pdb_sprintf(buffer, fmt, r->pdb.user_gfx_draw.xyz[0],
	X			r->pdb.user_gfx_draw.xyz[1],
	X			r->pdb.user_gfx_draw.xyz[2]);
	X		break;
	X
	X	case PDB_USER_GFX_MARKER:
	X		pdb_sprintf(buffer, fmt, r->pdb.user_gfx_marker.xyz[0],
	X			r->pdb.user_gfx_marker.xyz[1],
	X			r->pdb.user_gfx_marker.xyz[2]);
	X		break;
	X
	X	case PDB_USER_GFX_POINT:
	X		pdb_sprintf(buffer, fmt, r->pdb.user_gfx_point.xyz[0],
	X			r->pdb.user_gfx_point.xyz[1],
	X			r->pdb.user_gfx_point.xyz[2]);
	X		break;
	X
	X	default:
	X		(void) sprintf(buffer, "unknown pdb record #%d",
	X								r->record_type);
	X		break;
	X	}
	X
	X	/* find last non-blank in buffer, and shorten it */
	X	t = NULL;
	X	for (s = buffer; *s != '\0'; s++)
	X		if (!isspace(*s))
	X			t = s + 1;
	X	if (t == NULL)		/* this should never happen, but ... */
	X		t = buffer;
	X	*t = '\0';
	X}
	X
	X# ifdef vms
	Xpdb_write_dummy()
	X{
	X	pdb_fmt_dummy();
	X}
	X# endif
SHAR_EOF
if test 18051 -ne "`wc -c < 'pdb_write.c'`"
then
	echo shar: "error transmitting 'pdb_write.c'" '(should have been 18051 characters)'
fi
fi
echo shar: "extracting 'read_format.i'" '(3131 characters)'
if test -f 'read_format.i'
then
	echo shar: "will not over-write existing file 'read_format.i'"
else
sed 's/^	X//' << \SHAR_EOF > 'read_format.i'
	X/*
	X *	Copyright (c) 1993 The Regents of the University of California.
	X *	All rights reserved.
	X *
	X *	Redistribution and use in source and binary forms are permitted
	X *	provided that the above copyright notice and this paragraph are
	X *	duplicated in all such forms and that any documentation,
	X *	advertising materials, and other materials related to such
	X *	distribution and use acknowledge that the software was developed
	X *	by the University of California, San Francisco.  The name of the
	X *	University may not be used to endorse or promote products derived
	X *	from this software without specific prior written permission.
	X *	THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
	X *	IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
	X *	WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
	X *
	X *	$Id: read_format.i,v 1.2 93/04/21 19:55:49 gregc Exp $
	X */
	X/* UNKNOWN */	NULL,
	X/* ANISOU */	"%6 %5d %4s%c%4s%c%4d%c %7d%7d%7d%7d%7d%7d",	/* SIGUIJ */
	X/* ATOM */	"%6 %5d %4s%c%4s%c%4d%c   %8f%8f%8f%6f%6f %3d",	/* HETATM, SIGATM */
	X/* AUTHOR */	"%9 %c%60s",		/* COMPND, EXPDTA, JRNL, SOURCE */
	X/* COMPND */	"%9 %c%60s",			/* AUTHOR */
	X/* CONECT */	"%6 %5d%5d%5d%5d%5d%5d%5d%5d%5d%5d%5d",
	X/* CRYST1 */	"%6 %9f%9f%9f%7f%7f%7f %11s%4d",
	X/* END */	NULL,
	X/* FORMUL */	"%8 %2d  %4s%2d%c%51s",
	X/* FTNOTE */	"%7 %3d %59s",	/*  REMARK, SYMDES, MTXDES, CMPDES, AGRDES */
	X/* HEADER */	"%10 %40s%9s  %c%4s",
	X/* HELIX */	"%7 %3d %3s %4s%c %4d%c %4s%c %4d%c%2d%30s",
	X/* HET */	"%7 %4s %c%4d%c  %5d%5 %40s",
	X/* HETATM */	"%6 %5d %4s%c%4s%c%4d%c   %8f%8f%8f%6f%6f %3d",	/* ATOM */
	X/* JRNL */	"%9 %c%60s",			/* AUTHOR */
	X/* MASTER */	"%10 %5d%5d%5d%5d%5d%5d%5d%5d%5d%5d%5d%5d",
	X/* MTRIX */	"%5 %d %3d%10f%10f%10f%5 %10f   %2d",
	X/* OBSLTE */	"%8 %2d %9s %4s%6 %4s %4s %4s %4s %4s %4s %4s %4s",
	X/* ORIGX */	"%5 %d%4 %10f%10f%10f%5 %10f",	/* SCALE */
	X/* REMARK */	"%7 %3d %59s",			/* FTNOTE */
	X/* REVDAT */	"%7 %3d%2d %9s %7s %c%7 %31s",
	X/* SCALE */	"%5 %d%4 %10f%10f%10f%5 %10f",
	X/* SEQRES */	"%6 %4d %c %4d  %4s%4s%4s%4s%4s%4s%4s%4s%4s%4s%4s%4s%4s",
	X/* SHEET */	"%6 %4d %3s%2d %4s%c%4d%c %4s%c%4d%c%2d %4s%4s%c%4d%c %4s%4s%c%4d%c",
	X/* SIGATM */	"%6 %5d %4s%c%4s%c%4d%c   %8f%8f%8f%6f%6f %3d",	/* ATOM */
	X/* SIGUIJ */	"%6 %5d %4s%c%4s%c%4d%c %7d%7d%7d%7d%7d%7d",	/* ANISOU */
	X/* SITE */	"%7 %3d %3s %2d %4s%c%4d%c %4s%c%4d%c %4s%c%4d%c %4s%c%4d%c",
	X/* SOURCE */	"%9 %c%60s",			/* AUTHOR */
	X/* SPRSDE */	"%8 %2d %9s %4s%6 %4s %4s %4s %4s %4s %4s %4s %4s",
	X/* SSBOND */	"%7 %3d %4s%c %4d%c   %4s%c %4d%c%4 %30s",
	X/* TER */	"%6 %5d%6 %4s%c%4d%c",
	X/* TURN */	"%7 %3d %3s %4s%c%4d%c %4s%c%4d%c%4 %30s",
	X/* TVECT */	"%7 %3d%10f%10f%10f%30s",
	X/* USER */	"%4 %2s%66s",
	X/* MODEL */	"%9 %5d",
	X/* ENDMDL */	NULL,
	X/* EXPDTA */	"%9 %c%60s",			/* AUTHOR */
	X/* SYMDES */	"%7 %3d %59s",			/* FTNOTE */
	X/* SYMOP */	"%5 %d %3d%10f%10f%10f%5 %10f",
	X/* MTXDES */	"%7 %3d %59s",			/* FTNOTE */
	X/* CMPDES */	"%7 %3d %59s",			/* FTNOTE */
	X/* CMPONT */	"%7 %3d %4s%c %4d%c %4s%c %4d%c",
	X/* TRNSFM */	"%7 %3d %3d %3d",
	X/* AGRDES */	"%7 %3d %59s",			/* FTNOTE */
	X/* AGGRGT */	"%7 %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d",
SHAR_EOF
if test 3131 -ne "`wc -c < 'read_format.i'`"
then
	echo shar: "error transmitting 'read_format.i'" '(should have been 3131 characters)'
fi
fi
echo shar: "extracting 'write_format.i'" '(2897 characters)'
if test -f 'write_format.i'
then
	echo shar: "will not over-write existing file 'write_format.i'"
else
sed 's/^	X//' << \SHAR_EOF > 'write_format.i'
	X/*
	X *	Copyright (c) 1993 The Regents of the University of California.
	X *	All rights reserved.
	X *
	X *	Redistribution and use in source and binary forms are permitted
	X *	provided that the above copyright notice and this paragraph are
	X *	duplicated in all such forms and that any documentation,
	X *	advertising materials, and other materials related to such
	X *	distribution and use acknowledge that the software was developed
	X *	by the University of California, San Francisco.  The name of the
	X *	University may not be used to endorse or promote products derived
	X *	from this software without specific prior written permission.
	X *	THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
	X *	IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
	X *	WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
	X *
	X *	$Id: write_format.i,v 1.3 93/06/24 11:53:47 gregc Exp $
	X */
	X"UNKNOWN:  ??%-6.6s??",
	X"ANISOU%5d %-4s%c%-4s%c%4d%c %7d%7d%7d%7d%7d%7d",	/* SIGUIJ */
	X"ATOM  %5d %-4s%c%-4s%c%4d%c   %8.3f%8.3f%8.3f%6.2f%6.2f %3D", /* HETATM, SIGATM */
	X"AUTHOR   %c%-60s",			/* COMPND, EXPDTA, JRNL, SOURCE */
	X"COMPND   %c%-60s",					/* AUTHOR */
	X"CONECT%5d%5D%5D%5D%5D%5D%5D%5D%5D%5D%5D",
	X"CRYST1%9.3f%9.3f%9.3f%7.2f%7.2f%7.2f %-11s%4d",
	X"END",
	X"FORMUL  %2D  %-4s%2D%c%-51s",
	X"FTNOTE %3D %-59s",					/* REMARK */
	X"HEADER    %-40s%-11s%c%-4s",
	X"HELIX  %3D %3s %-4s%c %4d%c %-4s%c %4d%c%2D%-30s",
	X"HET    %-4s %c%4d%c  %5d     %-40s",
	X"HETATM%5d %-4s%c%-4s%c%4d%c   %8.3f%8.3f%8.3f%6.2f%6.2f %3D",
	X"JRNL     %c%-60s",					/* AUTHOR */
	X"MASTER    %5d%5d%5d%5d%5d%5d%5d%5d%5d%5d%5d%5d",
	X"MTRIX%1d %3d%10.6f%10.6f%10.6f     %10.5f   %2D",
	X"OBSLTE  %2D %-9s %-10s%-5s%-5s%-5s%-5s%-5s%-5s%-5s%-4s",
	X"ORIGX%1d    %10.6f%10.6f%10.6f     %10.5f",		/* SCALE */
	X"REMARK %3D %-59s",
	X"REVDAT %3D%2D %-9s %-7s %c       %-31s",
	X"SCALE%1d    %10.6f%10.6f%10.6f     %10.5f",		/* ORIGX */
	X"SEQRES%4d %c %4d  %-4s%-4s%-4s%-4s%-4s%-4s%-4s%-4s%-4s%-4s%-4s%-4s%-4s",
	X"SHEET %4D %3s%2d %-4s%c%4d%c %-4s%c%4d%c%2d %-4s%-4s%c%4D%c %-4s%-4s%c%4D%c",
	X"SIGATM%5d %-4s%c%-4s%c%4d%c   %8.3f%8.3f%8.3f%6.2f%6.2f %3D",
	X"SIGUIJ%5d %-4s%c%-4s%c%4d%c %7D%7D%7D%7D%7D%7D",	/* ANISOU */
	X"SITE   %3d %3s %2d %-4s%c%4D%c %-4s%c%4D%c %-4s%c%4D%c %-4s%c%4D%c",
	X"SOURCE   %c%-60s",					/* AUTHOR */
	X"SPRSDE  %2D %-9s %-10s%-5s%-5s%-5s%-5s%-5s%-5s%-5s%-4s",
	X"SSBOND %3D %-4s%c %4d%c   %-4s%c %4D%c    %-30s",
	X"TER   %5d      %-4s%c%4d%c",
	X"TURN   %3D %3s %-4s%c%4d%c %-4s%c%4d%c    %-30s",
	X"TVECT  %3D%10.5f%10.5f%10.5f%-30s",
	X"USER%-2s%-66s",
	X"MODEL    %5d",
	X"ENDMDL",
	X"EXPDTA   %c%-60s",					/* AUTHOR */
	X"SYMDES %3d %59s",					/* FTNOTE */
	X"SYMOP%1d %3d%10.6f%10.6f%10.6f     %10.5f",
	X"MTXDES %3d %59s",					/* FTNOTE */
	X"CMPDES %3d %59s",					/* FTNOTE */
	X"CMPONT %3d %4s%c %4d%c %4s%c %4d%c",
	X"TRNSFM %3d %3d %3d",
	X"AGRDES %3d %59s",					/* FTNOTE */
	X"AGGRGT %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d",
SHAR_EOF
if test 2897 -ne "`wc -c < 'write_format.i'`"
then
	echo shar: "error transmitting 'write_format.i'" '(should have been 2897 characters)'
fi
fi
echo shar: "done with directory 'libpdb'"
cd ..
echo shar: "extracting 'ms.c'" '(7433 characters)'
if test -f 'ms.c'
then
	echo shar: "will not over-write existing file 'ms.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'ms.c'
	X/*
	X
	XCopyright (c) <2002> The Regents of the University of California.
	XAll rights reserved.
	X
	XRedistribution and use in source and binary forms, with or without
	Xmodification, are permitted provided that the following conditions
	Xare met:
	X  1. Redistributions of source code must retain the above copyright
	X     notice, this list of conditions, and the following disclaimer.
	X  2. Redistributions in binary form must reproduce the above
	X     copyright notice, this list of conditions, and the following
	X     disclaimer in the documentation and/or other materials provided
	X     with the distribution.
	X  3. Redistributions must acknowledge that this software was
	X     originally developed by the UCSF Computer Graphics Laboratory
	X     under support by the NIH National Center for Research Resources,
	X     grant P41-RR01081.
	X
	XTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
	XEXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
	XIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
	XPURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS BE LIABLE
	XFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
	XCONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
	XOF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
	XBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
	XWHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
	XOR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
	XEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
	X
	X */
	X#include <stdio.h>
	X#include "dms_param.h"
	X#include "wanted.h"
	X#include "atoms.h"
	X
	X#define	DEF_DENSITY	1.0		/* Default surface density */
	X#define	MIN_DENSITY	0.1
	X#define	MAX_DENSITY	10.0
	X#define	DEF_PROBE	1.4		/* Default probe radius */
	X#define	MIN_PROBE	1.0
	X#define	MAX_PROBE	201.0
	X
	X#define	MODE_PDB	0
	X#define	MODE_MIDAS	1
	X#define	MODE_KRAUT	2
	X
	X#ifndef	TRUE
	X#define	TRUE	1
	X#define	FALSE	0
	X#endif
	X
	Xvoid usage(char *);
	X
	X/*
	X * MS:
	X *	Compute the solvent accessible surface of a molecule
	X *	as defined by Richards.
	X */
	Xmain(ac, av)
	Xint	ac;
	Xchar	**av;
	X{
	X	register int	c;
	X	register ATOM	*ap;
	X	int		input_mode;
	X	int		aflg, nflg;
	X	int		natom;
	X	int		verbose;
	X	int		fd;
	X	int		any_wanted;
	X	double		density, probe;
	X	char		*in_file, *out_file;
	X	FILE		*out_fp;
	X	FILE		*wanted_fp;
	X	WANTED		*wanted_list;
	X	ATOM		*atom_list, **atom_array;
	X	extern int	optind;
	X	extern char	*optarg;
	X	extern double	atof();
	X	WANTED		*read_wanted();
	X	ATOM		*read_pdb(), *read_midas(), *read_kraut();
	X	ATOM		**make_array();
	X
	X	/*
	X	 * Initialize variables to default values which may be
	X	 * overridden by command line arguments
	X	 */
	X	verbose = FALSE;
	X	aflg = FALSE;
	X	nflg = FALSE;
	X	density = DEF_DENSITY;
	X	probe = DEF_PROBE;
	X	input_mode = MODE_PDB;
	X	out_fp = NULL;
	X	wanted_fp = NULL;
	X
	X	/*
	X	 * We process the arguments in a strange way because
	X	 * we want to be backwards compatible with the old ms
	X	 * program
	X	 */
	X	if (ac < 4) {
	X		usage(av[0]);
	X		exit(1);
	X	}
	X	in_file = av[1];
	X	av[1] = av[0];
	X	ac--;
	X	av++;
	X	while ((c = getopt(ac, av, "ad:e:g:i:kpmnr:w:o:v")) != EOF)
	X		switch (c) {
	X		  case 'a':
	X			aflg = TRUE;
	X			break;
	X		  case 'd':
	X			density = atof(optarg);
	X			if (density < MIN_DENSITY || density > MAX_DENSITY) {
	X				fprintf(stderr,
	X				"Density must be between %.2f and %.2f\n",
	X				MIN_DENSITY, MAX_DENSITY);
	X				exit(1);
	X			}
	X			break;
	X		  case 'g':
	X			(void) fflush(stderr);
	X			if ((fd = creat(optarg, 0666)) < 0) {
	X				perror(optarg);
	X				exit(1);
	X			}
	X			(void) dup2(fd, 2);
	X			(void) close(fd);
	X			break;
	X		  case 'i':
	X			if ((wanted_fp = fopen(optarg, "r")) == NULL) {
	X				perror(optarg);
	X				exit(1);
	X			}
	X			break;
	X		  case 'p':
	X			input_mode = MODE_PDB;
	X			break;
	X		  case 'w':
	X			probe = atof(optarg);
	X			if (probe < MIN_PROBE || probe > MAX_PROBE) {
	X				fprintf(stderr,
	X				"Probe size must be between %.2f and %.2f\n",
	X				MIN_PROBE, MAX_PROBE);
	X				exit(1);
	X			}
	X			break;
	X		  case 'n':
	X			nflg = TRUE;
	X			break;
	X		  case 'o':
	X			if ((out_fp = fopen(optarg, "w")) == NULL) {
	X				perror(optarg);
	X				exit(1);
	X			}
	X			out_file = optarg;
	X			break;
	X		  case 'k':
	X			input_mode = MODE_KRAUT;
	X			break;
	X		  case 'm':
	X			input_mode = MODE_MIDAS;
	X			break;
	X		  case 'e':
	X		  case 'r':
	X			fprintf(stderr, "-%c is not implemented\n", c);
	X			exit(1);
	X		  case 'v':
	X			verbose = TRUE;
	X			break;
	X		  default:
	X			fprintf(stderr, "-%c is not recognized\n", c);
	X			usage(av[0]);
	X			exit(1);
	X		}
	X	if (out_fp == NULL) {
	X		fprintf(stderr, "missing -o option\n");
	X		usage(av[0]);
	X		exit(1);
	X	}
	X#ifdef BSD
	X	(void) setlinebuf(stderr);
	X#endif
	X
	X	/*
	X	 * Read in the atoms
	X	 */
	X	switch (input_mode) {
	X	  case MODE_PDB:
	X		atom_list = read_pdb(in_file, aflg);
	X		break;
	X	  case MODE_KRAUT:
	X		atom_list = read_kraut(in_file, aflg);
	X		break;
	X	  case MODE_MIDAS:
	X		atom_list = read_midas(in_file, aflg);
	X		break;
	X	}
	X	if (atom_list == NULL) {
	X		fprintf(stderr, "No atoms in input file!\n");
	X		(void) fclose(out_fp);
	X		(void) unlink(out_file);
	X		exit(1);
	X	}
	X
	X	/*
	X	 * Read in the "ignore" file so we know what constraints
	X	 * we have on input, and check them against atoms present
	X	 */
	X	wanted_list = read_wanted(wanted_fp);
	X	if (wanted_fp != NULL)
	X		(void) fclose(wanted_fp);
	X
	X	any_wanted = 0;
	X	for (ap = atom_list; ap != NULL; ap = ap->next) {
	X		ap->wanted = (wanted_list == NULL || wanted(ap, wanted_list));
	X		if (ap->wanted)
	X			any_wanted = 1;
	X	}
	X	if (any_wanted == 0) {
	X		fprintf(stderr, "No atoms selected by site file.\n");
	X		(void) fclose(out_fp);
	X		(void) unlink(out_file);
	X		exit(1);
	X	}
	X	atom_array = make_array(atom_list, &natom);
	X	fprintf(stderr, "%d atoms\n", natom);
	X
	X	/*
	X	 * Compute the surface
	X	 */
	X	compute_ms(atom_array, natom, probe, density, nflg, verbose);
	X
	X	/*
	X	 * Output the surface in some appropriate format
	X	 */
	X	print_ms(out_fp, atom_list, nflg);
	X	(void) fclose(out_fp);
	X
	X	/*
	X	 * All done.  Clean up.
	X	 */
	X	exit(0);
	X}
	X
	X/*
	X * usage:
	X *	Print a usage message and a description of each argument
	X */
	Xvoid usage(prog_name)
	Xchar	*prog_name;
	X{
	X#if 0
	X	fprintf(stderr, "Usage: %s input_file [-a] [-d density] [-e file] [-g file] [-i file] [-k] [-m] [-p] [-n] [-r b-e] [-w radius] -o file\n", prog_name);
	X#else
	X	fprintf(stderr, "Usage: %s input_file [-a] [-d density] [-g file] [-i file] [-n] [-w radius] [-v] -o file\n", prog_name);
	X#endif
	X	fputs("\t-a\tuse all atoms, not just amino acids\n", stderr);
	X	fputs("\t-d\tchange density of points\n", stderr);
	X	fputs("\t-g\tsend messages to file\n", stderr);
	X	fputs("\t-i\tcalculate only surface for specified atoms\n", stderr);
	X#if 0
	X	fputs("\t-e\tcalculate only surface within ellipsoid\n", stderr);
	X	fputs("\t-k\tinput file is in Kraut format\n", stderr);
	X	fputs("\t-m\tinput file is in Midas format\n", stderr);
	X	fputs("\t-p\tinput file is in Protein Data Bank format\n", stderr);
	X	fputs("\t-r\tuse only specified residues\n", stderr);
	X#endif
	X	fputs("\t-n\tcalculate normals for surface points\n", stderr);
	X	fputs("\t-w\tchange probe radius\n", stderr);
	X	fputs("\t-v\tverbose\n", stderr);
	X	fputs("\t-o\tspecify output file name (required)\n", stderr);
	X}
	X
	X/*
	X * make_array:
	X *	Create an array which points at elements of a list
	X */
	XATOM **
	Xmake_array(alist, nel)
	XATOM	*alist;
	Xint	*nel;
	X{
	X	register ATOM	*ap, **app, **aarray;
	X	register int	n;
	X	extern char	*emalloc();
	X
	X	n = 0;
	X	for (ap = alist; ap != NULL; ap = ap->next)
	X		n++;
	X	aarray = (ATOM **) emalloc(n * sizeof (ATOM *));
	X	app = aarray;
	X	for (ap = alist; ap != NULL; ap = ap->next)
	X		*app++ = ap;
	X	*nel = n;
	X	return aarray;
	X}
SHAR_EOF
if test 7433 -ne "`wc -c < 'ms.c'`"
then
	echo shar: "error transmitting 'ms.c'" '(should have been 7433 characters)'
fi
fi
echo shar: "extracting 'output.c'" '(5374 characters)'
if test -f 'output.c'
then
	echo shar: "will not over-write existing file 'output.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'output.c'
	X/*
	X
	XCopyright (c) <2002> The Regents of the University of California.
	XAll rights reserved.
	X
	XRedistribution and use in source and binary forms, with or without
	Xmodification, are permitted provided that the following conditions
	Xare met:
	X  1. Redistributions of source code must retain the above copyright
	X     notice, this list of conditions, and the following disclaimer.
	X  2. Redistributions in binary form must reproduce the above
	X     copyright notice, this list of conditions, and the following
	X     disclaimer in the documentation and/or other materials provided
	X     with the distribution.
	X  3. Redistributions must acknowledge that this software was
	X     originally developed by the UCSF Computer Graphics Laboratory
	X     under support by the NIH National Center for Research Resources,
	X     grant P41-RR01081.
	X
	XTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
	XEXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
	XIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
	XPURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS BE LIABLE
	XFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
	XCONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
	XOF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
	XBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
	XWHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
	XOR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
	XEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
	X
	X */
	X#include <stdio.h>
	X#include <math.h>
	X#include "dms_param.h"
	X#include "atoms.h"
	X
	X#ifdef BILD_OUTPUT
	X#define	BYATOM	/* Color by atom ownership */
	X#undef	BYTYPE	/* Color by type of surface */
	X#endif
	X#undef	CHECKPT	/* Make sure points are okay */
	X
	Xstatic double	contact_area, reentrant_area;
	Xstatic int	contact_points, reentrant_points;
	X
	Xvoid print_atom();
	X
	X/*
	X * print_ms:
	X *	Print surface data in some format
	X */
	Xvoid print_ms(fp, alist, have_normal)
	XFILE	*fp;
	XATOM	*alist;
	Xint	have_normal;
	X{
	X	register ATOM	*ap;
	X#ifdef BILD_OUTPUT
	X	double		x, y, z;
	X#endif
	X
	X#ifdef BILD_OUTPUT
	X	x = y = z = 0;
	X	for (ap = alist; ap != NULL; ap = ap->next) {
	X		x += (*app)->coord[0];
	X		y += (*app)->coord[1];
	X		z += (*app)->coord[2];
	X	}
	X	fprintf(fp, ".tran %.3f %.3f %.3f\n",
	X		-x / natom, -y / natom, -z / natom);
	X#endif
	X	for (ap = alist; ap != NULL; ap = ap->next)
	X		print_atom(fp, ap, have_normal, alist);
	X
	X	/*
	X	 * Report statistics
	X	 */
	X	fprintf(stderr, "%d points\t(%d contact, %d reentrant)\n",
	X		contact_points + reentrant_points, contact_points,
	X		reentrant_points);
	X	fprintf(stderr, "%.2f sq. A\t(%.2f contact, %.2f reentrant)\n",
	X		contact_area + reentrant_area, contact_area,
	X		reentrant_area);
	X	fprintf(stderr, "%.2f pts/sq.A\t(%.2f contact, %.2f reentrant)\n",
	X		(contact_points + reentrant_points) /
	X		(contact_area + reentrant_area),
	X		contact_points / contact_area,
	X		reentrant_area == 0 ? 0.0 : reentrant_points / reentrant_area);
	X}
	X
	X#ifndef BILD_OUTPUT
	X/* ARGSUSED */
	X#endif
	X/*
	X * print_atom:
	X *	Print the atom and its associated surface points
	X */
	Xvoid print_atom(fp, ap, have_normal, alist)
	XFILE	*fp;
	XATOM	*ap;
	Xint	have_normal;
	XATOM	*alist;
	X{
	X	register SURFACE	*sp;
	X	register POINT		*pp, *endpp;
	X#ifndef BILD_OUTPUT
	X	register char		*typep;
	X	register POINT		*np;
	X#else
	X#ifdef BYATOM
	X	static int		color = 1;
	X#endif
	X#endif
	X
	X#ifdef BILD_OUTPUT
	X#ifdef BYATOM
	X	fprintf(fp, ".color %d\n", color);
	X	color = color % 7 + 1;
	X#endif
	X	fprintf(fp, ".cmov %.3f %.3f %.3f\n%s\n", ap->coord[0], ap->coord[1],
	X		ap->coord[2], ap->atname);
	X#else
	X	fprintf(fp, "%3s %4s %4.4s%8.3f %8.3f %8.3f A\n", ap->restype,
	X		ap->resseq, ap->atname, ap->coord[0], ap->coord[1],
	X		ap->coord[2]);
	X#endif
	X	if (!ap->wanted)
	X		return;
	X	for (sp = ap->surface; sp != NULL; sp = sp->next) {
	X		if (sp->type == CONTACT) {
	X			contact_points += sp->npoint;
	X			contact_area += sp->npoint * sp->area;
	X		}
	X		else {
	X			reentrant_points += sp->npoint;
	X			reentrant_area += sp->npoint * sp->area;
	X		}
	X#ifndef BILD_OUTPUT
	X		switch (sp->type) {
	X		  case CONTACT:
	X			typep = "SC0";
	X			break;
	X		  case TREENTRANT:
	X			typep = "SS0";
	X			break;
	X		  case SREENTRANT:
	X			typep = "SR0";
	X			break;
	X		}
	X		np = sp->normal;
	X#else
	X#ifdef BYTYPE
	X		fprintf(fp, ".color %d\n", sp->type + 1);
	X#endif
	X#endif
	X		endpp = sp->position + sp->npoint;
	X		for (pp = sp->position; pp < endpp; pp++) {
	X#ifdef CHECKPT
	X			verify_point(pp, alist);
	X#endif
	X#ifdef BILD_OUTPUT
	X			fprintf(fp, ".dot %.3f %.3f %.3f\n", pp->coord[0],
	X				pp->coord[1], pp->coord[2]);
	X#else
	X			fprintf(fp, "%3s %4s %4.4s%8.3f %8.3f %8.3f %3s %6.3f",
	X				ap->restype, ap->resseq, ap->atname,
	X				pp->coord[0], pp->coord[1], pp->coord[2],
	X				typep, sp->area);
	X			if (have_normal) {
	X				fprintf(fp, " %6.3f %6.3f %6.3f", np->coord[0],
	X					np->coord[1], np->coord[2]);
	X				np++;
	X			}
	X			(void) putc('\n', fp);
	X#endif
	X		}
	X	}
	X}
	X
	X#ifdef CHECKPT
	X/*
	X * verify_point:
	X *	Verify that the point is not inside any atom
	X */
	Xverify_point(pp, alist)
	Xregister POINT	*pp;
	XATOM		*alist;
	X{
	X	register ATOM	*ap;
	X	register int	i;
	X	double		delta, distsq;
	X
	X	for (ap = alist; ap != NULL; ap = ap->next) {
	X		distsq = 0;
	X		for (i = 0; i < 3; i++) {
	X			delta = ap->coord[i] - pp->coord[i];
	X			distsq += delta * delta;
	X		}
	X		if (distsq + 0.1 < ap->radius * ap->radius) {
	X			fprintf(stderr, "Point too close to %s@%s\n",
	X				ap->atname, ap->resseq);
	X			break;
	X		}
	X	}
	X}
	X#endif
SHAR_EOF
if test 5374 -ne "`wc -c < 'output.c'`"
then
	echo shar: "error transmitting 'output.c'" '(should have been 5374 characters)'
fi
fi
echo shar: "extracting 'protocol.h'" '(2355 characters)'
if test -f 'protocol.h'
then
	echo shar: "will not over-write existing file 'protocol.h'"
else
sed 's/^	X//' << \SHAR_EOF > 'protocol.h'
	X/*
	X
	XCopyright (c) <2002> The Regents of the University of California.
	XAll rights reserved.
	X
	XRedistribution and use in source and binary forms, with or without
	Xmodification, are permitted provided that the following conditions
	Xare met:
	X  1. Redistributions of source code must retain the above copyright
	X     notice, this list of conditions, and the following disclaimer.
	X  2. Redistributions in binary form must reproduce the above
	X     copyright notice, this list of conditions, and the following
	X     disclaimer in the documentation and/or other materials provided
	X     with the distribution.
	X  3. Redistributions must acknowledge that this software was
	X     originally developed by the UCSF Computer Graphics Laboratory
	X     under support by the NIH National Center for Research Resources,
	X     grant P41-RR01081.
	X
	XTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
	XEXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
	XIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
	XPURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS BE LIABLE
	XFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
	XCONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
	XOF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
	XBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
	XWHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
	XOR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
	XEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
	X
	X */
	X#define	PI_COMMAND	"paramdata radius %lf, density %lf, wantnormal %d\n"
	X#define	PI_RESPONSE	"received paramdata\n"
	X
	X#define	AI_COMMAND	"atomdata %d\n"
	X#define	AI_RESPONSE	"received atomdata\n"
	X
	X#define	NI_COMMAND	"neighbordata %d\n"
	X#define	NI_RESPONSE	"received neighbordata\n"
	X
	X#define	PRI_COMMAND	"probedata %d\n"
	X#define	PRI_RESPONSE	"received probedata\n"
	X
	X#define	C_COMMAND	"contacts %d\n"
	X#define	C_RESPONSE	"contactdata atom %d, %d neighbors\n"
	X
	X#define	P_COMMAND	"probes %d %d\n"
	X#define	P_BADNB		"badneighbor %d %d\n"
	X#define	P_RESPONSE	"probedata %d probes\n"
	X
	X#define	CS_COMMAND	"csurface %d\n"
	X#define	TS_COMMAND	"tsurface %d %d\n"
	X#define	PS_COMMAND	"psurface %d\n"
	X
	X#define	SURFACE_END	"surfacedata end\n"
	X#define	SURFACE_RESPONSE \
	X	"surfacedata atom %d, %d points, type %d, area %lf, havenormal %d\n"
SHAR_EOF
if test 2355 -ne "`wc -c < 'protocol.h'`"
then
	echo shar: "error transmitting 'protocol.h'" '(should have been 2355 characters)'
fi
fi
echo shar: "extracting 'radii.proto'" '(601 characters)'
if test -f 'radii.proto'
then
	echo shar: "will not over-write existing file 'radii.proto'"
else
sed 's/^	X//' << \SHAR_EOF > 'radii.proto'
	X# This file contains the atom radii used by dms.
	X# The radii appears one per line, atom type followed by atom radius.
	X# Note that the more specific the type (i.e. contains more characters)
	X# the further down the list it appears.  This is VERY important
	X# The default line is not required.  If it is not present, then dms
	X# will quit when it encounters an atom of unknown type, otherwise
	X# it will use the default radius.
	XH	1.20
	XD	1.20
	XC	1.90
	XN	1.50
	XO	1.40
	XF	1.35
	XP	1.90
	XS	1.85
	XI	2.15
	XCL	1.80
	XFE	0.64
	XCU	1.28
	XZN	1.38
	XBR	1.95
	X1H	1.20
	X2H	1.20
	X3H	1.20
	X4H	1.20
	X1D	1.20
	X2D	1.20
	X3D	1.20
	X4D	1.20
	Xdefault	1.90
SHAR_EOF
if test 601 -ne "`wc -c < 'radii.proto'`"
then
	echo shar: "error transmitting 'radii.proto'" '(should have been 601 characters)'
fi
fi
echo shar: "extracting 'README'" '(5800 characters)'
if test -f 'README'
then
	echo shar: "will not over-write existing file 'README'"
else
sed 's/^	X//' << \SHAR_EOF > 'README'
	XDescription:
	X
	X	DMS is "Distributed MS", a version of the solvent-accessible
	X	surface computation program.  This version splits the
	X	computation into independent units and executes each unit on a
	X	dms server which runs somewhere on the local area network.
	X
	X	Dms is distributed as open source, subject to the legal
	X	restrictions noted at the end of this file.
	X
	X	Consult the dms manual page (dms.1) for details on usage.
	X
	XPrerequisites:
	X
	X	You need GNU make and a C compiler to build this software.
	X	When we refer to the "make" command below, you should use
	X	the actual GNU make executable file name.  On Linux and
	X	Cygwin, the GNU make executable is called "make".  On IRIX,
	X	the GNU make executable is part of the free software installed
	X	in /usr/freeware/bin and is called "gmake".
	X
	X	This software has been built on Red Hat Enterprise Linux
	X	and on Windows XP Professional with Cygwin.
	X
	XInstallation:
	X
	X	Edit "GNUmakefile" and change LIBDIR and BINDIR to the
	X	appropriate location for your system.
	X
	X	At this point, you could get away with typing "make install"
	X	and be done.  You may or may not want to do the following
	X	before that:
	X
	X	Edit the file "dms_param.h" and set the appropriate
	X	parameters to the desired values.  You may need to twiddle with
	X	the last few parameters if you want to get the optimal performance.
	X
	X	By default, dms runs on the local host only, instead of running
	X	in parallel on multiple hosts.  If this behavior is sufficient
	X	for your needs, type "make install" and stop here.  Otherwise...
	X
	X	Edit the file "dms_servers.proto" to contain a list of hosts that
	X	will run dms servers.  All machines participating in a single dms
	X	calculation must be binary compatible with the machine initiating
	X	the calculation.  For sites with multiple machine architectures,
	X	this may mean that there are several distinct "pools" of dms
	X	servers, for calculations initiated by a machine within a pool.
	X	Now type "make install".
	X
	X	Dms must be installed as above on each server machine, and on each
	X	such machine the following steps must be performed as root:
	X
	X	1) Register the 'dms' service on the host.  On most UNIX systems
	X	this is done by editing /etc/services and adding the following
	X	line:
	X		dms 14148/tcp
	X	
	X	On Mac OS X systems, instead execute the following command:
	X
	X		echo dms 14148/tcp | niload services .
	X	
	X	2) Add this line to /etc/inetd.conf:
	X
	X		dms stream tcp nowait daemon dmsd_location dmsd
	X	
	X	where 'dmsd_location' is where dmsd is installed.  (If you
	X	didn't change the Makefile at all, then the location is
	X	/usr/local/lib/dms/dmsd)
	X
	X	3) Make the inetd daemon reread the inetd.conf file.  This is
	X	accomplished by sending the inetd process a HUP signal.  In
	X	order to send the signal, you need to know inetd's process ID.
	X	The process ID can be found by examining the output of 'ps agx'
	X	or 'ps -e' (depending on your system).  The rightmost column
	X	contains the process name, so look for the line that includes
	X	'inetd' somewhere in the righthand column.  On that line, in
	X	the 'PID' column, is inetd's process ID.  The signal is then 
	X	sent with the command:
	X
	X		kill -HUP process_ID
	X	
	X	After performing the above steps on all servers, you should 
	X	verify that dms is indeed performing distributed computations
	X	as expected.  To do this, you need to have a PDB file available
	X	to use as a test input (preferably a small one).  Once you do,
	X	run the command:
	X
	X		dms your_PDB_file -v -o /dev/null
	X	
	X	If you have correctly installed dms for distributed computation,
	X	the output will contain a line of the form:
	X
	X		Server request count:
	X
	X	followed by a list of hosts that dms ran on to do the calculation,
	X	and the amount of calculation that each host performed.  If the
	X	list of servers is what you expect, and no calculation count is
	X	zero, then you have installed dms correctly.  If one or more
	X	calculation counts are zero then you did not install dms correctly
	X	on those hosts.  For those problem hosts you should verify that
	X	the above steps were carried out correctly as well as insuring
	X	that dmsd is installed in the correct location and is executable.  
	X	If your list of server hosts is not what you expect and is simply
	X	'localhost' instead, the you have not correctly completed step (1)
	X	on the local machine.
	X
	X
	XLegal Restrictions:
	X
	XCopyright (c) <2002> The Regents of the University of California.
	XAll rights reserved.
	X
	XRedistribution and use in source and binary forms, with or without
	Xmodification, are permitted provided that the following conditions
	Xare met:
	X  1. Redistributions of source code must retain the above copyright
	X     notice, this list of conditions, and the following disclaimer.
	X  2. Redistributions in binary form must reproduce the above
	X     copyright notice, this list of conditions, and the following
	X     disclaimer in the documentation and/or other materials provided
	X     with the distribution.
	X  3. Redistributions must acknowledge that this software was
	X     originally developed by the UCSF Computer Graphics Laboratory
	X     under support by the NIH National Center for Research Resources,
	X     grant P41-RR01081.
	X
	XTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
	XEXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
	XIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
	XPURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS BE LIABLE
	XFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
	XCONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
	XOF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
	XBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
	XWHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
	XOR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
	XEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
	X
SHAR_EOF
if test 5800 -ne "`wc -c < 'README'`"
then
	echo shar: "error transmitting 'README'" '(should have been 5800 characters)'
fi
fi
echo shar: "extracting 'tokenize.c'" '(3625 characters)'
if test -f 'tokenize.c'
then
	echo shar: "will not over-write existing file 'tokenize.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'tokenize.c'
	X/*
	X
	XCopyright (c) <2002> The Regents of the University of California.
	XAll rights reserved.
	X
	XRedistribution and use in source and binary forms, with or without
	Xmodification, are permitted provided that the following conditions
	Xare met:
	X  1. Redistributions of source code must retain the above copyright
	X     notice, this list of conditions, and the following disclaimer.
	X  2. Redistributions in binary form must reproduce the above
	X     copyright notice, this list of conditions, and the following
	X     disclaimer in the documentation and/or other materials provided
	X     with the distribution.
	X  3. Redistributions must acknowledge that this software was
	X     originally developed by the UCSF Computer Graphics Laboratory
	X     under support by the NIH National Center for Research Resources,
	X     grant P41-RR01081.
	X
	XTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
	XEXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
	XIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
	XPURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS BE LIABLE
	XFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
	XCONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
	XOF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
	XBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
	XWHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
	XOR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
	XEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
	X
	X */
	X#include	<stdio.h>
	X#include	<ctype.h>
	X
	X/*
	X * tokenize:
	X *	Break string into array of words at spaces, keeping strings
	X *	intact and recognizing backslash escapes, returning number
	X *	of words found or -1 if more than n found or -2 if non-printable
	X *	character encountered or -3 if mismatched quotes.
	X */
	Xint
	Xtokenize(string, array, n)
	Xchar	*string,	/* string to be tokenized */
	X	*array[];	/* returned array of pointers to tokens in string */
	Xint	n;		/* maximum number of tokens to look for */
	X{
	X	register int	i;
	X
	X	for (i = 0; i < n; i++) {
	X		while (isspace(*string))
	X			string++;
	X		if (*string == '"') {
	X			*array++ = ++string;
	X			while (isprint(*string) && *string != '"') {
	X				if (*string == '\\') { /* backslash escapes */
	X					strcpy(string, string+1);
	X					switch (*string) {
	X					  case 't': /* tab */
	X						*string = '\t';
	X						break;
	X					  case 'b': /* backspace */
	X						*string = '\b';
	X						break;
	X					  case 'n': /* newline */
	X						*string = '\n';
	X						break;
	X					  case 'r': /* carriage return */
	X						*string = '\r';
	X						break;
	X					  case 'f': /* formfeed */
	X						*string = '\f';
	X						break;
	X					  default: /* treat as normal */
	X						break;
	X					}
	X				}
	X				string++;
	X			}
	X			if (*string == '\0')
	X				return -3;
	X			if (!isprint(*string))
	X				return -2;
	X			*string++ = '\0';
	X			continue;
	X		}
	X		*array++ = string;
	X		if (*string == '\0')
	X			break;
	X		if (!isprint(*string))
	X			return -2;
	X		while (!isspace(*string) && isprint(*string)) {
	X			if (*string == '\\') { /* backslash escapes */
	X				strcpy(string, string+1);
	X				switch (*string) {
	X				  case 't': /* tab */
	X					*string = '\t';
	X					break;
	X				  case 'b': /* backspace */
	X					*string = '\b';
	X					break;
	X				  case 'n': /* newline */
	X					*string = '\n';
	X					break;
	X				  case 'r': /* carriage return */
	X					*string = '\r';
	X					break;
	X				  case 'f': /* formfeed */
	X					*string = '\f';
	X					break;
	X				  default: /* treat as normal */
	X					break;
	X				}
	X			}
	X			string++;
	X		}
	X		if (isspace(*string))
	X			*string++ = '\0';
	X	}
	X	while (isspace(*string))
	X		string++;
	X	return *string == '\0' ? i : -1;
	X}
SHAR_EOF
if test 3625 -ne "`wc -c < 'tokenize.c'`"
then
	echo shar: "error transmitting 'tokenize.c'" '(should have been 3625 characters)'
fi
fi
echo shar: "extracting 'wanted.h'" '(1849 characters)'
if test -f 'wanted.h'
then
	echo shar: "will not over-write existing file 'wanted.h'"
else
sed 's/^	X//' << \SHAR_EOF > 'wanted.h'
	X/*
	X
	XCopyright (c) <2002> The Regents of the University of California.
	XAll rights reserved.
	X
	XRedistribution and use in source and binary forms, with or without
	Xmodification, are permitted provided that the following conditions
	Xare met:
	X  1. Redistributions of source code must retain the above copyright
	X     notice, this list of conditions, and the following disclaimer.
	X  2. Redistributions in binary form must reproduce the above
	X     copyright notice, this list of conditions, and the following
	X     disclaimer in the documentation and/or other materials provided
	X     with the distribution.
	X  3. Redistributions must acknowledge that this software was
	X     originally developed by the UCSF Computer Graphics Laboratory
	X     under support by the NIH National Center for Research Resources,
	X     grant P41-RR01081.
	X
	XTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
	XEXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
	XIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
	XPURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS BE LIABLE
	XFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
	XCONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
	XOF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
	XBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
	XWHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
	XOR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
	XEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
	X
	X */
	X#ifndef	__WANTED__
	X#define	__WANTED__
	X
	X#include "atoms.h"
	X
	X#define	W_RANGE	0
	X#define	W_ANY	1
	X#define	W_ATOM	2
	X
	Xtypedef	struct wanted_def	{
	X	struct wanted_def	*next;
	X	int			type;
	X	int			startres;
	X	union {
	X		int		endres;
	X		char		atom[AN_LEN];
	X	}			w;
	X}	WANTED;
	X
	Xextern int	wanted(ATOM *ap, WANTED *wlist);
	X
	X#endif
SHAR_EOF
if test 1849 -ne "`wc -c < 'wanted.h'`"
then
	echo shar: "error transmitting 'wanted.h'" '(should have been 1849 characters)'
fi
fi
echo shar: "extracting 'dms.html'" '(7375 characters)'
if test -f 'dms.html'
then
	echo shar: "will not over-write existing file 'dms.html'"
else
sed 's/^	X//' << \SHAR_EOF > 'dms.html'
	X<html>
	X<head>
	X<title>dms</title>
	X</head>
	X<body>
	X<h4>NAME</h4>
	X  <h3>dms - calculate a molecular surface</h3>
	X
	X<h4>SYNOPSIS</h4>
	X<h3><b>dms</b> <i>pdbfile</i> [ -a ] [ -d <i>density</i>] [ -g <i>logfile</i> ]
	X [ -i <i>sitefile</i> ] [-n] [-w <i>radius</i> ] [-v] -o <i>outfile</i>
	X</h3>
	X
	X<h4>DESCRIPTION</h4>
	X<p>
	X  <b>Dms</b> calculates the molecular surface of a molecule.
	X  The molecular surface
	X  resembles the van der Waals surface of a molecule, except that crevices
	X  between atoms are smoothed over and interstices too small to accommodate
	X  the probe are eliminated.  The surface includes cavities in the interior of
	X  the molecule, even if they are not accessible to a solvent molecule coming
	X  from the outside.
	X</p><p>
	X  The molecular surface calculated is that defined by Richards (see
	X  the <a href="#ref">reference</a> below).
	X  In particular, the calculated molecular surface is that traced out by
	X  the surface of the probe sphere rather that the
	X  probe sphere's center.  According to Richards' definition, the molecular
	X  surface consists of two parts: contact surface and reentrant surface. The
	X  contact surface is made up of "those parts of the molecular van der Waals
	X  surface that can actually be in contact with the surface of the probe."
	X  The reentrant surface is defined by "the interior-facing part of the probe
	X  when it is simultaneously in contact with more than one atom."  <b>Dms</b>
	X  reports the amounts of contact and reentrant surface area, and the combined
	X  total surface area on the standard error output (see <a href="#gflag">
	X  <b>-g</b></a>).
	X</p><p>
	X  <i>Pdbfile</i> is an input file of coordinates.
	X  The input file must be in the Protein Data Bank format.
	X  The first part of each atom
	X  name is used to determine the element type.  By default, implicit hydrogens
	X  are included for carbon, nitrogen and oxygen atoms; thus, aromatic carbons
	X  and nitrogens will have van der Waals radii that are somewhat too big.
	X  Note that only amino acid and nucleic acid residues will be included unless
	X  <a href="#aflag"><b>-a</b></a> is also specified.
	X</p>
	X
	X<h4>COMMAND-LINE ARGUMENTS</h4>
	X
	X<blockquote>
	X<a name="aflag">
	X  <tt><b>-a</b></tt>
	X</a>
	X<br>Include all atoms, not just those in amino acid and nucleic acid residues.
	X</blockquote>
	X
	X<blockquote>
	X  <tt><b>-d</b> <i>density</i></tt>
	X<br>   <i>Density</i> is a factor affecting the density of points
	X       on the surface; the default of <b>1.0</b>
	X       produces about 5 points per square angstrom.  Only values between
	X       <b>0.1</b> and <b>10.0</b> are permitted.
	X       A density of <b>0.5</b> is recommended for large molecules.
	X</blockquote>
	X
	X<blockquote>
	X<a name="gflag">
	X  <tt><b>-g</b> <i>logfile</i></tt>
	X</a>
	X<br>   Write all the informative messages to <i>logfile</i> instead of the
	X       standard error output.  Genuine errors still go to the standard error
	X       output.  New log information is appended to <i>logfile</i> rather than
	X       overwriting it, and thus messages from several runs may be accumulated.
	X</blockquote>
	X
	X<blockquote>
	X<a name="iflag">
	X  <tt><b>-i</b> <i>sitefile</i></tt>
	X</a>
	X<br>   Calculate the molecular surface only for those residues and atoms
	X       specified in <i>sitefile</i>,
	X       keeping the rest of the molecule for collision checks.
	X       <i>Sitefile</i> consists of lines such as the following:
	X<blockquote><tt>
	X<table>
	X<tr>
	X<td>ASP</td> <td align="right">205</td> <td>CA</td>
	X</tr><tr>
	X<td>TYR</td> <td align="right">13</td> <td>*</td>
	X</tr><tr>
	X<td>GLY</td> <td align="right">116</td> <td>FRM</td>
	X</tr><tr>
	X<td>HIS</td> <td align="right">178</td> <td>TO</td>
	X</tr>
	X</table>
	X</tt></blockquote>
	X       The asterisk, <b>*</b>, means all atoms of the residue, and the 
	X       "FRM" and "TO" lines mean all residues from 116 to 178 inclusive.
	X       The sequence number may
	X       contain letters, and if the PDB input file contains chain identifiers,
	X       then those should be appended on the right of the sequence number.
	X       Residue insertion codes (if any) should be placed between the sequence
	X       number and any chain identifier.	 Residues contained in HETATM records
	X       should have an asterisk appended to the end of the residue identifier.
	X       The surface generated using <a href="#iflag"><b>-i</b></a>
	X       is not always the same as the
	X       surface generated by running the entire molecule and afterwards
	X       selecting the desired atoms.  The first surface will not include
	X       reentrant surface lying between an atom in <i>sitefile</i> and atoms not
	X       in the file.
	X</blockquote>
	X
	X<blockquote>
	X<a name="nflag">
	X  <tt><b>-n</b></tt>
	X</a>
	X<br>   Include the unit normals to the surface with each surface point record.
	X</blockquote>
	X
	X<blockquote>
	X  <tt><b>-w</b> <i>radius</i></tt>
	X<br>   Change the "water" probe <i>radius</i> from the default of <b>1.4</b>
	X       angstroms.  <i>Radius</i> must be between <b>1.0</b> and <b>201.0</b>.
	X</blockquote>
	X
	X<blockquote>
	X  <tt><b>-v</b></tt>
	X<br>   Produce more verbose output.  <b>Dms</b>
	X       will announce each computation phase
	X       as it is entered as well as a count of the atom types in the molecule
	X       and the number of computation requests handled by each host that
	X       participated in the calculation.
	X</blockquote>
	X
	X<blockquote>
	X  <tt><b>-o</b> <i>outfile</i></tt>
	X<br>   The output surface is written to <i>outfile</i>.
	X       This flag is not optional.
	X</blockquote>
	X
	X<p>
	X  The output consists of a series of atom and surface point records, with the
	X  same format for the first six fields.	 Each atom is followed by the surface
	X  points (if any) which belong to it.  These first six fields are in the
	X  following format: residue name, sequence number, atom name, x coordinate,
	X  y coordinate, z coordinate.  For an atom record, the seventh field is "A."
	X  For a surface point record, the seventh field begins with an "S,"
	X  followed by a "C," "R," or "S" according to whether the point is part of
	X  contact, reentrant, or saddle surface (saddle is a type of reentrant
	X   surface where the probe is in contact with exactly two atoms).  This
	X  is followed a digit used for depicting different density levels.  The
	X  eighth field is the molecular surface area associated with the point in
	X  square angstroms.  If <a href="#nflag"><b>-n</b></a> is specified, the
	X  next three fields are
	X  the unit normal vector pointing outward from the surface.
	X  Messages and errors are written to the standard error output
	X  unless a separate log file has been
	X  specified with <a href="#gflag"><b>-g</b></a>.
	X</p><p>
	X  <b>Dms</b> reads the elements and radii from a file named <b>radii</b>.
	X  If there is a file in the current
	X  directory called <b>radii</b>, then <b>dms</b> will use that file instead.
	X  To add uncommon elements or use different radii, one should copy the
	X  default radii file from the distribution and modify it.
	X  The file format is documented in the file itself.
	X</p>
	X
	X<h4>SEE ALSO</h4>
	X<p>
	X<a name="ref">
	X Richards, F.M.,</a>
	X "Areas, volumes, packing and protein structure,"
	X   <i>Ann. Rev. Biophys. Bioeng.</i> <b>6</b>, 151-176 (1977).
	X</p>
	X
	X<h4>AUTHOR</h4>
	X  Conrad Huang
	X  <br>University of California, San Francisco
	X
	X<h4>DIAGNOSTICS</h4>
	X  Many and varied.  Be sure to examine the output messages (standard error
	X  or <i>logfile</i>, if specified) before leaving a background job running.
	X</body></html>
SHAR_EOF
if test 7375 -ne "`wc -c < 'dms.html'`"
then
	echo shar: "error transmitting 'dms.html'" '(should have been 7375 characters)'
fi
fi
echo shar: "done with directory 'dms'"
cd ..
exit 0
#	End of shell archive
