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.)