V8/usr/src/cmd/troff/devaps/makeaps.c

Compare this file to the similar file:
Show the results in this format:

/*
  makedev:
	read text info about a particular device
	(e.g., cat, 202, aps5) from file, convert
	it into internal (binary) form suitable for
	fast reading by troff initialization (ptinit()).

	Usage:

	makedev DESC [ F ... ]
		uses DESC to create a description file
		using the information therein.
		It creates the file DESC.out.

	makedev F ...
		makes the font tables for fonts F only,
		creates files F.out.

	DESC.out contains:
	dev structure with fundamental sizes
	list of sizes (nsizes+1) terminated by 0, as short's
	indices of char names (nchtab * sizeof(short))
	char names as hy\0em\0... (lchname)
	nfonts occurrences of
		widths (nwidth)
		kerning (nwidth) [ascender+descender only so far]
		codes (nwidth) to drive actual typesetter
		fitab (nchtab+128-32)
	each of these is an array of char.

	dev.filesize contains the number of bytes
	in the file, excluding the dev part itself.

	F.out contains the font header, width, kern, codes, and fitab.
	Width, kern and codes are parallel arrays.
	(Which suggests that they ought to be together?)
	Later, we might allow for codes which are actually
	sequences of formatting info so characters can be drawn.
*/

#include	"stdio.h"
#include	"dev.h"

#define	BMASK	0377

#define	SLANT_BIT	1					/* slant flag is bit 0 */
#define	FONT_BIT	2					/* font flag is bit 1 */
#define	RANGE_BIT	4					/* range flag is bit 2 */

#define	SLANT_VAL	3					/* slant angle starts in bit 3 */
#define	RANGE_VAL	5					/* max range starts in bit 5 */

#define	skipline(f)	while(getc(f) != '\n')

struct	dev	dev;
struct	font	font;

#define	NSIZE	100	/* maximum number of sizes */
short	size[NSIZE];
#define	NCH	256	/* max number of characters with funny names */
char	chname[5*NCH];	/* character names, including \0 for each */
short	chtab[NCH];	/* index of character in chname */

#define	NFITAB	(NCH + 128-32)	/* includes ascii chars, but not non-graphics */
char	fitab[NFITAB];	/* font index table: position of char i on this font. */
			/* zero if not there */

#define	FSIZE	200	/* size of a physical font (e.g., 102 for cat) */
char	width[FSIZE];	/* width table for a physical font */
char	kern[FSIZE];	/* ascender+descender info */
char	code[FSIZE];	/* actual device codes for a physical font */
char	alt_code[FSIZE];				/* code for alternate font */
int		alt_font[FSIZE];				/* alternate font to use */

int		dbg = 0;						/* debug flag */


#define	NFONT	10	/* max number of default fonts */
char	fname[NFONT][10];	/* temp space to hold default font names */

int	fflag	= 0;	/* on if font table to be written */
int	fdout;	/* output file descriptor */
char	*fout	= "DESC.out";

main(argc, argv)
char *argv[];
{
	FILE *fin;
	char cmd[100], *p;
	int i, totfont, v;

	if ((fin = fopen("DESC", "r")) == NULL) {
		fprintf(stderr, "makedev: can't open %s\n", argv[1]);
		exit(1);
	}
	while (fscanf(fin, "%s", cmd) != EOF) {
		if (cmd[0] == '#')	/* comment */
			skipline(fin);
		else if (strcmp(cmd, "debug") == 0)  
			dbg++;
		else if (strcmp(cmd, "res") == 0) {
			fscanf(fin, "%hd", &dev.res);
		} else if (strcmp(cmd, "hor") == 0) {
			fscanf(fin, "%hd", &dev.hor);
		} else if (strcmp(cmd, "vert") == 0) {
			fscanf(fin, "%hd", &dev.vert);
		} else if (strcmp(cmd, "unitwidth") == 0) {
			fscanf(fin, "%hd", &dev.unitwidth);
		} else if (strcmp(cmd, "sizescale") == 0) {
			fscanf(fin, "%hd", &dev.sizescale);
		} else if (strcmp(cmd, "paperwidth") == 0) {
			fscanf(fin, "%hd", &dev.paperwidth);
		} else if (strcmp(cmd, "paperlength") == 0) {
			fscanf(fin, "%hd", &dev.paperlength);
		} else if (strcmp(cmd, "spare1") == 0) {
			fscanf(fin, "%hd", &dev.spare1);
		} else if (strcmp(cmd, "spare2") == 0) {
			fscanf(fin, "%hd", &dev.spare2);
		} else if (strcmp(cmd, "sizes") == 0) {
			dev.nsizes = 0;
			while (fscanf(fin, "%d", &v) != EOF && v != 0)
				size[dev.nsizes++] = v;
			size[dev.nsizes] = 0;	/* need an extra 0 at the end */
		} else if (strcmp(cmd, "fonts") == 0) {
			fscanf(fin, "%hd", &dev.nfonts);
			for (i = 0; i < dev.nfonts; i++)
				fscanf(fin, "%s", fname[i]);
		} else if (strcmp(cmd, "charset") == 0) {
			p = chname;
			dev.nchtab = 0;
			while (fscanf(fin, "%s", p) != EOF) {
				chtab[dev.nchtab++] = p - chname;
				while (*p++)	/* skip to end of name */
					;
			}
			dev.lchname = p - chname;
			chtab[dev.nchtab++] = 0;	/* terminate properly */
		} else
			fprintf(stderr, "makedev: unknown command %s\n", cmd);
	}
	if (argc > 0 && strcmp(argv[1], "DESC") == 0) {
		fdout = creat(fout, 0666);
		if (fdout < 0) {
			fprintf(stderr, "makedev: can't open %s\n", fout);
			exit(1);
		}
		write(fdout, &dev, sizeof(struct dev));
		write(fdout, size, (dev.nsizes+1) * sizeof(size[0]));	/* we need a 0 on the end */
		write(fdout, chtab, dev.nchtab * sizeof(chtab[0]));
		write(fdout, chname, dev.lchname);
		totfont = 0;
		for (i = 0; i < dev.nfonts; i++) {
			totfont += dofont(fname[i]);
			write(fdout, &font, sizeof(struct font));
			write(fdout, width, font.nwfont & BMASK);
			write(fdout, kern, font.nwfont & BMASK);
			write(fdout, code, font.nwfont & BMASK);
			write(fdout, fitab, dev.nchtab+128-32);
		}
		lseek(fdout, 0L, 0);	/* back to beginning to install proper size */
		dev.filesize =		/* excluding dev struct itself */
			(dev.nsizes+1) * sizeof(size[0])
			+ dev.nchtab * sizeof(chtab[0])
			+ dev.lchname * sizeof(char)
			+ totfont * sizeof(char);
		write(fdout, &dev, sizeof(struct dev));
		close(fdout);
		argc--;
		argv++;
	}
	for (i = 1; i < argc; i++)
		dofont(argv[i]);
	exit(0);
}


/*****************************************************************************/


dofont(name)


	char	*name;						/* string containing name of font */


