% Filename: makevpl.tex
% Author: Alan Jeffrey
% E-mail: jeffrey@cs.chalmers.se
% Version number: 1.03
% Last modified: 18 Dec 1991

% This is a TeX macros file which generates .vpl files, which can then
% be fed to vptovf to generate .vf and .tfm files, which can then be
% fed back into TeX again!

% 6 Nov 1991.  Finished version 1.0.
%
% 11 Dec 1991, V1.01.  Fixed a bug with \loadfont... a variant of the usual
%    forgetting to put a space after numbers mistake.  If you said
%
%       \loadfont\foo=cmr10 at 10pt; \foo 3
%
%    then previously \foo would expand out to \\foo\currfontnum 13,
%    whereas it should expand out to \\foo\currfontnum 1 3.  This is
%    why there is an explicit \space in the definition of \loadfont.
%
% 12 Dec 1991, V1.02.  \isdefined now gives a warning if you say
%    \isdefined for a character that already exists.
%
% 18 Dec 1991, V1.03.  \endmakevpl now generates a font table.

% These macros are designed to read in .tfm files, munge them around
% and spit out .vpl files.  I wrote it since I got very very bored
% editing .vpl files by hand.  To generate a .vpl file, you say:
%
%    \makevpl{FILENAME}
%       ...
%    \endmakevpl
%
% This produces a file FILENAME.vpl.  You can replace the ... by any
% TeX commands you like (although producing any horizontal material
% causes an error, which believe me is usually what you want to
% happen).
%
% This all uses a new output file \vplfile.

\newwrite\vplfile

% This can be written to (with various levels of indentation) by \vpl,
% \vvpl and \vvvpl:

\def\vpl{\immediate\write\vplfile}
\def\vvpl#1{\vpl{\space\space\space#1}}
\def\vvvpl#1{\vpl{\space\space\space\space\space\space#1}}

% To produce some raw vpl code, you can say
%
%    \raw
%    (CHARACTER \decimal\thiscount
%       (CHARWD \real\thatdimen)
%       )
%    \endraw

\def\raw{\bgroup\catcode`\^^M12\obeyspaces\newlinechar`\^^M\beginraw}
\def\beginraw#1\endraw{\vpl{#1}\egroup}

% Then \makevpl opens the output file and spits out a header,
% featuring \author, \email, \lastmodified, \versionnumber and
% \description, if these are defined.  It also defines \status0 up to
% \status255 to be \undefined. 

\newcount\totalchars 

