summaryrefslogtreecommitdiff
path: root/macros/generic/basix/basix.tex
diff options
context:
space:
mode:
Diffstat (limited to 'macros/generic/basix/basix.tex')
-rw-r--r--macros/generic/basix/basix.tex474
1 files changed, 474 insertions, 0 deletions
diff --git a/macros/generic/basix/basix.tex b/macros/generic/basix/basix.tex
new file mode 100644
index 0000000000..1592ff5853
--- /dev/null
+++ b/macros/generic/basix/basix.tex
@@ -0,0 +1,474 @@
+%
+% BaSiX (with the emphasis on SICK!) by Andrew Marc Greene
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Andrew's Affiliations
+%
+% Copyright (C) 1990 by Andrew Marc Greene
+% <amgreene@mit.edu>
+% MIT Project Athena
+% Student Information Processing Board
+% All rights reserved.
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% BaSiX's Beginnings
+%
+\def\flageol{\catcode13=13}
+\def\endflageol{\catcode13=5}
+\def\struncat{\catcode`\$=12}
+\def\strcat{\catcode`\$=11}
+\flageol\let\eol
+\endflageol
+\newif\ifresult
+%\newcount\xa\newcount\xb
+\def\iw{\immediate\write16}
+\def\empty{}
+\def\gobble#1{}
+\def\spc{ }
+\def\itstrue{tt}
+\def\itsfalse{tf}
+\def\isnull#1{\resultfalse
+\expandafter\ifx\csname empty#1\endcsname\empty\resulttrue\fi}
+\newcount\matha\newcount\mathb
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Character-string Calls
+%
+\newcount\strtmp
+\def\ascii#1{\strtmp`#1}
+\def\chr#1{\begingroup\uccode65=#1\uppercase{\gdef\tmp{A}}\endgroup}
+\def\strlen#1{\strtmp-2% don't count " " \iw tokens
+ \expandafter\if\stringP #1\let\next\strIter\strIter #1\iw\fi}
+\def\strIter#1{\ifx\iw#1\let\next\relax\else\advance\strtmp by 1\relax
+ \fi\next}
+\def\Flen{\expandafter\strlen\expandafter{\Pa}\return{\number\strtmp}}
+\strcat
+\def\F$chr${\expandafter\chr\expandafter{\Pa}\return{\tmp}}
+\struncat
+% first char only:
+% \def\Fasc{\expandafter\asc\expandafter{\Pa}\return{\number\strtmp}}
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Debugging Definitions
+%
+\def\debug{\tracingmacros=2}
+\def\diw#1{}
+\def\Cdebug{\let\diw\iw\tracingmacros=2 \endeval}
+\def\Cnodebug{\def\diw##1{}\endeval}
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Expression Evaluation
+%
+\def\expression{\let\afterexpression\afterscan\math}
+%
+% (math is a misnomer and should -> expr)
+%
+\newcount\parens\newcount\mathParams
+\def\math{\parens=0\mathParams96\mathInit\matheval}
+\def\mathRecurse{\advance\parens by 1\relax\mathParams96\mathInit\matheval}
+\def\mathInit{\begingroup
+ \let\mathAcc\empty
+ \let\mathOpRel\empty
+ \let\mathOpAdd\empty
+ \let\mathOpMul\empty
+ \let\mathlhRef\empty}
+%
+\def\matheval{\after\mathbranch\scan}
+%
+\def\mathbranch{\diw{EXPRESS:\expandafter\noexpand\word:}
+\let\next\matherr
+\ifx\empty\word\let\next\mathHardEnd\else % Expr. end?
+\expandafter\if\numberP\word\let\next\mathLiteral\diw{@@}\fi % Number?
+\expandafter\if\stringP\word\let\next\mathLiteral\fi % String literal?
+\expandafter\if\identifierP\word\let\next\mathIdentifier\fi % Identifier?
+\expandafter\if\stringvarP\word\let\next\mathIdentifier\fi % :-(
+\expandafter\if\macroP\word\let\next\mathMacro\fi % Macro?
+\ifx\word\Oleft\let\next\mathRecurse\fi % Open paren?
+\ifx\word\Oright\let\next\mathEndRecurse\fi % Close paren?
+\ifx\word\Ocomma\let\next\mathComma\fi % Comma?
+%
+% Operator?
+%
+\ifx\word\Oplus\let\next\mathOp\diw{!+}\fi
+\ifx\word\Ominus\let\next\mathOp\diw{!-}\fi
+\ifx\word\Otimes\let\next\mathOp\diw{!*}\fi
+\ifx\word\Odiv\let\next\mathOp\diw{!/}\fi
+\ifx\word\Olt\let\next\mathOp\diw{!<}\fi
+\ifx\word\Oeq\let\next\mathOp\diw{!=}\fi
+\ifx\word\Ogt\let\next\mathOp\diw{!>}\fi
+%
+\fi\next}
+%
+\def\Oleft{(}\def\Oright{)}\def\Ocomma{,}
+\def\Oplus{+}\def\Ominus{-}\def\Otimes{*}\def\Odiv{/}
+\def\Olt{<}\def\Oeq{=}\def\Ogt{>}
+%
+% There's got to be a better way to do the above....
+%
+\def\mathLiteral{\diw{MLIT}\ifx\empty\mathAcc\diw{ACCUMUL:\word:}
+\expandafter\def\expandafter\mathAcc\expandafter
+{\expandafter\expandafter\expandafter\empty\word}
+\else
+\diw{ACC has :\mathAcc: and word is :\word:}
+\errmessage{Syntax Error: Two values with no operator}\fi\matheval}
+%
+% Operator stuff: (Need to add string support / error checking)
+%
+\def\mathAdd{\advance\matha by \mathb}
+\def\mathSub{\advance\matha by -\mathb}
+\def\mathMul{\multiply\matha by \mathb}
+\def\mathDiv{\divide\matha by \mathb}
+\def\mathEQ{\ifnum\matha=\mathb\matha-1\else\matha0\fi}
+\def\mathGT{\ifnum\matha>\mathb\matha-1\else\matha0\fi}
+\def\mathLT{\ifnum\matha<\mathb\matha-1\else\matha0\fi}
+%
+\def\mathFlushRel{\mathFlushAdd\ifx\empty\mathOpRel\else
+ \matha=\mathlhRel\relax\mathb=\mathAcc\relax\mathOpRel
+ \edef\mathAcc{\number\matha}\let\mathOpRel\empty\fi}
+%
+\def\mathFlushAdd{\mathFlushMul\ifx\empty\mathOpAdd\else
+ \matha=\mathlhAdd\relax\mathb=\mathAcc\relax\mathOpAdd
+ \edef\mathAcc{\number\matha}\let\mathOpAdd\empty\fi}
+%
+\def\mathFlushMul{\mathFlushRef\ifx\empty\mathOpMul\else
+ \matha=\mathlhMul\relax\mathb=\mathAcc\relax\mathOpMul
+ \edef\mathAcc{\number\matha}\let\mathOpMul\empty\fi}
+%
+\def\mathFlushRef{\ifx\empty\mathlhRef\else
+ \mathParam
+ \mathlhRef\let\mathlhRef\empty\fi}
+%
+\def\mathOp{%
+\if\word+
+ \mathFlushAdd\let\mathlhAdd\mathAcc\let\mathOpAdd\mathAdd\fi
+\if\word-
+ \mathFlushAdd\let\mathlhAdd\mathAcc\let\mathOpAdd\mathSub\fi
+\if\word*
+ \mathFlushMul\let\mathlhMul\mathAcc\let\mathOpMul\mathMul\fi
+\if\word/
+ \mathFlushMul\let\mathlhMul\mathAcc\let\mathOpMul\mathDiv\fi
+\if\word=
+ \mathFlushRel\let\mathlhRel\mathAcc\let\mathOpRel\mathEQ\fi
+\if\word>
+ \mathFlushRel\let\mathlhRel\mathAcc\let\mathOpRel\mathGT\fi
+\if\word<
+ \mathFlushRel\let\mathlhRel\mathAcc\let\mathOpRel\mathLT\fi
+\let\mathAcc\empty
+\matheval}
+%
+\def\mathIdentifier{%
+\expandafter\ifx\csname C\word\endcsname\relax
+\expandafter\ifx\csname F\word\endcsname\relax
+\expandafter\ifx\csname V\word\endcsname\relax
+\let\next\matherr\diw{LOSING:\word:}
+\else\let\next\mathVariable\fi
+\else\let\next\mathFunction\fi
+\else\let\next\mathCommand\fi\next}
+%
+\def\mathVariable{\expandafter\edef\expandafter\word\expandafter
+{\csname V\word\endcsname}\mathbranch}
+\def\mathCommand{\expandafter\mathHardEnd\word}
+\def\mathFunction{\expandafter\let\expandafter\mathlhRef
+\csname F\word\endcsname\matheval}
+%
+\def\mathParam{\advance\mathParams by 1\relax\chr\mathParams
+ \diw{PARAM:\tmp:\mathAcc:}
+ \expandafter\edef\csname P\tmp\endcsname{\mathAcc}}
+\def\mathComma{\mathEnd\mathParam\mathInit\matheval}
+\def\mathEndRecurse{\mathEnd\advance\parens by -1\matheval}
+\def\mathEnd{\diw{MATHEND: ACC=\mathAcc:}\mathFlushRel
+ \xdef\mathtemp{\mathAcc}\endgroup\edef\mathAcc{\mathtemp}}
+\def\mathHardEnd{\ifnum\parens>0\errmessage{Insufficient closeparens.}\relax
+ \let\next\endeval\else\let\next\mathFinal\fi\next}
+\def\mathFinal{\mathEnd\let\value\mathAcc\endexpression}
+\def\matherr{\errmessage{Syntax error: Unknown symbol \word}}
+\def\endexpression{\afterexpression}
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Linked List
+%
+\def\gotofirstline{\edef\lpointer{\csname L0\endcsname}}
+\def\foreachline#1{\ifnum\lpointer<99999\edef\word{\lpointer}#1%
+\edef\lpointer{\csname L\word\endcsname}\foreachline{#1}\fi}
+%
+% gotopast{#1} where #1 is a line number, will set \lpointer to
+% the least value such that L(lpointer)>#1
+%
+\def\gotopast#1{\def\lpointer{0}\def\target{#1}\gotopastloop}
+%
+\def\gotopastloop{\edef\tmp{\csname L\lpointer\endcsname}%
+\ifnum\tmp<\target%
+\edef\lpointer{\csname L\lpointer\endcsname}%
+\let\next=\gotopastloop\else\let\next=\relax\fi
+\next}
+%
+\flageol\def\addLineToLinkedList#1#2
+{\def#1{#2}\diw{Just stored #2 in \noexpand #1}%
+% now put it into linked list...
+\expandafter\ifx\csname L\word\endcsname\relax% if it isn't already there,
+\gotopast{\word}% \def\lpointer{what-should-point-to-word}
+\expandafter\edef\csname L\word\endcsname{\csname L\lpointer\endcsname}%
+\expandafter\edef\csname L\lpointer\endcsname{\word}%
+\fi\endeval
+}\endflageol
+\expandafter\def\csname L0\endcsname{99999}
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Program Parser
+%
+\def\evalline{%\iw{EVALLINE :\word:}%
+\csname C\word\endcsname} %error-checking? :-)
+\def\evalerror{\errmessage{Unkonwn command. Sorry.}}
+%
+% \mandatory takes one argument and checks to see if the next
+% non-whitespace token matches it. If not, an error is generated.
+%
+\def\mandatory#1{\def\tmp{#1}\mandatest}
+\def\mandatest#1{\def\tmpp{#1}\ifx\tmp\tmpp\let\next\afterscan\else
+\let\next\manderror\fi\next}
+\def\manderror{\errmessage{\tmpp\spc read when \tmp\spc expected.}%
+\afterscan}
+%
+% \parseline gets the first WORD of the next line. If it's a line
+% number, \scanandstoreline is called; otherwise the line is executed.
+%
+\def\parseline{\after\firsttest\scan}
+\def\firsttest{\expandafter\if\numberP\word
+\let\next\grabandstoreline\else\let\next\evalline\fi\next}
+\def\grabandstoreline{\diw{Grabbing line \word.}%
+\expandafter\addLineToLinkedList\csname/\word\endcsname}
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Syntactic Scanner
+%
+% The \scan routine reads the next WORD and then calls \afterscan.
+%
+% As syntactic sugar, one can write \after\foo to set \afterscan to
+% \foo.
+%
+% Here are the rules governing WORD. Initial whitespace is
+% discarded. The word is the next single character, unless that
+% character is one of the following:
+%
+% A-Z or a-z: [A-Z,a-z][A-Z,a-z,0-9]*\$?
+% 0-9: [0-9]+
+% ": "[^"]*"
+% <,=,>: [<=>][<=>]? (one or two; not the same if two)
+%
+% Note that the string literal ignores spaces but may be abnormally
+% terminated by an end-of-line. (I wasn't sure how to express that
+% as a regexp).
+%
+%
+\newif\ifscan % shall we continue scanning?
+%
+\def\scan{\def\word{}\futurelet\q\scanFirst}
+%
+\def\scanFirst{% Checks the first character to determine type.
+\let\next\scanIter
+\expandafter\if\spc\noexpand\q % Space -- ignore it
+ \let\next\scanSpace\else
+\if\eol\noexpand\q % End of line -- no word here
+ \let\next\scanEnd\else
+\ifcat A\noexpand\q % Then we have an identifier
+ \let\scanTest\scanIdentifier\else
+\expandafter\if\digit\q
+ \let\scanTest\scanNumericConstant\else
+\if"\noexpand\q
+ \let\scanTest\scanStringConstant\else
+\expandafter\if\relationP\q
+ \let\scanTest\scanRelation
+\else
+ \let\scanTest\scanfalse
+\fi\fi\fi\fi\fi\fi\next}
+%
+\def\scanIter#1{\expandafter\def\expandafter\word\expandafter{\word #1}
+ \futurelet\q\scanContinueP}
+\def\scanContinueP{\scanTest\ifscan\let\next\scanIter
+ \else\let\next\scanEnd\fi\next}
+%
+\def\scanSpace#1{\scan}% If the first char is a space, gobble it and try again.
+\def\scanIdentifier{\ifcat A\noexpand\q\scantrue\else
+\expandafter\if\digit\q\scantrue
+\else\if$\noexpand\q\scantrue
+ \expandafter\def\expandafter\word\expandafter{\expandafter$\word}
+ \let\scanTest\scanfalse\else
+\scanfalse\fi\fi\fi}
+\def\scanEndString{\scanfalse}
+\def\scanNumericConstant{\expandafter\if\digit\q\scantrue\else\scanfalse\fi}
+\def\scanStringConstant{\scantrue\if"\q\let\scanTest\scanfalse\fi}
+\def\scanRelation{\if<\q\scantrue\else\if>\q\scantrue\else\if=\q\scantrue
+\else\scanfalse\fi\fi\fi}
+%
+\def\scanEnd#1{\relax\diw{SCANNED:\word:}
+\afterscan #1}% dumps trailing spaces.
+\def\after{\let\afterscan}%
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Type Tests (Predicates for type determination)
+%
+\def\relationP#1{tf} % for now, only single-char relations
+\def\identifierP#1{\expandafter\identifierTest #1\\}
+\def\identifierTest#1#2\\{\ifcat A#1\itstrue\else\itsfalse\fi}
+\def\stringvarP#1{\expandafter\stringvarTest #1\\}
+\def\stringvarTest#1#2\\{\if$#1\itstrue\else\itsfalse\fi}
+\def\stringP#1{\expandafter\stringTest #1\\}
+\def\stringTest#1#2\\{\if #1"\itstrue\else\itsfalse\fi}
+\def\numberP#1{\expandafter\numberTest #1\\}
+\def\numberTest#1#2\\{\expandafter\if\digit #1\itstrue\else\itsfalse\fi}
+\def\macroP#1{\expandafter\macroTest #1\\}
+\def\macroTest#1#2\\{\expandafter\ifx #1\relax\itstrue\else\itsfalse\fi}
+%
+% \digit tests its single-token argument and returns tt if true,
+% tf otherwise.
+%
+%
+\def\digit#1{%
+\if0\noexpand#1\itstrue\else
+\if1\noexpand#1\itstrue\else
+\if2\noexpand#1\itstrue\else
+\if3\noexpand#1\itstrue\else
+\if4\noexpand#1\itstrue\else
+\if5\noexpand#1\itstrue\else
+\if6\noexpand#1\itstrue\else
+\if7\noexpand#1\itstrue\else
+\if8\noexpand#1\itstrue\else
+\if9\noexpand#1\itstrue\else\itsfalse
+\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi
+% 9 8 7 6 5 4 3 2 1 0
+}
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% User Utilities. These are the commands that are called by the
+% user. We could really use a better section name. :-)
+%
+% List (one line or all lines, for now)
+%
+\def\Clist{\after\listmain\scan}
+\def\listmain{\isnull{\word}\ifresult\let\next\listalllines
+\else\let\next\listoneline\fi\next}
+\def\listline{\iw{\word\spc\csname/\word\endcsname}}
+\def\listalllines{\gotofirstline\foreachline{\listline}\endeval}
+\def\listoneline{\listline\endeval}
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Different degrees of ``stop execution''
+%
+\def\Csystem{\end} % exits to the system
+\def\Cexit{}% \endflageol} % exits to TeX
+\flageol%
+\def\Cstop#1
+{\iw{Stopped in \lineno.}\cleanstop}%
+\def\cleanstop{\diw{CLEANSTOP}\let\endeval\enduserline\endeval
+}\endflageol
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% The command ``rem'' introduces a remark
+%
+\def\Crem{\endeval}%
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% The ``let'' command allows variable assignments
+%
+\def\Clet{\after\letgetequals\scan}
+\def\letgetequals{\after\letgetvalue\mandatory{=}}
+\def\letgetvalue{\after\letdoit\expression}
+\def\letdoit{\expandafter\edef\csname V\word\endcsname{\value}%
+\endeval}
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% The ``print'' command takes a [list of] expression[s] and displays
+% it [them].
+%
+\def\Cprint{\after\printit\expression}
+\def\printit{\iw{\value}\endeval}
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% The ``if'' command takes an expression, the word ``then,'' and
+% another command. If the expression is non-zero, the command is
+% executed; otherwise it is ignored.
+%
+\def\Cif{\after\getift\expression}
+\def\Cthen{\errmessage{Syntax error: THEN without IF}}
+\def\getift{\after\getifh\mandatory t}
+\def\getifh{\after\getife\mandatory h}
+\def\getife{\after\getifn\mandatory e}
+\def\getifn{\after\consequent\mandatory n}
+\def\consequent{\ifnum\value=0\let\next=\endeval\else\let\next=\evalconsq\fi
+\next}
+\def\evalconsq{\after\evalline\scan}
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Functions
+%
+% Functions may read the counter \mathParams to find out the number
+% of the top parameter. Parameters are in Pa Pb Pc etc.
+%
+\def\return{\expandafter\def\expandafter\mathAcc\expandafter}
+%
+\def\Finc{\matha=\Pa \advance\matha by 1
+\return{\number\matha}}
+%
+\def\Fmin{\ifnum\Pa<\Pb\return{\Pa}\else\return{\Pb}\fi}
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Program execution control
+%
+\def\Crun{\let\endeval\endincrline\def\lineno{0}\endeval}
+\def\Cgoto{\let\endeval\endgotoline\after\gotomain\scan}
+\def\gotomain{\edef\lineno{\word}\endeval}
+%
+\flageol%
+\def\execline{%\message{Executing line \lineno...}%
+\edef\theline{\csname/\lineno\endcsname}%
+%\message{THE LINE\theline}%
+\let\endeval\endincrline\after\evalline\expandafter\scan\theline
+}\endflageol
+%
+% Different varieties of what to do at the end of a command:
+%
+% get new line from user (enduserline)
+% get next line in order (endincrline)
+% get line in \lineno (endgotoline)
+% keep parsing current line (endcolonline tbi)
+%
+\flageol%
+\def\endincrline#1
+{\diw{ENDINCRLINE}\edef\lineno{\csname L\lineno\endcsname}\execnextline}
+%
+\def\endgotoline#1
+{\diw{ENDGOTOLINE}\let\endeval\execincrline\execnextline}%
+%
+\def\execnextline{\diw{Ready to execute line \lineno...}%
+\ifnum\lineno<99999\let\next\execline\else\let\next\cleanstop\fi\next}%
+%
+\def\enduserline #1
+{\diw{ENDUSERLINE}\parseline}\endflageol
+%
+\let\endeval\enduserline
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Start your engines!
+%
+\iw{This is BaSiX, v0.3, emphasis on the SICK! by amgreene@mit.edu}
+\flageol
+\catcode32=12
+\endeval