{


	FILE	*fin;						/* input file descriptor */
	int		fdout;						/* output file descriptor */
	int		i, nw, spacewidth, n, v;
	char 	buf[100], ch[10], s1[10], s2[10], s3[10], cmd[30];
	char	s4[10];						/* used to check for extra info */
	int		count;						/* value returned from sscanf() */
	int		dflt_range;					/* default maximum range for font */
	int		dflt_slant;					/* default slant for this font */



	/********************************************************************
	 *																	*
	 *		This routine is responsible for making the '.out' file for	*
	 *	the font specified by the parameter name. It also sets up some	*
	 *	of the data structures needed to make the DESC.out file in the	*
	 *	main routine. In addition I have changed this routine so that	*
	 *	we can add some typesetter dependent parameters to the font		*
	 *	files and have this information dumped out to a 'add' file		*
	 *	for this font, which can be read as needed by the aps driver.	*
	 *																	*
	 ********************************************************************/



	if ((fin = fopen(name, "r")) == NULL) {
		fprintf(stderr, "makedev: can't open font %s\n", name);
		exit(2);
	}	/* End if */

	sprintf(cmd, "%s.out", name);		/* output file is name.out */
	fdout = creat(cmd, 0666);			/* create the '.out' font file */

	font.specfont = 0;					/* by default it isn't special font */
	font.ligfont = 0;					/* it also has no ligatures either */
	font.spare1 = 0;					/* all the flags are initially off */
	spacewidth = 0;						/* tables may specify a spacewidth */
	dflt_range = 3;						/* max range available on the APS-5 */
	dflt_slant = 0;						/* no slant for this font yet */

	for (i = 0; i < NFITAB; i++)		/* initialize font index table */
		fitab[i] = 0;

	for (i = 0; i < FSIZE; i++)  {		/* initialize character tables */
		width[i] = kern[i] = code[i] = 0;
		alt_font[i] = 0;
		alt_code[i] = 0;
	}	/* End for */

	while (fscanf(fin, "%s", cmd) != EOF)  {	/* read the font file */

		if (strcmp(cmd, "name") == 0)
			fscanf(fin, "%s", font.namefont);
		else if (strcmp(cmd, "internalname") == 0)
			fscanf(fin, "%s", font.intname);
		else if (strcmp(cmd, "special") == 0)
			font.specfont = 1;
		else if (strcmp(cmd, "ligatures") == 0) {
			skipline(fin);	/* skip over any names for now */
			font.ligfont = 1;
		} else if (strcmp(cmd, "spacewidth") == 0) {
			fscanf(fin, "%d", &spacewidth);
			width[0] = spacewidth;	/* width of space on this font */
		} else if (strcmp(cmd, "charset") == 0) {
			skipline(fin);
			nw = 0;

			/* widths are origin 1 so fitab==0 can mean "not there" */

			while (fgets(buf, 100, fin) != NULL)  {		/* read next line */

				count = sscanf(buf, "%s %s %s %s %s", ch, s1, s2, s3, s4);

				if (s1[0] != '"')  {	/* it's a genuine new character */

					nw++;
					width[nw] = atoi(s1);
					kern[nw] = atoi(s2);

					/* temporarily, pick up one byte as code */

					if ( s3[0] == '0' )			/* code is in octal */
						sscanf(s3, "%o", &i);
					else
						sscanf(s3, "%d", &i);	/* otherwise it is decimal */
					code[nw] = i;

					if ( count > 4  &&  font.spare1 )	/* process the rest */
						finish_line(buf, nw);	

				}	/* End if */

				/* otherwise it's a synonym for previous character,
				/* so leave previous values intact
				*/

				if (strlen(ch) == 1)	/* it's ascii */
					fitab[ch[0] - 32] = nw;	/* fitab origin omits non-graphics */
				else {		/* it has a funny name */
					for (i = 0; i < dev.nchtab; i++)
						if (strcmp(&chname[chtab[i]], ch) == 0) {
							fitab[i + 128-32] = nw;	/* starts after the ascii */
							break;
						}	/* End if */

					if (i >= dev.nchtab)
						fprintf(stderr, "makedev: font %s: %s not in charset\n", name, ch);
				}	/* End else */

			}	/* End while */
			nw++;
			font.nwfont = n = nw;
		} else if ( strcmp(cmd, "alternate_font") == 0 )
			font.spare1 |= FONT_BIT;		/* set alternate font bit */
		else if ( strcmp(cmd, "default_slant") == 0 )  {
			font.spare1 &= ~(3 << SLANT_VAL);	/* clear two slant val bits */
			font.spare1 |= SLANT_BIT;			/* set font slant bit */
			fscanf(fin, "%d", &dflt_slant);	/* read the default slant value */
			if ( dflt_slant > 0 )			/* encode it as 01 */
				font.spare1 |= (1 << SLANT_VAL);
			else if ( dflt_slant < 0 )		/* encode it as 10 */
				font.spare1 |= (1 << (SLANT_VAL + 1));
		} else if ( strcmp(cmd, "max_range") == 0 )  {
			font.spare1 |= RANGE_BIT;		/* set range bit in spare1 */
			fscanf(fin, "%d", &dflt_range);	/* read default font slant */
			if ( dflt_range < 1  ||  dflt_range > 4 )  {
				fprintf(stderr, "makedev: illegal default range %d\n",dflt_range);
				exit(1);
			}	/* End if */
			font.spare1 |= (dflt_range << RANGE_VAL);
		} else if ( strcmp(cmd, "debug") == 0 )
			dbg++;

	}	/* End while */

	if (spacewidth == 0)
		width[0] = dev.res * dev.unitwidth / 72 / 3;
	fclose(fin);

	write(fdout, &font, sizeof(struct font));
	write(fdout, width, font.nwfont & BMASK);
	write(fdout, kern, font.nwfont & BMASK);
	write(fdout, code, font.nwfont & BMASK);
	write(fdout, fitab, dev.nchtab+128-32);
	close(fdout);

	if ( font.spare1 ) add_font(name);

	if ( dbg ) dump_font();

	v = sizeof(struct font) + 3 * n + dev.nchtab + 128-32;
	fprintf(stderr, "%3s: %3d chars, width %3d, size %3d\n",
		font.namefont, nw, width[0], v);
	return v;

}	/* End of dofont */


