3

While researching on precompiling the preamble, usually the command to create the format file goes something like

pdftex -ini -jobname="foo" "&pdflatex" mylatexformat.ltx foo.tex

Reading pdftex --help, I understand that:

-jobname=STRING         set the job name to STRING
-ini                    be pdfinitex, for dumping formats; this is implicitly
                          true if the program name is `pdfinitex'

and the remaining argument is specified by this line

   or: pdftex [OPTION]... &FMT ARGS

So FMT is pdflatex, and ARGS is mylatexformat.ltx foo.tex.

Question:

  • What does ARGS specify here?
  • Why does it result in the preamble being generated?
  • Also, where is the documentation?
  • Why does the documentation of mylatexformat suggest using triple quotes for the foo.tex part?

2 Answers 2

4

The format of command line

tex &FMT ARGS

comes from ancient times, when the Unix command line was not as common as today, and leads to the classical TeX behavior: after reading the &FMT format, TeX scans the first letter; if it is a \ then the rest of command line is interpreted as a first line of the document. This is not exactly your example: the first letter is m in your example, so TeX interprets the following word (without spaces) as a file name and does \input mylatexformat.ltx. This is a very common situation; what is uncommon is tha the file you are using doesn't have the \end or \dump primitive (and the \end or \dump primitives are not expanded from used macros). This is a case when TeX reads next data from the rest of the command line and then from the terminal. The mylatexformat file ends by \expandafter\input\endinput, so the \input command is invoked, but its parameter isn't given in the file mylatexformat.ltx, so TeX tries to read the parameter from the rest of the command line, and that means that \input foo.tex is done.

About quotes. The command interpreter removes them and interprets the text inside it more verbose. Try echo """hello""", for example. It prints hello. But I don't know why they are recommended in the documentation.

2

Looks like I just need to stare at the documentation a bit more carefully.

Usage: pdftex [OPTION]... [TEXNAME[.tex]] [COMMANDS]
   or: pdftex [OPTION]... \FIRST-LINE
   or: pdftex [OPTION]... &FMT ARGS

Run pdfTeX on TEXNAME, usually creating TEXNAME.pdf. Any remaining COMMANDS are processed as pdfTeX input, after TEXNAME is read. If the first line of TEXNAME is %&FMT, and FMT is an existing .fmt file, use it. Else use `NAME.fmt', where NAME is the program invocation name, most commonly `pdftex'.

Alternatively, if the first non-option argument begins with a backslash, interpret all non-option arguments as a line of pdfTeX input.

Alternatively, if the first non-option argument begins with a &, the next word is taken as the FMT to read, overriding all else. Any remaining arguments are processed as above.

If no arguments or options are specified, prompt for input.

In other words, ARGS is the "any remaining arguments", which means written explicitly it would be

Usage: pdftex [OPTION]... [TEXNAME[.tex]] [COMMANDS]
   or: pdftex [OPTION]... \FIRST-LINE
   or: pdftex [OPTION]... &FMT [TEXNAME[.tex]] [COMMANDS]
   or: pdftex [OPTION]... &FMT \FIRST-LINE

Which means mylatexformat.ltx becomes the file name [TEXNAME[.tex]], and foo.tex becomes [COMMANDS] i.e. "processed as pdfTeX input".


Experiment to deduce the exact behavior (TeX Live on Linux only)

(without referring to the source code of pdftex-changes.pdf)

Some experiment to see how the "commands" work:

echo '\edef\a{' > a.tex
pdftex a.tex 'bc}' </dev/null

gets "runaway definition" error. (this one is clear: Use of \everyeof and \endlinechar with \scantokens)

echo '\edef\a{\noexpand' > a.tex
pdftex a.tex 'bc}\message{|\a|}' </dev/null

shows \a gets assigned bc, which means that after the EOF, the commands of the are put as a "line of TeX code", as explained.

Instead of \noexpand we can also use

echo '\endlinechar=`d\edef\a{' > a.tex
echo 'bc' >> a.tex
echo 'bc\noexpand%' >> a.tex
pdftex a.tex 'bc' '}\message{|\a|}\show' </dev/null

This outputs |⟨space⟩ bcdbcbc ⟨space⟩|, and the \show at the end does not show anything or give any error.

If there are multiple arguments, they're concatenated with a space, not interpreted as multiple lines of TeX codes.

(the above is equivalent to executing the following TeX code

\endlinechar=`d\edef\a{ ■¹
bc ■²
bc\noexpand% ■³
⟨EOF⟩
bc ∘⁴ }message{|\a|}\show ■⁵

Analysis: (each represents a endlinechar)

  • ■¹ is already fixed to be equivalent to char 13 as the first line is read.
  • ■² becomes the character d.
  • ■³ gets commented out.
  • ∘⁴ is not endlinechar, it's just a space.
  • We will look at ■⁵ later.

We can experiment a bit more:

pdftex '\catcode13=12\def~{\show}~' </dev/null

results in the character ^^M.

which means a "(untokenized) character" with character code 13 is appended after the "pseudo-line".


Remark on the code of mylatexformat.ltx

Unlike \edef, commands such as \input (the primitive one) can work across the EOF boundary:

echo '\message{hello world!!!}' > "hello world.tex"
echo '\input' > a.tex
pdftex a.tex '"hello world.tex"' </dev/null

(this inputs the content of hello world.tex to print out the message)

and the (expandable) \endinput is actually useless as long as it's already at the end of the file.


Remark on the note in mylatexformat.ltx documentation

On the other point, I suspect that the triple-quote recommendation is because that's the way to escape quotes in commands in Windows, although I haven't tested that.

So the TeX code being executed becomes something like

\input "file name.tex"

instead of

\input file name.tex

obviously the latter wouldn't work.

Also, as mentioned in a comment in mylatexformat.ltx:

%% Trick lookahead to allow mylatex.ltx and the document filename to be
%% given on the same command line. (initex &latex mylatex.ltx {abc.tex})
\expandafter\input\endinput%
\endinput

As such invocations such as

pdftex -ini -jobname="foo" "&pdflatex" mylatexformat.ltx "{foo.tex}"

would also work.


Allow getting the filename without extra quoting

Side note, with the above knowledge:

  • In the TeX code, it's impossible to distinguish between the case the user writes

    pdftex file.tex firstargument secondargument
    

    and

    pdftex file.tex "firstargument" "secondargument"
    

    as in both cases the arguments are concatenated with a space.

  • We can design a function that \input from the file whose name is given on the command-line, without needing an additional quote, as long as the filename is the whole thing on the command-line.

    cat > a.tex << 'EOF'
    \catcode `\^^M 2 %
    \def \process {\catcode `\^^M 5 \input {\filename}}%
    \afterassignment \process %
    \edef \filename {\noexpand%
    EOF
    
    # alternatively:
    cat > a.tex << 'EOF'
    \catcode `\^^M 12 %
    \def \process #1^^M{\catcode `\^^M 5 \input {#1}}%
    \expandafter \process \noexpand%
    EOF
    
    # then these can be used (as mentioned above, they're equivalent and indistinguishable)
    pdftex a.tex hello world.tex </dev/null
    pdftex a.tex "hello world.tex" </dev/null
    

    Additional precautions are required to handle { or } in file names, if needed (for academical purposes only, probably.)

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .