summaryrefslogtreecommitdiff
path: root/support/convert/convert.dtx
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /support/convert/convert.dtx
Initial commit
Diffstat (limited to 'support/convert/convert.dtx')
-rw-r--r--support/convert/convert.dtx765
1 files changed, 765 insertions, 0 deletions
diff --git a/support/convert/convert.dtx b/support/convert/convert.dtx
new file mode 100644
index 0000000000..adb3db00f9
--- /dev/null
+++ b/support/convert/convert.dtx
@@ -0,0 +1,765 @@
+\def\fileversion{1.0b}
+\def\filedate{1991/07/08}
+\def\docdate{1991/07/08}
+
+%% \CheckSum{556}
+%% \CharacterTable
+%% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
+%% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
+%% Digits \0\1\2\3\4\5\6\7\8\9
+%% Exclamation \! Double quote \" Hash (number) \#
+%% Dollar \$ Percent \% Ampersand \&
+%% Acute accent \' Left paren \( Right paren \)
+%% Asterisk \* Plus \+ Comma \,
+%% Minus \- Point \. Solidus \/
+%% Colon \: Semicolon \; Less than \<
+%% Equals \= Greater than \> Question mark \?
+%% Commercial at \@ Left bracket \[ Backslash \\
+%% Right bracket \] Circumflex \^ Underscore \_
+%% Grave accent \` Left brace \{ Vertical bar \|
+%% Right brace \} Tilde \~}
+%%
+%\iffalse
+%
+%% TeX utility `convert' to use with plainTeX or LaTeX v2.09
+%% Copyright (C) 1991 by Bernd Raichle.
+%
+% Copying of this file is authorized only if either
+% (1) you make absolutely no changes to your copy, including name, or
+% (2) if you do make changes, you name it something other than
+% convert.tex, convert.doc, or convert.dtx.
+% This restriction helps ensure that all utilities developed here
+% remain identical.
+%
+% Error reports please to:
+% Bernd Raichle
+% Stettener Str. 73
+% D-73732 Esslingen
+% Federal Republic of Germany
+% Email: raichle@.informatik.uni-stuttgart.de
+%
+%
+%\fi
+%
+% \changes{v1.0b}{21 april 1999}{small doc changes;
+% replaced extension doc with dtx;
+% license conditions changed to LPPL}
+% \changes{v1.0a}{8 july 1991}{revised documentation}
+% \changes{v0.6}{6 july 1991}{replaced `input by `read
+% when reading the input file}
+% \changes{v0.5}{18 june 1991}{added conversion table in a file}
+% \changes{v0.4}{14 may 1991}{added conversion to macros}
+% \changes{v0.3}{22 april 1991}{plain\TeX\ version, fixed NUL-char bug}
+% \changes{v0.2}{27 march 1991}{added C-I expansion and
+% C-M/C-J distinction}
+% \changes{v0.1}{16 march 1991}{first version (for \LaTeX)}
+%
+%
+% \DoNotIndex{\fileversion,\filedate,\docdate}
+% \DoNotIndex{\catcode,\def,\let,\string,\immediate,\write,\read}
+% \DoNotIndex{\ifx,\else,\fi,\expandafter,\csname,\endcsname,\end}
+% \DoNotIndex{\everypar,\errhelp,\errmessage,\inputlineno,\ifnum}
+% \DoNotIndex{\errorcontextlines,\afterassignment,\jobname,\relax}
+% \DoNotIndex{\chardef,\openout,\closeout,\openin,\closein,\the}
+% \DoNotIndex{\message,\begingroup,\endgroup,\lowercase,\advance}
+% \DoNotIndex{\gdef,\lccode,\xdef,\noexpand,\global,\ifcase,\or}
+% \DoNotIndex{\uppercase,\uccode,\count,\endlinechar,\ifeof}
+% \DoNotIndex{\endinput,\^^@}
+% \DoNotIndex{\sixt@@n,\nullfont,\count@,\z@,\@ne,\tw@,\thr@@,\m@ne}
+% \DoNotIndex{\sixt@@n,\@cclvi,\loop,\repeat,\space,\empty,\active}
+% \DoNotIndex{\undefined,\newcount,\newwrite}
+%
+%
+% \title{Convert -- a \TeX-file converter for
+% \TeX~3.0\thanks{This file has version number \fileversion,
+% last revised \filedate, documentation dated \docdate.}}
+% \author{Bernd Raichle}
+%
+% \address{Stettener Str.~73\\
+% D-73732 Esslingen\\
+% Federal Republic of Germany}
+% \netaddress{raichle@informatik.uni-stuttgart.de}
+% \signature{\signaturemark Bernd Raichle\\
+% \theaddress1}
+%
+% \date{June 12, 1991}
+%
+% \maketitle
+%
+% \begin{abstract}
+% The release of \TeX~3.0 and use of national character sets
+% arise one problem: the portability of texts. Users should be
+% able to use an customized \TeX\ which allows the input and
+% output of national characters.
+% The exchange of texts with extended character set is
+% supported by \TeX\ if you are using the \verb+^^x+ notation
+% described in the \TeX{}book. This utility written in \TeX\
+% converts a text to this notation.
+% \end{abstract}
+%
+%
+% \section{External and internal character representation}
+%
+% \subsection{Basics}
+%
+% {\small\it
+% {\S 17. The character set.}\\
+% In order to make \TeX\ readily portable to a wide variety of
+% computers, all of its input text is converted to an internal eight-bit
+% code that includes standard ASCII, the ``American Standard Code for
+% Information Interchange.'' This conversion is done immediately when each
+% character is read in. Conversely, characters are converted from ASCII to
+% the user's external representation just before they are output to a
+% text file.
+% \par\smallskip
+% {\S 23.}\\
+% The ASCII code is ``standard'' only to a certain extent, since many
+% computer installations have found it advantageous to have ready access
+% to more than 94 printing characters. Appendix~C of {\sl The \TeX book\/}
+% gives a complete specification of the intended correspondence between
+% characters and \TeX's internal representation.
+% \par
+% \hbox to\hsize{\hfil\rm from \TeX: The Program.}\par}
+%
+% \medskip
+%
+% \TeX\ reads the input file line by line and converts between the internal
+% character set (a superset of ASCII) and the user's external character
+% set with the help of two arrays named {\tt xord} and {\tt xchr}.
+%
+% Each character~$c_e$ read from the file or the terminal is replaced
+% by the (internal) character $c_i = \mathop{\rm xord}[c_e]$.
+%
+% When \TeX\ writes a character~$c_i$ to a file or the terminal the
+% string {\tt str\_pool$[c_i]$} is used to produce visible strings for
+% unprintable characters. Each (internal) character~$c_j$ from this
+% string is replaced by the (external) character
+% $c_e = \mathop{\rm xchr}[c_j]$.
+%
+% \medskip
+%
+% The conversions between the internal and the external character set
+% are system dependent. A text written on system~$A$ has to be translated
+% when it is transferred to system~$B$ with another external character set.
+%
+% {\catcode`\^=12
+% A text is portable only if both systems use the same mapping from their
+% external character set to ASCII characters $32-127$\footnote{Additionally
+% the mapping to ASCII characters with special functions like NUL, CR,
+% LF,\ldots has to be equal too.} and the text uses no other characters.
+% \TeX\ supports further the use of non-ASCII characters
+% if a special notation is used: when reading text the character sequence
+% \verb=^^x= is replaced by one character with internal code $x-64$ or
+% $x+64$. Additionally \TeX~3 allows the notation \verb=^^xy= where
+% \verb=xy= are two lowercase hexadecimal digits. The four character sequence
+% is replaced by one character with internal code equal to the
+% hexadecimal value.\footnote{The characters in {\tt ^^x} and {\tt ^^xy}
+% are first translated to their internal representation before the
+% replacement is done. Additionally the category code of character {\tt ^}
+% has to be~5. For example \LaTeX's {\tt verbatim} environment change the
+% category code to~12.}}
+%
+%
+% \subsection{Example}
+%
+% Assume that you have two \TeX\ versions and the external character set
+% uses ASCII for character codes~$< 128$. The code of the character
+% {\tt \"a} is {\it 132} (or hexadecimal \verb="84=) and \TeX's internal
+% code should be {\it 228} (or \verb="e4=) for this character.
+%
+% Version~1 uses idendity as mapping between external and internal
+% character codes, all characters not in $32-127$ are printed in
+% \verb=^^x= notation. Version~2 maps the character {\tt \"a} and
+% prints this character as {\tt \"a}.
+%
+% The interesting parts of the arrays in both versions are:
+%
+% \hbox to\hsize{\hfil
+% \begin{tabular}{|rlr|rlr|}
+% \hline
+% \multicolumn{3}{|l|}{\small Version 1:} &
+% \multicolumn{3}{|l|}{\small Version 2:} \\ \hline
+% xord[132]&=&132 & xord[132]&=&228 \\
+% & & & xchr[228]&=&132 \\
+% str\_pool[132]&=&\verb=^^84= & str\_pool[228]&=&{\tt \"a} \\
+% \hline
+% \end{tabular}\hfil}
+%
+% \medskip
+%
+% If version~1 reads the character {\tt \"a} it is translated to internal
+% code~$132$. When this character is printed \TeX\ writes the string
+% \verb=^^84= to the output and translates each of the four characters
+% of this string to their external representation.
+%
+% Using version~2 the character {\tt \"a} is translated to internal
+% code~$228$ when it is read. \TeX\ writes the character~$228$ as string
+% {\tt \"a} (an {\tt \"a} with code $228$!). This character is replaced
+% by its external code~$132$ and the user sees the character {\tt \"a}.
+%
+% \medskip
+%
+% The \verb=^^xy= notation can be used in both versions to get the same
+% internal character code for the {\tt \"a}.
+% \TeX\ replaces the character sequence \verb=^^e4= by one character with
+% internal code \verb="e4= ($= 228$).
+% This character is written as explained above, i.e., version~1 prints
+% \verb=^^e4=, version~2 prints {\tt \"a}.
+%
+%
+% \section{Usage}
+%
+% To use this utility just type ``\verb=tex convert='' or
+% ``\verb=latex convert=''.
+% You are prompted for the conversion type and the input and output
+% filename. This tool checks if you want to override your input file
+% but their is no check for an existing output file.
+% When an empty output filename is given the output is written only to
+% the terminal and in the log-file.
+%
+% In the current version of this tool there are two types for
+% conversion.
+% Type~1 converts all unprintable characters to the \verb=^^z=
+% or \verb=^^xy= notation.
+% Type~2 additionally reads the file {\tt convert.tbl} with
+% user-defined translation entries. Both conversion types expands
+% {\tt TAB} characters and ignores additional {\tt LF} and {\tt CR}
+% characters in a line with a warning.
+%
+% \bigskip
+%
+% The translation table in {\tt convert.tbl} is read without
+% expansion of the control sequences given. All characters except
+% `invalid' and `ignored' characters can be used in the replacement
+% string. Another exception is the comment character `\%' which can
+% be used to allow comments in this file.
+%
+% For each translation you wrote a line
+%
+% \begin{tabular}{p{2cm}p{2cm}l}
+% & \it charnum & \it replacement text
+% \end{tabular}
+%
+% {\em charnum} is one of the formats allowed for character numbers
+% in \TeX. Note that the replacement text can have unbalanced braces.
+%
+% \medskip
+% {\bf Examples:}
+%
+% You want to replace the character with internal code $228$ by
+% the string \verb={\" a}=.
+%
+% \begin{tabular}{p{2cm}p{2cm}l}
+% & {\tt 228} & \verb={\" a}=
+% \end{tabular}
+%
+% If you don't know the internal character code of an {\tt \"a}
+% you should specify this character as {\it charnum}. The
+% translation of the {\tt \"a} is done when reading the file
+% {\tt convert.tbl} and when reading the input file with the same
+% input/output translation.
+%
+% \begin{tabular}{p{2cm}p{2cm}l}
+% & {\tt \"a} & \verb={\" a}=
+% \end{tabular}
+%
+% You have just received a file where all {\tt \"a} characters are
+% printed as {\tt \v D} and you want to convert it to your external
+% character code.
+%
+% \begin{tabular}{p{2cm}p{2cm}l}
+% & {\tt \v D} & {\tt \"a}
+% \end{tabular}
+%
+%
+%\StopEventually{\makesignature\PrintIndex}
+%
+% \section{The implementation}
+%
+% \subsection{Initial Phase}
+%
+% Because we want to use internal macros, set the category code
+% of \verb=@= to `letter'.
+% \begin{macrocode}
+\catcode`@=11
+% \end{macrocode}
+%
+% This utility can be used with plain\TeX\ and \LaTeX. For plain\TeX\
+% we copy some useful things from `latex.tex'.
+% \begin{macrocode}
+\newwrite\@unused
+\def\typeout#1{{\let\protect\string\immediate\write\@unused{#1}}}
+\def\@strip#1#2 \@gobble{\def #1{#2}}
+\def\@defpar{\par}
+\def\@iden#1{#1}
+\def\@gobble#1{}
+\def\typein[#1]#2{\typeout{#2}\read\sixt@@n to#1%
+ \ifx #1\@defpar \def#1{}\else
+ \@iden{\expandafter\@strip\expandafter #1#1\@gobble\@gobble} \@gobble
+ \fi}
+% \end{macrocode}
+%
+% The first real thing to do is to write the current version of this file.
+% \begin{macrocode}
+\typeout{TeX Utility `convert' version \fileversion\space <\filedate> (br)}
+\typeout{English documentation dated <\docdate> (br)}
+% \end{macrocode}
+%
+% \LaTeX\ redefines \verb=\end=. We define a new macro to end this
+% job which works for plain\TeX\ and \LaTeX. The first \verb=\@@end=
+% has the meaning \verb=\relax= if we are using plain\TeX, otherwise
+% it's plain\TeX's \verb=\end= which is saved in \verb=\@@end= by
+% \LaTeX.
+% \begin{macro}{\endofjob}
+% \begin{macrocode}
+\def\endofjob{\csname @@end\endcsname \end}
+% \end{macrocode}
+% \end{macro}
+%
+% This utility should never produce a DVI-file. For the case that this
+% is not true\footnote{This should only happen when this tool is
+% corrupted!}, we produce an error message.
+% \begin{macrocode}
+\everypar{\errhelp{This TeX utility should not produce any dvi output.}%
+ \errmessage{Internal Error 1. -- Please fix me!}}
+\nullfont
+% \end{macrocode}
+%
+% We use the fact that \TeX~3 can distingiush 256~different
+% input characters.
+% If the user has started a pre-3 \TeX\ we exit with an error message
+% to inform the user about the need of a newer \TeX\ version.
+% \begin{macrocode}
+\def\sorry{%
+ \typeout{******************************************}
+ \typeout{* Sorry, you need TeX 3 for this Utility *}
+ \typeout{******************************************}
+ \endofjob}
+% \end{macrocode}
+% The new version of `plain.tex' and `lplain.tex' allocates normal
+% counter for the new \TeX~3 counter if you are using a pre-3 \TeX.
+% We use the fact that \verb=\inputlineno= is set to a negative value
+% after allocating the normal counter and that this counter is not
+% changed. For \TeX~3 it contains a positive value.
+% \begin{macrocode}
+\newif\iftexthree \texthreetrue
+\ifx\undefined\inputlineno
+ \texthreefalse
+\else
+ \count@=\inputlineno
+ \ifnum\inputlineno<\z@
+ \texthreefalse
+ \else\ifnum\inputlineno=\count@
+ \texthreefalse
+ \fi\fi
+\fi
+\iftexthree \else \expandafter\sorry\fi
+% \end{macrocode}
+%
+% If an error occurs it's unnecessary to print more than a few lines.
+% \begin{macrocode}
+\errorcontextlines=\m@ne
+% \end{macrocode}
+%
+% \subsection{User Input}
+%
+% We need the character \verb=^= as a normal character with category
+% code `other'.
+% \begin{macrocode}
+\catcode`^=12
+% \end{macrocode}
+%
+% Inform the user about the usefullness of this file.
+% \begin{macrocode}
+\typeout{}
+\typeout{********************************************************}
+\typeout{ This program converts text-files with 8bit-characters}
+\typeout{ into text-files with TeX's ^^xx syntax or TeX macros}
+\typeout{ for these characters.}
+\typeout{********************************************************}
+\typeout{}
+% \end{macrocode}
+%
+% Ask the user what type of conversion should be done. Currently
+% this file supports the conversion of unprintable characters in
+% \TeX's \verb=^^xx= syntax or user-defined replacement.
+%
+% The type of conversion is saved in the counter \verb=\convtype=.
+% \begin{macro}{\convtype}
+% \begin{macrocode}
+\newif\iffehler
+\newcount\convtype
+% \end{macrocode}
+% \end{macro}
+% The assignment to \verb=\convtype= is not error-prove. If the user
+% types more than an integer \TeX\ reports an error.
+% \begin{macrocode}
+\def\getnumber{\afterassignment\gobblerest\count@=}
+\def\gobblerest#1\lineend{}
+\loop
+ \typeout{ Should I convert 8bit characters to...}%
+ \typeout{ \space 1) ^^x notation or}%
+ \typein[\conversion]%
+ { \space 2) macros calls (defined in `convert.tbl')}%
+% \end{macrocode}
+% If the user types nothing, convtype should be set to zero.
+% \begin{macrocode}
+ \getnumber\conversion \space 0 \lineend
+ \convtype=\count@
+ \fehlertrue
+ \ifnum\convtype>\z@ \ifnum\convtype<\thr@@ \fehlerfalse \fi\fi
+ \iffehler
+ \typeout{ !! Please type 1 or 2 !!}\typeout{}%
+\repeat
+% \end{macrocode}
+% We ask the user about the input and the new output
+% filename.
+% \begin{macro}{\infilename}
+% \begin{macro}{\outfilename}
+% \begin{macrocode}
+\typeout{}
+\typein[\infilename]{First type the name of your input file:}
+\typeout{}
+\typein[\outfilename]{Now type the name of your output file:}
+\typeout{}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% We should avoid the case that the user overwrites the input file.
+% \begin{macrocode}
+\ifx\infilename\outfilename
+ \typeout{}
+ \typeout{!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!}
+ \typeout{! Not possible to read from and write to the same file !}
+ \typeout{!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!}
+ \expandafter\endofjob
+\fi
+% \end{macrocode}
+%
+% If the output filename is empty, we output into the log-file
+% and on the terminal. Otherwise we open the file given in
+% \verb=\outfilename= for output.
+% \begin{macrocode}
+\newwrite\outstream
+\ifx\outfilename\empty
+ \typeout{Output to \jobname.log and online.}
+ \typeout{------------------------------------------------------------}
+ \chardef\outstream=\sixt@@n
+\else
+ \immediate\openout\outstream \outfilename \relax
+\fi
+% \end{macrocode}
+%
+% \subsection{Collect and output one Line}
+%
+% To access unprintable characters in a portable way in this file we
+% change the category code of \verb=~= to~7. Additionally a character
+% with category code `active' is used very often.
+% \begin{macrocode}
+\catcode`~=7
+\catcode`$=\active
+% \end{macrocode}
+%
+% We save the current incomplete line in the token register
+% \verb=\currentline= and maintain an input line counter.
+% \begin{macrocode}
+\newtoks\currentline \currentline={}
+\newcount\lineno
+% \end{macrocode}
+%
+% We output a complete line with \verb=\finish@line=. When the output
+% is written in a file, we inform the user about the current processed
+% input line number.
+% \begin{macro}{\finish@line}
+% \begin{macrocode}
+\ifx\outfilename\empty
+ \def\finish@line{\immediate\write\outstream{\the\currentline}%
+ \currentline{}\outputpos\z@}
+\else
+ \def\finish@line{\immediate\write\outstream{\the\currentline}%
+ \currentline{}\outputpos\z@\message{\the\lineno}}
+\fi
+% \end{macrocode}
+% \end{macro}
+%
+% Tabs should be expanded so we need another counter.
+% \begin{macrocode}
+\newcount\outputpos \outputpos=\z@
+% \end{macrocode}
+%
+% The macro \verb=\expand@tab= inserts space characters in the input
+% stream until a tab position is reached. We need an active space
+% character, so we use a little trick with \verb=\lowercase=.
+% \begin{macro}{\expand@tab}
+% \begin{macrocode}
+\begingroup\lccode`$=32
+\lowercase{\endgroup
+\def\expand@tab{%
+ \count@\outputpos
+ \loop \ifnum\count@>7 \advance\count@ -8\repeat
+ \loop \ifnum\count@<8 \advance\count@\@ne $\repeat
+}
+} % end of lowercase
+% \end{macrocode}
+% \end{macro}
+%
+% With the macro \verb=\defoutstring= we define the character in argument~1
+% to write the string given in argument~2 of length given in argument~3.
+% The definition is done with \verb=\xdef= because the second argument can
+% contain some other macros (e.g. \verb=\hexnum=) which have to be expanded.
+%
+% But before this is done there is a special case where
+% \verb=\lowercase= doesn't work.
+% \begin{macrocode}
+\begingroup \catcode`\~~@=\active
+\gdef~~@{\currentline\expandafter{\the\currentline ^^@}%
+ \advance\outputpos\thr@@}
+\endgroup
+% \end{macrocode}
+% \begin{macro}{\defoutstring}
+% \begin{macrocode}
+\def\defoutstring#1#2#3{\ifnum#1=\z@ \else
+ \begingroup \lccode`$=#1\relax
+ \lowercase{\endgroup\xdef$}%
+ {\currentline\noexpand\expandafter{\noexpand\the\currentline #2}%
+ \advance\outputpos\noexpand#3}%
+ \fi
+}
+% \end{macrocode}
+% \end{macro}
+%
+% To assign control sequences to characters we use two additional macros.
+% \begin{macro}{\defout}
+% \begin{macrocode}
+\def\defout#1#2{\lccode`$=#1\relax
+ \lowercase{\gdef$}{#2}}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\letout}
+% \begin{macrocode}
+\def\letout#1#2{\lccode`$=#1\relax
+ \lowercase{\global\let$}#2}
+% \end{macrocode}
+% \end{macro}
+%
+% For characters greater than~127, we need a hexdecimal representation
+% with lowercase characters. The macro has to be expandable.
+% \begin{macro}{\hexnum}
+% \begin{macrocode}
+\def\hexnum#1{\ifcase#1 0\or 1\or 2\or 3\or 4\or 5\or 6\or 7\or
+ 8\or 9\or a\or b\or c\or d\or e\or f\fi}
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Definition of active Characters}
+%
+% We define macros for all of the 256 characters in TeX's internal
+% character representation.
+%
+% Here is the first use of \verb=\defoutstring=: We define the printable
+% character in \TeX's character positions 32--127 to output themself.
+% \begin{macrocode}
+\catcode`*=12
+\count@=32
+\loop
+ \lccode`*=\count@
+ \ifnum\count@<127
+ \lowercase{\defoutstring\count@*{\@ne}}
+ \advance\count@\@ne
+\repeat
+\defoutstring{127}{^^?}\thr@@
+% \end{macrocode}
+%
+% The characters in position 0--31 are output in the form \verb=^^X=.
+% \begin{macrocode}
+\count@=\@ne \count\thr@@=`A
+\loop
+ \uccode`*=\count\thr@@
+ \ifnum\count@<32
+ \uppercase{\defoutstring\count@{^^*}}\thr@@
+ \advance\count@\@ne \advance\count\thr@@\@ne
+\repeat
+% \end{macrocode}
+%
+% The character positions 128--255 (these are new in \TeX~3) are
+% written in the form \verb=^^xx=.
+% \begin{macrocode}
+\count@=128
+\count\@ne=8 \count\tw@=0 % hex-counter
+\loop
+ \ifnum\count@<\@cclvi
+ \defoutstring\count@
+ {^^\hexnum{\the\count\@ne}\hexnum{\the\count\tw@}}4
+ \advance\count@\@ne
+ \ifnum\count\tw@>14
+ \count\tw@\z@ \advance\count\@ne \@ne
+ \else
+ \advance\count\tw@ \@ne
+ \fi
+\repeat
+% \end{macrocode}
+%
+% \subsection{User-defined character translation}
+%
+% The user can define his own character translation. The translation
+% are specified in a file called `convert.tbl' which contains one
+% translation per line. Each line begins with the character number
+% (with the syntax of \TeX's \verb=<charnum>=), the rest of the line
+% is the replacement string.
+%
+% After the conversion string is read in we need to know the
+% length of this string.
+% \begin{macro}{\getlength}
+% \begin{macro}{\lengthloop}
+% \begin{macrocode}
+\newcount\length
+\def\getlength{\afterassignment\lengthloop\let\next= }
+\def\lengthloop{%
+ \ifx\next\empty
+ \else
+ \advance\length\@ne
+ \expandafter\getlength
+ \fi
+}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% For each line we get at first the character number and the length
+% of the translation string. With the macro \verb=\defoutstring=
+% we redefine the corresponding macro to produce this string.
+% \begin{macro}{\processline}
+% \begin{macrocode}
+\def\processline#1 #2\lineend{\length=\z@
+ \getlength#2\empty \getnumber#1\space -1 \lineend
+ \defoutstring\count@{#2}\length
+}
+% \end{macrocode}
+% \end{macro}
+%
+% Now we define the macro to read the file `convert.tbl'.
+% When reading the file we have to set most of the letter to
+% category codes `letter' or `other' to suppress expansion and
+% errors. Only the category codes of a few letters are left
+% unchanged.
+%
+% \begin{macro}{\readfile}
+% \begin{macrocode}
+\newif\ifmore \moretrue
+\def\readfile{\begingroup
+ \count@=\z@
+ \loop
+ \ifnum\count@<\@cclvi
+ \ifnum\catcode\count@<9
+ \catcode\count@ 12
+ \else\ifnum\catcode\count@=\active
+ \catcode\count@ 12
+ \fi\fi
+ \advance\count@ \@ne
+ \repeat
+ \loop
+ \endlinechar\m@ne
+ \read\@ne to \curline
+ \endlinechar`~~M
+ \ifx\curline\empty % ignore empty lines
+ \else
+ \expandafter\processline\curline\lineend
+ \fi
+ \ifeof\@ne \morefalse \fi
+ \ifmore
+ \repeat
+\endgroup}
+% \end{macrocode}
+% \end{macro}
+%
+% And here is the place where the file is read. But this is
+% only done if the user has asked for it.
+% \begin{macrocode}
+\ifnum\convtype=\tw@
+ \openin\@ne convert.tbl\relax
+ \ifeof\@ne
+ \typeout{I can't find file `convert.tbl' -- ignored.}%
+ \else
+ \readfile
+ \closein\@ne
+ \fi
+\fi
+% \end{macrocode}
+%
+% And the last action: we define macros for characters with special
+% functions. These are `line feed', `carriage return' and `tab'.
+% \begin{macrocode}
+\letout{9}\expand@tab
+\defout{10}{%
+ \typeout{!!--> Found ^J in line \the\lineno--I'll ignore all ^J.}%
+ \letout{10}\relax}
+\defout{13}{%
+ \typeout{!!--> Found ^M in line \the\lineno--I'll ignore all ^M.}%
+ \letout{13}\relax}
+% \end{macrocode}
+%
+% \subsection{Convert the file}
+%
+% Now after the character translation is set up we have to make
+% all characters active. We read the file line by line with TeX's
+% \verb+\read+ primitive. (If we would \verb+\input+ the file we
+% have to set \verb+\endlinechar+ to signal the end-of-line.)
+%
+% \begin{macrocode}
+\def\readfile{%
+ \read\@ne to\next
+ \ifeof\@ne
+ \else
+ \advance\lineno\@ne
+ \next\relax
+ \finish@line
+ \expandafter\readfile
+ \fi
+}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\def\makeactiveandinput{\begingroup
+ \count@=\z@
+ \loop
+ \ifnum\count@<\@cclvi
+ \catcode\count@\active
+ \advance\count@\@ne
+ \repeat
+% \end{macrocode}
+% While reading from the file it is useful to switch off the
+% recognition of the end-of-line character. This saves us stripping
+% off spaces from the contents of the line.
+% \begin{macrocode}
+ \endlinechar=-1
+ \openin\@ne \infilename\relax
+ \ifeof\@ne
+ \typeout{No input file \infilename.}%
+ \else
+ \lineno\z@
+ \readfile
+ \closein\@ne
+ \fi
+ \endlinechar=`~~M
+ \ifx\outfilename\empty
+ \typeout{------------------------------------------------------------}
+ \else
+ \immediate\closeout\outstream
+ \fi
+ \endgroup
+ \endofjob
+}
+% \end{macrocode}
+% The last task: call the macro.
+% \begin{macrocode}
+\makeactiveandinput
+% \end{macrocode}
+%
+% Normally we should never reach this point.
+% \begin{macrocode}
+\errhelp{This TeX utility should not reach this point.}%
+\errmessage{Internal Error 2. -- Please fix me!}
+\endinput
+% \end{macrocode}
+% \Finale
+\endinput