Hi Bruno,

Just a quick reply, sorry.

On 09/01/2011, at 8:53 AM, Bruno Le Floch wrote:

>   \cprotect\section[...\verb|#&!|...]{...\verb|#&!|...}  How does
>> \cprotect know what to read in?
> I propose the following: \cprotect[argument specification], where the
> argument specification is like in xparse. Your example would become
>   \cprotect[om]\section[...\verb|#&!|...]{...\verb|#&!|...}
> If the optional argument is missing, \cprotect\foo could proceed like
> this: [snip]

This seems like a sensible approach.
You could also scan ahead for opening braces and assume if they exist they're an argument for the macro. (Not sure if this would be more or less reliable than the other tests you proposed, though.)

> - Maybe also add the case of internal commands (\foo:Nn, or whatever),
>  where the argument specification would be read from the name? Although
>  I don't expect any use for that: internals should not need
>  \cprotect. Should they?

I doubt it. FWIW, for expl3 functions you can use \cs_get_arg_count_from_signature:N to find out how many arguments they take. (This is used internally for commands like \cs_new:Nn)

-- Will