[comp.sources.misc] v20i032: hp2pk - HP font conversion tool, Part02/04

steve@txsil.sil.org (Steve McConnel) (06/03/91)

Submitted-by: Steve McConnel <steve@txsil.sil.org>
Posting-number: Volume 20, Issue 32
Archive-name: hp2pk/part02

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 2 (of 4)."
# Contents:  bigendio.c fixnum.c hp2pk.lpt myalloc.c writepl.c
#   writetfm.c
# Wrapped by steve@txsil on Thu May 30 10:36:55 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'bigendio.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'bigendio.c'\"
else
echo shar: Extracting \"'bigendio.c'\" \(5783 characters\)
sed "s/^X//" >'bigendio.c' <<'END_OF_FILE'
X/*  BIGENDIO.C - binary I/O for big-endian values
X ***************************************************************************
X *
X *	signed char get_byte(fp)
X *	FILE *fp;
X *
X *	unsigned char get_ubyte(fp)
X *	FILE *fp;
X *
X *	short get_halfword(fp)
X *	FILE *fp;
X *
X *	unsigned short get_uhalfword(fp)
X *	FILE *fp;
X *
X *	long get_3_bytes(fp)
X *	FILE *fp;
X *
X *	long get_fullword(fp)
X *	FILE *fp;
X *
X *	unsigned long get_ufullword(fp)
X *	FILE *fp;
X *
X *	void put_fullword(val, fp)
X *	long val;
X *	FILE *fp;
X *
X *	void put_3_bytes(i,fp)
X *	long i;
X *	FILE *fp;
X *
X *	void put_halfword(val, fp)
X *	short val;
X *	FILE *fp;
X *
X ***************************************************************************
X *	EDIT HISTORY
X *	19-Oct-90	Steve McConnel - finish writing generalized functions
X *	20-Oct-90	SRMc - rename some functions for consistency
X *	15-Jan-91	SRMc - fix for Macintosh Lightspeed THINK C
X *	12-Apr-91	SRMc - add coercion of long to int in putc() calls
X ***************************************************************************
X * Copyright 1990, 1991 by the Summer Institute of Linguistics, Inc.
X * All rights reserved.
X */
X#include <stdio.h>
X#ifdef THINK_C
X#define signed
X#endif
X
Xextern void exit();
X
X/****************************************************************************
X * NAME
X *    bad_eof
X * ARGUMENTS
X *    none
X * DESCRIPTION
X *    Annouce an unexpected EOF and abort the program.
X * RETURN VALUE
X *    none
X */
Xstatic void bad_eof()
X{
Xfflush(stdout);
Xfprintf(stderr, "\nUnexpected end of input file.\n");
Xexit(1);
X}
X
X/****************************************************************************
X * NAME
X *    get_byte
X * ARGUMENTS
X *    fp - input FILE pointer
X * DESCRIPTION
X *    Get a one-byte signed integer from the HP soft font file.
X * RETURN VALUE
X *    the signed 8-bit value
X */
Xsigned char get_byte(fp)
XFILE *fp;
X{
Xint b;
X
Xb = getc(fp);
Xif (b == EOF)
X    bad_eof();
Xreturn( (signed char)b );
X}
X
X/****************************************************************************
X * NAME
X *    get_ubyte
X * ARGUMENTS
X *    fp - input FILE pointer
X * DESCRIPTION
X *    Get a one-byte unsigned integer from the HP soft font file.
X * RETURN VALUE
X *    the unsigned 8-bit value
X */
Xunsigned char get_ubyte(fp)
XFILE *fp;
X{
Xint b;
X
Xb = getc(fp);
Xif (b == EOF)
X    bad_eof();
Xreturn( (unsigned char)b );
X}
X
X/****************************************************************************
X * NAME
X *    get_halfword
X * ARGUMENTS
X *    fp - input FILE pointer
X * DESCRIPTION
X *    Get a two-byte bigendian signed integer from the HP soft font file.
X * RETURN VALUE
X *    the signed 16-bit value
X */
Xshort get_halfword(fp)
XFILE *fp;
X{
Xshort i;
X
Xi = get_ubyte(fp);
Xi = (i << 8) + get_ubyte(fp);
Xreturn(i);
X}
X
X/****************************************************************************
X * NAME
X *    get_uhalfword
X * ARGUMENTS
X *    fp - input FILE pointer
X * DESCRIPTION
X *    Get a two-byte bigendian unsigned integer from the HP soft font file.
X * RETURN VALUE
X *    the unsigned 16-bit value
X */
Xunsigned short get_uhalfword(fp)
XFILE *fp;
X{
Xunsigned short i;
X
Xi = get_ubyte(fp);
Xi = (i << 8) + get_ubyte(fp);
Xreturn( i );
X}
X
X/****************************************************************************
X * NAME
X *    get_3_bytes
X * ARGUMENTS
X *    fp - input FILE pointer
X * DESCRIPTION
X *    Get a three-byte bigendian unsigned integer from the HP soft font file.
X * RETURN VALUE
X *    the 24-bit value
X */
Xlong get_3_bytes(fp)
XFILE *fp;
X{
Xlong i;
X
Xi = get_ubyte(fp);
Xi = (i << 8) + get_ubyte(fp);
Xi = (i << 8) + get_ubyte(fp);
Xreturn( i );
X}
X
X/****************************************************************************
X * NAME
X *    get_fullword
X * ARGUMENTS
X *    fp - input FILE pointer
X * DESCRIPTION
X *    Get a four-byte bigendian integer from the HP soft font file.
X * RETURN VALUE
X *    the 32-bit value
X */
Xlong get_fullword(fp)
XFILE *fp;
X{
Xlong i;
X
Xi = get_ubyte(fp);
Xi = (i << 8) + get_ubyte(fp);
Xi = (i << 8) + get_ubyte(fp);
Xi = (i << 8) + get_ubyte(fp);
Xreturn( i );
X}
X
X/****************************************************************************
X * NAME
X *    get_ufullword
X * ARGUMENTS
X *    fp - input FILE pointer
X * DESCRIPTION
X *    Get a four-byte bigendian unsigned integer from the HP soft font file.
X * RETURN VALUE
X *    the unsigned 32-bit value
X */
Xunsigned long get_ufullword(fp)
XFILE *fp;
X{
Xunsigned long i;
X
Xi = get_ubyte(fp);
Xi = (i << 8) + get_ubyte(fp);
Xi = (i << 8) + get_ubyte(fp);
Xi = (i << 8) + get_ubyte(fp);
Xreturn( i );
X}
X
X/****************************************************************************
X * NAME
X *    put_fullword
X * ARGUMENTS
X *    val - 32-bit integer to write
X *    fp  - FILE pointer
X * DESCRIPTION
X *    Write a 32-bit binary integer to a file.
X * RETURN VALUE
X *    none
X */
Xvoid put_fullword(val, fp)
Xlong val;
XFILE *fp;
X{
Xputc( (int)((val >> 24) & 0xFF), fp);
Xputc( (int)((val >> 16) & 0xFF), fp);
Xputc( (int)((val >> 8)  & 0xFF), fp);
Xputc( (int)( val        & 0xFF), fp);
X}
X
X/****************************************************************************
X * NAME
X *    put_3_bytes
X * ARGUMENTS
X *    i  - 24-bit value for output
X *    fp - output FILE pointer
X * DESCRIPTION
X *    Write a three-byte (24-bit) value to the file.
X * RETURN VALUE
X *    none
X */
Xvoid put_3_bytes(i,fp)
Xlong i;
XFILE *fp;
X{
Xputc( (int)((i >> 16) & 0xFF), fp);
Xputc( (int)((i >>  8) & 0xFF), fp);
Xputc( (int)( i        & 0xFF), fp);
X}
X
X/****************************************************************************
X * NAME
X *    put_halfword
X * ARGUMENTS
X *    val - 16-bit integer to write
X *    fp  - FILE pointer
X * DESCRIPTION
X *    Write a 16-bit binary integer to a file.
X * RETURN VALUE
X *    none
X */
Xvoid put_halfword(val, fp)
Xshort val;
XFILE *fp;
X{
Xputc( (val >> 8) & 0xFF, fp);
Xputc(  val       & 0xFF, fp);
X}
END_OF_FILE
if test 5783 -ne `wc -c <'bigendio.c'`; then
    echo shar: \"'bigendio.c'\" unpacked with wrong size!
