diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..dd50574
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,204 @@
+*.tmp
+pan.*
+
+*.iml
+gen/
+.idea/
+*.ipr
+*.iws
+/out/
+.idea_modules/
+atlassian-ide-plugin.xml
+com_crashlytics_export_strings.xml
+crashlytics.properties
+crashlytics-build.properties
+target/
+pom.xml.tag
+pom.xml.releaseBackup
+pom.xml.versionsBackup
+pom.xml.next
+release.properties
+dependency-reduced-pom.xml
+buildNumber.properties
+.mvn/timing.properties
+
+## Core latex/pdflatex auxiliary files:
+*.aux
+*.lof
+*.log
+*.lot
+*.fls
+*.out
+*.toc
+*.fmt
+*.fot
+*.cb
+*.cb2
+
+## Intermediate documents:
+*.dvi
+*-converted-to.*
+# these rules might exclude image files for figures etc.
+# *.ps
+# *.eps
+# *.pdf
+
+## Bibliography auxiliary files (bibtex/biblatex/biber):
+*.bbl
+*.bcf
+*.blg
+*-blx.aux
+*-blx.bib
+*.brf
+*.run.xml
+
+## Build tool auxiliary files:
+*.fdb_latexmk
+*.synctex
+*.synctex.gz
+*.synctex.gz(busy)
+*.pdfsync
+
+## Auxiliary and intermediate files from other packages:
+# algorithms
+*.alg
+*.loa
+
+# achemso
+acs-*.bib
+
+# amsthm
+*.thm
+
+# beamer
+*.nav
+*.snm
+*.vrb
+
+# cprotect
+*.cpt
+
+# fixme
+*.lox
+
+#(r)(e)ledmac/(r)(e)ledpar
+*.end
+*.?end
+*.[1-9]
+*.[1-9][0-9]
+*.[1-9][0-9][0-9]
+*.[1-9]R
+*.[1-9][0-9]R
+*.[1-9][0-9][0-9]R
+*.eledsec[1-9]
+*.eledsec[1-9]R
+*.eledsec[1-9][0-9]
+*.eledsec[1-9][0-9]R
+*.eledsec[1-9][0-9][0-9]
+*.eledsec[1-9][0-9][0-9]R
+
+# glossaries
+*.acn
+*.acr
+*.glg
+*.glo
+*.gls
+*.glsdefs
+
+# gnuplottex
+*-gnuplottex-*
+
+# hyperref
+*.brf
+
+# knitr
+*-concordance.tex
+# TODO Comment the next line if you want to keep your tikz graphics files
+*.tikz
+*-tikzDictionary
+
+# listings
+*.lol
+
+# makeidx
+*.idx
+*.ilg
+*.ind
+*.ist
+
+# minitoc
+*.maf
+*.mlf
+*.mlt
+*.mtc
+*.mtc[0-9]
+*.mtc[1-9][0-9]
+
+# minted
+_minted*
+*.pyg
+
+# morewrites
+*.mw
+
+# mylatexformat
+*.fmt
+
+# nomencl
+*.nlo
+
+# sagetex
+*.sagetex.sage
+*.sagetex.py
+*.sagetex.scmd
+
+# sympy
+*.sout
+*.sympy
+sympy-plots-for-*.tex/
+
+# pdfcomment
+*.upa
+*.upb
+
+# pythontex
+*.pytxcode
+pythontex-files-*/
+
+# thmtools
+*.loe
+
+# TikZ & PGF
+*.dpth
+*.md5
+*.auxlock
+
+# todonotes
+*.tdo
+
+# xindy
+*.xdy
+
+# xypic precompiled matrices
+*.xyc
+
+# endfloat
+*.ttt
+*.fff
+
+# Latexian
+TSWLatexianTemp*
+
+## Editors:
+# WinEdt
+*.bak
+*.sav
+
+# Texpad
+.texpadtmp
+
+# Kile
+*.backup
+
+# KBibTeX
+*~[0-9]*
\ No newline at end of file
diff --git a/docs/jspin-release.html b/docs/jspin-release.html
index 676106b..485ae4f 100644
--- a/docs/jspin-release.html
+++ b/docs/jspin-release.html
@@ -1,63 +1,63 @@
-
-
-
-jSpin - Release Notes
-
-
-
-jSpin - Release Notes
-
-Version 5.0 (12.12.10)
- Adapted for Spin Version 6:
-different output format and internal LTL formulas.
-
-
Version 4.7 (05.03.10)
- Add menu entry Settings/Negate LTL
-and the associated configuration file option NEGATE_LTL which
-controls whether LTL formulas are automatically negated or not.
- Changed the button Trail to Guided to be consistent:
-random simulation, interactive simulation, guided simulation.
-
-
Version 4.6
-The divider locations and the width of the interactive select
-buttons can be saved in the configuration file after changing them
-interactively. STATEMENT_WIDTH can be changed interactively.
-The installation directory may have spaces.
-
-
Version 4.5.1
Fix a bug when an LTL formula contains spaces.
-
-
Version 4.5
Improvements to interactive simulation.
-
-
Version 4.4
Configuration file can be in current or installation
-directory.
-
-
Version 4.3.1
Fixes a serious bug introduced in 4.3.
-
-
Version 4.3
Standalone filter program. Integration of user manuals.
-
-
Version 4.2.2
Self-installing archive and relative path names.
-
-
Version 4.2.1
For random simulation the seed can be set.
-
-
Version 4.2
New Version of SpinSpider for graphically
-displaying the Promela source as automata. Help, About and raw files now
-displayed in the right text area.
-
-
Version 4.1.3
Minor fixes: The full error line from a
-verification is displayed. The fonts on option panes are fixed.
-
-
Version 4.1.2
The default configuration values are changed
-to point to the bin subdirectory for installing minimal binaries for
-Spin and dot. For non-Windows systems such as Mac OS X: the compilation
-target is specified as Java 1.5. The SINGLE_QUOTE option
-enables the use of single quotes when translating an LTL formula.
-
-
Version 4.1.1
Not released.
-
-
Version 4.1
Lines numbers appear in the filtered simulation output.
-
-
Version 4.0
Includes the new SpinSpider and an improved
-interface for running it.
-
-
+
+
+
+jSpin - Release Notes
+
+
+
+jSpin - Release Notes
+
+Version 5.0 (12.12.10)
+ Adapted for Spin Version 6:
+different output format and internal LTL formulas.
+
+
Version 4.7 (05.03.10)
+ Add menu entry Settings/Negate LTL
+and the associated configuration file option NEGATE_LTL which
+controls whether LTL formulas are automatically negated or not.
+ Changed the button Trail to Guided to be consistent:
+random simulation, interactive simulation, guided simulation.
+
+
Version 4.6
+The divider locations and the width of the interactive select
+buttons can be saved in the configuration file after changing them
+interactively. STATEMENT_WIDTH can be changed interactively.
+The installation directory may have spaces.
+
+
Version 4.5.1
Fix a bug when an LTL formula contains spaces.
+
+
Version 4.5
Improvements to interactive simulation.
+
+
Version 4.4
Configuration file can be in current or installation
+directory.
+
+
Version 4.3.1
Fixes a serious bug introduced in 4.3.
+
+
Version 4.3
Standalone filter program. Integration of user manuals.
+
+
Version 4.2.2
Self-installing archive and relative path names.
+
+
Version 4.2.1
For random simulation the seed can be set.
+
+
Version 4.2
New Version of SpinSpider for graphically
+displaying the Promela source as automata. Help, About and raw files now
+displayed in the right text area.
+
+
Version 4.1.3
Minor fixes: The full error line from a
+verification is displayed. The fonts on option panes are fixed.
+
+
Version 4.1.2
The default configuration values are changed
+to point to the bin subdirectory for installing minimal binaries for
+Spin and dot. For non-Windows systems such as Mac OS X: the compilation
+target is specified as Java 1.5. The SINGLE_QUOTE option
+enables the use of single quotes when translating an LTL formula.
+
+
Version 4.1.1
Not released.
+
+
Version 4.1
Lines numbers appear in the filtered simulation output.
+
+
Version 4.0
Includes the new SpinSpider and an improved
+interface for running it.
+
+
\ No newline at end of file
diff --git a/docs/jspin-user.tex b/docs/jspin-user.tex
index 74a0d6d..de841f1 100644
--- a/docs/jspin-user.tex
+++ b/docs/jspin-user.tex
@@ -1,1003 +1,1003 @@
-\documentclass[11pt]{article}
-\usepackage{mathpazo}
-\usepackage{url}
-\usepackage{graphicx}
-\usepackage{verbatim}
-
-\newcommand{\spn}{\textsc{Spin}}
-\newcommand{\prm}{\textsc{Promela}}
-\newcommand{\js}{\textsc{jSpin}}
-\newcommand{\spd}{\textsc{SpinSpider}}
-\newcommand{\fil}{\textsc{FilterSpin}}
-\newcommand{\dt}{\textsc{dot}}
-\newcommand{\dtf}{\texttt{dot}}
-\newcommand{\fsm}{\texttt{fsm}}
-\newcommand{\p}[1]{\texttt{#1}}
-\newcommand{\bu}[1]{\textsf{#1}}
-
-\textwidth=15cm
-\textheight=22cm
-\topmargin=0pt
-\headheight=0pt
-\oddsidemargin=1cm
-\headsep=0pt
-\renewcommand{\baselinestretch}{1.1}
-\setlength{\parskip}{0.20\baselineskip plus 1pt minus 1pt}
-\parindent=0pt
-
-\title{\js{} - Java GUI for \spn{}\\User's Guide\\\mbox{}\\\large{Version 5.0}}
-\author{Mordechai (Moti) Ben-Ari\\
-Department of Science Teaching\\
-Weizmann Institute of Science\\
-Rehovot 76100 Israel\\
-\textsf{http://stwww.weizmann.ac.il/g-cs/benari/}}
-%\date{}
-\begin{document}
-\maketitle
-\thispagestyle{empty}
-
-\vfill
-
-\begin{center}
-Copyright (c) 2003-10 by Mordechai (Moti) Ben-Ari.
-\end{center}
-Permission is granted to copy, distribute and/or modify this document
-under the terms of the GNU Free Documentation License, Version 1.2
-or any later version published by the Free Software Foundation;
-with Invariant Section ``Introduction,'' no Front-Cover Texts, and no
-Back-Cover Texts. A copy of the license is included in the file
-\p{fdl.txt} included in this archive.
-\newpage
-
-\section{Introduction}
-
-\subsection{\js{}}
-\js{} is a graphical user interface for the \spn{} Model Checker that is
-used for verifying concurrent and distributed programs. It is an
-alternative to the \textsc{XSpin} GUI and was developed primarily for
-pedagogical purposes. \js{} is written in Java, because the Java
-platform is both portable and widely used in computer science education.
-The user interface of \js{} is simple, consisting of a single window
-with menus, a toolbar and three adjustable text areas. \spn{} option
-strings are automatically supplied and the \spn{} output is filtered and
-formatted. All aspects of \js{} are configurable: some at compile time,
-some at initialization through a configuration file and some at runtime.
-The filtering algorithm in \js{} can also be run as a standalone
-program.
-
-\subsection{\spd{}}
-\js{} includes the \spd{} tool for creating a graphical representation for
-the state diagram of a \prm{} program by postprocessor the \spn{} output.
-\spd{} is integrated into \js{}, but it can also be run as a standalone program.
-
-\spd{} generates the complete state diagram of a \prm{} program; the
-diagrams are useful for demonstrating properties of concurrent programming.
-Consider the \emph{third attempt} at solving the critical section problem (line
-numbers added):
-\begin{verbatim}
-1. bool wantp = false, wantq = false;
-2.
-3. active proctype p() {
-4. do :: wantp = true;
-5. !wantq;
-6. wantp = false;
-7. od
-8. }
-9.
-10. active proctype q() {
-11. do :: wantq = true;
-12. !wantp;
-13. wantq = false;
-14. od
-15. }
-\end{verbatim}
-The processes \p{p} and \p{q} are in their critical sections if they are at
-lines~6 and~13, respectively. The figure on the next page shows the state
-diagram for this program. Each node contains the source code lines (and line
-numbers) for the two processes and the values of the variables \p{wantp} and
-\p{wantq}. The arrows show the possible transitions between states. Since no
-state has the processes together at lines~6 and~13 mutual exclusion is
-achieved. It is easy to see there is a computation that leads to deadlock in
-the state with \p{p} at line~5 and \p{q} at line~15.
-\begin{figure}[!htb]
-\begin{center}
-\includegraphics[width=6cm,keepaspectratio=true]{third.png}
-\end{center}
-\end{figure}
-
-\spd{} processes output of the \p{pan} verifier in order to create the full
-state diagram of a program. The diagram is produced in \dtf{} format and
-(optionally) the \dt{} program can be run to produce a graphics file.
-\spd{} can also produce state diagrams in \fsm{} format used by visualization
-tools developed at the Technische Universiteit Eindhoven (see the URLs below).
-
-\subsection{References}
-\begin{itemize}
-\item M. Ben-Ari. \textit{Principles of the Spin Model Checker}. Springer, 2008.
-\item M. Ben-Ari. \textit{Principles of Concurrent and Distributed Programming (Second
-Edition)}. Addison-Wesley, 2006.
-\item Gerard J. Holzmann. \textit{The Spin Model Checker: Primer
-and Reference Manual}.\\Addison-Wesley, 2004.
-\end{itemize}
-
-\subsection{URLs}
-
-\begin{tabular}{l@{\hspace{3em}}l}
-\hline
-\fsm{} & \url{http://www.win.tue.nl/~fvham/fsm/}\\
- & \url{http://www.mcrl2.org/}\\
-\textsc{Graphviz (dot)} & \url{http://www.graphviz.org/}\\
-\js{} & \url{http://stwww.weizmann.ac.il/g-cs/benari/jspin/}\\
-\textsc{MinGW} & \url{http://mingw.org/}\\
-\spn{} & \url{http://spinroot.com/}\\
-\hline
-\end{tabular}
-
-\subsection{Acknowledgement}
-I would like to thank Gerard J. Holzmann for his generous assistance throughout the
-development of this project.
-
-\section{Installation and execution}
-
-\subsection{Requirements}
-\begin{itemize}
-
-\item \js{} requires that the Java SDK or JRE (at least version 1.5) be
-installed.\footnote{The default font for \js{} is \p{Lucida Sans
-Typewriter}. This font may no longer be available in the JRE you use. If
-you have the fonts from a previous version you can copy them to the
-\p{lib/fonts} directory as explained in
-\url{http://java.sun.com/j2se/1.5.0/docs/guide/intl/font.html}.
-Alternatively, you can change the configuration file to use a monospaced
-font such as \p{Courier} that is installed by default.}
-
-\end{itemize}
-
-\subsection{Installation}
-This section describes installation on a Windows system;
-for custom installation and for other systems, see Appendix~\ref{a.install}.
-
-\begin{itemize}
-\item Download the \js{} installation file called \p{jspin-N.exe},
-where \p{N} is the version number.
-Execute the installation file.
-\item Create a directory \verb=c:\mingw= and download the C
-compiler archive \p{mingw.exe} into that directory. Execute this self-extracting file.
-\end{itemize}
-
-\subsection{Configuring and running \js{}}
-\begin{itemize}
-\item The installation will create the following subdirectories: \p{docs} for the
-documentation, \p{jspin} and \p{spinSpider} for the source files,
-\p{txts} for the text files
-(help, about and copyright), and \p{jspin-examples} and \p{spider-examples}
-for example programs.
-\item To run \js{}, execute the command \p{javaw -jar jSpin.jar}.
-An optional argument names the \prm{} file to be opened initially.
-A batch file \p{run.bat} is supplied which contains this command.
-\item Configuration data (Appendix~\ref{a.cfg}) is in the file
-\p{config.cfg}.
-\textbf{When upgrading \js{}, erase the configuration file before installing
-a new version, so that new configuration options will be recognized.}
-\item \js{} searches for the configuration file in the current
-directory; if it is not found, \js{} searches for it in the directory
-where the jar file is installed; if it is not found there, a new file
-with default values is written.
-\end{itemize}
-
-\subsection{Running \spd{} without \js{}*}
-If you want to run \spd{} without \js{}, create a configuration file
-with entries for the \p{SPIN}, \p{C\_COMPILER}, \p{PAN} and \p{DOT}
-commands. The prologues for the \dtf{} file can be changed in
-\p{Config.java} in the package \p{spinSpider}.
-
-The \p{SpinSpider} class has a main method that can be invoked from a command
-line:
-\begin{verbatim}
-java -cp jSpin.jar spinSpider.SpinSpider arguments filename
-\end{verbatim}
-\p{filename} is the source file name. The arguments are:
-
-\hspace*{1cm}
-\begin{tabular}{ll}
-\p{-pn} & The number of processes \p{n};\\
-\p{-vname} & One parameter for each variable \p{name};\\
-\p{-dot} & \dtf{} format;\\
-\p{-Txxx} & \dtf{} format followed by conversion to \p{xxx} format,\\
-& the default is \p{png};\\
-\p{-fsm} & \fsm{} format;\\
-\p{-t1} & Emphasize trail;\\
-\p{-t2} & Display the trail only;\\
-\p{-a} & Display automata for \prm{} source;\\
-\p{-small} & Small size for states; if absent, large size is used;\\
-\p{-bold} & Bold for emphasis; if absent, color is used.\\
-\p{-debug} & Write debug file;\\
-\end{tabular}\\
-\noindent{}The \p{-p} and \p{-v} arguments must be given (unless \p{-a} is selected).
-
-\subsection{Running \fil{} without \js{}*}
-To run \fil{} from the command line, first create a file with the output
-of a (random or guided) simulation:
-\begin{verbatim}
- spin -p -l -g -r -s -X src.pml > src.raw
-\end{verbatim}
-Next, run \fil{}:
-\begin{verbatim}
- java -cp jSpin.jar filterSpin.FilterSpin src.raw
-\end{verbatim}
-There are two optional arguments: \p{-v} to give a list of excluded
-variables and \p{-s} to give a list of excluded statements, as described
-in Section~\ref{s.filter}. The arguments may be file names or lists of
-identifiers separated with a separator string (by default \p{"\#"}, but
-it can be changed in \p{Config.java}\footnote{Do not use a backslash or
-dollar sign.}). At least one separator must be given so that the
-argument is not interpreted as a file name):
-\begin{verbatim}
- java -cp jSpin.jar filterSpin.FilterSpin -v "temp#i" -s "i+1#" src.raw
-\end{verbatim}
-The filtered output is sent to standard output and can be piped or
-redirected as needed. The configuration file must contain values for the
-properties listed in Appendix~\ref{a.cfg} under \emph{filter settings}.
-
-\section{\js{} Overview}
-The user interface includes a menu, a toolbar and three text areas.
-Menu and toolbar commands have keyboard mnemonics or accelerators.
-These can be easily configured by modifying the file \p{Config.java} and
-rebuilding.
-
-The left text area is used to display \prm{} source files. The bottom
-text area is used to display messages from both \spn{} and \js{}. The
-right text area is used to display the output from \spn{}: statements
-executed, values of variables and results of verifications. The text
-areas can be resized by dragging the dividers and an area can be hidden
-by clicking on the triangles in the dividers; the initial sizes can be
-set in the configuration file. The toolbar button \bu{Maximize} (with
-its mnemonic \bu{Alt-M}) toggles between a normal split pane and a
-maximized right text area that displays the \spn{} output.
-
-\begin{figure}[tb]
-\begin{center}
-\includegraphics[width=140mm]{jspin.png}
-\end{center}
-\end{figure}
-
-\begin{description}
-\item[\bu{File}] This menu includes selections for \bu{New}, \bu{Open},
-\bu{Save}, \bu{Save As}, and \bu{Exit}. \bu{Switch file} closes the
-current file and opens the last file that was edited, if any. This is
-useful for working with both a source file and an included file.
-
-\item[\bu{Edit}] This menu includes selections for \bu{Undo}, \bu{Redo},
-\bu{Copy}, \bu{Cut}, \bu{Paste}, \bu{Find} and \bu{Find again}.
-
-\item[\bu{Options}] This menu enables you to edit the option strings for
-each of the phases of execution of \spn{} and the C compiler. Normally, you
-will not need to change the options except for those that are more
-conveniently changed in \bu{Options/Common} or \bu{Settings}
-(Section~\ref{s.run}). \bu{Default} restores the default
-values and \bu{Save} saves the current set of option strings in the
-configuration file. In addition, the following configuration items are
-automatically saved:
-\begin{itemize}
-\item \p{SOURCE\_DIRECTORY}: the last directory from which a source file was opened.
-\item The current values of the splitpane dividers \p{TB\_DIVIDER} and
-\p{LR\_DIVIDER}.
-\item The current value of the width \p{SELECT\_BUTTON} for interactive
-simulation.
-\end{itemize}
-The file can be saved
-to the \bu{current} or \bu{install} directory. \textbf{Changes in the
-\spn{} options can cause the assumptions on the input to \p{filter} to
-become falsified. Be careful!}
-
-\item[\bu{Settings}] This menu sets parameters for the simulation and
-verification (Section~\ref{s.run}).
-
-\item[\bu{Output}] This menu controls the display of the simulation output
-in the right text area. \bu{Output/Maximize} toggles the text area to be
-maximized, hiding the editing area. \bu{Output/Save output} saves the
-contents of the text area in a file with extension \p{.out}.
-To debug the filtering algorithm,
-select \bu{Output/Raw output} to write a file with extension
-\p{.raw} that contains the raw \spn{} output;
-\bu{Output/Display raw} will display this file.
-The other items in this menu are discussed in Section~\ref{s.run}.
-
-\item[\bu{SpinSpider}] This menu enables interactive execution of the \spd{}
-tool for creating graphical representations for the state diagram of a
-\prm{} program. See the separate documentation for this tool.
-
-\item[\bu{Help}] \bu{Help} displays a short help file and \bu{About}
-displays copyright information about the software.
-\end{description}
-
-\section{Running \spn{}}\label{s.run}
-In the \bu{Spin} menu (and on the toolbar) are five selections for
-running \spn{}. They all use the \prm{} source file that has been opened,
-and save the file before execution.
-During simulation and verification,
-you can select \bu{Stop} to terminate the \spn{} process that has been forked.
-\begin{description}
-\item[\bu{Check}] Runs a \emph{syntax check}.
-\item[\bu{Random}] Runs a \emph{random simulation}.
-\item[\bu{Interactive}] Runs an \emph{interactive simulation}.
-\item[\bu{Guilded}] Runs a \emph{guided simulation} using the trail
-file created by the execution of the analyzer.
-\item[\bu{Verify}] Runs an \emph{verification}.
-\end{description}
-\textbf{If you terminate \js{} while \spn{} is running (for example by entering \bu{ctrl-C} from the
-command line), make sure to terminate the \spn{} process as well.}\\
-In Windows this is done by pressing \bu{ctrl-alt-del}, followed by
-selecting \bu{Task List} and \bu{Processes}. Select \bu{spin.exe} and
-\bu{End Process}.
-
-\subsection{Simulation}\label{s.sim}
-\bu{Check} should be run before any simulation run to ensure better display
-of errors.
-
-\bu{Settings/Max steps} changes the \p{-u} option to limit the number of
-simulation steps, and \bu{Settings/Max depth} changes the \p{-m} option
-to limit the \p{pan} search depth.
-
-A nonzero value for \bu{Settings/Seed} will be used as the seed for generating
-random numbers, enabling a random simulation to be repeated.
-
-\subsubsection{Interactive simulation}
-During an interactive simulation, a dialog frame will pop up with a list
-of statements that can be executed. The list can be displayed either as
-a row of buttons, or---if there is not enough room---as a pulldown menu.
-The choice of the format is dynamically determined according to the
-value of the configuration option \p{SELECT\_MENU}. By setting this
-value to an extreme, you can force the list to a certain format. There
-are also configuration options for setting the width and height of the
-buttons or menu items.
-
-The dialog can be navigated using the mouse; closing the dialog frame
-will terminate interactive simulation. For keyboard navigation:
-\begin{description}
-\item[Buttons] \bu{Tab} and \bu{Shift-Tab} move through the buttons
-and \bu{Space} selects the highlighted button. Press \bu{Esc} to terminate.
-\item[Menu] Press down arrow to display the list and to highlight the
-item you want; press \bu{Return} to select it. Press \bu{Esc} to terminate.
-\end{description}
-
-\subsubsection{Filtered output}\label{s.filter}
-The contents of the \spn{} output can be changed by selecting
-\bu{Options/Common}. This pops up a dialog with check boxes to select the
-\spn{} output options: statements (\p{-p}), local variables (\p{-l}),
-global variables (\p{-g}), messages sent (\p{-s}) and messages received
-(\p{-r}).
-
-Select \bu{Output/Exclude variables} to create a list of strings defining
-variables to be \emph{excluded} from the display. Any variable containing
-a string from the list is not displayed; for example, \p{:init:} will
-exclude all variables of the \p{init} process. If the variable name is
-prefixed by \p{+}, it will be included anyway. For exmple, if you have an
-array variable \p{test}, then the entries \p{test} and \p{+[1]} will
-exclude display of the elements of \p{test} except for \p{test[1]}. The
-list is saved on a file with extension \p{.exc}.
-
-Similarly, a file of excluded statements can be created. The file
-extension is \p{.exs} and it may be edited by selecting \bu{Output/Exclude
-statements}. \bu{Exclude statements} should \emph{not} be used with
-interactive simulation.
-
-The output strings from \p{printf} statements is displayed normally. Optionally,
-you can request that only strings beginning with \p{MSC:} be displayed (\p{MSC=true}).
-
-\subsection{Verification}
-Selecting \bu{Spin/Verify} or the \bu{Verify} button on the tool bar
-performs the three steps required to verify a \prm{} program in \spn{}:
-\begin{itemize}
-\item Run \spn{} to create an analyzer in files \p{pan.*}.
-\item Run the C compiler to compile the analyzer \p{pan.c}.
-\item Run the analyzer \p{pan.exe}.
-\end{itemize}
-There are three modes of verification in \spn{},
-one of which must be selected from the combo box on the toolbar
-or the radio buttons in the menu \bu{Settings}:
-\begin{description}
-\item[Safety] Checks basic safety properties such as assertions.
-\item[Acceptance] Checks for acceptance cycles.
-\item[Non-Progress] Checks that every cycle contains a
-\p{progress} label.
-\end{description}
-See the \spn{} reference manual for descriptions of these modes.
-Checking \bu{Weak fairness} in the menu \bu{Settings}
-or on the toolbar performs the verification only for executions that are
-weakly fair.
-
-\subsection{LTL formulas}\label{s.ltl}
-
-A correctness claim specified by a \emph{Linear Temporal Logic (LTL)}
-formula must be converted to an automaton written as a \prm{} \p{never}
-claim. LTL formulas can be contained within the \prm{} source code or
-they can be placed in external files.
-
-\subsection{Internal formulas}
-
-An LTL formula can be included in a \prm{} program:
-\begin{verbatim}
-ltl { []<>csp && []<>csq }
-\end{verbatim}
-The formula is translated internally by \spn{} into a \p{never} claim.
-
-A number of \emph{named} formulas can be included within a \prm{} program:
-\begin{verbatim}
-ltl p0 { [](gate <= 1) }
-ltl p1 { []((count == 0) -> (gate == 0)) }
-ltl p2 { [](((gate == 0) && notInTest) -> (count == 0)) }
-\end{verbatim}
-To select which claim will be used in a verification, enter the
-\emph{name} in the \bu{LTL formula} text field and select \bu{LTL name}.
-
-The above examples show that internal LTL formulas can have expressions
-and not just names as atomic propositions.
-
-\textbf{\spn{} automatically negates LTL formulas contained within a
-\prm{} program.}
-
-\subsubsection{External formulas}
-
-Enter a formula (such as \p{[]p} or \p{<>p}) in the text field labelled
-\bu{LTL formula} on the menu bar and select \bu{Translate} from the
-toolbar or the \bu{Convert} menu; the formula translated into a
-\p{never} claim which will be added to the next \spn{} verification. The
-\p{never} claim is stored in a file with extension \p{.ltl}. The formula
-is not automatically translated, so whatever \p{never} claim exists, if
-any, will continue to be used until \bu{Translate} is invoked again.
-
-\textbf{Before the formula is translated it is negated by \js}. This is
-done so that the LTL formula as displayed represents the correctness
-property being checked and not the negated formula which if satisfied
-represents a counterexample. Should you wish to enter negations yourself
-as in \spn{}, you can change the configuration file option
-\p{NEGATE\_LTL} to false; this can also be done by toggling
-\bu{Settings/Negate LTL}.
-
-LTL formulas are saved in \emph{property files} with extension \p{.prp}.
-By default, when you open a \prm{} file,
-\js{} opens and loads a \p{.prp} file of the same name.
-You can also load a different file by selecting \bu{Load} from
-the toolbar or the \bu{Convert} menu;
-the file name will be displayed on the toolbar.
-If the file does not exist,
-the text field is cleared and the new name is used when you \bu{Translate} the formula
-you enter.
-
-The property file is saved whenever the source file is
-and also before translation.
-
-\bu{Convert/Clear} not only to clears the text field, but ensures that
-no LTL formula will be used in the next verification. After selecting
-\bu{Convert/Clear} an empty file will not be saved. Note: In earlier
-versions of \js{}, a button \bu{Clear} was available on the toolbar;
-this has now been removed and the menu selection must be used.
-
-\section{\spd{}}
-Open a \prm{} program. If you wish to emphasize or draw the computation
-described by a \p{trail} file, execute \spn{} in verification mode with
-appropriate assertions or LTL formulas to create the trail file for a counterexample.
-
-Select \bu{SpinSpider/SpinSpider} (\bu{ctrl-D}) from the menu or \bu{SpinSpider}
-from the toolbar and the following frame will appear:
-\begin{center}
-\includegraphics[width=9cm,keepaspectratio=true]{spd.png}
-\end{center}
-\begin{description}
-\item[\bu{Format}] The output format, normally \bu{dot} or one of the formats
-such as \bu{png} that can be obtained by running \dt{}. The \bu{fsm} format is
-experimental and the processing of the trail file is not done for this format.
-\textbf{If \p{png} is selected as the format, the state diagram will be displayed in a
-separate frame when \spd{} has terminated.}
-\item[\bu{Processes}] The number of processes in the program (for generation of
-the \p{never} claim).
-\item[\bu{Variables}] A list of the variables in the program (for generation of
-the \p{never} claim).
-\item[\bu{No trail}, \bu{Emphasize trail}, \bu{Only trail}] If the first option
-is selected, the entire state diagram is created. The second option colors nodes
-and edges in the state diagram that are part of the trail. The third option
-creates a diagram containing only those states and nodes that are part of the
-trail.
-\item[\bu{Automata}] This displays the source of the \prm{} program as a set
-of automata, one for each \p{proctype}; for the \emph{third attempt}, this is:
-\begin{center}
-\includegraphics[width=7cm,keepaspectratio=true]{third-automata.png}
-\end{center}
-The states are labeled with the source code line numbers and the edges with
-the statements associated with each transition. \p{atomic} transitions
-are emphasized.
-\item[\bu{Dot size}] Chooses between two prologues for the \dtf{} file. The small
-option works better for display within \js{}.
-\item[\bu{Trail style}] Chooses between two ways of emphasizing the trail in a
-computation: in color or bold. The latter is useful for including the diagram in
-a document or for users with difficulty seeing colors.
-\item[\bu{Debug}] Writes a file (extension \p{.dbg}) with the internal data
-structures as collected from the execution of \spn{}: states, transitions,
-statements and the trail.
-(The file is automatically generated if \bu{Automata} is selected.)
-This file can be displayed by selecting
-\bu{SpinSpider/Display debug} from the \js{} menu.
-\item[\bu{Run}] Saves the current parameters in a file with the same name as the
-source file and with extension \p{.spd}. Then \spd{} is run.
-\item[\bu{Cancel}] Returns without saving the parameters or running \spd{}.
-\end{description}
-
-\subsection{\prm{} programs for \spd{}}
-The directory \bu{spider-examples} contains concurrent programs that demonstrate
-the use of \spd{}.
-
-To reduce the size of the diagrams, use \emph{remote references} rather than
-ghost variables in the specification of correctness properties. For example, to
-prover that mutual exclusion holds in the third attempt (\p{third.pml}), declare
-labels \p{cs:} at the two critical sections and then define the symbol:
-\begin{verbatim}
-#define notmutex (p@cs && q@cs)
-\end{verbatim}
-Mutual exclusion can shown by doing a verification in \bu{Safety} mode
-with the LTL formula:
-\begin{verbatim}
-!<>notmutex
-\end{verbatim}
-Recall that \spn{} finds the \emph{first} counterexample in a depth-first
-search, not the shortest one. The trail for the program for the fourth
-attempt (\p{fourth.pml}) was created by running \p{pan} with the \p{-i}
-parameter to do an iterative search for a short counterexample.
-
-The line numbers will be accurate if the first alternative of a \p{do}- or
-\p{if}-statement is written on the same line as the keyword. Note that all
-alternatives are considered to belong to the line containing the keyword.
-
-%\newpage
-
-\section{Troubleshooting}
-\begin{description}
-\item[\spn{} won't execute] Check the configuration items
-for \spn{} and the C compiler.
-It is recommended that they be in your path.
-\item[Exceptions in Filter] Your own output might be
-interfering with the filtering algorithm.
-If configuration option \p{MSC} is selected, use \p{printf} only with strings
-prefixed by \p{MSC:} and terminated by a newline.
-\item[Verification doesn't seem to work]
-Make sure that you have selected the appropriate mode
-from the \bu{Settings} menu:
-\bu{Safety}, \bu{Acceptance}, \bu{Non-progress}.
-If you are using an LTL formula,
-\bu{Translate} it before verifying.
-\item[Your computer works slowly] Forked processes for \spn{} are still executing.
-Terminate them from the operating system.
-\item[Settings, options and the directory aren't remembered]
-You must select \bu{Options/Save} before exiting \spn{}.
-\item[Preprocessing failed] Simple preprocessing like the use of \verb=#define=
-is done internally by \spn{}. For more complicated processing, \spn{} calls the
-C compiler's preprocessor. This error message can result if there is a problem
-with the installation; check also that the C compiler is in the path.
-To debug preprocessing, execute \spn{} with the argument \p{-I};
-this will perform preprocessing only on the \prm{} file and display the result.
-\end{description}
-
-\newpage
-
-\section{Software structure*}
-The software is divided into three Java packages.
-
-\subsection{Package \p{jspin}}
-\p{jSpin} is the main class and contains declarations
-of the GUI components and instances
-of the classes \p{Editor} and \p{RunSpin}.
-Method \p{init} and the methods it calls initialize the GUI.
-Method \p{action\-Per\-formed} is the event handler for all the menu items
-and buttons; it calls the appropriate methods for handling each event.
-The \bu{About} and \bu{Help} options are implemented by reading files
-\p{copyright.txt} and \p{help.txt}, respectively, and displaying
-them in a \p{JFrame} with a scrollable \p{JTextArea}.
-
-\p{JSpinFileFilter} is used with a \p{JFileChooser}
-when opening and saving files: \prm{} source files,
-LTL property files and \spn{} display output files.
-
-\p{Options} is the dialog frame with check boxes for
-changing the \spn{} display options.
-
-\p{Exclude} is the dialog frame for editing the list
-of variable strings to be excluded from the display.
-
-\p{Config} contains declarations of compile time configuration items.
-Method \p{init} calls \p{set\-Default\-Properties} to initialize the instance
-of \p{Properties} with the default values of the dynamic configuration
-items; it then attempts to load the configuration file, and if unsuccessful,
-the default properties are written to a new file.
-
-\p{Editor} implements an editor using operations on a
-\p{JTextArea}. It implements the interface \p{Document\-Listener} to flag
-when the source has been modified. The class is also responsible
-for the LTL formula \p{JTextField}. \p{jSpin} calls method \p{writeFile}
-to write \p{ltl} and \p{out} files, and method \p{readFile} to read
-the text files to be displayed.
-
-\p{LineNumbers} extends a \p{JComponent} to create line numbers
-for the \p{RowHeaderView} of the editor \p{JScrollPane}
-(thanks to Niko Myller for this code).
-
-\p{UndoRedo} was extracted from an example on the Java web site.
-
-The event handler in \p{jSpin} calls \p{run} in class \p{RunSpin}
-to execute \spn{}, the C compiler and the analyzer \p{pan}.
-\p{run} creates a thread of class \p{RunThread},
-and uses \p{ProcessBuilder} to set up the
-command, directory, merge the output and error streams,
-and set up streams for I/O.
-The call \p{runAndWait} is used for short calls like \bu{Check}
-and the creation and compilation of a model;
-this call does not return until the completion of the subprocess.
-The call \p{run} will return immediately after it has created the thread.
-In this case, the event handler in \p{jSpin} calls \p{isSpinRunning}
-to create a thread to poll for termination of \spn{};
-by creating a separate thread, the event handler is freed to accept
-a selection of \bu{Stop}.
-
-When \p{Select a statement} is received during an interactive simulation,
-method \p{select} is called.
-This method displays the choices in the bottom text area and pops up a
-dialog to enable the user to make a selection.
-A \p{JFrame} is created in a new thread of the inner class \p{SelectDialog} to wait
-for the selection.
-\p{select} polls \p{selectedValue} which is set with the selected button
-value or zero if the frame is closed or \bu{Esc} pressed.
-In that case, \p{q} is sent to \spn{} to terminate the simulation.
-
-\js{} contains source code for interactively invoking \spd{}.
-The class \p{SpiderOptions} pops up frame where parameters can be entered and
-\spd{} invoked. Each \prm{} file can have its own set of parameters; these are stored
-in property files with extension \p{.spd} and managed by \p{SpiderFile}.
-If the diagram is created in \bu{PNG} format, it is displayed interactively:
-\p{DisplayImage} creates a frame and
-the image is loaded into an instance of \p{ImagePanel}.
-
-\subsection{Package \p{filterSpin}}
-
-The output filtering is encapsulated in class \p{Filter}.
-For each line received from the output stream, \p{run}
-(of \p{RunThread}) calls \p{filter}
-which modifies the string; the modified string is displayed in the
-appropriate text area.
-A \p{TreeMap} is maintained for mapping variable names into value strings.
-Each new variable is checked against the list of excluded strings before
-it is entered in the map.
-For standalone filtering, the package
-contains a \p{Config} class and a class \p{FilterSpin} with a main method.
-
-\subsection{Package \p{spinSpider}}
-
-Most of the processing of the \spd{} program is done
-in the class \p{SpinSpider}.
-Static data like strings and the prologue for the \dtf{} file are
-contained in the class \p{Config}.
-
-Four classes are used for
-objects containing information extracted from the files:
-\begin{itemize}
-\item \p{State} contains the program counter values and the variables names
-and values that are extracted from the output of the \p{never} claim in the
-\p{.chk} file.
-\item \p{Transition} contains the transitions and is obtained by following
-the \p{New}, \p{Old}, \p{Up} and \p{Down} debugging trace in the \p{.chk} file.
-A stack is used to simulate the depth-first search of \spn{}.
-\item \p{Statement} contains the states, line numbers and source statements
-from the \p{.d} file.
-\item \p{Trail} contains the \p{id} of an entry in the trail file.
-\end{itemize}
-The processing sequence is invoked from the method \p{runSpider}.
-\p{runProcess} is called several times to fork processes as described in
-Section~\ref{s.how}. The \p{.d} file is analyzed in \p{createStatements},
-and the \p{.chk} file is analyzed in \p{readCheckFile} of class \p{Read}.
-If requested, these data structures are written to a file in method
-\p{writeDebug} of class \p{Write}.
-
-The class \p{SetTrail} traverses the state diagram according to the trail and
-marks states and transitions that are part of the trail.
-
-The data structures are used to write the files in class \p{Write}.
-See the description of the \fsm{} format to understand \p{writeFSMGraph}.
-In \p{writeDOTGraph}, the \p{states} array is traversed sequentially
-writing out numbered nodes including labels for each node. The
-elements of this array store the program counters of each process in the
-state; these are used to search the \p{statements} array for \emph{all}
-statements that start from the program counter. The line numbers and
-source code of the statements are appended to the label. The variable
-values are also obtained from the \p{states} array. The transitions are
-taken directly from the \p{transitions} array. Finally, \dt{} is called, if
-requested.
-
-The class \p{DrawAutomata} uses the information in the \p{.d} file
-to write a \dtf{} file and then calls \dt{}.
-
-\subsection{How \spd{} works}\label{s.how}
-
-\spd{} works with numerous files:
-\begin{itemize}
-\item The source file with extension \p{.pml}.
-\item A \p{never} claim file with extension \p{.nvr} as described below;
-this is normally generated automatically.
-\item The file with extension \p{.chk} obtained by running a verification of
-the program with the \p{-DCHECK} option and with the \p{never} claim that
-prints out the program counters and variable values.
-\item The statement file with extension \p{.d} obtained by running a verification
-with the \p{-d} option.
-\item A file with extension \p{.spd} that is used by \js{} to save \spd{} parameters.
-\item A debug file with extension \p{.dbg}.
-\end{itemize}
-
-\spd{} runs the following commands in subprocesses (\p{prog.pml} is the source file):
-
-\hspace*{1cm}\p{spin -a prog.pml}\\
-\hspace*{1cm}\p{gcc -DCHECK -DSAFETY -DPRINTF -o pan pan.c}\\
-\hspace*{1cm}\p{pan > prog.chk}\\
-\hspace*{1cm}\p{pan -d > prog.d}
-
-Then it runs its own algorithm to create a \dtf{} file. Finally, \dt{} is
-optionally run to create a display file in some format like \p{png}.
-
-A \prm{} program must be modified by giving a special \p{never} claim; this is
-generated automatically and included using the \p{-N} argument to \spn{}.
-
-The \p{never} claim contains a single \p{printf} statement in a loop, which is
-executed with every step of the verifier. The statement prints the
-following tokens separated by spaces:
-\begin{itemize}
-\item The string \p{*spd*};
-\item The number of processes, followed by the values of \p{pc\_value}
-for each process;
-\item The number of variables, followed by their names and values.
-\end{itemize}
-For the algorithm shown in the introduction the \p{never} claim is:
-\begin{verbatim}
-never {
- do :: printf("*spd* 2 %d %d 2 wantp %d wantq %d \n",
- pc_value(0), pc_value(1), wantp, wantq)
- od
-}
-\end{verbatim}
-
-\newpage
-
-\appendix
-
-\section{Installation}\label{a.install}
-
-\subsection{\spn{} version}
-
-Version 6.0.0 of \spn{} changed its output format; starting with version
-5.0, \js{} expects this format. You can still run \js{} with earlier
-versions of \spn{} (for example, 4.30): set the configuration option
-\p{VERSION} to a number less than 6 before you run \js{} and ensure that
-the option \p{SPIN} names the earlier version of the \spn{} executable
-(or copy the file over the later version).
-
-\subsection{Custom installation of \js{}}
-\begin{itemize}
-\item Download the \js{} distribution file called \p{jspin-N.zip},
-where \p{N} is the version number.
-Extract the files into a clean directory.
-%\textbf{Do not} install to a directory with spaces like \verb=c:\Program Files=.
-
-\item Install \spn{} and \textsc{dot} (\textsc{dot} is only needed for
-\textsc{SpinSpider}).
-
-\item Install an ANSI C compiler.
-
-\item Modify the configuration file \p{config.cfg} to reflect the
-locations of the programs.
-\end{itemize}
-
-\subsection{Building \js{}}
-
-To rebuild \js{}, execute \p{build.bat}, which will compile all the source
-files and create the file \p{jSpin.jar} with the manifest file.
-
-\subsection{Installing a C compiler}\label{a.c}
-The \p{gcc} compiler is normally used with \spn{}. On Windows, there are
-two distributions: Cygwin (\url{http://cygwin.com}) is a comprehensive
-Linux-like environment, and a smaller distribution called MinGW
-(\url{http://mingw.org/}). To install MinGW, download the following archives and
-open them in directory \verb=c:\mingw= \emph{in the following order}:
-\begin{quote}
-\p{binutils-V.tar.gz}\\
-\p{gcc-core-V.tar.gz}\\
-\p{mingw-runtime-V.tar.gz}\\
-\p{w32api-V.tar.gz}
-\end{quote}
-where V is the version and build number.
-It is OK if some files are overwritten when opening the archive.
-
-Set the path in
-\begin{quote}
-\p{Start/Control Panel/System/Advanced/Environment Variables/PATH}
-\end{quote}
-to include \verb=c:\mingw\bin=.
-
-\subsection{Installing \js{} on \textsc{Mac OS X}}\label{a.mac}
-
-Thanks to Christiaan Ottow for providing this material.
-
-Currently, there is no precompiled version of \spn{}, so you will have to
-compile it from the source code. Instructions for doing this are given
-in Section~2c of the webpage:
-\begin{quote}
-\url{http://spinroot.com/spin/Man/README.html}
-\end{quote}
-An alternative approach is change the location of the preprocessor specified in
-lines 75--88 of \p{main.c} from \p{/lib/cpp} to \p{/usr/bin/cpp}.
-
-\js{} is compiled with \p{-target 1.5} to conform with the \textsc{Java}
-version currently available on the \textsc{Mac}.
-
-To install \js{}:
-\begin{itemize}
-\item Unzip the file \p{jspin-V-V.zip}.
-\item Download \textsc{Graphviz} from
-\begin{quote}
-\url{http://www.pixelglow.com/graphviz/download}
-\end{quote}
-Open the \p{dmg} file you downloaded and copy the \textsc{Graphviz}
-application to the Applications folder.
-\item Open the configuration file \p{config.cfg} in a text editor and change the
-values of the following properties:
-\begin{itemize}
-\item \p{SPIN} to the directory with the compiled \spn{};
-\item \p{SOURCE\_DIRECTORY} to the subdirectory \p{jspin-examples} of the directory
-where you unpacked \js{};
-\item \p{C\_COMPILER} to directory containing \p{gcc},
-usually \p{/usr/bin/gcc}. You can verify this by issuing the command \p{which gcc};
-\item \p{PAN} to \p{pan};
-\item \p{DOT} to \p{/Applications/Graphviz.app/Contents/MacOS/dot}.
-\end{itemize}
-\end{itemize}
-
-\js{} can now be run by using the \p{Terminal} to execute the following command
-in the \p{jspin} directory:
-\begin{quote}
-\p{java jspin.jSpin}
-\end{quote}
-
-\subsection{Installing \js{} on \textsc{Linux}}\label{a.linux}
-
-Thanks to Vsevolod Krishchenko for providing this material.
-
-\begin{itemize}
-
-\item Install gcc, C preprocessor, dot, java. For Debian/Ubuntu:
-\begin{verbatim}
- sudo apt-get install gcc cpp graphviz sun-java6-jre
-\end{verbatim}
-\item Install spin as described above.
-\item Make the following changes in \p{config.cfg}:
-\begin{verbatim}
- C_COMPILER=gcc
- DOT=dot
-\end{verbatim}
-You many need to set \p{SINGLE\_QUOTE} to \p{true}.
-\item Create a shell file with:
-\begin{verbatim}
- #!/bin/sh
- java -jar jSpin.jar
-\end{verbatim}
-\end{itemize}
-
-\section{Configuration file}\label{a.cfg}
-
-These tables give the properties in the configuration file and their
-default values.
-
-\begin{center}
-
-\begin{tabular}{|p{.3\textwidth}|p{.4\textwidth}|}
-\hline
-\multicolumn{2}{|c|}{Version of \spn{}}\\ \hline
-\textsc{\ttfamily VERSION} &\verb+6+\\\hline
-\end{tabular}
-
-\bigskip
-
-\begin{tabular}{|p{.3\textwidth}|p{.4\textwidth}|}
-\hline
-\multicolumn{2}{|c|}{Directories for source and compilers}\\ \hline
-\textsc{\ttfamily SOURCE\_DIRECTORY} & \verb+"jspin-examples"+ \\
-\textsc{\ttfamily C\_COMPILER} &\verb+"c:\\mingw\\bin\\gcc.exe"+ \\
-\textsc{\ttfamily SPIN} &\verb+"bin\\spin.exe"+ \\
-\textsc{\ttfamily DOT} &\verb+"bin\\dot.exe"+ \\
-\textsc{\ttfamily PAN} &\verb+"pan"+ \\ \hline
-\end{tabular}
-
-\bigskip
-
-\begin{tabular}{|p{.3\textwidth}|p{.4\textwidth}|}
-\hline
-\multicolumn{2}{|c|}{Options for executing \spn{}}\\ \hline
-\textsc{\ttfamily COMMON\_OPTIONS} &\verb+"-g -l -p -r -s"+\\
-\textsc{\ttfamily CHECK\_OPTIONS} &\verb+"-a -v"+\\
-\textsc{\ttfamily RANDOM\_OPTIONS} &\verb+"-X"+\\
-\textsc{\ttfamily INTERACTIVE\_OPTIONS} &\verb+"-i -X"+\\
-\textsc{\ttfamily VERIFY\_OPTIONS} &\verb+"-a"+\\
-\textsc{\ttfamily C\_COMPILER\_OPTIONS} &\verb+"-o pan pan.c"+\\
-\textsc{\ttfamily PAN\_OPTIONS} &\verb+"-X"+\\
-\textsc{\ttfamily TRAIL\_OPTIONS} &\verb+"-t -X"+\\
-\textsc{\ttfamily TRANSLATE\_OPTIONS} &\verb+"-f"+\\
-\textsc{\ttfamily MAX\_STEPS} {\ttfamily (-u)} & \verb+250+\\
-\textsc{\ttfamily MAX\_DEPTH} {\ttfamily (-m)} & \verb+2000+\\
-\textsc{\ttfamily SEED} {\ttfamily (-n)} & \verb+0+\\
-\textsc{\ttfamily FAIRNESS} & \verb+true+\\
-\textsc{\ttfamily RAW} & \verb+false+\\
-\textsc{\ttfamily SINGLE\_QUOTE} & \verb+false+\\
-\textsc{\ttfamily NEGATE\_LTL} & \verb+true+\\
-\textsc{\ttfamily VERIFY\_MODE} & \verb+"Safety"+\\\hline
-\end{tabular}
-
-\bigskip
-
-\begin{tabular}{|p{.3\textwidth}|p{.4\textwidth}|}
-\hline
-\multicolumn{2}{|c|}{Filter settings}\\ \hline
-\textsc{\ttfamily PROCESS\_TITLE} & \verb+Process +\\
-\textsc{\ttfamily PROCESS\_WIDTH} & \verb+7+\\
-\textsc{\ttfamily STATEMENT\_TITLE} & \verb+Statement +\\
-\textsc{\ttfamily STATEMENT\_WIDTH} & \verb+18+\\
-\textsc{\ttfamily VARIABLE\_WIDTH} &\verb+10+\\
-\textsc{\ttfamily LINES\_PER\_TITLE} &\verb+20+\\
-\textsc{\ttfamily MSC} &\verb+false+\\
-\hline
-\end{tabular}
-
-\bigskip
-
-\begin{tabular}{|p{.3\textwidth}|p{.4\textwidth}|}
-\hline
-\multicolumn{2}{|c|}{Text settings}\\ \hline
-\textsc{\ttfamily WRAP} &\verb+true+\\
-\textsc{\ttfamily TAB\_SIZE} &\verb+4+\\
-\textsc{\ttfamily FONT\_FAMILY} & \verb+"Lucida Sans Typewriter"+\\
-\textsc{\ttfamily FONT\_STYLE} & \verb+java.awt.Font.PLAIN+\\
-\textsc{\ttfamily FONT\_SIZE} & \verb+14+\\\hline
-\end{tabular}
-
-\bigskip
-
-\begin{tabular}{|p{.3\textwidth}|p{.4\textwidth}|}
-\hline
-\multicolumn{2}{|c|}{Frame size}\\ \hline
-\textsc{\ttfamily WIDTH} &\verb+1000+\\
-\textsc{\ttfamily HEIGHT} &\verb+700+\\\hline
-\end{tabular}
-
-\bigskip
-
-\begin{tabular}{|p{.3\textwidth}|p{.4\textwidth}|}
-\hline
-\multicolumn{2}{|c|}{Interactive dialog settings}\\ \hline
-\textsc{\ttfamily SELECT\_BUTTON} &\verb+120+\\
-\textsc{\ttfamily SELECT\_HEIGHT} &\verb+70+\\
-\textsc{\ttfamily SELECT\_MENU} &\verb+5+\\\hline
-\end{tabular}
-
-\bigskip
-
-\begin{tabular}{|p{.3\textwidth}|p{.4\textwidth}|}
-\hline
-\multicolumn{2}{|c|}{Location of dividers}\\ \hline
-\textsc{\ttfamily LR\_DIVIDER} &\verb+400+\\
-\textsc{\ttfamily TB\_DIVIDER} &\verb+500+\\
-\textsc{\ttfamily MIN\_DIVIDER} &\verb+50+\\\hline
-\end{tabular}
-
-\bigskip
-
-\begin{tabular}{|p{.3\textwidth}|p{.4\textwidth}|}
-\hline
-\multicolumn{2}{|c|}{Delay while waiting for user input}\\ \hline
-\textsc{\ttfamily POLLING\_DELAY} &\verb+200+\\\hline
-\end{tabular}
-
-\end{center}
-
-\end{document}
+\documentclass[11pt]{article}
+\usepackage{mathpazo}
+\usepackage{url}
+\usepackage{graphicx}
+\usepackage{verbatim}
+
+\newcommand{\spn}{\textsc{Spin}}
+\newcommand{\prm}{\textsc{Promela}}
+\newcommand{\js}{\textsc{jSpin}}
+\newcommand{\spd}{\textsc{SpinSpider}}
+\newcommand{\fil}{\textsc{FilterSpin}}
+\newcommand{\dt}{\textsc{dot}}
+\newcommand{\dtf}{\texttt{dot}}
+\newcommand{\fsm}{\texttt{fsm}}
+\newcommand{\p}[1]{\texttt{#1}}
+\newcommand{\bu}[1]{\textsf{#1}}
+
+\textwidth=15cm
+\textheight=22cm
+\topmargin=0pt
+\headheight=0pt
+\oddsidemargin=1cm
+\headsep=0pt
+\renewcommand{\baselinestretch}{1.1}
+\setlength{\parskip}{0.20\baselineskip plus 1pt minus 1pt}
+\parindent=0pt
+
+\title{\js{} - Java GUI for \spn{}\\User's Guide\\\mbox{}\\\large{Version 5.0}}
+\author{Mordechai (Moti) Ben-Ari\\
+Department of Science Teaching\\
+Weizmann Institute of Science\\
+Rehovot 76100 Israel\\
+\textsf{http://stwww.weizmann.ac.il/g-cs/benari/}}
+%\date{}
+\begin{document}
+\maketitle
+\thispagestyle{empty}
+
+\vfill
+
+\begin{center}
+Copyright (c) 2003-10 by Mordechai (Moti) Ben-Ari.
+\end{center}
+Permission is granted to copy, distribute and/or modify this document
+under the terms of the GNU Free Documentation License, Version 1.2
+or any later version published by the Free Software Foundation;
+with Invariant Section ``Introduction,'' no Front-Cover Texts, and no
+Back-Cover Texts. A copy of the license is included in the file
+\p{fdl.txt} included in this archive.
+\newpage
+
+\section{Introduction}
+
+\subsection{\js{}}
+\js{} is a graphical user interface for the \spn{} Model Checker that is
+used for verifying concurrent and distributed programs. It is an
+alternative to the \textsc{XSpin} GUI and was developed primarily for
+pedagogical purposes. \js{} is written in Java, because the Java
+platform is both portable and widely used in computer science education.
+The user interface of \js{} is simple, consisting of a single window
+with menus, a toolbar and three adjustable text areas. \spn{} option
+strings are automatically supplied and the \spn{} output is filtered and
+formatted. All aspects of \js{} are configurable: some at compile time,
+some at initialization through a configuration file and some at runtime.
+The filtering algorithm in \js{} can also be run as a standalone
+program.
+
+\subsection{\spd{}}
+\js{} includes the \spd{} tool for creating a graphical representation for
+the state diagram of a \prm{} program by postprocessor the \spn{} output.
+\spd{} is integrated into \js{}, but it can also be run as a standalone program.
+
+\spd{} generates the complete state diagram of a \prm{} program; the
+diagrams are useful for demonstrating properties of concurrent programming.
+Consider the \emph{third attempt} at solving the critical section problem (line
+numbers added):
+\begin{verbatim}
+1. bool wantp = false, wantq = false;
+2.
+3. active proctype p() {
+4. do :: wantp = true;
+5. !wantq;
+6. wantp = false;
+7. od
+8. }
+9.
+10. active proctype q() {
+11. do :: wantq = true;
+12. !wantp;
+13. wantq = false;
+14. od
+15. }
+\end{verbatim}
+The processes \p{p} and \p{q} are in their critical sections if they are at
+lines~6 and~13, respectively. The figure on the next page shows the state
+diagram for this program. Each node contains the source code lines (and line
+numbers) for the two processes and the values of the variables \p{wantp} and
+\p{wantq}. The arrows show the possible transitions between states. Since no
+state has the processes together at lines~6 and~13 mutual exclusion is
+achieved. It is easy to see there is a computation that leads to deadlock in
+the state with \p{p} at line~5 and \p{q} at line~15.
+\begin{figure}[!htb]
+\begin{center}
+\includegraphics[width=6cm,keepaspectratio=true]{third.png}
+\end{center}
+\end{figure}
+
+\spd{} processes output of the \p{pan} verifier in order to create the full
+state diagram of a program. The diagram is produced in \dtf{} format and
+(optionally) the \dt{} program can be run to produce a graphics file.
+\spd{} can also produce state diagrams in \fsm{} format used by visualization
+tools developed at the Technische Universiteit Eindhoven (see the URLs below).
+
+\subsection{References}
+\begin{itemize}
+\item M. Ben-Ari. \textit{Principles of the Spin Model Checker}. Springer, 2008.
+\item M. Ben-Ari. \textit{Principles of Concurrent and Distributed Programming (Second
+Edition)}. Addison-Wesley, 2006.
+\item Gerard J. Holzmann. \textit{The Spin Model Checker: Primer
+and Reference Manual}.\\Addison-Wesley, 2004.
+\end{itemize}
+
+\subsection{URLs}
+
+\begin{tabular}{l@{\hspace{3em}}l}
+\hline
+\fsm{} & \url{http://www.win.tue.nl/~fvham/fsm/}\\
+ & \url{http://www.mcrl2.org/}\\
+\textsc{Graphviz (dot)} & \url{http://www.graphviz.org/}\\
+\js{} & \url{http://stwww.weizmann.ac.il/g-cs/benari/com.spinroot.jspin/}\\
+\textsc{MinGW} & \url{http://mingw.org/}\\
+\spn{} & \url{http://spinroot.com/}\\
+\hline
+\end{tabular}
+
+\subsection{Acknowledgement}
+I would like to thank Gerard J. Holzmann for his generous assistance throughout the
+development of this project.
+
+\section{Installation and execution}
+
+\subsection{Requirements}
+\begin{itemize}
+
+\item \js{} requires that the Java SDK or JRE (at least version 1.5) be
+installed.\footnote{The default font for \js{} is \p{Lucida Sans
+Typewriter}. This font may no longer be available in the JRE you use. If
+you have the fonts from a previous version you can copy them to the
+\p{lib/fonts} directory as explained in
+\url{http://java.sun.com/j2se/1.5.0/docs/guide/intl/font.html}.
+Alternatively, you can change the configuration file to use a monospaced
+font such as \p{Courier} that is installed by default.}
+
+\end{itemize}
+
+\subsection{Installation}
+This section describes installation on a Windows system;
+for custom installation and for other systems, see Appendix~\ref{a.install}.
+
+\begin{itemize}
+\item Download the \js{} installation file called \p{com.spinroot.jspin-N.exe},
+where \p{N} is the version number.
+Execute the installation file.
+\item Create a directory \verb=c:\mingw= and download the C
+compiler archive \p{mingw.exe} into that directory. Execute this self-extracting file.
+\end{itemize}
+
+\subsection{Configuring and running \js{}}
+\begin{itemize}
+\item The installation will create the following subdirectories: \p{docs} for the
+documentation, \p{com.spinroot.jspin} and \p{com.spinroot.spinSpider} for the source files,
+\p{txts} for the text files
+(help, about and copyright), and \p{com.spinroot.jspin-examples} and \p{spider-examples}
+for example programs.
+\item To run \js{}, execute the command \p{javaw -jar jSpin.jar}.
+An optional argument names the \prm{} file to be opened initially.
+A batch file \p{run.bat} is supplied which contains this command.
+\item Configuration data (Appendix~\ref{a.cfg}) is in the file
+\p{config.cfg}.
+\textbf{When upgrading \js{}, erase the configuration file before installing
+a new version, so that new configuration options will be recognized.}
+\item \js{} searches for the configuration file in the current
+directory; if it is not found, \js{} searches for it in the directory
+where the jar file is installed; if it is not found there, a new file
+with default values is written.
+\end{itemize}
+
+\subsection{Running \spd{} without \js{}*}
+If you want to run \spd{} without \js{}, create a configuration file
+with entries for the \p{SPIN}, \p{C\_COMPILER}, \p{PAN} and \p{DOT}
+commands. The prologues for the \dtf{} file can be changed in
+\p{Config.java} in the package \p{com.spinroot.spinSpider}.
+
+The \p{SpinSpider} class has a main method that can be invoked from a command
+line:
+\begin{verbatim}
+java -cp jSpin.jar com.spinroot.spinSpider.SpinSpider arguments filename
+\end{verbatim}
+\p{filename} is the source file name. The arguments are:
+
+\hspace*{1cm}
+\begin{tabular}{ll}
+\p{-pn} & The number of processes \p{n};\\
+\p{-vname} & One parameter for each variable \p{name};\\
+\p{-dot} & \dtf{} format;\\
+\p{-Txxx} & \dtf{} format followed by conversion to \p{xxx} format,\\
+& the default is \p{png};\\
+\p{-fsm} & \fsm{} format;\\
+\p{-t1} & Emphasize trail;\\
+\p{-t2} & Display the trail only;\\
+\p{-a} & Display automata for \prm{} source;\\
+\p{-small} & Small size for states; if absent, large size is used;\\
+\p{-bold} & Bold for emphasis; if absent, color is used.\\
+\p{-debug} & Write debug file;\\
+\end{tabular}\\
+\noindent{}The \p{-p} and \p{-v} arguments must be given (unless \p{-a} is selected).
+
+\subsection{Running \fil{} without \js{}*}
+To run \fil{} from the command line, first create a file with the output
+of a (random or guided) simulation:
+\begin{verbatim}
+ spin -p -l -g -r -s -X src.pml > src.raw
+\end{verbatim}
+Next, run \fil{}:
+\begin{verbatim}
+ java -cp jSpin.jar com.spinroot.filterSpin.FilterSpin src.raw
+\end{verbatim}
+There are two optional arguments: \p{-v} to give a list of excluded
+variables and \p{-s} to give a list of excluded statements, as described
+in Section~\ref{s.filter}. The arguments may be file names or lists of
+identifiers separated with a separator string (by default \p{"\#"}, but
+it can be changed in \p{Config.java}\footnote{Do not use a backslash or
+dollar sign.}). At least one separator must be given so that the
+argument is not interpreted as a file name):
+\begin{verbatim}
+ java -cp jSpin.jar com.spinroot.filterSpin.FilterSpin -v "temp#i" -s "i+1#" src.raw
+\end{verbatim}
+The filtered output is sent to standard output and can be piped or
+redirected as needed. The configuration file must contain values for the
+properties listed in Appendix~\ref{a.cfg} under \emph{filter settings}.
+
+\section{\js{} Overview}
+The user interface includes a menu, a toolbar and three text areas.
+Menu and toolbar commands have keyboard mnemonics or accelerators.
+These can be easily configured by modifying the file \p{Config.java} and
+rebuilding.
+
+The left text area is used to display \prm{} source files. The bottom
+text area is used to display messages from both \spn{} and \js{}. The
+right text area is used to display the output from \spn{}: statements
+executed, values of variables and results of verifications. The text
+areas can be resized by dragging the dividers and an area can be hidden
+by clicking on the triangles in the dividers; the initial sizes can be
+set in the configuration file. The toolbar button \bu{Maximize} (with
+its mnemonic \bu{Alt-M}) toggles between a normal split pane and a
+maximized right text area that displays the \spn{} output.
+
+\begin{figure}[tb]
+\begin{center}
+\includegraphics[width=140mm]{com.spinroot.jspin.png}
+\end{center}
+\end{figure}
+
+\begin{description}
+\item[\bu{File}] This menu includes selections for \bu{New}, \bu{Open},
+\bu{Save}, \bu{Save As}, and \bu{Exit}. \bu{Switch file} closes the
+current file and opens the last file that was edited, if any. This is
+useful for working with both a source file and an included file.
+
+\item[\bu{Edit}] This menu includes selections for \bu{Undo}, \bu{Redo},
+\bu{Copy}, \bu{Cut}, \bu{Paste}, \bu{Find} and \bu{Find again}.
+
+\item[\bu{Options}] This menu enables you to edit the option strings for
+each of the phases of execution of \spn{} and the C compiler. Normally, you
+will not need to change the options except for those that are more
+conveniently changed in \bu{Options/Common} or \bu{Settings}
+(Section~\ref{s.run}). \bu{Default} restores the default
+values and \bu{Save} saves the current set of option strings in the
+configuration file. In addition, the following configuration items are
+automatically saved:
+\begin{itemize}
+\item \p{SOURCE\_DIRECTORY}: the last directory from which a source file was opened.
+\item The current values of the splitpane dividers \p{TB\_DIVIDER} and
+\p{LR\_DIVIDER}.
+\item The current value of the width \p{SELECT\_BUTTON} for interactive
+simulation.
+\end{itemize}
+The file can be saved
+to the \bu{current} or \bu{install} directory. \textbf{Changes in the
+\spn{} options can cause the assumptions on the input to \p{filter} to
+become falsified. Be careful!}
+
+\item[\bu{Settings}] This menu sets parameters for the simulation and
+verification (Section~\ref{s.run}).
+
+\item[\bu{Output}] This menu controls the display of the simulation output
+in the right text area. \bu{Output/Maximize} toggles the text area to be
+maximized, hiding the editing area. \bu{Output/Save output} saves the
+contents of the text area in a file with extension \p{.out}.
+To debug the filtering algorithm,
+select \bu{Output/Raw output} to write a file with extension
+\p{.raw} that contains the raw \spn{} output;
+\bu{Output/Display raw} will display this file.
+The other items in this menu are discussed in Section~\ref{s.run}.
+
+\item[\bu{SpinSpider}] This menu enables interactive execution of the \spd{}
+tool for creating graphical representations for the state diagram of a
+\prm{} program. See the separate documentation for this tool.
+
+\item[\bu{Help}] \bu{Help} displays a short help file and \bu{About}
+displays copyright information about the software.
+\end{description}
+
+\section{Running \spn{}}\label{s.run}
+In the \bu{Spin} menu (and on the toolbar) are five selections for
+running \spn{}. They all use the \prm{} source file that has been opened,
+and save the file before execution.
+During simulation and verification,
+you can select \bu{Stop} to terminate the \spn{} process that has been forked.
+\begin{description}
+\item[\bu{Check}] Runs a \emph{syntax check}.
+\item[\bu{Random}] Runs a \emph{random simulation}.
+\item[\bu{Interactive}] Runs an \emph{interactive simulation}.
+\item[\bu{Guilded}] Runs a \emph{guided simulation} using the trail
+file created by the execution of the analyzer.
+\item[\bu{Verify}] Runs an \emph{verification}.
+\end{description}
+\textbf{If you terminate \js{} while \spn{} is running (for example by entering \bu{ctrl-C} from the
+command line), make sure to terminate the \spn{} process as well.}\\
+In Windows this is done by pressing \bu{ctrl-alt-del}, followed by
+selecting \bu{Task List} and \bu{Processes}. Select \bu{spin.exe} and
+\bu{End Process}.
+
+\subsection{Simulation}\label{s.sim}
+\bu{Check} should be run before any simulation run to ensure better display
+of errors.
+
+\bu{Settings/Max steps} changes the \p{-u} option to limit the number of
+simulation steps, and \bu{Settings/Max depth} changes the \p{-m} option
+to limit the \p{pan} search depth.
+
+A nonzero value for \bu{Settings/Seed} will be used as the seed for generating
+random numbers, enabling a random simulation to be repeated.
+
+\subsubsection{Interactive simulation}
+During an interactive simulation, a dialog frame will pop up with a list
+of statements that can be executed. The list can be displayed either as
+a row of buttons, or---if there is not enough room---as a pulldown menu.
+The choice of the format is dynamically determined according to the
+value of the configuration option \p{SELECT\_MENU}. By setting this
+value to an extreme, you can force the list to a certain format. There
+are also configuration options for setting the width and height of the
+buttons or menu items.
+
+The dialog can be navigated using the mouse; closing the dialog frame
+will terminate interactive simulation. For keyboard navigation:
+\begin{description}
+\item[Buttons] \bu{Tab} and \bu{Shift-Tab} move through the buttons
+and \bu{Space} selects the highlighted button. Press \bu{Esc} to terminate.
+\item[Menu] Press down arrow to display the list and to highlight the
+item you want; press \bu{Return} to select it. Press \bu{Esc} to terminate.
+\end{description}
+
+\subsubsection{Filtered output}\label{s.filter}
+The contents of the \spn{} output can be changed by selecting
+\bu{Options/Common}. This pops up a dialog with check boxes to select the
+\spn{} output options: statements (\p{-p}), local variables (\p{-l}),
+global variables (\p{-g}), messages sent (\p{-s}) and messages received
+(\p{-r}).
+
+Select \bu{Output/Exclude variables} to create a list of strings defining
+variables to be \emph{excluded} from the display. Any variable containing
+a string from the list is not displayed; for example, \p{:init:} will
+exclude all variables of the \p{init} process. If the variable name is
+prefixed by \p{+}, it will be included anyway. For exmple, if you have an
+array variable \p{test}, then the entries \p{test} and \p{+[1]} will
+exclude display of the elements of \p{test} except for \p{test[1]}. The
+list is saved on a file with extension \p{.exc}.
+
+Similarly, a file of excluded statements can be created. The file
+extension is \p{.exs} and it may be edited by selecting \bu{Output/Exclude
+statements}. \bu{Exclude statements} should \emph{not} be used with
+interactive simulation.
+
+The output strings from \p{printf} statements is displayed normally. Optionally,
+you can request that only strings beginning with \p{MSC:} be displayed (\p{MSC=true}).
+
+\subsection{Verification}
+Selecting \bu{Spin/Verify} or the \bu{Verify} button on the tool bar
+performs the three steps required to verify a \prm{} program in \spn{}:
+\begin{itemize}
+\item Run \spn{} to create an analyzer in files \p{pan.*}.
+\item Run the C compiler to compile the analyzer \p{pan.c}.
+\item Run the analyzer \p{pan.exe}.
+\end{itemize}
+There are three modes of verification in \spn{},
+one of which must be selected from the combo box on the toolbar
+or the radio buttons in the menu \bu{Settings}:
+\begin{description}
+\item[Safety] Checks basic safety properties such as assertions.
+\item[Acceptance] Checks for acceptance cycles.
+\item[Non-Progress] Checks that every cycle contains a
+\p{progress} label.
+\end{description}
+See the \spn{} reference manual for descriptions of these modes.
+Checking \bu{Weak fairness} in the menu \bu{Settings}
+or on the toolbar performs the verification only for executions that are
+weakly fair.
+
+\subsection{LTL formulas}\label{s.ltl}
+
+A correctness claim specified by a \emph{Linear Temporal Logic (LTL)}
+formula must be converted to an automaton written as a \prm{} \p{never}
+claim. LTL formulas can be contained within the \prm{} source code or
+they can be placed in external files.
+
+\subsection{Internal formulas}
+
+An LTL formula can be included in a \prm{} program:
+\begin{verbatim}
+ltl { []<>csp && []<>csq }
+\end{verbatim}
+The formula is translated internally by \spn{} into a \p{never} claim.
+
+A number of \emph{named} formulas can be included within a \prm{} program:
+\begin{verbatim}
+ltl p0 { [](gate <= 1) }
+ltl p1 { []((count == 0) -> (gate == 0)) }
+ltl p2 { [](((gate == 0) && notInTest) -> (count == 0)) }
+\end{verbatim}
+To select which claim will be used in a verification, enter the
+\emph{name} in the \bu{LTL formula} text field and select \bu{LTL name}.
+
+The above examples show that internal LTL formulas can have expressions
+and not just names as atomic propositions.
+
+\textbf{\spn{} automatically negates LTL formulas contained within a
+\prm{} program.}
+
+\subsubsection{External formulas}
+
+Enter a formula (such as \p{[]p} or \p{<>p}) in the text field labelled
+\bu{LTL formula} on the menu bar and select \bu{Translate} from the
+toolbar or the \bu{Convert} menu; the formula translated into a
+\p{never} claim which will be added to the next \spn{} verification. The
+\p{never} claim is stored in a file with extension \p{.ltl}. The formula
+is not automatically translated, so whatever \p{never} claim exists, if
+any, will continue to be used until \bu{Translate} is invoked again.
+
+\textbf{Before the formula is translated it is negated by \js}. This is
+done so that the LTL formula as displayed represents the correctness
+property being checked and not the negated formula which if satisfied
+represents a counterexample. Should you wish to enter negations yourself
+as in \spn{}, you can change the configuration file option
+\p{NEGATE\_LTL} to false; this can also be done by toggling
+\bu{Settings/Negate LTL}.
+
+LTL formulas are saved in \emph{property files} with extension \p{.prp}.
+By default, when you open a \prm{} file,
+\js{} opens and loads a \p{.prp} file of the same name.
+You can also load a different file by selecting \bu{Load} from
+the toolbar or the \bu{Convert} menu;
+the file name will be displayed on the toolbar.
+If the file does not exist,
+the text field is cleared and the new name is used when you \bu{Translate} the formula
+you enter.
+
+The property file is saved whenever the source file is
+and also before translation.
+
+\bu{Convert/Clear} not only to clears the text field, but ensures that
+no LTL formula will be used in the next verification. After selecting
+\bu{Convert/Clear} an empty file will not be saved. Note: In earlier
+versions of \js{}, a button \bu{Clear} was available on the toolbar;
+this has now been removed and the menu selection must be used.
+
+\section{\spd{}}
+Open a \prm{} program. If you wish to emphasize or draw the computation
+described by a \p{trail} file, execute \spn{} in verification mode with
+appropriate assertions or LTL formulas to create the trail file for a counterexample.
+
+Select \bu{SpinSpider/SpinSpider} (\bu{ctrl-D}) from the menu or \bu{SpinSpider}
+from the toolbar and the following frame will appear:
+\begin{center}
+\includegraphics[width=9cm,keepaspectratio=true]{spd.png}
+\end{center}
+\begin{description}
+\item[\bu{Format}] The output format, normally \bu{dot} or one of the formats
+such as \bu{png} that can be obtained by running \dt{}. The \bu{fsm} format is
+experimental and the processing of the trail file is not done for this format.
+\textbf{If \p{png} is selected as the format, the state diagram will be displayed in a
+separate frame when \spd{} has terminated.}
+\item[\bu{Processes}] The number of processes in the program (for generation of
+the \p{never} claim).
+\item[\bu{Variables}] A list of the variables in the program (for generation of
+the \p{never} claim).
+\item[\bu{No trail}, \bu{Emphasize trail}, \bu{Only trail}] If the first option
+is selected, the entire state diagram is created. The second option colors nodes
+and edges in the state diagram that are part of the trail. The third option
+creates a diagram containing only those states and nodes that are part of the
+trail.
+\item[\bu{Automata}] This displays the source of the \prm{} program as a set
+of automata, one for each \p{proctype}; for the \emph{third attempt}, this is:
+\begin{center}
+\includegraphics[width=7cm,keepaspectratio=true]{third-automata.png}
+\end{center}
+The states are labeled with the source code line numbers and the edges with
+the statements associated with each transition. \p{atomic} transitions
+are emphasized.
+\item[\bu{Dot size}] Chooses between two prologues for the \dtf{} file. The small
+option works better for display within \js{}.
+\item[\bu{Trail style}] Chooses between two ways of emphasizing the trail in a
+computation: in color or bold. The latter is useful for including the diagram in
+a document or for users with difficulty seeing colors.
+\item[\bu{Debug}] Writes a file (extension \p{.dbg}) with the internal data
+structures as collected from the execution of \spn{}: states, transitions,
+statements and the trail.
+(The file is automatically generated if \bu{Automata} is selected.)
+This file can be displayed by selecting
+\bu{SpinSpider/Display debug} from the \js{} menu.
+\item[\bu{Run}] Saves the current parameters in a file with the same name as the
+source file and with extension \p{.spd}. Then \spd{} is run.
+\item[\bu{Cancel}] Returns without saving the parameters or running \spd{}.
+\end{description}
+
+\subsection{\prm{} programs for \spd{}}
+The directory \bu{spider-examples} contains concurrent programs that demonstrate
+the use of \spd{}.
+
+To reduce the size of the diagrams, use \emph{remote references} rather than
+ghost variables in the specification of correctness properties. For example, to
+prover that mutual exclusion holds in the third attempt (\p{third.pml}), declare
+labels \p{cs:} at the two critical sections and then define the symbol:
+\begin{verbatim}
+#define notmutex (p@cs && q@cs)
+\end{verbatim}
+Mutual exclusion can shown by doing a verification in \bu{Safety} mode
+with the LTL formula:
+\begin{verbatim}
+!<>notmutex
+\end{verbatim}
+Recall that \spn{} finds the \emph{first} counterexample in a depth-first
+search, not the shortest one. The trail for the program for the fourth
+attempt (\p{fourth.pml}) was created by running \p{pan} with the \p{-i}
+parameter to do an iterative search for a short counterexample.
+
+The line numbers will be accurate if the first alternative of a \p{do}- or
+\p{if}-statement is written on the same line as the keyword. Note that all
+alternatives are considered to belong to the line containing the keyword.
+
+%\newpage
+
+\section{Troubleshooting}
+\begin{description}
+\item[\spn{} won't execute] Check the configuration items
+for \spn{} and the C compiler.
+It is recommended that they be in your path.
+\item[Exceptions in Filter] Your own output might be
+interfering with the filtering algorithm.
+If configuration option \p{MSC} is selected, use \p{printf} only with strings
+prefixed by \p{MSC:} and terminated by a newline.
+\item[Verification doesn't seem to work]
+Make sure that you have selected the appropriate mode
+from the \bu{Settings} menu:
+\bu{Safety}, \bu{Acceptance}, \bu{Non-progress}.
+If you are using an LTL formula,
+\bu{Translate} it before verifying.
+\item[Your computer works slowly] Forked processes for \spn{} are still executing.
+Terminate them from the operating system.
+\item[Settings, options and the directory aren't remembered]
+You must select \bu{Options/Save} before exiting \spn{}.
+\item[Preprocessing failed] Simple preprocessing like the use of \verb=#define=
+is done internally by \spn{}. For more complicated processing, \spn{} calls the
+C compiler's preprocessor. This error message can result if there is a problem
+with the installation; check also that the C compiler is in the path.
+To debug preprocessing, execute \spn{} with the argument \p{-I};
+this will perform preprocessing only on the \prm{} file and display the result.
+\end{description}
+
+\newpage
+
+\section{Software structure*}
+The software is divided into three Java packages.
+
+\subsection{Package \p{com.spinroot.jspin}}
+\p{jSpin} is the main class and contains declarations
+of the GUI components and instances
+of the classes \p{Editor} and \p{RunSpin}.
+Method \p{init} and the methods it calls initialize the GUI.
+Method \p{action\-Per\-formed} is the event handler for all the menu items
+and buttons; it calls the appropriate methods for handling each event.
+The \bu{About} and \bu{Help} options are implemented by reading files
+\p{copyright.txt} and \p{help.txt}, respectively, and displaying
+them in a \p{JFrame} with a scrollable \p{JTextArea}.
+
+\p{JSpinFileFilter} is used with a \p{JFileChooser}
+when opening and saving files: \prm{} source files,
+LTL property files and \spn{} display output files.
+
+\p{Options} is the dialog frame with check boxes for
+changing the \spn{} display options.
+
+\p{Exclude} is the dialog frame for editing the list
+of variable strings to be excluded from the display.
+
+\p{Config} contains declarations of compile time configuration items.
+Method \p{init} calls \p{set\-Default\-Properties} to initialize the instance
+of \p{Properties} with the default values of the dynamic configuration
+items; it then attempts to load the configuration file, and if unsuccessful,
+the default properties are written to a new file.
+
+\p{Editor} implements an editor using operations on a
+\p{JTextArea}. It implements the interface \p{Document\-Listener} to flag
+when the source has been modified. The class is also responsible
+for the LTL formula \p{JTextField}. \p{jSpin} calls method \p{writeFile}
+to write \p{ltl} and \p{out} files, and method \p{readFile} to read
+the text files to be displayed.
+
+\p{LineNumbers} extends a \p{JComponent} to create line numbers
+for the \p{RowHeaderView} of the editor \p{JScrollPane}
+(thanks to Niko Myller for this code).
+
+\p{UndoRedo} was extracted from an example on the Java web site.
+
+The event handler in \p{jSpin} calls \p{run} in class \p{RunSpin}
+to execute \spn{}, the C compiler and the analyzer \p{pan}.
+\p{run} creates a thread of class \p{RunThread},
+and uses \p{ProcessBuilder} to set up the
+command, directory, merge the output and error streams,
+and set up streams for I/O.
+The call \p{runAndWait} is used for short calls like \bu{Check}
+and the creation and compilation of a model;
+this call does not return until the completion of the subprocess.
+The call \p{run} will return immediately after it has created the thread.
+In this case, the event handler in \p{jSpin} calls \p{isSpinRunning}
+to create a thread to poll for termination of \spn{};
+by creating a separate thread, the event handler is freed to accept
+a selection of \bu{Stop}.
+
+When \p{Select a statement} is received during an interactive simulation,
+method \p{select} is called.
+This method displays the choices in the bottom text area and pops up a
+dialog to enable the user to make a selection.
+A \p{JFrame} is created in a new thread of the inner class \p{SelectDialog} to wait
+for the selection.
+\p{select} polls \p{selectedValue} which is set with the selected button
+value or zero if the frame is closed or \bu{Esc} pressed.
+In that case, \p{q} is sent to \spn{} to terminate the simulation.
+
+\js{} contains source code for interactively invoking \spd{}.
+The class \p{SpiderOptions} pops up frame where parameters can be entered and
+\spd{} invoked. Each \prm{} file can have its own set of parameters; these are stored
+in property files with extension \p{.spd} and managed by \p{SpiderFile}.
+If the diagram is created in \bu{PNG} format, it is displayed interactively:
+\p{DisplayImage} creates a frame and
+the image is loaded into an instance of \p{ImagePanel}.
+
+\subsection{Package \p{com.spinroot.filterSpin}}
+
+The output filtering is encapsulated in class \p{Filter}.
+For each line received from the output stream, \p{run}
+(of \p{RunThread}) calls \p{filter}
+which modifies the string; the modified string is displayed in the
+appropriate text area.
+A \p{TreeMap} is maintained for mapping variable names into value strings.
+Each new variable is checked against the list of excluded strings before
+it is entered in the map.
+For standalone filtering, the package
+contains a \p{Config} class and a class \p{FilterSpin} with a main method.
+
+\subsection{Package \p{com.spinroot.spinSpider}}
+
+Most of the processing of the \spd{} program is done
+in the class \p{SpinSpider}.
+Static data like strings and the prologue for the \dtf{} file are
+contained in the class \p{Config}.
+
+Four classes are used for
+objects containing information extracted from the files:
+\begin{itemize}
+\item \p{State} contains the program counter values and the variables names
+and values that are extracted from the output of the \p{never} claim in the
+\p{.chk} file.
+\item \p{Transition} contains the transitions and is obtained by following
+the \p{New}, \p{Old}, \p{Up} and \p{Down} debugging trace in the \p{.chk} file.
+A stack is used to simulate the depth-first search of \spn{}.
+\item \p{Statement} contains the states, line numbers and source statements
+from the \p{.d} file.
+\item \p{Trail} contains the \p{id} of an entry in the trail file.
+\end{itemize}
+The processing sequence is invoked from the method \p{runSpider}.
+\p{runProcess} is called several times to fork processes as described in
+Section~\ref{s.how}. The \p{.d} file is analyzed in \p{createStatements},
+and the \p{.chk} file is analyzed in \p{readCheckFile} of class \p{Read}.
+If requested, these data structures are written to a file in method
+\p{writeDebug} of class \p{Write}.
+
+The class \p{SetTrail} traverses the state diagram according to the trail and
+marks states and transitions that are part of the trail.
+
+The data structures are used to write the files in class \p{Write}.
+See the description of the \fsm{} format to understand \p{writeFSMGraph}.
+In \p{writeDOTGraph}, the \p{states} array is traversed sequentially
+writing out numbered nodes including labels for each node. The
+elements of this array store the program counters of each process in the
+state; these are used to search the \p{statements} array for \emph{all}
+statements that start from the program counter. The line numbers and
+source code of the statements are appended to the label. The variable
+values are also obtained from the \p{states} array. The transitions are
+taken directly from the \p{transitions} array. Finally, \dt{} is called, if
+requested.
+
+The class \p{DrawAutomata} uses the information in the \p{.d} file
+to write a \dtf{} file and then calls \dt{}.
+
+\subsection{How \spd{} works}\label{s.how}
+
+\spd{} works with numerous files:
+\begin{itemize}
+\item The source file with extension \p{.pml}.
+\item A \p{never} claim file with extension \p{.nvr} as described below;
+this is normally generated automatically.
+\item The file with extension \p{.chk} obtained by running a verification of
+the program with the \p{-DCHECK} option and with the \p{never} claim that
+prints out the program counters and variable values.
+\item The statement file with extension \p{.d} obtained by running a verification
+with the \p{-d} option.
+\item A file with extension \p{.spd} that is used by \js{} to save \spd{} parameters.
+\item A debug file with extension \p{.dbg}.
+\end{itemize}
+
+\spd{} runs the following commands in subprocesses (\p{prog.pml} is the source file):
+
+\hspace*{1cm}\p{spin -a prog.pml}\\
+\hspace*{1cm}\p{gcc -DCHECK -DSAFETY -DPRINTF -o pan pan.c}\\
+\hspace*{1cm}\p{pan > prog.chk}\\
+\hspace*{1cm}\p{pan -d > prog.d}
+
+Then it runs its own algorithm to create a \dtf{} file. Finally, \dt{} is
+optionally run to create a display file in some format like \p{png}.
+
+A \prm{} program must be modified by giving a special \p{never} claim; this is
+generated automatically and included using the \p{-N} argument to \spn{}.
+
+The \p{never} claim contains a single \p{printf} statement in a loop, which is
+executed with every step of the verifier. The statement prints the
+following tokens separated by spaces:
+\begin{itemize}
+\item The string \p{*spd*};
+\item The number of processes, followed by the values of \p{pc\_value}
+for each process;
+\item The number of variables, followed by their names and values.
+\end{itemize}
+For the algorithm shown in the introduction the \p{never} claim is:
+\begin{verbatim}
+never {
+ do :: printf("*spd* 2 %d %d 2 wantp %d wantq %d \n",
+ pc_value(0), pc_value(1), wantp, wantq)
+ od
+}
+\end{verbatim}
+
+\newpage
+
+\appendix
+
+\section{Installation}\label{a.install}
+
+\subsection{\spn{} version}
+
+Version 6.0.0 of \spn{} changed its output format; starting with version
+5.0, \js{} expects this format. You can still run \js{} with earlier
+versions of \spn{} (for example, 4.30): set the configuration option
+\p{VERSION} to a number less than 6 before you run \js{} and ensure that
+the option \p{SPIN} names the earlier version of the \spn{} executable
+(or copy the file over the later version).
+
+\subsection{Custom installation of \js{}}
+\begin{itemize}
+\item Download the \js{} distribution file called \p{com.spinroot.jspin-N.zip},
+where \p{N} is the version number.
+Extract the files into a clean directory.
+%\textbf{Do not} install to a directory with spaces like \verb=c:\Program Files=.
+
+\item Install \spn{} and \textsc{dot} (\textsc{dot} is only needed for
+\textsc{SpinSpider}).
+
+\item Install an ANSI C compiler.
+
+\item Modify the configuration file \p{config.cfg} to reflect the
+locations of the programs.
+\end{itemize}
+
+\subsection{Building \js{}}
+
+To rebuild \js{}, execute \p{build.bat}, which will compile all the source
+files and create the file \p{jSpin.jar} with the manifest file.
+
+\subsection{Installing a C compiler}\label{a.c}
+The \p{gcc} compiler is normally used with \spn{}. On Windows, there are
+two distributions: Cygwin (\url{http://cygwin.com}) is a comprehensive
+Linux-like environment, and a smaller distribution called MinGW
+(\url{http://mingw.org/}). To install MinGW, download the following archives and
+open them in directory \verb=c:\mingw= \emph{in the following order}:
+\begin{quote}
+\p{binutils-V.tar.gz}\\
+\p{gcc-core-V.tar.gz}\\
+\p{mingw-runtime-V.tar.gz}\\
+\p{w32api-V.tar.gz}
+\end{quote}
+where V is the version and build number.
+It is OK if some files are overwritten when opening the archive.
+
+Set the path in
+\begin{quote}
+\p{Start/Control Panel/System/Advanced/Environment Variables/PATH}
+\end{quote}
+to include \verb=c:\mingw\bin=.
+
+\subsection{Installing \js{} on \textsc{Mac OS X}}\label{a.mac}
+
+Thanks to Christiaan Ottow for providing this material.
+
+Currently, there is no precompiled version of \spn{}, so you will have to
+compile it from the source code. Instructions for doing this are given
+in Section~2c of the webpage:
+\begin{quote}
+\url{http://spinroot.com/spin/Man/README.html}
+\end{quote}
+An alternative approach is change the location of the preprocessor specified in
+lines 75--88 of \p{main.c} from \p{/lib/cpp} to \p{/usr/bin/cpp}.
+
+\js{} is compiled with \p{-target 1.5} to conform with the \textsc{Java}
+version currently available on the \textsc{Mac}.
+
+To install \js{}:
+\begin{itemize}
+\item Unzip the file \p{com.spinroot.jspin-V-V.zip}.
+\item Download \textsc{Graphviz} from
+\begin{quote}
+\url{http://www.pixelglow.com/graphviz/download}
+\end{quote}
+Open the \p{dmg} file you downloaded and copy the \textsc{Graphviz}
+application to the Applications folder.
+\item Open the configuration file \p{config.cfg} in a text editor and change the
+values of the following properties:
+\begin{itemize}
+\item \p{SPIN} to the directory with the compiled \spn{};
+\item \p{SOURCE\_DIRECTORY} to the subdirectory \p{com.spinroot.jspin-examples} of the directory
+where you unpacked \js{};
+\item \p{C\_COMPILER} to directory containing \p{gcc},
+usually \p{/usr/bin/gcc}. You can verify this by issuing the command \p{which gcc};
+\item \p{PAN} to \p{pan};
+\item \p{DOT} to \p{/Applications/Graphviz.app/Contents/MacOS/dot}.
+\end{itemize}
+\end{itemize}
+
+\js{} can now be run by using the \p{Terminal} to execute the following command
+in the \p{com.spinroot.jspin} directory:
+\begin{quote}
+\p{java com.spinroot.jspin.jSpin}
+\end{quote}
+
+\subsection{Installing \js{} on \textsc{Linux}}\label{a.linux}
+
+Thanks to Vsevolod Krishchenko for providing this material.
+
+\begin{itemize}
+
+\item Install gcc, C preprocessor, dot, java. For Debian/Ubuntu:
+\begin{verbatim}
+ sudo apt-get install gcc cpp graphviz sun-java6-jre
+\end{verbatim}
+\item Install spin as described above.
+\item Make the following changes in \p{config.cfg}:
+\begin{verbatim}
+ C_COMPILER=gcc
+ DOT=dot
+\end{verbatim}
+You many need to set \p{SINGLE\_QUOTE} to \p{true}.
+\item Create a shell file with:
+\begin{verbatim}
+ #!/bin/sh
+ java -jar jSpin.jar
+\end{verbatim}
+\end{itemize}
+
+\section{Configuration file}\label{a.cfg}
+
+These tables give the properties in the configuration file and their
+default values.
+
+\begin{center}
+
+\begin{tabular}{|p{.3\textwidth}|p{.4\textwidth}|}
+\hline
+\multicolumn{2}{|c|}{Version of \spn{}}\\ \hline
+\textsc{\ttfamily VERSION} &\verb+6+\\\hline
+\end{tabular}
+
+\bigskip
+
+\begin{tabular}{|p{.3\textwidth}|p{.4\textwidth}|}
+\hline
+\multicolumn{2}{|c|}{Directories for source and compilers}\\ \hline
+\textsc{\ttfamily SOURCE\_DIRECTORY} & \verb+"com.spinroot.jspin-examples"+ \\
+\textsc{\ttfamily C\_COMPILER} &\verb+"c:\\mingw\\bin\\gcc.exe"+ \\
+\textsc{\ttfamily SPIN} &\verb+"bin\\spin.exe"+ \\
+\textsc{\ttfamily DOT} &\verb+"bin\\dot.exe"+ \\
+\textsc{\ttfamily PAN} &\verb+"pan"+ \\ \hline
+\end{tabular}
+
+\bigskip
+
+\begin{tabular}{|p{.3\textwidth}|p{.4\textwidth}|}
+\hline
+\multicolumn{2}{|c|}{Options for executing \spn{}}\\ \hline
+\textsc{\ttfamily COMMON\_OPTIONS} &\verb+"-g -l -p -r -s"+\\
+\textsc{\ttfamily CHECK\_OPTIONS} &\verb+"-a -v"+\\
+\textsc{\ttfamily RANDOM\_OPTIONS} &\verb+"-X"+\\
+\textsc{\ttfamily INTERACTIVE\_OPTIONS} &\verb+"-i -X"+\\
+\textsc{\ttfamily VERIFY\_OPTIONS} &\verb+"-a"+\\
+\textsc{\ttfamily C\_COMPILER\_OPTIONS} &\verb+"-o pan pan.c"+\\
+\textsc{\ttfamily PAN\_OPTIONS} &\verb+"-X"+\\
+\textsc{\ttfamily TRAIL\_OPTIONS} &\verb+"-t -X"+\\
+\textsc{\ttfamily TRANSLATE\_OPTIONS} &\verb+"-f"+\\
+\textsc{\ttfamily MAX\_STEPS} {\ttfamily (-u)} & \verb+250+\\
+\textsc{\ttfamily MAX\_DEPTH} {\ttfamily (-m)} & \verb+2000+\\
+\textsc{\ttfamily SEED} {\ttfamily (-n)} & \verb+0+\\
+\textsc{\ttfamily FAIRNESS} & \verb+true+\\
+\textsc{\ttfamily RAW} & \verb+false+\\
+\textsc{\ttfamily SINGLE\_QUOTE} & \verb+false+\\
+\textsc{\ttfamily NEGATE\_LTL} & \verb+true+\\
+\textsc{\ttfamily VERIFY\_MODE} & \verb+"Safety"+\\\hline
+\end{tabular}
+
+\bigskip
+
+\begin{tabular}{|p{.3\textwidth}|p{.4\textwidth}|}
+\hline
+\multicolumn{2}{|c|}{Filter settings}\\ \hline
+\textsc{\ttfamily PROCESS\_TITLE} & \verb+Process +\\
+\textsc{\ttfamily PROCESS\_WIDTH} & \verb+7+\\
+\textsc{\ttfamily STATEMENT\_TITLE} & \verb+Statement +\\
+\textsc{\ttfamily STATEMENT\_WIDTH} & \verb+18+\\
+\textsc{\ttfamily VARIABLE\_WIDTH} &\verb+10+\\
+\textsc{\ttfamily LINES\_PER\_TITLE} &\verb+20+\\
+\textsc{\ttfamily MSC} &\verb+false+\\
+\hline
+\end{tabular}
+
+\bigskip
+
+\begin{tabular}{|p{.3\textwidth}|p{.4\textwidth}|}
+\hline
+\multicolumn{2}{|c|}{Text settings}\\ \hline
+\textsc{\ttfamily WRAP} &\verb+true+\\
+\textsc{\ttfamily TAB\_SIZE} &\verb+4+\\
+\textsc{\ttfamily FONT\_FAMILY} & \verb+"Lucida Sans Typewriter"+\\
+\textsc{\ttfamily FONT\_STYLE} & \verb+java.awt.Font.PLAIN+\\
+\textsc{\ttfamily FONT\_SIZE} & \verb+14+\\\hline
+\end{tabular}
+
+\bigskip
+
+\begin{tabular}{|p{.3\textwidth}|p{.4\textwidth}|}
+\hline
+\multicolumn{2}{|c|}{Frame size}\\ \hline
+\textsc{\ttfamily WIDTH} &\verb+1000+\\
+\textsc{\ttfamily HEIGHT} &\verb+700+\\\hline
+\end{tabular}
+
+\bigskip
+
+\begin{tabular}{|p{.3\textwidth}|p{.4\textwidth}|}
+\hline
+\multicolumn{2}{|c|}{Interactive dialog settings}\\ \hline
+\textsc{\ttfamily SELECT\_BUTTON} &\verb+120+\\
+\textsc{\ttfamily SELECT\_HEIGHT} &\verb+70+\\
+\textsc{\ttfamily SELECT\_MENU} &\verb+5+\\\hline
+\end{tabular}
+
+\bigskip
+
+\begin{tabular}{|p{.3\textwidth}|p{.4\textwidth}|}
+\hline
+\multicolumn{2}{|c|}{Location of dividers}\\ \hline
+\textsc{\ttfamily LR\_DIVIDER} &\verb+400+\\
+\textsc{\ttfamily TB\_DIVIDER} &\verb+500+\\
+\textsc{\ttfamily MIN\_DIVIDER} &\verb+50+\\\hline
+\end{tabular}
+
+\bigskip
+
+\begin{tabular}{|p{.3\textwidth}|p{.4\textwidth}|}
+\hline
+\multicolumn{2}{|c|}{Delay while waiting for user input}\\ \hline
+\textsc{\ttfamily POLLING\_DELAY} &\verb+200+\\\hline
+\end{tabular}
+
+\end{center}
+
+\end{document}
diff --git a/docs/spin-card.tex b/docs/spin-card.tex
index b048e52..60430f7 100644
--- a/docs/spin-card.tex
+++ b/docs/spin-card.tex
@@ -1,286 +1,286 @@
-%
-% Spin Reference Card
-%
-% Copyright 2007 by Mordechai (Moti) Ben-Ari.
-% This work is licensed under the Creative Commons
-% Attribution-Noncommercial-ShareAlike 3.0 License.
-% To view a copy of this license,
-% visit http://creativecommons.org/licenses/by-nc-sa/3.0/;
-% or, (b) send a letter to Creative Commons,
-% 543 Howard Street, 5th Floor, San Francisco, California, 94105, USA.
-%
-\documentclass{leaflet}
-%\documentclass[notumble,nocombine]{leaflet} % One page per column
-\usepackage{mathptmx}
-\usepackage{url}
-\newcommand{\sct}[1]{\subsubsection{#1}\mbox{}\\}
-\newcommand{\spc}{\hspace*{1.5em}}
-\CutLine*{1}\CutLine*{3}\CutLine*{4}\CutLine*{6}
-
-\title{\vspace*{-2ex}Spin Reference Card}
-\author{\vspace*{-2ex}Mordechai (Moti) Ben-Ari\vspace*{-2ex}}
-
-\begin{document}
-\maketitle
-\thispagestyle{empty}
-\vspace*{-2ex}
-{\scriptsize Copyright 2007 by Mordechai (Moti) Ben-Ari.
-This work is licensed under the Creative Commons
-Attribution-Noncommercial-ShareAlike 3.0 License.
-To view a copy of this license,
-visit \url{http://creativecommons.org/licenses/by-nc-sa/3.0/};
-or, (b) send a letter to Creative Commons,
-543 Howard Street, 5th Floor, San Francisco, California, 94105, USA.}
-
-\sct{Datatypes}
-\texttt{bit} (1 bit)\\
-\texttt{bool} (1 bit)\\
-\texttt{byte} (8 bits unsigned)\\
-\texttt{short} (16$^{*}$ bits signed)\\
-\texttt{int} (32$^{*}$ bits signed)\\
-\texttt{unsigned} ($\leq$ 32$^{*}$ bits unsigned)\\
-\spc{}$^{*}$ - for a 32-bit machine.\\
-\texttt{pid}\\
-\texttt{chan}\\
-\texttt{mtype} = \{ name, name, ... \} (8 bits) \\
-\texttt{typedef} typename \{ sequence of declarations \}\\
-\\
-Declaration - type var [= initial value]\\
-Default initial values are zero.\\
-Array declaration - type var[N] [= initial value]\\
-Array initial value assigned to all elements.
-
-\sct{Operators (descending precedence)}
-\spc{}\verb+()+ \spc{}\verb+[]+ \spc{}\verb+.+ \\
-\spc{}\verb+!+ \spc{}\verb+~+ \spc{}\verb=++= \spc{}\verb+--+\\
-\spc{}\verb+*+ \spc{}\verb+/+ \spc{}\verb+%+\\
-\spc{}\verb=+= \spc{}\verb+-+ \\
-\spc{}\verb+<<+ \spc{}\verb+>>+ \\
-\spc{}\verb+<+ \spc{}\verb+<=+ \spc{}\verb+>+ \spc{}\verb+>= +\\
-\spc{}\verb+==+ \spc{}\verb+!=+\\
-\spc{}\verb+&+ \\
-\spc{}\verb+^+ \\
-\spc{}\verb=|= \\
-\spc{}\verb+&&+\\
-\spc{}\verb=||=\\
-\spc{}\verb+( ... -> ... : ... )+ conditional expression\\
-\spc{}\verb+=+
-
-\sct{Predefined}
-Constants - \texttt{true}, \texttt{false}\\
-Variables (read-only except \texttt{\_}):\\
-\spc{}\texttt{\_} - write-only hidden scratch variable\\
-\spc{}\texttt{\_nr\_pr} - number of processes\\
-\spc{}\texttt{\_pid} - instantiation number of executing process\\
-\spc{}\texttt{timeout} - no executable statements in the system?
-
-\sct{Preprocessor}
-\texttt{\#define} name (arguments) string\\
-\texttt{\#undef}, \texttt{\#if}, \texttt{\#ifdef}, \texttt{\#ifndef}, \texttt{\#else}, \texttt{\#endif}\\
-\texttt{\#include} "file name"\\
-\texttt{inline} name (arguments) \{ ... \}
-
-\sct{Statements}
-Assignment - var = expression, var\verb=++=, var\verb=--=\\
-\texttt{assert}(expression)\\
-\\
-\texttt{printf}, \texttt{printm} - print to standard output\\
-\spc{}\verb=%c= (character), \verb=%d= (decimal), \verb=%e= (\texttt{mtype}),\\
-\spc{}\verb=%o= (octal), \verb=%u= (unsigned), \verb=%x= (hex)\\
-\texttt{scanf} - read from standard input in simulation mode\\
-\\
-\texttt{skip} - no operation\\
-\texttt{break} - exit from innermost \texttt{do} loop\\
-\texttt{goto} - jump to label\\
-Label prefixes with a special meaning:\\
-\spc{}\texttt{accept} - accept cycle\\
-\spc{}\texttt{end} - valid end state\\
-\spc{}\texttt{progress} - non-progress cycle\\
-\\
-\texttt{atomic} \{ ... \} - execute without interleaving\\
-\texttt{d\_step} \{ ... \} - execute deterministically (no jumping
-in or out; deterministic choice among true guards; only the first
-statement can block).\\
-\\
-\{ ... \} \texttt{unless} \{ ... \} - exception handling.
-
-\sct{Guarded commands}
-\texttt{if} :: guard \verb=->= statements :: ... \texttt{fi}\\
-\texttt{do} :: guard \verb=->= statements :: ... \texttt{od}\\
-\texttt{else} guard - executed if all others are false.
-
-\sct{Processes}
-Declaration - \texttt{proctype} procname (parameters) \{ ... \}\\
-Activate with prefixes - \texttt{active} or \texttt{active}[N]\\
-Explicit process activation - \texttt{run} procname (arguments)\\
-Initial process - \texttt{init} \{ ... \}\\
-Declaration suffixes:\\
-\spc{}\texttt{priority} - set simulation priority\\
-\spc{}\texttt{provided} (e) - executable only if expression e is true
-
-\sct{Channels}
-\texttt{chan} ch = [ capacity ] \texttt{of} \{ type, type, ... \}\\
-\\
-\begin{tabular}{@{\hspace*{0pt}}ll}
-ch ! args & send\\
-ch !! args & sorted send\\
-\\
-ch ? args & receive and remove if \emph{first} message matches\\
-ch ?? args & receive and remove if \emph{any} message matches\\
-ch ? \verb+<+args\verb+>+ & receive if \emph{first} message matches\\
-ch ?? \verb+<+args\verb+>+ & receive if \emph{any} message matches\\
-ch ? [args] & poll \emph{first} message (side-effect free)\\
-ch ?? [args] & poll \emph{any} message (side-effect free)\\
-\\
-\end{tabular}
-Matching in a receive statement: constants and \texttt{mtype} symbols must match;
-variables are assigned the values in the message;
-\texttt{eval}(expression) forces a match with the current
-value of the expression.\\
-\\
-\texttt{len}(ch) - number of messages in a channel\\
-\texttt{empty}(ch) / \texttt{nempty}(ch) - is channel empty / not empty?\\
-\texttt{full}(ch) / \texttt{nfull}(ch) - is channel full / not full?\\
-\\
-Channel use assertions:\\
-\spc{}\texttt{xr} ch - channel ch is receive-only in this process\\
-\spc{}\texttt{xs} ch - channel ch is send-only in this process
-
-\newpage
-
-\sct{Temporal logic}
-
-\vspace*{-2ex}\spc{}
-\begin{tabular}{cl}
-\verb+!+ & not\\
-\verb+&&+ & and\\
-\verb+||+ & or\\
-\verb+->+ & implies\\
-\verb+<->+ & equivalent to\\
-&\\
-\verb+[]+ & always\\
-\verb+<>+ & eventually\\
-\verb+X+ & next\\
-\verb+U+ & strong until\\
-\verb+V+ & dual of U defined as \verb+pVq <-> !(!pU!q)+
-\end{tabular}
-
-\sct{Remote references}
-Test the control state or the value of a variable:\\
-\spc{}process-name \verb+@+ label-name\\
-\spc{}proctype-name [ expression ] \verb+@+ label-name\\
-\spc{}process-name : label-name\\
-\spc{}proctype-name [ expression ] : label-name
-
-\sct{Never claim}
-\texttt{never} \{ ... \}.\\
-Predefined constructs that can only appear in a never claim:\\
-\spc{}\texttt{\_last} - last process to execute\\
-\spc{}\texttt{enabled}(p) - is process enabled?\\
-\spc{}\texttt{np\_} - true if no process is at a progress label\\
-\spc{}\texttt{pc\_value}(p) - current control state of process\\
-\spc{}remote references\\
-See also \texttt{trace} and \texttt{notrace}.
-
-\sct{Variable declaration prefixes}
-\texttt{hidden} - hide this variable from the system state\\
-\texttt{local} - a global variable is accessed only by one process\\
-\texttt{show} - track variable in Xspin message sequence charts
-
-\sct{Verification}
-Safety:\\
-\spc{}\verb+spin -a file+\\
-\spc{}\verb+gcc -DSAFETY -o pan pan.c+\\
-\spc{}\verb+pan+ or \verb+./pan+\\
-\spc{}\verb+spin -t -p -l -g -r -s file+
-
-\newpage
-
-Liveness:\\
-\spc{}\verb+spin -a file+\\
-\spc{}\verb+gcc -o pan pan.c+\\
-\spc{}\verb+pan -a -f+ or \verb+./pan -a -f+\\
-\spc{}\verb+spin -t -p -l -g -r -s file+
-
-\sct{Spin arguments}
-\begin{tabular}{ll}
-\texttt{-a} & generate verifier and syntax check\\
-\texttt{-i} & interactive simulation\\
-\texttt{-I} & display Promela program after preprocessing\\
-\texttt{-nN} & seed for random simulation\\
-\texttt{-t} & guided simulation with trail\\
-\texttt{-tN} & guided simulation with Nth trail\\
-\texttt{-uN} & maximum number of steps is N\\
-&\\
-\texttt{-f} & translate an LTL formula into a never claim\\
-\texttt{-F} & translate an LTL formula in a file into a never claim\\
-\texttt{-N} & include never claim from a file\\
-&\\
-\texttt{-l} & display local variables\\
-\texttt{-g} & display global variables\\
-\texttt{-p} & display statements\\
-\texttt{-r} & display receive events\\
-\texttt{-s} & display send events
-\end{tabular}
-
-\sct{Compile arguments}
-\begin{tabular}{ll}
-\texttt{-DBFS} & breadth-first search\\
-\texttt{-DNP} & enable detection of non-progress cycles\\
-\texttt{-DSAFETY} & optimize for safety\\
-\\
-\texttt{-DBITSTATE} & bitstate hashing\\
-\texttt{-DCOLLAPSE} & collapse compression\\
-\texttt{-DHC} & hash-compact compression\\
-\texttt{-DMA=n} & minimized DFA with maximum n bytes\\
-\texttt{-DMEMLIM=N} & use up to N megabytes of memory
-\end{tabular}
-
-\sct{Pan arguments}
-\begin{tabular}{ll}
-\texttt{-a} & find acceptance cycles\\
-\texttt{-f} & weak fairness\\
-\texttt{-l} & find non-progress cycles
-\end{tabular}
-
-\newpage
-
-\begin{tabular}{ll}
-\texttt{-cN} & stop after Nth error\\
-\texttt{-c0} & report all errors\\
-\texttt{-e} & create trails for all errors\\
-\texttt{-i} & search for shortest path to error\\
-\texttt{-I} & approximate search for shortest path to error\\
-\texttt{-mN} & maximum search depth is N\\
-\texttt{-wN} & $2^{N}$ hash table entries\\
-\\
-\texttt{-A} & suppress reporting of assertion violations\\
-\texttt{-E} & suppress reporting of invalid end states
-\end{tabular}
-
-\sct{Caveats}
-\vspace*{-2ex}
-\begin{itemize}
-\item Expessions must be side-effect free.
-\item Local variable declarations always take effect at the beginning of a process.
-\item A \texttt{true} guard can always be selected; an \texttt{else} guard is selected only if all others are false.
-\item Macros and \texttt{inline} do \emph{not} create a new scope.
-\item Place labels before an \texttt{if} or \texttt{do}, \emph{not} before a guard.
-\item In an \texttt{if} or \texttt{do} statement, interleaving can occur between a guard and the following statement.
-\item Processes are activated and die in LIFO order.
-\item Atomic propositions in LTL formulas must be identifiers starting with lowerase letters and must be boolean variables or symbols for boolean-valued expressions.
-\item Arrays of \texttt{bit} or \texttt{bool} are stored in bytes.
-\item The type of a message field of a channel cannot be an array;
-it can be a \texttt{typedef} that contains an array.
-\item The functions \texttt{empty} and \texttt{full} cannot be negated.
-\end{itemize}
-
-\sct{References}
-\vspace*{-2ex}
-\begin{itemize}
-\item G. J. Holzmann. \textit{The Spin Model Checker: Primer and Reference Manual},
-Addison-Wesley, 2004.\\\url{http://spinroot.com}.
-\item M. Ben-Ari. \textit{Principles of the Spin Model Checker},
-Springer, 2008.\\\url{http://www.springer.com/978-1-84628-769-5}.
-\end{itemize}
-\end{document}
+%
+% Spin Reference Card
+%
+% Copyright 2007 by Mordechai (Moti) Ben-Ari.
+% This work is licensed under the Creative Commons
+% Attribution-Noncommercial-ShareAlike 3.0 License.
+% To view a copy of this license,
+% visit http://creativecommons.org/licenses/by-nc-sa/3.0/;
+% or, (b) send a letter to Creative Commons,
+% 543 Howard Street, 5th Floor, San Francisco, California, 94105, USA.
+%
+\documentclass{leaflet}
+%\documentclass[notumble,nocombine]{leaflet} % One page per column
+\usepackage{mathptmx}
+\usepackage{url}
+\newcommand{\sct}[1]{\subsubsection{#1}\mbox{}\\}
+\newcommand{\spc}{\hspace*{1.5em}}
+\CutLine*{1}\CutLine*{3}\CutLine*{4}\CutLine*{6}
+
+\title{\vspace*{-2ex}Spin Reference Card}
+\author{\vspace*{-2ex}Mordechai (Moti) Ben-Ari\vspace*{-2ex}}
+
+\begin{document}
+\maketitle
+\thispagestyle{empty}
+\vspace*{-2ex}
+{\scriptsize Copyright 2007 by Mordechai (Moti) Ben-Ari.
+This work is licensed under the Creative Commons
+Attribution-Noncommercial-ShareAlike 3.0 License.
+To view a copy of this license,
+visit \url{http://creativecommons.org/licenses/by-nc-sa/3.0/};
+or, (b) send a letter to Creative Commons,
+543 Howard Street, 5th Floor, San Francisco, California, 94105, USA.}
+
+\sct{Datatypes}
+\texttt{bit} (1 bit)\\
+\texttt{bool} (1 bit)\\
+\texttt{byte} (8 bits unsigned)\\
+\texttt{short} (16$^{*}$ bits signed)\\
+\texttt{int} (32$^{*}$ bits signed)\\
+\texttt{unsigned} ($\leq$ 32$^{*}$ bits unsigned)\\
+\spc{}$^{*}$ - for a 32-bit machine.\\
+\texttt{pid}\\
+\texttt{chan}\\
+\texttt{mtype} = \{ name, name, ... \} (8 bits) \\
+\texttt{typedef} typename \{ sequence of declarations \}\\
+\\
+Declaration - type var [= initial value]\\
+Default initial values are zero.\\
+Array declaration - type var[N] [= initial value]\\
+Array initial value assigned to all elements.
+
+\sct{Operators (descending precedence)}
+\spc{}\verb+()+ \spc{}\verb+[]+ \spc{}\verb+.+ \\
+\spc{}\verb+!+ \spc{}\verb+~+ \spc{}\verb=++= \spc{}\verb+--+\\
+\spc{}\verb+*+ \spc{}\verb+/+ \spc{}\verb+%+\\
+\spc{}\verb=+= \spc{}\verb+-+ \\
+\spc{}\verb+<<+ \spc{}\verb+>>+ \\
+\spc{}\verb+<+ \spc{}\verb+<=+ \spc{}\verb+>+ \spc{}\verb+>= +\\
+\spc{}\verb+==+ \spc{}\verb+!=+\\
+\spc{}\verb+&+ \\
+\spc{}\verb+^+ \\
+\spc{}\verb=|= \\
+\spc{}\verb+&&+\\
+\spc{}\verb=||=\\
+\spc{}\verb+( ... -> ... : ... )+ conditional expression\\
+\spc{}\verb+=+
+
+\sct{Predefined}
+Constants - \texttt{true}, \texttt{false}\\
+Variables (read-only except \texttt{\_}):\\
+\spc{}\texttt{\_} - write-only hidden scratch variable\\
+\spc{}\texttt{\_nr\_pr} - number of processes\\
+\spc{}\texttt{\_pid} - instantiation number of executing process\\
+\spc{}\texttt{timeout} - no executable statements in the system?
+
+\sct{Preprocessor}
+\texttt{\#define} name (arguments) string\\
+\texttt{\#undef}, \texttt{\#if}, \texttt{\#ifdef}, \texttt{\#ifndef}, \texttt{\#else}, \texttt{\#endif}\\
+\texttt{\#include} "file name"\\
+\texttt{inline} name (arguments) \{ ... \}
+
+\sct{Statements}
+Assignment - var = expression, var\verb=++=, var\verb=--=\\
+\texttt{assert}(expression)\\
+\\
+\texttt{printf}, \texttt{printm} - print to standard output\\
+\spc{}\verb=%c= (character), \verb=%d= (decimal), \verb=%e= (\texttt{mtype}),\\
+\spc{}\verb=%o= (octal), \verb=%u= (unsigned), \verb=%x= (hex)\\
+\texttt{scanf} - read from standard input in simulation mode\\
+\\
+\texttt{skip} - no operation\\
+\texttt{break} - exit from innermost \texttt{do} loop\\
+\texttt{goto} - jump to label\\
+Label prefixes with a special meaning:\\
+\spc{}\texttt{accept} - accept cycle\\
+\spc{}\texttt{end} - valid end state\\
+\spc{}\texttt{progress} - non-progress cycle\\
+\\
+\texttt{atomic} \{ ... \} - execute without interleaving\\
+\texttt{d\_step} \{ ... \} - execute deterministically (no jumping
+in or out; deterministic choice among true guards; only the first
+statement can block).\\
+\\
+\{ ... \} \texttt{unless} \{ ... \} - exception handling.
+
+\sct{Guarded commands}
+\texttt{if} :: guard \verb=->= statements :: ... \texttt{fi}\\
+\texttt{do} :: guard \verb=->= statements :: ... \texttt{od}\\
+\texttt{else} guard - executed if all others are false.
+
+\sct{Processes}
+Declaration - \texttt{proctype} procname (parameters) \{ ... \}\\
+Activate with prefixes - \texttt{active} or \texttt{active}[N]\\
+Explicit process activation - \texttt{run} procname (arguments)\\
+Initial process - \texttt{init} \{ ... \}\\
+Declaration suffixes:\\
+\spc{}\texttt{priority} - set simulation priority\\
+\spc{}\texttt{provided} (e) - executable only if expression e is true
+
+\sct{Channels}
+\texttt{chan} ch = [ capacity ] \texttt{of} \{ type, type, ... \}\\
+\\
+\begin{tabular}{@{\hspace*{0pt}}ll}
+ch ! args & send\\
+ch !! args & sorted send\\
+\\
+ch ? args & receive and remove if \emph{first} message matches\\
+ch ?? args & receive and remove if \emph{any} message matches\\
+ch ? \verb+<+args\verb+>+ & receive if \emph{first} message matches\\
+ch ?? \verb+<+args\verb+>+ & receive if \emph{any} message matches\\
+ch ? [args] & poll \emph{first} message (side-effect free)\\
+ch ?? [args] & poll \emph{any} message (side-effect free)\\
+\\
+\end{tabular}
+Matching in a receive statement: constants and \texttt{mtype} symbols must match;
+variables are assigned the values in the message;
+\texttt{eval}(expression) forces a match with the current
+value of the expression.\\
+\\
+\texttt{len}(ch) - number of messages in a channel\\
+\texttt{empty}(ch) / \texttt{nempty}(ch) - is channel empty / not empty?\\
+\texttt{full}(ch) / \texttt{nfull}(ch) - is channel full / not full?\\
+\\
+Channel use assertions:\\
+\spc{}\texttt{xr} ch - channel ch is receive-only in this process\\
+\spc{}\texttt{xs} ch - channel ch is send-only in this process
+
+\newpage
+
+\sct{Temporal logic}
+
+\vspace*{-2ex}\spc{}
+\begin{tabular}{cl}
+\verb+!+ & not\\
+\verb+&&+ & and\\
+\verb+||+ & or\\
+\verb+->+ & implies\\
+\verb+<->+ & equivalent to\\
+&\\
+\verb+[]+ & always\\
+\verb+<>+ & eventually\\
+\verb+X+ & next\\
+\verb+U+ & strong until\\
+\verb+V+ & dual of U defined as \verb+pVq <-> !(!pU!q)+
+\end{tabular}
+
+\sct{Remote references}
+Test the control state or the value of a variable:\\
+\spc{}process-name \verb+@+ label-name\\
+\spc{}proctype-name [ expression ] \verb+@+ label-name\\
+\spc{}process-name : label-name\\
+\spc{}proctype-name [ expression ] : label-name
+
+\sct{Never claim}
+\texttt{never} \{ ... \}.\\
+Predefined constructs that can only appear in a never claim:\\
+\spc{}\texttt{\_last} - last process to execute\\
+\spc{}\texttt{enabled}(p) - is process enabled?\\
+\spc{}\texttt{np\_} - true if no process is at a progress label\\
+\spc{}\texttt{pc\_value}(p) - current control state of process\\
+\spc{}remote references\\
+See also \texttt{trace} and \texttt{notrace}.
+
+\sct{Variable declaration prefixes}
+\texttt{hidden} - hide this variable from the system state\\
+\texttt{local} - a global variable is accessed only by one process\\
+\texttt{show} - track variable in Xspin message sequence charts
+
+\sct{Verification}
+Safety:\\
+\spc{}\verb+spin -a file+\\
+\spc{}\verb+gcc -DSAFETY -o pan pan.c+\\
+\spc{}\verb+pan+ or \verb+./pan+\\
+\spc{}\verb+spin -t -p -l -g -r -s file+
+
+\newpage
+
+Liveness:\\
+\spc{}\verb+spin -a file+\\
+\spc{}\verb+gcc -o pan pan.c+\\
+\spc{}\verb+pan -a -f+ or \verb+./pan -a -f+\\
+\spc{}\verb+spin -t -p -l -g -r -s file+
+
+\sct{Spin arguments}
+\begin{tabular}{ll}
+\texttt{-a} & generate verifier and syntax check\\
+\texttt{-i} & interactive simulation\\
+\texttt{-I} & display Promela program after preprocessing\\
+\texttt{-nN} & seed for random simulation\\
+\texttt{-t} & guided simulation with trail\\
+\texttt{-tN} & guided simulation with Nth trail\\
+\texttt{-uN} & maximum number of steps is N\\
+&\\
+\texttt{-f} & translate an LTL formula into a never claim\\
+\texttt{-F} & translate an LTL formula in a file into a never claim\\
+\texttt{-N} & include never claim from a file\\
+&\\
+\texttt{-l} & display local variables\\
+\texttt{-g} & display global variables\\
+\texttt{-p} & display statements\\
+\texttt{-r} & display receive events\\
+\texttt{-s} & display send events
+\end{tabular}
+
+\sct{Compile arguments}
+\begin{tabular}{ll}
+\texttt{-DBFS} & breadth-first search\\
+\texttt{-DNP} & enable detection of non-progress cycles\\
+\texttt{-DSAFETY} & optimize for safety\\
+\\
+\texttt{-DBITSTATE} & bitstate hashing\\
+\texttt{-DCOLLAPSE} & collapse compression\\
+\texttt{-DHC} & hash-compact compression\\
+\texttt{-DMA=n} & minimized DFA with maximum n bytes\\
+\texttt{-DMEMLIM=N} & use up to N megabytes of memory
+\end{tabular}
+
+\sct{Pan arguments}
+\begin{tabular}{ll}
+\texttt{-a} & find acceptance cycles\\
+\texttt{-f} & weak fairness\\
+\texttt{-l} & find non-progress cycles
+\end{tabular}
+
+\newpage
+
+\begin{tabular}{ll}
+\texttt{-cN} & stop after Nth error\\
+\texttt{-c0} & report all errors\\
+\texttt{-e} & create trails for all errors\\
+\texttt{-i} & search for shortest path to error\\
+\texttt{-I} & approximate search for shortest path to error\\
+\texttt{-mN} & maximum search depth is N\\
+\texttt{-wN} & $2^{N}$ hash table entries\\
+\\
+\texttt{-A} & suppress reporting of assertion violations\\
+\texttt{-E} & suppress reporting of invalid end states
+\end{tabular}
+
+\sct{Caveats}
+\vspace*{-2ex}
+\begin{itemize}
+\item Expessions must be side-effect free.
+\item Local variable declarations always take effect at the beginning of a process.
+\item A \texttt{true} guard can always be selected; an \texttt{else} guard is selected only if all others are false.
+\item Macros and \texttt{inline} do \emph{not} create a new scope.
+\item Place labels before an \texttt{if} or \texttt{do}, \emph{not} before a guard.
+\item In an \texttt{if} or \texttt{do} statement, interleaving can occur between a guard and the following statement.
+\item Processes are activated and die in LIFO order.
+\item Atomic propositions in LTL formulas must be identifiers starting with lowerase letters and must be boolean variables or symbols for boolean-valued expressions.
+\item Arrays of \texttt{bit} or \texttt{bool} are stored in bytes.
+\item The type of a message field of a channel cannot be an array;
+it can be a \texttt{typedef} that contains an array.
+\item The functions \texttt{empty} and \texttt{full} cannot be negated.
+\end{itemize}
+
+\sct{References}
+\vspace*{-2ex}
+\begin{itemize}
+\item G. J. Holzmann. \textit{The Spin Model Checker: Primer and Reference Manual},
+Addison-Wesley, 2004.\\\url{http://spinroot.com}.
+\item M. Ben-Ari. \textit{Principles of the Spin Model Checker},
+Springer, 2008.\\\url{http://www.springer.com/978-1-84628-769-5}.
+\end{itemize}
+\end{document}
diff --git a/filterSpin/Config.java b/filterSpin/Config.java
deleted file mode 100644
index fff591d..0000000
--- a/filterSpin/Config.java
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2008 by Mordechai (Moti) Ben-Ari.
-/**
- Local configuration class for standalone FilterSpin
-*/
-package filterSpin;
-public class Config {
- static final String VERSION = "0.1";
- static final String CONFIG_FILE = "config.cfg";
- static final String SEPARATOR = "#";
-
- static void setDefaultProperties(
- java.util.Properties properties) {
- properties.put("PROCESS_WIDTH", Integer.toString(7));
- properties.put("STATEMENT_WIDTH", Integer.toString(18));
- properties.put("VARIABLE_WIDTH", Integer.toString(10));
- properties.put("LINES_PER_TITLE", Integer.toString(20));
- properties.put("PROCESS_TITLE", "Process ");
- properties.put("STATEMENT_TITLE", "Statement ");
- properties.put("MSC", Boolean.toString(false));
- }
-
- /**
- Set the default properties and then try to read configuration file
- */
- static void init(java.util.Properties properties) {
- setDefaultProperties(properties);
- try {
- properties.load(new java.io.FileInputStream(CONFIG_FILE));
- } catch (java.io.IOException e1) {
- System.err.println("Cannot open configuration file; using defaults");
- }
- }
-
- static final String USAGE =
- "FilterSpin Version " + VERSION +
- " Copyright 2008 (GNU GPL) by Moti Ben-Ari.\n" +
- "Usage java filterSpin.FilterSpin [arguments] file\n" +
- " file File with Spin output\n" +
- " -v string Variables to exclude\n" +
- " -s string Statements to exclude\n" +
- " string may be file name or list of identifiers with '/'";
-}
diff --git a/filterSpin/Filter.java b/filterSpin/Filter.java
deleted file mode 100644
index 1cb2a80..0000000
--- a/filterSpin/Filter.java
+++ /dev/null
@@ -1,247 +0,0 @@
-// Copyright 2004-10 by Mordechai (Moti) Ben-Ari. See copyright.txt.
-/**
- Filter Spin output.
- Display a table: process, statement, variables.
-*/
-package filterSpin;
-import java.util.*;
-public class Filter {
- // Properties and copies of the data from the properties
- private Properties properties;
- private static String processTitle;
- private static String statementTitle;
- private static int processWidth;
- private static int variableWidth;
- private static int statementWidth;
- private static int linesPerTitle;
- private static boolean msc;
- private static boolean newversion; // Spin version >= 6
-
- private String title; // Title string
- private int lines; // Line counter to redisplay title
-
- // Map from variable names to values
- private TreeMap variables = new TreeMap();
-
- // Excluded variable and statements
- private ArrayList excludedVar = new ArrayList();
- private ArrayList excludedState = new ArrayList();
-
- /**
- Initialize variables and local copies of properties
- */
- public void init (Properties properties) {
- variables.clear();
- title = "";
- lines = -1;
- this.properties = properties;
- processTitle = properties.getProperty("PROCESS_TITLE");
- statementTitle = properties.getProperty("STATEMENT_TITLE");
- processWidth = Integer.valueOf(properties.getProperty("PROCESS_WIDTH"));
- variableWidth = Integer.valueOf(properties.getProperty("VARIABLE_WIDTH"));
- statementWidth = Integer.valueOf(properties.getProperty("STATEMENT_WIDTH"));
- linesPerTitle = Integer.valueOf(properties.getProperty("LINES_PER_TITLE"));
- msc = Boolean.valueOf(properties.getProperty("MSC"));
- newversion = Integer.valueOf(properties.getProperty("VERSION")) >= 6;
- }
-
- // Parse string to initialize excluded arrays
- public void setExcluded(String s, boolean exVar) {
- ArrayList excluded = exVar ? excludedVar : excludedState;
- // Replace whitespace by separator
- s = s.replaceAll("\\s+", Config.SEPARATOR) + Config.SEPARATOR;
- excluded.clear();
- do {
- int nl = s.indexOf(Config.SEPARATOR);
- if (nl == -1) break;
- if (!s.substring(0,nl).equals(""))
- excluded.add(s.substring(0, nl));
- s = s.substring(nl+1);
- } while (true);
- }
-
- /**
- Check if name is excluded variable (exVar=true) or statement (exVar=false)
- For each excluded string S;
- If variable name includes S, do not display,
- but if some +T in file is in name, display anyway.
- */
- private boolean checkExcluded(String name, boolean exVar) {
- ArrayList excluded = exVar ? excludedVar : excludedState;
- for (int i = 0; i < excluded.size(); i++)
- if ((excluded.get(i).charAt(0) != '+') &&
- (name.indexOf(excluded.get(i)) != -1)) {
- boolean included = false;
- for (int j = 0; j < excluded.size(); j++)
- included = included ||
- ((excluded.get(j).charAt(0) == '+') &&
- (name.indexOf(excluded.get(j).substring(1)) != -1));
- return !included;
- }
- return false;
- }
-
- // Filter string s and return new string or "" to ignore
- public String filter(String s) {
- try {
- // Variables and queues start with double tab
- if (s.startsWith("\t\t"))
- return filterVariable(s);
-
- // Filter statements
- else if ((s.indexOf("proc") != -1) && (s.indexOf("[") != -1))
- return filterStatement(s);
-
- // Display some messages unmodified
- else if ((s.startsWith("pan:")) ||
- (s.startsWith("spin:")) ||
- (s.startsWith("tl_spin:")) ||
- (s.startsWith("Error:")) ||
- (s.startsWith("error:")) )
- return s + "\n";
- else if (s.indexOf("<<<<<") != -1)
- return s + "\n";
-
- // Display choices that have no proc and line number
- else if (s.indexOf("choice") != -1)
- return s.substring(s.indexOf("choice")) + "\n";
-
- // Display error count with bullets to emphasize
- else if (s.indexOf("errors:") != -1)
- return
- s.substring(0, s.indexOf("errors:")) + "\u2022\u2022\u2022 " +
- s.substring(s.indexOf("errors:")) + " \u2022\u2022\u2022\n";
-
- // Display MSC lines (without MSC:) if msc is true
- else if (msc && s.trim().startsWith("MSC:"))
- return s.substring(s.indexOf("MSC:")+5) + "\n";
-
- // Display printf lines if msc is false
- else if (!msc && !s.equals(""))
- return s + "\n";
- else
- return "";
- } catch (Exception e) {
- System.err.println("\n + Error in filter for:\n" + s + "\n");
- e.printStackTrace();
- return "";
- }
- }
-
- // Filter variables (including queues)
- private String filterVariable(String s) {
- String varName, varValue;
- if (s.startsWith("\t\tqueue")) {
- varName = s.substring(s.indexOf('(')+1, s.indexOf(')'));
- varValue = s.substring(s.indexOf(':')+1).trim();
- }
- else {
- varName = s.substring(2, s.indexOf('=')-1);
- varValue = s.substring(s.indexOf('=')+1).trim();
- }
- if (checkExcluded(varName, true)) return "";
- // Construct new title if new variables encountered
- boolean newTitle = !variables.containsKey(varName);
- variables.put(varName, varValue);
- if (newTitle) {
- title = formatItem(processTitle, processWidth) + " " +
- formatItem(statementTitle, statementWidth) + " " +
- collectionToString(variables.keySet()) + "\n";
- lines = -1;
- }
- return "";
- }
-
- // Filter statements
- private String filterStatement(String s) {
- String u = "";
- int procIndex = s.indexOf("proc")+4; // After "proc"
- // Get process name
- String proc =
- s.substring(procIndex, s.indexOf(")")+1).trim();
- proc = proc.substring(0, proc.indexOf("(")) +
- strip(proc.substring(proc.indexOf("(")));
-
- // Get line number and statement name
- String statement = "", line = "";
- if (s.indexOf('[') != -1) {
- if (newversion) {
- // Spin 6 has "filename:#"
- // Skip over initial ":" and start at file name
- int colonIndex = s.indexOf(":", procIndex);
- line = formatItem(
- s.substring(colonIndex+1, s.indexOf(" ", colonIndex)).trim(), 3);
- }
- else
- // Earlier versions had "line #"
- line = formatItem(
- s.substring(s.indexOf("line")+4, s.indexOf("\"")).trim(), 3);
- statement =
- strip(s.substring(s.indexOf('[')+1, s.lastIndexOf(']')));
- statement = line + " " + statement;
- }
-
- if (checkExcluded(statement, false)) return "";
-
- // For choice, display just process and statement
- if (s.indexOf("choice") != -1)
- u = s.substring(s.indexOf("choice"), s.indexOf(':')+2) +
- proc + " " + statement + "\n";
- // Display table line (unless goto/else/break)
- else if ((statement.indexOf("goto") == -1) &&
- !statement.equals("else") &&
- !statement.equals("break")) {
- u = formatItem(proc, processWidth) + " " +
- formatItem(statement, statementWidth) + " " +
- collectionToString(variables.values()) + "\n";
-
- // Display title if needed
- lines = (lines + 1) % linesPerTitle;
- if (lines == 0) u = title + u;
- }
- return u;
- }
-
- // Strip balanced parentheses
- private String strip(String s) {
- while ( (s.charAt(0)=='(') && (s.charAt(s.length()-1)==')'))
- s = s.substring(1, s.length()-1);
- return s;
- }
-
- /**
- Format a variable name or value s into a field of length len
- If item is too long, shorten it
- But, for array variables, shorten the name, not the index
- If item is too short, pad it
- */
- private String formatItem(String s, int len) {
- if (s.length() > len) {
- if (s.indexOf("[") != -1) {
- String subscript =
- s.substring(s.indexOf("["), s.lastIndexOf("]")+1);
- if (subscript.length() < len)
- return s.substring(0, len-subscript.length()) + subscript;
- else
- return s.substring(0, len);
- }
- else
- return s.substring(0,len);
- }
- else if (s.length() < len)
- return (s + " ").substring(0,len);
- else
- return s;
- }
-
- /** Transform a collection of variables to a string,
- calling formatItem for each element
- */
- private String collectionToString(Collection c) {
- String s = "";
- Iterator it = c.iterator();
- while (it.hasNext())
- s = s + formatItem(it.next(), variableWidth) + " ";
- return s;
- }
-}
diff --git a/filterSpin/FilterSpin.java b/filterSpin/FilterSpin.java
deleted file mode 100644
index ecbc71b..0000000
--- a/filterSpin/FilterSpin.java
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright 2008 by Mordechai (Moti) Ben-Ari. See copyright.txt.
-/**
- Class with main method for standalone FilterSpin
-*/
-package filterSpin;
-import java.io.*;
-class FilterSpin {
- /**
- Read the files of excluded variables/statements and
- return as a single string
- */
- private static String readFile(File fc) {
- BufferedReader textReader = null;
- String s = "";
- try {
- textReader = new BufferedReader(new FileReader(fc));
- String line;
- while (true) {
- line = textReader.readLine();
- if (line == null) break;
- else s = s + line + '\n';
- }
- textReader.close();
- return s;
- }
- catch (IOException e) {
- error("File error " + fc);
- return "";
- }
- }
-
- /**
- Read the Spin raw output and call the filter for each line
- */
- private static void filterFile(File fc, Filter filter) {
- BufferedReader textReader = null;
- try {
- textReader = new BufferedReader(new FileReader(fc));
- String line;
- while (true) {
- line = textReader.readLine();
- if (line == null) break;
- line = filter.filter(line);
- if (!line.equals("")) System.out.print(line);
- }
- textReader.close();
- }
- catch (IOException e) {
- error("File error " + fc);
- System.exit(1);
- }
- }
-
- static void error(String s) {
- System.err.println(s);
- System.exit(1);
- }
-
- public static void main(String[] args) {
- if (args.length == 0) error(Config.USAGE);
-
- // Last argument is file name
- File file = new File(args[args.length-1]);
-
- // Search for excluded file names or strings
- String exc = Config.SEPARATOR, exs = Config.SEPARATOR;
- for (int i = 0; i < args.length-1; i++)
- if (args[i].equals("-v")) exc = args[i+1];
- else if (args[i].equals("-s")) exs = args[i+1];
-
- // Create filter and property objects and initialize
- Filter filter = new Filter();
- java.util.Properties properties = new java.util.Properties();
- Config.init(properties);
- filter.init(properties);
-
- // Read excluded files (if any) and set excluded data structures
- if (exc.indexOf(Config.SEPARATOR) == -1)
- exc = readFile(new File(exc));
- filter.setExcluded(exc, true);
- if (exs.indexOf(Config.SEPARATOR) == -1)
- exs = readFile(new File(exs));
- filter.setExcluded(exs, false);
-
- // Filter the raw Spin data
- filterFile(file, filter);
- }
-}
diff --git a/jspin-examples/barz.pml b/jspin-examples/barz.pml
index 67dfa81..19554ef 100644
--- a/jspin-examples/barz.pml
+++ b/jspin-examples/barz.pml
@@ -1,50 +1,50 @@
-/* Copyright (C) 2006-10 M. Ben-Ari. See copyright.txt */
-/*
- Barz's implementation of general semaphores
- by binary semaphores
-*/
-
-#define NPROCS 3
-#define K 2
-#define PID
-#include "critical.h"
-
-byte gate = ((K == 0) -> 0 : 1);
-int count = K;
-
-bool test[NPROCS] = false;
-#define notInTest ((test[0]==false) && (test[1]==false) && (test[2]==false))
-
-/* Verify Safety with the following properties */
-
-ltl p0 { [](gate <= 1) } /* gate is a binary semaphore */
-ltl p1 { []((count == 0) -> (gate == 0)) }
-ltl p2 { [](((gate == 0) && notInTest) -> (count == 0)) }
-
-active [NPROCS] proctype P () {
- do ::
- /* Wait */
- atomic { gate > 0; gate--; test[_pid] = true; }
- assert(gate == 0);
- d_step {
- count--;
- if
- :: count > 0 -> gate++;
- :: else
- fi;
- test[_pid] = false;
- }
-
- critical_section();
-
- /* Signal */
- d_step {
- count++;
- if
- :: count == 1 -> gate++;
- :: else
- fi;
- }
- od
-}
-
+/* Copyright (C) 2006-10 M. Ben-Ari. See copyright.txt */
+/*
+ Barz's implementation of general semaphores
+ by binary semaphores
+*/
+
+#define NPROCS 3
+#define K 2
+#define PID
+#include "critical.h"
+
+byte gate = ((K == 0) -> 0 : 1);
+int count = K;
+
+bool test[NPROCS] = false;
+#define notInTest ((test[0]==false) && (test[1]==false) && (test[2]==false))
+
+/* Verify Safety with the following properties */
+
+ltl p0 { [](gate <= 1) } /* gate is a binary semaphore */
+ltl p1 { []((count == 0) -> (gate == 0)) }
+ltl p2 { [](((gate == 0) && notInTest) -> (count == 0)) }
+
+active [NPROCS] proctype P () {
+ do ::
+ /* Wait */
+ atomic { gate > 0; gate--; test[_pid] = true; }
+ assert(gate == 0);
+ d_step {
+ count--;
+ if
+ :: count > 0 -> gate++;
+ :: else
+ fi;
+ test[_pid] = false;
+ }
+
+ critical_section();
+
+ /* Signal */
+ d_step {
+ count++;
+ if
+ :: count == 1 -> gate++;
+ :: else
+ fi;
+ }
+ od
+}
+
diff --git a/jspin-examples/count.pml b/jspin-examples/count.pml
index fb88ba6..647cf15 100644
--- a/jspin-examples/count.pml
+++ b/jspin-examples/count.pml
@@ -3,24 +3,25 @@
Increment a variable in two processes.
Check that final value can be two!!
*/
-#define TIMES 10
-byte n = 0;
-byte finished = 0;
-
-active [2] proctype P() {
- byte i = 1;
- byte temp;
- do :: ( i > TIMES ) -> break
- :: else ->
- temp = n;
- n = temp + 1;
- i++
- od;
- finished++; /* Process terminates */
-}
-
-active proctype Finish() {
- finished == 2; /* Wait for termination */
+#define TIMES 10
+byte n = 0;
+byte finished = 0;
+
+active [2] proctype P() {
+ byte i = 1;
+ byte temp;
+ do :: ( i > TIMES ) -> break
+ :: else ->
+ temp = n;
+ n = temp + 1;
+ i++
+ od;
+ finished++; /* Process terminates */
+}
+
+active proctype Finish() {
+ finished == 2; /* Wait for termination */
printf("n = %d\n", n);
- assert (n > 2);
/* Assert can't be 2 */
-}
+ assert (n > 2);
+ /* Assert can't be 2 */
+}
diff --git a/jspin-examples/critical.h b/jspin-examples/critical.h
index 70c00cb..5965b33 100644
--- a/jspin-examples/critical.h
+++ b/jspin-examples/critical.h
@@ -1,37 +1,37 @@
-/* Copyright (C) 2006 M. Ben-Ari. See copyright.txt */
-/*
- Definitions for critical section
- If K is defined, checks (critical <= K), otherwise (critical == 1).
- If PID is defined, prints _pid in CS, otherwise prints a character parameter.
- If NOSTARVE is defined, you can Verify Acceptance of <>nostarve.
-*/
-
-#ifdef NOSTARVE
-bool P1inCS = false;
-#define nostarve P1inCS
-#endif
-
-byte critical = 0;
-
-#ifdef PID
-inline critical_section() {
- printf("MSC: %d in CS\n", _pid);
-#else
-inline critical_section(proc) {
- printf("MSC: %c in CS\n", proc);
-#endif
- critical++;
-#ifdef K
- assert (critical <= K);
-#else
- assert (critical == 1);
-#endif
-#ifdef NOSTARVE
+/* Copyright (C) 2006 M. Ben-Ari. See copyright.txt */
+/*
+ Definitions for critical section
+ If K is defined, checks (critical <= K), otherwise (critical == 1).
+ If PID is defined, prints _pid in CS, otherwise prints a character parameter.
+ If NOSTARVE is defined, you can Verify Acceptance of <>nostarve.
+*/
+
+#ifdef NOSTARVE
+bool P1inCS = false;
+#define nostarve P1inCS
+#endif
+
+byte critical = 0;
+
+#ifdef PID
+inline critical_section() {
+ printf("MSC: %d in CS\n", _pid);
+#else
+inline critical_section(proc) {
+ printf("MSC: %c in CS\n", proc);
+#endif
+ critical++;
+#ifdef K
+ assert (critical <= K);
+#else
+ assert (critical == 1);
+#endif
+#ifdef NOSTARVE
if :: _pid == 1 ->
P1inCS = true; P1inCS = false
:: else
- fi;
-#endif
- critical--;
-}
-
+ fi;
+#endif
+ critical--;
+}
+
diff --git a/jspin-examples/dekker.pml b/jspin-examples/dekker.pml
index 2f1f969..258710f 100644
--- a/jspin-examples/dekker.pml
+++ b/jspin-examples/dekker.pml
@@ -1,50 +1,50 @@
-/* Dekker's algorithm */
-bool wantp = false, wantq = false;
-byte turn = 1;
+/* Dekker's algorithm */
+bool wantp = false, wantq = false;
+byte turn = 1;
bool csp = false, csq = false;
-
+
ltl { []<>csp && []<>csq }
-active proctype p() {
- do
- :: wantp = true;
- do
- :: !wantq -> break;
- :: else ->
- if
- :: (turn == 1)
- :: (turn == 2) ->
- wantp = false;
- (turn == 1);
- wantp = true
- fi
- od;
+active proctype p() {
+ do
+ :: wantp = true;
+ do
+ :: !wantq -> break;
+ :: else ->
+ if
+ :: (turn == 1)
+ :: (turn == 2) ->
+ wantp = false;
+ (turn == 1);
+ wantp = true
+ fi
+ od;
csp = true;
assert (!(csp && csq));
csp = false;
- wantp = false;
- turn = 2
- od
-}
-
-active proctype q() {
- do
- :: wantq = true;
- do
- :: !wantp -> break;
- :: else ->
- if
- :: (turn == 2)
- :: (turn == 1) ->
- wantq = false;
- (turn == 2);
- wantq = true
- fi
- od;
+ wantp = false;
+ turn = 2
+ od
+}
+
+active proctype q() {
+ do
+ :: wantq = true;
+ do
+ :: !wantp -> break;
+ :: else ->
+ if
+ :: (turn == 2)
+ :: (turn == 1) ->
+ wantq = false;
+ (turn == 2);
+ wantq = true
+ fi
+ od;
csq = true;
assert (!(csp && csq));
csq = false;
- wantq = false;
- turn = 1
- od
-}
+ wantq = false;
+ turn = 1
+ od
+}
diff --git a/jspin-examples/second.pml b/jspin-examples/second.pml
index d2c37c6..a15f51c 100644
--- a/jspin-examples/second.pml
+++ b/jspin-examples/second.pml
@@ -1,26 +1,28 @@
-/* Second attempt */
-bool wantp = false, wantq = false;
+/* Second attempt */
+bool wantp = false, wantq = false;
byte critical = 0;
-
-active proctype p() {
+
+active proctype p() {
do
- ::
!wantq;
- wantp = true;
+ ::
+ !wantq;
+ wantp = true;
critical++;
assert (critical == 1);
critical--;
- wantp = false;
- od
-}
-
-active proctype q() {
+ wantp = false;
+ od
+}
+
+active proctype q() {
do
- ::
!wantp;
- wantq = true;
+ ::
+ !wantp;
+ wantq = true;
critical++;
assert (critical == 1);
critical--;
- wantq = false;
- od
-}
-
\ No newline at end of file
+ wantq = false;
+ od
+}
+
diff --git a/jspin-examples/third.pml b/jspin-examples/third.pml
index b27d820..b5adc66 100644
--- a/jspin-examples/third.pml
+++ b/jspin-examples/third.pml
@@ -1,26 +1,28 @@
-/* Third attempt */
-bool wantp = false, wantq = false;
+/* Third attempt */
+bool wantp = false, wantq = false;
byte critical = 0;
-
-active proctype p() {
+
+active proctype p() {
do
- ::
wantp = true;
- !wantq;
+ ::
+ wantp = true;
+ !wantq;
critical++;
assert (critical == 1);
critical--;
- wantp = false;
- od
-}
-
-active proctype q() {
+ wantp = false;
+ od
+}
+
+active proctype q() {
do
- ::
wantq = true;
- !wantp;
+ ::
+ wantq = true;
+ !wantp;
critical++;
assert (critical == 1);
critical--;
- wantq = false;
- od
-}
-
\ No newline at end of file
+ wantq = false;
+ od
+}
+
diff --git a/jspin.iss b/jspin.iss
index 54d2351..c9c12f1 100644
--- a/jspin.iss
+++ b/jspin.iss
@@ -1,47 +1,47 @@
-; Script generated by the Inno Setup Script Wizard.
-; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
-
-[Setup]
-AppName=jSpin - Spin Development Environment
-AppVerName=jSpin - Version 5.0
-AppPublisher=Moti Ben-Ari, Weizmann Institute of Science
-AppPublisherURL=http://stwww.weizmann.ac.il/g-cs/benari/jspin/index.html
-AppSupportURL=http://stwww.weizmann.ac.il/g-cs/benari/jspin/index.html
-AppUpdatesURL=http://stwww.weizmann.ac.il/g-cs/benari/jspin/index.html
-DefaultGroupName=jSpin
-OutputDir=c:\jspin
-DefaultDirName=c:\jspin
-AllowNoIcons=yes
-LicenseFile=C:\jspin\txt\gpl.txt
-SetupIconFile=C:\jspin\jspin.ico
-Compression=lzma
-SolidCompression=yes
-
-[Languages]
-Name: "english"; MessagesFile: "compiler:Default.isl"
-
-[Files]
-Source: "C:\jspin\bin\*"; DestDir: "{app}\bin"; Flags: ignoreversion
-Source: "C:\jspin\jspin-examples\*.p*"; DestDir: "{app}\jspin-examples"; Flags: ignoreversion
-Source: "C:\jspin\spider-examples\*.p*"; DestDir: "{app}\spider-examples"; Flags: ignoreversion
-Source: "C:\jspin\txt\*"; DestDir: "{app}\txt"; Flags: ignoreversion
-Source: "C:\jspin\jspin\*.java"; DestDir: "{app}\jspin"; Flags: ignoreversion
-Source: "C:\jspin\jspin\*.mf"; DestDir: "{app}\jspin"; Flags: ignoreversion
-Source: "C:\jspin\spinSpider\*.java"; DestDir: "{app}\spinSpider"; Flags: ignoreversion
-Source: "C:\jspin\filterSpin\*.java"; DestDir: "{app}\filterSpin"; Flags: ignoreversion
-Source: "C:\jspin\docs\*.png"; DestDir: "{app}\docs"; Flags: ignoreversion
-Source: "C:\jspin\docs\*.tex"; DestDir: "{app}\docs"; Flags: ignoreversion
-Source: "C:\jspin\docs\*.pdf"; DestDir: "{app}\docs"; Flags: ignoreversion
-Source: "C:\jspin\jspin.ico"; DestDir: "{app}"; Flags: ignoreversion
-Source: "C:\jspin\jspin.jar"; DestDir: "{app}"; Flags: ignoreversion
-Source: "C:\jspin\build.bat"; DestDir: "{app}"; Flags: ignoreversion
-Source: "C:\jspin\config.cfg"; DestDir: "{app}"; Flags: ignoreversion
-Source: "C:\jspin\run.bat"; DestDir: "{app}"; Flags: ignoreversion
-; NOTE: Don't use "Flags: ignoreversion" on any shared system files
-
-[Icons]
-Name: "{group}\jSpin"; Filename: "{app}\run.bat"; IconFilename: "{app}\jspin.ico"; WorkingDir: "{app}"
-Name: "{group}\jSpin User's Guide"; Filename: "{app}\docs\jspin-user.pdf"
-Name: "{group}\Website"; Filename: "http://stwww.weizmann.ac.il/g-cs/benari/jspin/index.html"
-Name: "{group}\Uninstall jSpin"; Filename: "{uninstallexe}"
-Name: "{userdesktop}\jSpin"; Filename: "{app}\run.bat"; IconFilename: "{app}\jspin.ico"; WorkingDir: "{app}"
+; Script generated by the Inno Setup Script Wizard.
+; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
+
+[Setup]
+AppName=jSpin - Spin Development Environment
+AppVerName=jSpin - Version 5.0
+AppPublisher=Moti Ben-Ari, Weizmann Institute of Science
+AppPublisherURL=http://stwww.weizmann.ac.il/g-cs/benari/com.spinroot.jspin/index.html
+AppSupportURL=http://stwww.weizmann.ac.il/g-cs/benari/com.spinroot.jspin/index.html
+AppUpdatesURL=http://stwww.weizmann.ac.il/g-cs/benari/com.spinroot.jspin/index.html
+DefaultGroupName=jSpin
+OutputDir=c:\com.spinroot.jspin
+DefaultDirName=c:\com.spinroot.jspin
+AllowNoIcons=yes
+LicenseFile=C:\com.spinroot.jspin\txt\gpl.txt
+SetupIconFile=C:\com.spinroot.jspin\com.spinroot.jspin.ico
+Compression=lzma
+SolidCompression=yes
+
+[Languages]
+Name: "english"; MessagesFile: "compiler:Default.isl"
+
+[Files]
+Source: "C:\com.spinroot.jspin\bin\*"; DestDir: "{app}\bin"; Flags: ignoreversion
+Source: "C:\com.spinroot.jspin\com.spinroot.jspin-examples\*.p*"; DestDir: "{app}\com.spinroot.jspin-examples"; Flags: ignoreversion
+Source: "C:\com.spinroot.jspin\spider-examples\*.p*"; DestDir: "{app}\spider-examples"; Flags: ignoreversion
+Source: "C:\com.spinroot.jspin\txt\*"; DestDir: "{app}\txt"; Flags: ignoreversion
+Source: "C:\com.spinroot.jspin\com.spinroot.jspin\*.java"; DestDir: "{app}\com.spinroot.jspin"; Flags: ignoreversion
+Source: "C:\com.spinroot.jspin\com.spinroot.jspin\*.mf"; DestDir: "{app}\com.spinroot.jspin"; Flags: ignoreversion
+Source: "C:\com.spinroot.jspin\com.spinroot.spinSpider\*.java"; DestDir: "{app}\com.spinroot.spinSpider"; Flags: ignoreversion
+Source: "C:\com.spinroot.jspin\com.spinroot.filterSpin\*.java"; DestDir: "{app}\com.spinroot.filterSpin"; Flags: ignoreversion
+Source: "C:\com.spinroot.jspin\docs\*.png"; DestDir: "{app}\docs"; Flags: ignoreversion
+Source: "C:\com.spinroot.jspin\docs\*.tex"; DestDir: "{app}\docs"; Flags: ignoreversion
+Source: "C:\com.spinroot.jspin\docs\*.pdf"; DestDir: "{app}\docs"; Flags: ignoreversion
+Source: "C:\com.spinroot.jspin\com.spinroot.jspin.ico"; DestDir: "{app}"; Flags: ignoreversion
+Source: "C:\com.spinroot.jspin\com.spinroot.jspin.jar"; DestDir: "{app}"; Flags: ignoreversion
+Source: "C:\com.spinroot.jspin\build.bat"; DestDir: "{app}"; Flags: ignoreversion
+Source: "C:\com.spinroot.jspin\config.cfg"; DestDir: "{app}"; Flags: ignoreversion
+Source: "C:\com.spinroot.jspin\run.bat"; DestDir: "{app}"; Flags: ignoreversion
+; NOTE: Don't use "Flags: ignoreversion" on any shared system files
+
+[Icons]
+Name: "{group}\jSpin"; Filename: "{app}\run.bat"; IconFilename: "{app}\com.spinroot.jspin.ico"; WorkingDir: "{app}"
+Name: "{group}\jSpin User's Guide"; Filename: "{app}\docs\com.spinroot.jspin-user.pdf"
+Name: "{group}\Website"; Filename: "http://stwww.weizmann.ac.il/g-cs/benari/com.spinroot.jspin/index.html"
+Name: "{group}\Uninstall jSpin"; Filename: "{uninstallexe}"
+Name: "{userdesktop}\jSpin"; Filename: "{app}\run.bat"; IconFilename: "{app}\com.spinroot.jspin.ico"; WorkingDir: "{app}"
diff --git a/jspin/Config.java b/jspin/Config.java
deleted file mode 100644
index 07bb7fb..0000000
--- a/jspin/Config.java
+++ /dev/null
@@ -1,404 +0,0 @@
-/* Copyright 2003-10 by Mordechai (Moti) Ben-Ari. See copyright.txt. */
-package jspin;
-import java.io.*;
-import java.awt.event.*;
-import java.util.*;
-
-public class Config {
- static Properties properties = new Properties();
- // Where to find configuration file
- public static String installationDirectory;
- public static String currentDirectory;
- public static String helpFileName;
- public static String aboutFileName;
- public static final char sep = java.io.File.separatorChar; // shortcut
-
- // Strings
- static final String SOFTWARE_NAME = "jSpin Version 5.0";
- static final String JAVA_VERSION = "1.5";
- static final String CONFIG_FILE_NAME = "config.cfg";
- static final String SPIDER_TITLE = "SpinSpider";
- static final String OPTIONS_TITLE = "Display";
- static final String SELECT = "Select a statement";
- static final String OPEN_FILE = "Open a Promela file\n";
- static final String processTitle = "Process ";
- static final String statementTitle = "Statement ";
-
- static void setDefaultProperties() {
- // Spin version: format changed with Spin 6
- properties.put("VERSION", "6");
-
- // Directories and file names
- properties.put("SOURCE_DIRECTORY", "jspin-examples");
- properties.put("C_COMPILER", "c:\\mingw\\bin\\gcc.exe");
- properties.put("SPIN", "bin" + sep + "spin.exe");
- properties.put("PAN", "pan");
- properties.put("DOT", "bin" + sep + "dot.exe");
- properties.put("HELP_FILE_NAME", "txt" + sep + "help.txt");
- properties.put("ABOUT_FILE_NAME", "txt" + sep + "copyright.txt");
-
- // Options for executing Spin
- properties.put("SINGLE_QUOTE", Boolean.toString(false));
- properties.put("COMMON_OPTIONS", "-g -l -p -r -s");
- // Check options changed for version 6 (for now)
- // properties.put("CHECK_OPTIONS", "-a -v");
- properties.put("CHECK_OPTIONS", "-a");
- properties.put("RANDOM_OPTIONS", "-X");
- properties.put("INTERACTIVE_OPTIONS", "-i -X");
- properties.put("VERIFY_OPTIONS", "-a");
- properties.put("C_COMPILER_OPTIONS", "-o pan pan.c");
- properties.put("PAN_OPTIONS", "-X");
- properties.put("TRAIL_OPTIONS", "-t -X");
- properties.put("TRANSLATE_OPTIONS", "-f");
-
- // Settings
- properties.put("MAX_STEPS", "250");
- properties.put("MAX_DEPTH", "2000");
- properties.put("SEED", "0");
- properties.put("NEGATE_LTL", Boolean.toString(true));
- properties.put("FAIRNESS", Boolean.toString(true));
- properties.put("VERIFY_MODE", Safety);
- properties.put("RAW", Boolean.toString(false));
- properties.put("PROCESS_WIDTH", Integer.toString(7));
- properties.put("STATEMENT_WIDTH",Integer.toString(18));
- properties.put("VARIABLE_WIDTH", Integer.toString(10));
- properties.put("LINES_PER_TITLE",Integer.toString(20));
-
- // Size of main frame
- properties.put("WIDTH", Integer.toString(1000));
- properties.put("HEIGHT", Integer.toString(700));
-
- // Select dialog
- properties.put("SELECT_BUTTON", Integer.toString(220));
- properties.put("SELECT_HEIGHT", Integer.toString(70));
- properties.put("SELECT_MENU", Integer.toString(5));
- properties.put("UNEXECUTABLE", Boolean.toString(false));
-
- // Location of dividers in JSplitPanes: Left-right and top-bottom
- properties.put("LR_DIVIDER", Integer.toString(400));
- properties.put("TB_DIVIDER", Integer.toString(500));
- properties.put("MIN_DIVIDER", Integer.toString(50));
-
- // Font
- properties.put("FONT_FAMILY", "Lucida Sans Typewriter");
- properties.put("FONT_STYLE", Integer.toString(java.awt.Font.PLAIN));
- properties.put("FONT_SIZE", Integer.toString(14));
-
- // Tab size in editor
- properties.put("TAB_SIZE", Integer.toString(4));
-
- // Display of Spin output
- properties.put("WRAP", Boolean.toString(true));
- properties.put("MSC", Boolean.toString(false));
- properties.put("PROCESS_TITLE", "Process ");
- properties.put("STATEMENT_TITLE", "Statement ");
-
- // Delay while waiting for user input
- properties.put("POLLING_DELAY", Integer.toString(200));
- }
-
- // Component names and mnemonics
- static final String File = "File";
- static final int FileMN = KeyEvent.VK_F;
- static final String New = "New";
- static final int NewMN = KeyEvent.VK_N;
- static final String Open = "Open";
- static final int OpenMN = KeyEvent.VK_O;
- static final String Save = "Save";
- static final int SaveMN = KeyEvent.VK_S;
- static final String SaveAs = "Save as";
- static final int SaveAsMN = KeyEvent.VK_A;
- static final String Switch = "Switch file";
- static final int SwitchMN = KeyEvent.VK_F;
- static final String Exit = "Exit";
- static final int ExitMN = KeyEvent.VK_X;
-
- static final String Editor = "Edit";
- static final int EditorMN = KeyEvent.VK_E;
- static final String Undo = "Undo";
- static final int UndoMN = KeyEvent.VK_U;
- static final String Redo = "Redo";
- static final int RedoMN = KeyEvent.VK_R;
- static final String Copy = "Copy";
- static final int CopyMN = KeyEvent.VK_C;
- static final String Cut = "Cut";
- static final int CutMN = KeyEvent.VK_T;
- static final String Paste = "Paste";
- static final int PasteMN = KeyEvent.VK_P;
- static final String Find = "Find";
- static final int FindMN = KeyEvent.VK_F;
- static final String FindAgain = "Find again";
- static final int FindAgainMN = KeyEvent.VK_A;
-
- static final String Spin = "Spin";
- static final int SpinMN = KeyEvent.VK_S;
- static final String Check = "Check";
- static final int CheckMN = KeyEvent.VK_K;
- static final String Random = "Random";
- static final int RandomMN = KeyEvent.VK_R;
- static final String Inter = "Interactive";
- static final int InterMN = KeyEvent.VK_I;
- static final String Verify = "Verify";
- static final int VerifyMN = KeyEvent.VK_V;
- static final String Trail = "Guided";
- static final int TrailMN = KeyEvent.VK_G;
- static final String Stop = "Stop";
- static final int StopMN = KeyEvent.VK_P;
-
- static final String Options = "Options";
- static final int OptionsMN = KeyEvent.VK_N;
- static final String Common = "Common";
- static final int CommonMN = KeyEvent.VK_C;
- static final String OptionsC = "C compiler";
- static final int OptionsCMN = KeyEvent.VK_C;
- static final String OptionsPan = "Pan";
- static final int OptionsPanMN = KeyEvent.VK_A;
- static final String Default = "Default";
- static final int DefaultMN = KeyEvent.VK_D;
- static final String SaveInstall = "Save install";
- static final int SaveInstallMN = KeyEvent.VK_L;
- static final String SaveCurrent = "Save current";
- static final int SaveCurrentMN = KeyEvent.VK_S;
-
- static final String Settings = "Settings";
- static final int SettingsMN = KeyEvent.VK_G;
- static final String MaxSteps = "Max steps";
- static final int MaxStepsMN = KeyEvent.VK_M;
- static final String MaxDepth = "Max depth";
- static final int MaxDepthMN = KeyEvent.VK_D;
- static final String Seed = "Seed";
- static final int SeedMN = KeyEvent.VK_S;
- static final String Negate = "Negate LTL";
- static final int NegateMN = KeyEvent.VK_L;
- static final String StWidth = "Statement width";
- static final int StWidthMN = KeyEvent.VK_S;
- static final String VarWidth = "Variable width";
- static final int VarWidthMN = KeyEvent.VK_V;
- static final String ExcludedV = "Exclude variables";
- static final int ExcludedVMN = KeyEvent.VK_E;
- static final String ExcludedS = "Exclude statements";
- static final int ExcludedSMN = KeyEvent.VK_X;
- static final String Fair = "Weak fairness";
- static final int FairMN = KeyEvent.VK_W;
- static final String Safety = "Safety";
- static final int SafetyMN = KeyEvent.VK_Y;
- static final String Acceptance = "Acceptance";
- static final int AcceptanceMN = KeyEvent.VK_C;
- static final String NonProgress = "Non-progress";
- static final int NonProgressMN = KeyEvent.VK_N;
-
- static final String Output = "Output";
- static final int OutputMN = KeyEvent.VK_U;
- static final String SaveSpin = "Save output";
- static final int SaveSpinMN = KeyEvent.VK_V;
- static final String Raw = "Raw output";
- static final int RawMN = KeyEvent.VK_R;
- static final String DisplayRaw = "Display raw";
- static final int DisplayRawMN = KeyEvent.VK_D;
-
- static final String Spider = "SpinSpider";
- static final int SpiderMN = KeyEvent.VK_D;
- static final String SpiderDisplay = "Display debug";
- static final int SpiderDisplayMN = KeyEvent.VK_L;
- static final String Run = "Run";
- static final int RunMN = KeyEvent.VK_R;
-
- static final String Help = "Help";
- static final int HelpMN = KeyEvent.VK_H;
- static final String About = "About";
- static final int AboutMN = KeyEvent.VK_A;
-
- static final String Max = "Maximize";
- static final int MaxMN = KeyEvent.VK_M;
-
- static final String LTLConvert = "Convert";
- static final int LTLConvertMN = KeyEvent.VK_C;
- static final String LTLFormula = " LTL formula ";
- static final String LTLTranslate = "Translate";
- static final int LTLTranslateMN = KeyEvent.VK_L;
- static final String LTLClear = "Clear";
- static final int LTLClearMN = KeyEvent.VK_A;
- static final String LTLLoad = "Load";
- static final int LTLLoadMN = KeyEvent.VK_O;
- static final String LTLName = "LTL name";
- static final int LTLNameMN = KeyEvent.VK_A; // For toolbar
- static final int LTLName1MN = KeyEvent.VK_N; // For menu
- static final int LTL_COLUMNS = 50;
-
- // Common options
- static final String OK = "OK";
- static final int OKMN = KeyEvent.VK_O;
- static final String Cancel = "Cancel";
- static final String Statements = "Statements";
- static final int StatementsMN = KeyEvent.VK_S;
- static final String Globals = "Globals";
- static final int GlobalsMN = KeyEvent.VK_G;
- static final String Locals = "Locals";
- static final int LocalsMN = KeyEvent.VK_L;
- static final String Sent = "Sent";
- static final int SentMN = KeyEvent.VK_T;
- static final String Received = "Received";
- static final int ReceivedMN = KeyEvent.VK_R;
- static final String ClearAll = "Clear all";
- static final int ClearAllMN = KeyEvent.VK_C;
- static final String SetAll = "Set all";
- static final int SetAllMN = KeyEvent.VK_A;
-
- // SpinSpider options
- static final String NoTrail = "No trail";
- static final int NoTrailMN = KeyEvent.VK_T;
- static final String EmphTrail = "Emphasize trail";
- static final int EmphTrailMN = KeyEvent.VK_E;
- static final String OnlyTrail = "Only trail";
- static final int OnlyTrailMN = KeyEvent.VK_O;
- static final String Automata = "Automata";
- static final int AutomataMN = KeyEvent.VK_A;
- static final String Debug = "Debug";
- static final int DebugMN = KeyEvent.VK_D;
- static final String DotSize = "Dot size";
- static final String DotSmall = "Small";
- static final int DotSmallMN = KeyEvent.VK_M;
- static final String DotLarge = "Large";
- static final int DotLargeMN = KeyEvent.VK_L;
- static final String TrailStyle = "Trail style";
- static final String TrailColor = "Color";
- static final int TrailColorMN = KeyEvent.VK_C;
- static final String TrailBold = "Bold";
- static final int TrailBoldMN = KeyEvent.VK_B;
- static final String Processes = "Processes";
- static final int MAX_PROCESS = 5;
- static final String Variables = "Variables";
- static final String Format = "Format";
- static final String DOT = "dot";
- static final String PNG = "png";
- static final String PS = "ps";
- static final String FSM = "fsm";
-
- // Accelerators
- // Select All by default "control A"
- static final String SwitchAC = "control B";
- static final String CopyAC = "control C";
- static final String SpiderAC = "control D";
- static final String VarWidthAC = "control E";
- static final String FindAC = "control F";
- static final String FindAgainAC = "control G";
- // Backspace by default "control H"
- static final String CommonAC = "control I";
- static final String ExcludedSAC = "control J";
- static final String AcceptanceAC = "control L";
- static final String MaxStepsAC = "control M";
- static final String NonProgressAC = "control N";
- static final String OpenAC = "control O";
- static final String ExitAC = "control Q";
- static final String DisplayRawAC = "control R";
- static final String SaveAC = "control S";
- static final String SafetyAC = "control T";
- static final String ExcludedVAC = "control U";
- static final String PasteAC = "control V";
- static final String FairAC = "control W";
- static final String CutAC = "control X";
- static final String RedoAC = "control Y";
- static final String UndoAC = "control Z";
-
- // Dummy accelerators
- static String
- AboutAC, CheckAC, DefaultAC, HelpAC, InterAC, LTLClearAC,
- LTLLoadAC, LTLTranslateAC, LTLNameAC, MaxAC, MaxDepthAC, SeedAC,
- NegateAC, NewAC, OptionsCAC, OptionsInterAC, OptionsPanAC,
- OptionsRandomAC, OptionsSaveCurrentAC, OptionsSaveInstallAC,
- OptionsTrailAC, RandomAC, SaveAsAC, SaveSpinAC,
- SpiderDisplayAC, StopAC, StWidthAC, TrailAC, VerifyAC, RawAC;
-
- // Initialize configuration file
- static public void init() {
- setDefaultProperties();
- // Try to open config file in current directory;
- // if not there, try installation directory;
- // if not there, write default file
- currentDirectory = System.getProperty("user.dir");
- installationDirectory = System.getProperty("java.class.path");
- int lastSeparator = installationDirectory.lastIndexOf(java.io.File.separator);
- if (lastSeparator == -1)
- installationDirectory = ".";
- else
- installationDirectory = installationDirectory.substring(0, lastSeparator);
-// System.err.println(currentDirectory + java.io.File.separator + CONFIG_FILE_NAME);
-// System.err.println(installationDirectory + java.io.File.separator + CONFIG_FILE_NAME);
- FileInputStream in = null;
- try {
- in = new FileInputStream(
- currentDirectory + java.io.File.separator + CONFIG_FILE_NAME);
- System.err.println("Read configuration file from current directory");
- } catch (FileNotFoundException e1) {
- try {
- in = new FileInputStream(
- installationDirectory + java.io.File.separator + CONFIG_FILE_NAME);
- System.err.println("Read configuration file from installation directory");
- } catch (FileNotFoundException e4) {
- System.err.println(
- "Cannot open configuration file, creating new file");
- try {
- saveFile(false);
- in = new FileInputStream(installationDirectory + java.io.File.separator + CONFIG_FILE_NAME);
- } catch (IOException e2) {
- System.err.println("Cannot write configuration file");
- return;
- }
- }
- }
- try {
- properties.load(in);
- in.close();
- } catch (IOException e3) {
- System.err.println("Cannot read configuration file");
- }
- helpFileName = installationDirectory + java.io.File.separator +
- properties.getProperty("HELP_FILE_NAME");
- aboutFileName = installationDirectory + java.io.File.separator +
- properties.getProperty("ABOUT_FILE_NAME");
- }
-
- // Save configuration file
- static void saveFile(boolean current) {
- try {
- FileOutputStream out =
- new FileOutputStream(
- (current ? currentDirectory : installationDirectory)
- + java.io.File.separator + CONFIG_FILE_NAME);
- properties.store(out, "jSpin configuration file");
- out.close();
- System.err.println("Saved jSpin configuration file config.cfg");
- } catch (IOException e2) {
- System.err.println("Cannot write configuration file");
- }
- }
-
- // Interface to get/set propertyies of various types
- public static String getStringProperty(String s) {
- return properties.getProperty(s);
- }
-
- static void setStringProperty(String s, String newValue) {
- properties.setProperty(s, newValue);
- }
-
- public static boolean getBooleanProperty(String s) {
- return Boolean.valueOf(properties.getProperty(s)).booleanValue();
- }
-
- static void setBooleanProperty(String s, boolean newValue) {
- properties.setProperty(s, Boolean.toString(newValue));
- }
-
- public static int getIntProperty(String s) {
- return Integer.valueOf(properties.getProperty(s)).intValue();
- }
-
- static void setIntProperty(String s, int newValue) {
- properties.setProperty(s, Integer.toString(newValue));
- }
-
- public static Properties getProperties() {
- return properties;
- }
-}
diff --git a/jspin/DisplayImage.java b/jspin/DisplayImage.java
deleted file mode 100644
index 22d877d..0000000
--- a/jspin/DisplayImage.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/* Copyright 2005 by Mordechai (Moti) Ben-Ari. See copyright.txt. */
-// Class DisplayFile for Help, About, Display raw
-package jspin;
-import javax.swing.*;
-import java.awt.event.*;
-class DisplayImage extends JFrame implements ActionListener {
- DisplayImage(String file) {
- ImagePanel image = new ImagePanel(file);
- getContentPane().add(new JScrollPane(image));
- setDefaultCloseOperation(
- javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
- getRootPane().registerKeyboardAction(this,
- KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0),
- JComponent.WHEN_IN_FOCUSED_WINDOW);
- setTitle(file);
- setSize((int) (0.8*Config.getIntProperty("WIDTH")),
- (int) (0.9*Config.getIntProperty("HEIGHT")));
- setLocationRelativeTo(null);
- setVisible(true);
- }
- public void actionPerformed(ActionEvent e) {
- dispose();
- }
-}
-
diff --git a/jspin/Editor.java b/jspin/Editor.java
deleted file mode 100644
index eb9b538..0000000
--- a/jspin/Editor.java
+++ /dev/null
@@ -1,347 +0,0 @@
-/* Copyright 2003-7 by Mordechai (Moti) Ben-Ari. See copyright.txt. */
-/*
- * Editor for Promela programs
- */
-
-package jspin;
-import javax.swing.*;
-import javax.swing.event.*;
-import javax.swing.border.*;
-import java.awt.*;
-import java.awt.datatransfer.*;
-import java.io.*;
-
-class Editor implements ClipboardOwner, DocumentListener {
- File file; // The file to be edited
- File lastFile; // Previous file to be edited
- String fileName; // The name of the file
- String fileRoot; // The file name without its extension
- String extension = ""; // The extension of the source file
- String root; // The path to the file
- String LTLFileName = ""; // LTL file name for this source file
- String OUTFileName = ""; // Spin display output file name
- String EXCFileName = ""; // File for excluded variable names
- String EXSFileName = ""; // File for excluded statements
- String PRPFileName = ""; // Property file name for this source file
- String PRPName; // Property file name without path
-
- private JTextArea area; // The area for editing
- private JTextField LTLField; // The area for LTL formulas
- private JTextArea messageArea; // The area for messages
- private String findString; // The string to search for
- private int findLoc; // The last location where it was found
- private boolean modified; // Was area modified?
- private boolean LTLmodified; // Was LTL field modified?
- private Border border1; // Border - not modified
- private Border border2; // Border - modified
- private static final Border border =
- BorderFactory.createMatteBorder(2,0,0,0,Color.gray);
- private Clipboard clipboard;
- private LineNumbers lineNumbers;
- private filterSpin.Filter filter; // For setting excluded variable names
-
- public Editor(JScrollPane jsp, JTextArea a, JTextArea m, JTextField l,
- javax.swing.event.UndoableEditListener ud, filterSpin.Filter f) {
- area = a;
- area.getDocument().addDocumentListener(this);
- area.getDocument().addUndoableEditListener(ud);
- LTLField = l;
- LTLField.getDocument().addDocumentListener(this);
- messageArea = m;
- PRPName = "";
- clipboard = area.getToolkit().getSystemClipboard();
- lineNumbers = new LineNumbers(area);
- jsp.setRowHeaderView(lineNumbers);
- filter = f;
- }
-
- void focus(boolean start) {
- area.requestFocusInWindow();
- if (start)
- area.setCaretPosition(0);
- }
-
- void caretToLine(int line) {
- try {
- area.requestFocusInWindow();
- area.setCaretPosition(area.getLineStartOffset(line-1));
- } catch (Exception e) {
- area.setCaretPosition(0);
- }
- }
-
- void cut() {
- if (area.getSelectionStart() != area.getSelectionEnd()) {
- String s = area.getSelectedText();
- StringSelection contents = new StringSelection(s);
- clipboard.setContents(contents, this);
- area.replaceRange(null,
- area.getSelectionStart(), area.getSelectionEnd());
- }
- }
-
- void copy() {
- if (area.getSelectionStart() != area.getSelectionEnd()) {
- String s = area.getSelectedText();
- StringSelection contents = new StringSelection(s);
- clipboard.setContents(contents, this);
- }
- }
-
- void paste() {
- Transferable content = clipboard.getContents(this);
- if (content != null) {
- try {
- String s = (String)content.getTransferData(
- DataFlavor.stringFlavor);
- area.replaceRange(s,
- area.getSelectionStart(), area.getSelectionEnd());
- } catch (Exception ex) {
- System.err.println("Can't paste");
- }
- }
- }
-
- private void showArea(String title) {
- String previousTitle = " / " +
- ((lastFile == null) ? "-" : lastFile.getName()) + " ";
- findString = null;
- findLoc = 0;
- modified = false;
- border1 = BorderFactory.createTitledBorder(
- border, " " + title + previousTitle,
- TitledBorder.LEFT, TitledBorder.TOP);
- border2 = BorderFactory.createTitledBorder(
- border, " " + title + " * " + previousTitle,
- TitledBorder.LEFT, TitledBorder.TOP);
- area.setBorder(border1);
- focus(true);
- }
-
- void newFile() {
- root = "";
- file = null;
- fileName = "";
- fileRoot = "";
- LTLFileName = "";
- OUTFileName = "";
- EXCFileName = "";
- EXSFileName = "";
- PRPFileName = "";
- area.setText("");
- showArea(" ");
- }
-
- private void setPMLRootAndName() {
- fileName = file.getName();
- if (file.getParentFile() == null)
- root = "";
- else
- root = file.getParentFile().getAbsolutePath();
- if (fileName.lastIndexOf('.') == -1)
- fileRoot = fileName;
- else {
- fileRoot = fileName.substring(0, fileName.lastIndexOf('.'));
- extension = fileName.substring(fileName.lastIndexOf('.'));
- }
- LTLFileName = root + File.separator + fileRoot + ".ltl";
- OUTFileName = root + File.separator + fileRoot + ".out";
- EXCFileName = root + File.separator + fileRoot + ".exc";
- EXSFileName = root + File.separator + fileRoot + ".exs";
- PRPFileName = root + File.separator + fileRoot + ".prp";
- PRPName = "";
- showArea(fileName);
- }
-
- private void setPRPRootAndName(File fc) {
- String fileName = fc.getName();
- String fileRoot, root;
- if (file.getParentFile() == null)
- root = "";
- else
- root = fc.getParentFile().getAbsolutePath();
- if (fileName.lastIndexOf('.') == -1)
- fileRoot = fileName;
- else
- fileRoot = fileName.substring(0, fileName.lastIndexOf('.'));
- LTLFileName = root + File.separator + fileRoot + ".ltl";
- PRPFileName = root + File.separator + fileRoot + ".prp";
- PRPName = fileRoot + ".prp";
- }
-
- // Open file: Promela (and excluded) or property file
- void openFile(File fc, boolean pml) {
- String prp = "";
- if (pml) {
- if (!fc.exists()) {
- messageArea.append("File "+fc+" does not exist\n");
- focus(true);
- return;
- }
- file = fc;
- area.setText(readFile(fc));
- setPMLRootAndName();
- prp = readFile(new java.io.File(PRPFileName));
- filter.setExcluded(readFile(new java.io.File(EXCFileName)), true);
- filter.setExcluded(readFile(new java.io.File(EXSFileName)), false);
- }
- else {
- if (fc.exists())
- prp = readFile(fc);
- else
- messageArea.append("Creating new prp file\n");
- setPRPRootAndName(fc);
- }
- LTLField.setText(prp.startsWith("Error") ? "" : prp);
- LTLmodified = false;
- }
-
- String readFile(File fc) {
- BufferedReader textReader = null;
- try {
- textReader = new BufferedReader(new FileReader(fc));
- } catch (IOException e) {
- focus(true);
- return "Error opening file " + fc;
- }
- StringWriter textWriter = new StringWriter();
- int c = 0;
- try {
- while (true) {
- c = textReader.read();
- if (c == -1)
- break;
- else
- textWriter.write(c);
- }
- } catch (IOException e) {
- focus(true);
- return "Error reading file " + fc;
- }
- try {
- textReader.close();
- }
- catch (IOException e) {
- focus(true);
- return "Error closing file " + fc;
- }
- return textWriter.toString();
- }
-
- void saveFile(File fc) {
- if (fc != null) {
- file = fc;
- setPMLRootAndName();
- LTLmodified = true; // To force saving
- modified = true;
- }
- if (LTLmodified) {
- if (!LTLField.getText().equals(""))
- writeFile(new java.io.File(PRPFileName), LTLField);
- LTLmodified = false;
- }
- if (modified) {
- area.setBorder(border1);
- writeFile(file, area);
- modified = false;
- }
- }
-
- void writeFile(File fc, javax.swing.text.JTextComponent area) {
- if (fc == null || area == null)
- return;
- BufferedWriter textWriter = null;
- try {
- textWriter = new BufferedWriter(new FileWriter(fc));
- } catch (IOException e) {
- System.err.println("Error opening file " + fc);
- focus(true);
- return;
- }
- BufferedReader textReader =
- new BufferedReader(new StringReader(area.getText()));
- int c = 0;
- try {
- while (true) {
- c = textReader.read();
- if (c == -1)
- break;
- else
- textWriter.write(c);
- }
- } catch (IOException e) {
- System.err.println("Error writing file " + fc);
- focus(true);
- return;
- }
- try {
- textWriter.flush();
- textWriter.close();
- } catch (IOException e) {
- System.err.println("Error closing file " + fc);
- focus(true);
- return;
- }
- messageArea.append("Saved " + fc.getName() + "\n");
- }
-
- void find() {
- findString = JOptionPane.showInputDialog(
- area, null, "Find", JOptionPane.PLAIN_MESSAGE);
- if (findString != null) {
- search();
- findLoc = area.getCaretPosition();
- } else
- focus(false);
- }
-
- void findAgain() {
- if (findString != null)
- search();
- else
- focus(false);
- }
-
- private void search() {
- int found = area.getText().toLowerCase().indexOf(
- findString.toLowerCase(), findLoc);
- if (found != -1) {
- findLoc = found + 1;
- area.setCaretPosition(found);
- area.moveCaretPosition(found+findString.length());
- }
- focus(false);
- }
-
- private void setModified(DocumentEvent e) {
- modified = true;
- area.setBorder(border2);
- final int lines = area.getLineCount();
- if (lineNumbers != null) {
- Runnable updateAComponent = new Runnable() {
- public void run() {
- lineNumbers.setHeightByLines(lines);
- }
- };
- SwingUtilities.invokeLater(updateAComponent);
- }
- }
-
- public void modifiedLTL() {
- LTLmodified = true;
- }
-
- public void changedUpdate(DocumentEvent e) {
- setModified(e);
- }
-
- public void insertUpdate(DocumentEvent e) {
- setModified(e);
- }
-
- public void removeUpdate(DocumentEvent e) {
- setModified(e);
- }
-
- public void lostOwnership(Clipboard clipboard, Transferable content) {}
-}
diff --git a/jspin/Filter.java b/jspin/Filter.java
deleted file mode 100644
index ed59baa..0000000
--- a/jspin/Filter.java
+++ /dev/null
@@ -1,213 +0,0 @@
-/* Copyright 2004-5 by Mordechai (Moti) Ben-Ari. See copyright.txt. */
-/*
- * Filter Spin output.
- * Display a table: process, statement, variables.
- * The width of a variable field is dynamically configurable (VARIABLE_WIDTH).
-*/
-
-package jspin;
-import java.util.*;
-
-class Filter {
- private static final String spacerTitle = " ";
-
- // Print the title repeatedly
- private static final int linesPerTitle = 20;
- private String title; // String for names of variables
- private int lines; // Line counter to redisplay title
-
- // Map of variable names and values
- private TreeMap variables = new TreeMap();
- private int oldSize; // Previous size to see if variable added
-
- // Excluded variable names and statements
- private ArrayList excludedVar = new ArrayList();
- private ArrayList excludedState = new ArrayList();
-
- // Called before each new command
- void init () {
- variables.clear();
- oldSize = 0;
- title = "";
- lines = -1;
- }
-
- // Parse string to initialize excluded array; ignore NL and CR
- void setExcluded(String s, boolean exVar) {
- ArrayList excluded = exVar ? excludedVar : excludedState;
- s = s.replace('\r', '\n');
- excluded.clear();
- do {
- int nl = s.indexOf('\n');
- if (nl == -1) break;
- if (!s.substring(0,nl).equals(""))
- excluded.add(s.substring(0,nl));
- s = s.substring(nl+1);
- } while (true);
- }
-
- // Check for excluded variables.
- // For each excluded string S;
- // If variable name includes S, do not display,
- // but if some +T in file is in name, display anyway.
- private boolean checkExcluded(String name, boolean exVar) {
- ArrayList excluded = exVar ? excludedVar : excludedState;
- for (int i = 0; i < excluded.size(); i++)
- if ((excluded.get(i).charAt(0) != '+') &&
- (name.indexOf(excluded.get(i)) != -1)) {
- boolean included = false;
- for (int j = 0; j < excluded.size(); j++)
- included = included ||
- ((excluded.get(j).charAt(0) == '+') &&
- (name.indexOf(excluded.get(j).substring(1)) != -1));
- return !included;
- }
- return false;
- }
-
- String filter(String s) {
- try {
- // Variables and queues start with double tab
- if (s.startsWith("\t\t")) {
- String varName, varValue;
- // Name and value of variable/queue to TreeMap
- if (s.startsWith("\t\tqueue")) {
- varName = s.substring(s.indexOf('(')+1, s.indexOf(')'));
- varValue = s.substring(s.indexOf(':')+1).trim();
- }
- else {
- varName = s.substring(2, s.indexOf('=')-1);
- varValue = s.substring(s.indexOf('=')+1).trim();
- }
- if (checkExcluded(varName, true)) return "";
- variables.put(varName, varValue);
- // Construct new title if new variables encountered
- if (variables.size() > oldSize) {
- title = formatItem(Config.processTitle,
- Config.getIntProperty("PROCESS_WIDTH")) +
- spacerTitle +
- formatItem(Config.statementTitle,
- Config.getIntProperty("STATEMENT_WIDTH")) +
- spacerTitle +
- collectionToString(variables.keySet()) + "\n";
- oldSize = variables.size();
- lines = -1;
- }
- return "";
- }
-
- // Display Spin and pan messages unmodified
- // Also non-prefixed error message
- else if ((s.startsWith("pan:")) ||
- (s.startsWith("spin:")) ||
- (s.startsWith("tl_spin:")) ||
- (s.startsWith("Error:")) ||
- (s.startsWith("error:")) )
- return s + "\n";
- // Display error count
- else if (s.indexOf("errors:") != -1)
- return
- s.substring(0, s.indexOf("errors:")) + "\u2022\u2022\u2022 " +
- s.substring(s.indexOf("errors:")) + " \u2022\u2022\u2022\n";
- // Display MSC lines (without MSC:)
- else if (Config.getBooleanProperty("MSC") &&
- s.trim().startsWith("MSC:"))
- return s.substring(s.indexOf("MSC:")+5) + "\n";
- // Display cycle messages
- else if (s.indexOf("<<<<<") != -1)
- return s + "\n";
-
- // Display lines with statements, including choices
- else if ((s.indexOf("proc") != -1) && (s.indexOf("line") != -1)) {
- String u = "";
- // Get process name
- String proc =
- s.substring(s.indexOf("proc")+4, s.indexOf(")")+1).trim();
- proc = proc.substring(0, proc.indexOf("(")) +
- strip(proc.substring(proc.indexOf("(")));
- // Get line number and statement name
- String statement = "";
- if (s.indexOf('[') != -1) {
- statement = formatItem(
- s.substring(s.indexOf("line")+4,s.indexOf("\"")).trim(), 3);
- statement = statement + " " +
- strip(s.substring(s.indexOf('[')+1, s.lastIndexOf(']')));
- }
- if (checkExcluded(statement, false)) return "";
- // For choice, display just process and statement
- if (s.indexOf("choice") != -1)
- u = s.substring(s.indexOf("choice"), s.indexOf(':')+2) +
- proc + " " + statement + "\n";
- // Display table line (unless goto/else/break)
- else if ((statement.indexOf("goto") == -1) &&
- !statement.equals("else") &&
- !statement.equals("break")) {
- u = formatItem(proc,
- Config.getIntProperty("PROCESS_WIDTH")) +
- spacerTitle +
- formatItem(statement,
- Config.getIntProperty("STATEMENT_WIDTH")) +
- spacerTitle +
- collectionToString(variables.values()) + "\n";
- lines = (lines + 1) % linesPerTitle;
- // Display title if needed
- if (lines == 0) u = title + u;
- }
- return u;
- }
- // Display choices that have no proc and line number
- else if (s.indexOf("choice") != -1)
- return s.substring(s.indexOf("choice")) + "\n";
- else if (!Config.getBooleanProperty("MSC") && !s.equals(""))
- return s + "\n";
- else
- return "";
-
- } catch (Exception e) {
- System.err.println("\n + jSpin error in filter for:\n" + s + "\n");
- e.printStackTrace();
- return "";
- }
- }
-
- // Strip parentheses
- String strip(String s) {
- while ( (s.charAt(0)=='(') && (s.charAt(s.length()-1)==')'))
- s = s.substring(1, s.length()-1);
- return s;
- }
-
- // Format a variable name or value
- private String formatItem(String s, int len) {
- // Item is too long, must shorten it
- if (s.length() > len) {
- // Array variable: shorten name, not index
- if (s.indexOf("[") != -1) {
- String subscript =
- s.substring(s.indexOf("["), s.lastIndexOf("]")+1);
- if (subscript.length() < len)
- return s.substring(0,
- len-subscript.length()) + subscript;
- else
- return s.substring(0, len);
- }
- else
- return s.substring(0,len);
- }
- // Item is too short, pad it
- else if (s.length() < len)
- return (s + " ").substring(0,len);
- else
- return s;
- }
-
- // Transform a collection to a string, calling formatItem for each element
- private String collectionToString(Collection c) {
- String s = "";
- Iterator it = c.iterator();
- while (it.hasNext())
- s = s + formatItem(it.next(),
- Config.getIntProperty("VARIABLE_WIDTH")) + " ";
- return s;
- }
-}
diff --git a/jspin/MANIFEST.MF b/jspin/MANIFEST.MF
deleted file mode 100644
index 5983cab..0000000
--- a/jspin/MANIFEST.MF
+++ /dev/null
@@ -1,3 +0,0 @@
-Manifest-Version: 1.0
-Main-Class: jspin.jSpin
-
diff --git a/jspin/Options.java b/jspin/Options.java
deleted file mode 100644
index 8bdb4e9..0000000
--- a/jspin/Options.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/* Copyright 2005 by Mordechai (Moti) Ben-Ari. See copyright.txt. */
-/*
- * Dialog for setting Common Options
- */
-
-package jspin;
-import javax.swing.*;
-import java.awt.event.*;
-
-class Options extends JFrame implements ActionListener, ItemListener {
- static final String
- ST = "-p", LOC = "-l", GLO = "-g", SENT = "-s", REC = "-r";
- private JCheckBox stBox, locBox, gloBox, sentBox, recBox;
- private JButton okButton, cancelButton, clearAllButton, setAllButton;
- private JPanel buttonPanel, OKPanel;
- private boolean st, loc, glo, sent, rec;
-
- JCheckBox create(String s, boolean set, int mn) {
- JCheckBox cb = new JCheckBox(s, set);
- cb.setMnemonic(mn);
- cb.addItemListener(this);
- buttonPanel.add(cb);
- return cb;
- }
-
- Options() {
- String s = Config.getStringProperty("COMMON_OPTIONS");
- st = s.indexOf(ST) != -1;
- loc = s.indexOf(LOC) != -1;
- glo = s.indexOf(GLO) != -1;
- sent = s.indexOf(SENT) != -1;
- rec = s.indexOf(REC) != -1;
- buttonPanel = new JPanel();
- buttonPanel.setLayout(new java.awt.GridLayout(5,1));
- stBox = create(Config.Statements, st, Config.StatementsMN);
- locBox = create(Config.Locals, loc, Config.LocalsMN);
- gloBox = create(Config.Globals, glo, Config.GlobalsMN);
- sentBox = create(Config.Sent, sent, Config.SentMN);
- recBox = create(Config.Received, rec, Config.ReceivedMN);
- OKPanel = new JPanel();
- OKPanel.setLayout(new java.awt.GridLayout(2,2));
- okButton = new JButton(Config.OK);
- cancelButton = new JButton(Config.Cancel);
- clearAllButton = new JButton(Config.ClearAll);
- setAllButton = new JButton(Config.SetAll);
- okButton.setMnemonic(Config.OKMN);
- clearAllButton.setMnemonic(Config.ClearAllMN);
- setAllButton.setMnemonic(Config.SetAllMN);
- OKPanel.add(okButton);
- OKPanel.add(cancelButton);
- OKPanel.add(setAllButton);
- OKPanel.add(clearAllButton);
- okButton.addActionListener(this);
- cancelButton.addActionListener(this);
- setAllButton.addActionListener(this);
- clearAllButton.addActionListener(this);
- getRootPane().setDefaultButton(okButton);
- getRootPane().registerKeyboardAction(this,
- KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0),
- JComponent.WHEN_IN_FOCUSED_WINDOW);
- getContentPane().add(buttonPanel, java.awt.BorderLayout.CENTER);
- getContentPane().add(OKPanel, java.awt.BorderLayout.SOUTH);
- setTitle(Config.OPTIONS_TITLE);
- setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
- setSize(200, 250);
- setLocationRelativeTo(null);
- validate();
- setVisible(true);
- }
-
- private void setClear(boolean b) {
- st = b; loc = b; glo = b; sent = b; rec = b;
- stBox.setSelected(b);
- locBox.setSelected(b);
- gloBox.setSelected(b);
- sentBox.setSelected(b);
- recBox.setSelected(b);
- }
-
- public void actionPerformed(ActionEvent e) {
- String options = "";
- if (e.getSource() == okButton) {
- options = options + (st ? ST + " " : "");
- options = options + (loc ? LOC + " " : "");
- options = options + (glo ? GLO + " " : "");
- options = options + (sent ? SENT + " " : "");
- options = options + (rec ? REC + " " : "");
- Config.setStringProperty("COMMON_OPTIONS", options);
- dispose();
- }
- else if (e.getSource() == setAllButton) {
- setClear(true);
- }
- else if (e.getSource() == clearAllButton) {
- setClear(false);
- }
- else
- dispose();
- }
-
- public void itemStateChanged(ItemEvent e) {
- if (e.getItemSelectable() == stBox)
- st = e.getStateChange() == ItemEvent.SELECTED;
- else if (e.getItemSelectable() == locBox)
- loc = e.getStateChange() == ItemEvent.SELECTED;
- else if (e.getItemSelectable() == gloBox)
- glo = e.getStateChange() == ItemEvent.SELECTED;
- else if (e.getItemSelectable() == sentBox)
- sent = e.getStateChange() == ItemEvent.SELECTED;
- else if (e.getItemSelectable() == recBox)
- rec = e.getStateChange() == ItemEvent.SELECTED;
- }
-}
diff --git a/jspin/RunSpin.java b/jspin/RunSpin.java
deleted file mode 100644
index f3b5a54..0000000
--- a/jspin/RunSpin.java
+++ /dev/null
@@ -1,376 +0,0 @@
-/* Copyright 2003-4 by Mordechai (Moti) Ben-Ari. See copyright.txt. */
-/*
-* Fork process for running Spin
-* Manage dialog for interactive simulation
-*/
-
-package jspin;
-import javax.swing.*;
-import java.io.*;
-import java.awt.event.*;
-import java.util.StringTokenizer;
-
-class RunSpin {
- private Editor editor; // The editor object
- private filterSpin.Filter filter; // The filter object
- private RunThread runThread; // Thread object for running Spin
- private SelectDialog selectDialog; // Thread object for select dialog
-
- private JTextArea messageArea; // The message area
- private JTextArea area; // Output area display
- private PrintWriter rawWriter; // To write raw spin output
-
- private String command, parameters; // The command being executed
- private boolean filtering; // Should the output be filtered
- private static final int MAX_SELECTIONS = 50;
- private String[] selections = new String[MAX_SELECTIONS];
- // Statements selected from
-
- RunSpin(Editor e, JTextArea m, filterSpin.Filter f) {
- editor = e;
- messageArea = m;
- filter = f;
- }
-
- // Called by jSpin to run Spin
- void run(JTextArea area, boolean filtering, String command, String parameters) {
- this.filtering = filtering;
- this.area = area;
- this.command = command;
- this.parameters = parameters;
- filter.init(Config.properties);
- // Make sure that a file has been opened
- if (editor.file == null) {
- jSpin.append(messageArea, Config.OPEN_FILE);
- return;
- }
- // Save editor buffer and set up display areas
- editor.saveFile(null);
- if (area != messageArea)
- this.area.setText("");
- jSpin.append(messageArea, command + " " + parameters + " ... ");
- // Create a thread to run Spin and start it
- runThread = new RunThread();
- runThread.start();
- }
-
- // Run Spin and wait for it to complete
- void runAndWait(JTextArea area, boolean filtering, String command, String parameters) {
- run(area, filtering, command, parameters);
- if (runThread == null) return; // If file not open
- try {
- runThread.join();
- jSpin.append(messageArea, "done!\n");
- } catch (InterruptedException e) {}
- }
-
- // Check is Spin is still running
- boolean isRunning() {
- return (runThread != null) && runThread.isAlive();
- }
-
- // Kill the thread running Spin and the selection dialog
- void killSpin() {
- if (runThread != null) {
- runThread.killSpin();
- runThread.interrupt();
- runThread = null;
- }
- if (selectDialog != null) {
- selectDialog.disposeDialog();
- selectDialog.interrupt();
- selectDialog = null;
- }
- jSpin.append(messageArea, "\nSpin process stopped\n");
- }
-
- // Class RunThread enables Spin to run asynchronously
- private class RunThread extends Thread {
- private Process p;
-
- public void run() {
- try {
- if (Config.getBooleanProperty("RAW"))
- rawFile();
- // Use ProcessBuilder to run Spin, redirecting ErrorStream
- String[] sa = stringToArray(command, parameters);
-// for (int i = 0; i < sa.length; i++) System.out.println(sa[i]);
- ProcessBuilder pb = new ProcessBuilder(sa);
- File pf = editor.file.getParentFile();
- if (pf != null) pb.directory(pf.getCanonicalFile());
- pb.redirectErrorStream(true);
- p = pb.start();
- // Connect to I/O streams
- InputStream istream = p.getInputStream();
- BufferedReader input =
- new BufferedReader(new InputStreamReader(istream));
- OutputStream ostream = p.getOutputStream();
- OutputStreamWriter output = new OutputStreamWriter(ostream);
- // Process Spin output line by line
- String s = "";
- boolean running = true;
- while (running) {
- s = input.readLine();
- if (Config.getBooleanProperty("RAW"))
- rawWriter.println(s);
- if (s == null)
- running = false;
- else if (s.startsWith("Select a statement") ||
- s.startsWith("Select stmnt"))
- running = select(area, p, input, output);
- else if (s.startsWith("spin: type return")) {
- output.write("\n");
- output.flush();
- }
- else if (filtering)
- jSpin.append(area, filter.filter(s));
- else
- jSpin.append(area, s + "\n");
- }
- // Wait for Spin process to end
- p.waitFor();
- if (Config.getBooleanProperty("RAW"))
- rawWriter.close();
- // If syntax error, set cursor to line in editor
- if (area.getText().indexOf("Error: syntax error") != -1) {
- s = area.getText();
- try {
- int line = Integer.parseInt(
- s.substring(
- s.indexOf("line")+4, s.indexOf('"')).trim());
- editor.caretToLine(line);
- } catch (NumberFormatException e1) {
- editor.caretToLine(0);
- }
- }
- } catch (InterruptedException e) {
- jSpin.append(messageArea, "Interrupted exception");
- }
- catch (java.io.IOException e) {
- jSpin.append(messageArea, "IO exception\n" + e);
- }
- }
-
- // String to array of tokens - for ProcessBuilder
- // Previous versions of jSpin used StringTokenizer
- // which caused problems in Linux
- String[] stringToArray(String command, String s) {
- char quote = Config.getBooleanProperty("SINGLE_QUOTE") ? '\'' : '"';
- String[] sa = new String[50];
- int count = 0, i = 0, start = 0;
- sa[count] = command;
- count++;
- while (i < s.length() && s.charAt(i) == ' ') i++;
- start = i;
- boolean isQuote;
- do {
- if (i == s.length()) break;
- isQuote = s.charAt(i) == quote;
- if (isQuote) i++;
- if (isQuote) {
- while (s.charAt(i) != quote) i++;
- i++;
- }
- else
- while (i < s.length() && s.charAt(i) != ' ') i++;
- sa[count] = s.substring(start, i);
- while (i < s.length() && s.charAt(i) == ' ') i++;
- start = i;
- count++;
- } while (true);
- String[] sb = new String[count];
- System.arraycopy(sa, 0, sb, 0, count);
- return sb;
- }
-
- // Kill spin process
- private void killSpin() {
- if (p != null) p.destroy();
- }
-
- // Open file for raw Spin output
- private void rawFile() {
- String s = editor.root + File.separator + editor.fileRoot + ".raw";
- try {
- rawWriter = new PrintWriter(new FileWriter(s));
- jSpin.append(messageArea, "\nOpened " + s + "\n");
- } catch (IOException e) {
- jSpin.append(messageArea, "\nCannot open " + s + "\n");
- }
- }
-
- // Select the next statement to run in interactive simulation
- private boolean select(
- JTextArea area, Process p,
- BufferedReader input, OutputStreamWriter output) {
- int numOptions = 0;
- String filtered;
- try {
- String s = input.readLine();
- if (Config.getBooleanProperty("RAW"))
- rawWriter.println(s);
- while (!s.startsWith("Make Selection")) {
- filtered = filter.filter(s);
- if ((numOptions < MAX_SELECTIONS) &&
- (Config.getBooleanProperty("UNEXECUTABLE") ||
- s.indexOf("unexecutable") == -1)) {
- selections[numOptions] = new String(filtered.substring(7));
- numOptions++;
- }
- s = input.readLine();
- if (Config.getBooleanProperty("RAW"))
- rawWriter.println(s);
- }
- if (numOptions == 0) {
- output.write("q\n");
- output.flush();
- return false;
- }
- // Get selection from dialog
- int selectedValue = -1;
- selectDialog =
- new SelectDialog(
- numOptions,
- numOptions <= Config.getIntProperty("SELECT_MENU"),
- selections);
- selectDialog.start();
- while (selectedValue == -1) {
- try {
- Thread.sleep(Config.getIntProperty("POLLING_DELAY"));
- }
- catch (InterruptedException e) {}
- if (selectDialog == null) break;
- else selectedValue = selectDialog.getValue();
- }
- // For Macintosh (?) - Angelika's problem (?)
- if (selectDialog != null) {
- selectDialog.interrupt();
- selectDialog = null;
- }
- // if (selectDialog != null) selectDialog.interrupt();
- // If 0 (escape or close) selected, quit Spin interaction
- if (selectedValue == 0) {
- output.write("q\n");
- output.flush();
- return false;
- }
- selectedValue = Integer.valueOf(
- selections[selectedValue-1].substring(
- 0, selections[selectedValue-1].indexOf(':')));
- // Send selection to Spin
- output.write(selectedValue + "\n");
- output.flush();
- s = input.readLine(); // Eat extra new line
- if (Config.getBooleanProperty("RAW"))
- rawWriter.println(s);
- return true;
- } catch (Exception e) {
- System.err.println(e);
- killSpin();
- return false;
- }
- }
- }
-
- // Class SelectDialog displays the statement select dialog in a thread
- private class SelectDialog extends Thread implements ActionListener {
- private int selectedValue = -1;
- // Positive when a button is selected, zero upon escape or close
- private int numOptions; // Number of process buttons
- private String[] selections;// The selections
-
- private JFrame dialog; // The frame
- private JPanel panel;
- private JButton[] options; // Array of process buttons
- private JComboBox pulldown = new JComboBox();
-
- // Constructor - set up frame with number of buttons required
- SelectDialog (int numOptions, boolean buttons, String[] selections) {
- this.numOptions = numOptions;
- this.selections = selections;
- dialog = new JFrame();
- dialog.addWindowListener(
- new WindowAdapter() {
- public void windowClosing(WindowEvent e) {
- selectedValue = 0;
- dialog.dispose();
- }
- });
- dialog.getRootPane().registerKeyboardAction(this,
- KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0),
- JComponent.WHEN_IN_FOCUSED_WINDOW);
- dialog.setTitle(Config.SELECT);
- panel = new JPanel();
- if (buttons) constructButtonsDialog(); else constructMenuDialog();
- dialog.getContentPane().setLayout(new java.awt.BorderLayout());
- dialog.getContentPane().add(panel, java.awt.BorderLayout.CENTER);
- dialog.setLocationRelativeTo(messageArea);
- dialog.validate();
- dialog.setVisible(true);
- }
-
- void constructButtonsDialog() {
- panel.setLayout(new java.awt.GridLayout(1, numOptions));
- options = new JButton[numOptions];
- JButton button = null;
- for (int i = 1; i <= numOptions; i++) {
- button = new JButton(selections[i-1]);
- button.setFont(messageArea.getFont());
- button.addActionListener(this);
- options[i-1] = button;
- panel.add(button);
- }
- dialog.setSize(
- Config.getIntProperty("SELECT_BUTTON") * numOptions,
- Config.getIntProperty("SELECT_HEIGHT"));
- }
-
- void constructMenuDialog() {
- panel.setLayout(new java.awt.BorderLayout());
- pulldown = new JComboBox();
- pulldown.setFont(messageArea.getFont());
- pulldown.putClientProperty("JComboBox.isTableCellEditor", Boolean.TRUE);
- pulldown.setEditable(false);
- for (int i = 0; i < numOptions; i++)
- pulldown.addItem(selections[i]);
- pulldown.setSelectedIndex(-1);
- pulldown.addActionListener(this);
- panel.add(pulldown, java.awt.BorderLayout.CENTER);
- dialog.setSize(
- Config.getIntProperty("SELECT_BUTTON"),
- Config.getIntProperty("SELECT_HEIGHT"));
- }
-
- // Display dialog
- public void run() {
- dialog.setVisible(true);
- }
-
- // ActionListener
- public void actionPerformed(ActionEvent e) {
- if (e.getSource() instanceof JButton) {
- JButton selected = (JButton) e.getSource();
- for (int i = 0; i < numOptions; i++)
- if (options[i].equals(selected))
- selectedValue = i+1;
- }
- else if (e.getSource() instanceof JComboBox) {
- selectedValue = ((JComboBox)e.getSource()).getSelectedIndex()+1;
- }
- else selectedValue = 0;
- dialog.dispose();
- java.awt.Dimension rv = ((JComponent)e.getSource()).getSize(null);
- Config.setIntProperty("SELECT_BUTTON", rv.width);
- }
-
- // Dispose of dialog frme
- private void disposeDialog() {
- if (dialog != null) dialog.dispose();
- }
-
- // Get value
- private int getValue() {
- return selectedValue;
- }
- }
-}
diff --git a/mingw.iss b/mingw.iss
index 6259025..79a513a 100644
--- a/mingw.iss
+++ b/mingw.iss
@@ -1,20 +1,20 @@
-; Script generated by the Inno Setup Script Wizard.
-; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
-
-[Setup]
-AppName=MINGW
-AppVerName=mingw
-DefaultDirName=c:\mingw
-DefaultGroupName=MinGW
-DisableProgramGroupPage=yes
-OutputDir=c:\vn
-Compression=lzma
-SolidCompression=yes
-
-[Languages]
-Name: "english"; MessagesFile: "compiler:Default.isl"
-
-[Files]
-Source: "C:\mingw\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
-; NOTE: Don't use "Flags: ignoreversion" on any shared system files
-
+; Script generated by the Inno Setup Script Wizard.
+; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
+
+[Setup]
+AppName=MINGW
+AppVerName=mingw
+DefaultDirName=c:\mingw
+DefaultGroupName=MinGW
+DisableProgramGroupPage=yes
+OutputDir=c:\vn
+Compression=lzma
+SolidCompression=yes
+
+[Languages]
+Name: "english"; MessagesFile: "compiler:Default.isl"
+
+[Files]
+Source: "C:\mingw\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
+; NOTE: Don't use "Flags: ignoreversion" on any shared system files
+
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..be39104
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,65 @@
+
+
+ 4.0.0
+
+ com.spinroot
+ jspin
+ 5.0.0
+
+ jar
+
+
+ 1.8
+ 1.8
+ UTF-8
+ UTF-8
+
+
+
+
+ commons-io
+ commons-io
+ 2.5
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-dependency-plugin
+ 3.0.0
+
+
+ copy-dependencies
+ prepare-package
+
+ copy-dependencies
+
+
+ ${project.build.directory}/lib
+ false
+ false
+ true
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+ 3.0.2
+
+
+
+ true
+ lib/
+ com.spinroot.jspin.jSpin
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spider-examples/second.pml b/spider-examples/second.pml
index 96c8e6c..47a1e9d 100644
--- a/spider-examples/second.pml
+++ b/spider-examples/second.pml
@@ -1,19 +1,19 @@
-/* Second attempt */
-bool wantp = false, wantq = false;
-
-active proctype p() {
- do ::
- !wantq;
- wantp = true;
-csp: wantp = false;
- od
-}
-
-active proctype q() {
- do :: !wantp;
- wantq = true;
-csq: wantq = false;
- od
-}
-
-ltl { !<>(p@csp && q@csq) }
+/* Second attempt */
+bool wantp = false, wantq = false;
+
+active proctype p() {
+ do ::
+ !wantq;
+ wantp = true;
+csp: wantp = false;
+ od
+}
+
+active proctype q() {
+ do :: !wantp;
+ wantq = true;
+csq: wantq = false;
+ od
+}
+
+ltl { !<>(p@csp && q@csq) }
diff --git a/spider-examples/third.pml b/spider-examples/third.pml
index b695c75..8fb3bcd 100644
--- a/spider-examples/third.pml
+++ b/spider-examples/third.pml
@@ -1,16 +1,17 @@
-bool wantp = false, wantq = false;
+bool wantp = false, wantq = false;
+
+active proctype p() {
+ do :: wantp = true;
+ !wantq;
+cs: wantp = false;
+ od
+}
+
+active proctype q() {
+ do ::
+wantq = true;
+ !wantp;
+cs: wantq = false;
+ od
+}
-active proctype p() {
- do :: wantp = true;
- !wantq;
-cs: wantp = false;
- od
-}
-
-active proctype q() {
- do ::
wantq = true;
- !wantp;
-cs: wantq = false;
- od
-}
-
diff --git a/spinSpider/Config.java b/spinSpider/Config.java
deleted file mode 100644
index d9ec322..0000000
--- a/spinSpider/Config.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- Config - configuration constants and file
- Copyright 2005-10 by Mordechai (Moti) Ben-Ari. See SpinSpider.java
-*/
-package spinSpider;
-
-public class Config {
- static final String VERSION = "6.0";
-
- // Properties data structure is used for command names
- // Initialize properties from file or create file or from defaults
- static final String CONFIG_FILE = "config.cfg";
- public static final String[] names = { "", "-trail-1", "-trail-2", "-automata" };
-
- static public void setDefaultProperties(
- java.util.Properties properties) {
- // Spin version: format changed with Spin 6
- properties.put("VERSION", "6");
-
- properties.put("C_COMPILER", "c:\\mingw\\bin\\gcc.exe");
- properties.put("SPIN", "bin\\spin.exe");
- properties.put("PAN", "pan.exe");
- properties.put("DOT", "bin\\dot.exe");
- }
-
- static public void init(java.util.Properties properties) {
- setDefaultProperties(properties);
- try {
- properties.load(new java.io.FileInputStream(CONFIG_FILE));
- } catch (java.io.IOException e1) {
- System.err.println("Cannot open configuration file; using defaults");
- }
- }
-
- static final int MAX_STACK = 1000; // Stack for processing -DCHECK file
- static final int INITIAL = 100; // For ArrayLists
- static final int DELTA = 1000; // For node offset in automata
-
- static final String TITLE =
- "SpinSpider Version " + VERSION +
- " Copyright 2005-7 (GNU GPL) by Moti Ben-Ari.";
-
- static final String USAGE =
- "Usage java spinSpider.SpinSpider arguments file\n\n" +
- " file Promela source file\n\n" +
- " -p number of processes (must be >= 1)\n" +
- " -vname name of a variable (one parameter per variable)\n\n" +
- " -dot dot format\n" +
- " -Txxx dot format and run DOT to convert to xxx format\n" +
- " (default is png)\n" +
- " -fsm fsm format\n\n" +
- " -t1 use trail file to emphasize a path\n" +
- " -t2 use trail file to draw a path\n" +
- " -a draw automata corresponding to source\n\n" +
- " -small size of dot graph is smaller\n" +
- " -bold bold style instead of color for path\n" +
- " -debug write internal tables to file.dbg";
-
- static final String dotTrailBold = " style = bold";
- static final String dotTrailColor = " color = red";
-
- static final String[] smallDotPrologue = {
- "\tgraph [size=\"12.5,7.5\",ranksep=.20];",
- "\tnode [shape=box,fontname=Helvetica,fontsize=10];",
- "\tnode [width=1.25,height=0.75,fixedsize=true];"
- };
-
- static final String[] largeDotPrologue = {
- "\tgraph [size=\"16,12\",ranksep=.25];",
- "\tnode [shape=box,fontname=Helvetica,fontsize=14];",
- "\tnode [width=1.6,height=1.2,fixedsize=true];"
- };
- static final String[] automataDotPrologue = {
- "\tgraph [size=\"16,12\",ranksep=.4];",
- "\tnode [shape=circle,fontname=Helvetica,fontsize=14];",
- "\tedge [fontname=Helvetica,fontsize=14];"
- };
-
-}
diff --git a/spinSpider/DrawAutomata.java b/spinSpider/DrawAutomata.java
deleted file mode 100644
index a51cc23..0000000
--- a/spinSpider/DrawAutomata.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/* Copyright 2007 by Mordechai (Moti) Ben-Ari. See copyright.txt */
-/*
- * Draw the automata representation of a Promela program.
-*/
-
-package spinSpider;
-import java.io.*;
-
-public class DrawAutomata {
- SpinSpider spd;
-
- public DrawAutomata(SpinSpider s) {
- spd = s;
- }
-
- // Extract an int value that appears between "from" and "to" in "s"
- private static int extract(String s, String from, String to) {
- return
- Integer.parseInt(
- s.substring(s.indexOf(from)+from.length(), s.indexOf(to))
- .trim());
- }
-
- public void drawAutomata() {
- BufferedReader statementReader = null;
- PrintWriter graphWriter = null;
- String s = "";
- String fn = spd.fileName + Config.names[3];
-
- spd.progress("Drawing automata");
- try {
- statementReader = new BufferedReader(
- new FileReader(spd.fileName + ".dbg"));
- } catch (IOException e) { spd.fileError(".dbg"); }
- try {
- graphWriter = new PrintWriter(
- new FileWriter(fn + ".dot"));
- } catch (IOException e) { spd.fileError(".dot"); }
-
- // Write dot prologue
- graphWriter.println("digraph \"" + fn + "\"" + " {");
- for (int i = 0; i < Config.automataDotPrologue.length; i++)
- graphWriter.println(Config.automataDotPrologue[i]);
-
- // Skip over first parts of debug files
- while (true) {
- try { s = statementReader.readLine(); }
- catch (IOException e) { spd.fileError(".dbg"); }
- if (s == null)
- spd.fileError(".dbg");
- else
- if (s.equals("Statements from -d file"))
- break;
- }
-
- // Extract data from each line and write nodes and edges
- // Use DELTA to create unique node numbers for each process
- int process = 0, proc, line, source, target;
- boolean endState = false, atomic = false, previousAtomic = false;
- String emphasize = spd.trailStyle == 0 ? Config.dotTrailColor : Config.dotTrailBold;
- while (true) {
- try { s = statementReader.readLine(); }
- catch (IOException e) { spd.fileError(".dbg"); }
- if (s == null) break;
- if (s.indexOf("process") == -1) break;
- proc = extract(s, "process=", ", source");
- // New process
- if (proc != process) {
- process = proc;
- endState = false;
- }
- source = extract(s, "source=", ", target") + process*Config.DELTA;
- line = extract(s, "line=", ".");
- graphWriter.println(source + " [label=" + line + "]");
- target = extract(s, "target=", ", id") + process*Config.DELTA;
- if ((target == process*Config.DELTA) && !endState) {
- endState = true;
- graphWriter.println(target + " [label=0]");
- }
- atomic = s.indexOf("atomic,") != -1;
- graphWriter.println(source + " -> " + target +
- " [label=\"" + s.substring(s.indexOf('.')+1) + "\"" +
- (atomic || previousAtomic ? emphasize : "") + "]");
- previousAtomic = atomic;
- }
-
- try { statementReader.close(); }
- catch (IOException e) { spd.fileError(".dbg"); }
- graphWriter.println("}");
- graphWriter.close();
-
- // Call dot to format dot file
- if (!spd.format.equals("dot"))
- spd.runProcess(spd.properties.getProperty("DOT") +
- " -T" + spd.format +
- " -o " + fn + "." + spd.format + " " +
- fn + ".dot", null);
- }
-
-}
diff --git a/spinSpider/Read.java b/spinSpider/Read.java
deleted file mode 100644
index 431fd3e..0000000
--- a/spinSpider/Read.java
+++ /dev/null
@@ -1,212 +0,0 @@
-/* Copyright 2006-10 by Mordechai (Moti) Ben-Ari. See copyright.txt */
-/*
- * Read the data files
-*/
-
-package spinSpider;
-import java.io.*;
-import java.util.Properties;
-
-class Read {
- SpinSpider spd;
- String fileName;
- Properties properties;
-
- Read(SpinSpider s, String f, Properties p) {
- spd = s;
- fileName = f;
- properties = p;
- }
-
- // Read the state transitions output by -DCHECK and never claim
- // Thanks to Gerard Holzmann for showing me how to do this.
- void readCheckFile() {
- BufferedReader checkReader = null;
- String s = ""; // Read line to s
- String[] tokens; // For tokenizing
- // Stack of states traversed
- int[] stack = new int[Config.MAX_STACK];
- int newState = 0; // State number in "New"
- int depth = 0; // Stack depth
- boolean needNew = false; // Need state information after "New"
- int offset = 0; // Offset of variables after procs
-
- spd.progress("Reading -DCHECK file");
- try {
- checkReader = new BufferedReader(
- new FileReader(fileName + ".chk"));
- } catch (IOException e) { spd.fileError(".chk"); }
-
- while (true) {
- try { s = checkReader.readLine(); }
- catch (IOException e) { spd.fileError(".chk"); }
- if ((s == null) || s.indexOf("Spin Version") != -1) break;
-
- tokens = s.trim().split("\\s");
- // "New" indicates a new state
- // Push on the stack
- // Immediately thereafter the *spd* output will appear
- if ((tokens.length > 2) && tokens[0].equals("New")) {
- newState = Integer.parseInt(tokens[2]);
- stack[depth] = newState;
- needNew = true;
- }
- // "Down" for a program (not a claim) indicates a transition
- // to the new state that was just pushed on the stack
- else if ((tokens.length > 3) && (tokens[1].equals("Down"))) {
- if (tokens[3].equals("program") && (newState > 0))
- spd.transitions.add(
- new Transition(stack[depth-1], newState));
- depth++;
- stack[depth] = stack[depth-1];
- }
- // "Up" - pop the stack
- else if ((tokens.length > 1) && tokens[1].equals("Up")) {
- depth--;
- }
- // "Old" - just a transition, no need to push a new state
- else if ((tokens.length > 2) && tokens[0].equals("Old")) {
- newState = Integer.parseInt(tokens[2]);
- spd.transitions.add(
- new Transition(stack[depth], newState));
- }
- // "Stack" - have never occurred
- // When it does you'll have to figure out what to do!
- else if ((tokens.length > 2) && tokens[0].equals("Stack")) {
- // For now, I don't know why this is here.....
- System.out.println("Stack line = " + s);
- System.exit(3);
- }
- // "*spd*" - The data created by the never claim
- else if (needNew && (tokens.length > 1) &&
- tokens[0].equals("*spd*")) {
- // The first time, set the number of processes and variables
- if (State.numProcs == 0) {
- State.numProcs = Integer.parseInt(tokens[1]);
- offset = State.numProcs + 3;
- State.numVars = Integer.parseInt(tokens[offset-1]);
- }
- // Parse the pc values and the values of the variables
- // and construct a new state
- needNew = false;
- int[] st = new int[State.numProcs];
- String[] vn = new String[State.numVars];
- String[] vr = new String[State.numVars];
- for (int proc = 0; proc < State.numProcs; proc++)
- st[proc] = Integer.parseInt(tokens[proc + 2]);
- for (int var = 0; var < State.numVars; var++) {
- vn[var] = tokens[offset + 2*var];
- vr[var] = tokens[offset + 2*var + 1];
- }
-
- spd.states.add(new State(st, vn, vr));
- }
- }
- try { checkReader.close(); }
- catch (IOException e) { spd.fileError(".chk"); }
- }
-
- // Extract an int value that appears between "from" and "to" in "s"
- private static int extract(String s, String from, String to) {
- return
- Integer.parseInt(
- s.substring(s.indexOf(from)+from.length(), s.indexOf(to))
- .trim());
- }
-
- // Create statement database from -d file
- void createStatements() {
- BufferedReader statementReader = null;
- String s = "";
- int proc = 0; // For detecting change of process
- int countStatements = 0; // Count statements per process
- spd.progress("Reading -d file");
- try {
- statementReader = new BufferedReader(
- new FileReader(fileName + ".d"));
- } catch (IOException e) { spd.fileError(".d"); }
-
- while (true) {
- try { s = statementReader.readLine(); }
- catch (IOException e) { spd.fileError(".d"); }
- if (s == null) {
- if (spd.trailCode != 3)
- spd.fileError(".d (the never claim may be missing)");
- break;
- }
-
- // Start of never claim - terminate processing
- else if (s.indexOf("claim never") != -1) {
- spd.statementsPerProcess.add(
- new Integer(countStatements));
- break;
- }
-
- // Beginning of transitions of a process - store and reset count
- else if (s.indexOf("proctype") != -1) {
- if (proc != 0)
- spd.statementsPerProcess.add(
- new Integer(countStatements));
- countStatements = 0;
- proc++;
- }
-
- // Entry for each transition
- else if (s.indexOf("-> state") != -1) {
- countStatements++;
- // For Spin 6 the format for the line number is different
- int arrow = s.indexOf("=>");
- int lineNumber;
- if (Integer.valueOf(properties.getProperty("VERSION")).intValue() >= 6)
- lineNumber = s.lastIndexOf(':', arrow) + 1;
- else
- lineNumber = s.lastIndexOf("line ", arrow) + 5;
-
- spd.statements.add(new Statement(
- proc-1, // process number
- extract(s, "state", "-(tr"), // source state
- extract(s, "-> state", "[id"), // target state
- extract(s, "[id", "tp"), // id number for trail
- s.indexOf("[A") != -1, // atomic for automata
- // source line number
- Integer.parseInt(s.substring(lineNumber, arrow-1)),
- s.substring(arrow+2).trim())); // source statement
- }
- }
- try { statementReader.close(); }
- catch (IOException e) { spd.fileError(".d"); }
- }
-
- // Read the trail file whose entries are -
- // "sequence number : process number : transition id"
- // Sequence number = -2 means there is a never claim
- // In that case, ignore its transitions (process number 0)
- void readTrail() {
- BufferedReader trailReader = null;
- boolean claim = false;
- String s = "";
- spd.progress("Reading trail file");
- try {
- trailReader = new BufferedReader(
- new FileReader(fileName + ".pml.trail"));
- } catch (IOException e) { spd.fileError(".pml.trail"); return; }
-
- while (true) {
- try { s = trailReader.readLine(); }
- catch (IOException e) { spd.fileError(".pml.tral"); }
- if (s == null) break;
- String[] t = s.split(":");
- if (t[0].startsWith("-2")) {
- claim = true;
- continue;
- }
- if ((t[0].charAt(0) == '-')) continue;
- if (claim && (t[1].charAt(0) == '0')) continue;
- Trail tr = new Trail(Integer.valueOf(t[2]).intValue());
- spd.trails.add(tr);
- }
- try { trailReader.close(); }
- catch (IOException e) { spd.fileError(".pml.trail"); }
- }
-
-}
diff --git a/spinSpider/SetTrail.java b/spinSpider/SetTrail.java
deleted file mode 100644
index 0a3ac06..0000000
--- a/spinSpider/SetTrail.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/* Copyright 2006 by Mordechai (Moti) Ben-Ari. See copyright.txt */
-/*
- * Use the trail file to give attributes to states and transitions
-*/
-
-package spinSpider;
-class SetTrail {
- SpinSpider spd;
- SetTrail(SpinSpider s) { spd = s; }
-
- // Traverse the state diagram according to the trail file
- void setTrail() {
- int i = 0;
- if (spd.states.size() == 0) return;
-
- // Start from first state
- spd.states.get(i).inTrail = true;
- // For each line in the trail, find a statement with matching id
- for (Trail tr : spd.trails) {
- Statement st = null;
- for (Statement stmt: spd.statements)
- if (stmt.id == tr.id) {
- st = stmt;
- break;
- }
- // Set trail flag for the state obtained by taking
- // this transition in the trail
- i = findNewState(i, st);
- spd.states.get(i).inTrail = true;
- }
- }
-
- // Starting from state "index", find where the state where
- // statement "stmt" goes to
- private int findNewState(int index, Statement stmt) {
- boolean ok;
- State currentState = spd.states.get(index);
- for (State s: spd.states) {
- ok = true;
- // For each process, the location is the same,
- // except for the process executed by this statement,
- // in which case the new state is reached by the statement
- for (int i = 0; i < s.s.length; i++) {
- if (i == stmt.process) ok = ok && (s.s[i] == stmt.targetState);
- if (i != stmt.process) ok = ok && (s.s[i] == currentState.s[i]);
- }
-
- // Flag the transition
- if (ok) {
- boolean foundTransition = false;
- for (Transition tr: spd.transitions)
- if ((tr.head == index) && (tr.tail == spd.states.indexOf(s))) {
- tr.inTrail = true;
- foundTransition = true;
- }
- if (foundTransition)
- return spd.states.indexOf(s);
- else continue;
- }
- }
- return 0;
- }
-}
diff --git a/spinSpider/Write.java b/spinSpider/Write.java
deleted file mode 100644
index 2a3a5c7..0000000
--- a/spinSpider/Write.java
+++ /dev/null
@@ -1,259 +0,0 @@
-/* Copyright 2005-7 by Mordechai (Moti) Ben-Ari. See copyright.txt */
-/*
- * Write the output in different formats
-*/
-
-package spinSpider;
-
-import java.io.*;
-
-public class Write {
- SpinSpider spd;
- Write(SpinSpider s, String f) {
- spd = s;
- }
-
- // Write the never claim from the number of processes and
- // the names of the variables
- boolean writeNeverClaim(int numProcs, String[] vars) {
- PrintWriter neverWriter = null;
- spd.progress("Writing never claim");
- if (vars.length == 0) {
- spd.progress("No variables for never claim");
- return false;
- }
- try {
- neverWriter = new PrintWriter(new FileWriter(spd.fileName + ".nvr"));
- } catch (IOException e) { spd.fileError(".nvr"); }
-
- neverWriter.print("never {\n\tdo\n\t:: printf(\"*spd* " + numProcs);
- for (int i = 0; i < numProcs; i++)
- neverWriter.print(" %d");
- neverWriter.print(" " + vars.length);
- for (int i = 0; i < vars.length; i++)
- neverWriter.print(" " + vars[i] + " %d");
- neverWriter.print("\\n\",\n\t\t");
- for (int i = 0; i < numProcs; i++)
- neverWriter.print("pc_value(" + i + "), ");
- for (int i = 0; i < vars.length; i++)
- neverWriter.print((i==0?"":", ") + vars[i]);
- neverWriter.println(")\n\tod\n}");
- neverWriter.close();
- return true;
- }
-
- // Write the graph in dot format - nodes and edges
- // trailCode = 0 (no trail), 1 (emphasize trail), 2 (just trail)
- void writeDotGraph() {
- PrintWriter graphWriter = null;
- String fn = spd.fileName + Config.names[spd.trailCode];
- String label; // Building the label in this string
- int numStates = 0; // For printing a node number
- String[] dotPrologue =
- spd.dotSize == 0 ? Config.smallDotPrologue : Config.largeDotPrologue;
- String dotTrail =
- spd.trailStyle == 0 ? Config.dotTrailColor : Config.dotTrailBold;
-
- spd.progress("Writing dot file");
- try {
- graphWriter = new PrintWriter(new FileWriter(fn + ".dot"));
- } catch (IOException e) { spd.fileError(".dot"); }
-
- // Write dot prologue
- graphWriter.println("digraph \"" + fn + "\"" + " {");
- for (int i = 0; i < dotPrologue.length; i++)
- graphWriter.println(dotPrologue[i]);
-
- // Write states
- for (State st : spd.states) {
- label = (numStates++) + " [label=\"";
- for (int proc = 0; proc < State.numProcs; proc++)
- for (Statement t : spd.statements)
- if ((t.process == proc) &&
- (t.sourceState == st.s[proc]))
- label = label + t.line + ". " + t.source + "\\n";
- for (int var = 0; var < State.numVars; var++)
- label = label + " " + st.v[var];
- graphWriter.print(label+ "\"");
- if ((spd.trailCode == 1) && st.inTrail)
- graphWriter.print(dotTrail);
- if ((spd.trailCode == 2) && !st.inTrail)
- graphWriter.print(" style = invis ");
- graphWriter.println("];");
- }
-
- // Write transitions
- for (Transition t : spd.transitions) {
- graphWriter.print(t.head + " -> " + t.tail);
- if ((spd.trailCode == 1) && t.inTrail)
- graphWriter.print(" [" + dotTrail + "]");
- if ((spd.trailCode == 2) && !t.inTrail)
- graphWriter.print(" [ style = invis ]");
- graphWriter.println(";");
- }
- graphWriter.println("}");
- graphWriter.close();
- if ((spd.trailCode != 3) && !spd.format.equals("dot"))
- spd.runProcess(spd.properties.getProperty("DOT") +
- " -T" + spd.format +
- " -o " + fn + "." + spd.format + " " +
- fn + ".dot", null);
- }
-
- // Write the graph in fsm format
- // This format is used by tools developed at the
- // Eindhoven University of Technology
- void writeFSMGraph() {
- int offset;
- PrintWriter graphWriter = null;
- spd.progress("Writing fsm file");
- try {
- graphWriter = new PrintWriter(new FileWriter(spd.fileName + ".fsm"));
- } catch (IOException e) { spd.fileError(".fsm"); }
-
- // If the program terminates there is an end statement
- // that is not a "source" in the -d file
- // Add dummy statements at the end of the "statements" data structure
- // spp1 is the original statementsPerProcess
- // spp2 is statementsPerProcess with added dummy statements
- int[] spp1 = new int[spd.statementsPerProcess.size()];
- int[] spp2 = new int[spd.statementsPerProcess.size()];
- for (int i = 0; i < spp1.length; i++) {
- spp1[i] = spd.statementsPerProcess.get(i).intValue();
- spp2[i] = spp1[i];
- }
- boolean[] endStates = new boolean[State.numProcs];
- for (int i = 0; i < spd.statements.size(); i++) {
- Statement st = spd.statements.get(i);
- if ( (st.targetState == 0) && (!endStates[st.process])) {
- spd.statements.add(new Statement(st.process, 0, 0, 0, false, 0, ""));
- spp2[st.process]++;
- endStates[st.process] = true;
- }
- }
-
- // Compute fan in and fan out of each node
- int[] fanIn = new int[spd.states.size()];
- int[] fanOut = new int[spd.states.size()];
- for (int i = 0; i < spd.transitions.size(); i++) {
- fanIn[spd.transitions.get(i).tail]++;
- fanOut[spd.transitions.get(i).head]++;
- }
- // Compute the maximum fan in and fan out in the diagram
- int maxFanIn = 0, maxFanOut = 0;
- for (int i = 0; i < spd.states.size(); i++) {
- if (fanIn[i] > maxFanIn) maxFanIn = fanIn[i];
- if (fanOut[i] > maxFanOut) maxFanOut = fanOut[i];
- }
- maxFanIn++;
- maxFanOut++;
-
- // Processes:
- // "p" + number of process + "(" + statements per process + ")"
- // + "String" + list of statements
- offset = 0;
- for (int proc = 0; proc < State.numProcs; proc++) {
- graphWriter.print("p" + (proc+1) +
- "(" + spp2[proc] + ") String");
- for (int stmt = 0; stmt < spp1[proc]; stmt++) {
- Statement stm = spd.statements.get(offset + stmt);
- graphWriter.print(" \"" + stm.line + "," + stm.source + "\"");
- }
- offset = offset + spp1[proc];
- if (spp2[proc] > spp1[proc])
- graphWriter.print(" \" end state \"");
- graphWriter.println();
- }
-
- // Variables:
- // name of variable + "(" + number of values + ")"
- // + "Nat" + list of values
- for (int var = 0; var < State.numVars; var++) {
- int max = 0;
- for (State st : spd.states) {
- int val = Integer.parseInt(st.v[var]);
- if (val > max) max = val;
- }
- graphWriter.print(spd.states.get(0).vname[var] + "(" + (max+1) + ") Nat");
- for (int i = 0; i <= max; i++)
- graphWriter.print(" \"" + i + "\"");
- graphWriter.println();
- }
-
- // Fan in, fan out, node nr
- graphWriter.print("fan_in(" + maxFanIn + ") Nat");
- for (int i = 0; i < maxFanIn; i++)
- graphWriter.print(" \"" + i + "\"");
- graphWriter.println();
- graphWriter.print("fan_out(" + maxFanOut + ") Nat");
- for (int i = 0; i < maxFanOut; i++)
- graphWriter.print(" \"" + i + "\"");
- graphWriter.println();
- graphWriter.println("node_nr(0)");
- graphWriter.println("---");
-
- // States:
- // Process location counters (relative to lists above!)
- // Values of variables
- // Fan-in and fan-out
- int stateCount = 0;
- for (State st : spd.states) {
- offset = 0;
- for (int proc = 0; proc < State.numProcs; proc++) {
- boolean found = false;
- for (int i = 0; i < spp1[proc]; i++)
- if (spd.statements.get(offset + i).sourceState == st.s[proc]) {
- graphWriter.print(i + " ");
- found = true;
- break;
- }
- if (!found) {
- graphWriter.print((spp2[proc]-1) + " ");
- }
- offset = offset + spp1[proc];
- }
- for (int var = 0; var < State.numVars; var++)
- graphWriter.print(st.v[var] + " ");
- graphWriter.print(fanIn[stateCount] + " " +
- fanOut[stateCount] + " " + (stateCount+1));
- stateCount++;
- graphWriter.println();
- }
- graphWriter.println("---");
-
- // Transitions
- for (Transition t : spd.transitions)
- graphWriter.println((t.head+1) + " " + (t.tail+1));
- graphWriter.close();
- }
-
- // Write debug file using toString defined in each class
- void writeDebug() {
- PrintWriter debugWriter = null;
- spd.progress("Writing debug file");
- try {
- debugWriter = new PrintWriter(
- new FileWriter(spd.fileName + ".dbg"));
- } catch (IOException e) { spd.fileError(".dbg"); }
-
- debugWriter.println("States");
- int n = 0;
- for (State s: spd.states)
- debugWriter.println((n++) + ". " + s);
-
- debugWriter.println("\nTransitions");
- for (Transition t: spd.transitions)
- debugWriter.println(t);
-
- debugWriter.println("\nStatements from -d file");
- for (Statement st: spd.statements)
- debugWriter.println(st);
-
- if (spd.trailCode > 0) {
- debugWriter.println("\nTrail");
- for (Trail tr: spd.trails)
- debugWriter.println(tr);
- }
- debugWriter.close();
- }
-}
diff --git a/src/main/java/com/spinroot/filterSpin/Config.java b/src/main/java/com/spinroot/filterSpin/Config.java
new file mode 100644
index 0000000..636d438
--- /dev/null
+++ b/src/main/java/com/spinroot/filterSpin/Config.java
@@ -0,0 +1,42 @@
+// Copyright 2008 by Mordechai (Moti) Ben-Ari.
+/**
+ * Local configuration class for standalone FilterSpin
+ */
+package com.spinroot.filterSpin;
+
+public class Config {
+ static final String VERSION = "0.1";
+ static final String CONFIG_FILE = "config.cfg";
+ static final String SEPARATOR = "#";
+ static final String USAGE =
+ "FilterSpin Version " + VERSION +
+ " Copyright 2008 (GNU GPL) by Moti Ben-Ari.\n" +
+ "Usage java com.spinroot.filterSpin.FilterSpin [arguments] file\n" +
+ " file File with Spin output\n" +
+ " -v string Variables to exclude\n" +
+ " -s string Statements to exclude\n" +
+ " string may be file name or list of identifiers with '/'";
+
+ static void setDefaultProperties(
+ java.util.Properties properties) {
+ properties.put("PROCESS_WIDTH", Integer.toString(7));
+ properties.put("STATEMENT_WIDTH", Integer.toString(18));
+ properties.put("VARIABLE_WIDTH", Integer.toString(10));
+ properties.put("LINES_PER_TITLE", Integer.toString(20));
+ properties.put("PROCESS_TITLE", "Process ");
+ properties.put("STATEMENT_TITLE", "Statement ");
+ properties.put("MSC", Boolean.toString(false));
+ }
+
+ /**
+ * Set the default properties and then try to read configuration file
+ */
+ static void init(java.util.Properties properties) {
+ setDefaultProperties(properties);
+ try {
+ properties.load(new java.io.FileInputStream(CONFIG_FILE));
+ } catch (java.io.IOException e1) {
+ System.err.println("Cannot open configuration file; using defaults");
+ }
+ }
+}
diff --git a/src/main/java/com/spinroot/filterSpin/Filter.java b/src/main/java/com/spinroot/filterSpin/Filter.java
new file mode 100644
index 0000000..3e1c172
--- /dev/null
+++ b/src/main/java/com/spinroot/filterSpin/Filter.java
@@ -0,0 +1,245 @@
+// Copyright 2004-10 by Mordechai (Moti) Ben-Ari. See copyright.txt.
+/**
+ * Filter Spin output.
+ * Display a table: process, statement, variables.
+ */
+package com.spinroot.filterSpin;
+
+import java.util.*;
+
+public class Filter {
+ private static String processTitle;
+ private static String statementTitle;
+ private static int processWidth;
+ private static int variableWidth;
+ private static int statementWidth;
+ private static int linesPerTitle;
+ private static boolean msc;
+ private static boolean newversion; // Spin version >= 6
+ // Properties and copies of the data from the properties
+ private Properties properties;
+ private String title; // Title string
+ private int lines; // Line counter to redisplay title
+
+ // Map from variable names to values
+ private Map variables = new TreeMap<>();
+
+ // Excluded variable and statements
+ private List excludedVar = new ArrayList<>();
+ private List excludedState = new ArrayList<>();
+
+ /**
+ * Initialize variables and local copies of properties
+ */
+ public void init(Properties properties) {
+ variables.clear();
+ title = "";
+ lines = -1;
+ this.properties = properties;
+ processTitle = properties.getProperty("PROCESS_TITLE");
+ statementTitle = properties.getProperty("STATEMENT_TITLE");
+ processWidth = Integer.valueOf(properties.getProperty("PROCESS_WIDTH"));
+ variableWidth = Integer.valueOf(properties.getProperty("VARIABLE_WIDTH"));
+ statementWidth = Integer.valueOf(properties.getProperty("STATEMENT_WIDTH"));
+ linesPerTitle = Integer.valueOf(properties.getProperty("LINES_PER_TITLE"));
+ msc = Boolean.valueOf(properties.getProperty("MSC"));
+ newversion = Integer.valueOf(properties.getProperty("VERSION")) >= 6;
+ }
+
+ // Parse string to initialize excluded arrays
+ public void setExcluded(String s, boolean exVar) {
+ List excluded = exVar ? excludedVar : excludedState;
+ // Replace whitespace by separator
+ s = s.replaceAll("\\s+", Config.SEPARATOR) + Config.SEPARATOR;
+ excluded.clear();
+ do {
+ int nl = s.indexOf(Config.SEPARATOR);
+ if (nl == -1) break;
+ if (!s.substring(0, nl).equals(""))
+ excluded.add(s.substring(0, nl));
+ s = s.substring(nl + 1);
+ } while (true);
+ }
+
+ /**
+ * Check if name is excluded variable (exVar=true) or statement (exVar=false)
+ * For each excluded string S;
+ * If variable name includes S, do not display,
+ * but if some +T in file is in name, display anyway.
+ */
+ private boolean checkExcluded(String name, boolean exVar) {
+ List excluded = exVar ? excludedVar : excludedState;
+ for (int i = 0; i < excluded.size(); i++)
+ if ((excluded.get(i).charAt(0) != '+') &&
+ (name.indexOf(excluded.get(i)) != -1)) {
+ boolean included = false;
+ for (int j = 0; j < excluded.size(); j++)
+ included = included ||
+ ((excluded.get(j).charAt(0) == '+') &&
+ (name.indexOf(excluded.get(j).substring(1)) != -1));
+ return !included;
+ }
+ return false;
+ }
+
+ // Filter string s and return new string or "" to ignore
+ public String filter(String s) {
+ try {
+ // Variables and queues start with double tab
+ if (s.startsWith("\t\t"))
+ return filterVariable(s);
+
+ // Filter statements
+ else if ((s.indexOf("proc") != -1) && (s.indexOf("[") != -1))
+ return filterStatement(s);
+
+ // Display some messages unmodified
+ else if ((s.startsWith("pan:")) ||
+ (s.startsWith("spin:")) ||
+ (s.startsWith("tl_spin:")) ||
+ (s.startsWith("Error:")) ||
+ (s.startsWith("error:")))
+ return s + "\n";
+ else if (s.indexOf("<<<<<") != -1)
+ return s + "\n";
+
+ // Display choices that have no proc and line number
+ else if (s.indexOf("choice") != -1)
+ return s.substring(s.indexOf("choice")) + "\n";
+
+ // Display error count with bullets to emphasize
+ else if (s.indexOf("errors:") != -1)
+ return
+ s.substring(0, s.indexOf("errors:")) + "\u2022\u2022\u2022 " +
+ s.substring(s.indexOf("errors:")) + " \u2022\u2022\u2022\n";
+
+ // Display MSC lines (without MSC:) if msc is true
+ else if (msc && s.trim().startsWith("MSC:"))
+ return s.substring(s.indexOf("MSC:") + 5) + "\n";
+
+ // Display printf lines if msc is false
+ else if (!msc && !s.equals(""))
+ return s + "\n";
+ else
+ return "";
+ } catch (Exception e) {
+ System.err.println("\n + Error in filter for:\n" + s + "\n");
+ e.printStackTrace();
+ return "";
+ }
+ }
+
+ // Filter variables (including queues)
+ private String filterVariable(String s) {
+ String varName, varValue;
+ if (s.startsWith("\t\tqueue")) {
+ varName = s.substring(s.indexOf('(') + 1, s.indexOf(')'));
+ varValue = s.substring(s.indexOf(':') + 1).trim();
+ } else {
+ varName = s.substring(2, s.indexOf('=') - 1);
+ varValue = s.substring(s.indexOf('=') + 1).trim();
+ }
+ if (checkExcluded(varName, true)) return "";
+ // Construct new title if new variables encountered
+ boolean newTitle = !variables.containsKey(varName);
+ variables.put(varName, varValue);
+ if (newTitle) {
+ title = formatItem(processTitle, processWidth) + " " +
+ formatItem(statementTitle, statementWidth) + " " +
+ collectionToString(variables.keySet()) + "\n";
+ lines = -1;
+ }
+ return "";
+ }
+
+ // Filter statements
+ private String filterStatement(String s) {
+ String u = "";
+ int procIndex = s.indexOf("proc") + 4; // After "proc"
+ // Get process name
+ String proc =
+ s.substring(procIndex, s.indexOf(")") + 1).trim();
+ proc = proc.substring(0, proc.indexOf("(")) +
+ strip(proc.substring(proc.indexOf("(")));
+
+ // Get line number and statement name
+ String statement = "", line = "";
+ if (s.indexOf('[') != -1) {
+ if (newversion) {
+ // Spin 6 has "filename:#"
+ // Skip over initial ":" and start at file name
+ int colonIndex = s.indexOf(":", procIndex);
+ line = formatItem(
+ s.substring(colonIndex + 1, s.indexOf(" ", colonIndex)).trim(), 3);
+ } else
+ // Earlier versions had "line #"
+ line = formatItem(
+ s.substring(s.indexOf("line") + 4, s.indexOf("\"")).trim(), 3);
+ statement =
+ strip(s.substring(s.indexOf('[') + 1, s.lastIndexOf(']')));
+ statement = line + " " + statement;
+ }
+
+ if (checkExcluded(statement, false)) return "";
+
+ // For choice, display just process and statement
+ if (s.indexOf("choice") != -1)
+ u = s.substring(s.indexOf("choice"), s.indexOf(':') + 2) +
+ proc + " " + statement + "\n";
+ // Display table line (unless goto/else/break)
+ else if ((statement.indexOf("goto") == -1) &&
+ !statement.equals("else") &&
+ !statement.equals("break")) {
+ u = formatItem(proc, processWidth) + " " +
+ formatItem(statement, statementWidth) + " " +
+ collectionToString(variables.values()) + "\n";
+
+ // Display title if needed
+ lines = (lines + 1) % linesPerTitle;
+ if (lines == 0) u = title + u;
+ }
+ return u;
+ }
+
+ // Strip balanced parentheses
+ private String strip(String s) {
+ while ((s.charAt(0) == '(') && (s.charAt(s.length() - 1) == ')'))
+ s = s.substring(1, s.length() - 1);
+ return s;
+ }
+
+ /**
+ * Format a variable name or value s into a field of length len
+ * If item is too long, shorten it
+ * But, for array variables, shorten the name, not the index
+ * If item is too short, pad it
+ */
+ private String formatItem(String s, int len) {
+ if (s.length() > len) {
+ if (s.indexOf("[") != -1) {
+ String subscript =
+ s.substring(s.indexOf("["), s.lastIndexOf("]") + 1);
+ if (subscript.length() < len)
+ return s.substring(0, len - subscript.length()) + subscript;
+ else
+ return s.substring(0, len);
+ } else
+ return s.substring(0, len);
+ } else if (s.length() < len)
+ return (s + " ").substring(0, len);
+ else
+ return s;
+ }
+
+ /**
+ * Transform a collection of variables to a string,
+ * calling formatItem for each element
+ */
+ private String collectionToString(Collection c) {
+ String s = "";
+ Iterator it = c.iterator();
+ while (it.hasNext())
+ s = s + formatItem(it.next(), variableWidth) + " ";
+ return s;
+ }
+}
diff --git a/src/main/java/com/spinroot/filterSpin/FilterSpin.java b/src/main/java/com/spinroot/filterSpin/FilterSpin.java
new file mode 100644
index 0000000..702d167
--- /dev/null
+++ b/src/main/java/com/spinroot/filterSpin/FilterSpin.java
@@ -0,0 +1,91 @@
+// Copyright 2008 by Mordechai (Moti) Ben-Ari. See copyright.txt.
+/**
+ * Class with main method for standalone FilterSpin
+ */
+package com.spinroot.filterSpin;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+
+class FilterSpin {
+ /**
+ * Read the files of excluded variables/statements and
+ * return as a single string
+ */
+ private static String readFile(File fc) {
+ BufferedReader textReader = null;
+ String s = "";
+ try {
+ textReader = new BufferedReader(new FileReader(fc));
+ String line;
+ while (true) {
+ line = textReader.readLine();
+ if (line == null) break;
+ else s = s + line + '\n';
+ }
+ textReader.close();
+ return s;
+ } catch (IOException e) {
+ error("File error " + fc);
+ return "";
+ }
+ }
+
+ /**
+ * Read the Spin raw output and call the filter for each line
+ */
+ private static void filterFile(File fc, Filter filter) {
+ BufferedReader textReader = null;
+ try {
+ textReader = new BufferedReader(new FileReader(fc));
+ String line;
+ while (true) {
+ line = textReader.readLine();
+ if (line == null) break;
+ line = filter.filter(line);
+ if (!line.equals("")) System.out.print(line);
+ }
+ textReader.close();
+ } catch (IOException e) {
+ error("File error " + fc);
+ System.exit(1);
+ }
+ }
+
+ static void error(String s) {
+ System.err.println(s);
+ System.exit(1);
+ }
+
+ public static void main(String[] args) {
+ if (args.length == 0) error(Config.USAGE);
+
+ // Last argument is file name
+ File file = new File(args[args.length - 1]);
+
+ // Search for excluded file names or strings
+ String exc = Config.SEPARATOR, exs = Config.SEPARATOR;
+ for (int i = 0; i < args.length - 1; i++)
+ if (args[i].equals("-v")) exc = args[i + 1];
+ else if (args[i].equals("-s")) exs = args[i + 1];
+
+ // Create filter and property objects and initialize
+ Filter filter = new Filter();
+ java.util.Properties properties = new java.util.Properties();
+ Config.init(properties);
+ filter.init(properties);
+
+ // Read excluded files (if any) and set excluded data structures
+ if (exc.indexOf(Config.SEPARATOR) == -1)
+ exc = readFile(new File(exc));
+ filter.setExcluded(exc, true);
+ if (exs.indexOf(Config.SEPARATOR) == -1)
+ exs = readFile(new File(exs));
+ filter.setExcluded(exs, false);
+
+ // Filter the raw Spin data
+ filterFile(file, filter);
+ }
+}
diff --git a/src/main/java/com/spinroot/jspin/Config.java b/src/main/java/com/spinroot/jspin/Config.java
new file mode 100644
index 0000000..7e0aa1f
--- /dev/null
+++ b/src/main/java/com/spinroot/jspin/Config.java
@@ -0,0 +1,397 @@
+/* Copyright 2003-10 by Mordechai (Moti) Ben-Ari. See copyright.txt. */
+package com.spinroot.jspin;
+
+import java.awt.event.KeyEvent;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Properties;
+
+public class Config {
+ public static final char sep = java.io.File.separatorChar; // shortcut
+ // Strings
+ static final String SOFTWARE_NAME = "jSpin Version 5.0";
+ static final String JAVA_VERSION = "1.8";
+ static final String CONFIG_FILE_NAME = "config.cfg";
+ static final String SPIDER_TITLE = "SpinSpider";
+ static final String OPTIONS_TITLE = "Display";
+ static final String SELECT = "Select a statement";
+ static final String OPEN_FILE = "Open a Promela file\n";
+ static final String processTitle = "Process ";
+ static final String statementTitle = "Statement ";
+ // Component names and mnemonics
+ static final String File = "File";
+ static final int FileMN = KeyEvent.VK_F;
+ static final String New = "New";
+ static final int NewMN = KeyEvent.VK_N;
+ static final String Open = "Open";
+ static final int OpenMN = KeyEvent.VK_O;
+ static final String Save = "Save";
+ static final int SaveMN = KeyEvent.VK_S;
+ static final String SaveAs = "Save as";
+ static final int SaveAsMN = KeyEvent.VK_A;
+ static final String Switch = "Switch file";
+ static final int SwitchMN = KeyEvent.VK_F;
+ static final String Exit = "Exit";
+ static final int ExitMN = KeyEvent.VK_X;
+ static final String Editor = "Edit";
+ static final int EditorMN = KeyEvent.VK_E;
+ static final String Undo = "Undo";
+ static final int UndoMN = KeyEvent.VK_U;
+ static final String Redo = "Redo";
+ static final int RedoMN = KeyEvent.VK_R;
+ static final String Copy = "Copy";
+ static final int CopyMN = KeyEvent.VK_C;
+ static final String Cut = "Cut";
+ static final int CutMN = KeyEvent.VK_T;
+ static final String Paste = "Paste";
+ static final int PasteMN = KeyEvent.VK_P;
+ static final String Find = "Find";
+ static final int FindMN = KeyEvent.VK_F;
+ static final String FindAgain = "Find again";
+ static final int FindAgainMN = KeyEvent.VK_A;
+ static final String Spin = "Spin";
+ static final int SpinMN = KeyEvent.VK_S;
+ static final String Check = "Check";
+ static final int CheckMN = KeyEvent.VK_K;
+ static final String Random = "Random";
+ static final int RandomMN = KeyEvent.VK_R;
+ static final String Inter = "Interactive";
+ static final int InterMN = KeyEvent.VK_I;
+ static final String Verify = "Verify";
+ static final int VerifyMN = KeyEvent.VK_V;
+ static final String Trail = "Guided";
+ static final int TrailMN = KeyEvent.VK_G;
+ static final String Stop = "Stop";
+ static final int StopMN = KeyEvent.VK_P;
+ static final String Options = "Options";
+ static final int OptionsMN = KeyEvent.VK_N;
+ static final String Common = "Common";
+ static final int CommonMN = KeyEvent.VK_C;
+ static final String OptionsC = "C compiler";
+ static final int OptionsCMN = KeyEvent.VK_C;
+ static final String OptionsPan = "Pan";
+ static final int OptionsPanMN = KeyEvent.VK_A;
+ static final String Default = "Default";
+ static final int DefaultMN = KeyEvent.VK_D;
+ static final String SaveInstall = "Save install";
+ static final int SaveInstallMN = KeyEvent.VK_L;
+ static final String SaveCurrent = "Save current";
+ static final int SaveCurrentMN = KeyEvent.VK_S;
+ static final String Settings = "Settings";
+ static final int SettingsMN = KeyEvent.VK_G;
+ static final String MaxSteps = "Max steps";
+ static final int MaxStepsMN = KeyEvent.VK_M;
+ static final String MaxDepth = "Max depth";
+ static final int MaxDepthMN = KeyEvent.VK_D;
+ static final String Seed = "Seed";
+ static final int SeedMN = KeyEvent.VK_S;
+ static final String Negate = "Negate LTL";
+ static final int NegateMN = KeyEvent.VK_L;
+ static final String StWidth = "Statement width";
+ static final int StWidthMN = KeyEvent.VK_S;
+ static final String VarWidth = "Variable width";
+ static final int VarWidthMN = KeyEvent.VK_V;
+ static final String ExcludedV = "Exclude variables";
+ static final int ExcludedVMN = KeyEvent.VK_E;
+ static final String ExcludedS = "Exclude statements";
+ static final int ExcludedSMN = KeyEvent.VK_X;
+ static final String Fair = "Weak fairness";
+ static final int FairMN = KeyEvent.VK_W;
+ static final String Safety = "Safety";
+ static final int SafetyMN = KeyEvent.VK_Y;
+ static final String Acceptance = "Acceptance";
+ static final int AcceptanceMN = KeyEvent.VK_C;
+ static final String NonProgress = "Non-progress";
+ static final int NonProgressMN = KeyEvent.VK_N;
+ static final String Output = "Output";
+ static final int OutputMN = KeyEvent.VK_U;
+ static final String SaveSpin = "Save output";
+ static final int SaveSpinMN = KeyEvent.VK_V;
+ static final String Raw = "Raw output";
+ static final int RawMN = KeyEvent.VK_R;
+ static final String DisplayRaw = "Display raw";
+ static final int DisplayRawMN = KeyEvent.VK_D;
+ static final String Spider = "SpinSpider";
+ static final int SpiderMN = KeyEvent.VK_D;
+ static final String SpiderDisplay = "Display debug";
+ static final int SpiderDisplayMN = KeyEvent.VK_L;
+ static final String Run = "Run";
+ static final int RunMN = KeyEvent.VK_R;
+ static final String Help = "Help";
+ static final int HelpMN = KeyEvent.VK_H;
+ static final String About = "About";
+ static final int AboutMN = KeyEvent.VK_A;
+ static final String Max = "Maximize";
+ static final int MaxMN = KeyEvent.VK_M;
+ static final String LTLConvert = "Convert";
+ static final int LTLConvertMN = KeyEvent.VK_C;
+ static final String LTLFormula = " LTL formula ";
+ static final String LTLTranslate = "Translate";
+ static final int LTLTranslateMN = KeyEvent.VK_L;
+ static final String LTLClear = "Clear";
+ static final int LTLClearMN = KeyEvent.VK_A;
+ static final String LTLLoad = "Load";
+ static final int LTLLoadMN = KeyEvent.VK_O;
+ static final String LTLName = "LTL name";
+ static final int LTLNameMN = KeyEvent.VK_A; // For toolbar
+ static final int LTLName1MN = KeyEvent.VK_N; // For menu
+ static final int LTL_COLUMNS = 50;
+ // Common options
+ static final String OK = "OK";
+ static final int OKMN = KeyEvent.VK_O;
+ static final String Cancel = "Cancel";
+ static final String Statements = "Statements";
+ static final int StatementsMN = KeyEvent.VK_S;
+ static final String Globals = "Globals";
+ static final int GlobalsMN = KeyEvent.VK_G;
+ static final String Locals = "Locals";
+ static final int LocalsMN = KeyEvent.VK_L;
+ static final String Sent = "Sent";
+ static final int SentMN = KeyEvent.VK_T;
+ static final String Received = "Received";
+ static final int ReceivedMN = KeyEvent.VK_R;
+ static final String ClearAll = "Clear all";
+ static final int ClearAllMN = KeyEvent.VK_C;
+ static final String SetAll = "Set all";
+ static final int SetAllMN = KeyEvent.VK_A;
+ // SpinSpider options
+ static final String NoTrail = "No trail";
+ static final int NoTrailMN = KeyEvent.VK_T;
+ static final String EmphTrail = "Emphasize trail";
+ static final int EmphTrailMN = KeyEvent.VK_E;
+ static final String OnlyTrail = "Only trail";
+ static final int OnlyTrailMN = KeyEvent.VK_O;
+ static final String Automata = "Automata";
+ static final int AutomataMN = KeyEvent.VK_A;
+ static final String Debug = "Debug";
+ static final int DebugMN = KeyEvent.VK_D;
+ static final String DotSize = "Dot size";
+ static final String DotSmall = "Small";
+ static final int DotSmallMN = KeyEvent.VK_M;
+ static final String DotLarge = "Large";
+ static final int DotLargeMN = KeyEvent.VK_L;
+ static final String TrailStyle = "Trail style";
+ static final String TrailColor = "Color";
+ static final int TrailColorMN = KeyEvent.VK_C;
+ static final String TrailBold = "Bold";
+ static final int TrailBoldMN = KeyEvent.VK_B;
+ static final String Processes = "Processes";
+ static final int MAX_PROCESS = 5;
+ static final String Variables = "Variables";
+ static final String Format = "Format";
+ static final String DOT = "dot";
+ static final String PNG = "png";
+ static final String PS = "ps";
+ static final String FSM = "fsm";
+ // Accelerators
+ // Select All by default "control A"
+ static final String SwitchAC = "control B";
+ static final String CopyAC = "control C";
+ static final String SpiderAC = "control D";
+ static final String VarWidthAC = "control E";
+ static final String FindAC = "control F";
+ static final String FindAgainAC = "control G";
+ // Backspace by default "control H"
+ static final String CommonAC = "control I";
+ static final String ExcludedSAC = "control J";
+ static final String AcceptanceAC = "control L";
+ static final String MaxStepsAC = "control M";
+ static final String NonProgressAC = "control N";
+ static final String OpenAC = "control O";
+ static final String ExitAC = "control Q";
+ static final String DisplayRawAC = "control R";
+ static final String SaveAC = "control S";
+ static final String SafetyAC = "control T";
+ static final String ExcludedVAC = "control U";
+ static final String PasteAC = "control V";
+ static final String FairAC = "control W";
+ static final String CutAC = "control X";
+ static final String RedoAC = "control Y";
+ static final String UndoAC = "control Z";
+ // Where to find configuration file
+ public static String installationDirectory;
+ public static String currentDirectory;
+ public static String helpFileName;
+ public static String aboutFileName;
+ static Properties properties = new Properties();
+ // Dummy accelerators
+ static String
+ AboutAC, CheckAC, DefaultAC, HelpAC, InterAC, LTLClearAC,
+ LTLLoadAC, LTLTranslateAC, LTLNameAC, MaxAC, MaxDepthAC, SeedAC,
+ NegateAC, NewAC, OptionsCAC, OptionsInterAC, OptionsPanAC,
+ OptionsRandomAC, OptionsSaveCurrentAC, OptionsSaveInstallAC,
+ OptionsTrailAC, RandomAC, SaveAsAC, SaveSpinAC,
+ SpiderDisplayAC, StopAC, StWidthAC, TrailAC, VerifyAC, RawAC;
+
+ static void setDefaultProperties() {
+ // Spin version: format changed with Spin 6
+ properties.put("VERSION", "6");
+
+ // Directories and file names
+ properties.put("SOURCE_DIRECTORY", "jspin-examples");
+ properties.put("C_COMPILER", "clang");
+ properties.put("SPIN", "/home/victor/Spin/spin");
+ properties.put("PAN", "pan");
+ properties.put("DOT", "dot");
+ properties.put("HELP_FILE_NAME", "txt" + sep + "help.txt");
+ properties.put("ABOUT_FILE_NAME", "txt" + sep + "copyright.txt");
+
+ // Options for executing Spin
+ properties.put("SINGLE_QUOTE", Boolean.toString(false));
+ properties.put("COMMON_OPTIONS", "-g -l -p -r -s");
+ // Check options changed for version 6 (for now)
+ // properties.put("CHECK_OPTIONS", "-a -v");
+ properties.put("CHECK_OPTIONS", "-a");
+ properties.put("RANDOM_OPTIONS", "-X");
+ properties.put("INTERACTIVE_OPTIONS", "-i -X");
+ properties.put("VERIFY_OPTIONS", "-a");
+ properties.put("C_COMPILER_OPTIONS", "-o pan pan.c");
+ properties.put("PAN_OPTIONS", "-X");
+ properties.put("TRAIL_OPTIONS", "-t -X");
+ properties.put("TRANSLATE_OPTIONS", "-f");
+
+ // Settings
+ properties.put("MAX_STEPS", "250");
+ properties.put("MAX_DEPTH", "2000");
+ properties.put("SEED", "0");
+ properties.put("NEGATE_LTL", Boolean.toString(true));
+ properties.put("FAIRNESS", Boolean.toString(true));
+ properties.put("VERIFY_MODE", Safety);
+ properties.put("RAW", Boolean.toString(false));
+ properties.put("PROCESS_WIDTH", Integer.toString(7));
+ properties.put("STATEMENT_WIDTH", Integer.toString(18));
+ properties.put("VARIABLE_WIDTH", Integer.toString(10));
+ properties.put("LINES_PER_TITLE", Integer.toString(20));
+
+ // Size of main frame
+ properties.put("WIDTH", Integer.toString(1000));
+ properties.put("HEIGHT", Integer.toString(700));
+
+ // Select dialog
+ properties.put("SELECT_BUTTON", Integer.toString(220));
+ properties.put("SELECT_HEIGHT", Integer.toString(70));
+ properties.put("SELECT_MENU", Integer.toString(5));
+ properties.put("UNEXECUTABLE", Boolean.toString(false));
+
+ // Location of dividers in JSplitPanes: Left-right and top-bottom
+ properties.put("LR_DIVIDER", Integer.toString(400));
+ properties.put("TB_DIVIDER", Integer.toString(500));
+ properties.put("MIN_DIVIDER", Integer.toString(50));
+
+ // Font
+ properties.put("FONT_FAMILY", "Lucida Sans Typewriter");
+ properties.put("FONT_STYLE", Integer.toString(java.awt.Font.PLAIN));
+ properties.put("FONT_SIZE", Integer.toString(14));
+
+ // Tab size in editor
+ properties.put("TAB_SIZE", Integer.toString(4));
+
+ // Display of Spin output
+ properties.put("WRAP", Boolean.toString(true));
+ properties.put("MSC", Boolean.toString(false));
+ properties.put("PROCESS_TITLE", "Process ");
+ properties.put("STATEMENT_TITLE", "Statement ");
+
+ // Delay while waiting for user input
+ properties.put("POLLING_DELAY", Integer.toString(200));
+ }
+
+ // Initialize configuration file
+ static public void init() {
+ setDefaultProperties();
+ // Try to open config file in current directory;
+ // if not there, try installation directory;
+ // if not there, write default file
+ currentDirectory = System.getProperty("user.dir");
+ installationDirectory = System.getProperty("java.class.path");
+ int lastSeparator = installationDirectory.lastIndexOf(java.io.File.separator);
+ if (lastSeparator == -1)
+ installationDirectory = ".";
+ else
+ installationDirectory = installationDirectory.substring(0, lastSeparator);
+// System.err.println(currentDirectory + java.io.File.separator + CONFIG_FILE_NAME);
+// System.err.println(installationDirectory + java.io.File.separator + CONFIG_FILE_NAME);
+ FileInputStream in = null;
+ try {
+ in = new FileInputStream(
+ currentDirectory + java.io.File.separator + CONFIG_FILE_NAME);
+ System.err.println("Read configuration file from current directory");
+ } catch (FileNotFoundException e1) {
+ try {
+ in = new FileInputStream(
+ installationDirectory + java.io.File.separator + CONFIG_FILE_NAME);
+ System.err.println("Read configuration file from installation directory");
+ } catch (FileNotFoundException e4) {
+ System.err.println(
+ "Cannot open configuration file, creating new file");
+ try {
+ saveFile(false);
+ in = new FileInputStream(installationDirectory + java.io.File.separator + CONFIG_FILE_NAME);
+ } catch (IOException e2) {
+ System.err.println("Cannot write configuration file");
+ return;
+ }
+ }
+ }
+ try {
+ properties.load(in);
+ in.close();
+ } catch (IOException e3) {
+ System.err.println("Cannot read configuration file");
+ }
+ helpFileName = installationDirectory + java.io.File.separator +
+ properties.getProperty("HELP_FILE_NAME");
+ aboutFileName = installationDirectory + java.io.File.separator +
+ properties.getProperty("ABOUT_FILE_NAME");
+ }
+
+ // Save configuration file
+ static void saveFile(boolean current) {
+ try {
+ FileOutputStream out =
+ new FileOutputStream(
+ (current ? currentDirectory : installationDirectory)
+ + java.io.File.separator + CONFIG_FILE_NAME);
+ properties.store(out, "jSpin configuration file");
+ out.close();
+ System.err.println("Saved jSpin configuration file config.cfg");
+ } catch (IOException e2) {
+ System.err.println("Cannot write configuration file");
+ }
+ }
+
+ public static String getSpin() {
+ return Config.getStringProperty("SPIN");
+ }
+
+ // Interface to get/set propertyies of various types
+ public static String getStringProperty(String s) {
+ return properties.getProperty(s);
+ }
+
+ static void setStringProperty(String s, String newValue) {
+ properties.setProperty(s, newValue);
+ }
+
+ public static boolean getBooleanProperty(String s) {
+ return Boolean.valueOf(properties.getProperty(s));
+ }
+
+ static void setBooleanProperty(String s, boolean newValue) {
+ properties.setProperty(s, Boolean.toString(newValue));
+ }
+
+ public static int getIntProperty(String s) {
+ return Integer.valueOf(properties.getProperty(s));
+ }
+
+ static void setIntProperty(String s, int newValue) {
+ properties.setProperty(s, Integer.toString(newValue));
+ }
+
+ public static Properties getProperties() {
+ return properties;
+ }
+}
diff --git a/src/main/java/com/spinroot/jspin/DisplayImage.java b/src/main/java/com/spinroot/jspin/DisplayImage.java
new file mode 100644
index 0000000..55682a6
--- /dev/null
+++ b/src/main/java/com/spinroot/jspin/DisplayImage.java
@@ -0,0 +1,30 @@
+/* Copyright 2005 by Mordechai (Moti) Ben-Ari. See copyright.txt. */
+// Class DisplayFile for Help, About, Display raw
+package com.spinroot.jspin;
+
+import javax.swing.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyEvent;
+
+class DisplayImage extends JFrame implements ActionListener {
+ DisplayImage(String file) {
+ ImagePanel image = new ImagePanel(file);
+ getContentPane().add(new JScrollPane(image));
+ setDefaultCloseOperation(
+ javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
+ getRootPane().registerKeyboardAction(this,
+ KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0),
+ JComponent.WHEN_IN_FOCUSED_WINDOW);
+ setTitle(file);
+ setSize((int) (0.8 * Config.getIntProperty("WIDTH")),
+ (int) (0.9 * Config.getIntProperty("HEIGHT")));
+ setLocationRelativeTo(null);
+ setVisible(true);
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ dispose();
+ }
+}
+
diff --git a/src/main/java/com/spinroot/jspin/Editor.java b/src/main/java/com/spinroot/jspin/Editor.java
new file mode 100644
index 0000000..ae4284b
--- /dev/null
+++ b/src/main/java/com/spinroot/jspin/Editor.java
@@ -0,0 +1,411 @@
+/* Copyright 2003-7 by Mordechai (Moti) Ben-Ari. See copyright.txt. */
+/*
+ * Editor for Promela programs
+ */
+
+package com.spinroot.jspin;
+
+import org.apache.commons.io.FileUtils;
+
+import javax.swing.*;
+import javax.swing.border.Border;
+import javax.swing.border.TitledBorder;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
+import java.awt.*;
+import java.awt.datatransfer.*;
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+
+class Editor implements ClipboardOwner, DocumentListener {
+ private static final Border border = BorderFactory.createMatteBorder(2, 0, 0, 0, Color.gray);
+ /**
+ * The file to be edited
+ */
+ private File file;
+ /**
+ * Previous file to be edited
+ */
+ private File lastFile;
+ /**
+ * The name of the file
+ */
+ private String fileName;
+ /**
+ * The file name without its extension
+ */
+ private String fileRoot;
+ /**
+ * The extension of the source file
+ */
+ private String extension = "";
+ /**
+ * The path to the file
+ */
+ private String root;
+ /**
+ * LTL file name for this source file
+ */
+ private String LTLFileName = "";
+ /**
+ * Spin display output file name
+ */
+ private String OUTFileName = "";
+ /**
+ * File for excluded variable names
+ */
+ private String EXCFileName = "";
+ /**
+ * File for excluded statements
+ */
+ private String EXSFileName = "";
+ /**
+ * Property file name for this source file
+ */
+ private String PRPFileName = "";
+ /**
+ * Property file name without path
+ */
+ private String PRPName;
+ /**
+ * The area for editing
+ */
+ private JTextArea area;
+ /**
+ * The area for LTL formulas
+ */
+ private JTextField LTLField;
+ /**
+ * The area for messages
+ */
+ private JTextArea messageArea;
+ /**
+ * The string to search for
+ */
+ private String findString;
+ /**
+ * The last location where it was found
+ */
+ private int findLoc;
+ /**
+ * Was area modified?
+ */
+ private boolean modified;
+ /**
+ * Was LTL field modified?
+ */
+ private boolean LTLmodified;
+ /**
+ * Border - not modified
+ */
+ private Border border1;
+ /**
+ * Border - modified
+ */
+ private Border border2;
+ private Clipboard clipboard;
+ private LineNumbers lineNumbers;
+ /**
+ * For setting excluded variable names
+ */
+ private com.spinroot.filterSpin.Filter filter;
+
+ public Editor(JScrollPane jsp, JTextArea area, JTextArea m, JTextField l,
+ javax.swing.event.UndoableEditListener ud, com.spinroot.filterSpin.Filter filter) {
+ this.area = area;
+ LTLField = l;
+ LTLField.getDocument().addDocumentListener(this);
+ messageArea = m;
+ PRPName = "";
+ clipboard = this.area.getToolkit().getSystemClipboard();
+ lineNumbers = new LineNumbers(this.area);
+ jsp.setRowHeaderView(lineNumbers);
+ this.filter = filter;
+ }
+
+ public File getFile() {
+ return file;
+ }
+
+ public File getLastFile() {
+ return lastFile;
+ }
+
+ public void setLastFile(File lastFile) {
+ this.lastFile = lastFile;
+ }
+
+ public String getFileName() {
+ return fileName;
+ }
+
+ public String getFileRoot() {
+ return fileRoot;
+ }
+
+ public void setFileRoot(String fileRoot) {
+ this.fileRoot = fileRoot;
+ }
+
+ public String getExtension() {
+ return extension;
+ }
+
+ public String getRoot() {
+ return root;
+ }
+
+ public String getLTLFileName() {
+ return LTLFileName;
+ }
+
+ public String getOUTFileName() {
+ return OUTFileName;
+ }
+
+ public String getEXCFileName() {
+ return EXCFileName;
+ }
+
+ public String getEXSFileName() {
+ return EXSFileName;
+ }
+
+ void focus(boolean start) {
+ area.requestFocusInWindow();
+ if (start)
+ area.setCaretPosition(0);
+ }
+
+ void caretToLine(int line) {
+ try {
+ area.requestFocusInWindow();
+ area.setCaretPosition(area.getLineStartOffset(line - 1));
+ } catch (Exception e) {
+ area.setCaretPosition(0);
+ }
+ }
+
+ void cut() {
+ if (area.getSelectionStart() != area.getSelectionEnd()) {
+ String s = area.getSelectedText();
+ StringSelection contents = new StringSelection(s);
+ clipboard.setContents(contents, this);
+ area.replaceRange(null,
+ area.getSelectionStart(), area.getSelectionEnd());
+ }
+ }
+
+ void copy() {
+ if (area.getSelectionStart() != area.getSelectionEnd()) {
+ String s = area.getSelectedText();
+ StringSelection contents = new StringSelection(s);
+ clipboard.setContents(contents, this);
+ }
+ }
+
+ void paste() {
+ Transferable content = clipboard.getContents(this);
+ if (content != null) {
+ try {
+ String s = (String) content.getTransferData(
+ DataFlavor.stringFlavor);
+ area.replaceRange(s,
+ area.getSelectionStart(), area.getSelectionEnd());
+ } catch (Exception ex) {
+ System.err.println("Can't paste");
+ }
+ }
+ }
+
+ private void showArea(String title) {
+ String previousTitle = " / " +
+ ((lastFile == null) ? "-" : lastFile.getName()) + " ";
+ findString = null;
+ findLoc = 0;
+ modified = false;
+ border1 = BorderFactory.createTitledBorder(
+ border, " " + title + previousTitle,
+ TitledBorder.LEFT, TitledBorder.TOP);
+ border2 = BorderFactory.createTitledBorder(
+ border, " " + title + " * " + previousTitle,
+ TitledBorder.LEFT, TitledBorder.TOP);
+ area.setBorder(border1);
+ focus(true);
+ }
+
+ void newFile() {
+ root = "";
+ file = null;
+ fileName = "";
+ fileRoot = "";
+ LTLFileName = "";
+ OUTFileName = "";
+ EXCFileName = "";
+ EXSFileName = "";
+ PRPFileName = "";
+ area.setText("");
+ showArea(" ");
+ }
+
+ private void setPMLRootAndName() {
+ fileName = file.getName();
+ if (file.getParentFile() == null)
+ root = "";
+ else
+ root = file.getParentFile().getAbsolutePath();
+ if (fileName.lastIndexOf('.') == -1)
+ fileRoot = fileName;
+ else {
+ fileRoot = fileName.substring(0, fileName.lastIndexOf('.'));
+ extension = fileName.substring(fileName.lastIndexOf('.'));
+ }
+ LTLFileName = root + File.separator + fileRoot + ".ltl";
+ OUTFileName = root + File.separator + fileRoot + ".out";
+ EXCFileName = root + File.separator + fileRoot + ".exc";
+ EXSFileName = root + File.separator + fileRoot + ".exs";
+ PRPFileName = root + File.separator + fileRoot + ".prp";
+ PRPName = "";
+ showArea(fileName);
+ }
+
+ private void setPRPRootAndName(File fc) {
+ String fileName = fc.getName();
+ String fileRoot, root;
+ if (file.getParentFile() == null)
+ root = "";
+ else
+ root = fc.getParentFile().getAbsolutePath();
+ if (fileName.lastIndexOf('.') == -1)
+ fileRoot = fileName;
+ else
+ fileRoot = fileName.substring(0, fileName.lastIndexOf('.'));
+ LTLFileName = root + File.separator + fileRoot + ".ltl";
+ PRPFileName = root + File.separator + fileRoot + ".prp";
+ PRPName = fileRoot + ".prp";
+ }
+
+ // Open file: Promela (and excluded) or property file
+ void openFile(File fc, boolean pml) {
+ String prp = "";
+ if (pml) {
+ if (!fc.exists()) {
+ messageArea.append("File " + fc + " does not exist\n");
+ focus(true);
+ return;
+ }
+ file = fc;
+ area.setText(readFile(fc));
+ setPMLRootAndName();
+ prp = readFile(new java.io.File(PRPFileName));
+ filter.setExcluded(readFile(new java.io.File(EXCFileName)), true);
+ filter.setExcluded(readFile(new java.io.File(EXSFileName)), false);
+ } else {
+ if (fc.exists())
+ prp = readFile(fc);
+ else
+ messageArea.append("Creating new prp file\n");
+ setPRPRootAndName(fc);
+ }
+ LTLField.setText(prp.startsWith("Error") ? "" : prp);
+ LTLmodified = false;
+ }
+
+ String readFile(File fc) {
+ try {
+ return FileUtils.readFileToString(fc, StandardCharsets.UTF_8);
+ } catch (IOException e) {
+ focus(true);
+ return "IO error with file " + fc;
+ }
+ }
+
+ void saveFile(File fc) {
+ if (fc != null) {
+ file = fc;
+ setPMLRootAndName();
+ LTLmodified = true; // To force saving
+ modified = true;
+ }
+ if (LTLmodified) {
+ if (!LTLField.getText().equals(""))
+ writeFile(new java.io.File(PRPFileName), LTLField);
+ LTLmodified = false;
+ }
+ if (modified) {
+ area.setBorder(border1);
+ writeFile(file, area);
+ modified = false;
+ }
+ }
+
+ void writeFile(File fc, javax.swing.text.JTextComponent area) {
+ if (fc == null || area == null) {
+ return;
+ }
+ try {
+ FileUtils.writeStringToFile(fc, area.getText(), StandardCharsets.UTF_8);
+ messageArea.append("Saved " + fc.getName() + "\n");
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ void find() {
+ findString = JOptionPane.showInputDialog(
+ area, null, "Find", JOptionPane.PLAIN_MESSAGE);
+ if (findString != null) {
+ search();
+ findLoc = area.getCaretPosition();
+ } else
+ focus(false);
+ }
+
+ void findAgain() {
+ if (findString != null)
+ search();
+ else
+ focus(false);
+ }
+
+ private void search() {
+ int found = area.getText().toLowerCase().indexOf(
+ findString.toLowerCase(), findLoc);
+ if (found != -1) {
+ findLoc = found + 1;
+ area.setCaretPosition(found);
+ area.moveCaretPosition(found + findString.length());
+ }
+ focus(false);
+ }
+
+ private void setModified(DocumentEvent e) {
+ modified = true;
+ area.setBorder(border2);
+ final int lines = area.getLineCount();
+ if (lineNumbers != null) {
+ Runnable updateAComponent = () -> lineNumbers.setHeightByLines(lines);
+ SwingUtilities.invokeLater(updateAComponent);
+ }
+ }
+
+ public void modifiedLTL() {
+ LTLmodified = true;
+ }
+
+ public void changedUpdate(DocumentEvent e) {
+ setModified(e);
+ }
+
+ public void insertUpdate(DocumentEvent e) {
+ setModified(e);
+ }
+
+ public void removeUpdate(DocumentEvent e) {
+ setModified(e);
+ }
+
+ public void lostOwnership(Clipboard clipboard, Transferable content) {
+ }
+}
diff --git a/jspin/Excluded.java b/src/main/java/com/spinroot/jspin/Excluded.java
similarity index 55%
rename from jspin/Excluded.java
rename to src/main/java/com/spinroot/jspin/Excluded.java
index eef378a..7be83bc 100644
--- a/jspin/Excluded.java
+++ b/src/main/java/com/spinroot/jspin/Excluded.java
@@ -1,59 +1,62 @@
-/* Copyright 2005 by Mordechai (Moti) Ben-Ari. See copyright.txt. */
-/*
- * Edit excluded variables
- */
-
-package jspin;
-import javax.swing.*;
-import java.awt.event.*;
-
-class Excluded extends JFrame implements ActionListener {
- private JTextArea names;
- private JButton okButton = new JButton(Config.OK);
- private JButton cancelButton = new JButton(Config.Cancel);
- private JPanel textPanel = new JPanel();
- private JPanel OKPanel = new JPanel();
- private Editor editor;
- private filterSpin.Filter filter;
- private boolean exVar;
- private String fileName;
-
- Excluded(Editor e, java.awt.Font font, filterSpin.Filter f, boolean v) {
- editor = e;
- filter = f;
- exVar = v;
- fileName = exVar ? editor.EXCFileName : editor.EXSFileName;
- String read = editor.readFile(new java.io.File(fileName));
- if (read.startsWith("Error")) read = "";
- names = new JTextArea(read, 9, 32);
- names.setFont(font);
- textPanel.add(new JScrollPane(names));
- OKPanel.add(okButton);
- OKPanel.add(cancelButton);
- okButton.setMnemonic(Config.OKMN);
- okButton.addActionListener(this);
- cancelButton.addActionListener(this);
- getRootPane().setDefaultButton(okButton);
- getRootPane().registerKeyboardAction(this,
- KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0),
- JComponent.WHEN_IN_FOCUSED_WINDOW);
- getContentPane().add(textPanel, java.awt.BorderLayout.CENTER);
- getContentPane().add(OKPanel, java.awt.BorderLayout.SOUTH);
- setTitle(exVar ? Config.ExcludedV : Config.ExcludedS);
- setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
- setSize(Config.getIntProperty("WIDTH")/3,
- Config.getIntProperty("HEIGHT")/3);
- setLocationRelativeTo(null);
- validate();
- setVisible(true);
- jSpin.append(names, null); // Set caret to end of display
- }
-
- public void actionPerformed(ActionEvent e) {
- if ((e.getSource() == okButton) && !fileName.equals("")) {
- editor.writeFile(new java.io.File(fileName), names);
- filter.setExcluded(names.getText(), exVar);
- }
- dispose();
- }
-}
+/* Copyright 2005 by Mordechai (Moti) Ben-Ari. See copyright.txt. */
+/*
+ * Edit excluded variables
+ */
+
+package com.spinroot.jspin;
+
+import javax.swing.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyEvent;
+
+class Excluded extends JFrame implements ActionListener {
+ private JTextArea names;
+ private JButton okButton = new JButton(Config.OK);
+ private JButton cancelButton = new JButton(Config.Cancel);
+ private JPanel textPanel = new JPanel();
+ private JPanel OKPanel = new JPanel();
+ private Editor editor;
+ private com.spinroot.filterSpin.Filter filter;
+ private boolean exVar;
+ private String fileName;
+
+ Excluded(Editor editor, java.awt.Font font, com.spinroot.filterSpin.Filter filter, boolean v) {
+ this.editor = editor;
+ this.filter = filter;
+ exVar = v;
+ fileName = exVar ? this.editor.getEXCFileName() : this.editor.getEXSFileName();
+ String read = this.editor.readFile(new java.io.File(fileName));
+ if (read.startsWith("Error")) read = "";
+ names = new JTextArea(read, 9, 32);
+ names.setFont(font);
+ textPanel.add(new JScrollPane(names));
+ OKPanel.add(okButton);
+ OKPanel.add(cancelButton);
+ okButton.setMnemonic(Config.OKMN);
+ okButton.addActionListener(this);
+ cancelButton.addActionListener(this);
+ getRootPane().setDefaultButton(okButton);
+ getRootPane().registerKeyboardAction(this,
+ KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0),
+ JComponent.WHEN_IN_FOCUSED_WINDOW);
+ getContentPane().add(textPanel, java.awt.BorderLayout.CENTER);
+ getContentPane().add(OKPanel, java.awt.BorderLayout.SOUTH);
+ setTitle(exVar ? Config.ExcludedV : Config.ExcludedS);
+ setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
+ setSize(Config.getIntProperty("WIDTH") / 3,
+ Config.getIntProperty("HEIGHT") / 3);
+ setLocationRelativeTo(null);
+ validate();
+ setVisible(true);
+ jSpin.append(names, null); // Set caret to end of display
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ if ((e.getSource() == okButton) && !fileName.equals("")) {
+ editor.writeFile(new java.io.File(fileName), names);
+ filter.setExcluded(names.getText(), exVar);
+ }
+ dispose();
+ }
+}
diff --git a/src/main/java/com/spinroot/jspin/Filter.java b/src/main/java/com/spinroot/jspin/Filter.java
new file mode 100644
index 0000000..2fc2c86
--- /dev/null
+++ b/src/main/java/com/spinroot/jspin/Filter.java
@@ -0,0 +1,214 @@
+/* Copyright 2004-5 by Mordechai (Moti) Ben-Ari. See copyright.txt. */
+/*
+ * Filter Spin output.
+ * Display a table: process, statement, variables.
+ * The width of a variable field is dynamically configurable (VARIABLE_WIDTH).
+*/
+
+package com.spinroot.jspin;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.TreeMap;
+
+class Filter {
+ private static final String spacerTitle = " ";
+
+ // Print the title repeatedly
+ private static final int linesPerTitle = 20;
+ private String title; // String for names of variables
+ private int lines; // Line counter to redisplay title
+
+ // Map of variable names and values
+ private TreeMap variables = new TreeMap();
+ private int oldSize; // Previous size to see if variable added
+
+ // Excluded variable names and statements
+ private ArrayList excludedVar = new ArrayList();
+ private ArrayList excludedState = new ArrayList();
+
+ // Called before each new command
+ void init() {
+ variables.clear();
+ oldSize = 0;
+ title = "";
+ lines = -1;
+ }
+
+ // Parse string to initialize excluded array; ignore NL and CR
+ void setExcluded(String s, boolean exVar) {
+ List excluded = exVar ? excludedVar : excludedState;
+ s = s.replace('\r', '\n');
+ excluded.clear();
+ do {
+ int nl = s.indexOf('\n');
+ if (nl == -1) break;
+ if (!s.substring(0, nl).equals(""))
+ excluded.add(s.substring(0, nl));
+ s = s.substring(nl + 1);
+ } while (true);
+ }
+
+ // Check for excluded variables.
+ // For each excluded string S;
+ // If variable name includes S, do not display,
+ // but if some +T in file is in name, display anyway.
+ private boolean checkExcluded(String name, boolean exVar) {
+ List excluded = exVar ? excludedVar : excludedState;
+ for (int i = 0; i < excluded.size(); i++)
+ if ((excluded.get(i).charAt(0) != '+') &&
+ (name.indexOf(excluded.get(i)) != -1)) {
+ boolean included = false;
+ for (int j = 0; j < excluded.size(); j++)
+ included = included ||
+ ((excluded.get(j).charAt(0) == '+') &&
+ (name.indexOf(excluded.get(j).substring(1)) != -1));
+ return !included;
+ }
+ return false;
+ }
+
+ String filter(String s) {
+ try {
+ // Variables and queues start with double tab
+ if (s.startsWith("\t\t")) {
+ String varName, varValue;
+ // Name and value of variable/queue to TreeMap
+ if (s.startsWith("\t\tqueue")) {
+ varName = s.substring(s.indexOf('(') + 1, s.indexOf(')'));
+ varValue = s.substring(s.indexOf(':') + 1).trim();
+ } else {
+ varName = s.substring(2, s.indexOf('=') - 1);
+ varValue = s.substring(s.indexOf('=') + 1).trim();
+ }
+ if (checkExcluded(varName, true)) return "";
+ variables.put(varName, varValue);
+ // Construct new title if new variables encountered
+ if (variables.size() > oldSize) {
+ title = formatItem(Config.processTitle,
+ Config.getIntProperty("PROCESS_WIDTH")) +
+ spacerTitle +
+ formatItem(Config.statementTitle,
+ Config.getIntProperty("STATEMENT_WIDTH")) +
+ spacerTitle +
+ collectionToString(variables.keySet()) + "\n";
+ oldSize = variables.size();
+ lines = -1;
+ }
+ return "";
+ }
+
+ // Display Spin and pan messages unmodified
+ // Also non-prefixed error message
+ else if ((s.startsWith("pan:")) ||
+ (s.startsWith("spin:")) ||
+ (s.startsWith("tl_spin:")) ||
+ (s.startsWith("Error:")) ||
+ (s.startsWith("error:")))
+ return s + "\n";
+ // Display error count
+ else if (s.indexOf("errors:") != -1)
+ return
+ s.substring(0, s.indexOf("errors:")) + "\u2022\u2022\u2022 " +
+ s.substring(s.indexOf("errors:")) + " \u2022\u2022\u2022\n";
+ // Display MSC lines (without MSC:)
+ else if (Config.getBooleanProperty("MSC") &&
+ s.trim().startsWith("MSC:"))
+ return s.substring(s.indexOf("MSC:") + 5) + "\n";
+ // Display cycle messages
+ else if (s.indexOf("<<<<<") != -1)
+ return s + "\n";
+
+ // Display lines with statements, including choices
+ else if ((s.indexOf("proc") != -1) && (s.indexOf("line") != -1)) {
+ String u = "";
+ // Get process name
+ String proc =
+ s.substring(s.indexOf("proc") + 4, s.indexOf(")") + 1).trim();
+ proc = proc.substring(0, proc.indexOf("(")) +
+ strip(proc.substring(proc.indexOf("(")));
+ // Get line number and statement name
+ String statement = "";
+ if (s.indexOf('[') != -1) {
+ statement = formatItem(
+ s.substring(s.indexOf("line") + 4, s.indexOf("\"")).trim(), 3);
+ statement = statement + " " +
+ strip(s.substring(s.indexOf('[') + 1, s.lastIndexOf(']')));
+ }
+ if (checkExcluded(statement, false)) return "";
+ // For choice, display just process and statement
+ if (s.indexOf("choice") != -1)
+ u = s.substring(s.indexOf("choice"), s.indexOf(':') + 2) +
+ proc + " " + statement + "\n";
+ // Display table line (unless goto/else/break)
+ else if ((statement.indexOf("goto") == -1) &&
+ !statement.equals("else") &&
+ !statement.equals("break")) {
+ u = formatItem(proc,
+ Config.getIntProperty("PROCESS_WIDTH")) +
+ spacerTitle +
+ formatItem(statement,
+ Config.getIntProperty("STATEMENT_WIDTH")) +
+ spacerTitle +
+ collectionToString(variables.values()) + "\n";
+ lines = (lines + 1) % linesPerTitle;
+ // Display title if needed
+ if (lines == 0) u = title + u;
+ }
+ return u;
+ }
+ // Display choices that have no proc and line number
+ else if (s.indexOf("choice") != -1)
+ return s.substring(s.indexOf("choice")) + "\n";
+ else if (!Config.getBooleanProperty("MSC") && !s.equals(""))
+ return s + "\n";
+ else
+ return "";
+
+ } catch (Exception e) {
+ System.err.println("\n + jSpin error in filter for:\n" + s + "\n");
+ e.printStackTrace();
+ return "";
+ }
+ }
+
+ // Strip parentheses
+ String strip(String s) {
+ while ((s.charAt(0) == '(') && (s.charAt(s.length() - 1) == ')'))
+ s = s.substring(1, s.length() - 1);
+ return s;
+ }
+
+ // Format a variable name or value
+ private String formatItem(String s, int len) {
+ // Item is too long, must shorten it
+ if (s.length() > len) {
+ // Array variable: shorten name, not index
+ if (s.indexOf("[") != -1) {
+ String subscript =
+ s.substring(s.indexOf("["), s.lastIndexOf("]") + 1);
+ if (subscript.length() < len)
+ return s.substring(0,
+ len - subscript.length()) + subscript;
+ else
+ return s.substring(0, len);
+ } else
+ return s.substring(0, len);
+ }
+ // Item is too short, pad it
+ else if (s.length() < len)
+ return (s + " ").substring(0, len);
+ else
+ return s;
+ }
+
+ // Transform a collection to a string, calling formatItem for each element
+ private String collectionToString(Collection c) {
+ StringBuilder s = new StringBuilder();
+ for (String aC : c) {
+ s.append(formatItem(aC, Config.getIntProperty("VARIABLE_WIDTH"))).append(" ");
+ }
+ return s.toString();
+ }
+}
diff --git a/jspin/ImagePanel.java b/src/main/java/com/spinroot/jspin/ImagePanel.java
similarity index 72%
rename from jspin/ImagePanel.java
rename to src/main/java/com/spinroot/jspin/ImagePanel.java
index 816c778..4719236 100644
--- a/jspin/ImagePanel.java
+++ b/src/main/java/com/spinroot/jspin/ImagePanel.java
@@ -1,24 +1,29 @@
-/* Copyright 2005 by Mordechai (Moti) Ben-Ari. See copyright.txt. */
-/*
- * Display images from dot file
- */
-package jspin;
-import java.awt.*;
-
-import javax.swing.*;
-
-class ImagePanel extends JPanel {
- private Image image;
- ImagePanel(String fileName) {
- image = Toolkit.getDefaultToolkit().createImage(fileName);
- MediaTracker tracker = new MediaTracker(this);
- tracker.addImage(image, 0);
- try { tracker.waitForID(0); }
- catch (InterruptedException e) {}
- setPreferredSize(new Dimension(image.getWidth(this), image.getHeight(this)));
- }
- public void paintComponent(Graphics g) {
- super.paintComponent(g);
- g.drawImage(image, 0, 0, null);
- }
-}
+/* Copyright 2005 by Mordechai (Moti) Ben-Ari. See copyright.txt. */
+/*
+ * Display images from dot file
+ */
+package com.spinroot.jspin;
+
+import javafx.embed.swing.JFXPanel;
+
+import java.awt.*;
+
+class ImagePanel extends JFXPanel {
+ private Image image;
+
+ ImagePanel(String fileName) {
+ image = Toolkit.getDefaultToolkit().createImage(fileName);
+ MediaTracker tracker = new MediaTracker(this);
+ tracker.addImage(image, 0);
+ try {
+ tracker.waitForID(0);
+ } catch (InterruptedException e) {
+ }
+ setPreferredSize(new Dimension(image.getWidth(this), image.getHeight(this)));
+ }
+
+ public void paintComponent(Graphics g) {
+ super.paintComponent(g);
+ g.drawImage(image, 0, 0, null);
+ }
+}
diff --git a/jspin/JSpinFileFilter.java b/src/main/java/com/spinroot/jspin/JSpinFileFilter.java
similarity index 66%
rename from jspin/JSpinFileFilter.java
rename to src/main/java/com/spinroot/jspin/JSpinFileFilter.java
index 516b6e7..4ef0992 100644
--- a/jspin/JSpinFileFilter.java
+++ b/src/main/java/com/spinroot/jspin/JSpinFileFilter.java
@@ -1,35 +1,39 @@
-/* Copyright 2005 by Mordechai (Moti) Ben-Ari. See copyright.txt. */
-/*
- * File filter for jSpin
-*/
-
-package jspin;
-import java.io.File;
-import javax.swing.filechooser.*;
-
-public class JSpinFileFilter extends FileFilter {
-
- private String ext1 = "";
- private String ext2 = "";
- private String ext3 = "";
- private String description = "";
-
- public JSpinFileFilter(String d, String e1, String e2, String e3) {
- ext1 = e1; ext2 = e2; ext3 = e3; description = d;
- }
-
- public boolean accept(File f) {
- if (f.isDirectory())
- return true;
- else {
- String e = f.getName().toUpperCase();
- return e.endsWith(ext1) ||
- (ext2 == null ? false : e.endsWith(ext2)) ||
- (ext3 == null ? false : e.endsWith(ext3));
- }
- }
-
- public String getDescription() {
- return description;
- }
-}
+/* Copyright 2005 by Mordechai (Moti) Ben-Ari. See copyright.txt. */
+/*
+ * File filter for jSpin
+*/
+
+package com.spinroot.jspin;
+
+import javax.swing.filechooser.FileFilter;
+import java.io.File;
+
+public class JSpinFileFilter extends FileFilter {
+
+ private String ext1 = "";
+ private String ext2 = "";
+ private String ext3 = "";
+ private String description = "";
+
+ public JSpinFileFilter(String d, String e1, String e2, String e3) {
+ ext1 = e1;
+ ext2 = e2;
+ ext3 = e3;
+ description = d;
+ }
+
+ public boolean accept(File f) {
+ if (f.isDirectory())
+ return true;
+ else {
+ String e = f.getName().toUpperCase();
+ return e.endsWith(ext1) ||
+ (ext2 != null && e.endsWith(ext2)) ||
+ (ext3 != null && e.endsWith(ext3));
+ }
+ }
+
+ public String getDescription() {
+ return description;
+ }
+}
diff --git a/jspin/LineNumbers.java b/src/main/java/com/spinroot/jspin/LineNumbers.java
similarity index 76%
rename from jspin/LineNumbers.java
rename to src/main/java/com/spinroot/jspin/LineNumbers.java
index 9ecd38b..fbd34de 100644
--- a/jspin/LineNumbers.java
+++ b/src/main/java/com/spinroot/jspin/LineNumbers.java
@@ -3,14 +3,15 @@
* Display line numbers in editor
*/
-package jspin;
-import java.awt.*;
+package com.spinroot.jspin;
+
import javax.swing.*;
+import java.awt.*;
public class LineNumbers extends JComponent {
- private int size; // Width of line numbers
- private Font font; // Font of editor window
- private int ascent; // Data for computation of line height
+ private int size; // Width of line numbers
+ private Font font; // Font of editor window
+ private int ascent; // Data for computation of line height
private int increment;
private int top;
@@ -20,8 +21,8 @@ public class LineNumbers extends JComponent {
size = fm.stringWidth("000") + 6;
ascent = fm.getAscent();
increment = ascent + fm.getDescent();
- // Extra line for file name in border
- top = fm.getHeight() + fm.getDescent() + 3;
+ // Extra line for file name in border
+ top = fm.getHeight() + fm.getDescent() + 3;
setPreferredSize(new Dimension(size, area.getSize().height));
revalidate();
}
@@ -40,11 +41,11 @@ public void paintComponent(Graphics g) {
// Ruler labels in black color
g.setFont(font);
g.setColor(Color.black);
- int end = 0; //This keeps the position for the end of the view
- int start = 0; //This keeps the position for the beginning of the view
+ int end = 0; //This keeps the position for the end of the view
+ int start = 0; //This keeps the position for the beginning of the view
start = (drawHere.y / increment) * increment;
end = (((drawHere.y + drawHere.height) / increment) + 1)
- * increment;
+ * increment;
int lineNumber = (int) Math.floor(drawHere.y / increment) + 1;
start += top + ascent;
end += top + ascent;
diff --git a/src/main/java/com/spinroot/jspin/Options.java b/src/main/java/com/spinroot/jspin/Options.java
new file mode 100644
index 0000000..3b5052c
--- /dev/null
+++ b/src/main/java/com/spinroot/jspin/Options.java
@@ -0,0 +1,118 @@
+/* Copyright 2005 by Mordechai (Moti) Ben-Ari. See copyright.txt. */
+/*
+ * Dialog for setting Common Options
+ */
+
+package com.spinroot.jspin;
+
+import javax.swing.*;
+import java.awt.event.*;
+
+class Options extends JFrame implements ActionListener, ItemListener {
+ static final String ST = "-p", LOC = "-l", GLO = "-g", SENT = "-s", REC = "-r";
+ private JCheckBox stBox, locBox, gloBox, sentBox, recBox;
+ private JButton okButton, cancelButton, clearAllButton, setAllButton;
+ private JPanel buttonPanel, OKPanel;
+ private boolean st;
+ private boolean loc;
+ private boolean glo;
+ private boolean sent;
+ private boolean rec;
+
+ Options() {
+ String s = Config.getStringProperty("COMMON_OPTIONS");
+ st = s.contains(ST);
+ loc = s.contains(LOC);
+ glo = s.contains(GLO);
+ sent = s.contains(SENT);
+ rec = s.contains(REC);
+ buttonPanel = new JPanel();
+ buttonPanel.setLayout(new java.awt.GridLayout(5, 1));
+ stBox = create(Config.Statements, st, Config.StatementsMN);
+ locBox = create(Config.Locals, loc, Config.LocalsMN);
+ gloBox = create(Config.Globals, glo, Config.GlobalsMN);
+ sentBox = create(Config.Sent, sent, Config.SentMN);
+ recBox = create(Config.Received, rec, Config.ReceivedMN);
+ OKPanel = new JPanel();
+ OKPanel.setLayout(new java.awt.GridLayout(2, 2));
+ okButton = new JButton(Config.OK);
+ cancelButton = new JButton(Config.Cancel);
+ clearAllButton = new JButton(Config.ClearAll);
+ setAllButton = new JButton(Config.SetAll);
+ okButton.setMnemonic(Config.OKMN);
+ clearAllButton.setMnemonic(Config.ClearAllMN);
+ setAllButton.setMnemonic(Config.SetAllMN);
+ OKPanel.add(okButton);
+ OKPanel.add(cancelButton);
+ OKPanel.add(setAllButton);
+ OKPanel.add(clearAllButton);
+ okButton.addActionListener(this);
+ cancelButton.addActionListener(this);
+ setAllButton.addActionListener(this);
+ clearAllButton.addActionListener(this);
+ getRootPane().setDefaultButton(okButton);
+ getRootPane().registerKeyboardAction(this,
+ KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0),
+ JComponent.WHEN_IN_FOCUSED_WINDOW);
+ getContentPane().add(buttonPanel, java.awt.BorderLayout.CENTER);
+ getContentPane().add(OKPanel, java.awt.BorderLayout.SOUTH);
+ setTitle(Config.OPTIONS_TITLE);
+ setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
+ setSize(200, 250);
+ setLocationRelativeTo(null);
+ validate();
+ setVisible(true);
+ }
+
+ private JCheckBox create(String s, boolean set, int mn) {
+ JCheckBox cb = new JCheckBox(s, set);
+ cb.setMnemonic(mn);
+ cb.addItemListener(this);
+ buttonPanel.add(cb);
+ return cb;
+ }
+
+ private void setClear(boolean b) {
+ st = b;
+ loc = b;
+ glo = b;
+ sent = b;
+ rec = b;
+ stBox.setSelected(b);
+ locBox.setSelected(b);
+ gloBox.setSelected(b);
+ sentBox.setSelected(b);
+ recBox.setSelected(b);
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ String options = "";
+ if (e.getSource() == okButton) {
+ options = options + (st ? ST + " " : "");
+ options = options + (loc ? LOC + " " : "");
+ options = options + (glo ? GLO + " " : "");
+ options = options + (sent ? SENT + " " : "");
+ options = options + (rec ? REC + " " : "");
+ Config.setStringProperty("COMMON_OPTIONS", options);
+ dispose();
+ } else if (e.getSource() == setAllButton) {
+ setClear(true);
+ } else if (e.getSource() == clearAllButton) {
+ setClear(false);
+ } else
+ dispose();
+ }
+
+ public void itemStateChanged(ItemEvent e) {
+ if (e.getItemSelectable() == stBox)
+ st = e.getStateChange() == ItemEvent.SELECTED;
+ else if (e.getItemSelectable() == locBox)
+ loc = e.getStateChange() == ItemEvent.SELECTED;
+ else if (e.getItemSelectable() == gloBox)
+ glo = e.getStateChange() == ItemEvent.SELECTED;
+ else if (e.getItemSelectable() == sentBox)
+ sent = e.getStateChange() == ItemEvent.SELECTED;
+ else if (e.getItemSelectable() == recBox)
+ rec = e.getStateChange() == ItemEvent.SELECTED;
+ }
+}
diff --git a/src/main/java/com/spinroot/jspin/RunSpin.java b/src/main/java/com/spinroot/jspin/RunSpin.java
new file mode 100644
index 0000000..825a0a7
--- /dev/null
+++ b/src/main/java/com/spinroot/jspin/RunSpin.java
@@ -0,0 +1,371 @@
+/* Copyright 2003-4 by Mordechai (Moti) Ben-Ari. See copyright.txt. */
+/*
+* Fork process for running Spin
+* Manage dialog for interactive simulation
+*/
+
+package com.spinroot.jspin;
+
+import javax.swing.*;
+import java.awt.event.*;
+import java.io.*;
+
+class RunSpin {
+ private static final int MAX_SELECTIONS = 50;
+ private Editor editor; // The editor object
+ private com.spinroot.filterSpin.Filter filter; // The filter object
+ private RunThread runThread; // Thread object for running Spin
+ private SelectDialog selectDialog; // Thread object for select dialog
+ private JTextArea messageArea; // The message area
+ private JTextArea area; // Output area display
+ private PrintWriter rawWriter; // To write raw spin output
+ private String command, parameters; // The command being executed
+ private boolean filtering; // Should the output be filtered
+ private String[] selections = new String[MAX_SELECTIONS];
+ // Statements selected from
+
+ RunSpin(Editor e, JTextArea m, com.spinroot.filterSpin.Filter f) {
+ editor = e;
+ messageArea = m;
+ filter = f;
+ }
+
+ // Called by jSpin to run Spin
+ void run(JTextArea area, boolean filtering, String command, String parameters) {
+ this.filtering = filtering;
+ this.area = area;
+ this.command = command;
+ this.parameters = parameters;
+ filter.init(Config.properties);
+ // Make sure that a file has been opened
+ if (editor.getFile() == null) {
+ jSpin.append(messageArea, Config.OPEN_FILE);
+ return;
+ }
+ // Save editor buffer and set up display areas
+ editor.saveFile(null);
+ if (area != messageArea)
+ this.area.setText("");
+ jSpin.append(messageArea, command + " " + parameters + " ... ");
+ // Create a thread to run Spin and start it
+ runThread = new RunThread();
+ runThread.start();
+ }
+
+ // Run Spin and wait for it to complete
+ void runAndWait(JTextArea area, boolean filtering, String command, String parameters) {
+ run(area, filtering, command, parameters);
+ if (runThread == null) return; // If file not open
+ try {
+ runThread.join();
+ jSpin.append(messageArea, "done!\n");
+ } catch (InterruptedException e) {
+ }
+ }
+
+ // Check is Spin is still running
+ boolean isRunning() {
+ return (runThread != null) && runThread.isAlive();
+ }
+
+ // Kill the thread running Spin and the selection dialog
+ void killSpin() {
+ if (runThread != null) {
+ runThread.killSpin();
+ runThread.interrupt();
+ runThread = null;
+ }
+ if (selectDialog != null) {
+ selectDialog.disposeDialog();
+ selectDialog.interrupt();
+ selectDialog = null;
+ }
+ jSpin.append(messageArea, "\nSpin process stopped\n");
+ }
+
+ // Class RunThread enables Spin to run asynchronously
+ private class RunThread extends Thread {
+ private Process p;
+
+ public void run() {
+ try {
+ if (Config.getBooleanProperty("RAW"))
+ rawFile();
+ // Use ProcessBuilder to run Spin, redirecting ErrorStream
+ String[] sa = stringToArray(command, parameters);
+// for (int i = 0; i < sa.length; i++) System.out.println(sa[i]);
+ ProcessBuilder pb = new ProcessBuilder(sa);
+ File pf = editor.getFile().getParentFile();
+ if (pf != null) pb.directory(pf.getCanonicalFile());
+ pb.redirectErrorStream(true);
+ p = pb.start();
+ // Connect to I/O streams
+ InputStream istream = p.getInputStream();
+ BufferedReader input =
+ new BufferedReader(new InputStreamReader(istream));
+ OutputStream ostream = p.getOutputStream();
+ OutputStreamWriter output = new OutputStreamWriter(ostream);
+ // Process Spin output line by line
+ String s = "";
+ boolean running = true;
+ while (running) {
+ s = input.readLine();
+ if (Config.getBooleanProperty("RAW"))
+ rawWriter.println(s);
+ if (s == null)
+ running = false;
+ else if (s.startsWith("Select a statement") ||
+ s.startsWith("Select stmnt"))
+ running = select(area, p, input, output);
+ else if (s.startsWith("spin: type return")) {
+ output.write("\n");
+ output.flush();
+ } else if (filtering)
+ jSpin.append(area, filter.filter(s));
+ else
+ jSpin.append(area, s + "\n");
+ }
+ // Wait for Spin process to end
+ p.waitFor();
+ if (Config.getBooleanProperty("RAW"))
+ rawWriter.close();
+ // If syntax error, set cursor to line in editor
+ if (area.getText().indexOf("Error: syntax error") != -1) {
+ s = area.getText();
+ try {
+ int line = Integer.parseInt(
+ s.substring(
+ s.indexOf("line") + 4, s.indexOf('"')).trim());
+ editor.caretToLine(line);
+ } catch (NumberFormatException e1) {
+ editor.caretToLine(0);
+ }
+ }
+ } catch (InterruptedException e) {
+ jSpin.append(messageArea, "Interrupted exception");
+ } catch (java.io.IOException e) {
+ jSpin.append(messageArea, "IO exception\n" + e);
+ }
+ }
+
+ // String to array of tokens - for ProcessBuilder
+ // Previous versions of jSpin used StringTokenizer
+ // which caused problems in Linux
+ String[] stringToArray(String command, String s) {
+ char quote = Config.getBooleanProperty("SINGLE_QUOTE") ? '\'' : '"';
+ String[] sa = new String[50];
+ int count = 0, i = 0, start = 0;
+ sa[count] = command;
+ count++;
+ while (i < s.length() && s.charAt(i) == ' ') i++;
+ start = i;
+ boolean isQuote;
+ do {
+ if (i == s.length()) break;
+ isQuote = s.charAt(i) == quote;
+ if (isQuote) i++;
+ if (isQuote) {
+ while (s.charAt(i) != quote) i++;
+ i++;
+ } else
+ while (i < s.length() && s.charAt(i) != ' ') i++;
+ sa[count] = s.substring(start, i);
+ while (i < s.length() && s.charAt(i) == ' ') i++;
+ start = i;
+ count++;
+ } while (true);
+ String[] sb = new String[count];
+ System.arraycopy(sa, 0, sb, 0, count);
+ return sb;
+ }
+
+ // Kill spin process
+ private void killSpin() {
+ if (p != null) p.destroy();
+ }
+
+ // Open file for raw Spin output
+ private void rawFile() {
+ String s = editor.getRoot() + File.separator + editor.getFileRoot() + ".raw";
+ try {
+ rawWriter = new PrintWriter(new FileWriter(s));
+ jSpin.append(messageArea, "\nOpened " + s + "\n");
+ } catch (IOException e) {
+ jSpin.append(messageArea, "\nCannot open " + s + "\n");
+ }
+ }
+
+ // Select the next statement to run in interactive simulation
+ private boolean select(
+ JTextArea area, Process p,
+ BufferedReader input, OutputStreamWriter output) {
+ int numOptions = 0;
+ String filtered;
+ try {
+ String s = input.readLine();
+ if (Config.getBooleanProperty("RAW"))
+ rawWriter.println(s);
+ while (!s.startsWith("Make Selection")) {
+ filtered = filter.filter(s);
+ if ((numOptions < MAX_SELECTIONS) &&
+ (Config.getBooleanProperty("UNEXECUTABLE") ||
+ s.indexOf("unexecutable") == -1)) {
+ selections[numOptions] = new String(filtered.substring(7));
+ numOptions++;
+ }
+ s = input.readLine();
+ if (Config.getBooleanProperty("RAW"))
+ rawWriter.println(s);
+ }
+ if (numOptions == 0) {
+ output.write("q\n");
+ output.flush();
+ return false;
+ }
+ // Get selection from dialog
+ int selectedValue = -1;
+ selectDialog =
+ new SelectDialog(
+ numOptions,
+ numOptions <= Config.getIntProperty("SELECT_MENU"),
+ selections);
+ selectDialog.start();
+ while (selectedValue == -1) {
+ try {
+ Thread.sleep(Config.getIntProperty("POLLING_DELAY"));
+ } catch (InterruptedException e) {
+ }
+ if (selectDialog == null) break;
+ else selectedValue = selectDialog.getValue();
+ }
+ // For Macintosh (?) - Angelika's problem (?)
+ if (selectDialog != null) {
+ selectDialog.interrupt();
+ selectDialog = null;
+ }
+ // if (selectDialog != null) selectDialog.interrupt();
+ // If 0 (escape or close) selected, quit Spin interaction
+ if (selectedValue == 0) {
+ output.write("q\n");
+ output.flush();
+ return false;
+ }
+ selectedValue = Integer.valueOf(
+ selections[selectedValue - 1].substring(
+ 0, selections[selectedValue - 1].indexOf(':')));
+ // Send selection to Spin
+ output.write(selectedValue + "\n");
+ output.flush();
+ s = input.readLine(); // Eat extra new line
+ if (Config.getBooleanProperty("RAW"))
+ rawWriter.println(s);
+ return true;
+ } catch (Exception e) {
+ System.err.println(e);
+ killSpin();
+ return false;
+ }
+ }
+ }
+
+ // Class SelectDialog displays the statement select dialog in a thread
+ private class SelectDialog extends Thread implements ActionListener {
+ private int selectedValue = -1;
+ // Positive when a button is selected, zero upon escape or close
+ private int numOptions; // Number of process buttons
+ private String[] selections;// The selections
+
+ private JFrame dialog; // The frame
+ private JPanel panel;
+ private JButton[] options; // Array of process buttons
+ private JComboBox pulldown = new JComboBox();
+
+ // Constructor - set up frame with number of buttons required
+ SelectDialog(int numOptions, boolean buttons, String[] selections) {
+ this.numOptions = numOptions;
+ this.selections = selections;
+ dialog = new JFrame();
+ dialog.addWindowListener(
+ new WindowAdapter() {
+ public void windowClosing(WindowEvent e) {
+ selectedValue = 0;
+ dialog.dispose();
+ }
+ });
+ dialog.getRootPane().registerKeyboardAction(this,
+ KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0),
+ JComponent.WHEN_IN_FOCUSED_WINDOW);
+ dialog.setTitle(Config.SELECT);
+ panel = new JPanel();
+ if (buttons) constructButtonsDialog();
+ else constructMenuDialog();
+ dialog.getContentPane().setLayout(new java.awt.BorderLayout());
+ dialog.getContentPane().add(panel, java.awt.BorderLayout.CENTER);
+ dialog.setLocationRelativeTo(messageArea);
+ dialog.validate();
+ dialog.setVisible(true);
+ }
+
+ void constructButtonsDialog() {
+ panel.setLayout(new java.awt.GridLayout(1, numOptions));
+ options = new JButton[numOptions];
+ JButton button = null;
+ for (int i = 1; i <= numOptions; i++) {
+ button = new JButton(selections[i - 1]);
+ button.setFont(messageArea.getFont());
+ button.addActionListener(this);
+ options[i - 1] = button;
+ panel.add(button);
+ }
+ dialog.setSize(
+ Config.getIntProperty("SELECT_BUTTON") * numOptions,
+ Config.getIntProperty("SELECT_HEIGHT"));
+ }
+
+ void constructMenuDialog() {
+ panel.setLayout(new java.awt.BorderLayout());
+ pulldown = new JComboBox();
+ pulldown.setFont(messageArea.getFont());
+ pulldown.putClientProperty("JComboBox.isTableCellEditor", Boolean.TRUE);
+ pulldown.setEditable(false);
+ for (int i = 0; i < numOptions; i++)
+ pulldown.addItem(selections[i]);
+ pulldown.setSelectedIndex(-1);
+ pulldown.addActionListener(this);
+ panel.add(pulldown, java.awt.BorderLayout.CENTER);
+ dialog.setSize(
+ Config.getIntProperty("SELECT_BUTTON"),
+ Config.getIntProperty("SELECT_HEIGHT"));
+ }
+
+ // Display dialog
+ public void run() {
+ dialog.setVisible(true);
+ }
+
+ // ActionListener
+ public void actionPerformed(ActionEvent e) {
+ if (e.getSource() instanceof JButton) {
+ JButton selected = (JButton) e.getSource();
+ for (int i = 0; i < numOptions; i++)
+ if (options[i].equals(selected))
+ selectedValue = i + 1;
+ } else if (e.getSource() instanceof JComboBox) {
+ selectedValue = ((JComboBox) e.getSource()).getSelectedIndex() + 1;
+ } else selectedValue = 0;
+ dialog.dispose();
+ java.awt.Dimension rv = ((JComponent) e.getSource()).getSize(null);
+ Config.setIntProperty("SELECT_BUTTON", rv.width);
+ }
+
+ // Dispose of dialog frme
+ private void disposeDialog() {
+ if (dialog != null) dialog.dispose();
+ }
+
+ // Get value
+ private int getValue() {
+ return selectedValue;
+ }
+ }
+}
diff --git a/jspin/SpiderFile.java b/src/main/java/com/spinroot/jspin/SpiderFile.java
similarity index 62%
rename from jspin/SpiderFile.java
rename to src/main/java/com/spinroot/jspin/SpiderFile.java
index 48fcab5..ff80600 100644
--- a/jspin/SpiderFile.java
+++ b/src/main/java/com/spinroot/jspin/SpiderFile.java
@@ -1,89 +1,93 @@
-/* Copyright 2005 by Mordechai (Moti) Ben-Ari. See copyright.txt. */
-/*
- * Read and write the SpinSpider properties file for this program
- */
-
-package jspin;
-import java.io.*;
-import java.util.Properties;
-
-class SpiderFile {
- private Properties properties;
- private String fileName;
-
- SpiderFile (Properties p, String f) {
- properties = p;
- fileName = f + ".spd";
- }
-
- private void setDefaultProperties() {
- properties.put("TRAIL_CODE", Integer.toString(0));
- properties.put("DOT_SIZE", Integer.toString(0));
- properties.put("TRAIL_STYLE", Integer.toString(0));
- properties.put("SPIDER_DEBUG", Boolean.toString(false));
- properties.put("PROCESSES", Integer.toString(2));
- properties.put("FORMAT", Config.PNG);
- properties.put("VARIABLES", "");
- }
-
- // Initialize configuration file
- public void init() {
- setDefaultProperties();
- FileInputStream in = null;
- try {
- in = new FileInputStream(fileName);
- } catch (FileNotFoundException e1) {
- System.out.println(
- "Cannot open SpinSpider file, creating new file");
- try {
- saveFile();
- in = new FileInputStream(fileName);
- } catch (IOException e2) {
- System.err.println("Cannot write SpinSpider file");
- }
- }
- try {
- properties.load(in);
- in.close();
- } catch (IOException e3) {
- System.err.println("Cannot read SpinSpider file");
- }
- }
-
- // Save configuration file
- void saveFile() {
- try {
- FileOutputStream out = new FileOutputStream(fileName);
- properties.store(out, "SpinSpider configuration file");
- out.close();
- System.out.println("Saved SpinSpider file " + fileName);
- } catch (IOException e2) {
- System.err.println("Cannot write SpinSpider file");
- }
- }
-
- // Interface to get/set propertyies of various types
- public String getStringProperty(String s) {
- return properties.getProperty(s);
- }
-
- void setStringProperty(String s, String newValue) {
- properties.setProperty(s, newValue);
- }
-
- public boolean getBooleanProperty(String s) {
- return Boolean.valueOf(properties.getProperty(s)).booleanValue();
- }
-
- void setBooleanProperty(String s, boolean newValue) {
- properties.setProperty(s, Boolean.toString(newValue));
- }
-
- public int getIntProperty(String s) {
- return Integer.valueOf(properties.getProperty(s)).intValue();
- }
-
- void setIntProperty(String s, int newValue) {
- properties.setProperty(s, Integer.toString(newValue));
- }
-}
+/* Copyright 2005 by Mordechai (Moti) Ben-Ari. See copyright.txt. */
+/*
+ * Read and write the SpinSpider properties file for this program
+ */
+
+package com.spinroot.jspin;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Properties;
+
+class SpiderFile {
+ private Properties properties;
+ private String fileName;
+
+ SpiderFile(Properties p, String f) {
+ properties = p;
+ fileName = f + ".spd";
+ }
+
+ private void setDefaultProperties() {
+ properties.put("TRAIL_CODE", Integer.toString(0));
+ properties.put("DOT_SIZE", Integer.toString(0));
+ properties.put("TRAIL_STYLE", Integer.toString(0));
+ properties.put("SPIDER_DEBUG", Boolean.toString(false));
+ properties.put("PROCESSES", Integer.toString(2));
+ properties.put("FORMAT", Config.PNG);
+ properties.put("VARIABLES", "");
+ }
+
+ // Initialize configuration file
+ public void init() {
+ setDefaultProperties();
+ FileInputStream in = null;
+ try {
+ in = new FileInputStream(fileName);
+ } catch (FileNotFoundException e1) {
+ System.out.println(
+ "Cannot open SpinSpider file, creating new file");
+ try {
+ saveFile();
+ in = new FileInputStream(fileName);
+ } catch (IOException e2) {
+ System.err.println("Cannot write SpinSpider file");
+ }
+ }
+ try {
+ properties.load(in);
+ in.close();
+ } catch (IOException e3) {
+ System.err.println("Cannot read SpinSpider file");
+ }
+ }
+
+ // Save configuration file
+ void saveFile() {
+ try {
+ FileOutputStream out = new FileOutputStream(fileName);
+ properties.store(out, "SpinSpider configuration file");
+ out.close();
+ System.out.println("Saved SpinSpider file " + fileName);
+ } catch (IOException e2) {
+ System.err.println("Cannot write SpinSpider file");
+ }
+ }
+
+ // Interface to get/set propertyies of various types
+ public String getStringProperty(String s) {
+ return properties.getProperty(s);
+ }
+
+ void setStringProperty(String s, String newValue) {
+ properties.setProperty(s, newValue);
+ }
+
+ public boolean getBooleanProperty(String s) {
+ return Boolean.valueOf(properties.getProperty(s));
+ }
+
+ void setBooleanProperty(String s, boolean newValue) {
+ properties.setProperty(s, Boolean.toString(newValue));
+ }
+
+ public int getIntProperty(String s) {
+ return Integer.valueOf(properties.getProperty(s));
+ }
+
+ void setIntProperty(String s, int newValue) {
+ properties.setProperty(s, Integer.toString(newValue));
+ }
+}
diff --git a/jspin/SpiderOptions.java b/src/main/java/com/spinroot/jspin/SpiderOptions.java
similarity index 51%
rename from jspin/SpiderOptions.java
rename to src/main/java/com/spinroot/jspin/SpiderOptions.java
index 1a597f7..1d1b6c8 100644
--- a/jspin/SpiderOptions.java
+++ b/src/main/java/com/spinroot/jspin/SpiderOptions.java
@@ -1,212 +1,215 @@
-/* Copyright 2007 by Mordechai (Moti) Ben-Ari. See copyright.txt. */
-/*
- * Dialog for setting SpinSpider options
- */
-
-package jspin;
-import javax.swing.*;
-import javax.swing.border.*;
-import java.awt.event.*;
-
-class SpiderOptions extends JDialog implements ActionListener {
- private JCheckBox debugBox;
- private JRadioButton noTrail, emphTrail, onlyTrail, small, large, bold, color, automata;
- private ButtonGroup trailGroup, dotGroup, styleGroup;
- private JButton runButton, cancelButton;
- private JLabel processLabel, variablesLabel, dotLabel, formatLabel, styleLabel;
- private JComboBox formatBox, processBox;
- private JTextArea variablesText;
- private JPanel OKPanel, formatPanel, leftPanel, neverPanel, processPanel,
- variablesPanel, trailPanel, sizePanel, boxPanel, stylePanel;
- private Border border;
-
- private boolean ok;
- private SpiderFile sp;
-
- SpiderOptions(JFrame parent, SpiderFile sp, java.awt.Font font) {
- super(parent, true);
- this.sp = sp;
-
- border = BorderFactory.createEtchedBorder();
-
- formatLabel = new JLabel(Config.Format, JLabel.CENTER);
- formatBox = new JComboBox();
- formatBox.setEditable(false);
- formatBox.addItem(Config.DOT);
- formatBox.addItem(Config.PNG);
- formatBox.addItem(Config.FSM);
- formatBox.addItem(Config.PS);
- formatBox.setSelectedItem(sp.getStringProperty("FORMAT"));
-
- int trailCode = sp.getIntProperty("TRAIL_CODE");
- noTrail = new JRadioButton(Config.NoTrail, trailCode == 0);
- noTrail.setMnemonic(Config.NoTrailMN);
- emphTrail = new JRadioButton(Config.EmphTrail, trailCode == 1);
- emphTrail.setMnemonic(Config.EmphTrailMN);
- onlyTrail = new JRadioButton(Config.OnlyTrail, trailCode == 2);
- onlyTrail.setMnemonic(Config.OnlyTrailMN);
- automata = new JRadioButton(Config.Automata, trailCode == 3);
- automata.setMnemonic(Config.AutomataMN);
- trailGroup = new ButtonGroup();
- trailGroup.add(noTrail);
- trailGroup.add(emphTrail);
- trailGroup.add(onlyTrail);
- trailGroup.add(automata);
-
- dotLabel = new JLabel(Config.DotSize, JLabel.CENTER);
- int dotSize = sp.getIntProperty("DOT_SIZE");
- small = new JRadioButton(Config.DotSmall, dotSize == 0);
- small.setMnemonic(Config.DotSmallMN);
- large = new JRadioButton(Config.DotLarge, dotSize == 1);
- large.setMnemonic(Config.DotLargeMN);
- dotGroup = new ButtonGroup();
- dotGroup.add(small);
- dotGroup.add(large);
-
- styleLabel = new JLabel(Config.TrailStyle, JLabel.CENTER);
- int trailStyle = sp.getIntProperty("TRAIL_STYLE");
- color = new JRadioButton(Config.TrailColor, trailStyle == 0);
- color.setMnemonic(Config.TrailColorMN);
- bold = new JRadioButton(Config.TrailBold, trailStyle == 1);
- bold.setMnemonic(Config.TrailBoldMN);
- styleGroup = new ButtonGroup();
- styleGroup.add(color);
- styleGroup.add(bold);
-
- debugBox = new JCheckBox(Config.Debug,
- sp.getBooleanProperty("SPIDER_DEBUG"));
- debugBox.setMnemonic(Config.DebugMN);
-
- processLabel = new JLabel(Config.Processes, JLabel.CENTER);
- processBox = new JComboBox();
- processBox.setEditable(false);
- for (int i = 0; i < Config.MAX_PROCESS; i++)
- processBox.addItem(" " + (i+1));
- processBox.setSelectedIndex(sp.getIntProperty("PROCESSES")-1);
-
- variablesLabel = new JLabel(Config.Variables, JLabel.CENTER);
- variablesText = new JTextArea(sp.getStringProperty("VARIABLES"));
- variablesText.setFont(font);
-
- runButton = new JButton(Config.Run);
- cancelButton = new JButton(Config.Cancel);
- runButton.setMnemonic(Config.RunMN);
- runButton.addActionListener(this);
- cancelButton.addActionListener(this);
-
- trailPanel = new JPanel();
- trailPanel.setLayout(new java.awt.GridLayout(4,1));
- trailPanel.setBorder(border);
- trailPanel.add(noTrail);
- trailPanel.add(emphTrail);
- trailPanel.add(onlyTrail);
- trailPanel.add(automata);
-
- sizePanel = new JPanel();
- sizePanel.setLayout(new java.awt.GridLayout(3,1));
- sizePanel.setBorder(border);
- sizePanel.add(dotLabel);
- sizePanel.add(small);
- sizePanel.add(large);
-
- stylePanel = new JPanel();
- stylePanel.setLayout(new java.awt.GridLayout(3,1));
- stylePanel.setBorder(border);
- stylePanel.add(styleLabel);
- stylePanel.add(color);
- stylePanel.add(bold);
-
- formatPanel = new JPanel();
- formatPanel.setLayout(new java.awt.GridLayout(2,1));
- formatPanel.setBorder(border);
- formatPanel.add(formatLabel);
- formatPanel.add(formatBox);
-
- leftPanel = new JPanel();
- leftPanel.setLayout(new java.awt.BorderLayout());
- leftPanel.setBorder(border);
- leftPanel.add(formatPanel, java.awt.BorderLayout.NORTH);
- leftPanel.add(sizePanel, java.awt.BorderLayout.CENTER);
- leftPanel.add(stylePanel, java.awt.BorderLayout.SOUTH);
- leftPanel.setPreferredSize(new java.awt.Dimension(100,0));
-
- processPanel = new JPanel();
- processPanel.setLayout(new java.awt.GridLayout(2,1));
- processPanel.setBorder(border);
- processPanel.add(processLabel);
- processPanel.add(processBox);
-
- boxPanel = new JPanel();
- boxPanel.setLayout(new java.awt.BorderLayout());
- boxPanel.setBorder(border);
- boxPanel.add(debugBox, java.awt.BorderLayout.CENTER);
-
- neverPanel = new JPanel();
- neverPanel.setLayout(new java.awt.BorderLayout());
- neverPanel.setBorder(border);
- neverPanel.add(trailPanel, java.awt.BorderLayout.CENTER);
- neverPanel.add(processPanel, java.awt.BorderLayout.NORTH);
- neverPanel.add(boxPanel, java.awt.BorderLayout.SOUTH);
-
- variablesPanel = new JPanel();
- variablesPanel.setLayout(new java.awt.BorderLayout());
- variablesPanel.setBorder(border);
- variablesPanel.add(variablesLabel, java.awt.BorderLayout.NORTH);
- variablesPanel.add(variablesText, java.awt.BorderLayout.CENTER);
-
- OKPanel = new JPanel();
- OKPanel.setLayout(new java.awt.GridLayout(1,5));
- OKPanel.setBorder(border);
- OKPanel.add(new JLabel(" "));
- OKPanel.add(runButton);
- OKPanel.add(new JLabel(" "));
- OKPanel.add(cancelButton);
- OKPanel.add(new JLabel(" "));
-
- getRootPane().setDefaultButton(runButton);
- getRootPane().registerKeyboardAction(this,
- KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0),
- JComponent.WHEN_IN_FOCUSED_WINDOW);
-
- getContentPane().setLayout(new java.awt.BorderLayout());
- getContentPane().add(neverPanel, java.awt.BorderLayout.EAST);
- getContentPane().add(variablesPanel, java.awt.BorderLayout.CENTER);
- getContentPane().add(leftPanel, java.awt.BorderLayout.WEST);
- getContentPane().add(OKPanel, java.awt.BorderLayout.SOUTH);
-
- setTitle(Config.SPIDER_TITLE);
- setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
- setSize(400, 300);
- setLocationRelativeTo(null);
- validate();
- }
-
- boolean showDialog() {
- ok = false;
- setVisible(true);
- return ok;
- }
-
- public void actionPerformed(ActionEvent e) {
- if (e.getSource() == runButton) {
- sp.setIntProperty("TRAIL_CODE",
- noTrail.isSelected() ? 0 :
- (emphTrail.isSelected() ? 1 :
- (onlyTrail.isSelected() ? 2 :
- (automata.isSelected() ? 3 : 0))));
- sp.setIntProperty("DOT_SIZE",
- small.isSelected() ? 0 :
- (large.isSelected() ? 1 : 0));
- sp.setIntProperty("TRAIL_STYLE",
- color.isSelected() ? 0 :
- (bold.isSelected() ? 1 : 0));
- sp.setBooleanProperty("SPIDER_DEBUG", debugBox.isSelected());
- sp.setStringProperty("FORMAT", (String) formatBox.getSelectedItem());
- sp.setIntProperty("PROCESSES", Integer.parseInt(
- ((String) processBox.getSelectedItem()).trim()));
- sp.setStringProperty("VARIABLES", variablesText.getText());
- ok = true;
- }
- dispose();
- }
-}
+/* Copyright 2007 by Mordechai (Moti) Ben-Ari. See copyright.txt. */
+/*
+ * Dialog for setting SpinSpider options
+ */
+
+package com.spinroot.jspin;
+
+import javax.swing.*;
+import javax.swing.border.Border;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyEvent;
+
+class SpiderOptions extends JDialog implements ActionListener {
+ private JCheckBox debugBox;
+ private JRadioButton noTrail, emphTrail, onlyTrail, small, large, bold, color, automata;
+ private ButtonGroup trailGroup, dotGroup, styleGroup;
+ private JButton runButton, cancelButton;
+ private JLabel processLabel, variablesLabel, dotLabel, formatLabel, styleLabel;
+ private JComboBox formatBox, processBox;
+ private JTextArea variablesText;
+ private JPanel OKPanel, formatPanel, leftPanel, neverPanel, processPanel,
+ variablesPanel, trailPanel, sizePanel, boxPanel, stylePanel;
+ private Border border;
+
+ private boolean ok;
+ private SpiderFile sp;
+
+ SpiderOptions(JFrame parent, SpiderFile sp, java.awt.Font font) {
+ super(parent, true);
+ this.sp = sp;
+
+ border = BorderFactory.createEtchedBorder();
+
+ formatLabel = new JLabel(Config.Format, JLabel.CENTER);
+ formatBox = new JComboBox();
+ formatBox.setEditable(false);
+ formatBox.addItem(Config.DOT);
+ formatBox.addItem(Config.PNG);
+ formatBox.addItem(Config.FSM);
+ formatBox.addItem(Config.PS);
+ formatBox.setSelectedItem(sp.getStringProperty("FORMAT"));
+
+ int trailCode = sp.getIntProperty("TRAIL_CODE");
+ noTrail = new JRadioButton(Config.NoTrail, trailCode == 0);
+ noTrail.setMnemonic(Config.NoTrailMN);
+ emphTrail = new JRadioButton(Config.EmphTrail, trailCode == 1);
+ emphTrail.setMnemonic(Config.EmphTrailMN);
+ onlyTrail = new JRadioButton(Config.OnlyTrail, trailCode == 2);
+ onlyTrail.setMnemonic(Config.OnlyTrailMN);
+ automata = new JRadioButton(Config.Automata, trailCode == 3);
+ automata.setMnemonic(Config.AutomataMN);
+ trailGroup = new ButtonGroup();
+ trailGroup.add(noTrail);
+ trailGroup.add(emphTrail);
+ trailGroup.add(onlyTrail);
+ trailGroup.add(automata);
+
+ dotLabel = new JLabel(Config.DotSize, JLabel.CENTER);
+ int dotSize = sp.getIntProperty("DOT_SIZE");
+ small = new JRadioButton(Config.DotSmall, dotSize == 0);
+ small.setMnemonic(Config.DotSmallMN);
+ large = new JRadioButton(Config.DotLarge, dotSize == 1);
+ large.setMnemonic(Config.DotLargeMN);
+ dotGroup = new ButtonGroup();
+ dotGroup.add(small);
+ dotGroup.add(large);
+
+ styleLabel = new JLabel(Config.TrailStyle, JLabel.CENTER);
+ int trailStyle = sp.getIntProperty("TRAIL_STYLE");
+ color = new JRadioButton(Config.TrailColor, trailStyle == 0);
+ color.setMnemonic(Config.TrailColorMN);
+ bold = new JRadioButton(Config.TrailBold, trailStyle == 1);
+ bold.setMnemonic(Config.TrailBoldMN);
+ styleGroup = new ButtonGroup();
+ styleGroup.add(color);
+ styleGroup.add(bold);
+
+ debugBox = new JCheckBox(Config.Debug,
+ sp.getBooleanProperty("SPIDER_DEBUG"));
+ debugBox.setMnemonic(Config.DebugMN);
+
+ processLabel = new JLabel(Config.Processes, JLabel.CENTER);
+ processBox = new JComboBox();
+ processBox.setEditable(false);
+ for (int i = 0; i < Config.MAX_PROCESS; i++)
+ processBox.addItem(" " + (i + 1));
+ processBox.setSelectedIndex(sp.getIntProperty("PROCESSES") - 1);
+
+ variablesLabel = new JLabel(Config.Variables, JLabel.CENTER);
+ variablesText = new JTextArea(sp.getStringProperty("VARIABLES"));
+ variablesText.setFont(font);
+
+ runButton = new JButton(Config.Run);
+ cancelButton = new JButton(Config.Cancel);
+ runButton.setMnemonic(Config.RunMN);
+ runButton.addActionListener(this);
+ cancelButton.addActionListener(this);
+
+ trailPanel = new JPanel();
+ trailPanel.setLayout(new java.awt.GridLayout(4, 1));
+ trailPanel.setBorder(border);
+ trailPanel.add(noTrail);
+ trailPanel.add(emphTrail);
+ trailPanel.add(onlyTrail);
+ trailPanel.add(automata);
+
+ sizePanel = new JPanel();
+ sizePanel.setLayout(new java.awt.GridLayout(3, 1));
+ sizePanel.setBorder(border);
+ sizePanel.add(dotLabel);
+ sizePanel.add(small);
+ sizePanel.add(large);
+
+ stylePanel = new JPanel();
+ stylePanel.setLayout(new java.awt.GridLayout(3, 1));
+ stylePanel.setBorder(border);
+ stylePanel.add(styleLabel);
+ stylePanel.add(color);
+ stylePanel.add(bold);
+
+ formatPanel = new JPanel();
+ formatPanel.setLayout(new java.awt.GridLayout(2, 1));
+ formatPanel.setBorder(border);
+ formatPanel.add(formatLabel);
+ formatPanel.add(formatBox);
+
+ leftPanel = new JPanel();
+ leftPanel.setLayout(new java.awt.BorderLayout());
+ leftPanel.setBorder(border);
+ leftPanel.add(formatPanel, java.awt.BorderLayout.NORTH);
+ leftPanel.add(sizePanel, java.awt.BorderLayout.CENTER);
+ leftPanel.add(stylePanel, java.awt.BorderLayout.SOUTH);
+ leftPanel.setPreferredSize(new java.awt.Dimension(100, 0));
+
+ processPanel = new JPanel();
+ processPanel.setLayout(new java.awt.GridLayout(2, 1));
+ processPanel.setBorder(border);
+ processPanel.add(processLabel);
+ processPanel.add(processBox);
+
+ boxPanel = new JPanel();
+ boxPanel.setLayout(new java.awt.BorderLayout());
+ boxPanel.setBorder(border);
+ boxPanel.add(debugBox, java.awt.BorderLayout.CENTER);
+
+ neverPanel = new JPanel();
+ neverPanel.setLayout(new java.awt.BorderLayout());
+ neverPanel.setBorder(border);
+ neverPanel.add(trailPanel, java.awt.BorderLayout.CENTER);
+ neverPanel.add(processPanel, java.awt.BorderLayout.NORTH);
+ neverPanel.add(boxPanel, java.awt.BorderLayout.SOUTH);
+
+ variablesPanel = new JPanel();
+ variablesPanel.setLayout(new java.awt.BorderLayout());
+ variablesPanel.setBorder(border);
+ variablesPanel.add(variablesLabel, java.awt.BorderLayout.NORTH);
+ variablesPanel.add(variablesText, java.awt.BorderLayout.CENTER);
+
+ OKPanel = new JPanel();
+ OKPanel.setLayout(new java.awt.GridLayout(1, 5));
+ OKPanel.setBorder(border);
+ OKPanel.add(new JLabel(" "));
+ OKPanel.add(runButton);
+ OKPanel.add(new JLabel(" "));
+ OKPanel.add(cancelButton);
+ OKPanel.add(new JLabel(" "));
+
+ getRootPane().setDefaultButton(runButton);
+ getRootPane().registerKeyboardAction(this,
+ KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0),
+ JComponent.WHEN_IN_FOCUSED_WINDOW);
+
+ getContentPane().setLayout(new java.awt.BorderLayout());
+ getContentPane().add(neverPanel, java.awt.BorderLayout.EAST);
+ getContentPane().add(variablesPanel, java.awt.BorderLayout.CENTER);
+ getContentPane().add(leftPanel, java.awt.BorderLayout.WEST);
+ getContentPane().add(OKPanel, java.awt.BorderLayout.SOUTH);
+
+ setTitle(Config.SPIDER_TITLE);
+ setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
+ setSize(400, 300);
+ setLocationRelativeTo(null);
+ validate();
+ }
+
+ boolean showDialog() {
+ ok = false;
+ setVisible(true);
+ return ok;
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ if (e.getSource() == runButton) {
+ sp.setIntProperty("TRAIL_CODE",
+ noTrail.isSelected() ? 0 :
+ (emphTrail.isSelected() ? 1 :
+ (onlyTrail.isSelected() ? 2 :
+ (automata.isSelected() ? 3 : 0))));
+ sp.setIntProperty("DOT_SIZE",
+ small.isSelected() ? 0 :
+ (large.isSelected() ? 1 : 0));
+ sp.setIntProperty("TRAIL_STYLE",
+ color.isSelected() ? 0 :
+ (bold.isSelected() ? 1 : 0));
+ sp.setBooleanProperty("SPIDER_DEBUG", debugBox.isSelected());
+ sp.setStringProperty("FORMAT", (String) formatBox.getSelectedItem());
+ sp.setIntProperty("PROCESSES", Integer.parseInt(
+ ((String) processBox.getSelectedItem()).trim()));
+ sp.setStringProperty("VARIABLES", variablesText.getText());
+ ok = true;
+ }
+ dispose();
+ }
+}
diff --git a/jspin/UndoRedo.java b/src/main/java/com/spinroot/jspin/UndoRedo.java
similarity index 87%
rename from jspin/UndoRedo.java
rename to src/main/java/com/spinroot/jspin/UndoRedo.java
index 3d1c47e..0cfdb20 100644
--- a/jspin/UndoRedo.java
+++ b/src/main/java/com/spinroot/jspin/UndoRedo.java
@@ -1,83 +1,88 @@
-/* Copyright 2003-4 by Mordechai (Moti) Ben-Ari. See copyright.txt. */
-/*
- Class for undo/redo.
- Extracted from TextComponentDemo.java in java.sun.com.
-*/
-package jspin;
-import javax.swing.*;
-import javax.swing.undo.*;
-import javax.swing.event.*;
-import java.awt.event.*;
-class UndoRedo {
- UndoAction undoAction = new UndoAction();
- RedoAction redoAction = new RedoAction();
- UndoManager undo = new UndoManager();
- MyUndoableEditListener myundoable = new MyUndoableEditListener();
-
- class UndoAction extends AbstractAction {
- public UndoAction() {
- super(Config.Undo);
- setEnabled(false);
- }
-
- public void actionPerformed(ActionEvent e) {
- try {
- undo.undo();
- } catch (CannotUndoException ex) {
- System.out.println("Unable to undo: " + ex);
- ex.printStackTrace();
- }
- updateUndoState();
- redoAction.updateRedoState();
- }
-
- protected void updateUndoState() {
- if (undo.canUndo()) {
- setEnabled(true);
- putValue(Action.NAME, undo.getUndoPresentationName());
- } else {
- setEnabled(false);
- putValue(Action.NAME, "Undo");
- }
- }
- }
-
- class RedoAction extends AbstractAction {
- public RedoAction() {
- super(Config.Redo);
- setEnabled(false);
- }
-
- public void actionPerformed(ActionEvent e) {
- try {
- undo.redo();
- } catch (CannotRedoException ex) {
- System.out.println("Unable to redo: " + ex);
- ex.printStackTrace();
- }
- updateRedoState();
- undoAction.updateUndoState();
- }
-
- protected void updateRedoState() {
- if (undo.canRedo()) {
- setEnabled(true);
- putValue(Action.NAME, undo.getRedoPresentationName());
- } else {
- setEnabled(false);
- putValue(Action.NAME, "Redo");
- }
- }
- }
-
- protected class MyUndoableEditListener
- implements UndoableEditListener {
- public void undoableEditHappened(UndoableEditEvent e) {
- //Remember the edit and update the menus.
- undo.addEdit(e.getEdit());
- undoAction.updateUndoState();
- redoAction.updateRedoState();
- }
- }
-
-}
+/* Copyright 2003-4 by Mordechai (Moti) Ben-Ari. See copyright.txt. */
+/*
+ Class for undo/redo.
+ Extracted from TextComponentDemo.java in java.sun.com.
+*/
+package com.spinroot.jspin;
+
+import javax.swing.*;
+import javax.swing.event.UndoableEditEvent;
+import javax.swing.event.UndoableEditListener;
+import javax.swing.undo.CannotRedoException;
+import javax.swing.undo.CannotUndoException;
+import javax.swing.undo.UndoManager;
+import java.awt.event.ActionEvent;
+
+class UndoRedo {
+ UndoAction undoAction = new UndoAction();
+ RedoAction redoAction = new RedoAction();
+ UndoManager undo = new UndoManager();
+ MyUndoableEditListener myundoable = new MyUndoableEditListener();
+
+ class UndoAction extends AbstractAction {
+ public UndoAction() {
+ super(Config.Undo);
+ setEnabled(false);
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ try {
+ undo.undo();
+ } catch (CannotUndoException ex) {
+ System.out.println("Unable to undo: " + ex);
+ ex.printStackTrace();
+ }
+ updateUndoState();
+ redoAction.updateRedoState();
+ }
+
+ protected void updateUndoState() {
+ if (undo.canUndo()) {
+ setEnabled(true);
+ putValue(Action.NAME, undo.getUndoPresentationName());
+ } else {
+ setEnabled(false);
+ putValue(Action.NAME, "Undo");
+ }
+ }
+ }
+
+ class RedoAction extends AbstractAction {
+ public RedoAction() {
+ super(Config.Redo);
+ setEnabled(false);
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ try {
+ undo.redo();
+ } catch (CannotRedoException ex) {
+ System.out.println("Unable to redo: " + ex);
+ ex.printStackTrace();
+ }
+ updateRedoState();
+ undoAction.updateUndoState();
+ }
+
+ protected void updateRedoState() {
+ if (undo.canRedo()) {
+ setEnabled(true);
+ putValue(Action.NAME, undo.getRedoPresentationName());
+ } else {
+ setEnabled(false);
+ putValue(Action.NAME, "Redo");
+ }
+ }
+ }
+
+ protected class MyUndoableEditListener
+ implements UndoableEditListener {
+ public void undoableEditHappened(UndoableEditEvent e) {
+ //Remember the edit and update the menus.
+ undo.addEdit(e.getEdit());
+ undoAction.updateUndoState();
+ redoAction.updateRedoState();
+ }
+ }
+
+}
diff --git a/jspin/jSpin.java b/src/main/java/com/spinroot/jspin/jSpin.java
similarity index 66%
rename from jspin/jSpin.java
rename to src/main/java/com/spinroot/jspin/jSpin.java
index 7e9f2a2..05943c9 100644
--- a/jspin/jSpin.java
+++ b/src/main/java/com/spinroot/jspin/jSpin.java
@@ -1,836 +1,818 @@
-/*
- jSpin - Development environment for Spin
- Copyright 2003-10 by Mordechai (Moti) Ben-Ari.
-
-This program 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.
-This program 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 this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.
-*/
-
-package jspin;
-import java.awt.event.*;
-import javax.swing.*;
-import javax.swing.border.*;
-
-public class jSpin extends JFrame implements ActionListener {
- // Contained objects. Create only after initializing configuration.
- private Editor editor;
- private RunSpin runSpin;
- private filterSpin.Filter filter;
- private UndoRedo undoredo;
- private SpiderFile sp;
- private java.util.Properties spiderProperties;
-
- // User interface components
- private JTextArea editorArea = new JTextArea();
- private JTextArea trailArea = new JTextArea();
- private JTextArea messageArea = new JTextArea();
- private JTextField LTLField = new JTextField();
-
- private JFileChooser PMLfileChooser;
- private JFileChooser PRPfileChooser;
- private JFileChooser OUTfileChooser;
- private java.awt.Font font;
-
- private JScrollPane editorScrollPane = new JScrollPane(editorArea);
- private JScrollPane trailScrollPane = new JScrollPane(trailArea);
- private JScrollPane messageScrollPane = new JScrollPane(messageArea);
- private JSplitPane topSplitPane;
- private JSplitPane mainSplitPane;
-
- private JMenuBar menuBar = new JMenuBar();
-
- private JMenu menuFile = new JMenu();
- private JMenuItem menuItemNew = new JMenuItem(Config.New);
- private JMenuItem menuItemOpen = new JMenuItem(Config.Open);
- private JMenuItem menuItemSave = new JMenuItem(Config.Save);
- private JMenuItem menuItemSaveAs = new JMenuItem(Config.SaveAs);
- private JMenuItem menuItemSwitch = new JMenuItem(Config.Switch);
- private JMenuItem menuItemExit = new JMenuItem(Config.Exit);
-
- private JMenu menuEditor = new JMenu();
- private JMenuItem menuItemCopy = new JMenuItem(Config.Copy);
- private JMenuItem menuItemCut = new JMenuItem(Config.Cut);
- private JMenuItem menuItemPaste = new JMenuItem(Config.Paste);
- private JMenuItem menuItemFind = new JMenuItem(Config.Find);
- private JMenuItem menuItemFindAgain = new JMenuItem(Config.FindAgain);
-
- private JMenu menuSpin = new JMenu();
- private JMenuItem menuItemCheck = new JMenuItem(Config.Check);
- private JMenuItem menuItemRandom = new JMenuItem(Config.Random);
- private JMenuItem menuItemInter = new JMenuItem(Config.Inter);
- private JMenuItem menuItemVerify = new JMenuItem(Config.Verify);
- private JMenuItem menuItemTrail = new JMenuItem(Config.Trail);
- private JMenuItem menuItemStop = new JMenuItem(Config.Stop);
-
- private JMenu menuLTLConvert = new JMenu();
- private JMenuItem menuItemTranslate = new JMenuItem(Config.LTLTranslate);
- private JMenuItem menuItemClear = new JMenuItem(Config.LTLClear);
- private JMenuItem menuItemLoad = new JMenuItem(Config.LTLLoad);
- private JMenuItem menuItemName = new JMenuItem(Config.LTLName);
- private boolean ltlInternal;
-
- private JMenu menuOptions = new JMenu();
- private JMenuItem menuItemOptionsCheck = new JMenuItem(Config.Check);
- private JMenuItem menuItemOptionsCommon = new JMenuItem(Config.Common);
- private JMenuItem menuItemOptionsRandom = new JMenuItem(Config.Random);
- private JMenuItem menuItemOptionsInter = new JMenuItem(Config.Inter);
- private JMenuItem menuItemOptionsVerify = new JMenuItem(Config.Verify);
- private JMenuItem menuItemOptionsC = new JMenuItem(Config.OptionsC);
- private JMenuItem menuItemOptionsPan = new JMenuItem(Config.OptionsPan);
- private JMenuItem menuItemOptionsTrail = new JMenuItem(Config.Trail);
- private JMenuItem menuItemDefault = new JMenuItem(Config.Default);
- private JMenuItem menuItemOptionsSaveInstall = new JMenuItem(Config.SaveInstall);
- private JMenuItem menuItemOptionsSaveCurrent = new JMenuItem(Config.SaveCurrent);
-
- private JMenu menuSettings = new JMenu();
- private JMenuItem menuItemMaxSteps = new JMenuItem(Config.MaxSteps);
- private JMenuItem menuItemMaxDepth = new JMenuItem(Config.MaxDepth);
- private JMenuItem menuItemSeed = new JMenuItem(Config.Seed);
- private JCheckBoxMenuItem menuItemNegate = new JCheckBoxMenuItem(Config.Negate);
- private JCheckBoxMenuItem menuItemFair = new JCheckBoxMenuItem(Config.Fair);
- private JRadioButtonMenuItem menuItemSafety = new JRadioButtonMenuItem(Config.Safety, false);
- private JRadioButtonMenuItem menuItemAcceptance = new JRadioButtonMenuItem(Config.Acceptance, false);
- private JRadioButtonMenuItem menuItemNonProgress = new JRadioButtonMenuItem(Config.NonProgress, false);
- private ButtonGroup buttonGroup = new ButtonGroup();
-
- private JMenu menuOutput = new JMenu();
- private JMenuItem menuItemMax = new JMenuItem(Config.Max);
- private JMenuItem menuItemVarWidth = new JMenuItem(Config.VarWidth);
- private JMenuItem menuItemStWidth = new JMenuItem(Config.StWidth);
- private JMenuItem menuItemExcludedV = new JMenuItem(Config.ExcludedV);
- private JMenuItem menuItemExcludedS = new JMenuItem(Config.ExcludedS);
- private JCheckBoxMenuItem menuItemRaw = new JCheckBoxMenuItem(Config.Raw);
- private JMenuItem menuItemDisplayRaw = new JMenuItem(Config.DisplayRaw);
- private JMenuItem menuItemSaveSpin = new JMenuItem(Config.SaveSpin);
-
- private JMenu menuSpider = new JMenu();
- private JMenuItem menuItemSpider = new JMenuItem(Config.Spider);
- private JMenuItem menuItemSpiderDisplay = new JMenuItem(Config.SpiderDisplay);
-
- private JMenu menuHelp = new JMenu();
- private JMenuItem menuItemHelp = new JMenuItem(Config.Help);
- private JMenuItem menuItemAbout = new JMenuItem(Config.About);
-
- private JToolBar toolBar = new JToolBar();
-
- private JButton toolOpen = new JButton(Config.Open);
- private JButton toolCheck = new JButton(Config.Check);
- private JButton toolRandom = new JButton(Config.Random);
- private JButton toolInter = new JButton(Config.Inter);
- private JButton toolVerify = new JButton(Config.Verify);
- private JButton toolTrail = new JButton(Config.Trail);
- private JButton toolStop = new JButton(Config.Stop);
-
- private JButton toolSpider = new JButton(Config.Spider);
-
- private JLabel toolLabelFair = new JLabel(Config.Fair);
- private JCheckBox toolCheckFair = new JCheckBox();
- private JComboBox toolMode = new JComboBox();
- private JButton toolMax = new JButton(Config.Max);
- private boolean maxedDivider;
- private int currentDivider;
-
- private JLabel LTLLabel = new JLabel(Config.LTLFormula);
- private JButton LTLTranslateButton = new JButton(Config.LTLTranslate);
- private JButton LTLClearButton = new JButton(Config.LTLClear);
- private JButton LTLLoadButton = new JButton(Config.LTLLoad);
- private JButton LTLNameButton = new JButton(Config.LTLName);
-
- public void actionPerformed(ActionEvent e) {
- // File menu actions
- if (e.getSource() == menuItemNew) {
- editor.lastFile = editor.file;
- clearAreas();
- editor.newFile();
- }
- else if ((e.getSource() == menuItemOpen) || (e.getSource() == toolOpen)) {
- if(PMLfileChooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
- editor.lastFile = editor.file;
- clearAreas();
- editor.openFile(PMLfileChooser.getSelectedFile(), true);
- }
- }
- else if (e.getSource() == menuItemSave) {
- if (editor.file != null)
- editor.saveFile(null);
- else {
- if(PMLfileChooser.showSaveDialog(this) == JFileChooser.APPROVE_OPTION) {
- editor.saveFile(PMLfileChooser.getSelectedFile());
- }
- }
- }
- else if (e.getSource() == menuItemSaveAs) {
- if(PMLfileChooser.showSaveDialog(this) == JFileChooser.APPROVE_OPTION)
- editor.lastFile = editor.file;
- editor.saveFile(PMLfileChooser.getSelectedFile());
- }
- else if (e.getSource() == menuItemSwitch) {
- if (editor.lastFile != null) {
- java.io.File temp = editor.lastFile;
- if (editor.file != null)
- editor.saveFile(null);
- else {
- if(PMLfileChooser.showSaveDialog(this) == JFileChooser.APPROVE_OPTION) {
- editor.saveFile(PMLfileChooser.getSelectedFile());
- }
- }
- editor.lastFile = editor.file;
- editor.openFile(temp, true);
- }
- }
- else if (e.getSource() == menuItemExit) {
- runSpin.killSpin();
- System.exit(0);
- }
-
- // Editor menu actions
- else if (e.getSource() == menuItemCut)
- editor.cut();
- else if (e.getSource() == menuItemCopy)
- editor.copy();
- else if (e.getSource() == menuItemPaste)
- editor.paste();
- else if (e.getSource() == menuItemFind)
- editor.find();
- else if (e.getSource() == menuItemFindAgain)
- editor.findAgain();
-
- // Spin menu actions
- else if ((e.getSource() == menuItemCheck) || (e.getSource() == toolCheck)) {
- trailArea.setText("");
- runSpin.runAndWait(trailArea, false,
- Config.getStringProperty("SPIN"),
- Config.getStringProperty("CHECK_OPTIONS") + " " +
- editor.fileName);
- }
- else if ((e.getSource() == menuItemRandom) || (e.getSource() == toolRandom)) {
- int seed = Config.getIntProperty("SEED");
- trailArea.setText("");
- runSpin.run(trailArea, true,
- Config.getStringProperty("SPIN"),
- Config.getStringProperty("COMMON_OPTIONS") + " " +
- Config.getStringProperty("RANDOM_OPTIONS") + " " +
- (seed != 0 ? ("-n" + seed + " ") : "") +
- " -u" + Config.getStringProperty("MAX_STEPS") + " " +
- editor.fileName);
- isSpinRunning();
- }
- else if ((e.getSource() == menuItemInter) || (e.getSource() == toolInter)) {
- trailArea.setText("");
- runSpin.run(trailArea, true,
- Config.getStringProperty("SPIN"),
- Config.getStringProperty("COMMON_OPTIONS") + " " +
- Config.getStringProperty("INTERACTIVE_OPTIONS") + " " +
- editor.fileName);
- isSpinRunning();
- }
- else if ((e.getSource() == menuItemVerify) || (e.getSource() == toolVerify)) {
- trailArea.setText("");
- if (!ltlInternal && !LTLField.getText().equals("") &&
- !(new java.io.File(editor.LTLFileName).exists()))
- append(messageArea, "WARNING: Correctness property has not been translated\n");
- runSpin.runAndWait(trailArea, false,
- Config.getStringProperty("SPIN"),
- Config.getStringProperty("VERIFY_OPTIONS") + " " +
- ((ltlInternal || LTLField.getText().equals("")) ? "" : "-N " + " " +
- editor.LTLFileName + " ") + editor.fileName);
- if (trailArea.getText().indexOf("Error: syntax error") != -1)
- return;
- String mode = Config.getStringProperty("VERIFY_MODE");
- String CModeOptions = mode.equals(Config.Safety) ? " -DSAFETY " :
- (mode.equals(Config.NonProgress) ? " -DNP " : "");
- runSpin.runAndWait(messageArea, false,
- Config.getStringProperty("C_COMPILER"),
- CModeOptions + " " +
- Config.getStringProperty("C_COMPILER_OPTIONS") );
- String panModeOptions = mode.equals(Config.Acceptance) ? " -a " :
- (mode.equals(Config.NonProgress) ? " -l " : "");
- if (!mode.equals(Config.Safety) && Config.getBooleanProperty("FAIRNESS"))
- panModeOptions = " -f " + panModeOptions;
- runSpin.run(trailArea, true,
- editor.root + java.io.File.separator +
- Config.getStringProperty("PAN"),
- panModeOptions +
- " -m" + Config.getStringProperty("MAX_DEPTH") + " " +
- ((!ltlInternal || LTLField.getText().equals("")) ?
- "" : "-N " + LTLField.getText() + " ") +
- Config.getStringProperty("PAN_OPTIONS") );
- isSpinRunning();
- }
- else if ((e.getSource() == menuItemTrail) || (e.getSource() == toolTrail)) {
- runSpin.run(trailArea, true,
- Config.getStringProperty("SPIN"),
- Config.getStringProperty("COMMON_OPTIONS") + " " +
- Config.getStringProperty("TRAIL_OPTIONS") +
- " -u" + Config.getStringProperty("MAX_STEPS") + " " +
- editor.fileName);
- isSpinRunning();
- }
- else if ((e.getSource() == menuItemStop) || (e.getSource() == toolStop))
- runSpin.killSpin();
-
- // Options menu actions
- else if (e.getSource() == menuItemOptionsCommon)
- new Options();
- else if ((e.getSource() == menuItemOptionsCheck) ||
- (e.getSource() == menuItemOptionsRandom) ||
- (e.getSource() == menuItemOptionsInter) ||
- (e.getSource() == menuItemOptionsVerify) ||
- (e.getSource() == menuItemOptionsC) ||
- (e.getSource() == menuItemOptionsPan) ||
- (e.getSource() == menuItemOptionsTrail))
- changeOption(e.getActionCommand().toUpperCase().replace(' ','_') + "_OPTIONS", false);
- else if (e.getSource() == menuItemDefault)
- Config.setDefaultProperties();
-
- else if ((e.getSource() == menuItemOptionsSaveInstall) ||
- (e.getSource() == menuItemOptionsSaveCurrent)) {
- // Save current directory and divider locations
- Config.setStringProperty("SOURCE_DIRECTORY",
- PMLfileChooser.getCurrentDirectory().getAbsolutePath());
- Config.setIntProperty("LR_DIVIDER", topSplitPane.getDividerLocation());
- Config.setIntProperty("TB_DIVIDER", mainSplitPane.getDividerLocation());
- boolean currentConfig = e.getSource() == menuItemOptionsSaveCurrent;
- Config.saveFile(currentConfig);
- append(messageArea,
- "Saved jSpin configuration file config.cfg in " +
- (currentConfig ? "current" : "installation") + " directory\n");
- }
-
- // Settings menu actions
- else if (e.getSource() == menuItemMaxSteps)
- changeOption("MAX_STEPS", true);
- else if (e.getSource() == menuItemMaxDepth)
- changeOption("MAX_DEPTH", true);
- else if (e.getSource() == menuItemSeed)
- changeOption("SEED", true);
- else if (e.getSource() == menuItemNegate) {
- boolean negate = !Config.getBooleanProperty("NEGATE_LTL");
- Config.setBooleanProperty("NEGATE_LTL", negate);
- menuItemNegate.setSelected(negate);
- }
- else if ((e.getSource() == menuItemFair) || (e.getSource() == toolCheckFair)) {
- boolean fair = !Config.getBooleanProperty("FAIRNESS");
- Config.setBooleanProperty("FAIRNESS", fair);
- menuItemFair.setSelected(fair);
- toolCheckFair.setSelected(fair);
- }
- else if ((e.getSource() == menuItemSafety) ||
- (e.getSource() == menuItemAcceptance) ||
- (e.getSource() == menuItemNonProgress))
- changeMode(e.getActionCommand());
- else if (e.getSource() == toolMode)
- changeMode(((String)((JComboBox)e.getSource()).getSelectedItem()));
-
- // Output menu actions
- else if ((e.getSource() == menuItemMax) ||
- (e.getSource() == toolMax)) {
- if (maxedDivider)
- topSplitPane.setDividerLocation(currentDivider);
- else {
- currentDivider = topSplitPane.getDividerLocation();
- topSplitPane.setDividerLocation(Config.getIntProperty("MIN_DIVIDER"));
- }
- maxedDivider = ! maxedDivider;
- }
- else if (e.getSource() == menuItemExcludedV)
- new Excluded(editor, font, filter, true);
- else if (e.getSource() == menuItemExcludedS)
- new Excluded(editor, font, filter, false);
- else if (e.getSource() == menuItemStWidth)
- changeOption("STATEMENT_WIDTH", true);
- else if (e.getSource() == menuItemVarWidth)
- changeOption("VARIABLE_WIDTH", true);
- else if (e.getSource() == menuItemSaveSpin) {
- java.io.File outFile = new java.io.File(editor.OUTFileName);
- OUTfileChooser.setSelectedFile(outFile);
- if(OUTfileChooser.showSaveDialog(this) == JFileChooser.APPROVE_OPTION)
- editor.writeFile(OUTfileChooser.getSelectedFile(), trailArea);
- }
- else if (e.getSource() == menuItemRaw) {
- boolean raw = !Config.getBooleanProperty("RAW");
- Config.setBooleanProperty("RAW", raw);
- menuItemRaw.setSelected(raw);
- }
- else if (e.getSource() == menuItemDisplayRaw)
- displayFile(editor.root + java.io.File.separator + editor.fileRoot + ".raw");
-
- // Spider menu actions
- else if ((e.getSource() == menuItemSpider) || (e.getSource() == toolSpider)) {
- if (editor.file == null) {
- jSpin.append(messageArea, Config.OPEN_FILE);
- return;
- }
- // Read Spider properties from the file for this program
- sp = new SpiderFile(spiderProperties,
- editor.root + java.io.File.separator + editor.fileRoot);
- sp.init();
- if (new SpiderOptions(this, sp, font).showDialog()) {
- sp.saveFile();
- new Thread() { // Run in thread to display progress
- public void run() {
- spinSpider.SpinSpider spd =
- new spinSpider.SpinSpider(
- editor.root + java.io.File.separator + editor.fileRoot,
- editor.extension,
- sp.getStringProperty("FORMAT"),
- sp.getIntProperty("PROCESSES"),
- stringToArray(sp.getStringProperty("VARIABLES")),
- sp.getBooleanProperty("SPIDER_DEBUG"),
- sp.getIntProperty("TRAIL_CODE"),
- sp.getIntProperty("DOT_SIZE"),
- sp.getIntProperty("TRAIL_STYLE"),
- messageArea,
- Config.getProperties());
- if (!spd.runSpider()) return;
- // If PNG format, display in a frame
- if (sp.getStringProperty("FORMAT").equals(Config.PNG)) {
- // Draw automata if requested
- if (sp.getIntProperty("TRAIL_CODE") == 3)
- new spinSpider.DrawAutomata(spd).drawAutomata();
- new DisplayImage(editor.root + java.io.File.separator + editor.fileRoot +
- spinSpider.Config.names[sp.getIntProperty("TRAIL_CODE")] + ".png");
- }
- }
- }.start();
- }
- }
- else if (e.getSource() == menuItemSpiderDisplay)
- displayFile(editor.root + java.io.File.separator + editor.fileRoot + ".dbg");
-
- // Help menu actions
- else if (e.getSource() == menuItemHelp)
- displayFile(Config.helpFileName);
- else if (e.getSource() == menuItemAbout)
- displayFile(Config.aboutFileName);
-
- // LTL actions
- else if ((e.getSource() == LTLTranslateButton) || (e.getSource() == menuItemTranslate)) {
- editor.modifiedLTL();
- if (LTLField.getText().equals(""))
- return;
- ltlInternal = false;
- String quote = Config.getBooleanProperty("SINGLE_QUOTE") ? "'" : "\"";
- String negate = Config.getBooleanProperty("NEGATE_LTL") ? "!" : "";
- runSpin.runAndWait(trailArea, false,
- Config.getStringProperty("SPIN"),
- Config.getStringProperty("TRANSLATE_OPTIONS") + " " +
- quote + negate + "(" + LTLField.getText() + ")" + quote );
- editor.writeFile(new java.io.File(editor.LTLFileName), trailArea);
- }
- else if ((e.getSource() == LTLClearButton) || (e.getSource() == menuItemClear)) {
- LTLField.setText("");
- menuBar.revalidate();
- }
- else if ((e.getSource() == LTLLoadButton) || (e.getSource() == menuItemLoad)) {
- PRPfileChooser.setCurrentDirectory(
- PMLfileChooser.getCurrentDirectory());
- if(PRPfileChooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
- editor.openFile(PRPfileChooser.getSelectedFile(), false);
- }
- }
- else if ((e.getSource() == LTLNameButton) || (e.getSource() == menuItemName)) {
- ltlInternal = true;
- }
- if (editor != null) editor.focus(false);
- }
-
- // Display the contents of a file in the trail area
- private void displayFile(String fn) {
- trailArea.setText(editor.readFile(new java.io.File(fn)));
- trailArea.setCaretPosition(0);
- }
-
- // Convert String to array of Strings
- private static String[] stringToArray(String s) {
- java.util.StringTokenizer st = new java.util.StringTokenizer(s);
- int count = st.countTokens();
- String[] sa = new String[count];
- for (int i = 0; i < count; i++)
- sa[i] = st.nextToken();
- return sa;
- }
-
- // Append and move caret to end
- public static void append(JTextArea area, String s) {
- if (s != null) area.append(s);
- int last = area.getText().length();
- try {
- area.scrollRectToVisible(area.modelToView(last));
- area.setCaretPosition(last);
- }
- catch (javax.swing.text.BadLocationException e) {
- System.err.println("Error setting caret position when writing\n" + s + "\n");
- }
- }
-
- // Clear all areas before opening file or creating new file
- private void clearAreas() {
- messageArea.setText("");
- trailArea.setText("");
- LTLField.setText("");
- }
-
- // Change verification mode:
- // radio buttons in menu, combo box in toolbar and properties
- private void changeMode(String mode) {
- toolMode.setSelectedItem(mode);
- if (mode.equals(Config.Safety))
- menuItemSafety.setSelected(true);
- else if (mode.equals(Config.Acceptance))
- menuItemAcceptance.setSelected(true);
- else if (mode.equals(Config.NonProgress))
- menuItemNonProgress.setSelected(true);
- Config.setStringProperty("VERIFY_MODE", mode);
- }
-
- // Display an option pane to edit an option string
- private void changeOption(String property, boolean number) {
- String s = Config.getStringProperty(property);
- String answer = JOptionPane.showInputDialog(property, s);
- if (answer == null) return;
- if (!number || (number && checkInt(answer)))
- Config.setStringProperty(property, answer);
- else
- JOptionPane.showMessageDialog(null,
- answer + " is not an integer", "Format error",
- JOptionPane.ERROR_MESSAGE);
- }
-
- // Some option panes need to be positive integers
- private boolean checkInt(String property) {
- try {
- Integer.parseInt(property);
- return true;
- }
- catch (NumberFormatException e) {
- return false;
- }
- }
-
- // Create a thread to check if Spin is running
- // Enables user interface to continue running and press Stop
- void isSpinRunning() {
- Thread th = new Thread () {
- public void run() {
- while (runSpin.isRunning()) {
- try {
- Thread.sleep(Config.getIntProperty("POLLING_DELAY"));
- } catch (InterruptedException e) {}
- }
- append(messageArea, "done!\n");
- }
- };
- th.start();
- }
-
- // Initialize menus
- private void initMenuItem(
- JMenu menu, JMenuItem item, int mnemonic, String accelerator) {
- menu.add(item);
- item.addActionListener(this);
- item.setMnemonic(mnemonic);
- if (accelerator != null)
- item.setAccelerator(KeyStroke.getKeyStroke(accelerator));
- }
-
- private void initMenus() {
- menuBar.setBorder(new LineBorder(java.awt.Color.BLUE));
-
- menuBar.add(menuFile);
- menuFile.setText(Config.File);
- menuFile.setMnemonic(Config.FileMN);
- initMenuItem(menuFile, menuItemNew, Config.NewMN, Config.NewAC);
- initMenuItem(menuFile, menuItemOpen, Config.OpenMN, Config.OpenAC);
- initMenuItem(menuFile, menuItemSave, Config.SaveMN, Config.SaveAC);
- initMenuItem(menuFile, menuItemSaveAs, Config.SaveAsMN, Config.SaveAsAC);
- menuFile.addSeparator();
- initMenuItem(menuFile, menuItemSwitch, Config.SwitchMN, Config.SwitchAC);
- menuFile.addSeparator();
- initMenuItem(menuFile, menuItemExit, Config.ExitMN, Config.ExitAC);
-
- undoredo = new UndoRedo();
- menuBar.add(menuEditor);
- menuEditor.setText(Config.Editor);
- menuEditor.setMnemonic(Config.EditorMN);
- JMenuItem menuItemUndo = menuEditor.add(undoredo.undoAction);
- JMenuItem menuItemRedo = menuEditor.add(undoredo.redoAction);
- initMenuItem(menuEditor, menuItemUndo, Config.UndoMN, Config.UndoAC);
- initMenuItem(menuEditor, menuItemRedo, Config.RedoMN, Config.RedoAC);
- menuEditor.addSeparator();
- initMenuItem(menuEditor, menuItemCopy, Config.CopyMN, Config.CopyAC);
- initMenuItem(menuEditor, menuItemCut, Config.CutMN, Config.CutAC);
- initMenuItem(menuEditor, menuItemPaste, Config.PasteMN, Config.PasteAC);
- menuEditor.addSeparator();
- initMenuItem(menuEditor, menuItemFind, Config.FindMN, Config.FindAC);
- initMenuItem(menuEditor, menuItemFindAgain, Config.FindAgainMN, Config.FindAgainAC);
-
- menuBar.add(menuSpin);
- menuSpin.setText(Config.Spin);
- menuSpin.setMnemonic(Config.SpinMN);
- initMenuItem(menuSpin, menuItemCheck, Config.CheckMN, Config.CheckAC);
- menuSpin.addSeparator();
- initMenuItem(menuSpin, menuItemRandom, Config.RandomMN, Config.RandomAC);
- initMenuItem(menuSpin, menuItemInter, Config.InterMN, Config.InterAC);
- initMenuItem(menuSpin, menuItemTrail, Config.TrailMN, Config.TrailAC);
- menuSpin.addSeparator();
- initMenuItem(menuSpin, menuItemVerify, Config.VerifyMN, Config.VerifyAC);
- initMenuItem(menuSpin, menuItemStop, Config.StopMN, Config.StopAC);
-
- menuBar.add(menuLTLConvert);
- menuLTLConvert.setText(Config.LTLConvert);
- menuLTLConvert.setMnemonic(Config.LTLConvertMN);
- initMenuItem(menuLTLConvert, menuItemTranslate, Config.LTLTranslateMN, Config.LTLTranslateAC);
- initMenuItem(menuLTLConvert, menuItemClear, Config.LTLClearMN, Config.LTLClearAC);
- initMenuItem(menuLTLConvert, menuItemLoad, Config.LTLLoadMN, Config.LTLLoadAC);
- if (Config.getIntProperty("VERSION") >= 6) {
- menuLTLConvert.addSeparator();
- initMenuItem(menuLTLConvert, menuItemName, Config.LTLName1MN, Config.LTLNameAC);
- }
-
- menuBar.add(menuOptions);
- menuOptions.setText(Config.Options);
- menuOptions.setMnemonic(Config.OptionsMN);
- initMenuItem(menuOptions, menuItemOptionsCommon, Config.CommonMN, Config.CommonAC);
- menuOptions.addSeparator();
- initMenuItem(menuOptions, menuItemOptionsCheck, Config.CheckMN, Config.CheckAC);
- initMenuItem(menuOptions, menuItemOptionsRandom, Config.RandomMN, Config.OptionsRandomAC);
- initMenuItem(menuOptions, menuItemOptionsInter, Config.InterMN, Config.OptionsInterAC);
- initMenuItem(menuOptions, menuItemOptionsVerify, Config.VerifyMN, Config.VerifyAC);
- initMenuItem(menuOptions, menuItemOptionsC, Config.OptionsCMN, Config.OptionsCAC);
- initMenuItem(menuOptions, menuItemOptionsPan, Config.OptionsPanMN, Config.OptionsPanAC);
- initMenuItem(menuOptions, menuItemOptionsTrail, Config.TrailMN, Config.OptionsTrailAC);
- menuOptions.addSeparator();
- initMenuItem(menuOptions, menuItemDefault, Config.DefaultMN, Config.DefaultAC);
- initMenuItem(menuOptions, menuItemOptionsSaveInstall, Config.SaveInstallMN, Config.OptionsSaveInstallAC);
- initMenuItem(menuOptions, menuItemOptionsSaveCurrent, Config.SaveCurrentMN, Config.OptionsSaveCurrentAC);
-
- menuBar.add(menuSettings);
- menuSettings.setText(Config.Settings);
- menuSettings.setMnemonic(Config.SettingsMN);
- initMenuItem(menuSettings, menuItemMaxSteps, Config.MaxStepsMN, Config.MaxStepsAC);
- initMenuItem(menuSettings, menuItemMaxDepth, Config.MaxDepthMN, Config.MaxDepthAC);
- menuSettings.addSeparator();
- initMenuItem(menuSettings, menuItemSeed, Config.SeedMN, Config.SeedAC);
- menuSettings.addSeparator();
- initMenuItem(menuSettings, menuItemNegate, Config.NegateMN, Config.NegateAC);
- menuItemNegate.setSelected(Config.getBooleanProperty("NEGATE_LTL"));
- menuSettings.addSeparator();
- initMenuItem(menuSettings, menuItemFair, Config.FairMN, Config.FairAC);
- menuItemFair.setSelected(Config.getBooleanProperty("FAIRNESS"));
- menuSettings.addSeparator();
- initMenuItem(menuSettings, menuItemSafety, Config.SafetyMN, Config.SafetyAC);
- initMenuItem(menuSettings, menuItemAcceptance, Config.AcceptanceMN, Config.AcceptanceAC);
- initMenuItem(menuSettings, menuItemNonProgress, Config.NonProgressMN, Config.NonProgressAC);
- buttonGroup.add(menuItemSafety);
- buttonGroup.add(menuItemAcceptance);
- buttonGroup.add(menuItemNonProgress);
-
- menuBar.add(menuOutput);
- menuOutput.setText(Config.Output);
- menuOutput.setMnemonic(Config.OutputMN);
- initMenuItem(menuOutput, menuItemMax, Config.MaxMN, Config.MaxAC);
- menuOutput.addSeparator();
- initMenuItem(menuOutput, menuItemExcludedV, Config.ExcludedVMN, Config.ExcludedVAC);
- initMenuItem(menuOutput, menuItemExcludedS, Config.ExcludedSMN, Config.ExcludedSAC);
- menuOutput.addSeparator();
- initMenuItem(menuOutput, menuItemStWidth, Config.StWidthMN, Config.StWidthAC);
- initMenuItem(menuOutput, menuItemVarWidth, Config.VarWidthMN, Config.VarWidthAC);
- menuOutput.addSeparator();
- initMenuItem(menuOutput, menuItemSaveSpin, Config.SaveSpinMN, Config.SaveSpinAC);
- menuOutput.addSeparator();
- initMenuItem(menuOutput, menuItemRaw, Config.RawMN, Config.RawAC);
- initMenuItem(menuOutput, menuItemDisplayRaw, Config.DisplayRawMN, Config.DisplayRawAC);
- menuItemRaw.setSelected(Config.getBooleanProperty("RAW"));
-
- menuBar.add(menuSpider);
- menuSpider.setText(Config.Spider);
- menuSpider.setMnemonic(Config.SpiderMN);
- initMenuItem(menuSpider, menuItemSpider, Config.SpiderMN, Config.SpiderAC);
- menuSpider.addSeparator();
- initMenuItem(menuSpider, menuItemSpiderDisplay, Config.SpiderDisplayMN, Config.SpiderDisplayAC);
-
- menuBar.add(menuHelp);
- menuHelp.setText(Config.Help);
- menuHelp.setMnemonic(Config.HelpMN);
- initMenuItem(menuHelp, menuItemHelp, Config.HelpMN, Config.HelpAC);
- initMenuItem(menuHelp, menuItemAbout, Config.AboutMN, Config.AboutAC);
-
- menuBar.add(new JLabel(" "));
- menuBar.add(new JSeparator(SwingConstants.VERTICAL));
- menuBar.add(LTLLabel);
- LTLField.setColumns(Config.LTL_COLUMNS);
- LTLField.setPreferredSize(new java.awt.Dimension(250,30));
- menuBar.add(LTLField);
- }
-
- private void initToolButton(JButton item, int mnemonic) {
- item.setMaximumSize(new java.awt.Dimension(75,40));
- toolBar.add(item);
- if (mnemonic != -1) item.setMnemonic(mnemonic);
- item.addActionListener(this);
- }
-
- // Initialize toolbar
- private void initToolBar() {
- toolBar.setLayout(new BoxLayout(toolBar, BoxLayout.X_AXIS));
- toolBar.setFloatable(false);
- toolBar.setBorder(new LineBorder(java.awt.Color.BLUE));
-
- toolBar.add(toolOpen);
- initToolButton(toolOpen, -1);
- toolBar.addSeparator();
- initToolButton(toolCheck, Config.CheckMN);
- initToolButton(toolRandom, Config.RandomMN);
- initToolButton(toolInter, Config.InterMN);
- initToolButton(toolTrail, Config.TrailMN);
- toolBar.addSeparator();
-
- toolBar.add(toolLabelFair);
- toolBar.add(toolCheckFair);
- toolCheckFair.setSelected(Config.getBooleanProperty("FAIRNESS"));
-// toolCheckFair.setMnemonic(Config.FairMN);
-// toolLabelFair.setDisplayedMnemonic(Config.FairMN);
- toolCheckFair.addActionListener(this);
- toolMode.setMaximumSize(new java.awt.Dimension(110,50));
- toolMode.setEditable(false);
- toolMode.addItem(Config.Safety);
- toolMode.addItem(Config.Acceptance);
- toolMode.addItem(Config.NonProgress);
- toolMode.addActionListener(this);
- toolBar.add(toolMode);
- toolBar.addSeparator();
-
- initToolButton(toolVerify, Config.VerifyMN);
- initToolButton(toolStop, Config.StopMN);
- toolBar.addSeparator();
-
- if (Config.getIntProperty("VERSION") >= 6) {
- initToolButton(LTLTranslateButton, Config.LTLTranslateMN);
- initToolButton(LTLLoadButton, Config.LTLLoadMN);
- initToolButton(LTLNameButton, Config.LTLNameMN);
- } else {
- initToolButton(LTLTranslateButton, Config.LTLTranslateMN);
- initToolButton(LTLClearButton, Config.LTLClearMN);
- initToolButton(LTLLoadButton, Config.LTLLoadMN);
- }
-
- toolBar.addSeparator();
- initToolButton(toolSpider, -1);
- toolBar.addSeparator();
- initToolButton(toolMax, Config.MaxMN);
- }
-
- private JFileChooser newChooser(String title, String e1, String e2, String e3) {
- JFileChooser fileChooser = new JFileChooser(Config.getStringProperty("SOURCE_DIRECTORY"));
- fileChooser.setFileFilter(new JSpinFileFilter(title, e1, e2, e3));
- return fileChooser;
- }
-
- // Initialization, optionally with initial source file
- private void init(String file) {
- Config.init();
- spiderProperties = new java.util.Properties();
-
- // For Spin 6 default is internal LTL
- if (Config.getIntProperty("VERSION") >= 6)
- ltlInternal = true;
- else
- ltlInternal = false;
-
- // Set properties of text areas
- font = new java.awt.Font(
- Config.getStringProperty("FONT_FAMILY"),
- Config.getIntProperty("FONT_STYLE"),
- Config.getIntProperty("FONT_SIZE"));
- javax.swing.UIManager.put("TextField.font", font);
- editorArea.setFont(font);
- editorArea.setTabSize(Config.getIntProperty("TAB_SIZE"));
- trailArea.setFont(font);
- trailArea.setLineWrap(Config.getBooleanProperty("WRAP"));
- trailArea.setWrapStyleWord(true);
- messageArea.setFont(font);
- LTLField.setFont(font);
-
- // Create menus and toolbar
- initMenus();
- initToolBar();
- changeMode(Config.getStringProperty("VERIFY_MODE"));
- setJMenuBar(menuBar);
-
- // Set up frame with panes
- topSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, editorScrollPane, trailScrollPane);
- mainSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, topSplitPane, messageScrollPane);
- topSplitPane.setOneTouchExpandable(true);
- mainSplitPane.setOneTouchExpandable(true);
- topSplitPane.setDividerLocation(Config.getIntProperty("LR_DIVIDER"));
- currentDivider = Config.getIntProperty("LR_DIVIDER");
- mainSplitPane.setDividerLocation(Config.getIntProperty("TB_DIVIDER"));
- JPanel contentPane = new JPanel();
- contentPane.setLayout(new java.awt.BorderLayout());
- contentPane.add(toolBar, java.awt.BorderLayout.NORTH);
- contentPane.add(mainSplitPane, java.awt.BorderLayout.CENTER);
- setContentPane(contentPane);
-
- // Create objects
- filter = new filterSpin.Filter();
- editor = new Editor(editorScrollPane, editorArea, messageArea,
- LTLField, undoredo.myundoable, filter);
- runSpin = new RunSpin(editor, messageArea, filter);
- PMLfileChooser = newChooser("Promela source files", ".PML", ".PROM", ".H");
- PRPfileChooser = newChooser("LTL property files", ".PRP", null, null);
- OUTfileChooser = newChooser("Spin display output files", ".OUT", null, null);
-
- // Window listener: kill Spin process if window closed
- addWindowListener(new WindowAdapter() {
- public void windowClosing(WindowEvent e) {
- runSpin.killSpin();
- System.exit(0);
- }
- });
-
- // Configuration JFrame and make visible
- setFont(font);
- setTitle(Config.SOFTWARE_NAME);
- setSize(Config.getIntProperty("WIDTH"), Config.getIntProperty("HEIGHT"));
- setLocationRelativeTo(null);
- setVisible(true);
-
- // Open file if given as command argument
- if (file != "")
- editor.openFile(new java.io.File(file), true);
- else
- editor.newFile();
- }
-
- public static void main(java.lang.String[] args) {
- // Check Java version before executing
- String version = System.getProperty("java.version");
- if (version.compareTo(Config.JAVA_VERSION) < 0) {
- JOptionPane.showMessageDialog(null,
- "Your Java version is " + version + "\n" +
- "jSpin needs least " + Config.JAVA_VERSION, "Version error",
- JOptionPane.ERROR_MESSAGE);
- System.exit(1);
- }
- final String a = (args.length>0) ? args[0] : "";
- javax.swing.SwingUtilities.invokeLater(
- new Runnable() {
- public void run() {
- jSpin jspin = new jSpin();
- jspin.init(a);
- }
- });
- }
-
-}
+/*
+ jSpin - Development environment for Spin
+ Copyright 2003-10 by Mordechai (Moti) Ben-Ari.
+
+This program 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.
+This program 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 this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.
+*/
+
+package com.spinroot.jspin;
+
+import com.spinroot.spinSpider.DrawAutomata;
+import com.spinroot.spinSpider.SpinSpider;
+
+import javax.swing.*;
+import javax.swing.border.LineBorder;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.io.File;
+import java.util.Objects;
+
+public class jSpin extends JFrame implements ActionListener {
+ // Contained objects. Create only after initializing configuration.
+ private Editor editor;
+ private RunSpin runSpin;
+ private com.spinroot.filterSpin.Filter filter;
+ private UndoRedo undoredo;
+ private SpiderFile sp;
+ private java.util.Properties spiderProperties;
+
+ // User interface components
+ private JTextArea editorArea = new JTextArea();
+ private JTextArea trailArea = new JTextArea();
+ private JTextArea messageArea = new JTextArea();
+ private JTextField LTLField = new JTextField();
+
+ private JFileChooser PMLfileChooser;
+ private JFileChooser PRPfileChooser;
+ private JFileChooser OUTfileChooser;
+ private java.awt.Font font;
+
+ private JScrollPane editorScrollPane = new JScrollPane(editorArea);
+ private JScrollPane trailScrollPane = new JScrollPane(trailArea);
+ private JScrollPane messageScrollPane = new JScrollPane(messageArea);
+ private JSplitPane topSplitPane;
+ private JSplitPane mainSplitPane;
+
+ private JMenuBar menuBar = new JMenuBar();
+
+ private JMenu menuFile = new JMenu();
+ private JMenuItem menuItemNew = new JMenuItem(Config.New);
+ private JMenuItem menuItemOpen = new JMenuItem(Config.Open);
+ private JMenuItem menuItemSave = new JMenuItem(Config.Save);
+ private JMenuItem menuItemSaveAs = new JMenuItem(Config.SaveAs);
+ private JMenuItem menuItemSwitch = new JMenuItem(Config.Switch);
+ private JMenuItem menuItemExit = new JMenuItem(Config.Exit);
+
+ private JMenu menuEditor = new JMenu();
+ private JMenuItem menuItemCopy = new JMenuItem(Config.Copy);
+ private JMenuItem menuItemCut = new JMenuItem(Config.Cut);
+ private JMenuItem menuItemPaste = new JMenuItem(Config.Paste);
+ private JMenuItem menuItemFind = new JMenuItem(Config.Find);
+ private JMenuItem menuItemFindAgain = new JMenuItem(Config.FindAgain);
+
+ private JMenu menuSpin = new JMenu();
+ private JMenuItem menuItemCheck = new JMenuItem(Config.Check);
+ private JMenuItem menuItemRandom = new JMenuItem(Config.Random);
+ private JMenuItem menuItemInter = new JMenuItem(Config.Inter);
+ private JMenuItem menuItemVerify = new JMenuItem(Config.Verify);
+ private JMenuItem menuItemTrail = new JMenuItem(Config.Trail);
+ private JMenuItem menuItemStop = new JMenuItem(Config.Stop);
+
+ private JMenu menuLTLConvert = new JMenu();
+ private JMenuItem menuItemTranslate = new JMenuItem(Config.LTLTranslate);
+ private JMenuItem menuItemClear = new JMenuItem(Config.LTLClear);
+ private JMenuItem menuItemLoad = new JMenuItem(Config.LTLLoad);
+ private JMenuItem menuItemName = new JMenuItem(Config.LTLName);
+ private boolean ltlInternal;
+
+ private JMenu menuOptions = new JMenu();
+ private JMenuItem menuItemOptionsCheck = new JMenuItem(Config.Check);
+ private JMenuItem menuItemOptionsCommon = new JMenuItem(Config.Common);
+ private JMenuItem menuItemOptionsRandom = new JMenuItem(Config.Random);
+ private JMenuItem menuItemOptionsInter = new JMenuItem(Config.Inter);
+ private JMenuItem menuItemOptionsVerify = new JMenuItem(Config.Verify);
+ private JMenuItem menuItemOptionsC = new JMenuItem(Config.OptionsC);
+ private JMenuItem menuItemOptionsPan = new JMenuItem(Config.OptionsPan);
+ private JMenuItem menuItemOptionsTrail = new JMenuItem(Config.Trail);
+ private JMenuItem menuItemDefault = new JMenuItem(Config.Default);
+ private JMenuItem menuItemOptionsSaveInstall = new JMenuItem(Config.SaveInstall);
+ private JMenuItem menuItemOptionsSaveCurrent = new JMenuItem(Config.SaveCurrent);
+
+ private JMenu menuSettings = new JMenu();
+ private JMenuItem menuItemMaxSteps = new JMenuItem(Config.MaxSteps);
+ private JMenuItem menuItemMaxDepth = new JMenuItem(Config.MaxDepth);
+ private JMenuItem menuItemSeed = new JMenuItem(Config.Seed);
+ private JCheckBoxMenuItem menuItemNegate = new JCheckBoxMenuItem(Config.Negate);
+ private JCheckBoxMenuItem menuItemFair = new JCheckBoxMenuItem(Config.Fair);
+ private JRadioButtonMenuItem menuItemSafety = new JRadioButtonMenuItem(Config.Safety, false);
+ private JRadioButtonMenuItem menuItemAcceptance = new JRadioButtonMenuItem(Config.Acceptance, false);
+ private JRadioButtonMenuItem menuItemNonProgress = new JRadioButtonMenuItem(Config.NonProgress, false);
+ private ButtonGroup buttonGroup = new ButtonGroup();
+
+ private JMenu menuOutput = new JMenu();
+ private JMenuItem menuItemMax = new JMenuItem(Config.Max);
+ private JMenuItem menuItemVarWidth = new JMenuItem(Config.VarWidth);
+ private JMenuItem menuItemStWidth = new JMenuItem(Config.StWidth);
+ private JMenuItem menuItemExcludedV = new JMenuItem(Config.ExcludedV);
+ private JMenuItem menuItemExcludedS = new JMenuItem(Config.ExcludedS);
+ private JCheckBoxMenuItem menuItemRaw = new JCheckBoxMenuItem(Config.Raw);
+ private JMenuItem menuItemDisplayRaw = new JMenuItem(Config.DisplayRaw);
+ private JMenuItem menuItemSaveSpin = new JMenuItem(Config.SaveSpin);
+
+ private JMenu menuSpider = new JMenu();
+ private JMenuItem menuItemSpider = new JMenuItem(Config.Spider);
+ private JMenuItem menuItemSpiderDisplay = new JMenuItem(Config.SpiderDisplay);
+
+ private JMenu menuHelp = new JMenu();
+ private JMenuItem menuItemHelp = new JMenuItem(Config.Help);
+ private JMenuItem menuItemAbout = new JMenuItem(Config.About);
+
+ private JToolBar toolBar = new JToolBar();
+
+ private JButton toolOpen = new JButton(Config.Open);
+ private JButton toolCheck = new JButton(Config.Check);
+ private JButton toolRandom = new JButton(Config.Random);
+ private JButton toolInter = new JButton(Config.Inter);
+ private JButton toolVerify = new JButton(Config.Verify);
+ private JButton toolTrail = new JButton(Config.Trail);
+ private JButton toolStop = new JButton(Config.Stop);
+
+ private JButton toolSpider = new JButton(Config.Spider);
+
+ private JLabel toolLabelFair = new JLabel(Config.Fair);
+ private JCheckBox toolCheckFair = new JCheckBox();
+ private JComboBox toolMode = new JComboBox();
+ private JButton toolMax = new JButton(Config.Max);
+ private boolean maxedDivider;
+ private int currentDivider;
+
+ private JLabel LTLLabel = new JLabel(Config.LTLFormula);
+ private JButton LTLTranslateButton = new JButton(Config.LTLTranslate);
+ private JButton LTLClearButton = new JButton(Config.LTLClear);
+ private JButton LTLLoadButton = new JButton(Config.LTLLoad);
+ private JButton LTLNameButton = new JButton(Config.LTLName);
+
+ // Convert String to array of Strings
+ private static String[] stringToArray(String s) {
+ java.util.StringTokenizer st = new java.util.StringTokenizer(s);
+ int count = st.countTokens();
+ String[] sa = new String[count];
+ for (int i = 0; i < count; i++)
+ sa[i] = st.nextToken();
+ return sa;
+ }
+
+ // Append and move caret to end
+ public static void append(JTextArea area, String s) {
+ if (s != null) area.append(s);
+ int last = area.getText().length();
+ try {
+ area.scrollRectToVisible(area.modelToView(last));
+ area.setCaretPosition(last);
+ } catch (javax.swing.text.BadLocationException e) {
+ System.err.println("Error setting caret position when writing\n" + s + "\n");
+ }
+ }
+
+ public static void main(String[] args) {
+ // Check Java version before executing
+ String version = System.getProperty("java.version");
+ if (version.compareTo(Config.JAVA_VERSION) < 0) {
+ JOptionPane.showMessageDialog(null,
+ "Your Java version is " + version + "\n" +
+ "jSpin needs least " + Config.JAVA_VERSION, "Version error",
+ JOptionPane.ERROR_MESSAGE);
+ System.exit(1);
+ }
+ final String a = (args.length > 0) ? args[0] : "";
+ javax.swing.SwingUtilities.invokeLater(
+ () -> {
+ jSpin jspin = new jSpin();
+ jspin.init(a);
+ });
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ // File menu actions
+ if (e.getSource() == menuItemNew) {
+ editor.setLastFile(editor.getFile());
+ clearAreas();
+ editor.newFile();
+ } else if ((e.getSource() == menuItemOpen) || (e.getSource() == toolOpen)) {
+ if (PMLfileChooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
+ editor.setLastFile(editor.getFile());
+ clearAreas();
+ editor.openFile(PMLfileChooser.getSelectedFile(), true);
+ }
+ } else if (e.getSource() == menuItemSave) {
+ if (editor.getFile() != null)
+ editor.saveFile(null);
+ else {
+ if (PMLfileChooser.showSaveDialog(this) == JFileChooser.APPROVE_OPTION) {
+ editor.saveFile(PMLfileChooser.getSelectedFile());
+ }
+ }
+ } else if (e.getSource() == menuItemSaveAs) {
+ if (PMLfileChooser.showSaveDialog(this) == JFileChooser.APPROVE_OPTION)
+ editor.setLastFile(editor.getFile());
+ editor.saveFile(PMLfileChooser.getSelectedFile());
+ } else if (e.getSource() == menuItemSwitch) {
+ if (editor.getLastFile() != null) {
+ java.io.File temp = editor.getLastFile();
+ if (editor.getFile() != null)
+ editor.saveFile(null);
+ else {
+ if (PMLfileChooser.showSaveDialog(this) == JFileChooser.APPROVE_OPTION) {
+ editor.saveFile(PMLfileChooser.getSelectedFile());
+ }
+ }
+ editor.setLastFile(editor.getFile());
+ editor.openFile(temp, true);
+ }
+ } else if (e.getSource() == menuItemExit) {
+ runSpin.killSpin();
+ System.exit(0);
+ }
+
+ // Editor menu actions
+ else if (e.getSource() == menuItemCut)
+ editor.cut();
+ else if (e.getSource() == menuItemCopy)
+ editor.copy();
+ else if (e.getSource() == menuItemPaste)
+ editor.paste();
+ else if (e.getSource() == menuItemFind)
+ editor.find();
+ else if (e.getSource() == menuItemFindAgain)
+ editor.findAgain();
+
+ // Spin menu actions
+ else if ((e.getSource() == menuItemCheck) || (e.getSource() == toolCheck)) {
+ trailArea.setText("");
+ runSpin.runAndWait(trailArea, false,
+ Config.getSpin(),
+ Config.getStringProperty("CHECK_OPTIONS") + " " +
+ editor.getFileName());
+ } else if ((e.getSource() == menuItemRandom) || (e.getSource() == toolRandom)) {
+ int seed = Config.getIntProperty("SEED");
+ trailArea.setText("");
+ runSpin.run(trailArea, true,
+ Config.getSpin(),
+ Config.getStringProperty("COMMON_OPTIONS") + " " +
+ Config.getStringProperty("RANDOM_OPTIONS") + " " +
+ (seed != 0 ? ("-n" + seed + " ") : "") +
+ " -u" + Config.getStringProperty("MAX_STEPS") + " " +
+ editor.getFileName());
+ isSpinRunning();
+ } else if ((e.getSource() == menuItemInter) || (e.getSource() == toolInter)) {
+ trailArea.setText("");
+ runSpin.run(trailArea, true,
+ Config.getSpin(),
+ Config.getStringProperty("COMMON_OPTIONS") + " " +
+ Config.getStringProperty("INTERACTIVE_OPTIONS") + " " +
+ editor.getFileName());
+ isSpinRunning();
+ } else if ((e.getSource() == menuItemVerify) || (e.getSource() == toolVerify)) {
+ trailArea.setText("");
+ if (!ltlInternal && !LTLField.getText().equals("") &&
+ !(new java.io.File(editor.getLTLFileName()).exists()))
+ append(messageArea, "WARNING: Correctness property has not been translated\n");
+ runSpin.runAndWait(trailArea, false,
+ Config.getSpin(),
+ Config.getStringProperty("VERIFY_OPTIONS") + " " +
+ ((ltlInternal || LTLField.getText().equals("")) ? "" : "-N " + " " +
+ editor.getLTLFileName() + " ") + editor.getFileName());
+ if (trailArea.getText().contains("Error: syntax error"))
+ return;
+ String mode = Config.getStringProperty("VERIFY_MODE");
+ String CModeOptions = mode.equals(Config.Safety) ? " -DSAFETY " :
+ (mode.equals(Config.NonProgress) ? " -DNP " : "");
+ runSpin.runAndWait(messageArea, false,
+ Config.getStringProperty("C_COMPILER"),
+ CModeOptions + " " +
+ Config.getStringProperty("C_COMPILER_OPTIONS"));
+ String panModeOptions = mode.equals(Config.Acceptance) ? " -a " :
+ (mode.equals(Config.NonProgress) ? " -l " : "");
+ if (!mode.equals(Config.Safety) && Config.getBooleanProperty("FAIRNESS"))
+ panModeOptions = " -f " + panModeOptions;
+ runSpin.run(trailArea, true,
+ editor.getRoot() + java.io.File.separator +
+ Config.getStringProperty("PAN"),
+ panModeOptions +
+ " -m" + Config.getStringProperty("MAX_DEPTH") + " " +
+ ((!ltlInternal || LTLField.getText().equals("")) ?
+ "" : "-N " + LTLField.getText() + " ") +
+ Config.getStringProperty("PAN_OPTIONS"));
+ isSpinRunning();
+ } else if ((e.getSource() == menuItemTrail) || (e.getSource() == toolTrail)) {
+ runSpin.run(trailArea, true,
+ Config.getSpin(),
+ Config.getStringProperty("COMMON_OPTIONS") + " " +
+ Config.getStringProperty("TRAIL_OPTIONS") +
+ " -u" + Config.getStringProperty("MAX_STEPS") + " " +
+ editor.getFileName());
+ isSpinRunning();
+ } else if ((e.getSource() == menuItemStop) || (e.getSource() == toolStop))
+ runSpin.killSpin();
+
+ // Options menu actions
+ else if (e.getSource() == menuItemOptionsCommon)
+ new Options();
+ else if ((e.getSource() == menuItemOptionsCheck) ||
+ (e.getSource() == menuItemOptionsRandom) ||
+ (e.getSource() == menuItemOptionsInter) ||
+ (e.getSource() == menuItemOptionsVerify) ||
+ (e.getSource() == menuItemOptionsC) ||
+ (e.getSource() == menuItemOptionsPan) ||
+ (e.getSource() == menuItemOptionsTrail))
+ changeOption(e.getActionCommand().toUpperCase().replace(' ', '_') + "_OPTIONS", false);
+ else if (e.getSource() == menuItemDefault)
+ Config.setDefaultProperties();
+
+ else if ((e.getSource() == menuItemOptionsSaveInstall) ||
+ (e.getSource() == menuItemOptionsSaveCurrent)) {
+ // Save current directory and divider locations
+ Config.setStringProperty("SOURCE_DIRECTORY",
+ PMLfileChooser.getCurrentDirectory().getAbsolutePath());
+ Config.setIntProperty("LR_DIVIDER", topSplitPane.getDividerLocation());
+ Config.setIntProperty("TB_DIVIDER", mainSplitPane.getDividerLocation());
+ boolean currentConfig = e.getSource() == menuItemOptionsSaveCurrent;
+ Config.saveFile(currentConfig);
+ append(messageArea,
+ "Saved jSpin configuration file config.cfg in " +
+ (currentConfig ? "current" : "installation") + " directory\n");
+ }
+
+ // Settings menu actions
+ else if (e.getSource() == menuItemMaxSteps)
+ changeOption("MAX_STEPS", true);
+ else if (e.getSource() == menuItemMaxDepth)
+ changeOption("MAX_DEPTH", true);
+ else if (e.getSource() == menuItemSeed)
+ changeOption("SEED", true);
+ else if (e.getSource() == menuItemNegate) {
+ boolean negate = !Config.getBooleanProperty("NEGATE_LTL");
+ Config.setBooleanProperty("NEGATE_LTL", negate);
+ menuItemNegate.setSelected(negate);
+ } else if ((e.getSource() == menuItemFair) || (e.getSource() == toolCheckFair)) {
+ boolean fair = !Config.getBooleanProperty("FAIRNESS");
+ Config.setBooleanProperty("FAIRNESS", fair);
+ menuItemFair.setSelected(fair);
+ toolCheckFair.setSelected(fair);
+ } else if ((e.getSource() == menuItemSafety) ||
+ (e.getSource() == menuItemAcceptance) ||
+ (e.getSource() == menuItemNonProgress))
+ changeMode(e.getActionCommand());
+ else if (e.getSource() == toolMode)
+ changeMode(((String) ((JComboBox) e.getSource()).getSelectedItem()));
+
+ // Output menu actions
+ else if ((e.getSource() == menuItemMax) ||
+ (e.getSource() == toolMax)) {
+ if (maxedDivider)
+ topSplitPane.setDividerLocation(currentDivider);
+ else {
+ currentDivider = topSplitPane.getDividerLocation();
+ topSplitPane.setDividerLocation(Config.getIntProperty("MIN_DIVIDER"));
+ }
+ maxedDivider = !maxedDivider;
+ } else if (e.getSource() == menuItemExcludedV)
+ new Excluded(editor, font, filter, true);
+ else if (e.getSource() == menuItemExcludedS)
+ new Excluded(editor, font, filter, false);
+ else if (e.getSource() == menuItemStWidth)
+ changeOption("STATEMENT_WIDTH", true);
+ else if (e.getSource() == menuItemVarWidth)
+ changeOption("VARIABLE_WIDTH", true);
+ else if (e.getSource() == menuItemSaveSpin) {
+ java.io.File outFile = new java.io.File(editor.getOUTFileName());
+ OUTfileChooser.setSelectedFile(outFile);
+ if (OUTfileChooser.showSaveDialog(this) == JFileChooser.APPROVE_OPTION)
+ editor.writeFile(OUTfileChooser.getSelectedFile(), trailArea);
+ } else if (e.getSource() == menuItemRaw) {
+ boolean raw = !Config.getBooleanProperty("RAW");
+ Config.setBooleanProperty("RAW", raw);
+ menuItemRaw.setSelected(raw);
+ } else if (e.getSource() == menuItemDisplayRaw)
+ displayFile(editor.getRoot() + java.io.File.separator + editor.getFileRoot() + ".raw");
+
+ // Spider menu actions
+ else if ((e.getSource() == menuItemSpider) || (e.getSource() == toolSpider)) {
+ if (editor.getFile() == null) {
+ jSpin.append(messageArea, Config.OPEN_FILE);
+ return;
+ }
+ // Read Spider properties from the file for this program
+ sp = new SpiderFile(spiderProperties,
+ editor.getRoot() + java.io.File.separator + editor.getFileRoot());
+ sp.init();
+ if (new SpiderOptions(this, sp, font).showDialog()) {
+ sp.saveFile();
+ // Run in thread to display progress
+ new Thread(() -> {
+ SpinSpider spd =
+ new SpinSpider(
+ editor.getRoot() + File.separator + editor.getFileRoot(),
+ editor.getExtension(),
+ sp.getStringProperty("FORMAT"),
+ sp.getIntProperty("PROCESSES"),
+ stringToArray(sp.getStringProperty("VARIABLES")),
+ sp.getBooleanProperty("SPIDER_DEBUG"),
+ sp.getIntProperty("TRAIL_CODE"),
+ sp.getIntProperty("DOT_SIZE"),
+ sp.getIntProperty("TRAIL_STYLE"),
+ messageArea,
+ Config.getProperties());
+ if (!spd.runSpider()) return;
+ // If PNG format, display in a frame
+ if (sp.getStringProperty("FORMAT").equals(Config.PNG)) {
+ // Draw automata if requested
+ if (sp.getIntProperty("TRAIL_CODE") == 3)
+ new DrawAutomata(spd).drawAutomata();
+ new DisplayImage(editor.getRoot() + File.separator + editor.getFileRoot() +
+ com.spinroot.spinSpider.Config.names[sp.getIntProperty("TRAIL_CODE")] + ".png");
+ }
+ }).start();
+ }
+ } else if (e.getSource() == menuItemSpiderDisplay)
+ displayFile(editor.getRoot() + java.io.File.separator + editor.getFileRoot() + ".dbg");
+
+ // Help menu actions
+ else if (e.getSource() == menuItemHelp)
+ displayFile(Config.helpFileName);
+ else if (e.getSource() == menuItemAbout)
+ displayFile(Config.aboutFileName);
+
+ // LTL actions
+ else if ((e.getSource() == LTLTranslateButton) || (e.getSource() == menuItemTranslate)) {
+ editor.modifiedLTL();
+ if (LTLField.getText().equals(""))
+ return;
+ ltlInternal = false;
+ String quote = Config.getBooleanProperty("SINGLE_QUOTE") ? "'" : "\"";
+ String negate = Config.getBooleanProperty("NEGATE_LTL") ? "!" : "";
+ runSpin.runAndWait(trailArea, false,
+ Config.getSpin(),
+ Config.getStringProperty("TRANSLATE_OPTIONS") + " " +
+ quote + negate + "(" + LTLField.getText() + ")" + quote);
+ editor.writeFile(new java.io.File(editor.getLTLFileName()), trailArea);
+ } else if ((e.getSource() == LTLClearButton) || (e.getSource() == menuItemClear)) {
+ LTLField.setText("");
+ menuBar.revalidate();
+ } else if ((e.getSource() == LTLLoadButton) || (e.getSource() == menuItemLoad)) {
+ PRPfileChooser.setCurrentDirectory(
+ PMLfileChooser.getCurrentDirectory());
+ if (PRPfileChooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
+ editor.openFile(PRPfileChooser.getSelectedFile(), false);
+ }
+ } else if ((e.getSource() == LTLNameButton) || (e.getSource() == menuItemName)) {
+ ltlInternal = true;
+ }
+ if (editor != null) editor.focus(false);
+ }
+
+ // Display the contents of a file in the trail area
+ private void displayFile(String fn) {
+ trailArea.setText(editor.readFile(new java.io.File(fn)));
+ trailArea.setCaretPosition(0);
+ }
+
+ // Clear all areas before opening file or creating new file
+ private void clearAreas() {
+ messageArea.setText("");
+ trailArea.setText("");
+ LTLField.setText("");
+ }
+
+ // Change verification mode:
+ // radio buttons in menu, combo box in toolbar and properties
+ private void changeMode(String mode) {
+ toolMode.setSelectedItem(mode);
+ if (mode.equals(Config.Safety))
+ menuItemSafety.setSelected(true);
+ else if (mode.equals(Config.Acceptance))
+ menuItemAcceptance.setSelected(true);
+ else if (mode.equals(Config.NonProgress))
+ menuItemNonProgress.setSelected(true);
+ Config.setStringProperty("VERIFY_MODE", mode);
+ }
+
+ // Display an option pane to edit an option string
+ private void changeOption(String property, boolean number) {
+ String s = Config.getStringProperty(property);
+ String answer = JOptionPane.showInputDialog(property, s);
+ if (answer == null) return;
+ if (!number || (number && checkInt(answer)))
+ Config.setStringProperty(property, answer);
+ else
+ JOptionPane.showMessageDialog(null,
+ answer + " is not an integer", "Format error",
+ JOptionPane.ERROR_MESSAGE);
+ }
+
+ // Some option panes need to be positive integers
+ private boolean checkInt(String property) {
+ try {
+ Integer.parseInt(property);
+ return true;
+ } catch (NumberFormatException e) {
+ return false;
+ }
+ }
+
+ // Create a thread to check if Spin is running
+ // Enables user interface to continue running and press Stop
+ void isSpinRunning() {
+ Thread th = new Thread(() -> {
+ while (runSpin.isRunning()) {
+ try {
+ Thread.sleep(Config.getIntProperty("POLLING_DELAY"));
+ } catch (InterruptedException e) {
+ }
+ }
+ append(messageArea, "done!\n");
+ });
+ th.start();
+ }
+
+ // Initialize menus
+ private void initMenuItem(
+ JMenu menu, JMenuItem item, int mnemonic, String accelerator) {
+ menu.add(item);
+ item.addActionListener(this);
+ item.setMnemonic(mnemonic);
+ if (accelerator != null)
+ item.setAccelerator(KeyStroke.getKeyStroke(accelerator));
+ }
+
+ private void initMenus() {
+ menuBar.setBorder(new LineBorder(java.awt.Color.BLUE));
+
+ menuBar.add(menuFile);
+ menuFile.setText(Config.File);
+ menuFile.setMnemonic(Config.FileMN);
+ initMenuItem(menuFile, menuItemNew, Config.NewMN, Config.NewAC);
+ initMenuItem(menuFile, menuItemOpen, Config.OpenMN, Config.OpenAC);
+ initMenuItem(menuFile, menuItemSave, Config.SaveMN, Config.SaveAC);
+ initMenuItem(menuFile, menuItemSaveAs, Config.SaveAsMN, Config.SaveAsAC);
+ menuFile.addSeparator();
+ initMenuItem(menuFile, menuItemSwitch, Config.SwitchMN, Config.SwitchAC);
+ menuFile.addSeparator();
+ initMenuItem(menuFile, menuItemExit, Config.ExitMN, Config.ExitAC);
+
+ undoredo = new UndoRedo();
+ menuBar.add(menuEditor);
+ menuEditor.setText(Config.Editor);
+ menuEditor.setMnemonic(Config.EditorMN);
+ JMenuItem menuItemUndo = menuEditor.add(undoredo.undoAction);
+ JMenuItem menuItemRedo = menuEditor.add(undoredo.redoAction);
+ initMenuItem(menuEditor, menuItemUndo, Config.UndoMN, Config.UndoAC);
+ initMenuItem(menuEditor, menuItemRedo, Config.RedoMN, Config.RedoAC);
+ menuEditor.addSeparator();
+ initMenuItem(menuEditor, menuItemCopy, Config.CopyMN, Config.CopyAC);
+ initMenuItem(menuEditor, menuItemCut, Config.CutMN, Config.CutAC);
+ initMenuItem(menuEditor, menuItemPaste, Config.PasteMN, Config.PasteAC);
+ menuEditor.addSeparator();
+ initMenuItem(menuEditor, menuItemFind, Config.FindMN, Config.FindAC);
+ initMenuItem(menuEditor, menuItemFindAgain, Config.FindAgainMN, Config.FindAgainAC);
+
+ menuBar.add(menuSpin);
+ menuSpin.setText(Config.Spin);
+ menuSpin.setMnemonic(Config.SpinMN);
+ initMenuItem(menuSpin, menuItemCheck, Config.CheckMN, Config.CheckAC);
+ menuSpin.addSeparator();
+ initMenuItem(menuSpin, menuItemRandom, Config.RandomMN, Config.RandomAC);
+ initMenuItem(menuSpin, menuItemInter, Config.InterMN, Config.InterAC);
+ initMenuItem(menuSpin, menuItemTrail, Config.TrailMN, Config.TrailAC);
+ menuSpin.addSeparator();
+ initMenuItem(menuSpin, menuItemVerify, Config.VerifyMN, Config.VerifyAC);
+ initMenuItem(menuSpin, menuItemStop, Config.StopMN, Config.StopAC);
+
+ menuBar.add(menuLTLConvert);
+ menuLTLConvert.setText(Config.LTLConvert);
+ menuLTLConvert.setMnemonic(Config.LTLConvertMN);
+ initMenuItem(menuLTLConvert, menuItemTranslate, Config.LTLTranslateMN, Config.LTLTranslateAC);
+ initMenuItem(menuLTLConvert, menuItemClear, Config.LTLClearMN, Config.LTLClearAC);
+ initMenuItem(menuLTLConvert, menuItemLoad, Config.LTLLoadMN, Config.LTLLoadAC);
+ if (Config.getIntProperty("VERSION") >= 6) {
+ menuLTLConvert.addSeparator();
+ initMenuItem(menuLTLConvert, menuItemName, Config.LTLName1MN, Config.LTLNameAC);
+ }
+
+ menuBar.add(menuOptions);
+ menuOptions.setText(Config.Options);
+ menuOptions.setMnemonic(Config.OptionsMN);
+ initMenuItem(menuOptions, menuItemOptionsCommon, Config.CommonMN, Config.CommonAC);
+ menuOptions.addSeparator();
+ initMenuItem(menuOptions, menuItemOptionsCheck, Config.CheckMN, Config.CheckAC);
+ initMenuItem(menuOptions, menuItemOptionsRandom, Config.RandomMN, Config.OptionsRandomAC);
+ initMenuItem(menuOptions, menuItemOptionsInter, Config.InterMN, Config.OptionsInterAC);
+ initMenuItem(menuOptions, menuItemOptionsVerify, Config.VerifyMN, Config.VerifyAC);
+ initMenuItem(menuOptions, menuItemOptionsC, Config.OptionsCMN, Config.OptionsCAC);
+ initMenuItem(menuOptions, menuItemOptionsPan, Config.OptionsPanMN, Config.OptionsPanAC);
+ initMenuItem(menuOptions, menuItemOptionsTrail, Config.TrailMN, Config.OptionsTrailAC);
+ menuOptions.addSeparator();
+ initMenuItem(menuOptions, menuItemDefault, Config.DefaultMN, Config.DefaultAC);
+ initMenuItem(menuOptions, menuItemOptionsSaveInstall, Config.SaveInstallMN, Config.OptionsSaveInstallAC);
+ initMenuItem(menuOptions, menuItemOptionsSaveCurrent, Config.SaveCurrentMN, Config.OptionsSaveCurrentAC);
+
+ menuBar.add(menuSettings);
+ menuSettings.setText(Config.Settings);
+ menuSettings.setMnemonic(Config.SettingsMN);
+ initMenuItem(menuSettings, menuItemMaxSteps, Config.MaxStepsMN, Config.MaxStepsAC);
+ initMenuItem(menuSettings, menuItemMaxDepth, Config.MaxDepthMN, Config.MaxDepthAC);
+ menuSettings.addSeparator();
+ initMenuItem(menuSettings, menuItemSeed, Config.SeedMN, Config.SeedAC);
+ menuSettings.addSeparator();
+ initMenuItem(menuSettings, menuItemNegate, Config.NegateMN, Config.NegateAC);
+ menuItemNegate.setSelected(Config.getBooleanProperty("NEGATE_LTL"));
+ menuSettings.addSeparator();
+ initMenuItem(menuSettings, menuItemFair, Config.FairMN, Config.FairAC);
+ menuItemFair.setSelected(Config.getBooleanProperty("FAIRNESS"));
+ menuSettings.addSeparator();
+ initMenuItem(menuSettings, menuItemSafety, Config.SafetyMN, Config.SafetyAC);
+ initMenuItem(menuSettings, menuItemAcceptance, Config.AcceptanceMN, Config.AcceptanceAC);
+ initMenuItem(menuSettings, menuItemNonProgress, Config.NonProgressMN, Config.NonProgressAC);
+ buttonGroup.add(menuItemSafety);
+ buttonGroup.add(menuItemAcceptance);
+ buttonGroup.add(menuItemNonProgress);
+
+ menuBar.add(menuOutput);
+ menuOutput.setText(Config.Output);
+ menuOutput.setMnemonic(Config.OutputMN);
+ initMenuItem(menuOutput, menuItemMax, Config.MaxMN, Config.MaxAC);
+ menuOutput.addSeparator();
+ initMenuItem(menuOutput, menuItemExcludedV, Config.ExcludedVMN, Config.ExcludedVAC);
+ initMenuItem(menuOutput, menuItemExcludedS, Config.ExcludedSMN, Config.ExcludedSAC);
+ menuOutput.addSeparator();
+ initMenuItem(menuOutput, menuItemStWidth, Config.StWidthMN, Config.StWidthAC);
+ initMenuItem(menuOutput, menuItemVarWidth, Config.VarWidthMN, Config.VarWidthAC);
+ menuOutput.addSeparator();
+ initMenuItem(menuOutput, menuItemSaveSpin, Config.SaveSpinMN, Config.SaveSpinAC);
+ menuOutput.addSeparator();
+ initMenuItem(menuOutput, menuItemRaw, Config.RawMN, Config.RawAC);
+ initMenuItem(menuOutput, menuItemDisplayRaw, Config.DisplayRawMN, Config.DisplayRawAC);
+ menuItemRaw.setSelected(Config.getBooleanProperty("RAW"));
+
+ menuBar.add(menuSpider);
+ menuSpider.setText(Config.Spider);
+ menuSpider.setMnemonic(Config.SpiderMN);
+ initMenuItem(menuSpider, menuItemSpider, Config.SpiderMN, Config.SpiderAC);
+ menuSpider.addSeparator();
+ initMenuItem(menuSpider, menuItemSpiderDisplay, Config.SpiderDisplayMN, Config.SpiderDisplayAC);
+
+ menuBar.add(menuHelp);
+ menuHelp.setText(Config.Help);
+ menuHelp.setMnemonic(Config.HelpMN);
+ initMenuItem(menuHelp, menuItemHelp, Config.HelpMN, Config.HelpAC);
+ initMenuItem(menuHelp, menuItemAbout, Config.AboutMN, Config.AboutAC);
+
+ menuBar.add(new JLabel(" "));
+ menuBar.add(new JSeparator(SwingConstants.VERTICAL));
+ menuBar.add(LTLLabel);
+ LTLField.setColumns(Config.LTL_COLUMNS);
+ LTLField.setPreferredSize(new java.awt.Dimension(250, 30));
+ menuBar.add(LTLField);
+ }
+
+ private void initToolButton(JButton item, int mnemonic) {
+ item.setMaximumSize(new java.awt.Dimension(75, 40));
+ toolBar.add(item);
+ if (mnemonic != -1) item.setMnemonic(mnemonic);
+ item.addActionListener(this);
+ }
+
+ // Initialize toolbar
+ private void initToolBar() {
+ toolBar.setLayout(new BoxLayout(toolBar, BoxLayout.X_AXIS));
+ toolBar.setFloatable(false);
+ toolBar.setBorder(new LineBorder(java.awt.Color.BLUE));
+
+ toolBar.add(toolOpen);
+ initToolButton(toolOpen, -1);
+ toolBar.addSeparator();
+ initToolButton(toolCheck, Config.CheckMN);
+ initToolButton(toolRandom, Config.RandomMN);
+ initToolButton(toolInter, Config.InterMN);
+ initToolButton(toolTrail, Config.TrailMN);
+ toolBar.addSeparator();
+
+ toolBar.add(toolLabelFair);
+ toolBar.add(toolCheckFair);
+ toolCheckFair.setSelected(Config.getBooleanProperty("FAIRNESS"));
+// toolCheckFair.setMnemonic(Config.FairMN);
+// toolLabelFair.setDisplayedMnemonic(Config.FairMN);
+ toolCheckFair.addActionListener(this);
+ toolMode.setMaximumSize(new java.awt.Dimension(110, 50));
+ toolMode.setEditable(false);
+ toolMode.addItem(Config.Safety);
+ toolMode.addItem(Config.Acceptance);
+ toolMode.addItem(Config.NonProgress);
+ toolMode.addActionListener(this);
+ toolBar.add(toolMode);
+ toolBar.addSeparator();
+
+ initToolButton(toolVerify, Config.VerifyMN);
+ initToolButton(toolStop, Config.StopMN);
+ toolBar.addSeparator();
+
+ if (Config.getIntProperty("VERSION") >= 6) {
+ initToolButton(LTLTranslateButton, Config.LTLTranslateMN);
+ initToolButton(LTLLoadButton, Config.LTLLoadMN);
+ initToolButton(LTLNameButton, Config.LTLNameMN);
+ } else {
+ initToolButton(LTLTranslateButton, Config.LTLTranslateMN);
+ initToolButton(LTLClearButton, Config.LTLClearMN);
+ initToolButton(LTLLoadButton, Config.LTLLoadMN);
+ }
+
+ toolBar.addSeparator();
+ initToolButton(toolSpider, -1);
+ toolBar.addSeparator();
+ initToolButton(toolMax, Config.MaxMN);
+ }
+
+ private JFileChooser newChooser(String title, String e1, String e2, String e3) {
+ JFileChooser fileChooser = new JFileChooser(Config.getStringProperty("SOURCE_DIRECTORY"));
+ fileChooser.setFileFilter(new JSpinFileFilter(title, e1, e2, e3));
+ return fileChooser;
+ }
+
+ // Initialization, optionally with initial source file
+ private void init(String file) {
+ Config.init();
+ spiderProperties = new java.util.Properties();
+
+ // For Spin 6 default is internal LTL
+ ltlInternal = Config.getIntProperty("VERSION") >= 6;
+
+ // Set properties of text areas
+ font = new java.awt.Font(
+ Config.getStringProperty("FONT_FAMILY"),
+ Config.getIntProperty("FONT_STYLE"),
+ Config.getIntProperty("FONT_SIZE"));
+ javax.swing.UIManager.put("TextField.font", font);
+ editorArea.setFont(font);
+ editorArea.setTabSize(Config.getIntProperty("TAB_SIZE"));
+ trailArea.setFont(font);
+ trailArea.setLineWrap(Config.getBooleanProperty("WRAP"));
+ trailArea.setWrapStyleWord(true);
+ messageArea.setFont(font);
+ LTLField.setFont(font);
+
+ // Create menus and toolbar
+ initMenus();
+ initToolBar();
+ changeMode(Config.getStringProperty("VERIFY_MODE"));
+ setJMenuBar(menuBar);
+
+ // Set up frame with panes
+ topSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, editorScrollPane, trailScrollPane);
+ mainSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, topSplitPane, messageScrollPane);
+ topSplitPane.setOneTouchExpandable(true);
+ mainSplitPane.setOneTouchExpandable(true);
+ topSplitPane.setDividerLocation(Config.getIntProperty("LR_DIVIDER"));
+ currentDivider = Config.getIntProperty("LR_DIVIDER");
+ mainSplitPane.setDividerLocation(Config.getIntProperty("TB_DIVIDER"));
+ JPanel contentPane = new JPanel();
+ contentPane.setLayout(new java.awt.BorderLayout());
+ contentPane.add(toolBar, java.awt.BorderLayout.NORTH);
+ contentPane.add(mainSplitPane, java.awt.BorderLayout.CENTER);
+ setContentPane(contentPane);
+
+ // Create objects
+ filter = new com.spinroot.filterSpin.Filter();
+ editor = new Editor(editorScrollPane, editorArea, messageArea,
+ LTLField, undoredo.myundoable, filter);
+ runSpin = new RunSpin(editor, messageArea, filter);
+ PMLfileChooser = newChooser("Promela source files", ".PML", ".PROM", ".H");
+ PRPfileChooser = newChooser("LTL property files", ".PRP", null, null);
+ OUTfileChooser = newChooser("Spin display output files", ".OUT", null, null);
+
+ // Window listener: kill Spin process if window closed
+ addWindowListener(new WindowAdapter() {
+ public void windowClosing(WindowEvent e) {
+ runSpin.killSpin();
+ System.exit(0);
+ }
+ });
+
+ // Configuration JFrame and make visible
+ setFont(font);
+ setTitle(Config.SOFTWARE_NAME);
+ setSize(Config.getIntProperty("WIDTH"), Config.getIntProperty("HEIGHT"));
+ setLocationRelativeTo(null);
+ setVisible(true);
+
+ // Open file if given as command argument
+ if (!Objects.equals(file, "")) {
+ editor.openFile(new java.io.File(file), true);
+ } else {
+ editor.newFile();
+ }
+ }
+
+}
diff --git a/src/main/java/com/spinroot/spinSpider/Config.java b/src/main/java/com/spinroot/spinSpider/Config.java
new file mode 100644
index 0000000..2561ec8
--- /dev/null
+++ b/src/main/java/com/spinroot/spinSpider/Config.java
@@ -0,0 +1,72 @@
+/*
+ Config - configuration constants and file
+ Copyright 2005-10 by Mordechai (Moti) Ben-Ari. See SpinSpider.java
+*/
+package com.spinroot.spinSpider;
+
+public class Config {
+ public static final String[] names = {"", "-trail-1", "-trail-2", "-automata"};
+ static final String VERSION = "6.0";
+ // Properties data structure is used for command names
+ // Initialize properties from file or create file or from defaults
+ static final String CONFIG_FILE = "config.cfg";
+ static final int MAX_STACK = 1000; // Stack for processing -DCHECK file
+ static final int INITIAL = 100; // For ArrayLists
+ static final int DELTA = 1000; // For node offset in automata
+ static final String TITLE =
+ "SpinSpider Version " + VERSION +
+ " Copyright 2005-7 (GNU GPL) by Moti Ben-Ari.";
+ static final String USAGE =
+ "Usage java com.spinroot.spinSpider.SpinSpider arguments file\n\n" +
+ " file Promela source file\n\n" +
+ " -p number of processes (must be >= 1)\n" +
+ " -vname name of a variable (one parameter per variable)\n\n" +
+ " -dot dot format\n" +
+ " -Txxx dot format and run DOT to convert to xxx format\n" +
+ " (default is png)\n" +
+ " -fsm fsm format\n\n" +
+ " -t1 use trail file to emphasize a path\n" +
+ " -t2 use trail file to draw a path\n" +
+ " -a draw automata corresponding to source\n\n" +
+ " -small size of dot graph is smaller\n" +
+ " -bold bold style instead of color for path\n" +
+ " -debug write internal tables to file.dbg";
+ static final String dotTrailBold = " style = bold";
+ static final String dotTrailColor = " color = red";
+ static final String[] smallDotPrologue = {
+ "\tgraph [size=\"12.5,7.5\",ranksep=.20];",
+ "\tnode [shape=box,fontname=Helvetica,fontsize=10];",
+ "\tnode [width=1.25,height=0.75,fixedsize=true];"
+ };
+ static final String[] largeDotPrologue = {
+ "\tgraph [size=\"16,12\",ranksep=.25];",
+ "\tnode [shape=box,fontname=Helvetica,fontsize=14];",
+ "\tnode [width=1.6,height=1.2,fixedsize=true];"
+ };
+ static final String[] automataDotPrologue = {
+ "\tgraph [size=\"16,12\",ranksep=.4];",
+ "\tnode [shape=circle,fontname=Helvetica,fontsize=14];",
+ "\tedge [fontname=Helvetica,fontsize=14];"
+ };
+
+ static public void setDefaultProperties(
+ java.util.Properties properties) {
+ // Spin version: format changed with Spin 6
+ properties.put("VERSION", "6");
+
+ properties.put("C_COMPILER", "c:\\mingw\\bin\\gcc.exe");
+ properties.put("SPIN", "bin\\spin.exe");
+ properties.put("PAN", "pan.exe");
+ properties.put("DOT", "bin\\dot.exe");
+ }
+
+ static public void init(java.util.Properties properties) {
+ setDefaultProperties(properties);
+ try {
+ properties.load(new java.io.FileInputStream(CONFIG_FILE));
+ } catch (java.io.IOException e1) {
+ System.err.println("Cannot open configuration file; using defaults");
+ }
+ }
+
+}
diff --git a/src/main/java/com/spinroot/spinSpider/DrawAutomata.java b/src/main/java/com/spinroot/spinSpider/DrawAutomata.java
new file mode 100644
index 0000000..e833f4a
--- /dev/null
+++ b/src/main/java/com/spinroot/spinSpider/DrawAutomata.java
@@ -0,0 +1,113 @@
+/* Copyright 2007 by Mordechai (Moti) Ben-Ari. See copyright.txt */
+/*
+ * Draw the automata representation of a Promela program.
+*/
+
+package com.spinroot.spinSpider;
+
+import java.io.*;
+
+public class DrawAutomata {
+ SpinSpider spd;
+
+ public DrawAutomata(SpinSpider s) {
+ spd = s;
+ }
+
+ // Extract an int value that appears between "from" and "to" in "s"
+ private static int extract(String s, String from, String to) {
+ return
+ Integer.parseInt(
+ s.substring(s.indexOf(from) + from.length(), s.indexOf(to))
+ .trim());
+ }
+
+ public void drawAutomata() {
+ BufferedReader statementReader = null;
+ PrintWriter graphWriter = null;
+ String s = "";
+ String fn = spd.fileName + Config.names[3];
+
+ spd.progress("Drawing automata");
+ try {
+ statementReader = new BufferedReader(
+ new FileReader(spd.fileName + ".dbg"));
+ } catch (IOException e) {
+ spd.fileError(".dbg");
+ }
+ try {
+ graphWriter = new PrintWriter(
+ new FileWriter(fn + ".dot"));
+ } catch (IOException e) {
+ spd.fileError(".dot");
+ }
+
+ // Write dot prologue
+ graphWriter.println("digraph \"" + fn + "\"" + " {");
+ for (int i = 0; i < Config.automataDotPrologue.length; i++)
+ graphWriter.println(Config.automataDotPrologue[i]);
+
+ // Skip over first parts of debug files
+ while (true) {
+ try {
+ s = statementReader.readLine();
+ } catch (IOException e) {
+ spd.fileError(".dbg");
+ }
+ if (s == null)
+ spd.fileError(".dbg");
+ else if (s.equals("Statements from -d file"))
+ break;
+ }
+
+ // Extract data from each line and write nodes and edges
+ // Use DELTA to create unique node numbers for each process
+ int process = 0, proc, line, source, target;
+ boolean endState = false, atomic = false, previousAtomic = false;
+ String emphasize = spd.trailStyle == 0 ? Config.dotTrailColor : Config.dotTrailBold;
+ while (true) {
+ try {
+ s = statementReader.readLine();
+ } catch (IOException e) {
+ spd.fileError(".dbg");
+ }
+ if (s == null) break;
+ if (s.indexOf("process") == -1) break;
+ proc = extract(s, "process=", ", source");
+ // New process
+ if (proc != process) {
+ process = proc;
+ endState = false;
+ }
+ source = extract(s, "source=", ", target") + process * Config.DELTA;
+ line = extract(s, "line=", ".");
+ graphWriter.println(source + " [label=" + line + "]");
+ target = extract(s, "target=", ", id") + process * Config.DELTA;
+ if ((target == process * Config.DELTA) && !endState) {
+ endState = true;
+ graphWriter.println(target + " [label=0]");
+ }
+ atomic = s.indexOf("atomic,") != -1;
+ graphWriter.println(source + " -> " + target +
+ " [label=\"" + s.substring(s.indexOf('.') + 1) + "\"" +
+ (atomic || previousAtomic ? emphasize : "") + "]");
+ previousAtomic = atomic;
+ }
+
+ try {
+ statementReader.close();
+ } catch (IOException e) {
+ spd.fileError(".dbg");
+ }
+ graphWriter.println("}");
+ graphWriter.close();
+
+ // Call dot to format dot file
+ if (!spd.format.equals("dot"))
+ spd.runProcess(spd.properties.getProperty("DOT") +
+ " -T" + spd.format +
+ " -o " + fn + "." + spd.format + " " +
+ fn + ".dot", null);
+ }
+
+}
diff --git a/src/main/java/com/spinroot/spinSpider/Read.java b/src/main/java/com/spinroot/spinSpider/Read.java
new file mode 100644
index 0000000..bd33772
--- /dev/null
+++ b/src/main/java/com/spinroot/spinSpider/Read.java
@@ -0,0 +1,240 @@
+/* Copyright 2006-10 by Mordechai (Moti) Ben-Ari. See copyright.txt */
+/*
+ * Read the data files
+*/
+
+package com.spinroot.spinSpider;
+
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.Properties;
+
+class Read {
+ SpinSpider spd;
+ String fileName;
+ Properties properties;
+
+ Read(SpinSpider s, String f, Properties p) {
+ spd = s;
+ fileName = f;
+ properties = p;
+ }
+
+ // Extract an int value that appears between "from" and "to" in "s"
+ private static int extract(String s, String from, String to) {
+ return
+ Integer.parseInt(
+ s.substring(s.indexOf(from) + from.length(), s.indexOf(to))
+ .trim());
+ }
+
+ // Read the state transitions output by -DCHECK and never claim
+ // Thanks to Gerard Holzmann for showing me how to do this.
+ void readCheckFile() {
+ BufferedReader checkReader = null;
+ String s = ""; // Read line to s
+ String[] tokens; // For tokenizing
+ // Stack of states traversed
+ int[] stack = new int[Config.MAX_STACK];
+ int newState = 0; // State number in "New"
+ int depth = 0; // Stack depth
+ boolean needNew = false; // Need state information after "New"
+ int offset = 0; // Offset of variables after procs
+
+ spd.progress("Reading -DCHECK file");
+ try {
+ checkReader = new BufferedReader(
+ new FileReader(fileName + ".chk"));
+ } catch (IOException e) {
+ spd.fileError(".chk");
+ }
+
+ while (true) {
+ try {
+ s = checkReader.readLine();
+ } catch (IOException e) {
+ spd.fileError(".chk");
+ }
+ if ((s == null) || s.indexOf("Spin Version") != -1) break;
+
+ tokens = s.trim().split("\\s");
+ // "New" indicates a new state
+ // Push on the stack
+ // Immediately thereafter the *spd* output will appear
+ if ((tokens.length > 2) && tokens[0].equals("New")) {
+ newState = Integer.parseInt(tokens[2]);
+ stack[depth] = newState;
+ needNew = true;
+ }
+ // "Down" for a program (not a claim) indicates a transition
+ // to the new state that was just pushed on the stack
+ else if ((tokens.length > 3) && (tokens[1].equals("Down"))) {
+ if (tokens[3].equals("program") && (newState > 0))
+ spd.transitions.add(
+ new Transition(stack[depth - 1], newState));
+ depth++;
+ stack[depth] = stack[depth - 1];
+ }
+ // "Up" - pop the stack
+ else if ((tokens.length > 1) && tokens[1].equals("Up")) {
+ depth--;
+ }
+ // "Old" - just a transition, no need to push a new state
+ else if ((tokens.length > 2) && tokens[0].equals("Old")) {
+ newState = Integer.parseInt(tokens[2]);
+ spd.transitions.add(
+ new Transition(stack[depth], newState));
+ }
+ // "Stack" - have never occurred
+ // When it does you'll have to figure out what to do!
+ else if ((tokens.length > 2) && tokens[0].equals("Stack")) {
+ // For now, I don't know why this is here.....
+ System.out.println("Stack line = " + s);
+ System.exit(3);
+ }
+ // "*spd*" - The data created by the never claim
+ else if (needNew && (tokens.length > 1) &&
+ tokens[0].equals("*spd*")) {
+ // The first time, set the number of processes and variables
+ if (State.numProcs == 0) {
+ State.numProcs = Integer.parseInt(tokens[1]);
+ offset = State.numProcs + 3;
+ State.numVars = Integer.parseInt(tokens[offset - 1]);
+ }
+ // Parse the pc values and the values of the variables
+ // and construct a new state
+ needNew = false;
+ int[] st = new int[State.numProcs];
+ String[] vn = new String[State.numVars];
+ String[] vr = new String[State.numVars];
+ for (int proc = 0; proc < State.numProcs; proc++)
+ st[proc] = Integer.parseInt(tokens[proc + 2]);
+ for (int var = 0; var < State.numVars; var++) {
+ vn[var] = tokens[offset + 2 * var];
+ vr[var] = tokens[offset + 2 * var + 1];
+ }
+
+ spd.states.add(new State(st, vn, vr));
+ }
+ }
+ try {
+ checkReader.close();
+ } catch (IOException e) {
+ spd.fileError(".chk");
+ }
+ }
+
+ // Create statement database from -d file
+ void createStatements() {
+ BufferedReader statementReader = null;
+ String s = "";
+ int proc = 0; // For detecting change of process
+ int countStatements = 0; // Count statements per process
+ spd.progress("Reading -d file");
+ try {
+ statementReader = new BufferedReader(
+ new FileReader(fileName + ".d"));
+ } catch (IOException e) {
+ spd.fileError(".d");
+ }
+
+ while (true) {
+ try {
+ s = statementReader.readLine();
+ } catch (IOException e) {
+ spd.fileError(".d");
+ }
+ if (s == null) {
+ if (spd.trailCode != 3)
+ spd.fileError(".d (the never claim may be missing)");
+ break;
+ }
+
+ // Start of never claim - terminate processing
+ else if (s.indexOf("claim never") != -1) {
+ spd.statementsPerProcess.add(
+ new Integer(countStatements));
+ break;
+ }
+
+ // Beginning of transitions of a process - store and reset count
+ else if (s.indexOf("proctype") != -1) {
+ if (proc != 0)
+ spd.statementsPerProcess.add(
+ new Integer(countStatements));
+ countStatements = 0;
+ proc++;
+ }
+
+ // Entry for each transition
+ else if (s.indexOf("-> state") != -1) {
+ countStatements++;
+ // For Spin 6 the format for the line number is different
+ int arrow = s.indexOf("=>");
+ int lineNumber;
+ if (Integer.valueOf(properties.getProperty("VERSION")).intValue() >= 6)
+ lineNumber = s.lastIndexOf(':', arrow) + 1;
+ else
+ lineNumber = s.lastIndexOf("line ", arrow) + 5;
+
+ spd.statements.add(new Statement(
+ proc - 1, // process number
+ extract(s, "state", "-(tr"), // source state
+ extract(s, "-> state", "[id"), // target state
+ extract(s, "[id", "tp"), // id number for trail
+ s.indexOf("[A") != -1, // atomic for automata
+ // source line number
+ Integer.parseInt(s.substring(lineNumber, arrow - 1)),
+ s.substring(arrow + 2).trim())); // source statement
+ }
+ }
+ try {
+ statementReader.close();
+ } catch (IOException e) {
+ spd.fileError(".d");
+ }
+ }
+
+ // Read the trail file whose entries are -
+ // "sequence number : process number : transition id"
+ // Sequence number = -2 means there is a never claim
+ // In that case, ignore its transitions (process number 0)
+ void readTrail() {
+ BufferedReader trailReader = null;
+ boolean claim = false;
+ String s = "";
+ spd.progress("Reading trail file");
+ try {
+ trailReader = new BufferedReader(
+ new FileReader(fileName + ".pml.trail"));
+ } catch (IOException e) {
+ spd.fileError(".pml.trail");
+ return;
+ }
+
+ while (true) {
+ try {
+ s = trailReader.readLine();
+ } catch (IOException e) {
+ spd.fileError(".pml.tral");
+ }
+ if (s == null) break;
+ String[] t = s.split(":");
+ if (t[0].startsWith("-2")) {
+ claim = true;
+ continue;
+ }
+ if ((t[0].charAt(0) == '-')) continue;
+ if (claim && (t[1].charAt(0) == '0')) continue;
+ Trail tr = new Trail(Integer.valueOf(t[2]).intValue());
+ spd.trails.add(tr);
+ }
+ try {
+ trailReader.close();
+ } catch (IOException e) {
+ spd.fileError(".pml.trail");
+ }
+ }
+
+}
diff --git a/src/main/java/com/spinroot/spinSpider/SetTrail.java b/src/main/java/com/spinroot/spinSpider/SetTrail.java
new file mode 100644
index 0000000..c0a85ae
--- /dev/null
+++ b/src/main/java/com/spinroot/spinSpider/SetTrail.java
@@ -0,0 +1,67 @@
+/* Copyright 2006 by Mordechai (Moti) Ben-Ari. See copyright.txt */
+/*
+ * Use the trail file to give attributes to states and transitions
+*/
+
+package com.spinroot.spinSpider;
+
+class SetTrail {
+ SpinSpider spd;
+
+ SetTrail(SpinSpider s) {
+ spd = s;
+ }
+
+ // Traverse the state diagram according to the trail file
+ void setTrail() {
+ int i = 0;
+ if (spd.states.size() == 0) return;
+
+ // Start from first state
+ spd.states.get(i).inTrail = true;
+ // For each line in the trail, find a statement with matching id
+ for (Trail tr : spd.trails) {
+ Statement st = null;
+ for (Statement stmt : spd.statements)
+ if (stmt.id == tr.id) {
+ st = stmt;
+ break;
+ }
+ // Set trail flag for the state obtained by taking
+ // this transition in the trail
+ i = findNewState(i, st);
+ spd.states.get(i).inTrail = true;
+ }
+ }
+
+ // Starting from state "index", find where the state where
+ // statement "stmt" goes to
+ private int findNewState(int index, Statement stmt) {
+ boolean ok;
+ State currentState = spd.states.get(index);
+ for (State s : spd.states) {
+ ok = true;
+ // For each process, the location is the same,
+ // except for the process executed by this statement,
+ // in which case the new state is reached by the statement
+ for (int i = 0; i < s.s.length; i++) {
+ if (i == stmt.process) ok = ok && (s.s[i] == stmt.targetState);
+ if (i != stmt.process) ok = ok && (s.s[i] == currentState.s[i]);
+ }
+
+ // Flag the transition
+ if (ok) {
+ boolean foundTransition = false;
+ for (Transition tr : spd.transitions)
+ if ((tr.head == index) && (tr.tail == spd.states.indexOf(s))) {
+ tr.inTrail = true;
+ foundTransition = true;
+ }
+ if (foundTransition)
+ return spd.states.indexOf(s);
+ else continue;
+ }
+ }
+ return 0;
+ }
+}
diff --git a/spinSpider/SpinSpider.java b/src/main/java/com/spinroot/spinSpider/SpinSpider.java
similarity index 51%
rename from spinSpider/SpinSpider.java
rename to src/main/java/com/spinroot/spinSpider/SpinSpider.java
index 665ca03..d17ae38 100644
--- a/spinSpider/SpinSpider.java
+++ b/src/main/java/com/spinroot/spinSpider/SpinSpider.java
@@ -1,286 +1,286 @@
-/*
- SpinSpider - Use Spin to Create State Transition Diagrams
- Copyright 2005 by Mordechai (Moti) Ben-Ari.
-
-This program 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.
-This program 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 this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.
-*/
-
-//package jspin.spinSpider;
-package spinSpider;
-
-import java.io.*;
-import java.util.ArrayList;
-import java.util.Properties;
-
-public class SpinSpider {
-
- // The following two variables are passed from jSpin
- // For standalone execution, properties is set in the main method
- // and output is to standard output
- Properties properties;
- private javax.swing.JTextArea area;
-
- String fileName; // File name (without extension)
- String extension; // Extension of Promela file name
- String format; // Graph format (dot/fsm/png ...)
- int trailCode; // Use trail file to draw or emphasize a computation
- int dotSize; // Size of dot graph
- int trailStyle; // Style of trail in dot graph color/bold
- private boolean debug; // Write debug file
- // For writing never claim:
- private int numProcs; // Number of processes -
- // write never claim if numProcs > 0
- private String[] vars; // Names of variables
-
- // Databases
- ArrayList states =
- new ArrayList(Config.INITIAL);
- ArrayList statements =
- new ArrayList(Config.INITIAL);
- ArrayList transitions =
- new ArrayList(Config.INITIAL);
- ArrayList trails =
- new ArrayList(Config.INITIAL);
-
- // For FSM we need to compute the number of statements per process
- ArrayList statementsPerProcess =
- new ArrayList(Config.INITIAL);
-
- public SpinSpider(
- String fileName,
- String extension,
- String format,
- int numProcs,
- String[] vars,
- boolean debug,
- int trailCode,
- int dotSize,
- int trailStyle,
- javax.swing.JTextArea area,
- Properties properties) {
- this.fileName = fileName;
- this.extension = extension;
- this.format = format;
- this.numProcs = numProcs;
- this.vars = vars;
- this.debug = debug;
- this.trailCode = trailCode;
- this.dotSize = dotSize;
- this.trailStyle = trailStyle;
- this.area = area;
- this.properties = properties;
- State.numProcs = 0;
- State.numVars = 0;
- }
-
- // Create array of tokens from a string for ProcessBuilder
- private static String[] stringToArray(String s) {
- java.util.StringTokenizer st = new java.util.StringTokenizer(s);
- int count = st.countTokens();
- String[] sa = new String[count];
- for (int i = 0; i < count; i++)
- sa[i] = st.nextToken();
- return sa;
- }
-
- // Build a process and run it
- // command is the command string with parameters
- // ext is the extension for redirecting standard output
- // if null, output is sent to System.out
- void runProcess(String command, String ext) {
- PrintWriter outWriter = null;
- progress("Running " + command);
- if (ext != null)
- try {
- outWriter = new PrintWriter(new FileWriter(fileName + ext));
- } catch (IOException e) { fileError(ext); }
- try {
- ProcessBuilder pb = new ProcessBuilder(stringToArray(command));
- File pf = new File(fileName).getParentFile();
- if (pf != null) pb.directory(pf.getCanonicalFile());
- pb.redirectErrorStream(true);
- Process p = pb.start();
- BufferedReader input =
- new BufferedReader(new InputStreamReader(p.getInputStream()));
- String s;
- while (true) {
- s = input.readLine();
- if (s == null) break;
- if (ext == null) System.out.println(s);
- else outWriter.println(s);
- }
- p.waitFor();
- if (ext != null) outWriter.close();
- } catch (IOException e) {
- progress("IO exception " + e.getMessage() +
- " while executing " + command);
- } catch (InterruptedException e) {
- progress("Interrupted exception while executing " + command);
- }
- }
-
- // This method runs SpinSpider
- public boolean runSpider() {
- progress(Config.TITLE);
- // Create objects for reading and writing files
- Write write = new Write(this, fileName);
- Read read = new Read(this, fileName, properties);
-
- // Write never claim if requested
- String never = "";
- if (trailCode != 3) {
- if (!write.writeNeverClaim(numProcs, vars)) return false;
- never = " -N " + fileName + ".nvr ";
- }
-
- // Run Spin and C compiler
- runProcess(properties.getProperty("SPIN") +
- " -a -o3 " + never + fileName + extension, null);
- runProcess(properties.getProperty("C_COMPILER") +
- " -DCHECK -DSAFETY -DPRINTF -DNOREDUCE -o pan pan.c", null);
-
- // Run pan twice: once for -DCHECK file and once for -d file
- String pan = "";
- try {
- File f = new File(fileName).getParentFile();
- if (f != null)
- pan = f.getCanonicalPath() + java.io.File.separator;
- } catch(IOException e) {};
- pan = pan + properties.getProperty("PAN");
- if (trailCode != 3) runProcess(pan, ".chk");
- runProcess(pan + " -d", ".d");
-
- // Read the file created by -d
- read.createStatements();
- // Read the file created by -DCHECK and never claim
- if (trailCode != 3) read.readCheckFile();
-
- // Read the trail file
- if ((trailCode == 1) || (trailCode == 2)) {
- read.readTrail();
- new SetTrail(this).setTrail();
- }
-
- // Write output files
- if (debug || (trailCode == 3))
- write.writeDebug();
- if (format.equals("fsm"))
- write.writeFSMGraph();
- else
- write.writeDotGraph();
-
- progress("Done");
- return true;
- }
-
- // Display progress messages in text area of jSpin or on standard output
- void progress(String s) {
- if (s == null)
- return;
- if (area == null) {
- System.out.println(s);
- return;
- }
- area.append(s + '\n');
- int last = area.getText().length();
- try {
- area.scrollRectToVisible(area.modelToView(last));
- area.setCaretPosition(last);
- }
- catch (javax.swing.text.BadLocationException e) {
- System.err.println(
- "Error setting caret position when writing\n" + s + "\n");
- }
- }
-
- // Print error message and exit
- static void error(String e) {
- System.err.println(e);
- System.exit(1);
- }
-
- // Print file error message and exit
- void fileError(String ext) {
- String s = "FILE ERROR " + fileName + ext;
- if (area == null) error(s); else progress(s);
- }
-
- // Main method for running independently of jSpin
- public static void main(String[] args) {
- if (args.length == 0) error(Config.USAGE);
- File file = new File(args[args.length-1]);
- String fileName = file.getName();
- String root;
- String extension = "";
- if (fileName.lastIndexOf('.') != -1) {
- extension = fileName.substring(fileName.lastIndexOf('.'));
- }
- if (file.getParentFile() == null)
- root = "";
- else
- root = file.getParentFile().getAbsolutePath();
- fileName = root + File.separator +
- fileName.substring(0, fileName.lastIndexOf('.'));
-
- boolean debug = false;
- boolean automata = false;
- int trailCode = 0;
- int dotSize = 1;
- int trailStyle = 0;
- String format = "png";
- int numProcs = 0;
- // Variable names for automatic writing of never claim
- ArrayList vars = new ArrayList(Config.INITIAL);
-
- for (int i = 0; i < args.length-1; i++)
- if (args[i].equals("-dot")) format = "dot";
- else if (args[i].equals("-fsm")) format = "fsm";
- else if (args[i].equals("-a")) automata = true;
- else if (args[i].equals("-debug")) debug = true;
- else if (args[i].equals("-small")) dotSize = 0;
- else if (args[i].equals("-bold")) trailStyle = 1;
- else if (args[i].equals("-t1")) trailCode = 1;
- else if (args[i].equals("-t2")) trailCode = 2;
- else if (args[i].startsWith("-T"))
- format = args[i].substring(2);
- else if (args[i].startsWith("-p"))
- try {
- numProcs = Integer.parseInt(args[i].substring(2));
- } catch (NumberFormatException e) {
- error(Config.USAGE);
- }
- else if (args[i].startsWith("-v"))
- vars.add(args[i].substring(2));
- else error(Config.USAGE);
-
- if (!automata && (numProcs <= 0)) error(Config.USAGE);
-
- String[] varArray = new String[vars.size()];
- varArray = vars.toArray(varArray);
-
- Properties properties = new Properties();
- Config.init(properties);
- if (automata) {
- debug = true;
- trailCode = 3;
- }
- SpinSpider spd = new SpinSpider(
- fileName, extension, format, numProcs, varArray,
- debug, trailCode, dotSize, trailStyle,
- null, properties);
- if (!spd.runSpider()) return;
- if (automata)
- new DrawAutomata(spd).drawAutomata();
- }
-}
+/*
+ SpinSpider - Use Spin to Create State Transition Diagrams
+ Copyright 2005 by Mordechai (Moti) Ben-Ari.
+
+This program 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.
+This program 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 this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.
+*/
+
+//package com.spinroot.jspin.com.spinroot.spinSpider;
+package com.spinroot.spinSpider;
+
+import java.io.*;
+import java.util.ArrayList;
+import java.util.Properties;
+
+public class SpinSpider {
+
+ // The following two variables are passed from jSpin
+ // For standalone execution, properties is set in the main method
+ // and output is to standard output
+ Properties properties;
+ String fileName; // File name (without extension)
+ String extension; // Extension of Promela file name
+ String format; // Graph format (dot/fsm/png ...)
+ int trailCode; // Use trail file to draw or emphasize a computation
+ int dotSize; // Size of dot graph
+ int trailStyle; // Style of trail in dot graph color/bold
+ // Databases
+ ArrayList states =
+ new ArrayList<>(Config.INITIAL);
+ ArrayList statements =
+ new ArrayList<>(Config.INITIAL);
+ ArrayList transitions =
+ new ArrayList<>(Config.INITIAL);
+ ArrayList trails =
+ new ArrayList<>(Config.INITIAL);
+ // For FSM we need to compute the number of statements per process
+ ArrayList statementsPerProcess =
+ new ArrayList<>(Config.INITIAL);
+ private javax.swing.JTextArea area;
+ private boolean debug; // Write debug file
+ // For writing never claim:
+ private int numProcs; // Number of processes -
+ // write never claim if numProcs > 0
+ private String[] vars; // Names of variables
+
+ public SpinSpider(
+ String fileName,
+ String extension,
+ String format,
+ int numProcs,
+ String[] vars,
+ boolean debug,
+ int trailCode,
+ int dotSize,
+ int trailStyle,
+ javax.swing.JTextArea area,
+ Properties properties) {
+ this.fileName = fileName;
+ this.extension = extension;
+ this.format = format;
+ this.numProcs = numProcs;
+ this.vars = vars;
+ this.debug = debug;
+ this.trailCode = trailCode;
+ this.dotSize = dotSize;
+ this.trailStyle = trailStyle;
+ this.area = area;
+ this.properties = properties;
+ State.numProcs = 0;
+ State.numVars = 0;
+ }
+
+ // Create array of tokens from a string for ProcessBuilder
+ private static String[] stringToArray(String s) {
+ java.util.StringTokenizer st = new java.util.StringTokenizer(s);
+ int count = st.countTokens();
+ String[] sa = new String[count];
+ for (int i = 0; i < count; i++)
+ sa[i] = st.nextToken();
+ return sa;
+ }
+
+ // Print error message and exit
+ static void error(String e) {
+ System.err.println(e);
+ System.exit(1);
+ }
+
+ // Main method for running independently of jSpin
+ public static void main(String[] args) {
+ if (args.length == 0) error(Config.USAGE);
+ File file = new File(args[args.length - 1]);
+ String fileName = file.getName();
+ String root;
+ String extension = "";
+ if (fileName.lastIndexOf('.') != -1) {
+ extension = fileName.substring(fileName.lastIndexOf('.'));
+ }
+ if (file.getParentFile() == null)
+ root = "";
+ else
+ root = file.getParentFile().getAbsolutePath();
+ fileName = root + File.separator +
+ fileName.substring(0, fileName.lastIndexOf('.'));
+
+ boolean debug = false;
+ boolean automata = false;
+ int trailCode = 0;
+ int dotSize = 1;
+ int trailStyle = 0;
+ String format = "png";
+ int numProcs = 0;
+ // Variable names for automatic writing of never claim
+ ArrayList vars = new ArrayList(Config.INITIAL);
+
+ for (int i = 0; i < args.length - 1; i++)
+ if (args[i].equals("-dot")) format = "dot";
+ else if (args[i].equals("-fsm")) format = "fsm";
+ else if (args[i].equals("-a")) automata = true;
+ else if (args[i].equals("-debug")) debug = true;
+ else if (args[i].equals("-small")) dotSize = 0;
+ else if (args[i].equals("-bold")) trailStyle = 1;
+ else if (args[i].equals("-t1")) trailCode = 1;
+ else if (args[i].equals("-t2")) trailCode = 2;
+ else if (args[i].startsWith("-T"))
+ format = args[i].substring(2);
+ else if (args[i].startsWith("-p"))
+ try {
+ numProcs = Integer.parseInt(args[i].substring(2));
+ } catch (NumberFormatException e) {
+ error(Config.USAGE);
+ }
+ else if (args[i].startsWith("-v"))
+ vars.add(args[i].substring(2));
+ else error(Config.USAGE);
+
+ if (!automata && (numProcs <= 0)) error(Config.USAGE);
+
+ String[] varArray = new String[vars.size()];
+ varArray = vars.toArray(varArray);
+
+ Properties properties = new Properties();
+ Config.init(properties);
+ if (automata) {
+ debug = true;
+ trailCode = 3;
+ }
+ SpinSpider spd = new SpinSpider(
+ fileName, extension, format, numProcs, varArray,
+ debug, trailCode, dotSize, trailStyle,
+ null, properties);
+ if (!spd.runSpider()) return;
+ if (automata)
+ new DrawAutomata(spd).drawAutomata();
+ }
+
+ // Build a process and run it
+ // command is the command string with parameters
+ // ext is the extension for redirecting standard output
+ // if null, output is sent to System.out
+ void runProcess(String command, String ext) {
+ PrintWriter outWriter = null;
+ progress("Running " + command);
+ if (ext != null)
+ try {
+ outWriter = new PrintWriter(new FileWriter(fileName + ext));
+ } catch (IOException e) {
+ fileError(ext);
+ }
+ try {
+ ProcessBuilder pb = new ProcessBuilder(stringToArray(command));
+ File pf = new File(fileName).getParentFile();
+ if (pf != null) pb.directory(pf.getCanonicalFile());
+ pb.redirectErrorStream(true);
+ Process p = pb.start();
+ BufferedReader input =
+ new BufferedReader(new InputStreamReader(p.getInputStream()));
+ String s;
+ while (true) {
+ s = input.readLine();
+ if (s == null) break;
+ if (ext == null) System.out.println(s);
+ else outWriter.println(s);
+ }
+ p.waitFor();
+ if (ext != null) outWriter.close();
+ } catch (IOException e) {
+ progress("IO exception " + e.getMessage() +
+ " while executing " + command);
+ } catch (InterruptedException e) {
+ progress("Interrupted exception while executing " + command);
+ }
+ }
+
+ // This method runs SpinSpider
+ public boolean runSpider() {
+ progress(Config.TITLE);
+ // Create objects for reading and writing files
+ Write write = new Write(this, fileName);
+ Read read = new Read(this, fileName, properties);
+
+ // Write never claim if requested
+ String never = "";
+ if (trailCode != 3) {
+ if (!write.writeNeverClaim(numProcs, vars)) return false;
+ never = " -N " + fileName + ".nvr ";
+ }
+
+ // Run Spin and C compiler
+ runProcess(properties.getProperty("SPIN") +
+ " -a -o3 " + never + fileName + extension, null);
+ runProcess(properties.getProperty("C_COMPILER") +
+ " -DCHECK -DSAFETY -DPRINTF -DNOREDUCE -o pan pan.c", null);
+
+ // Run pan twice: once for -DCHECK file and once for -d file
+ String pan = "";
+ try {
+ File f = new File(fileName).getParentFile();
+ if (f != null)
+ pan = f.getCanonicalPath() + java.io.File.separator;
+ } catch (IOException e) {
+ }
+ pan = pan + properties.getProperty("PAN");
+ if (trailCode != 3) runProcess(pan, ".chk");
+ runProcess(pan + " -d", ".d");
+
+ // Read the file created by -d
+ read.createStatements();
+ // Read the file created by -DCHECK and never claim
+ if (trailCode != 3) read.readCheckFile();
+
+ // Read the trail file
+ if ((trailCode == 1) || (trailCode == 2)) {
+ read.readTrail();
+ new SetTrail(this).setTrail();
+ }
+
+ // Write output files
+ if (debug || (trailCode == 3))
+ write.writeDebug();
+ if (format.equals("fsm"))
+ write.writeFSMGraph();
+ else
+ write.writeDotGraph();
+
+ progress("Done");
+ return true;
+ }
+
+ // Display progress messages in text area of jSpin or on standard output
+ void progress(String s) {
+ if (s == null)
+ return;
+ if (area == null) {
+ System.out.println(s);
+ return;
+ }
+ area.append(s + '\n');
+ int last = area.getText().length();
+ try {
+ area.scrollRectToVisible(area.modelToView(last));
+ area.setCaretPosition(last);
+ } catch (javax.swing.text.BadLocationException e) {
+ System.err.println(
+ "Error setting caret position when writing\n" + s + "\n");
+ }
+ }
+
+ // Print file error message and exit
+ void fileError(String ext) {
+ String s = "FILE ERROR " + fileName + ext;
+ if (area == null) error(s);
+ else progress(s);
+ }
+}
diff --git a/spinSpider/State.java b/src/main/java/com/spinroot/spinSpider/State.java
similarity index 64%
rename from spinSpider/State.java
rename to src/main/java/com/spinroot/spinSpider/State.java
index 7d76d13..d3dbcd3 100644
--- a/spinSpider/State.java
+++ b/src/main/java/com/spinroot/spinSpider/State.java
@@ -1,35 +1,36 @@
-/* Copyright 2005-6 by Mordechai (Moti) Ben-Ari. See copyright.txt */
-/*
- * Definine a state of the state transition diagram
-*/
-
-package spinSpider;
-class State {
- // Static variables
- // The number of processes and variables is
- // the same for all *spd* lines printed out
- static int numProcs;
- static int numVars;
-
- // Variables for each state
- int[] s; // pc_value for each process
- String[] vname; // Name for each variable
- String[] v; // Value for each variable
- boolean inTrail; // Is this state in the trail?
-
- public State(int[] st, String[] vn, String[] vr) {
- s = st;
- vname = vn;
- v = vr;
- inTrail = false;
- }
-
- public String toString() {
- String str = "(";
- for (int proc = 0; proc < numProcs; proc++)
- str = str + ((proc == 0) ? "" : ",") + s[proc];
- for (int var = 0; var < numVars; var++)
- str = str + "," + vname[var] + "=" + v[var];
- return str + ")" + (inTrail ? " *" : "");
- }
-}
+/* Copyright 2005-6 by Mordechai (Moti) Ben-Ari. See copyright.txt */
+/*
+ * Definine a state of the state transition diagram
+*/
+
+package com.spinroot.spinSpider;
+
+class State {
+ // Static variables
+ // The number of processes and variables is
+ // the same for all *spd* lines printed out
+ static int numProcs;
+ static int numVars;
+
+ // Variables for each state
+ int[] s; // pc_value for each process
+ String[] vname; // Name for each variable
+ String[] v; // Value for each variable
+ boolean inTrail; // Is this state in the trail?
+
+ public State(int[] st, String[] vn, String[] vr) {
+ s = st;
+ vname = vn;
+ v = vr;
+ inTrail = false;
+ }
+
+ public String toString() {
+ StringBuilder str = new StringBuilder("(");
+ for (int proc = 0; proc < numProcs; proc++)
+ str.append((proc == 0) ? "" : ",").append(s[proc]);
+ for (int var = 0; var < numVars; var++)
+ str.append(",").append(vname[var]).append("=").append(v[var]);
+ return str + ")" + (inTrail ? " *" : "");
+ }
+}
diff --git a/spinSpider/Statement.java b/src/main/java/com/spinroot/spinSpider/Statement.java
similarity index 63%
rename from spinSpider/Statement.java
rename to src/main/java/com/spinroot/spinSpider/Statement.java
index 939b5b1..df55205 100644
--- a/spinSpider/Statement.java
+++ b/src/main/java/com/spinroot/spinSpider/Statement.java
@@ -1,39 +1,40 @@
-/* Copyright 2005-6 by Mordechai (Moti) Ben-Ari. See copyright.txt */
-/*
- * Process a source statement
-*/
-
-package spinSpider;
-class Statement {
- int process; // Process where the statement is declared
- int sourceState; // Source state
- int targetState; // Target state
- int id; // Used for trail
- boolean atomic; // Atomic statement (for automata)
- int line; // Line number of source statement
- String source; // Source code statement
-
- public Statement(int p, int s, int t, int i, boolean a, int l, String src) {
- process = p;
- sourceState = s;
- id = i;
- targetState = t;
- atomic = a;
- line = l;
- if (src.indexOf("printf") != -1) // Remove printf and quotes
- src = src.substring(src.indexOf("printf")+8, src.indexOf("\\n"));
- src = src.replaceAll("[()]", ""); // Remove parentheses
- source = src.trim();
- }
-
- public String toString() {
- return
- "process=" + process +
- ", source=" + sourceState +
- ", target=" + targetState +
- ", id=" + id +
- (atomic ? ", atomic" : "") +
- ", line=" + line +
- "." + source;
- }
+/* Copyright 2005-6 by Mordechai (Moti) Ben-Ari. See copyright.txt */
+/*
+ * Process a source statement
+*/
+
+package com.spinroot.spinSpider;
+
+class Statement {
+ int process; // Process where the statement is declared
+ int sourceState; // Source state
+ int targetState; // Target state
+ int id; // Used for trail
+ boolean atomic; // Atomic statement (for automata)
+ int line; // Line number of source statement
+ String source; // Source code statement
+
+ public Statement(int p, int s, int t, int i, boolean a, int l, String src) {
+ process = p;
+ sourceState = s;
+ id = i;
+ targetState = t;
+ atomic = a;
+ line = l;
+ if (src.indexOf("printf") != -1) // Remove printf and quotes
+ src = src.substring(src.indexOf("printf") + 8, src.indexOf("\\n"));
+ src = src.replaceAll("[()]", ""); // Remove parentheses
+ source = src.trim();
+ }
+
+ public String toString() {
+ return
+ "process=" + process +
+ ", source=" + sourceState +
+ ", target=" + targetState +
+ ", id=" + id +
+ (atomic ? ", atomic" : "") +
+ ", line=" + line +
+ "." + source;
+ }
}
\ No newline at end of file
diff --git a/spinSpider/Trail.java b/src/main/java/com/spinroot/spinSpider/Trail.java
similarity index 87%
rename from spinSpider/Trail.java
rename to src/main/java/com/spinroot/spinSpider/Trail.java
index 97fa504..4df4c2d 100644
--- a/spinSpider/Trail.java
+++ b/src/main/java/com/spinroot/spinSpider/Trail.java
@@ -1,16 +1,17 @@
-/* Copyright 2005-6 by Mordechai (Moti) Ben-Ari. See copyright.txt */
-/* Transitions obtained by processing New/Old/Up/Down in -DCHECK file
- */
-
-package spinSpider;
-class Trail {
- int id;
-
- public Trail(int i) {
- id = i;
- }
-
- public String toString() {
- return "id " + id;
- }
-};
+/* Copyright 2005-6 by Mordechai (Moti) Ben-Ari. See copyright.txt */
+/* Transitions obtained by processing New/Old/Up/Down in -DCHECK file
+ */
+
+package com.spinroot.spinSpider;
+
+class Trail {
+ int id;
+
+ public Trail(int i) {
+ id = i;
+ }
+
+ public String toString() {
+ return "id " + id;
+ }
+}
diff --git a/spinSpider/Transition.java b/src/main/java/com/spinroot/spinSpider/Transition.java
similarity index 61%
rename from spinSpider/Transition.java
rename to src/main/java/com/spinroot/spinSpider/Transition.java
index 93f999c..79ff828 100644
--- a/spinSpider/Transition.java
+++ b/src/main/java/com/spinroot/spinSpider/Transition.java
@@ -1,21 +1,22 @@
-/* Copyright 2005-6 by Mordechai (Moti) Ben-Ari. See copyright.txt */
-/*
- * Defining a transition of the state transition diagram
-*/
-
-package spinSpider;
-class Transition {
- int head; // head state
- int tail; // tail state
- boolean inTrail; // Is this transition in the trail?
-
- public Transition(int h, int t) {
- head = h;
- tail = t;
- inTrail = false;
- }
-
- public String toString() {
- return head + " -> " + tail + (inTrail ? " *" : "");
- }
-}
+/* Copyright 2005-6 by Mordechai (Moti) Ben-Ari. See copyright.txt */
+/*
+ * Defining a transition of the state transition diagram
+*/
+
+package com.spinroot.spinSpider;
+
+class Transition {
+ final int head; // head state
+ final int tail; // tail state
+ boolean inTrail; // Is this transition in the trail?
+
+ public Transition(int head, int tail) {
+ this.head = head;
+ this.tail = tail;
+ inTrail = false;
+ }
+
+ public String toString() {
+ return head + " -> " + tail + (inTrail ? " *" : "");
+ }
+}
diff --git a/src/main/java/com/spinroot/spinSpider/Write.java b/src/main/java/com/spinroot/spinSpider/Write.java
new file mode 100644
index 0000000..f3a2d6e
--- /dev/null
+++ b/src/main/java/com/spinroot/spinSpider/Write.java
@@ -0,0 +1,270 @@
+/* Copyright 2005-7 by Mordechai (Moti) Ben-Ari. See copyright.txt */
+/*
+ * Write the output in different formats
+*/
+
+package com.spinroot.spinSpider;
+
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+public class Write {
+ SpinSpider spd;
+
+ Write(SpinSpider s, String f) {
+ spd = s;
+ }
+
+ // Write the never claim from the number of processes and
+ // the names of the variables
+ boolean writeNeverClaim(int numProcs, String[] vars) {
+ PrintWriter neverWriter = null;
+ spd.progress("Writing never claim");
+ if (vars.length == 0) {
+ spd.progress("No variables for never claim");
+ return false;
+ }
+ try {
+ neverWriter = new PrintWriter(new FileWriter(spd.fileName + ".nvr"));
+ } catch (IOException e) {
+ spd.fileError(".nvr");
+ }
+
+ neverWriter.print("never {\n\tdo\n\t:: printf(\"*spd* " + numProcs);
+ for (int i = 0; i < numProcs; i++)
+ neverWriter.print(" %d");
+ neverWriter.print(" " + vars.length);
+ for (int i = 0; i < vars.length; i++)
+ neverWriter.print(" " + vars[i] + " %d");
+ neverWriter.print("\\n\",\n\t\t");
+ for (int i = 0; i < numProcs; i++)
+ neverWriter.print("pc_value(" + i + "), ");
+ for (int i = 0; i < vars.length; i++)
+ neverWriter.print((i == 0 ? "" : ", ") + vars[i]);
+ neverWriter.println(")\n\tod\n}");
+ neverWriter.close();
+ return true;
+ }
+
+ // Write the graph in dot format - nodes and edges
+ // trailCode = 0 (no trail), 1 (emphasize trail), 2 (just trail)
+ void writeDotGraph() {
+ PrintWriter graphWriter = null;
+ String fn = spd.fileName + Config.names[spd.trailCode];
+ String label; // Building the label in this string
+ int numStates = 0; // For printing a node number
+ String[] dotPrologue =
+ spd.dotSize == 0 ? Config.smallDotPrologue : Config.largeDotPrologue;
+ String dotTrail =
+ spd.trailStyle == 0 ? Config.dotTrailColor : Config.dotTrailBold;
+
+ spd.progress("Writing dot file");
+ try {
+ graphWriter = new PrintWriter(new FileWriter(fn + ".dot"));
+ } catch (IOException e) {
+ spd.fileError(".dot");
+ }
+
+ // Write dot prologue
+ graphWriter.println("digraph \"" + fn + "\"" + " {");
+ for (int i = 0; i < dotPrologue.length; i++)
+ graphWriter.println(dotPrologue[i]);
+
+ // Write states
+ for (State st : spd.states) {
+ label = (numStates++) + " [label=\"";
+ for (int proc = 0; proc < State.numProcs; proc++)
+ for (Statement t : spd.statements)
+ if ((t.process == proc) &&
+ (t.sourceState == st.s[proc]))
+ label = label + t.line + ". " + t.source + "\\n";
+ for (int var = 0; var < State.numVars; var++)
+ label = label + " " + st.v[var];
+ graphWriter.print(label + "\"");
+ if ((spd.trailCode == 1) && st.inTrail)
+ graphWriter.print(dotTrail);
+ if ((spd.trailCode == 2) && !st.inTrail)
+ graphWriter.print(" style = invis ");
+ graphWriter.println("];");
+ }
+
+ // Write transitions
+ for (Transition t : spd.transitions) {
+ graphWriter.print(t.head + " -> " + t.tail);
+ if ((spd.trailCode == 1) && t.inTrail)
+ graphWriter.print(" [" + dotTrail + "]");
+ if ((spd.trailCode == 2) && !t.inTrail)
+ graphWriter.print(" [ style = invis ]");
+ graphWriter.println(";");
+ }
+ graphWriter.println("}");
+ graphWriter.close();
+ if ((spd.trailCode != 3) && !spd.format.equals("dot"))
+ spd.runProcess(spd.properties.getProperty("DOT") +
+ " -T" + spd.format +
+ " -o " + fn + "." + spd.format + " " +
+ fn + ".dot", null);
+ }
+
+ // Write the graph in fsm format
+ // This format is used by tools developed at the
+ // Eindhoven University of Technology
+ void writeFSMGraph() {
+ int offset;
+ PrintWriter graphWriter = null;
+ spd.progress("Writing fsm file");
+ try {
+ graphWriter = new PrintWriter(new FileWriter(spd.fileName + ".fsm"));
+ } catch (IOException e) {
+ spd.fileError(".fsm");
+ }
+
+ // If the program terminates there is an end statement
+ // that is not a "source" in the -d file
+ // Add dummy statements at the end of the "statements" data structure
+ // spp1 is the original statementsPerProcess
+ // spp2 is statementsPerProcess with added dummy statements
+ int[] spp1 = new int[spd.statementsPerProcess.size()];
+ int[] spp2 = new int[spd.statementsPerProcess.size()];
+ for (int i = 0; i < spp1.length; i++) {
+ spp1[i] = spd.statementsPerProcess.get(i).intValue();
+ spp2[i] = spp1[i];
+ }
+ boolean[] endStates = new boolean[State.numProcs];
+ for (int i = 0; i < spd.statements.size(); i++) {
+ Statement st = spd.statements.get(i);
+ if ((st.targetState == 0) && (!endStates[st.process])) {
+ spd.statements.add(new Statement(st.process, 0, 0, 0, false, 0, ""));
+ spp2[st.process]++;
+ endStates[st.process] = true;
+ }
+ }
+
+ // Compute fan in and fan out of each node
+ int[] fanIn = new int[spd.states.size()];
+ int[] fanOut = new int[spd.states.size()];
+ for (int i = 0; i < spd.transitions.size(); i++) {
+ fanIn[spd.transitions.get(i).tail]++;
+ fanOut[spd.transitions.get(i).head]++;
+ }
+ // Compute the maximum fan in and fan out in the diagram
+ int maxFanIn = 0, maxFanOut = 0;
+ for (int i = 0; i < spd.states.size(); i++) {
+ if (fanIn[i] > maxFanIn) maxFanIn = fanIn[i];
+ if (fanOut[i] > maxFanOut) maxFanOut = fanOut[i];
+ }
+ maxFanIn++;
+ maxFanOut++;
+
+ // Processes:
+ // "p" + number of process + "(" + statements per process + ")"
+ // + "String" + list of statements
+ offset = 0;
+ for (int proc = 0; proc < State.numProcs; proc++) {
+ graphWriter.print("p" + (proc + 1) +
+ "(" + spp2[proc] + ") String");
+ for (int stmt = 0; stmt < spp1[proc]; stmt++) {
+ Statement stm = spd.statements.get(offset + stmt);
+ graphWriter.print(" \"" + stm.line + "," + stm.source + "\"");
+ }
+ offset = offset + spp1[proc];
+ if (spp2[proc] > spp1[proc])
+ graphWriter.print(" \" end state \"");
+ graphWriter.println();
+ }
+
+ // Variables:
+ // name of variable + "(" + number of values + ")"
+ // + "Nat" + list of values
+ for (int var = 0; var < State.numVars; var++) {
+ int max = 0;
+ for (State st : spd.states) {
+ int val = Integer.parseInt(st.v[var]);
+ if (val > max) max = val;
+ }
+ graphWriter.print(spd.states.get(0).vname[var] + "(" + (max + 1) + ") Nat");
+ for (int i = 0; i <= max; i++)
+ graphWriter.print(" \"" + i + "\"");
+ graphWriter.println();
+ }
+
+ // Fan in, fan out, node nr
+ graphWriter.print("fan_in(" + maxFanIn + ") Nat");
+ for (int i = 0; i < maxFanIn; i++)
+ graphWriter.print(" \"" + i + "\"");
+ graphWriter.println();
+ graphWriter.print("fan_out(" + maxFanOut + ") Nat");
+ for (int i = 0; i < maxFanOut; i++)
+ graphWriter.print(" \"" + i + "\"");
+ graphWriter.println();
+ graphWriter.println("node_nr(0)");
+ graphWriter.println("---");
+
+ // States:
+ // Process location counters (relative to lists above!)
+ // Values of variables
+ // Fan-in and fan-out
+ int stateCount = 0;
+ for (State st : spd.states) {
+ offset = 0;
+ for (int proc = 0; proc < State.numProcs; proc++) {
+ boolean found = false;
+ for (int i = 0; i < spp1[proc]; i++)
+ if (spd.statements.get(offset + i).sourceState == st.s[proc]) {
+ graphWriter.print(i + " ");
+ found = true;
+ break;
+ }
+ if (!found) {
+ graphWriter.print((spp2[proc] - 1) + " ");
+ }
+ offset = offset + spp1[proc];
+ }
+ for (int var = 0; var < State.numVars; var++)
+ graphWriter.print(st.v[var] + " ");
+ graphWriter.print(fanIn[stateCount] + " " +
+ fanOut[stateCount] + " " + (stateCount + 1));
+ stateCount++;
+ graphWriter.println();
+ }
+ graphWriter.println("---");
+
+ // Transitions
+ for (Transition t : spd.transitions)
+ graphWriter.println((t.head + 1) + " " + (t.tail + 1));
+ graphWriter.close();
+ }
+
+ // Write debug file using toString defined in each class
+ void writeDebug() {
+ PrintWriter debugWriter = null;
+ spd.progress("Writing debug file");
+ try {
+ debugWriter = new PrintWriter(
+ new FileWriter(spd.fileName + ".dbg"));
+ } catch (IOException e) {
+ spd.fileError(".dbg");
+ }
+
+ debugWriter.println("States");
+ int n = 0;
+ for (State s : spd.states)
+ debugWriter.println((n++) + ". " + s);
+
+ debugWriter.println("\nTransitions");
+ for (Transition t : spd.transitions)
+ debugWriter.println(t);
+
+ debugWriter.println("\nStatements from -d file");
+ for (Statement st : spd.statements)
+ debugWriter.println(st);
+
+ if (spd.trailCode > 0) {
+ debugWriter.println("\nTrail");
+ for (Trail tr : spd.trails)
+ debugWriter.println(tr);
+ }
+ debugWriter.close();
+ }
+}
diff --git a/txt/copyright.txt b/txt/copyright.txt
index 25631ca..1bd8720 100644
--- a/txt/copyright.txt
+++ b/txt/copyright.txt
@@ -1,17 +1,17 @@
- jSpin - Java Graphical User Interface for Spin
- SpinSpider - Automatic Generation of State Transition Diagrams
- (See title bar for version number)
- Copyright 2003-10 by Mordechai (Moti) Ben-Ari.
-
-This program 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.
-This program 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 this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.
+ jSpin - Java Graphical User Interface for Spin
+ SpinSpider - Automatic Generation of State Transition Diagrams
+ (See title bar for version number)
+ Copyright 2003-10 by Mordechai (Moti) Ben-Ari.
+
+This program 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.
+This program 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 this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.
diff --git a/txt/help.txt b/txt/help.txt
index 6bf110d..5d7064c 100644
--- a/txt/help.txt
+++ b/txt/help.txt
@@ -1,80 +1,80 @@
- jSpin - Java Graphical User Interface for Spin
- SpinSpider - Automatic Generation of State Transition Diagrams
- (See title bar for version number)
- Copyright 2003-10 by Mordechai (Moti) Ben-Ari.
-
-jSpin is a graphical user interface for the Spin Model Checker
-that is used for verifying concurrent and distributed programs.
-The Spin website is http://spinroot.com.
-The jSpin website is
-http://stwww.weizmann.ac.il/g-cs/benari/jspin/.
-
-PLEASE READ THE MANUALS jspin-user.pdf and spider-use.pdf!!
-In particular, read the sections on installation,
-configuration and troubleshooting.
-This Help file presents a short description of the menus.
-
-File:
-New, Open, Save, Save As, and Exit are standard.
-Switch file closes the current file and opens the previous one.
-
-Editor:
-Undo, Redo, Copy, Cut, Paste, Find and Find again are standard.
-
-Spin:
-Run Spin in one of five modes:
-Check runs a syntax check.
-Random runs a random simulation.
-Interactive runs an interactive simulation.
-Verify runs an verification.
-Guided runs a guided simulation using the trail file created
-by the execution of the analyzer.
-
-Convert:
-Load loads a .prp file into the LTL formula field:
-Clear clears the field.
-Translate translates it into a never claim stored in a .ltl file.
-LTL Name selects an internal LTL formula to use for verification.
-
-Options - change the option strings used with Spin:
-Common is used to select which data to display for Random,
-Interactive and Trail: statements, local and global variables
-and messages sent and received.
-The next options are for running the Spin sequence:
- Spin: Check, Random, Interactive, Verify, Trail.
- C Compiler.
- Pan.
-Default restores the defaults of all options and settings.
-Save saves the options, settings and the current directory for File/Open.
-
-Settings - change settings for verification and display:
-Max steps for Random, Interactive and Trail modes.
-Max depth for search depth when running the pan verifier.
-Seed - if non-zero its value is used for Random simulation.
-Weak fairness during verification.
-Safety, Acceptance, Non-progress verification modes.
-
-Output - control display of filtered Spin output:
-Maximize the right text area that displays the output.
-Exclude variables - exclude (and include) these variables in the display.
-Exclude statements - exclude (and include) these statements in the display.
-Variable width - width of the columns used to display the variable values.
-Save output - saves the filtered Spin output in a file with extension .out.
-Raw output - saves the unfiltered Spin output in a file with extension .raw.
-Display raw - displays this file for debugging purposes.
-
-SpinSpider:
-Display debug - display the debug file created by SpinSpider.
-SpiderSpider - popup SpinSpider dialog:
- Format - graphical output format
- Dot size - size parameter for dot
- Trail style - emphasize with color or bold
- Variables - a list of the variables in the program must be given
- Processes - the number of processes
- Radio buttons:
- No trail - display state diagram without trail (if any)
- Emphasize/only trail - a trail from a verification must exist
- Automata - display the processes as automata
-
-Help:
-Help and About are standard.
+ jSpin - Java Graphical User Interface for Spin
+ SpinSpider - Automatic Generation of State Transition Diagrams
+ (See title bar for version number)
+ Copyright 2003-10 by Mordechai (Moti) Ben-Ari.
+
+jSpin is a graphical user interface for the Spin Model Checker
+that is used for verifying concurrent and distributed programs.
+The Spin website is http://spinroot.com.
+The jSpin website is
+http://stwww.weizmann.ac.il/g-cs/benari/com.spinroot.jspin/.
+
+PLEASE READ THE MANUALS com.spinroot.jspin-user.pdf and spider-use.pdf!!
+In particular, read the sections on installation,
+configuration and troubleshooting.
+This Help file presents a short description of the menus.
+
+File:
+New, Open, Save, Save As, and Exit are standard.
+Switch file closes the current file and opens the previous one.
+
+Editor:
+Undo, Redo, Copy, Cut, Paste, Find and Find again are standard.
+
+Spin:
+Run Spin in one of five modes:
+Check runs a syntax check.
+Random runs a random simulation.
+Interactive runs an interactive simulation.
+Verify runs an verification.
+Guided runs a guided simulation using the trail file created
+by the execution of the analyzer.
+
+Convert:
+Load loads a .prp file into the LTL formula field:
+Clear clears the field.
+Translate translates it into a never claim stored in a .ltl file.
+LTL Name selects an internal LTL formula to use for verification.
+
+Options - change the option strings used with Spin:
+Common is used to select which data to display for Random,
+Interactive and Trail: statements, local and global variables
+and messages sent and received.
+The next options are for running the Spin sequence:
+ Spin: Check, Random, Interactive, Verify, Trail.
+ C Compiler.
+ Pan.
+Default restores the defaults of all options and settings.
+Save saves the options, settings and the current directory for File/Open.
+
+Settings - change settings for verification and display:
+Max steps for Random, Interactive and Trail modes.
+Max depth for search depth when running the pan verifier.
+Seed - if non-zero its value is used for Random simulation.
+Weak fairness during verification.
+Safety, Acceptance, Non-progress verification modes.
+
+Output - control display of filtered Spin output:
+Maximize the right text area that displays the output.
+Exclude variables - exclude (and include) these variables in the display.
+Exclude statements - exclude (and include) these statements in the display.
+Variable width - width of the columns used to display the variable values.
+Save output - saves the filtered Spin output in a file with extension .out.
+Raw output - saves the unfiltered Spin output in a file with extension .raw.
+Display raw - displays this file for debugging purposes.
+
+SpinSpider:
+Display debug - display the debug file created by SpinSpider.
+SpiderSpider - popup SpinSpider dialog:
+ Format - graphical output format
+ Dot size - size parameter for dot
+ Trail style - emphasize with color or bold
+ Variables - a list of the variables in the program must be given
+ Processes - the number of processes
+ Radio buttons:
+ No trail - display state diagram without trail (if any)
+ Emphasize/only trail - a trail from a verification must exist
+ Automata - display the processes as automata
+
+Help:
+Help and About are standard.