/*****************************************************************************/


finish_line(buf, nw)


	char	*buf;						/* contains current input line */
	int		nw;							/* current index in char tables */


{


	char	s[3][20];					/* used for special char commands */
	char	v[3][20];					/* used to hold values */
	int		count;						/* number of vals read in sscanf() */
	int		range;						/* value of max range for character */
	int		angle;						/* value of slant angle for char */
	int		i;							/* for loop index */



	/********************************************************************
	 *																	*
	 *		This routine is called from dofont() to finish scanning an	*
	 *	input line which has additional character information on it.	*
	 *	The line was read in dofont() and put in the buffer buf, while	*
	 *	the current index that we are using for the character tables is	*
	 *	the value of the parameter nw. The format of the additional		*
	 *	information that may appear in a line in the character set part	*
	 *	of a font file is shown below,									*
	 *																	*
	 *				 slant l  max_range m  font n						*
	 *																	*
	 *	where l, m, and n are integers. Any or all of these commands	*
	 *	may appear on a given line after the normal code entry for the	*
	 *	current character.												*
	 *																	*
	 ********************************************************************/



	count = sscanf(buf,"%*s %*s %*s %*s %s %s %s %s %s %s",s[0],v[0],s[1],v[1],s[2],v[2]);

	if ( (count % 2 != 0) || (count == 0) )  {
		fprintf(stderr, "makedev: format error in charset table\n");
		exit(1);
	}	/* End if */

	alt_code[nw] = code[nw];			/* store real code in alt_code array */
	code[nw] = 128;						/* turn bit 7 on */

	for ( i = 0; i < count/2; i++ )  {		/* process the strings */

		if ( strcmp(s[i], "font") == 0 )  {		/* have an alternate font */
			code[nw] |= FONT_BIT;		/* turn font bit on */
			alt_font[nw] = atoi(v[i]);	/* save this font number */
		} else if ( strcmp(s[i], "max_range") == 0 )  {
			code[nw] &= ~(3 << RANGE_VAL);
			code[nw] |= RANGE_BIT;
			range = atoi(v[i]);
			if ( range < 1  ||  range > 4 )  {
				fprintf(stderr, "makedev: illegal range\n");
				exit(1);
			}	/* End if */
			code[nw] |= (range << RANGE_VAL);
		} else if ( strcmp(s[i], "slant" ) == 0 )  {
			code[nw] &= ~(3 << SLANT_VAL);
			code[nw] |= SLANT_BIT;
			angle = atoi(v[i]);
			if ( angle > 0 )			/* set angle bits to 01 */
				code[nw] |= (1 << SLANT_VAL);
			else if ( angle < 0 )		/* set angle bits to 10 */
				code[nw] |= (1 << (SLANT_VAL + 1));
		} else {						/* illegal command - abort */
			fprintf(stderr, "makedev: illegal command\n");
			exit(1);
		}	/* End else */

	}	/* End for */
	if ( code[nw] & BMASK == 128 )  {
		fprintf(stderr, "makedev: char code %d less than 129\n", code[nw]);
		exit(1);
	}	/* End if */

}	/* End of finish_line */


