Commit 34f49a86 authored by Alexandre Duret-Lutz's avatar Alexandre Duret-Lutz

Preliminary implementation of an ajax-based ltl2tgba translator.

* configure.ac: Output wrap/python/ajax/Makefile.
* wrap/python/Makefile.am (SUBDIRS): Add ajax.
* wrap/python/ajax/Makefile.am, wrap/python/ajax/README,
wrap/python/ajax/ltl2tgba.html, wrap/python/ajax/spot.in: New files.
* wrap/python/ajax/css/, wrap/python/ajax/js,
wrap/python/ajax/logos: New directories.
* README: Document wrap/python/ajax/.
parent dc2a89f8
2011-01-18 Alexandre Duret-Lutz <adl@lrde.epita.fr>
Preliminary implementation of an ajax-based ltl2tgba translator.
* configure.ac: Output wrap/python/ajax/Makefile.
* wrap/python/Makefile.am (SUBDIRS): Add ajax.
* wrap/python/ajax/Makefile.am, wrap/python/ajax/README,
wrap/python/ajax/ltl2tgba.html, wrap/python/ajax/spot.in: New files.
* wrap/python/ajax/css/, wrap/python/ajax/js,
wrap/python/ajax/logos: New directories.
* README: Document wrap/python/ajax/.
2011-01-17 Alexandre Duret-Lutz <adl@lrde.epita.fr>
Do not output empty parse error blocks in the CGI script.
......
......@@ -143,6 +143,7 @@ wrap/ Wrappers for other languages.
python/ Python bindings for Spot and BuDDy
tests/ Tests for these bindings
cgi-bin/ Python-based CGI script (ltl-to-tgba translator)
ajax/ Moderner LTL-to-TGBA translator, using Ajax.
iface/ Interfaces to other libraries.
gspn/ GreatSPN interface.
examples/ Supporting models used by the test cases.
......
# Copyright (C) 2008, 2009, 2010 Laboratoire de Recherche et
# Copyright (C) 2008, 2009, 2010, 2011 Laboratoire de Recherche et
# Dveloppement de l'Epita (LRDE).
# Copyright (C) 2003, 2004, 2005, 2006, 2007 Laboratoire d'Informatique de
# Paris 6 (LIP6), dpartement Systmes Rpartis Coopratifs (SRC), Universit
......@@ -134,6 +134,7 @@ AC_CONFIG_FILES([
src/tgbatest/Makefile
wrap/Makefile
wrap/python/Makefile
wrap/python/ajax/Makefile
wrap/python/cgi-bin/Makefile
wrap/python/tests/Makefile
])
......
## Copyright (C) 2010 Laboratoire de Recherche et Development de
## Copyright (C) 2010, 2011 Laboratoire de Recherche et Development de
## l'Epita (LRDE).
## Copyright (C) 2003, 2004 Laboratoire d'Informatique de Paris 6 (LIP6),
## dpartement Systmes Rpartis Coopratifs (SRC), Universit Pierre
......@@ -21,7 +21,7 @@
## Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
## 02111-1307, USA.
SUBDIRS = . cgi-bin tests
SUBDIRS = . cgi-bin ajax tests
AM_CPPFLAGS = -I$(PYTHONINC) -I$(top_srcdir)/src $(BUDDY_CPPFLAGS) \
-DSWIG_TYPE_TABLE=spot
......
## Copyright (C) 2011 Laboratoire d'Informatique de Paris 6 (LIP6),
## dpartement Systmes Rpartis Coopratifs (SRC), Universit Pierre
## et Marie Curie.
##
## This file is part of Spot, a model checking library.
##
## Spot is free software; you can redistribute it and/or modify it
## under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2 of the License, or
## (at your option) any later version.
##
## Spot is distributed in the hope that it will be useful, but WITHOUT
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
## or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
## License for more details.
##
## You should have received a copy of the GNU General Public License
## along with Spot; see the file COPYING. If not, write to the Free
## Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
## 02111-1307, USA.
nodist_noinst_SCRIPTS = spot.py
EXTRA_DIST = $(srcdir)/spot.in README ltl2tgba.html css/ltl2tgba.css \
css/tipTip.css js/jquery.tipTip.minified.js logos/lip6sys64.png \
logos/lrde64.png logos/spot64s.png \
css/ui-lightness/jquery-ui-1.8.8.custom.css \
css/ui-lightness/images/ui-icons_222222_256x240.png \
css/ui-lightness/images/ui-bg_glass_100_f6f6f6_1x400.png \
css/ui-lightness/images/ui-bg_glass_100_fdf5ce_1x400.png \
css/ui-lightness/images/ui-bg_diagonals-thick_18_b81900_40x40.png \
css/ui-lightness/images/ui-icons_ffd27a_256x240.png \
css/ui-lightness/images/ui-icons_ffffff_256x240.png \
css/ui-lightness/images/ui-icons_228ef1_256x240.png \
css/ui-lightness/images/ui-bg_flat_10_000000_40x100.png \
css/ui-lightness/images/ui-bg_highlight-soft_100_eeeeee_1x100.png \
css/ui-lightness/images/ui-icons_ef8c08_256x240.png \
css/ui-lightness/images/ui-bg_gloss-wave_35_f6a828_500x100.png \
css/ui-lightness/images/ui-bg_glass_65_ffffff_1x400.png \
css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png \
css/ui-lightness/images/ui-bg_highlight-soft_75_ffe45c_1x100.png
CLEANFILES = $(nodist_noinst_SCRIPTS)
spot.py: $(srcdir)/spot.in Makefile
sed -e 's|[@]PYTHON[@]|@PYTHON@|g' \
-e 's|[@]pythondir[@]|@pythondir@|g' \
-e 's|[@]srcdir[@]|@srcdir@|g' \
-e 's|[@]top_builddir[@]|@top_builddir@|g' \
-e 's|[@]PACKAGE_VERSION[@]|@PACKAGE_VERSION@|g' \
-e 's|[@]DOT[@]|@DOT@|g' \
<$(srcdir)/spot.in >spot.tmp
chmod +x spot.tmp
mv -f spot.tmp $@
clean-local:
rm -rf spotimg
ltl2tgba.html is a dynamic web page that translates user-supplied LTL
formulae to Transition-based Generalized Büchi Automata. The actual
translation work is performed by a CGI script in Python: spot.py.
This is actually meant to be a moderner rewrite of the cgi script in
../cgi-bin/
There are two ways to use the page: using a web server such as
Apache, or standalone.
In both cases you should ensure that the command `dot', from the
GraphViz package, is in the PATH. configure should have picked it up.
Standalone usage
================
Simply run the spot.py from this directory. This will create a
directory called spotimg/ in the current directory (this will hold the
generated pictures) and start an HTTP server on port 8000. Point your
browser to http://localhost:8000/ltl2tgba.html and you should be OK.
After you have killed the server process (e.g. with Control-C),
you may want to erase the spotimg/ directory.
Installing on a real web server
===============================
1) Install Spot first (run `make install' from the top-level).
The CGI script uses the Python bindings and assume they
have been installed. Near the top of the script, you
should see a call to sys.path.insert(), with the expected
location of the Python bindings for spot. This path was
configured from ./configure's arguments and you should not
have to fiddle with it. I'm mentionning it just in case.
2) Copy spot.py to some place were CGI execution is allowed.
Depending on your HTTP server's configuration, you may have
to rename the script as spot.cgi or something else, so
that the server accepts to run it.
Apache users in trouble should look at the following options
before digging the Apache manual deeper. These can go
in a .htaccess file (if allowed).
# Treat *.py files as CGI scripts
AddHandle cgi-script .py
# Allow CGI execution in some directory.
Options +ExecCGI
3) In the directory where you have installed spot.py,
create a subdirectory called spotimg/. This is where
the script will output its images and other temporary
files. (If you want to change this name, see the imgdir
variable at the top of the script.)
This directory must be writable by the Unix user that
will run the script when the HTTP server processes the
request.
spot.py purges old files (>15min) from this directory
each time it runs.
4) Copy the directories css/, js/, and logos/ along with ltl2tgba.html
to there destination. You may have to adjust a few paths at the
top of the html page.
html {overflow-y:scroll;}
.ltl2tgba .ui-widget {
font-size: 1em;
}
div.ltl2tgba {
width: 800px;
position:relative;
left:0px;
top:0px;
margin-left: auto;
margin-right: auto;
z-index:10;
}
#spotlogo {
position:fixed;
left:10px;
top:10px;
z-index:1;
}
#lrdelogo {
position:fixed;
left:10px;
bottom:84px;
z-index:1;
}
#lip6logo {
position:fixed;
left:10px;
bottom:10px;
z-index:1;
}
.ltl2tgba div.ui-widget-content {
padding: 3px;
margin: 2px 0px;
}
.ltl2tgba h3 {
font-size:1em;
margin: 0;
padding: 0px 0.2em 0px;
border-bottom:1px solid #eee;
text-transform: capitalize;
}
.ltl2tgba .head .ui-icon {
float: right;
margin: 0.2em 0px;
}
.ltl2tgba .formula, #tiptip_content .formula {
font-family: monospace;
font-weight: bold;
font-size: 1.1em;
}
.ltl2tgba .parse-error {
font-family: monospace;
white-space: pre;
color: red;
font-size: 1.1em;
}
.ltl2tgba .ec-error {
color: red;
}
.ltl2tgba .neverclaim, .ltl2tgba .accrun {
font-family: monospace;
white-space: pre;
font-size: 1.1em;
}
/* TipTip CSS - Version 1.2 */
#tiptip_holder {
display: none;
position: absolute;
top: 0;
left: 0;
z-index: 99999;
}
#tiptip_holder.tip_top {
padding-bottom: 5px;
}
#tiptip_holder.tip_bottom {
padding-top: 5px;
}
#tiptip_holder.tip_right {
padding-left: 5px;
}
#tiptip_holder.tip_left {
padding-right: 5px;
}
#tiptip_content {
font-family: Trebuchet MS, Tahoma, Verdana, Arial, sans-serif;
font-size: 1em;
color: #fff;
text-shadow: 0 0 2px #000;
padding: 4px 8px;
border: 1px solid rgba(255,255,255,0.25);
background-color: rgb(25,25,25);
background-color: rgba(25,25,25,0.92);
background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, from(transparent), to(#000));
border-radius: 3px;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
box-shadow: 0 0 3px #555;
-webkit-box-shadow: 0 0 3px #555;
-moz-box-shadow: 0 0 3px #555;
}
#tiptip_arrow, #tiptip_arrow_inner {
position: absolute;
border-color: transparent;
border-style: solid;
border-width: 6px;
height: 0;
width: 0;
}
#tiptip_holder.tip_top #tiptip_arrow {
border-top-color: #fff;
border-top-color: rgba(255,255,255,0.35);
}
#tiptip_holder.tip_bottom #tiptip_arrow {
border-bottom-color: #fff;
border-bottom-color: rgba(255,255,255,0.35);
}
#tiptip_holder.tip_right #tiptip_arrow {
border-right-color: #fff;
border-right-color: rgba(255,255,255,0.35);
}
#tiptip_holder.tip_left #tiptip_arrow {
border-left-color: #fff;
border-left-color: rgba(255,255,255,0.35);
}
#tiptip_holder.tip_top #tiptip_arrow_inner {
margin-top: -7px;
margin-left: -6px;
border-top-color: rgb(25,25,25);
border-top-color: rgba(25,25,25,0.92);
}
#tiptip_holder.tip_bottom #tiptip_arrow_inner {
margin-top: -5px;
margin-left: -6px;
border-bottom-color: rgb(25,25,25);
border-bottom-color: rgba(25,25,25,0.92);
}
#tiptip_holder.tip_right #tiptip_arrow_inner {
margin-top: -6px;
margin-left: -5px;
border-right-color: rgb(25,25,25);
border-right-color: rgba(25,25,25,0.92);
}
#tiptip_holder.tip_left #tiptip_arrow_inner {
margin-top: -6px;
margin-left: -7px;
border-left-color: rgb(25,25,25);
border-left-color: rgba(25,25,25,0.92);
}
/* Webkit Hacks */
@media screen and (-webkit-min-device-pixel-ratio:0) {
#tiptip_content {
padding: 4px 8px 5px 8px;
background-color: rgba(45,45,45,0.88);
}
#tiptip_holder.tip_bottom #tiptip_arrow_inner {
border-bottom-color: rgba(45,45,45,0.88);
}
#tiptip_holder.tip_top #tiptip_arrow_inner {
border-top-color: rgba(20,20,20,0.92);
}
}
This diff is collapsed.
/*
* TipTip
* Copyright 2010 Drew Wilson
* www.drewwilson.com
* code.drewwilson.com/entry/tiptip-jquery-plugin
*
* Version 1.3 - Updated: Mar. 23, 2010
*
* This Plug-In will create a custom tooltip to replace the default
* browser tooltip. It is extremely lightweight and very smart in
* that it detects the edges of the browser window and will make sure
* the tooltip stays within the current window size. As a result the
* tooltip will adjust itself to be displayed above, below, to the left
* or to the right depending on what is necessary to stay within the
* browser window. It is completely customizable as well via CSS.
*
* This TipTip jQuery plug-in is dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
*/
(function($){$.fn.tipTip=function(options){var defaults={activation:"hover",keepAlive:false,maxWidth:"200px",edgeOffset:3,defaultPosition:"bottom",delay:400,fadeIn:200,fadeOut:200,attribute:"title",content:false,enter:function(){},exit:function(){}};var opts=$.extend(defaults,options);if($("#tiptip_holder").length<=0){var tiptip_holder=$('<div id="tiptip_holder" style="max-width:'+opts.maxWidth+';"></div>');var tiptip_content=$('<div id="tiptip_content"></div>');var tiptip_arrow=$('<div id="tiptip_arrow"></div>');$("body").append(tiptip_holder.html(tiptip_content).prepend(tiptip_arrow.html('<div id="tiptip_arrow_inner"></div>')))}else{var tiptip_holder=$("#tiptip_holder");var tiptip_content=$("#tiptip_content");var tiptip_arrow=$("#tiptip_arrow")}return this.each(function(){var org_elem=$(this);if(opts.content){var org_title=opts.content}else{var org_title=org_elem.attr(opts.attribute)}if(org_title!=""){if(!opts.content){org_elem.removeAttr(opts.attribute)}var timeout=false;if(opts.activation=="hover"){org_elem.hover(function(){active_tiptip()},function(){if(!opts.keepAlive){deactive_tiptip()}});if(opts.keepAlive){tiptip_holder.hover(function(){},function(){deactive_tiptip()})}}else if(opts.activation=="focus"){org_elem.focus(function(){active_tiptip()}).blur(function(){deactive_tiptip()})}else if(opts.activation=="click"){org_elem.click(function(){active_tiptip();return false}).hover(function(){},function(){if(!opts.keepAlive){deactive_tiptip()}});if(opts.keepAlive){tiptip_holder.hover(function(){},function(){deactive_tiptip()})}}function active_tiptip(){opts.enter.call(this);tiptip_content.html(org_title);tiptip_holder.hide().removeAttr("class").css("margin","0");tiptip_arrow.removeAttr("style");var top=parseInt(org_elem.offset()['top']);var left=parseInt(org_elem.offset()['left']);var org_width=parseInt(org_elem.outerWidth());var org_height=parseInt(org_elem.outerHeight());var tip_w=tiptip_holder.outerWidth();var tip_h=tiptip_holder.outerHeight();var w_compare=Math.round((org_width-tip_w)/2);var h_compare=Math.round((org_height-tip_h)/2);var marg_left=Math.round(left+w_compare);var marg_top=Math.round(top+org_height+opts.edgeOffset);var t_class="";var arrow_top="";var arrow_left=Math.round(tip_w-12)/2;if(opts.defaultPosition=="bottom"){t_class="_bottom"}else if(opts.defaultPosition=="top"){t_class="_top"}else if(opts.defaultPosition=="left"){t_class="_left"}else if(opts.defaultPosition=="right"){t_class="_right"}var right_compare=(w_compare+left)<parseInt($(window).scrollLeft());var left_compare=(tip_w+left)>parseInt($(window).width());if((right_compare&&w_compare<0)||(t_class=="_right"&&!left_compare)||(t_class=="_left"&&left<(tip_w+opts.edgeOffset+5))){t_class="_right";arrow_top=Math.round(tip_h-13)/2;arrow_left=-12;marg_left=Math.round(left+org_width+opts.edgeOffset);marg_top=Math.round(top+h_compare)}else if((left_compare&&w_compare<0)||(t_class=="_left"&&!right_compare)){t_class="_left";arrow_top=Math.round(tip_h-13)/2;arrow_left=Math.round(tip_w);marg_left=Math.round(left-(tip_w+opts.edgeOffset+5));marg_top=Math.round(top+h_compare)}var top_compare=(top+org_height+opts.edgeOffset+tip_h+8)>parseInt($(window).height()+$(window).scrollTop());var bottom_compare=((top+org_height)-(opts.edgeOffset+tip_h+8))<0;if(top_compare||(t_class=="_bottom"&&top_compare)||(t_class=="_top"&&!bottom_compare)){if(t_class=="_top"||t_class=="_bottom"){t_class="_top"}else{t_class=t_class+"_top"}arrow_top=tip_h;marg_top=Math.round(top-(tip_h+5+opts.edgeOffset))}else if(bottom_compare|(t_class=="_top"&&bottom_compare)||(t_class=="_bottom"&&!top_compare)){if(t_class=="_top"||t_class=="_bottom"){t_class="_bottom"}else{t_class=t_class+"_bottom"}arrow_top=-12;marg_top=Math.round(top+org_height+opts.edgeOffset)}if(t_class=="_right_top"||t_class=="_left_top"){marg_top=marg_top+5}else if(t_class=="_right_bottom"||t_class=="_left_bottom"){marg_top=marg_top-5}if(t_class=="_left_top"||t_class=="_left_bottom"){marg_left=marg_left+5}tiptip_arrow.css({"margin-left":arrow_left+"px","margin-top":arrow_top+"px"});tiptip_holder.css({"margin-left":marg_left+"px","margin-top":marg_top+"px"}).attr("class","tip"+t_class);if(timeout){clearTimeout(timeout)}timeout=setTimeout(function(){tiptip_holder.stop(true,true).fadeIn(opts.fadeIn)},opts.delay)}function deactive_tiptip(){opts.exit.call(this);if(timeout){clearTimeout(timeout)}tiptip_holder.fadeOut(opts.fadeOut)}}})}})(jQuery);
\ No newline at end of file
This diff is collapsed.
#!@PYTHON@
# -*- mode: python; coding: iso-8859-1 -*-
# Copyright (C) 2011 Laboratoire de Recherche et Dveloppement de
# l'Epita (LRDE).
#
# This file is part of Spot, a model checking library.
#
# Spot is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# Spot is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
# License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Spot; see the file COPYING. If not, write to the Free
# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
import os
# Directory for temporary files (images and other auxiliary files).
imgdir = 'spotimg'
# Location of the dot command
dot = '@DOT@'
dot_bgcolor = '-Gbgcolor=#FFFFFF00'
svg_output = False # FIXME: SVG output seems to be working well with
# Firefox only. We have to figure out how
# to get the correct size and transparent
# background in Chrome.
from CGIHTTPServer import CGIHTTPRequestHandler
class MyHandler(CGIHTTPRequestHandler):
def is_cgi(self):
if self.path.startswith('/cgi-bin/spot.py'):
self.cgi_info = '', self.path[9:]
return True
return False
if not os.environ.has_key('SCRIPT_NAME'):
# If this is not run as a cgi script, let's start an HTTP server.
from BaseHTTPServer import HTTPServer
server_address=('',8000)
if not os.access(imgdir, os.F_OK):
os.mkdir(imgdir, 0755)
print "Directory spotimg/ created."
httpd = HTTPServer(server_address, MyHandler)
print "Point your browser to http://localhost:8000/ltl2tgba.html"
httpd.serve_forever()
import sys
import cgi
import cgitb; cgitb.enable()
import signal
import uuid
print "Content-Type: text/html"
print
# Redirect stderr to stdout.
os.close(sys.stderr.fileno())
os.dup2(sys.stdout.fileno(), sys.stderr.fileno())
# Assume Spot is installed
sys.path.insert(0, '@pythondir@')
if (os.environ.has_key('SERVER_SOFTWARE') and
os.environ['SERVER_SOFTWARE'].startswith(MyHandler.server_version)):
# We might be running from the build tree (but it's not sure).
# Add the build and source directories first in the search path.
# If we are not in the right place, python will find the installed
# libraries later.
sys.path.insert(0, '@srcdir@/../.libs')
sys.path.insert(0, '@srcdir@/..')
sys.path.insert(0, '../.libs')
sys.path.insert(0, '..')
# Darwin needs some help in figuring out where non-installed libtool
# libraries are (on this platform libtool encodes the expected final
# path of dependent libraries in each library).
m = '../.libs:@top_builddir@/src/.libs:@top_builddir@/buddy/src/.libs'
os.environ['DYLD_LIBRARY_PATH'] = m
try:
execfile('ltl2tgba.opt')
except IOError:
pass
import spot
import buddy
def alarm_handler(signum, frame):
print """<p><font color="red">The script was aborted because
it has been running for too long.</font> Please try a shorter formula,
or different options (not drawing automata usually helps).
If you want to benchmark big formulae it is
better to install Spot on your own computer.</p>"""
sys.stdout.flush()
os.kill(0, signal.SIGTERM)
def reset_alarm():
signal.alarm(30)
def render_dot(basename):
print '<div class="dot">'
if svg_output:
ext = 'svg'
else:
ext = 'png'
os.spawnlp(os.P_WAIT, dot, dot, dot_bgcolor, '-T' + ext,
'-Gsize=8.2,8.2', '-o', basename + '.' + ext, basename + '.txt')
reset_alarm()
b = cgi.escape(basename)
if svg_output:
print ('<object type="image/svg+xml" data="' + b + '.svg">'
+ 'Your browser does not support SVG.</object>')
else:
print ('<img src="' + b + '.png"><br>(<a href="' + b
+ '.txt">dot source</a>)')
print '</div>'
sys.stdout.flush()
def render_automaton(basename, automata, dont_run_dot, deco = False):
outfile = spot.ofstream(basename + '.txt')
if not deco:
spot.dotty_reachable(outfile, automata)
else:
spot.dotty_reachable(outfile, automata, deco)
del outfile
if dont_run_dot:
print ('<p>' + dont_run_dot + ''' to be rendered on-line. However
you may download the <a href="''' + cgi.escape(basename)
+ '.txt">source in dot format</a> and render it yourself.')
else:
render_dot(basename)
def print_stats(automaton):
stats = spot.stats_reachable(automaton)
print "<p>", stats.states,
if stats.states <= 1:
print " state,",
else:
print " states,",
print stats.transitions,
if stats.transitions <= 1:
print " transition,",
else:
print " transitions,",
# compute the number of acceptance conditions
count = automaton.number_of_acceptance_conditions()
if count > 0: