[comp.unix.microport] Makedev for Ditroff sources!

jantypas@hope.UUCP (John Antypas) (06/02/88)

Here it is!  A PD mkdev for Ditroff.  Now that you have the tools I expect
to see my Ditroff-->Ticker posprocessor Real Soon Now :-) Actually something
for matrix printers at 240 dpi. would sure be a nice addition to 2.4/

Great heaps of thanks go to Ken Yap for providing this code!
(ken@cs.rochester.edu)
--- Cut/Slice/Dice/Shred Here --------------
#! /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:
#	Cakefile
#	Conf
#	Makefile
#	README
#	dev.h
#	font.h
#	makedesc.c
#	mkfont.c
#	mkfont.p
#	nextword.c
#	rdfont.c
#	readdesc.c
#	strsave.c
# This archive created: Wed Jun  1 13:51:07 1988
# By:	Ken Yap ()
export PATH; PATH=/bin:/usr/bin:$PATH
echo shar: "extracting 'Cakefile'" '(31 characters)'
if test -f 'Cakefile'
then
	echo shar: "will not over-write existing file 'Cakefile'"
else
cat << \SHAR_EOF > 'Cakefile'
#include "C"
#include "System"
SHAR_EOF
if test 31 -ne "`wc -c < 'Cakefile'`"
then
	echo shar: "error transmitting 'Cakefile'" '(should have been 31 characters)'
fi
fi
echo shar: "extracting 'Conf'" '(80 characters)'
if test -f 'Conf'
then
	echo shar: "will not over-write existing file 'Conf'"
else
cat << \SHAR_EOF > 'Conf'
mkfont makedesc mkfont strsave nextword
rdfont readdesc rdfont strsave nextword
SHAR_EOF
if test 80 -ne "`wc -c < 'Conf'`"
then
	echo shar: "error transmitting 'Conf'" '(should have been 80 characters)'
fi
fi
echo shar: "extracting 'Makefile'" '(578 characters)'
if test -f 'Makefile'
then
	echo shar: "will not over-write existing file 'Makefile'"
else
cat << \SHAR_EOF > 'Makefile'
#for S5 uncomment next line
# CFLAGS=-DSYS5

RDSRC=	readdesc.c rdfont.c strsave.c
RDOBJ=	readdesc.o rdfont.o strsave.o
MKSRC=	makedesc.c mkfont.c nextword.c strsave.c
MKOBJ=	makedesc.o mkfont.o nextword.o strsave.o


all: mkfont rdfont

mkfont:	${MKOBJ}
	cc -o mkfont -O ${MKOBJ}

rdfont:	${RDOBJ}
	cc -o rdfont -O ${RDOBJ}

rdfont.o:	rdfont.c font.h
readdesc.o:	readdesc.c  dev.h

mkfont.o:	mkfont.c font.h
makedesc.o:	makedesc.c  dev.h

clean:
	rm -f *.o mkfont rdfont

lint:
	lint -phbvac dev.h font.h ${MKSRC} > lint.mkfont
	lint -phbvac dev.h font.h ${RDSRC} > lint.rdfont
SHAR_EOF
if test 578 -ne "`wc -c < 'Makefile'`"
then
	echo shar: "error transmitting 'Makefile'" '(should have been 578 characters)'
fi
fi
echo shar: "extracting 'README'" '(1989 characters)'
if test -f 'README'
then
	echo shar: "will not over-write existing file 'README'"
else
cat << \SHAR_EOF > 'README'
Mkfont duplicates  the actions  (more or  less) of  the ATT  "makedev"
program,  tp  produce  binary  font  files  for  ditroff,  from  ascii
descriptions for the fonts.   Rdfont will read  the binary font  files
and produce an  ascii equivalent  (which may then  be re-compiled)  by
mkfont.

These programs were written on a Pyramid 90x in the ucb universe,  and
should compile fairly  readily in  any BSD  environment; they've  been
compiled in the att  environment, and on a  Vax 750 under 4.3BSD  (but
not really tested  in those environments).   Check the  CFLAGS in  the
Makefile for SYS5.  There is also a cakefile, for those so inclined.
For some systems, you may have to deal with the 3-argument open() calls.

The programs were written  after Pyramid supplied  ditroff with an  OS
upgrade,  but  didn't  supply  makedev.    "makedev"  has  since  been
supplied, and mkfont checked against it.

Mkfont has  been used  to compile  Postscript fonts  from  description
files posted to USENET in May of 1986 by Stephen Frede at U of NSW  in
Sydney, Australia--you  should  be able  to  find them  in  a  sources
archive somewhere, if you need them.

I am the author of  these programs, and I  submit them for public  use
without restriction.

CAVEATS
The binary font  files produced  by mkfont will  differ slightly  from
those produced by makedev if there are duplicate entries in the  width
table, unless you use the '-c' option to mkfont (see the man page  for
a little more info).

If you use  these to produce  Postscript font files,  be aware of  the
standard ditroff limit of 10 fonts (enforced by core dump).  I believe
patches to  fix  this  and  other bugs  are  in  the  USENET  archives
somewhere.   For those  of you  with  Pyramids, RTOC  can send  you  a
version which will  handle up to  25 files; otherwise  you'll have  to
pick and  chose.    NOTE:  mkfont will  compile  them  fine  (as  will
makedev), but ditroff won't like 'em.


Duane H. Hesser
dhh@teltone.com
SHAR_EOF
if test 1989 -ne "`wc -c < 'README'`"
then
	echo shar: "error transmitting 'README'" '(should have been 1989 characters)'
fi
fi
echo shar: "extracting 'dev.h'" '(410 characters)'
if test -f 'dev.h'
then
	echo shar: "will not over-write existing file 'dev.h'"
else
cat << \SHAR_EOF > 'dev.h'
/*
 * $Header: dev.h,v 1.1 87/10/23 19:08:07 sysad Exp $
 */

/*
 * $Log:	dev.h,v $
 * Revision 1.1  87/10/23  19:08:07  sysad
 * Initial revision
 * 
 * 
 */

 struct dev {
	unsigned short filesize;
	short res;
	short hor;
	short vert;
	short unitwidth;
	short nfonts;
	short nsizes;
	short sizescale;
	short paperwidth;
	short paperlength;
	short nchtab;
	short lchname;
	short biggestfont;
	short spare;
};
SHAR_EOF
if test 410 -ne "`wc -c < 'dev.h'`"
then
	echo shar: "error transmitting 'dev.h'" '(should have been 410 characters)'
fi
fi
echo shar: "extracting 'font.h'" '(369 characters)'
if test -f 'font.h'
then
	echo shar: "will not over-write existing file 'font.h'"
else
cat << \SHAR_EOF > 'font.h'
/*
 * $Header: font.h,v 1.1 87/10/23 19:08:08 sysad Exp $
 */

/*
 * $Log:	font.h,v $
 * Revision 1.1  87/10/23  19:08:08  sysad
 * Initial revision
 * 
 * 
 */

struct Font {
	char nwfont;
	char specfont;
	char ligfont;
	char pad;
	char namefont[10];
	char intname[10];
};

#define	LIG_FF	01
#define	LIG_FI	02
#define	LIG_FL	04
#define	LIG_FFI	010
#define	LIG_FFL	020
SHAR_EOF
if test 369 -ne "`wc -c < 'font.h'`"
then
	echo shar: "error transmitting 'font.h'" '(should have been 369 characters)'
fi
fi
echo shar: "extracting 'makedesc.c'" '(8441 characters)'
if test -f 'makedesc.c'
then
	echo shar: "will not over-write existing file 'makedesc.c'"
else
cat << \SHAR_EOF > 'makedesc.c'
static char *RCSid = "$Header: makedesc.c,v 1.1 87/10/23 19:08:09 sysad Exp $";

/* Read an ascii description of a ditroff font and create the         */
/* corresponding binary font files                                    */


/*
 * $Log:	makedesc.c,v $
 * Revision 1.1  87/10/23  19:08:09  sysad
 * Initial revision
 * 
 * 
 */

#include <stdio.h>
#include <sys/file.h>
#include "dev.h"

#define	SHORT	0xffff
#define	MAXP	128		/* allocate space for point sizes in MAXP chunks */
int compat = 0;		/* compatibility with att "makedev"; duplicate "width"
					 * entries are re-used if this is non-zero.
					 */
char *Progname;
struct dev dev;
extern char *malloc(),*nextword(),*savestr();
extern char **font_names(),*fgets();
extern FILE *fopen();
extern short *p_sizes();

