1 #ifdef lint
2 static char sccsid[] = "@(#)makedev.c	1.1	(CWI)	1.1	85/03/27";
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	10	/* max number of default fonts */
101 char	fname[NFONT][10];	/* temp space to hold default font names */
102 
103 int	fflag	= 0;	/* on if font table to be written */
104 int	fdout;	/* output file descriptor */
105 char	*fout	= "DESC.out";
106 
107 main(argc, argv)
108 char *argv[];
109 {
110 	FILE *fin;
111 	char cmd[100], *p;
112 	int i, totfont, v, check;
113 
114 	if ((fin = fopen("DESC", "r")) == NULL) {
115 		fprintf(stderr, "makedev: can't open %s\n", argv[1]);
116 		exit(1);
117 	}
118 	while (fscanf(fin, "%s", cmd) != EOF) {
119 		if (cmd[0] == '#')	/* comment */
120 			skipline(fin);
121 		else if (strcmp(cmd, "res") == 0) {
122 			fscanf(fin, "%hd", &dev.res);
123 		} else if (strcmp(cmd, "hor") == 0) {
124 			fscanf(fin, "%hd", &dev.hor);
125 		} else if (strcmp(cmd, "vert") == 0) {
126 			fscanf(fin, "%hd", &dev.vert);
127 		} else if (strcmp(cmd, "unitwidth") == 0) {
128 			fscanf(fin, "%hd", &dev.unitwidth);
129 		} else if (strcmp(cmd, "sizescale") == 0) {
130 			fscanf(fin, "%hd", &dev.sizescale);
131 		} else if (strcmp(cmd, "paperwidth") == 0) {
132 			fscanf(fin, "%hd", &dev.paperwidth);
133 		} else if (strcmp(cmd, "paperlength") == 0) {
134 			fscanf(fin, "%hd", &dev.paperlength);
135 		} else if (strcmp(cmd, "spare1") == 0) {
136 			fscanf(fin, "%hd", &dev.spare1);
137 		} else if (strcmp(cmd, "spare2") == 0) {
138 			fscanf(fin, "%hd", &dev.spare2);
139 		} else if (strcmp(cmd, "sizes") == 0) {
140 			dev.nsizes = 0;
141 			while (fscanf(fin, "%d", &v) != EOF && v != 0) {
142 				size[dev.nsizes++] = v;
143 				if(dev.nsizes >= NSIZE) { /*MC:jna addition */
144 					fprintf(stderr, "Too many sizes\n");
145 					exit(3);
146 				}
147 			}
148 			size[dev.nsizes] = 0;	/* need an extra 0 at the end */
149 		} else if (strcmp(cmd, "fonts") == 0) {
150 			fscanf(fin, "%hd", &dev.nfonts);
151 			for (i = 0; i < dev.nfonts; i++) {
152 				if ( i >=  NFONT) {
153 					fprintf(stderr,"Too many default fonts\n");
154 					exit(3);
155 				}
156 				fscanf(fin, "%s", fname[i]);
157 			}
158 		} else if (strcmp(cmd, "charset") == 0) {
159 			p = chname;
160 			dev.nchtab = 0;
161 			while (fscanf(fin, "%s", p) != EOF) {
162 				chtab[dev.nchtab++] = p - chname;
163 				if (dev.nchtab > NCH) {
164 					fprintf("Too many charnames at %s\n",p);
165 					exit(3);
166 				}
167 				for (i = 0; i < dev.nchtab - 1; i++)
168 					if (strcmp(&chname[chtab[i]], p) == 0)
169 						printf("Warning: charname %s used more then once\n", p);
170 				while (*p++)	/* skip to end of name */
171 					;
172 			}
173 			dev.lchname = p - chname;
174 			chtab[dev.nchtab++] = 0;	/* terminate properly */
175 		} else
176 			fprintf(stderr, "makedev: unknown command %s\n", cmd);
177 	}
178 	if (argc > 0 && strcmp(argv[1], "DESC") == 0) {
179 		check++;
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 & BMASK);
194 			write(fdout, kern, font.nwfont & BMASK);
195 			write(fdout, code, font.nwfont & BMASK);
196 			write(fdout, fitab, dev.nchtab+128-32);
197 			if(font.fonttab == 1)
198 				write(fdout, fcode, (font.nwfont & BMASK) * sizeof(fcode[0]));
199 		}
200 		lseek(fdout, 0L, 0);	/* back to beginning to install proper size */
201 		dev.filesize =		/* excluding dev struct itself */
202 			(dev.nsizes+1) * sizeof(size[0])
203 			+ dev.nchtab * sizeof(chtab[0])
204 			+ dev.lchname * sizeof(char)
205 			+ totfont * sizeof(char);
206 		write(fdout, &dev, sizeof(struct dev));
207 		close(fdout);
208 		argc--;
209 		argv++;
210 	}
211 	for (i = 1; i < argc; i++)
212 		dofont(argv[i]);
213 	if( check)
214 		checknames();
215 	exit(0);
216 }
217 
218 dofont(name)	/* create fitab and width tab for font */
219 char *name;
220 {
221 	FILE *fin;
222 	int fdout;
223 	int i, nw, spacewidth, n, v;
224 	char buf[100], ch[10], s1[10], s2[10], s3[10],s4[10], cmd[30];
225 	char *p, *p1;
226 
227 	if ((fin = fopen(name, "r")) == NULL) {
228 		fprintf(stderr, "makedev: can't open font %s\n", name);
229 		exit(2);
230 	}
231 	sprintf(cmd, "%s.out", name);
232 	fdout = creat(cmd, 0666);
233 	for (i = 0; i < NFITAB; i++)
234 		fitab[i] = 0;
235 	for (i = 0; i < FSIZE; i++) {
236 		width[i] = kern[i] = code[i] = 0;
237 		fcode[i] = 0;
238 	}
239 	font.fonttab = font.slant = font.specfont = font.ligfont = spacewidth = 0;
240 	font.spare1 = NULL;
241 	font.namefont[0] = font.intname[0] = NULL;
242 
243 	while (fscanf(fin, "%s", cmd) != EOF) {
244 		if (cmd[0] == '#')
245 			skipline(fin);
246 		else if (strcmp(cmd, "name") == 0)
247 			fscanf(fin, "%s", font.namefont);
248 		else if (strcmp(cmd, "internalname") == 0)
249 			fscanf(fin, "%s", font.intname);
250 		else if (strcmp(cmd, "special") == 0)
251 			font.specfont = 1;
252 		else if (strcmp(cmd, "fonttab") == 0)
253 			font.fonttab = 1;
254 		else if (strcmp(cmd, "slant") == 0) {
255 			fscanf(fin, "%d", &i);
256 			font.slant = i;
257 		} else if (strcmp(cmd, "spare1") == 0) {
258 			fscanf(fin, "%1s", s1); /*MC:jna %1s will get 1 char +
259 						 * a \0 added, so
260 						 * &font.spare1 will place
261 						 * a \0 in font.name[0]
262 						 */
263 			font.spare1 = s1[0];
264 		} else if (strcmp(cmd, "ligatures") == 0) {
265 			font.ligfont = getlig(fin);
266 		} else if (strcmp(cmd, "spacewidth") == 0) {
267 			fscanf(fin, "%d", &spacewidth);
268 			width[0] = spacewidth;	/* width of space on this font */
269 		} else if (strcmp(cmd, "charset") == 0) {
270 			skipline(fin);
271 			nw = 0;
272 			/* widths are origin 1 so fitab==0 can mean "not there" */
273 			/*
274 			 *MC:jna and so width[0] can mean spacewidth
275 			 *
276 			 * note that in charset part cann't be any comments!
277 			 */
278 			while (fgets(buf, 100, fin) != NULL) {
279 				int x;
280 /*
281 printf(buf);
282 */
283 				if(font.fonttab == 1) {
284 					x = sscanf(buf, "%s %s %s %s %s", ch,s1,s2,s3,s4);
285 					if (x != 5 && s1[0] != '"')
286 						printf("sscanf mismatch %d\n", x);
287 				}
288 				else {
289 					x = sscanf(buf, "%s %s %s %s", ch, s1, s2, s3);
290 					if (x != 4 && s1[0] != '"')
291 						printf("sscanf mismatch %d\n", x);
292 				}
293 				if (s1[0] != '"') {	/* it's a genuine new character */
294 					nw++;
295 					if( nw > FSIZE) {
296 						fprintf(stderr,"Too big font!\n");
297 						exit(1);
298 					}
299 					width[nw] = atoi(s1);
300 					kern[nw] = atoi(s2);
301 					/* temporarily, pick up one byte as code */
302 					if (s3[0] == '0')
303 						sscanf(s3, "%o", &i);
304 					else
305 						sscanf(s3, "%d", &i);
306 					code[nw] = i;
307 					if(font.fonttab == 1)
308 						fcode[nw] = atoi(s4);
309 				}
310 				/* otherwise it's a synonym for previous character,
311 				/* so leave previous values intact
312 				*/
313 				if (strlen(ch) == 1) {	/* it's ascii */
314 					if(fitab[ch[0] - 32])
315 						printf("Warning: redefining character %c\n", ch[0]);
316 					fitab[ch[0] - 32] = nw;	/* fitab origin omits non-graphics */
317 				} else {		/* it has a funny name */
318 					for (i = 0; i < dev.nchtab; i++)
319 						if (strcmp(&chname[chtab[i]], ch) == 0) {
320 							if(fitab[i+128-32])
321 								printf("Warning: redefining character %s\n", ch);
322 							fitab[i + 128-32] = nw;	/* starts after the ascii */
323 							if(!nmseen[chtab[i]]) {
324 								p = &nmseen[chtab[i]];
325 								p1 = ch;
326 								while(*p1)
327 									*p++ = *p1++;
328 							}
329 							break;
330 						}
331 					if (i >= dev.nchtab)
332 						fprintf(stderr, "makedev: font %s: %s not in charset\n", name, ch);
333 				}
334 			}
335 			nw++;
336 			font.nwfont = n = nw;
337 		}
338 	}
339 	if (spacewidth == 0)
340 		width[0] = dev.res * dev.unitwidth / 72 / 3;
341 	if (font.intname[0] == NULL)
342 		fprintf(stderr, "Keyword internalname not specified\n");
343 	if (font.namefont[0] == NULL)
344 		fprintf(stderr, "Keyword fontname not specified\n");
345 	fclose(fin);
346 
347 	write(fdout, &font, sizeof(struct font));
348 	write(fdout, width, font.nwfont & BMASK);
349 	write(fdout, kern, font.nwfont & BMASK);
350 	write(fdout, code, font.nwfont & BMASK);
351 	write(fdout, fitab, dev.nchtab+128-32);
352 	if(font.fonttab == 1)
353 		write(fdout, fcode, (font.nwfont & BMASK) * sizeof(fcode[0]));
354 	close(fdout);
355 	v = sizeof(struct font) + 3 * n + dev.nchtab + 128-32;
356 	if(font.fonttab == 1)
357 		v += n * sizeof( short );
358 	fprintf(stderr, "%3s: %3d chars, width %3d, size %3d\n",
359 		font.namefont, nw, width[0], v);
360 	return v;
361 	/*
362 	 * MC:jna v is the filesize of one font in bytes
363 	 */
364 }
365 
366 getlig(fin)	/* pick up ligature list */
367 	FILE *fin;
368 {
369 	int lig;
370 	char temp[100];
371 
372 	lig = 0;
373 	while (fscanf(fin, "%s", temp) != EOF && strcmp(temp, "0") != 0) {
374 		if (strcmp(temp, "fi") == 0)
375 			lig |= LFI;
376 		else if (strcmp(temp, "fl") == 0)
377 			lig |= LFL;
378 		else if (strcmp(temp, "ff") == 0)
379 			lig |= LFF;
380 		else if (strcmp(temp, "ffi") == 0)
381 			lig |= LFFI;
382 		else if (strcmp(temp, "ffl") == 0)
383 			lig |= LFFL;
384 		else
385 			fprintf(stderr, "illegal ligature %s\n", temp);
386 	}
387 	skipline(fin);
388 	return lig;
389 }
390 
391 checknames()
392 {	register int i, error;
393 
394 	error = 0;
395 
396 	for( i =0; i < dev.nchtab; i++) {
397 		if( !nmseen[chtab[i]]) {
398 			printf("Warning: %s not defined in any of the font(s)\n",
399 							&chname[chtab[i]]);
400 			if ( !error)
401 				error++;
402 		}
403 	}
404 	if (error) {
405 		printf("This can lead to strange results when these ");
406 		printf("characters are actually used!\n");
407 	}
408 	printf("Number of special character names: %d\n", dev.nchtab -1);
409 }
410