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