###
### Runs Axiom and returns a latex code block for each Axiom block
###
import os, sys, re, popen2, glob
import zLOG
from util import fileNameFor, workingDir
from cgi import escape
# For testing without Zope
#workingDir = './'
#def fileNameFor(code,num,ext):
# return 'axiom'+ext
class AxiomSyntaxError(Exception): pass
axiomTemplate = r""")set output algebra off
)set output tex on
)set message autoload off
)set quit unprotected
%s)quit
"""
outputPattern = r'(.*?)\s*\n\(\d+\) -> '
reConsts = re.MULTILINE+re.DOTALL
def log(message,summary='',severity=0):
zLOG.LOG('LatexWikiDebugLog',severity,summary,message)
def renderAxiom(axiomCodeList):
def securityCheck(code):
newCode = re.compile(r'^[ \t]*\)sys([^\n]*)',reConsts).sub(r'-- not allowed: )sys\1\n)sys',code)
# newCode = re.compile(r'^[ \t]*\)lisp([^\n]*)',reConsts).sub(r'-- not allowed: )lisp\1\n)sys',newCode)
newCode = re.compile(r'^[ \t]*\)fin([^\n]*)',reConsts).sub(r'-- not allowed: )fin\1\n)sys',newCode)
newCode = re.compile(r'^[ \t]*\)spool([^\n]*)',reConsts).sub(r'-- not allowed: )spool\1\n)sys',newCode)
return newCode
n = 0
unifiedCode = ''
for axiomCode in axiomCodeList:
newAxiomCode = securityCheck(axiomCode)
n = n + 1
if re.match(r'^\s*\)abb',newAxiomCode):
# Starts like spad so compile as library code
axiomFileName = os.path.join(workingDir,fileNameFor(newAxiomCode, 25, '.%3.3d.spad'%n))
unifiedCode = unifiedCode + ')set message prompt none\n'
unifiedCode = unifiedCode + ')sys cat %s\n'%axiomFileName
unifiedCode = unifiedCode + ')compile %s\n'%axiomFileName
unifiedCode = unifiedCode + ')set message prompt step\n'
elif re.match(r'^\\begin *{spad}\s*.*?\s*\\end *{spad}',newAxiomCode,
reConsts):
# spad so compile as library code
m = re.match(r'^\\begin *{spad}\s*(.*?)\s*\\end *{spad}',
newAxiomCode,reConsts)
newAxiomCode = m.group(1) # just the spad code
axiomFileName = os.path.join(workingDir,fileNameFor(newAxiomCode, 25, '%3.3d.spad'%n))
unifiedCode = unifiedCode + ')set message prompt none\n'
unifiedCode = unifiedCode + ')sys echo "";cat %s;echo ""\n'%axiomFileName
unifiedCode = unifiedCode + ')compile %s\n'%axiomFileName
unifiedCode = unifiedCode + ')set message prompt step\n'
elif re.match(r'^\\begin *{aldor}\s*.*?\s*\\end *{aldor}',newAxiomCode,
reConsts):
# aldor so compile as library code
m = re.match(r'^\\begin *{aldor} *(?:\[(.*?)\])?\s*(.*?)\s*\\end *{aldor}',
newAxiomCode,reConsts)
if m.group(1): # optional file name
axiomFileName = os.path.join(workingDir,m.group(1)+'.as')
else :
axiomFileName = os.path.join(workingDir,fileNameFor(newAxiomCode, 25, '%3.3d.as'%n))
newAxiomCode = m.group(2) # just the aldor code
unifiedCode = unifiedCode + ')set message prompt none\n'
unifiedCode = unifiedCode + ')sys echo "";cat %s;echo ""\n'%axiomFileName
unifiedCode = unifiedCode + ')compile %s\n'%axiomFileName
unifiedCode = unifiedCode + ')set message prompt step\n'
elif re.match(r'^\\begin *{boot}\s*.*?\s*\\end *{boot}',newAxiomCode, reConsts):
m = re.match(r'^\\begin *{boot}\s*(.*?)\s*\\end *{boot}',
newAxiomCode,reConsts)
newAxiomCode = m.group(1) # just the boot code
fileName = fileNameFor(newAxiomCode, 25, '%3.3d'%n)
axiomFileName = os.path.join(workingDir,fileName+'.boot')
axiomFileName2 = fileName+'.clisp'
unifiedCode = unifiedCode + ')set message prompt none\n'
unifiedCode = unifiedCode + ')sys echo "";cat %s;echo ""\n'%axiomFileName
unifiedCode = unifiedCode + ')lisp (boottran::boottocl "%s")\n'%axiomFileName
unifiedCode = unifiedCode + ')lisp (load (compile-file (truename (concat (si:getenv "AXIOM") "/../../int/interp/%s"))))\n'%axiomFileName2
unifiedCode = unifiedCode + ')set message prompt step\n'
elif re.match(r'^\\begin *{lisp}\s*.*?\s*\\end *{lisp}',newAxiomCode, reConsts):
m = re.match(r'^\\begin *{lisp}\s*(.*?)\s*\\end *{lisp}',
newAxiomCode,reConsts)
newAxiomCode = m.group(1) # just the lisp code
axiomFileName = os.path.join(workingDir,fileNameFor(newAxiomCode, 25, '%3.3d.lisp'%n))
unifiedCode = unifiedCode + ')set message prompt none\n'
unifiedCode = unifiedCode + ')sys echo "";cat %s;echo ""\n'%axiomFileName
unifiedCode = unifiedCode + ')lisp (load (compile-file "%s"))\n'%axiomFileName
unifiedCode = unifiedCode + ')set message prompt step\n'
else:
# otherwise it is just an input file
axiomFileName = os.path.join(workingDir,fileNameFor(newAxiomCode, 25, '.%3.3d.input'%n))
unifiedCode = unifiedCode + ')read %s\n'%axiomFileName
axiomFile = open(axiomFileName, 'w')
axiomFile.write(newAxiomCode)
axiomFile.close()
if unifiedCode:
try:
latexCode=runAxiom(unifiedCode,axiomTemplate)
latexCodeList = re.compile(outputPattern, reConsts).findall(latexCode)
return (latexCodeList,'')
except AxiomSyntaxError, data:
errors = str(data)
log(errors, 'AxiomSyntaxError')
return ([],escape(errors))
return ([],'')
def runCommand(cmdLine):
program = popen2.Popen3('cd %s; '%(workingDir) + cmdLine, 1, 4096)
program.tochild.close()
stderr = ''
stdout = ''
while(not os.WIFEXITED(program.poll())):
# Seems Axiom doesn't properly close stderr
# stderr = stderr + program.childerr.read()
stdout = stdout + program.fromchild.read()
program.fromchild.close()
program.childerr.close()
status = program.poll()
error = os.WEXITSTATUS(status) or not os.WIFEXITED(status)
return error, stdout, stderr
def runAxiom(axiomCode, axiomTemplate):
axiomFileName = os.path.join(workingDir,fileNameFor(axiomCode, 25, '.axm'))
# problem: http://wiki.axiom-developer.org/145PipingCommandsToSmanDoesNotWork
#cmdLine = '/usr/bin/axiom < %s' %(axiomFileName)
#cmdLine = 'export AXIOM=/usr/local/axiom/mnt/linux; export PATH=$AXIOM/bin:$PATH; export ALDORROOT=/usr/local/aldor/linux/1.0.2; export PATH=$ALDORROOT/bin:$PATH; export HOME=/var/lib/plone2/main; AXIOMsys < %s' %(axiomFileName)
# enough for now on debian
cmdLine = 'export AXIOM=/usr/lib/axiom-20050901; $AXIOM/bin/AXIOMsys < %s' %(axiomFileName)
file = open(axiomFileName, 'w')
file.write(axiomTemplate%axiomCode)
file.close()
err, stdout, stderr = runCommand(cmdLine)
if err:
out = 'Error: ' + cmdLine + '\n' + stderr + '\n' + stdout
raise AxiomSyntaxError(out)
else:
# Clean up the startup prompts
newcode = re.compile(r'^.*?(?:\(1\) -> ){5}', reConsts).sub('',stdout)
# Temporary fix for Axiom bug \spadcommand{radix(10**90,32)}
newcode = re.compile(r'#\\', reConsts).sub('',newcode)
return newcode