main(argc,argv)
int argc;
char **argv;
{
	FILE *inptr;
	int fdout,nchtab,lchname,i,fsize,biggestfont;
	long fontf_start;
	short *point_list,*funny_ind;
	char *funny_chars;
	char **font_list;
	char mybuf[1024];
	char *str,*descfile;

	Progname = argv[0];
	++argv; --argc;

	if(strcmp(*argv,"-c") == 0)
	{
		++compat;
		++argv;
		--argc;
	}
	if(argc == 0)
	{
		descfile = "DESC";
	}
	else if(argc == 1)
	{
		descfile = argv[0];
	}
	else
	{
		fprintf(stderr,"usage: %s [-c] [descfile]\n",Progname);
		exit(1);
	}

	if((inptr = fopen(descfile,"r")) == (FILE *)0)
	{
		fprintf(stderr,"%s: can't open %s\n",Progname,descfile);
		exit(2);
	}
	sprintf(mybuf,"%s.out",descfile);
	if((fdout = open(mybuf,O_CREAT | O_WRONLY,0644)) < 0)
	{
		fprintf(stderr,"%s: can't create %s\n",Progname,mybuf);
		exit(2);
	}
	dev.filesize = (short)0;
	dev.sizescale = (short)1;
	biggestfont = 0;
	dev.spare = (short)0;
	/* Build the dev structure first */
	while(fgets(mybuf,1024,inptr))
	{
start:	/* we come back here if we read ahead in a font_names() */
		if(!*mybuf || (*mybuf == '#'))
			continue;
		nextword("");	/* reset to beginning of line */
		/* printf("line = %s\n",mybuf); */
		str = nextword(mybuf);
		if(strcmp(str,"charset") == 0)
			break;
		if(strcmp(str,"res") == 0)
			dev.res = (short)atoi(nextword(mybuf));
		else if(strcmp(str,"hor") == 0)
			dev.hor = (short)atoi(nextword(mybuf));
		else if(strcmp(str,"vert") == 0)
			dev.vert = (short)atoi(nextword(mybuf));
		else if(strcmp(str,"unitwidth") == 0)
			dev.unitwidth = (short)atoi(nextword(mybuf));
		else if(strcmp(str,"sizescale") == 0)
			dev.sizescale = (short)atoi(nextword(mybuf));
		else if(strcmp(str,"paperwidth") == 0)
			dev.paperwidth = (short)atoi(nextword(mybuf));
		else if(strcmp(str,"paperlength") == 0)
			dev.paperlength = (short)atoi(nextword(mybuf));
		else if(strcmp(str,"biggestfont") == 0)
		{
			biggestfont = atoi(nextword(mybuf));
			dev.biggestfont = (short)biggestfont;
		}
		else if(strcmp(str,"sizes") == 0)
		{
			/* accumulate the list of legal point sizes */
			point_list = p_sizes(inptr,mybuf,&dev);
		}
		else if(strcmp(str,"fonts") == 0)
		{
			dev.nfonts = (short)atoi(nextword(mybuf));
			font_list = font_names(inptr,mybuf,dev.nfonts);
			goto start;
		}
	}
	nextword("");
	/* Next comes the funny index table and the character strings; read
	 * the description and stuff the information into the binary format 
	 * tables.
	 */
	if(fgets(mybuf,1024,inptr) == (char *)0)
	{
		fprintf(stderr,"%s: no funny char strings table\n",Progname);
		exit(1);
	}
	nchtab = get_funny(inptr,mybuf,&funny_ind,&funny_chars,&lchname);
	dev.nchtab = (short)nchtab;
	dev.lchname = (short)lchname;

	/* We don't have enough information yet to write the dev structure
	 * (don't know how many fonts, or their names...).  We do know how
	 * big it is, and how long the description tables are, so we seek
	 * past all that stuff andd write the font descriptions first.
	 * Later, we'll go back and write the stuff we skipped over.
	 */
	fontf_start = (long)(sizeof(dev) + ((dev.nsizes +1) * sizeof(short))
					+ (nchtab * sizeof(short)) + lchname);
	(void)lseek(fdout,fontf_start,0);

	/* Read the font files, and write the binary equivalents */
	for(i = 0; i < (int)dev.nfonts; ++i)
	{
		fsize = do_font(font_list[i],funny_chars,funny_ind,nchtab,fdout);
		/* keep track of the biggest font */
		if(fsize > biggestfont)
			biggestfont = fsize;
	}
	dev.biggestfont = (short)(biggestfont & SHORT);
	dev.filesize = (unsigned short)(lseek(fdout,0L,2) - sizeof(dev));
	write_desc(fdout,&dev,point_list,funny_ind,funny_chars);
	exit(0);
}

