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