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