/* Read the point sizes list */

short *
p_sizes(inptr,buf,dev)
FILE *inptr;
char *buf;
struct dev *dev;
{
	short *pl,*ret;
	char *word,*realloc();
	int nwords = 0;
	int n;

	/* allow for MAXP point sizes; we have to reallocate if we exceed that */
	ret = pl = (short *)malloc((unsigned)(MAXP * sizeof(short)));
	if(!pl)
	{
		fprintf(stderr,"can't malloc space for psizes\n",Progname);
		exit(1);
	}
	n = 1;
	while((word = nextword(buf)) || fgets(buf,1024,inptr))
	{
		if(!word)
		{
			nextword("");
			word = nextword(buf);
		}
		if(!word)	/* ran out of words this line, had to fgets more */
		{
			nextword("");
			if(fgets(buf,1024,inptr))
				word = nextword(buf);
			else
			{
				*buf = '\0';
				break;
			}
		}
		nwords++;
		if(nwords >= MAXP)
		{
			/* Oops! ran out os space; get more */
			ret = (short *)realloc((char *)ret,(unsigned)(MAXP * ++n * sizeof(short)));
			pl = &ret[nwords];	/* could have moved */
		}
		*pl = (short)atoi(word);
		if(*pl == (short)0)
			break;
		++pl;
	}
	/* don't count the zero at the end */
	--nwords;
	dev->nsizes = (short)nwords;
	return(ret);
}

/* Read and save the font names; return the list */

char **
font_names(inptr,buf,nfonts)
FILE *inptr;
char *buf;
short nfonts;
{
	char **ret,**next;
	char *word;
	int nwords = 0;

	ret = next = (char **)malloc((unsigned)((nfonts + 1) * sizeof(char *)));

	while((word = nextword(buf)) || fgets(buf,1024,inptr))
	{
		if(!word)
		{
			nextword("");
			word = nextword(buf);
		}
		*next++ = savestr(word);
		if(++nwords >= (int)nfonts)
		{
			/* main() expects a new buffer */
			fgets(buf,1024,inptr);
			break;
		}
	}
	*next = (char *)0;
	if(nwords != (int)nfonts)
		printf("%s: warning; only got %d of %d font names\n",Progname,nwords,(int)nfonts);
	return(ret);
}


/* Read the special character strings, and set up the string table and
 * the index into it.
 */
get_funny(inptr,mybuf,funny_ind,funny_chars,lchname)
FILE *inptr;
char *mybuf;
short **funny_ind;
char **funny_chars;
int *lchname;
{
	char *fct;	/* funny char string table */
	short *fci; /* funny char index		   */
	int i = 0;
	int lastp = 0;
	char *str;

	/* allocate for 256 3-character strings (plus null) 			*/
	/* We should probably check for overflow, but I can't imagine a	*/
	/* character set with more than 256 special chars (FLW)			*/

	*funny_chars = fct = malloc((unsigned)768);
	*funny_ind = fci = (short *)malloc((unsigned)(257 * sizeof(short)));

	/* assume the strings start on a new line */
	fci[0] = (short)0;
	while((str = nextword(mybuf)) || fgets(mybuf,1024,inptr))
	{
		if(!str)
		{
			nextword("");
			str = nextword(mybuf);
			if(!str)
				continue;
		}
		(void)strcpy(fct + lastp,str);
		fci[i++] = (short)(lastp & SHORT);
		lastp += strlen(str) + 1;
		if(i > 256)
		{
			fprintf(stderr,"%s: too many special strings (> 256)\n",Progname);
			break;
		}
	}
	fci[i++] = (short)0;
	*lchname = lastp;
	return(i);
}

