• No results found

Index of /CTAN/macros/latex/contrib/inlinedef

N/A
N/A
Protected

Academic year: 2022

Share "Index of /CTAN/macros/latex/contrib/inlinedef"

Copied!
23
0
0

Full text

(1)

The inlinedef package

Stephen Hicks

v1.0 – 2008/07/10

1 Usage

1.1 The problem

Often package writers want to redefine certain macros to do slightly more than what they did previously, adding a control sequence or two to the beginning or the end of the definition. The easiest way to accomplish this is to use something like

\let\old@macro\macro

\def\macro{...\old@macro...}

But this sort of construction can cause problems if another package also wants to redefine the same macro and happens to choose the same name to save it to. It’s also an ugly solution in that it pollutes the global namespace with extra macro names. A much cleaner solution is to define the new macro with the old macro expanded inline, as in \edef\macro{...\macro...}. This is generally problemmatic because there are often undefined control sequences and macros that we don’t want to expand quite yet. A compromise is to use\expandafter, but this leads to error-prone and unreadable code:

\expandafter\def\expandafter\macro\expandafter{\expandafter ...\macro...}

1.2 The solution

What we really want is a way to expand just a few tokens in the definition and leave the rest untouched. We provide a command\Inlinethat can be inserted

\Inline

before a\def or \gdef (optionally prefixed by\long, \outer, and/or\global, as in \Inline\long\outer\gdef...). Within \Inline definitions, only tokens preceded by\Expandare expanded. Thus, the previous example becomes

\Expand

\Inline\def\macro{...\Expand\macro...}

email: [email protected]

(2)

1.3 Special commands

While nearly everything can be done with\Expandalone, we provide a few more keywords for completeness and convenience.

• \Expand - Performs a single expansion on the token or group immediately

\Expand

following and places the result directly into the definition without further processing. In the case of a group, only the first token is expanded (although

\expandafters may be used to expand a different token), and the outermost grouping braces are discarded.

• \MultiExpand{hnumberi}- Expands the following token or group the given

\MultiExpand

number of times. For example,

\MultiExpand{3}{\expandafter\expandafter\expandafter\a

\expandafter\b\c}

expands first\c, then\b, then\a, and inserts the whole expansion into the definition with no braces. Note that the braces are important. Otherwise it will just try to expand the first\expandafterthree times, which is clearly wrong.

• \UnsafeExpand- This version simply inserts an\expandafter, performing

\UnsafeExpand

the expansion as in\Expandabove, but reinserting the result back into the stream to be processed. Thus, any tokens like \Expand or \Super in the expansion will be acted on. Unlike the previous two commands, groups are not treated differently.

• \NoExpand - If a token is preceeded by \NoExpand then it is inserted in

\NoExpand

the definition exactly as-is. This is required to insert any of the special tokens\Expand,\NoExpand, etc, as well as the internal token\Q@END, into a definition. If the token immediately following\NoExpandis an open-brace then the entire text of the group will be inserted without expansion, and the outer level of grouping will be lost.

• \Super- When redefining an already existing macro,\Superwill expand to

\Super

the previous definition of the macro. Any macro parameters are automat- ically substituted. If the macro is undefined, or if the new parameter text doesn’t match with the old text, then this will cause an error.

• \Recurse - This is complementary to \Super and, while not strictly nec-

\Recurse

essary, is included for clarity. \Recurseis equivalent to\NoExpand\macro when defining\macro. However, since \macrois, by default, not expanded anyway, this is a bit redundant.

(3)

1.4 Calling options

When the name of the macro we’re defining is encountered, there are three differ- ent ways we might proceed: leave it alone (\NoExpand), expand it with implicit parameters (\Super), or expand it with explicit parameters (\UnsafeExpand).

We therefore allow zero, one, or two stars to come after\Inline to change this behavior.

• \Inline- Without any stars, we default to leaving the macro name alone,

\Inline

as in\NoExpand\macro. This is the most consistent behavior with the rest of the package and works regardless of whether the macro is being defined or redefined.

• \Inline*- With a single star, we treat the macro name as a call to\Super

\Inline*

and expand it with parameters inserted automatically. This is preferred over\Expandbecause it doesn’t lead to the possible surprises in the case of recursively-defined macros.

• \Inline**- Finally, with two stars, the macro name is treated as if it were

\Inline**

preceeded by \UnsafeExpand. Any parameters must be inserted explicitly, and the expansion is itself subject to inline processing. Note that this form is the most dangerous.

One final option applies only in the case of redefining an already-existing macro.

\Inline!

In this case, if the parameter text of the new definition differs from the parameter text of the old definition, we will produce an error. This error can be suppressed by adding a bang to the end of\Inline(either before or after the stars), acknowl- edging that any ill consequences that result are your own fault.

1.5 Known issues

• If a macro is defined with a character other than # catcoded to 6, then

\Superwill fail unless the same character is used in the redefinition.

1.6 Related packages

moredefs Themoredefspackage in thefrankensteincollection provides some sim- ilar syntactic sugar, but is not as expressive.

(4)

2 Implementation

\xa Make the @-sign into a letter for use in macro names. As long as the packages are well-behaved, we can put this here and not later. We also define \xato be

\expandafterfor convenience.

1h∗packagei

2\makeatletter

3\let\xa\expandafter

\ifID@aborted

\ifID@star

\ifID@starstar

\ifID@bang

We define a conditional so that we can gracefully abort in case of an error.

4\newif\ifID@aborted

5\newif\ifID@star

6\newif\ifID@starstar

7\newif\ifID@bang

\ID@toks

\ID@count

At some point we need to stop using the internal toks registers and allo- cate our own, because somebody might want to\Expand{\the\toks@} and ex- pect something else. We can get by with a single one though by defining a

\ID@pdef that doubles all the # signs and then does a regular def, so that

\ID@pdef\cs\ID@toks ... \cswill be the same as\the\ID@toks.

8\newtoks\ID@toks

9\newcount\ID@count

\Inline

\ID@scandef

