# Detecting catcode in parameter text

Say someone has defined

\documentclass{minimal}
\begin{document}

\def\fooA#1@{}
\makeatletter
\def\fooB#1@{}

\end{document}


It is easy to test and see that the two are different: \ifx\fooA\fooB...\else...\fi.

But if we are given one of \fooA and \fooB and we have not seen the definition before, can we tell what the catcode of the @ delimiting the parameter is?

Disclaimer: I am interested in the answer out of sheer curiosity.

EDIT: basically, is there a version of \meaning which keeps catcodes? or is there a way to show the catcodes of tokens in the parameter text? --- The answer, below, is "no".

-
You might want to look at what etoolbox does, where it checks if the catcodes in a definition are at least the same as those which are current. –  Joseph Wright Jan 28 '11 at 22:38
@Joseph: an interesting piece of code. etoolbox does not seem to have a documented source :(. --- For those interested, \etb@ifscanable does the following: it reads the meaning of its argument; splits it in the different pieces (prefixes, parameter text, replacement text) ; and builds a definition out of this. Then it compares the result of the definition with the original command using \ifx. If it is the same, then etoolbox knows that it can recreate the macro, and hence patch it. –  Bruno Le Floch Jan 28 '11 at 23:04

No, you cannot.

The only ways to read the definition of a macro (and its parameter text) is \meaning (\show only displays it to the user). Unfortunately it turns all characters to the catcode "other", except spaces which stay spaces. Therefore you can not detect the difference.

-
Ok. I was afraid this would be the answer in general. What about ts special case? Maybe trying something like ...\foo...@...@... with two different catcodes for @ might work? or some more devious \batchmode\foo@\errorstopmode to check if \foo accepts its argument? –  Bruno Le Floch Jan 28 '11 at 22:44
@Bruno: What exactly do you want to do? Test if the macro will expand correctly? Or defining one which will expand correctly independent from the current catcodes? –  Martin Scharrer Jan 28 '11 at 22:48
Thinking about it, I guess that the general question made sense, but the more specific one would only make sense with a specific application in mind. And as I said, I was only curious... And I cannot remember what made me think about this. Sorry for the hassle :). –  Bruno Le Floch Jan 28 '11 at 23:15

A disappointing answer: This has nothing to do with catcodes of \fooA or \fooB. The \ifx test just sees that the parameter texts of the two macros are different (they contain different @s), so it turns out negative. The \ifx test doesn't care what the difference is.

-
@Bruno, ups, you edited your code parallel to me writing my comment, so I deleted it again, because I thought it was not necessary any longer ... –  Martin Scharrer Jan 28 '11 at 22:31
@Bruno: My answer was not formulated well (it was the last thing before going to bed); I tried to make it clearer what I mean. –  Hendrik Vogt Jan 29 '11 at 8:29
Now this makes sense. It doesn't quite answer my question, but that's because the question was unclear :). –  Bruno Le Floch Jan 29 '11 at 8:39
I think that your first comment should remain. --- For the record, many comments were written and deleted on this answer. –  Bruno Le Floch Jan 29 '11 at 11:25

Following the comments of Bruno and Joseph on the question, if you were willing to sacrifice speed (significantly), you could reconstruct the command a la \etb@ifscanable in etoolbox for every possible catcode combination of the tokens (characters?) in the parameter text, and see which one \ifxed to the original command.

(I don't think you'd even be able to special case #1, etc., if you wanted it to catch \bar in something like

\def\gobblethree#1#2#3{}
\edef\foo{\def\noexpand\bar\expandafter\gobblethree\detokenize{##}1{}}
\foo


)

-
I thought about this, and indeed, it is possible in principle, but really... ;-) An alternative perhaps would be to hook into the definition of \def (and \edef, \gdef, \xdef, \afterassignment, \global, \let, \fututrelet and a few others) at the very start of the run, and save all the definitions as we go. –  Bruno Le Floch Apr 9 '11 at 1:40