/* Write out the dev structure,the sizes table, and the funny char tables */
write_desc(fdout,dev,point_list,funny_ind,funny_chars)
int fdout;
struct dev *dev;
short *point_list,*funny_ind;
char *funny_chars;
{

	long l;

	/* Seek back to the beginning of the file */

	(void)lseek(fdout,0L,0);

	/* dev structure */
	if(write(fdout,(char *)dev,sizeof(struct dev)) != sizeof(struct dev))
	{
		fprintf(stderr,"%s: write dev struct to description file failed\n",Progname);
		exit(1);
	}

	/* point sizes table */
	if(write(fdout,(char *)point_list,(int)(dev->nsizes +1) * 2) != (int)(dev->nsizes + 1) * 2)
	{
		fprintf(stderr,"%s: write size list to description file failed\n",Progname);
		exit(1);
	}

	/* table of indexes into special char strings */
	if(write(fdout,(char *)funny_ind,(int)(dev->nchtab * 2)) != (int)(dev->nchtab * 2))
	{
		fprintf(stderr,"%s: write index list to description file failed\n",Progname);
		exit(1);
	}

	/* special char strings */
	if(write(fdout,funny_chars,(int)(dev->lchname)) != (int)(dev->lchname))
	{
		fprintf(stderr,"%s: write funny char strings to description file failed\n",Progname);
		exit(1);
	}
	l = lseek(fdout,0L,1);
}
SHAR_EOF
if test 8441 -ne "`wc -c < 'makedesc.c'`"
then
	echo shar: "error transmitting 'makedesc.c'" '(should have been 8441 characters)'
fi
fi
echo shar: "extracting 'mkfont.c'" '(7751 characters)'
if test -f 'mkfont.c'
then
	echo shar: "will not over-write existing file 'mkfont.c'"
else
cat << \SHAR_EOF > 'mkfont.c'
static char *RCSid = "$Header: mkfont.c,v 1.1 87/10/23 19:08:10 sysad Exp $";

/*
 * $Log:	mkfont.c,v $
 * Revision 1.1  87/10/23  19:08:10  sysad
 * Initial revision
 * 
 * 
 */

#include <stdio.h>
#include <sys/file.h>
#include "font.h"
#ifdef SYS5
#define	bzero(a,b)	memset(a,0,b)
#endif

#define NCHARMAX	256			/* max chars in font */
#define	NASC		96			/* number of printable ascii chars */
#define	BYTE		0xff		/* mask */
#define	SHORT		0xffff		/* mask */

extern char *malloc(),*savestr(),*nextword(),*fgets();
extern FILE *fopen();
extern char *Progname;
extern int compat;

/* Read the ascii font description files, and write the binary files. */
/*                                                                    */

