#!/usr/X11R6/bin/wish -f

#======================================================================#
# Tcl/Tk Spin Controller, Gerard J. Holzmann, Bell Laboratories, USA.  #
# Copyright (c) 1995-2001 by Lucent Technologies. All Rights Reserved. #
# See the README.html file for full installation notes.                #
#        http://netlib.bell-labs.com/netlib/spin/whatispin.html        #
#======================================================================#

set xversion "3.4.7 -- 23 April 2001"

# -- Xspin Installation Notes (see also README.html):

# 1. On Unix systems: change the first line of this file to point to the wish
#    executable you want to use (e.g., wish4.2 or /usr/local/bin/wish8.0)
#    ==> be careful the pathname should be 30 characters or less
#
# 2. If you use cc instead of gcc, change the set CC line below
#
# 3. Browse the configurable options below if you would like to
#    change or adjust the visual appearance of the GUI
#
# 4. If you run on a PC, and have an ancient version of tcl/tk,
#    you must set the values fo Unix, CMD, and Go32 by hand below
#    => with Tcl/Tk 7.5/4.1 or later, this happens automatically

  set CC   "gcc -w"	;# ANSI-C compiler, suppress warnings
  set SPIN "spin"	;# use a full path-name if necessary
  set DOT  "dot"	;# optional, graph layout interface
  			;# no prob if dot is not available
  set BG   "white"	;# default background color for text
  set FG   "black"	;# default foreground color for text
  set GO32 ""		;# PC use, not needed on Unix
  set CMD  ""		;# ditto
  set Unix 1		;# default is Unix, but this is adjusted below
  set Ptype "color"	;# printer-type: mono, color, or gray
  set NT 0		;# scratch variable, ignore

  if [info exists tcl_platform] {
	set sys $tcl_platform(platform)
	if {$sys == "macintosh"} {
		puts "sorry: xspin does run on macs yet..."
		exit
	}
	if {$sys == "windows"} {
		set Unix 0	;# Windows95 or WindowsNT
	#	set GO32 "go32"	;# not needed with newer versions of gcc
		if {$tcl_platform(os) == "Windows 95"} {
			set CMD  "command.com"	;# Windows95
		} else {
			set CMD  "cmd"	;# WindowsNT
			set NT 1
  }	}	}

#-- GUI configuration options - by Leszek Holenderski <lhol@win.tue.nl>
#-- basic text sizes:
# menu text - captions:
	set HelvBig	-Adobe-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*
# fsm graphs:
	set HelvSml	-Adobe-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*
# mscs:
	if {$NT} {	;# on a windows nt machine
	set SmallFont	"-*-Courier-Bold-R-Normal--*-110-*"
	set BigFont	"-*-Courier-Bold-R-Normal--*-110-*"
	} else {
	set SmallFont	"-*-Courier-Bold-R-Normal--*-80-*"
	set BigFont	"-*-Courier-Bold-R-Normal--*-80-*"
	}

# Some visual aspects of Xspin GUI can be configured by the user.
# On PCs, the values of configuration options that are hard-coded
# into this script can be modified (see below). On Unix, in addition to
# (or rather, instead of) the manual modification, the values can be set in
# an Xspin resource file ($HOME/.xspinrc) and/or in the X11 default resource
# file (usually, $HOME/.Xdefaults).

# Since the same option can be specified in several places, options can have
# several, possibly inconsistent, values. The value which takes effect is
# determined by the order in which options are scanned. The values specified
# later in the order have higher priority. First, hard-coded options are
# scanned, then options specified in .Xdefaults, and finally options
# specified in .xspinrc.

# When setting configuration options in an .xspinrc file, convert the 
# settings below to the format of an X11 resource file. For example,
#
#	# width of scrollbars (any Tk dimension, default 15 pixels)
#	option add *Scrollbar.width	13	startupFile
#
# should be converted to
#
#	! width of scrollbars (any Tk dimension, default 15 pixels)
#	*Scrollbar.width	13
# In .Xdefaults file, configuration options should be preceded by the
# application's name, so the above option should be converted to
#
#	! width of scrollbars (any Tk dimension, default 15 pixels)
#	xspin*Scrollbar.width	13
# side on which side scrollbars are put (left or right, default=right)

option add *Scrollbar.side	left	startupFile

#--- sizes
	# width of scrollbars (any Tk dimension, default 15 pixels)
	option add *Scrollbar.width	13	startupFile
	# width of borders (in pixels, typically 1 or 2, default 2)
	option add *borderWidth		1	startupFile
	# initial width of the input/log area (in characters, default 80)
	option add *Input*Text.width	72	startupFile
	option add *Log*Text.width	72	startupFile
	# initial height of the input area (in lines, default 24)
	option add *Input*Text.height	20	startupFile
	# initial height of the log area (in lines, default 24)
	option add *Log*Text.height	5	startupFile
	# size of the handle used to adjust the height of the log area
	# (in pixels, default 0)
	option add *Handle.width	10	startupFile
	option add *Handle.height	10	startupFile
#--- colors
	# colors for the input/log area
	option add *Input*Text.background	white	startupFile
	option add *Input*Text.foreground	black	startupFile
	option add *Log*Text.background		gray95	startupFile
	option add *Log*Text.foreground		black	startupFile
	# colors for the editable/read-only area
	option add *Entry.background		white	startupFile
	option add *Edit*Text.background	white	startupFile
	option add *Edit*Text.foreground	black	startupFile
	# colors for the editable/read-only area
	option add *Read*Text.background	gray95	startupFile
	option add *Read*Text.foreground	black	startupFile
#--- fonts
	# fonts for the input/log area (default is system dependent,
	# usually -*-Courier-Medium-R-Normal--*-120-*)
#option add *Input*Text.font	-schumacher-clean-medium-r-normal--*-120-*-60-*	startupFile
#option add *Log*Text.font	-schumacher-clean-medium-r-normal--*-120-*-60-*	startupFile

#--- widgets
	# simple texts (dialogs which present read-only texts, such as help)
	option add *SimpleText.Text.width 60
	option add *SimpleText.Text.height 30
	option add *SimpleText.Text.background white

	# sections (decorated frames for grouping related buttons)
	option add *Section*Title.font		-*-Helvetica-Bold-R-Normal--*-100-*	startupFile

#option add *Section*Checkbutton.font	-*-Helvetica-Medium-R-Normal--*-100-*	startupFile
#option add *Section*Radiobutton.font	-*-Helvetica-Medium-R-Normal--*-100-*	startupFile
#option add *Section*Label.font		-*-Helvetica-Medium-R-Normal--*-100-*	startupFile

################ end of configurable parameters #######################

wm title . "SPIN CONTROL $xversion"
wm iconname . "SPIN"
wm geometry . +50+50
wm minsize  . 400 200

set Fname ""
set firstime 1

#### seed the advanced parameters settings

set e(0)	"Physical Memory Available (in Mbytes): "
set ival(0)	64
set expl(0)	"explain"

set e(1)	"Estimated State Space Size (states x 10^3): "
set ival(1)	500
set expl(1)	"explain"

set e(2)	"Maximum Search Depth (steps): "
set ival(2)	10000
set expl(2)	"explain"

set e(3)	"Extra Compile-Time Directives (Optional): "
set ival(3)	""
set expl(3)	"Choose"

set e(4)	"Extra Run-Time Options (Optional): "
set ival(4)	""
set expl(4)	"Choose"

set e(5)	"Extra Verifier Generation Options: "
set ival(5)	""
set expl(5)	"Choose"

set ival(6)	1	;# which error is reported, default is 1st


# allow no more than one entry per selection
catch { tk_listboxSingleSelect Listbox }

proc msg_file {f nowarn} {
	set msg ""
	set ef [open $f r]
	while {[gets $ef line] > -1} {
		if {$nowarn} {
			if {[string first "warning" $line] < 0} {
				set msg "$msg$line"
			}
		} else {
			set msg "$msg$line"
	}	}
	close $ef
	return $msg
}

	scan $tk_version "%d.%d" tk_major tk_minor

	if {[auto_execok $SPIN] == "" \
	||  [auto_execok $SPIN] == 0} {
		set version "Error: No executable $SPIN found..."
	} else {
		if {$Unix} {
			set version [exec $SPIN -V]
		} else {
			catch { exec $SPIN -V >&pan.tmp } err
			if {$err == ""} {
				set version [msg_file pan.tmp 1]
			} else {
				puts "error: $err"
				puts "is there a $SPIN and a go32.exe?"
				exit
		}	}
		if {[string first "Spin Version 2" $version] < 0 \
		&&  [string first "Spin Version 3" $version]} {
			set version "Installed Spin: older than Version 2.0"
		}
	}


frame .menu
	# top level menu bar
	menubutton .menu.file -text "File.." \
		-relief raised -menu .menu.file.m
	menubutton .menu.run -text "Run.." -fg red \
		-relief raised -menu .menu.run.m
# HSF
	menubutton .menu.hsf-spin -text "HSF-SPIN.." -fg blue \
		-relief raised -menu .menu.hsf-spin.m
	menubutton .menu.view -text "View.." \
		-relief raised -menu .menu.view.m
	menubutton .menu.edit -text "Edit.." \
		-relief raised -menu .menu.edit.m
	label .menu.title -text "SPIN  DESIGN  VERIFICATION" -fg blue

	set lno 1
	label .menu.lno -text "Line#:" -relief raised 
	entry .menu.ent -width 6 -textvariable lno \
		-relief sunken -background white -foreground black
	bind  .menu.ent <Return> {
		.inp.t tag remove hilite 0.0 end
		.inp.t tag add hilite $lno.0 $lno.1000
		.inp.t tag configure hilite -background $FG -foreground $BG
		.inp.t yview -pickplace [expr $lno-4]
	}

	label .menu.fnd1 -text "Find:" -relief raised 
	entry .menu.fnd2 -width 8 -textvariable pat \
		-relief sunken -background white -foreground black
	bind  .menu.fnd2 <Return> {
		.inp.t tag remove hilite 0.0 end
		forAllMatches .inp.t $pat
	}

	menubutton .menu.help -text "Help" -relief raised \
		-menu .menu.help.m

	pack append .menu \
		.menu.file {left frame w} \
		.menu.edit {left frame w} \
		.menu.run {left frame w} \
		.menu.hsf-spin {left frame w} \
		.menu.help {left frame w} \
		.menu.title {left frame c expand} \
		.menu.fnd2 {right frame e} \
		.menu.fnd1 {right frame e} \
		.menu.ent {right frame e} \
		.menu.lno {right frame e}

set loglines 5
frame .log
	text .log.t -bd 2 -height $loglines -background $FG -foreground $BG
frame .log.b
	button .log.b.pl -text "+" \
		-command {incr loglines  1; .log.t configure -height $loglines}
	button .log.b.mn -text "-" \
		-command {incr loglines -1; .log.t configure -height $loglines}
	pack append .log.b .log.b.pl {top}
	pack append .log.b .log.b.mn {top}
	pack append .log .log.b {left filly}
	pack append .log .log.t {right expand fill}

proc dopaste {} {
	global FG BG
	set from [.inp.t index insert]
	tk_textPaste .inp.t
	set upto [.inp.t index insert]
	.inp.t tag add sel $from $upto
#	.inp.t tag configure hilite -background $FG -foreground $BG
}

#- fetch the value of user-defined configuration options

