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 2002 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 /* from OpenSolaris "makedev.c 1.7 05/06/08 SMI" */
32
33 /*
34 * Portions Copyright (c) 2005 Gunnar Ritter, Freiburg i. Br., Germany
35 *
36 * Sccsid @(#)makedev.c 1.3 (gritter) 8/9/05
37 */
38
39 /*
40 * University Copyright- Copyright (c) 1982, 1986, 1988
41 * The Regents of the University of California
42 * All Rights Reserved
43 *
44 * University Acknowledgment- Portions of this document are derived from
45 * software developed by the University of California, Berkeley, and its
46 * contributors.
47 */
48
49 /*
50 * This is a special version of makedev, tailored for the font disk
51 * of the APS-5 in the MH Computing Center. It is not to be used
52 * to set up font description files for other devices.
53 *
54 * makedev:
55 * read text info about a particular device
56 * (e.g., cat, 202, aps5) from file, convert
57 * it into internal (binary) form suitable for
58 * fast reading by troff initialization (ptinit()).
59 *
60 * Usage:
61 *
62 * makedev DESC [ F ... ]
63 * uses DESC to create a description file
64 * using the information therein.
65 * It creates the file DESC.out.
66 *
67 * makedev F ...
68 * makes the font tables for fonts F only,
69 * creates files F.out.
70 *
71 * DESC.out contains:
72 * dev structure with fundamental sizes
73 * list of sizes (nsizes+1) terminated by 0, as short's
74 * indices of char names (nchtab * sizeof (short))
75 * char names as hy\0em\0... (lchname)
76 * nfonts occurrences of
77 * widths (nwidth)
78 * kerning (nwidth) [ascender+descender only so far]
79 * codes (nwidth) to drive actual typesetter
80 * fitab (nchtab+128-32)
81 * each of these is an array of char.
82 *
83 * dev.filesize contains the number of bytes
84 * in the file, excluding the dev part itself.
85 *
86 * F.out contains the font header, width, kern, codes, and fitab.
87 * Width, kern and codes are parallel arrays.
88 * (Which suggests that they ought to be together?)
89 * Later, we might allow for codes which are actually
90 * sequences of formatting info so characters can be drawn.
91 */
92
93 #include <stdio.h>
94 #include <stdlib.h>
95 #include <unistd.h>
96 #include <string.h>
97 #include <fcntl.h>
98 #include "dev.h"
99
100 #define BYTEMASK 0377
101
102 #define SLANT_BIT 1 /* slant flag is bit 0 */
103 #define FONT_BIT 2 /* font flag is bit 1 */
104 #define RANGE_BIT 4 /* range flag is bit 2 */
105
106 #define SLANT_VAL 3 /* slant angle starts in bit 3 */
107 #define RANGE_VAL 5 /* max range starts in bit 5 */
108
109 #define skipline(f) while (getc(f) != '\n')
110
111 struct dev dev;
112 struct Font font;
113
114 #define NSIZE 100 /* maximum number of sizes */
115 short size[NSIZE];
116 #define NCH 256 /* max number of characters with funny names */
117 char chname[5*NCH]; /* character names, including \0 for each */
118 short chtab[NCH]; /* index of character in chname */
119
120 #define NFITAB (NCH + 128-32) /* includes ascii chars, but not non-graphics */
121 char fitab[NFITAB]; /* font index table: position of char i on this font. */
122 /* zero if not there */
123
124 #define FSIZE 256 /* size of a physical font (e.g., 102 for cat) */
125 char width[FSIZE]; /* width table for a physical font */
126 char kern[FSIZE]; /* ascender+descender info */
127 char code[FSIZE]; /* actual device codes for a physical font */
128 char alt_code[FSIZE]; /* code for alternate font */
129 int alt_font[FSIZE]; /* alternate font to use */
130
131 int dbg = 0; /* debug flag */
132 int verbose = 0;
133
134 #define NFONT 60 /* max number of default fonts */
135 char fname[NFONT][10]; /* temp space to hold default font names */
136
137 int fflag = 0; /* on if font table to be written */
138 int fdout; /* output file descriptor */
139 char *fout = "DESC.out";
140
141 int dofont(char *name);
142 int getlig(FILE *fin);
143 void dump_font(void);
144 void finish_line(char *buf, int nw);
145 void add_font(char *name);
146
147 int
main(int argc,char * argv[])148 main(int argc, char *argv[])
149 {
150 FILE *fin;
151 char cmd[100], *p;
152 int i, totfont, v;
153
154 if (!strcmp(argv[1], "-v")) {
155 verbose = 1;
156 argv++;
157 argc--;
158 }
159
160 if (argc < 2) {
161 fprintf(stderr, "Usage: makedev [-v] [DESC] [fonts]\n");
162 exit(1);
163 }
164
165 if ((fin = fopen("DESC", "r")) == NULL) {
166 fprintf(stderr, "makedev: can't open %s\n", argv[1]);
167 exit(1);
168 }
169 while (fscanf(fin, "%s", cmd) != EOF) {
170 if (cmd[0] == '#') /* comment */
171 skipline(fin);
172 else if (strcmp(cmd, "debug") == 0)
173 dbg++;
174 else if (strcmp(cmd, "res") == 0) {
175 fscanf(fin, "%hd", &dev.res);
176 } else if (strcmp(cmd, "hor") == 0) {
177 fscanf(fin, "%hd", &dev.hor);
178 } else if (strcmp(cmd, "vert") == 0) {
179 fscanf(fin, "%hd", &dev.vert);
180 } else if (strcmp(cmd, "unitwidth") == 0) {
181 fscanf(fin, "%hd", &dev.unitwidth);
182 } else if (strcmp(cmd, "sizescale") == 0) {
183 fscanf(fin, "%hd", &dev.sizescale);
184 } else if (strcmp(cmd, "paperwidth") == 0) {
185 fscanf(fin, "%hd", &dev.paperwidth);
186 } else if (strcmp(cmd, "paperlength") == 0) {
187 fscanf(fin, "%hd", &dev.paperlength);
188 } else if (strcmp(cmd, "biggestfont") == 0) {
189 fscanf(fin, "%hd", &dev.biggestfont);
190 } else if (strcmp(cmd, "spare2") == 0) {
191 fscanf(fin, "%hd", &dev.spare2);
192 } else if (strcmp(cmd, "sizes") == 0) {
193 dev.nsizes = 0;
194 while (fscanf(fin, "%d", &v) != EOF && v != 0)
195 size[dev.nsizes++] = v;
196 size[dev.nsizes] = 0; /* need an extra 0 at the end */
197 } else if (strcmp(cmd, "fonts") == 0) {
198 fscanf(fin, "%hd", &dev.nfonts);
199 for (i = 0; i < dev.nfonts; i++)
200 fscanf(fin, "%s", fname[i]);
201 } else if (strcmp(cmd, "charset") == 0) {
202 p = chname;
203 dev.nchtab = 0;
204 while (fscanf(fin, "%s", p) != EOF) {
205 chtab[dev.nchtab++] = p - chname;
206 while (*p++) /* skip to end of name */
207 ;
208 }
209 dev.lchname = p - chname;
210 chtab[dev.nchtab++] = 0; /* terminate properly */
211 } else
212 fprintf(stderr, "makedev: unknown command %s\n", cmd);
213 }
214 if (argc > 0 && strcmp(argv[1], "DESC") == 0) {
215 fdout = creat(fout, 0666);
216 if (fdout < 0) {
217 fprintf(stderr, "makedev: can't open %s\n", fout);
218 exit(1);
219 }
220 write(fdout, &dev, sizeof (struct dev));
221 /* we need a 0 on the end */
222 write(fdout, size, (dev.nsizes+1) * sizeof (size[0]));
223 write(fdout, chtab, dev.nchtab * sizeof (chtab[0]));
224 write(fdout, chname, dev.lchname);
225 totfont = 0;
226 for (i = 0; i < dev.nfonts; i++) {
227 totfont += dofont(fname[i]);
228 write(fdout, &font, sizeof (struct Font));
229 write(fdout, width, font.nwfont & BYTEMASK);
230 write(fdout, kern, font.nwfont & BYTEMASK);
231 write(fdout, code, font.nwfont & BYTEMASK);
232 write(fdout, fitab, dev.nchtab+128-32);
233 }
234 /* back to beginning to install proper size */
235 lseek(fdout, 0L, 0);
236 dev.filesize = /* excluding dev struct itself */
237 (dev.nsizes+1) * sizeof (size[0])
238 + dev.nchtab * sizeof (chtab[0])
239 + dev.lchname * sizeof (char)
240 + totfont * sizeof (char);
241 write(fdout, &dev, sizeof (struct dev));
242 close(fdout);
243 argc--;
244 argv++;
245 }
246 for (i = 1; i < argc; i++)
247 dofont(argv[i]);
248 exit(0);
249 }
250
251
252 int
dofont(char * name)253 dofont(char *name)
254 /* string containing name of font */
255 {
256
257
258 FILE *fin; /* input file descriptor */
259 int fdout; /* output file descriptor */
260 int i, nw = 0, spacewidth, n = 0, v;
261 char buf[100], ch[10], s1[10], s2[10], s3[10], cmd[30];
262 char s4[10]; /* used to check for extra info */
263 int count; /* value returned from sscanf() */
264 int dflt_range; /* default maximum range for font */
265 int dflt_slant; /* default slant for this font */
266
267 /*
268 * This routine is responsible for making the '.out' file for
269 * the font specified by the parameter name. It also sets up some
270 * of the data structures needed to make the DESC.out file in the
271 * main routine. In addition I have changed this routine so that
272 * we can add some typesetter dependent parameters to the font
273 * files and have this information dumped out to a 'add' file
274 * for this font, which can be read as needed by the aps driver.
275 */
276 if ((fin = fopen(name, "r")) == NULL) {
277 fprintf(stderr, "makedev: can't open font %s\n", name);
278 exit(2);
279 } /* End if */
280
281 sprintf(cmd, "%s.out", name); /* output file is name.out */
282 fdout = creat(cmd, 0666);
283
284 font.specfont = 0; /* by default it isn't special font */
285 font.ligfont = 0; /* and has no ligatures */
286 font.spare1 = 0; /* all the flags are initially off */
287 spacewidth = 0; /* really useful for CW font */
288 dflt_range = 3; /* max range available on our APS-5 */
289 dflt_slant = 0; /* no slant for this font yet */
290
291 for (i = 0; i < NFITAB; i++) /* initialize font index table */
292 fitab[i] = 0;
293
294 for (i = 0; i < FSIZE; i++) { /* initialize font index table */
295 width[i] = kern[i] = code[i] = 0;
296 alt_font[i] = 0;
297 alt_code[i] = 0;
298 } /* End for */
299
300 while (fscanf(fin, "%s", cmd) != EOF) { /* read the font file */
301
302 if (cmd[0] == '#')
303 skipline(fin);
304 else if (strcmp(cmd, "name") == 0)
305 fscanf(fin, "%s", font.namefont);
306 else if (strcmp(cmd, "internalname") == 0)
307 fscanf(fin, "%s", font.intname);
308 else if (strcmp(cmd, "special") == 0)
309 font.specfont = 1;
310 else if (strcmp(cmd, "ligatures") == 0) {
311 font.ligfont = getlig(fin);
312 } else if (strcmp(cmd, "spacewidth") == 0) {
313 fscanf(fin, "%d", &spacewidth);
314 /* width of space on this font */
315 width[0] = spacewidth;
316 } else if (strcmp(cmd, "charset") == 0) {
317 skipline(fin);
318 nw = 0;
319
320 /* widths are origin 1 so fitab==0 can mean */
321 /* "not there" */
322
323 while (fgets(buf, 100, fin) != NULL) {
324
325 count = sscanf(buf, "%s %s %s %s %s", ch, s1,
326 s2, s3, s4);
327
328 if (s1[0] != '"') {
329 /* it's a genuine new character */
330
331 nw++;
332 width[nw] = atoi(s1);
333 kern[nw] = atoi(s2);
334
335 /* temporarily, pick up one byte as */
336 /* code */
337
338 if (s3[0] == '0')
339 sscanf(s3, "%o", &i);
340 else
341 sscanf(s3, "%d", &i);
342 code[nw] = i;
343
344 if (count > 4 && font.spare1)
345 finish_line(buf, nw);
346
347 } /* End if */
348
349 /* otherwise it's a synonym for previous */
350 /* character, so leave previous values intact */
351
352 if (strlen(ch) == 1) /* it's ascii */
353 fitab[ch[0] - 32] = nw;
354 /* fitab origin omits non-graphics */
355 else { /* it has a funny name */
356 for (i = 0; i < dev.nchtab; i++)
357 if (strcmp(&chname[chtab[i]],
358 ch) == 0) {
359 /* starts after the */
360 /* ascii */
361 fitab[i + 128-32] = nw;
362 break;
363 } /* End if */
364
365 if (i >= dev.nchtab)
366 fprintf(stderr,
367 "makedev: font %s: %s not "
368 "in charset\n", name, ch);
369 } /* End else */
370
371 } /* End while */
372 nw++;
373 if (dev.biggestfont >= nw)
374 n = dev.biggestfont;
375 else {
376 if (dev.biggestfont > 0)
377 fprintf(stderr, "font %s too big\n",
378 name);
379 n = nw;
380 }
381 font.nwfont = n;
382 } else if (strcmp(cmd, "alternate_font") == 0)
383 font.spare1 |= FONT_BIT; /* set alternate font bit */
384 else if (strcmp(cmd, "default_slant") == 0) {
385 /* clear two slant val bits */
386 font.spare1 &= ~(3 << SLANT_VAL);
387 /* set font slant bit */
388 font.spare1 |= SLANT_BIT;
389 /* read the default slant value */
390 fscanf(fin, "%d", &dflt_slant);
391 if (dflt_slant > 0) /* encode it as 01 */
392 font.spare1 |= (1 << SLANT_VAL);
393 else if (dflt_slant < 0) /* encode it as 10 */
394 font.spare1 |= (1 << (SLANT_VAL + 1));
395 } else if (strcmp(cmd, "max_range") == 0) {
396 /* set range bit in spare1 */
397 font.spare1 |= RANGE_BIT;
398 /* read default font slant */
399 fscanf(fin, "%d", &dflt_range);
400 if (dflt_range < 1 || dflt_range > 4) {
401 fprintf(stderr,
402 "makedev: illegal default range %d\n",
403 dflt_range);
404 exit(1);
405 } /* End if */
406 font.spare1 |= (dflt_range << RANGE_VAL);
407 } else if (strcmp(cmd, "debug") == 0)
408 dbg++;
409
410 } /* End while */
411
412 if (spacewidth == 0)
413 width[0] = dev.res * dev.unitwidth / 72 / 3;
414 fclose(fin);
415
416 write(fdout, &font, sizeof (struct Font));
417 write(fdout, width, font.nwfont & BYTEMASK);
418 write(fdout, kern, font.nwfont & BYTEMASK);
419 write(fdout, code, font.nwfont & BYTEMASK);
420 write(fdout, fitab, dev.nchtab+128-32);
421 close(fdout);
422
423 if (font.spare1)
424 add_font(name);
425
426 if (dbg)
427 dump_font();
428
429 v = sizeof (struct Font) + 3 * n + dev.nchtab + 128-32;
430 if (verbose)
431 fprintf(stderr, "%3s: %3d chars, width %3d, size %3d\n",
432 font.namefont, nw, width[0], v);
433 return (v);
434
435 } /* End of dofont */
436
437
438 /* pick up ligature list */
439 int
getlig(FILE * fin)440 getlig(FILE *fin)
441 {
442
443
444 int lig;
445 char temp[100];
446
447
448 lig = 0;
449 while (fscanf(fin, "%s", temp) != EOF && strcmp(temp, "0") != 0) {
450 if (strcmp(temp, "fi") == 0)
451 lig |= LFI;
452 else if (strcmp(temp, "fl") == 0)
453 lig |= LFL;
454 else if (strcmp(temp, "ff") == 0)
455 lig |= LFF;
456 else if (strcmp(temp, "ffi") == 0)
457 lig |= LFFI;
458 else if (strcmp(temp, "ffl") == 0)
459 lig |= LFFL;
460 else
461 fprintf(stderr, "illegal ligature %s\n", temp);
462 }
463
464 skipline(fin);
465 return (lig);
466
467 } /* End of getlg */
468
469
470 void
finish_line(char * buf,int nw)471 finish_line(
472 char *buf, /* last input line */
473 int nw) /* data for next char goes here */
474 {
475
476
477 char s[3][20]; /* used for special char commands */
478 char v[3][20]; /* and their values */
479 int count; /* number of extra commands */
480 int range; /* largest allowed master range */
481 int angle; /* slant the character by this much */
482 int i; /* loop index */
483
484
485 /*
486 *
487 * Called from dofont() to interpret any extra fields in the current input
488 * line. The additional stuff can include one or more of the following
489 *
490 * slant n
491 * max_range n
492 * font n
493 *
494 * separated by white space and in any order. In all the above n is an
495 * integer. Comments will really screw things up so leave them out of the
496 * charset part in the APS-5 font files.
497 *
498 */
499
500
501 count = sscanf(buf, "%*s %*s %*s %*s %s %s %s %s %s %s",
502 s[0], v[0], s[1], v[1], s[2], v[2]);
503
504 if ((count % 2 != 0) || (count == 0)) {
505 fprintf(stderr, "makedev: format error in charset table\n");
506 exit(1);
507 } /* End if */
508
509 alt_code[nw] = code[nw]; /* real code will go in .add file */
510 code[nw] = 128; /* tells daps it's not a real code */
511
512 for (i = 0; i < count/2; i++) {
513
514 if (strcmp(s[i], "font") == 0) {
515 /* get char from another font */
516 /* daps checks this bit */
517 code[nw] |= FONT_BIT;
518 alt_font[nw] = atoi(v[i]); /* APS-5 font number */
519 } else if (strcmp(s[i], "max_range") == 0) {
520 code[nw] &= ~(3 << RANGE_VAL);
521 code[nw] |= RANGE_BIT;
522 range = atoi(v[i]);
523 if (range < 1 || range > 4) {
524 fprintf(stderr, "makedev: illegal range\n");
525 exit(1);
526 } /* End if */
527 code[nw] |= (range << RANGE_VAL);
528 } else if (strcmp(s[i], "slant") == 0) {
529 code[nw] &= ~(3 << SLANT_VAL);
530 code[nw] |= SLANT_BIT;
531 angle = atoi(v[i]);
532 if (angle > 0) /* again daps understands these */
533 code[nw] |= (1 << SLANT_VAL);
534 else if (angle < 0)
535 code[nw] |= (1 << (SLANT_VAL + 1));
536 } else {
537 fprintf(stderr, "makedev: illegal command\n");
538 exit(1);
539 } /* End else */
540
541 } /* End for */
542 if (code[nw] & BYTEMASK == 128) {
543 fprintf(stderr, "makedev: char code %d less than 129\n",
544 code[nw]);
545 exit(1);
546 } /* End if */
547
548 } /* End of finish_line */
549
550
551 void
add_font(char * name)552 add_font(char *name)
553 {
554
555
556 int fdout; /* output file descriptor */
557 int k; /* number of width entries */
558 char cmd[30]; /* used to create output file */
559
560
561
562 /*
563 *
564 * If there were any special requests made in the current font file we'll
565 * want to save the real data (for daps) in a binary file that ends with
566 * the suffix ".add". When daps tries to print a character and finds that
567 * it's character code bigger than 129 it knows it will need to get more
568 * real data from the appropriate .add file.
569 *
570 */
571
572
573
574 sprintf(cmd, "%s.add", name); /* file will be 'name'.add */
575 fdout = creat(cmd, 0666);
576
577 k = font.nwfont & BYTEMASK;
578
579 write(fdout, alt_font, k * sizeof (alt_font[0]));
580 write(fdout, alt_code, k);
581
582 close(fdout);
583
584 } /* End of add_font */
585
586
587 void
dump_font(void)588 dump_font(void)
589 {
590
591
592 int pos; /* position in character tables */
593 int j; /* for loop index */
594 int code_val; /* number in code table */
595
596
597
598 /*
599 *
600 * Just a debugging routine that's really not important anymore. It's
601 * called from dofont() after everything's been built for the current
602 * font file. Need to include the string "debug" in the font file that
603 * we want to check.
604 *
605 */
606
607
608 printf("DATA FOR FONT %s:\n\n", font.namefont);
609
610 printf(" font structure data:\n");
611 printf("\t\tfont.nwfont = %d\n", font.nwfont & BYTEMASK);
612 printf("\t\tfont.specfont = %d\n", font.specfont & BYTEMASK);
613 printf("\t\tfont.ligfont = %d\n", font.ligfont & BYTEMASK);
614 printf("\t\tfont.spare1 = 0%o\n", font.spare1 & BYTEMASK);
615 printf("\t\tfont.intname = %s\n\n", font.intname);
616
617 printf(" CHAR WIDTH KERN CODE INDEX\n");
618
619 for (j = 0; j < dev.nchtab + 128 - 32; j++) {
620
621 if ((pos = fitab[j] & BYTEMASK) != 0) {
622 if (j >= 96)
623 printf("%5s", &chname[chtab[j-96]]);
624 else printf("%5c", (j + 32) & BYTEMASK);
625 printf("%10d", width[pos] & BYTEMASK);
626 printf("%10d", kern[pos] & BYTEMASK);
627 code_val = code[pos] & BYTEMASK;
628 printf("%10d", code_val & BYTEMASK);
629 printf("%10d", j);
630
631 if (code_val > 128) {
632 printf("%5d", alt_code[pos] & BYTEMASK);
633 if (code_val & SLANT_BIT)
634 printf(" slant %d",
635 (code_val >> SLANT_VAL) & 03);
636 if (code_val & FONT_BIT)
637 printf(" font %d", alt_font[pos]);
638 if (code_val & RANGE_BIT)
639 printf(" range %d",
640 (code_val >> RANGE_VAL) & 03);
641 } /* End if */
642
643 printf("\n");
644 } /* End if */
645
646 } /* End for */
647
648 printf("\n\n");
649
650 } /* End of dump_font */
651