fi
# end of 'bigendio.c'
fi
if test -f 'fixnum.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'fixnum.c'\"
else
echo shar: Extracting \"'fixnum.c'\" \(5176 characters\)
sed "s/^X//" >'fixnum.c' <<'END_OF_FILE'
X/*  FIXNUM.C - functions to convert between fixed-pointed numbers and strings
X ***************************************************************************
X *
X *	fixnum str_to_fixnum(str)
X *	char *str;
X *
X *	char *fixnum_to_str(x, buf, numdig)
X *	fixnum x;
X *	char buf[];
X *	int numdig;
X *
X ***************************************************************************
X *	EDIT HISTORY
X *	19-Oct-90	Steve McConnel - finish writing generalized functions
X *				that don't depend on floating point
X *	20-Oct-90	SRMc - remove I/O functions
X ***************************************************************************
X * Copyright 1990 by the Summer Institute of Linguistics, Inc.
X * All rights reserved.
X */
X#include <stdio.h>
X#include <ctype.h>
X#include "fixnum.h"
X
X/************************************************************************/
X/*			STATIC GLOBAL VARIABLES				*/
X/************************************************************************/
X
Xstatic unsigned long tenpow[10] = { 0,
X    0631463146L,	/* 0.1 */    /* Knuth, vol. 2 (2nd ed.), page 660 */
X    0050753412L,	/* 0.01 */   /* 30-bit fractions */
X    0004061116L,	/* 0.001 */	/* since we end up with 20-bit */
X    0000321556L,	/* 0.0001 */	/* fractions, these should */
X    0000024761L,	/* 0.00001 */	/* provide enough precision */
X    0000002062L,	/* 0.000001 */
X    0000000153L,	/* 0.0000001 */
X    0000000013L,	/* 0.00000001 */
X    0000000001L		/* 0.000000001 */
X    };
X
X/****************************************************************************
X * NAME
X *    str_to_fixnum
X * ARGUMENTS
X *    str - string containing fixed-point number
X * DESCRIPTION
X *    Convert ASCII character string to a fixnum binary value.
X * RETURN VALUE
X *    "fixnum" value
X */
Xfixnum str_to_fixnum(str)
Xchar *str;
X{
Xchar *p;		/* pointer into fixed-point number string */
Xlong i;			/* integer part, then entire fixnum value */
Xunsigned long f;	/* fraction part of fixnum value */
Xlong k;			/* fraction bits thrown away -- useful for rounding */
Xint neg;		/* flag negative value */
Xint log;		/* number of decimal digits processed */
X
Xfor ( p = str ; isascii(*p) && isspace(*p) ; ++p )
X    ;
Xif (*p == '-')
X    {
X    neg = 1;
X    ++p;
X    }
Xelse
X    neg = 0;
X
Xif ( !isascii(*p) || !isdigit(*p) )
X    return( 0L );
X
Xfor ( i = 0 ; isascii(*p) && isdigit(*p) ; ++p)
X    i = (i * 10) + (*p - '0');
X
Xif (i > 2047)
X    return( 0x80000000 );	/* overflow condition actually */
Xi = int_to_fixnum(i);
X
Xif (*p++ != '.')
X    return( (neg) ? -i : i );
X/*
X *  convert the fraction part of the number
X */
Xfor ( f = 0, log = 1 ; isascii(*p) && isdigit(*p) && (log < 10) ; ++log )
X    f += (*p++ - '0') * tenpow[log];
X
Xk = f & 0x000003FFL;
Xf >>= 10;	/* convert from 30-bit fraction to 20-bit fraction */
X/*
X *  merge the fraction and the integer parts
X */
Xi = i | f;
Xif (k > 0x00000200L)
X    ++i;		/* round up the LSB */
Xreturn( (neg) ? -i : i );
X}
X
X/****************************************************************************
X * NAME
X *    fixnum_to_str
X * ARGUMENTS
X *    x      - fixed-point fraction to turn into a string
X *    buf    - character array for holding fixed-point number string
X *    numdig - number of decimal places to expand (buffer must hold at
X *		least 7 more bytes for results like "-2047.xxxxxx\0")
X * DESCRIPTION
X *    Convert a fixnum binary value to an ASCII character string.
X * RETURN VALUE
X *    address of buffer (i.e., buf)
X */
Xchar *fixnum_to_str(x, buf, numdig)
Xfixnum x;
Xchar buf[];
Xint numdig;
X{
Xlong ix;
Xchar *p;
Xint j;		/* index into buf[] of last character added */
Xchar tbuf[6];	/* temporary scratch buffer */
Xint carry;	/* carry flag for rounding up the number string */
Xchar *q;	/* pointer used in shuffling result to add new top digit */
X/*
X *  check for a minus sign
X */
Xj = 0;
Xif (x < 0L)
X    {
X    buf[j++] = '-';
X    x = -x;
X    }
Xix = fixnum_to_int(x) & 0x00000FFFL;	/* handle -2048.xxx properly */
X/*
X *  work through the integer part of the number
X *  (the digits come out in reverse order with the simplest algorithm)
X */
Xfor ( p = tbuf ; ix ; ix /= 10 )
X    *p++ = (ix % 10) + '0';
Xif (p == tbuf)			/* allow for value == 0 */
X    *p++ = '0';
Xwhile ( p > tbuf )		/* put the digits in the proper order */
X    buf[j++] = (*--p);
X
Xif (numdig <= 0)
X    {
X    buf[j] = '\0';		/* no fraction wanted! */
X    return(buf);
X    }
Xbuf[j++] = '.';
X/*
X *  convert the fraction
X */
Xfor ( ix = x & 0x000FFFFFL ; numdig > 0 ; --numdig )
X    {
X    ix *= 10;
X    buf[j++] = fixnum_to_int(ix) + '0';
X    ix &= 0x000FFFFFL;
X    }
Xif (ix > 0x00080000L)
X    {
X    /*
X     *  round up.  this can be rather a pain!
X     */
X    for ( carry = 1, p = &buf[j-1] ; (p >= buf) && carry ; --p )
X	{
X	if (isdigit(*p))	/* skip over decimal point */
X	    {
X	    ++(*p);			/* add the carry bit */
X	    if (*p > '9')		/* check for overflow */
X		{
X		*p -= 10;
X		carry = 1;
X		}
X	    else
X		carry = 0;
X	    }
X	}
X    if (carry)
X	{
X	/*
X	 *  make room for adding another digit to the integer
X	 */
X	for ( p = &buf[j], q = &buf[j+1] ; p >= buf ; *q-- = *p-- )
X	    ;
X	++j;			/* add to end-of-string index */
X	if (buf[1] == '-')
X	    {
X	    buf[0] = '-';
X	    buf[1] = '1';
X	    }
X	else
X	    buf[0] = '1';
X	}
X    }
Xbuf[j] = '\0';
Xreturn(buf);
X}
END_OF_FILE
if test 5176 -ne `wc -c <'fixnum.c'`; then
    echo shar: \"'fixnum.c'\" unpacked with wrong size!
