[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
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
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 := ""
-- 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,"&"]
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>
<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,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}
Message not available