do_font(fontname,funny_chars,funny_ind,nchtab,fdout)
char *fontname,*funny_chars;
short *funny_ind;
int nchtab,fdout;
{
	FILE *src;
	char mybuf[256];
	/* allocate them just once */
	static char *width,*kern,*code,*fontindex = (char *)0;
	
	struct Font font;
	char *word;
	int dest,spacewidth,nwfont,indx;

	/* The ascii source file, named by the font name. */
	if((src = fopen(fontname,"r")) == (FILE *)0)
	{
		fprintf(stderr,"%s: can't open font %s\n",Progname,fontname);
		exit(1);
	}

	/* create the binary font face file */
	sprintf(mybuf,"%s.out",fontname);
	if((dest = open(mybuf,O_CREAT | O_WRONLY,0644)) < 0)
	{
		fprintf(stderr,"%s: can't create font %s output file\n",Progname,mybuf);
		exit(1);
	}
	fontindex = width = kern = code = (char *)0;

	spacewidth = 0;
	font.ligfont = (char)0;

    /* Build the font structure.                                      */

	while(fgets(mybuf,256,src))
	{
		word = nextword("");	/* reset to beginning of line */
		word = nextword(mybuf);
		if(!word || !*word || (*word == '#'))
			continue;
		if(strcmp(word,"charset") == 0)
			break;
		if(strcmp(word,"name") == 0)
			strncpy(font.namefont,nextword(mybuf),10);
		else if(strcmp(word,"internalname") == 0)
			strncpy(font.intname,nextword(mybuf),10);
		else if(strcmp(word,"spacewidth") == 0)
			spacewidth = atoi(nextword(mybuf)) & BYTE;
		else if(strcmp(word,"special") == 0)
			font.specfont =  0x01;
		else if(strcmp(word,"ligatures") == 0)
		{
			while(word = nextword(mybuf))
			{
				if(*word == '0')
					break;
				else if(strcmp(word,"fi") == 0)
					font.ligfont |= LIG_FI;
				else if(strcmp(word,"fl") == 0)
					font.ligfont |= LIG_FL;
				else if(strcmp(word,"ff") == 0)
					font.ligfont |= LIG_FF;
				else if(strcmp(word,"ffi") == 0)
					font.ligfont |= LIG_FFI;
				else if(strcmp(word,"ffl") == 0)
					font.ligfont |= LIG_FFL;
			}
		}
	}

	/* The next 4 tables are allocated just once, big enough for any font,
	 * then re-used for each font face.
	 */

	if(fontindex == (char *)0)
	{
		fontindex = malloc((unsigned)(NASC + nchtab));
		if(fontindex == (char *)0)
		{
			fprintf(stderr,"%s: can't malloc font index table\n",Progname);
			exit(1);
		}
	}

	if(width == (char *)0)
	{
		width = malloc(NCHARMAX);
		if(width == (char *)0)
		{
			free(fontindex);
			fontindex = (char *)0;
			fprintf(stderr,"%s: can't malloc font widths table\n",Progname);
			exit(1);
		}
	}
	if(kern == (char *)0)
	{
		kern = malloc(NCHARMAX);
		if(kern == (char *)0)
		{
			free(width);
			free(fontindex);
			fontindex = (char *)0;
			width = (char *)0;
			fprintf(stderr,"%s: can't malloc font kern table\n",Progname);
			exit(1);
		}
	}

	if(code == (char *)0)
	{
		code = malloc(NCHARMAX);
		if(code == (char *)0)
		{
			free(width);
			free(kern);
			free(fontindex);
			fontindex = (char *)0;
			width = (char *)0;
			kern = (char *)0;
			fprintf(stderr,"%s: can't malloc font code table\n",Progname);
			exit(1);
		}
	}

	/* clear them */
	bzero(width,NCHARMAX);
	bzero(kern,NCHARMAX);
	bzero(code,NCHARMAX);
	bzero(fontindex,NASC + nchtab);

	/* first width entry is width of space if non-zero */
	width[0] = (char)(spacewidth & BYTE);
	kern[0] = '\0';
	code[0] = '\0';

	nwfont = 1;
	
	/* decode the character set info and stuff the width, kern, code
	 * tables, building the font index table as we go
	 */
	while(fgets(mybuf,256,src))
	{
		nextword("");	/* reset to beginning of line */
		word = nextword(mybuf);
		if(!word || !*word)
			continue;
		if(strlen(word) == 1)
			indx = (*word & BYTE) - 32;		/* printable ascii */
		else
			indx = spcl(word,funny_chars,funny_ind,nchtab); /* troff special chars */
		if(indx < 0)
		{
			fprintf(stderr,"%s: special string \"%s\" is not defined in desc\n",Progname,word);
			fprintf(stderr,"...skipping\n");
			continue;
		}

		/* check for repeat characters ( " in width column) */
		word = nextword(mybuf);

		if(*word == '"')
		{
			/* It appears that att's "makefont" doesn't make a new
			 * width entry for dups--it just reuses the earlier one.
			 * It would be much easier for "rdfont" to decode these
			 * things if we just made a duplicate entry, but for
			 * compatibility with "makefont" (as determined by examination
			 * of compiled fonts delivered to us)...
			 */
			if(!compat)
			{
				/* make a separate width entry for each duplicate */
				width[nwfont] = width[nwfont - 1];
				kern[nwfont] = kern[nwfont - 1];
				code[nwfont] = code[nwfont - 1];
				fontindex[indx] = (char)(nwfont & BYTE);
				nwfont++;
			}
			fontindex[indx] = (char)((nwfont - 1) & BYTE);
			continue;
		}
		fontindex[indx] = (char)(nwfont & BYTE);
		width[nwfont] = (char)(atoi(word) & BYTE);
		word = nextword(mybuf);
		kern[nwfont] = (char)(atoi(word) & BYTE);
		word = nextword(mybuf);
		code[nwfont++] = (char)(atoo(word) & BYTE);
	}

	fclose(src);
	font.nwfont = (short)(nwfont & BYTE);
	printf("%s: nwfont = %d\n",fontname,nwfont);



	/* write the tables, first to the description file, then to the
	 * individual font file.
	 */
	if(write(fdout,(char *)&font,sizeof(struct Font)) != sizeof(struct Font))
	{
		fprintf(stderr,"%s: write font struct to description file failed\n",Progname);
		exit(1);
	}
	if(write(dest,(char *)&font,sizeof(struct Font)) != sizeof(struct Font))
	{
		fprintf(stderr,"%s: write font struct to font output file failed\n",Progname);
		exit(1);
	}
	if(write(fdout,width,nwfont) != nwfont)
	{
		fprintf(stderr,"%s: write width table to description file failed\n",Progname);
		exit(1);
	}
	if(write(dest,width,nwfont) != nwfont)
	{
		fprintf(stderr,"%s: write width table to font output file failed\n",Progname);
		exit(1);
	}
	if(write(fdout,kern,nwfont) != nwfont)
	{
		fprintf(stderr,"%s: write kern table to description file failed\n",Progname);
		exit(1);
	}
	if(write(dest,kern,nwfont) != nwfont)
	{
		fprintf(stderr,"%s: write kern table to font output file failed\n",Progname);
		exit(1);
	}
	if(write(fdout,code,nwfont) != nwfont)
	{
		fprintf(stderr,"%s: write code table to description file failed\n",Progname);
		exit(1);
	}
	if(write(dest,code,nwfont) != nwfont)
	{
		fprintf(stderr,"%s: write code table to font output file failed\n",Progname);
		exit(1);
	}
	if(write(fdout,fontindex,nchtab + NASC) != nchtab + NASC)
	{
		fprintf(stderr,"%s: write font index table to description file failed\n",Progname);
		exit(1);
	}
	if(write(dest,fontindex,nchtab + NASC) != nchtab + NASC)
	{
		fprintf(stderr,"%s: write font index table to font output file failed\n",Progname);
		exit(1);
	}
	close(dest);	/* done with this font file */
	return(nwfont);	/* the return is extraneous here */
}