These are the macros that get it all started. \Inlineopens up a group (which is closed at the end of \ID@def) and initializes a toks register (we don’t bother allocating it since we’re in a group and don’t call any LATEX or TEX macros that make use of allocated toks registers. Then we scan the tokens until we find either an\edefor an\xdef. If it’s anything else, we just add it to the toks register. We also have a list of bad tokens that will cause an error message, so that we don’t go too far before figuring out what went wrong. Should\Inlinebe \outer?

10\DeclareRobustCommand\Inline{%

11 \begingroup

12 % Define a few ‘‘quarks’’

13 \def\Expand{\Expand}\def\Super{\Super}%

14 \def\UnsafeExpand{\UnsafeExpand}\def\MultiExpand{\MultiExpand}%

15 \def\Recurse{\Recurse}\def\NoExpand{\NoExpand}%

16 \def\Q@END{\Q@END}%

17 % Define a toks register

18 \ID@toks{}%

19 % Signal that we need to look for a star

20 \@testtrue\ID@starfalse\ID@starstarfalse\ID@bangfalse

21 % Start scanning for \def or \gdef

22 \futurelet\@foo\ID@scandef

23}

24\newcommand\ID@scandef{%

25 \let\next\ID@saveprefix % Default behavior

26 % If this is the first few tokens after the \Inline, check for * or !

27 \if@test

(5)

28 \ifx\@foo*%

29 \ifID@star

30 \ifID@bang\let\next\ID@sd@lastcheck\else\let\next\ID@sd@checkagain\fi

31 \ID@starstartrue

32 \else

33 \let\next\ID@sd@checkagain

34 \ID@startrue

35 \fi

36 \fi

37 \ifx\@foo!%

38 \ifID@bang\else % two bangs - can this be anything but an error?

39 \ID@bangtrue

40 \xa\let\xa\next\ifID@starstar\ID@sd@lastcheck\else\ID@sd@checkagain\fi

41 \fi

42 \fi

43 \fi

44 % Now look for a \def or \gdef

45 \ifx\@foo\def

46 \def\next{\ID@start\def}%

47 \fi

48 \ifx\@foo\gdef

49 \def\next{\ID@start\gdef}%

50 \fi

51 \ifcat\noexpand\@foo\space

52 \def\next{\ID@toks\xa\xa\xa{\xa\the\xa\ID@toks\space}%

53 \xa\futurelet\xa\@foo\xa\ID@scandef\ID@unspace}% copied from ID@space

54 \fi

55 % Error checking (minimal)

56 \@testfalse

57 \ifx\@foo\edef\@testtrue\fi\ifx\@foo\xdef\@testtrue\fi

58 \ifx\@foo\newcommand\@testtrue\fi\ifx\@foo\renewcommand\@testtrue\fi

59 \ifx\@foo\DeclareRobustCommand\@testtrue\fi

60 \if@test\PackageError{inlinedef}{Only \protect\def\space and \protect\gdef\space are

61 allowed after \protect\Inline,\MessageBreak but some other type of

62 definition was found}\@eha\let\next\ID@abort\fi

63 \@testfalse

64 \ifx\@foo\bgroup\@testtrue\fi\ifx\@foo\let\@testtrue\fi

65 \if@test\PackageError{inlinedef}{No \protect\def\space or \protect\gdef\space found

66 after \protect\Inline}\@ehd\def\next{\ID@abort{}}\fi

67 \next

68}

\ID@sd@checkagain

\ID@sd@lastcheck

These just get the scandef loop started again and set \@testtrue if we’re still looking for stars and/or bangs.

69\def\ID@sd@checkagain#1{\@testtrue\futurelet\@foo\ID@scandef}

70\def\ID@sd@lastcheck#1{\futurelet\@foo\ID@scandef}

\ID@saveprefix

\ID@abort

\ID@start

These are the three macros called by\ID@scandefto either save the prefix (\long,

\outer, etc) to a token register, (attempt to) abort the procedure in case of an error, or else get the definition started once we find the\edef or\xdef.

(6)

71\newcommand*\ID@saveprefix[1]{%

72 \ID@toks\xa{\the\ID@toks#1}%

73 \futurelet\@foo\ID@scandef

74}

In case the error was just the wrong type of\def, we consume up to and including the first explicit group.

75\newcommand\ID@abort{}\def\ID@abort#1#{\endgroup\@gobble}

To get the definition process started, we take#1as the definition command to save (either\defor\gdef),#2as the command that was provided (which we discard),

#3is the name of the macro to define, and#4is the parameter text, delimited by a begin-group character.

76\newcommand\ID@start{}\def\ID@start#1#2#3#4#{%

77 \xa\def\xa\ID@prefix\xa{\the\ID@toks#1}%

78 \ID@def#3{#4}%

79}

\ID@fixparams

\ID@fp@start

In order for\Superto work properly, we need to fix the parameter list to put the

#1in braces, since it actually consists of two tokens. Therefore,\ID@fixparams takes everything between it and\Q@END and puts it in\toks@fixedparams. If it finds a#, then it checks whether the argument is delimited or not, and if not, it inserts a pair of braces. We currently define these with\newcommand*, though if there were a reason we could conceivably make them\long. Update: we now use

\ID@toksand then define \ID@fixedparamsfrom there.

80\newcommand*\ID@fixparams{\begingroup\ID@toks{}\futurelet\@foo\ID@fp@start}

81\newcommand*\ID@fp@start{%

82 \let\next\ID@fp@normal

83 \ifx\@foo\Q@END\let\next\ID@fp@end\fi

84 \ifcat\noexpand\@foo##\let\next\ID@fp@param\fi % was \ifx\@foo - broken?

85 \ifcat\noexpand\@foo\space

86 \def\next{\ID@toks\xa\xa\xa{\xa\the\xa\ID@toks\space}%

87 \xa\futurelet\xa\@foo\xa\ID@fp@start\ID@unspace}% copied from ID@space

88 \fi

89 \next

90}

\ID@fp@normal

\ID@fp@param

\ID@fp@end

These are the two commands that\ID@fixparamscalls to actually consume each token, depending on whether it was a parameter.

91\newcommand*\ID@fp@normal[1]{%

92 \ID@toks\xa{\the\ID@toks#1}\futurelet\@foo\ID@fp@start

93}

94\newcommand*\ID@fp@param[2]{%

95 % We used to just use ###2 but need two more now...

96 % Need another doubling because we’re now using it inside a def...

97 \def\@arg{#########2}% assume delimited unless we find # or \Q@END

98 \ifcat\noexpand\@foo##\def\@arg{{#########2}}\fi

99 \ifx\@foo\Q@END\def\@arg{{#########2}}\fi

100 \ID@toks\xa\xa\xa{\xa\the\xa\ID@toks\@arg}%

(7)

101 \futurelet\@foo\ID@fp@start

102}

103\newcommand*\ID@fp@end[1]{%

104 \xa\endgroup\xa\def\xa\ID@fixedparams\xa{\the\ID@toks}%

105}

This should deal with everythingexcept a single#, but that’s a hairy situation in the first place and we really don’t want to allow using\Super in that case. We could probably make an error message to say so. The only other alternative would be to “go back in time” and change the last{#1}to a#1{}and even then we end up with an extra{}on the input stream. I can’t actually figure out how to test if this has happened in...@insertp, anyway.

\ID@def Here is where the “main loop” is initiated. We start by pretending to allocate another token register (though we actually just\toksdef it), and then define a number of quarks which we use as delimiters for various purposes. Finally, we start scanning. Afterwards, we test if there was an error and if not, we expand the definition commandafter the\endgroupso that we can clean up all the local variables.

106\newcommand\ID@def[3]{%

107 % Other definitions

108 \global\ID@abortedfalse

109 \let\@reservedc#1%

110 \def\@macroname{#1}% for error message

111 \ID@fixparams#2\Q@END

112 % These are used by \Super but easier to define here

113 \def\@reservedb#2{}%

114 \edef\@reservedb{\xa\ID@getprefix\meaning\@reservedb\Q@END}%

115 \ifx#1\undefined % hopefully nobody’s going around defining \undefined

116 \let\@reserveda\undefined

117 \else

118 \edef\@reserveda{\xa\ID@getprefix\meaning#1\Q@END}%

119 \fi

120 % Scan it all into \ID@toks

121 \ifID@bang\else\ID@checkusage\fi

122 \ifID@aborted\else

123 \ID@toks{}\ID@scan#3\Q@END{}% we need the {} so that the the #1# works...

124 \fi

125 \ifID@aborted

126 \def\command{}% gracefully ignore

127 \else

128 \let#1\relax % don’t want it expanded in the |\edef| below

129 % We don’t need to worry about scope anymore

130 \toks0\ID@toks % likely redundant, but what if ID@toks=1 or 2?

131 \toks1\xa{\ID@prefix}% (easiest way to avoid expansion...)

132 \toks2{#2}%

133 \edef\command{\the\toks1#1\the\toks2{\the\toks0}}%

134 % We could also write this with 3 levels of \xa...

135 \fi

(8)

136 \global\ID@toks\xa{\ID@fixedparams}% just to test...

137 \expandafter\endgroup\command

138}

\ID@scan

\ID@switch

This is the main loop. We look at each token in turn and deal with it, mostly by inserting it into\ID@toks. If it’s a\Q@ENDthen we’re done. If it’s\Super or

\Expandthen we need to do something special. If it’s a space, then we need to add the space to\ID@toks. Finally, if it’s a\bgroup then we need to figure out whether it’s an explicit or an implicit group. In the former case, we descend into it (writing{...}to\ID@toks) and in the latter, we just pick it up like normal.

139\newcommand\ID@scan{\futurelet\@foo\ID@switch}

140\newcommand\ID@switch{%

141 \let\next\ID@normal

142 \ifx\@foo\Q@END

143 \let\next\@gobble

144 \fi

145 \ifx\@foo\@reservedc % macro name... what to do?

146 \ifID@star

147 \ifID@starstar

148 \let\next\ID@expandmacro

149 \else

150 \let\next\ID@expandsuper

151 \fi

152 \fi

153 \fi

154 \ifx\@foo\Super

155 \let\next\ID@expandsuper

156 \fi

157 \ifx\@foo\Expand

158 \let\next\ID@expandnext

159 \fi

160 \ifx\@foo\UnsafeExpand

161 \let\next\ID@expandunsafe

162 \fi

163 \ifx\@foo\MultiExpand

164 \let\next\ID@expandmulti

165 \fi

166 \ifx\@foo\NoExpand

167 \let\next\ID@noexpandnext

168 \fi

169 \ifx\@foo\Recurse

170 \def\next{\xa\xa\xa\ID@scan\xa\xa\xa\NoExpand\xa\@macroname\@gobble}%

171 \fi

172 \ifcat\noexpand\@foo\space

173 \let\next\ID@space

174 \fi

175 \ifcat\noexpand\@foo\bgroup

176 \let\next\ID@trygroup

177 \fi

(9)

178 \next

179}

\ID@space

\ID@unspace

It’s a bit tricky to deal with spaces properly. In particular, picking up just a space from the token list takes some doing. We need a fully-expandable macro so that the whole thing disappears. \ID@spacethen adds a space to\ID@toksand then expands\ID@unspace after\ID@scanso that the\futurelet sees the next token after the space and can deal with it properly. We need the\expandafter in defining\ID@unspaceto actually get the space token into the parameter text;

otherwise, it gets gobbled up by the lexer after reading the control sequence name.

180\newcommand\ID@space{%

181 \ID@toks\xa\xa\xa{\xa\the\xa\ID@toks\space}%

182 \xa\ID@scan\ID@unspace

183}

184\newcommand\ID@unspace{}

185\xa\def\xa\ID@unspace\space{}

\ID@trygroup

\ID@recurse

The next two macros are used to check if the\bgroup token was an explicit or an implicit grouping character. If it’s explicit then the next macro that takes an argument will scoop the whole thing up at once, and so we need to be aware of this to deal with it. \ID@trygroupuses the special #delimiter and compares the argument with\@emptyto see if anything comes before the next{}. If it doesn’t find anything then it was an explicit group and we recurse. One consequence of this is that we always need to put a{}after\Q@ENDso that we don’t get an error here.

186\newcommand\ID@trygroup{}

187\long\def\ID@trygroup#1#{% check for explicit/implicit grouping!

188 \def\@reservedd{#1}%

189 \xa\let\xa\next

190 \ifx\@reservedd\@empty\ID@recurse\else\ID@normal\fi

191 \next#1%

192}

Here we need to do some gymnastics to get the { and } tokens into the toks register. It would be easiest if we could just add them one at a time, but we can only addbalanced text, so we need to expand the whole thingfirst and then add it back to the register we expanded it into. Thus, we enter a new level of grouping to save the contents of\ID@toks, expand the inner group, and use\expandafter across an\endgroupto get the correct tokens in the right place in\ID@toks.

193\newcommand\ID@recurse[1]{%

194 \begingroup\ID@toks{}% start a new level of grouping and empty \ID@toks

195 \ID@scan#1\Q@END{}% % parse...

196 \xa\endgroup\xa % this fiasco should get the job done...!

197 \ID@toks\xa\xa\xa{\xa\the\xa\ID@toks\xa{\the\ID@toks}}%

198 \ID@scan

199}

\ID@normal ID@noexpandnext

This is what we do when it’s not anything special.

(10)

200\newcommand\ID@normal[1]{\ID@toks\xa{\the\ID@toks#1}\ID@scan}

201\newcommand\ID@noexpandnext[2]{\ID@toks\xa{\the\ID@toks#2}\ID@scan}

\ID@checkusage

\ID@checkredef

Here we define tests that will issue errors if the parameter texts aren’t the same, or the original function isn’t defined.

202\newcommand*\ID@checkusage{%

203 % Make sure parameter lists are the same, does nothing if undefined

204 \ifx\@reserveda\@reservedb

205 \else

206 % Error messages

207 \ifx\@reserveda\undefined % undefined - okay

208 \else

209 \global\ID@abortedtrue

210 \ifx\@foo\Super

211 \PackageError{inlinedef}{Cannot use \protect\Super\space in \expandafter

212 \protect\@macroname\space because\MessageBreak

213 parameter lists don’t match:\MessageBreak

214 ‘\@reservedb’ (new) != ‘\@reserveda’ (old)}\@eha

215 \else

216 \ifID@bang % auto-expansion forbidden

217 \PackageError{inlinedef}{Cannot use \protect\Inline* auto-expansion in

218 \expandafter\protect\@macroname\MessageBreak

219 because parameter lists don’t match:\MessageBreak

220 ‘\@reservedb’ (new) != ‘\@reserveda’ (old)}\@eha

221 \else

222 \PackageError{inlinedef}{Parameter lists for

223 \expandafter\protect\@macroname\space don’t match:\MessageBreak

224 ‘\@reservedb’ (new) != ‘\@reserveda’ (old)\MessageBreak

225 Use !-form of \protect\Inline\space to ignore this}\@eha

226 \fi

227 \fi

228 \fi

229 \fi

230}

231\newcommand*\ID@checkredef{%

232 \ifx\@reserveda\undefined % undefined - okay

233 \PackageError{inlinedef}{Cannot use \ifx\@foo\Super\protect\Super\space

234 \else\protect\Inline** \fi in \expandafter\protect\@macroname\space

235 because \MessageBreak it hasn’t been defined yet}%

236 \@eha

237 \global\ID@abortedtrue

238 \fi

239}

\ID@expandsuper

\ID@expandnext

\ID@expandmulti

\ID@expandunsafe

\ID@expandmacro

These correspond to the two special tokens,\Super and\Expand. The first one tests that the parameter list is alright and that the original command wasn’t undefined. If all is well, it expands everything in the right order. The second one is simpler, just inserting an\expandafterbefore the continuation (\ID@scan) to expand whatever comes next once. There is (yet) no way to fully-expand, although

(11)

several \Expands and \expandafters can be stacked cleverly to expand several things in a specific order.

240\newcommand*\ID@expandsuper[1]{%

241 \ID@checkusage\ID@checkredef

242 \ifID@aborted\else

243 \ID@toks\xa\xa\xa\xa\xa\xa\xa

244 {\xa\xa\xa\the\xa\xa\xa\ID@toks\xa\@reservedc\ID@fixedparams}%

245 \fi

246 \ID@scan

247}

248\newcommand\ID@expandnext[2]{%

249 \ID@toks\xa\xa\xa{\xa\the\xa\ID@toks#2}\ID@scan

250}

251\newcommand\ID@expandmulti[3]{%

252 \begingroup % #1 is the \MultiExpand...

253 \ID@count#2\relax % this will need to be allocated too!

254 \ID@toks{#3}%

255 \@testtrue\ifnum\ID@count<\@ne\@testfalse\fi

256 \@whilesw\if@test\fi{%

257 \ID@toks\xa\xa\xa{\the\ID@toks}% one expansion...

258 \advance\ID@count\m@ne\ifnum\ID@count<\@ne\@testfalse\fi

259 }%

260 \xa\endgroup\xa\ID@toks\xa\xa\xa{\xa\the\xa\ID@toks\the\ID@toks}\ID@scan

261}

262

263\newcommand*\ID@expandunsafe[1]{\expandafter\ID@scan}

264\newcommand*\ID@expandmacro[1]{\expandafter\ID@scan\@reservedc}

\ID@getprefix This is used to compare argument lists.

265\newcommand\ID@getprefix{}\long\def\ID@getprefix#1:#2->#3\Q@END{\detokenize{#2}}

Finally we clean up by restoring@’s catcode.

266\makeatother

267h/packagei

(12)

3 Test suite

We include a somewhat-comprehensive test suite to make sure that everything is working. If it works properly, it should output nothing.

First we define a few helper-functions to test for errors, etc.

268h∗testsuitei

269\makeatletter

270\errorcontextlines=10

271\def\WantError#1#2#3{%

272 \let\WE@packageerror\PackageError

273 \def\PackageError##1##2##3{%

274 \protected@edef\@goterror{##2}\protected@edef\@wanterror{#2}%

275 \edef\@goterror{\xa\detokenize\xa{\@goterror}}%

276 \edef\@wanterror{\xa\detokenize\xa{\@wanterror}}%

277 \protected@edef\@gotpackage{##1}\protected@edef\@wantpackage{#1}%

278 \edef\@gotpackage{\xa\detokenize\xa{\@gotpackage}}%

279 \edef\@wantpackage{\xa\detokenize\xa{\@wantpackage}}%

280 \global\let\PackageError\WE@packageerror

281 \@tempswafalse

282 \ifx\@gotpackage\@wantpackage\else\message{^^J(arg 1 differs)^^J}\@tempswatrue\fi

283 \ifx\@goterror\@wanterror\else\message{^^J(arg 2 differs)^^J}\@tempswatrue\fi

284 \ifx#3##3\else\message{^^J(arg 3 differs)^^J}\@tempswatrue\fi

285 \if@tempswa\PackageError{inlinedef (test)}{wrong error}\@eha\PackageError{##1}{##2}##3\fi

286 }%

287}

288

289\def\CheckError{%

290 \ifx\PackageError\WE@packageerror\else

291 \PackageError{inlinedef (test)}{expected error not thrown}\@eha\fi

292 \global\let\PackageError\WE@packageerror

293}

294\newcommand\CheckDefinition[1][]{\@CheckDefinition{#1}}

295\def\@CheckDefinition#1#2#3#{\@checkdefn{#1}#2{#3}}

296\def\@checkdefn#1#2#3#4{#1\def\@reserveda#3{#4}\ifx#2\@reserveda\else

297 \message{^^J^^J\meaning#2^^J(got)vs(wanted)^^J\meaning\@reserveda^^J^^J}

298 \PackageError{inlinedef (test)}{definition of \detokenize{#2}didn’t match}\@eha\fi

299}

300\let\eha\@eha\let\ehd\@ehd

301\makeatother

Here we predefine copies of the errors so that we can look for them easily

302\catcode‘\#=12

303\def\pound{#}

304\catcode‘\#=6

305

306\def\WantSuperNoMatch#1#2#3{%

307 \WantError{inlinedef}{Cannot use \protect\Super\space in

308 \protect#1\space because\MessageBreak

309 parameter lists don’t match:\MessageBreak

310 ‘#3’ (new) != ‘#2’ (old)}\eha

(13)

311}

312\def\WantStarNoMatch#1#2#3{%

313 \WantError{inlinedef}{Cannot use \protect\Inline* auto-expansion in

314 \protect#1\MessageBreak because

315 parameter lists don’t match:\MessageBreak

316 ‘#3’ (new) != ‘#2’ (old)}\eha

317}

318\def\WantNoMatchBang#1#2#3{%

319\WantError{inlinedef}{Parameter lists for

320 \protect#1\space don’t match:\MessageBreak

321 ‘#3’ (new) != ‘#2’ (old)\MessageBreak

322 Use !-form of \protect\Inline\space to ignore this}\eha

323}

324\def\WantOnlyDefGdef{%

325 \WantError{inlinedef}{Only \protect\def\space and \protect\gdef\space are

326 allowed after \protect\Inline,\MessageBreak but some other type of

327 definition was found}\eha

328}

329\def\WantNoDefGdef{%

330 \WantError{inlinedef}{No \protect\def\space or \protect\gdef\space found

331 after \protect\Inline}\ehd

332}

333\def\WantSuperNoRedef#1{%

334 \WantError{inlinedef}{Cannot use \protect\Super\space in \protect#1\space

335 because \MessageBreak it hasn’t been defined yet}\eha

336}

Now we start the actual tests.

337 % I. Basic stuff

338 % A. Simple definition

339\let\a\undefined

340\Inline\def\a{b}

341\CheckDefinition\a{b}

342

343 % B. Simple redefinition

344\def\a{b}

345\Inline\def\a{d}

346\CheckDefinition\a{d}

347

348 % C. Erroneous redefinition (needs !)

349\def\a{b}

350\WantNoMatchBang\a{}{\pound1}

351\Inline\def\a#1{c}

352\CheckError

353\CheckDefinition\a{b} % shouldn’t have changed

354

355\def\a{b}

356\Inline!\def\a#1{c}

357\CheckDefinition\a#1{c}

358

(14)

359 % D. Local/global definition

360\def\a{b}

361\begingroup

362\Inline\def\a{c}

363\endgroup

364\CheckDefinition\a{b}

365

366\begingroup

367\Inline\gdef\a{c}

368\endgroup

369\CheckDefinition\a{c}

370

371{\Inline\global\def\a{d}}

372\CheckDefinition\a{d}

373

374 % E. Collecting arguments

375\Inline\long\def\a{e}

376\CheckDefinition[\long]\a{e}

377

378\Inline\outer\def\a{f}

379\edef\a{\meaning\a}

380\edef\b{\detokenize{\outer macro:->f}}

381\xa\CheckDefinition\xa\a\xa{\b}

382

383\Inline\long\outer\def\a{g}

384\edef\a{\meaning\a}

385\edef\b{\string\long\string\outer\space\detokenize{macro:->g}}

386\xa\CheckDefinition\xa\a\xa{\b}

387

388\def\a{g}

389\Inline!\long\def\a#1{h}

390\CheckDefinition[\long]\a#1{h}

391

392 % II. Special tokens

393 % A. Recursion

394\def\a{b}

395\Inline\def\a{a\a c}

396\CheckDefinition\a{a\a c}

397

398 % B. Expansion

399\def\a{b}

400\Inline\def\a{a\Expand\a c}

401\CheckDefinition\a{abc}

402

403\def\a{b}

404\Inline\def\a{\Expand a\Expand\a\Expand c}

405\CheckDefinition\a{abc}

406

407\def\a{\b}

408\def\b{c}

(15)

409\Inline\def\a{a\Expand\a c}

410\CheckDefinition\a{a\b c}

411

412\toks0{b}\toks1{d}

413\Inline\def\a{a\the\toks0c\the\toks1e}

414\CheckDefinition\a{a\the\toks0c\the\toks1e}

415

416\Inline\def\a{a\Expand{\the\toks0}c\Expand{\the\toks1}e}

417\CheckDefinition\a{abcde}

418

419\Inline\def\a{\Expand{a\the\toks0}c\Expand{\the\toks1}e}

420\CheckDefinition\a{a\the\toks0cde}

421

422\Inline\def\a{\Expand{\expandafter a\the\toks0}c\Expand{\the\toks1e}}

423\CheckDefinition\a{abcde}

424

425 % C. MultiExpand

426\def\x{\y}

427\def\y{\z}

428\def\z{0}

429\Inline\def\a{a\MultiExpand0\x b}

430\CheckDefinition\a{a\x b}

431

432\Inline\def\a{a\MultiExpand1\x b}

433\CheckDefinition\a{a\y b}

434

435\Inline\def\a{a\MultiExpand2\x b}

436\CheckDefinition\a{a\z b}

437

438\Inline\def\a{a\MultiExpand3\x b}

439\CheckDefinition\a{a0b}

440

441\Inline\def\a{a\MultiExpand{10}\x b}

442\CheckDefinition\a{a0b}

443

444 % i. use with \expandafter

445\Inline\def\a{a\MultiExpand2{\expandafter\expandafter\x\x}b}

446\CheckDefinition\a{a\y\y b}

447

448\Inline\def\a{a\MultiExpand1{\expandafter\expandafter\x\x}b}

449\CheckDefinition\a{a\expandafter\y\x b}

450

451\Inline\def\a{a\MultiExpand2{\expandafter\expandafter\expandafter\x\x}b}

452\CheckDefinition\a{a\x\z b}

453

454\Inline\def\a{a\MultiExpand3{\expandafter\expandafter\expandafter\x\x}b}

455\CheckDefinition\a{a\y\z b}

456

457\Inline\def\a{a\MultiExpand4{\expandafter\expandafter\expandafter\x\x}b}

458\CheckDefinition\a{a\z\z b}

(16)

459

460\Inline\def\a{a\MultiExpand5{\expandafter\expandafter\expandafter\x\x}b}

461\CheckDefinition\a{a0\z b}

462

463 % D. UnsafeExpand

464\def\x{b\Super c}

465\Inline\def\a{a\Expand\x d}

466\CheckDefinition\a{ab\Super cd}

467

468\def\a{0}

469\Inline\def\a{a\UnsafeExpand\x d}

470\CheckDefinition\a{ab0cd}

471

472\def\a{b\Super d}

473\Inline\def\a{a\UnsafeExpand\a e}

474\CheckDefinition\a{abb\Super dde}

475

476\def\a{b\Super d}

477\Inline**\def\a{a\a e}

478\CheckDefinition\a{abb\Super dde}

479

480 % Would be nice if we could catch TeX capacity exceeded errors...

481 % Then try \def\a{b\a d}\Inline**\def\a{a\a e}

482

483\def\x#1{b#1d}

484\Inline\def\a{a\x ce}

485\CheckDefinition\a{a\x ce}

486

487\Inline\def\a{a\UnsafeExpand\x ce}

488\CheckDefinition\a{abcde}

489

490 % E. NoExpand

491\Inline\def\a{a\NoExpand\Expand\x b}

492\CheckDefinition\a{a\Expand\x b}

493

494\Inline*\def\a{a\NoExpand\a b}

495\CheckDefinition\a{a\a b}

496

497\Inline**\def\a{a\NoExpand\a b}

498\CheckDefinition\a{a\a b}

499

500\Inline\def\a{a\NoExpand{\Expand\x\Expand\y}b}

501\CheckDefinition\a{a\Expand\x\Expand\y b}

502

503 % F. Super

504\def\a{bcd}

505\Inline\def\a{a\Super e}

506\CheckDefinition\a{abcde}

507

508\def\a#1{b#1d}

(17)

509\Inline\def\a#1{a\Super e}

510\CheckDefinition\a#1{ab#1de}

511

512\def\a#1{b#1d}

513\Inline*\def\a#1{a\Super e}

514\CheckDefinition\a#1{ab#1de}

515

516\def\a#1{b#1d}

517\Inline**\def\a#1{a\Super e}

518\CheckDefinition\a#1{ab#1de}

519

520 % G. Recurse

521\def\a{q}

522\Inline\def\a{a\Recurse b}

523\CheckDefinition\a{a\a b}

524

525\Inline*\def\a{a\Recurse b}

526\CheckDefinition\a{a\a b}

527

528\Inline**\def\a{a\Recurse b}

529\CheckDefinition\a{a\a b}

530

531 % III. Tricky parsing

532 % A. Spaces

533\def\a{b c d}

534\Inline\def\a{a \Super e}

535\CheckDefinition\a{a b c de}

536

537\def\a{b c d}

538\Inline\def\a{a \Expand\a e}

539\CheckDefinition\a{a b c de}

540

541\def\a{b c d}

542\Inline\def\a{a \Expand{\a} e}

543\CheckDefinition\a{a b c d e}

544

545\Inline\def\a{a\NoExpand{\Expand\x\Expand\y} b}

546\xa\CheckDefinition\xa\a\xa{\xa a\xa\Expand\xa\x\xa\Expand\xa\y\space b}

547

548 % B. Grouping

549\def\a{b{c d}e}

550\Inline\def\a{{a\Super}f\Super}

551\CheckDefinition\a{{ab{c d}e}fb{c d}e}

552

553\Inline\def\a{{ }{}}

554\Inline\def\a{{\Expand\a\a}{} {{\Super}{}}}

555\CheckDefinition\a{{{ }{}\a}{} {{{ }{}}{}}}

556

557 % C. Parameters

558\def\a#1bcd#2{[#1...#2]}

(18)

559\Inline\def\a#1bcd#2{a\Super b}

560\CheckDefinition\a#1bcd#2{a[#1...#2]b}

561

562\def\a#1\##2{y}

563\Inline\def\a#1\##2{x\UnsafeExpand\a{#1}\#{#2}z}

564\CheckDefinition\a#1\##2{xyz}

565

566\def\a#1\##2{#1y#2}

567\Inline\def\a#1\##2{x\UnsafeExpand\a{#1}\#{#2}z}

568\CheckDefinition\a#1\##2{x#1y#2z}

569

570 % i. spaces!

571\def\a #1 {y}

572\Inline\def\a#1 {x\Super z}

573\CheckDefinition\a#1 {xyz}

574

575\xa\def\xa\a\space{y}

576\xa\Inline\xa\def\xa\a\space{x\Super z}

577\xa\CheckDefinition\xa\a\space{xyz}

578

579 % ii. funky catcodes

580 %%%% This test fails.

581 %\begingroup

582 % \catcode‘&=6

583 % \def\a&1{b#1d}

584 % \Inline\def\a#1{a\Super e}

585 % \CheckDefinition\a#1{b&1d}

586 %\endgroup

587

588 % D. Active characters

589\begingroup

590 \catcode‘A=13

591 \defA#1{b#1d}

592 \Inline\defA#1{aAe}

593 \CheckDefinitionA#1{aAe}

594

595 \defA#1{b#1d}

596 \Inline*\defA#1{aAe}

597 \CheckDefinitionA#1{ab#1de}

598\endgroup

599

600 % IV. Auto-expansion

601

602\def\a#1{y}

603\Inline\def\a#1{x\a z}

604\CheckDefinition\a#1{x\a z}

605

606\def\a#1{y}

607\Inline*\def\a#1{x\a z}

608\CheckDefinition\a#1{xyz}

(19)

609

610\def\a#1{y}

611\Inline**\def\a#1{x\a{#1}z}

612\CheckDefinition\a#1{xyz}

613

614 % A. With delimited arguments

615\def\a[#1]#2{#1y#2}

616\Inline*\def\a[#1]#2{x\a z}

617\CheckDefinition\a[#1]#2{x#1y#2z}

618

619\def\a[#1]#2{#1y#2}

620\Inline**\def\a[#1]#2{x\a[#1]{#2}z}

621\CheckDefinition\a[#1]#2{x#1y#2z}

622

623 % V. Errors

624

625\def\bar#1{d #1 f}

626\def\x{b}

627

628\WantSuperNoMatch\a{\pound1}{.\pound1}

629\def\a#1{x}

630\Inline!\def\a.#1{y\Super}

631\CheckError

632\CheckDefinition\a#1{x}

633

634\WantStarNoMatch\a{\pound1}{.\pound1}

635\def\a#1{x}

636\Inline*!\def\a.#1{y\a}

637\CheckError

638\CheckDefinition\a#1{x}

639

640\def\a#1{x}

641\Inline!\def\a.#1{y} % ok

642\CheckDefinition\a.#1{y}

643

644\WantOnlyDefGdef

645\def\foo{a}

646\Inline\edef\foo{b}

647\CheckError

648\CheckDefinition\foo{a}

649\let\foo\undefined

650

651\WantOnlyDefGdef

652\Inline\global\outer\xdef{}

653\CheckError

654

655\WantOnlyDefGdef

656\Inline\global\outer\abc\space vbcda s \newcommand{}

657\CheckError

658

(20)

659\WantNoDefGdef

660\Inline\let\relax\relax

661\CheckError

662

663\WantNoDefGdef

664\Inline{}

665\CheckError

666

667\WantSuperNoRedef\foo

668\Inline\def\foo#1{a \Expand\x\space cd #1 fg \x\space i\Super}

669\CheckError

670

671\WantNoMatchBang\a{}{\pound1}

672\def\a{b}

673\Inline\def\a#1{a\a c}

674\CheckError

675

676 % Miscellaneous (read: "old") tests

677

678\def\test#1{d #1 f}

679\Inline\def\test#1{a \Expand\x\space c\Super g \x\space i}

680\CheckDefinition\test#1{a b\space cd #1 fg \x\space i}

681

682\Inline*\def\bar#1{a \Expand\x\space c\bar g \x\space i}

683\CheckDefinition\bar#1{a b\space cd #1 fg \x\space i}

684

685\def\bar#1{d #1 f}

686\Inline**\def\bar#1{a \Expand\x\space c\bar{#1}g \x\space i}

687\CheckDefinition\bar#1{a b\space cd #1 fg \x\space i}

688

689\Inline\def\foo#1{a \Expand\x\space cd #1 fg \x\space i}

690\CheckDefinition\foo#1{a b\space cd #1 fg \x\space i}

691

692\def\a{b}

693\Inline!\def\a#1{a\Expand\a c}

694\CheckDefinition\a#1{abc}

695

696\def\a{b}

697\Inline!**\def\a#1{a\a c}

698\CheckDefinition\a#1{abc}

699

700\Inline\def\a#1{a\a c}

701\CheckDefinition\a#1{a\a c}

702

703\Inline\def\a#1{a\Recurse c}

704\CheckDefinition\a#1{a\a c}

705

706\Inline!\def\a{a\NoExpand{b\Super c}d}

707\CheckDefinition\a{ab\Super cd}

708

(21)

709\Inline*\def\a{gh\a jk}

710\CheckDefinition\a{ghab\Super cdjk}

711

712 % SURPRISE! unsafe expansion...

713\def\a{ab\Super cd}

714\Inline**\def\a{gh\a jk}

715\CheckDefinition\a{ghabab\Super cdcdjk}

716

717\def\a{ab\Super cd}

718\Inline\def\a{gh\UnsafeExpand\a jk}

719\CheckDefinition\a{ghabab\Super cdcdjk}

720

721\def\x{\x a} % This is a fun one...!

722\Inline\def\a{\MultiExpand{5}\x}

723\CheckDefinition\a{\x aaaaa}

724

725\message{^^JAll tests completed.^^J}

726

727\begin{document}

728\end{document}

729h/testsuitei

(22)

Index

Numbers written in italic refer to the page where the corresponding entry is de- scribed; numbers underlined refer to the code line of the definition; numbers in roman refer to the code lines where the entry is used.

Symbols

\@arg . . . 97–100

\@foo . . . 22, 28, 37, 45, 48, 51, 53, 57–59, 64, 69, 70, 73, 80, 83–85, 87, 92, 98, 99, 101, 139, 142, 145, 154, 157, 160, 163, 166, 169, 172, 175, 210, 233

\@macroname 110, 170, 212, 218, 223, 234

\@reserveda . . . 116, 118, 204, 207, 214, 220, 224, 232

\@reservedb 113, 114, 204, 214, 220, 224

\@reservedc . . . 109, 145, 244, 264

\@reservedd . . . 188, 190

\@testfalse . . . 56, 63, 255, 258

\@testtrue . . . . 20, 57–59, 64, 69, 255 B

\bgroup . . . 64, 175 C

\command . . . 126, 133, 137 E

\Expand . . . 1, 2, 13, 157 I

\ID@abort . . . 62, 66, 71, 75

\ID@abortedfalse . . . 108

\ID@abortedtrue . . . 209, 237

\ID@bangfalse . . . 20

\ID@bangtrue . . . 39

\ID@checkredef . . . 202, 231, 241

\ID@checkusage . . . . 121, 202, 202, 241

\ID@count . . . 8, 9, 253, 255, 258

\ID@def . . . 78, 106, 106

\ID@expandmacro . . . 148, 240, 264

\ID@expandmulti . . . 164, 240, 251

\ID@expandnext . . . 158, 240, 248

\ID@expandsuper . . . 150, 155, 240, 240

\ID@expandunsafe . . . 161, 240, 263

\ID@fixedparams . . . 104, 136, 244

\ID@fixparams . . . 80, 80, 111

\ID@fp@end . . . 83, 91, 103

\ID@fp@normal . . . 82, 91, 91

\ID@fp@param . . . 84, 91, 94

\ID@fp@start . . . 80, 80, 81, 87, 92, 101

\ID@getprefix . . . 114, 118, 265, 265

\ID@noexpandnext . . . 167, 200, 201

\ID@normal . . . 141, 190, 200, 200

\ID@prefix . . . 77, 131

\ID@recurse . . . 186, 190, 193

\ID@saveprefix . . . 25, 71, 71

\ID@scan . . . 123, 139, 139, 170, 182, 195, 198, 200, 201, 246, 249, 260, 263, 264

\ID@scandef . . 10, 22, 24, 53, 69, 70, 73

\ID@sd@checkagain . . 30, 33, 40, 69, 69

\ID@sd@lastcheck . . . 30, 40, 69, 70

\ID@space . . . 173, 180, 180

\ID@starfalse . . . 20

\ID@starstarfalse . . . 20

\ID@starstartrue . . . 31

\ID@start . . . 46, 49, 71, 76

\ID@startrue . . . 34

\ID@switch . . . 139, 139, 140

\ID@toks . . . 8, 8, 18, 52, 72, 77, 80, 86, 92, 100, 104, 120, 123, 130, 136, 181, 194, 197, 200, 201, 243, 244, 249, 254, 257, 260

\ID@trygroup . . . 176, 186, 186, 187

\ID@unspace . . 53, 87, 180, 182, 184, 185

\if@test . . . 27, 60, 65, 256

\ifID@aborted . . . 4, 4, 122, 125, 242

\ifID@bang . . . 4, 7, 30, 38, 121, 216

\ifID@star . . . 4, 5, 29, 146

\ifID@starstar . . . 4, 6, 40, 147

\Inline . . . 1, 3, 10, 10, 26, 61, 66, 217, 225, 234

\Inline* . . . 3

\Inline** . . . 3

\Inline! . . . 3 M

\MultiExpand . . . 2, 14, 163, 252 N

\next . 25, 30, 33, 40, 46, 49, 52, 62, 66, 67, 82–84, 86, 89, 141, 143,

(23)

148, 150, 155, 158, 161, 164, 167, 170, 173, 176, 178, 189, 191

\NoExpand . . . 2, 15, 166, 170 Q

\Q@END . . . 16, 83, 97, 99, 111, 114, 118, 123, 142, 195, 265

R

\Recurse . . . 2, 15, 169 S

\Super . . . 2, 13, 112, 154, 210, 211, 233

T

\the . . . 52, 72, 77, 86, 92, 100, 104, 133, 181, 197, 200, 201, 244, 249, 257, 260

U

\UnsafeExpand . . . 2, 14, 160

X

\xa . . . 1

References

Related documents

These results take time to accumulate, and it is the longer monitoring of nesting success and subsequent increase in the number of breeding birds that heralds the benefit of

The analysis presented analyses the most common standard, the IAI’s IFC, from a meta- level and asks questions about the evolving model from the viewpoint of metrics for data

conference, which had the goal to “… examine New Zealand’s future in a world where learning, 

Le lieu et le titre sont mis en premier dans la seconde colonne, chacun dans la bonne fonte, et en les faisant suivre d’un point. Ensuite, on ajoute, si elle existe,

M AGNETICS formats present a difficulty in that compsoc and transmag journal (but not compsoc conference) papers place the abstract and index terms sections in single column format

The package consists of a preprocessor that converts an indented list tree format into L A TEX input (plain TEX doesn’t seem to work), and some macro files which lay out the trees

\nodeconnect takes the same arguments as in tree-dvips, with a final optional [ ] argument taking PSTricks graphics parameters:.. (4) \nodeconnect[from loc]{from node}[to

production down whilst finding more innovative ways to add value to keep profits up. This will mean that at least the same, and probably more, will need to be spent on R&amp;D in the

This helped ensure, along with the institution of Empire Day in 1905, that “the Union Jack became firmly established as the flag for Australian public schools.” 95 This

intersections model to critically examine the Productivity Commission’s (2015) policy-framing report “More Effective Social Services.” The social investment approach is discussed

• *Two shipping containers to continue existing commercial or industrial land uses on affected land (not on a flood control lot) (2 years only) (Cl 2.72C).. *These will have

 There can be times when we don’t want LaTeX to automatically insert a new line break. The Lord of the Rings is an

Council adopted a policy on 7 September 2005 which recommended the current determination of hiring fees for community organisations for the use of Council Auditoria, Halls

To safely store, save versions, and regularly save a copy (backup) of your files.. Lost files may be able to be recovered - but there are

When mergeFields reads a line of data, you want the field- name-macros to expand to their current values but you often do not want your TEX code to expand.. It is good practice stick

If you want some text typeset with the duerer fonts for a short text you can use one of the commands. \

It takes two arguments — the first is the character you want to turn into a shortcut, the second is the macro code that will be executed when that character is encountered. If

Finally, the \printindex command is used in your L A TEX document to indicate where the file foo.idx should be inserted, i.e., where the index should appear in your document.. The

• When the komacv-lco package is used within CV of the komacv class, it provides a macro for loading LCO files and setting the komacv variables based on these macros.. • When

Intuitively, a random looks like it was created by flipping a fair coin for each bit?. Each toss of the coin

(d) It displays aesthetic merit and design characteristics of significance to the local area, being a good example of a two-storey corner hotel from early in the

 There can be times when we don’t want LaTeX to automatically insert a new line break.

In this study, we proposed a linkage structure-based sim- ilarity measure based on [7], compared it to cosine and basic hyperlink structure-based similarity measures, using differ-