%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 <return> = control <space>
\def\^^I{\   } % same for <tab>

%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 will 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          \bigskipamount       = 12pt plus 4pt minus 4pt
\newskip  \medskipamount          \medskipamount       =  6pt plus 2pt minus 2pt
\newskip  \smallskipamount        \smallskipamount     =  3pt plus 1pt minus 1pt

\newskip  \normalbaselineskip     \normalbaselineskip  = 12pt
\newskip  \normallineskip         \normallineskip      =  1pt
\newdimen \normallineskiplimit    \normallineskiplimit =  0pt

\newdimen \jot                    \jot                 =  3pt

%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):
%D
%D \starttyping
%D \def\@@plniterate{\@@plnbody\let\next\@@plniterate\else\let\next\relax\fi\next}
%D \stoptyping
%D
%D A more efficient alternative:
%D
%D \starttyping
%D \def\@@plniterate{\@@plnbody\expandafter\@@plniterate\else\expandafter\relax\fi}
%D \stoptyping
%D
%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}

% begin of tab code

\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@}

% end to tab code

%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}}
\def\_{\dontleavehmode \kern.06em \vbox{\hrule width.3em}}

%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 Let's end in the plain way:

\ifx\fmtname   \undefined \def\fmtname   {ConTeXt Minimized Plain TeX} \fi
\ifx\fmtversion\undefined \def\fmtversion{3.1415926}                   \fi

\protect \endinput
