Defining Macros.

Last-modified: 2011-06-04 (土) 02:04:06

\def - primitive

  • \def の引数における空白の処理

    \def\somecs#1\+#2\plus#3+#4\+{1: [#1] \quad 2: [#2] \quad 3: [#3] \quad 4: [#4]}

    のように定義して, 以下の場合を考えてみる.

    \somecsa\+b\plusc+d\+

    ! Undefined control sequence.

    \somecs a\+b\plusc+d\+

    ! Paragraph ended before \somecs was complete.

    \somecs a\+b\plus c+d\+

    1: [a]     2: [b]     3: [c]     4: [d]

    \somecs a\+ b\plus c+ d\+

    1: [a]     2: [ b]     3: [c]     4: [ d]

    \somecs a \+b \plus c +d \+

    1: [a ]     2: [b ]     3: [c ]     4: [d ]

    第一例では, 当然ながら \somecs と解釈されない. 第二例では, \plusc と解釈されて \somecs の定義に沿わないため, \somecs が imcomplete となる. 第三例では, control sequence \somecs と \plus の後の空白は無視されるが, control symbol \+ と通常の文字である + の後の空白はそのまま引数に含まれる. 最後の第四例では, 当然ながらどの場合も引数の最後の空白はそのまま引数に含められる.

\zap@space

\ignorespaces

\tracingmacros

正の値にすると,
log に macro の展開結果が記録される.

\@ifdefinable

\long\def\@ifdefinable #1#2{%
      \edef\reserved@a{\expandafter\@gobble\string #1}%
     \@ifundefined\reserved@a
         {\edef\reserved@b{\expandafter\@carcube \reserved@a xxx\@nil}%
          \ifx \reserved@b\@qend \@notdefinable\else
            \ifx \reserved@a\@qrelax \@notdefinable\else
              #2%
            \fi
          \fi}%
         \@notdefinable}
\let\@@ifdefinable\@ifdefinable
\long\def\@rc@ifdefinable#1#2{%
  \let\@ifdefinable\@@ifdefinable
  #2}
(Definition in latex.ltx)
  • 用法

    \@ifdefinable{\somecs}{macro}

    \edef\reserved@a{\expandafter\@gobble\string \somecs}%

    \@ifundefined\reserved@a

        {\edef\reserved@b{\expandafter\@carcube \reserved@a xxx\@nil}%

         \ifx \reserved@b\@qend \@notdefinable\else

           \ifx \reserved@a\@qrelax \@notdefinable\else

             macro%

           \fi

         \fi}%

        \@notdefinable}

    \edef\reserved@a{\@gobble\somecs}%

    \@ifundefined\reserved@a

        {\edef\reserved@b{\expandafter\@carcube \reserved@a xxx\@nil}%

         \ifx \reserved@b\@qend \@notdefinable\else

           \ifx \reserved@a\@qrelax \@notdefinable\else

             macro%

           \fi

         \fi}%

        \@notdefinable}

    \edef\reserved@a{somecs}%

    \@ifundefined\reserved@a

        {\edef\reserved@b{\expandafter\@carcube \reserved@a xxx\@nil}%

         \ifx \reserved@b\@qend \@notdefinable\else

           \ifx \reserved@a\@qrelax \@notdefinable\else

             macro%

           \fi

         \fi}%

        \@notdefinable}

\gdef\@notdefinable{%
 \@latex@error{%
   Command \@backslashchar\reserved@a\space
   already defined.\MessageBreak
   Or name \@backslashchar\@qend... illegal,
   see p.192 of the manual}\@eha}
\edef\@qend{\expandafter\@cdr\string\end\@nil}
\edef\@qrelax{\expandafter\@cdr\string\relax\@nil}

\newcommand

\def\newcommand{\@star@or@long\new@command}
\def\new@command#1{%
  \@testopt{\@newcommand#1}0}

\@testopt により option をとるかどうかを判定する.
Option が与えられていない場合は, \@newcommand#1[0] を実行.

\def\@newcommand#1[#2]{%
  \@ifnextchar [{\@xargdef#1[#2]}%
                {\@argdef#1[#2]}}
\long\def\@argdef#1[#2]#3{%
   \@ifdefinable #1{\@yargdef#1\@ne{#2}{#3}}}
\long\def\@xargdef#1[#2][#3]#4{%
  \@ifdefinable#1{%
     \expandafter\def\expandafter#1\expandafter{%
          \expandafter
          \@protected@testopt
          \expandafter
          #1%
          \csname\string#1\endcsname
          {#3}}%
       \expandafter\@yargdef
          \csname\string#1\endcsname
           \tw@
           {#2}%
           {#4}}}
\def\@protected@testopt#1{%%
  \ifx\protect\@typeset@protect
    \expandafter\@testopt
  \else
    \@x@protect#1%
  \fi}
\long\def\@yargdef#1#2#3{%
  \@tempcnta#3\relax
  \advance \@tempcnta \@ne
  \let\@hash@\relax
  \edef\reserved@a{\ifx#2\tw@ [\@hash@1]\fi}%
  \@tempcntb #2%
  \@whilenum\@tempcntb <\@tempcnta
     \do{%
         \edef\reserved@a{\reserved@a\@hash@\the\@tempcntb}%
         \advance\@tempcntb \@ne}%
  \let\@hash@##%
  \l@ngrel@x\expandafter\def\expandafter#1\reserved@a}
\long\def\@reargdef#1[#2]{%
  \@yargdef#1\@ne{#2}}

\renewcommand

\def\renewcommand{\@star@or@long\renew@command}
\def\renew@command#1{%

 \begingroup \escapechar\m@ne\xdef\@gtempa{{\string#1}}\endgroup
 \expandafter\@ifundefined\@gtempa
    {\@latex@error{\noexpand#1undefined}\@ehc}%
    \relax
 \let\@ifdefinable\@rc@ifdefinable
 \new@command#1}

\DeclareRobustCommand

\def\DeclareRobustCommand{\@star@or@long\declare@robustcommand}
(Definition in latex.ltx)

\DeclareRobustCommand* とすると, \l@ngrel@x が \long になる.

\def\declare@robustcommand#1{%
   \ifx#1\@undefined\else\ifx#1\relax\else
       \@latex@info{Redefining \string#1}%
    \fi\fi
    \edef\reserved@a{\string#1}%
    \def\reserved@b{#1}%
    \edef\reserved@b{\expandafter\strip@prefix\meaning\reserved@b}%
   \edef#1{%
      \ifx\reserved@a\reserved@b
         \noexpand\x@protect
         \noexpand#1%
      \fi
      \noexpand\protect
       \expandafter\noexpand\csname
         \expandafter\@gobble\string#1 \endcsname
   }%
   \let\@ifdefinable\@rc@ifdefinable
   \expandafter\new@command\csname
      \expandafter\@gobble\string#1 \endcsname
}
(Definition in latex.ltx)