1 /*   $Id: afm2tfm.c 36523 2015-03-15 22:47:12Z kakuto $  */
2 
3 /*   Public domain, originally written by Tom Rokicki.
4  *   This program converts AFM files to TeX TFM files, and optionally
5  *   to TeX VPL files that retain all kerning and ligature information.
6  *   Both files make the characters not normally encoded by TeX available
7  *   by character codes greater than 127.
8  */
9 
10 /*   (Modified by Don Knuth from Tom Rokicki's pre-VPL version.) */
11 /*   VM/CMS port by J. Hafner (hafner@almaden.ibm.com), based on
12  *   the port by Alessio Guglielmi (guglielmi@ipisnsib.bitnet)
13  *   and Marco Prevedelli (prevedelli@ipisnsva.bitnet).
14  *   This port is still in test state.  No guarantees.
15  *   11/3/92: more corrections to VM/CMS port. Now it looks correct
16  *   and will be supported by J. Hafner.
17  *
18  */
19 /*
20  *   More changes, primarily from Karl Berry, enough for a new version
21  *   number to 8.0; 1 December 1996.  Note that this version computes
22  *   checksums differently (more intelligently).
23  */
24 
25 #ifdef KPATHSEA
26 #include "config.h"
27 #include <kpathsea/c-ctype.h>
28 #include <kpathsea/progname.h>
29 #include <kpathsea/version.h>
30 #include <math.h>
31 #else /* ! KPATHSEA */
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <ctype.h>
35 #if defined(SYSV) || defined(VMS) || defined(__THINK__) || defined(MSDOS) || defined(OS2) || defined(ATARIST) || defined(WIN32)
36 #include <string.h>
37 #else
38 #include <strings.h>
39 #endif
40 #include <math.h>
41 #ifdef ATARIST
42 #include <float.h>
43 #endif
44 #endif /* KPATHSEA */
45 
46 /* JLH: added these to make the code easier to read and remove some
47    ascii<->ebcdic dependencies */
48 #define ASCII_A 65
49 #define ASCII_Z 90
50 #define ASCII_a 97
51 #define ASCII_z 122
52 #define ASCII_0 48
53 #define ASCII_9 57
54 
55 #ifdef VMCMS
56 #define interesting lookstr  /* for 8 character truncation conflicts */
57 #include "dvipscms.h"
58 extern FILE *cmsfopen();
59 extern char ebcdic2ascii[];
60 extern char ascii2ebcdic[];
61 #ifdef fopen
62 #undef fopen
63 #endif
64 #define fopen cmsfopen
65 #endif /* VMCMS */
66 
67 #include "dvips.h"
68 /* debug.h redefines fopen to my_real_fopen, but it's still a FILE * */
69 #ifdef fopen
70 #undef fopen
71 extern FILE *fopen ();
72 #endif
73 
74 struct encoding {
75    const char *name;
76    const char *vec[256];
77 };
78 struct encoding staticencoding = {
79   "TeX text",
80   {"Gamma", "Delta", "Theta", "Lambda", "Xi", "Pi", "Sigma",
81    "Upsilon", "Phi", "Psi", "Omega", "arrowup", "arrowdown", "quotesingle",
82    "exclamdown", "questiondown", "dotlessi", "dotlessj", "grave", "acute",
83    "caron", "breve", "macron", "ring", "cedilla", "germandbls", "ae", "oe",
84    "oslash", "AE", "OE", "Oslash", "space", "exclam", "quotedbl", "numbersign",
85    "dollar", "percent", "ampersand", "quoteright", "parenleft", "parenright",
86    "asterisk", "plus", "comma", "hyphen", "period", "slash", "zero", "one",
87    "two", "three", "four", "five", "six", "seven", "eight", "nine", "colon",
88    "semicolon", "less", "equal", "greater", "question", "at", "A", "B", "C",
89    "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R",
90    "S", "T", "U", "V", "W", "X", "Y", "Z", "bracketleft", "backslash",
91    "bracketright", "circumflex", "underscore", "quoteleft", "a", "b", "c", "d",
92    "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s",
93    "t", "u", "v", "w", "x", "y", "z", "braceleft", "bar", "braceright",
94    "tilde", "dieresis", "", "", "", "", "", "", "", "", "", "", "", "", "",
95     "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
96     "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
97     "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
98     "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
99     "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
100     "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
101     "", "", "", "", "", "", "" } };
102 /*
103  *   It's easier to put this in static storage and parse it as we go
104  *   than to build the structures ourselves.
105  */
106 const char *staticligkern[] = {
107    "% LIGKERN space l =: lslash ; space L =: Lslash ;",
108    "% LIGKERN question quoteleft =: questiondown ;",
109    "% LIGKERN exclam quoteleft =: exclamdown ;",
110    "% LIGKERN hyphen hyphen =: endash ; endash hyphen =: emdash ;",
111    "% LIGKERN quoteleft quoteleft =: quotedblleft ;",
112    "% LIGKERN quoteright quoteright =: quotedblright ;",
113    "% LIGKERN space {} * ; * {} space ; zero {} * ; * {} zero ;",
114    "% LIGKERN one {} * ; * {} one ; two {} * ; * {} two ;",
115    "% LIGKERN three {} * ; * {} three ; four {} * ; * {} four ;",
116    "% LIGKERN five {} * ; * {} five ; six {} * ; * {} six ;",
117    "% LIGKERN seven {} * ; * {} seven ; eight {} * ; * {} eight ;",
118    "% LIGKERN nine {} * ; * {} nine ;",
119 /* Kern accented characters the same way as their base. */
120    "% LIGKERN Aacute <> A ; aacute <> a ;",
121    "% LIGKERN Acircumflex <> A ; acircumflex <> a ;",
122    "% LIGKERN Adieresis <> A ; adieresis <> a ;",
123    "% LIGKERN Agrave <> A ; agrave <> a ;",
124    "% LIGKERN Aring <> A ; aring <> a ;",
125    "% LIGKERN Atilde <> A ; atilde <> a ;",
126    "% LIGKERN Ccedilla <> C ; ccedilla <> c ;",
127    "% LIGKERN Eacute <> E ; eacute <> e ;",
128    "% LIGKERN Ecircumflex <> E ; ecircumflex <> e ;",
129    "% LIGKERN Edieresis <> E ; edieresis <> e ;",
130    "% LIGKERN Egrave <> E ; egrave <> e ;",
131    "% LIGKERN Iacute <> I ; iacute <> i ;",
132    "% LIGKERN Icircumflex <> I ; icircumflex <> i ;",
133    "% LIGKERN Idieresis <> I ; idieresis <> i ;",
134    "% LIGKERN Igrave <> I ; igrave <> i ;",
135    "% LIGKERN Ntilde <> N ; ntilde <> n ;",
136    "% LIGKERN Oacute <> O ; oacute <> o ;",
137    "% LIGKERN Ocircumflex <> O ; ocircumflex <> o ;",
138    "% LIGKERN Odieresis <> O ; odieresis <> o ;",
139    "% LIGKERN Ograve <> O ; ograve <> o ;",
140    "% LIGKERN Oslash <> O ; oslash <> o ;",
141    "% LIGKERN Otilde <> O ; otilde <> o ;",
142    "% LIGKERN Scaron <> S ; scaron <> s ;",
143    "% LIGKERN Uacute <> U ; uacute <> u ;",
144    "% LIGKERN Ucircumflex <> U ; ucircumflex <> u ;",
145    "% LIGKERN Udieresis <> U ; udieresis <> u ;",
146    "% LIGKERN Ugrave <> U ; ugrave <> u ;",
147    "% LIGKERN Yacute <> Y ; yacute <> y ;",
148    "% LIGKERN Ydieresis <> Y ; ydieresis <> y ;",
149    "% LIGKERN Zcaron <> Z ; zcaron <> z ;",
150 /*
151  *   These next are only included for deficient afm files that
152  *   have the lig characters but not the lig commands.
153  */
154    "% LIGKERN f i =: fi ; f l =: fl ; f f =: ff ; ff i =: ffi ;",
155    "% LIGKERN ff l =: ffl ;",
156    0 };
157 /*
158  *   The above layout corresponds to TeX Typewriter Type and is compatible
159  *   with TeX Text because the position of ligatures is immaterial.
160  */
161 struct encoding *outencoding = 0;
162 struct encoding *inencoding = 0;
163 char *outenname = NULL,
164   *inenname = NULL;/* the file names for input and output encodings */
165 int boundarychar = -1;     /* the boundary character */
166 int ignoreligkern;         /* do we look at ligkern info in the encoding? */
167 /*
168  *   This is what we store Adobe data in.
169  */
170 struct adobeinfo {
171    struct adobeinfo *next;
172    int adobenum, texnum, width;
173    const char *adobename;
174    int llx, lly, urx, ury;
175    struct lig *ligs;
176    struct kern *kerns;
177    struct adobeptr *kern_equivs;
178    struct pcc *pccs;
179    int wptr, hptr, dptr, iptr;
180 } *adobechars, *adobeptrs[256], *texptrs[256],
181   *uppercase[256], *lowercase[256];
182 int nexttex[256]; /* for characters encoded multiple times in output */
183 /*
184  *   These are the eight ligature ops, in VPL terms and in METAFONT terms.
185  */
186 const char *vplligops[] = {
187    "LIG", "/LIG", "/LIG>", "LIG/", "LIG/>", "/LIG/", "/LIG/>", "/LIG/>>", 0
188 };
189 const char *encligops[] = {
190    "=:", "|=:", "|=:>", "=:|", "=:|>", "|=:|", "|=:|>", "|=:|>>", 0
191 };
192 struct lig {
193    struct lig *next;
194    const char *succ, *sub;
195    short op, boundleft;
196 };
197 struct kern {
198    struct kern *next;
199    const char *succ;
200    int delta;
201 };
202 struct adobeptr {
203    struct adobeptr *next;
204    struct adobeinfo *ch;
205 };
206 struct pcc {
207    struct pcc *next;
208    const char * partname;
209    int xoffset, yoffset;
210 };
211 
212 FILE *afmin, *vplout, *tfmout;
213 char inname[200], outname[200]; /* names of input and output files */
214 char tmpstr[200]; /* a buffer for one string */
215 #define INBUFSIZE 1024
216 char buffer[INBUFSIZE+10]; /* input buffer (modified while parsing) */
217 char obuffer[INBUFSIZE+10]; /* unmodified copy of input buffer */
218 char *param; /* current position in input buffer */
219 const char *fontname = "Unknown";
220 const char *codingscheme = "Unspecified";
221 #ifdef VMCMS
222 char *ebfontname;
223 char *ebcodingscheme;
224 #endif
225 float italicangle = 0.0;
226 char fixedpitch;
227 char makevpl;
228 char pedantic;
229 int xheight = 400;
230 int fontspace;
231 int bc, ec;
232 long cksum;
233 float efactor = 1.0, slant = 0.0;
234 float capheight = 0.8;
235 char *efactorparam, *slantparam;
236 double newslant;
237 char titlebuf[500];
238 
239 static void
error(const char * s)240 error(const char *s)
241 {
242    fprintf(stderr, "%s\n", s);
243    if (obuffer[0]) {
244       fprintf(stderr, "%s\n", obuffer);
245       while (param > buffer) {
246          fprintf(stderr, " ");
247          param--;
248       }
249       fprintf(stderr, "^\n");
250    }
251    if (*s == '!')
252       exit(1);
253 }
254 
255 static int
transform(register int x,register int y)256 transform(register int x, register int y)
257 {
258    register double acc;
259    acc = efactor * x + slant *y;
260    return (int)(acc>=0? floor(acc+0.5) : ceil(acc-0.5) );
261 }
262 
263 static int
texlive_getline(void)264 texlive_getline(void) {
265    register char *p;
266    register int c;
267 
268    param = buffer;
269    for (p=buffer; (c=getc(afmin)) != EOF;) {
270       if (p - buffer >= INBUFSIZE)
271          error("! input line too long; perhaps input file is malformed?");
272       *p++ = c;
273       if (c == '\r') {
274          c = getc(afmin);
275          if (c != EOF) {
276             if (c == '\n') {
277                *p++ = c;
278             } else {
279                ungetc(c, afmin);
280             }
281          }
282          break;
283       } else if (c == '\n') {
284          break;
285       }
286    }
287    *p = 0;
288    strcpy(obuffer, buffer);
289    if (p == buffer && c == EOF)
290       return(0);
291    else
292       return(1);
293 }
294 
295 const char *interesting[] = { "FontName", "ItalicAngle", "IsFixedPitch",
296    "XHeight", "C", "KPX", "CC", "EncodingScheme", NULL};
297 #define FontName (0)
298 #define ItalicAngle (1)
299 #define IsFixedPitch (2)
300 #define XHeight (3)
301 #define C (4)
302 #define KPX (5)
303 #define CC (6)
304 #define EncodingScheme (7)
305 #define NONE (-1)
306 static int
interest(const char * s)307 interest(const char *s)
308 {
309    register const char **p;
310    register int n;
311 
312    for (p=interesting, n=0; *p; p++, n++)
313       if (strcmp(s, *p)==0)
314          return(n);
315    return(NONE);
316 }
317 
318 static char *
mymalloc(unsigned long len)319 mymalloc(unsigned long len)
320 {
321    register char *p;
322    int i;
323 
324 #ifdef SMALLMALLOC
325    if (len > 65500L)
326       error("! can't allocate more than 64K!");
327 #endif
328    p = (char *) malloc((unsigned)len);
329    if (p==NULL)
330       error("! out of memory");
331    for (i=0; i<len; i++)
332       p[i] = 0;
333    return(p);
334 }
335 
336 static char *
newstring(char * s)337 newstring(char *s)
338 {
339    char *q = mymalloc((unsigned long)(strlen(s) + 1));
340    strcpy(q, s);
341    return q;
342 }
343 
344 static char *
paramnewstring(void)345 paramnewstring(void) {
346    register char *p, *q;
347 
348    p = param;
349    while (*p > ' ')
350       p++;
351    if (*p != 0)
352       *p++ = 0;
353    q = newstring(param);
354    while (*p && *p <= ' ')
355       p++;
356    param = p;
357    return(q);
358 }
359 
360 static char *
paramstring(void)361 paramstring(void) {
362    register char *p, *q;
363 
364    p = param;
365    while (*p > ' ')
366       p++;
367    q = param;
368    if (*p != 0)
369       *p++ = 0;
370    while (*p && *p <= ' ')
371       p++;
372    param = p;
373    return(q);
374 }
375 
376 static int
paramnum(void)377 paramnum(void) {
378    register char *p;
379    int i;
380 
381    p = paramstring();
382    if (sscanf(p, "%d", &i) != 1)
383       error("! integer expected");
384    return(i);
385 }
386 
387 static float
paramfloat(void)388 paramfloat(void) {
389    register char *p;
390    float i;
391 
392    p = paramstring();
393    if (sscanf(p, "%f", &i) != 1)
394       error("! number expected");
395    return(i);
396 }
397 
398 static struct adobeinfo *
newchar(void)399 newchar(void) {
400    register struct adobeinfo *ai;
401 
402    ai = (struct adobeinfo *)mymalloc((unsigned long)sizeof(struct adobeinfo));
403    ai->adobenum = -1;
404    ai->texnum = -1;
405    ai->width = -1;
406    ai->adobename = NULL;
407    ai->llx = -1;
408    ai->lly = -1;
409    ai->urx = -1;
410    ai->ury = -1;
411    ai->ligs = NULL;
412    ai->kerns = NULL;
413    ai->kern_equivs = NULL;
414    ai->pccs = NULL;
415    ai->next = adobechars;
416    adobechars = ai;
417    return(ai);
418 }
419 
420 static struct kern *
newkern(void)421 newkern(void) {
422    register struct kern *nk;
423 
424    nk = (struct kern *)mymalloc((unsigned long)sizeof(struct kern));
425    nk->next = NULL;
426    nk->succ = NULL;
427    nk->delta = 0;
428    return(nk);
429 }
430 
431 static struct pcc *
newpcc(void)432 newpcc(void) {
433    register struct pcc *np;
434 
435    np = (struct pcc *)mymalloc((unsigned long)sizeof(struct pcc));
436    np->next = NULL;
437    np->partname = NULL;
438    np->xoffset = 0;
439    np->yoffset = 0;
440    return(np);
441 }
442 
443 static struct lig *
newlig(void)444 newlig(void) {
445    register struct lig *nl;
446 
447    nl = (struct lig *)mymalloc((unsigned long)sizeof(struct lig));
448    nl->next = NULL;
449    nl->succ = NULL;
450    nl->sub = NULL;
451    nl->op = 0; /* the default =: op */
452    nl->boundleft = 0;
453    return(nl);
454 }
455 
456 static void
expect(const char * s)457 expect(const char *s)
458 {
459    if (strcmp(paramstring(), s) != 0) {
460       fprintf(stderr, "%s expected: ", s);
461       error("! syntax error");
462    }
463 }
464 
465 static void
handlechar(void)466 handlechar(void) { /* an input line beginning with C */
467    register struct adobeinfo *ai;
468    register struct lig *nl;
469 
470    ai = newchar();
471    ai->adobenum = paramnum();
472    expect(";");
473    expect("WX");
474    ai->width = transform(paramnum(),0);
475    if (ai->adobenum >= 0 && ai->adobenum < 256) {
476       adobeptrs[ai->adobenum] = ai;
477    }
478    expect(";");
479 /* Ignore vertical metrics information */
480    if (*param == 'W' && *(param + 1) == 'Y') {
481       expect("WY");
482       paramnum();
483       expect(";");
484    }
485    expect("N");
486    ai->adobename = paramnewstring();
487    expect(";");
488    expect("B");
489    ai->llx = paramnum();
490    ai->lly = paramnum();
491    ai->llx = transform(ai->llx, ai->lly);
492    ai->urx = paramnum();
493    ai->ury = paramnum();
494    ai->urx = transform(ai->urx, ai->ury);
495 /* We need to avoid negative heights or depths. They break accents in
496    math mode, among other things.  */
497    if (ai->lly > 0)
498       ai->lly = 0;
499    if (ai->ury < 0)
500       ai->ury = 0;
501    expect(";");
502 /* Now look for ligatures (which aren't present in fixedpitch fonts) */
503    while (*param == 'L' && !fixedpitch) {
504       expect("L");
505       nl = newlig();
506       nl->succ = paramnewstring();
507       nl->sub = paramnewstring();
508       nl->next = ai->ligs;
509       ai->ligs = nl;
510       expect(";");
511    }
512 }
513 
514 static struct adobeinfo *
findadobe(const char * p)515 findadobe(const char *p)
516 {
517    register struct adobeinfo *ai;
518 
519    for (ai=adobechars; ai; ai = ai->next)
520       if (strcmp(p, ai->adobename)==0)
521          return(ai);
522    return(NULL);
523 }
524 
525 
526 /*
527  *   The following comment no longer applies; we rely on the LIGKERN
528  *   entries to kill space kerns.  Also, the same applies to numbers.
529  *
530  * We ignore kerns before and after space characters, because (1) TeX
531  * is using the space only for Polish ligatures, and (2) TeX's
532  * boundarychar mechanisms are not oriented to kerns (they apply
533  * to both spaces and punctuation) so we don't want to use them.
534  */
535 static void
handlekern(void)536 handlekern(void) { /* an input line beginning with KPX */
537    register struct adobeinfo *ai;
538    register char *p;
539    register struct kern *nk;
540 
541    p = paramstring();
542    ai = findadobe(p);
543    if (ai == NULL)
544       error("kern char not found");
545    else {
546       nk = newkern();
547       nk->succ = paramnewstring();
548       nk->delta = transform(paramnum(),0);
549       nk->next = ai->kerns;
550       ai->kerns = nk;
551     }
552 }
553 
554 static void
handleconstruct(void)555 handleconstruct(void) { /* an input line beginning with CC */
556    register struct adobeinfo *ai;
557    register char *p;
558    register struct pcc *np;
559    register int n;
560    struct pcc *npp = NULL;
561 
562    p = paramstring();
563    ai = findadobe(p);
564    if (ai == NULL)
565       error("! composite character name not found");
566    n = paramnum();
567    expect(";");
568    while (n--) {
569       if (strcmp(paramstring(),"PCC") != 0) return;
570         /* maybe I should expect("PCC") instead, but I'm playing it safe */
571       np = newpcc();
572       np->partname = paramnewstring();
573       if (findadobe(np->partname)==NULL) return;
574       np->xoffset = paramnum();
575       np->yoffset = paramnum();
576       np->xoffset = transform(np->xoffset, np->yoffset);
577       if (npp) npp->next = np;
578       else ai->pccs = np;
579       npp = np;
580       expect(";");
581    }
582 }
583 
584 static struct encoding *readencoding(char *);
585 
586 #if 0
587 /* Not used */
588 static void
589 makeaccentligs(void) {
590    register struct adobeinfo *ai, *aci;
591    register char *p;
592    register struct lig *nl;
593    for (ai=adobechars; ai; ai=ai->next) {
594       p = ai->adobename;
595       if (strlen(p)>2)
596          if ((aci=findadobe(p+1)) && (aci->adobenum > 127)) {
597             nl = newlig();
598             nl->succ = mymalloc((unsigned long)2);
599             *(nl->succ + 1) = 0;
600             *(nl->succ) = *p;
601             nl->sub = ai->adobename;
602             nl->next = aci->ligs;
603             aci->ligs = nl;
604          }
605    }
606 }
607 #endif
608 
609 static void
readadobe(void)610 readadobe(void) {
611    struct adobeinfo *ai;
612 #ifdef VMCMS
613     int i;
614 #endif
615 
616 /*
617  *   We allocate a placeholder boundary char.
618  */
619    ai = newchar();
620    ai->adobenum = -1;
621    ai->adobename = "||"; /* boundary character name */
622    while (texlive_getline()) {
623       switch(interest(paramstring())) {
624 case FontName:
625          fontname = paramnewstring();
626 #ifdef VMCMS
627 /* fontname comes in as ebcdic but we need it asciified for tfm file
628    so we save it in ebfontname and change it in fontname */
629    ebfontname = newstring(fontname);
630    i=0;
631    while(fontname[i] != '\0') {
632       fontname[i]=ebcdic2ascii[fontname[i]];
633       i++;
634    };
635 #endif
636          break;
637 case EncodingScheme:
638          codingscheme = paramnewstring();
639 #ifdef VMCMS
640 /* for codingscheme, we do the same as we did for fontname */
641    ebcodingscheme = newstring(codingscheme);
642    i=0;
643    while(codingscheme[i] != '\0') {
644       codingscheme[i]=ebcdic2ascii[codingscheme[i]];
645       i++;
646    }
647 #endif
648          break;
649 case ItalicAngle:
650          italicangle = paramfloat();
651          break;
652 case IsFixedPitch:
653          if (*param == 't' || *param == 'T')
654             fixedpitch = 1;
655          else
656             fixedpitch = 0;
657          break;
658 case XHeight:
659          xheight = paramnum();
660          break;
661 case C:
662          handlechar();
663          break;
664 case KPX:
665          handlekern();
666          break;
667 case CC:
668          handleconstruct();
669          break;
670 default:
671          break;
672       }
673    }
674    fclose(afmin);
675    afmin = 0;
676 }
677 /*
678  *   Re-encode the adobe font.  Assumes that the header file will
679  *   also contain the appropriate instructions!
680  */
681 static void
handlereencoding(void)682 handlereencoding(void) {
683    if (inenname) {
684       int i;
685       struct adobeinfo *ai;
686       const char *p;
687 
688       ignoreligkern = 1;
689       inencoding = readencoding(inenname);
690       for (i=0; i<256; i++)
691          if (0 != (ai=adobeptrs[i])) {
692             ai->adobenum = -1;
693             adobeptrs[i] = NULL;
694          }
695       for (i=0; i<256; i++) {
696          p = inencoding->vec[i];
697          if (p && *p && strcmp(p, ".notdef") != 0 && 0 != (ai = findadobe(p))) {
698             ai->adobenum = i;
699             adobeptrs[i] = ai;
700          }
701       }
702       codingscheme = inencoding->name;
703    }
704    ignoreligkern = 0;
705    if (outenname) {
706       outencoding = readencoding(outenname);
707    } else {
708       outencoding = readencoding((char *)0);
709    }
710 }
711 
712 /*
713  *   This routine reverses a list.  We use it because we accumulate the
714  *   adobeinfo list in reverse order, but when we go to map the
715  *   characters, we would prefer to use the original ordering.  It just
716  *   makes more sense.
717  */
718 static struct adobeinfo *
revlist(struct adobeinfo * p)719 revlist (struct adobeinfo *p)
720 {
721    struct adobeinfo *q = 0, *t;
722 
723    while (p) {
724       t = p->next;
725       p->next = q;
726       q = p;
727       p = t;
728    }
729    return q;
730 }
731 
732 static void
assignchars(void)733 assignchars(void) {
734    register const char **p;
735    register int i, j;
736    register struct adobeinfo *ai, *pai;
737    int nextfree = 128;
738    struct pcc *pcp;
739 
740 /*
741  *   First, we assign all those that match perfectly.
742  */
743    for (i=0, p=outencoding->vec; i<256; i++, p++)
744       if (*p && strcmp(*p, ".notdef") != 0 &&
745           (ai=findadobe(*p)) && (ai->adobenum >= 0 || ai->pccs != NULL)) {
746          if (ai->texnum >= 0)
747             nexttex[i] = ai->texnum; /* linked list */
748          ai->texnum = i;
749          texptrs[i] = ai;
750       }
751    if (pedantic)
752       return;
753 /*
754  *   Next, we assign all the others, retaining the adobe positions, possibly
755  *   multiply assigning characters. Unless the output encoding was
756  *   precisely specified.
757  */
758    for (ai=adobechars; ai; ai=ai->next)
759       if (ai->adobenum >= 0 && ai->adobenum <256
760           && ai->texnum < 0 && texptrs[ai->adobenum] == 0) {
761          ai->texnum = ai->adobenum;
762          texptrs[ai->adobenum] = ai;
763       }
764 /*
765  *   Finally, we map all remaining characters into free locations beginning
766  *   with 128, if we know how to construct those characters.  We need to
767  *   make sure the component pieces are mapped.
768  */
769    adobechars = revlist(adobechars);
770    for (ai=adobechars; ai; ai=ai->next)
771       if (ai->texnum<0 && (ai->adobenum>=0 || ai->pccs != NULL)) {
772          while (texptrs[nextfree]) {
773             nextfree=(nextfree+1)&255;
774             if (nextfree==128) goto finishup; /* all slots full */
775          }
776          ai->texnum = nextfree;
777          texptrs[nextfree] = ai;
778       }
779 finishup:
780 /*
781  *   We now check all of the composite characters.  If any of the
782  *   components are not mapped, we unmap the composite character.
783  */
784    for (i=0; i<256; i++) {
785       ai = texptrs[i];
786       if (ai && ai->pccs != NULL && ai->texnum >= 0) {
787          for (pcp = ai->pccs; pcp; pcp = pcp->next) {
788             pai = findadobe(pcp->partname);
789             if (pai == NULL || pai->texnum < 0) {
790                texptrs[ai->texnum] = 0;
791                ai->texnum = -1;
792                break;
793             }
794          }
795       }
796    }
797 /*
798  *   Now, if any of the characters are encoded multiple times, we want
799  *   ai->texnum to be the first one assigned, since that is most likely
800  *   to be the most important one.  So we reverse the above lists.
801  */
802    for (ai=adobechars; ai; ai=ai->next)
803       if (ai->texnum >= 0 && ai->texnum < 256) {
804          j = -1;
805          while (nexttex[ai->texnum] >= 0) {
806             i = nexttex[ai->texnum];
807             nexttex[ai->texnum] = j;
808             j = ai->texnum;
809             ai->texnum = i;
810          }
811          nexttex[ai->texnum] = j;
812       }
813 }
814 
815 static void
upmap(void)816 upmap(void) { /* Compute uppercase mapping, when making a small caps font */
817    register struct adobeinfo *ai, *Ai;
818    register const char *p;
819    register char *q;
820    register struct pcc *np, *nq;
821    int i;
822    char lwr[50];
823 
824 /* JLH: changed some lines below to be ascii<->ebcdic independent
825    any reason we don't use 'isupper'?.
826    Looks like we should use isupper to me --karl.  */
827    for (Ai=adobechars; Ai; Ai=Ai->next) {
828       p = Ai->adobename;
829       if (isupper ((unsigned char)*p)) {
830          q = lwr;
831          for (; *p; p++)
832             *q++ = TOLOWER (*p);
833          *q = '\0';   /* changed this too! */
834 
835          if (0 != (ai=findadobe(lwr))) {
836             for (i = ai->texnum; i >= 0; i = nexttex[i])
837                uppercase[i] = Ai;
838             for (i = Ai->texnum; i >= 0; i = nexttex[i])
839                lowercase[i] = ai;
840          }
841       }
842    }
843 /* Note that, contrary to the normal true/false conventions,
844  * uppercase[i] is NULL and lowercase[i] is non-NULL when i is the
845  * ASCII code of an uppercase letter; and vice versa for lowercase letters */
846 
847    if (0 != (ai=findadobe("germandbls")))
848       if (0 != (Ai=findadobe("S"))) { /* we also construct SS */
849          for (i=ai->texnum; i >= 0; i = nexttex[i])
850             uppercase[i] = ai;
851          ai->adobenum = -1;
852          ai->width = Ai->width << 1;
853          ai->llx = Ai->llx;
854          ai->lly = Ai->lly;
855          ai->urx = Ai->width + Ai->urx;
856          ai->ury = Ai->ury;
857          ai->kerns = Ai->kerns;
858          np = newpcc();
859          np->partname = "S";
860          nq = newpcc();
861          nq->partname = "S";
862          nq->xoffset = Ai->width;
863          np->next = nq;
864          ai->pccs = np;
865       }
866    if ((ai=findadobe("dotlessi")))
867       for (i=ai->texnum; i >= 0; i = nexttex[i])
868          uppercase[i] = findadobe("I");
869    if ((ai=findadobe("dotlessj")))
870       for (i=ai->texnum; i >= 0; i = nexttex[i])
871          uppercase[i] = findadobe("J");
872 }
873 /* The logic above seems to work well enough, but it leaves useless characters
874  * like `fi' and `fl' in the font if they were present initially,
875  * and it omits characters like `dotlessj' if they are absent initially */
876 
877 /* Now we turn to computing the TFM file */
878 
879 int lf, lh, nw, nh, nd, ni, nl, nk, ne, np;
880 
881 static void
write16(register short what)882 write16(register short what)
883 {
884    fputc(what >> 8, tfmout);
885    fputc(what & 255, tfmout);
886 }
887 
888 static void
writearr(register long * p,register int n)889 writearr(register long *p, register int n)
890 {
891    while (n) {
892       write16((short)(*p >> 16));
893       write16((short)(*p & 65535));
894       p++;
895       n--;
896    }
897 }
898 
899 static void
makebcpl(register long * p,register const char * s,register int n)900 makebcpl(register long *p, register const char *s, register int n)
901 {
902    register long t;
903    register long sc;
904 
905    if (strlen(s) < n)
906       n = strlen(s);
907    t = ((long)n) << 24;
908    sc = 16;
909    while (n > 0) {
910       t |= ((long)(*(unsigned const char *)s++)) << sc;
911       sc -= 8;
912       if (sc < 0) {
913          *p++ = t;
914          t = 0;
915          sc = 24;
916       }
917       n--;
918    }
919    *p++ = t;
920 }
921 
922 int source[257];
923 int unsort[257];
924 
925 /*
926  *   Next we need a routine to reduce the number of distinct dimensions
927  *   in a TFM file. Given an array what[0]...what[oldn-1], we want to
928  *   group its elements into newn clusters, in such a way that the maximum
929  *   difference between elements of a cluster is as small as possible.
930  *   Furthermore, what[0]=0, and this value must remain in a cluster by
931  *   itself. Data such as `0 4 6 7 9' with newn=3 shows that an iterative
932  *   scheme in which 6 is first clustered with 7 will not work. So we
933  *   borrow a neat algorithm from METAFONT to find the true optimum.
934  *   Memory location what[oldn] is set to 0x7fffffffL for convenience.
935  */
936 long nextd; /* smallest value that will give a different mincover */
937 static int
mincover(long * what,register long d)938 mincover(long *what,
939          register long d) /* tells how many clusters result, given max difference d */
940 {
941    register int m;
942    register long l;
943    register long *p;
944 
945    nextd = 0x7fffffffL;
946    p = what+1;
947    m = 1;
948    while (*p<0x7fffffffL) {
949       m++;
950       l = *p;
951       while (*++p <= l+d);
952       if (*p-l < nextd) nextd = *p-l;
953    }
954    return (m);
955 }
956 
957 static void
remap(long * what,int oldn,int newn)958 remap(long * what, int oldn, int newn)
959 {
960    register int i, j;
961    register long d, l;
962 
963    what[oldn] = 0x7fffffffL;
964    for (i=oldn-1; i>0; i--) {
965       d = what[i];
966       for (j=i; what[j+1]<d; j++) {
967          what[j] = what[j+1];
968          source[j] = source[j+1];
969       }
970       what[j] = d;
971       source[j] = i;
972    } /* Tom, don't let me ever catch you using bubblesort again! -- Don */
973 
974    i = mincover(what, 0L);
975    d = nextd;
976    while (mincover(what,d+d)>newn) d += d;
977    while (mincover(what,d)>newn) d = nextd;
978 
979    i = 1;
980    j = 0;
981    while (i<oldn) {
982       j++;
983       l = what[i];
984       unsort[source[i]] = j;
985       while (what[++i] <= l+d) {
986          unsort[source[i]] = j;
987          if (i-j == oldn-newn) d = 0;
988       }
989       what[j] = (l+what[i-1])/2;
990    }
991 }
992 
993 static long
checksum(void)994 checksum(void) {
995    int i;
996    unsigned long s1 = 0, s2 = 0;
997    const char *p;
998    struct adobeinfo *ai;
999 
1000    for (i=0; i<256; i++)
1001       if (0 != (ai=adobeptrs[i])) {
1002          s1 = ((s1 << 1) ^ (s1>>31)) ^ ai->width; /* cyclic left shift */
1003          s1 &= 0xffffffff; /* in case we're on a 64-bit machine */
1004          for (p=ai->adobename; *p; p++)
1005 #ifndef VMCMS
1006             s2 = (s2 * 3) + *p;
1007 #else
1008             s2 = (s2 * 3) + ebcdic2ascii[*p];
1009 #endif
1010       }
1011    s1 = (s1 << 1) ^ s2;
1012    return s1;
1013 }
1014 
1015 /*
1016  *   The next routine simply scales something.
1017  *   Input is in 1000ths of an em.  Output is in FIXFACTORths of 1000.
1018  */
1019 #define FIXFACTOR (0x100000L) /* 2^{20}, the unit fixnum */
1020 static long
scale(long what)1021 scale(long what)
1022 {
1023    return(((what / 1000) << 20) +
1024           (((what % 1000) << 20) + 500) / 1000);
1025 }
1026 
1027 long *header, *charinfo, *width, *height, *depth, *ligkern, *kern, *tparam,
1028      *italic;
1029 long *tfmdata;
1030 
1031 static void
buildtfm(void)1032 buildtfm(void) {
1033    register int i, j;
1034    register struct adobeinfo *ai;
1035 
1036    header = tfmdata;
1037    cksum = checksum();
1038    header[0] = cksum;
1039    header[1] = 0xa00000; /* 10pt design size */
1040    makebcpl(header+2, codingscheme, 39);
1041    makebcpl(header+12, fontname, 19);
1042    lh = 17;
1043    charinfo = header + lh;
1044 
1045    for (i=0; i<256 && adobeptrs[i]==NULL; i++);
1046    bc = i;
1047    for (i=255; i>=0 && adobeptrs[i]==NULL; i--);
1048    ec = i;
1049    if (ec < bc)
1050       error("! no Adobe characters");
1051 
1052    width = charinfo + (ec - bc + 1);
1053    width[0] = 0;
1054    nw++;
1055    for (i=bc; i<=ec; i++)
1056       if (0 != (ai=adobeptrs[i])) {
1057          width[nw]=ai->width;
1058          for (j=1; width[j]!=ai->width; j++);
1059          ai->wptr = j;
1060          if (j==nw)
1061             nw++;
1062       }
1063    if (nw>256)
1064       error("! 256 chars with different widths");
1065    depth = width + nw;
1066    depth[0] = 0;
1067    nd = 1;
1068    for (i=bc; i<=ec; i++)
1069       if (0 != (ai=adobeptrs[i])) {
1070          depth[nd] = -ai->lly;
1071          for (j=0; depth[j]!=-ai->lly; j++);
1072          ai->dptr = j;
1073          if (j==nd)
1074             nd++;
1075       }
1076    if (nd > 16) {
1077       remap(depth, nd, 16);
1078       nd = 16;
1079       for (i=bc; i<=ec; i++)
1080          if (0 != (ai=adobeptrs[i]))
1081             ai->dptr = unsort[ai->dptr];
1082    }
1083    height = depth + nd;
1084    height[0] = 0;
1085    nh = 1;
1086    for (i=bc; i<=ec; i++)
1087       if (0 != (ai=adobeptrs[i])) {
1088          height[nh]=ai->ury;
1089          for (j=0; height[j]!=ai->ury; j++);
1090          ai->hptr = j;
1091          if (j==nh)
1092             nh++;
1093       }
1094    if (nh > 16) {
1095       remap(height, nh, 16);
1096       nh = 16;
1097       for (i=bc; i<=ec; i++)
1098          if (0 != (ai=adobeptrs[i]))
1099             ai->hptr = unsort[ai->hptr];
1100    }
1101    italic  = height + nh;
1102    italic[0] = 0;
1103    ni = 1;
1104    for (i=bc; i<=ec; i++)
1105       if (0 != (ai=adobeptrs[i])) {
1106          italic[ni] = ai->urx - ai->width;
1107          if (italic[ni]<0)
1108             italic[ni] = 0;
1109          for (j=0; italic[j]!=italic[ni]; j++);
1110          ai->iptr = j;
1111          if (j==ni)
1112             ni++;
1113       }
1114    if (ni > 64) {
1115       remap(italic, ni, 64);
1116       ni = 64;
1117       for (i=bc; i<=ec; i++)
1118          if (0 != (ai=adobeptrs[i]))
1119             ai->iptr = unsort[ai->iptr];
1120    }
1121 
1122    for (i=bc; i<=ec; i++)
1123       if (0 != (ai=adobeptrs[i]))
1124          charinfo[i-bc] = ((long)(ai->wptr)<<24) +
1125                            ((long)(ai->hptr)<<20) +
1126                             ((long)(ai->dptr)<<16) +
1127                              ((long)(ai->iptr)<<10);
1128 
1129    ligkern = italic + ni;
1130    nl = 0; /* ligatures and kerns omitted from raw Adobe font */
1131    kern = ligkern + nl;
1132    nk = 0;
1133 
1134    newslant = (double)slant - efactor * tan(italicangle*(3.1415926535/180.0));
1135    tparam = kern + nk;
1136    tparam[0] = (long)(FIXFACTOR * newslant + 0.5);
1137    tparam[1] = scale((long)fontspace);
1138    tparam[2] = (fixedpitch ? 0 : scale((long)(300*efactor+0.5)));
1139    tparam[3] = (fixedpitch ? 0 : scale((long)(100*efactor+0.5)));
1140    tparam[4] = scale((long)xheight);
1141    tparam[5] = scale((long)(1000*efactor+0.5));
1142    np = 6;
1143 }
1144 
1145 static void
writesarr(long * what,int len)1146 writesarr(long *what, int len)
1147 {
1148    register long *p;
1149    int i;
1150 
1151    p = what;
1152    i = len;
1153    while (i) {
1154       *p = scale(*p);
1155       scale(*p); /* need this kludge for some compilers */
1156       p++;
1157       i--;
1158    }
1159    writearr(what, len);
1160 }
1161 
1162 static void
writetfm(void)1163 writetfm(void) {
1164    lf = 6 + lh + (ec - bc + 1) + nw + nh + nd + ni + nl + nk + ne + np;
1165    write16((short)lf);
1166    write16((short)lh);
1167    write16((short)bc);
1168    write16((short)ec);
1169    write16((short)nw);
1170    write16((short)nh);
1171    write16((short)nd);
1172    write16((short)ni);
1173    write16((short)nl);
1174    write16((short)nk);
1175    write16((short)ne);
1176    write16((short)np);
1177    writearr(header, lh);
1178    writearr(charinfo, ec-bc+1);
1179    writesarr(width, nw);
1180    writesarr(height, nh);
1181    writesarr(depth, nd);
1182    writesarr(italic, ni);
1183    writearr(ligkern, nl);
1184    writesarr(kern, nk);
1185    writearr(tparam, np);
1186 }
1187 
1188 /* OK, the TFM file is done! Now for our next trick, the VPL file. */
1189 
1190 /* For TeX we want to compute a character height that works properly
1191  * with accents. The following list of accents doesn't need to be complete. */
1192 /*
1193  *   We only do this if the xheight has a reasonable value.
1194  *   (>50)
1195  */
1196 const char *accents[] = { "acute", "tilde", "caron", "dieresis", NULL};
1197 static int
texheight(register struct adobeinfo * ai)1198 texheight(register struct adobeinfo *ai)
1199 {
1200    register const char **p;
1201    register struct adobeinfo *aci, *acci;
1202    if (xheight <= 50 || *(ai->adobename + 1)) return (ai->ury);
1203                                            /* that was the simple case */
1204    for (p=accents; *p; p++)  /* otherwise we look for accented letters */
1205       if (0 != (aci=findadobe(*p))) {
1206          strcpy(buffer,ai->adobename);
1207          strcat(buffer,*p);
1208          if (0 != (acci=findadobe(buffer)))
1209             return (acci->ury - aci->ury + xheight);
1210       }
1211    return (ai->ury);
1212 }
1213 
1214 /* modified tgr to eliminate varargs problems */
1215 
1216 #define vout(s)  fprintf(vplout, s)
1217 int level; /* the depth of parenthesis nesting in VPL file being written */
1218 static void
vlevout(void)1219 vlevout(void)
1220 {
1221    register int l = level;
1222    while (l--) vout("   ");
1223 }
1224 static void
vlevnlout(void)1225 vlevnlout(void)
1226 {
1227    vout("\n");
1228    vlevout();
1229 }
1230 #define voutln(str) {fprintf(vplout,"%s\n",str);vlevout();}
1231 #define voutln2(f,s) {fprintf(vplout,f,s);vlevnlout();}
1232 #define voutln3(f,a,b) {fprintf(vplout,f,a,b);vlevnlout();}
1233 #define voutln4(f,a,b,c) {fprintf(vplout,f,a,b,c);vlevnlout();}
1234 static void
vleft(void)1235 vleft(void)
1236 {
1237    level++;
1238    vout("(");
1239 }
1240 
1241 static void
vright(void)1242 vright(void)
1243 {
1244    level--;
1245    voutln(")");
1246 }
1247 
1248 int forceoctal = 0;
1249 
1250 char vcharbuf[100];
1251 static char *
vchar(int c)1252 vchar(int c)
1253 {
1254    if (forceoctal == 0 && ISALNUM (c))
1255       sprintf(vcharbuf,"C %c",
1256 #ifndef VMCMS
1257       c);
1258 #else
1259       ascii2ebcdic[c]);
1260 #endif
1261    else sprintf(vcharbuf,"O %o", (unsigned)c);
1262    return vcharbuf;
1263 }
1264 
1265 char vnamebuf[1000];
1266 static char *
vname(int c)1267 vname(int c)
1268 {
1269   if (!forceoctal && ISALNUM (c)) {
1270     vnamebuf[0] = 0;
1271   } else if (c >= 0 && c < 256) {
1272     snprintf (vnamebuf, sizeof (vnamebuf),
1273               " (comment %s)", texptrs[c]->adobename);
1274   }
1275   return vnamebuf;
1276 }
1277 
1278 static void
writevpl(void)1279 writevpl(void)
1280 {
1281    register int i, j, k;
1282    register struct adobeinfo *ai;
1283    register struct lig *nlig;
1284    register struct kern *nkern;
1285    register struct pcc *npcc;
1286    struct adobeinfo *asucc, *asub, *api;
1287    struct adobeptr *kern_eq;
1288    int xoff, yoff, ht;
1289    char unlabeled;
1290 
1291    voutln2("(VTITLE Created by %s)", titlebuf);
1292    voutln("(COMMENT Please edit that VTITLE if you edit this file)");
1293    snprintf(obuffer, sizeof(obuffer), "TeX-%s%s%s%s", outname,
1294       (efactor==1.0? "" : "-E"), (slant==0.0? "" : "-S"),
1295                  (makevpl==1? "" : "-CSC"));
1296    if (strlen(obuffer)>19) { /* too long, will retain first 9 and last 10 */
1297       register char *p, *q;
1298       for (p = &obuffer[9], q = &obuffer[strlen(obuffer)-10]; p<&obuffer[19];
1299               p++, q++) *p = *q;
1300       obuffer[19] = '\0';
1301    }
1302    voutln2("(FAMILY %s)" , obuffer);
1303    {
1304       char tbuf[300];
1305       const char *base_encoding =
1306 #ifndef VMCMS
1307          codingscheme;
1308 #else
1309          ebcodingscheme;
1310 #endif
1311 
1312       if (strcmp (outencoding->name, base_encoding) == 0) {
1313         snprintf(tbuf, sizeof(tbuf), "%s", outencoding->name);
1314       } else {
1315         snprintf(tbuf, sizeof(tbuf), "%s + %s", base_encoding,
1316                  outencoding->name);
1317       }
1318 
1319       if (strlen(tbuf) > 39) {
1320          error("Coding scheme too long; shortening to 39 characters.");
1321          tbuf[39] = 0;
1322       }
1323       voutln2("(CODINGSCHEME %s)", tbuf);
1324    }
1325    voutln("(DESIGNSIZE R 10.0)");
1326    voutln("(DESIGNUNITS R 1000)");
1327    voutln("(COMMENT DESIGNSIZE (1 em) IS IN POINTS)");
1328    voutln("(COMMENT OTHER DIMENSIONS ARE MULTIPLES OF DESIGNSIZE/1000)");
1329    /* Let vptovf compute the checksum. */
1330    /* voutln2("(CHECKSUM O %lo)",cksum ^ 0xffffffff); */
1331    if (boundarychar >= 0)
1332       voutln2("(BOUNDARYCHAR O %lo)", (unsigned long)boundarychar);
1333    vleft(); voutln("FONTDIMEN");
1334    if (newslant)
1335       voutln2("(SLANT R %f)", newslant);
1336    voutln2("(SPACE D %d)", fontspace);
1337    if (! fixedpitch) {
1338       voutln2("(STRETCH D %d)", transform(200,0));
1339       voutln2("(SHRINK D %d)", transform(100,0));
1340    }
1341    voutln2("(XHEIGHT D %d)", xheight);
1342    voutln2("(QUAD D %d)", transform(1000,0));
1343    voutln2("(EXTRASPACE D %d)", fixedpitch ? fontspace : transform(111, 0));
1344    vright();
1345    vleft(); voutln("MAPFONT D 0");
1346    voutln2("(FONTNAME %s)", outname);
1347    /* voutln2("(FONTCHECKSUM O %lo)", (unsigned long)cksum); */
1348    vright();
1349    if (makevpl>1) {
1350       vleft(); voutln("MAPFONT D 1");
1351       voutln2("(FONTNAME %s)", outname);
1352       voutln2("(FONTAT D %d)", (int)(1000.0*capheight+0.5));
1353       /* voutln2("(FONTCHECKSUM O %lo)", (unsigned long)cksum); */
1354       vright();
1355    }
1356 
1357    for (i=0; i<256 && texptrs[i]==NULL; i++);
1358    bc = i;
1359    for (i=255; i>=0 && texptrs[i]==NULL; i--);
1360    ec = i;
1361 
1362    vleft(); voutln("LIGTABLE");
1363    ai = findadobe("||");
1364    unlabeled = 1;
1365    for (nlig=ai->ligs; nlig; nlig=nlig->next)
1366       if (0 != (asucc=findadobe(nlig->succ))) {
1367          if (0 != (asub=findadobe(nlig->sub)))
1368             if (asucc->texnum>=0)
1369                if (asub->texnum>=0) {
1370                   if (unlabeled) {
1371                      voutln("(LABEL BOUNDARYCHAR)");
1372                      unlabeled = 0;
1373                   }
1374                   for (j = asucc->texnum; j >= 0; j = nexttex[j]) {
1375                      voutln4("(%s %s O %o)", vplligops[nlig->op],
1376                          vchar(j), (unsigned)asub->texnum);
1377                   }
1378                }
1379        }
1380    if (! unlabeled) voutln("(STOP)");
1381    for (i=bc; i<=ec; i++)
1382       if ((ai=texptrs[i]) && ai->texnum == i) {
1383          unlabeled = 1;
1384          if (uppercase[i]==NULL) /* omit ligatures from smallcap lowercase */
1385             for (nlig=ai->ligs; nlig; nlig=nlig->next)
1386                if (0 != (asucc=findadobe(nlig->succ)))
1387                   if (0 != (asub=findadobe(nlig->sub)))
1388                      if (asucc->texnum>=0)
1389                         if (asub->texnum>=0) {
1390                            if (unlabeled) {
1391                               for (j = ai->texnum; j >= 0; j = nexttex[j])
1392                                  voutln3("(LABEL %s)%s", vchar(j), vname(j));
1393                               unlabeled = 0;
1394                            }
1395                            for (j = asucc->texnum; j >= 0; j = nexttex[j]) {
1396                               voutln4("(%s %s O %o)", vplligops[nlig->op],
1397                                    vchar(j), (unsigned)asub->texnum);
1398                               if (nlig->boundleft)
1399                                  break;
1400                            }
1401                         }
1402          for (nkern = (uppercase[i] ? uppercase[i]->kerns : ai->kerns);
1403                     nkern; nkern=nkern->next)
1404             if (0 != (asucc=findadobe(nkern->succ)))
1405                for (j = asucc->texnum; j >= 0; j = nexttex[j]) {
1406                   if (uppercase[j]==NULL) {
1407                      if (unlabeled) {
1408                         for (k = ai->texnum; k >= 0; k = nexttex[k])
1409                            voutln3("(LABEL %s)%s", vchar(k), vname(k));
1410                         unlabeled = 0;
1411                      }
1412                      /* If other characters have the same kerns as this
1413                         one, output the label here.  This makes the TFM
1414                         file much smaller than if we output all the
1415                         kerns again under a different label.  */
1416                      for (kern_eq = ai->kern_equivs; kern_eq;
1417                           kern_eq = kern_eq->next) {
1418                         k = kern_eq->ch->texnum;
1419                         if (k >= 0 && k < 256)
1420                           voutln3("(LABEL %s)%s", vchar(k), vname(k));
1421                      }
1422                      ai->kern_equivs = 0; /* Only output those labels once. */
1423                      if (uppercase[i]) {
1424                         if (lowercase[j]) {
1425                            for (k=lowercase[j]->texnum; k >= 0; k = nexttex[k])
1426                               voutln4("(KRN %s R %.1f)%s", vchar(k),
1427                                     capheight*nkern->delta, vname(k));
1428                         } else voutln4("(KRN %s R %.1f)%s",
1429                                  vchar(j), capheight*nkern->delta, vname(j));
1430                      } else {
1431                         voutln4("(KRN %s R %d)%s", vchar(j),
1432                                 nkern->delta, vname(j));
1433                         if (lowercase[j])
1434                            for (k=lowercase[j]->texnum; k >= 0; k = nexttex[k])
1435                               voutln4("(KRN %s R %.1f)%s", vchar(k),
1436                                 capheight*nkern->delta, vname(k));
1437                      }
1438                   }
1439                }
1440          if (! unlabeled) voutln("(STOP)");
1441       }
1442    vright();
1443 
1444    for (i=bc; i<=ec; i++)
1445       if (0 != (ai=texptrs[i])) {
1446          vleft(); fprintf(vplout, "CHARACTER %s", vchar(i));
1447          if (*vcharbuf=='C') {
1448             voutln("");
1449          } else
1450             voutln2(" (comment %s)", ai->adobename);
1451          if (uppercase[i]) {
1452             ai=uppercase[i];
1453             voutln2("(CHARWD R %.1f)", capheight * (ai->width));
1454             if (0 != (ht=texheight(ai)))
1455                voutln2("(CHARHT R %.1f)", capheight * ht);
1456             if (ai->lly)
1457                voutln2("(CHARDP R %.1f)", -capheight * ai->lly);
1458             if (ai->urx > ai->width)
1459                voutln2("(CHARIC R %.1f)", capheight * (ai->urx - ai->width));
1460          } else {
1461             voutln2("(CHARWD R %d)", ai->width);
1462             if (0 != (ht=texheight(ai)))
1463                voutln2("(CHARHT R %d)", ht);
1464             if (ai->lly)
1465                voutln2("(CHARDP R %d)", -ai->lly);
1466             if (ai->urx > ai->width)
1467                voutln2("(CHARIC R %d)", ai->urx - ai->width);
1468          }
1469          if (ai->adobenum != i || uppercase[i]) {
1470             vleft(); voutln("MAP");
1471             if (uppercase[i]) voutln("(SELECTFONT D 1)");
1472             if (ai->pccs && ai->adobenum < 0) {
1473                xoff = 0; yoff = 0;
1474                for (npcc = ai->pccs; npcc; npcc=npcc->next)
1475                   if (0 != (api=findadobe(npcc->partname)))
1476                      if (api->texnum>=0) {
1477                         if (npcc->xoffset != xoff) {
1478                            if (uppercase[i]) {
1479                               voutln2("(MOVERIGHT R %.1f)",
1480                                       capheight * (npcc->xoffset - xoff));
1481                            } else voutln2("(MOVERIGHT R %d)",
1482                                       npcc->xoffset - xoff);
1483                            xoff = npcc->xoffset;
1484                         }
1485                         if (npcc->yoffset != yoff) {
1486                            if (uppercase[i]) {
1487                               voutln2("(MOVEUP R %.1f)",
1488                                       capheight * (npcc->yoffset - yoff));
1489                            } else voutln2("(MOVEUP R %d)",
1490                                       npcc->yoffset - yoff);
1491                            yoff = npcc->yoffset;
1492                         }
1493                         voutln2("(SETCHAR O %o)", (unsigned)api->adobenum);
1494                         xoff += texptrs[api->texnum]->width;
1495                      }
1496             } else voutln2("(SETCHAR O %o)", (unsigned)ai->adobenum);
1497             vright();
1498          }
1499          vright();
1500       }
1501    if (level) error("! I forgot to match the parentheses");
1502 }
1503 
1504 #ifdef KPATHSEA
1505 static void
version(FILE * f)1506 version(FILE *f)
1507 {
1508   fputs ("afm2tfm(k) (dvips(k) 5.995) 8.3\n", f);
1509   fprintf (f, "%s\n", kpathsea_version_string);
1510   fputs ("Copyright 2015 Radical Eye Software.\n\
1511 There is NO warranty.  You may redistribute this software\n\
1512 under the terms of the GNU General Public License\n\
1513 and the Dvips copyright.\n\
1514 For more information about these matters, see the files\n\
1515 named COPYING and afm2tfm.c.\n\
1516 Original author of afm2tfm: T. Rokicki.\n", f);
1517 }
1518 
1519 #define USAGE "\
1520   Convert an Adobe font metric file to TeX font metric format.\n\
1521 \n\
1522 -c REAL             use REAL for height of small caps made with -V [0.8]\n\
1523 -e REAL             widen (extend) characters by a factor of REAL\n\
1524 -O                  use octal for all character codes in the vpl file\n\
1525 -p ENCFILE          read/download ENCFILE for the PostScript encoding\n\
1526 -s REAL             oblique (slant) characters by REAL, generally <<1\n\
1527 -t ENCFILE          read ENCFILE for the encoding of the vpl file\n\
1528 -T ENCFILE          equivalent to -p ENCFILE -t ENCFILE\n\
1529 -u                  output only characters from encodings, nothing extra\n\
1530 -v FILE[.vpl]       make a VPL file for conversion to VF\n\
1531 -V SCFILE[.vpl]     like -v, but synthesize smallcaps as lowercase\n\
1532 --help              print this message and exit.\n\
1533 --version           print version number and exit.\n\
1534 "
1535 
1536 static void
usage(FILE * f)1537 usage(FILE *f)
1538 {
1539    fputs ("Usage: afm2tfm FILE[.afm] [OPTION]... [FILE[.tfm]]\n", f);
1540    fputs (USAGE, f);
1541    putc ('\n', f);
1542    fputs (kpse_bug_address, f);
1543 }
1544 #else /* ! KPATHSEA */
1545 static void
usage(FILE * f)1546 usage(FILE *f)
1547 {
1548    fprintf(f,
1549  "afm2tfm 8.1, Copyright 1990-97 by Radical Eye Software\n");
1550    fprintf(f,
1551  "Usage: afm2tfm foo[.afm] [-O] [-u] [-v|-V bar[.vpl]]\n");
1552    fprintf(f,
1553  "                 [-e expansion] [-s slant] [-c capheight]\n");
1554    fprintf(f,
1555  "                 [-p|-t|-T encodingfile] [foo[.tfm]]\n");
1556 }
1557 #endif
1558 
1559 #define CHECKARG3 if (argc < 4) { usage(stderr); exit(1); }
1560 
1561 static void
openfiles(int argc,char ** argv)1562 openfiles(int argc, char **argv)
1563 {
1564 #ifndef KPATHSEA
1565    register int lastext;
1566 #else
1567    const char *q;
1568 #endif
1569    register int i;
1570    const char *p;
1571    int arginc;
1572 
1573    tfmout = (FILE *)NULL;
1574 
1575    if (argc == 1) {
1576       usage(stdout);
1577       exit(0);
1578    }
1579 
1580 #if defined(MSDOS) || defined(OS2) || defined(ATARIST)
1581    /* Make VPL file identical to that created under Unix */
1582    snprintf(titlebuf, sizeof(titlebuf), "afm2tfm %s", argv[1]);
1583 #else
1584 #ifdef VMCMS
1585    /* Make VPL file identical to that created under Unix */
1586    snprintf(titlebuf, sizeof(titlebuf), "afm2tfm %s", argv[1]);
1587 #else
1588    snprintf(titlebuf, sizeof(titlebuf), "%s %s", argv[0], argv[1]);
1589 #endif
1590 #endif
1591    strcpy(inname, argv[1]);
1592 #ifdef KPATHSEA
1593    if (find_suffix(inname) == NULL)
1594        strcat(inname, ".afm");
1595 #else
1596    lastext = -1;
1597    for (i=0; inname[i]; i++)
1598       if (inname[i] == '.')
1599          lastext = i;
1600       else if (inname[i] == '/' || inname[i] == ':')
1601          lastext = -1;
1602    if (lastext == -1) strcat(inname, ".afm");
1603 #endif
1604    while (argc>2 && *argv[2]=='-') {
1605       arginc = 2;
1606       i = argv[2][1];
1607       if (i == '/')
1608          i = argv[2][2] - 32; /* /a ==> A for VMS */
1609       switch (i) {
1610 case 'V': makevpl++;
1611 case 'v': makevpl++;
1612          CHECKARG3
1613          strcpy(outname, argv[3]);
1614 #ifdef KPATHSEA
1615          if (find_suffix(outname) == NULL)
1616             strcat(outname, ".vpl");
1617 #else
1618          lastext = -1;
1619          for (i=0; outname[i]; i++)
1620             if (outname[i] == '.')
1621                lastext = i;
1622             else if (outname[i] == '/' || outname[i] == ':')
1623                lastext = -1;
1624          if (lastext == -1) strcat(outname, ".vpl");
1625 #endif
1626 #ifndef VMCMS
1627 #ifndef ATARIST
1628          if ((vplout=fopen(outname, WRITEBIN))==NULL)
1629 #else
1630          if ((vplout=fopen(outname, "w"))==NULL)
1631 #endif
1632 #else
1633          if ((vplout=fopen(outname, "w"))==NULL)
1634 #endif
1635             error("! can't open vpl output file");
1636          break;
1637 case 'e': CHECKARG3
1638           if (sscanf(argv[3], "%f", &efactor)==0 || efactor<0.01)
1639             error("! Bad extension factor");
1640          efactorparam = argv[3];
1641          break;
1642 case 'c':
1643          CHECKARG3
1644          if (sscanf(argv[3], "%f", &capheight)==0 || capheight<0.01)
1645             error("! Bad small caps height");
1646          break;
1647 case 's':
1648          CHECKARG3
1649          if (sscanf(argv[3], "%f", &slant)==0)
1650             error("! Bad slant parameter");
1651          slantparam = argv[3];
1652          break;
1653 case 'P':
1654 case 'p':
1655          CHECKARG3
1656          inenname = argv[3];
1657          break;
1658 case 'T':
1659          CHECKARG3
1660          inenname = outenname = argv[3];
1661          break;
1662 case 't':
1663          CHECKARG3
1664          outenname = argv[3];
1665          break;
1666 case 'O':
1667          forceoctal = 1;
1668          arginc = 1;
1669          break;
1670 case 'u':
1671          pedantic = 1;
1672          arginc = 1;
1673          break;
1674 default: fprintf(stderr, "Unknown option %s %s ignored.\n", argv[2], argv[3]);
1675       }
1676       for (i=0; i<arginc; i++) {
1677          snprintf(titlebuf + strlen(titlebuf),
1678                   sizeof(titlebuf) - strlen(titlebuf), " %s", argv[2]);
1679          argv++;
1680          argc--;
1681       }
1682    }
1683 
1684 #ifdef KPATHSEA
1685    afmin = kpse_open_file (inname, kpse_afm_format);
1686 #else /* ! KPATHSEA */
1687    if ((afmin=fopen(inname, "r"))==NULL)
1688       error("! can't open afm input file");
1689 #endif /* KPATHSEA */
1690    SET_BINARY(fileno(afmin));
1691 
1692    if (argc>3 || (argc==3 && *argv[2]=='-')) {
1693      error("! need at most two non-option arguments");
1694      usage(stderr);
1695    }
1696 
1697    if (argc == 2) strcpy(outname, inname);
1698    else strcpy(outname, argv[2]);
1699 
1700 #ifdef KPATHSEA
1701    if ((p = find_suffix(outname)) != NULL)
1702       outname[p-outname-1] = 0;
1703    strcat(outname, ".tfm");
1704    if (tfmout == NULL && (tfmout=fopen(outname, WRITEBIN))==NULL)
1705       error("! can't open tfm output file");
1706 /*
1707  *   Now we strip off any directory information, so we only use the
1708  *   base name in the vf file.
1709  */
1710    if (p == NULL)
1711      p = find_suffix(outname);
1712    outname[p-outname-1] = 0;
1713 
1714    q = xbasename(outname);
1715    strcpy(tmpstr, q);        /* be careful, q and outname are overlapping */
1716    strcpy(outname, tmpstr);
1717 #else
1718    lastext = -1;
1719    for (i=0; outname[i]; i++)
1720       if (outname[i] == '.')
1721          lastext = i;
1722       else if (outname[i] == '/' || outname[i] == ':' || outname[i] == '\\')
1723          lastext = -1;
1724    if (argc == 2) {
1725       outname[lastext] = 0;
1726       lastext = -1;
1727    }
1728    if (lastext == -1) {
1729       lastext = strlen(outname);
1730       strcat(outname, ".tfm");
1731    }
1732    if (tfmout == NULL && (tfmout=fopen(outname, WRITEBIN))==NULL)
1733       error("! can't open tfm output file");
1734    outname[lastext] = 0;
1735 /*
1736  *   Now we strip off any directory information, so we only use the
1737  *   base name in the vf file.  We accept any of /, :, or \ as directory
1738  *   delimiters, so none of these are available for use inside the
1739  *   base name; this shouldn't be a problem.
1740  */
1741    for (i=0, lastext=0; outname[i]; i++)
1742       if (outname[i] == '/' || outname[i] == ':' || outname[i] == '\\')
1743          lastext = i + 1;
1744    if (lastext)
1745       strcpy(outname, outname + lastext);
1746 #endif
1747 }
1748 /*
1749  *   Some routines to remove kerns that match certain patterns.
1750  */
1751 static struct kern *
rmkernmatch(struct kern * k,char * s)1752 rmkernmatch(struct kern *k, char *s)
1753 {
1754    struct kern *nkern;
1755 
1756    while (k && strcmp(k->succ, s)==0)
1757       k = k->next;
1758    if (k) {
1759       for (nkern = k; nkern; nkern = nkern->next)
1760          while (nkern->next && strcmp(nkern->next->succ, s)==0)
1761             nkern->next = nkern->next->next;
1762    }
1763    return k;
1764 }
1765 /*
1766  *   Recursive to one level.
1767  */
1768 static void
rmkern(char * s1,char * s2,struct adobeinfo * ai)1769 rmkern(char *s1, char *s2, struct adobeinfo *ai)
1770 {
1771    if (ai == 0) {
1772       if (strcmp(s1, "*") == 0) {
1773          for (ai=adobechars; ai; ai = ai->next)
1774             rmkern(s1, s2, ai);
1775          return;
1776       } else {
1777          ai = findadobe(s1);
1778          if (ai == 0)
1779             return;
1780       }
1781    }
1782    if (strcmp(s2, "*")==0)
1783       ai->kerns = 0; /* drop them on the floor */
1784    else
1785       ai->kerns = rmkernmatch(ai->kerns, s2);
1786 }
1787 
1788 /* Make the kerning for character S1 equivalent to that for S2.
1789    If either S1 or S2 do not exist, do nothing.
1790    If S1 already has kerning, do nothing.  */
1791 static void
addkern(char * s1,char * s2)1792 addkern(char *s1, char *s2)
1793 {
1794   struct adobeinfo *ai1 = findadobe (s1);
1795   struct adobeinfo *ai2 = findadobe (s2);
1796   if (ai1 && ai2 && !ai1->kerns) {
1797     /* Put the new one at the head of the list, since order is immaterial.  */
1798     struct adobeptr *ap
1799       = (struct adobeptr *) mymalloc((unsigned long)sizeof(struct adobeptr));
1800     ap->next = ai2->kern_equivs;
1801     ap->ch = ai1;
1802     ai2->kern_equivs = ap;
1803   }
1804 }
1805 int sawligkern;
1806 /*
1807  *   Reads a ligkern line, if this is one.  Assumes the first character
1808  *   passed is `%'.
1809  */
1810 static void
checkligkern(char * s)1811 checkligkern(char *s)
1812 {
1813    char *oparam = param;
1814    char *mlist[5];
1815    int n;
1816 
1817    s++;
1818    while (*s && *s <= ' ')
1819       s++;
1820    if (strncmp(s, "LIGKERN", 7)==0) {
1821       sawligkern = 1;
1822       s += 7;
1823       while (*s && *s <= ' ')
1824          s++;
1825       param = s;
1826       while (*param) {
1827          for (n=0; n<5;) {
1828             if (*param == 0)
1829                break;
1830             mlist[n] = paramstring();
1831             if (strcmp(mlist[n], ";") == 0)
1832                break;
1833             n++;
1834          }
1835          if (n > 4)
1836             error("! too many parameters in lig kern data");
1837          if (n < 3)
1838             error("! too few parameters in lig kern data");
1839          if (n == 3 && strcmp(mlist[1], "{}") == 0) { /* rmkern command */
1840             rmkern(mlist[0], mlist[2], (struct adobeinfo *)0);
1841          } else if (n == 3 && strcmp(mlist[1], "<>") == 0) { /* addkern */
1842             addkern(mlist[0], mlist[2]);
1843          } else if (n == 3 && strcmp(mlist[0], "||") == 0 &&
1844                               strcmp(mlist[1], "=") == 0) { /* bc command */
1845             struct adobeinfo *ai = findadobe("||");
1846 
1847             if (boundarychar != -1)
1848                error("! multiple boundary character commands?");
1849             if (sscanf(mlist[2], "%d", &n) != 1)
1850                error("! expected number assignment for boundary char");
1851             if (n < 0 || n > 255)
1852                error("! boundary character number must be 0..255");
1853             boundarychar = n;
1854             if (ai == 0)
1855                error("! internal error: boundary char");
1856             ai->texnum = n; /* prime the pump, so to speak, for lig/kerns */
1857          } else if (n == 4) {
1858             int op = -1;
1859             struct adobeinfo *ai;
1860 
1861             for (n=0; encligops[n]; n++)
1862                if (strcmp(mlist[2], encligops[n])==0) {
1863                   op = n;
1864                   break;
1865                }
1866             if (op < 0)
1867                error("! bad ligature op specified");
1868             if (0 != (ai = findadobe(mlist[0]))) {
1869                struct lig *lig;
1870 
1871                if (findadobe(mlist[2]))     /* remove coincident kerns */
1872                   rmkern(mlist[0], mlist[1], ai);
1873                if (strcmp(mlist[3], "||") == 0)
1874                   error("! you can't lig to the boundary character!");
1875                if (! fixedpitch) { /* fixed pitch fonts get *0* ligs */
1876                   for (lig=ai->ligs; lig; lig = lig->next)
1877                      if (strcmp(lig->succ, mlist[1]) == 0)
1878                         break; /* we'll re-use this structure */
1879                   if (lig == 0) {
1880                      lig = newlig();
1881                      lig->succ = newstring(mlist[1]);
1882                      lig->next = ai->ligs;
1883                      ai->ligs = lig;
1884                   }
1885                   lig->sub = newstring(mlist[3]);
1886                   lig->op = op;
1887                   if (strcmp(mlist[1], "||")==0) {
1888                      lig->boundleft = 1;
1889                      if (strcmp(mlist[0], "||")==0)
1890                         error("! you can't lig boundarychar boundarychar!");
1891                   } else
1892                      lig->boundleft = 0;
1893                }
1894             }
1895          } else
1896             error("! bad form in LIGKERN command");
1897       }
1898    }
1899    param = oparam;
1900 }
1901 /*
1902  *   Here we get a token from the AFM file.  We parse just as much PostScript
1903  *   as we expect to find in an encoding file.  We allow commented lines and
1904  *   names like 0, .notdef, _foo_.  We do not allow //abc.
1905  */
1906 char smbuffer[100];    /* for tokens */
1907 static char *
gettoken(void)1908 gettoken(void) {
1909    char *p, *q;
1910 
1911    while (1) {
1912       while (param == 0 || *param == 0) {
1913          if (texlive_getline() == 0)
1914             error("! premature end in encoding file");
1915          for (p=buffer; *p; p++)
1916             if (*p == '%') {
1917                if (ignoreligkern == 0)
1918                   checkligkern(p);
1919                *p = 0;
1920                break;
1921             }
1922       }
1923       while (*param && *param <= ' ')
1924          param++;
1925       if (*param) {
1926          if (*param == '[' || *param == ']' ||
1927              *param == '{' || *param == '}') {
1928             smbuffer[0] = *param++;
1929             smbuffer[1] = 0;
1930             return smbuffer;
1931          } else if (*param == '/' || *param == '-' || *param == '_' ||
1932                     *param == '.' ||
1933                     ('0' <= *param && *param <= '9') ||
1934                     ('a' <= *param && *param <= 'z') ||
1935                     ('A' <= *param && *param <= 'Z')) {
1936             smbuffer[0] = *param;
1937             for (p=param+1, q=smbuffer+1;
1938                         *p == '-' || *p == '_' || *p == '.' ||
1939                         ('0' <= *p && *p <= '9') ||
1940                         ('a' <= *p && *p <= 'z') ||
1941                         ('A' <= *p && *p <= 'Z'); p++, q++)
1942                *q = *p;
1943             *q = 0;
1944             param = p;
1945             return smbuffer;
1946          }
1947       }
1948    }
1949 }
1950 static void
getligkerndefaults(void)1951 getligkerndefaults(void) {
1952    int i;
1953 
1954    for (i=0; staticligkern[i]; i++) {
1955       strcpy(buffer, staticligkern[i]);
1956       strcpy(obuffer, staticligkern[i]);
1957       param = buffer;
1958       checkligkern(buffer);
1959    }
1960 }
1961 /*
1962  *   This routine reads in an encoding file, given the name.  It returns
1963  *   the final total structure.  It performs a number of consistency checks.
1964  */
1965 static struct encoding *
readencoding(char * enc)1966 readencoding(char *enc)
1967 {
1968    char *p;
1969    int i;
1970    struct encoding *e =
1971       (struct encoding *)mymalloc((unsigned long)sizeof(struct encoding));
1972 
1973    sawligkern = 0;
1974    if (afmin)
1975       error("! oops; internal afmin error");
1976    if (enc) {
1977 #ifdef KPATHSEA
1978      afmin = kpse_open_file(enc, kpse_enc_format);
1979 #else
1980       afmin = fopen(enc, "r");
1981 #endif
1982       SET_BINARY(fileno(afmin));
1983       param = 0;
1984       if (afmin == 0)
1985 #ifdef KPATHSEA
1986          FATAL1 ("couldn't open encoding file `%s'", enc);
1987 #else
1988          error("! couldn't open that encoding file");
1989 #endif
1990       p = gettoken();
1991       if (*p != '/' || p[1] == 0)
1992          error("! first token in encoding must be literal encoding name");
1993       e->name = newstring(p+1);
1994       p = gettoken();
1995       if (strcmp(p, "["))
1996          error("! second token in encoding must be mark ([) token");
1997       for (i=0; i<256; i++) {
1998          p = gettoken();
1999          if (*p != '/' || p[1] == 0)
2000             error("! tokens 3 to 257 in encoding must be literal names");
2001          e->vec[i] = newstring(p+1);
2002       }
2003       p = gettoken();
2004       if (strcmp(p, "]"))
2005          error("! token 258 in encoding must be make-array (])");
2006       while (texlive_getline()) {
2007          for (p=buffer; *p; p++)
2008             if (*p == '%') {
2009                if (ignoreligkern == 0)
2010                   checkligkern(p);
2011                *p = 0;
2012                break;
2013             }
2014       }
2015       fclose(afmin);
2016       afmin = 0;
2017       if (ignoreligkern == 0 && sawligkern == 0)
2018          getligkerndefaults();
2019    } else {
2020       e = &staticencoding;
2021       getligkerndefaults();
2022    }
2023    param = 0;
2024    return e;
2025 }
2026 /*
2027  *   This routine prints out the line that needs to be added to psfonts.map.
2028  */
2029 static void
conspsfonts(void)2030 conspsfonts(void) {
2031 #ifndef VMCMS
2032    printf("%s %s", outname,
2033    fontname);
2034 #else /* VM/CMS: fontname is ascii, so we use ebfontname */
2035    printf("%s %s", outname,
2036    ebfontname);
2037 #endif
2038    if (slantparam || efactorparam || inenname) {
2039       printf(" \"");
2040       if (slantparam)
2041          printf(" %s SlantFont", slantparam);
2042       if (efactorparam)
2043          printf(" %s ExtendFont", efactorparam);
2044       if (inenname)
2045          printf(" %s ReEncodeFont", inencoding->name);
2046       printf(" \"");
2047       if (inenname)
2048          printf(" <%s", inenname);
2049    }
2050    printf("\n");
2051 }
2052 #ifndef VMS
2053 int
2054 #endif
main(int argc,char ** argv)2055 main(int argc, char **argv)
2056 {
2057    int i;
2058 
2059 #ifdef KPATHSEA
2060    kpse_set_program_name (argv[0], "afm2tfm");
2061 
2062    if (argc == 1) {
2063       fputs ("afm2tfm: Need at least one file argument.\n", stderr);
2064       fputs ("Try `afm2tfm --help' for more information.\n", stderr);
2065       exit(1);
2066    }
2067    if (argc == 2) {
2068       if (strcmp (argv[1], "--help") == 0) {
2069         usage (stdout);
2070         exit (0);
2071       } else if (strcmp (argv[1], "--version") == 0) {
2072         version (stdout);
2073         exit (0);
2074       }
2075    }
2076 #endif /* KPATHSEA */
2077    for (i=0; i<256; i++)
2078       nexttex[i] = -1; /* encoding chains have length 0 */
2079    tfmdata = (long *)mymalloc((unsigned long)40000L);
2080    openfiles(argc, argv);
2081    readadobe();
2082    if (fontspace == 0) {
2083       struct adobeinfo *ai;
2084 
2085       if (0 != (ai = findadobe("space")))
2086          fontspace = ai->width;
2087       else if (adobeptrs[32])
2088          fontspace = adobeptrs[32]->width;
2089       else
2090          fontspace = transform(500, 0);
2091    }
2092    handlereencoding();
2093    buildtfm();
2094    writetfm();
2095    conspsfonts();
2096    if (makevpl) {
2097       assignchars();
2098       if (makevpl>1) upmap();
2099       writevpl();
2100    }
2101    return 0;
2102    /*NOTREACHED*/
2103 }
2104 
2105