Given TeX's system of catcodes, I imagine that one can obfuscate TeX to a remarkable degree. With a view to learning more about the internals of TeX, I ask: How might I go about adding a block of obfuscated code to my document? Let's say I want to add a watermark to my document that I don't want my co-author to be able to edit. How might I do that?

What tricks can I use to make a certain piece of code harder to understand?


Try out xii.tex. It's a plainTeX file, you can find it on CTAN.

And Enrico “egreg” Gregorio produced a similar code, even shorter. See in What is the most bizarre thing you have seen done with TeX, where it is called xcix.tex.

  • 2
    Wow, that is pretty impressive. In comparison, obfuscated C reads like a newspaper :-) – Daniel Jun 17 '11 at 18:26
  • 4
    There's also Brainfuck which is obfuscated almost by design. – Alan Munn Jun 17 '11 at 18:37
  • How is this even possible? The input file contains 766 characters, the output document about thrice that number‽ Is there a package used containing the lyrics? Also: Brainfuck ... we meet again. – doncherry Jun 17 '11 at 19:34
  • 1
    @doncherry: If you look at the answers to the question Yiannis has linked to (comment on the question) then you will see how to analyse xii.tex. It is most enlightening: \tracingall is your friend here :-) – Joseph Wright Jun 17 '11 at 20:14
  • 2
    @Alan: I don't find Brainfuck all that hard to read, I have to say. You shift cells left and right, increment or decrement their contents, and input/output their contents as characters - only the looping construct holds any slight mystery. Tedious, verbose, encoding intense, but not really hard to figure out. Tex is much more interesting. I haven't see obfuscated Tex that really got to grips with the joys of \let\\\loop\let\|\ifx\let\/\repeat, say. – Charles Stewart Jun 18 '11 at 8:35

If you are using XeTeX, here is some (slightly obfuscated) code to pack (\p) pairs of Ascii characters into one Unicode character, storing the result in \toks0 (token register, which I called \| below), or unpack (\u) the result.

The encoding uses the fact that visible ascii characters have a character code (acessed with \number`) between 32 (space) and 127 (tilde), so they can be stored in two digits by shifting by 32. Four digits are then packed in one character by adding 10000 (minus the two shifts of 32, hence 6768, minus a 32 hidden in the definition of \., hence 6736), to ensure that this gives 5 digits (starting with 1).

Decoding reads characters one at a time, through \number`, which gives 1, followed by two pairs of digits. We add 32 to each pair, set the uppercase code of . to that value, and store \uppercase{.} in \|.

Stopping the loop is done by inserting \iffalse at the right place in both packing and unpacking.

% Packing 2 ascii char per Unicode char with XeTeX.
\def\p#1{\|{}\ea\q#1\ {\ \iffalse}\ \fi\relax}
\def\u#1{\|{}\ea\v\number`#1 \^^J{\iffalse}..\fi\relax}
% Example
\p{The\ main\ author\ is\ Seamus!}\showthe\|
\csname @@end\endcsname\end

The group is there to avoid leaking out the definitions. Of course, you probably want to only leave the definitions for \u, and write \u{㮨䈄䃉䠨䘾❙䝼㭁䃁䢗❴}\message{\the\|} in your document.


I have just found \char and so:

\char'110 \char'105 \char'114 \char'114 \char'117 \kern .8em \char'127 \char'117\char'122 \char'114 \char'104

Also, I wonder if there's a way to access what your document looks like after it's all been expanded down to primitives. I think that would in itself be pretty obfuscated...

  • As gets pointed out a lot, TeX does not expand to primitives independent of typesetting. The nearest you can get is \tracingall. – Joseph Wright Jun 30 '11 at 17:30
  • 1
    @Joseph well, what I meant was, I wonder if there's a way to see what the output would look like if you expanded a whole bunch of the macros (but perhaps not all of them)... – Seamus Jul 1 '11 at 10:19

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.