[Top][All Lists]
[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
-- &,<,>. 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 & and may also need to
-- replace < and > with < and >
strlist:List String
WriteLine(str)$Lisp
strlist := split(str,char "&")
str := ""
for s in strlist repeat
str := concat [str,s,"&"]
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)
- [Axiom-developer] Axiom server,
Arthur Ralfs <=