login  home  contents  what's new  discussion  bug reports     help  links  subscribe  changes  refresh  edit

Edit detail for AxServer revision 1 of 3

1 2 3
Editor: alfredo
Time: 2008/03/16 19:56:27 GMT-7
Note:

changed:
-
\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
             headers := concat [headers,char]
         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)
             getFile(s,headers.u)
         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);
   http_request.onreadystatechange = handleResponse;
//    http_request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
//    http_request.send("command="+encodeURIComponent(command));
   http_request.setRequestHeader('Content-Type', 'text/plain');
   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"?>
<!--
<<license-xml>>
-->
<!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" xmlns:xlink="http://www.w3.org/1999/xlink">

<head>
<title>Axiom Interface</title>
&lt;disabled script type="text/javascript"&gt;
<<axiom javascript>>
&lt;disabled /script&gt;

</head>

<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

)lisp (load "http.lisp")

)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.


\section{License}
<<license>>=
--Copyright (c) 2007 Arthur C. Ralfs
--All rights reserved.
--
--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.


@

<<license-xml>>=
 Copyright (c) 2007 Arthur C. Ralfs
 All rights reserved.

 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.


@

<<*>>=
<<license>>
<<package AXSERV AxiomServer>>

@

\eject
\begin{thebibliography}{99}
\bibitem{1} nothing
\end{thebibliography}
\end{document}

Download: pdf dvi ps src tex log