xref: /illumos-gate/usr/src/cmd/troff/troff.d/makedev.c (revision 4de2612967d06c4fdbf524a62556a1e8118a006f)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 1989 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
28 /*	  All Rights Reserved  	*/
29 
30 /*
31  * University Copyright- Copyright (c) 1982, 1986, 1988
32  * The Regents of the University of California
33  * All Rights Reserved
34  *
35  * University Acknowledgment- Portions of this document are derived from
36  * software developed by the University of California, Berkeley, and its
37  * contributors.
38  */
39 
40 #pragma ident	"%Z%%M%	%I%	%E% SMI"
41 
42 /* Note added 9/25/83
43 	Setting the parameter biggestfont in the DESC file
44 	to be at least as big as the number of characters
45 	in the largest font for a particular device
46 	eliminates the "font X too big for position Y"
47 	message from troff.
48 	Thanks to Dave Stephens, WECo.
49 */
50 /*
51   makedev:
52 	read text info about a particular device
53 	(e.g., cat, 202, aps5) from file, convert
54 	it into internal (binary) form suitable for
55 	fast reading by troff initialization (ptinit()).
56 
57 	Usage:
58 
59 	makedev DESC [ F ... ]
60 		uses DESC to create a description file
61 		using the information therein.
62 		It creates the file DESC.out.
63 
64 	makedev F ...
65 		makes the font tables for fonts F only,
66 		creates files F.out.
67 
68 	DESC.out contains:
69 	dev structure with fundamental sizes
70 	list of sizes (nsizes+1) terminated by 0, as short's
71 	indices of char names (nchtab * sizeof(short))
72 	char names as hy\0em\0... (lchname)
73 	nfonts occurrences of
74 		widths (nwidth)
75 		kerning (nwidth) [ascender+descender only so far]
76 		codes (nwidth) to drive actual typesetter
77 		fitab (nchtab+128-32)
78 	each of these is an array of char.
79 
80 	dev.filesize contains the number of bytes
81 	in the file, excluding the dev part itself.
82 
83 	F.out contains the font header, width, kern, codes, and fitab.
84 	Width, kern and codes are parallel arrays.
85 	(Which suggests that they ought to be together?)
86 	Later, we might allow for codes which are actually
87 	sequences of formatting info so characters can be drawn.
88 */
89 
90 #include	"stdio.h"
91 #include	"dev.h"
92 
93 #define	BYTEMASK	0377
94 #define	skipline(f)	while(getc(f) != '\n')
95 
96 struct	dev	dev;
97 struct	Font	font;
98 
99 #define	NSIZE	100	/* maximum number of sizes */
100 short	size[NSIZE];
101 #define	NCH	256	/* max number of characters with funny names */
102 char	chname[5*NCH];	/* character names, including \0 for each */
103 short	chtab[NCH];	/* index of character in chname */
104 
105 #define	NFITAB	(NCH + 128-32)	/* includes ascii chars, but not non-graphics */
106 char	fitab[NFITAB];	/* font index table: position of char i on this font. */
107 			/* zero if not there */
108 
109 #define	FSIZE	256	/* size of a physical font (e.g., 102 for cat) */
110 char	width[FSIZE];	/* width table for a physical font */
111 char	kern[FSIZE];	/* ascender+descender info */
112 char	code[FSIZE];	/* actual device codes for a physical font */
113 
114 #define	NFONT	60	/* max number of default fonts */
115 char	fname[NFONT][10];	/* temp space to hold default font names */
116 
117 int	fflag	= 0;	/* on if font table to be written */
118 int	fdout;	/* output file descriptor */
119 char	*fout	= "DESC.out";
120 
121 int main(int argc, char *argv[])
122 {
123 	FILE *fin;
124 	char cmd[100], *p;
125 	int i, totfont, v;
126 
127     if (argc < 2) {
128         fprintf(stderr, "Usage:  makedev [DESC] [fonts]\n");
129         exit(1);
130     }
131 
132 	if ((fin = fopen("DESC", "r")) == NULL) {
133 		fprintf(stderr, "makedev: can't open %s\n", argv[1]);
134 		exit(1);
135 	}
136 	while (fscanf(fin, "%s", cmd) != EOF) {
137 		if (cmd[0] == '#')	/* comment */
138 			skipline(fin);
139 		else if (strcmp(cmd, "res") == 0) {
140 			fscanf(fin, "%hd", &dev.res);
141 		} else if (strcmp(cmd, "hor") == 0) {
142 			fscanf(fin, "%hd", &dev.hor);
143 		} else if (strcmp(cmd, "vert") == 0) {
144 			fscanf(fin, "%hd", &dev.vert);
145 		} else if (strcmp(cmd, "unitwidth") == 0) {
146 			fscanf(fin, "%hd", &dev.unitwidth);
147 		} else if (strcmp(cmd, "sizescale") == 0) {
148 			fscanf(fin, "%hd", &dev.sizescale);
149 		} else if (strcmp(cmd, "paperwidth") == 0) {
150 			fscanf(fin, "%hd", &dev.paperwidth);
151 		} else if (strcmp(cmd, "paperlength") == 0) {
152 			fscanf(fin, "%hd", &dev.paperlength);
153 		} else if (strcmp(cmd, "biggestfont") == 0) {
154 			fscanf(fin, "%hd", &dev.biggestfont);
155 		} else if (strcmp(cmd, "spare2") == 0) {
156 			fscanf(fin, "%hd", &dev.spare2);
157 		} else if (strcmp(cmd, "sizes") == 0) {
158 			dev.nsizes = 0;
159 			while (fscanf(fin, "%d", &v) != EOF && v != 0)
160 				size[dev.nsizes++] = v;
161 			size[dev.nsizes] = 0;	/* need an extra 0 at the end */
162 		} else if (strcmp(cmd, "fonts") == 0) {
163 			fscanf(fin, "%hd", &dev.nfonts);
164 			for (i = 0; i < dev.nfonts; i++)
165 				fscanf(fin, "%s", fname[i]);
166 		} else if (strcmp(cmd, "charset") == 0) {
167 			p = chname;
168 			dev.nchtab = 0;
169 			while (fscanf(fin, "%s", p) != EOF) {
170 				chtab[dev.nchtab++] = p - chname;
171 				while (*p++)	/* skip to end of name */
172 					;
173 			}
174 			dev.lchname = p - chname;
175 			chtab[dev.nchtab++] = 0;	/* terminate properly */
176 		} else
177 			fprintf(stderr, "makedev: unknown command %s\n", cmd);
178 	}
179 	if (argc > 0 && strcmp(argv[1], "DESC") == 0) {
180 		fdout = creat(fout, 0666);
181 		if (fdout < 0) {
182 			fprintf(stderr, "makedev: can't open %s\n", fout);
183 			exit(1);
184 		}
185 		write(fdout, &dev, sizeof(struct dev));
186 		write(fdout, size, (dev.nsizes+1) * sizeof(size[0]));	/* we need a 0 on the end */
187 		write(fdout, chtab, dev.nchtab * sizeof(chtab[0]));
188 		write(fdout, chname, dev.lchname);
189 		totfont = 0;
190 		for (i = 0; i < dev.nfonts; i++) {
191 			totfont += dofont(fname[i]);
192 			write(fdout, &font, sizeof(struct Font));
193 			write(fdout, width, font.nwfont & BYTEMASK);
194 			write(fdout, kern, font.nwfont & BYTEMASK);
195 			write(fdout, code, font.nwfont & BYTEMASK);
196 			write(fdout, fitab, dev.nchtab+128-32);
197 		}
198 		lseek(fdout, 0L, 0);	/* back to beginning to install proper size */
199 		dev.filesize =		/* excluding dev struct itself */
200 			(dev.nsizes+1) * sizeof(size[0])
201 			+ dev.nchtab * sizeof(chtab[0])
202 			+ dev.lchname * sizeof(char)
203 			+ totfont * sizeof(char);
204 		write(fdout, &dev, sizeof(struct dev));
205 		close(fdout);
206 		argc--;
207 		argv++;
208 	}
209 	for (i = 1; i < argc; i++)
210 		dofont(argv[i]);
211 	exit(0);
212 
213 	return (0);
214 }
215 
216 int
217 dofont(name)	/* create fitab and width tab for font */
218 char *name;
219 {
220 	FILE *fin;
221 	int fdout;
222 	int i, nw, spacewidth, n, v;
223 	char buf[100], ch[10], s1[10], s2[10], s3[10], cmd[30];
224 
225 	if ((fin = fopen(name, "r")) == NULL) {
226 		fprintf(stderr, "makedev: can't open font %s\n", name);
227 		exit(2);
228 	}
229 	sprintf(cmd, "%s.out", name);
230 	fdout = creat(cmd, 0666);
231 	for (i = 0; i < NFITAB; i++)
232 		fitab[i] = 0;
233 	for (i = 0; i < FSIZE; i++)
234 		width[i] = kern[i] = code[i] = 0;
235 	font.specfont = font.ligfont = spacewidth = 0;
236 	while (fscanf(fin, "%s", cmd) != EOF) {
237 		if (cmd[0] == '#')
238 			skipline(fin);
239 		else if (strcmp(cmd, "name") == 0)
240 			fscanf(fin, "%s", font.namefont);
241 		else if (strcmp(cmd, "internalname") == 0)
242 			fscanf(fin, "%s", font.intname);
243 		else if (strcmp(cmd, "special") == 0)
244 			font.specfont = 1;
245 		else if (strcmp(cmd, "spare1") == 0)
246 			fscanf(fin, "%1s", &font.spare1);
247 		else if (strcmp(cmd, "ligatures") == 0) {
248 			font.ligfont = getlig(fin);
249 		} else if (strcmp(cmd, "spacewidth") == 0) {
250 			fscanf(fin, "%d", &spacewidth);
251 			width[0] = spacewidth;	/* width of space on this font */
252 		} else if (strcmp(cmd, "charset") == 0) {
253 			skipline(fin);
254 			nw = 0;
255 			/* widths are origin 1 so fitab==0 can mean "not there" */
256 			while (fgets(buf, 100, fin) != NULL) {
257 				sscanf(buf, "%s %s %s %s", ch, s1, s2, s3);
258 				if (s1[0] != '"') {	/* it's a genuine new character */
259 					nw++;
260 					width[nw] = atoi(s1);
261 					kern[nw] = atoi(s2);
262 					/* temporarily, pick up one byte as code */
263 					if (s3[0] == '0')
264 						sscanf(s3, "%o", &i);
265 					else
266 						sscanf(s3, "%d", &i);
267 					code[nw] = i;
268 				}
269 				/*
270 				 * otherwise it's a synonym for previous character,
271 				 * so leave previous values intact
272 				*/
273 				if (strlen(ch) == 1)	/* it's ascii */
274 					fitab[ch[0] - 32] = nw;	/* fitab origin omits non-graphics */
275 				else {		/* it has a funny name */
276 					for (i = 0; i < dev.nchtab; i++)
277 						if (strcmp(&chname[chtab[i]], ch) == 0) {
278 							fitab[i + 128-32] = nw;	/* starts after the ascii */
279 							break;
280 						}
281 					if (i >= dev.nchtab)
282 						fprintf(stderr, "makedev: font %s: %s not in charset\n", name, ch);
283 				}
284 			}
285 			nw++;
286 			if (dev.biggestfont >= nw)
287 				n = dev.biggestfont;
288 			else {
289 				if (dev.biggestfont > 0)
290 					fprintf(stderr, "font %s too big\n", name);
291 				n = nw;
292 			}
293 			font.nwfont = n;
294 		}
295 	}
296 	if (spacewidth == 0)
297 		width[0] = dev.res * dev.unitwidth / 72 / 3;
298 	fclose(fin);
299 
300 	write(fdout, &font, sizeof(struct Font));
301 	write(fdout, width, font.nwfont & BYTEMASK);
302 	write(fdout, kern, font.nwfont & BYTEMASK);
303 	write(fdout, code, font.nwfont & BYTEMASK);
304 	write(fdout, fitab, dev.nchtab+128-32);
305 	close(fdout);
306 	v = sizeof(struct Font) + 3 * n + dev.nchtab + 128-32;
307 	fprintf(stderr, "%3s: %3d chars, width %3d, size %3d\n",
308 		font.namefont, nw, width[0], v);
309 	return v;
310 }
311 
312 int
313 getlig(fin)	/* pick up ligature list */
314 	FILE *fin;
315 {
316 	int lig;
317 	char temp[100];
318 
319 	lig = 0;
320 	while (fscanf(fin, "%s", temp) != EOF && strcmp(temp, "0") != 0) {
321 		if (strcmp(temp, "fi") == 0)
322 			lig |= LFI;
323 		else if (strcmp(temp, "fl") == 0)
324 			lig |= LFL;
325 		else if (strcmp(temp, "ff") == 0)
326 			lig |= LFF;
327 		else if (strcmp(temp, "ffi") == 0)
328 			lig |= LFFI;
329 		else if (strcmp(temp, "ffl") == 0)
330 			lig |= LFFL;
331 		else
332 			fprintf(stderr, "illegal ligature %s\n", temp);
333 	}
334 	skipline(fin);
335 	return lig;
336 }
337