\def\makevpl#1%
   {\bgroup
      \catcode`\"\active
      \everypar{\errmessage{There should be no horizontal material here!}}
      \def\fontname{#1}
      \immediate\openout\vplfile=#1.vpl 
      \global\totalchars=0
      \vpl{(VTITLE Created by `tex \jobname' using `\string\makevpl{#1}')}
      \vpl{(COMMENT Please edit that VTITLE if you edit this file)}
      \vpl{(COMMENT Filename: #1.vpl)}
      \expandafter\ifx\csname author\endcsname\relax\else
         \vpl{(COMMENT Author: \author)}\fi
      \expandafter\ifx\csname email\endcsname\relax\else
         \vpl{(COMMENT Email: \email)}\fi
      \expandafter\ifx\csname lastmodified\endcsname\relax\else
         \vpl{(COMMENT Last modified: \lastmodified)}\fi
      \expandafter\ifx\csname versionnumber\endcsname\relax\else
         \vpl{(COMMENT Version number: \versionnumber)}\fi
      \expandafter\ifx\csname description\endcsname\relax\else
         \vpl{(COMMENT \description)}\fi
      \vpl{(FAMILY TeX-#1)}
      \for\tempcount\in0\to255\do
         \expandafter\def\csname status\the\tempcount\endcsname{\undefined}
      \od}

% When we close down the .vpl file, we look to see how many of
% the characters are still undefined, issue appropriate warnings, and
% generate the font table.

\def\endmakevpl
   {\immediate\closeout\vplfile
      \immediate\write16{Virtual property list written on
         \fontname.vpl (\the\totalchars\space characters).}
      \def\defined##1{}
      \def\undefined{\message{The following characters remained
         undefined: \the\tempcount} \def\undefined{\message{\the\tempcount}}}
      \for\tempcount\in0\to255\do\csname status\the\tempcount\endcsname\od
      \immediate\write16{}
      \everypar{}\catcode`\"12\generatetable
   \egroup}

% To say that a character is not being defined in this font, say
% \notdefined{number}.  To say that a character is being defined, but
% not by \character (for example, by \raw ... \endraw), say
% \isdefined{number}{FOO}, where FOO is the TeX that should appear in
% the font table.

\def\notdefined#1;%
   {{\tempcount#1\expandafter\gdef\csname status\the\tempcount\endcsname{}}}
\def\isdefined#1=#2;%
   {{\tempcount#1\message{(\the\tempcount)}
      \global\advance\totalchars by 1
      \let\undefined\relax
      \def\defined##1{\immediate\write16{You've defined character
         \the\tempcount\space twice!}}
      \csname status\the\tempcount\endcsname
      \expandafter\xdef\csname status\the\tempcount\endcsname
         {\noexpand\defined{#2}}}}

% Some commands to turn TeX counters into the format that VPtoVF
% expects:

\def\decimal{ D \the}
\def\real{ R \expandafter\removemeasure\the}
{\catcode`\p=12 \catcode`\t=12 \gdef\removemeasure#1pt{#1}}

% To conform to MF numbering, we can say "A", \hex"41" or \oct"101" to
% refer to character A.

\def\hexadecimal{"}
{\catcode`\"\active 
   \gdef"#1"{\expandafter`\csname#1\endcsname}
   \gdef\hex"#1"{\hexadecimal#1 }
   \gdef\oct"#1"{'#1 }}

% The rest of the code uses a bunch of temporary counters:

\newcount\tempcount
\newcount\tempcounta
\newcount\tempcountb
\newcount\tempcountc
\newcount\tempcountd
\newdimen\tempdimen

% Then some commands to produce the header information.

\newdimen\u

\def\comment#1;{\vpl{(COMMENT #1)}}
\def\codingscheme#1;{\vpl{(CODINGSCHEME #1)}}
\def\designsize#1;%
   {\tempdimen=#1 \u=#1 \divide\u by 36
      \vpl{(DESIGNSIZE\real\tempdimen)}
      \vpl{(DESIGNUNITS\real\tempdimen)}
      \vpl{(COMMENT One design unit is one point)}}

% You can load fonts with \loadfont, for example:
%
%    \loadfont\times=rptmr\at 10pt;
% 
% loads raw Adobe Times roman at 10pt.  This spits out a MAPFONT to
% the .vpl file, and defines three new tokens:
%
%    \\times   is the font rptmr at 10pt,
%    \times    selects \\times, and sets the value of \currfontnum to
%              the font number for Times in the .vpl file.
%    \timesnum is the number of the times font.

\newcount\currfontnum \newcount\nextfontnum 

\def\loadfont#1=#2 at#3;%
   {\expandafter\font \csname\string#1\endcsname #2 at #3 
      \expandafter\edef\csname\expandafter\gobble\string#1num\endcsname
         {\the\nextfontnum}
      \edef#1{\expandafter\noexpand\csname\string#1\endcsname 
         \currfontnum\the\nextfontnum\space}
      \tempdimen #3
      \vpl{(MAPFONT\decimal\nextfontnum\space
         (FONTNAME #2) (FONTAT\real\tempdimen))}
      \advance\nextfontnum by 1}

\def\gobble#1{}

% The syntax for a ligtable is (adapted from Appendix F of the MFbook):
%
%    <ligtable command> ::= \ligtable <ligtable program> ;
%    <ligtable program> ::= <ligtable step>
%       | <ligtable program> , <ligtable step>
%    <ligable step> ::= <number> =: <number>
%       | <number> \kern <dimen>
%       | <number> : <ligtable step>

{\catcode`\,\active \catcode`\=\active \catcode`\:\active \catcode`\;\active
   \gdef\activateligs
      {\catcode`\,\active \catcode`\=\active 
         \catcode`\:\active \catcode`\;\active
         \let,\ligcomma \let;\ligsemi \let=\ligequal
         \let\kern\ligkern \let:\ligcolon}}

\def\ligtable
   {\bgroup\vpl{(LIGTABLE}\activateligs\let\doit\relax\tempcount}
\def\ligsemi{\relax\doit\vvpl{)}\egroup}
\def\ligcomma{\relax\doit\tempcount}
\def\ligequal#1{\relax\edef\doit
   {\vvpl{(LIG\decimal\tempcount \noexpand\decimal\tempcount)}}\tempcount}
\def\ligkern{\relax\edef\doit
   {\vvpl{(KRN\decimal\tempcount\noexpand\real\tempdimen)}}\tempdimen}
\def\ligcolon{\relax\vvpl{(LABEL \decimal\tempcount)}\tempcount}

% The syntax for a charlist is:
%
%    <charlist command> ::= \charlist <labelled code> ;
%    <labelled code> ::= <code>
%       | <number> : <labelled code>

{\catcode`\;\active \catcode`\:\active
   \gdef\activatecharlist
      {\catcode`\;\active \catcode`\:\active
         \let;\charlistsemi \let:\charlistcolon}}

\def\charlist{\bgroup\activatecharlist\let\doit\relax\tempcount}
\def\charlistsemi{\relax\doit\egroup}
\def\charlistcolon
   {\doit\edef\doit{\xdef\expandafter\noexpand
      \csname nextlarger\the\tempcount\endcsname
         {\vvpl{(NEXTLARGER D \noexpand\the\tempcount)}}}
      \tempcount}

% The syntax for an extension is:
%
%    <extensible command> ::= 
%       \extensible <number> : <number> , <number> , <number> , <number> ;

{\catcode`\;\active \catcode`\:\active \catcode`\,\active
   \gdef\activateextensible
      {\catcode`\;\active \catcode`\:\active \catcode`\,\active
         \let;\extensiblesemi \let:\extensiblecolon \let,\extensibletop}
   \gdef\commalet{\let,}}

\def\extensible{\bgroup\activateextensible\tempcount}
\def\extensiblecolon{\relax\tempcounta}
\def\extensibletop{\relax\commalet\extensiblemid\tempcountb}
\def\extensiblemid{\relax\commalet\extensiblebot\tempcountc}
\def\extensiblebot{\relax\commalet\relax\tempcountd}
\def\extensiblesemi
   {\relax\expandafter\xdef\csname varchar\the\tempcount\endcsname
      {\vvpl{(VARCHAR (TOP D \the\tempcounta) (MID D \the\tempcountb)
         (BOT D \the\tempcountc) (REP D \the\tempcountd))}}\egroup}

% The syntax for a fontdimen is:
%
%    <fontdimen command> ::= \fontdimens <number> : <numeric list> ;
%    <numeric list> ::= <number> | <numeric list> , <number>
%
% (Note that \fontdimens is plural, to avoid overriding TeX's
% primitive \fontdimen command.)

{\catcode`\;\active \catcode`\:\active \catcode`\,\active
   \gdef\activatefontdimen
      {\catcode`\;\active \catcode`\:\active \catcode`\,\active
         \let;\fontdimensemi \let:\fontdimencolon \let,\fontdimencomma}}

\def\fontdimens{\bgroup\vpl{(FONTDIMEN}\activatefontdimen\tempcount}
\def\fontdimensemi{\relax\onefontdimen\vvpl{)}\egroup}
\def\fontdimencolon{\relax\tempdimen}
\def\fontdimencomma{\relax\onefontdimen\advance\tempcount by 1\tempdimen}
\def\onefontdimen{\vvpl{(PARAMETER\decimal\tempcount\real\tempdimen)}}

% The syntax of a character command is:
%
%    <char command> ::= \character <char program> ;
%    <char program> ::= <char step> | <char program> , <char step>
%    <char step> ::= <number> | <number> = <number>

{\catcode`\;\active \catcode`\=\active \catcode`\,\active
   \gdef\activatechar
      {\catcode`\;\active \catcode`\=\active \catcode`\,\active
         \let;\charsemi \let=\charequals \let,\charcomma}}

\def\character{\bgroup\activatechar\let\doit\defaultcharacter\tempcount}
\def\charsemi{\relax\doit\egroup}
\def\charequals{\relax\let\doit\setcharacter\tempcounta}
\def\charcomma{\relax\doit\let\doit\defaultcharacter\tempcount}
\def\defaultcharacter{\tempcounta\tempcount\setcharacter}

% This is the main program, that sets one character.  

\def\setcharacter
   {\isdefined\tempcount={\the\font\char\the\tempcounta};
      \vpl{(CHARACTER \decimal\tempcount}
      \setbox0\hbox{\kern\leftgap\char\tempcounta\/\kern\rightgap}
      \tempdimen\wd0
      \setbox0\hbox{\kern\leftgap\char\tempcounta\kern\rightgap}
      \advance\tempdimen by -\wd0
      \vvpl{(CHARWD\real\wd0)}
      \vvpl{(CHARHT\real\ht0)}
      \vvpl{(CHARDP\real\dp0)}
      \vvpl{(CHARIC\real\tempdimen)}
      \vvpl{(MAP}
         \ifnum\leftgap=0\else\vvvpl{(MOVERIGHT\real\leftgap)}\fi
         \ifnum\currfontnum=0\else\vvvpl{(SELECTFONT\decimal\currfontnum)}\fi
         \vvvpl{(SETCHAR\decimal\tempcounta)}
         \vvvpl{)}
      \csname nextlarger\the\tempcount\endcsname
      \csname varchar\the\tempcount\endcsname
      \vvpl{)}}

\newdimen\leftgap \newdimen\rightgap

% The syntax of a for loop is:
%
%    <for loop> ::= \for <counter> \in <number> \to <number> \do <command> \od

\def\for#1\in#2\to#3\do#4\od
   {#1#2\relax\loop#4\ifnum #1<#3 \advance#1 by1 \repeat}

% \generatetable produces the font table, using macros stolen from
% testfont.tex.

\def\generatetable
   {{\let\undefined\relax \let\defined\relax
      \let\oct\DEKoct \let\hex\DEKhex \table}}
\def\tablechar#1%
   {{\tempcount#1 \csname status\the\tempcount\endcsname}}

% The following is adapted from testfont.tex:

\def\DEKoct#1{\hbox{\rm\'{}\kern-.2em\it#1\/\kern.05em}} % octal constant
\def\DEKhex#1{\hbox{\rm\H{}\tt#1}} % hexadecimal constant
\def\testrow{\setbox0=\hbox{\penalty 1\def\\##1{\tablechar{"\h##1}}%
 \\0\\1\\2\\3\\4\\5\\6\\7\\8\\9\\A\\B\\C\\D\\E\\F%
 \global\p=\lastpenalty}} % \p=1 if none of the characters exist

% The rest is the same as testfont.tex:

\newcount\m \newcount\n \newcount\p \newdimen\dim

\def\setdigs#1"#2{\gdef\h{#2}% \h=hex prefix; \0\1=corresponding octal
 \m=\n \divide\m by 64 \xdef\0{\the\m}%
 \multiply\m by-64 \advance\m by\n \divide\m by 8 \xdef\1{\the\m}}
\def\oddline{\cr
  \noalign{\nointerlineskip}
  \multispan{19}\hrulefill&
  \setbox0=\hbox{\lower 2.3pt\hbox{\hex{\h x}}}\smash{\box0}\cr
  \noalign{\nointerlineskip}}
\newif\ifskipping
\def\evenline{\loop\skippingfalse
 \ifnum\n<256 \m=\n \divide\m 16 \chardef\next=\m
 \expandafter\setdigs\meaning\next \testrow
 \ifnum\p=1 \skippingtrue \fi\fi
 \ifskipping \global\advance\n 16 \repeat
 \ifnum\n=256 \let\next=\endchart\else\let\next=\morechart\fi
 \next}
\def\morechart{\cr\noalign{\hrule\penalty5000}
 \chartline \oddline \m=\1 \advance\m 1 \xdef\1{\the\m}
 \chartline \evenline}
\def\chartline{&\oct{\0\1x}&&\:&&\:&&\:&&\:&&\:&&\:&&\:&&\:&&}
\def\chartstrut{\lower4.5pt\vbox to14pt{}}
\def\table{$$\global\n=0
  \halign to\hsize\bgroup
    \chartstrut##\tabskip0pt plus10pt&
    &\hfil##\hfil&\vrule##\cr
    \lower6.5pt\null
    &&&\oct0&&\oct1&&\oct2&&\oct3&&\oct4&&\oct5&&\oct6&&\oct7&\evenline}
\def\endchart{\cr\noalign{\hrule}
  \raise11.5pt\null&&&\hex 8&&\hex 9&&\hex A&&\hex B&
  &\hex C&&\hex D&&\hex E&&\hex F&\cr\egroup$$\par}
\def\:{\setbox0=\hbox{\tablechar\n}%
  \ifdim\ht0>7.5pt\reposition
  \else\ifdim\dp0>2.5pt\reposition\fi\fi
  \box0\global\advance\n 1 }
\def\reposition{\setbox0=\vbox{\kern2pt\box0}\dim=\dp0
  \advance\dim 2pt \dp0=\dim}
\def\centerlargechars{
  \def\reposition{\setbox0=\hbox{$\vcenter{\kern2pt\box0\kern2pt}$}}}
