1%D \module 2%D [ file=catc-ini, 3%D version=2006.09.18, 4%D title=\CONTEXT\ System Macros, 5%D subtitle=Catcode Handling, 6%D author=Hans Hagen, 7%D date=\currentdate, 8%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] 9%C 10%C This module is part of the \CONTEXT\ macro||package and is 11%C therefore copyrighted by \PRAGMA. See mreadme.pdf for 12%C details. 13 14\registerctxluafile{catc-ini}{autosuffix} 15 16\unprotect 17 18%D A long standing wish has been the availability of catcode arrays. Because 19%D traditional \TEX\ does not provide this we implement a fake method in the \MKII\ 20%D file. There is some overlap in code with \MKII\ but we take that for granted. 21%D Also, in \MKIV\ less active characters are used. 22 23% \begingroup 24% \letcharcode\newlineasciicode\relax \xdef\outputnewlinechar{\tocharacter\newlineasciicode} 25% \endgroup 26 27% \endlinechar = \endoflineasciicode % appended to input lines 28% \newlinechar = \newlineasciicode % can be used in write 29 30% rather special and used in writing to file: \let\par\outputnewlinechar 31 32% \permanent\protected\def\initializenewlinechar % operating system dependent 33% {\begingroup 34% \enforced\letcharcode\newlineasciicode\relax 35% \newlinechar\newlineasciicode 36% \xdef\outputnewlinechar{\tocharacter\newlineasciicode}% 37% \endgroup} 38 39%D We predefine some prefixes ahead of syst-aux and mult-sys. We reserve 8 slots for 40%D catcodes. (This active mess probably needs an update some day.) 41 42% \installsystemnamespace{catcodelet} % let : \let 43% \installsystemnamespace{catcodedef} % def : \def 44% \installsystemnamespace{catcodeued} % ued : \protected\def 45% \installsystemnamespace{catcodeget} % \meaning 46 47\installsystemnamespace{catcodetablet} 48\installsystemnamespace{catcodetablen} 49 50\newinteger\c_syst_catcodes_n \c_syst_catcodes_n\zerocount % 0 = signal, so advance before allocate 51 52%newinteger\c_syst_catcodes_a 53%newinteger\c_syst_catcodes_b 54%newinteger\c_syst_catcodes_c 55 56\permanent\protected\def\newcatcodetable#1% we could move the cctdefcounter to lua 57 {\global\advanceby\c_syst_catcodes_n\plusone 58 \gdefcsname\??catcodetablen\the\c_syst_catcodes_n\endcsname{\string#1}% logging 59 \immutable\integerdef#1\c_syst_catcodes_n 60 catcodes.register("\expandafter\gobbleoneargument\string#1",\number#1)} 61 62\newtoks\everysetdefaultcatcodes 63 64\everysetdefaultcatcodes % this might get dropped 65 {\catcode\backslashasciicode\othercatcode 66 \catcode\endoflineasciicode\othercatcode 67 \catcode\spaceasciicode \othercatcode 68 \catcode\commentasciicode \othercatcode 69 \catcode\delasciicode \othercatcode} 70 71\permanent\protected\def\startcatcodetable#1#2\stopcatcodetable 72 {\begingroup 73 \catcodetable\inicatcodes 74 \expand\everysetdefaultcatcodes 75 #2% 76 \savecatcodetable#1\relax 77 \endgroup} 78 79\permanent\let\stopcatcodetable\relax 80 81\permanent\protected\def\startextendcatcodetable#1#2\stopextendcatcodetable 82 {\begingroup 83 \catcodetable#1\relax 84 \globaldefs\plusone % a bit hackish 85 #2% 86 \globaldefs\zerocount 87 \endgroup} 88 89% doesn't work these tables are global anyway 90% 91% \permanent\protected\def\startextendcatcodetable#1#2\stopextendcatcodetable 92% {\begingroup 93% \c_syst_catcodes_n\catcodetable 94% \catcodetable#1\relax 95% #2% 96% \catcodetable\c_syst_catcodes_n 97% \endgroup} 98 99\permanent\let\stopextendcatcodetable\relax 100 101\permanent\protected\def\permitcircumflexescape % to be used grouped 102 {\catcode\circumflexasciicode\superscriptcatcode} 103 104\aliased\let\permitcaretescape\permitcircumflexescape 105 106\newconstant\defaultcatcodetable 107 108%D The next command can be defined in a cleaner way in the MkIV way but we want 109%D to have a fast one with a minimal chance for interference. Do we still need 110%D this complex mechanism? Probably not. Future versions of \MKIV\ might only use 111%D active characters for very special cases. Older files demonstrate this old 112%D hackery tilde abuse. 113 114% %D Once a catcode is assigned, the next assignments will happen faster. However, 115% %D redefinitions probably happen seldom so it's sort of overkill. We also need to 116% %D take care of the initial (shared between catcode regimes) binding. 117% 118% \permanent\protected\def\letcatcodecommand{\afterassignment\syst_catcodes_let_a\c_syst_catcodes_a} 119% \permanent\protected\def\defcatcodecommand{\afterassignment\syst_catcodes_def_a\c_syst_catcodes_a} % obsolete 120% \permanent\protected\def\uedcatcodecommand{\afterassignment\syst_catcodes_ued_a\c_syst_catcodes_a} % obsolete 121% 122% \def\syst_catcodes_let_a{\afterassignment\syst_catcodes_let_b\c_syst_catcodes_b} 123% \def\syst_catcodes_def_a{\afterassignment\syst_catcodes_def_b\c_syst_catcodes_b} 124% \def\syst_catcodes_ued_a{\afterassignment\syst_catcodes_ued_b\c_syst_catcodes_b} 125% 126% % The two step definition is used because we need to fetch the third argument. 127% 128% \def\syst_catcodes_let_b % each time 129% {\ifcsname\??catcodelet\the\c_syst_catcodes_a:\the\c_syst_catcodes_b\endcsname 130% \expandafter\lastnamedcs 131% \else 132% \expandafter\syst_catcodes_let_c 133% \fi} 134% 135% \def\syst_catcodes_def_b % each time 136% {\ifcsname\??catcodedef\the\c_syst_catcodes_a:\the\c_syst_catcodes_b\endcsname 137% \expandafter\lastnamedcs 138% \else 139% \expandafter\syst_catcodes_def_c 140% \fi} 141% 142% \def\syst_catcodes_ued_b % each time 143% {\ifcsname\??catcodeued\the\c_syst_catcodes_a:\the\c_syst_catcodes_b\endcsname 144% \expandafter\lastnamedcs 145% \else 146% \expandafter\syst_catcodes_ued_c 147% \fi} 148% 149% \def\syst_catcodes_let_c % only first time 150% {\frozen\enforced\gdefcsname\??catcodelet\the\c_syst_catcodes_a:\the\c_syst_catcodes_b\expandafter\endcsname\expandafter 151% {\expandafter\enforced\letcsname\??catcodeget\the\c_syst_catcodes_a:\the\c_syst_catcodes_b\endcsname}% 152% \syst_catcodes_reinstate_unexpanded 153% \csname\??catcodelet\the\c_syst_catcodes_a:\the\c_syst_catcodes_b\endcsname} 154% 155% \def\syst_catcodes_def_c % only first time (we could use \normalexpanded here) 156% {\frozen\enforced\gdefcsname\??catcodedef\the\c_syst_catcodes_a:\the\c_syst_catcodes_b\expandafter\endcsname 157% \expandafter##\expandafter1\expandafter 158% {\expandafter\frozen\expandafter\enforced\defcsname\??catcodeget\the\c_syst_catcodes_a:\the\c_syst_catcodes_b\endcsname{##1}}% 159% \syst_catcodes_reinstate_normal 160% \csname\??catcodedef\the\c_syst_catcodes_a:\the\c_syst_catcodes_b\endcsname} 161% 162% \def\syst_catcodes_ued_c % only first time 163% {\frozen\enforced\gdefcsname\??catcodeued\the\c_syst_catcodes_a:\the\c_syst_catcodes_b\expandafter\endcsname 164% \expandafter##\expandafter1\expandafter 165% {\expandafter\frozen\expandafter\enforced\expandafter\protected\defcsname\??catcodeget\the\c_syst_catcodes_a:\the\c_syst_catcodes_b\endcsname{##1}}% 166% \syst_catcodes_reinstate_unexpanded 167% \csname\??catcodeued\the\c_syst_catcodes_a:\the\c_syst_catcodes_b\endcsname} 168% 169% %D We can simplify this a bit (not that critical): 170% 171% \def\syst_catcodes_let_b 172% {\afterassignment\syst_catcodes_let_c\let\m_syst_catcodes_temp} 173% 174% \def\syst_catcodes_let_c 175% {\enforced\letcsname\??catcodeget\the\c_syst_catcodes_a:\the\c_syst_catcodes_b\endcsname\m_syst_catcodes_temp 176% \protected\edef\m_syst_catcodes_temp{\noexpand\catcodecommand{\the\c_syst_catcodes_b}}% 177% \letcharcode\c_syst_catcodes_b\m_syst_catcodes_temp} 178% 179% \def\syst_catcodes_let_c 180% {\letcharcode\c_syst_catcodes_b\m_syst_catcodes_temp} 181% 182% % not that much gain: 183% 184% \def\syst_catcodes_let_c % only first time 185% {\expandafter\integerdef\csname\??catcodelet\the\c_syst_catcodes_a:\the\c_syst_catcodes_b\endcsname\c_syst_catcodes_b 186% \letcsname\??catcodeget\the\c_syst_catcodes_a:\the\c_syst_catcodes_b\endcsname\m_syst_catcodes_temp 187% \protected\edef\m_syst_catcodes_temp{\noexpand\catcodecommand\csname\??catcodelet\the\c_syst_catcodes_a:\the\c_syst_catcodes_b\endcsname}% 188% \letcharcode\c_syst_catcodes_b\m_syst_catcodes_temp} 189 190%D This can be used when a direct definition has been done and the selector has been 191%D lost. I really need to get rid of this ... 192 193% \permanent\def\reinstatecatcodecommand{\afterassignment\syst_catcodes_reinstate_normal\c_syst_catcodes_b} 194% 195% \let\m_syst_catcodes_temp\relax 196% 197% \def\syst_catcodes_reinstate_normal 198% {\edef\m_syst_catcodes_temp{\noexpand\catcodecommand{\the\c_syst_catcodes_b}}% 199% \letcharcode\c_syst_catcodes_b\m_syst_catcodes_temp} 200% 201% \def\syst_catcodes_reinstate_unexpanded 202% {\protected\edef\m_syst_catcodes_temp{\noexpand\catcodecommand{\the\c_syst_catcodes_b}}% 203% \letcharcode\c_syst_catcodes_b\m_syst_catcodes_temp} 204% 205% \permanent\def\catcodecommand#1% 206% {\csname\??catcodeget\number 207% \ifcsname\??catcodeget\number\currentcatcodetable:\number#1\endcsname 208% \currentcatcodetable \else \defaultcatcodetable 209% \fi 210% :\number#1\endcsname} 211 212%D For now, will become just letcharcode: 213 214\permanent\protected\def\letcatcodecommand{\afterassignment\letcharcode\scratchcounter} 215 216%D \startbuffer 217%D \def\foo{foo} 218%D \start 219%D \pushactivechar | \letcharcode124 \foo test||test\par 220%D \popactivechar | test||test\par 221%D \stop 222%D \start 223%D \pushactivecharcode124 \letcharcode124 \foo test||test\par 224%D \popactivecharcode 124 test||test\par 225%D \stop 226%D \stopbuffer 227%D 228%D \typebuffer \getbuffer 229 230\permanent\protected\def\pushactivechar#1% 231 {\expandafter\let\expandafter\m_active\csname\csactive#1\endcsname 232 %\expandafter\let\expandafter\m_active\csname\tocharacter"FFFF\tocharacter\expandafter`\string#1\endcsname 233 \pushmacro\m_active} 234 235\permanent\protected\def\popactivechar#1% 236 {\popmacro\m_active 237 %\letcsname\tocharacter"FFFF\tocharacter\expandafter`\string#1\endcsname\m_active 238 \letcsname\csactive#1\endcsname\m_active} 239 240\mutable\integerdef\c_active_char_code\zerocount 241 242\permanent\protected\def\pushactivecharcode{\afterassignment\syst_active_push\integerdef\c_active_char_code} 243\permanent\protected\def\popactivecharcode {\afterassignment\syst_active_pop \integerdef\c_active_char_code} 244 245\permanent\protected\def\syst_active_push 246 {\expandafter\let\expandafter\m_active\csname\csactive\tocharacter\c_active_char_code\endcsname 247 %\expandafter\let\expandafter\m_active\csname\tocharacter"FFFF\tocharacter\c_active_char_code\endcsname 248 \pushmacro\m_active} 249 250\permanent\protected\def\syst_active_pop 251 {\popmacro\m_active 252 %\letcsname\tocharacter"FFFF\tocharacter\c_active_char_code\endcsname\m_active 253 \letcsname\csactive\tocharacter\c_active_char_code\endcsname\m_active} 254 255%D \macros 256%D {restorecatcodes,pushcatcodetable,popcatcodetable} 257%D 258%D We're not finished dealing \CATCODES\ yet. In \CONTEXT\ we use only one auxiliary 259%D file, which deals with tables of contents, registers, two pass tracking, 260%D references etc. This file, as well as files concerning graphics, is processed 261%D when needed, which can be in the mid of typesetting verbatim. However, when 262%D reading in data in verbatim mode, we should temporary restore the normal 263%D \CATCODES, and that's exactly what the next macros do. Saving the catcodes can be 264%D disabled by saying \type {\localcatcodestrue}. In \MKIV\ instead we can push and 265%D pop catcode tables and as we keep track of used tables users seldom need to deal 266%D with this themselves. 267 268\newinteger\c_syst_catcodes_level 269 270\permanent\protected\def\pushcatcodetable 271 {\advanceby\c_syst_catcodes_level\plusone 272 \syst_catcodes_trace_push 273 \expandafter\integerdef\csname\??catcodetablet\the\c_syst_catcodes_level\endcsname\currentcatcodetable} 274 275\permanent\protected\def\popcatcodetable 276 {\ifcase\c_syst_catcodes_level 277 \syst_catcodes_trace_nesting_error 278 \else 279 \catcodetable\csname\??catcodetablet\the\c_syst_catcodes_level\endcsname 280 \syst_catcodes_trace_pop 281 \advanceby\c_syst_catcodes_level\minusone 282 \fi} 283 284\protected\def\syst_catcodes_trace_nesting_error 285 {\immediate\write\statuswrite{}% 286 \immediate\write\statuswrite{Fatal error: catcode push/pop mismatch. Fix this! (restore level: \the\c_syst_catcodes_level)}\wait\end 287 \immediate\write\statuswrite{}} 288 289\permanent\protected\def\restorecatcodes % takes previous level 290 {\ifnum\c_syst_catcodes_level>\plusone 291 \catcodetable\csname\??catcodetablet\the\numexpr\c_syst_catcodes_level-1\relax\endcsname 292 \fi} 293 294\permanent\protected\def\setcatcodetable#1% 295 {\catcodetable#1% 296 \syst_catcodes_trace_set} 297 298%D Handy for debugging (not that we ever use(d) it): 299%D 300%D \starttyping 301%D \tracecatcodetables 302%D \stoptyping 303 304\permanent\protected\def\tracecatcodetables 305 {\def\syst_catcodes_trace_set {\syst_catcodes_trace{set \catcodetablename\space at \the\c_syst_catcodes_level}}% 306 \def\syst_catcodes_trace_push{\syst_catcodes_trace{push \catcodetablename\space from \syst_catcodes_prev\space at \the\c_syst_catcodes_level}}% 307 \def\syst_catcodes_trace_pop {\syst_catcodes_trace{pop \catcodetablename\space to \syst_catcodes_prev\space at \the\c_syst_catcodes_level}}} 308 309\def\syst_catcodes_trace#1{\immediate\write\statuswrite{[#1]}} 310 311\def\syst_catcodes_prev 312 {\ifnum\numexpr\c_syst_catcodes_level-1\relax>\zerocount 313 \csname\??catcodetablen\number\csname\??catcodetablet\the\numexpr\c_syst_catcodes_level-1\relax\endcsname\endcsname 314 \else 315 -% 316 \fi} 317 318\permanent\def\catcodetablename 319 {\ifnum\currentcatcodetable>\zerocount 320 \csname\??catcodetablen\number\currentcatcodetable\endcsname 321 \else 322 -% 323 \fi} 324 325\lettonothing\syst_catcodes_trace_set 326\lettonothing\syst_catcodes_trace_push 327\lettonothing\syst_catcodes_trace_pop 328 329% \tracecatcodetables 330 331\protect 332 333%D We still have to define these so let's do that now: 334 335\newcatcodetable \inicatcodes 336\initcatcodetable\inicatcodes 337 338\mutable\let\currentcatcodetable\catcodetable 339 340\endinput 341 |