How to print and assign category codes?

Consider the code below, which after giving me some trouble (especially with catcode 9 and 15), prints all the category codes up to catcode 15.

\documentclass{minimal}
\parindent0pt
\begin{document}
\the\catcode\\  \ control character  \\
\the\catcode{  \ open curly\\
\the\catcode}  \ closing curly \\
\the\catcode\$  \ dollar\\
\the\catcode&  \ alignment\\
\the\catcode\
\ space \\\the\catcode#  \ sharp\\
\the\catcode^ \ hat \\
\the\catcode_ \ underscore \\
\number\catcode\  \ space \\
\catcode \y=9
\the\catcode\y    \ ignored character \\
\the\catcodea \ letters\\
\number\catcode@  \ restricted  \\
\number\catcode~ \ tilde \\
\the\catcode\%   \ comment\\
\catcode\z = 15
\the\catcode\z  \ invalid character \\
\def\test{}
%\catcode \t=16
\ifcat\test 16  16  control sequence\fi
\end{document}


Now, getting TeX to print the catcode 16, has me puzzled. For starters if you uncomment the line, %\catcode \t=16 you get,

! Invalid code (16), should be in the range 0..15.
l.23 \catcode\t=16


but, if you test with \ifcat a control sequence is definitely equal to category code 16. So my question is, how can I coerce TeX to say sixteen for a control sequence and how come the error message says 16 is an invalid code, but the TeXbook says it is?

Mildy related question How do I get the category code of a character that is the value of a control sequence?

-
Where in the TeX Book does it refer to a catcode of 16? I thought there were 16 in total, numbered 0 to 15. –  Werner Oct 18 '11 at 22:55
@Werner Chapter 20, page 209 detailing the if commands. –  Yiannis Lazarides Oct 18 '11 at 23:01
Please correct the title to "category code", not character code. –  Bruno Le Floch Oct 19 '11 at 8:04
@BrunoLeFloch ny bad! Thanks for picking it up! –  Yiannis Lazarides Oct 19 '11 at 10:10

There's really no category code 16. This code is assigned to control sequences (not \let to a character) only for the purposes of \ifcat.

Similarly, character code 256 is assigned to the same tokens for the purposes of \if.

You can get category codes 9 and 15 with

\the\catcode\^^@
\the\catcode\^^?


(these are the only characters that have those category codes in the default setting, bytes 0 and 127).

Notice also that \ifcat doesn't compare a token with a number, but two tokens:

\ifcat ab
\ifcat a1


The first evaluates to true, the second to false.

Quoting from the TeXbook, page 209:

\ifcat<token1><token2> (test if category codes agree)
TeX will expand macros following \if until two unexpandable tokens are found. If either token is a control sequence, TeX considers it to have character code 256 and category code 16, unless the current equivalent of that control sequence has been \let equal to a non-active character token.

The key word is considers. Look at page 38:

A token is either (a) a single character with an attached category code, or (b) a control sequence.

Section 506 of "TeX, the program" tells the truth about this: if the next token is not an active character or is a control sequence (not let to a character), then the variable *cur_chr* gets the value 256.

-
Why then this \ifcat\test 16 true\else false\fi is true? Where in the TeXbook does it say it is really no category 16? I read it differently on page 209, chapter 20. –  Yiannis Lazarides Oct 18 '11 at 23:10
@YiannisLazarides With your definition \test expands to nothing; so \ifcat compares 1 with 6 and their category codes agree. –  egreg Oct 18 '11 at 23:16
Just thinking aloud this is also one of Knuth's jokes \ifcat doesn't compare a token with a number, but two tokens in my ifcat test it definitely compares one with two i.e, cs, number,number???? Two numbers are two tokens, right? –  Yiannis Lazarides Oct 18 '11 at 23:19
@YiannisLazarides Yes, 16 is two tokens and they are unexpandable, so the expansions triggered by \ifcat stop. It's not like \ifcat#=4`, to be clearer. –  egreg Oct 18 '11 at 23:25