Can a macro access its own name?
No. The macro must be expanded to reveal and execute the code. But the expansion replaces the macro token with the definition text, meaning the original macro is gone and no trace* is left that shows, where the code has come from.
* If \tracingmacros
is active, then the .log
file would tell the expansion step, but enabling \tracingmacros
in the macro itself is too late. Also reading the .log
file from within TeX is not as easy because the .log
file block might not yet be written (buffered output/OS dependent behavior/...) and in the second run the .log
file will be overwritten.
I don't know the origin of this question (two macros are the same from
\ifx
point of view and behaves differently with respect of their name).
But I would to present the way to modification of TeX source to solve this
task. I don't expect that somebody use this patch. This is only an
illustration how easy or hard such modification is. Let me start by
citation:
Certainly, if I were in the publishing business myself, I would have probably had ten different versions of TEX by now for ten different complicated projects that had come in. They would all look almost the same as TEX, but no one else would have this program--they wouldn't need it, they're not doing exactly the book that my publishing house was doing.
Donald E. Knuth, Prague, March 1996
We need to add the new primitive \lastexpanded
which expands to the name
of the last expanded macro similar as \string
does it. This means, that
\TeX \edef\a{\lastexpanded} \edef\b{\string\TeX}
now: \a is equal to \b
We do this by creating mytex.ch
change file. This is a "patch" to the
tex.web
source file. We start by intensively flipping through second
volume of C&T (TeX: The program) and by intensively thinking about it.
Then we create the following file:
% This is a modification of TeX inspired by
% http://tex.stackexchange.com/questions/130285/has-a-command-access-to-its-own-name
% This modification adds new primitive \lastexpanded which expands to the
% \string of the last expanded macro name.
\S 297 declaration of global variables
@x
@!cur_tok: halfword; {packed representative of |cur_cmd| and |cur_chr|}
@y
@!cur_tok: halfword; {packed representative of |cur_cmd| and |cur_chr|}
@!lastexpanded_cs: pointer; {variable for \.{\\lastexpanded}}
@!lastexpanded_chr: halfword; {|cur_chr| for \.{\\lastexpanded}}
@z
\S 389 macro_call saves its name
@x
warning_index:=cur_cs; ref_count:=cur_chr; r:=link(ref_count); n:=0;
@y
warning_index:=cur_cs; ref_count:=cur_chr; r:=link(ref_count); n:=0;
lastexpanded_cs:=cur_cs; lastexpanded_chr:=cur_chr;
@z
\S 439 default values
@x
cur_val:=0; cur_val_level:=int_val; radix:=0; cur_order:=normal;
@y
cur_val:=0; cur_val_level:=int_val; radix:=0; cur_order:=normal;
lastexpanded_cs:=0; lastexpanded_chr:=0;
@z
\S 468 adding new expandable primitive \lastexpanded
@x
@d job_name_code=pdftex_convert_codes {command code for \.{\\jobname}}
@y
@d job_name_code=pdftex_convert_codes {command code for \.{\\jobname}}
@d lastexpanded_code=pdftex_convert_codes + 1 {command code for
\.{\\lastexpanded}}
@z
@x
primitive("jobname",convert,job_name_code);@/
@!@:job_name_}{\.{\\jobname} primitive@>
@y
primitive("jobname",convert,job_name_code);@/
@!@:job_name_}{\.{\\jobname} primitive@>
primitive("lastexpanded",convert,lastexpanded_code);@/
@!@:lastexpanded_}{\.{\\lastexpanded} primitive@>
@z
\S 469 printing about new primitive
@x
othercases print_esc("jobname")
@y
lastexpanded_code: print_esc("lastexpanded");
othercases print_esc("jobname")
@z
\S 470 the c declaration
@x
@!c:number_code..job_name_code; {desired type of conversion}
@y
@!c:number_code..lastexpanded_code; {desired type of conversion}
@z
\S 471 Scanning argument, \lastexpanded has no argument
@x
job_name_code: if job_name=0 then open_log_file;
@y
job_name_code: if job_name=0 then open_log_file;
lastexpanded_code: do_nothing;
@z
\S 472
@x
job_name_code: print(job_name);
@y
job_name_code: print(job_name);
lastexpanded_code: if lastexpanded_cs<>0 then sprint_cs(lastexpanded_cs)
else print_char(lastexpanded_chr);
@z
The new expandable primitive is added in section 468. Here is a
little complication because our patch will be applied to the pdftex
: there
are many new primitives and this is a reason why there is different value of the last code job_name_code
than in the original TeX.
The global variables lastexpanded_cs
and lastexpanded_chr
are set in
macro_call
procedure (section 389) and they are used in section 472 when
\lastexpanded
is expanded.
Now, you can add the mytex.ch
as the last item to the pdftex_ch_srcs
list in the Makefile
in the source/build/texk/web2c/
of the pdftex
source.
Then you can run make pdftex
. The new pdftex
binary is compiled. You can
try:
./pdftex -ini
**\relax
*\show\lastexpanded
> \lastexpanded=\lastexpanded.
You can generate the format ./pdftex -ini -jobname pdftex -etex pdfetex.ini
and use it in the same directory by ./pdftex test
. The test.tex
would be:
\edef\redname{\string\red}
\def\red{\edef\myname{\lastexpanded}%
\ifx\myname\redname \message{I am RED}%
\else \message{I am NOT red}%
\fi
}
\let\foo=\red
\red % the output: I am RED
\foo % the output: I am NOT red
\ifx\red\foo \message{YES}\fi % the otput: YES
\end
Also as Heiko has said, it is not possible to do that using a macro by itself, I think it might be possible to do this using something that looks like a macro but is not.
The mean i think of would be do decide of a prefix character that would be applied to every color, and make this to be active. You would then be able to gobble the tokens of the color name from within that active character and do what you described.
For exemple, using "/" as the active character, you would then declare your color using
/red % Gives "red"
/blue % Gives "not red"