A new font selection scheme for TEX macro packages (Declarative Interface)^{∗}

Frank Mittelbach  Rainer Schöpf

March 27, 1996

This file contains the main implementation of the font selection scheme commands. See other parts of the L^{A}TEX distribution, or The L^{A}TEX Companion for higher level documentation of these commands.

Warning: The macro documentation is still basically the documentation from the first NFSS release and therefore in some cases probably not completely accurate.

1 Interface Commands

{\in@ \atop \ifin@} \@in is a utility macro with two arguments. It determines whether its first argument occurs in its second (after expanding it) and sets the switch \if@in accordingly.

1 ⟨∗2ekernel | autoload⟩

 2 \def\in@#1#2{%
 3 \def\in@@##1#1##2##3\in@@{%
 4 \ifx\in@##2\in@false\else\in@true\fi}%
 5 \in@@#2#1\in@\in@@}
 6 \newif\ifin@

Before the \begin{document} command several ⟨math versions⟩ and ⟨math alphabet identifiers⟩ may be declared. In principle, there should be exactly one family/series/shape combination be declared for each version/alphabet pair. But we want to allow for defaults as well for automagical filling of holes.

While building the tables for math alphabet identifiers and math versions we keep several lists:

• the list of all math versions, \version@list, each entry prefixed by the control sequence \version@elt, i.e. this list has the following form

∗This file has version number v3.0d dated 1995/10/10

         \version@elt⟨version_{1}⟩\version@elt⟨version_{2}⟩. . .
                                           \version@elt⟨version_{n}⟩

• the list of all math alphabet identifiers. Here every entry has the form: \group@elt⟨math group number⟩ {{⟨default family⟩}{⟨default series⟩}{⟨default shape⟩}}.

• Each defined math alphabet identifier holds a list containing Information about the versions for which it is defined. This list has a more complicated structure: it looks as follows:

\set@alpha⟨the alphabet identifier itself ⟩ \reserved@c⟨math version⟩⟨font info⟩ …

         \@nil

where ⟨font info⟩ is either \reserved@e (if the combination is not defined yet) or

{{⟨family⟩}{⟨series⟩}{⟨shape⟩}}

\version@list We initialize the version list to be empty.

 7 \let\version@list=\@empty
 8 \@onlypreamble\version@list
\version@elt
 9 \let\version@elt\relax
10 \@onlypreamble\version@elt

\new@mathversion The macro \new@mathversion is called with the version control sequence as its argument.

11 %\def\new@mathversion#1{%

The first thing this macro does is to check if the version identifier is already present in \version@list. We enclose \version@list in braces since it might be empty (if no version is defined yet). But this means that we need a suitable number of

\expandafter primitives.
12 %  \expandafter\in@\expandafter#1\expandafter{\version@list}%
13 %  \ifin@

If so it prints an error message. The \next macro is used to get rid of the four characters \mv@ that would otherwise appear at the begin of the version name in the error message.

