basic more docs

This commit is contained in:
minjaesong
2020-12-17 11:24:44 +09:00
parent bb6d359491
commit fcc356439c
10 changed files with 254 additions and 56 deletions

View File

@@ -1678,31 +1678,34 @@ line =
linenumber = digits ;
stmt =
"IF" , expr_sans_asgn , "THEN" , stmt , ["ELSE" , stmt]
| "FOR" , expr
"REM" , ? anything ?
| "IF" , expr_sans_asgn , "THEN" , stmt , ["ELSE" , stmt]
| "DEFUN" , [ident] , "(" , [ident , {" , " , ident}] , ")" , "=" , expr
| "ON" , expr_sans_asgn , ("GOTO" | "GOSUB") , expr_sans_asgn , {"," , expr_sans_asgn}
| "(" , stmt , ")"
| expr ; (* if the statement is 'lit' and contains only one word, treat it as function_call e.g. NEXT for FOR loop *)
expr = (* this basically blocks some funny attemps such as using DEFUN as anon function because everything is global in BASIC *)
| expr ; (* if the statement is 'lit' and contains only one word, treat it as function_call
e.g. NEXT for FOR loop *)
expr = (* this basically blocks some funny attemps such as using DEFUN as anon function
because everything is global in BASIC *)
lit
| "(" , expr , ")"
| "IF" , expr_sans_asgn , "THEN" , expr , ["ELSE" , expr]
| kywd , expr - "(" (* also deals with FOR statement *)
(* at this point, if OP is found in paren-level 0, skip function_call *)
| function_call
| expr , op , expr
| op_uni , expr ;
expr_sans_asgn = ? identical to expr except errors out whenever "=" is found ? ;
function_call =
ident , "(" , [expr , {argsep , expr} , [argsep]] , ")"
| ident , expr , {argsep , expr} , [argsep] ;
(* don't bother looking at these, because you already know the stuff *)
kywd = ? words that exists on the list of predefined function that are not operators ? ;
(* don't bother looking at these, because you already know the stuff *)
argsep = "," | ";" ;
ident = alph , [digits] ; (* variable and function names *)
lit = alph , [digits] | num | string ; (* ident + numbers and string literals *)
@@ -1716,26 +1719,22 @@ digits = digit | digit , digits ;
hexdigits = hexdigit | hexdigit , hexdigits ;
bindigits = bindigit | bindigit , bindigits ;
num = digits | digits , "." , [digits] | "." , digits
| ("0x"|"0X") , hexdigits
| ("0x"|"0X") , hexdigits
| ("0b"|"0B") , bindigits ; (* sorry, no e-notation! *)
visible = ? ASCII 0x20 to 0x7E ? ;
string = '"' , (visible | visible , stringlit) , '"' ;
letter = "A" | "B" | "C" | "D" | "E" | "F" | "G"
| "H" | "I" | "J" | "K" | "L" | "M" | "N"
| "O" | "P" | "Q" | "R" | "S" | "T" | "U"
| "V" | "W" | "X" | "Y" | "Z" | "a" | "b"
| "c" | "d" | "e" | "f" | "g" | "h" | "i"
| "j" | "k" | "l" | "m" | "n" | "o" | "p"
| "q" | "r" | "s" | "t" | "u" | "v" | "w"
| "x" | "y" | "z" | "_" ;
letter = "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J" | "K" | "L" | "M" | "N"
| "O" | "P" | "Q" | "R" | "S" | "T" | "U" | "V" | "W" | "X" | "Y" | "Z" | "a" | "b"
| "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" | "k" | "l" | "m" | "n" | "o" | "p"
| "q" | "r" | "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z" | "_" ;
digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ;
hexdigit = "A" | "B" | "C" | "D" | "E" | "F" | "a" | "b"
| "c" | "d" | "e" | "f" | "0" | "1" | "2" | "3" | "4" | "5" | "6"
| "7" | "8" | "9" ;
hexdigit = "A" | "B" | "C" | "D" | "E" | "F" | "a" | "b" | "c" | "d" | "e" | "f" | "0" | "1"
| "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ;
bindigit = "0" | "1" ;
(* all possible token states: lit num op bool qot paren sep *)
(* below are schematic of trees generated after parsing the statements *)
IF (type: function, value: IF)
1. cond

View File

@@ -2,17 +2,16 @@ This chapter describes the basic concepts of the language.
\section{Values and Types}
\label{valuesandtypes}
BASIC is a \emph{Dynamically Typed Language}, which means variables do not know which group they should barge in; only values of the variable do. In fact, there is no type definition in the language: We do want our variables to feel themselves awkward.
BASIC is a \emph{Dynamically Typed Language}, which means variables do not know which group they should barge in; only values of the variable do. In fact, there is no type definition in the language: \emph{we do want our variables to feel themselves awkward.}
There are five basic types: \emph{undefined}, \emph{boolean}, \emph{number}, \emph{string}, \emph{array}, \emph{generator} and \emph{function}.
\emph{Undefined} is the type of the literal value \textbf{undefined}, who likes to possess nothing (I think he's secretly a buddhist).
\emph{Boolean} is the type of the values that is either \textbf{TRUE} or \textbf{FALSE}, he knows no in-between. \textbf{undefined}, \emph{number 0} and \textbf{FALSE} makes condition \emph{false}.
There are six basic types: \emph{number}, \emph{boolean}, \emph{string}, \emph{array}, \emph{generator} and \emph{function}.
\emph{Number} represents real (double-precision floating-point or \emph{actually rational}) numbers. Operations on numbers follow the same rules of the underlying virtual machine\footnote{if you are not a computer person, just disregard}, and such machines must follow the IEEE 754 standard\footnote{ditto.}.
\emph{Boolean} is the type of the values that is either \textbf{TRUE} or \textbf{FALSE}. \textbf{number 0} and \textbf{FALSE} makes condition \emph{false}. When used in numeric context, \textbf{FALSE} will be interpreted as 0 and \textbf{TRUE} as 1.
\emph{String} represents immutable\footnote{cannot be altered directly} sequences of bytes. However, you can't weave them to make something like \emph{string array}\footnote{future feature\ldots maybe\ldots? Probably not\ldots}.
\emph{Array} represents collection of numbers in 1-- or more dimensions.

View File

@@ -0,0 +1 @@
Builtin functions

View File

@@ -0,0 +1 @@
Keycodes follow LWJGL2 lol

View File

@@ -1,4 +1,4 @@
\tbas{} is a BASIC dialect and its interpreter. \tbas emulates most of the common BASIC syntax while adds more advanced and up-to-date concepts gracefully, such as user-defined function that can \emph{actually} recurse, arbitrary list construction using CONS-operator and some of the features on functional programming such as \code{MAP} and \code{FOLD}.
\tbas{} is a BASIC dialect and its interpreter. \tbas{} emulates most of the common BASIC syntax while adds more advanced and up-to-date concepts gracefully, such as user-defined function that can \emph{actually} recurse, arbitrary list construction using CONS-operator and some of the features in the realm of functional programming such as \code{MAP} and \code{FOLD}.
This is the documentation for \tbas{} \tbasver{}.

View File

@@ -0,0 +1,9 @@
\begin{verbatim}
10 REM TERRAN BASIC
20 REM REFERENCE MANUAL
30 REM For Version 1.0
40 REM First Edition
100 PRINT "Hello, world!"
110 PRINT "Git gud!"
999 END
\end{verbatim}

View File

@@ -1,12 +1,13 @@
This chapter descibes the \tbas{} language.
\newcommand{\intrange}{\hl{[$0..2^{53}-1$]}}
This chapter describes the \tbas{} language.
\section{Metasyntax}
In the descriptions of BASIC syntax, this conventions apply.
\\
In the descriptions of BASIC syntax, these conventions apply.
\begin{itemize}
\item \codebf{"VERBATIM"} --- Type exactly as shown
\item \codebf{VERBATIM} --- Type exactly as shown
\item \code{IDENTIFIER} --- Replace \emph{identifier} with appropriate metavariable
\item \code{[a]} --- Words within square brackets are optional
\item \code{\{a|b\}} --- Choose either \code{a} or \code{b}
@@ -14,7 +15,179 @@ In the descriptions of BASIC syntax, this conventions apply.
\item \code{a...} --- The preceding entity can be repeated
\end{itemize}
\section{Definitions}
A \emph{Program Line} consists of a line number followed by a \emph{Statements}. Program Lines are terminated by a line break or by the end-of-the-file.
A \emph{Line Number} is an integer within the range of \intrange{}.
A \emph{Statements} consists of 1 statement or more, separated by colons:
\codeline{STATEMENT [: STATEMENT]...}
An \emph{Expression} takes one of the following forms:
\codeline{VARIABLE\_OR\_FUNCTION}\\
\codeline{( EXPRESSION )}\\
\codeline{\textbf{IF} EXPRESSION \textbf{THEN} EXPRESSION [\textbf{ELSE} EXPRESSION]}\\
\codeline{FUNCTION \textbf{(} [EXPRESSION \{\textbf{,}|\textbf{;}\} [\{\textbf{,}|\textbf{;}\}]] \textbf{)}}\\
\codeline{FUNCTION [EXPRESSION \{\textbf{,}|\textbf{;}\} [\{\textbf{,}|\textbf{;}\}]]}\\
\codeline{EXPRESSION BINARY\_OPERATOR EXPRESSION}\\
\codeline{UNARY\_OPERATOR EXPRESSION}
An \emph{Array} takes following form:
\codeline{ARRAY\_NAME \textbf{(} EXPRESSION [\textbf{,} EXPRESSION]... \textbf{)}}
\section{Literals}
\subsection{String Literals}
String literals take the following form:
\codeline{\textbf{"} [CHARACTERS] \textbf{"}}
where \code{CHARACTERS} is a 0 or more repetition of ASCII-printable letters.\footnote{In other words, \code{0x20..0x7E}}
To print out graphical letters outside of ASCII-printable, use string concatenation with \code{CHR} function, or use \code{EMIT} function.
\subsection{Numeric Literals}
Numeric literals take one of the following forms:
\codeline{[\textbf{+}|\textbf{-}][\textbf{0}|\textbf{1}|\textbf{2}|\textbf{3}|\textbf{4}|\textbf{5}|\textbf{6}|\textbf{7}|\textbf{8}|\textbf{9}]... [\textbf{.}][\textbf{0}|\textbf{1}|\textbf{2}|\textbf{3}|\textbf{4}|\textbf{5}|\textbf{6}|\textbf{7}|\textbf{8}|\textbf{9}]...}\\
\codeline{\textbf{0}\{\textbf{x}|\textbf{X}\}[\textbf{0}|\textbf{1}|\textbf{2}|\textbf{3}|\textbf{4}|\textbf{5}|\textbf{6}|\textbf{7}|\textbf{8}|\textbf{9}]...}\\
\codeline{\textbf{0}\{\textbf{b}|\textbf{B}\}[\textbf{0}|\textbf{1}|\textbf{2}|\textbf{3}|\textbf{4}|\textbf{5}|\textbf{6}|\textbf{7}|\textbf{8}|\textbf{9}]...}
Hexadecimal and binary literals are always interpreted as \emph{unsigned} integers. They must range between \intrange{}.
\subsection{Variables}
Variable names must start with a letter and all characters of the name must be letters \code{A-Z}, figures \code{0-9}. Variable names must not be identical to reserved words, but may \emph{contain} one. Variable names are case-insensitive.
Unlike conventional BASIC dialects (especially GW-BASIC), name pool of variables are shared between all the types. For example, if you have a numeric variable \code{A}, and define an array named \code{A} later in the program, the new array will overwrite your numeric \code{A}.
Furthermore, \emph{sigils} are not used in the \tbas{} and attempting to use one will raise syntax-error or undefined behaviour.
\subsection{Types}
Types of data recognised by \tbas{} are distinguished by some arcane magic of Javascript auto-casing mumbo-jumbo
\begin{tabulary}{\textwidth}{RCL}
Type & Range & Precision \\
\hline \hline
String & As many as the machine can handle & \, \\
\hline
Integer & $ \pm 2^{53}-1 $ & exact within the range \\
\hline
Float & $ \pm 4.9406564584124654 \times 10^{-324} $ -- $ \pm 1.7976931348623157 \times 10^{308} $ & about 16 significant figures \\
\end{tabulary}
\section{Operators}
\subsection{Order of Precedence}
The order of precedence of the operators is as shown below, lower numbers means they have higher precedence (more tightly bound)
\begin{tabulary}{\textwidth}{CCC|CCC}
Precedence & Operators & Associativity & Precedence & Operators & Associativity \\
\hline
1 & \basicexp & Right & 10 & \condensedfont{BAND} & Left \\
2 & \ast \quad $/$ \quad $\backslash$ & Left & 11 & \condensedfont{BXOR} & Left \\
3 & \condensedfont{MOD} & Left & 12 & \condensedfont{BOR} & Left \\
4 & $+$ \quad $-$ & Left & 13 & \condensedfont{AND} & Left \\
5 & \condensedfont{NOT} \enskip \condensedfont{BNOT} & Left & 14 & \condensedfont{OR} & Left \\
6 & <\!< \quad >\!> & Left & 15 & \condensedfont{TO} \enskip \condensedfont{STEP} & Left \\
7 & < \enskip > \enskip <\!= \enskip =\!< \enskip >\!= \enskip =\!> & Left & 16 & ! & Right \\
8 & == \quad <\!> \quad >\!< & Left & 17 & \sim & Left\\
9 & \condensedfont{MIN} \enskip \condensedfont{MAX} & Left & 18 & \# & Left \\
& & & 19 & = & Right \\
\end{tabulary}
\subsubsection*{Examples}
\begin{itemize}
\item Exponentiation is more tightly bound than negation: \code{-1\basicexp 2 == -(1\basicexp 2) == -1} but \code{(-1)\basicexp 2 == 1}
\item Exponentiation is right-associative: \code{4\basicexp 3\basicexp 2 == 4\basicexp (3\basicexp 2) == 262144}. This behaviour is \emph{different} from GW-BASIC in which its exponentiation is left-associative.
\end{itemize}
\subsection{Mathematical Operators}
Mathematical operators operate on expressions that returns numeric value only, except for the \code{+} operator which will take the action of string concatenation if either of the operand is non-numeric.
\begin{tabulary}{\textwidth}{CLL}
Code & Operation & Result \\
\hline
\emph{x} $\basicexp$ \emph{y} & Exponentiation & \emph{x} raised to the \emph{y}th power \\
\emph{x} $\ast$ \emph{y} & Multiplication & Product of \emph{x} and \emph{y} \\
\emph{x} $/$ \emph{y} & Division & Quotient of \emph{x} and \emph{y} \\
\emph{x} $\backslash$ \emph{y} & Truncated Division & Integer quotient of \emph{x} and \emph{y} \\
\emph{x} \condensedfont{MOD} \emph{y} & Modulo & Integer remainder of \emph{x} and \emph{y} with sign of \emph{x} \\
\emph{x} $+$ \emph{y} & Addition & Sum of \emph{x} and \emph{y} \\
\emph{x} $-$ \emph{y} & Subtraction & Difference of \emph{x} and \emph{y} \\
$+$ \emph{x} & Unary Plus & Value of \emph{x} \\
$-$ \emph{x} & Unary Minus & Negative value of \emph{x} \\
\end{tabulary}
\subsubsection*{Notes}
\begin{itemize}
\item Type conversion rule follows underlying Javascript implementation. In other words, \emph{only the god knows.}
\item The expression \code{0\basicexp 0} will return \code{1}, even though the expression is indeterminant.
\end{itemize}
\subsubsection*{Errors}
\begin{itemize}
\item Any expression that results \code{NaN} or \code{Infinity} in Javascript will return some kind of errors, mainly \code{Division by zero}.
\item If \code{\emph{x}<0} and \code{\emph{y}} is not integer, \code{\emph{x}\basicexp\emph{y}} will raise \code{Illegal function call}.
\end{itemize}
\subsection{Comparison Operators}
Comparison operator can operate on numeric and string operands. String operands will be automatically converted to numeric value if they can be; if one operand is numeric and other is non-numeric string, the former will be converted to string value.
\begin{tabulary}{\textwidth}{CLL}
Code & Operation & Result \\
\hline
\emph{x} == \emph{y} & Equal & True if \emph{x} equals \emph{y} \\
\emph{x} <\!> \emph{y} \quad \emph{x} >\!< \emph{y} & Not equal & False if \emph{x} equals \emph{y} \\
\emph{x} < \emph{y} & Less than & True if \emph{x} is less than \emph{y} \\
\emph{x} > \emph{y} & Greater than & True if \emph{x} is greater than \emph{y} \\
\emph{x} <\!= \emph{y} \quad \emph{x} =\!< \emph{y} & Less than or equal & False if \emph{x} is greater than \emph{y} \\
\emph{x} >\!= \emph{y} \quad \emph{x} =\!> \emph{y} & Greater than or equal & False if \emph{x} is less than \emph{y} \\
\end{tabulary}
When comparing strings, the ordering is as follows:
\begin{itemize}
\item Two strings are equal only when they are of the same length and every codepoint of the first string is identical to that of the second. This includes any whitespace or unprintable characters.
\item Each character position of the string is compared starting from the leftmost character. When a pair of different characters is encountered, the string with the character of lesser codepoint is less than the string with the character of greater codepoint.
\item If the strings are of different length, but equal up to the length of the shorter string, then the shorter string is less than the longer string.
\end{itemize}
\subsection{Bitwise Operators}
Bitwise operators operate on integers only. Floating points are truncated\footnote{truncated towards zero} to integers.
\begin{tabulary}{\textwidth}{CLL}
Code & Operation & Result \\
\hline
\condensedfont{BNOT} \emph{x} & Ones' complement & $-\emph{x}-1$ \\
\emph{x} \condensedfont{BAND} \emph{y} & Bitwise conjunction & Bitwise AND of \emph{x} and \emph{y} \\
\emph{x} \condensedfont{BOR} \emph{y} & Bitwise disjunction & Bitwise OR of \emph{x} and \emph{y} \\
\emph{x} \condensedfont{BXOR} \emph{y} & Bitwise add-with-no-carry & Bitwise XOR of \emph{x} and \emph{y} \\
\end{tabulary}
\subsection{Boolean Operators}
Boolean operators operate on boolean values. If one of the operand is not boolean, it will be cast to appropriate boolean value. See \ref{valuesandtypes}
\begin{tabulary}{\textwidth}{CLL}
Code & Operation & Result \\
\hline
\condensedfont{NOT} \emph{x} & Logical negation & True if \emph{x} is false and vice versa \\
\emph{x} \condensedfont{AND} \emph{y} & Bitwise conjunction & True if \emph{x} and \emph{y} are both true \\
\emph{x} \condensedfont{OR} \emph{y} & Bitwise disjunction & True if \emph{x} or \emph{y} is true, or both are true \\
\end{tabulary}
\section{Syntax In EBNF}
\small\verbatiminput{syntax.txt}
If you're \emph{that} into the language theory of computer science, texts above are just waste of bytes/inks/pixel-spaces/whatever; this little section should be more than enough!
\verbatiminput{syntax.txt}

View File

@@ -0,0 +1 @@
IF DEFUN ON

View File

@@ -13,9 +13,11 @@ stmt =
| "DEFUN" , [ident] , "(" , [ident , {" , " , ident}] , ")" , "=" , expr
| "ON" , expr_sans_asgn , ("GOTO" | "GOSUB") , expr_sans_asgn , {"," , expr_sans_asgn}
| "(" , stmt , ")"
| expr ; (* if the statement is 'lit' and contains only one word, treat it as function_call e.g. NEXT for FOR loop *)
| expr ; (* if the statement is 'lit' and contains only one word, treat it as function_call
e.g. NEXT for FOR loop *)
expr = (* this basically blocks some funny attemps such as using DEFUN as anon function because everything is global in BASIC *)
expr = (* this basically blocks some funny attemps such as using DEFUN as anon function
because everything is global in BASIC *)
lit
| "(" , expr , ")"
| "IF" , expr_sans_asgn , "THEN" , expr , ["ELSE" , expr]
@@ -52,21 +54,17 @@ num = digits | digits , "." , [digits] | "." , digits
visible = ? ASCII 0x20 to 0x7E ? ;
string = '"' , (visible | visible , stringlit) , '"' ;
letter = "A" | "B" | "C" | "D" | "E" | "F" | "G"
| "H" | "I" | "J" | "K" | "L" | "M" | "N"
| "O" | "P" | "Q" | "R" | "S" | "T" | "U"
| "V" | "W" | "X" | "Y" | "Z" | "a" | "b"
| "c" | "d" | "e" | "f" | "g" | "h" | "i"
| "j" | "k" | "l" | "m" | "n" | "o" | "p"
| "q" | "r" | "s" | "t" | "u" | "v" | "w"
| "x" | "y" | "z" | "_" ;
letter = "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J" | "K" | "L" | "M" | "N"
| "O" | "P" | "Q" | "R" | "S" | "T" | "U" | "V" | "W" | "X" | "Y" | "Z" | "a" | "b"
| "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" | "k" | "l" | "m" | "n" | "o" | "p"
| "q" | "r" | "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z" | "_" ;
digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ;
hexdigit = "A" | "B" | "C" | "D" | "E" | "F" | "a" | "b"
| "c" | "d" | "e" | "f" | "0" | "1" | "2" | "3" | "4" | "5" | "6"
| "7" | "8" | "9" ;
hexdigit = "A" | "B" | "C" | "D" | "E" | "F" | "a" | "b" | "c" | "d" | "e" | "f" | "0" | "1"
| "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ;
bindigit = "0" | "1" ;
(* all possible token states: lit num op bool qot paren sep *)
(* below are schematic of trees generated after parsing the statements *)
IF (type: function, value: IF)
1. cond

View File

@@ -19,12 +19,14 @@
\usepackage{afterpage}
\usepackage{hyperref}
\usepackage{graphicx}
\usepackage{xcolor}
\usepackage{tabulary}
\usepackage[table]{xcolor}
\usepackage{ltablex}
\usepackage{parskip}
\usepackage{multicol}
\usepackage{soul}
\usepackage{verbatim}
\usepackage{etoolbox}
\usepackage{lineno} % debug
@@ -34,11 +36,10 @@
\setlength{\mytextsize}{\f@size pt}
\newlength{\mybaselineskip}
\setlength{\mybaselineskip}{1.3\mytextsize}
\patchcmd{\verbatim@input}{\@verbatim}{\scriptsize\@verbatim}{}{}
\makeatother
\setlength{\baselineskip}{\mybaselineskip}
\usepackage[fontsize=\mytextsize,baseline=\baselineskip,lines=38]{grid}
\frenchspacing
\setlength{\parindent}{0pt}
\setlength{\parskip}{10pt}
@@ -50,7 +51,7 @@
\hyphenation{ECMA-scr-ipt}
\newcommand\forceindent{\hskip1.5em}
\newcommand\basicexp{\raisebox{0.25ex}{\scriptsize\wedge}}
% Title styling
\pretitle{\begin{flushright}}
@@ -79,8 +80,16 @@
\definecolor{lgrey}{HTML}{eeeeee}
\sethlcolor{lgrey}
\renewcommand{\thefootnote}{\fnsymbol{footnote}}
\newcommand{\code}[1]{{\monofont\hl{#1}}}
\newcommand{\codebf}[1]{{\monofont \textbf{\hl{#1}}}}
\newcommand{\code}[1]{{\monofont\hl{\,#1\,}}}
\newcommand{\codebf}[1]{{\monofont \textbf{\hl{\,#1\,}}}}
%%\newcommand{\codeline}[1]{{\monofont\hl{\,#1\,}}}
\newcommand{\codeline}[1]{%
\colorbox{lgrey}{%
\begin{tabular*}{\textwidth}{l}%
\monofont #1 \\% TODO fill the cell with \hl colour
\end{tabular*}%
}}
%\aliaspagestyle{part}{empty}
@@ -130,9 +139,15 @@
\chapter{Language Reference}
\input{langref}
\chapter{Implementation}
\chapter{Statements}
\input{statements}
\chapter{Functions}
\input{functions}
\chapter{Technical Reference}
\input{implementation}
\input{theinterpreter}
%% Bibliography %%
% https://robhagemans.github.io/pcbasic/doc/2.0/
@@ -140,7 +155,9 @@
\chapter{Index}
\chapter*{Disclaimers}
\oreallypress{} is entirely fictional publishing entity; \oreallypress{} has no affiliation whatsoever with any of the real-world publishers.
\afterpage{\pagestyle{empty}\null\newpage}