/* Find the font index of special character strings */

spcl(word,funny_chars,funny_ind,nchtab)
char *word,*funny_chars;
short *funny_ind;
int nchtab;
{
	int i;

	for(i = 0; i < nchtab; ++i)
	{	
		if(strcmp(word,funny_chars + (int)(funny_ind[i] & SHORT)) == 0)
			return(i + NASC);
	}
	return(-1);
}

/* convert an octal string representation to an int */

atoo(str)
char *str;
{
	int i;
	/* cheat */
	sscanf(str,"%o",&i);
	return(i);
}
SHAR_EOF
if test 7751 -ne "`wc -c < 'mkfont.c'`"
then
	echo shar: "error transmitting 'mkfont.c'" '(should have been 7751 characters)'
fi
fi
echo shar: "extracting 'mkfont.p'" '(2115 characters)'
if test -f 'mkfont.p'
then
	echo shar: "will not over-write existing file 'mkfont.p'"
else
cat << \SHAR_EOF > 'mkfont.p'
.TH MKFONT  1-P
.SH NAME
mkfont,rdfont \- create/read ditroff font files
.SH SYNOPSIS
.br
.B mkfont
.I \-c
[DESC]
.br
.B rdfont
[DESC.out]
.SH DESCRIPTION
.PP
.I Mkfont
reads ascii format font description files and creates binary format
files usable by
.I ditroff.
The format of the ascii files may be guessed reasonably closely by
reading \fCfont\fP(5) and \fCtroff\fP(5).
Alternatively, if you have existing fonts, you may run
.I rdfont
on them to produce their ascii equivalents (which you may then
modify, if you like, and re-compile with \fImkfont\fP).
The produced binary files are named by the input files suffixed with
.I .out.
.I Ditroff
expects the font description file to be named
.I DESC.out,
so \fImkfont\fP expects an ascii file named \fIDESC\fP in the
current directory if no arguments are given; otherwise, the name
of the description file must be given as argument.
The \fI-c\fP flag causes the binary files produced to be more
nearly compatible with those produced by the ATT \fImakedev\fP
program (\fImakedev\fP does not make duplicate width table entries
in the binary file for characters whose width is given by double
quotes in the ascii file; \fImkfont\fP does, unless \fI-c\fP is
given).
.PP
.I Rdfont
examines a binary format font set and produces a set of ascii files
which describe them.  The ascii files are in a form suitable for
re-compiling with \fImkfont\fP.
If no arguments are given, a description file named \fIDESC.out\fP
is expected.  An alternate description file name may be given as
argument.
The produced files are named by replacing the \fI.out\fP extensions
of the input files by \fI.new\fP, to avoid overwriting existing
description files.  If these files are to be re-compiled, the
extensions should be removed.

John Antypas -- Soft21 --21st Century Software:

UUCP: {buita|garp|killer|pyramid|reed|sdeggo|ucsd!ucrmath|uport}!soft21!jantypas
Internet: jantypas%soft21.uucp@{garp.MIT.EDU, ucsd.EDU} BITNET: jantypas@ucrvms