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 2005 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	254	/* 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 #define	BIGGESTFONT	FSIZE	/* biggest font if no size in DESC */
114 				/* MUST be < 256 */
115 
116 #define	NFONT	50	/* max number of default fonts */
117 char	fname[NFONT][10];	/* temp space to hold default font names */
118 
119 int	fflag	= 0;	/* on if font table to be written */
120 int	fdout;	/* output file descriptor */
121 char	*fout	= "DESC.out";
122 
123 static int dofont(char *);
124 static int getlig(FILE *);
125 
126 int
127 main(int argc, char *argv[])
128 {
129 	FILE *fin;
130 	char cmd[100], *p;
131 	int i, totfont, v;
132 
133 	if (argc < 2) {
134 		fprintf(stderr, "Usage:  makedev [DESC] [fonts]\n");
135 		exit(1);
136 	}
137 	if ((fin = fopen("DESC", "r")) == NULL) {
138 		fprintf(stderr, "makedev: can't open DESC file\n");
139 		exit(1);
140 	}
141 	while (fscanf(fin, "%s", cmd) != EOF) {
142 		if (cmd[0] == '#')	/* comment */
143 			skipline(fin);
144 		else if (strcmp(cmd, "res") == 0) {
145 			fscanf(fin, "%hd", &dev.res);
146 		} else if (strcmp(cmd, "hor") == 0) {
147 			fscanf(fin, "%hd", &dev.hor);
148 		} else if (strcmp(cmd, "vert") == 0) {
149 			fscanf(fin, "%hd", &dev.vert);
150 		} else if (strcmp(cmd, "unitwidth") == 0) {
151 			fscanf(fin, "%hd", &dev.unitwidth);
152 		} else if (strcmp(cmd, "sizescale") == 0) {
153 			fscanf(fin, "%hd", &dev.sizescale);
154 		} else if (strcmp(cmd, "paperwidth") == 0) {
155 			fscanf(fin, "%hd", &dev.paperwidth);
156 		} else if (strcmp(cmd, "paperlength") == 0) {
157 			fscanf(fin, "%hd", &dev.paperlength);
158 		} else if (strcmp(cmd, "biggestfont") == 0) {
159 			fscanf(fin, "%hd", &dev.biggestfont);
160 		} else if (strcmp(cmd, "spare2") == 0) {
161 			fscanf(fin, "%hd", &dev.spare2);
162 		} else if (strcmp(cmd, "sizes") == 0) {
163 			dev.nsizes = 0;
164 			while (fscanf(fin, "%d", &v) != EOF && v != 0)
165 				size[dev.nsizes++] = v;
166 			size[dev.nsizes] = 0;	/* need an extra 0 at the end */
167 		} else if (strcmp(cmd, "fonts") == 0) {
168 			fscanf(fin, "%hd", &dev.nfonts);
169 			for (i = 0; i < dev.nfonts; i++)
170 				fscanf(fin, "%s", fname[i]);
171 		} else if (strcmp(cmd, "charset") == 0) {
172 			short	pchname;
173 
174 			p = chname;
175 			pchname = 0;
176 			dev.nchtab = 0;
177 			while (fscanf(fin, "%s", p) != EOF) {
178 				chtab[dev.nchtab++] = pchname;
179 				while (*p++)	/* skip to end of name */
180 					pchname++;
181 				pchname++;
182 			}
183 			dev.lchname = pchname;
184 			chtab[dev.nchtab++] = 0;	/* terminate properly */
185 		} else
186 			fprintf(stderr, "makedev: unknown command %s\n", cmd);
187 	}
188 	if (argc > 1 && strcmp(argv[1], "DESC") == 0) {
189 		fdout = creat(fout, 0666);
190 		if (fdout < 0) {
191 			fprintf(stderr, "makedev: can't open %s\n", fout);
192 			exit(1);
193 		}
194 		write(fdout, &dev, sizeof(struct dev));
195 		write(fdout, size, (dev.nsizes+1) * sizeof(size[0]));	/* we need a 0 on the end */
196 		write(fdout, chtab, dev.nchtab * sizeof(chtab[0]));
197 		write(fdout, chname, dev.lchname);
198 		totfont = 0;
199 		for (i = 0; i < dev.nfonts; i++) {
200 			totfont += dofont(fname[i]);
201 			write(fdout, &font, sizeof(struct Font));
202 			write(fdout, width, font.nwfont & BYTEMASK);
203 			write(fdout, kern, font.nwfont & BYTEMASK);
204 			write(fdout, code, font.nwfont & BYTEMASK);
205 			write(fdout, fitab, dev.nchtab+128-32);
206 		}
207 		lseek(fdout, 0L, 0);	/* back to beginning to install proper size */
208 		dev.filesize =		/* excluding dev struct itself */
209 			(dev.nsizes+1) * sizeof(size[0])
210 			+ dev.nchtab * sizeof(chtab[0])
211 			+ dev.lchname * sizeof(char)
212 			+ totfont * sizeof(char);
213 		write(fdout, &dev, sizeof(struct dev));
214 		close(fdout);
215 		argc--;
216 		argv++;
217 	}
218 	for (i = 1; i < argc; i++)
219 		dofont(argv[i]);
220 	return (0);
221 }
222 
223 static int
224 dofont(char *name)	/* create fitab and width tab for font */
225 {
226 	FILE *fin;
227 	int fdout;
228 	int i, nw, spacewidth, n, v;
229 	char buf[100], ch[10], s1[10], s2[10], s3[10], cmd[30];
230 
231 	if ((fin = fopen(name, "r")) == NULL) {
232 		fprintf(stderr, "makedev: can't open font %s\n", name);
233 		exit(2);
234 	}
235 	sprintf(cmd, "%s.out", name);
236 	fdout = creat(cmd, 0666);
237 	if (fdout < 0) {
238 		fprintf(stderr, "makedev: can't open %s\n", fout);
239 		exit(1);
240 	}
241 	for (i = 0; i < NFITAB; i++)
242 		fitab[i] = 0;
243 	for (i = 0; i < FSIZE; i++)
244 		width[i] = kern[i] = code[i] = 0;
245 	font.specfont = font.ligfont = spacewidth = 0;
246 	while (fscanf(fin, "%s", cmd) != EOF) {
247 		if (cmd[0] == '#')
248 			skipline(fin);
249 		else if (strcmp(cmd, "name") == 0)
250 			fscanf(fin, "%s", font.namefont);
251 		else if (strcmp(cmd, "internalname") == 0)
252 			fscanf(fin, "%s", font.intname);
253 		else if (strcmp(cmd, "special") == 0)
254 			font.specfont = 1;
255 		else if (strcmp(cmd, "spare1") == 0)
256 			fscanf(fin, "%1s", &font.spare1);
257 		else if (strcmp(cmd, "ligatures") == 0) {
258 			font.ligfont = getlig(fin);
259 		} else if (strcmp(cmd, "spacewidth") == 0) {
260 			fscanf(fin, "%d", &spacewidth);
261 			width[0] = spacewidth;	/* width of space on this font */
262 		} else if (strcmp(cmd, "charset") == 0) {
263 			skipline(fin);
264 			nw = 0;
265 			/* widths are origin 1 so fitab==0 can mean "not there" */
266 			while (fgets(buf, 100, fin) != NULL) {
267 				sscanf(buf, "%s %s %s %s", ch, s1, s2, s3);
268 				if (s1[0] != '"') {	/* it's a genuine new character */
269 					nw++;
270 					width[nw] = atoi(s1);
271 					kern[nw] = atoi(s2);
272 					/* temporarily, pick up one byte as code */
273 					if (s3[0] == '0')
274 						sscanf(s3, "%o", &i);
275 					else
276 						sscanf(s3, "%d", &i);
277 					code[nw] = i;
278 				}
279 				/* otherwise it's a synonym for previous character,
280 				* so leave previous values intact
281 				*/
282 				if (strlen(ch) == 1)	/* it's ascii */
283 					fitab[ch[0] - 32] = nw;	/* fitab origin omits non-graphics */
284 				else if (strcmp(ch, "---") != 0) {	/* it has a 2-char name */
285 					for (i = 0; i < dev.nchtab; i++)
286 						if (strcmp(&chname[chtab[i]], ch) == 0) {
287 							fitab[i + 128-32] = nw;	/* starts after the ascii */
288 							break;
289 						}
290 					if (i >= dev.nchtab)
291 						fprintf(stderr, "makedev: font %s: %s not in charset\n", name, ch);
292 				}
293 			}
294 			nw++;
295 			if (dev.biggestfont > 0)
296 				n = dev.biggestfont + 1;
297 			else
298 				n = BIGGESTFONT;
299 			/*
300 			 * Make files at least as big as biggestfont. Larger fonts
301 			 * may only fit in postion 0.
302 			 */
303 			if ( nw > n )  {
304 				n = nw;
305 				fprintf(stderr, "makedev: warning font %s may only fit in position 0\n", font.namefont);
306 			}
307 			if (n >= NCH) {
308 				fprintf(stderr, "makedev: font has %d characters, too big\n", n);
309 				exit(2);
310 			}
311 			font.nwfont = n;
312 		}
313 	}
314 	if (spacewidth == 0)
315 		width[0] = dev.res * dev.unitwidth / 72 / 3; /* should be rounded */
316 	fclose(fin);
317 
318 	write(fdout, &font, sizeof(struct Font));
319 	write(fdout, width, font.nwfont & BYTEMASK);
320 	write(fdout, kern, font.nwfont & BYTEMASK);
321 	write(fdout, code, font.nwfont & BYTEMASK);
322 	write(fdout, fitab, dev.nchtab+128-32);
323 	close(fdout);
324 	v = sizeof(struct Font) + 3 * n + dev.nchtab + 128-32;
325 	fprintf(stderr, "%3s: %3d chars, width %3d, size %3d\n",
326 		font.namefont, nw, width[0], v);
327 	return (v);
328 }
329 
330 static int
331 getlig(FILE *fin)	/* pick up ligature list */
332 {
333 	int lig;
334 	char temp[100];
335 
336 	lig = 0;
337 	while (fscanf(fin, "%s", temp) != EOF && strcmp(temp, "0") != 0) {
338 		if (strcmp(temp, "fi") == 0)
339 			lig |= LFI;
340 		else if (strcmp(temp, "fl") == 0)
341 			lig |= LFL;
342 		else if (strcmp(temp, "ff") == 0)
343 			lig |= LFF;
344 		else if (strcmp(temp, "ffi") == 0)
345 			lig |= LFFI;
346 		else if (strcmp(temp, "ffl") == 0)
347 			lig |= LFFL;
348 		else
349 			fprintf(stderr, "illegal ligature %s\n", temp);
350 	}
351 	skipline(fin);
352 	return (lig);
353 }
354