axiom-developer
[Top][All Lists]

## Re: [Axiom-developer] axserver patch

 From: Arthur Ralfs Subject: Re: [Axiom-developer] axserver patch Date: Sat, 22 Sep 2007 09:56:45 -0700 User-agent: Thunderbird 1.5.0.12 (X11/20060911)

Alfredo Portes wrote:
> Hi Arthur,
>
> Do you think is possible to put your latest axserver.pamphlet
> as a pamphlet file in the wiki? If you send me the latest version,
> I can do this.
>
> Regards,
>
> Alfredo
>
>
Alfredo,

The wiki won't let me upload files so I've stopped using it for the time
being.   However I've attached the latest version if you want to try.

Arthur

\documentclass{article}
\usepackage{axiom}
\begin{document}
\title{\$SPAD/src/algebra axserver.spad} \author{Arthur C. Ralfs} \maketitle \begin{abstract} The AxiomServer package is designed to provide a web interface to axiom. \end{abstract} \eject \tableofcontents \eject \section{Lisp preliminaries} Extract the lisp to a file named, say, http.lisp with the command notangle -RServer$\backslash$Lisp axserver.pamphlet$>$http.lisp <<Server Lisp>>= ;; file: http.lisp (defvar |StandardOutput| *standard-output*) (defvar |NewLine| '#\NewLine) ;; some regexp stuff (defun |StringMatch| (s1 s2) (si::string-match s1 s2) ) (defun |ListMatches| (&rest args) (si::list-matches args) ) (defun |MatchBeginning| (i) (si::match-beginning i) ) (defun |MatchEnd| (i) (si::match-end i) ) ;; the socket stuff (defun |SiSock| (p spadfn) ;; (format t "SiSocket-1") (si::socket p :server (function (lambda (w) (SPADCALL w spadfn) ) ) :daemon nil) ) (defun |SiListen| (s) ;; (format t "SiListen-1") (si::listen s) ) (defun |SiAccept| (s) (si::accept s)) (defun |SiCopyStream| (q s) (si::copy-stream q s)) ;; Camm Maguire's modified demo server (defun foo (s) (setq get "" pathvar "") (do ((c (read-char s) (read-char s))) ((eq c '#\Space)) (setq get (concat get (string c))) ) (write-line "get: ") (write-line get) (do ((c (read-char s) (read-char s nil 'the-end))) ((eq c '#\Space)) (setq pathvar (concat pathvar (string c))) ) (write-line "pathvar: ") (write-line pathvar) (when pathvar (if (pathname-name (pathname pathvar)) (with-open-file (q pathvar) (si::copy-stream q s)) (dolist (l (directory pathvar)) (format s "~a~%" (namestring l))) ) ) (close s) ) (defun bar (p fn) (let ((s (si::socket p :server fn))) (tagbody l (when (si::listen s) (let ((w (si::accept s))) (foo w))) (sleep 3) (go l)))) ;;(bar 8080 #'foo) @ \section{Axiom Server} Extract the AxiomServer package with the command notangle axserver.pamphlet$>$axserver.spad <<package AXSERV AxiomServer>>= )abbrev package AXSERV AxiomServer AxiomServer: public == private where public == with axServer: (Integer, SExpression->Void) -> Void multiServ: SExpression -> Void fileserver: SExpression -> Void axget: SExpression -> Void axpost: SExpression -> Void private == add getFile: (SExpression,String) -> Void getCommand: (SExpression,String) -> Void lastStep: () -> String lastType: () -> String formatMessages: String -> String formatMessages1: String -> String axServer(port:Integer,serverfunc:SExpression->Void):Void == WriteLine("socketServer")$Lisp
s := SiSock(port,serverfunc)$Lisp -- To listen for just one connection and then close the socket -- uncomment i := 0. i:Integer := 1 while (i > 0) repeat if not null?(SiListen(s)$Lisp)$SExpression then w := SiAccept(s)$Lisp
serverfunc(w)
--        i := 0

multiServ(s:SExpression):Void ==
WriteLine("multiServ")$Lisp headers:String := "" char:String -- read in the http headers while (char := STRING(READ_-CHAR_-NO_-HANG(s,NIL$Lisp,'EOF)$Lisp)$Lisp) ^= "EOF" repeat
sayTeX$Lisp headers StringMatch("([^ ]*)", headers)$Lisp
u:UniversalSegment(Integer)
u :=
segment(MatchBeginning(1)$Lisp+1,MatchEnd(1)$Lisp)$UniversalSegment(Integer) reqtype:String := headers.u sayTeX$Lisp  concat ["request type: ",reqtype]
if  reqtype = "GET" then
StringMatch("GET ([^ ]*)",headers)$Lisp u:UniversalSegment(Integer) u := segment(MatchBeginning(1)$Lisp+1,MatchEnd(1)$Lisp)$UniversalSegment(Integer)
if reqtype = "POST" then
StringMatch("command=(.*)$",headers)$Lisp
u:UniversalSegment(Integer)
u :=
segment(MatchBeginning(1)$Lisp+1,MatchEnd(1)$Lisp)$UniversalSegment(Integer) getCommand(s,headers.u) getFile(s:SExpression,pathvar:String):Void == WriteLine("getFile")$Lisp
if not null? PATHNAME_-NAME(PATHNAME(pathvar)$Lisp)$Lisp then
-- display contents of file
q:=OPEN(pathvar)$Lisp else q:=MAKE_-STRING_-INPUT_-STREAM("Problem with file path")$Lisp
file:String := ""
while (char := STRING(READ_-CHAR_-NO_-HANG(q,NIL$Lisp,'EOF)$Lisp)$Lisp) ^= "EOF" repeat file := concat [file,char] CLOSE(q)$Lisp
file := concat ["Content-Length:
",string(#file),STRING(NewLine$Lisp)$Lisp,STRING(NewLine$Lisp)$Lisp,file]
file := concat ["Connection: close",STRING(NewLine$Lisp)$Lisp,file]
file := concat ["Content-Type:
application/xhtml+xml",STRING(NewLine$Lisp)$Lisp,file]
file := concat ["HTTP/1.1 200 OK",STRING(NewLine$Lisp)$Lisp,file]
f:=MAKE_-STRING_-INPUT_-STREAM(file)$Lisp SiCopyStream(f,s)$Lisp
CLOSE(f)$Lisp CLOSE(s)$Lisp

getCommand(s:SExpression,command:String):Void ==
WriteLine$Lisp concat ["getCommand: ",command] SETQ(tmpmathml$Lisp, MAKE_-STRING_-OUTPUT_-STREAM()$Lisp)$Lisp
SETQ(tmpalgebra$Lisp, MAKE_-STRING_-OUTPUT_-STREAM()$Lisp)$Lisp SETQ(savemathml$Lisp, _$texOutputStream$Lisp)$Lisp SETQ(savealgebra$Lisp, _$algebraOutputStream$Lisp)$Lisp SETQ(_$texOutputStream$Lisp,tmpmathml$Lisp)$Lisp SETQ(_$algebraOutputStream$Lisp,tmpalgebra$Lisp)$Lisp -- parseAndInterpret$Lisp command
--      parseAndEvalStr$Lisp command -- The previous two commands don't exit nicely when a syntactically incorrect command is -- given to them. They somehow need to be wrapped in CATCH statements but I haven't -- figured out how to do this. parseAndEvalToStringEqNum uses the following CATCH -- statements to call parseAndEvalStr but when I try these they don't work. I get a -- "NIL is not a valid identifier to use in AXIOM" message. Using parseAndEvalToStringEqNum -- works and doesn't crash on a syntax error. -- v := CATCH('SPAD__READER, CATCH('top__level, parseAndEvalStr$Lisp
command)$Lisp)$Lisp
--        v = 'restart => ['"error"]
ans := string parseAndEvalToStringEqNum$Lisp command SETQ(resultmathml$Lisp,GET_-OUTPUT_-STREAM_-STRING(_$texOutputStream$Lisp)$Lisp)$Lisp

SETQ(resultalgebra$Lisp,GET_-OUTPUT_-STREAM_-STRING(_$algebraOutputStream$Lisp)$Lisp)$Lisp SETQ(_$texOutputStream$Lisp,savemathml$Lisp)$Lisp SETQ(_$algebraOutputStream$Lisp,savealgebra$Lisp)$Lisp CLOSE(tmpmathml$Lisp)$Lisp CLOSE(tmpalgebra$Lisp)$Lisp -- Since strings returned from axiom are going to be displayed in html I -- should really check for the characters &,<,> and replace them with -- &amp;,&lt;,&gt;. At present I only check for ampersands in formatMessages. mathml:String := string(resultmathml$Lisp)
algebra:String := string(resultalgebra$Lisp) algebra := formatMessages(algebra) -- At this point mathml contains the mathml for the output but does not -- include step number or type information. We should also save the command. -- I get the type and step number from the$internalHistoryTable
axans:String := concat ["<div><div class=_"command_">Input:
",command,"</div><div class=_"stepnum_">Step number: ",lastStep(),"</div><div
class=_"algebra_">",algebra,"</div><div class=_"mathml_">",mathml,"</div><div
class=_"type_">Type: ",lastType(),"</div></div>"]
WriteLine$Lisp concat ["mathml answer: ",mathml] WriteLine$Lisp concat ["algebra answer: ",algebra]
q:=MAKE_-STRING_-INPUT_-STREAM(axans)$Lisp SiCopyStream(q,s)$Lisp
CLOSE(q)$Lisp CLOSE(s)$Lisp

lastType():String ==
--  The last history entry is the first item in the $internalHistoryTable list so -- car(_$internalHistoryTable$Lisp) selects it. Here's an example: -- (3 (x+y)**3 (% (value (Polynomial (Integer)) WRAPPED 1 y (3 0 . 1) (2 1 x (1 0 . 3)) (1 1 x (2 0 . 3)) (0 1 x (3 0 . 1))))) -- This corresponds to the input "(x+y)**3" being issued as the third command after -- starting axiom. The following line selects the type information. string car(cdr(car(cdr(car(cdr(cdr(car(_$internalHistoryTable$Lisp)$Lisp)$Lisp)$Lisp)$Lisp)$Lisp)$Lisp)$Lisp)$Lisp lastStep():String == string car(car(_$internalHistoryTable$Lisp)$Lisp)$Lisp formatMessages(str:String):String == WriteLine("formatMessages")$Lisp
-- I need to replace any ampersands with &amp; and may also need to
-- replace < and > with &lt; and &gt;
strlist:List String
WriteLine(str)$Lisp strlist := split(str,char "&") str := "" -- oops, if & is the last character in the string this method -- will eliminate it. Need to redo this. for s in strlist repeat str := concat [str,s,"&amp;"] strlen:Integer := #str str := str.(1..(#str - 5)) WriteLine(str)$Lisp
-- Here I split the string into lines and put each line in a "div".
strlist := split(str, char string NewlineChar$Lisp) str := "" WriteLine("formatMessages1")$Lisp
WriteLine(concat strlist)$Lisp for s in strlist repeat WriteLine(s)$Lisp
str := concat [str,"<div>",s,"</div>"]
str
@

\section{Axiom javascript}

The javascript is currently included in a "script" element in the
Axiom xml page.

<<axiom javascript>>=

function init() {
}

function makeRequest() {
//    The following instantiation of the XMLHttpRequest object is for
//    browsers other than IE.  IE requires something different.
http_request = new XMLHttpRequest();
var command = document.getElementById('comm').value;
http_request.open('POST', '127.0.0.1:8085', true);
'application/x-www-form-urlencoded');
//    http_request.send("command="+encodeURIComponent(command));
http_request.send("command="+command);
}

function handleResponse() {
if (http_request.readyState == 4) {
if (http_request.status == 200) {
// stick response in div=mathBox
var mathString = http_request.responseText;
var mathRange = document.createRange();
var mathBox =
document.createElementNS('http://www.w3.org/1999/xhtml','div');
mathRange.selectNodeContents(mathBox);
var mathFragment = mathRange.createContextualFragment(mathString);
mathBox.appendChild(mathFragment);
// set id on mathBox
//          var stepNum = mathBox.firstChild.firstChild.data;
//          mathBox.setAttribute('id', 'step'+stepNum);
//          mathBox.setAttribute('class', 'mathbox');
// remove old mathbox

document.getElementById('mathAns').removeChild(document.getElementById('mathAns').firstChild)

// insert everything into the document

document.getElementById('mathAns').appendChild(mathBox);

// delete linenum box
//            mathBox.removeChild(mathBox.firstChild);

} else
{
alert('There was a problem with the request.'+
http_request.statusText);
}
}
}

@

\section{Axiom xml}

Extract the Axiom xml interface page with the commmand

notangle -RAxiom$\backslash$ xml axserver.pamphlet $>$ axiom.xml

or in fact make the file name whatever you like instead of
"axiom.xml".

<<Axiom xml>>=
<?xml version="1.0" encoding="UTF-8"?>
<!--
-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1 plus MathML 2.0//EN"
"http://www.w3.org/Math/DTD/mathml2/xhtml-math11-f.dtd"; [
<!ENTITY mathml "http://www.w3.org/1998/Math/MathML";>
<!ENTITY InvisibleTimes " ">
]>

<html xmlns="http://www.w3.org/1999/xhtml";

<title>Axiom Interface</title>
<script type="text/javascript">
<<axiom javascript>>
</script>

<body id="body">

<form id="commreq" action="javascript:makeRequest();">
<p>
Enter command: <input type="text" id="comm" name="command" size="80"/>
<input type="submit" value="submit command"/>
</p>
</form>

<div id="mathAns"><div></div></div>

</body>

</html>

@

\section{Running Axiom Server}

Put the extracted files in a suitable directory, like the one you
started Axiom from, and issue the commands:

)set output mathml on

)compile axserver

axServer(8085,multiServ\\$AXSERV)

Of course you need a mathml enabled build of axiom to do this.
You may also want to issue the command

)set messages autoload off

before starting the Axiom server.

--Copyright (c) 2007 Arthur C. Ralfs
--
--Redistribution and use in source and binary forms, with or without
--modification, are permitted provided that the following conditions are
--met:
--
--    - Redistributions of source code must retain the above copyright
--      notice, this list of conditions and the following disclaimer.
--
--    - Redistributions in binary form must reproduce the above copyright
--      notice, this list of conditions and the following disclaimer in
--      the documentation and/or other materials provided with the
--      distribution.
--
--    - Neither the name of Arthur C. Ralfs nor the
--      names of its contributors may be used to endorse or promote products
--      derived from this software without specific prior written permission.
--
--THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
--IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
--TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
--PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
--OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
--EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
--PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
--PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
--LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
--NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
--SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

@

Copyright (c) 2007 Arthur C. Ralfs

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:

- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.

- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.

- Neither the name of Arthur C. Ralfs nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

@

<<*>>=
\end{document}