proc fetchOption {name default args} {

  set class Dummy
  set fullName $name

  # class encoded in name ?
  switch -glob -- $name *.* {
    set list [split $name .]
    switch [llength $list] 2 {} default { error "wrong option \"$name\" }
    set class [lindex $list 0]
    set name  [lindex $list 1]
  }

  # create a unique dummy frame of requested class and get the option's value
  set dummy .0
  while {[winfo exists $dummy]} { append dummy 0 }
  frame $dummy -class $class
  set value [option get $dummy $name $class]
  destroy $dummy

  # option not defined ?
  switch -- $value "" { return $default }

  # check a restriction on option's value
  switch [llength $args] {
    0 { # no restriction
      }
    1 { # restriction is given as a list of allowed values
        switch -- [lsearch -exact [lindex $args 0] $value] -1 {
          set msg "wrong value \"$value\" of option \"$fullName\"\
                   (should be one of $args)"
          return -code error -errorinfo $msg $msg
        }
      }
    2 { # restriction is given as a range (min and max)
        set min [lindex $args 0]
        set max [lindex $args 1]
        if {$value < $min} { set $value $min }
        if {$value > $max} { set $value $max }
      }
    default {
      error "internal error in fetchOption: wrong restriction \"$args\""
    }
  }

  return $value
}

# width of borders
set BD [fetchOption borderWidth 1 0 4]
#option add *Text.highlightThickness $BD startupFile

# scrollbar's side
set scrollbarSide [fetchOption Scrollbar.side right {left right}]

frame .inp
	# view of spin input
	scrollbar .inp.s  -command ".inp.t yview"
	text .inp.t -bd 2  -yscrollcommand ".inp.s set" -wrap word

	pack .inp.s -side $scrollbarSide -fill y
	pack append .inp \
		.inp.t {left expand fill}

	menu .inp.t.edit -tearoff 0
	.inp.t.edit add command -label "Cut" \
		-command {tk_textCopy .inp.t; tk_textCut .inp.t}
	.inp.t.edit add command -label "Copy" \
		-command {tk_textCopy .inp.t}
	.inp.t.edit add command -label "Paste" \
		-command {dopaste}

	bind .inp.t <ButtonPress-3> {
		tk_popup .inp.t.edit %X %Y
	}
	bind .inp.t <ButtonRelease-1> { setlno }


set l_typ 0;	# used by both simulator and validator
set lt_typ 0;	# used by ltl panel
set ol_typ -1;	# remembers setting last used in compilation
set m_typ 2;	# used by simulator

menu .menu.file.m
	.menu.file.m add command -label "New"  \
		-command ".inp.t delete 0.0 end"
	.menu.file.m add command -label "UnSelect" \
		-command ".inp.t tag remove hilite 0.0 end;\
			  .inp.t tag remove Rev 0.0 end;\
			  .inp.t tag remove sel 0.0 end"
	.menu.file.m add command -label "ReOpen" -command "open_spec"
	.menu.file.m add command -label "Open.." -command "open_spec 0"
	.menu.file.m add command -label "Save As.." -command "save_spec 0"
	.menu.file.m add command -label "Save" -command "save_spec"
	.menu.file.m add command -label "Quit" \
		-command "cleanup; destroy .; exit"

menu .menu.help.m
	.menu.help.m add command -label "About Spin" \
		-command "aboutspin"
	.menu.help.m add separator
	.menu.help.m add command -label "Promela Usage" \
		-command "promela"
	.menu.help.m add command -label "Xspin Usage" \
		-command "helper"
	.menu.help.m add command -label "Simulation" \
		-command "roadmap1"
	.menu.help.m add command -label "Verification" \
		-command "roadmap2"
	.menu.help.m add command -label "LTL Formulae" \
		-command "roadmap4"
	.menu.help.m add command -label "Spin Automata View" \
		-command "roadmap5"
	.menu.help.m add command -label "Reducing Complexity" \
		-command "roadmap3"

menu .menu.run.m
	.menu.run.m add command -label "Run Syntax Check" \
		-command {syntax_check "-a -v" "Syntax Check"}
	.menu.run.m add command -label "Run Slicing Algorithm" \
		-command {syntax_check "-A" "Property-Specific Slicing"}
	.menu.run.m add separator
	.menu.run.m add command -label "Set Simulation Parameters.." \
		-command simulation
	.menu.run.m add command -label "(Re)Run Simulation" \
		-command Rewind -state disabled
	.menu.run.m add separator
	.menu.run.m add command -label "Set Verification Parameters.." \
		-command basicval
	.menu.run.m add command -label "(Re)Run Verification" \
		-command {runval "0"} -state disabled
	.menu.run.m add separator
	.menu.run.m add command -label "LTL Property manager.." \
		-command call_tl
	.menu.run.m add separator
	.menu.run.m add command -label "View Spin Automaton for each Proctype.." \
		-command fsmview

# HSF
menu .menu.hsf-spin.m
	.menu.hsf-spin.m add command -label "About Spin" \
		-command "abouthsf-spin"
	.menu.hsf-spin.m add separator
	.menu.hsf-spin.m add command -label "Set Verification Parameters.." \
		-command basichsf-spinval
	.menu.hsf-spin.m add command -label "(Re)Run Verification" \
		-command {runval "0"} -state disabled

menu .menu.edit.m
	.menu.edit.m add command -label "Cut" \
		-command {tk_textCopy .inp.t; tk_textCut .inp.t}
	.menu.edit.m add command -label "Copy" \
		-command {tk_textCopy .inp.t}
	.menu.edit.m add command -label "Paste" \
		-command {tk_textPaste .inp.t}

proc setlno {} {
	scan [.inp.t index insert] "%d.%d" lno cno
	.menu.ent delete 0 end
	.menu.ent insert end $lno
	.inp.t tag remove hilite $lno.0 $lno.end	;# or else cursor is invis
	update
}

proc cleanup {} {
	global Unix
	if {$Unix == 0} {
		add_log "removing temporary files, please wait.."; update
	}
	rmfile "pan.h pan.c pan.t pan.m pan.b pan.tmp pan.ltl"
	rmfile "pan.oin pan.pre pan.out pan.exe pan.otl"
	rmfile "pan_in pan_in.trail trail.out pan"
	if {$Unix == 0} { add_log "done.." }
}

proc add_log {{y ""}} {

	if {$y == "\n"} { return }
	.log.t insert end "\n$y"
	.log.t yview -pickplace end
}


pack append . \
	.log  {bot frame w fillx} \
	.inp  {bot frame w expand fill} \
	.menu {top fillx}

# simulation parameters - initial settings
	set fvars 1
	set msc   1;	set svars 1
	set rvars 1
	set stop  0;	set tsc 0
	set seed	"1";	# random sumulation
	set jumpsteps	"0";	# guided simulation

	set s_typ 0
	# meaning s_type values:
	# 0 - Random Simulation (using seed)
	# 1 - Guided Simulation (using pan.trail)
	# 2 - Interactive Simulation

tkwait visibility .log
add_log "SPIN LOG:"
add_log " $version"
add_log "Xspin Version $xversion"
add_log "TclTk Version [info tclversion]/$tk_version\n"

	if {$Unix == 0} {
	if {[auto_execok "cpp"] == "" \
	||  [auto_execok "cpp"] == 0} {
		set m "Error: no cpp.exe (macro preprocessor) found"
		add_log $m
		catch { tk_messageBox -icon info -message $m }
	}}

.inp.t configure -background $BG -foreground $FG

# process execution barchart

set Data(0) 0
set Name(0) "-"
set n 0
set bar_handle 0
set PlaceBar	""

proc stopbar {} {
	global Data Name n PlaceBar
	for {set i 0} {$i <= $n} {incr i} {
		set Data($i) 0
		set Name($i) ""
	}
	set n 0
	set PlaceBar [wm geometry .bar]
	set k [string first "\+" $PlaceBar]
	if {$k > 0} {
		set PlaceBar [string range $PlaceBar $k end]
	}
	catch { destroy .bar }
}

proc growbar {v} {
	global n Data
	set Data($n) $v
	incr n
	catch { fillbar }
}

proc shrinkbar {} {
	global n
	incr n -1
	set Data($n) 0
	catch { fillbar }
}

proc stepbar {v nm} {
	global n Data Name

	if {$v >= 0} {
		if { [info exists Data($v)] } {
			incr Data($v)
		} else {
			set Data($v) 1
		}
		if {$v >= $n} {
			set n [expr $v+1]
		}
		if { [string length $nm] > 4} {
			set Name($v) [string range $nm 0 4]
		} else {
			set Name($v) $nm
		}
		catch { fillbar }
	}
}

proc adjustbar {v w} {
	global Data

	set Data($v) $w
	catch { fillbar }
}

proc startbar {tl} {
	global n Data bar_handle Ptype PlaceBar

	catch { destroy .bar }
	toplevel .bar
	wm minsize .bar 200 200
	wm title .bar "$tl"

	set maxy [expr [winfo screenheight .] - 200]
	if {$PlaceBar == ""} {
		set PlaceBar "+[expr [winfo rootx .]+150]+$maxy"
	}
	wm geometry .bar $PlaceBar

	set bar_handle [canvas .bar.c -height 410 -width 410 -relief raised]
	frame  .bar.buts

	button .bar.buts.s1 -text "Save in:  panbar.ps" \
		-command ".bar.c postscript -file panbar.ps -colormode $Ptype"

	button .bar.buts.b -text " Close " -command "stopbar"
	pack .bar.buts.b .bar.buts.s1 -side right
	pack append .bar  .bar.c {top expand fill}  .bar.buts {bot frame e}
}

proc fillbar {} {
	global n Data Name

	.bar.c delete grid
	.bar.c delete data
	set sum 0
	for {set i 0} {$i < $n} {incr i} {
		if { [info exists Data($i)] } {
			incr sum $Data($i)
		} else {
			set Data($i) 0
			set Name($i) "-"
		}
	}
	for {set i 0} {$i < $n} {incr i} {
		.bar.c create line \
			$i 0 \
			$i 100 \
			-fill #222222 -tags grid
		.bar.c create text $i 105 \
			-text $i -tags grid
		.bar.c create text $i 110 \
			-text "$Name($i)" \
			-fill blue -tags grid

		if { [info exists Data($i)] } {
			set y [expr ($Data($i)*100)/$sum]
			.bar.c create line \
				$i 100  \
				$i [expr 100-$y] \
				-width 35 -fill red -tags data
			if {$y > 6} {
				set nrcol "yellow"
			} else {
				set nrcol "red"
			}
			.bar.c create text $i 95 \
				-text "$Data($i)" \
				-fill $nrcol -tags grid
		}
	}

	.bar.c create text [expr ($n)/2.0] -15 -text "Percentage of $sum System Steps" \
		-anchor c -justify center -tags grid
	.bar.c create text [expr ($n)/2.0] -8 -text "Executed Per Process ($n total)" \
		-anchor c -justify center -tags grid
	.bar.c scale all 0 0 55 3
	if {$n <= 5} {
		.bar.c move all 100 60
	} else {
		.bar.c move all 50 60
	}
}

proc barscales {} {
	global bar_handle

	catch {
		button .bar.buts.b4 -text "Larger" \
			-command "$bar_handle scale all 0 0 1.1 1.1"
		button .bar.buts.b5 -text "Smaller" \
			-command "$bar_handle scale all 0 0 0.9 0.9"
		pack append .bar.buts \
			.bar.buts.b4 {right padx 5} \
			.bar.buts.b5 {right padx 5}
	}
}

# Files and Generic Boxes

set file ""
set boxnr 0

proc rmfile {f} {
	global Unix CMD tk_major tk_minor

	set err ""
	catch { eval file delete -force $f } err
	if {$err == "" } { return }

	if {$Unix} {
		catch {exec rm -f $f}
	} else {
		set n [llength $f]
		for {set i 0} {$i < $n} {incr i} {
			set g [lindex $f $i]
			add_log "rm $g"
			if {$tk_major >= 4 && $tk_minor >= 2} {
				catch {exec $CMD /c del $g}
			} else {
				catch {exec $CMD >&@stdout /c del $g}
			}
	}	}
}

proc mvfile {f g} {
	global Unix CMD tk_major tk_minor

	set err ""
	catch { file rename -force $f $g } err
	if {$err == "" } { return }

	if {$Unix} {
		catch {exec mv $f $g}
	} else {
		if {$tk_major >= 4 && $tk_minor >= 2} {
			catch {exec $CMD /c move $f $g}
		} else {
			catch {exec $CMD >&@stdout /c move $f $g}
		}
	}
}

proc cpfile {f g} {
	global Unix CMD tk_major tk_minor

	set err ""
	catch { file copy -force $f $g } err
	if {$err == "" } { return }

	if {$Unix} {
		catch {exec cp $f $g}
	} else {
		if {$tk_major >= 4 && $tk_minor >= 2} {
		catch {exec $CMD /c copy $f $g}
		} else {
		catch {exec $CMD >&@stdout /c copy $f $g}
	}	}
}

proc cmpfile {f g} {
	global Unix

	set err ""
	if {$Unix} {
		catch {exec cmp $f $g} err
	} else {
		if {[file exists $f] == 0 \
		||  [file exists $g] == 0} {
			return "error"
		}
		set fd1 [open $f r]
		set fd2 [open $g r]
		while {1} {
			set n1 [gets $fd1 line1]
			set n2 [gets $fd2 line2]
			if {$n1 != $n2 \
			||  [string compare $line1 $line2] != 0} {
				set err "files differ"
				break
			}
			if {$n1 < 0} { break }
		}
		close $fd1
		close $fd2
	}
	return $err
}

proc file_ok {f} {
	if {[file exists $f]} {
		if {![file isfile $f] || ![file writable $f]} {
			set m "error: file $f is not writable"
			add_log $m
			catch { tk_messageBox -icon info -message $m }
			return 0
	}	}
	return 1
}

proc mkpan_in {} {
	set fd [open pan_in w]
	puts $fd [.inp.t get 0.0 end] nonewline
	catch "flush $fd"
	catch "close $fd"
}

proc no_ltlchange {} {

	if {![file exists pan.ltl]} {
		return 1
	}
	if {![file exists pan.otl]} {
		cpfile pan.ltl pan.otl
		return 0		; first time
	}
	set err [cmpfile pan.ltl pan.otl]
	if {[string length $err] > 0} {
		cpfile pan.ltl pan.otl
		return 0		;# different
	}
	return 1			;# unchanged
}

proc no_change {} {
	global nv_typ

	mkpan_in	;# keep this up to date
	if {![file exists pan.oin]} {
		cpfile pan_in pan.oin
		return 0		; first time
	}
	set err [cmpfile pan_in pan.oin]
	if {[string length $err] > 0} {
		cpfile pan_in pan.oin
		return 0		;# different
	}
	if {$nv_typ == 0} {
		return 1
	}
	return [no_ltlchange]		;# unchanged
}

proc mk_exec {} {
	global Unix CC SPIN

	set nochange [no_change]
	if {$nochange == 1 && [file exists "pan"]} {
		add_log "<no recompilation needed>"
		return 1
	}

	add_log "<compiling executable>"
	catch {
	warner "Compiling" "Please wait until compilation of the \
executable produced by spin completes." 300
	}
	add_log "$SPIN -a pan_in"

	catch {exec $SPIN -a pan_in >&pan.tmp}
	set errmsg [msg_file pan.tmp 1]

	if {[string length $errmsg]>0} {
		add_log "$errmsg"
		catch { tk_messageBox -icon info -message $errmsg }
		add_log "<stopped compilation attempt>"
		catch { destroy .warn }
		return 0
	}

	add_log "$CC -o pan -D_POSIX_SOURCE pan.c"; update
	if {$Unix} {
		catch { eval exec $CC -o pan -D_POSIX_SOURCE pan.c } errmsg
	} else {
		catch { eval exec $CC -o pan -D_POSIX_SOURCE pan.c >&pan.tmp }
		set errmsg [msg_file pan.tmp 0]
	}
		if {[string length $errmsg]>0} {
			add_log "$errmsg"
			catch { tk_messageBox -icon info -message $errmsg }
			catch { destroy .warn }
			return 0
		}
	add_log "<compilation complete>"
	catch {destroy .warn}
	return 1
}

set PlaceWarn	"+20+20"

proc warner {banner msg w} {
	global PlaceWarn

	catch {destroy .warn}
	toplevel .warn

	wm title .warn "$banner"
	wm iconname .warn "Info"
	set k [string first "\+" $PlaceWarn]
	if {$k > 0} {
		set PlaceWarn [string range $PlaceWarn $k end]
	}
	wm geometry .warn $PlaceWarn

	message .warn.t -width $w -text $msg
	button .warn.ok -text "Ok" \
		-command "set PlaceWarn [wm geometry .warn]; destroy .warn"

	pack append .warn .warn.t {top expand fill}
	pack append .warn .warn.ok {bottom}

	update
}

proc dosave {} {
	global Fname xversion

	if {[file_ok $Fname]==0} return
	set fd [open $Fname w]
	add_log "<saved spec in $Fname>"
	puts $fd "[.inp.t get 0.0 end]" nonewline
	catch "flush $fd"
	catch "close $fd"
	wm title . "SPIN CONTROL $xversion -- File: $Fname"
}

proc save_spec {{curr 1}} {
#-
#- Save the input area into a file.
#-
#- If 'curr' is true then we save to the current file. Otherwise, a file
#- selection dialog is presented. If a file is selected (note that the
#- dialog can be canceled) then we try to write to it.
#-

  global Fname

  if $curr {
    switch -- $Fname "" {
      add_log "no file to save to, try \"Save as ...\""
      return
    }
    writeoutfile .inp.t $Fname
  } else {
    # try to use the predefined file selection dialog
    switch [info commands tk_getSaveFile] "" {
      # some old version of Tk so use our own file selection dialog
      set fileselect "FileSelect save"
    } default {
      set fileselect "tk_getSaveFile"
    }
  
    # get the file (return if the file selection dialog canceled)
    switch -- [set file [eval $fileselect]] "" return
  
    # write the file and update Fname if the file written successfully
    if [writeoutfile .inp.t $file] {
      set Fname $file
    }
  }
}

proc consider_it {} {
	global file Fname xversion

	if {[file isdirectory $file]} then {
		cd $file
		fillerup ""
		add_log "cd $file"
	} else {
		if {![file isfile $file]} {
			set file ""
		} else {
			readinfile .inp.t $file

			rmfile pan_in.trail
			cpfile $file.trail pan_in.trail

			set dir [pwd]
			set Fname $file
			wm title . "SPIN CONTROL $xversion -- File: $Fname"
			destroy .b
	}	}
}

#----------------------------------------------------------------------
# Improvements - by Leszek Holenderski <lhol@win.tue.nl>
# GUI configuration and File Selection dialogs
#----------------------------------------------------------------------

# predefined priorities for options stored in the option data base are
#	widgetDefault	20
#	startupFile	40
#	userDefault	60
#	interactive	80

# most of frames are used for layout purposes so they should be invisible
option add *Frame.borderWidth 0 interactive

proc try_with {xspinrc} {

  if ![file exists $xspinrc] return

  if ![file isfile $xspinrc] {
    puts "xspin warning: the resource file \"$xspinrc\" exists but is not\
          a normal file"
    return
  }
  if ![file readable $xspinrc] {
    puts "xspin warning: the resource file \"$xspinrc\" exists but is not\
          readable"
    return
  }
  if [catch {option readfile $xspinrc userDefault} result] {
    puts "xspin warning: some problems when trying to load the resource\
          file \"$xspinrc\"\n$result"
    return
  }
}

if [info exists env(HOME)] {
  if $Unix {
    try_with [file join $env(HOME) .xspinrc]
  } else {
    try_with [file join $env(HOME) xspinrc]
  }
}

proc FileSelect {mode {title ""}} {
  switch -- $mode open - save {} default { set mode open }

  switch $mode {
    open {
      set title Open
      set okButtonText Open
    }
    save {
      set title Save
      set okButtonText Save
    }
  }

  set w .fileselect
  upvar #0 $w this

  if [winfo exists $w] {
    wm title $w $title
    $this(okButton) config -text $okButtonText
    catch {wm geom $w $this(geom)}
    wm deiconify $w
  } else {
    toplevel $w -class Fileselect
    wm title $w $title
    # the minimal size is given in characters and lines (setgrid is on)
    wm minsize $w 14 7

    # layout frames
    pack [set f [frame $w.f]] -padx 5 -pady 5 -fill both -expand yes
    pack [set buttons [frame $f.b]] -side bottom -fill x
    pack [set name    [frame $f.n]] -side bottom -fill x -pady 5
    pack [set path    [frame $f.p]] -side top -fill x
    pack [set files   [frame $f.f]] -side top -fill both -expand yes
  
    # create ok/cancel buttons
    set okButton [button $buttons.ok -text $okButtonText \
			-command "FileSelect.Close $w 1"]
    pack $okButton -side right

    set cancelButton [button $buttons.cancel -text Cancel \
			-command "FileSelect.Close $w 0"]
    pack $cancelButton -side left

    MakeSameWidth "$okButton $cancelButton"
  
    # create path button
    set pathButton $path.path
    global $w|currDir
    set pathMenu [tk_optionMenu $pathButton $w|currDir ""]
    pack $pathButton -side top
  
    # create the list of files
    global scrollbarSide

    set fileList $files.l
    set scrollbar $files.s
    pack [scrollbar $files.s -command "$fileList yview"] \
	 -side $scrollbarSide -fill y
    pack [listbox $fileList -yscrollcommand "$files.s set" -selectmode single -setgrid on] \
	 -side $scrollbarSide -expand yes -fill both
  
    bind $fileList <ButtonPress-1>        "FileSelect.Selected $w %x %y"
    bind $fileList <Double-ButtonPress-1> "FileSelect.Chosen   $w %x %y"

    set fileEntry $name.e
    pack [label $name.l -text File:] -side left
    pack [entry $fileEntry] -side right -expand yes -fill x

    set this(okButton)   $okButton
    set this(pathButton) $pathButton
    set this(pathMenu)   $pathMenu
    set this(fileList)   $fileList
    set this(fileEntry)  $fileEntry

    foreach widget "$okButton $cancelButton $pathButton $fileList $scrollbar" {
      $widget config -highlightthickness 0
    }

    wm protocol $w WM_DELETE_WINDOW [$cancelButton cget -command]
  }

  # fill in the list of files
  if ![info exists this(path)] { set this(path) [pwd] }
  FileSelect.cd $w $this(path)

  # make the dialog modal (set a grab and claim the focus)

  set oldFocus [focus]
  set oldGrab [grab current $w]
  if {$oldGrab != ""} { set grabStatus [grab status $oldGrab] }
  grab $w
  focus $this(fileEntry)

  # make the contents of file entry selected (for easy deletion)
  $this(fileEntry) select from 0
  $this(fileEntry) select to end

  # Wait for the user to respond, then restore the focus and return the
  # contents of file entry.
  # Restore the focus before deleting the window, since otherwise the
  # window manager may take the focus away so we can't redirect it.
  # Finally, restore any grab that was in effect.

  global $w|response
  tkwait variable $w|response
  catch {focus $oldFocus}
  grab release $w
  set this(geom) [wm geom $w]
  wm withdraw $w
  if {$oldGrab != ""} {
      if {$grabStatus == "global"} {
	  grab -global $oldGrab
      } else {
	  grab $oldGrab
      }
  }
  return [set $w|response]
}

proc CompareNoCase {s1 s2} {
  return [string compare [string tolower $s1] [string tolower $s2]]
}

proc FileSelect.LoadFiles {w} {
    upvar #0 $w this

    # split all names in the current directory into dirs and files
    set dirs ""
    set files ""
    set filter ""
    if [info exists this(filter)] { set filter $this(filter) }
    switch -- $filter "" { set filter * }
    foreach f [lsort -command CompareNoCase [glob -nocomplain .* *]] {
	if [file isdir $f] {
	  # exclude the '.' and '..' directory
	  switch -- $f . - .. continue
	  lappend dirs $f
	}
	if [file isfile $f] {
	  # filter files
	  switch -glob -- $f $filter { lappend files $f }
	}
    }

    # Fill in the file list
    $this(fileList) delete 0 end
    foreach d $dirs {
	# append directory mark to the name (tricky)
	set d [string trimright [file join $d a] a]
	$this(fileList) insert end $d
    }
    foreach f $files { $this(fileList) insert end $f }
}

proc FileSelect.LoadPath {w} {
    upvar #0 $w this

    # convert path to list
    set dirs [file split $this(path)]

    # compute prefix paths
    set path ""
    set paths ""
    foreach d $dirs {
	set path [file join $path $d]
	lappend paths $path
    }

    # reverse dirs and paths
    set rev_dirs ""
    foreach d $dirs { set rev_dirs [concat [list $d] $rev_dirs] }
    set rev_paths ""
    foreach p $paths { set rev_paths [concat [list $p] $rev_paths] }

    # update the path menubutton
    global $w|currDir
    set $w|currDir [lindex $rev_dirs 0]

    # fill in the path menu
    $this(pathMenu) delete 0 end
    foreach d [lrange $rev_dirs 1 end] p [lrange $rev_paths 1 end] {
	$this(pathMenu) add command -label $d -command "FileSelect.cd $w $p"
    }
}

proc FileSelect.Selected {w x y} {
    upvar #0 $w this

    # determine the selected list element
    set elem [$this(fileList) get [$this(fileList) index @$x,$y]]
    switch -- $elem "" return

    # directories cannot be selected (they can only be chosen)
    if [file isdir $elem] return

    $this(fileEntry) delete 0 end
    $this(fileEntry) insert end $elem
}

proc FileSelect.Chosen {w x y} {
    upvar #0 $w this

    # determine the selected list element
    set elem [$this(fileList) get [$this(fileList) index @$x,$y]]
    switch -- $elem "" return

    # if directory then cd, otherwise close the dialog
    if [file isdir $elem] { FileSelect.cd $w $elem } { FileSelect.Close $w 1 }
}

proc FileSelect.Close {w {ok 1}} {
  # trigger the end of dialog
  upvar #0 $w this $w|response response
  if $ok {
    set response [file join $this(path) [$this(fileEntry) get]]
  } else {
    set response ""
  }
}

proc FileSelect.cd {w dir} {
    upvar #0 $w this

    if [catch {cd $dir} errmsg] {
	puts "xspin warning: $errmsg"
	return
    }

    set this(path) [pwd]
    FileSelect.LoadFiles $w
    FileSelect.LoadPath $w
}

proc open_spec {{curr 1}} {
  global Fname

  if $curr {
    switch -- $Fname "" {
      add_log "no file to reopen, try \"Open ...\""
      return
    }
    readinfile .inp.t $Fname
  } else {
    # try to use the predefined file selection dialog
    switch [info commands tk_getOpenFile] "" {
      # some old version of Tk so use our own file selection dialog
      set fileselect "FileSelect open"
    } default {
      set fileselect "tk_getOpenFile"
    }
  
    # get the file (return if the file selection dialog canceled)
    switch -- [set file [eval $fileselect]] "" return
  
    # load the file and update some items if the file loaded successfully
    if [readinfile .inp.t $file] {
      rmfile pan_in.trail
      cpfile $file.trail pan_in.trail
      set Fname $file
    }
  }
}

set defname ""

proc loaddefault_tl {} {
	global Fname defname

	if {$defname ==""} {
		set file2 "$Fname.ltl"
	} else {
		set file2 $defname
	}
	catch {
		.tl.main.e1 delete 0 end
		.tl.macros.t delete 0.0 end
		.tl.notes.t delete 0.0 end
		.tl.never.t delete 0.0 end
		.tl.results.t delete 0.0 end
	}
	if {![file exists $file2]} {
		.tl.notes.t insert end "Use Load to open a file or a template."
		return
	}
	catch {
		.tl.notes.title configure -text "Notes \[file $file2]:"
	}
	readinfile .tl.never.t $file2
	catch { extract_defs }
}

proc browse_tl {} {
	global defname

	set suffix "ltl"

	catch {destroy .b}
	toplevel .b
	wm iconname .b "Load"

	frame .b.top
	scrollbar .b.top.scroll -command ".b.top.list yview"
	listbox .b.top.list -yscroll ".b.top.scroll set" -relief raised 

	button .b.zap -text "Cancel" -command "destroy .b"
	button .b.all -text "Show All Files" \
		-command {
			set suffix ""
			fillerup ""
			destroy .b.all
		}

	pack append .b.top \
		.b.top.scroll {right filly} \
		.b.top.list {left expand fill}
	pack append .b \
		.b.top {top} \
		.b.all {left} \
		.b.zap {left}

	fillerup  $suffix
	bind .b.top.list <Double-Button-1> {
		set file2 [selection get]
		if {[string first "---" $file2] >= 0} {
			# ignore
		} elseif {[string first "Invariance" $file2] >= 0} {
			catch {
			.tl.main.e1 delete 0 end
			.tl.macros.t delete 0.0 end
			.tl.notes.t delete 0.0 end
			.tl.never.t delete 0.0 end
			.tl.results.t delete 0.0 end

			.tl.main.e1 insert end "\[\] (p)"
			.tl.notes.t insert end "'p' is invariantly true throughout
an execution"
			.tl.notes.title configure \
				-text "Notes \[template $file2]:"
			do_ltl
			destroy .b
			}
		} elseif {[string first "Response" $file2] >= 0} {
			catch {
			.tl.main.e1 delete 0 end
			.tl.macros.t delete 0.0 end
			.tl.notes.t delete 0.0 end
			.tl.never.t delete 0.0 end
			.tl.results.t delete 0.0 end

			.tl.main.e1 insert end "\[\] ((p) -> (<> (q)))"
			.tl.notes.t insert end "if 'p' is true in at least one state,
then sometime thereafter 'q' must also
become true at least once."
			.tl.notes.title configure \
				-text "Notes \[template $file2]:"
			do_ltl
			destroy .b
			}
		} elseif {[string first "Precedence" $file2] >= 0} {
			catch {
			.tl.main.e1 delete 0 end
			.tl.macros.t delete 0.0 end
			.tl.notes.t delete 0.0 end
			.tl.never.t delete 0.0 end
			.tl.results.t delete 0.0 end

			.tl.main.e1 insert end "\[\] ((p) -> ((q) U (r)))"
			.tl.notes.t insert end "'p' is a trigger, or 'enabling' condition that
determines when this requirement becomes applicable
'r' is the fullfillment of the requirement, and
'q' is a condition that must remain true in the interim."
			.tl.notes.title configure \
				-text "Notes \[template $file2]:"
			do_ltl
			destroy .b
			}
		} elseif {[string first "Objective" $file2] >= 0} {
			catch {
			.tl.main.e1 delete 0 end
			.tl.macros.t delete 0.0 end
			.tl.notes.t delete 0.0 end
			.tl.never.t delete 0.0 end
			.tl.results.t delete 0.0 end

			.tl.main.e1 insert end "\[\] ((p) -> <>((q) || (r)))"
			.tl.notes.t insert end "'p' is a trigger, or 'enabling' condition that
determines when this requirement becomes applicable
'q' is the fullfillment of the requirement, and
'r' is a discharging condition that terminates the
applicability of the requirement."

			.tl.notes.title configure \
				-text "Notes \[template $file2]:"
			do_ltl
			destroy .b
			}
		} elseif {[file isdirectory $file2]} then {
			cd $file2
			fillerup $suffix
			add_log "cd $file2"
		} else {
			if {![file isfile $file2]} {
				set file2 ""
			} else {
				catch {
				.tl.main.e1 delete 0 end
				.tl.macros.t delete 0.0 end
				.tl.notes.t delete 0.0 end
				.tl.never.t delete 0.0 end
				.tl.results.t delete 0.0 end
				.tl.notes.title configure \
					-text "Notes \[file $file2]:"
				}
				readinfile .tl.never.t $file2
				set defname $file2
				catch { extract_defs }
				set dir [pwd]
				destroy .b
			}
		}
	}
}

proc reopen {} {
	global Fname

	catch {readinfile .inp.t $Fname} ermsg
	if {[string length $ermsg]<=1} { return }
	add_log $ermsg
	catch { tk_messageBox -icon info -message $ermsg }
}

proc writeoutfile {from to} {

  if ![file_ok $to] { return 0 }

  if [catch {set fd [open $to w]} errmsg] {
    add_log $errmsg
    catch { tk_messageBox -icon info -message $ermsg }
    return 0
  }

  add_log "<saved spec in $to>"
  puts $fd [string trimright [$from get 0.0 end] "\n"]
# puts -nonewline $fd [$from get 0.0 end]
  close $fd
  return 1
}

proc readinfile {into from} {

  if [catch {set fd [open $from r]} errmsg] {
    add_log $errmsg
    catch { tk_messageBox -icon info -message $ermsg }
    return 0
  }
	
  $into delete 0.0 end
  while {[gets $fd line] > -1} { $into insert end $line\n }
  catch { close $fd }
  add_log "<open $from>"

  global LastGenerate
  set LastGenerate ""	;# used in Validation.tcl
  return 1
}

proc fillerup {suffix} {
	wm title .b [pwd]
	.b.top.list delete 0 end

	set dotdot 0
	set l {}
	catch {	if {$suffix != ""} {
			set l [lsort [glob *.$suffix]]
		} else {
			set l [lsort [glob *]]
	}	}
	foreach i $l {
		.b.top.list insert end $i
		if {$i == ".."} { set dotdot 1 }
	}
	if {$dotdot == 0} {
		.b.top.list insert 0 ".."
	}
	if {$suffix != ""} {
		.b.top.list insert 0 "------files:--------"
		.b.top.list insert 0 "Objective(p,q,r)"
		.b.top.list insert 0 "Precedence(p,q,r)"
		.b.top.list insert 0 "Response(p,q)"
		.b.top.list insert 0 "Invariance(p)"
		.b.top.list insert 0 "-----templates:-----"
	}
}

proc gotoline {} {
	global BG FG

	catch { destroy .ln }
	toplevel .ln
	wm title .ln "Goto Line"
	wm iconname .ln "Goto"

	label .ln.lab -text "Enter line number:"
	entry .ln.ent -width 20 -relief sunken -textvariable lno
	pack append .ln \
		.ln.lab {left padx 1m} \
		.ln.ent {right expand}
	bind .ln.ent <Return> {
		.inp.t tag remove hilite 0.0 end
		.inp.t tag add hilite $lno.0 $lno.1000
		.inp.t tag configure hilite \
			-background $FG -foreground $BG
		.inp.t yview -pickplace [expr $lno-1]
	}
	focus .ln.ent
}

proc savebox {b} {
	set fname [.c$b.f.e1 get]
	if {[file_ok $fname]==0} return
	set fd [open $fname w]
	add_log "<saved output in $fname>"
	puts $fd "[.c$b.z.t get 0.0 end]" nonewline
	catch "flush $fd"
	catch "close $fd"
}

proc doplace {a b} {
	global PlaceBox
	set PlaceBox($a) [wm geometry .c$b]
	set k [string first "\+" $PlaceBox($a)]
	if {$k > 0} {
		set PlaceBox($a) [string range $PlaceBox($a) $k end]
	}
}

proc mkbox {n m p {wd 60} {ht 10} {xp 200} {yp 200}} {
	global boxnr FG BG PlaceBox

	incr boxnr

	toplevel .c$boxnr
	wm title .c$boxnr $n
	wm iconname .c$boxnr $m

	if {[info exists PlaceBox($n)] == 0} {
		set PlaceBox($n) "+$xp+$yp"
	} 
	wm geometry .c$boxnr $PlaceBox($n)

	frame .c$boxnr.z
	text .c$boxnr.z.t -relief raised -bd 2 \
		-background $BG -foreground $FG \
		-yscrollcommand ".c$boxnr.z.s set" \
		-setgrid 1 -width $wd -height $ht -wrap word
	scrollbar .c$boxnr.z.s \
		-command ".c$boxnr.z.t yview"
	pack append .c$boxnr.z \
		.c$boxnr.z.s {left filly} \
		.c$boxnr.z.t {left expand fill}

	button .c$boxnr.b -text "Close" \
	-command "doplace {$n} {$boxnr}; destroy .c$boxnr"
	button .c$boxnr.c -text "Clear" \
		-command ".c$boxnr.z.t delete 0.0 end"
	pack append .c$boxnr \
		.c$boxnr.z {top expand fill} \
		.c$boxnr.b {right padx 5} \
		.c$boxnr.c {right padx 5}

	if {[string length $p]>0} {
		frame  .c$boxnr.f -relief sunken
		button .c$boxnr.f.e0 -text "Save in: " \
			-command "savebox $boxnr"
		entry  .c$boxnr.f.e1 -relief flat -width 10
		.c$boxnr.f.e1 insert end $p
		pack append .c$boxnr.f \
			.c$boxnr.f.e0 {left padx 5} \
			.c$boxnr.f.e1 {left}
		pack append .c$boxnr \
			.c$boxnr.f {right padx 5}
	}

	tkwait visibility .c$boxnr
	return $boxnr
}

# Tcl/Tk book, page 219
proc forAllMatches {w pattern} {
	global BG FG lno

	scan [$w index end] %d numLines
	for {set i 1} {$i < $numLines} { incr i} {
		$w mark set last $i.0
		if {[regexp -indices $pattern \
			[$w get last "last lineend"] indices]} {
				$w mark set first \
					"last + [lindex $indices 0] chars"
				$w mark set last "last + 1 chars \
					+ [lindex $indices 1] chars"
			.inp.t tag add hilite $i.0 $i.end
			.inp.t tag configure hilite \
				-background $FG -foreground $BG
#			.inp.t yview -pickplace [expr $i-1]
	}	}

#	move to the next line that matches

	for {set i [expr $lno+1]} {$i < $numLines} { incr i} {
		$w mark set last $i.0
		if {[regexp -indices $pattern \
			[$w get last "last lineend"] indices]} {
				$w mark set first \
					"last + [lindex $indices 0] chars"
				$w mark set last "last + 1 chars \
					+ [lindex $indices 1] chars"
			.inp.t yview -pickplace [expr $i-5]
			set lno $i
			return
	}	}
	for {set i 1} {$i <= $lno} { incr i} {
		$w mark set last $i.0
		if {[regexp -indices $pattern \
			[$w get last "last lineend"] indices]} {
				$w mark set first \
					"last + [lindex $indices 0] chars"
				$w mark set last "last + 1 chars \
					+ [lindex $indices 1] chars"
			.inp.t yview -pickplace [expr $i-5]
			set lno $i
			return
	}	}
	catch {
		tk_messageBox -icon info -message "No Match of \"$pattern\""
	}
}

set noprep 0
set hasfile 0

proc hasWord {pattern} {
	global SPIN noprep hasfile

	set err ""
	if {$hasfile == 0 && $noprep == 0} {
		add_log "$SPIN -Z pan_in ;# preprocess input"
		catch {exec $SPIN -Z pan_in >&pan.tmp} err
		# leaves output in pan.pre
		add_log "<done preprocess>"
	}

	if {[string length $err] == 0 && $noprep == 0} {
		set hasfile 1
		set fd [open pan.pre r]
		while {[gets $fd line] > -1} {
		  if {[regexp -indices $pattern $line indices]} {
			catch "close $fd"
			return 1
		} }
		catch "close $fd"
		return 0
	}
	# else, ignore the include files:
	set noprep 1
	add_log "$err"
	scan [.inp.t index end] %d numLines
	for {set i 1} {$i < $numLines} { incr i} {
		.inp.t mark set last $i.0
		if {[regexp -indices $pattern \
			[.inp.t get last "last lineend"] indices]} {
				return 1
		}
	}
	return 0
}

# FSM view option

set nodeX(0) 0
set nodeY(0) 0
set Label(0) 0
set Transit(0) {}
set TLabel(0) 0
set Lab2Node(0) 0
set Dist(0) 0
set State(0) 0
set Edges(0) {}
set New 0
set MaxDist 0
set Maxx 0
set Maxy 0
set Minx 50
set Miny 50
set reached_end 0
set Scale 1

set cnr	0
set x 0
set y 0

proc fsmview {} {
	global Unix GO32

	add_log "<fsm view option>"

	if {[mk_exec] != 1} { return }

	catch {destroy .z}
	toplevel .z

	wm title .z "Double-Click Proc"

	listbox .z.list -setgrid 1
	button .z.b -text "Cancel" -command "destroy .z"

	pack append .z \
		.z.list {top expand fill} \
		.z.b {right padx 5}

	if {$Unix} {
		add_log "./pan -d	# find proc names"; update
		set fd [open "|./pan -d" w+]
	} else {
		add_log "$GO32 pan -d	# find proc names"; update
		set PREFIX "$GO32 pan"
		catch { eval exec $PREFIX -d >&pan.tmp } err
		if {$err != ""} {
			add_log "error: $err"
		}
		set fd [open pan.tmp r]
	}
	while {[gets $fd line] > -1} {
		if {[string first "proctype" $line] >= 0 } {
			.z.list insert end \
			[string trim [string range $line 9 end]]
	}	}
	catch { close $fd }

	bind .z.list <Double-Button-1> {
		set pfind [selection get]
		catch { destroy .z }
		findfsm $pfind
	}
	focus .z.list
}

proc findfsm {pfind} {
	global Unix GO32 New Dist State Edges Label
	global Transit MaxDist reached_end TLabel DOT

	if {[mk_exec] != 1} { return }

	set src  0; set trn 0; set trg 0
	set Want 0; set MaxDist 0; set startstate ""

	catch { foreach el [array names State] { unset State($el) } }
	catch { foreach el [array names Edges] { unset Edges($el) } }
	catch { foreach el [array names Dist]  { unset Dist($el) } }

	if {$Unix} {
		add_log "./pan -d	# compute fsm"; update
		set fd [open "|./pan -d" w+]
	} else {
		add_log "$GO32 pan -d	# compute fsm"; update
		set PREFIX "$GO32 pan"
		catch { eval exec $PREFIX -d >&pan.tmp }
		set fd [open pan.tmp r]
	}
	while {[gets $fd line] > -1} {
		set k [string first "proctype" $line]
		if { $k >= 0 } {
			if { $Want == 1 } {
				break
			}
			incr k 9
			set pname [string range $line $k end]

			if { [string first $pfind $line] >= 0 \
			&&   [string length $pfind] == [string length $pname]} {
				set Want 1
				set reached_end 0
				set nsrc "$pname:0"
				set Dist($nsrc) 0
				set Label($nsrc) "end"
				set Edges($nsrc) {}
			}
		} elseif { $Want == 1 \
			&& [string first "state" $line] >= 0} {
			scan $line "	state %d -(tr %d)-> state %d" \
				src trn trg
			if {$trg == 0} { set reached_end 1 }

			set nsrc "$pname:$src"
			set ntrg "$pname:$trg"

			if {$startstate == ""} { set startstate $nsrc }

			set k [string first "line" $line]
			if { $k > 0 } {
				set m [string first "=>" $line]
				incr m -1
				set lbl [string range $line $k $m]
				incr m 3
				set action [string range $line $m end]
			} else {
				set lbl "line 0"
				set action "line 0"
			}
			set Label($nsrc) $lbl
			if { [info exists Dist($nsrc)] == 0 } {
				set Dist($nsrc) 0
				set Edges($nsrc) {}
			}
			if { [info exists Dist($ntrg)] == 0 } {
				set Dist($ntrg) [expr $Dist($nsrc) + 1]
				set Edges($ntrg) {}
				if {$Dist($ntrg) > $MaxDist } {
					set MaxDist $Dist($ntrg)
				}
			} else {
				if { [expr $Dist($nsrc) + 1] < $Dist($ntrg) } {
					set Dist($ntrg) [expr $Dist($nsrc) + 1]
					if {$Dist($ntrg) > $MaxDist } {
						set MaxDist $Dist($ntrg)
					}
			}	}
if {0 \
&&  [auto_execok $DOT] != 0 \
&&  [auto_execok $DOT] != ""} {
	set z1 [string first "\[" $action]
	set z2 [string last  "\]" $action]
	if {$z1 > 0 && $z2 > $z1} {
		incr z1 -1; incr z2
		set a1 [string range $action 0 $z1]
		set a2 [string range $action $z2 end]
		set action "$a1$a2"
	}
			set kkk "$nsrc;$trg:$action"
			lappend Edges($nsrc) "$kkk"
			lappend Edges($kkk) $ntrg
			lappend Transit($nsrc) "$lbl"
			lappend Transit($kkk) ""
			set Dist($kkk) $Dist($ntrg)
			set Label($kkk) "T3"
} else {
			lappend Edges($nsrc) $ntrg
			lappend Transit($nsrc) $action
}
		}
	}
	if { $Want == 1 } {
		dograph $pfind $startstate
	} else {
		add_log "sorry, $pfind not found..."
		catch {
		tk_messageBox -icon info -message "$pfind not found..."
		}
	}
	catch "close $fd"
	add_log "<done>"
	update
}

proc plunknode {el prefix} {
	global State Label TLabel
	global x y

	set pn [string range $el $prefix end]
	set State($el) [mkNode "$Label($el)" $pn $x $y]

	if { $x > 250 } {
		set x [expr $x - 250]
		set x [expr 250 - $x]
	} else {
		set x [expr 250 - $x]
		incr x 75
		set x [expr 250 + $x]
	}
}

proc dograph {n s} {
	global Dist Edges Label Transit MaxDist State ELabel
	global cnr lcnr reached_end x y Unix DOT
	set count -1

	set lcnr [mkcanvas "FSM $n" $n 300 300 0]
	set prefix [string length $n]
	incr prefix
	set y 0

	while {$count < $MaxDist} {
		incr count
		incr y 50
		set x 250
		foreach el [array names Dist] {
			if { [ string first $n $el ] >= 0 \
			&&   $Dist($el) == $count \
			&&   $el != "$n:0" } {
				plunknode $el $prefix
		}	}
	}
	if {$reached_end == 1} {
		# force end state at the bottom
		incr y 50
		set x 250
		plunknode "$n:0" $prefix
	}

	foreach el [array names Edges] {
		if { [ string first $n $el ] >= 0 } {
			for {set i 0} { [lindex $Edges($el) $i] != "" } {incr i} {
				set ntrg [lindex $Edges($el) $i]
				set lbl  [lindex $Transit($el) $i]
				mkEdge $lbl $State($el) $State($ntrg)
				set ELabel($el,$ntrg) "$lbl"
			}
	}	}
	addscales $lcnr

	.f$cnr.c itemconfigure $State($s) -outline red; update

	if {[auto_execok $DOT] != 0 \
	&&  [auto_execok $DOT] != ""} {
		dodot $n
#		button .f$lcnr.b6 -text "Redraw with Dot"  -command "dodot $n"
#		pack append .f$lcnr .f$lcnr.b6 {right padx 5}
	}
	update
}

proc mkNode {n t x y} {
	# tcl book p. 213
	global cnr NodeWidth NodeHeight HelvSml
	global nodeX nodeY New TLabel Lab2Node

if {[string first ";" $t] > 0} {
	set New [.f$cnr.c create rectangle [expr $x-1] [expr $y-1] \
		[expr $x+1] [expr $y+1] \
		-outline white \
		-fill white \
		-tags node]
	set z [string first ":" $t]; incr z
	set t [string range $t $z end]
	set Lab [.f$cnr.c create text $x $y -font $HelvSml -text $t -tags node]
} else {
	set New [.f$cnr.c create oval [expr $x-10] [expr $y-10] \
		[expr $x+10] [expr $y+10] \
		-outline black \
		-fill white \
		-tags node]
	set Lab [.f$cnr.c create text $x $y -font $HelvSml -text $t -tags node]

	.f$cnr.c bind $Lab <Any-Enter> "
		.f$cnr.c itemconfigure {$Lab} -fill black -text {$n}
		if {[string first \"end\" $n] < 0 } { set_src {$n} }
	"
	.f$cnr.c bind $Lab <Any-Leave> "
		.f$cnr.c itemconfigure {$Lab} -fill black -text {$t}
	"
}
	set nodeX($New) $x
	set nodeY($New) $y
	set TLabel($New) $Lab
	set Lab2Node($Lab) $New
	set NodeWidth($New) 10
	set NodeHeight($New) 10

	update
	return $New
}

proc set_src {n} {
	set where 0
	scan $n "line %d" where
	.inp.t tag remove hilite 0.0 end
	src_line $where
}

proc mkEdge {L a b} {
	global cnr Xrem Yrem TransLabel HelvSml
	global nodeX nodeY edgeHead edgeTail

	if { $nodeY($b) > $nodeY($a) } {
		set ydiff -11
	} elseif { $nodeY($b) < $nodeY($a) } {
		set ydiff 11
	} else {
		set ydiff 0
	}
	if { $nodeX($b) > $nodeX($a) } {
		set xdiff -6
	} elseif { $nodeX($b) < $nodeX($a) } {
		set xdiff 6
	} else {
		set xdiff 0
	}
	set edge [.f$cnr.c create line \
		$nodeX($a) $nodeY($a) \
		[expr $nodeX($b) + $xdiff] \
		[expr $nodeY($b) + $ydiff] \
		 -arrow both -arrowshape {4 3 3} ]
	.f$cnr.c lower $edge
	lappend edgeHead($a) $edge
	lappend edgeTail($b) $edge

	set Xrem($edge) $xdiff
	set Yrem($edge) $ydiff

	set midX [expr $nodeX($a) + $nodeX($b)]
	set midX [expr $midX / 2 ]
	set midY [expr $nodeY($a) + $nodeY($b)]
	set midY [expr $midY / 2 ]

	set TransLabel($a,$b) \
	[.f$cnr.c create text $midX $midY -font $HelvSml -tags texttag]

	.f$cnr.c bind $edge <Button-1> "
		.f$cnr.c coords $TransLabel($a,$b) \[.f$cnr.c canvasx %x\] \[.f$cnr.c canvasy %y\]
		.f$cnr.c itemconfigure $TransLabel($a,$b) \
			-fill black -text {$L} -font $HelvSml
	"
	.f$cnr.c bind $edge <ButtonRelease-1> "
		.f$cnr.c itemconfigure $TransLabel($a,$b) \
			-fill black -text {}
	"
}

proc moveNode {cnr node mx my together} {
	global edgeHead edgeTail TLabel NodeWidth NodeHeight
	global nodeX nodeY Lab2Node
	global Xrem Yrem Scale

	set x [.f$cnr.c coords $node]
	if {[llength $x] == 2} { set node $Lab2Node($node) }

	set mx [.f$cnr.c canvasx $mx]
	set my [.f$cnr.c canvasy $my]

	set wx $NodeWidth($node)
	set wy $NodeHeight($node)

	.f$cnr.c coords $node \
		[expr $mx-$wx] [expr $my-$wy] \
		[expr $mx+$wx] [expr $my+$wy]
	.f$cnr.c coords $TLabel($node) $mx $my

	set nodeX($node) $mx
	set nodeY($node) $my
	if {$together == 0} { return }
	catch {
	foreach edge $edgeHead($node) {
		set ec [.f$cnr.c coords $edge]
		set nx [expr $nodeX($node) + $Xrem($edge)*$Scale]
		set ny [expr $nodeY($node) + $Yrem($edge)*$Scale]
		.f$cnr.c coords $edge \
			$nx $ny \
			[lindex $ec 2] [lindex $ec 3]
	}}
	catch {
	foreach edge $edgeTail($node) {
		set ec [.f$cnr.c coords $edge]
		set nx [expr $nodeX($node) + $Xrem($edge)*$Scale]
		set ny [expr $nodeY($node) + $Yrem($edge)*$Scale]
		.f$cnr.c coords $edge \
			[lindex $ec 0] [lindex $ec 1] \
			$nx $ny
	}}
}

set PlaceCanvas(msc)	""

proc mkcanvas {n m geox geoy placed} {
	global cnr tk_version
	global Chandle Sticky
	global FG BG Ptype PlaceCanvas

	incr cnr
	toplevel .f$cnr
	wm title .f$cnr "$n"
	wm iconname .f$cnr $m
	if {$placed} {
		if {$PlaceCanvas($m) == ""} {
			set PlaceCanvas($m) "+$geox+$geoy"
		}
		set k [string first "\+" $PlaceCanvas($m)]
		if {$k > 0} {
		set PlaceCanvas($m) [string range $PlaceCanvas($m) $k end]
		}
		wm geometry .f$cnr $PlaceCanvas($m)
	}
	wm minsize .f$cnr 100 100

	if {[string first "4." $tk_version] == 0 \
	||  [string first "8." $tk_version] == 0} {
		set cv [canvas .f$cnr.c  -relief raised -bd 2\
			-scrollregion {-15c -5c 30c 40c} \
			-background $BG \
			-xscrollcommand ".f$cnr.hscroll set" \
			-yscrollcommand ".f$cnr.vscroll set"]
		scrollbar .f$cnr.vscroll -relief sunken \
			-command ".f$cnr.c yview"
		scrollbar .f$cnr.hscroll -relief sunken -orient horiz \
			-command ".f$cnr.c xview"
	} else {
		set cv [canvas .f$cnr.c  -relief raised -bd 2\
			-scrollregion {-15c -5c 30c 40c} \
			-background $BG \
			-xscroll ".f$cnr.hscroll set" \
			-yscroll ".f$cnr.vscroll set"]
		scrollbar .f$cnr.vscroll -relief sunken \
			-command ".f$cnr.c yview"
		scrollbar .f$cnr.hscroll -relief sunken -orient horiz \
			-command ".f$cnr.c xview"
	}
	set Chandle($cnr) $cv
	#-width 500 -height 500

	button .f$cnr.b1 -text "Close" \
		-command "set PlaceCanvas($m) [wm geometry .f$cnr]; destroy .f$cnr"
	button .f$cnr.b2 -text "Save in: $m.ps" \
		-command "$cv postscript -file $m.ps -colormode $Ptype"

	pack append .f$cnr \
		.f$cnr.vscroll {right filly} \
		.f$cnr.hscroll {bottom fillx} \
		.f$cnr.c {top expand fill}

	if {$m == "msc"} {
		set Sticky($cnr) 0
		checkbutton .f$cnr.b6 -text "Preserve" \
			-variable Sticky($cnr) \
			-relief flat
		pack append .f$cnr \
			.f$cnr.b6 { right padx 5}
	}
	pack append .f$cnr \
		.f$cnr.b1 {right padx 5} \
		.f$cnr.b2 {right padx 5}

	bind $cv <2> "$cv scan mark %x %y"	;# Geert Janssen, TUE
	bind $cv <B2-Motion> "$cv scan dragto %x %y"

	.f$cnr.c bind node <B1-Motion> "
		moveNode $cnr \[.f$cnr.c find withtag current] %x %y 1
	"

#	.f$cnr.c bind node <B2-Motion> "
#		moveNode $cnr \[.f$cnr.c find withtag current] %x %y 1
#	"

	tkwait visibility .f$cnr
	return $cnr
}

proc addscales {p} {
	global Chandle Scale

	catch {
		set cv $Chandle($p)
		button .f$p.b4 -text "Larger" \
			-command "$cv scale all 0 0 1.1 1.1; set Scale [expr $Scale*1.1]"
		button .f$p.b5 -text "Smaller" \
			-command "$cv scale all 0 0 0.9 0.9; set Scale [expr $Scale*0.9]"
		pack append .f$p \
			.f$p.b4 {right padx 5} \
			.f$p.b5 {right padx 5}
	}
}

proc dodot {n} {
	global Edges edgeHead edgeTail NodeWidth NodeHeight Maxx Maxy
	global State ELabel TransLabel Unix cnr lcnr Xrem Yrem DOT

	add_log "<dot graph layout...>"
	set fd [open "|$DOT" w+]

	puts $fd "digraph dodot {"

	foreach el [array names Edges] {
		if { [ string first $n $el ] >= 0 } {
		for {set i 0} { [lindex $Edges($el) $i] != "" } {incr i} {
			set ntrg [lindex $Edges($el) $i]
			puts $fd " \"$el\" -> \"$ntrg\"; "
		}
	}}

	puts $fd "}"
	flush $fd
	set ends ""
	set nodot 1
	while {[gets $fd line] > -1} {
		if {[string first "\}" $line] >= 0} {
			break;
		}
		set dd [string length $line]; incr dd -1
		while {[string range $line $dd $dd] == "\\"} {
			gets $fd more
			set line "[string range $line 0 [expr $dd-1]]$more"
			set dd [string length $line]; incr dd -1
		}
		if {[string first " -> " $line] >= 0} {
			set a [string first "\[pos=\"" $line]; incr a 8
			set b [string first "\"\];" $line]; incr b -1
			set b2 [string first "->" $line]
			set line1 [string range $line 0 [expr $a - 9]]
			set src [string range $line1 0 [expr $b2 - 1]]
			set src [string trim $src "	 \""]
			set trg [string range $line1 [expr $b2 + 3] [expr $a - 1]]
			set trg [string trim $trg "	 \""]
			set tp [string range $line [expr $a-2] [expr $a-2]]
			set line [string range $line $a $b]
			set k [split $line " "]
			set j [llength $k]
			set j2 [trunc [expr $j/2]]
			set coords ".f$cnr.c create line "
			set spline "-smooth 1"
			set nl $ELabel($src,$trg)
			if {$tp == "e"} {
				set ends "last"
				for {set i 1} {$i < $j} {incr i} {
					scan [lindex $k $i] "%d,%d" x y
					set coords " $coords[expr 50 + $x] [expr 50 + $Maxy - $y] "
					if {$i == $j2} {
						.f$cnr.c coords \
							$TransLabel($State($src),$State($trg)) \
							[expr 50 + $x] [expr 50 + $Maxy - $y]
						.f$cnr.c itemconfigure \
							$TransLabel($State($src),$State($trg)) \
							-fill black -text "$nl"
					}
				}
				scan [lindex $k 0] "%d,%d" x y
				set coords " $coords[expr 50 + $x] [expr 50 + $Maxy - $y] "
			} else {
				set ends "first"
				for {set i 0} {$i < $j} {incr i} {
					scan [lindex $k $i] "%d,%d" x y
					set coords " $coords[expr 50 + $x] [expr 50 + $Maxy - $y] "
					if {$i == $j2} {
						.f$cnr.c coords \
							$TransLabel($State($src),$State($trg)) \
							[expr 50 + $x] [expr 50 + $Maxy - $y]
						.f$cnr.c itemconfigure \
							$TransLabel($State($src),$State($trg)) \
							-fill black -text "$nl"
			}	}	}
			set coords "$coords -arrow $ends $spline -tags connector"

			set ne [eval $coords]
			set Xrem($ne) 10
			set Yrem($ne) 10

			continue
		}
		if {[string first "node " $line] >= 0 \
		||  [string first "\{" $line]    >= 0} {
			continue
		}
		if {[string first "graph " $line] >= 0} {
			set a [string first "\"" $line]; incr a
			set b [string last  "\"" $line]; incr b -1
			set line [string range $line $a $b]
			set k [split $line ","]
			if {[llength $k] == 4} {
				set Maxx [lindex $k 2]
				set Maxy [lindex $k 3]
			} else {
				set Maxx [lindex $k 0]
				set Maxy [lindex $k 1]
			}
			set nodot 0
		} else {	;# a node
			set a [string first "\[" $line]; incr a
			set b [string last  "\]" $line]; incr b -1
			set line1 [string range $line 0 [expr $a - 2]]
			set line  [string range $line $a $b]
			set nn [string trim $line1 "	 \""]

			set a [string first "pos=" $line]; incr a 5
			set b [string first "\"" [string range $line $a end]]
			set b [expr $a + $b - 1]
			set line1  [string range $line $a $b]
			set k [split $line1 ","]
			set x [lindex $k 0]
			set y [lindex $k 1]

			set a [string first "width=" $line]; incr a 7
			set b [string first "\"" [string range $line $a end]]
			set b [expr $a + $b - 1]
			set w [expr 75 * [string range $line $a $b]]

			set a [string first "height=" $line]; incr a 8
			set b [string first "\"" [string range $line $a end]]
			set b [expr $a + $b - 1]
			set h [expr 75 * [string range $line $a $b]]

		catch {
			set NodeWidth($State($nn)) [expr $w/2]
			set NodeHeight($State($nn)) [expr $h/2]
			moveNode $lcnr $State($nn) \
				[expr 50 + $x] [expr 50 + $Maxy - $y] 0
		} err
#puts $err
		}
	}
	catch { close $fd }

	if {$nodot} {
		add_log "<cannot find dot>"
		catch {
		tk_messageBox -icon info -message "<cannot find dot>"
		}
		return
	}

	foreach el [array names Edges] {
		if { [ string first $n $el ] >= 0 } {
			catch {
			foreach edge $edgeHead($State($el)) {
				.f$cnr.c delete $edge
			}
			unset edgeHead($State($el))
			unset edgeTail($State($el))
			}
	}	}
	.f$cnr.c bind node <B1-Motion> {}	;# no moving
	.f$cnr.c bind node <B2-Motion> {}
	catch { destroy .f$lcnr.b6 }
	button .f$lcnr.b6 -text "No Labels" \
		-command ".f$lcnr.c delete texttag; destroy .f$lcnr.b6"
	pack append .f$lcnr .f$lcnr.b6 {right padx 5}
}

proc trunc {p} {
	set foo [string first "." $p]
	if {$foo >= 0} {
		incr foo -1
		set p [string range $p 0 $foo]
	}
	return $p
}

# Help menus

proc aboutspin {} {
	global FG BG version xversion

	catch {destroy .h}
	toplevel .h

	wm title .h "About SPIN"
	wm iconname .h "About"
	message .h.t -width 600 -background $BG -foreground $FG \
	-text " $version
Xspin Version $xversion

Spin is an on-the-fly LTL model checking system
for proving properties of asynchronous software
system designs, first distributed in 1991.

The master sources for the latest version of
this software can always be found via:

http://netlib.bell-labs.com/netlib/spin/whatispin.html

or via anonymous ftp from host netlib.bell-labs.com
in directory /netlib/spin

For help:  spin_list@research.bell-labs.com

The Spin sources are (c) 1990-2000 Bell Labs,
Lucent Technologies, Murray Hill, NJ, USA.
All rights are reserved. This software is for
educational and research purposes only.
No guarantee whatsoever is expressed or implied
by the distribution of this code.
"
	button .h.b -text "Ok" -command {destroy .h}
	pack append .h .h.t {top expand fill}
	pack append .h .h.b {top}
}

proc abouthsf-spin {} {
	global FG BG version xversion

	catch {destroy .h}
	toplevel .h

	wm title .h "About HSF-SPIN"
	wm iconname .h "About"
	message .h.t -width 600 -background $BG -foreground $FG \
	-text " $version
Xspin Version $xversion

HSF-SPIN 1.0
A Simple Promela Verifier based on Heuristic Search Strategies.
This tool is based on Spin 3.4.5  (by G.J. Holzmann) and
                   on HsfLight 2.0 (by S. Edelkamp)

The master sources for the latest version of
this software can always be found via:

http://www.informatik.uni-freiburg.de/~lafuente/hsf-spin

The Spin sources are (c) Institut for Computer Science,
Albert-Ludwigs-University Freiburg, Germany
All rights are reserved. This software is for
educational and research purposes only.
No guarantee whatsoever is expressed or implied
by the distribution of this code.
"
	button .h.b -text "Ok" -command {destroy .h}
	pack append .h .h.t {top expand fill}
	pack append .h .h.b {top}
}

proc promela {} {
	global FG BG

	catch {destroy .h}
	toplevel .h

	wm title .h "Promela URL"
	wm iconname .h "Promela"
	message .h.t -width 600 -background $BG -foreground $FG \
	-text "All Promela references are available online:

http://cm.bell-labs.com/cm/cs/what/spin/Man/index.html

"
	button .h.b -text "Ok" -command {destroy .h}
	pack append .h .h.t {top expand fill}
	pack append .h .h.b {top}
}

proc helper {} {
	global FG BG

	catch {destroy .h}
	toplevel .h

	wm title .h "Help with Xspin"
	wm iconname .h "Help"
	message .h.t -background $BG -foreground $FG \
	-text "\
Spin Version 3.4 Controller - (c) 1993-2000 Bell Laboratories

To use this interface you need Spin Version 3.4.0 or later.

Enter a Promela model into the main text window, or 'Open'
one via the File Menu (e.g., from Spin's Test directory).
Once loaded, you can revert to the stored version of the file
with option ReOpen.  Select Clear to empty the text window.

In the log, just below the text-window, background
commands are printed that Xspin generates.
Outputs from Simulation and Verification runs always
appear in separate windows.

All run-time options are available through the Run menu.
A typical way of working with Xspin is to use:

- First a Syntax Check to get hints and warnings
- Random Simulation for further debugging
- Add the properties to be verified (assertions, never claims)
- Perform a Slicing Check to check for redundancy
- Perform Verification for a correctness proof
- Guided Simulation to inspect errors reported by
  the Verification option

Clicking Button-1 in the main window updates the
Line number display at the top of the window -- as a
simple way of finding out at what line you are.

You can also use another editor to update the
specifications outside Xspin, and use the ReOpen
command from the File menu to refresh the Xspin
edit buffer before starting each new simulation or
verification run."
	button .h.b -text "Ok" -command {destroy .h}
	pack append .h .h.t {top expand fill}
	pack append .h .h.b {top}
}

# LTL interface

set formula ""
set tl_stat 0

proc put_template {s} {
	.tl.main.e1 delete 0 end
	.tl.main.e1 insert end "$s"
}

set PlaceTL	"+100+1"

proc call_tl {} {	;# expanded interface
	global formula tl_stat nv_typ an_typ cp_typ
	global FG BG Fname firstime PlaceTL

	catch {destroy .tl}
	toplevel .tl

	set k [string first "\+" $PlaceTL]
	if {$k > 0} {
		set PlaceTL [string range $PlaceTL $k end]
	}

	wm title .tl "Linear Time Temporal Logic Formulae"
	wm iconname .tl "LTL"
	wm geometry .tl $PlaceTL

	frame .tl.main
	entry .tl.main.e1 -relief sunken \
		-background $BG -foreground $FG
	label .tl.main.e2 -text "Formula: "

	frame .tl.op
	set alw {\[\] }
	set eve {\<\> }
	pack append .tl.op [label .tl.op.s0 -text "Operators: " \
		-relief flat] {left}
	pack append .tl.op [button .tl.op.always -width 1 -text "\[\]" \
		-command ".tl.main.e1 insert insert \"$alw \""] {left}
	pack append .tl.op [button .tl.op.event -width 1 -text "\<\>" \
		-command ".tl.main.e1 insert insert \"$eve \""] {left}
	pack append .tl.op [button .tl.op.until -width 1 -text "U" \
		-command ".tl.main.e1 insert insert \" U \""] {left}
	pack append .tl.op [button .tl.op.impl -width 1 -text "->" \
		-command ".tl.main.e1 insert insert \" -> \""] {left}
	pack append .tl.op [button .tl.op.and -width 1 -text "and" \
		-command ".tl.main.e1 insert insert \" && \""] {left}
	pack append .tl.op [button .tl.op.or -width 1 -text "or" \
		-command ".tl.main.e1 insert insert \" || \""] {left}
	pack append .tl.op [button .tl.op.not -width 1 -text "not" \
		-command ".tl.main.e1 insert insert \" ! \""] {left}

	frame .tl.b -relief ridge -borderwidth 4
	label .tl.b.s0 -text "Property holds for: "
	radiobutton .tl.b.s1 -text "All Executions (desired behavior)" \
		-variable tl_stat -value 0
	radiobutton .tl.b.s2 -text "No Executions (error behavior)" \
		-variable tl_stat -value 1
	pack append .tl.b \
		.tl.b.s0 {left} \
		.tl.b.s1 {left} \
		.tl.b.s2 {left}

	.tl.main.e1 insert end $formula

	button .tl.main.file -text "Load..." \
		-command "browse_tl"

	bind .tl.main.e1 <Return> { do_ltl }

	pack append .tl.main \
		.tl.main.e2 {top left}\
		.tl.main.e1 {top left expand fill} \
		.tl.main.file {top right}

	pack append .tl .tl.main {top fillx frame e}
	pack append .tl .tl.op {top frame w}
	pack append .tl .tl.b {top fillx frame w}

	frame .tl.macros -relief ridge -borderwidth 4
	label .tl.macros.title -text "Symbol Definitions:" -relief flat
	scrollbar .tl.macros.s -relief flat \
		-command ".tl.macros.t yview"
	text .tl.macros.t -height 4 -relief raised -bd 2 \
		-yscrollcommand ".tl.macros.s set" \
		-background $BG -foreground $FG \
		-setgrid 1 \
		-wrap word

	pack append .tl.macros \
		.tl.macros.title {top frame w} \
		.tl.macros.s {left filly} \
		.tl.macros.t {left expand fill}

	frame .tl.notes -relief ridge -borderwidth 4
	label .tl.notes.title -text "Notes: " -relief flat
	scrollbar .tl.notes.s -relief flat \
		-command ".tl.notes.t yview"
	text .tl.notes.t -height 4 -relief raised -bd 2 \
		-yscrollcommand ".tl.notes.s set" \
		-background $BG -foreground $FG \
		-setgrid 1 \
		-wrap word
	pack append .tl.notes \
		.tl.notes.title {top fillx frame w} \
		.tl.notes.s {left filly} \
		.tl.notes.t {left expand fill}

	frame .tl.never
	frame .tl.never.top
	label .tl.never.top.title -text "Never Claim:"\
		 -relief flat
	button .tl.never.top.gc -text "Generate" \
		-command "do_ltl"
	pack append .tl.never.top \
		.tl.never.top.gc {right}\
		.tl.never.top.title {left}

	scrollbar .tl.never.s -relief flat \
		-command ".tl.never.t yview"
	text .tl.never.t -height 8 -relief raised -bd 2 \
		-yscrollcommand ".tl.never.s set" \
		-setgrid 1 \
		-wrap word
	pack append .tl.never \
		.tl.never.top {top fillx frame w} \
		.tl.never.s {left filly} \
		.tl.never.t {left expand fill}

	frame .tl.results
	frame .tl.results.top

	button .tl.results.top.svp -text "Run Verification" \
		-command "do_ltl; basicval2"
	label .tl.results.top.title -text "Verification Result:"\
		 -relief flat
	pack append .tl.results.top \
		.tl.results.top.svp {right}\
		.tl.results.top.title {left}

	scrollbar .tl.results.s -relief flat \
		-command ".tl.results.t yview"
	text .tl.results.t -height 7 -relief raised -bd 2 \
		-yscrollcommand ".tl.results.s set" \
		-setgrid 1 \
		-wrap word
	pack append .tl.results \
		.tl.results.top {top fillx frame w} \
		.tl.results.s {left filly} \
		.tl.results.t {left expand fill}

	pack append .tl \
		.tl.notes {top expand fill} \
		.tl.macros {top expand fill} \
		.tl.never {top expand fill} \
		.tl.results {top expand fill} \

	pack append .tl [button .tl.sv -text "Save As.." \
		-command "save_tl"] {right}
	pack append .tl [button .tl.exit -text "Close" \
	-command "set PlaceTL [wm geometry .tl]; destroy .tl"] {right}

	pack append .tl [button .tl.help -text "Help" -fg red \
		-command "roadmap4"] {left}
	pack append .tl [button .tl.clear -text "Clear" \
		-command ".tl.main.e1 delete 0 end; .tl.never.t delete 0.0 end"] {left}

	loaddefault_tl
	focus .tl.main.e1
}

proc purge_nvr {foo} {
	set j [llength $foo]; incr j -1
	for {set i $j} {$i >= 0} {incr i -1} {
		set k [lindex $foo $i]
		set kk [expr $k+1]
		.tl.never.t delete $k.0 $kk.0
	}
}

proc grab_nvr {inp target} {

	set pattern $inp
	scan [.tl.never.t index end] %d numLines
	set foo {}
	set yes 0

	for {set i 1} {$i < $numLines} { incr i} {
		.tl.never.t mark set last $i.0
		set have [.tl.never.t get last "last lineend + 1 chars"]
		if {[regexp -indices $pattern $have indices]} {
			lappend foo $i
			set yes [expr 1 - $yes]
			if {$yes} {
				set pattern "#endif"
			} else {
				set pattern $inp
			}
		}
		if {$yes && [string first $inp $have] != 0} {
			$target insert end "$have"
			lappend foo $i
		}
	}
	purge_nvr $foo
}

proc extract_defs {} {
	global tl_stat

	set pattern "#define "
	scan [.tl.never.t index end] %d numLines
	set foo {}
	set tl_stat 1
	for {set i 1} {$i < $numLines} { incr i} {
		.tl.never.t mark set last $i.0
		set have [.tl.never.t get last "last lineend + 1 chars"]
		if {[regexp -indices $pattern $have indices]} {
			.tl.macros.t insert end "$have"
			lappend foo $i
		}
		set have [.tl.never.t get last "last lineend"]
		set k [string first "Formula As Typed: " $have]
		if {$k > 0} {
			set ff [string range $have [expr $k+18] end]
			.tl.main.e1 insert end $ff
		}
		if {[string first "To The Negated Formula " $have] > 0} {
			set tl_stat 0
		}
	}
	purge_nvr $foo

	grab_nvr "#ifdef NOTES"  .tl.notes.t
	grab_nvr "#ifdef RESULT" .tl.results.t
}

proc inspect_ltl {} {
	global formula
	set formula "[.tl.main.e1 get]"

	set x $formula
	regsub -all {\&\&} "$x" " " y; set x $y
	regsub -all {\|\|} "$x" " " y; set x $y
	regsub -all {\/\\} "$x" " " y; set x $y
	regsub -all {\\\/} "$x" " " y; set x $y
	regsub -all {\!}  "$x" " " y; set x $y
	regsub -all {<->} "$x" " " y; set x $y
	regsub -all {\->}  "$x" " " y; set x $y
	regsub -all {\[\]} "$x" " " y; set x $y
	regsub -all {\<\>} "$x" " " y; set x $y
	regsub -all {[()]} "$x" " " y; set x $y
	regsub -all {\ \ *} "$x" " " y; set x $y
	regsub -all { U} "$x" " " y; set x $y
	regsub -all { V} "$x" " " y; set x $y
	regsub -all { X} "$x" " " y; set x $y

	set predefs " np_ true false "

	set k [split $x " "]
	set j [llength $k]
	set line [.tl.macros.t get 0.0 end]
	for {set i 0} {$i < $j} {incr i} {
		if {[string length [lindex $k $i]] > 0 \
		&&  [string first " [lindex $k $i] " $predefs] < 0} {
		  set pattern "#define [lindex $k $i]"
		  if {[string first $pattern $line] < 0} {
			catch {
			.tl.macros.t insert end "$pattern\t?\n"
			}
			set line [.tl.macros.t get 0.0 end]
	}	} }
}

proc do_ltl {} {
	global formula tl_stat Unix SPIN tk_major tk_minor

	set formula "[.tl.main.e1 get]"
	.tl.never.t delete 0.0 end
	update

	catch { inspect_ltl }

	if {$tl_stat == 0} {
		add_log "$SPIN -f \"!( $formula )\""
		if {$Unix || ($tk_major == 4 && $tk_minor >= 2)} {
		catch {exec $SPIN -f "!($formula)" >&pan.ltl} err
		} else {
		catch {exec $SPIN -f \"!($formula)\" >&pan.ltl} err
		}
	} else {
		add_log "$SPIN -f \"( $formula )\""
		if {$Unix} {
		catch {exec $SPIN -f "($formula)" >&pan.ltl} err
		} else {
		catch {exec $SPIN -f \"($formula)\" >&pan.ltl} err
		}
	}
	set lno 0

	if {$err != ""} {
		add_log "<error: $err>"
		add_log "hint: check the Help Button for syntax rules"
	} else {
		.tl.never.t insert end \
		"	/*\n"
		.tl.never.t insert end \
		"	 * Formula As Typed: $formula\n"
		incr lno 2
		if {$tl_stat == 0} {
			.tl.never.t insert end \
			"	 * The Never Claim Below Corresponds\n"
			.tl.never.t insert end \
			"	 * To The Negated Formula !($formula)\n"
			.tl.never.t insert end \
			"	 * (formalizing violations of the original)\n"
			incr lno 3
		}
		.tl.never.t insert end \
		"	 */\n\n"
		incr lno 2
	}
	catch {
		set fd [open pan.ltl r]
		while {[gets $fd line] > -1} {
			.tl.never.t insert end "$line\n"
		}
		close $fd
	}
	rmfile pan.ltl
}

proc dump_tl {bb} {

	if {$bb != ""} {
		set fnm $bb
	} else {
		set fnm [.sv_tl.ent get]
	}

	if {[file_ok $fnm]==0} return
	set fd [open $fnm w]
	add_log "<save claim in $fnm>"
	catch {	puts $fd "[.tl.macros.t get 0.0 end]" nonewline }

	puts $fd "[.tl.never.t get 0.0 end]" nonewline

	catch {	puts $fd "#ifdef NOTES"
		puts $fd "[.tl.notes.t get 0.0 end]" nonewline
		puts $fd "#endif"
	}
	catch {	puts $fd "#ifdef RESULT"
		puts $fd "[.tl.results.t get 0.0 end]" nonewline
		puts $fd "#endif"
	}

	catch "flush $fd"
	catch "close $fd"
	catch "destroy .sv_tl"
	catch "focus .tl.main.e1"
}

proc save_tl {} {
	global Fname PlaceWarn
	catch {destroy .sv_tl}
	toplevel .sv_tl

	wm title .sv_tl "Save Claim"
	wm iconname .sv_tl "Save"
	wm geometry .sv_tl $PlaceWarn

	label  .sv_tl.msg -text "Name for LTL File: " -relief flat
	entry  .sv_tl.ent -width 6 -relief sunken -textvariable fnm
	button .sv_tl.b1 -text "Ok" -command { dump_tl "" }
	button .sv_tl.b2 -text "Cancel" -command "destroy .sv_tl"
	bind   .sv_tl.ent <Return> { dump_tl "" }

	set fnm [.sv_tl.ent get]
	if {$fnm == ""} {
		.sv_tl.ent insert end "$Fname.ltl"
	}

	pack append .sv_tl \
		.sv_tl.msg {top frame w} \
		.sv_tl.ent {top frame e expand fill} \
		.sv_tl.b1 {right frame e} \
		.sv_tl.b2 {right frame e}
	focus .sv_tl.ent
}

proc add_tl {} {
	global BG FG PlaceWarn
	catch {destroy .warn}
	toplevel .warn
	set k [string first "\+" $PlaceWarn]
	if {$k > 0} {
		set PlaceWarn [string range $PlaceWarn $k end]
	}

	wm title .warn "Accept"
	wm iconname .warn "Accept"
	wm geometry .warn $PlaceWarn

	message .warn.t -width 300 \
		-background $BG -foreground $FG \
		-text " \
Instructions:

1. Save the Never Claim in a file, \
for instance a file called 'never', \
using the <Save> button.

2. Insert the line

#include \"never\"

(the name of the file with the claim) \
at the end of the main specification.

3. Insert macro definitions (#define's) for all \
propositional symbols used in the formula.

For instance, with LTL formula
'[] p -> <> q'  add the macro defs:

#define p	(cnt == 1)
#define q	(cnt > 1)

These macros must be defined just above the line \
with the #include \"never\" directive

4. Perform the verification, and make sure that \
the box 'Apply Never Claim' is checked in the \
Verification Panel (or else the claim is ignored).
You can have a library of claim files that you can \
choose from for verification, by changing only the \
name of the include file.

5. Never claims have no effect during simulation runs.

6. See the HELP->LTL menu for more information.

"
	button .warn.b -text "Ok" \
		-command {set PlaceWarn [wm geometry .warn]; destroy .warn}
	pack append .warn .warn.t {top expand fill}
	pack append .warn .warn.b {right frame e}
}

proc roadmap4 {} {
	global FG BG

	catch {destroy .h}
	toplevel .h

	wm title .h "LTL Help"
	wm iconname .h "Help"
	frame .h.z
	scrollbar .h.z.s -command ".h.z.t yview"
	text .h.z.t -relief raised -bd 2 \
		-background $BG -foreground $FG \
		-yscrollcommand ".h.z.s set" \
		-setgrid 1 -width 60 -height 30 -wrap word
	pack append .h.z \
		.h.z.s {left filly} \
		.h.z.t {left expand fill}
	.h.z.t insert end "GUIDELINES:
You can load an LTL template or a previously saved LTL
formula from a file via the LOAD button on the upper
right of the LTL Property Manager panel.

Define a new LTL formula using lowercase names for the
propositional symbols, for instance:
	[] (p U q)
The formula expresses either a positive (desired) or a
negative (undesired) property of the model.  A positive
property is negated automatically by the translator to
convert it in a never claim (which expresses the
corresponding negative property (the undesired behavior
that is claimed 'never' to occur).

When you type a <Return> or hit the <Generate> button,
the formula is translated into an equivalent never-claim.

You must add a macro-definition for each propositional
symbol used in the LTL formula.  Insert these definitions
in the symbols window of the LTL panel, they will be
remembered together with the annotations and verification
result if the formula is saved in an .ltl file.
Enclose the symbol definitions in braces, to secure correct
operator precedence, for instance:

#define p	(a > b)
#define q	(len(q) < 5)

Valid temporal logic operators are:
	\[\]  Always (no space between \[ and \])
	<>  Eventually (no space between < and >)
	U   (Strong) Until
	V   The Dual of Until: (p V q) == !(!p U !q)

	All operators are left-associative (incl. U and V).

Boolean Operators:
	&&  Logical And (alternative form: /\\, no spaces)
	!   Logical Negation
	||  Logical Or  (alternative form: \\/, no spaces)
	->  Logical Implication
	<-> Logical Equivalence

Boolean Predicates:
	true, false
	any name that starts with a lowercase letter

Examples:
	\[\] p
	!( <> !q )
	p U q
	p U (\[\] (q U r))

Generic properties/Templates:
	Invariance: \[\] p
	Response:   p -> \<\> q
	Precedence: p -> (q U r)
	Objective:  p -> \<\> (q || r)

	Each of the above 4 generic types of properties
	can (and will generally have to) be prefixed by
	temporal operators such as
		\[\], \<\>, \[\]\<\>, \<\>\[\]
	The last (objective) property can be read to mean
	that 'p' is a trigger, or 'enabling' condition that
	determines when the requirement becomes applicable
	(e.g. the sending of a new data message); then 'q'
	can be the fullfillment of the requirement (e.g.
	the arrival of the matching acknowledgement), and
	'r' could be a discharging condition that voids the
	applicability of the check (an abort condition).
"
	button .h.b -text "Ok" -command {destroy .h}
	pack append .h .h.z {top expand fill}
	pack append .h .h.b {top}
	.h.z.t configure -state disabled 
	.h.z.t yview -pickplace 1.0      
	focus .h.z.t
}



# Specific Help

proc roadmap1 {} {
	global FG BG

	catch {destroy .road1}
	toplevel .road1

	wm title .road1 "Help with Simulation"
	wm iconname .road1 "SimHelp"
	frame .road1.z
	scrollbar .road1.z.s -command ".road1.z.t yview"
	text .road1.z.t -relief raised -bd 2 \
		-background $BG -foreground $FG \
		-yscrollcommand ".road1.z.s set" \
		-setgrid 1 -width 60 -height 30 -wrap word
	pack append .road1.z \
		.road1.z.s {left filly} \
		.road1.z.t {left expand fill}
	.road1.z.t insert end "GUIDELINES:
0.  Always use a Syntax Check before running simulations.\
It shakes out the more obvious flaws in the model.

1.  Random simulation option is used to debug a model.\
Other than assert statements, no correctness requirements\
are checked during simulation runs. All nondeterministic\
decisions are resolved randomly.  You can of course still\
force a selection to go into a specific direction by \
modifying the model.\
A random run is repeated precisely if the Seed Value\
for the random number generator is kept the same.

2.  Interactive simulation can be used to force the\
execution towards a known point.  The user is prompted\
at every point in the execution where a nondeterministic\
choice has to be resolved.

3.  A guided simulation is used to follow an error-trail that was\
produced by the verifier.  If the trail gets to be thousands of execution\
steps long, this can be time-consuming. \
You can skip the initial portion of such a long trail by typing\
a number in  the 'Steps Skipped' box in the Simulation Panel .

4. The options in the Simulations Panel allow you to enable or\
disable types of displays that are maintained during simulation\
runs.  Usually, it is not necessary to look at all possible display panels.\
Experiment to see which displays you find most useful.

5. To track the value changes of Selected variables, in the\
Message Sequence Chart and in the Variable Values Panel, add a prefix\
'show ' to the declaration of the selected variables in the Promela\
specification, e.g. use 'show byte cnt;' instead of 'byte cnt;'"

	button .road1.b -text "Ok" -command {destroy .road1}
	pack append .road1 .road1.z {top expand fill}
	pack append .road1 .road1.b {top}
	.road1.z.t configure -state disabled 
	.road1.z.t yview -pickplace 1.0      
	focus .road1.z.t
}

proc roadmap2a {} {
	global FG BG

	catch {destroy .road2}
	toplevel .road2

	wm title .road2 "Help with Verification Parameters"
	wm iconname .road2 "ValHelp"
	frame .road2.z
	scrollbar .road2.z.s -command ".road2.z.t yview"
	text .road2.z.t -relief raised -bd 2 \
		-background $BG -foreground $FG \
		-yscrollcommand ".road2.z.s set" \
		-setgrid 1 -width 60 -height 18 -wrap word
	pack append .road2.z \
		.road2.z.s {left filly} \
		.road2.z.t {left expand fill}
	.road2.z.t insert end "Physical Memory Available:
Set this number to amount of physical (not virtual)
memory in your system, in MegaBytes, and leave it there for all runs.

When the limit is reached, the verification is stopped to
avoid trashing.

The number entered here is the number of MegaBytes directly
(not a power of two, as in previous versions of xspin).

If an exhaustive verification cannot be completed due to
lack of memory, use compression, or switch to a
supertrace/bitstate run under basic options."

	button .road2.b -text "Ok" -command {destroy .road2}
	pack append .road2 .road2.z {top expand fill}
	pack append .road2 .road2.b {top}
	.road2.z.t configure -state disabled 
	.road2.z.t yview -pickplace 1.0      
	focus .road2.z.t
}
proc roadmap2b {} {
	global FG BG

	catch {destroy .road2}
	toplevel .road2

	wm title .road2 "Help with Verification"
	wm iconname .road2 "ValHelp"
	frame .road2.z
	scrollbar .road2.z.s -command ".road2.z.t yview"
	text .road2.z.t -relief raised -bd 2 \
		-background $BG -foreground $FG \
		-yscrollcommand ".road2.z.s set" \
		-setgrid 1 -width 60 -height 15 -wrap word
	pack append .road2.z \
		.road2.z.s {left filly} \
		.road2.z.t {left expand fill}
	.road2.z.t insert end "Estimated State Space Size:
This parameter is used to calculate the size of the
hash-table.  Setting it too high may cause an
out-of-memory error with zero states reached (meaning
that the verification cannot even be started).
Setting it too low can cause inefficiencies due to
hash collisions.

In Bitstate runs begin with the default estimate for
this parameter.  After a run completes successfully,
double the estimate, and see if the number of reached
stated changes much.  Continue to do this until
it stops changing, or until you overflow the memory
bound and run out of memory.

The closest power of two is taken by xspin to set the
true number used for the number of reachable states.
(The selected power of two is visible as the -w argument
in the run-line that xspin synthesizes)."

	button .road2.b -text "Ok" -command {destroy .road2}
	pack append .road2 .road2.z {top expand fill}
	pack append .road2 .road2.b {top}
	.road2.z.t configure -state disabled 
	.road2.z.t yview -pickplace 1.0      
	focus .road2.z.t
}
proc roadmap2c {} {
	global FG BG

	catch {destroy .road2}
	toplevel .road2

	wm title .road2 "Help with Verification"
	wm iconname .road2 "ValHelp"
	frame .road2.z
	scrollbar .road2.z.s -command ".road2.z.t yview"
	text .road2.z.t -relief raised -bd 2 \
		-background $BG -foreground $FG \
		-yscrollcommand ".road2.z.s set" \
		-setgrid 1 -width 60 -height 20 -wrap word
	pack append .road2.z \
		.road2.z.s {left filly} \
		.road2.z.t {left expand fill}
	.road2.z.t insert end "Maximum Search Depth:
This number determines the size of the depth-first
search stack that is used during the verification.
The stack uses memory, so a larger number increases
the memory requirements, and a lower number decreases
it.  In a tight spot, when there seems not to be
sufficient memory for the search depth needed, you
can reduce the estimated state space size to free some
more memory for the stack.

If you hit the maximum search depth during a verification
(noted as 'Search not completed' or 'Search Truncated'
in the verification output) without finding an error,
double the search depth parameter and repeat the run."

	button .road2.b -text "Ok" -command {destroy .road2}
	pack append .road2 .road2.z {top expand fill}
	pack append .road2 .road2.b {top}
	.road2.z.t configure -state disabled 
	.road2.z.t yview -pickplace 1.0      
	focus .road2.z.t
}

proc roadmap2d {} {
	global FG BG

	catch {destroy .road2}
	toplevel .road2

	wm title .road2 "Help with Verification"
	wm iconname .road2 "ValHelp"
	frame .road2.z
	scrollbar .road2.z.s -command ".road2.z.t yview"
	text .road2.z.t -relief raised -bd 2 \
		-background $BG -foreground $FG \
		-yscrollcommand ".road2.z.s set" \
		-setgrid 1 -width 60 -height 26 -wrap word
	pack append .road2.z \
		.road2.z.s {left filly} \
		.road2.z.t {left expand fill}
	.road2.z.t insert end "GENERAL GUIDELINES:
=> When just starting out, it is safe to leave all parameters in the\
Verification Options Panel set at their initial value and to simply\
push the Run button in the Basic Options Panel for a default\
exhaustive verification.\
If you run out of memory, adjust the parameter settings as \
indicated under the 'explain' options.

=> If an error is found, first try to reduce the search depth to \
find a shorter equivalent.  Once you're content with the length,\
move on to a guided simulation to inspect the error-trail in detail.\
Optionally, use the Find Shortest Trail option, but note that this\
can increase runtime and memory use. So: do not use this option until\
you are certain that an error exists -- leave it turned off by default).

=> It is always safe to leave the Partial Order Reduction option enabled.\
Turn it off only for debugging purposes, or when warned to do so by the \
verifier itself.  The Profiling option gathers statistics about the \
verification hot-spots in the model.

=> If you save all error-trails, you have to copy the one you are\
interested in inspecting with a guided simulation onto the file\
pan_in.trail manually (outside xspin) after the run completes.\
The trails are numbered in order of discovery."

	button .road2.b -text "Ok" -command {destroy .road2}
	pack append .road2 .road2.z {top expand fill}
	pack append .road2 .road2.b {top}
	.road2.z.t configure -state disabled 
	.road2.z.t yview -pickplace 1.0      
	focus .road2.z.t
}

proc roadmap2e {} {
	global FG BG

	catch {destroy .road2}
	toplevel .road2

	wm title .road2 "Help with Verification"
	wm iconname .road2 "ValHelp"
	frame .road2.z
	scrollbar .road2.z.s -command ".road2.z.t yview"
	text .road2.z.t -relief raised -bd 2 \
		-background $BG -foreground $FG \
		-yscrollcommand ".road2.z.s set" \
		-setgrid 1 -width 60 -height 25 -wrap word
	pack append .road2.z \
		.road2.z.s {left filly} \
		.road2.z.t {left expand fill}
	.road2.z.t insert end "BASIC GUIDELINES:
When just starting out, it is safe to leave all parameters\
at their initial value and to push the Run button for a\
default exhaustive verification.\
If you run out of memory, adjust the parameter settings\
under Advanced Options.

=> Safety properties are properties of single states (like\
deadlocks = invalid endstates, or assertion violations).

=> Liveness properties are properties of sequences of\
states (typically: infinite sequences, i.e., cycles).\
There are two types of cycles: non-progress (not passing\
through any state marked with a 'progress' label) and\
acceptance (passing infinitely often through a state\
marked with an 'accept' label).

=> Use the Weak Fairness option only when really necessary,\
to avoid unwated error reports.  It can increase the CPU-time\
requirements by a factor roughly equal to twice the number of\
active processes.

=> It is safe to leave the Reduced Search option enabled.\
Turn it off only for debugging purposes, or when warned to do so by the \
verifier itself.   The Profiling option gathers statistics about the \
verification hot-spots in the model.

=> You can apply a Never Claim even when checking Safety Properties\
when you want to restrict the search to the sequences that are\
matched by the claim (a user-guided search pruning technique)."

	button .road2.b -text "Ok" -command {destroy .road2}
	pack append .road2 .road2.z {top expand fill}
	pack append .road2 .road2.b {top}
	.road2.z.t configure -state disabled 
	.road2.z.t yview -pickplace 1.0      
	focus .road2.z.t
}

proc roadmap2f {} {
	global FG BG

	catch {destroy .road2}
	toplevel .road2

	wm title .road2 "Help with Verification"
	wm iconname .road2 "ValHelp"
	frame .road2.z
	scrollbar .road2.z.s -command ".road2.z.t yview"
	text .road2.z.t -relief raised -bd 2 \
		-background $BG -foreground $FG \
		-yscrollcommand ".road2.z.s set" \
		-setgrid 1 -width 60 -height 15 -wrap word
	pack append .road2.z \
		.road2.z.s {left filly} \
		.road2.z.t {left expand fill}
	.road2.z.t insert end "GUIDELINES:
This will run a verification for the specific LTL property\
that was defined in the LTL options panel that brought you\
here.  The claim was placed in a separate .ltl\
file, not included in the main specification.\
(It will be picked up in the verification automatically.)\
The separate .ltl file combines the notes, formula,\
macros, results, etc., for easier tracking.

On a first run, leave all choices at their initial\
value and push the Run button for a default verification.\
If you run out of memory, adjust the parameter settings\
under Advanced Options.

Use the Weak Fairness option only when really necessary,\
to avoid unwated error reports.  It can increase the CPU-time\
requirements by a factor roughly equal to twice the number of\
active processes."

	button .road2.b -text "Ok" -command {destroy .road2}
	pack append .road2 .road2.z {top expand fill}
	pack append .road2 .road2.b {top}
	.road2.z.t configure -state disabled 
	.road2.z.t yview -pickplace 1.0      
	focus .road2.z.t
}

proc roadmap2 {} {
	global FG BG

	catch {destroy .road2}
	toplevel .road2

	wm title .road2 "Help with Verification"
	wm iconname .road2 "ValHelp"
	frame .road2.z
	scrollbar .road2.z.s -command ".road2.z.t yview"
	text .road2.z.t -relief raised -bd 2 \
		-background $BG -foreground $FG \
		-yscrollcommand ".road2.z.s set" \
		-setgrid 1 -width 60 -height 20 -wrap word
	pack append .road2.z \
		.road2.z.s {left filly} \
		.road2.z.t {left expand fill}
	.road2.z.t insert end "GUIDELINES:
When just starting out, it is safe to leave all
verification parameters set at their initial values
and to Run a default verification.
If you run out of memory, or encounter other problems,
look at the specific help options in the verification
settings panel.
One parameter is important to set correctly right from
the start: the physical memory size of your system.
It is by default set to 64 Mbytes.  Set it once to the
true amount of physical memory on your system, in Megabytes,
and never change it again (unless you buy more physical
memory for your machine of course).
You can find this parameter under advanced options in the
verification parameters panel.
Bitstate/Supertrace verifications are approximate, and
only used for models too large to verify exhaustively.
This option allows you to get at least an approximate
answer to the correctness of models that could otherwise
not be verified by a finite state system."

	button .road2.b -text "Ok" -command {destroy .road2}
	pack append .road2 .road2.z {top expand fill}
	pack append .road2 .road2.b {top}
	.road2.z.t configure -state disabled 
	.road2.z.t yview -pickplace 1.0      
	focus .road2.z.t
}

proc roadmap3 {} {
	global FG BG

	catch {destroy .road3}
	toplevel .road3

	wm title .road3 "Reducing Complexity"
	wm iconname .road3 "CompHelp"
	frame .road3.z
	scrollbar .road3.z.s -command ".road3.z.t yview"
	text .road3.z.t -relief raised -bd 2 \
		-background $BG -foreground $FG \
		-yscrollcommand ".road3.z.s set" \
		-setgrid 1 -width 60 -height 30 -wrap word
	pack append .road3.z \
		.road3.z.s {left filly} \
		.road3.z.t {left expand fill}
	.road3.z.t insert end "
When a verification cannot be completed because of\
computational complexity; here are some strategies that\
can be applied to combat this problem.

0. Run the Slicing Algorithm (in the Run Menu) to find\
potential redundancy in your model for the stated properties.

1. Try to make the model more general, more abstract.\
Remember that you are constructing a verification model and not\
an implementation.  SPIN's strength is in proving properties of\
*interactions* in a distributed system (the implicit assumptions\
that processes make about each other) -- it's strength is not in\
proving things about local *computations*, data dependencies etc.

2. Remove everything that is not directly related to the property\
you are trying to prove: redundant computations, redundant data. \
*Avoid counters*; avoid incrementing variables that are used for\
only book-keeping purposes.
The Syntax Check option will warn about the gravest offenses.

3. Asynchronous channels are a significant source of complexity in\
verification.  Use a synchronous channel where possible.  Reduce the\
number of slots in asynchronous channels to a minimum (use 2, or 3\
slots to get started).

4. Look for processes that merely transfer messages. Consider if\
you can remove processes that only copy incoming messages from\
one channel into another, by letting the sender generate the\
final message right away.  If the intermediate process makes\
choices (e.g., to delete or duplicate, etc.), let the sender\
make that choice, rather than the intermediate process.

5. Combine local computations into atomic, or d_step, sequences.

6. Avoid leaving scratch data around in variables.  You can reduce\
the number of states by, for instance, resetting local variables\
that are used inside atomic sequences to zero at the end of those\
sequences; so that the scratch values aren't visible outside the\
sequence.  Alternatively: introduce some extra global 'hidden'\
variables for these purposes (see the WhatsNew.html document).
Use the predefined variable \"_\" as a write-only scratch variable\
wherever possible.

7. If possible to do so: combine the behavior of two processes into\
a single one.  Generalize behavior;  focus on coordination aspects\
(i.e., the interfaces between processes, rather than the local\
computation inside processes).

8. Try to exploit the partial order reduction strategies.\
Use the xr and xs assertions (see WhatsNew.html); avoid sharing\
channels between multiple receivers or multiple senders.\
Avoid merging independent data-streams into a single shared channel."

	button .road3.b -text "Ok" -command {destroy .road3}
	pack append .road3 .road3.z {top expand fill}
	pack append .road3 .road3.b {top}
	.road3.z.t configure -state disabled 
	.road3.z.t yview -pickplace 1.0      
	focus .road3.z.t
}

proc roadmap5 {} {
	global FG BG

	catch {destroy .road5}
	toplevel .road5

	wm title .road5 "Spin Automata"
	wm iconname .road5 "FsmHelp"
	frame .road5.z
	scrollbar .road5.z.s -command ".road5.z.t yview"
	text .road5.z.t -relief raised -bd 2 \
		-background $BG -foreground $FG \
		-yscrollcommand ".road5.z.s set" \
		-setgrid 1 -width 60 -height 30 -wrap word
	pack append .road5.z \
		.road5.z.s {left filly} \
		.road5.z.t {left expand fill}
	.road5.z.t insert end "
The Spin Automata view option give a view of the
structure of the automata models that Spin uses in
the verification process.
Each proctype is represented by a unique automaton.

Chosing this option (in the Run menu) will cause Spin to
first generate a verifier, compile it, and then run it
(as pan -d) to obtain a description of the proctype
names and the corresponding automata.

After selecting (double-clicking) the proctype name desired,
the graph will be produced.  The default graph layout
algorithm is small and a self-contained part of Xspin,
but also rather crude.  Be on guard, therefore, for edges
that overlap (a typical case, for instance, is a backedge
that hides behind a series of forward edges. Use DOT
(see the README.html file on Spin) when possible for much
better graph layout.

In the default layout, the following button actions are
defined (the first one is not needed when using DOT):

1. Moving Nodes: either Button-1 or Button-2.
2. Displaying Edge Labels: hold Button-1 down on the edge.
3. Cross-References: Move the cursor over a Node to see the
   corresponding line in the Promela source, in the main
   Xspin window.

If labels look bad -- try changing the font definitions at
the start of the xspin.tcl file (hints are given there).
"
	button .road5.b -text "Ok" -command {destroy .road5}
	pack append .road5 .road5.z {top expand fill}
	pack append .road5 .road5.b {top}
	.road5.z.t configure -state disabled 
	.road5.z.t yview -pickplace 1.0      
	focus .road5.z.t
}

proc roadmap6 {} {
	global FG BG

	catch {destroy .road6}
	toplevel .road6

	wm title .road6 "Optional Compiler Directives"
	wm iconname .road6 "Optional"
	frame .road6.z
	scrollbar .road6.z.s -command ".road6.z.t yview"
	text .road6.z.t -relief raised -bd 2 \
		-background $BG -foreground $FG \
		-yscrollcommand ".road6.z.s set" \
		-setgrid 1 -width 80 -height 30 -wrap word
	pack append .road6.z \
		.road6.z.s {left filly} \
		.road6.z.t {left expand fill}
	.road6.z.t insert end "
		Use only when prompted:

NFAIR=N		size memory used for enforcing weak fairness (default N=2)
VECTORSZ=N	allocates memory (in bytes) for state vector (default N=1024)

		Related to partial order reduction:

CTL		limit p.o.reduction to subset consistent with branching time logic
GLOB_ALPHA	consider process death a global action
XUSAFE		disable validity checks of xr/xs assertions

		Speedups:

NOBOUNDCHECK	don't check array bound violations
NOCOMP		don't compress states with fullstate storage (uses more memory)
NOSTUTTER	disable stuttering rules (warning: changes semantics)

		Memory saving (slower):

MA=N		use a minimized DFA encoding for state vectors up to N bytes

		Experimental:

BCOMP		when in BITSTATE mode, computes hash over compressed state-vector
HYBRID_HASH	can shave a word (4 bytes) from state vectors with N%4=1
NIBIS		apply a small optimization of partial order reduction
NOVSZ		risky - removes 4 bytes from state vector - its length field.
PRINTF		enables printfs during verification runs
RANDSTORE=N	in BITSTATE mode, -DRANDSTORE=33 lowers prob of storing a state to 33%
W_XPT=N		with MA, write checkpoint files every multiple of N states stored
R_XPT		with MA, restart run from last checkpoint file written

		Debugging:

SDUMP		with CHECK: adds ascii dumps of state vectors
SVDUMP		add run option -pN to write N-byte state vectors into file sv_dump

		Already set by the other xspin options:

BITSTATE	use supertrace/bitstate instead of exhaustive exploration
HC		use hash-compact instead of exhaustive exploration
COLLAPSE	collapses state vector size by up to 80% to 90%
MEMCNT=N	set upperbound of 2^N bytes to memory that can be allocated
MEMLIM=N	set upperbound of N Mbytes to memory that can be allocated
NOCLAIM		exclude never claim from the verification, if present
NOFAIR		disable the code for weak-fairness (is faster)
NOREDUCE	disables the partial order reduction algorithm
NP		enable non-progress cycle detection (option -l, replacing -a),
PEG		add complexity profiling (transition counts)
REACH		guarantee absence of errors within the -m depth-limit
SAFETY		optimize for the case where no cycle detection is needed
VAR_RANGES	compute the effective value range of byte variables
CHECK		generate debugging information (see also below)
VERBOSE		elaborate debugging printouts
"
	button .road6.b -text "Ok" -command {destroy .road6}
	pack append .road6 .road6.z {top expand fill}
	pack append .road6 .road6.b {top}
	.road6.z.t configure -state disabled 
	.road6.z.t yview -pickplace 1.0      
	focus .road6.z.t
}


# simulation options panel

set s_options	""
set v_options	""
set a_options	""
set c_options	""
set hsf_v_options ""

set Blue	"blue";		#"yellow"
set Yellow	"yellow";	#"red"
set White	"white";	#"yellow"
set Red		"red";		#"yellow"
set Green	"green";	#"green"

set fd		0
set Depth	0
set Seq(0)	0
set Sdbox	0
set Spbox(0)	0
set sbox	0

set simruns	0
set stepper	0
set stepped	0
set VERBOSE	0
set SYMBOLIC	0
set howmany	0
set Choice(1)	0
set Sticky(0)	0
set SparseMsc	1
set showvars	0
set vv		1
set qv		1
set gvars	1
set lvars	0
set hide_q1	""
set hide_q2	""
set hide_q3	""
set PlaceSim	"+100+100"

proc simulation {} {
	global s_typ l_typ showvars hasfile qv PlaceSim
	global fvars gvars lvars SparseMsc HelvBig HelvSml
	global msc ebc tsc vv svars rvars seed jumpsteps
	global hide_q1 hide_q2 hide_q3

	.menu.run.m entryconfigure 4 -state normal
	set hasfile 0

	catch {destroy .s}
	toplevel .s
	set k [string first "\+" $PlaceSim]
	if {$k > 0} {
		set PlaceSim [string range $PlaceSim $k end]
	}

	wm title .s "Simulation Options"
	wm iconname .s "SIM"
	wm geometry .s $PlaceSim

	frame .s.opt -relief flat

	mkpan_in

	frame .s.opt.mode -relief raised -borderwidth 1m
	label .s.opt.mode.fld0 \
		-font $HelvBig \
		-text "Display Mode" \
		-relief sunken -borderwidth 1m

	checkbutton .s.opt.mode.fld4b -text "Time Sequence Panel - with:" \
		-variable tsc \
		-relief flat
	frame .s.opt.mode.flds
	radiobutton .s.opt.mode.flds.fld3 \
		-text "    Interleaved Steps" \
		-variable m_typ -value 2 \
		-relief flat
	radiobutton .s.opt.mode.flds.fld1 \
		-text "    One Window per Process" \
		-variable m_typ -value 0 \
		-relief flat
	radiobutton .s.opt.mode.flds.fld2 \
		-text "    One Trace per Process" \
		-variable m_typ -value 1 \
		-relief flat
	frame .s.opt.mode.flds.fld0 -width 15
	pack append .s.opt.mode.flds \
		.s.opt.mode.flds.fld0 {left frame w}\
		.s.opt.mode.flds.fld3 {top frame w}\
		.s.opt.mode.flds.fld1 {top frame w}\
		.s.opt.mode.flds.fld2 {top frame w}

	checkbutton .s.opt.mode.fld4a -text "MSC Panel - with:" \
		-variable msc \
		-relief flat
	frame .s.opt.mode.steps
	radiobutton .s.opt.mode.steps.fld5 -text "    Step Number Labels" \
		-variable SYMBOLIC -value 0 \
		-relief flat
	radiobutton .s.opt.mode.steps.fld6 -text "    Source Text Labels" \
		-variable SYMBOLIC -value 1 \
		-relief flat
	radiobutton .s.opt.mode.steps.fld7 -text "    Normal Spacing" \
		-variable SparseMsc -value 1 \
		-relief flat
	radiobutton .s.opt.mode.steps.fld8 -text "    Condensed Spacing" \
		-variable SparseMsc -value 0 \
		-relief flat
	frame .s.opt.mode.steps.fld0 -width 15
	pack append .s.opt.mode.steps \
		.s.opt.mode.steps.fld0 {left frame w}\
		.s.opt.mode.steps.fld5 {top frame w}\
		.s.opt.mode.steps.fld6 {top frame w}\
		.s.opt.mode.steps.fld7 {top frame w}\
		.s.opt.mode.steps.fld8 {top frame w}

	checkbutton .s.opt.mode.fld4c -text "Execution Bar Panel" \
		-variable ebc \
		-relief flat
	checkbutton .s.opt.mode.fld4d -text "Data Values Panel" \
		-variable vv \
		-relief flat

	frame .s.opt.mode.vars

	checkbutton .s.opt.mode.vars.fld4c -text "    Track Buffered Channels" \
		-variable qv \
		-relief flat
	checkbutton .s.opt.mode.vars.fld4d -text "    Track Global Variables" \
		-variable gvars \
		-relief flat
	checkbutton .s.opt.mode.vars.fld4e -text "    Track Local Variables" \
		-variable lvars \
		-relief flat

	checkbutton .s.opt.mode.vars.fld4f \
		-text "    Display vars marked 'show' in MSC" \
		-variable showvars \
		-relief flat
	frame .s.opt.mode.vars.fld0 -width 15
	pack append .s.opt.mode.vars \
		.s.opt.mode.vars.fld0 {left frame w}\
		.s.opt.mode.vars.fld4c {top frame w}\
		.s.opt.mode.vars.fld4d {top frame w}\
		.s.opt.mode.vars.fld4e {top frame w}\
		.s.opt.mode.vars.fld4f {top frame w}

	pack append .s.opt.mode .s.opt.mode.fld0 {top pady 4 frame w fillx}

	pack append .s.opt.mode .s.opt.mode.fld4a {top pady 4 frame w}
	pack append .s.opt.mode .s.opt.mode.steps {top frame w}

	pack append .s.opt.mode .s.opt.mode.fld4b {top pady 4 frame w}
	pack append .s.opt.mode .s.opt.mode.flds  {top frame w}

	pack append .s.opt.mode .s.opt.mode.fld4d {top pady 4 frame w}
	pack append .s.opt.mode .s.opt.mode.vars {top frame w}

	pack append .s.opt.mode .s.opt.mode.fld4c {top pady 4 frame w}

	pack append .s.opt .s.opt.mode {left frame n}

	frame .s.opt.mesg -relief raised -borderwidth 1m
	label .s.opt.mesg.loss0 \
		-font $HelvBig \
		-text "A Full Queue" \
		-relief sunken -borderwidth 1m
	radiobutton .s.opt.mesg.loss1 -text "Blocks New Msgs" \
		-variable l_typ -value 0 \
		-relief flat
	radiobutton .s.opt.mesg.loss2 -text "Loses New Msgs" \
		-variable l_typ -value 1 \
		-relief flat
	pack append .s.opt.mesg .s.opt.mesg.loss0 {top pady 4 frame w fillx}
	pack append .s.opt.mesg .s.opt.mesg.loss1 {top pady 4 frame w}
	pack append .s.opt.mesg .s.opt.mesg.loss2 {top pady 4 frame w}

	frame .s.opt.hide -relief raised -borderwidth 1m
	label .s.opt.hide.txt  \
		-font $HelvBig \
		-text "Hide Queues in MSC" \
		-relief sunken -borderwidth 1m
	pack append .s.opt.hide .s.opt.hide.txt {top pady 4 frame w fillx }

	for {set i 1} {$i < 4} {incr i} {
		frame .s.opt.hide.q$i
		label .s.opt.hide.q$i.qno \
			-font $HelvBig \
			-text "Queue nr:"
		entry .s.opt.hide.q$i.entry \
			-relief sunken -width 8
		pack append .s.opt.hide.q$i .s.opt.hide.q$i.qno {left pady 4 frame n }
		pack append .s.opt.hide.q$i .s.opt.hide.q$i.entry {left pady 4 frame n}
		pack append .s.opt.hide .s.opt.hide.q$i {top pady 4 frame w fillx}
	}
	frame .s.opt.lframe -relief raised -borderwidth 1m
	label .s.opt.lframe.tl \
		-font $HelvBig \
		-text "Simulation Style" \
		-relief sunken -borderwidth 1m
	radiobutton .s.opt.lframe.is -text "Interactive" \
		-variable s_typ -value 2 \
		-relief flat
	radiobutton .s.opt.lframe.gs -text "Guided (using pan.trail)" \
		-variable s_typ -value 1 \
		-relief flat
	frame .s.opt.lframe.b
	entry .s.opt.lframe.b.entry -relief sunken -width 8 
	label .s.opt.lframe.b.label \
		-font $HelvBig \
		-text "Steps Skipped"
	pack append .s.opt.lframe.b \
		.s.opt.lframe.b.label {left} \
		.s.opt.lframe.b.entry {left}

	radiobutton .s.opt.lframe.rs -text "Random (using seed)" \
		-variable s_typ -value 0 \
		-relief flat
	frame .s.opt.lframe.s
	entry .s.opt.lframe.s.entry -relief sunken -width 8 
	label .s.opt.lframe.s.label \
		-font $HelvBig \
		-text "Seed Value"
	pack append .s.opt.lframe.s \
		.s.opt.lframe.s.label {left} \
		.s.opt.lframe.s.entry {left}

	pack append .s.opt.lframe .s.opt.lframe.tl {top pady 4 frame w fillx} \
		.s.opt.lframe.rs {top pady 4 frame w} \
		.s.opt.lframe.s  {top pady 4 frame e} \
		.s.opt.lframe.gs {top pady 4 frame w} \
		.s.opt.lframe.b  {top pady 4 frame e} \
		.s.opt.lframe.is {top pady 4 frame w}

	pack append .s.opt .s.opt.lframe {top frame n}
	pack append .s.opt .s.opt.mesg {top frame n fillx}
	pack append .s.opt .s.opt.hide {top frame n expand fillx filly}

	pack append .s .s.opt { top frame n }

	pack append .s [button .s.rewind -text "Start" \
		-command "Rewind"  ] {right frame e}
	pack append .s [button .s.exit -text "Cancel" \
		-command "Stopsim" ] {right frame e}
	pack append .s [button .s.help -text "Help" -fg red \
		-command "roadmap1" ] {right frame e}

	.s.opt.lframe.s.entry  insert end $seed
	.s.opt.lframe.b.entry insert end $jumpsteps

	.s.opt.hide.q1.entry insert end $hide_q1
	.s.opt.hide.q2.entry insert end $hide_q2
	.s.opt.hide.q3.entry insert end $hide_q3
}

proc bld_s_options {} {
	global fvars gvars lvars svars qv
	global rvars l_typ showvars vv
	global s_typ seed jumpsteps s_options
	global hide_q1 hide_q2 hide_q3 ival

	set s_options "-X -p -v $ival(5)"

	if {$showvars && $gvars == 0 && $lvars == 0} {
		catch { tk_messageBox -icon info \
		-message "Display variables marked 'show' selected, \
		but no local or global vars are being tracked"
	}	}
	if {$showvars==1} { set s_options [format "%s -Y" $s_options] }
	if {$s_typ==2} { set s_options [format "%s -i" $s_options] }
	if {$vv && $gvars} { set s_options [format "%s -g" $s_options] }
	if {$vv && $lvars} { set s_options [format "%s -l" $s_options] }
	if {$svars} { set s_options [format "%s -s" $s_options] }
	if {$rvars} { set s_options [format "%s -r" $s_options] }
	if {$l_typ} { set s_options [format "%s -m" $s_options] }
	if {$hide_q1 != ""} { set s_options [format "%s -q%s" $s_options $hide_q1] }
	if {$hide_q2 != ""} { set s_options [format "%s -q%s" $s_options $hide_q2] }
	if {$hide_q3 != ""} { set s_options [format "%s -q%s" $s_options $hide_q3] }
	if {$s_typ==1} then {
		set s_options [format "%s -t" $s_options]
	} else {
		if {[string length $seed] > 0} {
			set s_options [format "%s -n%s" $s_options $seed]
	}	}
	if {$s_typ!=2} then {
		if {[string length $jumpsteps] > 0} {
			set s_options [format "%s -j%s" $s_options $jumpsteps]
	}	}
}

proc Stopsim {} {
	global stop dbox2 Sticky PlaceSim PlaceCanvas
	global stepper stepped howmany fd

	set stop 1
	set stepped 0
	set stepper 0
	add_log "<stop simulation>"
	if {[winfo exists .s]} {
		set PlaceSim [wm geometry .s]
		destroy .s
	}
	catch {set howmany 0}
	catch {stopbar}
	catch {	if {$Sticky($dbox2) == 0} {
			set PlaceCanvas(msc) [wm geometry .f$dbox2]
			destroy .f$dbox2
	}	}
	catch {
		puts $fd "q"
		flush $fd
	}
	update
}

proc Step_forw {} {
	global stepper stepped sbox simruns PlaceSim

	set stepped 1
	set stepper 1
	if {$simruns == 0} {
		if {[winfo exists .s]} {
			set PlaceSim [wm geometry .s]
			destroy .s
		}
		runsim
	} else {
		catch { .c$sbox.run configure \
		-text "Run" -command "Runsim" }
	}
}

proc Rewind {} {
	global Depth s_typ
	global Sdbox Spbox
	global seed jumpsteps
	global hide_q1 hide_q2 hide_q3

	catch { set jumpsteps [.s.opt.lframe.b.entry get] }
	catch { set hide_q1 [.s.opt.hide.q1.entry get] }
	catch { set hide_q2 [.s.opt.hide.q2.entry get] }
	catch { set hide_q3 [.s.opt.hide.q3.entry get] }

	if {$s_typ == 0} {
		catch { set seed [.s.opt.lframe.s.entry get] }
	}
	if {$s_typ == 1} {
		set Depth 0
		catch {
			foreach el [array names Spbox] {
				set Sdbox $Spbox($el)
				.c$Sdbox.z.t tag remove Rev 1.0 end
	}	}	}
	Step_forw
}

proc Runsim {} {
	global stepper stepped sbox

	catch { .c$sbox.run configure \
		-text "Suspend" -command "Step_forw" }
	set stepper 1
	set stepped 0
}

proc BreakPoint {} {
	global stepped sbox

	set stepped 1
	catch { .c$sbox.run configure \
		-text "BreakPoint" -command "Runsim" }
}

proc runsim {} {
	global Unix SPIN GO32 tk_major
	global s_options s_typ dbox2
	global stepper stepped
	global simruns m_typ
	global gvars lvars
	global fd stop Depth Seq
	global Sdbox Spbox pbox howmany Choice
	global sbox VERBOSE SYMBOLIC msc ebc vv tsc
	global Blue Yellow White Red Green
	global SmallFont BigFont Sticky SparseMsc
	global FG BG qv gvars lvars PlaceBox
	global dbox Vvbox 

	set simruns 1
	set Vvbox 0
	set pno 0
	set Varnm("") ""
	set Queues("")	""
	set Depth 0
	set Seq(0) 0
	set Pstp 1
	set Seenpno 1
	set Banner "Select"

#	catch { unset Spbox(0) }
	catch {
		foreach el [array names pbox] {
			catch { destroy .c$pbox($el) }
			catch { unset pbox($el) }
		}
		foreach el [array names Spbox] {
			catch { destroy .c$Spbox($el) }
			catch { unset Spbox($el) }
		}
	}
	bld_s_options

	add_log "<starting simulation>"
	add_log "$SPIN $s_options pan_in"
	update
	set s_options [format "%s pan_in" $s_options]

	mkpan_in

	set sbox [mkbox "Simulation Output" "SimOut" "sim.out" 80 10 100 100]

	pack append .c$sbox [button .c$sbox.stepf -text "Single Step" \
		-command "Step_forw" ] {left frame w}
	pack append .c$sbox [button .c$sbox.run -text "Run" \
		-command "Runsim" ] {left frame w}

	.c$sbox.b configure -text "Cancel" -command "Stopsim"

	set YSZ 12
	set XSZ 84
	set YNR 60
	set NPR 10
	set SMX 250
	set Easy 1
	set HAS 0
	set HAS_CYCLE 0
	set dontwait 0
	set notexecutable 0
	set lastexecutable 0

	if {$m_typ == 2} {
		if {$tsc} {
		set pbox(0) \
		[mkbox "Time Sequence" "Sequence" "seq.out" 80 10 100 325]
		set dbox $pbox(0)
	}	}
	if {$msc} {
		if {[hasWord "!!"] || [hasWord "\\?\\?"]} {
			set Easy 0
		}

		set maxx [expr [winfo screenwidth .]  - 500]	;# button widths
		set maxh [expr [winfo screenheight .] - (350+120)]	;# borders+buttons
		set dbox2 \
		[mkcanvas "Message Sequence Chart" "msc" $maxx 350 1]
		.f$dbox2.c configure -height $maxh \
			-scrollregion "[expr -$XSZ/2] 0 \
				[expr $NPR*$XSZ] [expr $SMX*$YSZ]"
	}
	set stop 0
	if {$s_typ == 1} {
		if {[file exists pan_in.trail] || [file exists pan_in.tra]} {
			catch { .c$sbox.z.t insert end "preparing trail, please wait..." }
			update
			rmfile trail.out
			catch {eval exec $SPIN $s_options >&trail.out} errmsg
		} else {
			set errmsg "error: no trail file for guided simulation"
		}
		if {[string length $errmsg]>0} {
			add_log "$errmsg"
			catch {
			tk_messageBox -icon info -message $errmsg
			}
			catch {
				set fd [open trail.out r]
				while {[gets $fd line] > -1} {
					add_log "$line"
				}
				close $fd
			}
			Stopsim
			catch { destroy .c$sbox }
			catch { destroy .c$dbox }
			set simruns 0
			update
			return
		}
		set fd [open trail.out r]
		catch { .c$sbox.z.t insert end "done\n" }
	} else {
		update
		set fd [open "|$SPIN $s_options" r+]
		catch "flush $fd"
		update
	}

	if {$s_typ == 2} {
		Runsim
	}

	if {$ebc} { startbar "Xspin Bar Chart" }

	set pstp -1
	set bailout 0
	set realstring ""

	while {$stop == 0 && [eof $fd] == 0} {
	if {$bailout == 0 && [gets $fd line] > -1} {
		set pln 0
		set syntax 0
		set isvar 0
		set pname ""
		set i 0
		set VERBOSE 0
		set Fnm "pan_in"
		if {$Unix == 0} {
			if {[string first "processes created" $line] > 0} {
				set bailout 1
		}	}
		if {[string first "type return to proceed" $line] > 0} {
			puts $fd ""
			flush $fd
			update
			continue
		}
		set lastpstp $pstp
		set pmtch [scan $line \
			"%d: proc %d (%s line %d \"%s\" " \
			pstp pno pname pln Fnm]
		incr pmtch -1
		set i [string first "\[" $line]
		if {$i > 0} {
			set i [expr $i + 1]
			set j [string length $line]
			set j [expr $j - 2]
			set stmnt [string range $line $i $j]
		} else {
			set stmnt "-"
		}
		if {$pmtch != 4} {
			set pmtch [scan $line \
				"	proc %d (%s line %d \"%s\" " \
				pno pname pln Fnm]
		}
		if {$pmtch != 4} {
			if {[string first "spin: line" $line] == 0 } {
				scan $line "spin: line %d \"%s\" " pln Fnm
				if {[string first "pan_in" $Fnm] >= 0} {
				.inp.t tag add Rev $pln.0 $pln.end
				.inp.t tag configure Rev \
					-background $FG -foreground $BG
				.inp.t yview -pickplace $pln.0
				}
				if {[string first "assertion viol" $line] < 0} {
					set syntax 1
				}
			}
			if {[string first "Error: "   $line] >= 0 \
			||  [string first "warning: " $line] >= 0 } {
				set syntax 1
			}
		}
		if {$pmtch != 4 && $syntax == 0} {
			set pmtch [scan $line \
				"%d: proc - (%s line %d \"%s\" " \
				pstp pname pln Fnm]
			if { $pmtch == 4 } {
				set pno -1
			}
		}
		#	set Fnm [string trim $Fnm "\""]
		set pname [string trim $pname "()"]

		if {[string first "TRACK" $pname] >= 0} {
			set nwcol([expr $pno+1]) 1
		} elseif {[string length $pname] > 0} {
			if {[info exists nwcol([expr $pno+1])] \
			&&  $nwcol([expr $pno+1])} {
				unset Plabel($pno)
##
				set TMP1 [expr ($pno + 1)*$XSZ]
				set TMP2 [expr $Pstp*$YSZ]
				.f$dbox2.c create line \
					[expr $TMP1 - 20] $TMP2 \
					[expr $TMP1 + 20] $TMP2 \
					-width 2 \
					-fill $Red
				incr TMP2 4
				.f$dbox2.c create line \
					[expr $TMP1 - 20] $TMP2 \
					[expr $TMP1 + 20] $TMP2 \
					-width 2 \
					-fill $Red
##
			}
			set nwcol([expr $pno+1]) 0
		}
		if {$pmtch == 4 && $syntax == 0} {
			if {$ebc} {
				if {[string first "values:" $line] < 0} {
					stepbar $pno $pname
			}	}
			if {$m_typ == 1 && $tsc} {
				if { [info exists pbox($pno)] == 0 } {
					set pbox($pno) [mkbox \
						"Proc $pno ($pname)" \
						"Proc$pno" "proc.$pno.out" \
						60 10 \
						[expr 100+$pno*25] \
						[expr 325+$pno*35] ]
				}
				set dbox $pbox($pno)
			} elseif {$m_typ == 0 && $tsc} {
				if { [info exists Spbox($pno)] == 0 } {
					set Spbox($pno) \
						[mkbox "$pname (proc $pno)" \
						"$pname" "" \
						60 10 \
						[expr 100+$pno*25] \
						[expr 325+$pno*35] ]
					readinfile .c$Spbox($pno).z.t "pan_in"
				}
				set Sdbox $Spbox($pno)
			}
		} elseif { [string first "..." $line] > 0 && \
			   [regexp "^\\\t*MSC: (.*)" $line] == 0 } {
			set $line ""
			set syntax 1
			set pln 0
		} elseif {$s_typ == 2 \
		      && [string first "Select " $line] == 0 } {
			set Banner $line
			set pln 0
			set notexecutable 0
			set lastexecutable 0
			set has_timeout 0
		} elseif {$s_typ == 2 \
		      && [string first "choice" $line] >= 0 } {
			scan $line "	choice %d" howmany
			set NN [string first ":" $line]; incr NN 2
			set Choice($howmany) [string range $line $NN end]
			if {[string first "timeout" $Choice($howmany)] > 0} {
				set has_timeout 1
			}
			if {[string first "unexecutable," $line] >= 0} {
				incr notexecutable
			} else {
				set lastexecutable $howmany
			}
			set pln 0
		} elseif {$s_typ == 2 \
		      && [string first "Make Selection" $line] >= 0 } {
			scan $line "Make Selection %d" howmany
			if {$notexecutable == $howmany-1 && $has_timeout == 0} {
				set howmany $lastexecutable
				add_log "selected: $howmany (forced)"
				catch {
					foreach el [array names Choice] {
					unset Choice($el)
				} }
			} else {
				pickoption $Banner
				add_log "selected: $howmany"
			}
			puts $fd $howmany
			catch "flush $fd"
			set dontwait 1
			set pln 0
		} elseif { [regexp "^\\\t*MSC: (.*)" $line mch rstr] != 0 } {
			if {$realstring != ""} {
			set realstring "$realstring $rstr"
			} else {
			set realstring $rstr
			}
			# picked up in next cycle
		} elseif { [string first "processes" $line] > 0 \
		      ||   [string first "timeout" $line]  == 0 \
		      ||   [string first "=s==" $line]  > 0 \
		      ||   [string first "=r==" $line]  > 0 } {

			if { $m_typ == 1 && $tsc} {
				set dbox $pbox(0)
			} elseif { $m_typ == 0 && $tsc} {
				if { [info exists Spbox($pno)] == 0 } {
					set Spbox($pno) \
						[mkbox "$pname (proc $pno)" \
						"$pname" "" \
						60 10 \
						[expr 100+$pno*25] \
						[expr 325+$pno*35] ]
					readinfile .c$Spbox($pno).z.t "pan_in"
				}
				set Sdbox $Spbox($pno)
			}
			set pln 0;	# prevent tag update
		} elseif {$syntax == 0 && [string first " = " $line] > 0 } {
				set isvar [string first "=" $line]
				set isvar [expr $isvar + 1]
				set varvl [string range $line $isvar end]
				set isvar [expr $isvar - 2]
				set varnm [string range $line 0 $isvar]
				set varnm [string trim $varnm "	"]
				set Varnm($varnm) $varvl
				set isvar 1
		} elseif { [scan $line " %s %d " varnm qnr] == 2} {
			if {$syntax == 0 &&  [string compare $varnm "queue"] == 0} {
				set isvar [string last ":" $line]
				set isvar [expr $isvar + 1]
				set varvl [string range $line $isvar end]
				set XX [string first "(" $line]
				set YY [string last  ")" $line]
				set ZZ [string range $line $XX $YY]
				set Queues($qnr) $varvl
				if {[info exists Alias($qnr)]} {
				if {[string first $ZZ $Alias($qnr)] < 0} {
					set Alias($qnr) "$Alias($qnr), $ZZ"
				}
				} else {
					set Alias($qnr) $ZZ
				}
				set isvar 1
			}
		} elseif {[string length $line] == 0} {
			if {$dontwait == 0} { set stepper 0 }
			set pln 0
			set Depth [expr $Depth + 1]
			set Seq($Depth) [tell $fd]
			set dontwait 0
		}


	if {$syntax == 0} {
		if {[string first "terminates" $line] > 0} {
			set pln -1
			set stmnt "<stop>"
		}

		if {$m_typ == 0} {
			if {$pln != 0 && [string first "pan_in" $Fnm] >= 0} {
				catch {
				.c$Sdbox.z.t yview -pickplace $pln.0
				.c$Sdbox.z.t tag remove Rev 1.0 end
				.c$Sdbox.z.t tag add Rev $pln.0 $pln.end
				.c$Sdbox.z.t tag configure Rev \
					-background $FG -foreground $BG
			}	}
		} elseif {$m_typ == 1} {
			if { [info exists pbox($pno)] == 0 } {
				set pbox($pno) [mkbox \
					"Proc $pno ($pname)" \
					"Proc$pno" "proc.$pno.out" \
					60 10 \
					[expr 100+$pno*25] \
					[expr 325+$pno*35] ]
			}
			set dbox $pbox($pno)
			catch {
				.c$dbox.z.t yview -pickplace end
				.c$dbox.z.t insert end "$line\n"
			}
		} elseif {$m_typ == 2 && $pln != 0 \
		&&  [string first "unexecutable, " $line] < 0} {
			catch { .c$dbox.z.t yview -pickplace end }
			catch { .c$dbox.z.t insert end "$pno:$pln" }
			for {set i $pno} {$i > 0} {incr i -1} {
				catch { .c$dbox.z.t insert end "\t|" }
			}
			catch { .c$dbox.z.t insert end "\t|>$stmnt\n" }
		}
		if {$msc && $pln != 0} {
			set Mcont "--"
			set HAS 0
			if { [scan $stmnt "values: %d!%d" inq inp1] == 2 \
			||   [scan $stmnt "values: %d!%s" inq inp2] == 2 } {
				set HAS   [string first "!" $stmnt]
				incr HAS
				set Mcont [string range $stmnt $HAS end]
				set HAS 1
			} elseif { [scan $stmnt "values: %d?%d" inq inp1] == 2 \
			|| [scan $stmnt "values: %d?%s" inq inp2] == 2 } {
				set HAS   [string first "?" $stmnt]
				incr HAS
				set Mcont [string range $stmnt $HAS end]
				set HAS 2
			} elseif { [string first "-" $stmnt] == 0} {
				set HAS 3
				if {$HAS_CYCLE} {
					set stmnt [format "Cycle>>"]
				} else {
					set stmnt [format "<waiting>"]
				}
			} elseif { [string first "<stop>" $stmnt] == 0} {
				set HAS 3
				set stmnt [format "<stopped>"]
			}
			if {$pno+1 > $Seenpno} { set Seenpno [expr $pno+1] }
			set XLOC [expr (1+$pno)*$XSZ]
			set YLOC [expr $Pstp*$YSZ]
			if {[string first "printf('MSC: " $stmnt] == 0} {
				set VERBOSE 1
				set stmnt $realstring
				if {[string first "BREAK" $realstring] >= 0} {
					BreakPoint
				}
				set realstring ""
			} else {
				set VERBOSE 0
			}
			catch {
			if {$VERBOSE \
			||  $HAS != 0 \
			||  [info exists R($pstp,$pno)]} {

				if { $SparseMsc == 1 \
				||   [info exists Plabel($pno)] == 0 \
				||   ([info exists R($pstp,$pno)] == 0 \
				&&   ($HAS != 1 \
				||   [info exists HasBox($YLOC,[expr 1+$pno])])) } {
					incr Pstp
					for	{set i 1} \
						{$Pstp > 1 && $i <= $Seenpno} \
						{incr i} {
						if {[info exists HasBox($YLOC,$i)]} {
							continue
						}
						set TMP1 [expr $i*$XSZ]
set lncol $Blue
set lnwdt 1
catch {
	if {$nwcol($i)} {
		set lncol "gray"
		set lnwdt 15
}	}
						.f$dbox2.c create line \
						$TMP1 $YLOC $TMP1 \
						[expr $YLOC+$YSZ] \
						-width $lnwdt \
						-fill $lncol
					}
					if {[info exists HasBox($YLOC,[expr 1+$pno])]} {
						set YLOC [expr $Pstp*$YSZ]
				}	}
				if {$HAS == 1 || $HAS == 2} {
					set stmnt [string range $stmnt 8 end]
				}
				if { [info exists Plabel($pno)] == 0} {
					set Plabel($pno) 0
					if {$SparseMsc == 0} {
						set HasBox($YLOC,[expr 1+$pno]) 1
					}
					.f$dbox2.c create rectangle \
						[expr $XLOC-20] $YLOC \
						[expr $XLOC+20] \
						[expr $YLOC+$YSZ] \
						-outline $Red -fill $Yellow
				if {$pname != "TRACK"} {
					.f$dbox2.c create text $XLOC \
						[expr $YLOC+$YSZ/2] \
						-font $SmallFont \
						-text "$pname:$pno"
				} else {
					.f$dbox2.c create text $XLOC \
						[expr $YLOC+$YSZ/2] \
						-font $SmallFont \
						-text "<show>"
				}

					set YLOC [expr $Pstp*$YSZ]
					incr Pstp
					for	{set i 1} \
						{$Pstp > 1 && $i <= $Seenpno} \
						{incr i} {
						set TMP1 [expr $i*$XSZ]
				set lncol $Blue
				set lnwdt 1
				catch {
					if {$nwcol($i)} {
						set lncol "gray"
						set lnwdt 15
				}	}
						.f$dbox2.c create line \
						$TMP1 $YLOC $TMP1 \
						[expr $YLOC+$YSZ] \
						-width $lnwdt \
						-fill $lncol
					}
				}
				if {(1+$pno) > $NPR} {
					set NPR [expr $pno+2]
					.f$dbox2.c configure \
					 -scrollregion \
					 "[expr -$XSZ/2] 0 \
					  [expr $NPR*$XSZ] [expr $SMX*$YSZ]"
				}
				if {$Pstp > $SMX-2} {
					set SMX [expr 2*$SMX]
					.f$dbox2.c configure \
					 -scrollregion \
					 "[expr -$XSZ/2] 0 \
					  [expr $NPR*$XSZ] [expr $SMX*$YSZ]"
				}

				if { [info exists R($pstp,$pno)] == 0 } {
					if {$VERBOSE == 1} {
					#	set BoxFil $Yellow
					#	Michael Griffioen:
						if {[string first "~W " $stmnt] == 0} {
							set BoxFil $White
							set stmnt [string range $stmnt 3 end] 
						} else { if {[string first "~G " $stmnt] == 0} {
							set BoxFil $Green
							set stmnt [string range $stmnt 3 end]
						} else { if {[string first "~R " $stmnt] == 0} {
							set BoxFil $Red
							set stmnt [string range $stmnt 3 end]
						} else { if {[string first "~B " $stmnt] == 0} {
							set BoxFil $Blue
							set stmnt [string range $stmnt 3 end]
						} else { set BoxFil $Yellow } } } }
						set BoxLab $stmnt
					} else {
						set BoxLab $pstp
						set BoxFil $White
					}
					if {$SparseMsc == 0} {
						set HasBox($YLOC,[expr 1+$pno]) 1
					}
					set R($pstp,$pno) \
						[.f$dbox2.c create rectangle \
						 [expr $XLOC-20] $YLOC \
						 [expr $XLOC+20] \
						 [expr $YLOC+$YSZ] \
						 -outline $Blue -fill $BoxFil]
					set T($pstp,$pno) \
						[.f$dbox2.c create text \
						 $XLOC \
						 [expr $YLOC+$YSZ/2] \
						-font $SmallFont \
						-text $BoxLab]
					#if {$Pstp > $YNR-2} {
					#	.f$dbox2.c yview \
					#	 [expr ($Pstp-$YNR)]
					#}
				}
				if { $HAS == 3 } {
					.f$dbox2.c itemconfigure \
					 $R($pstp,$pno) \
					 -outline $Red -fill $Yellow
				}

				if {$SYMBOLIC} {
					.f$dbox2.c itemconfigure $T($pstp,$pno) \
						-font $SmallFont -text "$stmnt"
				} else {
				if {$VERBOSE == 0 } {
					.f$dbox2.c bind $T($pstp,$pno) <Any-Enter> "
					.f$dbox2.c itemconfigure $T($pstp,$pno) \
						-font $BigFont -text {$stmnt}
					.inp.t tag remove hilite 0.0 end
					if {[string first "pan_in" $Fnm] >= 0} {
						src_line {[format "%d" $pln]}
					}
					"
					.f$dbox2.c bind $T($pstp,$pno) <Any-Leave> "
					.f$dbox2.c itemconfigure $T($pstp,$pno) \
						-font $SmallFont -text {$pstp}
					"
				} else {
					.f$dbox2.c bind $T($pstp,$pno) <Any-Enter> "
					.inp.t tag remove hilite 0.0 end
					if {[string first "pan_in" $Fnm] >= 0} {
						src_line {[format "%d" $pln]}
					}
					"
				}
				}
			}

			set YLOC [expr $YLOC+$YSZ/2]
			if {$HAS == 1} {
				if { [info exists Q_add($inq)] == 0 } {
					set Q_add($inq) 0
					set Q_del($inq) 0
				}
				set Slot $Q_add($inq)
				incr Q_add($inq) 1

				set Mesg_y($inq,$Slot) $YLOC
				set Mesg_x($inq,$Slot) $XLOC
				set Q_val($inq,$Slot) $Mcont
			
				set Rem($inq,$Slot) \
					[.f$dbox2.c create text \
					[expr $XLOC-40] $YLOC \
					-font $SmallFont -text $stmnt]
			} elseif { $HAS == 2 } {
				if {$Easy} {
					set Slot $Q_del($inq)
					incr Q_del($inq) 1
				} else {
					for {set Slot $Q_del($inq)} \
						{$Slot < $Q_add($inq)} \
						{incr Slot} {
					if {$Q_val($inq,$Slot) == "_X_"} {
							incr Q_del($inq) 1
						} else {
							break
					}	}

					for {set Slot $Q_del($inq)} \
						{$Slot < $Q_add($inq)} \
						{incr Slot} {
					if {$Mcont == $Q_val($inq,$Slot)} {
						set Q_val($inq,$Slot) "_X_"
						break
					}	}
				}
				if {$Slot >= $Q_add($inq)} {
					add_log "<<error: cannot match $stmnt>>"
				} else {
					set TMP1 $Mesg_x($inq,$Slot)
					set TMP2 $Mesg_y($inq,$Slot)
					if {$XLOC < $TMP1} {
						set Delta -20
					} else {
						set Delta 20
					}
					.f$dbox2.c create line \
						[expr $TMP1+$Delta] $TMP2 \
						[expr $XLOC-$Delta] $YLOC \
						-fill $Red -width 2 \
						-arrow last -arrowshape {5 5 5}

					if {$SparseMsc == 0} {
						set TMP3 5
					} else {
						set TMP3 0
					}

					.f$dbox2.c coords $Rem($inq,$Slot) \
						[expr ($TMP1 + $XLOC)/2] \
						[expr ($TMP2 + $YLOC)/2 - $TMP3]
					.f$dbox2.c raise $Rem($inq,$Slot)
				}
			} }
		}
		if {$pln == 0 && ($gvars || $lvars || $qv)} {
			if {$Vvbox == 0} {
				if {$vv} { set Vvbox [mkbox "Data Values" \
					"Vars" "var.out" 50 30 100 350] }
			} else {
				catch { .c$Vvbox.z.t delete 0.0 end }
			}
			if {$vv} {
if {$gvars || $lvars} {
			foreach el [lsort [array names Varnm]] {
				if {[string length $Varnm($el)] > 0} {
				catch { .c$Vvbox.z.t insert \
					end "$el = $Varnm($el)\n" }
			}	}
}
if {$qv} {
			foreach el [lsort [array names Queues]] {
				catch {
				.c$Vvbox.z.t insert end "queue $el ($Alias($el))\n"
				.c$Vvbox.z.t insert end "	$Queues($el)\n"
			}	}
}
			}
		}
	} else {
			set stepper 0
	}
		if {$isvar == 0} {
			if {$syntax == 1} {
				if {[string first "..." $line] < 0} {
					add_log "$line"
				catch { .c$sbox.z.t insert end "$line\n" }
				catch { .c$sbox.z.t yview -pickplace end }
				}
			} else {
				if {[string length $line] > 0} {
				catch { .c$sbox.z.t insert end "$line\n" }
				catch { .c$sbox.z.t yview -pickplace end }
				}
				if {$m_typ == 2 && \
					[string first "START OF CYCLE" $line] > 0} {
					catch { .c$dbox.z.t yview -pickplace end }
					catch { .c$dbox.z.t insert end "$line\n" }
					catch {
					set XLOC [expr $Seenpno*$XSZ+$XSZ/2]
					set YLOC [expr $Pstp*$YSZ+$YSZ/2]

					.f$dbox2.c create text \
						[expr $XLOC+$XSZ] $YLOC \
						-font $SmallFont \
						-text "Cycle/Waiting" \
						-fill $Red

					.f$dbox2.c create line \
						$XLOC $YLOC \
						[expr $XLOC+$XSZ/2] $YLOC \
						-fill $Red \
						-arrow first -arrowshape {5 5 5}
					}
					set HAS_CYCLE [expr $YLOC+1]
				}
				if {$m_typ == 2 && $HAS == 3 && $HAS_CYCLE != 0} {
					catch {
					set YLOC [expr $Pstp*$YSZ+$YSZ/2]
					set XLOC0 [expr $pno*$XSZ+$XSZ]
					set XLOC [expr $Seenpno*$XSZ+$XSZ]
					.f$dbox2.c create line \
						$XLOC0 [expr $YLOC-$YSZ/2] \
						$XLOC0 $YLOC \
						-fill $Red
					.f$dbox2.c create line \
						$XLOC0 $YLOC $XLOC $YLOC \
						-fill $Red

					set XLOC [expr $Seenpno*$XSZ+$XSZ]

					.f$dbox2.c create line \
						$XLOC $YLOC $XLOC \
						[expr $HAS_CYCLE-1] \
						-fill $Red
		}	}	}	}
		# mystery update:
		if {$tk_major >= 4 || $m_typ != 1} {
			update	;# tk 3.x can crash on this
		}

		if {$syntax == 0 \
		&&  $stop == 0 \
		&&  $stepped == 1 \
		&&  $stepper == 0 \
		&&  $dontwait == 0} {
			update	;# here it is harmless also with tk 3.x
			tkwait variable stepper
		}
	} else {
		if {$s_typ == 0 || $s_typ == 2} {
			add_log "<at end of run>"
		} else {
			add_log "<at end of trail>"
		}
		catch { addscales $dbox2 }
		if {$ebc} { barscales }
		update
		tkwait variable stepper
	}
	}
	# end of guided trail

	while {$stepper == 1} {
		tkwait variable stepper
	}
	teardown
	
	catch "close $fd"
	add_log "<done>"

	update
}

proc teardown {} {
	global m_typ pbox sbox dbox Spbox Vvbox
	global simruns stop stepped stepper howmany

	set simruns 0
	set stop 1
	set stepped 0
	set stepper 0
	catch { set howmany 0 }
	catch {
		if { $m_typ == 1 } {
			foreach el [array names pbox] {
				catch { destroy .c$pbox($el) }
				catch { unset pbox($el) }
			}
		} elseif { $m_typ == 0 } {
			foreach el [array names Spbox] {
				catch { destroy .c$Spbox($el) }
				catch { unset Spbox($el) }
		}	}
	}
	if {[winfo exists .c$sbox]} {
		set x "Simulation Output"
		set PlaceBox($x) [wm geometry .c$sbox]
		set k [string first "\+" $PlaceBox($x)]
		if {$k > 0} {
			set PlaceBox($x) [string range $PlaceBox($x) $k end]
		}
		destroy .c$sbox
	}
	catch { destroy .c$dbox }
	if {[winfo exists .c$Vvbox]} {
		set x "Data Values"
		set PlaceBox($x) [wm geometry .c$Vvbox]
		set k [string first "\+" $PlaceBox($x)]
		if {$k > 0} {
			set PlaceBox($x) [string range $PlaceBox($x) $k end]
		}
		destroy .c$Vvbox
	}
}

set PlaceMenu	"+150+150"

proc pickoption {nm} {
	global howmany Choice PlaceMenu

	catch {destroy .prompt}
	toplevel .prompt
	wm title .prompt "Select"
	wm iconname .prompt "Select"
	wm geometry .prompt $PlaceMenu

	text .prompt.t -relief raised -bd 2 \
		-width [string length $nm] -height 1 \
		-setgrid 1
	pack append .prompt .prompt.t { top expand fillx }
	.prompt.t insert end "$nm"
	for {set i 0} {$i <= $howmany} {incr i} {
		if {[info exists Choice($i)] \
		&&  $Choice($i) != 0 \
		&&  [string first "outside range" $Choice($i)] < 0 \
		&&  [string first "unexecutable," $Choice($i)] <= 0} {
			pack append .prompt \
			  [button .prompt.b$i -text "$i: $Choice($i)" \
			  -anchor w \
			  -command "set howmany $i" ] \
			  {top expand fillx}

			set j [string first "line " $Choice($i)]
			if {$j > 0} {
			  set k [string range $Choice($i) $j end]
			  scan $k "line %d" k
			  bind .prompt.b$i <Enter> "report $k"
			  bind .prompt.b$i <Leave> "report 0"
			  bind .prompt.b$i <ButtonRelease-1> "set howmany $i"
	}	}	}
	tkwait variable howmany
	set PlaceMenu [wm geometry .prompt]
	set k [string first "\+" $PlaceMenu]
	if {$k > 0} {
		set PlaceMenu [string range $PlaceMenu $k end]
	}
	catch { foreach el [array names Choice]  { unset Choice($el) } }
	destroy .prompt
}

proc report {n} {
	.inp.t tag remove hilite 0.0 end
	if {$n > 0} { src_line $n }
}

# validation options panel

#HSF
set er_typ 0; # type of error
set sa_typ 0; # type of search algorithm
set hf_typ 0; # type of estimate

set an_typ -1;	set cp_typ 0; set cyc_typ 0
set as_typ -1;  set ie_typ 1; set ebc 0
set ct_typ 0;	set et_typ 1
set st_typ 0;	set se_typ 0
set oct_typ -1;	# remembers last setting used for compilation
set nv_typ 1
set po_typ -1;	set cm_typ 0; set vb_typ 0
set pr_typ 0;	set where 0
set vr_typ 0;	set xu_typ -1
set ur_typ 1;	set vbox 0
set killed 0;	set Job_Done 0;	set tcnt 0
set waitwhat "none"
set not_warned_yet 1

set LastGenerate	""
set LastCompile	""
set NextCompile	""

proc syntax_check {a T} {
	global SPIN BG FG

	mkpan_in
	add_log "$SPIN $a pan_in"
	catch {exec $SPIN $a pan_in >&pan.tmp} err ;# added -v
	set cnt 0
	set maxln 50
	set ef [open pan.tmp r]
	.inp.t tag remove hilite 0.0 end
	.inp.t tag remove sel 0.0 end
	set pln 0
	set allmsg ""
	while {[gets $ef line] > -1} {
		add_log "$line"
		set allmsg "$allmsg\n$line"
		if {[string first "spin: line" $line] >= 0} {
			scan $line "spin: line %d" pln
			src_line [format "%d" $pln]
		}
		if {[string first "spin: warning, line" $line] >= 0} {
			scan $line "spin: warning, line %d" pln
			src_line [format "%d" $pln]
		}
		incr cnt
	}
	close $ef
	if {$cnt == 0} { add_log "no syntax errors" } else {
		warner $T "$allmsg" 800
	}
	update
}

proc prescan {} {
	global an_typ cp_typ nv_typ po_typ
	global xu_typ as_typ ie_typ

	mkpan_in

	if {$an_typ == -1} {
		set an_typ 0
		set nv_typ [hasWord "never"]
		if {[hasWord "accept.*:"]} {
			set an_typ 1
			set cp_typ 2
		} elseif {[hasWord "progress.*:"]} {
			set an_typ 1
			set cp_typ 1
		}
	}
	if {$po_typ == -1} {
		if {[hasWord "_last"] \
		||  [hasWord "provided.*\\("] \
		||  [hasWord "enabled\\("]} {
			set po_typ 0
		} else {
			set po_typ 1
		}
	}
	if {$xu_typ == -1} {
		if {[hasWord "xr"] || [hasWord "xs"]} {
			set xu_typ 1
		} else {
			set xu_typ 0
		}
	}
	if {$as_typ == -1} {
		if {$an_typ == 0} {
			set as_typ [hasWord "assert"]
			set ie_typ 1
		} else {
			set as_typ 0
			set ie_typ 0
		}
	}
}

proc basicval2 {} {
	global e ival expl hasfile HelvBig PlaceSim
	global an_typ cp_typ nv_typ firstime
	global cyc_typ ct_typ lt_typ
	global et_typ st_typ se_typ stop
	global vb_typ pr_typ vr_typ ur_typ xu_typ

	set nv_typ 1
	set an_typ 1
	set cp_typ 2

	dump_tl "pan.ltl"

	catch { .menu.run.m entryconfigure 7 -state normal }
	catch { .tl.results.top.rv configure -state normal }
	set stop 0
	set hasfile 0
	set firstime 0
	set lt_typ 1

	catch {destroy .v}
	toplevel .v

	set k [string first "\+" $PlaceSim]
	if {$k > 0} {
		set PlaceSim [string range $PlaceSim $k end]
	}

	wm title .v "LTL Verification Options"
	wm iconname .v "VAL"
	wm geometry .v $PlaceSim

	prescan

	frame .v.correct -relief flat -borderwidth 1m
	frame .v.cframe  -relief raised -borderwidth 1m

	set z .v.correct

	frame $z.rframe  -relief raised -borderwidth 1m

	label $z.rframe.lb \
		-font $HelvBig \
		-text "Options" \
		-relief sunken -borderwidth 1m

	checkbutton $z.rframe.fc -text "With Weak Fairness" \
		-variable cyc_typ \
		-relief flat 
	checkbutton $z.rframe.xu -text "Check xr/xs Assertions" \
		-variable xu_typ \
		-relief flat

	pack append $z.rframe \
		$z.rframe.lb {top pady 4 frame w fillx} \
		$z.rframe.fc {top pady 4 frame w} \
		$z.rframe.xu {top pady 4 frame w filly}

	pack append $z $z.rframe {top frame nw filly}

	label .v.cframe.lb \
		-font $HelvBig \
		-text "Verification" \
		-relief sunken -borderwidth 1m

	radiobutton .v.cframe.ea -text "Exhaustive" \
		-variable ct_typ -value 0 \
		-relief flat 
	radiobutton .v.cframe.sa -text "Supertrace/Bitstate" \
		-variable ct_typ -value 1 \
		-relief flat 
	radiobutton .v.cframe.hc -text "Hash-Compact" \
		-variable ct_typ -value 2 \
		-relief flat 

	pack append .v.cframe .v.cframe.lb {top pady 4 frame nw fillx} \
		.v.cframe.ea {top pady 4 frame nw} \
		.v.cframe.sa {top pady 4 frame nw} \
		.v.cframe.hc {top pady 4 frame nw}

	frame .v.pf -relief raised -borderwidth 1m
	frame .v.pf.mesg -borderwidth 1m
	
	label .v.pf.mesg.loss0 \
		-font $HelvBig \
		-text "A Full Queue" \
		-relief sunken -borderwidth 1m
	radiobutton .v.pf.mesg.loss1 -text "Blocks New Msgs" \
		-variable l_typ -value 0 \
		-relief flat
	radiobutton .v.pf.mesg.loss2 -text "Loses New Msgs" \
		-variable l_typ -value 1 \
		-relief flat
	pack append .v.pf.mesg \
		.v.pf.mesg.loss0 {top pady 4 frame w expand fillx} \
		.v.pf.mesg.loss1 {top pady 4 frame w} \
		.v.pf.mesg.loss2 {top pady 4 frame w}
	pack append .v.pf \
		.v.pf.mesg   {left frame w expand fillx}

	pack append .v \
		.v.cframe  {top frame w fill}\
		.v.correct {top frame w fill}\
		.v.pf {top frame w expand fill}

	pack append .v [button .v.adv -text "\[Set Advanced Options]" \
		-command "advanced_val" ] {top fillx}
	pack append .v [button .v.run -text "Run" \
		-command {runval ".tl.results.t"} ] {right frame se}
	pack append .v [button .v.exit -text "Cancel" \
		-command "set PlaceSim [wm geometry .v]; \
		set stop 1; destroy .v"] {right frame se}
	pack append .v [button .v.help -text "Help" -fg red \
		-command "roadmap2f" ] {right frame se}
}

set PlaceBasic	"+100+100"
set PlaceAdv	"+150+100"

proc basicval {} {
	global e ival expl hasfile HelvBig PlaceBasic
	global an_typ nv_typ firstime as_typ ie_typ
	global cyc_typ ct_typ lt_typ as_typ ie_typ
	global et_typ st_typ se_typ stop
	global vb_typ pr_typ vr_typ ur_typ xu_typ

	catch { .menu.run.m entryconfigure 7 -state normal }
	catch { .tl.results.top.rv configure -state normal }
	set stop 0
	set hasfile 0
	set firstime 0
	set lt_typ 0

	catch {destroy .v}
	toplevel .v

	wm title .v "Basic Verification Options"
	wm iconname .v "VAL"
	wm geometry .v $PlaceBasic

	prescan

	frame .v.correct -relief flat -borderwidth 1m
	frame .v.cframe  -relief raised -borderwidth 1m

	set z .v.correct

	frame $z.rframe  -relief raised -borderwidth 1m

	label $z.rframe.lb \
		-font $HelvBig \
		-text "Correctness Properties" \
		-relief sunken -borderwidth 1m
	radiobutton $z.rframe.sp -text "Safety (state properties)" \
		-variable an_typ -value 0 \
		-relief flat \
		-command { set cyc_typ 0; set cp_typ 0
			if {$an_typ == 0} {
				set as_typ [hasWord "assert"]
				set ie_typ 1
			}
		 }
	frame $z.rframe.sf
	checkbutton $z.rframe.sf.as -text "Assertions" \
		-variable as_typ \
		-relief flat \
		-command {
			set an_typ 0
			if {![hasWord "assert"] && $as_typ==1} then {
				complain6
			}
		 }
	checkbutton $z.rframe.sf.ie -text "Invalid Endstates" \
		-variable ie_typ \
		-relief flat \
		-command { set an_typ 0 }

	frame $z.rframe.sf.fill -width 15
	pack append $z.rframe.sf \
		$z.rframe.sf.fill {left frame w} \
		$z.rframe.sf.as {top pady 4 frame w} \
		$z.rframe.sf.ie {top pady 4 frame w}

	radiobutton $z.rframe.cp -text "Liveness (cycles/sequences)" \
		-variable an_typ -value 1 \
		-relief flat \
		-command {
			set as_typ 0; set ie_typ 0
			if {[hasWord "accept"]} then { set cp_typ 2 }\
			elseif {[hasWord "progress"]} then { set cp_typ 1 } \
			else complain5
		}

	frame $z.rframe.sub
	radiobutton $z.rframe.sub.np -text "Non-Progress Cycles" \
		-variable cp_typ -value 1 \
		-relief flat \
		-command {
			set an_typ 1
			if {![hasWord "progress"] && $cp_typ==1} then {
				complain4
			}
		 }
	radiobutton $z.rframe.sub.ac -text "Acceptance Cycles" \
		-variable cp_typ -value 2 \
		-relief flat \
		-command {
			set an_typ 1
			if {![hasWord "accept"] && $cp_typ==2} then {
				complain1
			}
		}
	checkbutton $z.rframe.sub.fc -text "With Weak Fairness" \
		-variable cyc_typ \
		-relief flat  \
		-command { if {$an_typ==0} then "set cyc_typ 0; complain3" }

	checkbutton $z.rframe.nv -text "Apply Never Claim (If Present)" \
		-variable nv_typ \
		-relief flat \
		-command { if {![hasWord "never"] && $nv_typ==1} then "complain2" }
	checkbutton $z.rframe.ur -text "Report Unreachable Code" \
		-variable ur_typ \
		-relief flat
	checkbutton $z.rframe.xu -text "Check xr/xs Assertions" \
		-variable xu_typ \
		-relief flat

	frame $z.rframe.sub.fill -width 15
	pack append $z.rframe.sub \
		$z.rframe.sub.fill {left frame w} \
		$z.rframe.sub.np {top pady 4 frame w} \
		$z.rframe.sub.ac {top pady 4 frame w} \
		$z.rframe.sub.fc {top pady 4 frame w}

	pack append $z.rframe \
		$z.rframe.lb {top pady 4 frame w fillx} \
		$z.rframe.sp {top pady 4 frame w} \
			$z.rframe.sf {top pady 4 frame w} \
		$z.rframe.cp {top pady 4 frame w} \
			$z.rframe.sub {top pady 4 frame w} \
		$z.rframe.nv {top pady 4 frame w} \
		$z.rframe.ur {top pady 4 frame w} \
		$z.rframe.xu {top pady 4 frame w filly}

	pack append $z $z.rframe {top frame nw filly}

	label .v.cframe.lb \
		-font $HelvBig \
		-text "Search Mode" \
		-relief sunken -borderwidth 1m

	radiobutton .v.cframe.ea -text "Exhaustive" \
		-variable ct_typ -value 0 \
		-relief flat 
	radiobutton .v.cframe.sa -text "Supertrace/Bitstate" \
		-variable ct_typ -value 1 \
		-relief flat 
	radiobutton .v.cframe.hc -text "Hash-Compact" \
		-variable ct_typ -value 2 \
		-relief flat 

	pack append .v.cframe .v.cframe.lb {top pady 4 frame nw fillx} \
		.v.cframe.ea {top pady 4 frame nw} \
		.v.cframe.sa {top pady 4 frame nw} \
		.v.cframe.hc {top pady 4 frame nw}

	frame .v.pf -relief raised -borderwidth 1m
	frame .v.pf.mesg -borderwidth 1m
	
	label .v.pf.mesg.loss0 \
		-font $HelvBig \
		-text "A Full Queue" \
		-relief sunken -borderwidth 1m
	radiobutton .v.pf.mesg.loss1 -text "Blocks New Msgs" \
		-variable l_typ -value 0 \
		-relief flat
	radiobutton .v.pf.mesg.loss2 -text "Loses New Msgs" \
		-variable l_typ -value 1 \
		-relief flat
	pack append .v.pf.mesg \
		.v.pf.mesg.loss0 {top pady 4 frame w fillx} \
		.v.pf.mesg.loss1 {top pady 4 frame w} \
		.v.pf.mesg.loss2 {top pady 4 frame w}
	pack append .v.pf \
		.v.pf.mesg {left frame nw expand fill}

	pack append .v \
		.v.correct {left} \
		.v.cframe  {top frame n expand fill}\
		.v.pf {top frame n expand fill}

	pack append .v [button .v.ltl -text "\[Verify an LTL Property]" \
		-command "destroy .v; call_tl" ] {top fillx}
	pack append .v [button .v.adv -text "\[Set Advanced Options]" \
		-command "advanced_val" ] {top fillx}
	pack append .v [button .v.run -text "Run" \
		-command {set PlaceBasic [wm geometry .v]; runval "0"} ] {right frame se}
	pack append .v [button .v.exit -text "Cancel" \
		-command {set PlaceBasic [wm geometry .v]; \
		set stop 1; destroy .v}] {right frame se}
	pack append .v [button .v.help -text "Help" -fg red \
		-command "roadmap2e" ] {right frame se}
}

# HSF
proc basichsf-spinval {} {
	global e ival expl hasfile HelvBig PlaceBasic
	global firstime er_typ
	global cyc_typ ct_typ lt_typ as_typ ie_typ
	global et_typ st_typ se_typ stop
	global vb_typ pr_typ vr_typ ur_typ xu_typ

	catch { .menu.run.m entryconfigure 7 -state normal }
	catch { .tl.results.top.rv configure -state normal }
	set stop 0
	set hasfile 0
	set firstime 0
	set lt_typ 0

	catch {destroy .v}
	toplevel .v

	wm title .v "Basic Verification Options"
	wm iconname .v "VAL"
	wm geometry .v $PlaceBasic

	prescan

	frame .v.error -relief raised -borderwidth 1m
	frame .v.algo -relief raised -borderwidth 1m
	frame .v.estimate -relief raised -borderwidth 1m
	frame .v.cframe  -relief raised -borderwidth 1m

	label .v.error.lb \
		-font $HelvBig \
		-text "Correctness Properties" \
		-relief sunken -borderwidth 1m
	radiobutton .v.error.no -text "None" \
		-variable er_typ -value 0 \
		-relief flat
	radiobutton .v.error.as -text "Assertions" \
		-variable er_typ -value 1 \
		-relief flat \
		-command {
			set an_typ 0
			if {![hasWord "assert"] && $as_typ==1} then {
				complain6
			}
		 }
	radiobutton .v.error.ie -text "Invalid Endstates" \
		-variable er_typ -value 2\
		-relief flat \
		-command { set an_typ 0 }
	radiobutton .v.error.cp -text "Liveness (cycles/sequences)" \
		-variable er_typ -value 3 \
		-relief flat \
		-command { if {![hasWord "never"] && $nv_typ==1} then "complain2" }

	pack append .v.error \
		.v.error.lb {top pady 4 frame w fillx} \
		.v.error.no {top pady 4 frame nw} \
		.v.error.as {top pady 4 frame w} \
		.v.error.ie {top pady 4 frame w} \
		.v.error.cp {top pady 4 frame w}

	label .v.estimate.hf \
		-font $HelvBig \
		-text "Heuristic Function" \
		-relief sunken -borderwidth 1m
	radiobutton .v.estimate.no -text "None" \
		-variable hf_typ -value 0 \
		-relief flat
	radiobutton .v.estimate.ap -text "Active Processes" \
		-variable hf_typ -value 1 \
		-relief flat
	radiobutton .v.estimate.fb -text "Formula Based" \
		-variable hf_typ -value 2\
		-relief flat
	radiobutton .v.estimate.hd -text "Hamming Distance" \
		-variable hf_typ -value 3\
		-relief flat
	radiobutton .v.estimate.fd -text "FSM Distance" \
		-variable hf_typ -value 4\
		-relief flat

	pack append .v.estimate \
		.v.estimate.hf {top pady 4 frame w fillx} \
		.v.estimate.no {top pady 4 frame nw} \
		.v.estimate.ap {top pady 4 frame w} \
		.v.estimate.fb {top pady 4 frame w} \
		.v.estimate.hd {top pady 4 frame w} \
		.v.estimate.fd {top pady 4 frame w}

	label .v.cframe.lb \
		-font $HelvBig \
		-text "Search Algorithm" \
		-relief sunken -borderwidth 1m

	radiobutton .v.cframe.df -text "Depth-first Search" \
		-variable sa_typ -value 0 \
		-relief flat 
	radiobutton .v.cframe.as -text "A*" \
		-variable sa_typ -value 1 \
		-relief flat 
	radiobutton .v.cframe.id -text "IDA*" \
		-variable sa_typ -value 2 \
		-relief flat 

	pack append .v.cframe .v.cframe.lb {top pady 4 frame nw fillx} \
		.v.cframe.df {top pady 4 frame nw} \
		.v.cframe.as {top pady 4 frame nw} \
		.v.cframe.id {top pady 4 frame nw}

	frame .v.pf -relief raised -borderwidth 1m
	frame .v.pf.mesg -borderwidth 1m
	
	label .v.pf.mesg.loss0 \
		-font $HelvBig \
		-text "A Full Queue" \
		-relief sunken -borderwidth 1m
	radiobutton .v.pf.mesg.loss1 -text "Blocks New Msgs" \
		-variable l_typ -value 0 \
		-relief flat
	radiobutton .v.pf.mesg.loss2 -text "Loses New Msgs" \
		-variable l_typ -value 1 \
		-relief flat
	pack append .v.pf.mesg \
		.v.pf.mesg.loss0 {top pady 4 frame w fillx} \
		.v.pf.mesg.loss1 {top pady 4 frame w} \
		.v.pf.mesg.loss2 {top pady 4 frame w}
	pack append .v.pf \
		.v.pf.mesg {left frame nw expand fill}

	pack append .v \
		.v.error {top frame n expand fill}\
		.v.estimate {top frame n expand fill}\
		.v.cframe  {top frame n expand fill}\
		.v.pf {top frame n expand fill}

	pack append .v [button .v.ltl -text "\[Verify an LTL Property]" \
		-command "destroy .v; call_tl" ] {top fillx}
	pack append .v [button .v.adv -text "\[Set Advanced Options]" \
		-command "advanced_val" ] {top fillx}
	# HSF
	pack append .v [button .v.hsf -text "\[Set Heuristic Options]" \
		-command "heuristic_val" ] {top fillx}
	pack append .v [button .v.run -text "Run" \
		-command {set PlaceBasic [wm geometry .v]; runval "0"} ] {right frame se}
	pack append .v [button .v.exit -text "Cancel" \
		-command {set PlaceBasic [wm geometry .v]; \
		set stop 1; destroy .v}] {right frame se}
	pack append .v [button .v.help -text "Help" -fg red \
		-command "roadmap2e" ] {right frame se}
}

proc advanced_val {} {
	global e ival expl hasfile HelvBig
	global nv_typ firstime PlaceAdv
	global cyc_typ ct_typ
	global et_typ st_typ se_typ stop po_typ cm_typ
	global vb_typ pr_typ vr_typ ur_typ xu_typ

	catch { .menu.run.m entryconfigure 7 -state normal }
	catch { .tl.results.top.rv configure -state normal }
	set stop 0
	set hasfile 0
	set firstime 0

	catch {destroy .av}
	toplevel .av

	wm title .av "Heuristic Verification Options"
	wm iconname .av "VAL"
	wm geometry .av $PlaceAdv

	frame .av.pans
	frame .av.pans.correct -relief flat
	frame .av.memopts -relief flat;		# memory options panel
	frame .av.oframe  -relief raised -borderwidth 1m ;# error trail options
	frame .av.recomp  -relief raised -borderwidth 1m ;# recompilation

	prescan

	for {set x 0} {$x<=5} {incr x} {
		global e
		global ival

		frame .av.memopts.choice$x -relief flat
		entry .av.memopts.choice$x.e1 -relief sunken -width 20
		label .av.memopts.choice$x.e2 -text $e($x) -relief flat
		.av.memopts.choice$x.e1 insert end $ival($x)

		pack append .av.memopts.choice$x \
			.av.memopts.choice$x.e2 {left  frame w fillx} \
			[button .av.memopts.choice$x.e3 -text $expl($x) \
			-command "d_list $x" ] {right frame e} \
			.av.memopts.choice$x.e1 {right frame e fillx}

		pack append .av.memopts \
			.av.memopts.choice$x { top frame w pady 5 fillx}
	}
	set z .av.pans.correct
#	frame $z.rframe  -relief raised -borderwidth 1m
#	label $z.rframe.lb3 \
#		-font $HelvBig \
#		-text "   Error Trapping   " \
#		-relief sunken -borderwidth 1m
#	radiobutton $z.rframe.c0 -text "Don't Stop at Errors" \
#		-variable et_typ -value 0 \
#		-relief flat 
#	checkbutton $z.rframe.c0a -text "Save All Error-trails" \
#		-variable st_typ \
#		-relief flat 
#	checkbutton $z.rframe.c0b -text "Find Shortest Trail (costly!)" \
#		-variable se_typ \
#		-relief flat
#	frame  $z.rframe.basic1 

#	frame $z.rframe.cc
#	radiobutton $z.rframe.cc.c1 -text "Stop at Error Nr:" \
#		-variable et_typ -value 1 \
#		-relief flat 
#	entry $z.rframe.cc.c2 -relief sunken -width 8
#	$z.rframe.cc.c2 insert end "$ival(6)"
#	pack append $z.rframe.cc \
#		$z.rframe.cc.c1 {left}\
#		$z.rframe.cc.c2 {right expand fillx}
#
#	pack append $z.rframe \
#		$z.rframe.lb3 { top expand fillx frame nw} \
#		$z.rframe.cc  {top pady 4 frame w} \
#		$z.rframe.c0  {top pady 4 frame w} \
#		$z.rframe.c0a {top pady 4 frame w} \
#		$z.rframe.c0b {top pady 4 frame w} \
#		$z.rframe.basic1 {top frame w}
#	pack append $z $z.rframe {top frame nw expand fill}

	frame .av.pans.pf -relief flat
	set z .av.pans.pf
	frame $z.mesg -relief raised -borderwidth 1m;		# queue loss options
	frame $z.pframe -relief raised -borderwidth 1m
	label $z.pframe.lb2 \
		-font $HelvBig \
		-text "   Type of Run   " \
		-relief sunken -borderwidth 1m
	checkbutton $z.pframe.po -text "Use Partial Order Reduction" \
		-variable po_typ \
		-relief flat 
	checkbutton $z.pframe.cm -text "Use Compression" \
		-variable cm_typ \
		-relief flat 
#	checkbutton $z.pframe.vb -text "Verbose (For Debugging Only)" \
#		-variable vb_typ \
#		-relief flat
	checkbutton $z.pframe.pr -text "Add Complexity Profiling" \
		-variable pr_typ \
		-relief flat
	checkbutton $z.pframe.vr -text "Compute Variable Ranges" \
		-variable vr_typ \
		-relief flat

	pack append $z.pframe \
		$z.pframe.lb2 {top fillx pady 4 frame w} \
		$z.pframe.po {top pady 4 frame w} \
		$z.pframe.cm {top pady 4 frame w} \
		$z.pframe.pr  {top pady 4 frame w} \
		$z.pframe.vr  {top pady 4 frame w}

	pack append .av.pans.pf \
		.av.pans.pf.pframe  {top frame nw expand fill}
	pack append .av.pans \
		.av.pans.correct {left frame nw expand fillx}\
		.av.pans.pf {left frame nw expand fillx}

	button .av.help -text "Help" -fg red -command "roadmap2d"
	button  .av.basic1 -text "Set" -fg red -command "stopval 1" 
	button  .av.basic0 -text "Cancel" -command "stopval 0" 

	pack append .av \
		.av.memopts {top frame w} \
		.av.pans {top fillx} \
		.av.help  {left frame w} \
		.av.basic1 {right frame e} \
		.av.basic0 {right frame e}
}

proc g_list {} {
	global FG BG

	catch {destroy .r}
	toplevel .r

	wm title .r "Options"
	wm iconname .r "Options"

	frame .r.top
		listbox .r.top.list -width  6 -height 3 -relief raised
		listbox .r.top.expl -width 40 -height 3  -relief flat
	pack append .r.top \
		.r.top.list {left}\
		.r.top.expl {left}
	frame .r.bot
		text .r.bot.text -width 40 -height 1 -relief flat
		.r.bot.text insert end "(Double-Click option or Cancel)"
		button .r.bot.quit -text "Cancel" -command "destroy .r"
	pack append .r.bot \
		.r.bot.text {top}\
		.r.bot.quit {frame s}

	frame .r.caps
		text .r.caps.cap1 -width 6 -height -1 -fg blue
		text .r.caps.cap2 -width 30 -height -1 -fg blue
		.r.caps.cap1 insert end "Option:"
		.r.caps.cap2 insert end "Meaning:"
	pack append .r.caps \
		.r.caps.cap1 {left} \
		.r.caps.cap2 {left}

	pack append .r \
		.r.caps  {frame w}\
		.r.top {top expand} \
		.r.bot {bottom expand}

	foreach i { "-o1" "-o2" "-o3" } {
		.r.top.list insert end $i
	}
 
	foreach i { \
		"disable dataflow-optimizations" \
		"disable dead variables elimination" \
		"disable statement merging" } {
		.r.top.expl insert end $i
	}
	bind .r.top.list <Double-Button-1> {
		set extra [selection get]
		.av.memopts.choice5.e1 insert end " $extra"
		destroy .r
	}
}

proc r_list {} {
	global FG BG

	catch {destroy .r}
	toplevel .r

	wm title .r "Options"
	wm iconname .r "Options"

	frame .r.top
		listbox .r.top.list -width  6 -height 7 -relief raised
		listbox .r.top.expl -width 40 -height 7  -relief flat
	pack append .r.top \
		.r.top.list {left}\
		.r.top.expl {left}
	frame .r.bot
		text .r.bot.text -width 40 -height 1 -relief flat
		.r.bot.text insert end "(Double-Click option or Cancel)"
		button .r.bot.quit -text "Cancel" -command "destroy .r"
	pack append .r.bot \
		.r.bot.text {top}\
		.r.bot.quit {frame s}

	frame .r.caps
		text .r.caps.cap1 -width 6 -height -1 -fg blue
		text .r.caps.cap2 -width 30 -height -1 -fg blue
		.r.caps.cap1 insert end "Option:"
		.r.caps.cap2 insert end "Meaning:"
	pack append .r.caps \
		.r.caps.cap1 {left} \
		.r.caps.cap2 {left}

	pack append .r \
		.r.caps  {frame w}\
		.r.top {top expand} \
		.r.bot {bottom expand}

	foreach i { "-d" "-q" "-I" "-h?" "-s" } {
		.r.top.list insert end $i
	}
 
	foreach i { \
		"print state tables and stop" \
		"require all chans to be empty in valid endstates" \
		"try to find shortest trail" \
		"choose another hash-function 1..32 (default 1)" \
		"use 1-bit hashing (default is 2-bit)" \
		"ignore invalid endstate errors" } {
		.r.top.expl insert end $i
	}
	bind .r.top.list <Double-Button-1> {
		set extra [selection get]
		.av.memopts.choice4.e1 insert end " $extra"
		destroy .r
	}
}

proc d_list {nr} {

	if {$nr == 0} { roadmap2a; return }
	if {$nr == 1} { roadmap2b; return }
	if {$nr == 2} { roadmap2c; return }
	if {$nr == 4} { r_list; return }
	if {$nr == 5} { g_list; return }
#	if {$nr != 3} { roadmap2; return }

	catch {destroy .b}
	toplevel .b

	wm title .b "Options"
	wm iconname .b "Options"

	frame .b.top
		scrollbar .b.top.scroll -command ".b.top.list yview"
		listbox   .b.top.list -yscroll ".b.top.scroll set" -relief raised
	pack append .b.top \
		.b.top.scroll {right filly}\
		.b.top.list {left expand}

	frame .b.bot
		text .b.bot.text -width 21 -height 1 -relief flat
		.b.bot.text insert end "(Double-Click option)"
		button .b.bot.quit -text "Cancel" -command "destroy .b"
		button .b.bot.expl -text "Explanations" -command "roadmap6"
	pack append .b.bot \
		.b.bot.text {top frame nw}\
		.b.bot.expl {left}\
		.b.bot.quit {left}


	pack append .b \
		.b.top {top frame nw expand} \
		.b.bot {bottom}

	foreach i { \
		"-DBCOMP" \
		"-DCTL" \
		"-DGLOB_ALPHA" \
		"-DHYBRID_HASH" \
		"-DMA=?" \
		"-DNFAIR=?" \
		"-DNIBIS" \
		"-DNOBOUNDCHECK" \
		"-DNOCOMP" \
		"-DNOSTUTTER" \
		"-DNOVSZ" \
		"-DPRINTF" \
		"-DRANDSTORE=?" \
		"-DR_XPT" \
		"-DSDUMP" \
		"-DSVDUMP" \
		"-DVECTORSZ=?" \
		"-DW_XPT=?" \
		"-DXUSAFE" \
		} {
		.b.top.list insert end $i
	}
	bind .b.top.list <Double-Button-1> {
		set directive [selection get]
		.av.memopts.choice3.e1 insert end " $directive"
		destroy .b
	}
}

proc complain1 {} {
	set m "warning: there are no accept labels"
	add_log $m
	catch { tk_messageBox -icon info -message $m }
}

proc complain2 {} {
	set m "warning: there is no never claim"
	add_log $m
	catch { tk_messageBox -icon info -message $m }
}

proc complain3 {} {
	set m "weak fairness is irrelevant to state properties"
	add_log $m
	catch { tk_messageBox -icon info -message $m }
}

proc complain4 {} {
	set m "warning: there are no progress labels"
	add_log $m
	catch { tk_messageBox -icon info -message $m }
}

proc complain5 {} {
	global an_typ
	set m "warning: there are neither accept nor progress labels"
	add_log $m
	set an_typ 0
	catch { tk_messageBox -icon info -message $m }
}

proc complain6 {} {
	set m "warning: there are no assert statements in the spec"
	add_log $m
	catch { tk_messageBox -icon info -message $m }
}

proc stopval {how} {
	global stop ival PlaceAdv

	if {$how} {
	set ival(0) "[.av.memopts.choice0.e1 get]"
	set ival(1) "[.av.memopts.choice1.e1 get]"
	set ival(2) "[.av.memopts.choice2.e1 get]"
	set ival(3) "[.av.memopts.choice3.e1 get]"
	set ival(4) "[.av.memopts.choice4.e1 get]"
	set ival(5) "[.av.memopts.choice5.e1 get]"
	set ival(6) "[.av.pans.correct.rframe.cc.c2 get]"
	}
	set stop 1
	if {[winfo exists .av]} {
		set PlaceAdv [wm geometry .av]
		set k [string first "\+" $PlaceAdv]
		if {$k > 0} {
			set PlaceAdv [string range $PlaceAdv $k end]
		}
		destroy .av
	}
}

proc log {n} {
	set m 1
	set cnt 0
	while {$m<$n} {
		set m [expr $m*2]
		incr cnt
	}
	return $cnt
}

proc bld_v_options {} {
	global an_typ cp_typ cyc_typ as_typ ie_typ
	global et_typ st_typ se_typ l_typ
	global ct_typ ival v_options hsf_v_options a_options; #HSF
	global c_options po_typ cm_typ vb_typ
	global pr_typ vr_typ ur_typ xu_typ
	global ol_typ oct_typ nv_typ lt_typ

	set ol_typ $l_typ
	set oct_typ $ct_typ

	set a_options "-a -X"
	if {$l_typ==1}  { set a_options [format "%s -m" $a_options] }
	if {$lt_typ==1} { set a_options [format "%s -N pan.ltl" $a_options] }


	set Mbytes $ival(0)
	catch { set Mbytes [.av.memopts.choice0.e1 get] }
#	now using MEMLIM
#	set Mbytes [expr 20 + log($Mbytes) / log(2) ]
#		# the Mbytes scale resolution is in millions
#		# 2^20 is 1 million
#		# round down by removing the decimal part
#	set foo [string first "." $Mbytes]
#	if {$foo >= 0} {
#		incr foo -1
#		set Mbytes [string range $Mbytes 0 $foo]
#	}
#	unset foo

	# the Mstate scale resolution is in thousands: 2^10
	set Mstate [expr 10+[log $ival(1)]]
	catch { set Mstate [expr 10+[log [.av.memopts.choice1.e1 get]]] }
	set Mdepth $ival(2)
	catch { set Mdepth [.av.memopts.choice2.e1 get] }
	catch { set ival(0) "[.av.memopts.choice0.e1 get]" }
	catch { set ival(1) "[.av.memopts.choice1.e1 get]" }
	catch { set ival(2) "[.av.memopts.choice2.e1 get]" }
	catch { set ival(3) "[.av.memopts.choice3.e1 get]" }
	catch { set ival(4) "[.av.memopts.choice4.e1 get]" }
	catch { set ival(5) "[.av.memopts.choice5.e1 get]" }

	if {$ct_typ == 2} {	;# hash-compact
		set c_options [format "-DHC -DMEMLIM=%d" $Mbytes]

		# in exhaustive mode: #hashtable ~~ #states

		set v_options "-X -m$Mdepth -w$Mstate"

		if {$Mstate >= $Mbytes} {
		catch {
		tk_messageBox -icon info \
			-message "The Estimated Statespace size exceeds \
the maximum that the Memory limit you set would allow."
		}
			return 0
		}
	} elseif {$ct_typ==1}	{
		set c_options [format "-DBITSTATE -DMEMLIM=%d" $Mbytes]

		# in supertrace mode: #bits ~~ 128x #states
		# (effectively the #bytes will be ~~ 16x #states)

		set Mstate [expr 7+$Mstate]
		set v_options "-X -m$Mdepth -w$Mstate"

		if {$Mstate-3 >= $Mbytes} {
		catch {
		tk_messageBox -icon info \
			-message "The Estimated Statespace size exceeds \
maximum allowed by the Memory limit that you set would allow."
		}
			return 0
		}
	} else {
		set c_options [format "-DMEMLIM=%d" $Mbytes]

		# in exhaustive mode: #hashtable ~~ #states

		set v_options "-X -m$Mdepth -w$Mstate"

		if {$Mstate >= $Mbytes} {
		catch {
		tk_messageBox -icon info \
			-message "The Estimated Statespace size exceeds \
the maximum that the Physical Memory limit allows."
		}
			return 0
		}
	}
	set c_options [format "-D_POSIX_SOURCE %s" $c_options]
	if {$an_typ==0}	{ set c_options [format "%s -DSAFETY" $c_options] }
	if {$an_typ==1 && $cp_typ==1}	{ set c_options [format "%s -DNP" $c_options] }
	if {$po_typ==0}	{ set c_options [format "%s -DNOREDUCE" $c_options] }
	if {$cm_typ==1}	{ set c_options [format "%s -DCOLLAPSE" $c_options] }
	if {$vb_typ==1}	{ set c_options [format "%s -DCHECK" $c_options] }
	if {$nv_typ==0}	{ set c_options [format "%s -DNOCLAIM" $c_options] }
	if {$se_typ!=0}	{ set c_options [format "%s -DREACH" $c_options] }
	if {$xu_typ==0 && $po_typ!=0}	{ set c_options [format "%s -DXUSAFE" $c_options] }
	if {$pr_typ==1}	{ set c_options [format "%s -DPEG" $c_options] }
	if {$vr_typ==1}	{ set c_options [format "%s -DVAR_RANGES" $c_options] }
	if {$cyc_typ==1}	{
		set c_options [format "%s -DNFAIR=3" $c_options]
	} else {
		set c_options [format "%s -DNOFAIR" $c_options]
	}
	set foo $ival(3)
	catch { set foo [.av.memopts.choice3.e1 get] }
	set c_options [format "%s %s" $c_options $foo ]
	set foo $ival(4)
	catch { set foo [.av.memopts.choice4.e1 get] }
	set v_options [format "%s %s" $v_options $foo ] 

	set foo $ival(5)
	catch { set foo [.av.memopts.choice.5.e1 get] }
	set a_options [format "%s %s" $a_options $foo ]

	if {$an_typ==0 && $as_typ==0} { set v_options [format "%s -A" $v_options] }
	if {$an_typ==0 && $ie_typ==0} { set v_options [format "%s -E" $v_options] }
	if {$an_typ==1 && $cp_typ==1} { set v_options [format "%s -l" $v_options] }
	if {$an_typ==1 && $cp_typ==2} { set v_options [format "%s -a" $v_options] }
	if {$cyc_typ==1} { set v_options [format "%s -f" $v_options] }
	if {$ur_typ==0}	{ set v_options [format "%s -n" $v_options] }
	if {$st_typ==1}	{ set v_options [format "%s -e" $v_options] }
	if {$se_typ!=0}	{ set v_options [format "%s -i" $v_options] }
	if {$et_typ==0}	{ set v_options [format "%s -c0" $v_options] }
	if {$et_typ==1}	{ set v_options [format "%s -c%s" $v_options $ival(6)] }
	return 1
}

set mt 0
set skipmax 10

proc runval {havedest} {
	global Unix GO32 CC SPIN Fname PlaceSim
	global v_options a_options hsf_v_options; # HSF
	global c_options Job_Done mt skipmax
	global stop s_typ vbox waitwhat not_warned_yet
	global LastGenerate LastCompile NextCompile

	set stop 0
	if {[bld_v_options] == 0} {
		advanced_val
		return
	}
	if {[winfo exists .v]} {
		set PlaceSim [wm geometry .v]
		destroy .v
	}
	catch {destroy .av}
	if {[string first "\?" $c_options] > 0} {
		add_log "error: undefined '?' in optional compiler directives"
		return
	}
	if {[string first "\?" $v_options] > 0} {
		add_log "error: undefined '?' in extra runtime options"
		return
	}
	add_log "<starting verification>"
	if {$havedest != "0"} {
		$havedest insert end "<starting verification>\n"
	}

	set nochange [no_change]
	if {$nochange == 0} { set LastGenerate "" }

	if {$LastGenerate == $a_options} {
		add_log "<no code regeneration necessary>"
		if {$havedest != "0"} {
			$havedest insert end "<no code regeneration necessary>\n"
		}
		set errmsg 0
	} else {
		set LastCompile ""
		add_log "$SPIN $a_options pan_in"; update
		if {$havedest != "0"} {
			$havedest insert end "$SPIN $a_options pan_in\n"
		}
		if {$Unix} {
			catch {eval exec $SPIN $a_options pan_in} errmsg
		} else {
			catch {eval exec $SPIN $a_options pan_in >&pan.tmp}
			set errmsg [msg_file pan.tmp 0]
		}
		if {[string length $errmsg]>0} {
			set foo [string first "Exit-Status 0" $errmsg]
			if {$foo<0} {
				add_log "$errmsg"
				if {$havedest != "0"} {
					$havedest insert end "$errmsg\n"
				}
				update
				return
			}
			incr foo -2
			set errmsg [string range $errmsg 0 $foo]
			add_log "$errmsg"
			if {$havedest != "0"} {
				$havedest insert end "$errmsg\n"
			}
	}	}
	set LastGenerate $a_options

	set NextCompile "$CC -o pan $c_options pan.c"

	if {$havedest != "0"} {
		catch { $havedest yview -pickplace end }
	}
	if {$LastCompile == $NextCompile && [file exists pan]} {
		add_log "<no recompilation necessary>"
		if {$havedest != "0"} {
			$havedest insert end "<no recompilation necessary>\n"
		}
		set errmsg 0
	} else {
		add_log $NextCompile
		if {$havedest != "0"} {
			$havedest insert end "$NextCompile\n"
		}
		catch {
			warner "Compiling" "Please wait until compilation of the \
executable produced by spin completes." 300
		}
		update
		set nok 1
		if {$Unix} {
			set errmsg [catch {eval exec $NextCompile}]
			if {[string compare $errmsg "0"] == 0} {
				set nok 0
			}
		} else {
			catch "eval exec $NextCompile >&pan.tmp"
			set errmsg [msg_file pan.tmp 0]
			if {[string length $errmsg] == 0} {
				set nok 0
		}	}
		catch {destroy .warn}
		if {$nok} {
			add_log "$errmsg"
			add_log "compilation failed"
			if {$havedest != "0"} {
				$havedest insert end "<compilation failed>\n"
			}
			update
			return
		}
		auto_reset
		if {$Unix} {
			if {[auto_execok "./pan"] == "" \
			||  [auto_execok "./pan"] == 0} {
				add_log "compilation failed"
				if {$havedest != "0"} {
					$havedest insert end "<compilation failed>\n"
				}
				update
				return
			}
		} else {
			if {[auto_execok "pan"] == "" \
			||  [auto_execok "pan"] == 0} {
				add_log "compilation failed"
				if {$havedest != "0"} {
					$havedest insert end "<compilation failed>\n"
				}
				update
				return
			}
		}
	}
	set LastCompile $NextCompile
	set NextCompile ""

	if {$Unix} {
	        # HSF
		# set PREFIX "time ./pan"
		set PREFIX "time ./check"
	} else {
		set PREFIX "$GO32 pan"
	}
	# HSF
	#add_log "$PREFIX $v_options"; update
	add_log "$PREFIX $hsf_v_options"; update
	if {$havedest != "0"} {
		$havedest insert end "$PREFIX $v_options\n"
		catch { $havedest yview -pickplace end }
	}
	set errmsg ""
	update
	rmfile pan.out
	# HSF
	# set errmsg [catch {eval exec $PREFIX $v_options >&pan.out &}]
	set errmsg [catch {eval exec $PREFIX "-En" $hsf_v_options >&pan.out &}]
	if {$errmsg} {
		add_log "$errmsg"
		add_log "could not run verification"
		if {$havedest != "0"} {
			$havedest insert end "<could not run verification>\n"
		}
		update
		return
	}

	set not_warned_yet 1
	if {$havedest != "0"} {
		set vbox $havedest
	} else {
		set vv [mkbox "Verification Output" "VerOut" "$Fname.out" 80 20]
		set vbox .c$vv.z.t
	}
	update
	set mt 0
	after 5000 outcheck $vbox
	update
}

proc outcheck {vbox} {
	global stop where not_warned_yet runtime mt Unix Fname FG skipmax

	set firstline 1
	set have_trail 0
	set po_red_viol 0

	if {[winfo exists $vbox] == 0} {
		add_log "<verification output panel $vbox was closed>"
		return
	}

	set erline 0; set lnr 0
	set nomem 0; set nerr 0

	if {$stop == 0} {
	  catch { set nt [file mtime pan.out] }
	  if {$mt == $nt && $skipmax > 0} {
		incr skipmax -1
	  } else {
	  set mt $nt
	  set skipmax 10
	  set fd [open pan.out r]
	  while {[gets $fd line] > -1} {
		if {$firstline} {
			set firstline 0
			set nerr 0
			set trunc 0
			set nomem 0
			.inp.t tag remove hilite 0.0 end
			catch { $vbox delete 0.0 end }
set lnr 0
		}
		catch { $vbox insert end "$line\n" }
incr lnr
		catch { $vbox yview -pickplace end }
		update

		if {[string first "line" $line]>=0} {
			scan $line "\tline %d" where
			catch { src_line $where }
		}
		if {[string first "State-vector" $line] == 0 \
		||  ([string first "error:" $line] == 0 \
		&&   [string first "error: max search depth too small" $line] != 0)} {
			set stop 1	;# run must have completed
			set nerr [string first "errors:" $line]
			if {$nerr > 0} {
			set part [string range $line $nerr end]
			scan $part "errors: %d" nerr
			if {$nerr == 0} {
				catch { .tl.results.top.title configure\
					-text "Verification Result: valid" -fg $FG
				}
			} else {
				catch { .tl.results.top.title configure\
					-text "Verification Result: not valid" -fg red
				}
			}
			set erline $lnr
			incr erline -1
			}
		}
		if {[string first "search depth too small" $line]>0} {
			set trunc 1
		}
		if {[string first "wrote pan_in.trail" $line]>0} {
			set have_trail 1
		}
		if {[string first "violated: access to chan" $line]>0} {
			set po_red_viol 1
		}
		if {[string first "out of memory" $line]>0} {
			set nomem 1
		}
		if {[string first "A=atomic;" $line]>0} {
			set stop 1
		}
		update
	  }
	  catch "close $fd"
	} }
	if {$nomem || $po_red_viol} { set erline 0 }

	if {$stop || ($have_trail && $po_red_viol==0 && ($nerr>0 || $trunc>0))} {
		catch { $vbox yview 0.0 }
		add_log "<verification done>"
		if {$nerr > 0 || $trunc == 1 || $nomem == 1} {
			if {[file exists pan_in.trail]} {
				cpfile pan_in.trail $Fname.trail
			} elseif {[file exists pan_in.tra]} {
				cpfile pan_in.tra $Fname.trail
			}
			catch { repeatbox $nerr $trunc $nomem }
		}
	} else {
		if {$not_warned_yet} {
			set runtime 0
			set stop 0
			set line "Running verification -- waiting for output"
			catch { $vbox insert end "$line\n" }
			set line "\t(kill background process 'pan' to abort run)"
			catch { $vbox insert end "$line\n" }
			if {$Unix == 0} {
			set line "\t(use ctl-alt-del to kill pan)"
			catch { $vbox insert end "$line\n" }
			} else {
			set line "\t(use /bin/ps to find pid; then: kill -2 pid)"
			catch { $vbox insert end "$line\n" }
			catch { $vbox yview -pickplace end }
			}
			set not_warned_yet 0
		} else {
			incr runtime 5
			if {$stop} {
				add_log "<done>"
				return
			} else {
			if {$runtime%60 == 0} {
				set rt [expr $runtime / 60]
				add_log "verification now running for approx $rt min.."
			}}
			update
		}
		after 5000 outcheck $vbox
	}
}

proc src_line {s} {
	global FG BG
	scan $s %d tgt_lnr

	if {$tgt_lnr > 0} {
	.inp.t tag add hilite $tgt_lnr.0 $tgt_lnr.end
	.inp.t tag configure hilite -background $FG -foreground $BG
		if {$tgt_lnr > 10} {
	.inp.t yview -pickplace [expr $tgt_lnr-10]
		} else {
	.inp.t yview -pickplace [expr $tgt_lnr-1]
		}
	}
}

proc repeatbox { {nerr} {trunc} {nomem}} {
	global s_typ PlaceWarn

	if {$nerr <= 0 && $trunc <= 0 && $nomem <= 0} { return }

	catch {destroy .rep}
	toplevel .rep

	wm title .rep "Suggested Action"
	wm iconname .rep "Suggest"
	wm geometry .rep $PlaceWarn
	button .rep.b0 -text "Close" -command {destroy .rep}
	button .rep.b1 -text "Run Guided Simulation.." \
		-command {destroy .rep; Rewind }
	button .rep.b2 -text "Setup Guided Simulation.." \
		-command {destroy .rep; simulation }

	if {$nerr>0} {
		message .rep.t -width 500 -text "\
Optionally, repeat the run with a different search\
depth to find a shorter path to the error.

Or, perform a GUIDED simulation to retrace\
the error found in this run, and skip\
the first series of steps if the error was\
found at a depth greater than about 100 steps)."
		set s_typ 1

		pack append .rep .rep.t {top expand fill}
		pack append .rep .rep.b0 {right}
		pack append .rep .rep.b1 {right}
		pack append .rep .rep.b2 {right}
	} else {

		if {$nomem>0} {
			message .rep.t -width 500 -text "\
Make sure the Physical Memory parameter (under Advanced\
Options) is set to the maximum physical memory available.\
If not, repeat the verification with the true maximum.\
(Don't set it higher than the physical limit though.)\
Otherwise, use compression, or switch to a\
Supertrace Verification."
		} else {

			if {$trunc} {

			message .rep.t -width 500 -text "\
If the search was incomplete (truncated)\
because the max search depth was too small,\
try to increase the depth limit (it is set\
in Advanced Options of the Verification Parameters\
Panel), and repeat the verification."
			}
		}
		pack append .rep .rep.t {top expand fill}
		pack append .rep .rep.b0 {right}
	}
}

# Main startup and arg processing
# this is at the end - to make sure all
# proc declarations were seen

if {$argc == 1 && $Unix == 1} {
	set Fname "$argv"
	wm title . "SPIN CONTROL $xversion -- File: $Fname"
	cleanup
	cpfile $argv.trail pan_in.trail
	reopen
}

focus .inp.t
update