fi
# end of 'fixnum.c'
fi
if test -f 'hp2pk.lpt' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'hp2pk.lpt'\"
else
echo shar: Extracting \"'hp2pk.lpt'\" \(4883 characters\)
sed "s/^X//" >'hp2pk.lpt' <<'END_OF_FILE'
X
X
X
X     HP2PK(1L)                                               HP2PK(1L)
X
X
X
X     NAME
X          hp2pk - convert Hewlett-Packard soft fonts into TeX fonts
X
X     SYNOPSIS
X          hp2pk [-b density] [-d size] [-h] [-l pl-file[.pl]]
X                [-m magnification] [-p pk-file[.pk]] [-r {l|u}]
X                [-s space-width] [-t tfm-file[.tfm]] [-v] sfp-file[.sfp]
X
X     DESCRIPTION
X          HP2PK converts Hewlett-Packard Soft Font/Portrait (SFP) files
X          into the TFM and PK files needed by TeX.  (Okay, okay, so TeX
X          itself doesn't need PK files--the DVI driver programs associated
X          with TeX generally do!)  Only bitmap fonts, either Class 1 bitmap
X          or Class 2 compressed bitmap, are handled by HP2PK.  The program
X          cannot process Intellifont Scalable Fonts.
X
X          For all files read or written by HP2PK, an appropriate filename
X          extension is automatically appended to the filename if one is not
X          specified explicitly.
X
X     OPTIONS
X          The command line options are described below.
X
X          -b density
X               The -b option specifies the pixel density of the font in
X               dots per inch.  If this is not given on the command line,
X               HP2PK assumes a value of 300 dpi.
X
X          -d size
X               The -d option specifies the design size of the font in
X               points.  If this is not given on the command line, HP2PK
X               calculates a value from the information given in the input
X               font header, writing the computed value to the standard
X               output.
X
X          -h   The -h option causes a brief description of the command line
X               options to be written to the standard error output (normally
X               the screen).  No other action is performed when this option
X               is used.
X
X          -m magnification
X               The -m option specifies the magnification of the font.  The
X               default value is 1000, which indicates no magnification.
X
X          -l pl-file
X               The -l option specifies a Property List (PL) font metric
X               output file.  This is a human-readable form of a TeX font
X               metric file.
X
X          -p pk-file
X               The -p option specifies the font PacKed bitmap (PK) output
X               file.  If it is not given on the command line, HP2PK
X
X
X
X     Page 1                                          (printed 4/12/91)
X
X
X
X
X
X
X     HP2PK(1L)                                               HP2PK(1L)
X
X
X
X               produces a PK file with the same basic name as the input
X               file, but with a ".pk" filetype extension.
X
X          -r {l|u}
X               The -rl option specifies that only the lower 128 character
X               codes be converted and written to the output files.  The -ru
X               option specifies that only the upper 128 character codes be
X               converted, with the codes translated from the range 128-255
X               to the range 0-127.  This allows font files to be prepared
X               for antiquated DVI drivers that cannot handle 8-bit fonts.
X
X          -s space-width
X               The -s option specifies the basic width of a space character
X               in points, if none exists in the soft font.  Character code
X               32 (octal 040) is assumed to be a space character if it
X               exists.  If the space character is not defined in the font,
X               and the -s option is not used, then the width of the x
X               character (decimal code 120, octal code 170) is used.
X
X          -t tfm-file
X               The -t option specifies the TeX Font Metric (TFM) output
X               file.  If neither a TFM (-t) nor a PL (-l) file is given on
X               the command line, HP2PK produces a TFM file with the same
X               basic name as the input file, but with a ".tfm" filetype
X               extension.
X
X          -v   The -v option tells HP2PK to be more talkative as it works.
X
X     SEE ALSO
X          TFtoPL(1), PLtoTF(1), GFtoPK(1)
X
X     BUGS
X          The Hewlett-Packard Soft Font file provides neither kerning
X          nor ligature information.  It also does not supply the slant
X          information for italic fonts.  If needed, these values must
X          be supplied by editing the PL file and then running PLtoTF to
X          produce the TFM file.
X
X          The font's pixel density must be a integral number of dots per
X          inch.
X
X          Bitmaps larger than 32767 bytes are not (yet) handled.  (Such
X          a bitmap would be larger than 510 dots square!)
X
X     AUTHOR
X          Stephen McConnel (steve@txsil.sil.org)
X          Summer Institute of Linguistics
X          7500 W. Camp Wisdom Road
X          Dallas, TX 75236, U.S.A.
X
X
X
X
X
X
X     Page 2                                          (printed 4/12/91)
X
X
X
END_OF_FILE
if test 4883 -ne `wc -c <'hp2pk.lpt'`; then
    echo shar: \"'hp2pk.lpt'\" unpacked with wrong size!
