util.tex (6640B)
1 % Special constants 2 \chardef\maxchar=1114111 3 \newcount\maxcount \maxcount="7FFFFFFF 4 \newdimen\maxdimen \maxdimen=16383.99999pt 5 \newskip\centering \centering=0pt plus1000pt minus1000pt 6 \newbox\voidbox 7 8 % These macros help cope with TeX's bad behaviour regarding \afterassignment 9 % and \setbox with a literal box (e.g., \hbox{...}). 10 \newcount\@grouplevel 11 \def\@checkgrouplevel{\ifnum\currentgrouplevel>\@grouplevel \ea\aftergroup \fi} 12 \def\@savegrouplevel{\@grouplevel\currentgrouplevel} 13 14 % \defevent defines an "event". Hooks can be attached to events with \addhook, 15 % and all hooks are run in order when the event is triggered with \event. 16 % Events can have parameters like macros, and hooks have access to these 17 % parameters. For example, 18 % \defevent#1#2[myevent] 19 % \addhook[myevent]{Hello from my 1st hook! (\#1 = #1)} 20 % \addhook[myevent]{Hello from my 2nd hook! (\#2 = #2)} 21 % \event[myevent]{abc}{xyz} 22 % produces 23 % Hello from my 1st hook! (#1 = abc)Hello from my 2nd hook! (#2 = xyz) 24 % Events are always defined globally, but hooks can be local (the default) or 25 % global (prefix \addhook with \global). 26 \protected\def\defevent#1[#2]{% 27 \toksA={#1}% Double hashes 28 \xcsdef{event:#2}{\def\nx\@hooks\the\toksA}% 29 \ea\gnewtoks\begcs hooks:#2\endcs \cs{hooks:#2}={}% 30 } 31 \protected\def\event[#1]{% 32 \relax % Events can appear in weird places (e.g., the standard \par event) 33 \begcs event:#1\ea\endcs\ea{\the\cs{hooks:#1}}% 34 \@hooks 35 } 36 \protected\def\addhook[#1]#2{\cs{hooks:#1}\ea{\the\cs{hooks:#1}#2}} 37 38 % \begparser...\endparser defines a "parser". Usage: 39 % \begparser\x 40 % \stage<param 0>{<body 0>}<assign 0>... 41 % \stage<param 1>{<body 1>}<assign 1>... 42 % etc... 43 % \stage<param n-1>{<body n-1>}<assign n-1>... 44 % \stage<param n>{<body n>}... 45 % \endparser 46 % 47 % This defines a series of macros of form 48 % \csdef{x:0}<param 0>{<body 0> \afterassignment\x:1 <assign 0>} 49 % \csdef{x:1}<param 1>{<body 1> \afterassignment\x:2 <assign 1>} 50 % etc... 51 % \csdef{x:n-1}<param n-1>{<body n-1> \afterassignment\x:n <assign n-1>} 52 % \csdef{x:n}<param n>{<body n>} 53 % 54 % Any of the <assign i>'s may be empty, in which case the corresponding 55 % \afterassignment is omitted. Also, any of the \stage's may be replaced by a 56 % \boxstage, in which case an intermediate stage is inserted to deal with the 57 % behaviour of \afterassignment on box assignments with literal boxes 58 % (e.g., \hbox{...}). 59 % 60 % Note that the text between \begparser\x and \endparser is essentially 61 % arbitrary, so one can employ tricks such as 62 % \toksA={ } 63 % \ea\stage\the\toksA{<body>}<assign>... 64 % 65 % Parsers are always defined locally. 66 % TODO: Add version of \begparser that defines each stage globally. 67 \newcount\@parsern 68 \newif\if@boxstage 69 \newtoks\@stageparam 70 \def\@parsercs{\@parsername:\number\numexpr\@parsern} 71 \protected\def\begparser#1{% 72 \@parsern=0 73 \edef\@parsername{\csstring#1}% 74 \def\@prevstage##1{}% 75 } 76 \protected\def\boxstage{\@boxstagetrue \stage} 77 \protected\def\stage#1#{\@stageparam={#1}\@stage} 78 \def\@stage#1#2...{% 79 \@prevstage\iftrue % Define the prev stage with linkage to the curr stage. 80 \def\@stageasn{#2}% 81 \if@boxstage 82 \ifx\@stageasn\empty \else 83 \ecsdef{\@parsercs!}{% 84 \nx\@checkgrouplevel \ea\nx\begcs\@parsercs+1\endcs 85 }% 86 \fi 87 \fi 88 \edef\@stagedef{\csdef{\@parsercs}\the\@stageparam}% 89 \edef\@stagelinkage{% 90 \ifx\@stageasn\empty % Omit \afterassignment? 91 \ea\nx\begcs\@parsercs+1\endcs 92 \else 93 \if@boxstage 94 \nx\@savegrouplevel 95 \afterassignment\ea\nx\begcs\@parsercs!\endcs 96 \else 97 \afterassignment\ea\nx\begcs\@parsercs+1\endcs 98 \fi 99 \unexpanded{#2}% 100 \fi 101 }% 102 \def\@prevstage##1{% 103 \edef\@stagebody{{% 104 \unexpanded{#1}% 105 ##1% Include linkage? 106 \unexpanded\ea{\@stagelinkage}% 107 \fi 108 }}% 109 \ea\@stagedef\@stagebody 110 }% 111 \incr\@parsern 112 \@boxstagefalse 113 } 114 \protected\def\endparser{% 115 \ifnum\@parsern=0 116 \errmessage{parser misuse: no stages}% 117 \fi 118 \ifx\@stageasn\empty \else 119 \errmessage{parser misuse: last stage must have no assignment}% 120 \fi 121 \@prevstage\iffalse % Define last stage with no linkage. 122 \csletcs\@parsername{\@parsername:0}% 123 } 124 125 % White space control 126 \def\^^M{\ } % control <return> = control <space> 127 \def\^^I{\ } % control <tab> = control <space> 128 { 129 \catcode`\^^M=13 % These lines must end with %. 130 % In \obeylines, we say `\let^^M=\par' instead of `\def^^M{\par}' 131 % since this allows, for example, `\let\par=\cr \obeylines \halign{...'. 132 \gdef\obeylines{\catcode`\^^M=13 \let^^M=\par}% 133 \glet^^M=\par % See The TeXBook, page 254. 134 } 135 \def\obeyspaces{\catcode`\ =13 } 136 {\obeyspaces\glet =\space} % See The TeXBook, page 254. 137 \def\obeytabs{\catcode`\^^I=13 } 138 {\obeytabs\glet^^I=\tab} % See The TeXBook, page 254. 139 { 140 \obeytabs % These lines can not have tab indents. 141 \gdef\@expandtabs{% 142 \toksA={}% 143 \loop\ifnum\countA>0 \toksA\ea{\the\toksA\ }\decr\countA\repeat 144 \obeytabs \edef^^I{\the\toksA}% 145 } 146 \gdef\expandtabs{\afterassignment\@expandtabs \countA=} 147 } 148 \def\gobblespace{\let\csA= } 149 \def\@optionalspace{\ifcat\next\space \ea\gobblespace \fi} 150 \def\optionalspace{\futurelet\next\@optionalspace} 151 152 % Mode control 153 \def\leavevmode{\relax \ifvmode \unhbox\voidbox \fi} 154 \def\leavehmode{\relax \ifhmode \par \fi} 155 \def\modechoice#1#2#3{% 156 \relax 157 \ifvmode 158 \def\next{#1}% 159 \else\ifhmode 160 \def\next{#2}% 161 \else % mmode 162 \def\next{#3}% 163 \fi\fi 164 \next 165 } 166 167 % Generalized mathpalette---gives number to be used with \ifcase 168 \def\mathpalette#1#2{\mathchoice{#10{#2}}{#11{#2}}{#12{#2}}{#13{#2}}} 169 170 \protected\def\sty#1{% 171 \ifcase\numexpr#1\relax 172 \displaystyle 173 \or\textstyle 174 \or\scriptstyle 175 \or\scriptscriptstyle 176 \fi 177 } 178 179 \protected\def\styfont#1{% 180 \ifcase\numexpr#1\relax 181 \textfont 182 \or\textfont 183 \or\scriptfont 184 \or\scriptscriptfont 185 \fi 186 } 187 188 % Usage: \styfontdimen<sty><fam><number> 189 \def\styfontdimen#1#2#3{\fontdimen\numexpr#3\relax\styfont{#1}\numexpr#2\relax} 190 191 % \defer defers execution of the given tokens until after the current group 192 % (like \aftergroup, but with multiple tokens). 193 \newcount\@defernext \@defernext=0 194 \protected\def\defer#1{% 195 \ifnum\currentgrouplevel>0 196 \gcsdef{defer:\the\@defernext}{#1}% 197 \ea\aftergroup\begcs defer:\the\@defernext\endcs 198 \incr\@defernext 199 \fi 200 } 201 202 % \deferasn defers execution of the given tokens until after the next 203 % assignment (like \afterassignment, but with multiple tokens). For box 204 % register assignments, the tokens are placed after the entire assignment, 205 % unlike with \afterassignment. \deferasn does not use any temporary registers. 206 \def\@deferasnA{\@checkgrouplevel\@deferasnB} 207 \protected\def\deferasn#1{% 208 \@savegrouplevel 209 \def\@deferasnB{#1}% 210 \afterassignment\@deferasnA 211 } 212 213 \endinput