1 #ifdef lint
2 static char sccsid[] = "@(#)makedev.c	1.2	(CWI)	1.2	85/10/24";
3 #endif lint
4 /*
5   makedev:
6 	read text info about a particular device
7 	(e.g., cat, 202, aps5) from file, convert
8 	it into internal (binary) form suitable for
9 	fast reading by troff initialization (ptinit()).
10 
11 	Usage:
12 
13 	makedev DESC [ F ... ]
14 		uses DESC to create a description file
15 		using the information therein.
16 		It creates the file DESC.out.
17 
18 	makedev F ...
19 		makes the font tables for fonts F only,
20 		creates files F.out.
21 
22 	DESC.out contains:
23 	dev structure with fundamental sizes
24 	list of sizes (nsizes+1) terminated by 0, as short's
25 	indices of char names (nchtab * sizeof(short))
26 	char names as hy\0em\0... (lchname)
27 	nfonts occurrences of
28 		widths (nwidth)
29 		kerning (nwidth) [ascender+descender only so far]
30 		codes (nwidth) to drive actual typesetter
31 		fitab (nchtab+128-32)
32 	each of these is an array of char.
33 
34 	dev.filesize contains the number of bytes
35 	in the file, excluding the dev part itself.
36 
37 	F.out contains the font header, width, kern, codes, and fitab.
38 	Width, kern and codes are parallel arrays.
39 	(Which suggests that they ought to be together?)
40 	Later, we might allow for codes which are actually
41 	sequences of formatting info so characters can be drawn.
42 */
43 
44 /*
45  * Changes made at the Mathematisch centrum:
46  *
47  * 1	added another table of shorts, with contains a number of the
48  *	physical font where the char actual lives. This is done because
49  *	the typesetter at the MC (harris 7400)has "mixed fonts".
50  *	(for instance, the font with number 4478 contains the
51  *	ligatures etc. for as well the times roman
52  *	and the times italic fonts).
53  *	This table (fcode(nwidth)) starts after the fitab,
54  *	this is done so we don't have to change in troff t6.c setfp().
55  *	For the sake of compatibility, this change will only be effective
56  *	if the field fonttab is set to 1. This change has to be wired
57  *	in troff etc. as well.
58  *
59  * 2	The sans-serif fonts of the Harris doesn't have an italian
60  *	equivalent, they are suppose to be made bij the Oblique
61  *	facility of the Harris. This will slant the character by
62  *	9, 12 or 15 degrees. So another field in the font sruct is added
63  *	for this function as well.
64  *
65  * 3	added some checking of input desciption (for instance declaring
66  *	too many sizes).
67  *
68  * These changes are made by jaap akkerhuis, 1982
69  *
70  * Warning: using the spare fields may give bizarre effects, see comment
71  *	at font.spare1
72  */
73 
74 #include	"stdio.h"
75 #include	"../dev.h"
76 
77 #define	BMASK	0377
78 #define	skipline(f)	while(getc(f) != '\n')
79 
80 struct	dev	dev;
81 struct	Font	font;
82 
83 #define	NSIZE	100	/* maximum number of sizes */
84 short	size[NSIZE];
85 #define	NCH	256	/* max number of characters with funny names */
86 char	chname[5*NCH];	/* character names, including \0 for each */
87 short	chtab[NCH];	/* index of character in chname */
88 char	nmseen[5*NCH];	/* The names we have seen */
89 
90 #define	NFITAB	(NCH + 128-32)	/* includes ascii chars, but not non-graphics */
91 char	fitab[NFITAB];	/* font index table: position of char i on this font. */
92 			/* zero if not there */
93 
94 #define	FSIZE	200	/* size of a physical font (e.g., 102 for cat) */
95 char	width[FSIZE];	/* width table for a physical font */
96 char	kern[FSIZE];	/* ascender+descender info */
97 char	code[FSIZE];	/* actual device codes for a physical font */
98 short	fcode[FSIZE];	/* MC:jna physical font number */
99 
100 #define	NFONT	60	/* max number of default fonts */
101 				/*
102 				 * 60 to support Versatec Berkeley style
103 				 * filters. Aargh!
104 				 */
105 char	fname[NFONT][10];	/* temp space to hold default font names */
106 
107 int	fflag	= 0;	/* on if font table to be written */
108 int	fdout;	/* output file descriptor */
109 char	*fout	= "DESC.out";
110 
main(argc,argv)111 main(argc, argv)
112 char *argv[];
113 {
114 	FILE *fin;
115 	char cmd[100], *p;
116 	int i, totfont, v, check;
117 
118 	if ((fin = fopen("DESC", "r")) == NULL) {
119 		fprintf(stderr, "makedev: can't open %s\n", argv[1]);
120 		exit(1);
121 	}
122 	while (fscanf(fin, "%s", cmd) != EOF) {
123 		if (cmd[0] == '#')	/* comment */
124 			skipline(fin);
125 		else if (strcmp(cmd, "res") == 0) {
126 			fscanf(fin, "%hd", &dev.res);
127 		} else if (strcmp(cmd, "hor") == 0) {
128 			fscanf(fin, "%hd", &dev.hor);
129 		} else if (strcmp(cmd, "vert") == 0) {
130 			fscanf(fin, "%hd", &dev.vert);
131 		} else if (strcmp(cmd, "unitwidth") == 0) {
132 			fscanf(fin, "%hd", &dev.unitwidth);
133 		} else if (strcmp(cmd, "sizescale") == 0) {
134 			fscanf(fin, "%hd", &dev.sizescale);
135 		} else if (strcmp(cmd, "paperwidth") == 0) {
136 			fscanf(fin, "%hd", &dev.paperwidth);
137 		} else if (strcmp(cmd, "paperlength") == 0) {
138 			fscanf(fin, "%hd", &dev.paperlength);
139 		} else if (strcmp(cmd, "spare1") == 0) {
140 			fscanf(fin, "%hd", &dev.spare1);
141 		} else if (strcmp(cmd, "spare2") == 0) {
142 			fscanf(fin, "%hd", &dev.spare2);
143 		} else if (strcmp(cmd, "sizes") == 0) {
144 			dev.nsizes = 0;
145 			while (fscanf(fin, "%d", &v) != EOF && v != 0) {
146 				size[dev.nsizes++] = v;
147 				if(dev.nsizes >= NSIZE) { /*MC:jna addition */
148 					fprintf(stderr, "Too many sizes\n");
149 					exit(3);
150 				}
151 			}
152 			size[dev.nsizes] = 0;	/* need an extra 0 at the end */
153 		} else if (strcmp(cmd, "fonts") == 0) {
154 			fscanf(fin, "%hd", &dev.nfonts);
155 			for (i = 0; i < dev.nfonts; i++) {
156 				if ( i >=  NFONT) {
157 					fprintf(stderr,"Too many default fonts\n");
158 					exit(3);
159 				}
160 				fscanf(fin, "%s", fname[i]);
161 			}
162 		} else if (strcmp(cmd, "charset") == 0) {
163 			p = chname;
164 			dev.nchtab = 0;
165 			while (fscanf(fin, "%s", p) != EOF) {
166 				chtab[dev.nchtab++] = p - chname;
167 				if (dev.nchtab > NCH) {
168 					fprintf(stderr,
169 						"Too many charnames at %s\n",p);
170 					exit(3);
171 				}
172 				for (i = 0; i < dev.nchtab - 1; i++)
173 					if (strcmp(&chname[chtab[i]], p) == 0)
174 						printf("Warning: charname %s used more then once\n", p);
175 				while (*p++)	/* skip to end of name */
176 					;
177 			}
178 			dev.lchname = p - chname;
179 			chtab[dev.nchtab++] = 0;	/* terminate properly */
180 		} else
181 			fprintf(stderr, "makedev: unknown command %s\n", cmd);
182 	}
183 	if (argc > 0 && strcmp(argv[1], "DESC") == 0) {
184 		check++;
185 		fdout = creat(fout, 0666);
186 		if (fdout < 0) {
187 			fprintf(stderr, "makedev: can't open %s\n", fout);
188 			exit(1);
189 		}
190 		write(fdout, &dev, sizeof(struct dev));
191 		write(fdout, size, (dev.nsizes+1) * sizeof(size[0]));	/* we need a 0 on the end */
192 		write(fdout, chtab, dev.nchtab * sizeof(chtab[0]));
193 		write(fdout, chname, dev.lchname);
194 		totfont = 0;
195 		for (i = 0; i < dev.nfonts; i++) {
196 			/*
197 			 * Get fontinfo ...
198 			 */
199 			dofont(fname[i]);
200 			/*
201 			 * ... and force space in troff allocated for the
202 			 * biggest font possible and limited by makedev
203 			 * to be loaded in troff by faking font.nwfont
204 			 * (and bumping up the size of DESC.out) by
205 			 * recalculating the padded out fontsize (v)
206 			 *	jna
207 			 */
208 			font.nwfont = FSIZE;
209 			v = sizeof(struct Font) + 3 * FSIZE + dev.nchtab + 128-32;
210 				/*
211 				 * This is not correct, we can still
212 				 * have too less space if the default
213 				 * mounted fonts does not contain a
214 				 * fonttab, but I don't want to change
215 				 * troff on the moment...
216 				 */
217 			if(font.fonttab == 1)
218 				v += FSIZE * sizeof( short );
219 			totfont += v;
220 			write(fdout, &font, sizeof(struct Font));
221 			write(fdout, width, font.nwfont & BMASK);
222 			write(fdout, kern, font.nwfont & BMASK);
223 			write(fdout, code, font.nwfont & BMASK);
224 			write(fdout, fitab, dev.nchtab+128-32);
225 			if(font.fonttab == 1)
226 				write(fdout, fcode, (font.nwfont & BMASK) * sizeof(fcode[0]));
227 		}
228 		lseek(fdout, 0L, 0);	/* back to beginning to install proper size */
229 		dev.filesize =		/* excluding dev struct itself */
230 			(dev.nsizes+1) * sizeof(size[0])
231 			+ dev.nchtab * sizeof(chtab[0])
232 			+ dev.lchname * sizeof(char)
233 			+ totfont * sizeof(char);
234 		write(fdout, &dev, sizeof(struct dev));
235 		close(fdout);
236 		argc--;
237 		argv++;
238 	}
239 	for (i = 1; i < argc; i++)
240 		dofont(argv[i]);
241 	if( check)
242 		checknames();
243 	exit(0);
244 }
245 
dofont(name)246 dofont(name)	/* create fitab and width tab for font */
247 char *name;
248 {
249 	FILE *fin;
250 	int fdout;
251 	int i, nw, spacewidth, n, v;
252 	char buf[100], ch[10], s1[10], s2[10], s3[10],s4[10], cmd[30];
253 	char *p, *p1;
254 
255 	if ((fin = fopen(name, "r")) == NULL) {
256 		fprintf(stderr, "makedev: can't open font %s\n", name);
257 		exit(2);
258 	}
259 	sprintf(cmd, "%s.out", name);
260 	fdout = creat(cmd, 0666);
261 	for (i = 0; i < NFITAB; i++)
262 		fitab[i] = 0;
263 	for (i = 0; i < FSIZE; i++) {
264 		width[i] = kern[i] = code[i] = 0;
265 		fcode[i] = 0;
266 	}
267 	font.fonttab = font.slant = font.specfont = font.ligfont = spacewidth = 0;
268 	font.spare1 = NULL;
269 	font.namefont[0] = font.intname[0] = NULL;
270 
271 	while (fscanf(fin, "%s", cmd) != EOF) {
272 		if (cmd[0] == '#')
273 			skipline(fin);
274 		else if (strcmp(cmd, "name") == 0)
275 			fscanf(fin, "%s", font.namefont);
276 		else if (strcmp(cmd, "internalname") == 0)
277 			fscanf(fin, "%s", font.intname);
278 		else if (strcmp(cmd, "special") == 0)
279 			font.specfont = 1;
280 		else if (strcmp(cmd, "fonttab") == 0)
281 			font.fonttab = 1;
282 		else if (strcmp(cmd, "slant") == 0) {
283 			fscanf(fin, "%d", &i);
284 			font.slant = i;
285 		} else if (strcmp(cmd, "spare1") == 0) {
286 			fscanf(fin, "%1s", s1); /*MC:jna %1s will get 1 char +
287 						 * a \0 added, so
288 						 * &font.spare1 will place
289 						 * a \0 in font.name[0]
290 						 */
291 			font.spare1 = s1[0];
292 		} else if (strcmp(cmd, "ligatures") == 0) {
293 			font.ligfont = getlig(fin);
294 		} else if (strcmp(cmd, "spacewidth") == 0) {
295 			fscanf(fin, "%d", &spacewidth);
296 			width[0] = spacewidth;	/* width of space on this font */
297 		} else if (strcmp(cmd, "charset") == 0) {
298 			skipline(fin);
299 			nw = 0;
300 			/* widths are origin 1 so fitab==0 can mean "not there" */
301 			/*
302 			 *MC:jna and so width[0] can mean spacewidth
303 			 *
304 			 * note that in charset part cann't be any comments!
305 			 */
306 			while (fgets(buf, 100, fin) != NULL) {
307 				int x;
308 /*
309 printf(buf);
310 */
311 				if(font.fonttab == 1) {
312 					x = sscanf(buf, "%s %s %s %s %s", ch,s1,s2,s3,s4);
313 					if (x != 5 && s1[0] != '"')
314 						printf("sscanf mismatch %d\n", x);
315 				}
316 				else {
317 					x = sscanf(buf, "%s %s %s %s", ch, s1, s2, s3);
318 					if (x != 4 && s1[0] != '"')
319 						printf("sscanf mismatch %d\n", x);
320 				}
321 				if (s1[0] != '"') {	/* it's a genuine new character */
322 					nw++;
323 					if( nw > FSIZE) {
324 						fprintf(stderr,"Too big font!\n");
325 						exit(1);
326 					}
327 					width[nw] = atoi(s1);
328 					kern[nw] = atoi(s2);
329 					/* temporarily, pick up one byte as code */
330 					if (s3[0] == '0')
331 						sscanf(s3, "%o", &i);
332 					else
333 						sscanf(s3, "%d", &i);
334 					code[nw] = i;
335 					if(font.fonttab == 1)
336 						fcode[nw] = atoi(s4);
337 				}
338 				/* otherwise it's a synonym for previous character,
339 				/* so leave previous values intact
340 				*/
341 				if (strlen(ch) == 1) {	/* it's ascii */
342 					if(fitab[ch[0] - 32])
343 						printf("Warning: redefining character %c\n", ch[0]);
344 					fitab[ch[0] - 32] = nw;	/* fitab origin omits non-graphics */
345 				} else {		/* it has a funny name */
346 					for (i = 0; i < dev.nchtab; i++)
347 						if (strcmp(&chname[chtab[i]], ch) == 0) {
348 							if(fitab[i+128-32])
349 								printf("Warning: redefining character %s\n", ch);
350 							fitab[i + 128-32] = nw;	/* starts after the ascii */
351 							if(!nmseen[chtab[i]]) {
352 								p = &nmseen[chtab[i]];
353 								p1 = ch;
354 								while(*p1)
355 									*p++ = *p1++;
356 							}
357 							break;
358 						}
359 					if (i >= dev.nchtab)
360 						fprintf(stderr, "makedev: font %s: %s not in charset\n", name, ch);
361 				}
362 			}
363 			nw++;
364 			font.nwfont = n = nw;
365 		}
366 	}
367 	if (spacewidth == 0)
368 		width[0] = dev.res * dev.unitwidth / 72 / 3;
369 	if (font.intname[0] == NULL)
370 		fprintf(stderr, "Keyword internalname not specified\n");
371 	if (font.namefont[0] == NULL)
372 		fprintf(stderr, "Keyword fontname not specified\n");
373 	fclose(fin);
374 
375 	write(fdout, &font, sizeof(struct Font));
376 	write(fdout, width, font.nwfont & BMASK);
377 	write(fdout, kern, font.nwfont & BMASK);
378 	write(fdout, code, font.nwfont & BMASK);
379 	write(fdout, fitab, dev.nchtab+128-32);
380 	if(font.fonttab == 1)
381 		write(fdout, fcode, (font.nwfont & BMASK) * sizeof(fcode[0]));
382 	close(fdout);
383 	v = sizeof(struct Font) + 3 * n + dev.nchtab + 128-32;
384 	if(font.fonttab == 1)
385 		v += n * sizeof( short );
386 	fprintf(stderr, "%3s: %3d chars, width %3d, size %3d\n",
387 		font.namefont, nw, width[0], v);
388 	return v;
389 	/*
390 	 * MC:jna v is the filesize of one font in bytes
391 	 */
392 }
393 
getlig(fin)394 getlig(fin)	/* pick up ligature list */
395 	FILE *fin;
396 {
397 	int lig;
398 	char temp[100];
399 
400 	lig = 0;
401 	while (fscanf(fin, "%s", temp) != EOF && strcmp(temp, "0") != 0) {
402 		if (strcmp(temp, "fi") == 0)
403 			lig |= LFI;
404 		else if (strcmp(temp, "fl") == 0)
405 			lig |= LFL;
406 		else if (strcmp(temp, "ff") == 0)
407 			lig |= LFF;
408 		else if (strcmp(temp, "ffi") == 0)
409 			lig |= LFFI;
410 		else if (strcmp(temp, "ffl") == 0)
411 			lig |= LFFL;
412 		else
413 			fprintf(stderr, "illegal ligature %s\n", temp);
414 	}
415 	skipline(fin);
416 	return lig;
417 }
418 
checknames()419 checknames()
420 {	register int i, error;
421 
422 	error = 0;
423 
424 	for( i =0; i < dev.nchtab; i++) {
425 		if( !nmseen[chtab[i]]) {
426 			printf("Warning: %s not defined in any of the font(s)\n",
427 							&chname[chtab[i]]);
428 			if ( !error)
429 				error++;
430 		}
431 	}
432 	if (error) {
433 		printf("This can lead to strange results when these ");
434 		printf("characters are actually used!\n");
435 	}
436 	printf("Number of special character names: %d\n", dev.nchtab -1);
437 }
438