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: Thu, 13 Sep 2007 21:53:21 -0700
User-agent: Thunderbird 1.5.0.12 (X11/20060911)

Here's a simple axiom  server example.  It consists of
three files, axserver.spad, http.lisp  and axiomax.xml, which I've
attached.  To test it out put the axserver.spad and http.lisp files
in a suitable place, like the directory from which you start axiom,
then issue the commands:

->  )set output mathml on
->  )lisp (load "http.lisp")
->  )compile axserver
->  axServer(8085,multiServ$AXSERV)

If I put the axiomax.xml file in my axiom directory then I enter the
URL http://127.0.0.1:8085/home/arthur/axiom/axiomax.xml into Firefox
to get the file.  Commands can then be entered via the text box.

Arthur Ralfs


<?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"; 
xmlns:xlink="http://www.w3.org/1999/xlink";>
<head>
<title>Axiom Interface</title>
<script type="text/javascript">
<!--
 This software is to enable displaying Axiom output on the Firefox 
 web browser.  It falls under the GNU version 2 general public license and 
comes 
 WITHOUT ANY WARRANTY WHATSOEVER.
 COPYRIGHT : (C) 2006 Arthur C. Ralfs
-->

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);
        }
    }
}

</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>
)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
        
;; 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)

reply via email to

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