Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

\in@ and the category code 6

33 views
Skip to first unread message

GL

unread,
May 20, 2013, 6:13:06 AM5/20/13
to
Hello,

is there a way to check if a string contains
a macro parameter # ?

Thanks for your ideas.

zappathustra

unread,
May 20, 2013, 7:38:09 AM5/20/13
to
GL <goua...@gmail.com> a écrit:
Try this:

\def\endcheck{\endcheck}
\def\checkhash#1{%
\docheckhash#1\endcheck
}
\def\docheckhash#1{%
\ifx#1\endcheck
\expandafter\second
\else
\ifx#1##%
\expandafter\expandafter\expandafter\gobbletocheck
\else
\expandafter\expandafter\expandafter\docheckhash
\fi
\fi
}
\def\second#1#2{#2}
\def\gobbletocheck#1\endcheck#2#3{#2}

\checkhash{abc#def}{YES}{NO}
\checkhash{abcdef}{YES}{NO}
\bye

This will run into trouble if the string to test contains groups with
the first two tokens repeated, e.g.:

\checkhash{ab{cc}def}{YES}{NO} % This will hang indefinitely.

If you’re interested in the hash character, no matter its catcode, the
following definition is more robust (only two lines have changed):

\def\endcheck{\endcheck}
\def\checkhash#1{%
\docheckhash#1\endcheck
}
\csname my hash string: #\endcsname
\def\docheckhash#1{%
\ifx#1\endcheck
\expandafter\second
\else
\ifcsname my hash string: \detokenize{#1}\endcsname
\expandafter\expandafter\expandafter\gobbletocheck
\else
\expandafter\expandafter\expandafter\docheckhash
\fi
\fi
}
\def\second#1#2{#2}
\def\gobbletocheck#1\endcheck#2#3{#2}

Otherwise, if the test needs not be expandable, other solutions can be found.

Best,
Paul

Ahmed Musa

unread,
May 21, 2013, 12:35:34 PM5/21/13
to

Ulrich D i e z

unread,
May 22, 2013, 5:28:23 AM5/22/13
to
That depends.

How to treat active characters let equal to their catcode-6-equivalents?

How to treat control-sequence-tokens let equal to catcode-6-characters?

If it is just about the charcode 35/catcode 6-character-token, then it
is possible to iterate and "cut down" the string "undelimited-argumentwise"
until either a catcode6-# is found or the string is empty,
hereby forking the cases of within an iteration the string starting
either with space or with an argument nested in catcode1/2-braces.
(In the first case remove the space, in the latter case apply the
hash-checking-routine on the item within the catcode 1/2-braces.)
Determining whether a catcode6-# is found can be done via an \ifx-check/
\ifcat-check (probably in combination with some delimited-argument-checks
for detecting the case of a control-sequence or an active-hash let equal
to a catcode6-hash).

A non-expandable approach might be to apply \detokenize /
\@onelevel@sanitize in order to see if hash-doubling occurred...

Sincerely

Ulrich

Ulrich D i e z

unread,
May 22, 2013, 6:03:13 AM5/22/13
to
zappathustra wrote:

> This will run into trouble if the string to test contains groups with
> the first two tokens repeated, e.g.:

This uses \ifx-comparison.

\ifx-comparison yields the <if-branch> when comparing
character-tokens with active-characters/control-sequences
\let equal to these character-tokens...

You might need some additional (delimited-argument-)checks
for distinguishing.

E.g.

\begingroup
\catcode`\#=13
\def\hashlet{\endgroup\let#=}%
\hashlet#

\let\foobar=#
\let\#=#

\catcode`\#=13
\meaning#

\catcode`\#=6
\meaning#

\meaning\foobar

\meaning\# % might require extra consideration if \escapechar=-1...

\bye



Ulrich
0 new messages