/*****************************************************************************/


add_font(name)


	char	*name;						/* name of currnent font */


{


	int		fdout;						/* output file descriptor */
	int		k;							/* number of width entries */
	char	cmd[30];					/* used to create output file */



	/********************************************************************
	 *																	*
	 *		This routine is called from dofont() to write out the 		*
	 *	additional information that was specified in the input font		*
	 *	file. As currently implemented the alternate code table and		*
	 *	the alternate font tables are always written to the output		*
	 *	file. 															*
	 *																	*
	 ********************************************************************/



	sprintf(cmd, "%s.add", name);		/* file will be 'name'.add */
	fdout = creat(cmd, 0666);			/* create the '.add' file */

	k = font.nwfont & BMASK;

	write(fdout, alt_font, FSIZE * sizeof(alt_font[0]));
	write(fdout, alt_code, FSIZE);

	close(fdout);

}	/* End of add_font */


/*****************************************************************************/


dump_font()


{


	int		pos;						/* position in character tables */
	int		j;							/* for loop index */
	int		code_val;					/* number in code table */



	/********************************************************************
	 *																	*
	 *		This routine is called to dump the information that we have	*
	 *	read from the current font file.								*
	 *																	*
	 ********************************************************************/



	printf("DATA FOR FONT %s:\n\n", font.namefont);

	printf("  font structure data:\n");
	printf("\t\tfont.nwfont = %d\n", font.nwfont & BMASK);
	printf("\t\tfont.specfont = %d\n", font.specfont & BMASK);
	printf("\t\tfont.ligfont = %d\n", font.ligfont & BMASK);
	printf("\t\tfont.spare1 = 0%o\n", font.spare1 & BMASK);
	printf("\t\tfont.intname = %s\n\n", font.intname);

	printf("  CHAR     WIDTH      KERN      CODE     INDEX\n");

	for ( j = 0; j < dev.nchtab + 128 - 32; j++ )  {

		if ( (pos = fitab[j] & BMASK) != 0 )  {
			if ( j >= 96 )
				printf("%5s", &chname[chtab[j-96]]);
			else printf("%5c", (j + 32) & BMASK);
			printf("%10d", width[pos] & BMASK);
			printf("%10d", kern[pos] & BMASK);
			code_val = code[pos] & BMASK;
			printf("%10d", code_val & BMASK);
			printf("%10d", j);

			if ( code_val > 128 )  {
				printf("%5d", alt_code[pos] & BMASK);
				if ( code_val & SLANT_BIT )  
					printf("  slant %d", (code_val >> SLANT_VAL) & 03);
				if ( code_val & FONT_BIT )
					printf("  font %d", alt_font[pos]);
				if ( code_val & RANGE_BIT )
					printf("  range %d", (code_val >> RANGE_VAL) & 03);
			}	/* End if */

			printf("\n");
		}	/* End if */

	}	/* End for */

	printf("\n\n");

}	/* End of dump_font */


/*****************************************************************************/