%D \module %D [ file=syst-pln, %D version=2001.11.16, % 1999.03.17, % an oldie: 1995.10.10 %D title=\CONTEXT\ System Macros, %D subtitle=Efficient \PLAIN\ \TEX\ loading, %D author=Hans Hagen, %D date=\currentdate, %D copyright={PRAGMA / Hans Hagen \& Ton Otten}] %C %C This module is part of the \CONTEXT\ macro||package and is %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. %D We used to load plain \TEX\ in a special way, but redefining %D a couple of primitives so that for instance font loading was %D ignored. For those interested, this loader is found in %D \type {syst-tex.tex}. %D This is a stripped down version of plain \TEX. We need this %D module to get started. Whole sections are missing here, %D like font loading and math. Thise are taken care of in %D dedicated modules. A few definitions are added (and %D marked as such). %D Characters can have special states, that can be triggered %D by setting their category coded. Some are preset, others %D are to be set as soon as possible, otherwise we cannot %D define any useful macros. %catcode`\^^@ = 9 % ascii null is ignored %catcode`\\ = 0 % backslash is TeX escape character \catcode`\{ = 1 % left brace is begin-group character \catcode`\} = 2 % right brace is end-group character \catcode`\$ = 3 % dollar sign is math shift \catcode`\& = 4 % ampersand is alignment tab \catcode`\# = 6 % hash mark is macro parameter character \catcode`\^ = 7 % circumflex and uparrow are for superscripts \catcode`\_ = 8 % underline and downarrow are for subscripts \catcode`\^^I = 10 % ascii tab is a blank space %catcode`\^^M = 5 % ascii return is end-line %catcode`\% = 14 % percent sign is comment character %catcode`\ = 10 % ascii space is blank space %catcode`\^^? = 15 % ascii delete is invalid \catcode`\~ = 13 % tilde is active \catcode`\^^L = 13 % ascii form-feed %catcode`\A = 11 %....... %catcode`\Z = 11 %catcode`\a = 11 %....... %catcode`\z = 11 \chardef\active = 13 \def ^^L{\par} \def\^^M{\ } % control = control \def\^^I{\ } % same for %D In \CONTEXT, we simply ignore end||of||file tokens: \catcode`\^^Z=9 %D First we define a simplified version of the \CONTEXT\ %D protection mechanism. \def\unprotect{\catcode`@=11} \def\protect {\catcode`@=12} \unprotect %D We do not set up mathcodes here, but postpone that to the %D math modules. \mathcode`\ = "8000 % \space \mathcode`\' = "8000 % ^\prime \mathcode`\_ = "8000 % \_ \mathcode`\^^? = "1273 % \smallint \sfcode`\)=0 \sfcode`\'=0 \sfcode`\]=0 \chardef\@ne = 1 \chardef\tw@ = 2 \chardef\thr@@ = 3 \chardef\sixt@@n = 16 \chardef\@cclv = 255 \mathchardef\@cclvi = 256 \mathchardef\@m = 1000 \mathchardef\@M = 10000 \mathchardef\@MM = 20000 %D Pretty important definitions: \let\bgroup={ \let\egroup=} %D In plain \TEX\ the following explanation about the register %D allocation mechanism is given: %D %D \startnarrower %D The following counters are reserved: %D %D \starttabulate %D \NC 0--9 \NC page numbering \NC \NR %D \NC 10 \NC count allocation \NC \NR %D \NC 11 \NC dimen allocation \NC \NR %D \NC 12 \NC skip allocation \NC \NR %D \NC 13 \NC muskip allocation \NC \NR %D \NC 14 \NC box allocation \NC \NR %D \NC 15 \NC toks allocation \NC \NR %D \NC 16 \NC read file allocation \NC \NR %D \NC 17 \NC write file allocation \NC \NR %D \NC 18 \NC math family allocation \NC \NR %D \NC 19 \NC language allocation \NC \NR %D \NC 20 \NC insert allocation \NC \NR %D \NC 21 \NC the most recently allocated number \NC \NR %D \NC 22 \NC constant $-1$ \NC \NR %D \stoptabulate %D %D New counters are allocated starting with 23, 24, etc. Other %D registers are allocated starting with 10. This leaves 0 %D through 9 for the user to play with safely, except that %D counts 0 to 9 are considered to be the page and subpage %D numbers (since they are displayed during output). In this %D scheme, \type {\count10} always contains the number of the %D highest||numbered counter that has been allocated, \type %D {\count14} the highest||numbered box, etc. Inserts are given %D numbers 254, 253, etc., since they require a \type %D {\count}, \type {\dimen}, \type {\skip}, and \type {\box} %D all with the same number; \type {\count20} contains the %D lowest-numbered insert that has been allocated. Of course, %D \type {\box255} is reserved for \type {\output}; \type %D {\count255}, \type {\dimen255}, and \type {\skip255} can be %D used freely. %D %D It is recommended that macro designers always use \type %D {\globa}l assignments with respect to registers numbered 1, %D 3, 5, 7, 9, and always non||\type {\global} assignments %D with respect to registers 0, 2, 4, 6, 8, 255. This will %D prevent \quote {save stack buildup} that might otherwise %D occur. %D \stopnarrower %D %D We well overload some macros in \ETEX\ mode. \count10 = 22 % allocates \count registers 23, 24, ... \count11 = 9 % allocates \dimen registers 10, 11, ... \count12 = 9 % allocates \skip registers 10, 11, ... \count13 = 9 % allocates \muskip registers 10, 11, ... \count14 = 9 % allocates \box registers 10, 11, ... \count15 = 9 % allocates \toks registers 10, 11, ... \count16 = -1 % allocates input streams 0, 1, ... \count17 = -1 % allocates output streams 0, 1, ... \count18 = 3 % allocates math families 4, 5, ... \count19 = 0 % allocates \language codes 1, 2, ... \count20 =255 % allocates insertion classes 254, 253, ... \countdef\insc@unt = 20 % the insertion counter \countdef\allocationnumber= 21 % the most recent allocation \countdef\m@ne = 22 % a handy constant \m@ne = -1 \def\wlog{\immediate\write\m@ne} % write on log file (only) %D \startnarrower %D Here are abbreviations for the names of scratch registers %D that don't need to be allocated. %D \stopnarrower \countdef \count@ = 255 \dimendef \dimen@ = 0 \dimendef \dimen@i = 1 % global only \dimendef \dimen@ii = 2 \skipdef \skip@ = 0 \toksdef \toks@ = 0 %D \startnarrower %D Now, we define \type {\newcount}, \type {\newbox}, etc. so %D that you can say \newcount\foo and \type {\foo} will be %D defined (with \type {\countdef}) to be the next counter. To %D find out which counter \type {\foo} is, you can look at %D \type {\allocationnumber}. Since there's no \type {\boxdef} %D command, \type {\chardef} is used to define a \type %D {\newbox}, \type {\newinsert}, \type {\newfam}, and so on. %D \stopnarrower \def\newcount {\alloc@0\count \countdef \insc@unt} \def\newdimen {\alloc@1\dimen \dimendef \insc@unt} \def\newskip {\alloc@2\skip \skipdef \insc@unt} \def\newmuskip {\alloc@3\muskip \muskipdef\@cclvi } \def\newbox {\alloc@4\box \chardef \insc@unt} \def\newtoks {\alloc@5\toks \toksdef \@cclvi } \def\newread {\alloc@6\read \chardef \sixt@@n } \def\newwrite {\alloc@7\write \chardef \sixt@@n } \def\newfam {\alloc@8\fam \chardef \sixt@@n } \def\newlanguage{\alloc@9\language\chardef \@cclvi } \def\newhelp#1#2{\newtoks#1#1\expandafter{\csname#2\endcsname}} \def\alloc@#1#2#3#4#5% {\global\advance\count1#1by\@ne \ch@ck#1#4#2% make sure there's still room \allocationnumber=\count1#1% \global#3#5=\allocationnumber \wlog{\string#5=\string#2\the\allocationnumber}} \def\newinsert#1% {\global\advance\insc@unt by\m@ne \ch@ck0\insc@unt\count \ch@ck1\insc@unt\dimen \ch@ck2\insc@unt\skip \ch@ck4\insc@unt\box \allocationnumber=\insc@unt \global\chardef#1=\allocationnumber \wlog{\string#1=\string\insert\the\allocationnumber}} \def\ch@ck#1#2#3% {\ifnum\count1#1<#2\else \errmessage{No room for a new #3} \fi} \newdimen\maxdimen \maxdimen = 16383.99999pt \newskip \hideskip \hideskip = -1000pt plus 1fill \newskip \centering \centering = 0pt plus 1000pt minus 1000pt \newdimen\p@ \p@ = 1pt \newdimen\z@ \z@ = 0pt \newskip \z@skip \z@skip = 0pt plus 0pt minus 0pt \newbox \voidb@x % permanently void box register %D We define \type {\newif} a la plain \TEX, but will %D redefine it later. As Knuth says: %D %D \startnarrower %D And here's a different sort of allocation: for example, %D %D \starttyping %D \newif\iffoo %D \stoptyping %D %D creates \type {\footrue}, \type {\foofalse} to go %D with \type {\iffoo}. %D \stopnarrower \def\newif#1% {\count@\escapechar \escapechar\m@ne \expandafter\expandafter\expandafter\def\@if #1{true}{\let#1\iftrue }% \expandafter\expandafter\expandafter\def\@if#1{false}{\let#1\iffalse}% \@if#1{false}% the condition starts out false \escapechar\count@} \def\@if#1#2% {\csname\expandafter\if@\string#1#2\endcsname} \bgroup % `if' is required \uccode`1=`i \uccode`2=`f \uppercase{\gdef\if@12{}} \egroup %D Build||in numeric variables. \adjdemerits = 10000 \binoppenalty = 700 \brokenpenalty = 100 \clubpenalty = 150 %day = 0 \defaulthyphenchar = `\- \defaultskewchar = -1 \delimiterfactor = 901 \displaywidowpenalty = 50 \doublehyphendemerits = 10000 %endlinechar = `\^^M \errorcontextlines = 5 %escapechar = `\\ \exhyphenpenalty = 50 %fam = 0 \finalhyphendemerits = 5000 %floatingpenalty = 0 %globaldefs = 0 %hangafter = 1 \hbadness = 1000 %holdinginserts = 0 \hyphenpenalty = 50 %interlinepenalty = 0 %language = 0 \lefthyphenmin = 2 \linepenalty = 10 %looseness = 0 %mag = 1000 %maxdeadcycles = 25 %month = 0 \newlinechar = -1 %outputpenalty = 0 %pausing = 0 %postdisplaypenalty = 0 \predisplaypenalty = 10000 \pretolerance = 100 \relpenalty = 500 \righthyphenmin = 3 \showboxbreadth = 5 \showboxdepth = 3 %time = 0 \tolerance = 200 %tracingcommands = 0 \tracinglostchars = 1 %tracingmacros = 0 %tracingonline = 0 %tracingoutput = 0 %tracingpages = 0 %tracingparagraphs = 0 %tracingrestores = 0 %tracingstats = 0 \uchyph = 1 \vbadness = 1000 \widowpenalty = 150 %year = 0 %D Extra numeric variables. \newcount \interdisplaylinepenalty \newcount \interfootnotelinepenalty \interdisplaylinepenalty = 100 \interfootnotelinepenalty = 100 %D Build in dimension variables. \abovedisplayshortskip = 0pt plus 3pt \abovedisplayskip = 12pt plus 3pt minus 9pt %baselineskip = 0pt \belowdisplayshortskip = 7pt plus 3pt minus 4pt \belowdisplayskip = 12pt plus 3pt minus 9pt \boxmaxdepth = \maxdimen \delimitershortfall = 5pt %displayindent = 0pt %displaywidth = 0pt %hangindent = 0pt \hfuzz = 0.1pt %hoffset = 0pt \hsize = 6.5in %leftskip = 0pt %lineskip = 0pt %lineskiplimit = 0pt %mathsurround = 0pt \maxdepth = 4pt \medmuskip = 4mu plus 2mu minus 4mu \nulldelimiterspace = 1.2pt \overfullrule = 5pt \parfillskip = 0pt plus 1fil \parindent = 20pt \parskip = 0pt plus 1pt %predisplaysize = 0pt %rightskip = 0pt \scriptspace = 0.5pt %spaceskip = 0pt \splitmaxdepth = \maxdimen \splittopskip = 10pt %tabskip = 0pt \thickmuskip = 5mu plus 5mu \thinmuskip = 3mu \topskip = 10pt \vfuzz = 0.1pt %voffset = 0pt \vsize = 8.9in %xspaceskip = 0pt %D Extra dimension parameters. \newskip \bigskipamount \newdimen \jot \newskip \medskipamount \newskip \normalbaselineskip \newskip \normallineskip \newdimen \normallineskiplimit \newskip \smallskipamount \bigskipamount = 12pt plus 4pt minus 4pt \jot = 3pt \medskipamount = 6pt plus 2pt minus 2pt \normalbaselineskip = 12pt \normallineskip = 1pt \normallineskiplimit = 0pt \smallskipamount = 3pt plus 1pt minus 1pt %D The following shortcuts are rather standard: \def\lq{`} \def\rq{'} \def\lbrack{[} \def\rbrack{]} \let\endgraf=\par \let\endline=\cr \def\space{ } \def\empty{} \def\null {\hbox{}} %D The next loop construct is about the fastest you can get. %D Beware: this macro does not support nested loops. We use %D a namespace prefix \type {@@pln}. \long\def\loop#1\repeat{\long\def\@@plnbody{#1}\@@plniterate} %D The following makes \type {\loop} \unknown\ \type {\if} %D \unknown\ \type {\repeat} skippable (clever trick): \let\repeat=\fi %D The original (no \type {@@pln} there): \def\@@plniterate{\@@plnbody\let\next\@@plniterate\else\let\next\relax\fi\next} %D A more efficient alternative: \def\@@plniterate{\@@plnbody\expandafter\@@plniterate\else\expandafter\relax\fi} %D An even more efficient one: \def\@@plniterate{\@@plnbody\expandafter\@@plniterate\else\fi} %D Counter 0 is normally used as page counter: \countdef\pageno=0 \pageno=1 % first page is number 1 %D Beside the raw counter \type {\pageno} the \type {\folio} %D macro provides the value. \def\folio{\the\pageno} %D Indeed, we don't define a real output routine yet: \output{\box255} %D We don't support \type {\magnification} and just consume %D the value. \let\magnification\count@ %D The following macro will be overloaded in \ETEX. \def\tracingall {\tracingonline \@ne \tracingcommands \tw@ \tracingstats \tw@ \tracingpages \@ne \tracingoutput \@ne \tracinglostchars \@ne \tracingmacros \tw@ \tracingparagraphs\@ne \tracingrestores \@ne \showboxbreadth \maxdimen \showboxdepth \maxdimen \errorstopmode} %D Some users expect this macro to be present. This one %D sends the hyphenated word to the terminal. \def\showhyphens#1% {\setbox0\vbox {\parfillskip\z@skip \hsize\maxdimen\tenrm \pretolerance\m@ne \tolerance\m@ne \hbadness0 \showboxdepth0 \ #1}} %D The following bunch of macros deals with basic alignment. %D We just include them here so that they can be used if %D needed. Normally, \CONTEXT\ users will fall back on one of %D the three table environments. \newcount \mscount \newif \ifus@ \newif \if@cr \newbox \tabs \newbox \tabsyet \newbox \tabsdone \def\hidewidth % for alignment entries that can stick out {\hskip\hideskip} \def\ialign % initialized \halign {\everycr{} \tabskip\z@skip \halign} \def\multispan#1% {\omit \mscount#1\relax \loop \ifnum\mscount>\@ne \sp@n \repeat} \def\sp@n {\span \omit \advance\mscount\m@ne} \def\cleartabs {\global\setbox\tabsyet\null \setbox\tabs\null} \def\settabs {\setbox\tabs\null \futurelet\next\sett@b} \def\sett@b {\ifx\next\+% \def\nxt{\afterassignment\s@tt@b\let\nxt}% \else \let\nxt\s@tcols \fi \let\next\relax \nxt} \def\s@tt@b% {\let\nxt\relax \us@false\m@ketabbox} \def\tabalign% {\us@true\m@ketabbox} \let\+\tabalign % no outer here \def\s@tcols#1\columns% {\count@#1% \dimen@\hsize \loop \ifnum\count@>\z@ \@nother \repeat} \def\@nother% {\dimen@ii\dimen@ \divide\dimen@ii\count@ \setbox\tabs\hbox{\hbox to\dimen@ii{}\unhbox\tabs}% \advance\dimen@-\dimen@ii \advance\count@\m@ne} \def\m@ketabbox% {\begingroup \global\setbox\tabsyet\copy\tabs \global\setbox\tabsdone\null \def\cr {\@crtrue\crcr\egroup\egroup \ifus@\unvbox\z@\lastbox\fi\endgroup \setbox\tabs\hbox{\unhbox\tabsyet\unhbox\tabsdone}}% \setbox\z@\vbox\bgroup\@crfalse \ialign\bgroup&\t@bbox##\t@bb@x\crcr} \def\t@bbox {\setbox\z@\hbox\bgroup} \def\t@bb@x {\if@cr \egroup % now \box\z@ holds the column \else \hss\egroup \global\setbox\tabsyet\hbox {\unhbox\tabsyet\global\setbox\@ne\lastbox}% now \box\@ne holds its size \ifvoid\@ne \global\setbox\@ne\hbox to\wd\z@{}% \else \setbox\z@\hbox to\wd\@ne{\unhbox\z@}% \fi \global\setbox\tabsdone\hbox{\box\@ne\unhbox\tabsdone}% \fi \box\z@} %D Users are advised not to use the following macros: \def\hang {\hangindent\parindent} \def\textindent#1% {\indent \llap{#1\enspace}% \ignorespaces} \def\narrower% {\advance\leftskip \parindent \advance\rightskip\parindent} %D Useful, used too, but sometimes dangerous: \def\leavevmode{\unhbox\voidb@x} %D We will overload these, but may need them beforehand: \bgroup \catcode`\^^M=\active% \gdef\obeylines{\catcode`\^^M\active \let^^M\par}% \global\let^^M\par% \egroup \def\obeyspaces{\catcode`\ \active} {\obeyspaces\global\let =\space} %D Useful and expected: \def~{\penalty\@M \ } % tie \chardef\%=`\% \chardef\&=`\& \chardef\#=`\# \chardef\$=`\$ \def\_{\leavevmode \kern.06em \vbox{\hrule width.3em}} %D Used at all? \def\slash{/\penalty\exhyphenpenalty} % a `/' that acts like a `-' %D Replaced later on: \def\line {\hbox to\hsize} \def\leftline #1{\line{#1\hss}} \def\rightline #1{\line{\hss#1}} \def\centerline#1{\line{\hss#1\hss}} %D These are used by TaBlE: \newif\ifh@ \newif\ifv@ %D Let's end in the plain way: \def\fmtname {ConTeXt Minimized Plain TeX} \def\fmtversion{3.1415926} \protect \endinput