added makefile-defnied bit directories
[unix-history] / usr / src / local / ditroff / ditroff.old.okeeffe / driver / makevfont.c
CommitLineData
52898c9b 1/* makevfont.c (Berkeley) 85/02/26 1.5
f5eb0a89
DS
2 *
3 * Font description file producer for versatec fonts: David Slattengren
ebac57d3
DS
4 * Taken from vfontinfo by Andy Hertzfeld 4/79
5 *
eb33dc06 6 * Use: makevfont [ -nNAME ] [ -s -a -o -l -c -p# -r# -f# -ddir ]
ae72ba14 7 * [ "-xs1,s2[;s1,s2...]" ] [ "-ys1,s2[;s1,s2...]" ] font
ebac57d3 8 *
eb33dc06 9 * Makefont takes the font named "font" and produces a ditroff description
ae72ba14
DS
10 * file from it. The -n option takes the 1 or 2 letter troff name to put
11 * the description (default = XX). The -f option takes an integer per-
eb33dc06 12 * centage factor to multiply widths by. The -s, -o and -a options select
ae72ba14 13 * a different character mapping than for a "roman" font. s = special;
eb33dc06
DS
14 * o = otimespecal; a = ascii. The -l option indicates it has ligatures.
15 * The -c option tells makevfont that the font is constant width and
16 * will set parameters appropriately.
ae72ba14 17 *
eb33dc06
DS
18 * Both -x and -y options allow character name mapping. A colon separated
19 * list of comma-separated character-name pairs follows the x or y.
20 * Notice that there are no spaces in the -x or -y command. A -x pair
21 * REPLACES the definition for s1 by s2. A -y pair creates a synonym for
22 * s1 and calls it s2. -x and -y MUST be sent after -s, -m, -i, or -a
23 * if one of them is used. Some synonyms are defaulted. To remove a
24 * synonym or character, leave out s2.
ae72ba14 25 *
eb33dc06
DS
26 * The -p# option tells what point size the DESC file has as it's
27 * "unitwidth" argument (default: 36). The -r# option is the resolution
28 * of the device (default: 200, in units/inch). The -d option tells
29 * where to find fonts (default: /usr/lib/vfont).
ebac57d3
DS
30 */
31
32/*
33 * Here's an ascii character set, just in case you need it:
34
35 | 00 nul| 01 soh| 02 stx| 03 etx| 04 eot| 05 enq| 06 ack| 07 bel|
36 | 08 bs | 09 ht | 0a nl | 0b vt | 0c np | 0d cr | 0e so | 0f si |
37 | 10 dle| 11 dc1| 12 dc2| 13 dc3| 14 dc4| 15 nak| 16 syn| 17 etb|
38 | 18 can| 19 em | 1a sub| 1b esc| 1c fs | 1d gs | 1e rs | 1f us |
39 | 20 sp | 21 ! | 22 " | 23 # | 24 $ | 25 % | 26 & | 27 ' |
40 | 28 ( | 29 ) | 2a * | 2b + | 2c , | 2d - | 2e . | 2f / |
41 | 30 0 | 31 1 | 32 2 | 33 3 | 34 4 | 35 5 | 36 6 | 37 7 |
42 | 38 8 | 39 9 | 3a : | 3b ; | 3c < | 3d = | 3e > | 3f ? |
43 | 40 @ | 41 A | 42 B | 43 C | 44 D | 45 E | 46 F | 47 G |
44 | 48 H | 49 I | 4a J | 4b K | 4c L | 4d M | 4e N | 4f O |
45 | 50 P | 51 Q | 52 R | 53 S | 54 T | 55 U | 56 V | 57 W |
46 | 58 X | 59 Y | 5a Z | 5b [ | 5c \ | 5d ] | 5e ^ | 5f _ |
47 | 60 ` | 61 a | 62 b | 63 c | 64 d | 65 e | 66 f | 67 g |
48 | 68 h | 69 i | 6a j | 6b k | 6c l | 6d m | 6e n | 6f o |
49 | 70 p | 71 q | 72 r | 73 s | 74 t | 75 u | 76 v | 77 w |
50 | 78 x | 79 y | 7a z | 7b { | 7c | | 7d } | 7e ~ | 7f del|
51
52 *
53 */
54
55#include <stdio.h>
56#include <ctype.h>
57#include <vfont.h>
58
52898c9b 59char sccsid[] = "@(#)makevfont.c 1.5 (Berkeley) %G%";
ebac57d3
DS
60
61#define MAGICN 0436 /* font file magic number */
62#define PCNTUP 62 /* percent of maximum height for an ascender */
63#define PCNTDOWN 73 /* percent of maximum droop for a descender */
52898c9b 64#ifndef BITDIR
eb33dc06 65#define BITDIR "/usr/lib/vfont"
52898c9b 66#endif
ebac57d3
DS
67#define POINTSIZE 36 /* this is the "unitwidth" point size */
68#define MINSIZE 6 /* the minimum and maximum point size values */
69#define MAXSIZE 36 /* acceptible for use as "unitwidth"s */
70#define RESOLUTION 200 /* resolution of versatec (dots/inch) */
71#define MINRES 10 /* check up on resolution input by setting */
72#define MAXRES 100000 /* absurdly out-of-range limits on them */
73#define APOINT 72 /* 1/APOINT inches = 1 point */
ae72ba14
DS
74#define SYNON 100 /* 2 * pairs allowed in synonym table */
75
ebac57d3
DS
76
77struct header FontHeader;
78struct dispatch disptable[256];
79
80int res = RESOLUTION; /* resolution of the device (units/inch) */
81int pointsize = POINTSIZE; /* point size being used for unitwidth */
ae72ba14 82int factor = 100; /* percent for magnifying (shrinking) widths */
ebac57d3 83int psize; /* point size of font actually used */
ae72ba14 84int psizelist[] = { 36,24,22,20,18,16,14,28,12,11,10,9,8,7,6,0 };
ebac57d3 85
ae72ba14 86char *fontname = "XX"; /* troff font name - set on command line */
eb33dc06 87char *fontdir = BITDIR; /* place to look for fonts */
ebac57d3
DS
88char IName[100]; /* input file name put here */
89char *rdchar (); /* function makes strings for ascii */
90int FID = -1; /* input file number */
91
92int maxdown = 0; /* size of the most "droopy" character */
93int maxup = 0; /* size of the tallest character */
94int type; /* 1, 2, or 3 for type of ascend/descending */
eb33dc06 95int nullchar = -1; /* finds non-existant character in the font */
ae72ba14 96int ligsf = 0; /* flag "does this font have ligatures?" */
eb33dc06 97int constant = 0; /* flag constant width font (spacewidth, etc.)*/
ebac57d3
DS
98
99 /* following are the character maps for */
100 /* ascii code-conversion to printables... */
101char **charmap;
ae72ba14
DS
102char **synonyms;
103int numsyn;
104
ebac57d3
DS
105char *vregular[] = {
106
ae72ba14 107 "??", "fi", "fl", "ff", "\\-", "ru", "em", "bu", "sq", "Fi", "Fl", "de",
ebac57d3 108 "dg", "fm", "co", "rg", "ct", "14", "12", "34", "^T", "^U", "^V", "^W",
ae72ba14 109 "^X", "^Y", "^Z", "^[", "^\\", "^]", "^^", "^_", "", "!", "\"", "#",
ebac57d3
DS
110 "$", "%", "&", "'", "(", ")", "*", "+", ",", "-", ".", "/", "0", "1",
111 "2", "3", "4", "5", "6", "7", "8", "9", ":", ";", "<", "=", ">", "?",
112 "@", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
113 "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "[",
114 "\\", "]", "^", "_", "`", "a", "b", "c", "d", "e", "f", "g", "h", "i",
115 "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w",
ae72ba14
DS
116 "x", "y", "z", "{", "|", "}", "~", "^?",
117 (char *) 0
118};
119int nregular = 2;
120char *sregular[SYNON] = {
121 "-", "hy", "_", "\\_"
ebac57d3 122};
ae72ba14 123
ebac57d3
DS
124char *vspecial[] = {
125
ae72ba14 126 "??", "if", "ip", "pt", "rh", "cu", "rn", "bs", "+-", "<=", ">=", "sr",
ebac57d3 127 "ts", "is", "sl", "bv", "lf", "rf", "lc", "rc", "lt", "lb", "rt", "rb",
ae72ba14 128 "lk", "rk", "sb", "sp", "ca", "no", "lh", "mo", "", "!", "\"", "#",
ebac57d3
DS
129 "$", "%", "&", "aa", "gr", ")", "mu", "pl", ",", "mi", ".", "di", "==",
130 "~=", "ap", "!=", "<-", "->", "ua", "da", "sc", "**", ":", ";", "<",
131 "eq", ">", "?", "@", "*A", "*B", "*G", "*D", "*E", "*Z", "*Y", "*H",
132 "*I", "*K", "*L", "*M", "*N", "*C", "*O", "*P", "*R", "*S", "*T", "*U",
133 "*F", "*X", "*Q", "*W", "dd", "br", "ib", "\\", "ci", "^", "ul", "ga",
134 "*a", "*b", "*g", "*d", "*e", "*z", "*y", "*h", "*i", "*k", "*l", "*m",
135 "*n", "*c", "*o", "*p", "*r", "*s", "*t", "*u", "es", "*x", "*q", "*w",
ae72ba14
DS
136 "pd", "*f", "{", "|", "}", "~", "^?",
137 (char *) 0
138};
139int nspecial = 0;
140char *sspecial[SYNON] = {
141 "",""
142};
143
144char *vtimes[] = {
145
146 "??", "if", "ip", "pt", "rh", "cu", "rn", "bs", "+-", "<=", ">=", "mi",
147 "**", "pl", "eq", "gr", "lt", "lk", "lb", "rt", "rk", "rb", "ap", "mo",
148 "br", "rk", "sb", "sp", "ca", "no", "~=", "mo", "", "da", "no", "ua",
149 "sc", "dd", "if", "pd", "sb", "sp", "mu", "+-", "ca", "cu", "<-", "di",
150 "->",
151 "!=", "sr", "<=", ">=", "==", "or", "is", "bv", "lc", "rc", "lf", "rf",
152 "~=", "_", "ib", "ul", "rn", "ip", "*G", "*D", "*E", "*F", "*G", "*H",
153 "*I", "??", "*L", "*L", "*N", "*C", "*O", "*P", "*H", "*S", "*S", "*U",
154 "*U", "*X", "*W", "*C", "*Q", "br", "ib", "ga", "aa", "^", "ul", "ga",
155 "*a", "*b", "*g", "*d", "*e", "*z", "*y", "*h", "*i", "*k", "*l", "*m",
156 "*n", "*c", "*o", "*p", "*r", "*s", "*t", "*u", "es", "*x", "*q", "*w",
157 "pd", "*f", "{", "|", "}", "~", "^?",
158 (char *) 0
159};
160int ntimes = 0;
161char *stimes[SYNON] = {
162 "",""
163};
164
165
166char *vascii[] = {
eb33dc06 167 "", "da", "*a", "*b", "an", "no", "mo", "*p", "*l", "*g", "*d",
ae72ba14
DS
168 "ua", "+-", "O+", "if", "pd", "sb", "sp", "ca", "cu", "fa", "te",
169 "OX", "<>", "<-", "->", "!=", "ap", "<=", ">=", "==", "or", "",
170 "!", "\"", "#", "$", "%", "&", "'", "(", ")", "*", "+", ",", "-",
171 ".", "/", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ":", ";",
172 "<", "=", ">", "?",
173 "@", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
174 "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "[",
175 "\\", "]", "^", "_", "`", "a", "b", "c", "d", "e", "f", "g", "h", "i",
176 "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w",
eb33dc06 177 "x", "y", "z", "{", "|", "}", "~", "??",
ae72ba14
DS
178 (char *)0
179};
180int nascii = 3;
181char *sascii[SYNON] = {
182 "-", "hy", "-", "\\-", "_", "\\_"
ebac57d3
DS
183};
184
185
186main (argc, argv)
187int argc;
188char **argv;
189{
ae72ba14
DS
190 register int i; /* two indexes */
191 register int j;
192 register char *ptr; /* string traveler */
193 register char delimit; /* place for delimiters on command line */
eb33dc06
DS
194 char *replacelist = NULL; /* string of character name replacements */
195 char *synonymlist = NULL; /* string of synonym entries */
ae72ba14
DS
196 char tostring(); /* function makes a string */
197 char *nextstring(); /* moves to next string on list */
eb33dc06 198 char *operand();
ebac57d3 199
ae72ba14
DS
200
201 charmap = vregular; /* default character map */
202 synonyms = sregular;
203 numsyn = nregular;
eb33dc06
DS
204 while (--argc > 0 && *(*(++argv)) == '-') { /* do options... */
205 switch ((*argv)[1]) {
ebac57d3 206
ae72ba14
DS
207 case 's': charmap = vspecial; /* special font */
208 synonyms = sspecial;
209 numsyn = nspecial;
210 break;
211
eb33dc06 212 case 'o': charmap = vtimes; /* times special font */
ae72ba14
DS
213 synonyms = stimes;
214 numsyn = ntimes;
ebac57d3 215 break;
ae72ba14
DS
216
217 case 'a': charmap = vascii; /* ascii font */
218 synonyms = sascii;
219 numsyn = nascii;
220 break;
221
eb33dc06
DS
222 case 'c': constant = 1; /* constant width font */
223 break;
224
ae72ba14
DS
225 case 'l': ligsf = 1; /* ascii font */
226 break;
227
eb33dc06 228 case 'n': fontname = operand(&argc, &argv); /* troff font name */
ae72ba14
DS
229 break;
230
eb33dc06 231 case 'x': replacelist = operand(&argc, &argv); /* replacements */
ae72ba14
DS
232 break;
233
eb33dc06 234 case 'y': synonymlist = operand(&argc, &argv); /* synonyms */
ae72ba14
DS
235 break;
236
eb33dc06 237 case 'd': fontdir = operand(&argc, &argv); /* directory */
ebac57d3
DS
238 break;
239
eb33dc06
DS
240 case 'p': pointsize = atoi(operand(&argc, &argv)); /* point size */
241 if (pointsize < MINSIZE || pointsize > MAXSIZE)
242 error("Illegal point size: %d", pointsize);
ebac57d3
DS
243 break;
244
eb33dc06
DS
245 case 'f': factor = atoi(operand(&argc, &argv)); /* % reduction */
246 if (factor < 1 || factor > 1000)
247 error("Illegal factor: %d", factor);
ae72ba14
DS
248 break;
249
eb33dc06
DS
250 case 'r': res = atoi(operand(&argc, &argv)); /* resolution */
251 if (res < MINRES || res > MAXRES)
252 error("Illegal resolution: %d", res);
ebac57d3
DS
253 break;
254
eb33dc06
DS
255 default: error("Bad option: %c", **argv);
256 }
257 }
258 /* do character name replacements */
259 if (replacelist != NULL) {
260 ptr = replacelist;
261 while (delimit = tostring(ptr, ',')) { /* get s1 */
262 for (i = 0; charmap[i] != 0; i++) /* search for match */
263 if (strcmp (charmap[i], ptr) == 0)
264 break;
265 if (!charmap[i]) error("-x option: no match");
266 charmap[i] = ptr = nextstring(ptr); /* replace s1 */
267 delimit = tostring(ptr, ':'); /* with string s2 */
268 if (delimit) ptr = nextstring(ptr);
269 }
270 }
271 /* do the synonym list */
272 if (synonymlist != NULL) {
273 ptr = synonymlist;
274 while (delimit = tostring(ptr, ',')) { /* get s1 */
275 synonyms[2 * numsyn] = ptr; /* set on end of list */
276 ptr = nextstring(ptr); /* get string s2 */
277 delimit = tostring(ptr, ':');
278 if (*ptr) { /* if something there */
279 synonyms[2 * numsyn++ + 1] = ptr; /* add to list */
280 } else { /* otherwise remove */
281 for (i = 0; i < numsyn; i++) { /* from list */
282 if (!strcmp(synonyms[2*i],synonyms[2*numsyn])) {
283 numsyn--;
284 for (j = i--; j < numsyn; j++) {
285 synonyms[2 * j] = synonyms[2 * (j+1)];
286 synonyms[2*j + 1] = synonyms[2*j + 3];
287 }
288 }
289 }
290 }
291 if (delimit) ptr = nextstring(ptr);
292 if (numsyn > SYNON) error("out of synonym space");
ebac57d3
DS
293 }
294 }
ebac57d3 295
eb33dc06
DS
296 if (argc != 1) /* open font file */
297 error("A vfont filename must be the last operand.");
ebac57d3
DS
298 for (i = 0; FID < 0 && (psize = psizelist[i]) > 0; i++) {
299 sprintf (IName, "%s/%s.%d", fontdir, *argv, psize);
300 FID = open (IName, 0);
301 }
302 if (FID < 0) {
303 printf ("Can't find %s\n", *argv);
304 exit (8);
305 }
306
eb33dc06 307 /* read font width table */
ebac57d3 308 if (read (FID, &FontHeader, sizeof FontHeader) != sizeof FontHeader)
eb33dc06 309 error("Bad header in Font file.");
ebac57d3 310 if (read (FID, &disptable[0], sizeof disptable) != sizeof disptable)
eb33dc06 311 error("Bad dispatch table in Font file");
ebac57d3
DS
312 if (FontHeader.magic != MAGICN)
313 printf ("Magic number %o wrong\n", FontHeader.magic);
314
315
316 printf ("# Font %s, ", IName); /* head off the file */
317 printf ("max width %d, max height %d\n",
318 FontHeader.maxx, FontHeader.maxy);
ae72ba14
DS
319 printf ("name %s\n", fontname);
320 if (ligsf)
ebac57d3 321 printf ("ligatures ff fl fi ffl ffi 0\n");
ebac57d3 322
ae72ba14 323 /* pass 1 - set up maximums for ups and downs */
eb33dc06 324 for (j=0; j<256; j++) { /* and find out constant width if requested */
ebac57d3
DS
325 if (disptable[j].nbytes != 0) {
326 if (disptable[j].up > maxup) maxup = disptable[j].up;
327 if (disptable[j].down > maxdown) maxdown = disptable[j].down;
eb33dc06
DS
328 if (constant && disptable[j].width) constant = disptable[j].width;
329 } else /* find a non-existant character to put \| in */
330 if (nullchar < 0) nullchar = j;
ebac57d3
DS
331 }
332 if (maxdown == 0) maxdown = 1;
333
eb33dc06
DS
334 if (constant) {
335 constant = (factor * (pointsize * constant + psize/2) / psize) / 100;
336 printf ("spacewidth %d\n", constant);
337 }
338 printf ("# char width u/d octal\ncharset\n");
339 if (nullchar >= 0) {
340 printf ("\\| %4d 0 0%o\n\\^ %4d 0 0%o\n",
341 constant ? constant : (res*pointsize / APOINT + 4)/6, nullchar,
342 constant ? 0 : (res * pointsize / APOINT + 7) / 12, nullchar);
343 }
344
ebac57d3
DS
345/*******************************************************************************
346
347 `type' is used to determine overhangs (up/down) from percentage of
348 the maximum heights and dips. Ascenders are higher than PCNTUP%
349 of the highest, as descenders are more than PCNTDOWN%.
350 widths [i = f(width)] are calculated from the definition point
351 size (pointsize) and the one from this font (psize).
352
353*******************************************************************************/
354
355 for (j=0; j<256; j++) {
356 if (disptable[j].nbytes != 0) {
357 type = (int) (((disptable[j].up * 100) / maxup) > PCNTUP) * 2 |
358 (int) (((disptable[j].down * 100) / maxdown) > PCNTDOWN);
ae72ba14
DS
359 if (*(ptr = charmap[j])) {
360 printf ("%s %4d %d 0%o\n", ptr, (factor *
361 (pointsize * disptable[j].width + psize/2) / psize)/100,
362 type, j);
363 for (i = 0; i < numsyn; i++)
364 if (strcmp (ptr, synonyms[2 * i]) == 0)
365 printf ("%s \"\n", synonyms[2 * i + 1]);
366 }
ebac57d3 367 }
f5eb0a89
DS
368 } /* for j */
369 exit(0);
ebac57d3
DS
370}
371
ae72ba14 372
eb33dc06
DS
373/*----------------------------------------------------------------------------*
374 | Routine: char * operand (& argc, & argv)
375 |
376 | Results: returns address of the operand given with a command-line
377 | option. It uses either "-Xoperand" or "-X operand", whichever
378 | is present. The program is terminated if no option is present.
379 |
380 | Side Efct: argc and argv are updated as necessary.
381 *----------------------------------------------------------------------------*/
382
383char *operand(argcp, argvp)
384int * argcp;
385char ***argvp;
386{
387 if ((**argvp)[2]) return(**argvp + 2); /* operand immediately follows */
388 if ((--*argcp) <= 0) /* no operand */
389 error("command-line option operand missing.");
390 return(*(++(*argvp))); /* operand next word */
391}
392
393
ae72ba14
DS
394/*----------------------------------------------------------------------------*
395 | Routine: char tostring (pointer, delimitter)
396 |
397 | Results: checks string pointed to by pointer and turns it into a
398 | string at 'delimitter' by replacing it with '\0'. If the
399 | end of the string is found first, '\0' is returned; otherwise
400 | the delimitter found there is returned.
401 |
402 *----------------------------------------------------------------------------*/
403
404char tostring(p, d)
405register char *p;
406register char d;
407{
408 while (*p && *p != d) p++;
409 d = *p;
410 *p = '\0';
411 return d;
412}
413
414
415/*----------------------------------------------------------------------------*
416 | Routine: char * nextstring (pointer)
417 |
418 | Results: returns address of next string after one pointed to by
419 | pointer. The next string is after the '\0' byte.
420 |
421 *----------------------------------------------------------------------------*/
422
423char *nextstring(p)
424register char *p;
425{
426 while (*(p++));
427 return p;
428}
429
430
eb33dc06
DS
431error(s, a1, a2, a3, a4, a5)
432char *s;
ebac57d3 433{
eb33dc06
DS
434 fprintf(stderr, "makefont: ");
435 fprintf(stderr, s, a1, a2, a3, a4);
436 fprintf(stderr, "\n");
ebac57d3
DS
437 exit(8);
438}