diff --git a/books/bookvol5.pamphlet b/books/bookvol5.pamphlet index 8f3c941..8ef1abf 100644 --- a/books/bookvol5.pamphlet +++ b/books/bookvol5.pamphlet @@ -22892,6 +22892,8 @@ we return the remainder of the string without the leading prefix. (t nil)))))) \end{chunk} + +\newpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \cmdhead{abbreviations help page} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -23066,6 +23068,7 @@ o )compile \end{chunk} +\newpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \cmdhead{boot help page} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -23110,6 +23113,7 @@ This command is in the list of \verb|$noParseCommands| verbatim. This will eventually result in a call to the function \verb|handleNoParseCommands| \ref{handleNoParseCommands} +\newpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \cmdhead{browse help page} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -23331,6 +23335,7 @@ if the token is a command. \section{The server support code} +\newpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \cmdhead{cd help page} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -23379,6 +23384,7 @@ o )spool \section{Variables Used} \section{Functions} +\newpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \cmdhead{clear help page} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -23803,6 +23809,7 @@ Clear all the options except the argument. \end{chunk} +\newpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \cmdhead{close help page} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -23913,6 +23920,7 @@ Returns the number of active scratchpad clients \end{chunk} +\newpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \cmdhead{compile help page} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -24044,7 +24052,7 @@ o )library \end{chunk} - +\newpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \cmdhead{copyright help page} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -24329,6 +24337,7 @@ This command is in the list of \verb|$noParseCommands| verbatim. This will eventually result in a call to the function \verb|handleNoParseCommands| \ref{handleNoParseCommands} +\newpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \cmdhead{credits help page} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -24349,6 +24358,7 @@ This command is in the list of \verb|$noParseCommands| verbatim. This will eventually result in a call to the function \verb|handleNoParseCommands| \ref{handleNoParseCommands} +\newpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \cmdhead{describe help page} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -24544,6 +24554,7 @@ in the Category, Domain, or Package source code. \end{chunk} +\newpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \cmdhead{display help page} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -24921,6 +24932,7 @@ next brace but the problem does not arise in practice. \end{chunk} +\newpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \cmdhead{edit help page} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -25097,6 +25109,7 @@ fi \end{chunk} +\newpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \cmdhead{fin help page} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -25143,6 +25156,7 @@ This command is in the list of \verb|$noParseCommands| verbatim. This will eventually result in a call to the function \verb|handleNoParseCommands| \ref{handleNoParseCommands} +\newpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \cmdhead{frame help page} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -25922,6 +25936,7 @@ S2IZ0079 AXIOM cannot import %1b from frame %2b because it cannot be found. \end{chunk} +\newpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \cmdhead{help help page} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -26132,6 +26147,7 @@ Available algebra help topics are: \end{chunk} +\newpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \cmdhead{history help page} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -28032,6 +28048,7 @@ S2IH0038 You must specify a file name to the history write command \end{chunk} +\newpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \cmdhead{include help page} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -28116,6 +28133,7 @@ token in the string. If the string only 0 or more blanks it returns nil. \end{chunk} +\newpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \cmdhead{library help page} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -28180,6 +28198,7 @@ o )set \fnref{frame} \fnref{set}} +\newpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \cmdhead{lisp help page} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -28223,32 +28242,7 @@ This command is in the list of \verb|$noParseCommands| verbatim. This will eventually result in a call to the function \verb|handleNoParseCommands| \ref{handleNoParseCommands} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\cmdhead{load help page} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\begin{chunk}{load.help} -==================================================================== -A.16. )load -==================================================================== - -User Level Required: interpreter - -Command Description: - -This command is obsolete. Use )library instead. - -\end{chunk} - -\defun{load}{The )load command (obsolete)} -We keep this command around in case anyone has the original Axiom book. -\calls{load}{sayKeyedMsg} -\begin{chunk}{defun load} -(defun |load| (ignore) - (declare (ignore ignore)) - (|sayKeyedMsg| 'S2IU0003 nil)) - -\end{chunk} - +\newpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \cmdhead{ltrace help page} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -28288,6 +28282,8 @@ o )trace \section{Variables Used} \section{Functions} + +\newpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \cmdhead{pquit help page} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -28371,6 +28367,7 @@ This command is in the list of \verb|$noParseCommands| verbatim. This will eventually result in a call to the function \verb|handleNoParseCommands| \ref{handleNoParseCommands} +\newpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \cmdhead{quit help page} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -28468,6 +28465,7 @@ This command is in the list of \verb|$noParseCommands| verbatim. This will eventually result in a call to the function \verb|handleNoParseCommands| \ref{handleNoParseCommands} +\newpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \cmdhead{read help page} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -28603,6 +28601,7 @@ o )history \end{chunk} +\newpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \cmdhead{regress help page} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -28760,7 +28759,7 @@ The last line of output is a summary: \end{chunk} -\begin{chunk}{defun regress} +\begin{chunk}{defun regress command} (defun |regress| (arg) (let (|$InteractiveMode| namestring dot1 outfile (extension "output")) (declare (special |$InteractiveMode|)) @@ -28775,7 +28774,355 @@ The last line of output is a summary: \end{chunk} +\section{The regress function details} +This is the regression test mechanism. The input files have been +rewritten to have a standard structure. This fixed format identifies +the tests within a file. Each test is run and any mismatch between +the actual and expected results is reported. + +In order to regression test axiom results we created a standard +file format. This format has 3 kinds of markers: +\begin{itemize} +\item ``--S'' marker which must have a integer test number +\item ``--R'' marker lines, one per expected output from axiom +\item ``--E'' marker which has an integer matching the preceeding ``--S'' +\item ``--I'' marker ignores the line, useful for gensyms and random +\end{itemize} +Because these markers use Axiom's standard comment prefix they +are valid lines in input files and are ignored by the ``)read'' +command. They are simply copied to the output file. This allows +us to include the expected output in the output file so we can +compare what Axiom computes with what it should compute. + +To create these regression files all you need to do is create an +input file and run it through Axiom. Then, for each test case in +the file you mark it up by putting a ``--S number'' {\bf before} +the Axiom input line. You put ``--R'' prefixes on each line of +Axiom output, including the blank lines. Then you put a ``--E number'' +line after the last output line, usually the {\tt Type:} line. +This newly marked-up input file is now a regression test. + +To actually run the regression test you simply include the +marked up the input file in the {\tt src/input} subdirectory. +This file will automatically be run at build time and any failing +tests will be marked. This code will ignore any input that does +not contain proper regression markups. + +Ideally the regression test files should be pamphlet files that +explain the content and purpose of each regression test case. + +Thus you run the marked-up input file {\tt foo.input} +and spool the result to {\tt foo.output} and then run the +lisp function\\ +{\tt (regress ``foo.output'')} + +If the file does not contain proper regression markups it is +ignored. Comments or any other commands in the file that are not +surrounded by ``--S'' and ``--E'' boundaries are ignored. + +\defvar{*all-tests-ran*} +This variable is used to check whether all of the tests actually +ran. This is needed to see if the execution ended early. +\begin{chunk}{initvars} +(defvar *all-tests-ran* nil "true implies that all tests ran") + +\end{chunk} + +\defun{regress}{Scan a spool output file for failures} +This function takes an output file which has been created by the +Axiom {\tt )spool} command and looks for regression test markups. +Each regression test is checked against the actual result and any +failures are marked. + +\calls{regress}{getspoolname} +\calls{regress}{findnexttest} +\calls{regress}{testpassed} +\uses{regress}{*all-tests-ran*} +\begin{chunk}{defun regress} +(defun regress (infile) + (let (name comment test (count 0) (passed 0) (failed 0)) + (declare (special *all-tests-ran*)) + (setq *all-tests-ran* nil) + (with-open-file (stream infile :direction :input) + (setq name (getspoolname stream)) + (when name + (format t "testing ~a~%" name) + (loop + (setq *ok* nil) + (multiple-value-setq (comment test) (findnexttest stream)) + (unless comment (return)) + (setq count (+ count 1)) + (if (testpassed test) + (progn + (setq passed (+ passed 1)) + (format t "passed ~a ~a~%" name comment)) + (progn + (setq failed (+ failed 1)) + (format t "FAILED ~a ~a~%" name comment)))) + (if (= failed 0) + (format t "regression result passed ~a of ~a stanzas ~Tfile ~a~%" + passed count name) + (format t "regression result FAILED ~a of ~a stanzas ~Tfile ~a~%" + failed count name)) + (unless *all-tests-ran* + (format t "regression result FAILED early exit in file ~a?~%" name)))))) + +\end{chunk} + +\defun{getspoolname}{Parse test name from the spool command} +We need to parse out the name of the test. The ``)spool'' command +writes a line into the output file containing the name of the test. +We parse out the name of the test from this line. +\begin{chunk}{defun getspoolname 0} +(defun getspoolname (stream) + (let (line point) + (setq line (read-line stream)) + (setq point (position #\. line)) + (if (or (null point) + (< (length line) 30) + (not (string= (subseq line (+ point 1) (+ point 7)) "output"))) + nil + (subseq line 20 point)))) + +\end{chunk} + +\defun{findnexttest}{Find the next --S marker} +We need to break the file into separate test cases. This routine +looks for the ``--S'' line which indicates a test is starting. It +collects up input lines until it encounters the ``--E'' line marking +the end of the test case. These lines are returned as a list of strings. +\calls{findnexttest}{testnumberp} +\begin{chunk}{defun findnexttest} +(defun findnexttest (stream) + (let (teststart result) + (do ((line (read-line stream nil 'done) (read-line stream nil 'done))) + ((or (eq line 'done) (endedp line)) + (values (if line teststart) result)) + (if teststart + (push line result) + (setq teststart (testnumberp line)))))) + +\end{chunk} + +\defun{testnumberp}{Parse out the test number from --S lines} +The ``--S'' line has a test number on the line. We parse out the +test number for printing. +\calls{testnumberp}{startp} +\begin{chunk}{defun testnumberp} +(defun testnumberp (oneline) + (when (startp oneline) (subseq oneline 3))) + +\end{chunk} + +\defvar{*ok*} +We can mark a test as always ok by putting the word ``ok'' anywhere +on the start line. The regress function resets this value. The startp +function checks the --S line for the word ``ok''. If found, it sets +this value to true which causes a failing test to be considered as +passed. +\begin{chunk}{initvars} +(defvar *ok* nil "did we mark this test as always ok?") + +\end{chunk} + +\defun{testpassed}{Compare the computed and expected results} +This routine takes the test input, passes it to split to clean up +and break into two lists, and then compares the resulting lists +element by element, complaining about any mismatches. The result +is either true if everything passes or false if a mismatch occurs. + +A test line can also be considered at passing if the expected line +is the string ``ignore''. + +The ok variable allows us to mark failing tests as ``ok'' because +we expect the test might fail due to random values or testing known +bugs against expected output. We filter these tests marked ``ok'' +so they do not count as ``real'' failures. +\calls{testpassed}{split} +\uses{testpassed}{*ok*} +\begin{chunk}{defun testpassed} +(defun testpassed (test) + (let (answer expected (passed t) mismatchedLines) + (declare (special *ok*)) + (multiple-value-setq (answer expected) (split test)) + (dotimes (i (length answer)) + (unless + (or (string= (first expected) "ignore") + (string= (first expected) (first answer))) + (unless *ok* (setq passed nil)) + (push (cons (first expected) (first answer)) mismatchedLines)) + (pop answer) + (pop expected)) + (when mismatchedLines + (dolist (pair mismatchedLines) + (format t "expected:~s~% got:~s~%" (car pair) (cdr pair)))) + passed)) + +\end{chunk} + +\defun{split}{Split the calculated and expect results into lists} +We have a list containing all of the lines in a test. The input is of +the form: +\begin{verbatim} +("--R Type: List Integer" + "--R (1) [1,4,2,- 6,0,3,5,4,2,3]" + "--R" + "--R " + " Type: List Integer" + " (1) [1,4,2,- 6,0,3,5,4,2,3]" + "" + " " + "l := [1,4,2,-6,0,3,5,4,2,3]") +\end{verbatim} +It removes the ``--R'' prefix from the result strings +and generates two hopefully equal-length lists, thus: +\begin{verbatim} +(" Type: List Integer" + " (1) [1,4,2,- 6,0,3,5,4,2,3]" + "" + " ") +(" Type: List Integer" + " (1) [1,4,2,- 6,0,3,5,4,2,3]" + "" + " ")) +\end{verbatim} +Thus the first line is the start line, the second line is the Axiom +input line, followed by the Axiom output. Then we have the lines marked +``--R'' which are the expected result. We split these into two separate +lists and throw way the lines that are the start and end lines. + +Once we have classified all of the lines we need to throw away the +input lines. By assumption there will be more answer lines than +expected lines because the input lines are included. And given the way +we process the file these input lines are on the top of the answer +stack. Since the number of answer lines should equal the number of +expected lines we pop the stack until the numbers are equal. + +Each element of the answer list should +be {\tt string=} to the corresponding element of the result list. + +If the input line starts with ``--I'' we push the string ``ignore''. +This is useful for handling random results or gensym symbols. + +\calls{split}{startp} +\calls{split}{endedp} +\calls{split}{ignorep} +\calls{split}{resultp} +\begin{chunk}{defun split} +(defun split (test) + (let (answer (acnt 0) expected (ecnt 0)) + (dolist (oneline test) + (cond + ((startp oneline)) + ((endedp oneline)) + ((ignorep oneline) + (setq ecnt (+ ecnt 1)) + (push "ignore" expected)) + ((resultp oneline) + (setq ecnt (+ ecnt 1)) + (push (subseq oneline 3) expected)) + (t + (setq acnt (+ acnt 1)) + (push oneline answer)))) + (dotimes (i (- acnt ecnt)) (pop answer)) + (values (nreverse answer) (nreverse expected)))) + +\end{chunk} + +\defun{startp}{Returns true on --S lines} +This test returns true if we have a ``start'' line. That is, a line +with a ``--S'' prefix. + +The *all-tests-ran* variable is true if the start line is of the form +"--S N of M" and N=M, that is, it checks that all tests were performed +since this should only occur on the last start line. This will detect +``premature exit'' in processing. + +If a test is failing because of random input values or we want the +test to fail but not to count toward failing values then put the +string ``ok'' somewhere on the ``--S'' line as in: +\begin{verbatim} +--S 29 of 42 fails due to random values but that is ok +\end{verbatim} + +\calls{startp}{lastcount} +\uses{startp}{*ok*} +\begin{chunk}{defun startp} +(defun startp (oneline) + (let (result) + (declare (special *ok*)) + (when + (setq result + (and (>= (length oneline) 3) (string= (subseq oneline 0 3) "--S"))) + (setq *ok* (search "ok" oneline)) + (setq *all-tests-ran* (lastcount oneline))) + result)) + +\end{chunk} + +\defun{endedp}{Returns true on --E lines} +This test returns true if we have a ``ended'' line. That is, a line +with a ``--E'' prefix. +\begin{chunk}{defun endedp 0} +(defun endedp (oneline) + (and (>= (length oneline) 3) (string= (subseq oneline 0 3) "--E"))) + +\end{chunk} + +\defun{resultp}{Returns true on --R lines} +This test returns true if we have a ``results'' line. That is, a line +with a ``--R'' prefix. +\begin{chunk}{defun resultp 0} +(defun resultp (oneline) + (and (>= (length oneline) 3) (string= (subseq oneline 0 3) "--R"))) + +\end{chunk} + +\defun{ignorep}{Returns true on --I lines} +This test returns true if we have an ``ignore'' line. That is, a line +with a ``--I'' prefix. +\begin{chunk}{defun ignorep 0} +(defun ignorep (oneline) + (and (>= (length oneline) 3) (string= (subseq oneline 0 3) "--I"))) + +\end{chunk} +\defun{lastcount}{Check the last --S line ran} +If the ``--S'' line has the format ``--S n of m'' we return true if +n=m, false otherwise. +Thus, +\begin{verbatim} + "--S" => nil + "--S 1 of 4" => nil + "--S 10 of 40" => nil + "--S 4 of 4" => t + "--S 40 of 40" => t + "--S 1 of a" => nil +\end{verbatim} +This is used as a final end check to make sure that all of the +tests actually ran rather than having the regression test exit +early and quietly. This will be false on all but the last test +and will be false if the ``--S'' line does not contain the optional +count marker. It is not required but is highly recommended. + +\begin{chunk}{defun lastcount 0} +(defun lastcount (oneline) + (let ((n :done) (m :done) next somemore) + (when (and (>= (length oneline) 3) (string= (subseq oneline 0 3) "--S")) + (setq somemore (string-trim " " (subseq oneline 3))) + (when somemore + (multiple-value-setq (n next) (read-from-string somemore nil :done)) + (when (integerp n) + (setq somemore (string-trim " " (subseq somemore next))) + (multiple-value-setq (isof next) (read-from-string somemore nil :done)) + (when (string= isof "OF") + (setq somemore (string-trim " " (subseq somemore next))) + (multiple-value-setq (m next) (read-from-string somemore nil :done)))))) + (and (integerp m) (integerp n) (= m n)))) + +\end{chunk} + +\newpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \cmdhead{savesystem help page} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -28810,6 +29157,16 @@ were already loaded when the system was saved. There is currently a restriction that only systems started with the command "AXIOMsys" may be saved. + axiom + (1) -> t1:=4 + (1) -> )savesystem foo + +and Axiom exits. Then do + + ./foo + (1) -> t1 + 4 + \end{chunk} \defun{savesystem}{The )savesystem command} @@ -28823,6 +29180,7 @@ command "AXIOMsys" may be saved. \end{chunk} +\newpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \cmdhead{set help page} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -35612,6 +35970,7 @@ printLoadMessages, which gets called with \verb|%describe%| \end{chunk} +\newpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \cmdhead{show help page} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -36193,6 +36552,7 @@ where = ELT | CONST | Subsumed | (XLAM..) .. \end{chunk} +\newpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \cmdhead{spool help page} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -36230,6 +36590,7 @@ o )cd \end{chunk} \footnote{\fnref{cd}} +\newpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \cmdhead{summary help page} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -36240,6 +36601,7 @@ o )cd )quit : exit AXIOM )abbreviation : query, set and remove abbreviations for constructors + )browse : start an Axiom http server on 127.0.0.1 port 8085 )cd : set working directory )clear : remove declarations, definitions or values )close : throw away an interpreter client and workspace @@ -36248,17 +36610,24 @@ o )cd )describe : show database information for a category, domain, or package )display : display Library operations and objects in your workspace )edit : edit a file + )fin : drop into lisp, use (restart) to return to the session )frame : manage interpreter workspaces )history : manage aspects of interactive session + )include : insert a file into a .input file )library : introduce new constructors )lisp : evaluate a LISP expression + )ltrace : trace functions + )pquit : ask if you really want to exit Axiom + )quit : exit Axiom )read : execute AXIOM commands from a file + )regress : regression test an output spool file )savesystem : save LISP image to a file )set : view and set system variables )show : show constructor information )spool : log input and output to a file )synonym : define an abbreviation for system commands )system : issue shell commands + )tangle : extract chunks from a literate program to an input file )trace : trace execution of functions )undo : restore workspace to earlier state )what : search for various things by name @@ -36275,6 +36644,7 @@ o )cd \end{chunk} +\newpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \cmdhead{synonym help page} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -36443,6 +36813,7 @@ This command is in the list of \verb|$noParseCommands| verbatim. This will eventually result in a call to the function \verb|handleNoParseCommands| \ref{handleNoParseCommands} +\newpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \cmdhead{system help page} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -36494,6 +36865,7 @@ This command is in the list of \verb|$noParseCommands| verbatim. This will eventually result in a call to the function \verb|handleNoParseCommands| \ref{handleNoParseCommands} +\newpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \cmdhead{tangle help page} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -36548,6 +36920,7 @@ matrix.input. The ``.input.pamphlet'' is optional. \end{chunk} +\newpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \cmdhead{trace help page} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -39327,6 +39700,7 @@ to convert the data into type "Expression" \end{chunk} +\newpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \cmdhead{undo help page} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -40530,6 +40904,7 @@ Removing undo lines from \verb|)hist )write linelist| \end{chunk} +\newpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \cmdhead{what help page} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -40929,29 +41304,7 @@ This displays all operation names containing these fragments \end{chunk} - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\cmdhead{with help page} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\begin{chunk}{with.help} - -This command is obsolete. -This has been renamed )library. - -See also: -o )library - -\end{chunk} -\footnote{\fnref{library}} - -\defun{with}{with} -\calls{with}{library} -\begin{chunk}{defun with} -(defun |with| (args) - (|library| args)) - -\end{chunk} - +\newpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \cmdhead{workfiles help page} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -41033,6 +41386,7 @@ o )library \end{chunk} +\newpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \cmdhead{zsystemdevelopment help page} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -58602,6 +58956,7 @@ digits in TechExplorer. Since Saturn is gone we can remove it. \getchunk{defun dqUnit 0} \getchunk{defun emptyInterpreterFrame 0} +\getchunk{defun endedp 0} \getchunk{defun fin 0} \getchunk{defun findFrameInRing 0} @@ -58640,9 +58995,11 @@ digits in TechExplorer. Since Saturn is gone we can remove it. \getchunk{defun getMsgText 0} \getchunk{defun getParserMacroNames 0} \getchunk{defun getPreStL 0} +\getchunk{defun getspoolname 0} \getchunk{defun hasOptArgs? 0} +\getchunk{defun ignorep 0} \getchunk{defun incActive? 0} \getchunk{defun incCommand? 0} \getchunk{defun incDrop 0} @@ -58665,6 +59022,7 @@ digits in TechExplorer. Since Saturn is gone we can remove it. \getchunk{defun keyword 0} \getchunk{defun keyword? 0} +\getchunk{defun lastcount 0} \getchunk{defun lfcomment 0} \getchunk{defun lferror 0} \getchunk{defun lffloat 0} @@ -58824,6 +59182,7 @@ digits in TechExplorer. Since Saturn is gone we can remove it. \getchunk{defun remLine 0} \getchunk{defun rep 0} \getchunk{defun resetStackLimits 0} +\getchunk{defun resultp 0} \getchunk{defun sameUnionBranch 0} \getchunk{defun satisfiesUserLevel 0} @@ -59157,6 +59516,7 @@ digits in TechExplorer. Since Saturn is gone we can remove it. \getchunk{defun filterListOfStrings} \getchunk{defun filterListOfStringsWithFn} \getchunk{defun finalExactRequest} +\getchunk{defun findnexttest} \getchunk{defun firstTokPosn} \getchunk{defun fixObjectForPrinting} \getchunk{defun flattenOperationAlist} @@ -60104,6 +60464,7 @@ digits in TechExplorer. Since Saturn is gone we can remove it. \getchunk{defun recordOldValue0} \getchunk{defun reduceAlistForDomain} \getchunk{defun redundant} +\getchunk{defun regress command} \getchunk{defun regress} \getchunk{defun remFile} \getchunk{defun removeOption} @@ -60266,8 +60627,10 @@ digits in TechExplorer. Since Saturn is gone we can remove it. \getchunk{defun specialChar} \getchunk{defun spleI} \getchunk{defun spleI1} +\getchunk{defun split} \getchunk{defun splitIntoOptionBlocks} \getchunk{defun stackTraceOptionError} +\getchunk{defun startp} \getchunk{defun startsComment?} \getchunk{defun startsNegComment?} \getchunk{defun statisticsInitialization} @@ -60299,6 +60662,8 @@ digits in TechExplorer. Since Saturn is gone we can remove it. \getchunk{defun tangle} \getchunk{defun terminateSystemCommand} \getchunk{defun tersyscommand} +\getchunk{defun testnumberp} +\getchunk{defun testpassed} \getchunk{defun thisPosIsEqual} \getchunk{defun thisPosIsLess} \getchunk{defun throwEvalTypeMsg} diff --git a/changelog b/changelog index 597c9d3..176d89f 100644 --- a/changelog +++ b/changelog @@ -1,3 +1,7 @@ +20141213 tpd src/axiom-website/patches.html 20141213.01.tpd.patch +20141213 tpd books/bookvol5 merge and remove regress.lisp +20141212 tpd src/axiom-website/patches.html 20141212.02.tpd.patch +20141212 tpd books/bookvol0 fix the system commands section 20141212 tpd src/axiom-website/patches.html 20141212.01.tpd.patch 20141212 tpd src/input/graphviz.input fix typo in section numbering 20141211 tpd src/axiom-website/patches.html 20141211.01.tpd.patch diff --git a/patch b/patch index 23fba94..36f679e 100644 --- a/patch +++ b/patch @@ -1,3 +1,3 @@ -src/input/graphviz.input fix typo in section numbering +books/bookvol5 merge and remove regress.lisp -The typo caused the regress function to complain about an early exit. +The regression code is now part of the interpreter diff --git a/src/axiom-website/patches.html b/src/axiom-website/patches.html index b6fc6ca..ebcb391 100644 --- a/src/axiom-website/patches.html +++ b/src/axiom-website/patches.html @@ -4802,6 +4802,10 @@ books/bookvol10.3 add UnivariateLaurentSeries tests
src/input/bug10312.input fix ** to ^ conversion
20141212.01.tpd.patch src/input/graphviz.input fix typo in section numbering
+20141212.02.tpd.patch +books/bookvol0 fix the system commands section
+20141213.01.tpd.patch +books/bookvol5 merge and remove regress.lisp
diff --git a/src/interp/Makefile.pamphlet b/src/interp/Makefile.pamphlet index f4ea573..fd42e7b 100644 --- a/src/interp/Makefile.pamphlet +++ b/src/interp/Makefile.pamphlet @@ -174,7 +174,7 @@ OBJS= ${OUT}/vmlisp.${O} \ ${OUT}/nrunfast.${O} \ ${OUT}/nrungo.${O} ${OUT}/nrunopt.${O} \ ${OUT}/posit.${O} \ - ${OUT}/record.${O} ${OUT}/regress.${O} \ + ${OUT}/record.${O} \ ${OUT}/rulesets.${O} \ ${OUT}/server.${O} \ ${OUT}/sfsfun-l.${O} ${OUT}/sfsfun.${O} \ diff --git a/src/interp/regress.lisp.pamphlet b/src/interp/regress.lisp.pamphlet deleted file mode 100644 index e8f8ad8..0000000 --- a/src/interp/regress.lisp.pamphlet +++ /dev/null @@ -1,333 +0,0 @@ -\documentclass{article} -\usepackage{axiom} -\begin{document} -\title{\$SPAD/src/interp regress.lisp} -\author{Timothy Daly} -\maketitle -\begin{abstract} -This is the regression test mechanism. The input files have been -rewritten to have a standard structure. This fixed format identifies -the tests within a file. Each test is run and any mismatch between -the actual and expected results is reported. -\end{abstract} -\eject -\tableofcontents -\eject -\section{Regress} -In order to regression test axiom results we created a standard -file format. This format has 3 kinds of markers: -\begin{itemize} -\item ``--S'' marker which must have a integer test number -\item ``--R'' marker lines, one per expected output from axiom -\item ``--E'' marker which has an integer matching the preceeding ``--S'' -\item ``--I'' marker ignores the line, useful for gensyms and random -\end{itemize} -Because these markers use Axiom's standard comment prefix they -are valid lines in input files and are ignored by the ``)read'' -command. They are simply copied to the output file. This allows -us to include the expected output in the output file so we can -compare what Axiom computes with what it should compute. - -To create these regression files all you need to do is create an -input file and run it through Axiom. Then, for each test case in -the file you mark it up by putting a ``--S number'' {\bf before} -the Axiom input line. You put ``--R'' prefixes on each line of -Axiom output, including the blank lines. Then you put a ``--E number'' -line after the last output line, usually the {\tt Type:} line. -This newly marked-up input file is now a regression test. - -To actually run the regression test you simply include the -marked up the input file in the {\tt src/input} subdirectory. -This file will automatically be run at build time and any failing -tests will be marked. This code will ignore any input that does -not contain proper regression markups. - -Ideally the regression test files should be pamphlet files that -explain the content and purpose of each regression test case. - -Thus you run the marked-up input file {\tt foo.input} -and spool the result to {\tt foo.output} and then run the -lisp function\\ -{\tt (regress ``foo.output'')} - -If the file does not contain proper regression markups it is -ignored. Comments or any other commands in the file that are not -surrounded by ``--S'' and ``--E'' boundaries are ignored. - -\subsection{defun regress} -This function takes an output file which has been created by the -Axiom {\tt )spool} command and looks for regression test markups. -Each regression test is checked against the actual result and any -failures are marked. -\begin{chunk}{*} -(in-package "BOOT") - -(defvar *all-tests-ran* nil "true implies that all tests ran") - -(defun regress (infile) - (let (name comment test (count 0) (passed 0) (failed 0)) - (declare (special *all-tests-ran*)) - (setq *all-tests-ran* nil) - (with-open-file (stream infile :direction :input) - (setq name (getspoolname stream)) - (when name - (format t "testing ~a~%" name) - (loop - (setq *ok* nil) - (multiple-value-setq (comment test) (findnexttest stream)) - (unless comment (return)) - (setq count (+ count 1)) - (if (testpassed test) - (progn - (setq passed (+ passed 1)) - (format t "passed ~a ~a~%" name comment)) - (progn - (setq failed (+ failed 1)) - (format t "FAILED ~a ~a~%" name comment)))) - (if (= failed 0) - (format t "regression result passed ~a of ~a stanzas ~Tfile ~a~%" - passed count name) - (format t "regression result FAILED ~a of ~a stanzas ~Tfile ~a~%" - failed count name)) - (unless *all-tests-ran* - (format t "regression result FAILED early exit in file ~a?~%" name)))))) - -\end{chunk} -\subsection{defun getspoolname} -We need to parse out the name of the test. The ``)spool'' command -writes a line into the output file containing the name of the test. -We parse out the name of the test from this line. -\begin{chunk}{*} -(defun getspoolname (stream) - (let (line point) - (setq line (read-line stream)) - (setq point (position #\. line)) - (if (or (null point) - (< (length line) 30) - (not (string= (subseq line (+ point 1) (+ point 7)) "output"))) - nil - (subseq line 20 point)))) - -\end{chunk} -\subsection{defun findnexttest} -We need to break the file into separate test cases. This routine -looks for the ``--S'' line which indicates a test is starting. It -collects up input lines until it encounters the ``--E'' line marking -the end of the test case. These lines are returned as a list of strings. -\begin{chunk}{*} -(defun findnexttest (stream) - (let (teststart result) - (do ((line (read-line stream nil 'done) (read-line stream nil 'done))) - ((or (eq line 'done) (endedp line)) - (values (if line teststart) result)) - (if teststart - (push line result) - (setq teststart (testnumberp line)))))) - -\end{chunk} -\subsection{defun testnumberp} -The ``--S'' line has a test number on the line. We parse out the -test number for printing. -\begin{chunk}{*} -(defun testnumberp (oneline) - (when (startp oneline) (subseq oneline 3))) -; (parse-integer (string-trim '(#\Space) (subseq oneline 3))))) - -\end{chunk} -\subsection{defvar *ok*} -We can mark a test as always ok by putting the word ``ok'' anywhere -on the start line. The regress function resets this value. The startp -function checks the --S line for the word ``ok''. If found, it sets -this value to true which causes a failing test to be considered as -passed. -\begin{chunk}{*} -(defvar *ok* nil "did we mark this test as always ok?") - -\end{chunk} - -\subsection{defun testpassed} -This routine takes the test input, passes it to split to clean up -and break into two lists, and then compares the resulting lists -element by element, complaining about any mismatches. The result -is either true if everything passes or false if a mismatch occurs. - -A test line can also be considered at passing if the expected line -is the string ``ignore''. - -The ok variable allows us to mark failing tests as ``ok'' because -we expect the test might fail due to random values or testing known -bugs against expected output. We filter these tests marked ``ok'' -so they do not count as ``real'' failures. -\begin{chunk}{*} -(defun testpassed (test) - (let (answer expected (passed t) mismatchedLines) - (declare (special *ok*)) - (multiple-value-setq (answer expected) (split test)) - (dotimes (i (length answer)) - (unless - (or (string= (first expected) "ignore") - (string= (first expected) (first answer))) - (unless *ok* (setq passed nil)) - (push (cons (first expected) (first answer)) mismatchedLines)) - (pop answer) - (pop expected)) - (when mismatchedLines - (dolist (pair mismatchedLines) - (format t "expected:~s~% got:~s~%" (car pair) (cdr pair)))) - passed)) - -\end{chunk} -\subsection{defun split} -We have a list containing all of the lines in a test. The input is of -the form: -\begin{verbatim} -("--R Type: List Integer" - "--R (1) [1,4,2,- 6,0,3,5,4,2,3]" - "--R" - "--R " - " Type: List Integer" - " (1) [1,4,2,- 6,0,3,5,4,2,3]" - "" - " " - "l := [1,4,2,-6,0,3,5,4,2,3]") -\end{verbatim} -It removes the ``--R'' prefix from the result strings -and generates two hopefully equal-length lists, thus: -\begin{verbatim} -(" Type: List Integer" - " (1) [1,4,2,- 6,0,3,5,4,2,3]" - "" - " ") -(" Type: List Integer" - " (1) [1,4,2,- 6,0,3,5,4,2,3]" - "" - " ")) -\end{verbatim} -Thus the first line is the start line, the second line is the Axiom -input line, followed by the Axiom output. Then we have the lines marked -``--R'' which are the expected result. We split these into two separate -lists and throw way the lines that are the start and end lines. - -Once we -have classified all of the lines we need to throw away the input lines. -By assumption there will be more answer lines than expected lines because -the input lines are included. And given the way we process the file these -input lines are on the top of the answer stack. Since the number of -answer lines should equal the number of expected lines we pop the -stack until the numbers are equal. - -Each element of the answer list should -be {\tt string=} to the corresponding element of the result list. - -If the input line starts with ``--I'' we push the string ``ignore''. -This is useful for handling random results or gensym symbols. - -\begin{chunk}{*} -(defun split (test) - (let (answer (acnt 0) expected (ecnt 0)) - (dolist (oneline test) - (cond - ((startp oneline)) - ((endedp oneline)) - ((ignorep oneline) - (setq ecnt (+ ecnt 1)) - (push "ignore" expected)) - ((resultp oneline) - (setq ecnt (+ ecnt 1)) - (push (subseq oneline 3) expected)) - (t - (setq acnt (+ acnt 1)) - (push oneline answer)))) - (dotimes (i (- acnt ecnt)) (pop answer)) - (values (nreverse answer) (nreverse expected)))) - -\end{chunk} -\subsection{defun startp} -This test returns true if we have a ``start'' line. That is, a line -with a ``--S'' prefix. - -The *all-tests-ran* variable is true if the start line is of the form -"--S N of M" and N=M, that is, it checks that all tests were performed -since this should only occur on the last start line. This will detect -``premature exit'' in processing. - -If a test is failing because of random input values or we want the -test to fail but not to count toward failing values then put the -string ``ok'' somewhere on the ``--S'' line as in: -\begin{verbatim} ---S 29 of 42 fails due to random values but that is ok -\end{verbatim} -\begin{chunk}{*} -(defun startp (oneline) - (let (result) - (declare (special *ok*)) - (when - (setq result - (and (>= (length oneline) 3) (string= (subseq oneline 0 3) "--S"))) - (setq *ok* (search "ok" oneline)) - (setq *all-tests-ran* (lastcount oneline))) - result)) - -\end{chunk} -\subsection{defun endedp} -This test returns true if we have a ``ended'' line. That is, a line -with a ``--E'' prefix. -\begin{chunk}{*} -(defun endedp (oneline) - (and (>= (length oneline) 3) (string= (subseq oneline 0 3) "--E"))) - -\end{chunk} -\subsection{defun resultp} -This test returns true if we have a ``results'' line. That is, a line -with a ``--R'' prefix. -\begin{chunk}{*} -(defun resultp (oneline) - (and (>= (length oneline) 3) (string= (subseq oneline 0 3) "--R"))) - -\end{chunk} -\subsection{defun ignorep} -This test returns true if we have an ``ignore'' line. That is, a line -with a ``--I'' prefix. -\begin{chunk}{*} -(defun ignorep (oneline) - (and (>= (length oneline) 3) (string= (subseq oneline 0 3) "--I"))) - -\end{chunk} -\subsection{defun lastcount} -If the ``--S'' line has the format ``--S n of m'' we return true if -n=m, false otherwise. -Thus, -\begin{verbatim} - "--S" => nil - "--S 1 of 4" => nil - "--S 10 of 40" => nil - "--S 4 of 4" => t - "--S 40 of 40" => t - "--S 1 of a" => nil -\end{verbatim} -This is used as a final end check to make sure that all of the -tests actually ran rather than having the regression test exit -early and quietly. This will be false on all but the last test -and will be false if the ``--S'' line does not contain the optional -count marker. It is not required but is highly recommended. -\begin{chunk}{*} -(defun lastcount (oneline) - (let ((n :done) (m :done) next somemore) - (when (and (>= (length oneline) 3) (string= (subseq oneline 0 3) "--S")) - (setq somemore (string-trim " " (subseq oneline 3))) - (when somemore - (multiple-value-setq (n next) (read-from-string somemore nil :done)) - (when (integerp n) - (setq somemore (string-trim " " (subseq somemore next))) - (multiple-value-setq (isof next) (read-from-string somemore nil :done)) - (when (string= isof "OF") - (setq somemore (string-trim " " (subseq somemore next))) - (multiple-value-setq (m next) (read-from-string somemore nil :done)))))) - (and (integerp m) (integerp n) (= m n)))) - -\end{chunk} -\eject -\begin{thebibliography}{99} -\bibitem{1} nothing -\end{thebibliography} -\end{document}