axiom-developer
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Axiom-developer] Axiom server


From: Arthur Ralfs
Subject: [Axiom-developer] Axiom server
Date: Sun, 16 Sep 2007 08:12:07 -0700
User-agent: Thunderbird 1.5.0.12 (X11/20060911)

This is just the previous example I posted with everything
in one pamphlet file and with the right license.  The documentation
is minimal at this point.

Arthur Ralfs
\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{Preface}

\section{Lisp preliminaries}

Extract the lisp to a file named, say, http.lisp with the
command

notangle -RServer\ 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 := ""
        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\ 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>
<script type="text/javascript">
<<axiom javascript>>
</script>

</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,mutliServ$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}

reply via email to

[Prev in Thread] Current Thread [Next in Thread]