[comp.sources.misc] v02i084: mkfont/rdfont--compile and uncompile ditroff fonts

sysad@tikal.teltone.com (Duane Hesser) (04/03/88)

Submitted-By: "Duane Hesser" <sysad@tikal.teltone.com>

Archive-Name: mkfont


comp.sources.misc: Volume 2, Issue 84
Submitted-By: "Duane Hesser" <sysad@tikal.teltone.com>
Archive-Name: mkfont

There are two complementary programs enclosed here.
'mkfont' duplicates the function of "makedev" to create binary
font files, readable by ditroff, from ascii descriptions.
'rdfont' reverses the process, generating ascii descriptions
form existing binary font files.  It's all in the README and
man page.
------ cut here --------
#!/bin/sh
echo 'Start of MKFONT/RDFONT, part 01 of 01:'
echo 'x - README'
sed 's/^X//' > README << '/'
XMkfont duplicates  the actions  (more or  less) of  the ATT  "makedev"
Xprogram,  tp  produce  binary  font  files  for  ditroff,  from  ascii
Xdescriptions for the fonts.   Rdfont will read  the binary font  files
Xand produce an  ascii equivalent  (which may then  be re-compiled)  by
Xmkfont.
X
XThese programs were written on a Pyramid 90x in the ucb universe,  and
Xshould compile fairly  readily in  any BSD  environment; they've  been
Xcompiled in the att  environment, and on a  Vax 750 under 4.3BSD  (but
Xnot really tested  in those environments).   Check the  CFLAGS in  the
XMakefile for SYS5.  There is also a cakefile, for those so inclined.
XFor some systems, you may have to deal with the 3-argument open() calls.
X
XThe programs were written  after Pyramid supplied  ditroff with an  OS
Xupgrade,  but  didn't  supply  makedev.    "makedev"  has  since  been
Xsupplied, and mkfont checked against it.
X
XMkfont has  been used  to compile  Postscript fonts  from  description
Xfiles posted to USENET in May of 1986 by Stephen Frede at U of NSW  in
XSydney, Australia--you  should  be able  to  find them  in  a  sources
Xarchive somewhere, if you need them.
X
XI am the author of  these programs, and I  submit them for public  use
Xwithout restriction.
X
XCAVEATS
XThe binary font  files produced  by mkfont will  differ slightly  from
Xthose produced by makedev if there are duplicate entries in the  width
Xtable, unless you use the '-c' option to mkfont (see the man page  for
Xa little more info).
X
XIf you use  these to produce  Postscript font files,  be aware of  the
Xstandard ditroff limit of 10 fonts (enforced by core dump).  I believe
Xpatches to  fix  this  and  other bugs  are  in  the  USENET  archives
Xsomewhere.   For those  of you  with  Pyramids, RTOC  can send  you  a
Xversion which will  handle up to  25 files; otherwise  you'll have  to
Xpick and  chose.    NOTE:  mkfont will  compile  them  fine  (as  will
Xmakedev), but ditroff won't like 'em.
X
X
XDuane H. Hesser
Xdhh@teltone.com
/
echo 'x - Makefile'
sed 's/^X//' > Makefile << '/'
X#for S5 uncomment next line
X# CFLAGS=-DSYS5
X
XRDSRC=	readdesc.c rdfont.c strsave.c
XRDOBJ=	readdesc.o rdfont.o strsave.o
XMKSRC=	makedesc.c mkfont.c nextword.c strsave.c
XMKOBJ=	makedesc.o mkfont.o nextword.o strsave.o
X
X
Xall: mkfont rdfont
X
Xmkfont:	${MKOBJ}
X	cc -o mkfont -O ${MKOBJ}
X
Xrdfont:	${RDOBJ}
X	cc -o rdfont -O ${RDOBJ}
X
Xrdfont.o:	rdfont.c font.h
Xreaddesc.o:	readdesc.c  dev.h
X
Xmkfont.o:	mkfont.c font.h
Xmakedesc.o:	makedesc.c  dev.h
X
Xclean:
X	rm -f *.o mkfont rdfont
X
Xlint:
X	lint -phbvac dev.h font.h ${MKSRC} > lint.mkfont
X	lint -phbvac dev.h font.h ${RDSRC} > lint.rdfont
/
echo 'x - Cakefile'
sed 's/^X//' > Cakefile << '/'
X#include "C"
X#include "System"
/
echo 'x - Conf'
sed 's/^X//' > Conf << '/'
Xmkfont makedesc mkfont strsave nextword
Xrdfont readdesc rdfont strsave nextword
/
echo 'x - mkfont.p'
sed 's/^X//' > mkfont.p << '/'
X.TH MKFONT  1-P
X.SH NAME
Xmkfont,rdfont \- create/read ditroff font files
X.SH SYNOPSIS
X.br
X.B mkfont
X.I \-c
X[DESC]
X.br
X.B rdfont
X[DESC.out]
X.SH DESCRIPTION
X.PP
X.I Mkfont
Xreads ascii format font description files and creates binary format
Xfiles usable by
X.I ditroff.
XThe format of the ascii files may be guessed reasonably closely by
Xreading \fCfont\fP(5) and \fCtroff\fP(5).
XAlternatively, if you have existing fonts, you may run
X.I rdfont
Xon them to produce their ascii equivalents (which you may then
Xmodify, if you like, and re-compile with \fImkfont\fP).
XThe produced binary files are named by the input files suffixed with
X.I .out.
X.I Ditroff
Xexpects the font description file to be named
X.I DESC.out,
Xso \fImkfont\fP expects an ascii file named \fIDESC\fP in the
Xcurrent directory if no arguments are given; otherwise, the name
Xof the description file must be given as argument.
XThe \fI-c\fP flag causes the binary files produced to be more
Xnearly compatible with those produced by the ATT \fImakedev\fP
Xprogram (\fImakedev\fP does not make duplicate width table entries
Xin the binary file for characters whose width is given by double
Xquotes in the ascii file; \fImkfont\fP does, unless \fI-c\fP is
Xgiven).
X.PP
X.I Rdfont
Xexamines a binary format font set and produces a set of ascii files
Xwhich describe them.  The ascii files are in a form suitable for
Xre-compiling with \fImkfont\fP.
XIf no arguments are given, a description file named \fIDESC.out\fP
Xis expected.  An alternate description file name may be given as
Xargument.
XThe produced files are named by replacing the \fI.out\fP extensions
Xof the input files by \fI.new\fP, to avoid overwriting existing
Xdescription files.  If these files are to be re-compiled, the
Xextensions should be removed.
X.
X.SH DIAGNOSTICS
X.PP
X.SH BUGS
X.PP
X.I Mkfont
Xdoes not do much checking on the validity of the font, although it
Xcould do so.
X.I Rdfont
Xwrites a few information items to the ascii file as comment lines.
XThat's not a bug, but it does make comparison of originals and
Xduplicates a bit (not muuch) harder.
X.SH AUTHOR
X.br
XDuane H. Hesser
X.br
XTeltone Corporation
/
echo 'x - dev.h'
sed 's/^X//' > dev.h << '/'
X/*
X * $Header: dev.h,v 1.1 87/10/23 19:08:07 sysad Exp $
X */
X
X/*
X * $Log:	dev.h,v $
X * Revision 1.1  87/10/23  19:08:07  sysad
X * Initial revision
X * 
X * 
X */
X
X struct dev {
X	unsigned short filesize;
X	short res;
X	short hor;
X	short vert;
X	short unitwidth;
X	short nfonts;
X	short nsizes;
X	short sizescale;
X	short paperwidth;
X	short paperlength;
X	short nchtab;
X	short lchname;
X	short biggestfont;
X	short spare;
X};
/
echo 'x - font.h'
sed 's/^X//' > font.h << '/'
X/*
X * $Header: font.h,v 1.1 87/10/23 19:08:08 sysad Exp $
X */
X
X/*
X * $Log:	font.h,v $
X * Revision 1.1  87/10/23  19:08:08  sysad
X * Initial revision
X * 
X * 
X */
X
Xstruct Font {
X	char nwfont;
X	char specfont;
X	char ligfont;
X	char pad;
X	char namefont[10];
X	char intname[10];
X};
X
X#define	LIG_FF	01
X#define	LIG_FI	02
X#define	LIG_FL	04
X#define	LIG_FFI	010
X#define	LIG_FFL	020
/
echo 'x - makedesc.c'
sed 's/^X//' > makedesc.c << '/'
Xstatic char *RCSid = "$Header: makedesc.c,v 1.1 87/10/23 19:08:09 sysad Exp $";
X
X/* Read an ascii description of a ditroff font and create the         */
X/* corresponding binary font files                                    */
X
X
X/*
X * $Log:	makedesc.c,v $
X * Revision 1.1  87/10/23  19:08:09  sysad
X * Initial revision
X * 
X * 
X */
X
X#include <stdio.h>
X#include <sys/file.h>
X#include "dev.h"
X
X#define	SHORT	0xffff
X#define	MAXP	128		/* allocate space for point sizes in MAXP chunks */
Xint compat = 0;		/* compatibility with att "makedev"; duplicate "width"
X					 * entries are re-used if this is non-zero.
X					 */
Xchar *Progname;
Xstruct dev dev;
Xextern char *malloc(),*nextword(),*savestr();
Xextern char **font_names(),*fgets();
Xextern FILE *fopen();
Xextern short *p_sizes();
X
Xmain(argc,argv)
Xint argc;
Xchar **argv;
X{
X	FILE *inptr;
X	int fdout,nchtab,lchname,i,fsize,biggestfont;
X	long fontf_start;
X	short *point_list,*funny_ind;
X	char *funny_chars;
X	char **font_list;
X	char mybuf[1024];
X	char *str,*descfile;
X
X	Progname = argv[0];
X	++argv; --argc;
X
X	if(strcmp(*argv,"-c") == 0)
X	{
X		++compat;
X		++argv;
X		--argc;
X	}
X	if(argc == 0)
X	{
X		descfile = "DESC";
X	}
X	else if(argc == 1)
X	{
X		descfile = argv[0];
X	}
X	else
X	{
X		fprintf(stderr,"usage: %s [-c] [descfile]\n",Progname);
X		exit(1);
X	}
X
X	if((inptr = fopen(descfile,"r")) == (FILE *)0)
X	{
X		fprintf(stderr,"%s: can't open %s\n",Progname,descfile);
X		exit(2);
X	}
X	sprintf(mybuf,"%s.out",descfile);
X	if((fdout = open(mybuf,O_CREAT | O_WRONLY,0644)) < 0)
X	{
X		fprintf(stderr,"%s: can't create %s\n",Progname,mybuf);
X		exit(2);
X	}
X	dev.filesize = (short)0;
X	dev.sizescale = (short)1;
X	biggestfont = 0;
X	dev.spare = (short)0;
X	/* Build the dev structure first */
X	while(fgets(mybuf,1024,inptr))
X	{
Xstart:	/* we come back here if we read ahead in a font_names() */
X		if(!*mybuf || (*mybuf == '#'))
X			continue;
X		nextword("");	/* reset to beginning of line */
X		/* printf("line = %s\n",mybuf); */
X		str = nextword(mybuf);
X		if(strcmp(str,"charset") == 0)
X			break;
X		if(strcmp(str,"res") == 0)
X			dev.res = (short)atoi(nextword(mybuf));
X		else if(strcmp(str,"hor") == 0)
X			dev.hor = (short)atoi(nextword(mybuf));
X		else if(strcmp(str,"vert") == 0)
X			dev.vert = (short)atoi(nextword(mybuf));
X		else if(strcmp(str,"unitwidth") == 0)
X			dev.unitwidth = (short)atoi(nextword(mybuf));
X		else if(strcmp(str,"sizescale") == 0)
X			dev.sizescale = (short)atoi(nextword(mybuf));
X		else if(strcmp(str,"paperwidth") == 0)
X			dev.paperwidth = (short)atoi(nextword(mybuf));
X		else if(strcmp(str,"paperlength") == 0)
X			dev.paperlength = (short)atoi(nextword(mybuf));
X		else if(strcmp(str,"biggestfont") == 0)
X		{
X			biggestfont = atoi(nextword(mybuf));
X			dev.biggestfont = (short)biggestfont;
X		}
X		else if(strcmp(str,"sizes") == 0)
X		{
X			/* accumulate the list of legal point sizes */
X			point_list = p_sizes(inptr,mybuf,&dev);
X		}
X		else if(strcmp(str,"fonts") == 0)
X		{
X			dev.nfonts = (short)atoi(nextword(mybuf));
X			font_list = font_names(inptr,mybuf,dev.nfonts);
X			goto start;
X		}
X	}
X	nextword("");
X	/* Next comes the funny index table and the character strings; read
X	 * the description and stuff the information into the binary format 
X	 * tables.
X	 */
X	if(fgets(mybuf,1024,inptr) == (char *)0)
X	{
X		fprintf(stderr,"%s: no funny char strings table\n",Progname);
X		exit(1);
X	}
X	nchtab = get_funny(inptr,mybuf,&funny_ind,&funny_chars,&lchname);
X	dev.nchtab = (short)nchtab;
X	dev.lchname = (short)lchname;
X
X	/* We don't have enough information yet to write the dev structure
X	 * (don't know how many fonts, or their names...).  We do know how
X	 * big it is, and how long the description tables are, so we seek
X	 * past all that stuff andd write the font descriptions first.
X	 * Later, we'll go back and write the stuff we skipped over.
X	 */
X	fontf_start = (long)(sizeof(dev) + ((dev.nsizes +1) * sizeof(short))
X					+ (nchtab * sizeof(short)) + lchname);
X	(void)lseek(fdout,fontf_start,0);
X
X	/* Read the font files, and write the binary equivalents */
X	for(i = 0; i < (int)dev.nfonts; ++i)
X	{
X		fsize = do_font(font_list[i],funny_chars,funny_ind,nchtab,fdout);
X		/* keep track of the biggest font */
X		if(fsize > biggestfont)
X			biggestfont = fsize;
X	}
X	dev.biggestfont = (short)(biggestfont & SHORT);
X	dev.filesize = (unsigned short)(lseek(fdout,0L,2) - sizeof(dev));
X	write_desc(fdout,&dev,point_list,funny_ind,funny_chars);
X	exit(0);
X}
X
X/* Read the point sizes list */
X
Xshort *
Xp_sizes(inptr,buf,dev)
XFILE *inptr;
Xchar *buf;
Xstruct dev *dev;
X{
X	short *pl,*ret;
X	char *word,*realloc();
X	int nwords = 0;
X	int n;
X
X	/* allow for MAXP point sizes; we have to reallocate if we exceed that */
X	ret = pl = (short *)malloc((unsigned)(MAXP * sizeof(short)));
X	if(!pl)
X	{
X		fprintf(stderr,"can't malloc space for psizes\n",Progname);
X		exit(1);
X	}
X	n = 1;
X	while((word = nextword(buf)) || fgets(buf,1024,inptr))
X	{
X		if(!word)
X		{
X			nextword("");
X			word = nextword(buf);
X		}
X		if(!word)	/* ran out of words this line, had to fgets more */
X		{
X			nextword("");
X			if(fgets(buf,1024,inptr))
X				word = nextword(buf);
X			else
X			{
X				*buf = '\0';
X				break;
X			}
X		}
X		nwords++;
X		if(nwords >= MAXP)
X		{
X			/* Oops! ran out os space; get more */
X			ret = (short *)realloc((char *)ret,(unsigned)(MAXP * ++n * sizeof(short)));
X			pl = &ret[nwords];	/* could have moved */
X		}
X		*pl = (short)atoi(word);
X		if(*pl == (short)0)
X			break;
X		++pl;
X	}
X	/* don't count the zero at the end */
X	--nwords;
X	dev->nsizes = (short)nwords;
X	return(ret);
X}
X
X/* Read and save the font names; return the list */
X
Xchar **
Xfont_names(inptr,buf,nfonts)
XFILE *inptr;
Xchar *buf;
Xshort nfonts;
X{
X	char **ret,**next;
X	char *word;
X	int nwords = 0;
X
X	ret = next = (char **)malloc((unsigned)((nfonts + 1) * sizeof(char *)));
X
X	while((word = nextword(buf)) || fgets(buf,1024,inptr))
X	{
X		if(!word)
X		{
X			nextword("");
X			word = nextword(buf);
X		}
X		*next++ = savestr(word);
X		if(++nwords >= (int)nfonts)
X		{
X			/* main() expects a new buffer */
X			fgets(buf,1024,inptr);
X			break;
X		}
X	}
X	*next = (char *)0;
X	if(nwords != (int)nfonts)
X		printf("%s: warning; only got %d of %d font names\n",Progname,nwords,(int)nfonts);
X	return(ret);
X}
X
X
X/* Read the special character strings, and set up the string table and
X * the index into it.
X */
Xget_funny(inptr,mybuf,funny_ind,funny_chars,lchname)
XFILE *inptr;
Xchar *mybuf;
Xshort **funny_ind;
Xchar **funny_chars;
Xint *lchname;
X{
X	char *fct;	/* funny char string table */
X	short *fci; /* funny char index		   */
X	int i = 0;
X	int lastp = 0;
X	char *str;
X
X	/* allocate for 256 3-character strings (plus null) 			*/
X	/* We should probably check for overflow, but I can't imagine a	*/
X	/* character set with more than 256 special chars (FLW)			*/
X
X	*funny_chars = fct = malloc((unsigned)768);
X	*funny_ind = fci = (short *)malloc((unsigned)(257 * sizeof(short)));
X
X	/* assume the strings start on a new line */
X	fci[0] = (short)0;
X	while((str = nextword(mybuf)) || fgets(mybuf,1024,inptr))
X	{
X		if(!str)
X		{
X			nextword("");
X			str = nextword(mybuf);
X			if(!str)
X				continue;
X		}
X		(void)strcpy(fct + lastp,str);
X		fci[i++] = (short)(lastp & SHORT);
X		lastp += strlen(str) + 1;
X		if(i > 256)
X		{
X			fprintf(stderr,"%s: too many special strings (> 256)\n",Progname);
X			break;
X		}
X	}
X	fci[i++] = (short)0;
X	*lchname = lastp;
X	return(i);
X}
X
X/* Write out the dev structure,the sizes table, and the funny char tables */
Xwrite_desc(fdout,dev,point_list,funny_ind,funny_chars)
Xint fdout;
Xstruct dev *dev;
Xshort *point_list,*funny_ind;
Xchar *funny_chars;
X{
X
X	long l;
X
X	/* Seek back to the beginning of the file */
X
X	(void)lseek(fdout,0L,0);
X
X	/* dev structure */
X	if(write(fdout,(char *)dev,sizeof(struct dev)) != sizeof(struct dev))
X	{
X		fprintf(stderr,"%s: write dev struct to description file failed\n",Progname);
X		exit(1);
X	}
X
X	/* point sizes table */
X	if(write(fdout,(char *)point_list,(int)(dev->nsizes +1) * 2) != (int)(dev->nsizes + 1) * 2)
X	{
X		fprintf(stderr,"%s: write size list to description file failed\n",Progname);
X		exit(1);
X	}
X
X	/* table of indexes into special char strings */
X	if(write(fdout,(char *)funny_ind,(int)(dev->nchtab * 2)) != (int)(dev->nchtab * 2))
X	{
X		fprintf(stderr,"%s: write index list to description file failed\n",Progname);
X		exit(1);
X	}
X
X	/* special char strings */
X	if(write(fdout,funny_chars,(int)(dev->lchname)) != (int)(dev->lchname))
X	{
X		fprintf(stderr,"%s: write funny char strings to description file failed\n",Progname);
X		exit(1);
X	}
X	l = lseek(fdout,0L,1);
X}
/
echo 'x - mkfont.c'
sed 's/^X//' > mkfont.c << '/'
Xstatic char *RCSid = "$Header: mkfont.c,v 1.1 87/10/23 19:08:10 sysad Exp $";
X
X/*
X * $Log:	mkfont.c,v $
X * Revision 1.1  87/10/23  19:08:10  sysad
X * Initial revision
X * 
X * 
X */
X
X#include <stdio.h>
X#include <sys/file.h>
X#include "font.h"
X#ifdef SYS5
X#define	bzero(a,b)	memset(a,0,b)
X#endif
X
X#define NCHARMAX	256			/* max chars in font */
X#define	NASC		96			/* number of printable ascii chars */
X#define	BYTE		0xff		/* mask */
X#define	SHORT		0xffff		/* mask */
X
Xextern char *malloc(),*savestr(),*nextword(),*fgets();
Xextern FILE *fopen();
Xextern char *Progname;
Xextern int compat;
X
X/* Read the ascii font description files, and write the binary files. */
X/*                                                                    */
X
Xdo_font(fontname,funny_chars,funny_ind,nchtab,fdout)
Xchar *fontname,*funny_chars;
Xshort *funny_ind;
Xint nchtab,fdout;
X{
X	FILE *src;
X	char mybuf[256];
X	/* allocate them just once */
X	static char *width,*kern,*code,*fontindex = (char *)0;
X	
X	struct Font font;
X	char *word;
X	int dest,spacewidth,nwfont,indx;
X
X	/* The ascii source file, named by the font name. */
X	if((src = fopen(fontname,"r")) == (FILE *)0)
X	{
X		fprintf(stderr,"%s: can't open font %s\n",Progname,fontname);
X		exit(1);
X	}
X
X	/* create the binary font face file */
X	sprintf(mybuf,"%s.out",fontname);
X	if((dest = open(mybuf,O_CREAT | O_WRONLY,0644)) < 0)
X	{
X		fprintf(stderr,"%s: can't create font %s output file\n",Progname,mybuf);
X		exit(1);
X	}
X	fontindex = width = kern = code = (char *)0;
X
X	spacewidth = 0;
X	font.ligfont = (char)0;
X
X    /* Build the font structure.                                      */
X
X	while(fgets(mybuf,256,src))
X	{
X		word = nextword("");	/* reset to beginning of line */
X		word = nextword(mybuf);
X		if(!word || !*word || (*word == '#'))
X			continue;
X		if(strcmp(word,"charset") == 0)
X			break;
X		if(strcmp(word,"name") == 0)
X			strncpy(font.namefont,nextword(mybuf),10);
X		else if(strcmp(word,"internalname") == 0)
X			strncpy(font.intname,nextword(mybuf),10);
X		else if(strcmp(word,"spacewidth") == 0)
X			spacewidth = atoi(nextword(mybuf)) & BYTE;
X		else if(strcmp(word,"special") == 0)
X			font.specfont =  0x01;
X		else if(strcmp(word,"ligatures") == 0)
X		{
X			while(word = nextword(mybuf))
X			{
X				if(*word == '0')
X					break;
X				else if(strcmp(word,"fi") == 0)
X					font.ligfont |= LIG_FI;
X				else if(strcmp(word,"fl") == 0)
X					font.ligfont |= LIG_FL;
X				else if(strcmp(word,"ff") == 0)
X					font.ligfont |= LIG_FF;
X				else if(strcmp(word,"ffi") == 0)
X					font.ligfont |= LIG_FFI;
X				else if(strcmp(word,"ffl") == 0)
X					font.ligfont |= LIG_FFL;
X			}
X		}
X	}
X
X	/* The next 4 tables are allocated just once, big enough for any font,
X	 * then re-used for each font face.
X	 */
X
X	if(fontindex == (char *)0)
X	{
X		fontindex = malloc((unsigned)(NASC + nchtab));
X		if(fontindex == (char *)0)
X		{
X			fprintf(stderr,"%s: can't malloc font index table\n",Progname);
X			exit(1);
X		}
X	}
X
X	if(width == (char *)0)
X	{
X		width = malloc(NCHARMAX);
X		if(width == (char *)0)
X		{
X			free(fontindex);
X			fontindex = (char *)0;
X			fprintf(stderr,"%s: can't malloc font widths table\n",Progname);
X			exit(1);
X		}
X	}
X	if(kern == (char *)0)
X	{
X		kern = malloc(NCHARMAX);
X		if(kern == (char *)0)
X		{
X			free(width);
X			free(fontindex);
X			fontindex = (char *)0;
X			width = (char *)0;
X			fprintf(stderr,"%s: can't malloc font kern table\n",Progname);
X			exit(1);
X		}
X	}
X
X	if(code == (char *)0)
X	{
X		code = malloc(NCHARMAX);
X		if(code == (char *)0)
X		{
X			free(width);
X			free(kern);
X			free(fontindex);
X			fontindex = (char *)0;
X			width = (char *)0;
X			kern = (char *)0;
X			fprintf(stderr,"%s: can't malloc font code table\n",Progname);
X			exit(1);
X		}
X	}
X
X	/* clear them */
X	bzero(width,NCHARMAX);
X	bzero(kern,NCHARMAX);
X	bzero(code,NCHARMAX);
X	bzero(fontindex,NASC + nchtab);
X
X	/* first width entry is width of space if non-zero */
X	width[0] = (char)(spacewidth & BYTE);
X	kern[0] = '\0';
X	code[0] = '\0';
X
X	nwfont = 1;
X	
X	/* decode the character set info and stuff the width, kern, code
X	 * tables, building the font index table as we go
X	 */
X	while(fgets(mybuf,256,src))
X	{
X		nextword("");	/* reset to beginning of line */
X		word = nextword(mybuf);
X		if(!word || !*word)
X			continue;
X		if(strlen(word) == 1)
X			indx = (*word & BYTE) - 32;		/* printable ascii */
X		else
X			indx = spcl(word,funny_chars,funny_ind,nchtab); /* troff special chars */
X		if(indx < 0)
X		{
X			fprintf(stderr,"%s: special string \"%s\" is not defined in desc\n",Progname,word);
X			fprintf(stderr,"...skipping\n");
X			continue;
X		}
X
X		/* check for repeat characters ( " in width column) */
X		word = nextword(mybuf);
X
X		if(*word == '"')
X		{
X			/* It appears that att's "makefont" doesn't make a new
X			 * width entry for dups--it just reuses the earlier one.
X			 * It would be much easier for "rdfont" to decode these
X			 * things if we just made a duplicate entry, but for
X			 * compatibility with "makefont" (as determined by examination
X			 * of compiled fonts delivered to us)...
X			 */
X			if(!compat)
X			{
X				/* make a separate width entry for each duplicate */
X				width[nwfont] = width[nwfont - 1];
X				kern[nwfont] = kern[nwfont - 1];
X				code[nwfont] = code[nwfont - 1];
X				fontindex[indx] = (char)(nwfont & BYTE);
X				nwfont++;
X			}
X			fontindex[indx] = (char)((nwfont - 1) & BYTE);
X			continue;
X		}
X		fontindex[indx] = (char)(nwfont & BYTE);
X		width[nwfont] = (char)(atoi(word) & BYTE);
X		word = nextword(mybuf);
X		kern[nwfont] = (char)(atoi(word) & BYTE);
X		word = nextword(mybuf);
X		code[nwfont++] = (char)(atoo(word) & BYTE);
X	}
X
X	fclose(src);
X	font.nwfont = (short)(nwfont & BYTE);
X	printf("%s: nwfont = %d\n",fontname,nwfont);
X
X
X
X	/* write the tables, first to the description file, then to the
X	 * individual font file.
X	 */
X	if(write(fdout,(char *)&font,sizeof(struct Font)) != sizeof(struct Font))
X	{
X		fprintf(stderr,"%s: write font struct to description file failed\n",Progname);
X		exit(1);
X	}
X	if(write(dest,(char *)&font,sizeof(struct Font)) != sizeof(struct Font))
X	{
X		fprintf(stderr,"%s: write font struct to font output file failed\n",Progname);
X		exit(1);
X	}
X	if(write(fdout,width,nwfont) != nwfont)
X	{
X		fprintf(stderr,"%s: write width table to description file failed\n",Progname);
X		exit(1);
X	}
X	if(write(dest,width,nwfont) != nwfont)
X	{
X		fprintf(stderr,"%s: write width table to font output file failed\n",Progname);
X		exit(1);
X	}
X	if(write(fdout,kern,nwfont) != nwfont)
X	{
X		fprintf(stderr,"%s: write kern table to description file failed\n",Progname);
X		exit(1);
X	}
X	if(write(dest,kern,nwfont) != nwfont)
X	{
X		fprintf(stderr,"%s: write kern table to font output file failed\n",Progname);
X		exit(1);
X	}
X	if(write(fdout,code,nwfont) != nwfont)
X	{
X		fprintf(stderr,"%s: write code table to description file failed\n",Progname);
X		exit(1);
X	}
X	if(write(dest,code,nwfont) != nwfont)
X	{
X		fprintf(stderr,"%s: write code table to font output file failed\n",Progname);
X		exit(1);
X	}
X	if(write(fdout,fontindex,nchtab + NASC) != nchtab + NASC)
X	{
X		fprintf(stderr,"%s: write font index table to description file failed\n",Progname);
X		exit(1);
X	}
X	if(write(dest,fontindex,nchtab + NASC) != nchtab + NASC)
X	{
X		fprintf(stderr,"%s: write font index table to font output file failed\n",Progname);
X		exit(1);
X	}
X	close(dest);	/* done with this font file */
X	return(nwfont);	/* the return is extraneous here */
X}
X
X/* Find the font index of special character strings */
X
Xspcl(word,funny_chars,funny_ind,nchtab)
Xchar *word,*funny_chars;
Xshort *funny_ind;
Xint nchtab;
X{
X	int i;
X
X	for(i = 0; i < nchtab; ++i)
X	{	
X		if(strcmp(word,funny_chars + (int)(funny_ind[i] & SHORT)) == 0)
X			return(i + NASC);
X	}
X	return(-1);
X}
X
X/* convert an octal string representation to an int */
X
Xatoo(str)
Xchar *str;
X{
X	int i;
X	/* cheat */
X	sscanf(str,"%o",&i);
X	return(i);
X}
/
echo 'x - rdfont.c'
sed 's/^X//' > rdfont.c << '/'
Xstatic char *RCSid = "$Header: rdfont.c,v 1.1 87/10/23 19:08:13 sysad Exp $";
X
X/*
X * $Log:	rdfont.c,v $
X * Revision 1.1  87/10/23  19:08:13  sysad
X * Initial revision
X * 
X * 
X */
X
X#include <stdio.h>
X#include "font.h"
X
X#ifdef SYS5
X#define	bzero(a,b)	memset(a,0,b)
X#endif
X
X#define	SHORT	0xffff		/* mask */
X#define	HISHORT	0xffff0000	/* mask */
X#define	BYTE	0xff		/* mask */
X#define NASC	96			/* number of printable ascii characters */
Xextern char *malloc(),*savestr(),*pr_font();
Xextern char *Progname;
Xextern int debugging;
X
Xchar *
X/* Read a binary font face file */
X
Xrdfont(fd,nspec,funny_tab,funny_index)
Xint fd,nspec;
Xchar *funny_tab;
Xshort *funny_index;
X{
X	char *widths;
X	char *kerning;
X	char *code;
X	char *font_ind;
X	char *fname;
X	struct Font font;
X	unsigned int nwidths;
X	int i;
X
X	/* get the font info from the description file */
X	if(read(fd,(char *)&font,sizeof(struct Font)) != sizeof(struct Font))
X	{
X		fprintf(stderr,"%s: can't read font info\n",Progname);
X		return((char *)0);
X	}
X
X	/* Allocate space for the tables */
X	nwidths = font.nwfont & BYTE;
X	widths = malloc(nwidths);
X	if(!widths)
X	{
X		fprintf(stderr,"%s: can't malloc widths\n",Progname);
X		return((char *)0);
X	}
X	kerning = malloc(nwidths);
X	if(!kerning)
X	{
X		fprintf(stderr,"%s: can't malloc kerning\n",Progname);
X		free(widths);
X		return((char *)0);
X	}
X	code = malloc(nwidths);
X	if(!code)
X	{
X		fprintf(stderr,"%s: can't malloc code\n",Progname);
X		free(widths);
X		free(kerning);
X		return((char *)0);
X	}
X
X	/* Read 'em in */
X	if((i = read(fd,widths,nwidths)) != nwidths)
X	{
X		fprintf(stderr,"%s: read %d of %d widths \n",i,nwidths,Progname);
X		free(widths);
X		free(kerning);
X		free(code);
X		return((char *)0);
X	}
X	if((i = read(fd,kerning,nwidths)) != nwidths)
X	{
X		fprintf(stderr,"%s: read %d of %d kernings\n",i,nwidths,Progname);
X		free(widths);
X		free(kerning);
X		free(code);
X		return((char *)0);
X	}
X	if((i = read(fd,code,nwidths)) != nwidths)
X	{
X		fprintf(stderr,"%s: read %d of %d codes\n",i,nwidths,Progname);
X		free(widths);
X		free(kerning);
X		free(code);
X		return((char *)0);
X	}
X	font_ind = malloc(NASC + nspec);
X	if(!font_ind)
X	{
X		fprintf(stderr,"%s: malloc font_ind failed\n",Progname);
X		free(widths);
X		free(kerning);
X		free(code);
X		return((char *)0);
X	}
X	if(read(fd,font_ind,NASC + nspec) != NASC + nspec)
X	{
X		fprintf(stderr,"%s: read %d of %d of index table\n",i,NASC + nspec,Progname);
X		free(font_ind);
X		free(widths);
X		free(kerning);
X		free(code);
X		return((char *)0);
X	}
X	/* Now we can print the font description files; pr_font() also saves
X	 * the font name for us, to return to main().
X	 */
X	fname = pr_font(&font,widths,kerning,code,font_ind,funny_tab,funny_index,nspec);
X	free(font_ind);
X	free(widths);
X	free(kerning);
X	free(code);
X	return(fname);
X}
X
X
X/* Prints tha ascii font description.  Saves the fontname, properly
X * null-terminated, and returns it to rdfont() for pass back to main().
X */
Xchar *
Xpr_font(font,widths,kerning,code,font_ind,funny_tab,funny_index,nspec)
Xstruct Font *font;
Xchar *widths,*kerning,*code,*font_ind,*funny_tab;
Xshort *funny_index;
Xint nspec;
X{
X	int f,i,j,k,f_ind;
X	char *funny_str;
X	int nwidths;
X	FILE *fontf;
X	char fontname[16];
X	char intname[16];
X	char *fname;
X	int rti[4][256];		/* for a "reverse index table" into the font index */
X
X	nwidths = (int)(font->nwfont & BYTE);
X
X	/* make sure we have null-terminated names */
X	strncpy(fontname,font->namefont,10);
X	strncpy(intname,font->intname,10);
X	fontname[10] = '\0';
X	intname[10] = '\0';
X
X	/* now save a copy of the processed fontname for return (never freed) */
X	fname = savestr(fontname);
X
X	/* In case there's an original file, avoid overwriting it */
X	strcat(fontname,".new");
X
X	if((fontf = fopen(fontname,"w")) == (FILE *)0)
X	{
X		fprintf(stderr,"%s: can't open font file %s for writing\n",Progname,fontname);
X		exit(1);
X	}
X	if(debugging)		/* if compiled for debugging */
X		printf("\n\n\n\nwriting %s (%s)\n",fname,intname);
X
X	/* print the header information, from the font structure */
X	/* nwfont is printed as a comment, for reference 		 */
X	fprintf(fontf,"#nwfont %d\n",nwidths);
X	fprintf(fontf,"name %s\n",fname);
X	fprintf(fontf,"internalname %s\n",intname);
X	if(font->specfont)
X		fprintf(fontf,"special\n");
X	if(font->ligfont)
X		pr_lig(fontf,(char)(font->ligfont & BYTE));
X
X	/* widths[0] is spacewidth (if non-zero); real stuff starts at 1 */
X	if(widths[0] & BYTE)
X		fprintf(fontf,"spacewidth %u\n",(int)(widths[0] & BYTE));
X
X	widths[0] = '\0';
X	fprintf(fontf,"charset\n");
X	if(debugging)
X		printf("font index table\n\n");
X
X	/* Build a "reverse index table" which permits us to find the character
X	 * which corresponds to a given width table entry.
X	 */
X	bzero(rti,sizeof(rti));
X	for(j = 1; j < nspec + NASC ; ++j)
X	{
X		i = (int)(font_ind[j] & BYTE);
X		if(i > nwidths)
X		{
X			fprintf(stderr,"%s: width table too small ? (%d; need %d)\n",
X					Progname,nwidths,i & BYTE);
X			continue;
X		}
X		/* If rti[i] is non-zero, we have two names for the same character,
X		 * and it's a pain.  This is a hack, and only allows for four names.
X		 * It would be unnecessary if "makefont" simply made a duplicate
X		 * width table entry for each duplicate.  It also assumes that
X		 * each of the indexes will be < 256.
X		 * Tack the new value into the next free byte of the int.
X		 */
X		if(i && rti[0][i])
X		{
X			for(k = 1; k < 4; ++k)
X			{
X				if(rti[k][i] == 0)
X				{
X					rti[k][i] = j;
X					break;
X				}
X			}
X			if(k == 4)
X			{
X				fprintf(stderr,"%s: too many duplicates, width index %d\n",Progname,i);
X				exit(1);
X			}
X		}
X		else
X			rti[0][i] = j;
X		if(debugging)
X		{
X			printf("%d\t%d\t",j,i);
X			if(j < NASC)
X				printf("\t\t\t%c\t%d  %d  %#o\n",j + 32,
X					(int)(widths[i] & BYTE),(int)(kerning[i] & BYTE),(int)(code[i] & BYTE));
X			else
X			{
X				f_ind = (int)(funny_index[j - NASC] & SHORT);
X				funny_str = funny_tab + (f_ind & SHORT);
X				if(!funny_str)
X					funny_str = "??";
X				printf("(f_ind=%d)\t%s\t%d\t%d\t%#o\n",f_ind,funny_str,
X					(int)(widths[i] & BYTE),(int)(kerning[i] & BYTE),(int)(code[i] & BYTE));
X			}
X		}
X	}
X
X	/* Now print the width table, starting at 1 (since width 0 is spacewidth) */
X	if(debugging)
X	{
X		printf("\n\nWidth table\n\n");
X		printf("POS\tWIDTH\t\tKERN\t\tCODE\n");
X	}
X	for(i = 1; i < nwidths; ++i)
X	{
X		/* position in the font index table tells us what character 
X		 * corresponds to this width table entry (if any).  Except we
X		 * have to handle the hack for duplicate names...
X		 */
X		for(k = 0; k < 4; ++k)
X		{
X			j = rti[k][i];
X			if(j == 0)
X			{
X				break;
X			}
X			f = (int)(font_ind[j] & BYTE);
X			if(f == 0)
X			{
X				continue;	/* not in this font */
X			}
X			if(f != i)
X			{
X				fprintf(stderr,"%s: reverse index table out of sync (%d != %d) at %d\n",Progname,f,i,j);
X				exit(1);
X			}
X			if(j < NASC)
X			{
X				if(debugging)
X					printf("\t\t\t%c\t%d  %d  %#o\n",j + 32,
X						(int)(widths[i] & BYTE),(int)(kerning[i] & BYTE),(int)(code[i] & BYTE));
X				if(k)
X					fprintf(fontf,"%c\t\"\n",j + 32);	/* duplicate */
X				else
X					fprintf(fontf,"%c\t%d\t%d\t%#o\n",j + 32,
X						(int)(widths[i] & BYTE),(int)(kerning[i] & BYTE),(int)(code[i] & BYTE));
X			}
X			else
X			{
X				f_ind = (int)(funny_index[j - NASC] & SHORT);
X				funny_str = funny_tab + (f_ind & SHORT);
X				if(!funny_str)
X					funny_str = "??";
X				if(debugging)
X					printf("(f_ind=%d)\t%s\t%d\t%d\t%#o\n",f_ind,funny_str,
X						(int)(widths[i] & BYTE),(int)(kerning[i] & BYTE),(int)(code[i] & BYTE));
X				if(k)
X					fprintf(fontf,"%s\t\"\n",funny_str);
X				else
X					fprintf(fontf,"%s\t%d  %d  %#o\n",funny_str,
X						(int)(widths[i] & BYTE),(int)(kerning[i] & BYTE),(int)(code[i] & BYTE));
X			}
X		}
X	}
X	fclose(fontf);
X	printf("%s.out --> %s\n",fname,fontname);
X	return(fname);
X}
X
Xpr_lig(fontf,ligatures)
XFILE *fontf;
Xchar ligatures;
X{
X	fprintf(fontf,"ligatures ");
X	if(ligatures & LIG_FF)
X		fprintf(fontf," ff");
X	if(ligatures & LIG_FI)
X		fprintf(fontf," fi");
X	if(ligatures & LIG_FL)
X		fprintf(fontf," fl");
X	if(ligatures & LIG_FFI)
X		fprintf(fontf," ffi");
X	if(ligatures & LIG_FFL)
X		fprintf(fontf," ffl");
X	fprintf(fontf," 0\n");
X}
X
X/* 'nuff said...  */
Xunion kludge {
X	int i;
X	char c[4];
X} kludge;
X
X/* add byte y to x in the lowest zero-valued byte, if any. */
X
Xaddbyte(x,y)
Xint x,y;
X{
X	int i;
X
X	kludge.i = x;
X	for(i = 3; i >= 0; --i)
X		if((kludge.c[i] & BYTE) == 0)
X		{
X			kludge.c[i] = y & BYTE;
X			return(kludge.i);
X		}
X	return(x);
X}
X
X/* shift bytes down in an int, zeroing high byte */
X
Xshiftdown(x)
Xint x;
X{
X	int i;
X
X	kludge.i = x;
X	for(i = 3; i > 0; --i)
X		kludge.c[i] = kludge.c[i - 1];
X	kludge.c[0] = '\0';
X	return(kludge.i);
X}
/
echo 'x - readdesc.c'
sed 's/^X//' > readdesc.c << '/'
Xstatic char *RCSid = "$Header: readdesc.c,v 1.1 87/10/23 19:08:14 sysad Exp $";
X
X/*
X * $Log:	readdesc.c,v $
X * Revision 1.1  87/10/23  19:08:14  sysad
X * Initial revision
X * 
X * 
X */
X
X/* Read a binary "ditroff" font file and write an ascii equivalent.   */
X/* The written file is in a form which may be re-compiled.            */
X/*                                                                    */
X
X#include <stdio.h>
X#include <sys/file.h>
X#include "dev.h"
X
X#ifdef SYS5
X#define	rindex		strrchr
X#endif
X
X#define	SHORT	0xffff
X
Xchar *Progname;
Xstruct dev dev;
Xextern char *malloc(),*rdfont(),*rindex();
X
X/* debugging is always compiled off; use adb to set or unset it	*/
Xint debugging = 0;		/* prints tables to stdout if set		*/
X
Xmain(argc,argv)
Xint argc;
Xchar **argv;
X{
X	int fd,devsize,pointsizes,indexsize,funnysize,i;
X	short *points,*char_ind;
X	char *funny_chars,*ptr;
X	char **font_list,**fl;
X	char descbuf[256];
X	FILE *descfile;
X	char *descfn;
X
X	Progname = argv[0];
X	if(argc > 2)
X	{
X		fprintf(stderr,"usage: %s [descfile]\n",Progname);
X		exit(1);
X	}
X	else if(argc == 2)
X		descfn = argv[1];
X	else
X		descfn = "DESC.out";
X
X	if((fd = open(descfn,0,0)) < 0)
X	{
X		fprintf(stderr,"%s: can't open %s\n",Progname,descfn);
X		exit(2);
X	}
X	/* copy the name, strip the ".out", and replace it with ".new
X	 * to get the name of the new ascii file.
X	 */
X	sprintf(descbuf,"%s",descfn);
X	ptr = rindex(descbuf + 4,'.');
X	if(ptr)
X		*ptr = '\0';
X	strcat(descbuf,".new");
X	if((descfile = fopen(descbuf,"w")) == (FILE *)0)
X	{
X		fprintf(stderr,"%s: can't open new description file %s for writing\n",
X				Progname,descbuf);
X		exit(1);
X	}
X
X	/* Get the dev structure from the description file */
X	devsize = read(fd,(char *)&dev,sizeof(dev));
X	if(devsize != sizeof(dev))
X	{
X		fprintf(stderr,"%s: should have been %u bytes\n",Progname,sizeof(dev));
X		exit(3);
X	}
X
X	/* Allocate space for the sizes array, then read it in */
X	points = (short *)malloc((unsigned)(2 * (dev.nsizes + 1)));
X	pointsizes = read(fd,(char *)points,2 *(dev.nsizes + 1));
X	pointsizes /= 2;
X	if(--pointsizes != dev.nsizes)
X	{
X		fprintf(stderr,"%s: got %d of %d sizes\n",Progname,pointsizes,dev.nsizes);
X		exit(3);
X	}
X
X	/* Now the funny char index table */
X	char_ind = (short *)malloc((unsigned)(dev.nchtab * 2));
X	funny_chars = malloc(dev.lchname);
X	indexsize = read(fd,(char *)char_ind,dev.nchtab * 2);
X	indexsize /= 2;
X	if(indexsize != dev.nchtab)
X	{
X		fprintf(stderr,"%s: got %d of %d index entries\n",Progname,indexsize,dev.nchtab);
X		exit(4);
X	}
X
X	/* Now the funny char strings themseleves */
X	funnysize = read(fd,funny_chars,dev.lchname);
X	if(funnysize != dev.lchname)
X	{
X		fprintf(stderr,"%s: got %d of %d funny chars\n",Progname,funnysize,dev.lchname);
X		exit(5);
X	}
X	
X    /* allocate array space to hold pointers to the font names, which */
X    /* we accumulate as we read the font descriptions in rdfont().    */
X
X	font_list = (char **)malloc((unsigned)(dev.nfonts * sizeof(char *)));
X	fl = font_list;
X
X    /* Now read the font descriptions, print the tables and grab the  */
X    /* names String space for the names is allocated by rdfont(), so  */
X    /* we don't have to worry about saving them here.                 */
X
X	for(i = 0; i < dev.nfonts; ++i)
X		*fl++= rdfont(fd,indexsize,funny_chars,char_ind);
X	*fl = (char *)0;
X	if(debugging)
X		printf("\n\n\n\nwriting %s\n",descbuf);
X
X	/* Now that we've read everything, we can print the ascii description
X	 * file; first the stuff from dev, then the funny char strings.
X	 */
X	pr_dev(descfile,&dev,points,font_list);
X	pr_funny(descfile,funny_chars,char_ind,indexsize);
X	
X	fl = font_list;
X	if(debugging)
X	{
X		/* read the individual files, to see if they match */
X		for(i = 0; i < dev.nfonts; ++i)
X		{
X			if(fd >= 0)
X				close(fd);
X			if(!*fl)
X			{
X				fprintf(stderr,"%s: font #%d--no name\n",Progname,i);
X				++fl;
X				continue;
X			}
X			sprintf(descbuf,"%s.out",*fl++);
X			fprintf(stderr,"checking %s\n",descbuf);
X			fd = open(descbuf,O_RDONLY,0);
X			if(fd < 0)
X				fprintf(stderr,"%s: can't open font file %s\n",Progname,*fl);
X			else
X				(void)rdfont(fd,indexsize,funny_chars,char_ind);
X		}
X	}
X	exit(0);
X}
X
X/* Print the "dev" structure to DESC.new, describing the general      */
X/* characteristics of the font style                                  */
X
Xpr_dev(descfile,dev,points,fontnames)
XFILE *descfile;
Xstruct dev *dev;
Xshort *points;
Xchar **fontnames;
X{
X	int npoints,i,j;
X
X	/* The first three are printed for reference only, as comments.
X	 * They won't be used by mkfont.
X	 */
X	fprintf(descfile,"#filesize %d\n",(int)(dev->filesize & SHORT));
X	fprintf(descfile,"#nchtab %d\n",(int)(dev->nchtab & SHORT));
X	fprintf(descfile,"#lchname %d\n",(int)(dev->lchname & SHORT));
X	fprintf(descfile,"fonts %d\t",(int)(dev->nfonts & SHORT));
X	pr_fonts(descfile,fontnames,(int)(dev->nfonts));
X	fprintf(descfile,"\nsizes\t");
X
X	npoints = (int)(dev->nsizes & SHORT);
X	for(i=0;i < npoints; )
X	{
X		for(j=0; (j < 15) && (i < npoints); ++j,++i)
X			fprintf(descfile,"%-4d",(int)(points[i] & SHORT));
X		fprintf(descfile,"\n\t\t");
X	}
X	fprintf(descfile," 0\n");
X	fprintf(descfile,"res %d\n",(int)(dev->res & SHORT));
X	fprintf(descfile,"hor %d\n",(int)(dev->hor & SHORT));
X	fprintf(descfile,"vert %d\n",(int)(dev->vert & SHORT));
X	fprintf(descfile,"unitwidth %d\n",(int)(dev->unitwidth & SHORT));
X	fprintf(descfile,"paperwidth %d\n",(int)(dev->paperwidth & SHORT));
X	fprintf(descfile,"paperlength %d\n",(int)(dev->paperlength & SHORT));
X	fprintf(descfile,"biggestfont %d\n",(int)(dev->biggestfont & SHORT));
X	fprintf(descfile,"sizescale %d\n",(int)(dev->sizescale & SHORT));
X}
X
X/* Print the character set to DESC.new                                */
X
Xpr_funny(descfile,str,ind,nstr)
XFILE *descfile;
Xchar *str;
Xshort *ind;
Xint nstr;
X{
X	int i,j,ent;
X	char *s;
X
X	fprintf(descfile,"charset\n");
X	if(debugging)
X		printf("\n\nFunny char table\n\nINDEX\tENT\tSTR\n");
X	for(i = 0; i < nstr; )
X	{
X		for(j = 0; (i < nstr) && (j < 15); ++i,++j)
X		{
X			ent = (int)(ind[i] & SHORT);
X			s = str+ent;
X			if(*s == '\0')
X				s = "??";
X			if(debugging)
X				printf("%d\t\t%d\t%s\n",i,ent,s);
X			/* The funny index table is null-terminated */
X			if((ent == 0) && (i != 0))
X			{
X				i = nstr;
X				break;
X			}
X			fprintf(descfile,"%4.4s",str+ent);
X		}
X		fprintf(descfile,"\n");
X	}
X}
X
X/* Print the names of the fonts to DESC.new.                          */
X
Xpr_fonts(descfile,names,nfonts)
XFILE *descfile;
Xchar **names;
Xint nfonts;
X{
X	int i;
X
X	/* assume they fit on one line */
X	if(!names)
X		return;
X	for(i = 0; i < nfonts; ++i)
X	{
X		if(names[i])
X			fprintf(descfile," %s",names[i]);
X		else
X			fprintf(descfile," ??");
X	}
X	fprintf(descfile,"\n");
X}
/
echo 'x - nextword.c'
sed 's/^X//' > nextword.c << '/'
Xstatic char *RCSid = "$Header: nextword.c,v 1.1 87/10/23 19:08:11 sysad Exp $";
X
X/*
X * $Log:	nextword.c,v $
X * Revision 1.1  87/10/23  19:08:11  sysad
X * Initial revision
X * 
X * 
X */
X
X#define	CNULL	(char *)0
X
X/*  nextword: return the next whitespace delimited word from the      */
X/*  string passed as argument.  The returned word is null- terminated */
X/*  and points to a static copy of the word.  Each time the routine   */
X/*  is called with a new string, the old string copy is freed, and a  */
X/*  static copy of the new string is made and the first word is       */
X/*  returned.  Subsequent calls with the same argument return         */
X/*  succeeding words, or null if no words remain.                     */
X/*                                                                    */
X
Xextern char *savestr();
X
X#include <ctype.h>
Xchar *
Xnextword(string)
Xchar *string;
X{
X	static char *ostring = CNULL;
X	static char *savedstr = CNULL;
X	static char *next = CNULL;
X	char *x,*start;
X
X	if((string == CNULL) || !*string)
X	{
X		/* no string or empty string */
X		if(savedstr)
X			free(savedstr);
X		savedstr = next = ostring = CNULL;
X		return(CNULL);
X	}
X
X	/* Have we seen this string before? */
X	if(string != ostring)
X	{
X		/* Nope; set up the copy and pointers */
X		ostring = string;
X		if(savedstr)
X			free(savedstr);
X		savedstr = savestr(string);
X		next = savedstr;
X	}
X	if(!next || !*next)
X		return(CNULL);
X
X	x = next;
X	/* strip off leading white space */
X	while(*x && (*x != '\n') && isspace(*x))
X		++x;
X	start = x; 					/* x is the start of the word */
X	while(*x && (*x != '\n') && !isspace(*x))
X		++x;
X	if(*x)
X	{
X		*x = '\0'; 						/* null terminate the word */
X		next = ++x;
X	}
X	else next = CNULL;		/* end of string, no more words */
X	if(*start != '\n' && *start != '\0')
X	{
X		/* printf("nw = %s\n",start); /**/
X		return(start);
X	}
X	else
X		return(CNULL);
X}
/
echo 'x - strsave.c'
sed 's/^X//' > strsave.c << '/'
Xstatic char *RCSid = "$Header: strsave.c,v 1.1 87/10/23 19:08:15 sysad Exp $";
X
X/*
X * $Log:	strsave.c,v $
X * Revision 1.1  87/10/23  19:08:15  sysad
X * Initial revision
X * 
X * 
X */
X
X/*                                                                    */
X/* save a copy of the string 'string' some place.                     */
X/*                                                                    */
X
X#define	NULL	(char *)0
X#define NOWORD	"(null)"
Xchar *TOOMUCH = "savestr; too much space allocated\n";
X
Xchar *
Xsavestr(str)
Xchar *str;
X{
X	char *place,*save,*calloc();
X	char *tmp;
X	int i,j;
X
X	if( (i = strlen(str)) <= 0 )
X	{
X		save = "garbage";
X		i = 7;
X	}
X	else save = str;
X	if((place = calloc(1,i+1)) == NULL ) 
X	{
X		/* dont' want or need stdio */
X		write(2,TOOMUCH,sizeof(TOOMUCH));
X		exit(1);
X	}
X	tmp = place;
X	i++;	/* room for the null byte */
X	j = 0;
X	while ( (j++ < i) &&  *save )
X		 *tmp++ = *save++;
X	*tmp = 0;
X	return(place);
X}
/
echo 'Part 01 of MKFONT/RDFONT complete.'
exit
_______

Duane