14 %    \@latex@error{Math version
15 %               `\expandafter\@gobblefour\string#1'
16 %               already defined}\@eha

Otherwise we have a new version, and we can proceed with entering it into the tables. We add it to \version@list. This is very easy: we define \version@elt (which is the delimiter in \version@list) to protect itself and the following token from being expanded and simply redefine \version@list.

17 %  \else
18 %     \global\expandafter\newcount\csname c@\expandafter
19 %                                 \@gobble\string#1\endcsname
20 %     \global\csname c@\expandafter
21 %                                 \@gobble\string#1\endcsname\@ne
22 %     \def\version@elt{\noexpand\version@elt\noexpand}%
23 %     \edef\version@list{\version@list\version@elt#1}%

Then we prepare to enter the new version into all math alphabet identifier lists. Remember that these lists use \reserved@c as delimiter, and that there appears the control sequence \reserved@e that must not be expanded. Therefore we take suitable precautions.

24 %     \def\reserved@c{\noexpand\reserved@c\noexpand}%
25 %     \let\reserved@e\relax

We will now go through the \alpha@list to process every ⟨math alphabet identifier⟩ in turn. Since this list has \group@elt as a delimiter we define this control sequence. It has three arguments as every entry consists of three items (as explained above).

26 %     \def\group@elt##1##2##3{%

The first of these arguments is the ⟨math alphabet identifier⟩. We redefine it by appending the information about the new version at the end of the list contained in it. However, there is one subtlety: the definitions for \reserved@c and \reserved@e made above prevent the main part of the list from being expanded. But we still have to take care of the header and the trailer. To do this we remove the trailer by means of the macro \remove@nil which also protect the header from being expanded. Its definition is given below. Now we can prepare to add the new version.

27 %          \edef##1{\expandafter\remove@nil##1%
28 %                   \reserved@c
29 %                   #1%
30 %                   \reserved@e
31 %                   \noexpand\@nil}}%

Finally we call \alpha@list which will now execute the macro \group@elt once for every defined ⟨math alphabet identifier⟩. And that’s all for now.

32 %     \alpha@list
33 %  \fi}

\alpha@list As we explained above every entry in \alpha@list has the form

\alpha@elt

⟨alphabet identifier⟩⟨internal group number⟩⟨default font assignments⟩… We initialize it to \@empty.

34 \let\alpha@list\@empty
35 \@onlypreamble\alpha@list

\alpha@elt
36 \let\alpha@elt\relax
37 \@onlypreamble\alpha@elt
new stuff
38 % start alloc at 0
39 \count18=-1

another begingroup bug:

40 \def\stepcounter #1{\global\advance\csname c@#1\endcsname\@ne
41 \begingroup\let\@elt\@stpelt \csname cl@#1\endcsname\endgroup }
42 \newif\ifrestore@version \restore@versiontrue
43 \@onlypreamble\ifrestore@version
44 \@onlypreamble\restore@versionfalse
45 \@onlypreamble\restore@versiontrue

We surround \select@group with braces so that functions using it can be used directly after _or ^. However, if we use oldstyle syntax where the math alphabet doesn’t have arguments (ie if \math@bgroup is not \bgroup) we need to get rid of the extra group.

46 \def\select@group#1#2#3#4{%
47 \ifx\math@bgroup\bgroup\else\relax\expandafter\@firstofone\fi
48 {%
49 \ifmmode
50 \ifnum\csname c@mv@\math@version\endcsname<\sixt@@n
51  \begingroup
52  \escapechar\m@ne
53  \getanddefine@fonts{\csname c@mv@\math@version\endcsname}#3%
54  \globaldefs\@ne  \math@fonts
55  \endgroup
56  \ifrestore@version
57  \global\restore@versionfalse
58  \xdef\restore@mathversion
59  {\expandafter\noexpand\csname mv@\math@version\endcsname
60  \global\csname c@mv@\math@version\endcsname
61  \number\csname c@mv@\math@version\endcsname\relax}%
62  \aftergroup\dorestore@version
63  \fi
64  \xdef#1{\noexpand\use@mathgroup\noexpand#2%
65  {\number\csname c@mv@\math@version\endcsname}}%
66  \stepcounter{mv@\math@version}%
67 \else
68  \let#1\relax
69  \@latex@error{Too many math alphabets used in
70  version \math@version}%
71  \@eha
72 \fi
73 \else \expandafter\non@alpherr\fi
74 #1{#4}%

75 }%

76 }

77 \@onlypreamble\restore@mathversion

78 ⟨/2ekernel | autoload⟩ 79 ⟨∗2ekernel | autoerr⟩

80 \gdef\non@alpherr#1{\@latex@error{%

Since the argument is the internal alphabet name, we have to get rid of the @ in its name. The trick here is to use \@firstoftwo which is a L^{A}TEX macro which discards the second of two arguments.

81  \expandafter\@firstoftwo\string#1 allowed only in math mode}\@ehd}

82 ⟨/2ekernel | autoerr⟩

83 ⟨autoload⟩\def\non@alpherr{\@autoerr\non@alpherr}

84 ⟨∗2ekernel | autoload⟩

85 \def\dorestore@version
86 {\ifmmode
87  \aftergroup\dorestore@version
88 \else
89  \global\restore@versiontrue
90  \begingroup
91  \let\getanddefine@fonts\@gobbletwo
92  \restore@mathversion
93  \endgroup
94 \fi}%
95 \@onlypreamble\dorestore@version

We surround \select@group with braces so that functions using it can be used directly after _or ^.

96 \def\document@select@group#1#2#3#4{%
97 \ifx\math@bgroup\bgroup\else\relax\expandafter\@firstofone\fi
98 {%
99 \ifmmode
100 \ifnum\csname c@mv@\math@version\endcsname<\sixt@@n
101  \begingroup
102  \escapechar\m@ne
103  \getanddefine@fonts{\csname c@mv@\math@version\endcsname}#3%
104  \globaldefs\@ne  \math@fonts
105  \endgroup
106  \expandafter\extract@alph@from@version
107  \csname mv@\math@version\expandafter\endcsname
108  \expandafter{\number\csname
109  c@mv@\math@version\endcsname}%
110  #1%
111  \stepcounter{mv@\math@version}%
112 \else
113  \let#1\relax
114  \@latex@error{Too many math alphabets used
115  in version \math@version}%
116  \@eha

117 \fi
118 \else \expandafter\non@alpherr\fi
119 #1{#4}%

120 }% 121 }

122 \def\process@table{%
123  \def\cdp@elt##1##2##3##4{%
124  \@font@info{Checking defaults for
125  ##1/##2/##3/##4}%
126  \expandafter
127  \ifx\csname##1/##2/##3/##4\endcsname\relax

Grouping is important for two reasons, first \cdp@elt will get redefined if \Declare... functions are executed within the external .fd file and secondly \try@load@fontshape changes a lot of catcodes without surrounding itself with a group.

128  \begingroup
129  \def\f@encoding{##1}\def\f@family{##2}%
130  \try@load@fontshape
131  \endgroup
132  \fi
133  \expandafter
134  \ifx\csname##1/##2/##3/##4\endcsname\relax
135  \@latex@error{This NFSS system isn't set up properly}%
136  {For encoding scheme ##1 the defaults
137  ##2/##3/##4 do not form a valid font shape}%
138  \else
139  \@font@info{... okay}%
140  \fi}%
141  \cdp@list

Now we make sure that \error@fontshape is okay.

142  \begingroup
143  \escapechar\m@ne
144  \error@fontshape
145  \expandafter\ifx\csname \curr@fontshape\endcsname\relax
146  \begingroup
147  \try@load@fontshape
148  \endgroup
149  \fi
150  \expandafter\ifx\csname \curr@fontshape\endcsname\relax
151  \@latex@error{This NFSS system isn't set up properly}%
152  {The system maintainer forgot to specify a suitable
153  substitution
154  font shape using the \noexpand\DeclareErrorFont
155  command}%
156  \fi
157  \endgroup

Set \select@group to its meaning used within the document body.

158  \let\select@group\document@select@group

Install the default font attributes they are currently pointing to error font shape. Don’t use \reset@font since that would trigger \selectfont.

159  \fontencoding{\encodingdefault}%
160  \fontfamily{\familydefault}%
161  \fontseries{\seriesdefault}%
162  \fontshape{\shapedefault}%

kill all macros not longer needed. we need to add many more!!!!!!

163 \everyjob{}%

164 }

165 \@onlypreamble\process@table

166 167

168 %\@onlypreamble\set@mathradical
169 \def\DeclareMathVersion#1{%
170 \expandafter\new@mathversion\csname mv@#1\endcsname}
171 \@onlypreamble\DeclareMathVersion
172 \def\new@mathversion#1{%
173 \expandafter\in@\expandafter#1\expandafter{\version@list}%
174 \ifin@
175  \@font@info{Redeclaring math version
176  `\expandafter\@gobblefour\string#1'}%
177 \else
178  \global\expandafter\newcount\csname c@\expandafter
179  \@gobble\string#1\endcsname
180  \def\version@elt{\noexpand\version@elt\noexpand}%
181  \edef\version@list{\version@list\version@elt#1}%
182 \fi

\toks@ is used to gather all tokens for the math version. \count@ will be used to count the math groups we add to this version.

183 \toks@{}%
184 \count@\z@

Now we loop over \group@list to add all math groups defined so far to the version and at the same time to count them.

185 \def\group@elt##1##2{%
186  \advance\count@\@ne
187  \addto@hook\toks@{\getanddefine@fonts##1##2}%

188 }%

189 \group@list

We set the counter for this math version to the number of math groups found in

 \group@list.
190 \global\csname c@\expandafter\@gobble\string#1\endcsname\count@

Now we loop over \alpha@list to add all math alphabets known so far. We have to distinugish the case that an alphabet by default should produce an error in new versions.

191 \def\alpha@elt##1##2##3{%
192  \ifx##2\no@alphabet@error
193  \toks@\expandafter{\the\toks@\install@mathalphabet##1%
194  {\no@alphabet@error##1}}%
195  \else
196  \toks@\expandafter{\the\toks@\install@mathalphabet##1%
197  {\select@group##1##2##3}}%
198  \fi

199 }%

200 \alpha@list

Finally we define the math version to expand to the contents of \toks@.

201 \xdef#1{\the\toks@}%

202 }

203 \@onlypreamble\new@mathversion
204 \def\DeclareSymbolFont#1#2#3#4#5{%
205 \@tempswafalse
206 \edef\reserved@b{#2}%
207 \def\cdp@elt##1##2##3##4{\def\reserved@c{##1}%
208  \ifx\reserved@b\reserved@c \@tempswatrue\fi}%
209 \cdp@list
210 \if@tempswa
211 \@ifundefined{sym#1}{%
212  \expandafter\new@mathgroup\csname sym#1\endcsname
213  \expandafter\new@symbolfont\csname sym#1\endcsname
214  {#2}{#3}{#4}{#5}}%

215 {%

216  \@font@info{Redeclaring symbol font `#1'}%
217  \def\group@elt##1##2{%
218  \expandafter\ifx\csname sym#1\endcsname##1%
219  \expandafter\addto@hook\expandafter
220  \toks@\expandafter{\expandafter\group@elt
221  \expandafter##1\csname#2/#3/#4/#5\endcsname}%
222  \else
223  \addto@hook\toks@{\group@elt##1##2}%
224  \fi

225 }%

226  \toks@{}%
227  \group@list
228  \def\version@elt##1{%
229  \expandafter
230  \SetSymbolFont@\expandafter##1\csname#2/#3/#4/#5\expandafter
231  \endcsname \csname sym#1\endcsname

232 }%

233  \version@list

234 }%

235 \else
236  \@latex@error{Encoding scheme  `#2' unknown}\@eha
237 \fi

238 }

239 \@onlypreamble\DeclareSymbolFont
240 \let\group@list\@empty
241 \@onlypreamble\group@list
242 \let\group@elt\relax
243 \@onlypreamble\group@elt
244 \def\new@symbolfont#1#2#3#4#5{%
245  \toks@\expandafter{\group@list}%
246  \edef\group@list{\the\toks@\noexpand\group@elt\noexpand#1%
247  \expandafter\noexpand\csname#2/#3/#4/#5\endcsname}%
248  \def\version@elt##1{\toks@\expandafter{##1}%
249  \edef##1{\the\toks@\noexpand\getanddefine@fonts
250  #1\expandafter\noexpand\csname#2/#3/#4/#5\endcsname}%
251  \global\advance\csname c@\expandafter
252  \@gobble\string##1\endcsname\@ne

253 }%

254  \version@list

255 }

256 \@onlypreamble\new@symbolfont
257 \def\SetSymbolFont#1#2#3#4#5#6{%
258 \@tempswafalse
259 \edef\reserved@b{#3}%
260 \def\cdp@elt##1##2##3##4{\def\reserved@c{##1}%
261  \ifx\reserved@b\reserved@c \@tempswatrue\fi}%
262 \cdp@list
263 \if@tempswa
264 \expandafter\SetSymbolFont@
265  \csname mv@#2\expandafter\endcsname\csname#3/#4/#5/#6\expandafter
266  \endcsname \csname sym#1\endcsname
267 \else
268 \@latex@error{Encoding scheme  `#3' unknown}\@eha
269 \fi

270 }

271 \@onlypreamble\SetSymbolFont
272 \def\SetSymbolFont@#1#2#3{%
273 \expandafter\in@\expandafter#1\expandafter{\version@list}%
274 \ifin@
275  \expandafter\in@\expandafter#3\expandafter{\group@list}%
276  \ifin@
277  \begingroup
278  \expandafter\get@cdp\string#2\@nil\reserved@a
279  \toks@{}%
280  \def\install@mathalphabet##1##2{%
281  \addto@hook\toks@{\install@mathalphabet##1{##2}}%

282 }%

283  \def\getanddefine@fonts##1##2{%
284  \ifnum##1=#3%
285  \addto@hook\toks@{\getanddefine@fonts#3#2}%
286  \expandafter\get@cdp\string##2\@nil\reserved@b

287  \ifx\reserved@a\reserved@b\else
288  \@font@warning{Encoding `\reserved@b' has changed
289  to `\reserved@a' for symbol font\MessageBreak
290  `\expandafter\@gobblefour\string#3' in the
291  math version `\expandafter
292  \@gobblefour\string#1'}%
293  \fi
294  \@font@info{%
295  Overwriting symbol font
296  `\expandafter\@gobblefour\string#3' in
297  version `\expandafter
298  \@gobblefour\string#1'\MessageBreak
299  \@spaces \expandafter\@gobble\string##2 -->
300  \expandafter\@gobble\string#2}%
301  \else
302  \addto@hook\toks@{\getanddefine@fonts##1##2}%
303  \fi}%
304  #1%
305  \xdef#1{\the\toks@}%
306  \endgroup
307  \else
308  \@latex@error{Symbol font `\expandafter\@gobblefour\string#3'
309  not defined}\@eha
310  \fi
311 \else
312  \@latex@error{Math version `\expandafter\@gobblefour\string#1'
313  is not
314  defined}{You probably mispelled the name of the math
315  version.^^JOr you have to specify an additional package.}%
316 \fi

317 }

318 \@onlypreamble\SetSymbolFont@
319 \def\get@cdp#1#2/#3\@nil#4{\def#4{#2}}
320 \@onlypreamble\get@cdp
321 \def\DeclareMathAlphabet#1#2#3#4#5{%
322 \@tempswafalse
323 \edef\reserved@b{#2}%
324 \def\cdp@elt##1##2##3##4{\def\reserved@c{##1}%
325  \ifx\reserved@b\reserved@c \@tempswatrue\fi}%
326 \cdp@list
327 \if@tempswa
328 \expandafter\ifx
329 \csname\expandafter\@gobble\string#1\endcsname
330 \relax
331  \new@mathalphabet#1{#2}{#3}{#4}{#5}%
332 \else

Check if it is already a math alphabet.

333  \edef\reserved@a{\noexpand\in@{\string\select@group}%

334  {\expandafter\meaning\csname @\expandafter
335  \@gobble\string#1\endcsname}}%
336  \reserved@a
337  \ifin@
338  \@font@info{Redeclaring math alphabet \string#1}%
339  \def\version@elt##1{%
340  \expandafter\SetMathAlphabet@\expandafter
341  ##1\csname#2/#3/#4/#5\expandafter\endcsname
342  \csname M@#2\expandafter\endcsname
343  \csname @\expandafter\@gobble\string#1\endcsname#1}%
344  \version@list
345  \else

Check if it is a math alphabet defined via \DeclareSymbolFontAlphabet.

346  \edef\reserved@a{\noexpand\in@{\string\use@mathgroup}%
347  {\expandafter\meaning\csname @\expandafter
348  \@gobble\string#1\endcsname}}%
349  \reserved@a
350  \ifin@

In that case overwriting is simple since there is nothing inserted in the math version macros.

351  \@font@info{Redeclaring math alphabet \string#1}%
352  \new@mathalphabet#1{#2}{#3}{#4}{#5}%

Otherwise panic.

353  \else
354  \@latex@error{Command `\string#1' already defined}\@eha
355  \fi
356  \fi
357 \fi
358 \else
359 \@latex@error{Encoding scheme  `#2' unknown}\@eha
360 \fi

361 }

362 \@onlypreamble\DeclareMathAlphabet
363 \def\new@mathalphabet#1#2#3#4#5{%
364  \toks@\expandafter{\alpha@list}%
365  \edef#1{\expandafter\noexpand\csname @\expandafter
366  \@gobble\string#1\endcsname
367  \if/#5/%
368  \noexpand\no@alphabet@error
369  \noexpand\no@alphabet@error
370  \else
371  \expandafter\noexpand\csname M@#2\endcsname
372  \expandafter\noexpand\csname#2/#3/#4/#5\endcsname
373  \fi

374 }%

375  \toks2\expandafter{#1}%
376  \edef\alpha@list{\the\toks@\noexpand\alpha@elt\the\toks2}%

377  \def\version@elt##1{\toks@\expandafter{##1}%
378  \edef##1{\the\toks@\install@mathalphabet
379  \expandafter\noexpand
380  \csname @\expandafter\@gobble
381  \string#1\endcsname
382  {\if/#5/%
383  \noexpand\no@alphabet@error
384  \noexpand#1%
385  \else
386  \noexpand\select@group\the\toks2
387  \fi}}%

388 }%

389  \version@list
390  \expandafter\edef\csname @\expandafter\@gobble
391  \string#1\endcsname{\if/#5/%
392  \noexpand\no@alphabet@error
393  \noexpand#1%
394  \else
395  \noexpand\select@group\the\toks2
396  \fi}%
397  \edef#1{\noexpand\protect
398  \expandafter\noexpand\csname @\expandafter
399  \@gobble\string#1\endcsname}%

400 }

401 \@onlypreamble\new@mathalphabet
402 \def\SetMathAlphabet#1#2#3#4#5#6{%
403 \@tempswafalse
404 \edef\reserved@b{#3}%
405 \def\cdp@elt##1##2##3##4{\def\reserved@c{##1}%
406  \ifx\reserved@b\reserved@c \@tempswatrue\fi}%
407 \cdp@list
408 \if@tempswa
409 \expandafter\SetMathAlphabet@
410  \csname mv@#2\expandafter\endcsname\csname#3/#4/#5/#6\expandafter
411  \endcsname \csname M@#3\expandafter\endcsname
412  \csname @\expandafter\@gobble\string#1\endcsname#1%
413 \else
414 \@latex@error{Encoding scheme  `#3' unknown}\@eha
415 \fi

416 }

417 \@onlypreamble\SetMathAlphabet
418 \def\SetMathAlphabet@#1#2#3#4#5{%
419 \expandafter\in@\expandafter#1\expandafter{\version@list}%
420 \ifin@
421  \expandafter\in@\expandafter#4\expandafter{\alpha@list}%
422  \ifin@
423  \begingroup
424  \toks@{}%
425  \def\getanddefine@fonts##1##2{%

426  \addto@hook\toks@{\getanddefine@fonts##1##2}%

427 }%

428  \def\reserved@c##1##2##3##4{%                % for message below
429  \expandafter\@gobble\string##4}%
430  \def\install@mathalphabet##1##2{%
431  \ifx##1#4%
432  \addto@hook\toks@
433  {\install@mathalphabet#4{\select@group#4#3#2}}%
434  \@font@info{Overwriting math alphabet
435  `\string#5' in version `\expandafter
436  \@gobblefour\string#1'\MessageBreak
437  \@spaces \reserved@c##2 -->
438  \expandafter\@gobble\string#2}%
439  \else
440  \addto@hook\toks@{\install@mathalphabet##1{##2}}%
441  \fi

442 }%

443  #1%
444  \xdef#1{\the\toks@}%
445  \endgroup
446  \else

If the math alphabet was defined via \DeclareSymbolFontAlphabet we have remove its external definition and add it as a normal math alphabet to every version before trying to change it in one version.

447  \edef\reserved@a{%
448  \noexpand\in@{\string\use@mathgroup}{\meaning#4}}%
449  \reserved@a
450  \ifin@
451  \def\reserved@b##1\use@mathgroup##2##3{%
452  \def\reserved@b{##3}\def\reserved@c{##2}}%
453  \expandafter\reserved@b#4%
454  \begingroup
455  \def\install@mathalphabet##1##2{%
456  \addto@hook\toks@{\install@mathalphabet##1{##2}}%

457 }%

458  \def\getanddefine@fonts##1##2{%
459  \addto@hook\toks@{\getanddefine@fonts##1##2}%
460  \ifnum##1=\reserved@b
461  \expandafter
462  \addto@hook\expandafter\toks@
463  \expandafter{\expandafter\install@mathalphabet
464  \expandafter#4\expandafter
465  {\expandafter\select@group\expandafter
466  #4\reserved@c##2}}%
467  \fi

468 }%

469  \def\version@elt##1{%
470  \toks@{}%
471  ##1%

472  \xdef##1{\the\toks@}%

473 }%

474  \version@list
475  \endgroup

Put it into the \alpha@list with default ‘error’

476  \expandafter\gdef\expandafter\alpha@list\expandafter
477  {\alpha@list
478  \alpha@elt #4\no@alphabet@error \no@alphabet@error}%
479  \gdef#4{\no@alphabet@error #5}% fake things :-)

Then call the internal setting routine again:

480  \SetMathAlphabet@{#1}{#2}{#3}#4#5%
481  \else
482  \@latex@error{Command `\string#5' not defined as a
483  math alphabet}%
484  {Use \noexpand\DeclareMathAlphabet to define it.}%
485  \fi
486  \fi
487 \else
488  \@latex@error{Math version `\expandafter\@gobblefour\string#1'
489  is not
490  defined}{You probably mispelled the name of the math
491  version.^^JOr you have to specify an additional package.}%
492 \fi

493 }

494 \@onlypreamble\SetMathAlphabet@

could do with more checks like allowing single number in #4 lowercase in #4 etc

495 \def\DeclareMathAccent#1#2#3#4{%
496 \expandafter\in@\csname sym#3\expandafter\endcsname
497  \expandafter{\group@list}%
498 \ifin@
499  \begingroup
500  \count\z@=#4\relax
501  \count\tw@\count\z@
502  \divide\count\z@\sixt@@n
503  \count@\count\z@
504  \multiply\count@\sixt@@n
505  \advance\count\tw@-\count@
506  \if\relax\noexpand#1% is command?
507  \edef\reserved@a{\noexpand\in@{\string\mathaccent}{\meaning#1}}%
508  \reserved@a
509  \ifin@
510  \expandafter\set@mathaccent
511  \csname sym#3\endcsname#1#2%
512  {\hexnumber@{\count\z@}\hexnumber@{\count\tw@}}%
513  \@font@info{Redeclaring math accent \string#1}%
514  \else
515  \expandafter\ifx

516  \csname\expandafter\@gobble\string#1\endcsname
517  \relax
518  \expandafter\set@mathaccent
519  \csname sym#3\endcsname#1#2%
520  {\hexnumber@{\count\z@}\hexnumber@{\count\tw@}}%
521  \else
522  \@latex@error{Command `\string#1' already defined}\@eha
523  \fi
524  \fi
525  \else
526  \@latex@error{Not a command name: `\noexpand#1'}\@eha
527  \fi
528  \endgroup
529 \else
530  \@latex@error{Symbol font `#3' is not defined}\@eha
531 \fi

532 }

533 \@onlypreamble\DeclareMathAccent
534 \def\set@mathaccent#1#2#3#4{%
535 \xdef#2{\mathaccent"\mathchar@type#3\hexnumber@#1#4\relax}}
536 \@onlypreamble\set@mathaccent
537 \def\DeclareMathSymbol#1#2#3#4{%
538 \expandafter\in@\csname sym#3\expandafter\endcsname
539  \expandafter{\group@list}%
540 \ifin@
541  \begingroup
542  \count\z@=#4\relax
543  \count\tw@\count\z@
544  \divide\count\z@\sixt@@n
545  \count@\count\z@
546  \multiply\count@\sixt@@n
547  \advance\count\tw@-\count@
548  \if\relax\noexpand#1% is command?
549  \edef\reserved@a{\noexpand\in@{\string\mathchar}{\meaning#1}}%
550  \reserved@a
551  \ifin@
552  \expandafter\set@mathsymbol
553  \csname sym#3\endcsname#1#2%
554  {\hexnumber@{\count\z@}\hexnumber@{\count\tw@}}%
555  \@font@info{Redeclaring math symbol \string#1}%
556  \else
557  \expandafter\ifx
558  \csname\expandafter\@gobble\string#1\endcsname
559  \relax
560  \expandafter\set@mathsymbol
561  \csname sym#3\endcsname#1#2%
562  {\hexnumber@{\count\z@}\hexnumber@{\count\tw@}}%
563  \else
564  \@latex@error{Command `\string#1' already defined}\@eha

565  \fi
566  \fi
567  \else
568  \expandafter\set@mathchar
569  \csname sym#3\endcsname#1#2
570  {\hexnumber@{\count\z@}\hexnumber@{\count\tw@}}%
571  \fi
572  \endgroup
573 \else
574  \@latex@error{Symbol font `#3' is not defined}\@eha
575 \fi

576 }

577 \@onlypreamble\DeclareMathSymbol
578 \def\set@mathchar#1#2#3#4{%
579 \global\mathcode`#2="\mathchar@type#3\hexnumber@#1#4\relax}
580 \@onlypreamble\set@mathchar
581 \def\set@mathsymbol#1#2#3#4{%
582 \global\mathchardef#2"\mathchar@type#3\hexnumber@#1#4\relax}
583 \@onlypreamble\set@mathsymbol
584 %\def\mathsymbol#1#2#3{%
585 %  \@tempcnta=#3\relax
586 %  \@tempcntb\@tempcnta
587 %  \divide\@tempcnta\sixt@@n
588 %  \count@\@tempcnta
589 %  \multiply\count@\sixt@@n
590 %  \advance\@tempcntb-\count@
591 %  \mathchar"\mathchar@type#1\hexnumber@#2%
592 %             \hexnumber@\@tempcnta\hexnumber@\@tempcntb\relax}

593 594

595 %

596 %\def\DeclareMathAlphabetCharacter#1#2#3{%
597 %  \DeclareMathSymbol{#1}7{#2}{#3}}
598 \def\DeclareMathDelimiter#1{%
599 \if\relax\noexpand#1%
600  \expandafter\@DeclareMathDelimiter
601 \else
602  \expandafter\@xDeclareMathDelimiter
603 \fi
604 #1}
605 \@onlypreamble\DeclareMathDelimiter
606 \def\@DeclareMathDelimiter#1#2#3#4#5#6{%
607 \expandafter\in@\csname sym#3\expandafter\endcsname
608  \expandafter{\group@list}%
609 \ifin@
610  \expandafter\in@\csname sym#5\expandafter\endcsname
611  \expandafter{\group@list}%
612  \ifin@

613  \begingroup
614  \count\z@=#4\relax
615  \count\tw@\count\z@
616  \divide\count\z@\sixt@@n
617  \count@\count\z@
618  \multiply\count@\sixt@@n
619  \advance\count\tw@-\count@
620  \edef\reserved@c{\hexnumber@{\count\z@}\hexnumber@{\count\tw@}}%

621 %

622  \count\z@=#6\relax
623  \count\tw@\count\z@
624  \divide\count\z@\sixt@@n
625  \count@\count\z@
626  \multiply\count@\sixt@@n
627  \advance\count\tw@-\count@
628  \edef\reserved@d{\hexnumber@{\count\z@}\hexnumber@{\count\tw@}}%

629 %

630  \edef\reserved@a{\noexpand\in@{\string\delimiter}{\meaning#1}}%
631  \reserved@a
632  \ifin@
633  \expandafter\set@mathdelimiter
634  \csname sym#3\expandafter\endcsname
635  \csname sym#5\endcsname#1#2%
636  \reserved@c\reserved@d
637  \@font@info{Redeclaring math delimiter \string#1}%
638  \else
639  \expandafter\ifx
640  \csname\expandafter\@gobble\string#1\endcsname
641  \relax
642  \expandafter\set@mathdelimiter
643  \csname sym#3\expandafter\endcsname
644  \csname sym#5\endcsname#1#2%
645  \reserved@c\reserved@d
646  \else
647  \@latex@error{Command `\string#1' already defined}\@eha
648  \fi
649  \fi
650  \endgroup
651  \else
652  \@latex@error{Symbol font `#5' is not defined}\@eha
653  \fi
654 \else
655  \@latex@error{Symbol font `#3' is not defined}\@eha
656 \fi

657 }

658 \@onlypreamble\@DeclareMathDelimiter
659 \def\@xDeclareMathDelimiter#1#2#3#4#5{%
660 \expandafter\in@\csname sym#2\expandafter\endcsname
661  \expandafter{\group@list}%

662 \ifin@
663  \expandafter\in@\csname sym#4\expandafter\endcsname
664  \expandafter{\group@list}%
665  \ifin@
666  \begingroup
667  \count\z@=#3\relax
668  \count\tw@\count\z@
669  \divide\count\z@\sixt@@n
670  \count@\count\z@
671  \multiply\count@\sixt@@n
672  \advance\count\tw@-\count@
673  \edef\reserved@c{\hexnumber@{\count\z@}\hexnumber@{\count\tw@}}%

674 %

675  \count\z@=#5\relax
676  \count\tw@\count\z@
677  \divide\count\z@\sixt@@n
678  \count@\count\z@
679  \multiply\count@\sixt@@n
680  \advance\count\tw@-\count@
681  \edef\reserved@d{\hexnumber@{\count\z@}\hexnumber@{\count\tw@}}%
682  \expandafter\set@@mathdelimiter
683  \csname sym#2\expandafter\endcsname\csname sym#4\endcsname#1%
684  \reserved@c\reserved@d
685  \endgroup
686  \else
687  \@latex@error{Symbol font `#4' is not defined}\@eha
688  \fi
689 \else
690  \@latex@error{Symbol font `#2' is not defined}\@eha
691 \fi

692 }

693 \@onlypreamble\@xDeclareMathDelimiter

We have to end the definition of a math delimiter like \lfloor with a space and not with \relax as we did before, because otherwise contructs involving \abovewithdelims will prematurely end (pr/1329)

694 \def\set@mathdelimiter#1#2#3#4#5#6{%
695 \xdef#3{\delimiter"\mathchar@type#4\hexnumber@#1#5%
696  \hexnumber@#2#6 }}
697 \@onlypreamble\set@mathdelimiter
698 \def\set@@mathdelimiter#1#2#3#4#5{%
699 \global\delcode`#3="\hexnumber@#1#4\hexnumber@#2#5\relax}
700 \@onlypreamble\set@@mathdelimiter
701 \def\DeclareMathRadical#1#2#3#4#5{%

Below is a crude fix to make this macro work if #1 is undefined or \relax. Should be improved!

702 \expandafter\ifx
703  \csname\expandafter\@gobble\string#1\endcsname

704  \relax
705  \let#1\radical
706 \fi
707 \edef\reserved@a{\noexpand\in@{\string\radical}{\meaning#1}}%
708 \reserved@a
709 \ifin@
710  \expandafter\in@\csname sym#2\expandafter\endcsname
711  \expandafter{\group@list}%
712  \ifin@
713  \expandafter\in@\csname sym#4\expandafter\endcsname
714  \expandafter{\group@list}%
715  \ifin@
716  \begingroup
717  \count\z@=#3\relax
718  \count\tw@\count\z@
719  \divide\count\z@\sixt@@n
720  \count@\count\z@
721  \multiply\count@\sixt@@n
722  \advance\count\tw@-\count@
723  \edef\reserved@c{%
724  \hexnumber@{\count\z@}\hexnumber@{\count\tw@}}%
725  \count\z@=#5\relax
726  \count\tw@\count\z@
727  \divide\count\z@\sixt@@n
728  \count@\count\z@
729  \multiply\count@\sixt@@n
730  \advance\count\tw@-\count@
731  \edef\reserved@d{%
732  \hexnumber@{\count\z@}\hexnumber@{\count\tw@}}%

Coded inline instead of using \set@mathradical

733 %          \expandafter\set@mathradical
734 %             \csname sym#2\expandafter\endcsname
735 %             \csname sym#4\endcsname#1%
736 %             \reserved@c\reserved@d
737  \xdef#1{\radical"\expandafter\hexnumber@
738  \csname sym#2\endcsname\reserved@c
739  \expandafter\hexnumber@
740  \csname sym#4\endcsname\reserved@d
741  \relax}%
742  \endgroup
743  \else
744  \@latex@error{Symbol font `#4' is not defined}\@eha
745  \fi
746  \else
747  \@latex@error{Symbol font `#2' is not defined}\@eha
748  \fi
749 \else
750  \@latex@error{Command `\string#1' already defined}\@eha
751 \fi

753 \@onlypreamble\DeclareMathRadical

Definition below was wrong it contained \delimiter !

 \def\set@mathradical#1#2#3#4#5{%
   \xdef#3{\radical"\hexnumber@#1#4\hexnumber@#2#5\relax}}
754 \let\mathalpha\relax % just a dummy currently
755 \def\mathchar@type#1{%
756 \ifodd 2#11 #1\else             % is this non-negative number?
757  \ifx#1\mathord 0\else
758  \ifx#1\mathop   1\else
759  \ifx#1\mathbin 2\else
760  \ifx#1\mathrel 3\else
761  \ifx#1\mathopen 4\else
762  \ifx#1\mathclose 5\else
763  \ifx#1\mathpunct 6\else
764  7%             % anything else is variable ord
765  \fi
766  \fi
767  \fi
768  \fi
769  \fi
770  \fi
771  \fi
772 \fi}
773 \@onlypreamble\mathchar@type
774 \def\DeclareSymbolFontAlphabet#1#2{%
775 \expandafter\DeclareSymbolFontAlphabet@
776  \csname @\expandafter\@gobble\string#1\endcsname{#2}#1}
777 \@onlypreamble\DeclareSymbolFontAlphabet
778 \def\DeclareSymbolFontAlphabet@#1#2#3{%

We use the switch \if@tempswa to decide if we can declare this symbol font alphabet.

779  \@tempswatrue

First check if #2 is known to be a symbol font

780 \expandafter\in@\csname sym#2\expandafter\endcsname
781  \expandafter{\group@list}%
782 \ifin@

Check if #1 is defined as a math alphabet defined via \DeclareMathAlphabet:

783  \expandafter\in@\expandafter#1\expandafter{\alpha@list}%
784  \ifin@

If so remove it from the \alpha@list and from all math version macros.

785  \@font@info{Redeclaring math alphabet \string#3}%
786  \toks@{}%
787  \def\alpha@elt##1##2##3{%

788  \ifx##1#1\else\addto@hook\toks@{\alpha@elt##1##2##3}\fi}%
789  \alpha@list
790  \xdef\alpha@list{\the\toks@}%

Now we loop over all versions and remove the math alphabet:

791  \def\version@elt##1{%
792  \begingroup
793  \toks@{}%
794  \def\getanddefine@fonts####1####2{%
795  \addto@hook\toks@{\getanddefine@fonts####1####2}}%
796  \def\install@mathalphabet####1####2{%
797  \ifx####1#1\else
798  \addto@hook\toks@{\install@mathalphabet
799  ####1{####2}}\fi}%
800  ##1%
801  \xdef##1{\the\toks@}%
802  \endgroup

803 }%

804  \version@list
805  \else

If #3 is not defined as a math alphabet check if it is defined at all:

806  \expandafter\ifx
807  \csname\expandafter\@gobble\string#1\endcsname
808  \relax

If it is undefined, fine otherwise check if it is a math alphabet defined via

 \DeclareSymbolFontAlphabet:
809  \else
810  \edef\reserved@a{%
811  \noexpand\in@{\string\use@mathgroup}{\meaning#1}}%
812  \reserved@a
813  \ifin@
814  \@font@info{Redeclaring math alphabet \string#3}%
815  \else

Since the command #3 is defined to be something which is not a math alphabet we have to skip redefining it.

816  \@tempswafalse
817  \@latex@error{Command `\string#3' already defined}\@eha
818  \fi
819  \fi
820  \fi
821 \else

Since the symbol font is not known we better skip defining this alphabet.

822  \@tempswafalse
823  \@latex@error{Unknown symbol font `#2'}\@eha
824 \fi
825 \if@tempswa

When we reach this point we are allowed to define #1 to be a symbol font math alphabet. This means that we have to set it to

\use@mathgroup ⟨math-settings⟩ \sym⟨name⟩

The ⟨math-settings⟩ are the one for the encoding that is used in the font shape where \sym⟨name⟩ is pointing to. This means that we have to get it from the information stored in \group@list. Thus we loop through that list after defining \group@elt in a suitable way.

826  \def\group@elt##1##2{%
827  \expandafter\ifx\csname sym#2\endcsname##1%
828  \expandafter\reserved@a\string##2\@nil
829  \fi}%
830  \def\reserved@a##1##2/##3\@nil{%
831  \def\reserved@a{##2}}%
832  \group@list
833  \toks@{\relax\ifmmode \else \non@alpherr#1\fi}%
834  \edef#1{\the\toks@
835  \noexpand\use@mathgroup
836  \expandafter\noexpand\csname M@\reserved@a\endcsname
837  \csname sym#2\endcsname}%
838  \def#3{\protect#1}%
839 \fi

840 }

841 \@onlypreamble\DeclareSymbolFontAlphabet@

842 ⟨/2ekernel | autoload⟩