Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I found this code somewhere on the Tex archives and have been puzzling over it for some time. Can anyone describe how it works?

     % Date: Thu, 7 Feb 91 12:20:50 -0500
%From: amgreene@ATHENA.MIT.EDU
%Subject: A response to perl hackers
\let~\catcode~`?`\
\let?\the~`#?~`~~`]?~`~\let]\let~`\.?~`~~`,?~`~~`\%?~`~~`=?~`~]=\def
],\expandafter~`[?~`~][{=%{\message[}~`\$?~`~=${\uccode`'.\uppercase
{,=,%,{%'}}}~`*?~`~=*{\advance.by}]#\number~`/?~`~=/{*-1}\newcount.
=\-{*-}~`-?~`~]-\-~`^?~`~=^{*1}~`\ ?~`~= {.`\ $}~`@?~`~=@{,.,"#`@^$}
.`#*`'$.?~`~0-?~`~$//$^$ .``^$*?~`~$^$.?~`~0-?~`~/$-?~`~^$@*?~`~$ *
?~`~*?~`~*?~`~*?~`~$@-?~`~$ .?~`~0-?~`~-?~`~$.``^$^^$.`<-?~`~*`<$@*
?~`~$*?~`~-`(-`+$%}\batchmode

It lists all your input files!

share|improve this question
1  
And outputs Just another TeX hacker. –  Geoff Aug 24 '10 at 22:50
4  
Are you sure you want us to spoil the fun? What are you stuck on? Do you know what the first line does? If not, use tex by topic for reference. –  Will Robertson Aug 24 '10 at 23:32
    
:( Now I am also curious.... –  Vivi Aug 25 '10 at 0:22
    
BTW, this doesn't do anything about input files: perhaps you are thinking of another example? –  Joseph Wright Aug 25 '10 at 8:38

2 Answers 2

up vote 41 down vote accepted

Most of the code here is set up, with very little actual 'payload'. Splitting things into one line per instruction is useful, with the proviso that this will cause issues with the real thing due to the spaces that get introduced as a result. \tracingall will help also, as already pointed out.

Taking the first line of the posted code we have

\let~\catcode
~`?`\

This starts with the assumption that ~ is active, and so can be \let to \catcode. Next, this new way of setting a catcode is used to make ? active, as the end-of-line character has character code 13, which is the category code for an active character. (To see this, notice that there is no space after the \ at the end of the line).

The next line in the original contains:

~`#?~`~
~`]?~`~
\let]\let
~`\.?~`~
~`,?~`~
~`\%?~`~
~`=?~`~
]=\def

So this is mainly catcode assignments (remembering that ~ is \catcode). The characters # and ] are both made active, and the ] is \let to \let. Next, ., ,, % and = are all made active. These line would normally be written

\catcode`\.\the\catcode`~

or more usually

\catcode`\.\active

The final instruction on the second line is to \let the = token to \def.

The third line of the original actually goes over slightly onto the forth one:

],\expandafter
~`[?~`~
][{
=%{\message[}
~`\$?~`~
=${\uccode`'.\uppercase{,=,%,{%'}}}

So we have another \let, a category code change and then yet another \let. There is then a \def (using the = version), which results in the active % having the definition \message[. That macro is going to be used later to build up the message that the code prints. Yet another category code change follows, to make $ active, and then this is defined in the last part of the line. The idea of that definition is to make ' active and to redefine % within a case-changing block.

The remainder of the fourth line contains

~`*?~`~
=*{\advance.by}
]#\number
~`/?~`~
=/{*-1}
\newcount.

So yet again we have a token made active, this time *, which is then defined to \advance.by. We then have # begin \let to \number, and then / is made active and defined as expanding to *-1. The last instruction on this line creates a new \count, which will be referred to as . (which was made active a while ago).

The next line can be broken up to read

=\-{*-}
~`-?~`~
]-\-
~`^?~`~
=^{*1}
~`\ ?~`~
= {.`\ $}
~`@?~`~
=@{,.,"#`@^$}

So there is a definition of \-, then - is made active and \let to the definition of \-. The ^ token is made active and defined as *1, then the space token is made active and given a definition. Finally, @ is made active and given a definition. That completes the bulk of the set up: most of the rest of the code is the message that gets printed!

The rest of the code consists of altering the value of . (a count) and then redefining %. The idea (in general) is that ' is given the upper-case code of the value of ., and this value is the character code of the letter required for the message. To keep the code complex, the numbers are done as far as possible using character codes rather than actual numbers. This is rather tedious to go through, so I'd recommend reading the \tracingall output for full details.

One more point to note is that the code finishes

%}\batchmode

As this stage, % is defined as \message[Just another TeX hacker, where [ will act as an opening brace but there is no closing brace. That is supplied by the literal }, which comes after % is finally used.

share|improve this answer
5  
+1 Wow, I used to enjoy each year's 'Obfuscated C' competitions way back in the day. But as C isn't self-modifying (*), TeX leaves it eating dust. I no longer have any doubt that TeX is 'Turing Complete', in the strict sense of "take a strip of paper, write a 1, move left,...,read,erase, move right,...". Obfuscated TeX, indeed. My hat's off to you, Joseph. [(*) technically, except in the pre-processor, that is.] –  Geoffrey Jones Aug 25 '10 at 8:17
1  
Remember that \tracingall is your friend (as long as you are only trying to understand something short!) –  Joseph Wright Aug 25 '10 at 8:36
    
Actually, the first line doesn't make a lot of sense to me. The end of line character has category code 5 as \showthe\catcode` demonstrates (there should be a newline after the \, alternatively, use ^^M. Why is ? getting catcode 13 instead? –  TH. Aug 25 '10 at 8:45
2  
Ah, I figured it out. It's not that ^^M has category code 13 (it doesn't), it's that `\^^M is the number 13. –  TH. Aug 25 '10 at 8:59
    
It is not the category code that gets assigned here but the character code. The backtick-slash construct means 'convert the following character to a number', whereas to get the category code you'd have \the\catcode before the backslash. –  Joseph Wright Aug 25 '10 at 9:00

Maybe this is cheating, but try running the code with \tracingall before the first line. You can watch TeX work.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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