2

I currently have the following code written in Plain TeX:

\loadtoks\END
int main(void)
{
    printf("Hello World! %!@#$%&*&^\n");
}
\END

{\tt\the\toks0}
\bye

The macro \loadtoks is something that I wrote myself. It sets the catcode of every ASCII character to 12 so that specials are now just regular characters, and then it scans ahead looking for the given \END token. As it scans, it appends every token that it finds to the \toks0 register. One could also do \loadtoks+Hello World+, for example, and in that case the end-marker would be +. It's a bit more complex than that internally, but that's basically the gist of it.

Now, what I need to do is something like:

\loadtoks\END
\input file.txt
\END

{\tt\the\toks0}
\bye

Of course this simply typesets the words "\input file.txt", as opposed to reading in the file. But naturally what I need for it to do is to actually read in the file, and to behave as if the file's contents had actually been typed into the TeX source file directly (as in the first example).

I've been scratching my head over this for a while now, but I can't seem to figure it out. Note I know about LaTeX's \verb, but I'm using strictly Plain TeX, and I'm curious to figure out a solution in terms of only TeX's plain and primitive macros.

  • You're painting yourself into a corner; if you don't have a character of category code 0, you can't type control sequences. The only way out is to reserve a character and give it category code 13, defining it to be \input. Or define a different macro, say \loadtoksinput. – egreg May 13 '14 at 11:09
6

I'll try to answer to the long unanswered question. The problem of this question was that the \loadtoks macro was not shown. This reminds us something about MWE mentioned very often at this site.

I've tried to estimate your mystic and undisclosed macro \loadtoks. I mean that you set all catcodes to 12 (others) and the first parameter (\END in the example) is processed by \string and put as a separator. It means that this:

\newcount\tmpnum
\def\loadtoks#1{\bgroup \tmpnum=32
   \loop\advance\tmpnum by1 \ifnum\tmpnum<128 \catcode\tmpnum=12 \repeat
   \obeylines \obeyspaces
   \expandafter\def\expandafter
      \loadtoksA\expandafter##\expandafter1\string#1{\egroup\toks0={##1}}%
   \loadtoksA
}
{\obeyspaces\global\let =\ }

\loadtoks\END
int main(void)
{
    printf("Hello World! %!@#$%&*&^\n");
}
\END
{\tt\the\toks0}
\bye

works. Now, your question is about reading the external file. First, IMHO it is impossible to do it in traditional TeX by scanning whole file content as a parameter. The error File ended while scanning occurs and there is no possibilities to put something after the end of file as a separator. If you insist on traditional TeX, you need to use the loop with \read primitive and you must to read the file line per line with \ifeof test.

But, if you are using eTeX then you can put tokens after end of the file by the \everyeof tokens register. So, all what you need is to process the separator by \string in the \everyeof and to write some \expandafters:

\everyeof \expandafter{\string\END} 
\expandafter\loadtoks\expandafter\END
\input file.txt

{\tt\the\toks0}
\bye

Edit: one redundant \expandafter removed.

4

The contents of a file can be loaded into a macro with the help of package catchfile. The package requires e-TeX because of \everyeof.

Example with visible spaces:

\input catchfile.sty\relax
\CatchFileDef\MyFileContents{file.txt}{%
  \def\do#1{\catcode`#1=12 }%
  \dospecials
  \obeylines
}

{\tt\MyFileContents}

\bye

Result with visible spaces

Example with invisible spaces:

\input catchfile.sty\relax
\CatchFileDef\MyFileContents{file.txt}{%
  \def\do#1{\catcode`#1=12 }%
  \dospecials
  \obeylines
  \obeyspaces
}

\begingroup
  \def\temp#1{\endgroup
    \def\DefActiveSpace{\def#1}%
  }%
  \catcode`\ =\active
\temp{ }

{\tt\DefActiveSpace{\ }\MyFileContents}

\bye

Result with invisible spaces

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.