fi
# end of 'hp2pk.lpt'
fi
if test -f 'myalloc.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'myalloc.c'\"
else
echo shar: Extracting \"'myalloc.c'\" \(5927 characters\)
sed "s/^X//" >'myalloc.c' <<'END_OF_FILE'
X/*  MYALLOC.C - "safe" memory allocation functions
X ***************************************************************************
X *
X *	char *myalloc(size)
X *	unsigned size;
X *
X *	char *mystrdup(str)
X *	char *str;
X *
X *	char *myrealloc(s,size)
X *	char *s;
X *	unsigned size;
X *
X *	char *myshrink(s)
X *	char *s;
X *
X *	void myfree(s)
X *	char *s;
X *
X *	void myalloc_fail()
X *	char myalloc_errmsg[101]
X *
X ***************************************************************************
X *	EDIT HISTORY
X *	28-Jul-88	Steve McConnel - write the original code
X *	 1-Aug-88	SRMc - delinted
X *	25-Aug-88	SRMc - regularized error messages
X *			     - change errmsg to errloc
X *	21-Oct-88	SRMc - remove register from function parameter
X *				declarations
X *			     - reorganize the file header comments
X *	10-Nov-88	SRMc - add myfree()
X *	 4-Jan-89	SRMc - fix for Microsoft C
X *	22-Mar-89	SRMc - nomem() is no longer a static function
X *	20-May-89	SRMc - remove #include "dict.h"
X *			     - change errloc to 101 rather than MAXMORPH+1
X *				bytes long (removed need for defs.h)
X *			     - rename errloc to myalloc_errmsg
X *			     - added mystrdup(),
X *			     - removed reliance on errexit()
X *	13-Jul-89	hab  - de-"lint" the source
X *	31-Jul-89	rk   - mods for MacIntosh Lightspeed's Think_C
X *	19-Oct-90	SRMc - rename file from MYALLO.C to MYALLOC.C
X *			     - fix myrealloc() to work properly
X *			     - rename nomem() to myalloc_fail()
X *	14-Jan-91	SRMc - add TURBO C patches from Thomas B. Ridgeway
X *				(ridgeway@blackbox.hacc.washington.edu)
X *	15-Jan-91	SRMc - refix for Macintosh Lightspeed THINK C
X *	 2-Mar-91	SRMc - add myshrink(), which disappeared sometime ago
X *			SRMc - revise myrealloc() to call malloc() if it's
X *				handed a NULL pointer (as in PCKFUNCS.C)
X ***************************************************************************
X * Copyright 1988, 1991 by the Summer Institute of Linguistics, Inc.
X * All rights reserved.
X */
X/*#define TURBO_C*/		/* uncomment if using MSDOS TURBO C */
X#include <stdio.h>
X
X/*#ifdef THINK_C*/
X/*#include <storage.h>*/
X/*#include <strings.h>*/
X/*#else*/
X#ifdef BSD
X#include <strings.h>
Xextern char *memset();
X#else
X#ifdef TURBO_C
X#include <mem.h>
X#define MSDOS
X#else
X#ifndef THINK_C		/* THINK C includes memxxx() functions in <string.h> */
X#include <memory.h>
X#endif
X#endif
X#include <string.h>
X#endif
Xextern char *malloc(), *realloc();
Xextern void free();
X/*#endif*/
Xextern int isatty();
Xextern void exit();
X
X/************************************************************************/
X/*			    GLOBAL VARIABLES				*/
X/************************************************************************/
X
Xchar myalloc_errmsg[101];		/* globally settable by callers */
X
X/***************************************************************************
X * NAME
X *    myalloc_fail
X * ARGUMENTS
X *    none
X * DESCRIPTION
X *    Die with an appropriate error message.
X * RETURN VALUE
X *    doesn't return!
X */
Xvoid myalloc_fail()
X{
Xif (*myalloc_errmsg)
X    {
X    fprintf(stderr,"\nALLOCATE MEMORY: No space left at: %s\n",
X							myalloc_errmsg);
X    if (!isatty(fileno(stdout)))
X	printf("\nALLOCATE MEMORY: No space left at: %s\n",
X							myalloc_errmsg);
X    }
Xelse
X    {
X    fprintf(stderr,"\nALLOCATE MEMORY: No space left\n");
X    if (!isatty(fileno(stdout)))
X	printf("\nALLOCATE MEMORY: No space left\n");
X    }
Xexit(2);
X}
X
X/***************************************************************************
X * NAME
X *    myalloc
X * ARGUMENTS
X *    size - number of bytes to allocate
X * DESCRIPTION
X *    "Safe" interface to malloc() -- abort the program with an error message
X *    if we run out of memory.
X * RETURN VALUE
X *    pointer to beginning of area allocated
X */
Xchar *myalloc(size)
Xunsigned size;
X{
Xregister char *p;
X
X#ifdef THINK_C
Xp = malloc((size_t)size);
X#else
Xp = malloc(size);
X#endif
Xif (p == (char *)NULL)
X    myalloc_fail();
Xmemset(p, 0, size);
Xreturn(p);
X}
X
X/***************************************************************************
X * NAME
X *    mystrdup
X * ARGUMENTS
X *    str - pointer to character string to duplicate
X * DESCRIPTION
X *    Create a duplicate of an existing NUL-terminated character string.
X * RETURN VALUE
X *    pointer to the newly allocated and copied duplicate
X */
Xchar *mystrdup(str)
Xchar *str;
X{
Xreturn( strcpy(myalloc((unsigned)strlen(str)+1), str) );
X}
X
X/***************************************************************************
X * NAME
X *    myrealloc
X * ARGUMENTS
X *    s    - pointer to string in allocated buffer
X *    size - new (?) size desired
X * DESCRIPTION
X *    Resize the allocated buffer to the desired size.
X *    Abort the program with an error message if we run out of memory.
X * RETURN VALUE
X *    pointer to reallocated block
X */
Xchar *myrealloc(s,size)
Xchar *s;
Xunsigned size;
X{
Xregister char *p;
X
Xif (s == NULL)
X    return( myalloc(size) );
X#ifdef THINK_C
Xp = realloc( s, (size_t)size );
X#else
Xp = realloc( s, size );
X#endif
Xif (p == (char *)NULL)
X    myalloc_fail();
Xreturn( p );
X}
X
X/***************************************************************************
X * NAME
X *    myshrink
X * ARGUMENTS
X *    s - pointer to string in overlarge allocated buffer
X * DESCRIPTION
X *    Shrink the allocated buffer to exactly fit the string.  Abort the
X *    program with an error message if we somehow run out of memory.
X * RETURN VALUE
X *    pointer to reallocated block
X */
Xchar *myshrink(s)
Xchar *s;
X{
Xregister char *p;
X
Xif (s == (char *)NULL)
X    return((char *)NULL);
Xp = realloc( s, (unsigned)strlen(s)+1 );
Xif (p == (char *)NULL)
X    myalloc_fail();
Xreturn( p );
X}
X
X/***************************************************************************
X * NAME
X *    myfree
X * ARGUMENTS
X *    s - pointer to block to deallocate
X * DESCRIPTION
X *    interface to free() -- release previously allocated memory
X * RETURN VALUE
X *    none
X */
Xvoid myfree(s)
Xchar *s;
X{
Xif (s == (char *)NULL)
X    return;		/* protect against braindead callers */
Xfree(s);
X}
END_OF_FILE
if test 5927 -ne `wc -c <'myalloc.c'`; then
    echo shar: \"'myalloc.c'\" unpacked with wrong size!
fi
# end of 'myalloc.c'
fi
if test -f 'writepl.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'writepl.c'\"
else
echo shar: Extracting \"'writepl.c'\" \(4328 characters\)
sed "s/^X//" >'writepl.c' <<'END_OF_FILE'
X/*  WRITEPL.C - Write data to a TeX PL font metric file
X ***************************************************************************
X *
X *	void init_pl_file(fp, program, version, time, tp)
X *	FILE *fp;
X *	char *program;
X *	char *version;
X *	char *time;
X *	struct tfm_header *tp;
X *
X *	void write_pl_entry(fp, ch_code, fmc)
X *	FILE *fp;
X *	unsigned char ch_code;
X *	struct tfm_chardata *fmc;
X *
X *	void end_pl_file(fp, tfp)
X *	FILE *fp;
X *	struct tfm_param *tfp;
X *
X ***************************************************************************
X *
X *	Sources of information for TeX font metric files:
X *
X *		The METAFONTbook by Donald E. Knuth (appendix F)
X *		PLtoTF.WEB by Donald E. Knuth, Leo Guibas, et al.
X *
X ***************************************************************************
X *	EDIT HISTORY
X *	19-Oct-90	SRMc - split out from HP2PK.C to improve modularity
X *	20-Oct-90	SRMc - remove ctime() call in init_pl_file()
X *	17-Jan-91	SRMc - put version information in PATCHLEVEL.H
X ***************************************************************************
X * Copyright 1990, 1991 by the Summer Institute of Linguistics, Inc.
X * All rights reserved.
X */
X#include <stdio.h>
X#include "patchlevel.h"
X#include "tfm.h"
X
Xextern char *fixnum_to_str();	/* from FIXNUM.C */
X
X/****************************************************************************
X * NAME
X *    init_pl_file
X * ARGUMENTS
X *    fp      - output PL FILE pointer
X *    program - program name string
X *    date    - date and time string
X *    tp      - pointer to TFM preamble structure
X * DESCRIPTION
X *    Write the initial heading of the .PL file.
X * RETURN VALUE
X *    none
X */
Xvoid init_pl_file(fp, program, date, tp)
XFILE *fp;
Xchar *program;
Xchar *date;
Xstruct tfm_header *tp;
X{
Xregister int i;
Xchar buf[16];		/* buffer for holding fixnum's string */
X
Xfprintf(fp,"(COMMENT THIS PL FILE WAS PRODUCED BY %s %d.%d.%d (%s), %s)\n",
X	program, VERSION, REVISION, PATCHLEVEL, PATCHDATE, date );
Xfprintf(fp,"(FAMILY ");
Xfor ( i = 1 ; i <= tp->tfm_fontid[0] ; ++i )
X    putc( tp->tfm_fontid[i], fp);
Xfprintf(fp,")\n");
Xfprintf(fp,"(DESIGNSIZE R %s)\n",fixnum_to_str(tp->tfm_design_size, buf, 7));
Xfprintf(fp,"(COMMENT DESIGNSIZE IS IN POINTS)\n");
Xfprintf(fp,"(COMMENT OTHER SIZES ARE MULTIPLES OF DESIGNSIZE)\n");
Xfprintf(fp,"(CHECKSUM O 0)\n");
Xfprintf(fp,"(CODINGSCHEME ");
Xfor ( i = 1 ; i <= tp->tfm_coding[0] ; ++i )
X    putc( tp->tfm_coding[i], fp);
Xfprintf(fp,")\n");
X}
X
X/****************************************************************************
X * NAME
X *    write_pl_entry
X * ARGUMENTS
X *    fp      - output PL FILE pointer
X *    ch_code - character code value
X *    fmc     - pointer to TeX font metric character info structure
X * DESCRIPTION
X *    Write the information for the current character to the .PL file.
X * RETURN VALUE
X *    none
X */
Xvoid write_pl_entry(fp, ch_code, fmc)
XFILE *fp;
Xint ch_code;
Xstruct tfm_chardata *fmc;
X{
Xchar buf[16];		/* buffer for holding fixnum's string */
X
Xfprintf(fp,"(CHARACTER D %d\n", ch_code );
Xfprintf(fp,"   (CHARWD R %s)\n", fixnum_to_str(fmc->charwd, buf, 7) );
Xfprintf(fp,"   (CHARHT R %s)\n", fixnum_to_str(fmc->charht, buf, 7) );
Xif (fmc->chardp > 0L)
X    fprintf(fp,"   (CHARDP R %s)\n", fixnum_to_str(fmc->chardp, buf, 7) );
Xif (fmc->charic > 0L)
X    fprintf(fp,"   (CHARIC R %s)\n", fixnum_to_str(fmc->charic, buf, 7) );
Xfprintf(fp,"   )\n");
X}
X
X/****************************************************************************
X * NAME
X *    end_pl_file
X * ARGUMENTS
X *    fp  - output PL FILE pointer
X *    tfp - pointer to TFM parameter structure
X * DESCRIPTION
X *    Write the tail of the .PL file.
X * RETURN VALUE
X *    none
X */
Xvoid end_pl_file(fp, tfp)
XFILE *fp;
Xstruct tfm_param *tfp;
X{
Xchar buf[16];		/* buffer for holding fixnum's string */
X
Xfprintf(fp,"(FONTDIMEN\n");
Xfprintf(fp,"   (SPACE      R  %s)\n",
X				fixnum_to_str(tfp->tfm_space,buf,7));
Xfprintf(fp,"   (STRETCH    R  %s)\n",
X				fixnum_to_str(tfp->tfm_space_stretch,buf,7));
Xfprintf(fp,"   (SHRINK     R  %s)\n",
X				fixnum_to_str(tfp->tfm_space_shrink,buf,7));
Xfprintf(fp,"   (EXTRASPACE R  %s)\n",
X				fixnum_to_str(tfp->tfm_extra_space,buf,7));
Xfprintf(fp,"   (QUAD       R  %s)\n",
X				fixnum_to_str(tfp->tfm_quad,buf,7));
Xfprintf(fp,"   (XHEIGHT    R  %s)\n",
X				fixnum_to_str(tfp->tfm_x_height,buf,7));
Xfprintf(fp,"   )\n");
X}
END_OF_FILE
if test 4328 -ne `wc -c <'writepl.c'`; then
    echo shar: \"'writepl.c'\" unpacked with wrong size!
fi
# end of 'writepl.c'
fi
if test -f 'writetfm.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'writetfm.c'\"
else
echo shar: Extracting \"'writetfm.c'\" \(11960 characters\)
sed "s/^X//" >'writetfm.c' <<'END_OF_FILE'
X/*  WRITETFM.C - Write all the data to a TeX TFM font metric file
X ***************************************************************************
X *
X *	void write_tfm_data(fp, tpfm, hdfm, chfm, pafm, designsize)
X *	FILE *fp;
X *	struct tfm_top      *tpfm;
X *	struct tfm_header   *hdfm;
X *	struct tfm_chardata chfm[];
X *	struct tfm_param    *pafm;
X *	fixnum designsize;
X *
X ***************************************************************************
X *
X *	Sources of information for TeX font metric files:
X *
X *		The METAFONTbook by Donald E. Knuth (appendix F)
X *		PLtoTF.WEB by Donald E. Knuth, Leo Guibas, et al.
X *
X ***************************************************************************
X *	EDIT HISTORY
X *	19-Oct-90	SRMc - split out from HP2PK.C to improve modularity
X *	20-Oct-90	SRMc - make write_tfm_data() the only externally
X *				visible function
X ***************************************************************************
X * Copyright 1990 by the Summer Institute of Linguistics, Inc.
X * All rights reserved.
X */
X#include <stdio.h>
X#include "tfm.h"
X#include "bitmap.h"
X
X/************************************************************************/
X/*			   EXTERN DECLARATIONS				*/
X/************************************************************************/
X
Xextern void put_halfword(), put_fullword();	/* from BIGENDIO.C */
Xextern char *fixnum_to_str();			/* from FIXNUM.C */
X
X/************************************************************************/
X/*			STATIC GLOBAL VARIABLES				*/
X/************************************************************************/
Xstatic long tfm_width_table[256];
Xstatic long tfm_height_table[256];
Xstatic long tfm_depth_table[256];
Xstatic long tfm_charic_table[256];
Xstatic int num_tfm_width, num_tfm_height, num_tfm_depth, num_tfm_charic;
X
X/****************************************************************************
X * NAME
X *    static insort
X * ARGUMENTS
X *    table - array of long integers
X *    size  - size of the array
X *    value - value to add to the array if not already there
X * DESCRIPTION
X *    Add a value to an array, in sorted order.
X * RETURN VALUE
X *    size of the array after (possibly) adding the value
X */
Xstatic int insort(table, size, value)
Xlong *table;
Xint size;
Xlong value;
X{
Xint i, j;
X
Xif (value == 0L)
X    return( size );		/* ignore zeros */
X
Xfor ( i = 0 ; i < size ; ++i )
X    {
X    if (table[i] == value)
X	return(size);
X    if (table[i] > value)
X	{
X	for ( j = size ; j > i ; --j)
X	    table[j] = table[j-1];	/* make room to */
X	table[i] = value;		/* insert the new value */
X	return(size+1);
X	}
X    }
Xtable[size] = value;	/* add to end of sorted table */
Xreturn( size + 1 );
X}
X
X#define labs(a) ((a >= 0) ? a : -a )
X
X/****************************************************************************
X * NAME
X *    static mindelta
X * ARGUMENTS
X *    table    - sorted array of long ints
X *    size     - size of the array
X * DESCRIPTION
X *    Find the minimum difference between adjacent entries in the array.
X * RETURN VALUE
X *    the minimum difference found (adjusted slightly for roundoff)
X */
Xstatic fixnum mindelta(table, size)
Xfixnum *table;
Xint size;
X{
Xint k;
Xfixnum min_diff;
X
Xmin_diff = 0x7FFFFFFFL;
X
Xfor ( k = 0 ; k < size-1 ; ++k )
X    {
X    if (labs(table[k+1] - table[k]) < min_diff)
X	min_diff = labs( table[k+1] - table[k] );
X    }
Xreturn( min_diff+1 );		/* adjust slightly for roundoff */
X}
X
X/****************************************************************************
X * NAME
X *    static trim_tfm_table
X * ARGUMENTS
X *    table   - array of long integers
X *    size    - size of the array
X *    max     - maximum allowable size of the array
X *    tabname - character string name of the table for error message
X *    dsize   - designsize of font (in 2**-20 points)
X * DESCRIPTION
X *    If the array is larger than allowed, throw out the minimum number of
X *    values, trying for minimum impact of the loss of precision.
X * RETURN VALUE
X *    number of entries in the reduced table
X */
Xstatic int trim_tfm_table(table, size, max, tabname, dsize)
Xlong *table;
Xint size;
Xint max;
Xchar *tabname;
Xfixnum dsize;
X{
Xlong scratch[256];
Xchar fixnumbuf[16];
Xint i;
Xint num;
Xfixnum min_d;
Xdouble d;
X
Xif (size <= max)
X    return(size);
X
Xdo  {
X    min_d = mindelta(table, size);
X    for ( num = 0, i = 0 ; i < size-1 ; ++i )
X	{
X	if ((table[i+1] - table[i]) <= min_d)
X	    {				/* split the difference */
X	    scratch[num++] = (table[i] + table[i+1]) / 2;
X	    ++i;			/* need to skip ahead in table[] */
X	    }
X	else
X	    scratch[num++] = table[i];	/* copy the original value */
X	}
X    if (i < size)
X	scratch[num++] = table[i];	/* if needed, store largest value */
X
X    size = num;
X    for ( i = 0 ; i < size ; ++i )
X	table[i] = scratch[i];
X
X    } while (size > max);
X
Xd = (min_d / 2.0) * (dsize / TWO_20th);
Xmin_d = d;
Xprintf( "TFM character %s may be rounded off by %s pt.\n",
X				tabname, fixnum_to_str(min_d, fixnumbuf, 7) );
Xreturn(size);
X}
X
X/****************************************************************************
X * NAME
X *    static table_index
X * ARGUMENTS
X *    table - array of long integers
X *    size  - size of the array
X *    value - value to search for
X * DESCRIPTION
X *    Search for the closest fit in the array to the given value.
X * RETURN VALUE
X *    index in the array of the closest fit
X */
Xstatic int table_index(table, size, value)
Xlong *table;
Xint size;
Xlong value;
X{
Xint i;
X/*
X *  first, try for exact matches
X */
Xfor ( i = 0 ; i < size ; ++i )
X    {
X    if (value == table[i])
X	return( i );
X    }
X/*
X *  now, try for closest fit
X */
Xfor ( i = 1 ; i < size-1 ; ++i )
X    {
X    if ((value > table[i]) && (value < table[i+1]))
X	{
X	if ((value < 0) && (table[i+1] > 0))
X	    return( ((value - table[i]) < -value) ? i : 0 );
X	if ((value > 0) && (table[i] < 0))
X	    return( (value < (table[i+1] - value)) ? 0 : i+1 );
X	return( ((value - table[i]) < (table[i+1] - value)) ? i : i+1 );
X	}
X    }
Xreturn(size-1);		/* largest value in table was rounded down */
X}
X
X/****************************************************************************
X * NAME
X *    static fix_tfm_data
X * ARGUMENTS
X *    chfm       - pointer to array of TFM character data structures
X *    tpfm       - pointer to TFM file top information structure
X *    designsize - font design size (used for roundoff messages)
X * DESCRIPTION
X *    Fix the TFM data in preparation for writing the file.
X *    This involves squeezing the character metric arrays to no more
X *    than their maximum sizes prior to converting character metric values
X *    into table indices.
X * RETURN VALUE
X *    none
X */
Xstatic void fix_tfm_data(chfm, tpfm, designsize)
Xstruct tfm_chardata chfm[];
Xstruct tfm_top *tpfm;
Xfixnum designsize;
X{
Xint i;
Xlong idx;
X/*
X *  ensure the character metric tables are no larger than allowed
X */
Xnum_tfm_width = num_tfm_height = num_tfm_depth = num_tfm_charic = 0;
Xfor ( i = 0 ; i < 256 ; ++i )
X    {
X    num_tfm_width  = insort(&tfm_width_table[1], num_tfm_width,
X				chfm[i].charwd);
X    num_tfm_height = insort(&tfm_height_table[1],num_tfm_height,
X				chfm[i].charht);
X    num_tfm_depth  = insort(&tfm_depth_table[1], num_tfm_depth,
X				chfm[i].chardp);
X    num_tfm_charic = insort(&tfm_charic_table[1],num_tfm_charic,
X				chfm[i].charic);
X    }
Xnum_tfm_width  = trim_tfm_table( &tfm_width_table[1],  num_tfm_width,
X			MAX_TFM_WIDTH-1,  "widths", designsize);
Xnum_tfm_height = trim_tfm_table( &tfm_height_table[1], num_tfm_height,
X			MAX_TFM_HEIGHT-1, "heights", designsize);
Xnum_tfm_depth  = trim_tfm_table( &tfm_depth_table[1],  num_tfm_depth,
X			MAX_TFM_DEPTH-1,  "depths", designsize );
Xnum_tfm_charic = trim_tfm_table( &tfm_charic_table[1], num_tfm_charic,
X			MAX_TFM_CHARIC-1, "italic corrections", designsize );
Xtfm_width_table[0]  = 0L;	++num_tfm_width;
Xtfm_height_table[0] = 0L;	++num_tfm_height;
Xtfm_depth_table[0]  = 0L;	++num_tfm_depth;
Xtfm_charic_table[0] = 0L;	++num_tfm_charic;
X/*
X *  convert the character data
X */
Xfor ( i = tpfm->tfm_bc ; i <= tpfm->tfm_ec ; ++i )
X    {
X    idx = (long)table_index(tfm_width_table, num_tfm_width, chfm[i].charwd);
X    chfm[i].char_info  = (idx << 24) & 0xFF000000L;
X
X    idx = (long)table_index(tfm_height_table,num_tfm_height,chfm[i].charht);
X    chfm[i].char_info |= (idx << 20) & 0x00F00000L;
X
X    idx = (long)table_index(tfm_depth_table, num_tfm_depth, chfm[i].chardp);
X    chfm[i].char_info |= (idx << 16) & 0x000F0000L;
X
X    idx = (long)table_index(tfm_charic_table,num_tfm_charic,chfm[i].charic);
X    chfm[i].char_info |= (idx << 10) & 0x0000FC00L;
X    }
X/*
X *  store the TFM file description data
X */
Xtpfm->tfm_lf = 6 +		/* length of the entire file, in words */
X		(tpfm->tfm_ec - tpfm->tfm_bc + 1) +
X		num_tfm_width + num_tfm_height + num_tfm_depth +
X		num_tfm_charic + 18 + 7;
Xtpfm->tfm_lh = 18;		/* length of the header data, in words */
Xtpfm->tfm_nw = num_tfm_width;	/* number of words in the width table */
Xtpfm->tfm_nh = num_tfm_height;	/* number of words in the height table */
Xtpfm->tfm_nd = num_tfm_depth;	/* number of words in the depth table */
Xtpfm->tfm_ni = num_tfm_charic;	/* number of words in the italic corr. table */
Xtpfm->tfm_nl = 0;		/* number of words in the lig/kern table */
Xtpfm->tfm_nk = 0;		/* number of words in the kern table */
Xtpfm->tfm_ne = 0;		/* number of words in the exten. char. table */
Xtpfm->tfm_np = 7;		/* number of font parameter words */
X}
X
X/****************************************************************************
X * NAME
X *    write_tfm_data
X * ARGUMENTS
X *    fp - FILE pointer
X *    tpfm - pointer to TFM file top information structure
X *    hdfm - pointer to TFM file header structure
X *    chfm - pointer to array of TFM character data structures
X *    pafm - pointer to TFM parameter structure
X *    designsize - font design size (used for roundoff messages)
X * DESCRIPTION
X *    Write the TFM data to a file.
X * RETURN VALUE
X *    none
X */
Xvoid write_tfm_data(fp, tpfm, hdfm, chfm, pafm, designsize)
XFILE *fp;
Xstruct tfm_top      *tpfm;
Xstruct tfm_header   *hdfm;
Xstruct tfm_chardata chfm[];
Xstruct tfm_param    *pafm;
Xfixnum designsize;
X{
Xint i;
X/*
X *  fix the TFM character data
X */
Xfix_tfm_data(chfm, tpfm, designsize);
X/*
X *  write the TFM file description info
X */
Xput_halfword( tpfm->tfm_lf, fp );
Xput_halfword( tpfm->tfm_lh, fp );
Xput_halfword( tpfm->tfm_bc, fp );
Xput_halfword( tpfm->tfm_ec, fp );
Xput_halfword( tpfm->tfm_nw, fp );
Xput_halfword( tpfm->tfm_nh, fp );
Xput_halfword( tpfm->tfm_nd, fp );
Xput_halfword( tpfm->tfm_ni, fp );
Xput_halfword( tpfm->tfm_nl, fp );
Xput_halfword( tpfm->tfm_nk, fp );
Xput_halfword( tpfm->tfm_ne, fp );
Xput_halfword( tpfm->tfm_np, fp );
X/*
X *  write the TFM File Header
X */
Xput_fullword( hdfm->tfm_checksum, fp );
Xput_fullword( hdfm->tfm_design_size, fp );
Xfor ( i = 0 ; i < 40 ; ++i )
X    putc( hdfm->tfm_coding[i], fp );
Xfor ( i = 0 ; i < 20 ; ++i )
X    putc( hdfm->tfm_fontid[i], fp );
Xputc( hdfm->tfm_7bitsafe, fp );
Xputc( hdfm->tfm_unused[0], fp );
Xputc( hdfm->tfm_unused[1], fp );
Xputc( hdfm->tfm_face, fp );
X/*
X *  write the TFM Character Data
X */
Xfor ( i = tpfm->tfm_bc ; i <= tpfm->tfm_ec ; ++i )
X    {
X    put_fullword( chfm[i].char_info, fp );
X    }
X/*
X *  write the TFM Character widths table
X */
Xfor ( i = 0 ; i < num_tfm_width ; ++i )
X    put_fullword( tfm_width_table[i], fp );
X/*
X *  write the TFM Character heights table
X */
Xfor ( i = 0 ; i < num_tfm_height ; ++i )
X    put_fullword( tfm_height_table[i], fp );
X/*
X *  write the TFM Character depths table
X */
Xfor ( i = 0 ; i < num_tfm_depth ; ++i )
X    put_fullword( tfm_depth_table[i], fp );
X/*
X *  write the TFM Character italic corrections table
X */
Xfor ( i = 0 ; i < num_tfm_charic ; ++i )
X    put_fullword( tfm_charic_table[i], fp );
X/*
X *  write the TFM Font Parameters
X */
Xput_fullword( pafm->tfm_slant, fp );
Xput_fullword( pafm->tfm_space, fp );
Xput_fullword( pafm->tfm_space_stretch, fp );
Xput_fullword( pafm->tfm_space_shrink, fp );
Xput_fullword( pafm->tfm_x_height, fp );
Xput_fullword( pafm->tfm_quad, fp );
Xput_fullword( pafm->tfm_extra_space, fp );
X}
END_OF_FILE
if test 11960 -ne `wc -c <'writetfm.c'`; then
    echo shar: \"'writetfm.c'\" unpacked with wrong size!
fi
# end of 'writetfm.c'
fi
echo shar: End of archive 2 \(of 4\).
cp /dev/null ark2isdone
MISSING=""
for I in 1 2 3 4 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 4 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0

exit 0 # Just in case...
-- 
Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
Sterling Software, IMD           UUCP:     uunet!sparky!kent
Phone:    (402) 291-8300         FAX:      (402) 291-4362
Please send comp.sources.misc-related mail to kent@uunet.uu.net.