It's simple, actually.
The \catcode
token alone tells TeX that a category code assignment is to be performed;
in this case, TeX looks for an 8-bit ⟨number⟩ (it's 21-bit for XeTeX or LuaTeX);
upon having found it, TeX looks for an ⟨optional equals⟩ (gobbling a space after =
, if both are present);
TeX looks for a 4-bit number.
How the ⟨number⟩ can be specified is too long to describe. In your case, both the required ⟨number⟩s are explicit constants, and a category 10 space would be gobbled after the sequence of digits.
It's also important to remember that an entire line of input is read, and the end-of-record is replaced by the \endlinechar
, after throwing out trailing spaces, but the characters haven't yet been tokenized: TeX tokenizes the input only when it needs to.
So the following code lines are completely equivalent:
\catcode32=13\def {o} \bye
\catcode32 =13\def {o} \bye
\catcode32= 13\def {o} \bye
\catcode32=13 \def {o} \bye
\catcode32 = 13\def {o} \bye
\catcode32 =13 \def {o} \bye
\catcode32 = 13 \def {o} \bye
Indeed, the input
{\catcode32=13\def {o} }\par
{\catcode32 =13\def {o} }\par
{\catcode32= 13\def {o} }\par
{\catcode32=13 \def {o} }\par
{\catcode32 = 13\def {o} }\par
{\catcode32 =13 \def {o} }\par
{\catcode32 = 13 \def {o} }\par
\bye
produces seven o's. Your case is the first one, where \def
cannot be interpreted as a digit: the token is put aside to be reread after the assignment has been performed.
Let's examine
\catcode32=13 \def {o} \bye
that's what you probably want to know about (the other two with a space after 13 are similar). When TeX has scanned the =
, it proceeds to look for a 4-bit ⟨number⟩. It finds 1
, so it knows that an explicit constant follows. Next comes 3
and further comes a space. No category code assignment has yet been done, so this space is given category code 10 and terminates the lookup for digits. Now TeX know what category code to assign, it performs the assignment and discards the category 10 character that follows.
Maybe you can ask what would happen with
\catcode32=13 \def {o} \bye
Exactly the same, because after scanning a category code 10 character, TeX enters the state “skipping blanks”, so the following category 10 characters are ignored. This action of skipping blanks happens before the assignment of category code is performed, because TeX wants to “normalize” the input stream.
Exercise: predict the output of
\catcode32=13\def {o} \ \bye
(there are two spaces after the backslash).