1#!/usr/local/bin/wish8.6 -f 2# The next line is executed by /bin/sh, but not tcl \ 3#exec wish "$0" -- $* 4 5## iSpin GUI -- http::/spinroot.com/ 6## (c) 2010-2014 All Rights Reserved 7## This software is for educational purposes only. 8## No guarantee whatsoever is expressed or implied 9## by the distribution of this code. 10 11wm title . "ispin" 12wm geometry . 1200x600+20+20 13 14set xversion "iSpin Version 1.1.4 -- 27 November 2014" 15set version "Spin Version unknown"; # updated below 16set Unix 1; # updated below 17 18### Tools 19 set SPIN spin ;# essential 20 set CC gcc ;# essential 21 set DOT dot ;# recommended, for automata view 22# set DOT "C:/Program\ Files\ \(x86\)/Graphviz2.36/bin/dot" 23 set SWARM swarm ;# optional, for swarm verification panel 24 set CURL curl ;# optional, for version check information 25 26 set CC_alt1 gcc-4 27 set CC_alt2 gcc-3 28 set RM "rm -f" 29 set KILL "kill -2" 30 31 ## check if we have the right version of Spin 32 if {[auto_execok $SPIN] == "" \ 33 || [auto_execok $SPIN] == 0} { 34 puts "No executable $SPIN found..." 35 puts "iSpin requires Spin Version 6.0 or later" 36 exit 0 37 } else { 38 catch { set fd [open "|$SPIN -V" r] } errmsg 39 if {$fd == -1} { 40 puts "$errmsg" 41 exit 0 42 } else { 43 set version "Spin Version unknown" 44 if {[gets $fd line] > -1} { 45 set version "$line" 46 } 47 catch "close $fd" 48 } 49 if {[string first "Spin Version " $version] < 0 \ 50 || [string first "Spin Version 5" $version] >= 0 \ 51 || [string first "Spin Version 4" $version] >= 0 \ 52 || [string first "Spin Version 3" $version] >= 0 } { 53 puts "iSpin requires Spin Version 6.0 or later" 54 puts "You have: $version" 55 exit 0 56 } } 57 58 if {[file isfile $CC] == 0} { ;# symbolic link 59 if {[auto_execok $CC_alt1] != ""} { 60 set CC $CC_alt1 61 } elseif {[auto_execok $CC_alt2] != ""} { 62 set CC $CC_alt2 63 } } 64 65 if [info exists tcl_platform] { 66 set sys $tcl_platform(platform) 67 if {[string match windows $sys]} { 68 set Unix 0 ;# Windows 69 } } 70 71### Some other configurable items 72 set ScrollBarSize 10 73 74### Colors 75 set MBG azure ;# menu 76 set MFG black 77 78 set XBB ivory ;# MSC canvas color 79 set XBG black ;# MSC rectangle border 80 set XFG gold ;# MSC rectangles 81 set XTX black ;# MSC text 82 set XAR blue ;# MSC arrows 83 set XPR gray ;# MSC process line color 84 85 set TBG azure ;#WhiteSmoke ;# text window 86 set TFG black 87 88 set CBG black ;# command window 89 set CFG azure ;# gold 90 91 set NBG darkblue ;# main tabs 92 set NFG gold 93 94 set SFG red ;# text selections - standout from TBG 95 96 set LTLbg darkblue 97 set LTL_Panel 0 ;# mostly overtaken by extensions in 6.0 98 set V_Panel_1 0 ;# Advanced verification options 1: Error trapping 99 set V_Panel_3 0 ;# ditto 3: Default Parameters 100 101### Fonts 102 set HV0 "helvetica 10" 103 set HV1 "helvetica 11" 104 105### end of configurable items ########################################## 106## ## 107## The first part of this code is based on the BWidget-1.9.2 package ## 108## To skip ahead to where the iSpin specific code starts, ## 109## search for "iSpin GUI code" which starts about half-way down ## 110## ## 111######################################################################## 112 113####### 114## The BWidget Toolkit comes with the following 115## license text that is reproduced here. 116####### 117## BWidget ToolKit 118## Copyright (c) 1998-1999 UNIFIX. 119## Copyright (c) 2001-2002 ActiveState Corp. 120## 121## The following terms apply to all files associated with the software 122## unless explicitly disclaimed in individual files. 123## 124## The authors hereby grant permission to use, copy, modify, distribute, 125## and license this software and its documentation for any purpose, provided 126## that existing copyright notices are retained in all copies and that this 127## notice is included verbatim in any distributions. No written agreement, 128## license, or royalty fee is required for any of the authorized uses. 129## Modifications to this software may be copyrighted by their authors 130## and need not follow the licensing terms described here, provided that 131## the new terms are clearly indicated on the first page of each file where 132## they apply. 133## 134## IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY 135## FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 136## ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY 137## DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE 138## POSSIBILITY OF SUCH DAMAGE. 139## 140## THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, 141## INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, 142## FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE 143## IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE 144## NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR 145## MODIFICATIONS. 146## 147## GOVERNMENT USE: If you are acquiring this software on behalf of the 148## U.S. government, the Government shall have only "Restricted Rights" 149## in the software and related documentation as defined in the Federal 150## Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you 151## are acquiring the software on behalf of the Department of Defense, the 152## software shall be classified as "Commercial Computer Software" and the 153## Government shall have only "Restricted Rights" as defined in Clause 154## 252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the 155## authors grant the U.S. Government and others acting in its behalf 156## permission to use and distribute the software in accordance with the 157## terms specified in this license. 158####### 159 160namespace eval Widget {} 161 162proc Widget::_opt_defaults {{prio widgetDefault}} { 163 if {$::tcl_version >= 8.4} { 164 set plat [tk windowingsystem] 165 } else { 166 set plat $::tcl_platform(platform) 167 } 168 switch -exact $plat { 169 "aqua" { 170 } 171 "win32" - 172 "windows" { 173 option add *ListBox.background SystemWindow $prio 174 option add *Dialog.padY 0 $prio 175 option add *Dialog.anchor e $prio 176 } 177 "x11" - 178 default { 179 option add *Scrollbar.width 12 $prio 180 option add *Scrollbar.borderWidth 1 $prio 181 option add *Dialog.separator 1 $prio 182 option add *MainFrame.relief raised $prio 183 option add *MainFrame.separator none $prio 184 } 185 } 186} 187 188Widget::_opt_defaults 189 190bind Entry <<TraverseIn>> { %W selection range 0 end; %W icursor end } 191bind all <Key-Tab> { Widget::traverseTo [Widget::focusNext %W] } 192bind all <<PrevWindow>> { Widget::traverseTo [Widget::focusPrev %W] } 193 194# ---------------------------------------------------------------------------- 195# widget.tcl -- part of Unifix BWidget Toolkit 196# ---------------------------------------------------------------------------- 197 198# Uses newer string operations 199package require Tcl 8.1.1 200 201namespace eval Widget { 202 variable _optiontype 203 variable _class 204 variable _tk_widget 205 206 # This controls whether we try to use themed widgets from Tile 207 variable _theme 0 208 209 variable _aqua [expr {($::tcl_version >= 8.4) && 210 [string equal [tk windowingsystem] "aqua"]}] 211 212 array set _optiontype { 213 TkResource Widget::_test_tkresource 214 BwResource Widget::_test_bwresource 215 Enum Widget::_test_enum 216 Int Widget::_test_int 217 Boolean Widget::_test_boolean 218 String Widget::_test_string 219 Flag Widget::_test_flag 220 Synonym Widget::_test_synonym 221 Color Widget::_test_color 222 Padding Widget::_test_padding 223 } 224 225 proc use {} {} 226} 227 228proc Widget::tkinclude { class tkwidget subpath args } { 229 foreach {cmd lopt} $args { 230 switch -- $cmd { 231 remove { 232 foreach option $lopt { 233 set remove($option) 1 234 } 235 } 236 include { 237 foreach option $lopt { 238 set include($option) 1 239 } 240 } 241 prefix { 242 set prefix [lindex $lopt 0] 243 foreach option [lrange $lopt 1 end] { 244 set rename($option) "-$prefix[string range $option 1 end]" 245 } 246 } 247 rename - 248 readonly - 249 initialize { 250 array set $cmd $lopt 251 } 252 default { 253 return -code error "invalid argument \"$cmd\"" 254 } 255 } 256 } 257 258 namespace eval $class {} 259 upvar 0 ${class}::opt classopt 260 upvar 0 ${class}::map classmap 261 upvar 0 ${class}::map$subpath submap 262 upvar 0 ${class}::optionExports exports 263 264 set foo [$tkwidget ".ericFoo###"] 265 # create resources informations from tk widget resources 266 foreach optdesc [_get_tkwidget_options $tkwidget] { 267 set option [lindex $optdesc 0] 268 if { (![info exists include] || [info exists include($option)]) && 269 ![info exists remove($option)] } { 270 if { [llength $optdesc] == 3 } { 271 # option is a synonym 272 set syn [lindex $optdesc 1] 273 if { ![info exists remove($syn)] } { 274 # original option is not removed 275 if { [info exists rename($syn)] } { 276 set classopt($option) [list Synonym $rename($syn)] 277 } else { 278 set classopt($option) [list Synonym $syn] 279 } 280 } 281 } else { 282 if { [info exists rename($option)] } { 283 set realopt $option 284 set option $rename($option) 285 } else { 286 set realopt $option 287 } 288 if { [info exists initialize($option)] } { 289 set value $initialize($option) 290 } else { 291 set value [lindex $optdesc 1] 292 } 293 if { [info exists readonly($option)] } { 294 set ro $readonly($option) 295 } else { 296 set ro 0 297 } 298 set classopt($option) \ 299 [list TkResource $value $ro [list $tkwidget $realopt]] 300 301 # Add an option database entry for this option 302 set optionDbName ".[lindex [_configure_option $realopt ""] 0]" 303 if { ![string equal $subpath ":cmd"] } { 304 set optionDbName "$subpath$optionDbName" 305 } 306 option add *${class}$optionDbName $value widgetDefault 307 lappend exports($option) "$optionDbName" 308 309 # Store the forward and backward mappings for this 310 # option <-> realoption pair 311 lappend classmap($option) $subpath "" $realopt 312 set submap($realopt) $option 313 } 314 } 315 } 316 ::destroy $foo 317} 318 319proc Widget::bwinclude { class subclass subpath args } { 320 foreach {cmd lopt} $args { 321 switch -- $cmd { 322 remove { 323 foreach option $lopt { 324 set remove($option) 1 325 } 326 } 327 include { 328 foreach option $lopt { 329 set include($option) 1 330 } 331 } 332 prefix { 333 set prefix [lindex $lopt 0] 334 foreach option [lrange $lopt 1 end] { 335 set rename($option) "-$prefix[string range $option 1 end]" 336 } 337 } 338 rename - 339 readonly - 340 initialize { 341 array set $cmd $lopt 342 } 343 default { 344 return -code error "invalid argument \"$cmd\"" 345 } 346 } 347 } 348 349 namespace eval $class {} 350 upvar 0 ${class}::opt classopt 351 upvar 0 ${class}::map classmap 352 upvar 0 ${class}::map$subpath submap 353 upvar 0 ${class}::optionExports exports 354 upvar 0 ${subclass}::opt subclassopt 355 upvar 0 ${subclass}::optionExports subexports 356 357 # create resources informations from BWidget resources 358 foreach {option optdesc} [array get subclassopt] { 359 set subOption $option 360 if { (![info exists include] || [info exists include($option)]) && 361 ![info exists remove($option)] } { 362 set type [lindex $optdesc 0] 363 if { [string equal $type "Synonym"] } { 364 # option is a synonym 365 set syn [lindex $optdesc 1] 366 if { ![info exists remove($syn)] } { 367 if { [info exists rename($syn)] } { 368 set classopt($option) [list Synonym $rename($syn)] 369 } else { 370 set classopt($option) [list Synonym $syn] 371 } 372 } 373 } else { 374 if { [info exists rename($option)] } { 375 set realopt $option 376 set option $rename($option) 377 } else { 378 set realopt $option 379 } 380 if { [info exists initialize($option)] } { 381 set value $initialize($option) 382 } else { 383 set value [lindex $optdesc 1] 384 } 385 if { [info exists readonly($option)] } { 386 set ro $readonly($option) 387 } else { 388 set ro [lindex $optdesc 2] 389 } 390 set classopt($option) \ 391 [list $type $value $ro [lindex $optdesc 3]] 392 393 # Add an option database entry for this option 394 foreach optionDbName $subexports($subOption) { 395 if { ![string equal $subpath ":cmd"] } { 396 set optionDbName "$subpath$optionDbName" 397 } 398 # Only add the option db entry if we are overriding the 399 # normal widget default 400 if { [info exists initialize($option)] } { 401 option add *${class}$optionDbName $value \ 402 widgetDefault 403 } 404 lappend exports($option) "$optionDbName" 405 } 406 407 # Store the forward and backward mappings for this 408 # option <-> realoption pair 409 lappend classmap($option) $subpath $subclass $realopt 410 set submap($realopt) $option 411 } 412 } 413 } 414} 415 416proc Widget::declare { class optlist } { 417 variable _optiontype 418 419 namespace eval $class {} 420 upvar 0 ${class}::opt classopt 421 upvar 0 ${class}::optionExports exports 422 upvar 0 ${class}::optionClass optionClass 423 424 foreach optdesc $optlist { 425 set option [lindex $optdesc 0] 426 set optdesc [lrange $optdesc 1 end] 427 set type [lindex $optdesc 0] 428 429 if { ![info exists _optiontype($type)] } { 430 # invalid resource type 431 return -code error "invalid option type \"$type\"" 432 } 433 434 if { [string equal $type "Synonym"] } { 435 # test existence of synonym option 436 set syn [lindex $optdesc 1] 437 if { ![info exists classopt($syn)] } { 438 return -code error "unknow option \"$syn\" for Synonym \"$option\"" 439 } 440 set classopt($option) [list Synonym $syn] 441 continue 442 } 443 444 # all other resource may have default value, readonly flag and 445 # optional arg depending on type 446 set value [lindex $optdesc 1] 447 set ro [lindex $optdesc 2] 448 set arg [lindex $optdesc 3] 449 450 if { [string equal $type "BwResource"] } { 451 # We don't keep BwResource. We simplify to type of sub BWidget 452 set subclass [lindex $arg 0] 453 set realopt [lindex $arg 1] 454 if { ![string length $realopt] } { 455 set realopt $option 456 } 457 458 upvar 0 ${subclass}::opt subclassopt 459 if { ![info exists subclassopt($realopt)] } { 460 return -code error "unknow option \"$realopt\"" 461 } 462 set suboptdesc $subclassopt($realopt) 463 if { $value == "" } { 464 # We initialize default value 465 set value [lindex $suboptdesc 1] 466 } 467 set type [lindex $suboptdesc 0] 468 set ro [lindex $suboptdesc 2] 469 set arg [lindex $suboptdesc 3] 470 set optionDbName ".[lindex [_configure_option $option ""] 0]" 471 option add *${class}${optionDbName} $value widgetDefault 472 set exports($option) $optionDbName 473 set classopt($option) [list $type $value $ro $arg] 474 continue 475 } 476 477 # retreive default value for TkResource 478 if { [string equal $type "TkResource"] } { 479 set tkwidget [lindex $arg 0] 480 set foo [$tkwidget ".ericFoo##"] 481 set realopt [lindex $arg 1] 482 if { ![string length $realopt] } { 483 set realopt $option 484 } 485 set tkoptions [_get_tkwidget_options $tkwidget] 486 if { ![string length $value] } { 487 # We initialize default value 488 set ind [lsearch $tkoptions [list $realopt *]] 489 set value [lindex [lindex $tkoptions $ind] end] 490 } 491 set optionDbName ".[lindex [_configure_option $option ""] 0]" 492 option add *${class}${optionDbName} $value widgetDefault 493 set exports($option) $optionDbName 494 set classopt($option) [list TkResource $value $ro \ 495 [list $tkwidget $realopt]] 496 set optionClass($option) [lindex [$foo configure $realopt] 1] 497 ::destroy $foo 498 continue 499 } 500 501 set optionDbName ".[lindex [_configure_option $option ""] 0]" 502 option add *${class}${optionDbName} $value widgetDefault 503 set exports($option) $optionDbName 504 # for any other resource type, we keep original optdesc 505 set classopt($option) [list $type $value $ro $arg] 506 } 507} 508 509proc Widget::define { class filename args } { 510 variable ::BWidget::use 511 set use($class) $args 512 set use($class,file) $filename 513 lappend use(classes) $class 514 515 if {[set x [lsearch -exact $args "-classonly"]] > -1} { 516 set args [lreplace $args $x $x] 517 } else { 518 interp alias {} ::${class} {} ${class}::create 519 proc ::${class}::use {} {} 520 521 bind $class <Destroy> [list Widget::destroy %W] 522 } 523 524 foreach class $args { ${class}::use } 525} 526 527proc Widget::create { class path {rename 1} } { 528 if {$rename} { rename $path ::$path:cmd } 529 proc ::$path { cmd args } \ 530 [subst {return \[eval \[linsert \$args 0 ${class}::\$cmd [list $path]\]\]}] 531 return $path 532} 533 534proc Widget::addmap { class subclass subpath options } { 535 upvar 0 ${class}::opt classopt 536 upvar 0 ${class}::optionExports exports 537 upvar 0 ${class}::optionClass optionClass 538 upvar 0 ${class}::map classmap 539 upvar 0 ${class}::map$subpath submap 540 541 foreach {option realopt} $options { 542 if { ![string length $realopt] } { 543 set realopt $option 544 } 545 set val [lindex $classopt($option) 1] 546 set optDb ".[lindex [_configure_option $realopt ""] 0]" 547 if { ![string equal $subpath ":cmd"] } { 548 set optDb "$subpath$optDb" 549 } 550 option add *${class}${optDb} $val widgetDefault 551 lappend exports($option) $optDb 552 # Store the forward and backward mappings for this 553 # option <-> realoption pair 554 lappend classmap($option) $subpath $subclass $realopt 555 set submap($realopt) $option 556 } 557} 558 559proc Widget::syncoptions { class subclass subpath options } { 560 upvar 0 ${class}::sync classync 561 562 foreach {option realopt} $options { 563 if { ![string length $realopt] } { 564 set realopt $option 565 } 566 set classync($option) [list $subpath $subclass $realopt] 567 } 568} 569 570proc Widget::init { class path options } { 571 variable _inuse 572 variable _class 573 variable _optiontype 574 575 upvar 0 ${class}::opt classopt 576 upvar 0 ${class}::$path:opt pathopt 577 upvar 0 ${class}::$path:mod pathmod 578 upvar 0 ${class}::map classmap 579 upvar 0 ${class}::$path:init pathinit 580 581 if { [info exists pathopt] } { 582 unset pathopt 583 } 584 if { [info exists pathmod] } { 585 unset pathmod 586 } 587 588 set fpath $path 589 set rdbclass [string map [list :: ""] $class] 590 if { ![winfo exists $path] } { 591 set fpath ".#BWidget.#Class#$class" 592 # encapsulation frame to not pollute '.' childspace 593 if {![winfo exists ".#BWidget"]} { frame ".#BWidget" } 594 if { ![winfo exists $fpath] } { 595 frame $fpath -class $rdbclass 596 } 597 } 598 foreach {option optdesc} [array get classopt] { 599 set pathmod($option) 0 600 if { [info exists classmap($option)] } { 601 continue 602 } 603 set type [lindex $optdesc 0] 604 if { [string equal $type "Synonym"] } { 605 continue 606 } 607 if { [string equal $type "TkResource"] } { 608 set alt [lindex [lindex $optdesc 3] 1] 609 } else { 610 set alt "" 611 } 612 set optdb [lindex [_configure_option $option $alt] 0] 613 set def [option get $fpath $optdb $rdbclass] 614 if { [string length $def] } { 615 set pathopt($option) $def 616 } else { 617 set pathopt($option) [lindex $optdesc 1] 618 } 619 } 620 621 if {![info exists _inuse($class)]} { set _inuse($class) 0 } 622 incr _inuse($class) 623 624 set _class($path) $class 625 foreach {option value} $options { 626 if { ![info exists classopt($option)] } { 627 unset pathopt 628 unset pathmod 629 return -code error "unknown option \"$option\"" 630 } 631 set optdesc $classopt($option) 632 set type [lindex $optdesc 0] 633 if { [string equal $type "Synonym"] } { 634 set option [lindex $optdesc 1] 635 set optdesc $classopt($option) 636 set type [lindex $optdesc 0] 637 } 638 # this may fail if a wrong enum element was used 639 if {[catch { 640 $_optiontype($type) $option $value [lindex $optdesc 3] 641 } msg]} { 642 if {[info exists pathopt]} { 643 unset pathopt 644 } 645 unset pathmod 646 return -code error $msg 647 } 648 set pathopt($option) $msg 649 set pathinit($option) $pathopt($option) 650 } 651} 652 653proc Widget::parseArgs {class options} { 654 variable _optiontype 655 upvar 0 ${class}::opt classopt 656 upvar 0 ${class}::map classmap 657 658 foreach {option val} $options { 659 if { ![info exists classopt($option)] } { 660 error "unknown option \"$option\"" 661 } 662 set optdesc $classopt($option) 663 set type [lindex $optdesc 0] 664 if { [string equal $type "Synonym"] } { 665 set option [lindex $optdesc 1] 666 set optdesc $classopt($option) 667 set type [lindex $optdesc 0] 668 } 669 if { [string equal $type "TkResource"] } { 670 # Make sure that the widget used for this TkResource exists 671 Widget::_get_tkwidget_options [lindex [lindex $optdesc 3] 0] 672 } 673 set val [$_optiontype($type) $option $val [lindex $optdesc 3]] 674 675 if { [info exists classmap($option)] } { 676 foreach {subpath subclass realopt} $classmap($option) { 677 lappend maps($subpath) $realopt $val 678 } 679 } else { 680 lappend maps($class) $option $val 681 } 682 } 683 return [array get maps] 684} 685 686proc Widget::initFromODB {class path options} { 687 variable _inuse 688 variable _class 689 690 upvar 0 ${class}::$path:opt pathopt 691 upvar 0 ${class}::$path:mod pathmod 692 upvar 0 ${class}::map classmap 693 694 if { [info exists pathopt] } { 695 unset pathopt 696 } 697 if { [info exists pathmod] } { 698 unset pathmod 699 } 700 701 set fpath [_get_window $class $path] 702 set rdbclass [string map [list :: ""] $class] 703 if { ![winfo exists $path] } { 704 set fpath ".#BWidget.#Class#$class" 705 # encapsulation frame to not pollute '.' childspace 706 if {![winfo exists ".#BWidget"]} { frame ".#BWidget" } 707 if { ![winfo exists $fpath] } { 708 frame $fpath -class $rdbclass 709 } 710 } 711 712 foreach {option optdesc} [array get ${class}::opt] { 713 set pathmod($option) 0 714 if { [info exists classmap($option)] } { 715 continue 716 } 717 set type [lindex $optdesc 0] 718 if { [string equal $type "Synonym"] } { 719 continue 720 } 721 if { [string equal $type "TkResource"] } { 722 set alt [lindex [lindex $optdesc 3] 1] 723 } else { 724 set alt "" 725 } 726 set optdb [lindex [_configure_option $option $alt] 0] 727 set def [option get $fpath $optdb $rdbclass] 728 if { [string length $def] } { 729 set pathopt($option) $def 730 } else { 731 set pathopt($option) [lindex $optdesc 1] 732 } 733 } 734 735 if {![info exists _inuse($class)]} { set _inuse($class) 0 } 736 incr _inuse($class) 737 738 set _class($path) $class 739 array set pathopt $options 740} 741 742proc Widget::destroy { path } { 743 variable _class 744 variable _inuse 745 746 if {![info exists _class($path)]} { return } 747 748 set class $_class($path) 749 upvar 0 ${class}::$path:opt pathopt 750 upvar 0 ${class}::$path:mod pathmod 751 upvar 0 ${class}::$path:init pathinit 752 753 if {[info exists _inuse($class)]} { incr _inuse($class) -1 } 754 755 if {[info exists pathopt]} { 756 unset pathopt 757 } 758 if {[info exists pathmod]} { 759 unset pathmod 760 } 761 if {[info exists pathinit]} { 762 unset pathinit 763 } 764 765 if {![string equal [info commands $path] ""]} { rename $path "" } 766 767 ## Unset any variables used in this widget. 768 foreach var [info vars ::${class}::$path:*] { unset $var } 769 770 unset _class($path) 771} 772 773proc Widget::configure { path options } { 774 set len [llength $options] 775 if { $len <= 1 } { 776 return [_get_configure $path $options] 777 } elseif { $len % 2 == 1 } { 778 return -code error "incorrect number of arguments" 779 } 780 781 variable _class 782 variable _optiontype 783 784 set class $_class($path) 785 upvar 0 ${class}::opt classopt 786 upvar 0 ${class}::map classmap 787 upvar 0 ${class}::$path:opt pathopt 788 upvar 0 ${class}::$path:mod pathmod 789 790 set window [_get_window $class $path] 791 foreach {option value} $options { 792 if { ![info exists classopt($option)] } { 793 return -code error "unknown option \"$option\"" 794 } 795 set optdesc $classopt($option) 796 set type [lindex $optdesc 0] 797 if { [string equal $type "Synonym"] } { 798 set option [lindex $optdesc 1] 799 set optdesc $classopt($option) 800 set type [lindex $optdesc 0] 801 } 802 if { ![lindex $optdesc 2] } { 803 set newval [$_optiontype($type) $option $value [lindex $optdesc 3]] 804 if { [info exists classmap($option)] } { 805 set window [_get_window $class $window] 806 foreach {subpath subclass realopt} $classmap($option) { 807 if { [string length $subclass] && ! [string equal $subclass ":cmd"] } { 808 if { [string equal $subpath ":cmd"] } { 809 set subpath "" 810 } 811 set curval [${subclass}::cget $window$subpath $realopt] 812 ${subclass}::configure $window$subpath $realopt $newval 813 } else { 814 set curval [$window$subpath cget $realopt] 815 $window$subpath configure $realopt $newval 816 } 817 } 818 } else { 819 set curval $pathopt($option) 820 set pathopt($option) $newval 821 } 822 set pathmod($option) [expr {![string equal $newval $curval]}] 823 } 824 } 825 826 return {} 827} 828 829proc Widget::cget { path option } { 830 variable _class 831 if { ![info exists _class($path)] } { 832 return -code error "unknown widget $path" 833 } 834 835 set class $_class($path) 836 if { ![info exists ${class}::opt($option)] } { 837 return -code error "unknown option \"$option\"" 838 } 839 840 set optdesc [set ${class}::opt($option)] 841 set type [lindex $optdesc 0] 842 if {[string equal $type "Synonym"]} { 843 set option [lindex $optdesc 1] 844 } 845 846 if { [info exists ${class}::map($option)] } { 847 foreach {subpath subclass realopt} [set ${class}::map($option)] {break} 848 set path "[_get_window $class $path]$subpath" 849 return [$path cget $realopt] 850 } 851 upvar 0 ${class}::$path:opt pathopt 852 set pathopt($option) 853} 854 855proc Widget::subcget { path subwidget } { 856 variable _class 857 set class $_class($path) 858 upvar 0 ${class}::$path:opt pathopt 859 upvar 0 ${class}::map$subwidget submap 860 upvar 0 ${class}::$path:init pathinit 861 862 set result {} 863 foreach realopt [array names submap] { 864 if { [info exists pathinit($submap($realopt))] } { 865 lappend result $realopt $pathopt($submap($realopt)) 866 } 867 } 868 return $result 869} 870 871proc Widget::hasChanged { path option pvalue } { 872 variable _class 873 upvar $pvalue value 874 set class $_class($path) 875 upvar 0 ${class}::$path:mod pathmod 876 877 set value [Widget::cget $path $option] 878 set result $pathmod($option) 879 set pathmod($option) 0 880 881 return $result 882} 883 884proc Widget::hasChangedX { path option args } { 885 variable _class 886 set class $_class($path) 887 upvar 0 ${class}::$path:mod pathmod 888 889 set result $pathmod($option) 890 set pathmod($option) 0 891 foreach option $args { 892 lappend result $pathmod($option) 893 set pathmod($option) 0 894 } 895 896 set result 897} 898 899proc Widget::setoption { path option value } { 900 Widget::configure $path [list $option $value] 901} 902 903proc Widget::getoption { path option } { 904 return [Widget::cget $path $option] 905} 906 907proc Widget::getMegawidgetOption {path option} { 908 variable _class 909 set class $_class($path) 910 upvar 0 ${class}::${path}:opt pathopt 911 set pathopt($option) 912} 913 914proc Widget::setMegawidgetOption {path option value} { 915 variable _class 916 set class $_class($path) 917 upvar 0 ${class}::${path}:opt pathopt 918 set pathopt($option) $value 919} 920 921proc Widget::_get_window { class path } { 922 set idx [string last "#" $path] 923 if { $idx != -1 && [string equal [string range $path [expr {$idx+1}] end] $class] } { 924 return [string range $path 0 [expr {$idx-1}]] 925 } else { 926 return $path 927 } 928} 929 930proc Widget::_get_configure { path options } { 931 variable _class 932 933 set class $_class($path) 934 upvar 0 ${class}::opt classopt 935 upvar 0 ${class}::map classmap 936 upvar 0 ${class}::$path:opt pathopt 937 upvar 0 ${class}::$path:mod pathmod 938 939 set len [llength $options] 940 if { !$len } { 941 set result {} 942 foreach option [lsort [array names classopt]] { 943 set optdesc $classopt($option) 944 set type [lindex $optdesc 0] 945 if { [string equal $type "Synonym"] } { 946 set syn $option 947 set option [lindex $optdesc 1] 948 set optdesc $classopt($option) 949 set type [lindex $optdesc 0] 950 } else { 951 set syn "" 952 } 953 if { [string equal $type "TkResource"] } { 954 set alt [lindex [lindex $optdesc 3] 1] 955 } else { 956 set alt "" 957 } 958 set res [_configure_option $option $alt] 959 if { $syn == "" } { 960 lappend result [concat $option $res [list [lindex $optdesc 1]] [list [cget $path $option]]] 961 } else { 962 lappend result [list $syn [lindex $res 0]] 963 } 964 } 965 return $result 966 } elseif { $len == 1 } { 967 set option [lindex $options 0] 968 if { ![info exists classopt($option)] } { 969 return -code error "unknown option \"$option\"" 970 } 971 set optdesc $classopt($option) 972 set type [lindex $optdesc 0] 973 if { [string equal $type "Synonym"] } { 974 set option [lindex $optdesc 1] 975 set optdesc $classopt($option) 976 set type [lindex $optdesc 0] 977 } 978 if { [string equal $type "TkResource"] } { 979 set alt [lindex [lindex $optdesc 3] 1] 980 } else { 981 set alt "" 982 } 983 set res [_configure_option $option $alt] 984 return [concat $option $res [list [lindex $optdesc 1]] [list [cget $path $option]]] 985 } 986} 987 988proc Widget::_configure_option { option altopt } { 989 variable _optiondb 990 variable _optionclass 991 992 if { [info exists _optiondb($option)] } { 993 set optdb $_optiondb($option) 994 } else { 995 set optdb [string range $option 1 end] 996 } 997 if { [info exists _optionclass($option)] } { 998 set optclass $_optionclass($option) 999 } elseif { [string length $altopt] } { 1000 if { [info exists _optionclass($altopt)] } { 1001 set optclass $_optionclass($altopt) 1002 } else { 1003 set optclass [string range $altopt 1 end] 1004 } 1005 } else { 1006 set optclass [string range $option 1 end] 1007 } 1008 return [list $optdb $optclass] 1009} 1010 1011proc Widget::_get_tkwidget_options { tkwidget } { 1012 variable _tk_widget 1013 variable _optiondb 1014 variable _optionclass 1015 1016 set widget ".#BWidget.#$tkwidget" 1017 # encapsulation frame to not pollute '.' childspace 1018 if {![winfo exists ".#BWidget"]} { frame ".#BWidget" } 1019 if { ![winfo exists $widget] || ![info exists _tk_widget($tkwidget)] } { 1020 set widget [$tkwidget $widget] 1021 # JDC: Withdraw toplevels, otherwise visible 1022 if {[string equal $tkwidget "toplevel"]} { 1023 wm withdraw $widget 1024 } 1025 set config [$widget configure] 1026 foreach optlist $config { 1027 set opt [lindex $optlist 0] 1028 if { [llength $optlist] == 2 } { 1029 set refsyn [lindex $optlist 1] 1030 # search for class 1031 set idx [lsearch $config [list * $refsyn *]] 1032 if { $idx == -1 } { 1033 if { [string index $refsyn 0] == "-" } { 1034 # search for option (tk8.1b1 bug) 1035 set idx [lsearch $config [list $refsyn * *]] 1036 } else { 1037 # last resort 1038 set idx [lsearch $config [list -[string tolower $refsyn] * *]] 1039 } 1040 if { $idx == -1 } { 1041 # fed up with "can't read classopt()" 1042 return -code error "can't find option of synonym $opt" 1043 } 1044 } 1045 set syn [lindex [lindex $config $idx] 0] 1046 # JDC: used 4 (was 3) to get def from optiondb 1047 set def [lindex [lindex $config $idx] 4] 1048 lappend _tk_widget($tkwidget) [list $opt $syn $def] 1049 } else { 1050 # JDC: used 4 (was 3) to get def from optiondb 1051 set def [lindex $optlist 4] 1052 lappend _tk_widget($tkwidget) [list $opt $def] 1053 set _optiondb($opt) [lindex $optlist 1] 1054 set _optionclass($opt) [lindex $optlist 2] 1055 } 1056 } 1057 } 1058 return $_tk_widget($tkwidget) 1059} 1060 1061proc Widget::_test_tkresource { option value arg } { 1062 foreach {tkwidget realopt} $arg break 1063 set path ".#BWidget.#$tkwidget" 1064 set old [$path cget $realopt] 1065 $path configure $realopt $value 1066 set res [$path cget $realopt] 1067 $path configure $realopt $old 1068 1069 return $res 1070} 1071 1072proc Widget::_test_bwresource { option value arg } { 1073 return -code error "bad option type BwResource in widget" 1074} 1075 1076proc Widget::_test_synonym { option value arg } { 1077 return -code error "bad option type Synonym in widget" 1078} 1079 1080proc Widget::_test_color { option value arg } { 1081 if {[catch {winfo rgb . $value} color]} { 1082 return -code error "bad $option value \"$value\": must be a colorname \ 1083 or #RRGGBB triplet" 1084 } 1085 1086 return $value 1087} 1088 1089proc Widget::_test_string { option value arg } { 1090 set value 1091} 1092 1093proc Widget::_test_flag { option value arg } { 1094 set len [string length $value] 1095 set res "" 1096 for {set i 0} {$i < $len} {incr i} { 1097 set c [string index $value $i] 1098 if { [string first $c $arg] == -1 } { 1099 return -code error "bad [string range $option 1 end] value \"$value\": characters must be in \"$arg\"" 1100 } 1101 if { [string first $c $res] == -1 } { 1102 append res $c 1103 } 1104 } 1105 return $res 1106} 1107 1108proc Widget::_test_enum { option value arg } { 1109 if { [lsearch $arg $value] == -1 } { 1110 set last [lindex $arg end] 1111 set sub [lreplace $arg end end] 1112 if { [llength $sub] } { 1113 set str "[join $sub ", "] or $last" 1114 } else { 1115 set str $last 1116 } 1117 return -code error "bad [string range $option 1 end] value \"$value\": must be $str" 1118 } 1119 return $value 1120} 1121 1122proc Widget::_test_int { option value arg } { 1123 if { ![string is int -strict $value] || \ 1124 ([string length $arg] && \ 1125 ![expr [string map [list %d $value] $arg]]) } { 1126 return -code error "bad $option value\ 1127 \"$value\": must be integer ($arg)" 1128 } 1129 return $value 1130} 1131 1132proc Widget::_test_boolean { option value arg } { 1133 if { ![string is boolean -strict $value] } { 1134 return -code error "bad $option value \"$value\": must be boolean" 1135 } 1136 1137 # Get the canonical form of the boolean value (1 for true, 0 for false) 1138 return [string is true $value] 1139} 1140 1141proc Widget::_test_padding { option values arg } { 1142 set len [llength $values] 1143 if {$len < 1 || $len > 2} { 1144 return -code error "bad pad value \"$values\":\ 1145 must be positive screen distance" 1146 } 1147 1148 foreach value $values { 1149 if { ![string is int -strict $value] || \ 1150 ([string length $arg] && \ 1151 ![expr [string map [list %d $value] $arg]]) } { 1152 return -code error "bad pad value \"$value\":\ 1153 must be positive screen distance ($arg)" 1154 } 1155 } 1156 return $values 1157} 1158 1159proc Widget::_get_padding { path option {index 0} } { 1160 set pad [Widget::cget $path $option] 1161 set val [lindex $pad $index] 1162 if {$val == ""} { set val [lindex $pad 0] } 1163 return $val 1164} 1165 1166proc Widget::focusNext { w } { 1167 set cur $w 1168 while 1 { 1169 # Descend to just before the first child of the current widget. 1170 set parent $cur 1171 set children [winfo children $cur] 1172 set i -1 1173 1174 # Look for the next sibling that isn't a top-level. 1175 while 1 { 1176 incr i 1177 if {$i < [llength $children]} { 1178 set cur [lindex $children $i] 1179 if {[string equal [winfo toplevel $cur] $cur]} { 1180 continue 1181 } else { 1182 break 1183 } 1184 } 1185 1186 set cur $parent 1187 if {[string equal [winfo toplevel $cur] $cur]} { 1188 break 1189 } 1190 set parent [winfo parent $parent] 1191 set children [winfo children $parent] 1192 set i [lsearch -exact $children $cur] 1193 } 1194 if {[string equal $cur $w] || [focusOK $cur]} { 1195 return $cur 1196 } 1197 } 1198} 1199 1200proc Widget::focusPrev { w } { 1201 set cur $w 1202 set origParent [winfo parent $w] 1203 while 1 { 1204 1205 if {[string equal [winfo toplevel $cur] $cur]} { 1206 set parent $cur 1207 set children [winfo children $cur] 1208 set i [llength $children] 1209 } else { 1210 set parent [winfo parent $cur] 1211 set children [winfo children $parent] 1212 set i [lsearch -exact $children $cur] 1213 } 1214 1215 while {$i > 0} { 1216 incr i -1 1217 set cur [lindex $children $i] 1218 if {[string equal [winfo toplevel $cur] $cur]} { 1219 continue 1220 } 1221 set parent $cur 1222 set children [winfo children $parent] 1223 set i [llength $children] 1224 } 1225 set cur $parent 1226 if {[string equal $cur $w]} { 1227 return $cur 1228 } 1229 1230 if {[string equal $cur $origParent] 1231 && [info procs ::$origParent] != ""} { 1232 continue 1233 } 1234 if {[focusOK $cur]} { 1235 return $cur 1236 } 1237 } 1238} 1239 1240proc Widget::focusOK { w } { 1241 set code [catch {$w cget -takefocus} value] 1242 if { $code == 1 } { 1243 return 0 1244 } 1245 if {($code == 0) && ($value != "")} { 1246 if {$value == 0} { 1247 return 0 1248 } elseif {$value == 1} { 1249 return [winfo viewable $w] 1250 } else { 1251 set value [uplevel \#0 $value $w] 1252 if {$value != ""} { 1253 return $value 1254 } 1255 } 1256 } 1257 if {![winfo viewable $w]} { 1258 return 0 1259 } 1260 set code [catch {$w cget -state} value] 1261 if {($code == 0) && ($value == "disabled")} { 1262 return 0 1263 } 1264 set code [catch {$w cget -editable} value] 1265 if {($code == 0) && ($value == 0)} { 1266 return 0 1267 } 1268 1269 set top [winfo toplevel $w] 1270 foreach tags [bindtags $w] { 1271 if { ![string equal $tags $top] && 1272 ![string equal $tags "all"] && 1273 [regexp Key [bind $tags]] } { 1274 return 1 1275 } 1276 } 1277 return 0 1278} 1279 1280proc Widget::traverseTo { w } { 1281 set focus [focus] 1282 if {![string equal $focus ""]} { 1283 event generate $focus <<TraverseOut>> 1284 } 1285 focus $w 1286 1287 event generate $w <<TraverseIn>> 1288} 1289 1290proc Widget::getVariable { path varName {newVarName ""} } { 1291 variable _class 1292 set class $_class($path) 1293 if {![string length $newVarName]} { set newVarName $varName } 1294 uplevel 1 [list upvar \#0 ${class}::$path:$varName $newVarName] 1295} 1296 1297proc Widget::options { path args } { 1298 if {[llength $args]} { 1299 foreach option $args { 1300 lappend options [_get_configure $path $option] 1301 } 1302 } else { 1303 set options [_get_configure $path {}] 1304 } 1305 1306 set result [list] 1307 foreach list $options { 1308 if {[llength $list] < 5} { continue } 1309 lappend result [lindex $list 0] [lindex $list end] 1310 } 1311 return $result 1312} 1313 1314proc Widget::exists { path } { 1315 variable _class 1316 return [info exists _class($path)] 1317} 1318# ---------------------------------------------------------------------------- 1319# utils.tcl -- part of Unifix BWidget Toolkit 1320# ---------------------------------------------------------------------------- 1321 1322namespace eval BWidget { 1323 variable _top 1324 variable _gstack {} 1325 variable _fstack {} 1326 proc use {} {} 1327} 1328 1329proc BWidget::get3dcolor { path bgcolor } { 1330 foreach val [winfo rgb $path $bgcolor] { 1331 lappend dark [expr {60*$val/100}] 1332 set tmp1 [expr {14*$val/10}] 1333 if { $tmp1 > 65535 } { 1334 set tmp1 65535 1335 } 1336 set tmp2 [expr {(65535+$val)/2}] 1337 lappend light [expr {($tmp1 > $tmp2) ? $tmp1:$tmp2}] 1338 } 1339 return [list [eval format "#%04x%04x%04x" $dark] [eval format "#%04x%04x%04x" $light]] 1340} 1341# ---------------------------------------------------------------------------- 1342# panedw.tcl -- part of Unifix BWidget Toolkit 1343# ---------------------------------------------------------------------------- 1344 1345namespace eval PanedWindow { 1346 Widget::define PanedWindow panedw 1347 1348 namespace eval Pane { 1349 Widget::declare PanedWindow::Pane { 1350 {-minsize Int 0 0 "%d >= 0"} 1351 {-weight Int 1 0 "%d >= 0"} 1352 } 1353 } 1354 1355 Widget::declare PanedWindow { 1356 {-side Enum top 1 {top left bottom right}} 1357 {-width Int 10 1 "%d >=3"} 1358 {-pad Int 4 1 "%d >= 0"} 1359 {-background TkResource "" 0 frame} 1360 {-bg Synonym -background} 1361 {-activator Enum "" 1 {line button}} 1362 {-weights Enum extra 1 {extra available}} 1363 } 1364 1365 variable _panedw 1366} 1367 1368proc PanedWindow::create { path args } { 1369 variable _panedw 1370 1371 Widget::init PanedWindow $path $args 1372 1373 frame $path -background [Widget::cget $path -background] -class PanedWindow 1374 set _panedw($path,nbpanes) 0 1375 set _panedw($path,weights) "" 1376 set _panedw($path,configuredone) 0 1377 1378 set activator [Widget::getoption $path -activator] 1379 if {[string equal $activator ""]} { 1380 if { $::tcl_platform(platform) != "windows" } { 1381 Widget::setMegawidgetOption $path -activator button 1382 } else { 1383 Widget::setMegawidgetOption $path -activator line 1384 } 1385 } 1386 if {[string equal [Widget::getoption $path -activator] "line"]} { 1387 Widget::setMegawidgetOption $path -width 3 1388 } 1389 1390 bind $path <Configure> [list PanedWindow::_realize $path %w %h] 1391 bind $path <Destroy> [list PanedWindow::_destroy $path] 1392 1393 return [Widget::create PanedWindow $path] 1394} 1395 1396proc PanedWindow::configure { path args } { 1397 variable _panedw 1398 1399 set res [Widget::configure $path $args] 1400 1401 if { [Widget::hasChanged $path -background bg] && $_panedw($path,nbpanes) > 0 } { 1402 $path:cmd configure -background $bg 1403 $path.f0 configure -background $bg 1404 for {set i 1} {$i < $_panedw($path,nbpanes)} {incr i} { 1405 set frame $path.sash$i 1406 $frame configure -background $bg 1407 $frame.sep configure -background $bg 1408 $frame.but configure -background $bg 1409 $path.f$i configure -background $bg 1410 $path.f$i.frame configure -background $bg 1411 } 1412 } 1413 return $res 1414} 1415 1416proc PanedWindow::cget { path option } { 1417 return [Widget::cget $path $option] 1418} 1419 1420proc PanedWindow::add { path args } { 1421 variable _panedw 1422 1423 set num $_panedw($path,nbpanes) 1424 Widget::init PanedWindow::Pane $path.f$num $args 1425 set bg [Widget::getoption $path -background] 1426 1427 set wbut [Widget::getoption $path -width] 1428 set pad [Widget::getoption $path -pad] 1429 set width [expr {$wbut+2*$pad}] 1430 set side [Widget::getoption $path -side] 1431 set weight [Widget::getoption $path.f$num -weight] 1432 lappend _panedw($path,weights) $weight 1433 1434 if { $num > 0 } { 1435 set frame [frame $path.sash$num -relief flat -bd 0 \ 1436 -highlightthickness 0 -width $width -height $width -bg $bg] 1437 set sep [frame $frame.sep -bd 5 -relief raised \ 1438 -highlightthickness 0 -bg $bg] 1439 set but [frame $frame.but -bd 1 -relief raised \ 1440 -highlightthickness 0 -bg $bg -width $wbut -height $wbut] 1441 set sepsize 2 1442 1443 set activator [Widget::getoption $path -activator] 1444 if {$activator == "button"} { 1445 set activator $but 1446 set placeButton 1 1447 } else { 1448 set activator $sep 1449 $sep configure -bd 1 1450 set placeButton 0 1451 } 1452 if {[string equal $side "top"] || [string equal $side "bottom"]} { 1453 place $sep -relx 0.5 -y 0 -width $sepsize -relheight 1.0 -anchor n 1454 if { $placeButton } { 1455 if {[string equal $side "top"]} { 1456 place $but -relx 0.5 -y [expr {6+$wbut/2}] -anchor c 1457 } else { 1458 place $but -relx 0.5 -rely 1.0 -y [expr {-6-$wbut/2}] \ 1459 -anchor c 1460 } 1461 } 1462 $activator configure -cursor sb_h_double_arrow 1463 grid $frame -column [expr {2*$num-1}] -row 0 -sticky ns 1464 grid columnconfigure $path [expr {2*$num-1}] -weight 0 1465 } else { 1466 place $sep -x 0 -rely 0.5 -height $sepsize -relwidth 1.0 -anchor w 1467 if { $placeButton } { 1468 if {[string equal $side "left"]} { 1469 place $but -rely 0.5 -x [expr {6+$wbut/2}] -anchor c 1470 } else { 1471 place $but -rely 0.5 -relx 1.0 -x [expr {-6-$wbut/2}] \ 1472 -anchor c 1473 } 1474 } 1475 $activator configure -cursor sb_v_double_arrow 1476 grid $frame -row [expr {2*$num-1}] -column 0 -sticky ew 1477 grid rowconfigure $path [expr {2*$num-1}] -weight 0 1478 } 1479 bind $activator <ButtonPress-1> \ 1480 [list PanedWindow::_beg_move_sash $path $num %X %Y] 1481 } else { 1482 if { [string equal $side "top"] || \ 1483 [string equal $side "bottom"] } { 1484 grid rowconfigure $path 0 -weight 1 1485 } else { 1486 grid columnconfigure $path 0 -weight 1 1487 } 1488 } 1489 1490 set pane [frame $path.f$num -bd 0 -relief flat \ 1491 -highlightthickness 0 -bg $bg] 1492 set user [frame $path.f$num.frame -bd 0 -relief flat \ 1493 -highlightthickness 0 -bg $bg] 1494 if { [string equal $side "top"] || [string equal $side "bottom"] } { 1495 grid $pane -column [expr {2*$num}] -row 0 -sticky nsew 1496 grid columnconfigure $path [expr {2*$num}] -weight $weight 1497 } else { 1498 grid $pane -row [expr {2*$num}] -column 0 -sticky nsew 1499 grid rowconfigure $path [expr {2*$num}] -weight $weight 1500 } 1501 pack $user -fill both -expand yes 1502 incr _panedw($path,nbpanes) 1503 if {$_panedw($path,configuredone)} { 1504 _realize $path [winfo width $path] [winfo height $path] 1505 } 1506 1507 return $user 1508} 1509 1510proc PanedWindow::getframe { path index } { 1511 if { [winfo exists $path.f$index.frame] } { 1512 return $path.f$index.frame 1513 } 1514} 1515 1516proc PanedWindow::_beg_move_sash { path num x y } { 1517 variable _panedw 1518 1519 set fprev $path.f[expr {$num-1}] 1520 set fnext $path.f$num 1521 set wsash [expr {[Widget::getoption $path -width] + 2*[Widget::getoption $path -pad]}] 1522 1523 $path.sash$num.but configure -relief sunken 1524 set top [toplevel $path.sash -borderwidth 1 -relief raised] 1525 1526 set minszg [Widget::getoption $fprev -minsize] 1527 set minszd [Widget::getoption $fnext -minsize] 1528 set side [Widget::getoption $path -side] 1529 1530 if { [string equal $side "top"] || [string equal $side "bottom"] } { 1531 $top configure -cursor sb_h_double_arrow 1532 set h [winfo height $path] 1533 set yr [winfo rooty $path.sash$num] 1534 set xmin [expr {$wsash/2+[winfo rootx $fprev]+$minszg}] 1535 set xmax [expr {-$wsash/2-1+[winfo rootx $fnext]+[winfo width $fnext]-$minszd}] 1536 wm overrideredirect $top 1 1537 wm geom $top "2x${h}+$x+$yr" 1538 1539 update idletasks 1540 grab set $top 1541 bind $top <ButtonRelease-1> [list PanedWindow::_end_move_sash $path $top $num $xmin $xmax %X rootx width] 1542 bind $top <Motion> [list PanedWindow::_move_sash $top $xmin $xmax %X +%%d+$yr] 1543 _move_sash $top $xmin $xmax $x "+%d+$yr" 1544 } else { 1545 $top configure -cursor sb_v_double_arrow 1546 set w [winfo width $path] 1547 set xr [winfo rootx $path.sash$num] 1548 set ymin [expr {$wsash/2+[winfo rooty $fprev]+$minszg}] 1549 set ymax [expr {-$wsash/2-1+[winfo rooty $fnext]+[winfo height $fnext]-$minszd}] 1550 wm overrideredirect $top 1 1551 wm geom $top "${w}x2+$xr+$y" 1552 1553 update idletasks 1554 grab set $top 1555 bind $top <ButtonRelease-1> [list PanedWindow::_end_move_sash \ 1556 $path $top $num $ymin $ymax %Y rooty height] 1557 bind $top <Motion> [list PanedWindow::_move_sash \ 1558 $top $ymin $ymax %Y +$xr+%%d] 1559 _move_sash $top $ymin $ymax $y "+$xr+%d" 1560 } 1561} 1562 1563proc PanedWindow::_move_sash { top min max v form } { 1564 1565 if { $v < $min } { 1566 set v $min 1567 } elseif { $v > $max } { 1568 set v $max 1569 } 1570 wm geom $top [format $form $v] 1571} 1572 1573proc PanedWindow::_end_move_sash { path top num min max v rootv size } { 1574 variable _panedw 1575 1576 destroy $top 1577 if { $v < $min } { 1578 set v $min 1579 } elseif { $v > $max } { 1580 set v $max 1581 } 1582 set fprev $path.f[expr {$num-1}] 1583 set fnext $path.f$num 1584 1585 $path.sash$num.but configure -relief raised 1586 1587 set wsash [expr {[Widget::getoption $path -width] + 2*[Widget::getoption $path -pad]}] 1588 set dv [expr {$v-[winfo $rootv $path.sash$num]-$wsash/2}] 1589 set w1 [winfo $size $fprev] 1590 set w2 [winfo $size $fnext] 1591 1592 for {set i 0} {$i < $_panedw($path,nbpanes)} {incr i} { 1593 if { $i == $num-1} { 1594 $fprev configure -$size [expr {[winfo $size $fprev]+$dv}] 1595 } elseif { $i == $num } { 1596 $fnext configure -$size [expr {[winfo $size $fnext]-$dv}] 1597 } else { 1598 $path.f$i configure -$size [winfo $size $path.f$i] 1599 } 1600 } 1601} 1602 1603proc PanedWindow::_realize { path width height } { 1604 variable _panedw 1605 1606 set x 0 1607 set y 0 1608 set hc [winfo reqheight $path] 1609 set hmax 0 1610 for {set i 0} {$i < $_panedw($path,nbpanes)} {incr i} { 1611 $path.f$i configure \ 1612 -width [winfo reqwidth $path.f$i.frame] \ 1613 -height [winfo reqheight $path.f$i.frame] 1614 place $path.f$i.frame -x 0 -y 0 -relwidth 1 -relheight 1 1615 } 1616 1617 bind $path <Configure> {} 1618 1619 _apply_weights $path 1620 set _panedw($path,configuredone) 1 1621 return 1622} 1623 1624proc PanedWindow::_apply_weights { path } { 1625 variable _panedw 1626 1627 set weights [Widget::getoption $path -weights] 1628 if {[string equal $weights "extra"]} { 1629 return 1630 } 1631 1632 set side [Widget::getoption $path -side] 1633 if {[string equal $side "top"] || [string equal $side "bottom"] } { 1634 set size width 1635 } else { 1636 set size height 1637 } 1638 set wsash [expr {[Widget::getoption $path -width] + 2*[Widget::getoption $path -pad]}] 1639 set rs [winfo $size $path] 1640 set s [expr {$rs - ($_panedw($path,nbpanes) - 1) * $wsash}] 1641 1642 set tw 0.0 1643 foreach w $_panedw($path,weights) { 1644 set tw [expr {$tw + $w}] 1645 } 1646 1647 for {set i 0} {$i < $_panedw($path,nbpanes)} {incr i} { 1648 set rw [lindex $_panedw($path,weights) $i] 1649 set ps [expr {int($rw / $tw * $s)}] 1650 $path.f$i configure -$size $ps 1651 } 1652 return 1653} 1654 1655proc PanedWindow::_destroy { path } { 1656 variable _panedw 1657 1658 for {set i 0} {$i < $_panedw($path,nbpanes)} {incr i} { 1659 Widget::destroy $path.f$i 1660 } 1661 unset _panedw($path,nbpanes) 1662 Widget::destroy $path 1663} 1664# ------------------------------------------------------------------------------ 1665# arrow.tcl -- part of Unifix BWidget Toolkit 1666# ------------------------------------------------------------------------------ 1667 1668namespace eval ArrowButton { 1669 Widget::define ArrowButton arrow 1670 1671 Widget::tkinclude ArrowButton button .c \ 1672 include [list \ 1673 -borderwidth -bd \ 1674 -relief -highlightbackground \ 1675 -highlightcolor -highlightthickness -takefocus] 1676 1677 Widget::declare ArrowButton [list \ 1678 [list -type Enum button 0 [list arrow button]] \ 1679 [list -dir Enum top 0 [list top bottom left right]] \ 1680 [list -width Int 15 0 "%d >= 0"] \ 1681 [list -height Int 15 0 "%d >= 0"] \ 1682 [list -ipadx Int 0 0 "%d >= 0"] \ 1683 [list -ipady Int 0 0 "%d >= 0"] \ 1684 [list -clean Int 2 0 "%d >= 0 && %d <= 2"] \ 1685 [list -activeforeground TkResource "" 0 button] \ 1686 [list -activebackground TkResource "" 0 button] \ 1687 [list -disabledforeground TkResource "" 0 button] \ 1688 [list -foreground TkResource "" 0 button] \ 1689 [list -background TkResource "" 0 button] \ 1690 [list -state TkResource "" 0 button] \ 1691 [list -troughcolor TkResource "" 0 scrollbar] \ 1692 [list -arrowbd Int 1 0 "%d >= 0 && %d <= 2"] \ 1693 [list -arrowrelief Enum raised 0 [list raised sunken]] \ 1694 [list -command String "" 0] \ 1695 [list -armcommand String "" 0] \ 1696 [list -disarmcommand String "" 0] \ 1697 [list -repeatdelay Int 0 0 "%d >= 0"] \ 1698 [list -repeatinterval Int 0 0 "%d >= 0"] \ 1699 [list -fg Synonym -foreground] \ 1700 [list -bg Synonym -background] \ 1701 ] 1702 1703 bind BwArrowButtonC <Enter> {ArrowButton::_enter %W} 1704 bind BwArrowButtonC <Leave> {ArrowButton::_leave %W} 1705 bind BwArrowButtonC <ButtonPress-1> {ArrowButton::_press %W} 1706 bind BwArrowButtonC <ButtonRelease-1> {ArrowButton::_release %W} 1707 bind BwArrowButtonC <Key-space> {ArrowButton::invoke %W; break} 1708 bind BwArrowButtonC <Return> {ArrowButton::invoke %W; break} 1709 bind BwArrowButton <Configure> {ArrowButton::_redraw_whole %W %w %h} 1710 bind BwArrowButton <Destroy> {ArrowButton::_destroy %W} 1711 1712 variable _grab 1713 variable _moved 1714 1715 array set _grab {current "" pressed "" oldstate "normal" oldrelief ""} 1716} 1717 1718proc ArrowButton::create { path args } { 1719 # Initialize configuration mappings and parse arguments 1720 array set submaps [list ArrowButton [list ] .c [list ]] 1721 array set submaps [Widget::parseArgs ArrowButton $args] 1722 1723 # Create the class frame (so we can do the option db queries) 1724 frame $path -class ArrowButton -borderwidth 0 -highlightthickness 0 1725 Widget::initFromODB ArrowButton $path $submaps(ArrowButton) 1726 1727 # Create the canvas with the initial options 1728 eval [list canvas $path.c] $submaps(.c) 1729 1730 # Compute the width and height of the canvas from the width/height 1731 # of the ArrowButton and the borderwidth/hightlightthickness. 1732 set w [Widget::getMegawidgetOption $path -width] 1733 set h [Widget::getMegawidgetOption $path -height] 1734 set bd [Widget::cget $path -borderwidth] 1735 set ht [Widget::cget $path -highlightthickness] 1736 set pad [expr {2*($bd+$ht)}] 1737 1738 $path.c configure -width [expr {$w-$pad}] -height [expr {$h-$pad}] 1739 bindtags $path [list $path BwArrowButton [winfo toplevel $path] all] 1740 bindtags $path.c [list $path.c BwArrowButtonC [winfo toplevel $path.c] all] 1741 pack $path.c -expand yes -fill both 1742 1743 set ::ArrowButton::_moved($path) 0 1744 1745 return [Widget::create ArrowButton $path] 1746} 1747 1748proc ArrowButton::configure { path args } { 1749 set res [Widget::configure $path $args] 1750 1751 set ch1 [expr {[Widget::hasChanged $path -width w] | 1752 [Widget::hasChanged $path -height h] | 1753 [Widget::hasChanged $path -borderwidth bd] | 1754 [Widget::hasChanged $path -highlightthickness ht]}] 1755 set ch2 [expr {[Widget::hasChanged $path -type val] | 1756 [Widget::hasChanged $path -ipadx val] | 1757 [Widget::hasChanged $path -ipady val] | 1758 [Widget::hasChanged $path -arrowbd val] | 1759 [Widget::hasChanged $path -clean val] | 1760 [Widget::hasChanged $path -dir val]}] 1761 1762 if { $ch1 } { 1763 set pad [expr {2*($bd+$ht)}] 1764 $path.c configure \ 1765 -width [expr {$w-$pad}] -height [expr {$h-$pad}] \ 1766 -borderwidth $bd -highlightthickness $ht 1767 set ch2 1 1768 } 1769 if { $ch2 } { 1770 _redraw_whole $path [winfo width $path] [winfo height $path] 1771 } else { 1772 _redraw_relief $path 1773 _redraw_state $path 1774 } 1775 1776 return $res 1777} 1778 1779proc ArrowButton::cget { path option } { 1780 return [Widget::cget $path $option] 1781} 1782 1783proc ArrowButton::invoke { path } { 1784 if { ![string equal [winfo class $path] "ArrowButton"] } { 1785 set path [winfo parent $path] 1786 } 1787 if { ![string equal [Widget::getoption $path -state] "disabled"] } { 1788 set oldstate [Widget::getoption $path -state] 1789 if { [string equal [Widget::getoption $path -type] "button"] } { 1790 set oldrelief [Widget::getoption $path -relief] 1791 configure $path -state active -relief sunken 1792 } else { 1793 set oldrelief [Widget::getoption $path -arrowrelief] 1794 configure $path -state active -arrowrelief sunken 1795 } 1796 update idletasks 1797 if {[llength [set cmd [Widget::getoption $path -armcommand]]]} { 1798 uplevel \#0 $cmd 1799 } 1800 after 10 1801 if { [string equal [Widget::getoption $path -type] "button"] } { 1802 configure $path -state $oldstate -relief $oldrelief 1803 } else { 1804 configure $path -state $oldstate -arrowrelief $oldrelief 1805 } 1806 if {[llength [set cmd [Widget::getoption $path -disarmcommand]]]} { 1807 uplevel \#0 $cmd 1808 } 1809 if {[llength [set cmd [Widget::getoption $path -command]]]} { 1810 uplevel \#0 $cmd 1811 } 1812 } 1813} 1814 1815proc ArrowButton::_redraw { path width height } { 1816 variable _moved 1817 1818 set _moved($path) 0 1819 set type [Widget::getoption $path -type] 1820 set dir [Widget::getoption $path -dir] 1821 set bd [expr {[$path.c cget -borderwidth] + [$path.c cget -highlightthickness] + 1}] 1822 set clean [Widget::getoption $path -clean] 1823 if { [string equal $type "arrow"] } { 1824 if { [set id [$path.c find withtag rect]] == "" } { 1825 $path.c create rectangle $bd $bd [expr {$width-$bd-1}] [expr {$height-$bd-1}] -tags rect 1826 } else { 1827 $path.c coords $id $bd $bd [expr {$width-$bd-1}] [expr {$height-$bd-1}] 1828 } 1829 $path.c lower rect 1830 set arrbd [Widget::getoption $path -arrowbd] 1831 set bd [expr {$bd+$arrbd-1}] 1832 } else { 1833 $path.c delete rect 1834 } 1835 # w and h are max width and max height of arrow 1836 set w [expr {$width - 2*([Widget::getoption $path -ipadx]+$bd)}] 1837 set h [expr {$height - 2*([Widget::getoption $path -ipady]+$bd)}] 1838 1839 if { $w < 2 } {set w 2} 1840 if { $h < 2 } {set h 2} 1841 1842 if { $clean > 0 } { 1843 # arrange for base to be odd 1844 if { [string equal $dir "top"] || [string equal $dir "bottom"] } { 1845 if { !($w % 2) } { 1846 incr w -1 1847 } 1848 if { $clean == 2 } { 1849 # arrange for h = (w+1)/2 1850 set h2 [expr {($w+1)/2}] 1851 if { $h2 > $h } { 1852 set w [expr {2*$h-1}] 1853 } else { 1854 set h $h2 1855 } 1856 } 1857 } else { 1858 if { !($h % 2) } { 1859 incr h -1 1860 } 1861 if { $clean == 2 } { 1862 # arrange for w = (h+1)/2 1863 set w2 [expr {($h+1)/2}] 1864 if { $w2 > $w } { 1865 set h [expr {2*$w-1}] 1866 } else { 1867 set w $w2 1868 } 1869 } 1870 } 1871 } 1872 1873 set x0 [expr {($width-$w)/2}] 1874 set y0 [expr {($height-$h)/2}] 1875 set x1 [expr {$x0+$w-1}] 1876 set y1 [expr {$y0+$h-1}] 1877 1878 switch $dir { 1879 top { 1880 set xd [expr {($x0+$x1)/2}] 1881 if { [set id [$path.c find withtag poly]] == "" } { 1882 $path.c create polygon $x0 $y1 $x1 $y1 $xd $y0 -tags poly 1883 } else { 1884 $path.c coords $id $x0 $y1 $x1 $y1 $xd $y0 1885 } 1886 if { [string equal $type "arrow"] } { 1887 if { [set id [$path.c find withtag bot]] == "" } { 1888 $path.c create line $x0 $y1 $x1 $y1 $xd $y0 -tags bot 1889 } else { 1890 $path.c coords $id $x0 $y1 $x1 $y1 $xd $y0 1891 } 1892 if { [set id [$path.c find withtag top]] == "" } { 1893 $path.c create line $x0 $y1 $xd $y0 -tags top 1894 } else { 1895 $path.c coords $id $x0 $y1 $xd $y0 1896 } 1897 $path.c itemconfigure top -width $arrbd 1898 $path.c itemconfigure bot -width $arrbd 1899 } else { 1900 $path.c delete top 1901 $path.c delete bot 1902 } 1903 } 1904 bottom { 1905 set xd [expr {($x0+$x1)/2}] 1906 if { [set id [$path.c find withtag poly]] == "" } { 1907 $path.c create polygon $x1 $y0 $x0 $y0 $xd $y1 -tags poly 1908 } else { 1909 $path.c coords $id $x1 $y0 $x0 $y0 $xd $y1 1910 } 1911 if { [string equal $type "arrow"] } { 1912 if { [set id [$path.c find withtag top]] == "" } { 1913 $path.c create line $x1 $y0 $x0 $y0 $xd $y1 -tags top 1914 } else { 1915 $path.c coords $id $x1 $y0 $x0 $y0 $xd $y1 1916 } 1917 if { [set id [$path.c find withtag bot]] == "" } { 1918 $path.c create line $x1 $y0 $xd $y1 -tags bot 1919 } else { 1920 $path.c coords $id $x1 $y0 $xd $y1 1921 } 1922 $path.c itemconfigure top -width $arrbd 1923 $path.c itemconfigure bot -width $arrbd 1924 } else { 1925 $path.c delete top 1926 $path.c delete bot 1927 } 1928 } 1929 left { 1930 set yd [expr {($y0+$y1)/2}] 1931 if { [set id [$path.c find withtag poly]] == "" } { 1932 $path.c create polygon $x1 $y0 $x1 $y1 $x0 $yd -tags poly 1933 } else { 1934 $path.c coords $id $x1 $y0 $x1 $y1 $x0 $yd 1935 } 1936 if { [string equal $type "arrow"] } { 1937 if { [set id [$path.c find withtag bot]] == "" } { 1938 $path.c create line $x1 $y0 $x1 $y1 $x0 $yd -tags bot 1939 } else { 1940 $path.c coords $id $x1 $y0 $x1 $y1 $x0 $yd 1941 } 1942 if { [set id [$path.c find withtag top]] == "" } { 1943 $path.c create line $x1 $y0 $x0 $yd -tags top 1944 } else { 1945 $path.c coords $id $x1 $y0 $x0 $yd 1946 } 1947 $path.c itemconfigure top -width $arrbd 1948 $path.c itemconfigure bot -width $arrbd 1949 } else { 1950 $path.c delete top 1951 $path.c delete bot 1952 } 1953 } 1954 right { 1955 set yd [expr {($y0+$y1)/2}] 1956 if { [set id [$path.c find withtag poly]] == "" } { 1957 $path.c create polygon $x0 $y1 $x0 $y0 $x1 $yd -tags poly 1958 } else { 1959 $path.c coords $id $x0 $y1 $x0 $y0 $x1 $yd 1960 } 1961 if { [string equal $type "arrow"] } { 1962 if { [set id [$path.c find withtag top]] == "" } { 1963 $path.c create line $x0 $y1 $x0 $y0 $x1 $yd -tags top 1964 } else { 1965 $path.c coords $id $x0 $y1 $x0 $y0 $x1 $yd 1966 } 1967 if { [set id [$path.c find withtag bot]] == "" } { 1968 $path.c create line $x0 $y1 $x1 $yd -tags bot 1969 } else { 1970 $path.c coords $id $x0 $y1 $x1 $yd 1971 } 1972 $path.c itemconfigure top -width $arrbd 1973 $path.c itemconfigure bot -width $arrbd 1974 } else { 1975 $path.c delete top 1976 $path.c delete bot 1977 } 1978 } 1979 } 1980} 1981 1982proc ArrowButton::_redraw_state { path } { 1983 set state [Widget::getoption $path -state] 1984 if { [string equal [Widget::getoption $path -type] "button"] } { 1985 switch $state { 1986 normal {set bg -background; set fg -foreground} 1987 active {set bg -activebackground; set fg -activeforeground} 1988 disabled {set bg -background; set fg -disabledforeground} 1989 } 1990 set fg [Widget::getoption $path $fg] 1991 $path.c configure -background [Widget::getoption $path $bg] 1992 $path.c itemconfigure poly -fill $fg -outline $fg 1993 } else { 1994 switch $state { 1995 normal {set stipple ""; set bg [Widget::getoption $path -background] } 1996 active {set stipple ""; set bg [Widget::getoption $path -activebackground] } 1997 disabled {set stipple gray50; set bg black } 1998 } 1999 set thrc [Widget::getoption $path -troughcolor] 2000 $path.c configure -background [Widget::getoption $path -background] 2001 $path.c itemconfigure rect -fill $thrc -outline $thrc 2002 $path.c itemconfigure poly -fill $bg -outline $bg -stipple $stipple 2003 } 2004} 2005 2006proc ArrowButton::_redraw_relief { path } { 2007 variable _moved 2008 2009 if { [string equal [Widget::getoption $path -type] "button"] } { 2010 if { [string equal [Widget::getoption $path -relief] "sunken"] } { 2011 if { !$_moved($path) } { 2012 $path.c move poly 1 1 2013 set _moved($path) 1 2014 } 2015 } else { 2016 if { $_moved($path) } { 2017 $path.c move poly -1 -1 2018 set _moved($path) 0 2019 } 2020 } 2021 } else { 2022 set col3d [BWidget::get3dcolor $path [Widget::getoption $path -background]] 2023 switch [Widget::getoption $path -arrowrelief] { 2024 raised {set top [lindex $col3d 1]; set bot [lindex $col3d 0]} 2025 sunken {set top [lindex $col3d 0]; set bot [lindex $col3d 1]} 2026 } 2027 $path.c itemconfigure top -fill $top 2028 $path.c itemconfigure bot -fill $bot 2029 } 2030} 2031 2032proc ArrowButton::_redraw_whole { path width height } { 2033 _redraw $path $width $height 2034 _redraw_relief $path 2035 _redraw_state $path 2036} 2037 2038proc ArrowButton::_enter { path } { 2039 variable _grab 2040 set path [winfo parent $path] 2041 set _grab(current) $path 2042 if { ![string equal [Widget::getoption $path -state] "disabled"] } { 2043 set _grab(oldstate) [Widget::getoption $path -state] 2044 configure $path -state active 2045 if { $_grab(pressed) == $path } { 2046 if { [string equal [Widget::getoption $path -type] "button"] } { 2047 set _grab(oldrelief) [Widget::getoption $path -relief] 2048 configure $path -relief sunken 2049 } else { 2050 set _grab(oldrelief) [Widget::getoption $path -arrowrelief] 2051 configure $path -arrowrelief sunken 2052 } 2053 } 2054 } 2055} 2056 2057proc ArrowButton::_leave { path } { 2058 variable _grab 2059 set path [winfo parent $path] 2060 set _grab(current) "" 2061 if { ![string equal [Widget::getoption $path -state] "disabled"] } { 2062 configure $path -state $_grab(oldstate) 2063 if { $_grab(pressed) == $path } { 2064 if { [string equal [Widget::getoption $path -type] "button"] } { 2065 configure $path -relief $_grab(oldrelief) 2066 } else { 2067 configure $path -arrowrelief $_grab(oldrelief) 2068 } 2069 } 2070 } 2071} 2072 2073proc ArrowButton::_press { path } { 2074 variable _grab 2075 set path [winfo parent $path] 2076 if { ![string equal [Widget::getoption $path -state] "disabled"] } { 2077 set _grab(pressed) $path 2078 if { [string equal [Widget::getoption $path -type] "button"] } { 2079 set _grab(oldrelief) [Widget::getoption $path -relief] 2080 configure $path -relief sunken 2081 } else { 2082 set _grab(oldrelief) [Widget::getoption $path -arrowrelief] 2083 configure $path -arrowrelief sunken 2084 } 2085 if {[llength [set cmd [Widget::getoption $path -armcommand]]]} { 2086 uplevel \#0 $cmd 2087 if { [set delay [Widget::getoption $path -repeatdelay]] > 0 || 2088 [set delay [Widget::getoption $path -repeatinterval]] > 0 } { 2089 after $delay [list ArrowButton::_repeat $path] 2090 } 2091 } 2092 } 2093} 2094 2095proc ArrowButton::_release { path } { 2096 variable _grab 2097 set path [winfo parent $path] 2098 if { $_grab(pressed) == $path } { 2099 set _grab(pressed) "" 2100 if { [string equal [Widget::getoption $path -type] "button"] } { 2101 configure $path -relief $_grab(oldrelief) 2102 } else { 2103 configure $path -arrowrelief $_grab(oldrelief) 2104 } 2105 if {[llength [set cmd [Widget::getoption $path -disarmcommand]]]} { 2106 uplevel \#0 $cmd 2107 } 2108 if { $_grab(current) == $path && 2109 ![string equal [Widget::getoption $path -state] "disabled"] && 2110 [llength [set cmd [Widget::getoption $path -command]]]} { 2111 uplevel \#0 $cmd 2112 } 2113 } 2114} 2115 2116proc ArrowButton::_repeat { path } { 2117 variable _grab 2118 if { $_grab(current) == $path && $_grab(pressed) == $path && 2119 ![string equal [Widget::getoption $path -state] "disabled"] && 2120 [llength [set cmd [Widget::getoption $path -armcommand]]]} { 2121 uplevel \#0 $cmd 2122 } 2123 if { $_grab(pressed) == $path && 2124 ([set delay [Widget::getoption $path -repeatinterval]] > 0 || 2125 [set delay [Widget::getoption $path -repeatdelay]] > 0) } { 2126 after $delay [list ArrowButton::_repeat $path] 2127 } 2128} 2129 2130proc ArrowButton::_destroy { path } { 2131 variable _moved 2132 Widget::destroy $path 2133 unset _moved($path) 2134} 2135# --------------------------------------------------------------------------- 2136# notebook.tcl -- part of Unifix BWidget Toolkit 2137# --------------------------------------------------------------------------- 2138 2139namespace eval NoteBook { 2140 Widget::define NoteBook notebook ArrowButton 2141 2142 namespace eval Page { 2143 Widget::declare NoteBook::Page { 2144 {-state Enum normal 0 {normal disabled}} 2145 {-createcmd String "" 0} 2146 {-raisecmd String "" 0} 2147 {-leavecmd String "" 0} 2148 {-image TkResource "" 0 label} 2149 {-text String "" 0} 2150 {-foreground String "" 0} 2151 {-background String "" 0} 2152 {-activeforeground String "" 0} 2153 {-activebackground String "" 0} 2154 {-disabledforeground String "" 0} 2155 } 2156 } 2157 2158 Widget::bwinclude NoteBook ArrowButton .c.fg \ 2159 include {-foreground -background -activeforeground \ 2160 -activebackground -disabledforeground -repeatinterval \ 2161 -repeatdelay -borderwidth} \ 2162 initialize {-borderwidth 1} 2163 Widget::bwinclude NoteBook ArrowButton .c.fd \ 2164 include {-foreground -background -activeforeground \ 2165 -activebackground -disabledforeground -repeatinterval \ 2166 -repeatdelay -borderwidth} \ 2167 initialize {-borderwidth 1} 2168 2169 Widget::declare NoteBook { 2170 {-foreground TkResource "" 0 button} 2171 {-background TkResource "" 0 button} 2172 {-activebackground TkResource "" 0 button} 2173 {-activeforeground TkResource "" 0 button} 2174 {-disabledforeground TkResource "" 0 button} 2175 {-font TkResource "" 0 button} 2176 {-side Enum top 0 {top bottom}} 2177 {-homogeneous Boolean 0 0} 2178 {-borderwidth Int 1 0 "%d >= 1 && %d <= 2"} 2179 {-internalborderwidth Int 10 0 "%d >= 0"} 2180 {-width Int 0 0 "%d >= 0"} 2181 {-height Int 0 0 "%d >= 0"} 2182 2183 {-repeatdelay BwResource "" 0 ArrowButton} 2184 {-repeatinterval BwResource "" 0 ArrowButton} 2185 2186 {-fg Synonym -foreground} 2187 {-bg Synonym -background} 2188 {-bd Synonym -borderwidth} 2189 {-ibd Synonym -internalborderwidth} 2190 2191 {-arcradius Int 2 0 "%d >= 0 && %d <= 8"} 2192 {-tabbevelsize Int 0 0 "%d >= 0 && %d <= 8"} 2193 {-tabpady Padding {0 6} 0 "%d >= 0"} 2194 } 2195 2196 Widget::addmap NoteBook "" .c {-background {}} 2197 2198 variable _warrow 12 2199 2200 bind NoteBook <Configure> [list NoteBook::_resize %W] 2201 bind NoteBook <Destroy> [list NoteBook::_destroy %W] 2202} 2203 2204proc NoteBook::create { path args } { 2205 variable $path 2206 upvar 0 $path data 2207 2208 Widget::init NoteBook $path $args 2209 2210 set data(base) 0 2211 set data(select) "" 2212 set data(pages) {} 2213 set data(pages) {} 2214 set data(cpt) 0 2215 set data(realized) 0 2216 set data(wpage) 0 2217 2218 _compute_height $path 2219 2220 # Create the canvas 2221 set w [expr {[Widget::cget $path -width]+4}] 2222 set h [expr {[Widget::cget $path -height]+$data(hpage)+4}] 2223 2224 frame $path -class NoteBook -borderwidth 0 -highlightthickness 0 \ 2225 -relief flat 2226 eval [list canvas $path.c] [Widget::subcget $path .c] \ 2227 [list -relief flat -borderwidth 0 -highlightthickness 0 \ 2228 -width $w -height $h] 2229 pack $path.c -expand yes -fill both 2230 2231 # Removing the Canvas global bindings from our canvas as 2232 # application specific bindings on that tag may interfere with its 2233 # operation here. [SF item #459033] 2234 2235 set bindings [bindtags $path.c] 2236 set pos [lsearch -exact $bindings Canvas] 2237 if {$pos >= 0} { 2238 set bindings [lreplace $bindings $pos $pos] 2239 } 2240 bindtags $path.c $bindings 2241 2242 # Create the arrow button 2243 eval [list ArrowButton::create $path.c.fg] [Widget::subcget $path .c.fg] \ 2244 [list -highlightthickness 0 -type button -dir left \ 2245 -armcommand [list NoteBook::_xview $path -1]] 2246 2247 eval [list ArrowButton::create $path.c.fd] [Widget::subcget $path .c.fd] \ 2248 [list -highlightthickness 0 -type button -dir right \ 2249 -armcommand [list NoteBook::_xview $path 1]] 2250 2251 Widget::create NoteBook $path 2252 2253 set bg [Widget::cget $path -background] 2254 foreach {data(dbg) data(lbg)} [BWidget::get3dcolor $path $bg] {break} 2255 2256 return $path 2257} 2258 2259proc NoteBook::configure { path args } { 2260 variable $path 2261 upvar 0 $path data 2262 2263 set res [Widget::configure $path $args] 2264 set redraw 0 2265 set opts [list -font -homogeneous -tabpady] 2266 foreach {cf ch cp} [eval Widget::hasChangedX $path $opts] {break} 2267 if {$cf || $ch || $cp} { 2268 if { $cf || $cp } { 2269 _compute_height $path 2270 } 2271 _compute_width $path 2272 set redraw 1 2273 } 2274 set chibd [Widget::hasChanged $path -internalborderwidth ibd] 2275 set chbg [Widget::hasChanged $path -background bg] 2276 if {$chibd || $chbg} { 2277 foreach page $data(pages) { 2278 $path.f$page configure \ 2279 -borderwidth $ibd -background $bg 2280 } 2281 } 2282 2283 if {$chbg} { 2284 set col [BWidget::get3dcolor $path $bg] 2285 set data(dbg) [lindex $col 0] 2286 set data(lbg) [lindex $col 1] 2287 set redraw 1 2288 } 2289 if { [Widget::hasChanged $path -foreground fg] || 2290 [Widget::hasChanged $path -borderwidth bd] || 2291 [Widget::hasChanged $path -arcradius radius] || 2292 [Widget::hasChanged $path -tabbevelsize bevel] || 2293 [Widget::hasChanged $path -side side] } { 2294 set redraw 1 2295 } 2296 set wc [Widget::hasChanged $path -width w] 2297 set hc [Widget::hasChanged $path -height h] 2298 if { $wc || $hc } { 2299 $path.c configure \ 2300 -width [expr {$w + 4}] \ 2301 -height [expr {$h + $data(hpage) + 4}] 2302 } 2303 if { $redraw } { 2304 _redraw $path 2305 } 2306 2307 return $res 2308} 2309 2310proc NoteBook::cget { path option } { 2311 return [Widget::cget $path $option] 2312} 2313 2314proc NoteBook::compute_size { path } { 2315 variable $path 2316 upvar 0 $path data 2317 2318 set wmax 0 2319 set hmax 0 2320 update idletasks 2321 foreach page $data(pages) { 2322 set w [winfo reqwidth $path.f$page] 2323 set h [winfo reqheight $path.f$page] 2324 set wmax [expr {$w>$wmax ? $w : $wmax}] 2325 set hmax [expr {$h>$hmax ? $h : $hmax}] 2326 } 2327 configure $path -width $wmax -height $hmax 2328 # Sven... well ok so this is called twice in some cases... 2329 NoteBook::_redraw $path 2330 # Sven end 2331} 2332 2333proc NoteBook::insert { path index page args } { 2334 variable $path 2335 upvar 0 $path data 2336 2337 if { [lsearch -exact $data(pages) $page] != -1 } { 2338 return -code error "page \"$page\" already exists" 2339 } 2340 2341 set f $path.f$page 2342 Widget::init NoteBook::Page $f $args 2343 2344 set data(pages) [linsert $data(pages) $index $page] 2345 # If the page doesn't exist, create it; if it does reset its bg and ibd 2346 if { ![winfo exists $f] } { 2347 frame $f \ 2348 -relief flat \ 2349 -background [Widget::cget $path -background] \ 2350 -borderwidth [Widget::cget $path -internalborderwidth] 2351 set data($page,realized) 0 2352 } else { 2353 $f configure \ 2354 -background [Widget::cget $path -background] \ 2355 -borderwidth [Widget::cget $path -internalborderwidth] 2356 } 2357 _compute_height $path 2358 _compute_width $path 2359 _draw_page $path $page 1 2360 _redraw $path 2361 2362 return $f 2363} 2364 2365proc NoteBook::delete { path page {destroyframe 1} } { 2366 variable $path 2367 upvar 0 $path data 2368 2369 set pos [_test_page $path $page] 2370 set data(pages) [lreplace $data(pages) $pos $pos] 2371 _compute_width $path 2372 $path.c delete p:$page 2373 if { $data(select) == $page } { 2374 set data(select) "" 2375 } 2376 if { $pos < $data(base) } { 2377 incr data(base) -1 2378 } 2379 if { $destroyframe } { 2380 destroy $path.f$page 2381 unset data($page,width) data($page,realized) 2382 } 2383 _redraw $path 2384} 2385 2386proc NoteBook::itemconfigure { path page args } { 2387 _test_page $path $page 2388 set res [_itemconfigure $path $page $args] 2389 _redraw $path 2390 2391 return $res 2392} 2393 2394proc NoteBook::itemcget { path page option } { 2395 _test_page $path $page 2396 return [Widget::cget $path.f$page $option] 2397} 2398 2399proc NoteBook::bindtabs { path event script } { 2400 if { $script != "" } { 2401 append script " \[NoteBook::_get_page_name [list $path] current 1\]" 2402 $path.c bind "page" $event $script 2403 } else { 2404 $path.c bind "page" $event {} 2405 } 2406} 2407 2408proc NoteBook::move { path page index } { 2409 variable $path 2410 upvar 0 $path data 2411 2412 set pos [_test_page $path $page] 2413 set data(pages) [linsert [lreplace $data(pages) $pos $pos] $index $page] 2414 _redraw $path 2415} 2416 2417proc NoteBook::raise { path {page ""} } { 2418 variable $path 2419 upvar 0 $path data 2420 2421 if { $page != "" } { 2422 _test_page $path $page 2423 _select $path $page 2424 } 2425 return $data(select) 2426} 2427 2428proc NoteBook::see { path page } { 2429 variable $path 2430 upvar 0 $path data 2431 2432 set pos [_test_page $path $page] 2433 if { $pos < $data(base) } { 2434 set data(base) $pos 2435 _redraw $path 2436 } else { 2437 set w [expr {[winfo width $path]-1}] 2438 set fpage [expr {[_get_x_page $path $pos] + $data($page,width) + 6}] 2439 set idx $data(base) 2440 while { $idx < $pos && $fpage > $w } { 2441 set fpage [expr {$fpage - $data([lindex $data(pages) $idx],width)}] 2442 incr idx 2443 } 2444 if { $idx != $data(base) } { 2445 set data(base) $idx 2446 _redraw $path 2447 } 2448 } 2449} 2450 2451proc NoteBook::page { path first {last ""} } { 2452 variable $path 2453 upvar 0 $path data 2454 2455 if { $last == "" } { 2456 return [lindex $data(pages) $first] 2457 } else { 2458 return [lrange $data(pages) $first $last] 2459 } 2460} 2461 2462proc NoteBook::pages { path {first ""} {last ""}} { 2463 variable $path 2464 upvar 0 $path data 2465 2466 if { ![string length $first] } { 2467 return $data(pages) 2468 } 2469 2470 if { ![string length $last] } { 2471 return [lindex $data(pages) $first] 2472 } else { 2473 return [lrange $data(pages) $first $last] 2474 } 2475} 2476 2477proc NoteBook::index { path page } { 2478 variable $path 2479 upvar 0 $path data 2480 2481 return [lsearch -exact $data(pages) $page] 2482} 2483 2484proc NoteBook::_destroy { path } { 2485 variable $path 2486 upvar 0 $path data 2487 2488 foreach page $data(pages) { 2489 Widget::destroy $path.f$page 2490 } 2491 Widget::destroy $path 2492 unset data 2493} 2494 2495proc NoteBook::getframe { path page } { 2496 return $path.f$page 2497} 2498 2499proc NoteBook::_test_page { path page } { 2500 variable $path 2501 upvar 0 $path data 2502 2503 if { [set pos [lsearch -exact $data(pages) $page]] == -1 } { 2504 return -code error "page \"$page\" does not exists" 2505 } 2506 return $pos 2507} 2508 2509proc NoteBook::_getoption { path page option } { 2510 set value [Widget::cget $path.f$page $option] 2511 if {![string length $value]} { 2512 set value [Widget::cget $path $option] 2513 } 2514 return $value 2515} 2516 2517proc NoteBook::_itemconfigure { path page lres } { 2518 variable $path 2519 upvar 0 $path data 2520 2521 set res [Widget::configure $path.f$page $lres] 2522 if { [Widget::hasChanged $path.f$page -text foo] } { 2523 _compute_width $path 2524 } elseif { [Widget::hasChanged $path.f$page -image foo] } { 2525 _compute_height $path 2526 _compute_width $path 2527 } 2528 if { [Widget::hasChanged $path.f$page -state state] && 2529 $state == "disabled" && $data(select) == $page } { 2530 set data(select) "" 2531 } 2532 return $res 2533} 2534 2535proc NoteBook::_compute_width { path } { 2536 variable $path 2537 upvar 0 $path data 2538 2539 set wmax 0 2540 set wtot 0 2541 set hmax $data(hpage) 2542 set font [Widget::cget $path -font] 2543 if { ![info exists data(textid)] } { 2544 set data(textid) [$path.c create text 0 -100 -font $font -anchor nw] 2545 } 2546 set id $data(textid) 2547 $path.c itemconfigure $id -font $font 2548 foreach page $data(pages) { 2549 $path.c itemconfigure $id -text [Widget::cget $path.f$page -text] 2550 # Get the bbox for this text to determine its width, then substract 2551 # 6 from the width to account for canvas bbox oddness w.r.t. widths of 2552 # simple text. 2553 foreach {x1 y1 x2 y2} [$path.c bbox $id] break 2554 set x2 [expr {$x2 - 6}] 2555 set wtext [expr {$x2 - $x1 + 20}] 2556 if { [set img [Widget::cget $path.f$page -image]] != "" } { 2557 set wtext [expr {$wtext + [image width $img] + 4}] 2558 set himg [expr {[image height $img] + 6}] 2559 if { $himg > $hmax } { 2560 set hmax $himg 2561 } 2562 } 2563 set wmax [expr {$wtext > $wmax ? $wtext : $wmax}] 2564 incr wtot $wtext 2565 set data($page,width) $wtext 2566 } 2567 if { [Widget::cget $path -homogeneous] } { 2568 foreach page $data(pages) { 2569 set data($page,width) $wmax 2570 } 2571 set wtot [expr {$wmax * [llength $data(pages)]}] 2572 } 2573 set data(hpage) $hmax 2574 set data(wpage) $wtot 2575} 2576 2577proc NoteBook::_compute_height { path } { 2578 variable $path 2579 upvar 0 $path data 2580 2581 set font [Widget::cget $path -font] 2582 set pady0 [Widget::_get_padding $path -tabpady 0] 2583 set pady1 [Widget::_get_padding $path -tabpady 1] 2584 set metrics [font metrics $font -linespace] 2585 set imgh 0 2586 set lines 1 2587 foreach page $data(pages) { 2588 set img [Widget::cget $path.f$page -image] 2589 set text [Widget::cget $path.f$page -text] 2590 set len [llength [split $text \n]] 2591 if {$len > $lines} { set lines $len} 2592 if {$img != ""} { 2593 set h [image height $img] 2594 if {$h > $imgh} { set imgh $h } 2595 } 2596 } 2597 set height [expr {$metrics * $lines}] 2598 if {$imgh > $height} { set height $imgh } 2599 set data(hpage) [expr {$height + $pady0 + $pady1}] 2600} 2601 2602proc NoteBook::_get_x_page { path pos } { 2603 variable _warrow 2604 variable $path 2605 upvar 0 $path data 2606 2607 set base $data(base) 2608 # notebook tabs start flush with the left side of the notebook 2609 set x 0 2610 if { $pos < $base } { 2611 foreach page [lrange $data(pages) $pos [expr {$base-1}]] { 2612 incr x [expr {-$data($page,width)}] 2613 } 2614 } elseif { $pos > $base } { 2615 foreach page [lrange $data(pages) $base [expr {$pos-1}]] { 2616 incr x $data($page,width) 2617 } 2618 } 2619 return $x 2620} 2621 2622proc NoteBook::_xview { path inc } { 2623 variable $path 2624 upvar 0 $path data 2625 2626 if { $inc == -1 } { 2627 set base [expr {$data(base)-1}] 2628 set dx $data([lindex $data(pages) $base],width) 2629 } else { 2630 set dx [expr {-$data([lindex $data(pages) $data(base)],width)}] 2631 set base [expr {$data(base)+1}] 2632 } 2633 2634 if { $base >= 0 && $base < [llength $data(pages)] } { 2635 set data(base) $base 2636 $path.c move page $dx 0 2637 _draw_area $path 2638 _draw_arrows $path 2639 } 2640} 2641 2642proc NoteBook::_highlight { type path page } { 2643 variable $path 2644 upvar 0 $path data 2645 2646 if { [string equal [Widget::cget $path.f$page -state] "disabled"] } { 2647 return 2648 } 2649 2650 switch -- $type { 2651 on { 2652 $path.c itemconfigure "$page:poly" \ 2653 -fill [_getoption $path $page -activebackground] 2654 $path.c itemconfigure "$page:text" \ 2655 -fill [_getoption $path $page -activeforeground] 2656 } 2657 off { 2658 $path.c itemconfigure "$page:poly" \ 2659 -fill [_getoption $path $page -background] 2660 $path.c itemconfigure "$page:text" \ 2661 -fill [_getoption $path $page -foreground] 2662 } 2663 } 2664} 2665 2666proc NoteBook::_select { path page } { 2667 variable $path 2668 upvar 0 $path data 2669 2670 if {![string equal [Widget::cget $path.f$page -state] "normal"]} { return } 2671 2672 set oldsel $data(select) 2673 2674 if {[string equal $page $oldsel]} { return } 2675 2676 if { ![string equal $oldsel ""] } { 2677 set cmd [Widget::cget $path.f$oldsel -leavecmd] 2678 if { ![string equal $cmd ""] } { 2679 set code [catch {uplevel \#0 $cmd} res] 2680 if { $code == 1 || $res == 0 } { 2681 return -code $code $res 2682 } 2683 } 2684 set data(select) "" 2685 _draw_page $path $oldsel 0 2686 } 2687 2688 set data(select) $page 2689 if { ![string equal $page ""] } { 2690 if { !$data($page,realized) } { 2691 set data($page,realized) 1 2692 set cmd [Widget::cget $path.f$page -createcmd] 2693 if { ![string equal $cmd ""] } { 2694 uplevel \#0 $cmd 2695 } 2696 } 2697 set cmd [Widget::cget $path.f$page -raisecmd] 2698 if { ![string equal $cmd ""] } { 2699 uplevel \#0 $cmd 2700 } 2701 _draw_page $path $page 0 2702 } 2703 2704 _draw_area $path 2705} 2706 2707proc NoteBook::_redraw { path } { 2708 variable $path 2709 upvar 0 $path data 2710 2711 if { !$data(realized) } { return } 2712 2713 _compute_height $path 2714 2715 foreach page $data(pages) { 2716 _draw_page $path $page 0 2717 } 2718 _draw_area $path 2719 _draw_arrows $path 2720} 2721 2722proc NoteBook::_draw_page { path page create } { 2723 variable $path 2724 upvar 0 $path data 2725 2726 # --- calcul des coordonnees et des couleurs de l'onglet ------------------ 2727 set pos [lsearch -exact $data(pages) $page] 2728 set bg [_getoption $path $page -background] 2729 2730 # lookup the tab colors 2731 set fgt $data(lbg) 2732 set fgb $data(dbg) 2733 2734 set h $data(hpage) 2735 set xd [_get_x_page $path $pos] 2736 set xf [expr {$xd + $data($page,width)}] 2737 2738 # Set the initial text offsets -- a few pixels down, centered left-to-right 2739 set textOffsetY [expr [Widget::_get_padding $path -tabpady 0] + 3] 2740 set textOffsetX 9 2741 2742 set top 2 2743 set arcRadius [Widget::cget $path -arcradius] 2744 set xBevel [Widget::cget $path -tabbevelsize] 2745 2746 if { $data(select) != $page } { 2747 if { $pos == 0 } { 2748 # The leftmost page is a special case -- it is drawn with its 2749 # tab a little indented. To achieve this, we incr xd. We also 2750 # decr textOffsetX, so that the text doesn't move left/right. 2751 incr xd 2 2752 incr textOffsetX -2 2753 } 2754 } else { 2755 # The selected page's text is raised higher than the others 2756 incr top -2 2757 } 2758 2759 # Precompute some coord values that we use a lot 2760 set topPlusRadius [expr {$top + $arcRadius}] 2761 set rightPlusRadius [expr {$xf + $arcRadius}] 2762 set leftPlusRadius [expr {$xd + $arcRadius}] 2763 2764 # Sven 2765 set side [Widget::cget $path -side] 2766 set tabsOnBottom [string equal $side "bottom"] 2767 2768 set h1 [expr {[winfo height $path]}] 2769 set bd [Widget::cget $path -borderwidth] 2770 if {$bd < 1} { set bd 1 } 2771 2772 if { $tabsOnBottom } { 2773 # adjust to keep bottom edge in view 2774 incr h1 -1 2775 set top [expr {$top * -1}] 2776 set topPlusRadius [expr {$topPlusRadius * -1}] 2777 # Hrm... the canvas has an issue with drawing diagonal segments 2778 # of lines from the bottom to the top, so we have to draw this line 2779 # backwards (ie, lt is actually the bottom, drawn from right to left) 2780 set lt [list \ 2781 $rightPlusRadius [expr {$h1-$h-1}] \ 2782 [expr {$rightPlusRadius - $xBevel}] [expr {$h1 + $topPlusRadius}] \ 2783 [expr {$xf - $xBevel}] [expr {$h1 + $top}] \ 2784 [expr {$leftPlusRadius + $xBevel}] [expr {$h1 + $top}] \ 2785 ] 2786 set lb [list \ 2787 [expr {$leftPlusRadius + $xBevel}] [expr {$h1 + $top}] \ 2788 [expr {$xd + $xBevel}] [expr {$h1 + $topPlusRadius}] \ 2789 $xd [expr {$h1-$h-1}] \ 2790 ] 2791 # Because we have to do this funky reverse order thing, we have to 2792 # swap the top/bottom colors too. 2793 set tmp $fgt 2794 set fgt $fgb 2795 set fgb $tmp 2796 } else { 2797 set lt [list \ 2798 $xd $h \ 2799 [expr {$xd + $xBevel}] $topPlusRadius \ 2800 [expr {$leftPlusRadius + $xBevel}] $top \ 2801 [expr {$xf + 1 - $xBevel}] $top \ 2802 ] 2803 set lb [list \ 2804 [expr {$xf + 1 - $xBevel}] [expr {$top + 1}] \ 2805 [expr {$rightPlusRadius - $xBevel}] $topPlusRadius \ 2806 $rightPlusRadius $h \ 2807 ] 2808 } 2809 2810 set img [Widget::cget $path.f$page -image] 2811 2812 set ytext $top 2813 if { $tabsOnBottom } { 2814 # The "+ 2" below moves the text closer to the bottom of the tab, 2815 # so it doesn't look so cramped. I should be able to achieve the 2816 # same goal by changing the anchor of the text and using this formula: 2817 # ytext = $top + $h1 - $textOffsetY 2818 # but that doesn't quite work (I think the linespace from the text 2819 # gets in the way) 2820 incr ytext [expr {$h1 - $h + 2}] 2821 } 2822 incr ytext $textOffsetY 2823 2824 set xtext [expr {$xd + $textOffsetX}] 2825 if { $img != "" } { 2826 # if there's an image, put it on the left and move the text right 2827 set ximg $xtext 2828 incr xtext [expr {[image width $img] + 2}] 2829 } 2830 2831 if { $data(select) == $page } { 2832 set bd [Widget::cget $path -borderwidth] 2833 if {$bd < 1} { set bd 1 } 2834 set fg [_getoption $path $page -foreground] 2835 } else { 2836 set bd 1 2837 if { [Widget::cget $path.f$page -state] == "normal" } { 2838 set fg [_getoption $path $page -foreground] 2839 } else { 2840 set fg [_getoption $path $page -disabledforeground] 2841 } 2842 } 2843 2844 # --- creation ou modification de l'onglet -------------------------------- 2845 # Sven 2846 if { $create } { 2847 # Create the tab region 2848 eval [list $path.c create polygon] [concat $lt $lb] [list \ 2849 -tags [list page p:$page $page:poly] \ 2850 -outline $bg \ 2851 -fill $bg \ 2852 ] 2853 eval [list $path.c create line] $lt [list \ 2854 -tags [list page p:$page $page:top top] -fill $fgt -width $bd] 2855 eval [list $path.c create line] $lb [list \ 2856 -tags [list page p:$page $page:bot bot] -fill $fgb -width $bd] 2857 $path.c create text $xtext $ytext \ 2858 -text [Widget::cget $path.f$page -text] \ 2859 -font [Widget::cget $path -font] \ 2860 -fill $fg \ 2861 -anchor nw \ 2862 -tags [list page p:$page $page:text] 2863 2864 $path.c bind p:$page <ButtonPress-1> \ 2865 [list NoteBook::_select $path $page] 2866 $path.c bind p:$page <Enter> \ 2867 [list NoteBook::_highlight on $path $page] 2868 $path.c bind p:$page <Leave> \ 2869 [list NoteBook::_highlight off $path $page] 2870 } else { 2871 $path.c coords "$page:text" $xtext $ytext 2872 2873 $path.c itemconfigure "$page:text" \ 2874 -text [Widget::cget $path.f$page -text] \ 2875 -font [Widget::cget $path -font] \ 2876 -fill $fg 2877 } 2878 eval [list $path.c coords "$page:poly"] [concat $lt $lb] 2879 eval [list $path.c coords "$page:top"] $lt 2880 eval [list $path.c coords "$page:bot"] $lb 2881 $path.c itemconfigure "$page:poly" -fill $bg -outline $bg 2882 $path.c itemconfigure "$page:top" -fill $fgt -width $bd 2883 $path.c itemconfigure "$page:bot" -fill $fgb -width $bd 2884 2885 # Sven end 2886 2887 if { $img != "" } { 2888 # Sven 2889 set id [$path.c find withtag $page:img] 2890 if { [string equal $id ""] } { 2891 set id [$path.c create image $ximg $ytext \ 2892 -anchor nw \ 2893 -tags [list page p:$page $page:img]] 2894 } 2895 $path.c coords $id $ximg $ytext 2896 $path.c itemconfigure $id -image $img 2897 # Sven end 2898 } else { 2899 $path.c delete $page:img 2900 } 2901 2902 if { $data(select) == $page } { 2903 $path.c raise p:$page 2904 } elseif { $pos == 0 } { 2905 if { $data(select) == "" } { 2906 $path.c raise p:$page 2907 } else { 2908 $path.c lower p:$page p:$data(select) 2909 } 2910 } else { 2911 set pred [lindex $data(pages) [expr {$pos-1}]] 2912 if { $data(select) != $pred || $pos == 1 } { 2913 $path.c lower p:$page p:$pred 2914 } else { 2915 $path.c lower p:$page p:[lindex $data(pages) [expr {$pos-2}]] 2916 } 2917 } 2918} 2919 2920proc NoteBook::_draw_arrows { path } { 2921 variable _warrow 2922 variable $path 2923 upvar 0 $path data 2924 2925 set w [expr {[winfo width $path]-1}] 2926 set h [expr {$data(hpage)-1}] 2927 set nbpages [llength $data(pages)] 2928 set xl 0 2929 set xr [expr {$w-$_warrow+1}] 2930 2931 set side [Widget::cget $path -side] 2932 if { [string equal $side "bottom"] } { 2933 set h1 [expr {[winfo height $path]-1}] 2934 set bd [Widget::cget $path -borderwidth] 2935 if {$bd < 1} { set bd 1 } 2936 set y0 [expr {$h1 - $data(hpage) + $bd}] 2937 } else { 2938 set y0 1 2939 } 2940 2941 if { $data(base) > 0 } { 2942 # Sven 2943 if { ![llength [$path.c find withtag "leftarrow"]] } { 2944 $path.c create window $xl $y0 \ 2945 -width $_warrow \ 2946 -height $h \ 2947 -anchor nw \ 2948 -window $path.c.fg \ 2949 -tags "leftarrow" 2950 } else { 2951 $path.c coords "leftarrow" $xl $y0 2952 $path.c itemconfigure "leftarrow" -width $_warrow -height $h 2953 } 2954 # Sven end 2955 } else { 2956 $path.c delete "leftarrow" 2957 } 2958 2959 if { $data(base) < $nbpages-1 && 2960 $data(wpage) + [_get_x_page $path 0] + 6 > $w } { 2961 # Sven 2962 if { ![llength [$path.c find withtag "rightarrow"]] } { 2963 $path.c create window $xr $y0 \ 2964 -width $_warrow \ 2965 -height $h \ 2966 -window $path.c.fd \ 2967 -anchor nw \ 2968 -tags "rightarrow" 2969 } else { 2970 $path.c coords "rightarrow" $xr $y0 2971 $path.c itemconfigure "rightarrow" -width $_warrow -height $h 2972 } 2973 # Sven end 2974 } else { 2975 $path.c delete "rightarrow" 2976 } 2977} 2978 2979proc NoteBook::_draw_area { path } { 2980 variable $path 2981 upvar 0 $path data 2982 2983 set w [expr {[winfo width $path] - 1}] 2984 set h [expr {[winfo height $path] - 1}] 2985 set bd [Widget::cget $path -borderwidth] 2986 if {$bd < 1} { set bd 1 } 2987 set x0 [expr {$bd - 1}] 2988 2989 set arcRadius [Widget::cget $path -arcradius] 2990 2991 # Sven 2992 set side [Widget::cget $path -side] 2993 if {"$side" == "bottom"} { 2994 set y0 0 2995 set y1 [expr {$h - $data(hpage)}] 2996 set yo $y1 2997 } else { 2998 set y0 $data(hpage) 2999 set y1 $h 3000 set yo [expr {$h-$y0}] 3001 } 3002 # Sven end 3003 set dbg $data(dbg) 3004 set sel $data(select) 3005 if { $sel == "" } { 3006 set xd [expr {$w/2}] 3007 set xf $xd 3008 set lbg $data(dbg) 3009 } else { 3010 set xd [_get_x_page $path [lsearch -exact $data(pages) $data(select)]] 3011 set xf [expr {$xd + $data($sel,width) + $arcRadius + 1}] 3012 set lbg $data(lbg) 3013 } 3014 3015 # Sven 3016 if { [llength [$path.c find withtag rect]] == 0} { 3017 $path.c create line $xd $y0 $x0 $y0 $x0 $y1 \ 3018 -tags "rect toprect1" 3019 $path.c create line $w $y0 $xf $y0 \ 3020 -tags "rect toprect2" 3021 $path.c create line 1 $h $w $h $w $y0 \ 3022 -tags "rect botrect" 3023 } 3024 if {"$side" == "bottom"} { 3025 $path.c coords "toprect1" $w $y0 $x0 $y0 $x0 $y1 3026 $path.c coords "toprect2" $x0 $y1 $xd $y1 3027 $path.c coords "botrect" $xf $y1 $w $y1 $w $y0 3028 $path.c itemconfigure "toprect1" -fill $lbg -width $bd 3029 $path.c itemconfigure "toprect2" -fill $dbg -width $bd 3030 $path.c itemconfigure "botrect" -fill $dbg -width $bd 3031 } else { 3032 $path.c coords "toprect1" $xd $y0 $x0 $y0 $x0 $y1 3033 $path.c coords "toprect2" $w $y0 $xf $y0 3034 $path.c coords "botrect" $x0 $h $w $h $w $y0 3035 $path.c itemconfigure "toprect1" -fill $lbg -width $bd 3036 $path.c itemconfigure "toprect2" -fill $lbg -width $bd 3037 $path.c itemconfigure "botrect" -fill $dbg -width $bd 3038 } 3039 $path.c raise "rect" 3040 # Sven end 3041 3042 if { $sel != "" } { 3043 # Sven 3044 if { [llength [$path.c find withtag "window"]] == 0 } { 3045 $path.c create window 2 [expr {$y0+1}] \ 3046 -width [expr {$w-3}] \ 3047 -height [expr {$yo-3}] \ 3048 -anchor nw \ 3049 -tags "window" \ 3050 -window $path.f$sel 3051 } 3052 $path.c coords "window" 2 [expr {$y0+1}] 3053 $path.c itemconfigure "window" \ 3054 -width [expr {$w-3}] \ 3055 -height [expr {$yo-3}] \ 3056 -window $path.f$sel 3057 # Sven end 3058 } else { 3059 $path.c delete "window" 3060 } 3061} 3062 3063proc NoteBook::_resize { path } { 3064 variable $path 3065 upvar 0 $path data 3066 3067 if {!$data(realized)} { 3068 if { [set width [Widget::cget $path -width]] == 0 || 3069 [set height [Widget::cget $path -height]] == 0 } { 3070 compute_size $path 3071 } 3072 set data(realized) 1 3073 } 3074 3075 NoteBook::_redraw $path 3076} 3077 3078proc NoteBook::_get_page_name { path {item current} {tagindex end-1} } { 3079 return [string range [lindex [$path.c gettags $item] $tagindex] 2 end] 3080} 3081# ----------------------------------------------------------------------------- 3082# scrollw.tcl -- part of Unifix BWidget Toolkit 3083# ----------------------------------------------------------------------------- 3084 3085namespace eval ScrolledWindow { 3086 Widget::define ScrolledWindow scrollw 3087 3088 Widget::declare ScrolledWindow { 3089 {-background TkResource "" 0 button} 3090 {-scrollbar Enum both 0 {none both vertical horizontal}} 3091 {-auto Enum both 0 {none both vertical horizontal}} 3092 {-sides Enum se 0 {ne en nw wn se es sw ws}} 3093 {-size Int 0 1 "%d >= 0"} 3094 {-ipad Int 1 1 "%d >= 0"} 3095 {-managed Boolean 1 1} 3096 {-relief TkResource flat 0 frame} 3097 {-borderwidth TkResource 0 0 frame} 3098 {-bg Synonym -background} 3099 {-bd Synonym -borderwidth} 3100 } 3101 3102 Widget::addmap ScrolledWindow "" :cmd {-relief {} -borderwidth {}} 3103} 3104 3105proc ScrolledWindow::create { path args } { 3106 Widget::init ScrolledWindow $path $args 3107 3108 Widget::getVariable $path data 3109 3110 set bg [Widget::cget $path -background] 3111 set sbsize [Widget::cget $path -size] 3112 set sw [eval [list frame $path \ 3113 -relief flat -borderwidth 0 -background $bg \ 3114 -highlightthickness 0 -takefocus 0] \ 3115 [Widget::subcget $path :cmd]] 3116 3117 scrollbar $path.hscroll \ 3118 -highlightthickness 0 -takefocus 0 \ 3119 -orient horiz \ 3120 -relief sunken \ 3121 -bg $bg 3122 scrollbar $path.vscroll \ 3123 -highlightthickness 0 -takefocus 0 \ 3124 -orient vert \ 3125 -relief sunken \ 3126 -bg $bg 3127 3128 set data(realized) 0 3129 3130 _setData $path \ 3131 [Widget::cget $path -scrollbar] \ 3132 [Widget::cget $path -auto] \ 3133 [Widget::cget $path -sides] 3134 3135 if {[Widget::cget $path -managed]} { 3136 set data(hsb,packed) $data(hsb,present) 3137 set data(vsb,packed) $data(vsb,present) 3138 } else { 3139 set data(hsb,packed) 0 3140 set data(vsb,packed) 0 3141 } 3142 if {$sbsize} { 3143 $path.vscroll configure -width $sbsize 3144 $path.hscroll configure -width $sbsize 3145 } else { 3146 set sbsize [$path.vscroll cget -width] 3147 } 3148 set data(ipad) [Widget::cget $path -ipad] 3149 3150 if {$data(hsb,packed)} { 3151 grid $path.hscroll -column 1 -row $data(hsb,row) \ 3152 -sticky ew -ipady $data(ipad) 3153 } 3154 if {$data(vsb,packed)} { 3155 grid $path.vscroll -column $data(vsb,column) -row 1 \ 3156 -sticky ns -ipadx $data(ipad) 3157 } 3158 3159 grid columnconfigure $path 1 -weight 1 3160 grid rowconfigure $path 1 -weight 1 3161 3162 bind $path <Configure> [list ScrolledWindow::_realize $path] 3163 bind $path <Destroy> [list ScrolledWindow::_destroy $path] 3164 3165 return [Widget::create ScrolledWindow $path] 3166} 3167 3168proc ScrolledWindow::getframe { path } { 3169 return $path 3170} 3171 3172proc ScrolledWindow::setwidget { path widget } { 3173 Widget::getVariable $path data 3174 3175 if {[info exists data(widget)] && [winfo exists $data(widget)] 3176 && ![string equal $data(widget) $widget]} { 3177 grid remove $data(widget) 3178 $data(widget) configure -xscrollcommand "" -yscrollcommand "" 3179 } 3180 set data(widget) $widget 3181 grid $widget -in $path -row 1 -column 1 -sticky news 3182 3183 $path.hscroll configure -command [list $widget xview] 3184 $path.vscroll configure -command [list $widget yview] 3185 $widget configure \ 3186 -xscrollcommand [list ScrolledWindow::_set_hscroll $path] \ 3187 -yscrollcommand [list ScrolledWindow::_set_vscroll $path] 3188} 3189 3190proc ScrolledWindow::configure { path args } { 3191 Widget::getVariable $path data 3192 3193 set res [Widget::configure $path $args] 3194 if { [Widget::hasChanged $path -background bg] } { 3195 $path configure -background $bg 3196 catch {$path.hscroll configure -background $bg} 3197 catch {$path.vscroll configure -background $bg} 3198 } 3199 3200 if {[Widget::hasChanged $path -scrollbar scrollbar] | \ 3201 [Widget::hasChanged $path -auto auto] | \ 3202 [Widget::hasChanged $path -sides sides]} { 3203 _setData $path $scrollbar $auto $sides 3204 foreach {vmin vmax} [$path.hscroll get] { break } 3205 set data(hsb,packed) [expr {$data(hsb,present) && \ 3206 (!$data(hsb,auto) || ($vmin != 0 || $vmax != 1))}] 3207 foreach {vmin vmax} [$path.vscroll get] { break } 3208 set data(vsb,packed) [expr {$data(vsb,present) && \ 3209 (!$data(vsb,auto) || ($vmin != 0 || $vmax != 1))}] 3210 3211 set data(ipad) [Widget::cget $path -ipad] 3212 3213 if {$data(hsb,packed)} { 3214 grid $path.hscroll -column 1 -row $data(hsb,row) \ 3215 -sticky ew -ipady $data(ipad) 3216 } else { 3217 if {![info exists data(hlock)]} { 3218 set data(hsb,packed) 0 3219 grid remove $path.hscroll 3220 } 3221 } 3222 if {$data(vsb,packed)} { 3223 grid $path.vscroll -column $data(vsb,column) -row 1 \ 3224 -sticky ns -ipadx $data(ipad) 3225 } else { 3226 if {![info exists data(hlock)]} { 3227 set data(vsb,packed) 0 3228 grid remove $path.vscroll 3229 } 3230 } 3231 } 3232 return $res 3233} 3234 3235proc ScrolledWindow::cget { path option } { 3236 return [Widget::cget $path $option] 3237} 3238 3239proc ScrolledWindow::_set_hscroll { path vmin vmax } { 3240 Widget::getVariable $path data 3241 3242 if {$data(realized) && $data(hsb,present)} { 3243 if {$data(hsb,auto) && ![info exists data(hlock)]} { 3244 if {$data(hsb,packed) && $vmin == 0 && $vmax == 1} { 3245 set data(hsb,packed) 0 3246 grid remove $path.hscroll 3247 set data(hlock) 1 3248 update idletasks 3249 unset data(hlock) 3250 } elseif {!$data(hsb,packed) && ($vmin != 0 || $vmax != 1)} { 3251 set data(hsb,packed) 1 3252 grid $path.hscroll -column 1 -row $data(hsb,row) \ 3253 -sticky ew -ipady $data(ipad) 3254 set data(hlock) 1 3255 update idletasks 3256 unset data(hlock) 3257 } 3258 } 3259 $path.hscroll set $vmin $vmax 3260 } 3261} 3262 3263proc ScrolledWindow::_set_vscroll { path vmin vmax } { 3264 Widget::getVariable $path data 3265 3266 if {$data(realized) && $data(vsb,present)} { 3267 if {$data(vsb,auto) && ![info exists data(vlock)]} { 3268 if {$data(vsb,packed) && $vmin == 0 && $vmax == 1} { 3269 set data(vsb,packed) 0 3270 grid remove $path.vscroll 3271 set data(vlock) 1 3272 update idletasks 3273 unset data(vlock) 3274 } elseif {!$data(vsb,packed) && ($vmin != 0 || $vmax != 1) } { 3275 set data(vsb,packed) 1 3276 grid $path.vscroll -column $data(vsb,column) -row 1 \ 3277 -sticky ns -ipadx $data(ipad) 3278 set data(vlock) 1 3279 update idletasks 3280 unset data(vlock) 3281 } 3282 } 3283 $path.vscroll set $vmin $vmax 3284 } 3285} 3286 3287proc ScrolledWindow::_setData {path scrollbar auto sides} { 3288 Widget::getVariable $path data 3289 3290 set sb [lsearch {none horizontal vertical both} $scrollbar] 3291 set auto [lsearch {none horizontal vertical both} $auto] 3292 3293 set data(hsb,present) [expr {($sb & 1) != 0}] 3294 set data(hsb,auto) [expr {($auto & 1) != 0}] 3295 set data(hsb,row) [expr {[string match *n* $sides] ? 0 : 2}] 3296 3297 set data(vsb,present) [expr {($sb & 2) != 0}] 3298 set data(vsb,auto) [expr {($auto & 2) != 0}] 3299 set data(vsb,column) [expr {[string match *w* $sides] ? 0 : 2}] 3300} 3301 3302proc ScrolledWindow::_realize { path } { 3303 Widget::getVariable $path data 3304 3305 bind $path <Configure> {} 3306 set data(realized) 1 3307} 3308 3309proc ScrolledWindow::_destroy { path } { 3310 Widget::destroy $path 3311} 3312 3313############ end of BWidget code ############## 3314############ iSpin GUI specific code: ######### 3315 3316set Fname "" 3317set Sname "ispin_session" 3318set lno 1 3319set Curp Mp 3320 3321set s_typ 0 3322set seed 123 3323set skipstep 0 3324set ubstep 10000 3325set l_typ 0 3326 3327set stop 0 3328set step 0 3329set maxn 0 3330set curn 0 3331set lno 0 3332set cnt 1 3333set msc_full 0 3334set negate_ltl 0 3335set var_vals 1 3336 3337set vo 0 ;# verification output 3338set vr 0 ;# verification reference 3339 3340set msc_x 75 3341set msc_y 20 3342set msc_w 75 3343set msc_h 20 3344set msc_max_x $msc_x 3345set msc_delay 25 ;# milliseconds update delay 3346set msc_max_w 20 3347 3348set Varnm() 0 3349set VarStep() 0 3350set Levels() 0 3351set LineNo() 0 3352set MSC_Y() 0 3353set LineTouched() 0 3354 3355set sym_pan "" 3356set note_pan "" 3357set nvr_pan "" 3358set log_pan "" 3359 3360set bet(0) "Physical Memory Available (in Mbytes): " 3361set ival(0) 1024 3362set expl(0) "explain" 3363 3364set bet(1) "Estimated State Space Size (states x 10^3): " 3365set ival(1) 1000 3366set expl(1) "explain" 3367 3368set bet(2) "Maximum Search Depth (steps): " 3369set ival(2) 10000 3370set expl(2) "explain" 3371 3372set bet(3) "Nr of hash-functions in Bitstate mode: " 3373set ival(3) 3 3374set expl(3) "explain" 3375 3376set bet(4) "Size for Minimized Automaton" 3377set ival(4) 100 3378set expl(4) "explain" 3379 3380set bet(5) "Extra Verifier Generation Options: " 3381set ival(5) "" 3382set expl(5) "explain" 3383 3384set bet(6) "Extra Compile-Time Directives: " 3385set ival(6) "-O2" 3386set expl(6) "explain" 3387 3388set bet(7) "Extra Run-Time Options: " 3389set ival(7) "" 3390set expl(7) "explain" 3391 3392set estop 0 3393set s_mode 0 3394set po_mode 1 3395set bf_mode 0 3396set ma_mode 0 3397set cc_mode 0 3398set p_mode 0 3399set c_mode 0 3400set u_mode 1 3401set a_mode 1 3402set x_mode 0 3403set e_mode 1 3404set q_mode 0 3405set f_mode 0 3406set bc_mode 0 3407set it_mode 0 3408set sv_mode 0 3409set vpanel 0 3410set spanel 0 3411 3412set pat "" ;# search pattern 3413 3414set swarm_p(0) "minimum nr of hash functions:" 3415set swarm_i(0) "1" 3416set swarm_p(1) "maximum nr of hash functions:" 3417set swarm_i(1) "5" 3418set swarm_p(2) "minimum search depth:" 3419set swarm_i(2) "100" 3420set swarm_p(3) "maximum search depth:" 3421set swarm_i(3) "10000" 3422set swarm_p(4) "number of local cpu-cores" 3423set swarm_i(4) "4" 3424set swarm_p(5) "list of remote_cpu_name:ncores" 3425set swarm_i(5) "" 3426set swarm_p(6) "maximum memory per run (suffix: M or G)" 3427set swarm_i(6) "512M" 3428set swarm_p(7) "maximum total runtime for swarm (suffix: s, m, h, d)" 3429set swarm_i(7) "60m" 3430 3431set swarm_p(8) "hash-factor" 3432set swarm_i(8) "1.5" 3433set swarm_p(9) "state-vector size in bytes" 3434set swarm_i(9) "512" 3435set swarm_p(10) "exploration speed in states/sec" 3436set swarm_i(10) "250000" 3437 3438set so 0 ;# swarm cfg output 3439set sr 0 ;# swarm run output 3440 3441set o_v 0 3442set o_y 30 3443 3444proc add_frame {fn t} { 3445 global TBG TFG 3446 3447 frame $fn -bg $TBG 3448 label $fn.lbl -text "$t" -bg $TBG -fg $TFG 3449 entry $fn.ent -relief sunken -width 10 3450 3451 pack $fn -side top -fill x -expand yes 3452 pack $fn.lbl -side left -fill x -expand no 3453 pack $fn.ent -side right -fill x -expand no 3454 3455 bind $fn.ent <Return> { run_sim } 3456} 3457 3458proc do_find {} { 3459 global twin pat 3460 3461 $twin tag remove hilite 0.0 end 3462 forAllMatches $twin $pat 3463} 3464 3465proc model_panel {t} { 3466 global clog twin fg CBG CFG HV0 HV1 TBG TFG MFG NFG NBG pat ScrollBarSize Fname 3467global xzx 3468 frame $t.buttons -bg $CBG 3469 button $t.buttons.open -text "Open..." -command "open_spec 1" \ 3470 -bg $NBG -fg white -font $HV0 \ 3471 -activebackground $NFG -activeforeground $NBG 3472 button $t.buttons.ref -text "ReOpen" -command "open_spec 0" \ 3473 -bg $NBG -fg white -font $HV0 \ 3474 -activebackground $NFG -activeforeground $NBG 3475 button $t.buttons.save -text "Save" -command "save_spec 0" \ 3476 -bg $NBG -fg white -font $HV0 \ 3477 -activebackground $NFG -activeforeground $NBG 3478 button $t.buttons.saveas -text "Save As..." -command "save_spec 1" \ 3479 -bg $NBG -fg white -font $HV0 \ 3480 -activebackground $NFG -activeforeground $NBG 3481 button $t.buttons.syntax -text "Syntax Check" -command "runsyntax 0" \ 3482 -bg $NBG -fg $NFG -font $HV0 \ 3483 -activebackground $NFG -activeforeground $NBG 3484 button $t.buttons.slice -text "Redundancy Check" -command "runsyntax 1" \ 3485 -bg $NBG -fg $NFG -font $HV0 \ 3486 -activebackground $NFG -activeforeground $NBG 3487 button $t.buttons.symb -text "Symbol Table" -command "symbol_table" \ 3488 -bg $NBG -fg $NFG -font $HV0 \ 3489 -activebackground $NFG -activeforeground $NBG 3490 button $t.buttons.fnd1 -text "Find:" \ 3491 -command "do_find" \ 3492 -bg $NBG -fg white -font $HV0 \ 3493 -activebackground $NFG -activeforeground $NBG 3494 entry $t.buttons.fnd2 -width 24 -textvariable pat -bg ivory \ 3495 -relief sunken -background $TBG -foreground $TFG 3496 bind $t.buttons.fnd2 <Return> { do_find } 3497 3498 pack $t.buttons -side top -fill x -expand no 3499 3500 pack $t.buttons.open $t.buttons.ref $t.buttons.save \ 3501 $t.buttons.saveas \ 3502 $t.buttons.syntax $t.buttons.slice \ 3503 $t.buttons.symb \ 3504 -side left -fill x -expand no 3505 3506 pack $t.buttons.fnd1 $t.buttons.fnd2 \ 3507 -side left -fill x -expand no 3508 3509 set pw [PanedWindow $t.pw -side left -activator button ] 3510 3511 set p2 [$pw add -minsize 100] 3512 set p1 [$pw add -minsize 20] 3513 3514 set sw11 [ScrolledWindow $p1.sw -size $ScrollBarSize] 3515 set clog [text $sw11.lb -height 15 -width 100 -highlightthickness 3 -bg $CBG -fg $CFG -font $HV1] 3516 $sw11 setwidget $clog 3517 pack $sw11 -fill both -expand yes 3518### 3519 set xx [PanedWindow $p2.wide -side top -activator button ] 3520 set q0 [$xx add -minsize 10] 3521 set q1 [$xx add -minsize 10] 3522 3523 set sw22 [ScrolledWindow $q0.wide -size $ScrollBarSize] 3524 set twin [text $sw22.lb -undo 1 -height 30 -highlightthickness 0 -font $HV1] 3525 $sw22 setwidget $twin 3526 3527 pack $sw22 -side left -fill both -expand yes 3528 3529 $twin insert end "model source $Fname" 3530 $twin edit modified false 3531 3532 global scrollxregion scrollyregion 3533 3534 set cv [ScrolledWindow $q1.wide -size $ScrollBarSize] 3535 set fg [canvas $cv.right -relief raised \ 3536 -background $NBG -scrollregion "0 0 $scrollxregion $scrollyregion" ] 3537set xzx $fg 3538 $cv setwidget $fg 3539 3540 frame $q1.ctl -bg $NBG 3541 3542 button $q1.ctl.mkg -text "Automata View" -command "mk_graphs" \ 3543 -bg $NBG -fg $NFG -font $HV0 \ 3544 -activebackground $NFG -activeforeground $NBG 3545 button $q1.ctl.plus -text "zoom in" -command "$fg scale all 0 0 1.1 1.1" -width 10 \ 3546 -bg $NBG -fg $NFG -font $HV0 \ 3547 -activebackground $NFG -activeforeground $NBG 3548 button $q1.ctl.minus -text "zoom out" -command "$fg scale all 0 0 0.9 0.9" -width 10 \ 3549 -bg $NBG -fg $NFG -font $HV0 \ 3550 -activebackground $NFG -activeforeground $NBG 3551 3552 pack $q1.ctl $q1.ctl.mkg -side left -fill x -expand no 3553 pack $q1.ctl $q1.ctl.minus -side right -fill x -expand no 3554 pack $q1.ctl $q1.ctl.plus -side right -fill x -expand no 3555 pack $q1 $q1.ctl -side top 3556 3557 pack $cv -side right -fill both -expand yes 3558 pack $xx -fill both -expand yes 3559 pack $pw -fill both -expand yes 3560 3561 bind $twin <KeyRelease> { 3562 if {"%K" == "Return"} { 3563 $twin insert insert "[$twin index insert] " 3564 $twin edit modified true 3565 } } 3566 3567 bind $fg <2> "$fg scan mark %x %y" 3568 bind $fg <B2-Motion> "$fg scan dragto %x %y" 3569} 3570 3571proc checked_exit {} { 3572 global twin 3573 3574 if {[$twin edit modified]} { 3575 set answer [tk_messageBox -icon question -type yesno \ 3576 -message "There are unsaved changes. Really Quit?" ] 3577 switch -- $answer { 3578 yes { } 3579 no { return } 3580 } 3581 } 3582 destroy . 3583 exit 3584} 3585 3586proc mk_pan { t GC CC } { 3587 global vo RM 3588 3589 set errmsg "" 3590 $vo insert end $GC\n; update 3591 set fd -1 3592 catch {set fd [open "|$GC" r]} errmsg 3593 if {$fd == -1} { 3594 $vo delete 0.0 end 3595 $vo insert end "error: $errmsg\n" 3596 $vo yview end 3597 return 3598 } else { 3599 while {[gets $fd line] > -1} { 3600 $vo insert end "$line\n" 3601 $vo yview end 3602 update 3603 } 3604 catch " close $fd " 3605 } 3606 3607 $vo insert end $CC\n; update 3608 3609 catch "eval exec $CC >& pan.tmp" 3610 3611 set fd -1 3612 catch {set fd [open "pan.tmp" r]} errmsg 3613 if {$fd == -1} { 3614 $vo delete 0.0 end 3615 $vo insert end "$errmsg\n" 3616 $vo yview end 3617 } else { 3618 while {[gets $fd line] > -1} { 3619 $vo insert end "$line\n" 3620 $vo yview end 3621 update 3622 } 3623 catch " close $fd " 3624 } 3625 catch { eval exec "$RM pan.tmp" } 3626 update 3627} 3628 3629proc run_pan { t VC d } { 3630 global vr vo stop KILL 3631 3632 if {[auto_execok "./pan"] == ""} { 3633 return 3634 } 3635 3636 $vo insert end $VC\n; update 3637 set fd -1 3638 3639 set pid [eval exec $VC >& run.tmp &] 3640 $vo insert end "Pid: $pid\n" 3641 $vo yview end 3642 3643 catch {set fd [open "run.tmp" r]} errmsg 3644 if {$fd == -1} { 3645 $vo insert end "error: $errmsg\n" 3646 $vo yview end 3647 return 3648 } 3649 set stop 0 3650 set pname "--" 3651 if {$d == 1} { 3652 $vo delete 0.0 end 3653 $vo insert end "proc\tfrom\ttrans\tto\tsrc\tstmnt\n" 3654 $vo insert end "name\tstate\tid\tstate\n" 3655 } 3656 set no_errors 0 3657 set seen_ln 0 3658 while {$stop == 0} { 3659 if {[gets $fd line] == -1} { 3660 after 10 3661 $vo yview end 3662 update 3663 if {$seen_ln == 0} { 3664 # courtesy martin vuille 3665 after 10 3666 catch { close $fd } 3667 set fd [open "run.tmp" r] 3668 } 3669 continue 3670 } 3671 set seen_ln 1 3672 if {[string first "No tty allocated" $line] >= 0} { 3673 continue 3674 } 3675 if {[string first "Valid Options are:" $line] >= 0} { 3676 while {[gets $fd line] != -1} { 3677 $vo insert end "$line\n" 3678 update 3679 } 3680 set stop 2 3681 } 3682 3683 if {[string first "pan: elapsed" $line] >= 0} { 3684 set stop 2 3685 } 3686 3687 if {$d == 0} { 3688 $vo insert end "$line\n" 3689 $vo yview end 3690 update 3691 if {[string first "State-vector " $line] >= 0} { 3692 if {[string first "errors: 0" $line] >= 0} { 3693 set no_errors 1 3694 } } 3695 continue 3696 } 3697 if {[string first "proctype" $line] == 0} { 3698 set pname [string range $line 9 end] 3699 $vo insert end "\n" 3700 $vo yview end 3701 continue 3702 } 3703 if {[string first "Transition" $line] >= 0 \ 3704 || [string first "Source-State" $line] >= 0 \ 3705 || [string first "Note:" $line] >= 0 \ 3706 || [string first "pan:" $line] >= 0} { 3707 continue 3708 } 3709 # format: 3710 # state 15 -(tr 18)-> state 31 [id 14 tp 5] [----L] leader:36 => out!first,number 3711 3712 regexp {[A-Za-z0-9_\.]+:[0-9]+} $line matched ;# file:line 3713 3714 set pre [string first "\[" $line] 3715 set frst [string range $line 0 $pre] 3716 set lst [string range $line $pre end] 3717 set arr [string first " => " $lst]; incr arr 4 3718 set stmnt [string range $lst $arr end] 3719 if {[scan $line "\tstate %d -(tr %d)-> state %d \[id %d tp %d\]" \ 3720 f1 f2 f3 f4 f5] == 5} { 3721 $vo insert end "$pname\t$f1\t\[$f2\]\t$f3\t$matched\t$stmnt\n" 3722 } else { 3723 $vo insert end "$line\n" 3724 } } 3725 3726 if {$stop == 1} { 3727 catch "eval exec $KILL $pid" 3728 $vo insert end "stopped\n" 3729 while {[gets $fd line] != -1} { 3730 $vo insert end "$line\n" 3731 $vo yview end 3732 update 3733 } } 3734 catch " close $fd " errmsg 3735 if {$errmsg != "" && [string first "No tty allocated" $errmsg] < 0} { 3736 $vo insert end "$errmsg\n" 3737 } 3738 $vo yview end 3739 3740 if {$no_errors == 0} { 3741 $vo insert end "To replay the error-trail, goto Simulate/Replay and select \"Run\"\n" 3742 } else { 3743 $vo insert end "No errors found -- did you verify all claims?\n" 3744 } 3745 3746 bind_lines $vo $vr 3747 3748 update 3749} 3750 3751proc log { n } { 3752 set m 1 3753 set cnt 0 3754 while {$m<$n} { 3755 set m [expr $m*2] 3756 incr cnt 3757 } 3758 return $cnt 3759} 3760 3761proc run_tbl { t } { 3762 global Fname CC 3763 3764 if {$Fname == ""} { return } 3765 3766 mk_pan $t "spin -a [$t.top.right.row5.ent get] $Fname" "$CC -w -o pan pan.c" 3767 run_pan $t "./pan -d" 1 3768 cleanup 3769} 3770 3771proc has_label {s dargs} { 3772 global vr SPIN Fname 3773 3774 set ST "$SPIN -d $dargs $Fname" 3775 set result 0 3776 3777 catch {set fd [open "|$ST" r]} errmsg 3778 if {$fd == -1} { 3779 $vr insert end "$errmsg\n" 3780 $vr yview end 3781 update 3782 } else { 3783 while {[gets $fd line] > -1} { 3784 if {[string first "label $s" $line] >= 0} { 3785 set result 1 3786 break 3787 } } 3788 catch " close $fd " 3789 } 3790 return $result 3791} 3792 3793proc check_sanity {gargs} { 3794 global p_mode vo 3795 3796 if {[has_label "accept" $gargs] == 1} { 3797 if {$p_mode != 2} { 3798 $vo insert end "warning: model has accept states\n" 3799 } 3800 } else { 3801 if {$p_mode == 2} { 3802 $vo insert end "error: model has no accept states\n" 3803 return 0 3804 } } 3805 if {[has_label "progress" $gargs] == 1} { 3806 if {$p_mode != 1} { 3807 $vo insert end "warning: model has progress states\n" 3808 } 3809 } else { 3810 if {$p_mode == 1} { 3811 $vo insert end "error: model has no progress states\n" 3812 return 0 3813 } } 3814 $vo yview end 3815 3816 return 1 3817} 3818 3819proc run_ver { t } { 3820 global Fname q_mode f_mode bc_mode it_mode sv_mode 3821 global bet ival expl estop s_mode po_mode bf_mode e_mode 3822 global ma_mode cc_mode p_mode c_mode u_mode a_mode x_mode 3823 global nvr_pan sym_pan SPIN CC vo peg vranges LTL_Panel 3824 global V_Panel_1 V_Panel_3 3825 3826 set nc_nm "" 3827 set match_start "" 3828 3829 set gargs "-a" 3830 if {$q_mode} { set gargs "$gargs -m" } 3831 if {$peg == 1} { set gargs "$gargs -o3" } 3832 3833 if {$c_mode == 2} { 3834 catch { exec $SPIN -e $Fname > "never_claim.tmp" } errmsg 3835 if {$errmsg != ""} { 3836 $vo insert end $errmsg\n 3837 $vo yview end 3838 return 3839 } 3840 set nc_nm "Product" 3841 set gargs "$gargs -N never_claim.tmp" 3842 if {[check_sanity $gargs] == 0} { 3843 $vo yview end 3844 return 3845 } } 3846 3847 if {$c_mode == 1} { 3848 if {$LTL_Panel} { 3849 if [catch { set fd [open "never_claim.tmp" w] } errmsg] { 3850 $vo insert end $errmsg\n 3851 $vo yview end 3852 return 3853 } 3854 puts $fd [$sym_pan get 0.0 end] 3855 puts $fd [$nvr_pan get 0.0 end] 3856 3857 regexp {never .*\{} [$nvr_pan get 0.0 end] match_start 3858 if {$match_start == ""} { 3859 $vo insert end "error: cannot find never claim\n" 3860 $vo yview end 3861 return 3862 } 3863 set match_end [string first " \{" $match_start] 3864 if {$match_end > 0} { 3865 incr match_end -1 3866 } 3867 set nc_nm [string range $match_start 6 $match_end] 3868 # $vo insert end "\nusing claim: \'$nc_nm\'\n\n" 3869 # $vo yview end 3870 3871 catch "close $fd" 3872 set gargs "$gargs -N never_claim.tmp" 3873 if {[check_sanity $gargs] == 0} { 3874 $vo yview end 3875 return 3876 } 3877 $vo insert end "wrote never_claim.tmp\n" 3878 } else { 3879 set nc_nm [$t.top.fourth.rowA.nr get] 3880 } 3881 } 3882 3883 $vo yview end 3884 update 3885 3886 if {$V_Panel_3} { 3887 set cargs "-DMEMLIM=[$t.top.right.row0.ent get] [$t.top.right.row6.ent get]" 3888 } else { 3889 set cargs "-DMEMLIM=$ival(0) $ival(6)" 3890 } 3891 if {$s_mode == 1} { set cargs "$cargs -DBITSTATE" } 3892 if {$s_mode == 2} { set cargs "$cargs -DHC4" } 3893 3894 if {$V_Panel_3} { 3895 if {$ma_mode == 1} { set cargs "$cargs -DMA=[$t.top.right.row4.ent get]" } 3896 if {$ma_mode == 1} { set cargs "$cargs -DMA=$ival(4)" } 3897 } else { 3898 } 3899 if {$bf_mode == 1} { set cargs "$cargs -DBFS" } 3900 if {$x_mode == 0} { set cargs "$cargs -DXUSAFE" } 3901 if {$p_mode == 0} { set cargs "$cargs -DSAFETY" } 3902 if {$p_mode == 1} { set cargs "$cargs -DNP" } 3903 if {$c_mode == 0} { set cargs "$cargs -DNOCLAIM" } 3904 if {$cc_mode == 1} { set cargs "$cargs -DCOLLAPSE" } 3905 if {$bc_mode == 1} { set cargs "$cargs -DBCS" } 3906 if {$it_mode == 1} { set cargs "$cargs -DREACH" } 3907 if {$po_mode == 0} { set cargs "$cargs -DNOREDUCE" } 3908 if {$peg == 1} { set cargs "$cargs -DPEG" } 3909 if {$vranges == 1} { set cargs "$cargs -DVAR_RANGES" } 3910 3911 if {$V_Panel_3} { 3912 set vargs "-m[$t.top.right.row2.ent get] [$t.top.right.row7.ent get]" 3913 if {$s_mode == 1} { set vargs "$vargs -k[$t.top.right.row3.ent get]" } 3914 } else { 3915 set vargs "-m$ival(2) $ival(7)" 3916 if {$s_mode == 1} { set vargs "$vargs -k$ival(3)" } 3917 } 3918 if {$e_mode == 0} { set vargs "$vargs -E" } 3919 if {$a_mode == 0} { set vargs "$vargs -A" } 3920 if {$p_mode == 1} { set vargs "$vargs -l" } 3921 if {$p_mode == 2} { set vargs "$vargs -a" } 3922 if {$f_mode == 1} { set vargs "$vargs -f" } 3923 if {$u_mode == 0} { set vargs "$vargs -n" } 3924 if {$it_mode == 1} { set vargs "$vargs -i" } 3925 if {$estop == 1} { set vargs "$vargs -c0" } 3926 3927 if {$V_Panel_1} { 3928 if {$estop == 0} { set vargs "$vargs -c[$t.top.middle.row1.nr get]" } 3929 } 3930 3931 if {$sv_mode == 1} { set vargs "$vargs -e" } 3932 if {$s_mode == 1} { 3933 if {$V_Panel_3} { 3934 set vargs "$vargs -w[expr 10+[log [$t.top.right.row1.ent get]]]" 3935 } else { 3936 set vargs "$vargs -w[expr 10+[log $ival(1)]]" 3937 } } 3938 if {$bc_mode == 1} { 3939 set vargs "$vargs -L[$t.top.third.rowB.ent get]" 3940 } 3941 if {$nc_nm != ""} { set vargs "$vargs -N $nc_nm" } 3942 3943 if {$V_Panel_3} { 3944 set GC "$SPIN $gargs [$t.top.right.row5.ent get] $Fname" 3945 } else { 3946 set GC "$SPIN $gargs $ival(5) $Fname" 3947 } 3948 set CL "$CC $cargs -w -o pan pan.c" 3949 set VC "./pan $vargs" 3950 3951 $vo yview end 3952 update 3953 3954 mk_pan $t $GC $CL 3955 run_pan $t $VC 0 3956 cleanup 3957} 3958 3959proc stop_ver { t } { 3960 global stop 3961 set stop 1 3962} 3963 3964proc useful_info { sr cmd } { 3965 3966 catch { set fd [open "|$cmd" r] } errmsg 3967 if {$fd == -1} { 3968 $sr insert end "error: $errmsg" 3969 return 3970 } 3971 while {[gets $fd line] > -1} { 3972 $sr insert end "$line\n" 3973 $sr yview end 3974 update 3975 } 3976 catch "close $fd" errmsg 3977 $sr insert end "$errmsg\n" 3978 $sr yview end 3979 update 3980} 3981 3982proc swarm_gen { t } { 3983 global so sr Fname SWARM 3984 3985 if {[auto_execok $SWARM] == ""} { 3986 add_log "no swarm command is installed on this system" 0 3987 add_log "it is available from: http://spinroot.com/swarm/" 0 3988 tk_messageBox -icon info -message "No executable $SWARM found..." 3989 return 3990 } 3991 3992 if [catch {set fd [open "swarm_cfg.tmp" w]} errmsg] { 3993 $so insert end "error: cannot write swarm_cfg.tmp\n" 3994 return 3995 } 3996 3997 puts $fd "## Swarm Version 3.0 -- 16 August 2010" 3998 puts $fd "#" 3999 puts $fd "# range" 4000 puts $fd "k [$t.top.left.row0.e0 get] [$t.top.left.row1.e0 get]\n" 4001 4002 puts $fd "# limits" 4003 puts $fd "d [$t.top.left.row3.e0 get]" ;# later also add min: [$t.top.left.row2.e0 get] 4004 puts $fd "cpus [$t.top.left.row4.e0 get] [$t.top.left.row5.e0 get]" 4005 4006 puts $fd "memory [$t.top.left.row6.e0 get]" 4007 puts $fd "time [$t.top.left.row7.e0 get]" 4008 puts $fd "hash [$t.top.middle.row8.e1 get]" 4009 puts $fd "vector [$t.top.middle.row9.e1 get]" 4010 puts $fd "speed [$t.top.middle.row10.e1 get]" 4011 puts $fd "file $Fname\n" 4012 4013 puts $fd "# compilation options" 4014 puts $fd "[$t.top.right.row0 get 0.0 end]" 4015 puts $fd "# runtime options (one line only)" 4016 puts $fd "[$t.top.middle.row12.e1 get]\n" 4017 puts $fd "# spin options other than -a (one line only)" 4018 puts $fd "[$t.top.middle.row11.e1 get]\n" 4019 catch "close $fd" errmsg 4020 4021 $so insert end "generated configuration file\n" 4022 4023 catch { set fd [open "|$SWARM swarm_cfg.tmp" r] } errmsg 4024 if {$fd == -1} { 4025 $so insert end "error: $errmsg" 4026 return 4027 } 4028 while {[gets $fd line] > -1} { 4029 $so insert end "$line\n" 4030 $so yview end 4031 update 4032 } 4033 catch "close $fd" errmsg 4034 $so insert end "done:: $errmsg \n" 4035 $so yview end 4036 update 4037 4038 $so insert end "----Running----\n" 4039 $so yview end 4040 update 4041 4042 set nxn [string first "." $Fname] 4043 if {$nxn > 0} { 4044 incr nxn -1 4045 set sFname [string range $Fname 0 $nxn] 4046 } else { 4047 set sFname $Fname 4048 } 4049## untested: 4050 if {[string first "C:" $sFname] >= 0 || [string first "/" $sFname] == 0} { 4051 catch { set fd [open "|sh $sFname*.swarm" r] } errmsg 4052 } else { 4053 catch { set fd [open "|sh ./$sFname*.swarm" r] } errmsg 4054 } 4055 if {$fd == -1} { 4056 $so insert end "error: $errmsg" 4057 return 4058 } 4059 while {[gets $fd line] > -1} { 4060 $so insert end "$line\n" 4061 $so yview end 4062 update 4063 } 4064 catch "close $fd" errmsg 4065 $so insert end "run completed\n$errmsg\n" 4066 $so yview end 4067 update 4068 4069 useful_info $sr "grep -e errors: script*.out" 4070 useful_info $sr "ls -l *.trail" 4071} 4072 4073proc swarm_clean { } { 4074 global Fname so RM 4075 4076 cleanup 4077 catch { eval exec $RM swarm_cfg.tmp $Fname.swarm script* } err 4078 $so insert end $err\n 4079 $so yview end 4080} 4081 4082proc swarm_panel { t } { 4083 global swarm_p swarm_i CBG CFG TBG TFG NBG NFG HV0 HV1 4084 global SWARM so sr ScrollBarSize spanel 4085 4086 set spanel $t 4087 4088 frame $t.top -bg $TBG 4089 pack $t.top -side top -fill both -expand no 4090 4091 frame $t.top.left -bg $TBG 4092 frame $t.top.middle -bg $TBG 4093 frame $t.top.right -bg $TBG 4094 pack $t.top.left $t.top.middle $t.top.right -side left -fill both -expand no 4095 4096 set p1 $t.top.left 4097 label $p1.limits -text "Search Constraints" -relief sunken -bg $TBG -fg $TFG 4098 pack $p1.limits -side top -fill x -expand no 4099 4100 for {set i 0} {$i < 8} {incr i} { 4101 frame $p1.row$i -bg $TBG 4102 label $p1.row$i.k0 -text "$swarm_p($i)" -bg $TBG -fg $TFG 4103 entry $p1.row$i.e0 -relief sunken 4104 $p1.row$i.e0 insert end "$swarm_i($i)" 4105 4106 pack $p1.row$i.k0 -side left -fill x -expand no 4107 pack $p1.row$i.e0 -side right -fill x -expand no 4108 pack $p1.row$i -side top -fill x -expand no 4109 } 4110 4111 set p2 $t.top.middle 4112 label $p2.limits -text "Estimates (Fine Tuning)" -relief sunken -bg $TBG -fg $TFG 4113 pack $p2.limits -side top -fill x -expand no 4114 4115 for {set i 8} {$i < 11} {incr i} { 4116 frame $p2.row$i -bg $TBG 4117 label $p2.row$i.k1 -text "$swarm_p($i)" -bg $TBG -fg $TFG 4118 entry $p2.row$i.e1 -relief sunken 4119 $p2.row$i.e1 insert end "$swarm_i($i)" 4120 pack $p2.row$i.k1 -side left -fill x -expand no 4121 pack $p2.row$i.e1 -side right -fill x -expand no 4122 pack $p2.row$i -side top -fill x -expand no 4123 } 4124 4125 label $p2.other -text "Model Generation" -relief sunken -bg $TBG -fg $TFG 4126 pack $p2.other -side top -fill x -expand no 4127 frame $p2.row11 -bg $TBG 4128 label $p2.row11.k1 -text "extra spin args" -bg $TBG -fg $TFG 4129 entry $p2.row11.e1 -relief sunken 4130 pack $p2.row11.k1 -side left -fill x -expand no 4131 pack $p2.row11.e1 -side right -fill x -expand no 4132 pack $p2.row11 -side top -fill x -expand no 4133 frame $p2.row12 -bg $TBG 4134 label $p2.row12.k1 -text "extra pan args" -bg $TBG -fg $TFG 4135 entry $p2.row12.e1 -relief sunken 4136 $p2.row12.e1 insert end "-c1 -x -n" 4137 pack $p2.row12.k1 -side left -fill x -expand no 4138 pack $p2.row12.e1 -side right -fill x -expand no 4139 pack $p2.row12 -side top -fill x -expand no 4140 4141 frame $p2.buttons -bg $TBG 4142 button $p2.buttons.run -text "Run" -command "swarm_gen $t" \ 4143 -bg $NBG -fg $NFG -font $HV0 \ 4144 -activebackground $NFG -activeforeground $NBG 4145 4146 button $p2.buttons.cln -text "Cleanup tmp files" -command "swarm_clean" \ 4147 -bg $NBG -fg $NFG -font $HV0 \ 4148 -activebackground $NFG -activeforeground $NBG 4149 4150 pack $p2.buttons.cln -side right -fill x -expand no 4151 pack $p2.buttons.run -side right -fill x -expand no 4152 pack $p2.buttons -side bottom -fill x -expand no 4153 4154 4155 set p3 $t.top.right 4156 label $p3.limits -text "Compilation Options (any number, one per line)" \ 4157 -relief sunken -bg $TBG -fg $TFG 4158 text $p3.row0 -height 12 -relief sunken 4159 4160 $p3.row0 insert end "-DBITSTATE -DPUTPID # basic dfs\n" 4161 $p3.row0 insert end "-DBITSTATE -DPUTPID -DREVERSE # reversed transition ordering\n" 4162 $p3.row0 insert end "-DBITSTATE -DPUTPID -DT_REVERSE # reversed process ordering\n" 4163 $p3.row0 insert end "-DBITSTATE -DPUTPID -DREVERSE -DT_REVERSE # both\n" 4164 $p3.row0 insert end "-DBITSTATE -DPUTPID -DP_RAND -DT_RAND # same series with randomization\n" 4165 $p3.row0 insert end "-DBITSTATE -DPUTPID -DP_RAND -DT_RAND -DT_REVERSE\n" 4166 $p3.row0 insert end "-DBITSTATE -DPUTPID -DP_RAND -DT_RAND -DREVERSE\n" 4167 $p3.row0 insert end "-DBITSTATE -DPUTPID -DP_RAND -DT_RAND -DREVERSE -DT_REVERSE\n" 4168 4169 pack $p3.limits $p3.row0 -side top -fill x -expand no 4170 4171# frame $p3.row2 4172# label $p3.row2.k1 -text "runtime options" -bg $TBG -fg $TFG 4173# entry $p3.row2.e1 -relief sunken -bg $TBG -fg $TFG 4174# $p3.row2.e1 insert end "-c1 -x -n" 4175# pack $p3.row2.k1 $p3.row2.e1 -side top -fill x -expand no 4176# pack $p3.row2 -side top -fill x -expand no 4177 4178 set vw [PanedWindow $t.bottom -side left -activator button ] 4179 4180 set p8 [$vw add -minsize 100] 4181 set p9 [$vw add -minsize 100] 4182 4183 set s11 [ScrolledWindow $p8.so -size $ScrollBarSize] ;# so - swarm output 4184 set so [text $s11.lb -height 5 -highlightthickness 3 -font $HV1] 4185 $s11 setwidget $so 4186 4187 set s22 [ScrolledWindow $p9.sr -size $ScrollBarSize] ;# sr - swarm run 4188 set sr [text $s22.lb -highlightthickness 0 -bg $CBG -fg $CFG -font $HV1] 4189 $s22 setwidget $sr 4190 4191 $so insert end "swarm setup output\n" 4192 $sr insert end "swarm run output\n" 4193 4194 set errmsg "" 4195 # a bit overkill, but execs compiled with gcc 4196 # behave differently from those compiled with cl 4197 # complaints about missing tty, for instance 4198 # spin on cygwin is compiled with cl, swarm with gcc 4199 4200 if {[auto_execok $SWARM] == ""} { 4201 $sr insert end "no 'swarm' command is found\n" 4202 $sr insert end "available from: http://spinroot.com/swarm/\n" 4203 } else { 4204 catch { set fd [open "|$SWARM -V" r] } errmsg 4205 if {$fd == -1} { 4206 $sr insert end "$errmsg\n" 4207 } else { 4208 while {[gets $fd line] > -1} { 4209 $sr insert end "$line\n" 4210 } 4211 catch " close $fd " 4212 } } 4213 4214 pack $s11 -fill both -expand yes 4215 pack $s22 -fill both -expand yes 4216 pack $vw -fill both -expand yes 4217 4218} 4219 4220proc explain0 {} { 4221 global vo 4222 4223 $vo insert end "\n" 4224 $vo insert end "\tPhysical Memory Available:\n" 4225 $vo insert end "\tSet this number to amount of physical (not virtual) memory\n" 4226 $vo insert end "\tin your system, in MegaBytes, and leave it there for all runs.\n" 4227 $vo insert end "\n" 4228 $vo insert end "\tWhen the limit is reached, the verification is stopped to\n" 4229 $vo insert end "\tavoid trashing.\n" 4230 $vo insert end "\n" 4231 $vo insert end "\tIf an exhaustive verification cannot be completed due to\n" 4232 $vo insert end "\tlack of memory, select a different storage mode.\n\n" 4233 $vo yview end 4234} 4235 4236proc explain1 {} { 4237 global vo 4238 4239 $vo insert end "\tEstimated State Space Size:\n" 4240 $vo insert end "\tThis parameter is used to calculate the size of the\n" 4241 $vo insert end "\thash-table. It results in a selection of a numeric argument\n" 4242 $vo insert end "\tfor the -w flag of the verifier. Setting it too high may\n" 4243 $vo insert end "\tcause an out-of-memory error with zero states reached\n" 4244 $vo insert end "\t(meaning that the verification could not be started).\n" 4245 $vo insert end "\tSetting it too low can cause inefficiencies due to\n" 4246 $vo insert end "\thash collisions.\n" 4247 $vo insert end "\t\n" 4248 $vo insert end "\tWhen using bitstate, start with the default\n" 4249 $vo insert end "\tsetting. After a run completes successfully,\n" 4250 $vo insert end "\tdouble the estimate, and see if the number of reached\n" 4251 $vo insert end "\tstated changes much. Continue to do this until\n" 4252 $vo insert end "\tit stops changing, or until you reach the memory bound.\n" 4253 $vo insert end "\t\n" 4254 $vo insert end "\tiSpin uses the closest power of two to determine the parameter\n" 4255 $vo insert end "\tgiven to the -w flag that is used for the run.\n\n" 4256 $vo yview end 4257} 4258 4259proc explain2 {} { 4260 global vo 4261 $vo insert end "\tMaximum Search Depth:\n" 4262 $vo insert end "\tThis number determines the size of the depth-first\n" 4263 $vo insert end "\tsearch stack that is used during the verification.\n" 4264 $vo insert end "\tA larger number increases the memory requirements, and\n" 4265 $vo insert end "\ta lower number decreases it. When there seems not to be\n" 4266 $vo insert end "\tsufficient memory for the search depth needed, reduce\n" 4267 $vo insert end "\treduce the estimated state space size to free some\n" 4268 $vo insert end "\tmore memory for the stack, or change the storage mode.\n" 4269 $vo insert end "\t\n" 4270 $vo insert end "\tIf you hit the maximum search depth during a verification\n" 4271 $vo insert end "\t(noted as 'Search not completed' or 'Search Truncated'\n" 4272 $vo insert end "\tin the verification output) without finding an error,\n" 4273 $vo insert end "\tincrease the search depth parameter and repeat the run.\n\n" 4274 $vo yview end 4275} 4276 4277proc explain3 {} { 4278 global vo 4279 4280 $vo insert end "\tNumber of hash functions:\n" 4281 $vo insert end "\tThis number determines how many bits are set per\n" 4282 $vo insert end "\tstate when in Bitstate verification mode. The default is 3,\n" 4283 $vo insert end "\tbut you can use any number greater to or equal to 1.\n" 4284 $vo insert end "\tAt the end of a Bitstate verification run, the verifier\n" 4285 $vo insert end "\tcan issue a recommendation for a different setting of\n" 4286 $vo insert end "\tthis parameter (specified with the -k flag), if this can\n" 4287 $vo insert end "\timprove coverage.\n\n" 4288 $vo yview end 4289} 4290 4291proc explain4 {} { 4292 global vo 4293 4294 $vo insert end "\tSize for Minimized Automata:\n" 4295 $vo insert end "\tWhen using the minimized automata storage mode, you should\n" 4296 $vo insert end "\tset this parameter to be equal to the statevector size at first.\n" 4297 $vo insert end "\tAt the end of the run, the verifier will then report if a smaller\n" 4298 $vo insert end "\tnumber can also be used. The smaller the number the faster the run.\n\n" 4299 $vo yview end 4300} 4301 4302proc explain5 {} { 4303 global vo 4304 4305 $vo insert end "\tExtra Verifier Generator Options:\n" 4306 $vo insert end "\tPossible options include:\n" 4307 $vo insert end "\t-o1 to disable dataflow optimizations\n" 4308 $vo insert end "\t-o2 to disable dead-variable elimination\n" 4309 $vo insert end "\t-o3 to disable statement merging (which improves source-line references)\n\n" 4310 $vo yview end 4311} 4312 4313proc explain6 {} { 4314 global vo 4315 4316 $vo insert end "\tExtra Compile-time Directives:\n" 4317 $vo insert end "\tFor possible options see:\n" 4318 $vo insert end "\thttp://spinroot.com/spin/Man/Pan.html#B\n\n" 4319 $vo yview end 4320} 4321 4322proc explain7 {} { 4323 global vo 4324 4325 $vo insert end "\tExtra Run-time Options:\n" 4326 $vo insert end "\tPossible options include:\n" 4327 $vo insert end "\t-hN use a different hash-function (N: 1..32, default 1)\n" 4328 $vo insert end "\t-J reverse evaluation order on nested unless structures\n" 4329 $vo insert end "\t-q require channels to be empty in valid endstates\n" 4330 $vo insert end "\t-QN try to stop the run after N minutes\n" 4331 $vo insert end "\t-tSuf use Suf as a suffix on trail files instead of .trail\n" 4332 $vo insert end "\t-T create trail files in read-only mode\n" 4333 $vo insert end "\t-x do not overwrite an existing trail file\n\n" 4334 $vo yview end 4335} 4336 4337proc ver_help {} { 4338 global vo 4339 4340 $vo insert end "\tHelp with Verification Complexity:\n" 4341 $vo insert end "\t---------------------------------------\n" 4342 $vo insert end "\tWhen a verification cannot be completed because it\n" 4343 $vo insert end "\truns out of memory or you run out of time, there are\n" 4344 $vo insert end "\tsome useful strategies that can be tried to restore tractability.\n" 4345 $vo insert end "\n" 4346 $vo insert end "\t0. Run the Redundancy Check (in the Edit/View tab) to see if you can\n" 4347 $vo insert end "\tsimplify the model and still prove the same properties.\n" 4348 $vo insert end "\n" 4349 $vo insert end "\t1. Try to make the model more general.\n" 4350 $vo insert end "\tRemember that you are constructing a verification model and not\n" 4351 $vo insert end "\tan implementation. The model checker is good at proving properties\n" 4352 $vo insert end "\tof *interactions* in a distributed system (the implicit assumptions\n" 4353 $vo insert end "\tthat processes make about each other) -- it is generally not strong\n" 4354 $vo insert end "\tin proving things about *computations*, data dependencies etc.\n" 4355 $vo insert end "\n" 4356 $vo insert end "\t2. Remove everything that is not directly related to the property\n" 4357 $vo insert end "\tyou are trying to prove: redundant computations, redundant data. \n" 4358 $vo insert end "\t*Avoid counters*; avoid incrementing variables that are used for\n" 4359 $vo insert end "\tonly book-keeping purposes.\n" 4360 $vo insert end "\tThe Syntax Check option (Edit/View tab) warns about the gravest offenses.\n" 4361 $vo insert end "\n" 4362 $vo insert end "\t3. Asynchronous channels can be a significant source of complexity in\n" 4363 $vo insert end "\tverification. Use *synchronous channels* where possible. Reduce the\n" 4364 $vo insert end "\tnumber of slots in asynchronous channels to a minimum (use 2, or 3\n" 4365 $vo insert end "\tslots to get started).\n" 4366 $vo insert end "\n" 4367 $vo insert end "\t4. Look for processes that merely transfer messages. Consider if\n" 4368 $vo insert end "\tyou can remove processes that only copy incoming messages from\n" 4369 $vo insert end "\tone channel into another, by letting the sender generate the\n" 4370 $vo insert end "\tfinal message right away. If the intermediate process makes\n" 4371 $vo insert end "\tchoices (e.g., to delete or duplicate, etc.), let the sender\n" 4372 $vo insert end "\tmake that choice, rather than an intermediate process.\n" 4373 $vo insert end "\n" 4374 $vo insert end "\t5. Combine local computations into atomic, or d_step, sequences.\n" 4375 $vo insert end "\n" 4376 $vo insert end "\t6. Avoid leaving scratch data around in variables. You can often reduce\n" 4377 $vo insert end "\tthe number of states by, for instance, resetting local variables\n" 4378 $vo insert end "\tthat are used inside atomic sequences to zero at the end of those\n" 4379 $vo insert end "\tsequences; so that the scratch values aren't visible outside the\n" 4380 $vo insert end "\tsequence. Consider using the predefined variable \"_\" as a write-only\n" 4381 $vo insert end "\tscratch variable where possible.\n" 4382 $vo insert end "\n" 4383 $vo insert end "\t7. Try to combine the behavior of two processes into one.\n" 4384 $vo insert end "\tGeneralize behavior. Focus on coordination aspects\n" 4385 $vo insert end "\t(i.e., the interfaces between processes, rather than the local\n" 4386 $vo insert end "\tcomputations inside processes).\n" 4387 $vo insert end "\n" 4388 $vo insert end "\t8. Try to exploit the partial order reduction strategies.\n" 4389 $vo insert end "\tUse the xr and xs assertions where possible (see the online manpages\n" 4390 $vo insert end "\tat spinroot.com; avoid sharing channels between multiple receivers or\n" 4391 $vo insert end "\tmultiple senders.\n" 4392 $vo insert end "\tAvoid merging independent data-streams into a single shared channel.\n" 4393 $vo yview end 4394} 4395 4396proc del_v_panel {n} { 4397 global vpanel 4398 4399 if {$n == 1} { 4400 catch { destroy $vpanel.top.middle } 4401 } 4402 if {$n == 2} { 4403 catch { destroy $vpanel.top.third } 4404 } 4405 if {$n == 3} { 4406 catch { destroy $vpanel.top.right } 4407 } 4408} 4409 4410proc toggle_a {n} { 4411 global V_Panel_1 V_Panel_3 vpanel LIB NBG HV0 NFG 4412 4413 if {$n == 1} { 4414 if {$V_Panel_1} { 4415 set V_Panel_1 0 4416 set p6 $vpanel.top.middle 4417 catch { 4418 destroy $p6.er 4419 destroy $p6.lb 4420 destroy $p6.row0 4421 destroy $p6.row1 4422 destroy $p6.row2 4423 destroy $p6.row4 4424 destroy $p6.row5 4425 destroy $p6.row7 4426 destroy $p6.row8 4427 destroy $p6.rowA 4428 destroy $p6.row66 4429 } 4430 4431 frame $p6.row66 -bg $LIB 4432 button $p6.row66.a1 -text "Show\nError\nTrapping\nOptions" \ 4433 -command "toggle_a 1" \ 4434 -fg white -bg black -activeforeground $NBG \ 4435 -activebackground $NFG -font $HV0 4436 pack $p6.row66.a1 -side left -fill x -expand yes 4437 pack $p6.row66 -side top -fill x -expand yes 4438 } else { 4439 set V_Panel_1 1 4440 $vpanel.top.middle.row66.a1 configure -text "Remove" 4441 advanced_1 4442 } } 4443 4444 if {$n == 3} { 4445 if {$V_Panel_3} { 4446 set V_Panel_3 0 4447 set p6 $vpanel.top.right 4448 catch { 4449 destroy $p6.t 4450 for {set i 0} {$i <= 7} {incr i} { 4451 destroy $p6.row$i 4452 } 4453 destroy $p6.row66 4454 } 4455 4456 frame $p6.row66 -bg $LIB 4457 button $p6.row66.a3 -text "Show\nAdvanced\nParameter\nSettings" \ 4458 -command "toggle_a 3" \ 4459 -fg white -bg black -activeforeground $NBG \ 4460 -activebackground $NFG -font $HV0 4461 pack $p6.row66.a3 -side left -fill x -expand yes 4462 pack $p6.row66 -side top -fill x -expand yes 4463 } else { 4464 set V_Panel_3 1 4465 $vpanel.top.right.row66.a3 configure -text "Remove" 4466 advanced_3 4467 } } 4468 4469} 4470 4471set peg 0 4472set vranges 0 4473set sv_mode 0 4474set estop 0 4475set q_mode 0 4476 4477proc advanced_1 {} { 4478 global LIB TFG NFG NBG HV0 vpanel V_Panel_1 4479 global peg sv_mode estop vranges q_mode 4480 4481 set t $vpanel 4482 4483 set p6 $t.top.middle 4484 label $p6.er -text "Advanced: Error Trapping" -relief raised -bg $LIB 4485 frame $p6.row0 -bg $LIB 4486 radiobutton $p6.row0.ds -variable estop -value 1 -text "don't stop at errors" -bg $LIB -fg $TFG 4487 pack $p6.row0.ds -side left -fill x -expand no 4488 4489 frame $p6.row1 -bg $LIB 4490 radiobutton $p6.row1.st -variable estop -value 0 -text "stop at error nr:" -bg $LIB -fg $TFG 4491 entry $p6.row1.nr 4492 $p6.row1.nr insert end "1" 4493 pack $p6.row1.st -side left -fill x -expand no 4494 pack $p6.row1.nr -side right -fill x -expand yes 4495 4496 frame $p6.row2 -bg $LIB 4497 checkbutton $p6.row2.se -variable sv_mode -text "save all error-trails" -bg $LIB -fg $TFG 4498 pack $p6.row2.se -side left -fill x -expand no 4499 frame $p6.row4 -bg $LIB 4500 checkbutton $p6.row4.ac -variable peg -text "add complexity profiling" -bg $LIB -fg $TFG 4501 pack $p6.row4.ac -side left -fill x -expand no 4502 frame $p6.row5 -bg $LIB 4503 checkbutton $p6.row5.vr -variable vranges -text "compute variable ranges" -bg $LIB -fg $TFG 4504 pack $p6.row5.vr -side left -fill x -expand no 4505 4506 pack $p6.er $p6.row0 $p6.row1 $p6.row2 $p6.row4 $p6.row5 \ 4507 -side top -fill x -expand yes 4508 4509 label $p6.lb -text "A Full Channel" -relief raised -bg $LIB -fg $TFG 4510 frame $p6.row7 -bg $LIB 4511 radiobutton $p6.row7.b -variable q_mode -value 0 -text "blocks new msgs" -bg $LIB -fg $TFG 4512 pack $p6.row7.b -side left -fill x -expand no 4513 frame $p6.row8 -bg $LIB 4514 radiobutton $p6.row8.l -variable q_mode -value 1 -text "loses new msgs" -bg $LIB -fg $TFG 4515 pack $p6.row8.l -side left -fill x -expand no 4516 4517 frame $p6.rowA -bg $LIB 4518 button $p6.rowA.tb -text "State Tables" \ 4519 -command " run_tbl $t " \ 4520 -fg white -bg grey -activeforeground $NBG -activebackground $NFG -font $HV0 4521 button $p6.rowA.clr -text "Clear" -command " do_clear " \ 4522 -fg white -bg grey -activeforeground $NBG -activebackground $NFG -font $HV0 4523 button $p6.rowA.hlp -text "Help" -command " ver_help " \ 4524 -fg white -bg grey -activeforeground $NBG -activebackground $NFG -font $HV0 4525 pack $p6.rowA.tb $p6.rowA.clr $p6.rowA.hlp -side left -fill x -expand yes 4526 4527 pack $p6.lb $p6.row7 $p6.row8 $p6.rowA -side top -fill x -expand no 4528} 4529 4530proc advanced_2 {} { 4531 global TFG NFG NBG HV0 vpanel TBG 4532 global po_mode bf_mode bc_mode it_mode u_mode 4533 4534 set LIB $TBG ;# overrides global 4535 set t $vpanel 4536 4537 set p5 $t.top.third 4538 label $p5.sm -text "Search Mode" -relief raised -bg $LIB -fg $TFG 4539 4540 frame $p5.row5 -bg $LIB 4541 label $p5.row5.sp -width 1 -bg $LIB -fg $TFG 4542 checkbutton $p5.row5.po -variable po_mode -text "+ partial order reduction" -bg $LIB -fg $TFG 4543 pack $p5.row5.sp $p5.row5.po -side left -fill x -expand no 4544 frame $p5.row6 -bg $LIB 4545 radiobutton $p5.row6.dfs -variable bf_mode -value 0 -text "depth-first search" -bg $LIB -fg $TFG 4546 pack $p5.row6.dfs -side left -fill x -expand no 4547 4548 frame $p5.row60 -bg $LIB 4549 label $p5.row60.sp -width 1 -bg $LIB -fg $TFG 4550 checkbutton $p5.row60.fs -variable bc_mode -text "+ bounded context switching" -bg $LIB -fg $TFG 4551 pack $p5.row60.sp $p5.row60.fs -side left -fill x -expand no 4552 4553 frame $p5.rowB -bg $LIB 4554 label $p5.rowB.sp -width 6 -bg $LIB -fg $TFG 4555 label $p5.rowB.nm -text "with bound:" -bg $LIB -fg $TFG 4556 entry $p5.rowB.ent -relief sunken -width 8 4557 $p5.rowB.ent insert end "0" 4558 pack $p5.rowB.sp $p5.rowB.nm -side left -fill x -expand no 4559 pack $p5.rowB.ent -side left -fill x -expand yes 4560 4561 frame $p5.row61 -bg $LIB 4562 label $p5.row61.sp -width 1 -bg $LIB -fg $TFG 4563 checkbutton $p5.row61.fs -variable it_mode -text "+ iterative search for short trail" -bg $LIB -fg $TFG 4564 pack $p5.row61.sp $p5.row61.fs -side left -fill x -expand no 4565 frame $p5.row62 -bg $LIB 4566 label $p5.row62.sp -width 1 -bg $LIB -fg $TFG 4567 checkbutton $p5.row62.po -variable po_mode -text "+ partial order reduction" -bg $LIB -fg $TFG 4568 pack $p5.row62.sp $p5.row62.po -side left -fill x -expand no 4569 4570 frame $p5.row7 -bg $LIB 4571 radiobutton $p5.row7.bfs -variable bf_mode -value 1 -text "breadth-first search" -bg $LIB -fg $TFG 4572 pack $p5.row7.bfs -side left -fill x -expand no 4573 frame $p5.row8 -bg $LIB 4574 checkbutton $p5.row8.ur -variable u_mode -text "report unreachable code" -bg $LIB -fg $TFG 4575 pack $p5.row8.ur -side left -fill x -expand no 4576 4577 frame $p5.row9 -bg $LIB 4578 entry $p5.row9.en -relief sunken -width 12 4579 button $p5.row9.lb -text "Save Result in:" \ 4580 -command " save_in $p5.row9.en" \ 4581 -bg grey -fg white \ 4582 -activeforeground $NBG -activebackground $NFG -font $HV0 4583 $p5.row9.en insert end "pan.out" 4584 pack $p5.row9.lb $p5.row9.en -side left -fill y -expand yes 4585 4586 pack $p5.sm $p5.row6 $p5.row62 $p5.row60 $p5.rowB $p5.row61 $p5.row7 $p5.row5 $p5.row8 $p5.row9 \ 4587 -side top -fill x -expand no 4588} 4589 4590proc advanced_3 {} { 4591 global bet ival expl LIB TFG NFG NBG HV0 vpanel V_Panel_3 4592 4593 set t $vpanel 4594 4595 set p7 $t.top.right 4596 label $p7.t -text "Advanced: Parameters" -relief raised -bg $LIB -fg $TFG 4597 pack $p7.t -side top -fill x -expand no 4598 4599 for {set i 0} {$i <= 7} {incr i} { 4600 frame $p7.row$i -bg $LIB 4601 label $p7.row$i.lbl -text $bet($i) -bg $LIB -fg $TFG 4602 entry $p7.row$i.ent -width 20 4603 $p7.row$i.ent insert end $ival($i) 4604 button $p7.row$i.exp -text $expl($i) -command " explain$i " -bg $LIB -fg $TFG 4605 pack $p7.row$i.lbl -side left -fill x -expand no 4606 pack $p7.row$i.exp -side right -fill x -expand no 4607 pack $p7.row$i.ent -side right -fill x -expand no 4608 pack $p7.row$i -side top -fill x -expand no 4609 } 4610} 4611 4612proc verify_panel {t} { 4613 global bet ival expl estop s_mode po_mode bf_mode e_mode HV0 HV1 CBG CFG TBG TFG NBG NFG it_mode 4614 global ma_mode cc_mode p_mode c_mode u_mode a_mode x_mode q_mode f_mode bc_mode 4615 global sv_mode vo vr Fname ScrollBarSize peg vranges vpanel 4616 global LTL_Panel V_Panel_1 V_Panel_3 LIB 4617 4618 set vpanel $t 4619 4620 set LIB lightgray ;# background for less important options -- was TBG 4621 4622 frame $t.top -bg $LIB 4623 pack $t.top -side top -fill both -expand no 4624 4625 frame $t.top.left -bg $TBG 4626 frame $t.top.fourth -bg $TBG 4627 frame $t.top.middle -bg $LIB 4628 frame $t.top.third -bg $LIB 4629 frame $t.top.right -bg $LIB 4630 pack $t.top.left $t.top.fourth -side left -fill both -expand yes 4631 pack $t.top.third -side left -fill both -expand yes 4632 pack $t.top.middle -side left -fill x -expand yes 4633 pack $t.top.right -side left -fill x -expand yes 4634 4635 set p1 $t.top.left 4636 label $p1.saf -text "Safety" -relief raised -bg $TBG -fg $TFG 4637 label $p1.liv -text "Liveness" -relief raised -bg $TBG -fg $TFG 4638 4639 frame $p1.row0 -bg $TBG 4640 radiobutton $p1.row0.sf -variable p_mode -value 0 -text "safety" -bg $TBG -fg $TFG 4641 pack $p1.row0.sf -side left -fill x -expand no 4642 frame $p1.row1 -bg $TBG 4643 label $p1.row1.sp -width 1 -bg $TBG -fg $TFG 4644 checkbutton $p1.row1.av -variable a_mode -text "+ assertion violations" -bg $TBG -fg $TFG 4645 pack $p1.row1.sp $p1.row1.av -side left -fill x -expand no 4646 frame $p1.row9 -bg $TBG 4647 label $p1.row9.sp -width 1 -bg $TBG -fg $TFG 4648 checkbutton $p1.row9.xr -variable x_mode -text "+ xr/xs assertions" -bg $TBG -fg $TFG 4649 pack $p1.row9.sp $p1.row9.xr -side left -fill x -expand no 4650 frame $p1.row2 -bg $TBG 4651 label $p1.row2.sp -width 1 -bg $TBG -fg $TFG 4652 checkbutton $p1.row2.ie -variable e_mode -text "+ invalid endstates (deadlock)" -bg $TBG -fg $TFG 4653 pack $p1.row2.sp $p1.row2.ie -side left -fill x -expand no 4654 4655 pack $p1.saf $p1.row0 $p1.row2 $p1.row1 $p1.row9 -side top -fill x -expand no 4656 4657 frame $p1.row3 -bg $TBG 4658 radiobutton $p1.row3.np -variable p_mode -value 1 -text "non-progress cycles" -bg $TBG -fg $TFG 4659 pack $p1.row3.np -side left -fill x -expand no 4660 frame $p1.row4 -bg $TBG 4661 radiobutton $p1.row4.ac -variable p_mode -value 2 -text "acceptance cycles" -bg $TBG -fg $TFG 4662 pack $p1.row4.ac -side left -fill x -expand no 4663 frame $p1.row5 -bg $TBG 4664 # label $p1.row5.sp -width 1 -bg $TBG -fg $TFG 4665 checkbutton $p1.row5.wf -variable f_mode -text "enforce weak fairness constraint" -bg $TBG -fg $TFG 4666 pack $p1.row5.wf -side left -fill x -expand no 4667 4668 pack $p1.liv $p1.row3 $p1.row4 $p1.row5 -side top -fill x -expand no 4669 4670 set p10 $t.top.fourth 4671 label $p10.alg -text "Storage Mode" -relief raised -bg $TBG -fg $TFG 4672 4673 frame $p10.row0 -bg $TBG 4674 radiobutton $p10.row0.ex -variable s_mode -value 0 -text "exhaustive" -bg $TBG -fg $TFG 4675 pack $p10.row0.ex -side left -fill x -expand no 4676# frame $p10.row1 -bg $TBG 4677# radiobutton $p10.row1.bs -variable s_mode -value 1 -text "bitstate" -bg $TBG -fg $TFG 4678# pack $p10.row1.bs -side left -fill x -expand no 4679 frame $p10.row2 -bg $TBG 4680 radiobutton $p10.row2.hc -variable s_mode -value 2 -text "hash-compact" -bg $TBG -fg $TFG 4681 radiobutton $p10.row2.bs -variable s_mode -value 1 -text "bitstate/supertrace" -bg $TBG -fg $TFG 4682 pack $p10.row2.hc $p10.row2.bs -side left -fill x -expand no 4683 frame $p10.row3 -bg $TBG 4684 label $p10.row3.sp -width 1 -bg $TBG -fg $TFG 4685 checkbutton $p10.row3.ma -variable ma_mode -text "+ minimized automata (slow)" -bg $TBG -fg $TFG 4686 pack $p10.row3.sp $p10.row3.ma -side left -fill x -expand no 4687 frame $p10.row4 -bg $TBG 4688 label $p10.row4.sp -width 1 -bg $TBG -fg $TFG 4689 checkbutton $p10.row4.cl -variable cc_mode -text "+ collapse compression" -bg $TBG -fg $TFG 4690 pack $p10.row4.sp $p10.row4.cl -side left -fill x -expand no 4691 4692 frame $p10.row6 -bg $TBG 4693 button $p10.row6.go -text "Run" \ 4694 -command " run_ver $t " \ 4695 -fg $NFG -bg $NBG -activeforeground $NBG -activebackground $NFG -font $HV0 4696 button $p10.row6.no -text "Stop" \ 4697 -command " stop_ver $t " \ 4698 -fg $NFG -bg $NBG -activeforeground $NBG -activebackground $NFG -font $HV0 4699 4700 pack $p10.row6.no $p10.row6.go -side right -fill x -expand yes 4701 4702 4703 pack $p10.alg $p10.row0 $p10.row3 $p10.row4 $p10.row2 \ 4704 -side top -fill x -expand no 4705 4706 label $p10.nc -text "Never Claims" -relief raised -bg $TBG -fg $TFG 4707 4708 frame $p10.row9 -bg $TBG 4709 if {$LTL_Panel} { 4710 radiobutton $p10.row9.nc -variable c_mode -value 1 -text "use claim from LTL panel:" -bg $TBG -fg $TFG 4711 pack $p10.row9.nc -side left -fill x -expand no 4712 } else { 4713 radiobutton $p10.row9.nc -variable c_mode -value 1 -text "use claim" -bg $TBG -fg $TFG 4714 pack $p10.row9.nc -side left -fill x -expand no 4715 frame $p10.rowA -bg $TBG 4716 label $p10.rowA.lb -text " claim name (opt):" -bg $TBG -fg $TFG 4717 entry $p10.rowA.nr 4718 pack $p10.rowA.lb -side left -fill x -expand no 4719 pack $p10.rowA.nr -side left -fill x -expand yes 4720 } 4721 4722# frame $p10.row10 -bg $TBG 4723# radiobutton $p10.row10.nc -variable c_mode -value 2 \ 4724# -text "use (only) product of claims in spec" -bg $TBG -fg $TFG 4725# pack $p10.row10.nc -side left -fill x -expand no 4726 4727 frame $p10.row11 -bg $TBG 4728 radiobutton $p10.row11.nc -variable c_mode -value 0 \ 4729 -text "do not use a never claim or ltl property" -bg $TBG -fg $TFG 4730 pack $p10.row11.nc -side left -fill x -expand no 4731 4732 pack $p10.nc $p10.row11 $p10.row9 \ 4733 -side top -fill x -expand no 4734 4735 if {$LTL_Panel == 0} { 4736 pack $p10.rowA -side top -fill x -expand no 4737 } 4738 4739 set p6 $t.top.middle 4740 frame $p6.row66 -bg $LIB 4741 button $p6.row66.a1 -text "Show\nError\nTrapping\nOptions" \ 4742 -command "toggle_a 1" \ 4743 -fg white -bg black -activeforeground $NBG \ 4744 -activebackground $NFG -font $HV0 4745 pack $p6.row66.a1 -side left -fill x -expand yes 4746 pack $p6.row66 -side top -fill x -expand yes 4747 4748 set p6 $t.top.right 4749 frame $p6.row66 -bg $LIB 4750 button $p6.row66.a3 -text "Show\nAdvanced\nParameter\nSettings" \ 4751 -command "toggle_a 3" \ 4752 -fg white -bg black -activeforeground $NBG \ 4753 -activebackground $NFG -font $HV0 4754 pack $p6.row66.a3 -side left -fill x -expand yes 4755 pack $p6.row66 -side top -fill x -expand yes 4756 4757 pack $p10.row6 -side bottom -fill x -expand no 4758 4759 advanced_2 4760 4761 if {$V_Panel_1} { 4762 advanced_1 4763 } 4764 if {$V_Panel_3} { 4765 advanced_3 4766 } 4767### 4768 set vw [PanedWindow $t.bottom -side top -activator button ] 4769 4770 set p9 [$vw add -minsize 100] 4771 set p8 [$vw add -minsize 100] 4772 4773 set s11 [ScrolledWindow $p8.vo -size $ScrollBarSize] ;# vo - verification output 4774 set vo [text $s11.lb -height 6 -width 100 -highlightthickness 3 -bg $CBG -fg $CFG -font $HV1] 4775 $s11 setwidget $vo 4776 4777 set s22 [ScrolledWindow $p9.vr -size $ScrollBarSize] ;# vr - verification reference 4778 set vr [text $s22.lb -height 35 -highlightthickness 0 -font $HV1] 4779 $s22 setwidget $vr 4780 4781 pack $s11 -fill both -expand yes 4782 pack $s22 -fill both -expand yes 4783 pack $vw -fill both -expand yes 4784 4785 $vo insert end "verification result:\n" 4786 $vr insert end "model source:\n" 4787} 4788 4789proc save_in {v} { 4790 global vo 4791 4792 set f [$v get] 4793 if {$f == ""} { 4794 return 4795 } 4796 add_log "save verification output in $f" 0 4797 if [ catch {set fd [open $f w]} errmsg ] { 4798 add_log $errmsg 0 4799 return 4800 } 4801 puts $fd [$vo get 0.0 end] 4802 catch { close $fd } 4803} 4804 4805proc do_clear {} { 4806 global vo 4807 $vo delete 0.0 end 4808} 4809 4810proc output_filters {x} { 4811 global TBG TFG 4812 4813 set fl $x.filters 4814 frame $fl -bg $TBG 4815 pack $fl -padx 1 -pady 1 -side left -fill both -expand no 4816 4817 label $fl.lbl -text "Output Filtering (reg. exps.)" -relief raised -bg $TBG -fg $TFG 4818 pack $fl.lbl -side top -fill x -expand no 4819 4820 add_frame $fl.pids "process ids:" 4821 add_frame $fl.qids "queue ids:" 4822 add_frame $fl.vars "var names:" 4823 add_frame $fl.track "tracked variable:" 4824 add_frame $fl.scale "track scaling:" 4825} 4826 4827proc find_trail {e} { 4828 set ftypes { 4829 {{Spin Trail File Format} {.trail} } 4830 {{All Files} *} 4831 } 4832 switch -- [set file [tk_getOpenFile -filetypes $ftypes]] "" return 4833 catch { $e delete 0.0 end } 4834 catch { $e insert end $file } 4835} 4836 4837proc setup_controls {x} { 4838 global TBG TFG NBG NFG 4839 4840 frame $x.run -bg $TBG 4841 pack $x.run -padx 1 -pady 1 -side left -fill both -expand no 4842 4843 frame $x.run.ctl -bg $TBG 4844 button $x.run.ctl.run -width 12 -text "(Re)Run" \ 4845 -command { run_sim } \ 4846 -bg $NBG -fg $NFG -activebackground $NFG -activeforeground $NBG 4847 4848 button $x.run.ctl.step -width 12 -text "Step Forward" \ 4849 -bg $NBG -fg grey -activebackground $NFG -activeforeground $NBG 4850 4851 button $x.run.ctl.stop -width 12 -text "Stop" \ 4852 -command { set stop 1 } \ 4853 -bg $NBG -fg $NFG -activebackground $NFG -activeforeground $NBG 4854 4855 button $x.run.ctl.back -width 12 -text "Step Backward" \ 4856 -bg $NBG -fg grey -activebackground $NFG -activeforeground $NBG 4857 4858 button $x.run.ctl.reset -width 12 -text "Rewind" \ 4859 -bg $NBG -fg grey -activebackground $NFG -activeforeground $NBG 4860 4861 pack $x.run.ctl -side left -fill both -expand no 4862 pack $x.run.ctl.run \ 4863 $x.run.ctl.stop \ 4864 $x.run.ctl.reset \ 4865 $x.run.ctl.step \ 4866 $x.run.ctl.back \ 4867 -side top -fill y -expand yes 4868} 4869 4870proc inspect_ltl {et ns} { 4871 4872 set x [$et get] 4873 4874 regsub -all {\&\&} "$x" " " y; set x $y 4875 regsub -all {\|\|} "$x" " " y; set x $y 4876 regsub -all {\/\\} "$x" " " y; set x $y 4877 regsub -all {\\\/} "$x" " " y; set x $y 4878 regsub -all {\!} "$x" " " y; set x $y 4879 regsub -all {<->} "$x" " " y; set x $y 4880 regsub -all {\->} "$x" " " y; set x $y 4881 regsub -all {\[\]} "$x" " " y; set x $y 4882 regsub -all {\<\>} "$x" " " y; set x $y 4883 regsub -all {[()]} "$x" " " y; set x $y 4884 regsub -all {\ \ *} "$x" " " y; set x $y 4885 regsub -all { U} "$x" " " y; set x $y 4886 regsub -all { V} "$x" " " y; set x $y 4887 regsub -all { X} "$x" " " y; set x $y 4888 4889 set predefs " np_ true false " 4890 4891 set k [split $x " "] 4892 set j [llength $k] 4893 set line [$ns get 0.0 end] 4894 for {set i 0} {$i < $j} {incr i} { 4895 if {[string length [lindex $k $i]] > 0 \ 4896 && [string first " [lindex $k $i] " $predefs] < 0} { 4897 set pattern "#define [lindex $k $i]" 4898 if {[string first $pattern $line] < 0} { 4899 catch { 4900 $ns insert end "$pattern\t?\n" 4901 } 4902 set line [$ns get 0.0 end] 4903 } } } 4904} 4905 4906set ltl_cnt 0 4907proc ltl_log {s} { 4908 global ltl_cnt log_pan 4909 4910 incr ltl_cnt 4911 $log_pan insert end "$ltl_cnt $s\n" 4912 $log_pan yview end 4913 update 4914} 4915 4916proc gen_claim {et nc ns} { 4917 global negate_ltl 4918 4919 inspect_ltl $et $ns 4920 set formula [$et get] 4921 4922 if {$negate_ltl == "1"} { 4923 set formula "!($formula)" 4924 } 4925 4926 $nc delete 0.0 end 4927 4928 catch { 4929 set fd [open "|spin -f \"($formula)\"" r] 4930 while {[eof $fd] == 0 && [gets $fd line] > -1} { 4931 $nc insert end $line\n 4932 } 4933 catch "close $fd" 4934 } 4935} 4936 4937proc clear_ltl {t} { 4938 global sym_pan nvr_pan note_pan 4939 4940 $t.left.frm.tmp delete 0 end 4941 $t.left.frm.ent delete 0 end 4942 $sym_pan delete 0.0 end 4943 $nvr_pan delete 0.0 end 4944 $note_pan delete 0.0 end 4945 4946 ltl_log "clear" 4947} 4948 4949proc help_ltl {} { 4950 ltl_log "\tLTL Help" 4951 ltl_log "\tYou can load an LTL template with a previously saved LTL" 4952 ltl_log "\tformula from a file via the Browse button on the upper" 4953 ltl_log "\tright of the LTL Property Manager panel." 4954 ltl_log "" 4955 ltl_log "\tDefine a new LTL formula using lowercase names for the" 4956 ltl_log "\tpropositional symbols, for instance:" 4957 ltl_log "\t [] (p U q)" 4958 ltl_log "\tThe formula expresses either a positive (desired) or a" 4959 ltl_log "\tnegative (undesired) property of the model. A positive" 4960 ltl_log "\tproperty is negated automatically by the translator to" 4961 ltl_log "\tconvert it in a never claim (which expresses the" 4962 ltl_log "\tcorresponding negative property (the undesired behavior" 4963 ltl_log "\tthat is claimed 'never' to occur)." 4964 ltl_log "" 4965 ltl_log "\tYou can also avoid the use of propositional symbols by" 4966 ltl_log "\tusing embedded expressions in curly braces, e.g., instead" 4967 ltl_log "\tof defining" 4968 ltl_log "\t #define p (nr_leaders > 0)" 4969 ltl_log "\tand using p as a propositional symbol in the LTL formula" 4970 ltl_log "\t <>\[\] p" 4971 ltl_log "\tyou can also use an embedded expression as follows:" 4972 ltl_log "\t <>\[\] {nr_leaders > 0}" 4973 ltl_log "" 4974 ltl_log "\tWhen you type a <Return> or hit the <click to generate> button" 4975 ltl_log "\tat the bottom of the screen, the formula is converted into" 4976 ltl_log "\ta never-claim, which can be imported into a verification on the" 4977 ltl_log "\tVerification Panel (or saved in a template file for later)." 4978 ltl_log "" 4979 ltl_log "\tIf you're using propositional symbols (p, q, etc.) a definition" 4980 ltl_log "\tfor each symbol used must be given in the top window (macros)" 4981 ltl_log "\tThese definitions become part of the LTL template." 4982 ltl_log "\tEnclose the symbol definitions in round braces, for instance:" 4983 ltl_log "" 4984 ltl_log "\t#define p (a > b)" 4985 ltl_log "\t#define q (len(q) < 5)" 4986 ltl_log "" 4987 ltl_log "\tValid temporal logic operators are:" 4988 ltl_log "\t \[\] Always (no space between \[ and \])" 4989 ltl_log "\t <> Eventually (no space between < and >)" 4990 ltl_log "\t U (Strong) Until" 4991 ltl_log "\t V The Dual of Until: (p V q) == !(!p U !q)" 4992 ltl_log "\t" 4993 ltl_log "\t All operators are left-associative." 4994 ltl_log "\t" 4995 ltl_log "\tBoolean Operators:" 4996 ltl_log "\t && Logical And (alternative form: /\\, no spaces)" 4997 ltl_log "\t ! Logical Negation" 4998 ltl_log "\t || Logical Or (alternative form: \\/, no spaces)" 4999 ltl_log "\t -> Logical Implication" 5000 ltl_log "\t <-> Logical Equivalence" 5001 ltl_log "" 5002 ltl_log "\tBoolean Predicates:" 5003 ltl_log "\t true, false" 5004 ltl_log "\t any name that starts with a lowercase letter, or" 5005 ltl_log "\t any state expression enclosed in curly braces {...}" 5006 ltl_log "\t" 5007 ltl_log "\tExamples:" 5008 ltl_log "\t \[\] p" 5009 ltl_log "\t !( <> !q )" 5010 ltl_log "\t p U q" 5011 ltl_log "\t p U (\[\] (q U r))" 5012 ltl_log "\t { a + b == 15 } U { qempty(qin) }" 5013 ltl_log "\t" 5014 ltl_log "\tGeneric types of LTL properties:" 5015 ltl_log "\t Invariance: \[\] p" 5016 ltl_log "\t Response: (p -> \<\> q)" 5017 ltl_log "\t Precedence: (p -> (q U r))" 5018 ltl_log "\t Objective: (p -> \<\> (q || r))" 5019 ltl_log "\t" 5020 ltl_log "\t Each of the above 4 generic types of properties" 5021 ltl_log "\t can (and will generally have to) be prefixed by" 5022 ltl_log "\t temporal operators such as" 5023 ltl_log "\t \[\], \<\>, \[\]\<\>, \<\>\[\]" 5024 ltl_log "\t The last (objective) property can be read to mean" 5025 ltl_log "\t that 'p' is a trigger, or 'enabling' condition that" 5026 ltl_log "\t determines when the requirement becomes applicable" 5027 ltl_log "\t (e.g. the sending of a new data message); then 'q'" 5028 ltl_log "\t can be the fullfillment of the requirement (e.g." 5029 ltl_log "\t the arrival of the matching acknowledgement), and" 5030 ltl_log "\t 'r' could be a discharging condition that voids the" 5031 ltl_log "\t applicability of the check (an abort condition)." 5032} 5033 5034proc put_t_name {t file} { 5035 5036 if {[string first "[pwd]/" $file] == 0} { 5037 set prf [string length "[pwd]/"] 5038 set file [string range $file $prf end] 5039 } 5040 5041 $t.left.frm.tmp delete 0 end 5042 $t.left.frm.tmp insert insert "$file" 5043} 5044 5045proc dump_contents {s fd w} { 5046 puts $fd "===start $s===" 5047 puts $fd [$w get 0.0 end] 5048 puts $fd "===end $s===" 5049} 5050 5051proc hunt_for {s fd} { 5052 5053 while {[gets $fd line] > -1} { 5054 if {[string first "$s" $line] >= 0} { 5055 return "$line" 5056 } 5057 } 5058 add_log "restore: $s not found" 0 5059 return "" 5060} 5061 5062proc get_contents {s fd w} { 5063 set found 0 5064 5065 if {[hunt_for "===start $s===" $fd] == ""} { 5066 catch { close $fd } 5067 return 0 5068 } 5069 $w delete 0.0 end 5070 5071 set found 0 5072 while {[gets $fd line] > -1} { 5073 if {[string first "===end $s===" $line] == 0} { 5074 set found 1 5075 break 5076 } else { 5077 $w insert end $line\n 5078 } } 5079 if {$found == 0} { 5080 add_log "restore: end tag $s not found" 0 5081 catch { close $fd } 5082 return 0 5083 } 5084 return 1 5085} 5086 5087proc get_field {s fd e} { 5088 5089 set want [hunt_for $s $fd] 5090 if {$want == ""} { 5091 add_log "restore: no field $s" 0 5092 return 0 5093 } 5094 set x [string last "\t" $want] 5095 incr x 5096 $e delete 0 end 5097 $e insert end [string range $want $x end] 5098} 5099 5100proc get_var {s fd} { 5101 5102 set want [hunt_for $s $fd] 5103 if {$want == ""} { 5104 add_log "restore: no var $s" 0 5105 return 0 5106 } 5107 set x [string last "\t" $want] 5108 incr x 5109 return [string range $want $x end] 5110} 5111 5112proc restore_session {} { 5113 global Fname Sname twin vwin qwin swin clog x 5114 5115 set ftypes { 5116 {{iSpin Session Format} {.isf} } 5117 {{All Files} *} 5118 } 5119 switch -- [set f [tk_getOpenFile -filetypes $ftypes]] "" return 5120 5121 if [catch {set fd [open "$f" r]} errmsg] { 5122 add_log $errmsg 1 5123 return 5124 } 5125 if {[gets $fd line] <= -1} { 5126 add_log "restore_session: empty file" 1 5127 return 5128 } 5129# Edit/View 5130 set nx [string first "\t" $line] 5131 if {[string first "Fname" $line] != 0 || $nx != 5} { 5132 add_log "$f is not an ispin session file" 1 5133 add_log "first line is: $line at: [string first "Fname" $line] x: $nx" 0 5134 return 5135 } 5136 incr nx 5137 set Fname [string range $line $nx end] 5138 wm title . "$Fname" 5139 5140 if {[get_contents "Model Spec" $fd $twin] == 0} { return } 5141 if {[get_contents "Model Log" $fd $clog] == 0} { return } 5142 5143# Simulate 5144global l_typ msc_full var_vals 5145 5146 get_field "Seed" $fd $x.sms.rnd.fld2 ;# random seed value 5147 get_field "Trail" $fd $x.sms.int.fld4 ;# error trail name 5148 get_field "SkipStep" $fd $x.sms.skp.ent ;# steps skipped 5149 get_field "MaxStep" $fd $x.sms.ub.ent ;# max steps 5150 5151 set var_vals [get_var "VarVals" $fd] ;# variable values 5152 set l_typ [get_var "FullQ" $fd] ;# block/loses choice 5153 set msc_full [get_var "MSC_Full" $fd] ;# MSC+stmnt boolean 5154 5155 get_field "MaxText" $fd $x.afq.max.me ;# MSC max text width 5156 get_field "Delay" $fd $x.afq.delay.me ;# MSC update delay 5157 get_field "Pids" $fd $x.filters.pids.ent ;# process ids 5158 get_field "Qids" $fd $x.filters.qids.ent ;# queue ids 5159 get_field "Vars" $fd $x.filters.vars.ent ;# var names 5160 get_field "Track" $fd $x.filters.track.ent ;# tracked var 5161 get_field "Scale" $fd $x.filters.scale.ent ;# track scaling 5162 5163 if {[get_contents "Data" $fd $vwin] == 0} { return } 5164 if {[get_contents "Sim" $fd $swin] == 0} { return } 5165 if {[get_contents "Queues" $fd $qwin] == 0} { return } 5166 5167# LTL 5168global nvr_pan note_pan sym_pan ltl_main 5169global negate_ltl 5170global LTL_Panel 5171 5172 set LTL_Panel [get_var "LTL_Panel" $fd] 5173 5174 if {$LTL_Panel} { 5175 get_field "Formula" $fd $ltl_main.left.frm.ent 5176 get_field "Template" $fd $ltl_main.left.frm.tmp 5177 5178 set negate_ltl [get_var "All" $fd] ;# all/no executions 5179 5180 if {[get_contents "Symbols" $fd $sym_pan] == 0} { return } 5181 if {[get_contents "Notes" $fd $note_pan] == 0} { return } 5182 if {[get_contents "Claim" $fd $nvr_pan] == 0} { return } 5183 } 5184 5185# Verification 5186global p_mode a_mode e_mode x_mode f_mode s_mode q_mode 5187global cc_mode ma_mode c_mode estop bf_mode po_mode 5188global bc_mode it_mode u_mode sv_mode peg vranges 5189global vpanel vo 5190 set a_mode [get_var "a_mode" $fd] 5191 set bc_mode [get_var "bc_mode" $fd] 5192 5193 get_field "bc_bound" $fd $vpanel.top.third.rowB.ent 5194 5195 set bf_mode [get_var "bf_mode" $fd] 5196 set c_mode [get_var "c_mode" $fd] 5197 set cc_mode [get_var "cc_mode" $fd] 5198 set e_mode [get_var "e_mode" $fd] 5199 set estop [get_var "estop" $fd] 5200 set f_mode [get_var "f_mode" $fd] 5201 set it_mode [get_var "it_mode" $fd] 5202 set ma_mode [get_var "ma_mode" $fd] 5203 set p_mode [get_var "p_mode" $fd] 5204 set peg [get_var "peg" $fd] 5205 set po_mode [get_var "po_mode" $fd] 5206 set q_mode [get_var "q_mode" $fd] 5207 set s_mode [get_var "s_mode" $fd] 5208 set sv_mode [get_var "sv_mode" $fd] 5209 set u_mode [get_var "u_mode" $fd] 5210 set vranges [get_var "vranges" $fd] 5211 set x_mode [get_var "x_mode" $fd] 5212 5213global vpanel vo V_Panel_3 5214 5215 if {$V_Panel_3} { 5216 get_field "vrow0" $fd $vpanel.top.right.row0.ent ;# phys mem 5217 get_field "vrow1" $fd $vpanel.top.right.row1.ent ;# state space size 5218 get_field "vrow2" $fd $vpanel.top.right.row2.ent ;# max depth 5219 get_field "vrow3" $fd $vpanel.top.right.row3.ent ;# nr hashfcts 5220 get_field "vrow4" $fd $vpanel.top.right.row4.ent ;# MA size 5221 get_field "vrow5" $fd $vpanel.top.right.row5.ent ;# extra spin options 5222 get_field "vrow6" $fd $vpanel.top.right.row6.ent ;# extra cc options 5223 get_field "vrow7" $fd $vpanel.top.right.row7.ent ;# extra pan options 5224 } 5225 5226 if {[get_contents "VerOut" $fd $vo] == 0} { return } 5227 5228# Swarm 5229global spanel so sr 5230 5231 get_field "srow0" $fd $spanel.top.left.row0.e0 ;# min hashfcts 5232 get_field "srow1" $fd $spanel.top.left.row1.e0 ;# max hashfcts 5233 get_field "srow2" $fd $spanel.top.left.row2.e0 ;# min search depth 5234 get_field "srow3" $fd $spanel.top.left.row3.e0 ;# max search depth 5235 get_field "srow4" $fd $spanel.top.left.row4.e0 ;# nr cpus local 5236 get_field "srow5" $fd $spanel.top.left.row5.e0 ;# nr cpus remote 5237 get_field "srow6" $fd $spanel.top.left.row6.e0 ;# max mem per run 5238 get_field "srow7" $fd $spanel.top.left.row7.e0 ;# max runtime 5239 5240 get_field "srow8" $fd $spanel.top.middle.row8.e1 ;# hash-factor 5241 get_field "srow9" $fd $spanel.top.middle.row9.e1 ;# statevector size in bytes 5242 get_field "srow10" $fd $spanel.top.middle.row10.e1 ;# exploration speed 5243 5244 get_field "srow11" $fd $spanel.top.middle.row11.e1 ;# extra spin args 5245 get_field "srow12" $fd $spanel.top.middle.row12.e1 ;# extra pan args 5246 5247 if {[get_contents "CCopts" $fd $spanel.top.right.row0] == 0} { return } 5248 if {[get_contents "SwSetup" $fd $so] == 0} { return } 5249 if {[get_contents "SwRun" $fd $sr] == 0} { return } 5250 5251 catch { close $fd } 5252 5253 add_log "restored session from file $f" 0 5254} 5255 5256proc save_session {n} { 5257 global Fname Sname twin vwin qwin swin clog x 5258 global l_typ msc_full LTL_Panel 5259 5260 set f "$Sname.isf" ;# ispin session file 5261 if {$n == 1} { set f [tk_getSaveFile -defaultextension .isf] } 5262 if {$f == ""} { return } 5263 5264 if {[string first "." $f] < 0} { 5265 set f "$f.isf" 5266 } 5267 5268 if ![file_ok $f] { return } 5269 if [catch {set fd [open $f w]} errmsg] { 5270 add_log $errmsg 5271 return 5272 } 5273 fconfigure $fd -translation lf ;# no cr at end of line 5274 5275 set Sname $f 5276 5277# Global 5278 # PM save colors/fonts/fontsizes, if modified from default 5279# Edit/View 5280 # PM save width/height logwindow in Edit panel 5281 # but $twin configure -height etc. doesnt seem to capture current size 5282 # set x [$twin configure -height] 5283 # set n [llength $x]; incr n -1 5284 # puts $fd "Height [lindex $x $n]" ;# data not current 5285 5286 # filename 5287 puts $fd "Fname $Fname" 5288 dump_contents "Model Spec" $fd $twin 5289 dump_contents "Model Log" $fd $clog 5290 5291# Simulate 5292 # PM width/height of text and msc/data/sim/queues panels 5293global var_vals 5294 5295 puts $fd "Seed [$x.sms.rnd.fld2 get]" ;# random seed value 5296 puts $fd "Trail [$x.sms.int.fld4 get]" ;# error trail name 5297 puts $fd "SkipStep [$x.sms.skp.ent get]" ;# steps skipped 5298 puts $fd "MaxStep [$x.sms.ub.ent get]" ;# max steps 5299 puts $fd "VarVals $var_vals" ;# variable values 5300 puts $fd "FullQ $l_typ" ;# block/loses choice 5301 puts $fd "MSC_Full $msc_full" ;# MSC+stmnt boolean 5302 puts $fd "MaxText [$x.afq.max.me get]" ;# MSC max text width 5303 puts $fd "Delay [$x.afq.delay.me get]" ;# MSC update delay 5304 puts $fd "Pids [$x.filters.pids.ent get]" ;# process ids 5305 puts $fd "Qids [$x.filters.qids.ent get]" ;# queue ids 5306 puts $fd "Vars [$x.filters.vars.ent get]" ;# var names 5307 puts $fd "Track [$x.filters.track.ent get]" ;# tracked var 5308 puts $fd "Scale [$x.filters.scale.ent get]" ;# track scaling 5309 5310 dump_contents "Data" $fd $vwin 5311 dump_contents "Sim" $fd $swin 5312 dump_contents "Queues" $fd $qwin 5313 5314# LTL 5315global nvr_pan note_pan sym_pan ltl_main 5316global negate_ltl 5317 5318 puts $fd "LTL_Panel $LTL_Panel" 5319 5320 if {$LTL_Panel} { 5321 # PM width/height of symbol/notes/claim/log panels 5322 5323 puts $fd "Formula [$ltl_main.left.frm.ent get]" 5324 puts $fd "Template [$ltl_main.left.frm.tmp get]" 5325 puts $fd "All $negate_ltl" ;# all/no executions 5326 5327 dump_contents "Symbols" $fd $sym_pan 5328 dump_contents "Notes" $fd $note_pan 5329 dump_contents "Claim" $fd $nvr_pan 5330 } 5331 5332# Verification 5333 # PM width/height of ref and output panels 5334 5335global p_mode a_mode e_mode x_mode f_mode s_mode q_mode 5336global cc_mode ma_mode c_mode estop bf_mode po_mode 5337global bc_mode it_mode u_mode sv_mode peg vranges 5338global vpanel vo V_Panel_3 5339 5340 puts $fd "a_mode $a_mode" 5341 puts $fd "bc_mode $bc_mode" 5342 puts $fd "bc_bound [$vpanel.top.third.rowB.ent get]" 5343 puts $fd "bf_mode $bf_mode" 5344 puts $fd "c_mode $c_mode" 5345 puts $fd "cc_mode $cc_mode" 5346 puts $fd "e_mode $e_mode" 5347 puts $fd "estop $estop" 5348 puts $fd "f_mode $f_mode" 5349 puts $fd "it_mode $it_mode" 5350 puts $fd "ma_mode $ma_mode" 5351 puts $fd "p_mode $p_mode" 5352 puts $fd "peg $peg" 5353 puts $fd "po_mode $po_mode" 5354 puts $fd "q_mode $q_mode" 5355 puts $fd "s_mode $s_mode" 5356 puts $fd "sv_mode $sv_mode" 5357 puts $fd "u_mode $u_mode" 5358 puts $fd "vranges $vranges" 5359 puts $fd "x_mode $x_mode" 5360 5361 if {$V_Panel_3} { 5362 puts $fd "vrow0 [$vpanel.top.right.row0.ent get]" ;# phys mem 5363 puts $fd "vrow1 [$vpanel.top.right.row1.ent get]" ;# state space size 5364 puts $fd "vrow2 [$vpanel.top.right.row2.ent get]" ;# max depth 5365 puts $fd "vrow3 [$vpanel.top.right.row3.ent get]" ;# nr hashfcts 5366 puts $fd "vrow4 [$vpanel.top.right.row4.ent get]" ;# MA size 5367 puts $fd "vrow5 [$vpanel.top.right.row5.ent get]" ;# extra spin options 5368 puts $fd "vrow6 [$vpanel.top.right.row6.ent get]" ;# extra cc options 5369 puts $fd "vrow7 [$vpanel.top.right.row7.ent get]" ;# extra pan options 5370 } 5371 dump_contents "VerOut" $fd $vo 5372 5373# Swarm 5374global spanel so sr 5375 # PM height setup and output panels 5376 5377 puts $fd "srow0 [$spanel.top.left.row0.e0 get]" ;# min hashfcts 5378 puts $fd "srow1 [$spanel.top.left.row1.e0 get]" ;# max hashfcts 5379 puts $fd "srow2 [$spanel.top.left.row2.e0 get]" ;# min search depth 5380 puts $fd "srow3 [$spanel.top.left.row3.e0 get]" ;# max search depth 5381 puts $fd "srow4 [$spanel.top.left.row4.e0 get]" ;# nr cpus local 5382 puts $fd "srow5 [$spanel.top.left.row5.e0 get]" ;# nr cpus remote 5383 puts $fd "srow6 [$spanel.top.left.row6.e0 get]" ;# max mem per run 5384 puts $fd "srow7 [$spanel.top.left.row7.e0 get]" ;# max runtime 5385 5386 puts $fd "srow8 [$spanel.top.middle.row8.e1 get]" ;# hash-factor 5387 puts $fd "srow9 [$spanel.top.middle.row9.e1 get]" ;# statevector size in bytes 5388 puts $fd "srow10 [$spanel.top.middle.row10.e1 get]" ;# exploration speed 5389 5390 puts $fd "srow11 [$spanel.top.middle.row11.e1 get]" ;# extra spin args 5391 puts $fd "srow12 [$spanel.top.middle.row12.e1 get]" ;# extra pan args 5392 5393 dump_contents "CCopts" $fd $spanel.top.right.row0 ;# compilation options 5394 dump_contents "SwSetup" $fd $so ;# contents setup output panel? 5395 dump_contents "SwRun" $fd $sr ;# contents swarm output panel? 5396 5397 catch "close $fd" 5398 add_log "session save in $Sname" 1 5399} 5400 5401proc save_spec {n} { 5402 global Fname twin 5403 5404 set f $Fname 5405 if {$n == 1} { set f [tk_getSaveFile] } 5406 if {$f != ""} { writeoutfile $f } 5407} 5408 5409proc save_ltl {t} { 5410 global sym_pan note_pan nvr_pan 5411 5412 if {[$t.left.frm.ent get] == ""} { 5413 ltl_log "error: save, no formula specified" 5414 return 5415 } 5416 gen_claim $t.left.frm.ent $nvr_pan $sym_pan ;# needed for negations 5417 5418 switch -- [set file [eval tk_getSaveFile -initialdir { [pwd] } ]] "" { 5419 ltl_log "error: file select failed" 5420 return 5421 } 5422 if ![file_ok $file] { 5423 ltl_log "error: save, '$file' is not writable" 5424 return 5425 } 5426 5427 if [catch {set fd [open $file w]} errmsg] { return } 5428 5429 puts $fd [string trimright [ $sym_pan get 0.0 end] "\n"] 5430 5431 puts $fd [string trimright " /*\n"] 5432 puts $fd [string trimright " * Formula As Typed: [$t.left.frm.ent get]\n"] 5433 puts $fd [string trimright " */\n"] 5434 puts $fd [string trimright [ $nvr_pan get 0.0 end] "\n"] 5435 5436 puts $fd [string trimright "#ifdef NOTES\n"] 5437 puts $fd [string trimright [ $note_pan get 0.0 end] "\n"] 5438 puts $fd [string trimright "#endif\n"] 5439 5440 close $fd 5441 5442 put_t_name $t $file 5443 ltl_log "saved in '[$t.left.frm.tmp get]'" 5444} 5445 5446proc load_from {t file} { 5447 global negate_ltl sym_pan nvr_pan note_pan 5448 5449 if [catch {set fd [open $file r]} errmsg] { 5450 ltl_log "error: cannot open '$file'" 5451 return 5452 } 5453 5454 clear_ltl $t 5455 put_t_name $t $file 5456 5457 set inside_claim 0 5458 set inside_notes 0 5459 while {[gets $fd line] > -1} { 5460 if {$inside_claim} { 5461 $nvr_pan insert end $line\n 5462 if {[string first "\}" $line] == 0} { 5463 set inside_claim 0 5464 } 5465 continue 5466 } 5467 if {$inside_notes} { 5468 if {[string first "#endif" $line] == 0} { 5469 set inside_notes 0 5470 continue 5471 } 5472 $note_pan insert end $line\n 5473 continue 5474 } 5475 if {[string first "#define" $line] >= 0} { 5476 $sym_pan insert end $line\n 5477 continue 5478 } 5479 if {[string first "* Formula As Typed: " $line] > 0} { 5480 set sof [string first ":" $line] 5481 incr sof 2 5482 $t.left.frm.ent insert end [string range $line $sof end] 5483 continue 5484 } 5485 if {[string first "never" $line] == 0} { 5486 set inside_claim 1 5487 if {[string first "/* !(" $line] > 0} { 5488 set negate_ltl 1 5489 } 5490 $nvr_pan insert end $line\n 5491 continue 5492 } 5493 if {[string first "#ifdef NOTES" $line] >= 0} { 5494 set inside_notes 1 5495 } 5496 if {[string first "#ifdef RESULT" $line] >= 0} { 5497 set inside_notes 1 5498 $note_pan insert end "==Verification Result===\n" 5499 } 5500 } 5501 5502 catch " close $fd " 5503 ltl_log "load '$file'" 5504} 5505 5506proc load_ltl {t} { 5507 5508 set ftypes { 5509 {{Spin LTL template format} {.ltl} } 5510 {{All Files} *} 5511 } 5512 switch -- [set file [tk_getOpenFile -filetypes $ftypes]] "" return 5513 5514 load_from $t $file 5515} 5516 5517proc reopen_ltl {t} { 5518 load_from $t [$t.left.frm.tmp get] 5519} 5520 5521proc ltl_panel {t} { 5522 global NBG NFG TBG TFG CBG CFG LTLbg HV0 HV1 negate_ltl ltl_main 5523 global sym_pan note_pan nvr_pan log_pan ScrollBarSize Fname 5524 5525 set ltl_main $t 5526 $t configure -background $LTLbg 5527 5528 frame $t.left 5529 pack $t.left -side top -fill both -expand yes 5530 5531 frame $t.left.frm -bg $TBG 5532 label $t.left.frm.lbl -text "LTL Formula:" -bg $TBG -fg $TFG -font $HV1 5533 entry $t.left.frm.ent -width 60 -relief sunken 5534 label $t.left.frm.tnm -text "Template File:" -bg $TBG -fg $TFG 5535 entry $t.left.frm.tmp -width 30 -relief sunken -bg white -fg $TFG 5536 button $t.left.frm.browse -text "browse" -command "load_ltl $t" \ 5537 -relief raised -bg $TBG -fg $TFG 5538 $t.left.frm.tmp insert insert "(use save/load)" 5539 5540 set et $t.left.frm.ent 5541 5542 frame $t.left.op -bg $TBG 5543 pack $t.left.op -side top -fill x -expand no 5544 set alw {\[\] } 5545 set eve {\<\> } 5546 pack [label $t.left.op.s0 -text "Valid Operators: " -bg $TBG -fg $TFG -relief flat] -side left 5547 pack [button $t.left.op.always -bg $CBG -fg $CFG -font $HV0 -text " always: \[\] " \ 5548 -command "$et insert insert \"$alw \""] -side left 5549 pack [button $t.left.op.event -bg $CBG -fg $CFG -font $HV0 -text " eventually: \<\> " \ 5550 -command "$et insert insert \"$eve \""] -side left 5551 pack [button $t.left.op.until -bg $CBG -fg $CFG -font $HV0 -text " strong-until: U " \ 5552 -command "$et insert insert \" U \""] -side left 5553 pack [button $t.left.op.impl -bg $CBG -fg $CFG -font $HV0 -text " implication: -> " \ 5554 -command "$et insert insert \" -> \""] -side left 5555 pack [button $t.left.op.and -bg $CBG -fg $CFG -font $HV0 -text " and: && " \ 5556 -command "$et insert insert \" && \""] -side left 5557 pack [button $t.left.op.or -bg $CBG -fg $CFG -font $HV0 -text " or: || " \ 5558 -command "$et insert insert \" || \""] -side left 5559 pack [button $t.left.op.not -bg $CBG -fg $CFG -font $HV0 -text "negation: ! " \ 5560 -command "$et insert insert \" ! \""] -side left 5561 5562 button $t.left.op.open -text "ReLoad" -command "reopen_ltl $t" \ 5563 -activebackground $NFG -activeforeground $NBG \ 5564 -relief raised -bg $NBG -fg $NFG -font $HV0 5565 button $t.left.op.save -text "Save as" -command "save_ltl $t" \ 5566 -activebackground $NFG -activeforeground $NBG \ 5567 -relief raised -bg $NBG -fg $NFG -font $HV0 5568 button $t.left.op.clear -text "Clear" -command "clear_ltl $t" \ 5569 -activebackground $NFG -activeforeground $NBG \ 5570 -relief raised -bg $NBG -fg $NFG -font $HV0 5571 button $t.left.op.help -text "Help" -command "help_ltl" \ 5572 -activebackground $NFG -activeforeground $NBG \ 5573 -relief raised -bg $NBG -fg $NFG -font $HV0 5574 5575 pack $t.left.op.help $t.left.op.clear $t.left.op.save $t.left.op.open \ 5576 -side right -fill x -expand no 5577 pack $t.left.frm.lbl $t.left.frm.ent \ 5578 -side left -fill x -expand no 5579 pack $t.left.frm.browse $t.left.frm.tmp $t.left.frm.tnm \ 5580 -side right -fill x -expand no 5581 pack $t.left.frm -fill x -expand no 5582 5583 frame $t.left.hlds -bg $TBG 5584 label $t.left.hlds.nm -text "Property holds for:" -bg $TBG -fg $TFG 5585 radiobutton $t.left.hlds.yes -text "all executions (expresses desired behavior)" \ 5586 -variable negate_ltl -value 0 -bg $TBG -fg $TFG 5587 radiobutton $t.left.hlds.non -text "no executions (expresses error behavior)" \ 5588 -variable negate_ltl -value 1 -bg $TBG -fg $TFG 5589 5590 pack $t.left.hlds -side top -fill x -expand no 5591 pack $t.left.hlds.nm $t.left.hlds.yes $t.left.hlds.non \ 5592 -side left -fill x -expand no 5593 5594 label $t.left.spacer1 -height 1 -bg $LTLbg 5595 pack $t.left.spacer1 -side top -fill x -expand no 5596### 5597 set horiz_pw [PanedWindow $t.left.top -side top -activator button ] 5598 set lft [$horiz_pw add] ;# left hand side 5599 set rgt [$horiz_pw add] ;# right hand side 5600 pack $horiz_pw -fill both -expand yes 5601 5602 set ltl_pw [PanedWindow $lft.x -side left -activator button ] 5603 set mp [$ltl_pw add] ;# macros 5604 set np [$ltl_pw add] ;# notes 5605 set cp [$ltl_pw add] ;# claim 5606 5607 set not_pw [PanedWindow $rgt.x -side left -activator button ] 5608 set lp [$not_pw add] ;# log 5609 pack $ltl_pw $not_pw -fill both -expand yes 5610### Macros 5611 set mp_t [label $mp.t -text "Symbol macro-definitions (all symbols used in formula):" \ 5612 -bg $TBG -fg $TFG -font $HV0] 5613 set sw1 [ScrolledWindow $mp.sw1 -size $ScrollBarSize] 5614 set sym_pan [text $sw1.lb -height 4 -font $HV1] 5615 $sw1 setwidget $sym_pan 5616### Notes 5617 set np_t [label $np.n -text "Notes (informal explanation of property):" \ 5618 -bg $TBG -fg $TFG -font $HV0] 5619 set sw3 [ScrolledWindow $np.sw3 -size $ScrollBarSize] 5620 set note_pan [text $sw3.lb -height 4 -font $HV1] 5621 $sw3 setwidget $note_pan 5622### Claim 5623 set cp_t [button $cp.n -text "Never Claim (click to generate):" \ 5624 -bg $TBG -fg $TFG -font $HV0] 5625 set sw5 [ScrolledWindow $cp.sw5 -size $ScrollBarSize] 5626 set nvr_pan [text $sw5.lb -height 4 -font $HV1] 5627 $sw5 setwidget $nvr_pan 5628 $cp.n configure -command "gen_claim $et $nvr_pan $sym_pan" 5629### Log 5630 set sw7 [ScrolledWindow $lp.sw7 -size $ScrollBarSize] 5631 set log_pan [text $sw7.lb -width 60 -relief sunken -bg $CBG -fg $CFG -font $HV1] 5632 $sw7 setwidget $log_pan 5633 5634 pack $mp_t -fill x -expand no 5635 pack $sw1 -fill both -expand yes 5636 5637 pack $np_t -fill x -expand no 5638 pack $sw3 -fill both -expand yes 5639 5640 pack $cp_t -fill x -expand no 5641 pack $sw5 -fill both -expand yes 5642 5643 pack $sw7 -fill both -expand yes 5644 5645 bind $et <Return> " gen_claim $et $nvr_pan $sym_pan" 5646 5647 ltl_log "ltl log" 5648} 5649 5650set scrollxregion 10000 5651set scrollyregion 40000 5652 5653proc simulate_panel {t} { 5654 global x CBG CFG HV0 HV1 ScrollBarSize scrollxregion scrollyregion 5655 global s_typ seed skipstep ubstep l_typ var_vals 5656 global TBG TFG NBG NFG XBB Fname msc_max_w msc_delay 5657 global rwin swin cwin vwin qwin msc msc_full 5658 5659 set pws [PanedWindow $t.pw -side left -activator button ] 5660 5661 set p2 [$pws add -minsize 10] 5662 set p1 [$pws add -minsize 10] 5663 5664 set sf1 [ScrolledWindow $p1.sw -size $ScrollBarSize] 5665 set tbot [text $sf1.lb -highlightthickness 0 -bg $CBG -fg $CFG -font $HV1] 5666 $sf1 setwidget $tbot 5667 5668 set ttop [frame $p2.sw ] ;# we create the ref scrolled text window below 5669 set sf2 $ttop 5670 5671 pack $sf1 $sf2 $pws -fill both -expand yes 5672 5673#### Simulation Mode 5674 set topf [frame $ttop.topf] 5675 pack $topf -pady 2 -side top -fill both -expand yes 5676 5677 frame $topf.left -bg $TBG ;# left side of top frame; there's no right side yet 5678 pack $topf.left -side top -fill both -expand no 5679 5680 set x $topf.left 5681 frame $x.sms -bg $TBG 5682 label $x.sms.fld0 -text "Mode" -relief raised -bg $TBG -fg $TFG 5683 5684 pack $x.sms -padx 1 -pady 1 -side left -fill both -expand no 5685 pack $x.sms.fld0 -side top -fill x -expand no 5686 5687#### Reference Model for Tracking 5688 set mws [PanedWindow $topf.middle -side top -activator button ] 5689 5690 set q0 [$mws add -minsize 10] 5691 set q1 [$mws add -minsize 10] 5692 5693 # bottom part of top frame: model text for tracking 5694 set ref [ScrolledWindow $q0.middle -size $ScrollBarSize] 5695 set rwin [text $ref.lb -highlightthickness 0 -font $HV1] 5696 $ref setwidget $rwin 5697 pack $ref -side left -fill both -expand yes 5698 5699 $rwin insert end "reference to model source $Fname" 5700 5701 set cref [ScrolledWindow $q1.middle -size $ScrollBarSize] 5702 set msc [canvas $cref.right -relief raised \ 5703 -background $XBB -scrollregion "0 0 $scrollxregion $scrollyregion" ] 5704 $cref setwidget $msc 5705 5706 pack $mws -side top -fill both -expand yes 5707 pack $cref -side right -fill both -expand yes 5708 5709 $msc create text 20 10 -text "MSC $msc_full" -fill white 5710 5711 bind $rwin <KeyRelease> { 5712 if {"%K" == "Return"} { 5713 $rwin insert insert "[$rwin index insert] " 5714 $rwin edit modified true 5715 } } 5716 5717 bind $msc <2> "$msc scan mark %x %y" 5718 bind $msc <B2-Motion> "$msc scan dragto %x %y" 5719 5720 5721#### Random 5722 frame $x.sms.rnd -bg $TBG 5723 radiobutton $x.sms.rnd.fld1 -text "Random, with seed: " \ 5724 -variable s_typ -value 0 -bg $TBG -fg $TFG 5725 entry $x.sms.rnd.fld2 -relief sunken -width 12 5726 5727 pack $x.sms.rnd -side top -fill x -expand no 5728 pack $x.sms.rnd.fld1 -side left -fill x -expand no 5729 pack $x.sms.rnd.fld2 -side right -fill x -expand no 5730 5731 $x.sms.rnd.fld2 insert end $seed 5732 5733### Interactive 5734 frame $x.sms.usr -bg $TBG 5735 radiobutton $x.sms.usr.fld -text "Interactive (for resolution of all nondeterminism)" \ 5736 -variable s_typ -value 2 -bg $TBG -fg $TFG 5737 pack $x.sms.usr -side top -fill x -expand no 5738 pack $x.sms.usr.fld -side left -fill x -expand no 5739 5740#### Guided 5741 frame $x.sms.int -bg $TBG 5742 radiobutton $x.sms.int.fld3 -text "Guided, with trail:" \ 5743 -variable s_typ -value 1 -bg $TBG -fg $TFG 5744 entry $x.sms.int.fld4 -relief sunken 5745 button $x.sms.int.fld5 -relief raised -text "browse" \ 5746 -command { find_trail $x.sms.int.fld4 } -bg $TBG -fg $TFG 5747 5748 pack $x.sms.int -side top -fill x -expand no 5749 pack $x.sms.int.fld3 -side left -fill x -expand no 5750 pack $x.sms.int.fld4 -side left -fill x -expand no 5751 pack $x.sms.int.fld5 -side left -fill x -expand no 5752 5753#### Initial Steps 5754 frame $x.sms.skp -bg $TBG 5755 label $x.sms.skp.lbl -text " initial steps skipped:" -bg $TBG -fg $TFG 5756 entry $x.sms.skp.ent -relief sunken -width 12 5757 5758 $x.sms.skp.ent insert end $skipstep 5759 5760 frame $x.sms.ub -bg $TBG 5761 label $x.sms.ub.lbl -text " maximum number of steps:" -bg $TBG -fg $TFG 5762 entry $x.sms.ub.ent -relief sunken -width 12 5763 $x.sms.ub.ent insert end $ubstep 5764 5765 frame $x.sms.vv -bg $TBG 5766 checkbutton $x.sms.vv.xx -variable var_vals \ 5767 -text "Track Data Values (this can be slow)" -bg $TBG -fg $TFG 5768 5769 pack $x.sms.skp -side top -fill x -expand no 5770 pack $x.sms.skp.lbl -side left -fill x -expand no 5771 pack $x.sms.skp.ent -side right -fill x -expand no 5772 5773 pack $x.sms.ub -side top -fill x -expand no 5774 pack $x.sms.ub.lbl -side left -fill x -expand no 5775 pack $x.sms.ub.ent -side right -fill x -expand no 5776 5777 pack $x.sms.vv -side top -fill x -expand no 5778 pack $x.sms.vv.xx -side left -fill x -expand no 5779 5780#### A Full Queue 5781 frame $x.afq -bg $TBG 5782 label $x.afq.fld0 -text "A Full Channel" -relief raised -bg $TBG -fg $TFG 5783 5784 pack $x.afq -padx 1 -pady 1 -side left -fill both -expand no 5785 pack $x.afq.fld0 -side top -fill x -expand no 5786#### Blocks/Loses 5787 frame $x.afq.int -bg $TBG 5788 frame $x.afq.int.la -bg $TBG 5789 radiobutton $x.afq.int.la.fld3 -text "blocks new messages" -variable l_typ -value 0 -bg $TBG -fg $TFG 5790 radiobutton $x.afq.int.la.fld4 -text "loses new messages" -variable l_typ -value 1 -bg $TBG -fg $TFG 5791 5792 pack $x.afq.int -side top -fill x -expand no 5793 pack $x.afq.int.la -side left -fill x -expand yes 5794 pack $x.afq.int.la.fld3 -side top -fill x -expand no -anchor w 5795 pack $x.afq.int.la.fld4 -side top -fill x -expand no -anchor w 5796 5797#### MSC 5798 frame $x.afq.ish -bg $TBG 5799 checkbutton $x.afq.ish.is -text "MSC+stmnt" -variable msc_full -bg $TBG -fg $TFG 5800 pack $x.afq.ish.is -side left -fill x -expand no 5801 pack $x.afq.ish -side top -fill x -expand no 5802 5803 frame $x.afq.max -bg $TBG 5804 label $x.afq.max.mx -text "MSC max text width" -bg $TBG -fg $TFG 5805 entry $x.afq.max.me -relief sunken -width 6 5806 pack $x.afq.max.mx $x.afq.max.me -side left -fill x -expand yes 5807 pack $x.afq.max -side top -fill x -expand no 5808 $x.afq.max.me insert end $msc_max_w 5809 5810 frame $x.afq.delay -bg $TBG 5811 label $x.afq.delay.mx -text "MSC update delay" -bg $TBG -fg $TFG 5812 entry $x.afq.delay.me -relief sunken -width 6 5813 pack $x.afq.delay.mx $x.afq.delay.me -side left -fill x -expand yes 5814 pack $x.afq.delay -side top -fill x -expand no 5815 $x.afq.delay.me insert end $msc_delay 5816 5817 5818#### Output Filters 5819 output_filters $x 5820 5821#### Controls 5822 setup_controls $x 5823 5824#### Command executed 5825 frame $x.bgf -bg $TBG 5826 pack $x.bgf -side right -fill both -expand yes 5827 set lwin [label $x.bgf.lbl -text "Background command executed:" -bg $TBG -fg $TFG] 5828 pack $lwin -side top -fill x -expand no 5829 set cwin [text $x.bgf.cmd -height 6 -bg lightgray -fg $TFG -font $HV1] 5830 pack $cwin -side top -fill both -expand yes 5831 button $x.bgf.ps -text "Save in: msc.ps" -font $HV0 \ 5832 -fg black -bg ivory -activeforeground $NBG -activebackground $NFG \ 5833 -command "$msc postscript -file msc.ps -colormode color" 5834 pack $x.bgf.ps -side right -expand no 5835 5836### Simulation output 5837 set bwp [PanedWindow $tbot.pw -side top -activator button ] 5838 5839 set p2 [$bwp add -minsize 10] 5840 set p1 [$bwp add -minsize 10] 5841 set p0 [$bwp add -minsize 10] 5842 5843 set lwp [ScrolledWindow $p1.sw -size $ScrollBarSize] 5844 set swin [text $lwp.lb -highlightthickness 0 -bg $CBG -fg $CFG -font $HV1] 5845 $lwp setwidget $swin 5846 5847 pack $lwp $bwp -fill both -expand yes 5848 5849 $swin insert end "Simulation output" 5850 5851### Data Values 5852 set si3 [ScrolledWindow $p2.sw2 -size $ScrollBarSize] 5853 set vwin [text $si3.lb -width 20 -highlightthickness 0 -bg $CBG -fg $CFG] 5854 $si3 setwidget $vwin 5855 5856 pack $si3 -side right -fill both -expand yes 5857 $vwin insert end "Data Values" 5858 5859 set si4 [ScrolledWindow $p0.sw0 -size $ScrollBarSize] 5860 set qwin [text $si4.qv -width 20 -highlightthickness 0 -bg $CBG -fg $CFG] 5861 $si4 setwidget $qwin 5862 5863 pack $si4 -side top -fill both -expand yes 5864 $qwin insert end "Queues" 5865} 5866 5867proc curp { x } { 5868 global Curp rwin vr 5869 5870 if {$Curp == "Sp"} { 5871 update_master $rwin 5872 } 5873 if {$Curp == "Vp"} { 5874 update_master $vr 5875 } 5876 5877 set Curp $x 5878} 5879 5880proc create_panels {} { 5881 global Curp NBG NFG MFG MBG version xversion HV0 Fname tcl_platform 5882 global LTL_Panel 5883 5884 frame .menu -bg $MFG 5885 label .menu.title -text "$version :: $xversion" -bg $MFG -fg $MBG ;# reversed menu colors 5886 pack append .menu .menu.title {left frame c expand} 5887 pack append . .menu {top frame w fillx} 5888 5889 set pane .f 5890 set nb [NoteBook $pane -bg $NBG -fg $NFG -font $HV0 \ 5891 -activebackground $NFG -activeforeground $NBG -side top] 5892 5893 pack $pane -fill both -expand yes 5894 5895 model_panel [$nb insert end Mp -text " Edit/View " -raisecmd "curp Mp" ] 5896 simulate_panel [$nb insert end Sp -text " Simulate / Replay " -raisecmd "curp Sp; runsim" ] 5897 5898 if {$LTL_Panel} { 5899 ltl_panel [$nb insert end Lp -text " LTL Properties " -raisecmd "curp Lp; runltl" ] 5900 } 5901 verify_panel [$nb insert end Vp -text " Verification " -raisecmd "curp Vp; runveri" ] 5902 swarm_panel [$nb insert end Sw -text " Swarm Run " -raisecmd "curp Sw; runswarm" ] 5903 5904 $nb insert end Hp -text " <Help> " -raisecmd "helper; $pane raise $Curp" 5905 $nb insert end Ss -text " Save Session " -raisecmd "save_session 1; $pane raise $Curp" 5906 $nb insert end Rs -text " Restore Session " -raisecmd "restore_session; $pane raise $Curp" 5907 $nb insert end Qt -text " <Quit> " -raisecmd "cleanup; checked_exit; $pane raise $Curp" 5908 5909 $pane raise Mp ;# default view 5910} 5911 5912proc runltl {} { add_log "ltl property" 1 } 5913proc runswarm {} { add_log "swarm run" 1 } 5914 5915proc runsim {} { 5916 global rwin s_typ Fname 5917 5918 update_ref $rwin 5919 add_log "simulate/replay" 1 5920 5921 if {[catch { set fd [open "$Fname.trail" r]} errmsg]} { 5922 ;# no trail file 5923 } else { 5924 catch { close $fd } 5925 set s_typ 1 5926 } 5927} 5928proc runveri {} { 5929 global vr p_mode 5930 5931 update_ref $vr 5932 add_log "verification" 1 5933 5934 if {[has_label "accept" ""]} { 5935 set p_mode 2 ;# liveness 5936 } else { 5937 if {[has_label "progress" ""]} { 5938 set p_mode 1 ;# liveness 5939 } else { 5940 set p_mode 0 ;# safety 5941 } } 5942 5943} 5944 5945 5946proc bind_lines {into rf} { 5947 global SFG CFG Fname pane 5948 5949 set cnt 0 5950 scan [$into index end] %d numLines 5951 for {set i 1} {$i <= $numLines} { incr i} { 5952 set line [$into get $i.0 $i.end] 5953 set matched "" 5954 regexp {[A-Za-z0-9_\.]+:[0-9]+} $line matched 5955 if {$matched == ""} { continue } 5956 5957 set fn [string first $matched $line] 5958 set char $fn 5959 set fn $i.$fn 5960 incr char [string length $matched] 5961 set splitx [split $matched ":"] 5962 set fnm [lindex $splitx 0] 5963 set lnr [lindex $splitx 1] 5964 5965 set indend $i 5966 append indend "." $char 5967 5968 $into tag add hilite$cnt $fn $indend 5969 $into tag bind hilite$cnt <ButtonPress-1> " 5970 if {\[string compare \"$fnm\" \$Fname] == 0 || \[readinfile \"$fnm\" \]} { 5971 $rf yview -pickplace $lnr.0 5972 catch { $rf tag delete hilite } 5973 $rf tag add hilite $lnr.0 $lnr.end 5974 $rf tag configure hilite -foreground $SFG 5975 } 5976 " 5977 $into tag bind hilite$cnt <Enter> " 5978 $into tag configure hilite$cnt -foreground $SFG 5979 " 5980 $into tag bind hilite$cnt <Leave> " 5981 $into tag configure hilite$cnt -foreground $CFG 5982 " 5983 incr cnt 5984 } 5985} 5986 5987proc queue_update {n} { ;# in separate panel from vars 5988 global QStep Qnm Levels qwin 5989 5990 if { [info exists Levels($n)] == 0 } { 5991 set Levels($n) "-" 5992 } 5993 5994 $qwin delete 0.0 end 5995 $qwin insert end "\[queues, step $Levels($n)\]\n\n" 5996 foreach el [lsort [array names Qnm]] { 5997 catch { 5998 set qc $QStep([list $n $el]) 5999 # set ff [string last ":" $qc] 6000 # incr ff 6001 # set cargo [string range $qc $ff end] 6002 6003 set ff [string first "(" $qc] 6004 set cargo [string range $qc $ff end] 6005 6006 $qwin insert end "q $el :: $cargo\n" 6007 } } 6008} 6009 6010proc step_forw {} { 6011 global curn maxn 6012 6013 if {$curn >= $maxn} { return } 6014 incr curn 6015 var_update $curn 6016 queue_update $curn 6017} 6018 6019proc step_back {} { 6020 global curn maxn 6021 6022 if {$curn <= 1} { return } 6023 incr curn -1 6024 var_update $curn 6025 queue_update $curn 6026} 6027 6028proc rewind {} { 6029 global curn x msc 6030 6031 set curn 1 6032 var_update $curn 6033 queue_update $curn 6034 catch { 6035 $x.run.ctl.step configure -fg gold -command step_forw 6036 $x.run.ctl.back configure -fg gold -command step_back 6037 } 6038 $msc yview moveto 0.0 6039} 6040 6041set ostep 0 6042 6043proc var_update {n} { 6044 global VarStep Varnm swin vwin Levels curn maxn LineNo 6045 global MSC_Y msc msc_w msc_h msc_max_x ostep SFG CFG NFG 6046 6047 set curn $n 6048 6049 if { [info exists Levels($n)] == 0 || $Levels($n) == "-" } { 6050 return 6051 # set Levels($n) "0" 6052 } 6053 6054 $vwin delete 0.0 end 6055 $vwin insert end "\[variable values, step $Levels($n)\]\n\n" 6056 foreach el [lsort [array names Varnm]] { 6057 catch { $vwin insert end " $el = $VarStep([list $n $el])\n" } 6058 } 6059 6060 set showln [expr $LineNo($n) - 1] 6061 if {$showln <= 0} { 6062 return 6063 # set showln 0 6064 } 6065 $swin yview -pickplace $showln 6066 6067 # find closest entry in MSC_Y not larger than lookfor 6068 set lookfor $Levels($n) 6069 set putithere 0 6070 foreach el [array names MSC_Y] { 6071 if {$el < $lookfor} { 6072 if {$el > $putithere} { 6073 set putithere $el 6074 } } } 6075 6076 $msc delete wherearewe 6077 if {[info exists MSC_Y($putithere)] == 0} { 6078 set MSC_Y($putithere) 0 ;# really $msc_min_y - $msc_h 6079 } 6080 set ty [expr $MSC_Y($putithere) + $msc_h] 6081 $msc create line \ 6082 30 $ty \ 6083 [expr $msc_max_x + $msc_w] $ty \ 6084 -width 1 -dash {8 2} -fill red -tags wherearewe 6085 6086 # highlight line in text view: 6087 catch { $swin tag configure bound$ostep -foreground $CFG } 6088 $swin tag configure bound$n -foreground $NFG 6089 set ostep $n 6090} 6091 6092proc file_view {fnm zzz} { 6093 global Fname SFG rwin 6094 6095 if {$fnm != ""} { 6096 if {[string compare "$fnm" $Fname] == 0 || [readinfile "$fnm" ]} { 6097 $rwin yview -pickplace $zzz.0 6098 catch { $rwin tag delete hilite } 6099 $rwin tag add hilite $zzz.0 $zzz.end 6100 $rwin tag configure hilite -foreground $SFG 6101 $rwin yview -pickplace [expr $zzz - 5] 6102 } } 6103} 6104 6105proc put_msc {how sno prno stmnt ss pnm fnm zzz} { 6106 global msc msc_x msc_y msc_w msc_h msc_max_x scrollyregion 6107 global x ProcessLine MSC_Y msc_max_w msc_delay HV0 CBG NFG 6108 global XBG XFG XTX XAR XPR 6109 6110 if {$msc_max_x < $msc_x} { 6111 set msc_max_x $msc_x 6112 } 6113 6114 set msc_max_w [$x.afq.max.me get] 6115 set mw [font measure $HV0 "w"] 6116 set mw [expr $mw * $msc_max_w] 6117 set msc_x [expr ($mw / 2) + $prno * ($msc_w + 10)] 6118 6119 set dx [expr $msc_x + $msc_w / 2 ] 6120 if {[info exists ProcessLine($prno)]} { 6121 $msc create line \ 6122 $dx $ProcessLine($prno) \ 6123 $dx $msc_y -tags session \ 6124 -width 1 -fill $XPR 6125 } else { 6126 $msc create text \ 6127 $dx [expr $msc_y - $msc_h / 2] \ 6128 -text "$pnm:$prno" -fill $XTX -tags session 6129 } 6130 set ProcessLine($prno) [expr $msc_y + $msc_h] 6131 6132 set MSC_Y($sno) $msc_y 6133 6134 if {$how} { 6135 $msc create rectangle \ 6136 $msc_x $msc_y \ 6137 [expr $msc_x + $msc_w] [expr $msc_y + $msc_h] \ 6138 -outline $XBG -fill $XFG -tags session 6139 set tcol $XTX 6140 } else { 6141 set tcol black 6142 } 6143 set stmnt [string trimleft $stmnt "\["] 6144 set stmnt [string trimright $stmnt "\]"] 6145 6146 if {[string length $stmnt] > $msc_max_w} { 6147 set stmnt [string range $stmnt 0 $msc_max_w] 6148 set stmnt "$stmnt..." 6149 } 6150 6151 set nv [$msc create text \ 6152 [expr $msc_x + $msc_w / 2] [expr $msc_y + $msc_h / 2] \ 6153 -text "$stmnt" -font $HV0 -fill $tcol -tags session] 6154 6155 $msc bind $nv <ButtonPress-1> " 6156 var_update $ss 6157 queue_update $ss 6158 file_view {$fnm} $zzz 6159 " 6160 6161 $msc create text \ 6162 15 [expr $msc_y + $msc_h / 2] \ 6163 -text "$sno" -fill $XTX -tags sno ;# sno: step number 6164 6165 catch " $msc yview moveto [expr 1.0 * ($msc_y - 10*$msc_h) / $scrollyregion] " 6166 update 6167 6168 set msc_delay [$x.afq.delay.me get] 6169 if {$msc_delay > 0} { 6170 after $msc_delay 6171 } 6172} 6173 6174proc handle_ipc {qno istype} { 6175 global Qfill Qempty Mbox_x Mbox_y XAR 6176 global msc msc_x msc_y msc_w msc_h 6177 6178 ## connect send to receive 6179 ## just deals with the easy case 6180 ## so far, ie not !! or ?? 6181 6182 if {[info exists Qfill($qno)] == 0} { 6183 set Qfill($qno) 1 6184 set Qempty($qno) 1 6185 } 6186 6187 if {$istype == 1} { ;# send 6188 set Mbox_x([list $Qfill($qno) $qno]) $msc_x 6189 set Mbox_y([list $Qfill($qno) $qno]) [expr $msc_y + $msc_h / 2] 6190 incr Qfill($qno) 6191 } else { ;# recv 6192 set ox $Mbox_x([list $Qempty($qno) $qno]) 6193 set oy $Mbox_y([list $Qempty($qno) $qno]) 6194 set tx $msc_x 6195 set ty [expr $msc_y + $msc_h / 2] 6196 6197 if {$oy != 0 && $oy != 0} { 6198 if {$ox < $tx} { 6199 incr ox $msc_w 6200 } else { 6201 incr tx $msc_w 6202 } 6203## -dash { 4 2 } -width 3 6204 $msc create line $ox $oy $tx $ty -width 1 \ 6205 -fill $XAR -arrow last -arrowshape {3 5 3} -tags session 6206 } 6207 incr Qempty($qno) 6208 } 6209} 6210 6211proc clearup {} { 6212 global Varnm Qnm ProcessLine cwin vwin 6213 global Qfill Qempty Mbox_x Mbox_y 6214 6215 $cwin delete 0.0 end 6216 $vwin delete 0.0 end 6217 6218 catch { 6219 foreach el [array names ProcessLine] { 6220 unset ProcessLine($el) 6221 } } 6222 6223 catch { 6224 foreach el [array names Varnm] { 6225 unset Varnm($el) 6226 } 6227 foreach el [array names Qnm] { 6228 unset Qnm($el) 6229 } } 6230 6231 catch { 6232 foreach el [array names Qfill] { 6233 unset Qfill($el) 6234 } 6235 foreach el [array names Qempty] { 6236 unset Qempty($el) 6237 } } 6238 6239 catch { 6240 foreach el [array names Mbox_x] { 6241 unset Mbox_x($el) 6242 } 6243 foreach el [array names Mbox_y] { 6244 unset Mbox_y($el) 6245 } } 6246} 6247 6248proc lines_touched {} { 6249 global LineTouched Fname rwin NBG 6250 6251 foreach el [array names LineTouched] { 6252 set f [lindex $el 0] 6253 if {$f == $Fname} { 6254 set n [lindex $el 1] 6255 $rwin tag add touched $n.0 $n.end 6256 } } 6257 $rwin tag configure touched -foreground $NBG 6258} 6259 6260proc line_bindings {lnr prno sno line} { 6261 global Levels LineNo step swin SFG CFG msc_full 6262 global Fname rwin step msc_h msc_y LineTouched 6263 6264 set LineNo($step) $lnr 6265 catch { $swin tag remove bound$step 0.0 end } 6266 set ft [string first ":" $line] ;# first colon 6267 set nft [expr $ft - 1] 6268 set Levels($step) [string range $line 0 $nft] 6269 6270 set fnm "" 6271 set zzz 0 6272 6273 set matched "" 6274 regexp {[A-Za-z0-9_\.]+:[0-9]+} $line matched 6275 if {$matched != ""} { 6276 set splitx [split $matched ":"] 6277 set fnm [lindex $splitx 0] 6278 set zzz [lindex $splitx 1] 6279 set LineTouched([list $fnm $zzz]) 1 6280 } 6281 6282 $swin tag add bound$step $lnr.0 $lnr.$ft 6283 6284 if {$matched == ""} { 6285 $swin tag bind bound$step <ButtonPress-1> " 6286 var_update $step 6287 queue_update $step 6288 " 6289 } else { 6290 $swin tag bind bound$step <ButtonPress-1> " 6291 var_update $step 6292 queue_update $step 6293 if {\[string compare \"$fnm\" \$Fname] == 0 || \[readinfile \"$fnm\" \]} { 6294 $rwin yview -pickplace $zzz.0 6295 catch { $rwin tag delete hilite } 6296 $rwin tag add hilite $zzz.0 $zzz.end 6297 $rwin tag configure hilite -foreground $SFG 6298 $rwin yview -pickplace [expr $zzz - 5] 6299 } 6300 " 6301 } 6302 $swin tag bind bound$step <Enter> " 6303 $swin tag configure bound$step -foreground $SFG 6304 " 6305 $swin tag bind bound$step <Leave> " 6306 $swin tag configure bound$step -foreground $CFG 6307 " 6308 6309 if {$msc_full} { 6310 set sos [string first "\[" $line] 6311 if {$sos > 0} { 6312 set stmnt [string range $line $sos end] 6313 if {[string first "!" $stmnt] < 0 \ 6314 && [string first "?" $stmnt] < 0} { 6315 6316 set a [string first "(" $line] 6317 set b [string first ")" $line] 6318 if {$a > 0 && $b > 0} { 6319 incr a 6320 incr b -1 6321 set c [string range $line $a $b] 6322 } else { 6323 set c "--" 6324 } 6325 6326 put_msc 0 $sno $prno $stmnt $step $c $fnm $zzz 6327 incr msc_y $msc_h 6328 } } } 6329} 6330 6331proc var_track {nm vl ts} { 6332 global msc msc_h msc_y o_y o_v 6333 6334 if {$msc_y > $o_y} { 6335 for {set i $o_y} {$i < $msc_y} {incr i $msc_h} { 6336 $msc create line \ 6337 30 $i \ 6338 [expr 30 + $o_v * $ts] $i \ 6339 -width [expr $msc_h - 5] -fill orange -tags vartrack 6340 } } 6341 set o_y $msc_y 6342 set o_v $vl 6343 6344 $msc create line \ 6345 30 $msc_y \ 6346 [expr 30 + $vl * $ts] $msc_y \ 6347 -width [expr $msc_h - 5] -fill orange -tags vartrack 6348} 6349 6350set Choice(0) "" 6351set PlaceMenu "+150+150" 6352set howmany 0 6353 6354proc pickoption {nm} { 6355 global Choice PlaceMenu howmany NBG NFG cwin swin rwin 6356 6357 set howmany 0 6358 catch {destroy .prompt} 6359 toplevel .prompt 6360 wm title .prompt "Select" 6361 wm iconname .prompt "Select" 6362 wm geometry .prompt $PlaceMenu 6363 6364 text .prompt.t -relief raised -bd 2 \ 6365 -width [string length $nm] -height 1 \ 6366 -setgrid 1 6367 pack append .prompt .prompt.t { top expand fillx } 6368 .prompt.t insert end "$nm" 6369 set cnt 0 6370 focus .prompt 6371 foreach i [lsort [array names Choice]] { 6372 if {$Choice($i) != 0} { 6373 incr cnt 6374 pack append .prompt \ 6375 [button .prompt.b$cnt -text "$i: $Choice($i)" \ 6376 -anchor w \ 6377 -bg $NBG -fg $NFG \ 6378 -command "set howmany $i" ] \ 6379 {top expand fillx} 6380 6381 set matched "" 6382 regexp {[A-Za-z0-9_\.]+:[0-9]+} $Choice($i) matched 6383 if {$matched == ""} { continue } 6384 set splitx [split $matched ":"] 6385 set fnm [lindex $splitx 0] 6386 set lnr [lindex $splitx 1] 6387 bind .prompt.b$cnt <Enter> "$rwin yview -pickplace $lnr.0" 6388 } } 6389 pack append .prompt \ 6390 [button .prompt.q -text "quit" \ 6391 -anchor w -bg $NBG -fg $NFG -command {set howmany "q\n"} ] \ 6392 {top expand fillx} 6393 6394 tkwait variable howmany 6395 set PlaceMenu [wm geometry .prompt] 6396 set k [string first "\+" $PlaceMenu] 6397 if {$k > 0} { 6398 set PlaceMenu [string range $PlaceMenu $k end] 6399 } 6400 catch { foreach el [array names Choice] { unset Choice($el) } } 6401 destroy .prompt 6402 $cwin insert end "$howmany " 6403 $swin insert end "Selected: $howmany\n" 6404 return $howmany 6405} 6406 6407proc run_sim {} { 6408 global stop x swin rwin vwin cwin stop l_typ s_typ Fname SPIN maxn 6409 global VarStep Varnm step QStep Qnm SFG CFG Levels LineNo var_vals 6410 global msc msc_x msc_y msc_w msc_h msc_max_x msc_full MSC_Y Choice 6411 6412 set stop 0 6413 update 6414 6415 set seed [$x.sms.rnd.fld2 get] 6416 set skipped [$x.sms.skp.ent get] 6417 set upper [$x.sms.ub.ent get] 6418 set pfilter [$x.filters.pids.ent get] 6419 set vfilter [$x.filters.vars.ent get] 6420 set qfilter [$x.filters.qids.ent get] 6421 set tfilter [$x.filters.track.ent get] 6422 set tscale [$x.filters.scale.ent get] 6423 6424 if {$tscale == ""} { set tscale 1 } 6425 6426 set args "-p -s -r -X -v -n$seed" 6427 6428 if {$var_vals} { set args "$args -l -g" } 6429 6430 if {$skipped > 0} { set args "$args -j$skipped" } 6431 if {$l_typ != 0} { set args "$args -m" } 6432 if {$s_typ == 2} { set args "$args -i" } 6433 if {$s_typ == 1} { 6434 set tname [$x.sms.int.fld4 get] 6435 if {$tname == ""} { 6436 $cwin insert end "error: no trailfile specified\n" 6437 return 6438 } 6439 if [catch {set fo [open "$tname" r]} errmsg] { 6440 $cwin insert end "$errmsg\n" 6441 return 6442 } 6443 catch { close $fo } 6444 6445 set args "$args -k $tname" 6446 # set upper 0 6447 } 6448 if {$upper > 0} { set args "$args -u$upper" } 6449 6450 clearup 6451 6452 set args "$args $Fname" 6453 6454 $cwin insert end "spin $args\n" 6455 6456 set fd [open "|$SPIN $args" r+] 6457 6458 catch "flush $fd" 6459 6460 $swin delete 0.0 end 6461 set step 0 6462 set lnr 1 6463 6464 $msc delete session 6465 $msc delete wherearewe 6466 $msc delete sno 6467 $msc delete vartrack 6468 6469 set msc_x 75 6470 set msc_y 20 6471 set msc_max_x $msc_x 6472 set Banner "" 6473 6474 if {$s_typ == 2} { 6475 catch { foreach el [array names Choice] { unset Choice($el) } } 6476 } 6477 6478 while {$stop == 0 && [eof $fd] == 0 && [gets $fd line] > -1} { 6479 if {$line == ""} { 6480 continue 6481 } 6482 if {[string first "type return to proceed" $line] > 0} { 6483 catch { puts $fd ""; flush $fd } 6484 update 6485 continue 6486 } 6487## interactive mode only: 6488 if {$s_typ == 2} { 6489 if {[string first "Select stmnt" $line] >= 0 \ 6490 || [string first "Select a statement" $line] >= 0} { 6491 set Banner $line 6492 continue 6493 } 6494 if {[string first "choice " $line] >= 0} { 6495 if {[string first " unexecutable" $line] < 0 \ 6496 && [string first " outside range" $line] < 0} { 6497 scan $line " choice %d:" which 6498 set NN [string first ":" $line] 6499 incr NN 2 6500 set what [string range $line $NN end] 6501 set Choice($which) $what 6502 ## $swin insert end "=$which=$what== $line\n" 6503 } 6504 continue 6505 } 6506 if {[string first "Make Selection" $line] >= 0} { 6507 set nr [pickoption $Banner] 6508 catch { puts $fd "$nr"; flush $fd } 6509 if {$nr == "q\n"} { set stop 1 } 6510 continue 6511 } } 6512 6513 set i [string first "<merge" $line] 6514 if {$i > 0} { 6515 incr i -1 6516 set line [string range $line 0 $i] 6517 set line [string trimright $line] 6518 } 6519 6520 set ipc [string first "\[values: " $line] 6521 if {$ipc > 0} { ;# send or receive action 6522 incr ipc 9 6523 set epc [string last "\]" $line] 6524 if {$epc > $ipc} { 6525 incr epc -1 6526 set stmnt [string range $line $ipc $epc] 6527 # eg 5!first,7 6528 set snd [string first "!" $stmnt] 6529 if {$snd > 0} { 6530 incr snd -1 6531 set qno [string range $stmnt 0 $snd] 6532 set istype 1 ;# send 6533 } else { 6534 set rcv [string first "?" $stmnt] 6535 incr rcv -1 6536 set qno [string range $stmnt 0 $rcv] 6537 set istype 2 ;# recv 6538 } 6539 if {$qfilter == "" || [regexp $qfilter $qno] > 0} { 6540 if {[scan $line "%d: proc %d (%s)" sno prno pnm] == 3} { 6541 6542 regexp {[A-Za-z0-9_\.]+:[0-9]+} $line matched 6543 if {$matched != ""} { 6544 set splitx [split $matched ":"] 6545 set fnm [lindex $splitx 0] 6546 set zzz [lindex $splitx 1] 6547 } 6548 6549 if {$pfilter == "" || [regexp $pfilter $prno] > 0} { 6550 set pnm [string trimright $pnm ")"] 6551 put_msc 1 $sno $prno $stmnt [expr $step + 1] $pnm $fnm $zzz 6552 catch { handle_ipc $qno $istype } 6553 incr msc_y $msc_h 6554 } } } 6555 } 6556 continue 6557 } 6558 6559 if {[scan $line "%d: proc %d " sno prno] == 2} { ;# process line: transition info 6560 set nstep [expr $step + 1] 6561 foreach el [array names Varnm] { 6562 if [info exists VarStep([list $step $el])] { 6563 set xx $VarStep([list $step $el]) 6564 set VarStep([list $nstep $el]) $xx 6565 } } 6566 foreach el [array names Qnm] { 6567 if [info exists QStep([list $step $el])] { 6568 set xx $QStep([list $step $el]) 6569 set QStep([list $nstep $el]) $xx 6570 } } 6571 6572 if [info exists LineNo($step)] { 6573 set LineNo($nstep) $LineNo($step) 6574 } else { 6575 set LineNo($nstep) 0 6576 } 6577 incr step 6578 if {$step > $maxn} { set maxn $step } 6579 6580 if {$pfilter == "" || [regexp $pfilter $prno] > 0} { 6581 if {[string first "\[.(goto)\]" $line] > 0 \ 6582 || [string first "goto :" $line] > 0} { 6583 continue 6584 } 6585 $swin insert end "$line\n" 6586 line_bindings $lnr $prno $sno $line 6587 lines_touched ;# update 6588 incr lnr 6589 } 6590 } else { ;# variables, queues, and other info 6591 if {[string first " = " $line] > 0 } { 6592 set isvar [string first "=" $line] 6593 set isvar [expr $isvar + 1] 6594 set varvl [string range $line $isvar end] 6595 set isvar [expr $isvar - 2] 6596 set varnm [string range $line 0 $isvar] 6597 set varnm [string trim $varnm " "] 6598 6599 if {$vfilter == "" || [regexp $vfilter $varnm] > 0} { 6600 set Varnm($varnm) 1 6601 set VarStep([list $step $varnm]) $varvl 6602 var_update $step 6603 if {$tfilter != "" && [regexp $tfilter $varnm] > 0} { 6604 var_track $varnm $varvl $tscale 6605 } 6606 } 6607 } else { ;# not a variable update 6608 ;# check for queue contents 6609 set qstart [string first " queue " $line] 6610 if {$qstart > 0} { 6611 incr qstart 7 6612 set ltail [string range $line $qstart end] 6613 set qend [string first " " $ltail] 6614 set qno [string range $ltail 0 $qend] 6615 if {$qfilter == "" || [regexp $qfilter $qno] > 0} { 6616 set Qnm($qno) 1 6617 set QStep([list $step $qno]) $ltail 6618 queue_update $step 6619 } 6620 } else { 6621 # could be never claim move 6622 set nvr [string first ":never:" $line] 6623 if {$nvr > 0} { 6624 incr nvr 8 6625 set envr $nvr 6626 while {[string is integer [string range $line $envr [expr $envr + 1]]]} { 6627 incr envr 6628 } 6629 set clmnt [string range $line $nvr $envr] 6630 set line " (never) [string range $line $nvr end]" 6631 } 6632 $swin insert end "$line\n"; incr lnr 6633 } } } 6634 } 6635 6636 if {$stop == 1} { 6637 while {[eof $fd] == 0 && [gets $fd line] > -1} { 6638 if {[string first "type return to proceed" $line] > 0} { 6639 puts $fd "q" 6640 flush $fd 6641 break 6642 } } 6643 } 6644 catch "close $fd" 6645 6646 catch { 6647 $x.run.ctl.reset configure -fg gold -command rewind 6648 } 6649 6650 bind_lines $swin $rwin 6651} 6652 6653proc add_log {s c} { 6654 global clog twin cnt 6655 6656 if {$c} { 6657 $clog insert end "$cnt $s\n" 6658 incr cnt 6659 } else { 6660 $clog insert end "$s\n" 6661 } 6662 bind_lines $clog $twin 6663 $clog yview -pickplace end 6664} 6665 6666proc runsyntax {a} { 6667 global twin swin pane 6668 6669 if {[$twin edit modified]} { 6670 set answer [tk_messageBox -icon question -type yesno \ 6671 -message "There are unsaved changes. Save first?" ] 6672 switch -- $answer { 6673 yes { save_spec 0; open_spec 0 } 6674 no { } 6675 } 6676 } 6677 6678 if {$a} { 6679 add_log "redundancies" 1 6680 } else { 6681 add_log "syntax check" 1 6682 } 6683 syntax_check $a $swin 6684} 6685 6686proc cleanup {} { 6687 global Fname RM 6688 catch { eval exec $RM never_claim.tmp } 6689 catch { eval exec $RM $Fname.nvr spinbat.bat dot.tmp dot.out dot.sel pan.tmp } 6690 catch { eval exec $RM pan.t pan.m pan.h pan.c pan.b pan.p pan.pre } 6691 catch { eval exec $RM run.tmp pan.exe pan } 6692} 6693 6694proc syntax_check {a into} { 6695 global clog Fname SPIN Unix 6696 6697 if {$Fname == ""} { 6698 add_log "no model" 0 6699 return 6700 } 6701 6702 set SPINBAT $SPIN ;# default 6703 if {$Unix == 0} { ;# on Windows systems only 6704 if [catch {set fd [open "spinbat.bat" w 0777]} errmsg] { 6705 ;# same as default 6706 } else { 6707 set SPINBAT "./spinbat.bat" ;# avoids windows popping up 6708 puts $fd "@spin %1 %2\n" 6709 catch "close $fd" 6710 } } 6711 6712 set cnt 0 6713 if {$a} { set args "-A" } else { set args "-a" } 6714 catch {eval exec $SPINBAT $args $Fname} err 6715 $into delete 0.0 end 6716 if {$err == ""} { 6717 add_log "spin: nothing to report" 0 6718 } else { 6719 add_log "$err" 0 6720 } 6721 update 6722 cleanup 6723} 6724 6725proc forAllMatches {w pattern} { 6726 global lno SFG 6727 6728 $w tag remove hilite 0.0 end 6729 6730 scan [$w index end] %d numLines 6731 for {set i 1} {$i < $numLines} { incr i} { 6732 $w mark set last $i.0 6733 if {[regexp -indices $pattern \ 6734 [$w get last "last lineend"] indices]} { 6735 $w mark set first \ 6736 "last + [lindex $indices 0] chars" 6737 $w mark set last "last + 1 chars \ 6738 + [lindex $indices 1] chars" 6739 $w tag add hilite $i.0 $i.end 6740 $w tag configure hilite -foreground $SFG 6741 } } 6742 6743 # move to the next line that matches 6744 for {set i [expr $lno+1]} {$i < $numLines} { incr i} { 6745 $w mark set last $i.0 6746 if {[regexp -indices $pattern \ 6747 [$w get last "last lineend"] indices]} { 6748 $w mark set first \ 6749 "last + [lindex $indices 0] chars" 6750 $w mark set last "last + 1 chars \ 6751 + [lindex $indices 1] chars" 6752 $w yview -pickplace [expr $i-5] 6753 set lno $i 6754 return 6755 } } 6756 for {set i 1} {$i <= $lno} { incr i} { 6757 $w mark set last $i.0 6758 if {[regexp -indices $pattern \ 6759 [$w get last "last lineend"] indices]} { 6760 $w mark set first \ 6761 "last + [lindex $indices 0] chars" 6762 $w mark set last "last + 1 chars \ 6763 + [lindex $indices 1] chars" 6764 $w yview -pickplace [expr $i-5] 6765 set lno $i 6766 return 6767 } } 6768 add_log "no match found of \"$pattern\"" 0 6769} 6770 6771proc file_ok {f} { 6772 6773 if {[file exists $f]} { 6774 if {![file isfile $f] || ![file writable $f]} { 6775 add_log "error: file $f is not writable" 0 6776 return 0 6777 } } 6778 return 1 6779} 6780 6781proc update_master {w} { ;# called for rwin and vr 6782 global twin ;# to make w match twin 6783 6784 $twin delete 0.0 end 6785 6786 scan [$w index end] %d numLines 6787 incr numLines -1 6788 for {set i 1} {$i < $numLines} {incr i} { 6789 set line [$w get $i.0 $i.end] 6790 $twin insert end "$line\n" 6791 } 6792 set line [$w get $i.0 $i.end] 6793 if {$line != ""} { 6794 $twin insert end "$line\n" 6795 } 6796} 6797 6798proc update_ref {w} { ;# called for rwin and vr 6799 global twin ;# to make w match twin 6800 6801 $w delete 0.0 end 6802 6803 scan [$twin index end] %d numLines 6804 incr numLines -1 6805 for {set i 1} {$i < $numLines} {incr i} { 6806 set line [$twin get $i.0 $i.end] 6807 $w insert end "$line\n" 6808 } 6809 set line [$w get $i.0 $i.end] 6810 if {$line != ""} { 6811 $twin insert end "$line\n" 6812 } 6813} 6814 6815proc writeoutfile {to} { 6816 global Fname twin 6817 6818 if ![file_ok $to] { return 0 } 6819 6820 if [catch {set fd [open $to w]} errmsg] { 6821 add_log $errmsg 0 6822 return 0 6823 } 6824 fconfigure $fd -translation lf ;# no cr at end of line, just lf 6825 6826 scan [$twin index end] %d numLines 6827 for {set i 1} {$i < $numLines} {incr i} { 6828 set line [$twin get $i.0 $i.end] 6829 if {[scan $line "%d " lnr] == 1} { 6830 set sol [string first "\t" $line] 6831 incr sol 6832 puts $fd [string range $line $sol end] 6833 } else { 6834 if {[string length $line] > 0} { 6835 puts $fd $line 6836 } } } 6837 close $fd 6838 6839 set Fname $to 6840 wm title . $Fname 6841 add_log "<saved $Fname>" 1 6842 6843 return 1 6844} 6845 6846proc readinfile {from} { 6847 global Fname CBG CFG LTL_Panel 6848 global vr twin rwin ltl_main 6849 6850 if [catch {set fd [open $from r]} errmsg] { 6851 add_log "$errmsg" 0 6852 return 0 6853 } 6854 6855# $rwin configure -state normal 6856# $twin configure -state normal 6857# $vr configure -state normal 6858 6859 $rwin delete 0.0 end 6860 $twin delete 0.0 end 6861 $vr delete 0.0 end 6862 6863 set ln 1 6864 while {[gets $fd line] > -1} { 6865 $rwin insert end "$ln $line\n" 6866 $twin insert end "$ln $line\n" 6867 $vr insert end "$ln $line\n" 6868 incr ln 6869 } 6870 6871# $rwin configure -state disabled 6872# $twin configure -state disabled 6873# $vr configure -state disabled 6874 $twin edit modified false 6875 6876 catch { close $fd } 6877 add_log "$from:1" 1 6878 6879 set prf "[pwd]/" 6880 if {[string first $prf $from] == 0} { 6881 set from [string range $from [string length $prf] end] 6882 } 6883 set Fname $from 6884 wm title . "$Fname" 6885 6886 if {$LTL_Panel} { 6887 $ltl_main.left.frm.tmp delete 0 end 6888 if [catch {set fo [open "$Fname.ltl" r]} errmsg] { 6889 # ltl_log "no ltl-file $Fname.ltl" 6890 } else { 6891 catch { close $fo } 6892 $ltl_main.left.frm.tmp insert insert "$Fname.ltl" 6893 reopen_ltl $ltl_main 6894 } } 6895 6896 return 1 6897} 6898 6899proc open_spec {h} { 6900 global Fname x 6901 6902 if {$h == 1} { 6903 set ftypes { 6904 {{Promela File Format} {.pml} } 6905 {{All Files} *} 6906 } 6907 switch -- [set file [tk_getOpenFile -filetypes $ftypes]] "" return 6908 } else { 6909 if {$Fname == ""} { return } 6910 set file $Fname 6911 } 6912 6913 if [readinfile $file] { 6914 set_path $Fname 6915 } 6916 6917 if {$Fname != ""} { 6918 $x.sms.int.fld4 delete 0 end 6919 $x.sms.int.fld4 insert end $Fname.trail 6920 } 6921} 6922 6923proc set_path {f} { 6924 global Fname 6925 6926 set fullpath [split $f /] 6927 set nlen [llength $fullpath] 6928 set Fname [lindex $fullpath [expr $nlen - 1]] 6929 wm title . "$Fname" 6930 set fullpath [lrange $fullpath 0 [expr $nlen - 2]] ;# strip filename 6931 set wd [join $fullpath /] ;# put path back together 6932 catch {cd $wd} 6933} 6934 6935proc symbol_table {} { 6936 global clog SPIN Fname 6937 6938 if {$Fname == ""} { 6939 add_log "no model" 0 6940 return 6941 } 6942 6943 set ST "$SPIN -d $Fname" 6944 6945 catch {set fd [open "|$ST" r]} errmsg 6946 if {$fd == -1} { 6947 $clog insert end "$errmsg\n" 6948 $clog yview end 6949 update 6950 return 6951 } 6952 $clog insert end "Symbol Table Information for $Fname:\n" 6953 while {[gets $fd line] > -1} { 6954 $clog insert end "$line\n" 6955 $clog yview end 6956 update 6957 } 6958 catch { close $fd } 6959} 6960 6961proc helper {} { 6962 global HV0 NBG NFG LTL_Panel 6963 6964 catch {destroy .hlp} 6965 toplevel .hlp -bg black 6966 wm title .hlp "Help with iSpin" 6967 wm iconname .hlp "Help" 6968 wm geometry .hlp 800x450+60+150 6969 6970 set hlp [NoteBook .hlp.x -bg black -fg $NFG -font $HV0 \ 6971 -activebackground $NFG -activeforeground $NBG -side top] 6972 6973 pack .hlp.x -fill both -expand yes 6974 6975 g_hlp [$hlp insert end Gh -text " General " ] 6976 n_hlp [$hlp insert end Nh -text " What is New in 6.0 " ] 6977 m_hlp [$hlp insert end Mh -text " Edit/View? " ] 6978 s_hlp [$hlp insert end Sh -text " Simulation/Replay? " ] 6979 6980 if {$LTL_Panel} { 6981 l_hlp [$hlp insert end Lh -text " LTL Properties? " ] 6982 } 6983 v_hlp [$hlp insert end Vh -text " Verification? " ] 6984 sw_hlp [$hlp insert end Swh -text " Swarm? " ] 6985 session_hlp [$hlp insert end Sessionh -text " Save/Restore Session? " ] 6986 q_hlp [$hlp insert end Qh -text " Quit? " ] 6987 6988 $hlp raise Gh 6989} 6990 6991proc boilerplate {t} { 6992 global version xversion CBG CFG HV1 ScrollBarSize 6993 6994 set x [ScrolledWindow $t.sw -size $ScrollBarSize] 6995 set y [text $x.lb -height 15 -width 100 -highlightthickness 3 -bg $CBG -fg $CFG -font $HV1] 6996 $x setwidget $y 6997 pack $x -fill both -expand yes 6998 return $y 6999} 7000 7001proc n_hlp {t} { 7002 set y [boilerplate $t] 7003 7004 $y insert end "Spin Version 6.0 has a number of new features. 7005 7006- Improved scope rules: 7007 so far, there were only two levels of scope for variable 7008 declarations: global or proctype local. 7009 6.0 supports the more traditional block scope as well: 7010 a variable declared inside an inline definition or inside 7011 a block has scope that is limited to that inline or block. 7012 You can revert to the old scope rules by using spin -O 7013- Multiple never claims: 7014 In 6.0 you can name never claims, by adding a name in 7015 between the keyword 'never' and the opening curly brace of 7016 the never claim body. 7017 This allows you to specify multiple never claims in a single 7018 Spin model. The model checker will still only use one never 7019 claim to perform the verification, but you can choose on the 7020 command line of pan which claim you want to use: pan -N name 7021- Synchronous product of claims: 7022 If multiple never claims are defined, you can use spin to 7023 generate a single claim which encodes the synchronous product 7024 of all never claims defined, using the new option -e: 7025 spin -e spec.pml 7026- Inline ltl properties: 7027 Instead of specifying an explicit never claim, you can now 7028 specify LTL properties directly inline. Any number of named 7029 properties can be provided, and you can again choose which 7030 one should be checked, using the -N command line argument to pan. 7031 Example LTL property: ltl p1 \{ []<>p \} 7032 Inline LTL properties state positive properties to prove, i.e., 7033 they are not negated. (When spin generates the corresponding 7034 never claim, it will perform the negation automatically, so that 7035 it can find counter-examples to the positive property.) 7036- Dot support: 7037 A new option for the executable pan supports the generation of 7038 the state tables in the format accepted by the dot tool from 7039 graphviz: pan -D (the ascii format is still available as pan -d). 7040- Standardized output: 7041 All filename / linenumber references are now in a single standard 7042 format, given as filename:linenumber, which allows postprocessing 7043 tools, like iSpin, to easily hotlink such references to the source. 7044" 7045} 7046 7047proc version_check {y} { 7048 global CURL 7049 7050 set TMP _version_check_.tmp 7051 set URL http://spinroot.com/spin/Src/index.html 7052 7053 if {[auto_execok $CURL] == ""} { 7054 return 7055 } 7056 catch { eval exec $RM $TMP } 7057 catch { eval exec $CURL -s -S $URL -o $TMP } err 7058 if {$err != ""} { 7059 catch { eval exec $RM $TMP } 7060 return 7061 } 7062 set fd -1 7063 catch { set fd [open $TMP r] } 7064 if {$fd != -1} { 7065 while {[gets $fd line] > -1} { 7066 set want [string first "Current Version" $line] 7067 if {$want >= 0} { 7068 set ln [expr $want + [string length "Current Version "]] 7069 set el [string first ":" $line] 7070 $y insert end "The latest Spin Version is: " 7071 $y insert end "[string range $line $ln [expr $el - 1]] " 7072 $y insert end "(visit http://spinroot.com/spin/Bin)\n" 7073 break 7074 } } 7075 catch { close $fd } 7076 } 7077 catch { eval exec $RM $TMP } 7078} 7079 7080proc g_hlp {t} { 7081 global version xversion 7082 7083 set y [boilerplate $t] 7084 7085 $y insert end " $version\n $xversion\n\n" 7086 7087 version_check $y 7088 7089 $y insert end " 7090 Spin is an on-the-fly LTL model checking system for proving properties 7091 of asynchronous software systems, and iSpin is a Graphical User Interface 7092 for Spin written in Tcl/Tk. 7093 7094 Click on one of the above tabs for a more detailed explanation of each 7095 options supported through this interface. 7096 7097 For the latest version of Spin, see: 7098 http://spinroot.com/spin/Bin (precompiled binaries) 7099 or 7100 http://spinroot.com/spin/Src (sources) 7101 7102 For help with Promela, the specification language used by Spin, see: 7103 http://spinroot.com/spin/Man/index.html (overview) 7104 http://spinroot.com/spin/Man/promela.html (manual pages) 7105 7106 For help not covered here and for bug-reports: gholzmann @ acm.org 7107 7108 iSpin works only with Spin Version 6.0.0 or later. 7109 7110 Spin is (c) 1989-2003 Bell Laboratories, Lucent Technologies, Murray Hill, NJ, USA, 7111 Extensions 2003-2010 (c) JPL/Caltech. All rights reserved. 7112 7113 Spin and iSpin are for educational and research purposes only. No guarantee 7114 whatsoever is expressed or implied by the distribution of this code. 7115 7116 Last updated: 4 December 2010. 7117" 7118} 7119 7120proc m_hlp {t} { 7121 7122 set y [boilerplate $t] 7123 7124 $y insert end " 7125 This panel allows you to Open or Save a Promela verification models 7126 The default file extension for Promela models is .pml. 7127 7128 Syntax Check, Redundancy Check, and Symbol Table can be used to produce 7129 the corresponding output in the black log window at the bottom of the panel. 7130 Each command issued by iSpin is actually performed by standard Spin 7131 running in the background, so without Spin (or with the wrong version of 7132 Spin pre 6.0) not much of interest can happen. 7133 7134 Find allows you to locate a search string in the Promela model text. 7135 7136 The Automata View button (in the right side mid panel) 7137 populates the blue canvas with the names of proctypes and never claims. 7138 It does so by first generating and compiling the model checking code, so 7139 if there are syntax errors that prevent compilation, you will see those first. 7140 7141 Click on a name to generate the control-flow graph of the corresponding 7142 state machine. Currently, the text in the graphs does not scale when you zoom 7143 in or out, so this is still of some limited use. 7144 You can scroll the display by holding button 2 (middle button) down 7145 and moving the mouse. 7146" 7147} 7148 7149proc s_hlp {t} { 7150 7151 set y [boilerplate $t] 7152 7153 $y insert end " 7154 The Simulation panel has all options that are relevant for random or guided 7155 simulations of the model. A guided similation uses an error-trail produced 7156 in a Verification or Swarm run to guide the execution. 7157 7158 Run button starts a simulation run 7159 Stop stops it 7160 Rewind rewinds a completed run to the start 7161 7162 Step Forward moves one step forward through an earlier run 7163 Step Back moves one step backwards through an earlier run 7164 7165 The background command executed by Spin to generate the output is shown in the box at the top right. 7166 7167 Clicking on a line of text in the Simulation output panel moves to that line 7168 and updates variable values and queue contents values to that point in the execution. 7169 You can also click on the boxes in an MSC display to achieve the same effect. 7170 7171 The entry box for process ids allows you to define a regular expression of pids 7172 that will be used to restrict the output to only processes with matching pids, 7173 for instance you can use 1|3 to display output for only processes 1 and 3 7174 or use \[^1-3\] to suppress output for processes 1, 2, and 3 7175 7176 The entry box for queue ids similarly allows the definition of a regular expression 7177 filter for operations on channels. 7178 7179 The entry box for var names allows you to restrict the output in the Data Values 7180 panel to only variable names matching the regular expression given 7181 7182 The entry box for tracked variable is an experimental option to display a bar in 7183 the MSC panel indicating the size of the variable specified -- the size of the 7184 bar can be scaled with the value given in the track scaling box (e.g., 10 or 0.01). 7185" 7186} 7187 7188proc l_hlp {t} { 7189 7190 set y [boilerplate $t] 7191 7192 $y insert end " 7193 Define an LTL formula in the top box, using the black buttons as 7194 short-hands if needed. Define any necessary symbols as macros in 7195 the Symbols panel, add notes to explain what it is you are trying 7196 to express in the Notes panel and then click the Never Claim bar 7197 (or type return in the Formula entry box) to generate the never claim. 7198 7199 You can save a filled in Properties panel as a template with the Save as button, 7200 and you can (re)load the contents of this panel from an earlier template by 7201 giving a file name in the Template file entry box (top right) and clicking ReLoad. 7202 7203 You can load an LTL template with a previously saved LTL 7204 formula from a file via the Browse button on the upper 7205 right of the LTL Property Manager panel. 7206 7207 See also the Help button on the far right on this panel -- with more detailed guidance. 7208" 7209} 7210 7211proc v_hlp {t} { 7212 7213 set y [boilerplate $t] 7214 7215 $y insert end " 7216 Many options are available here; the purpose of most will be clear from the labels. 7217 7218 A good practice is to go through the options from left to right: 7219 first choosing the type of verification to be done 7220 then what types of error trails you want to see 7221 next the specific type of search to be done (leave it at the default 7222 setting if you can't decide) 7223 next choose a storage mode (again, keep the default if you don't 7224 have a good reason to change it). the options other than exhaustive 7225 are there just to help you reduce memory. 7226 The panel at the far right allows you to provide more detailed parameters. 7227 each of these parameters comes with a short explanation -- press the 7228 'explain' button next to the parameter to check this. 7229 7230 Run generates and compiles the model checker and will execute it (if no errors 7231 prevent the compilation). You can interrupt a long running verification run with the 7232 Stop button. 7233 7234 Use the Help button (on the far right, in the middle) gives more detailed information 7235 on methods to reduce verification complexity. 7236" 7237} 7238 7239proc sw_hlp {t} { 7240 7241 set y [boilerplate $t] 7242 7243 $y insert end " 7244 This panel allows you to configure a Swarm verification run, which can be quite effective 7245 for large models. You specify the maximum runtime and the number of CPU cores 7246 to use (do not exceed the number of cores on your system). To use this option, 7247 you must have the swarm preprocessor installed on your system. 7248 7249 You can download swarm from: http://spinroot.com/swarm 7250" 7251} 7252 7253proc session_hlp {t} { 7254 7255 set y [boilerplate $t] 7256 7257 $y insert end " 7258 Save Session: 7259 Saves the state and contents of *all* panels and selections made, 7260 as well as all textual outputs displayed. 7261 7262 The data is recorded in a session snapshot file with file extension .isf 7263 7264 Restore Session: 7265 Restores the iSpin displays and selections to the a previously saved state." 7266} 7267 7268proc q_hlp {t} { 7269 7270 set y [boilerplate $t] 7271 7272 $y insert end " 7273 Performs an orderly exit from iSpin, cleaning up temporary files, etc. 7274 If you forgot to save a modified model, you'll get a warning. 7275 7276 You can of course also just kill the window itself -- but then none of these 7277 niceties will happen. 7278" 7279} 7280 7281proc find_field {fld ln} { 7282 7283 set a [string first "$fld" $ln] 7284 incr a [string length "$fld"] 7285 7286 set b [string first "\"" [string range $ln $a end]] 7287 if {$b <= 0} { 7288 set b [string first "," [string range $ln $a end]] 7289 } 7290 if {$b <= 0} { 7291 set b [string first "\]" [string range $ln $a end]] 7292 } 7293 set b [expr $a + $b - 1] 7294 7295 set mf [string range $ln $a $b] 7296 if {$mf == ""} { set mf 1 } 7297 7298 return [expr 50 * $mf] 7299} 7300 7301proc display_graph {pn} { 7302 global fg RM DOT 7303 7304 add_log "select $pn" 1 7305 set found 0 7306 set fd [open dot.tmp r] 7307 set fo [open dot.out w] 7308 while {[gets $fd line] > -1} { 7309 if {[string first "digraph" $line] >= 0} { 7310 if {[string first "$pn" $line] >= 0} { 7311 set found 1 7312 } else { 7313 set found 0 7314 } } 7315 if {$found} { 7316 puts $fo "$line" 7317 } } 7318 catch { close $fd } 7319 catch { close $fo } 7320 # do not overwrite dot.tmp 7321 catch { eval exec \"$DOT\" -Ttk < dot.out > dot.sel } err 7322 if {$err != ""} { 7323 add_log "$err" 0 7324 tk_messageBox -icon info -message "pan: $err" 7325 return 7326 } 7327 7328 catch { $fg delete graph } 7329 set c $fg 7330 set fd [open dot.sel r] 7331 while {[gets $fd line] > -1} { 7332 if {[string first "#" $line] < 0} { 7333 if {[string first "create polygon" $line] > 0} { 7334 set line [string map {black red} $line] 7335 set line [string map {white black} $line] 7336 } 7337 if {[string first "create oval" $line] > 0} { 7338 set line [string map {black ivory} $line] ;# outline black -> ivory 7339 set line [string map {white black} $line] ;# fill white -> black 7340 } 7341 if {[string first "create line" $line] > 0} { 7342 set line [string map {black ivory} $line] 7343 } 7344 if {[string first "create text" $line] > 0} { 7345 set line [string map {black gold} $line] 7346 } 7347 eval $line -tags graph 7348 } } 7349 catch { close $fd } 7350 catch { eval $RM dot.sel dot.out } ;# cannot delete dot.tmp yet 7351} 7352 7353proc mk_graphs {} { 7354 global fg Fname SPIN CC DOT HV1 RM 7355 7356 if {$Fname == ""} { return } 7357 7358 if {[auto_execok $DOT] == ""} { 7359 tk_messageBox -icon info -message "ispin: cannot find $DOT" 7360 return 7361 } 7362 7363 add_log "$SPIN -o3 -a $Fname" 1 7364 catch { eval exec $SPIN -o3 -a $Fname } err 7365 if {$err != ""} { 7366 if {[string first "Error:" $err] > 0} { 7367 tk_messageBox -icon info -message "spin: $err" 7368 return 7369 } 7370 add_log "$err" 0 7371 } 7372 add_log "$CC -o pan pan.c" 1 7373 catch { eval exec $CC -w -o pan pan.c } err 7374 if {$err != ""} { 7375 add_log "$err" 0 7376 tk_messageBox -icon info -message "cc: $err" 7377 return 7378 } 7379 7380 # use output from ./pan -D to build menu 7381 add_log "./pan -D > dot.tmp" 1 7382 catch { eval exec ./pan -D > dot.tmp } err 7383 if {$err != ""} { 7384 add_log "$err" 0 7385 tk_messageBox -icon info -message "pan: $err" 7386 return 7387 } 7388 set dx 50 7389 set dy 20 7390 7391 catch { $fg delete hotlinks } 7392 catch { $fg delete graph } 7393 set hl [$fg create text $dx $dy -text "Select:" \ 7394 -font $HV1 -fill white -tags hotlinks] 7395 incr dy 15 7396 set fd [open dot.tmp r] 7397 while {[gets $fd line] > -1} { 7398 if {[string first "digraph" $line] >= 0} { 7399 set x [string first "\{" $line] 7400 set pn [string trim [string range $line 8 [expr $x - 1]]] 7401 7402 set hl [$fg create text $dx $dy \ 7403 -text $pn -font $HV1 -fill lightblue -tags hotlinks] 7404 incr dy 15 7405 7406 $fg bind $hl <Any-Enter> " 7407 $fg itemconfigure $hl -fill gold 7408 " 7409 $fg bind $hl <Any-Leave> " 7410 $fg itemconfigure $hl -fill lightblue 7411 " 7412 $fg bind $hl <ButtonPress-1> " 7413 display_graph $pn 7414 " 7415 } } 7416 catch { close $fd } 7417} 7418 7419#### Startup 7420 create_panels 7421 7422 add_log "$version" 0 7423 add_log "$xversion" 0 7424 add_log "TclTk Version [info tclversion]/$tk_version" 0 7425 7426 if {$argc == 1} { 7427 set Fname "$argv" 7428 open_spec 0 7429 } 7430 7431 update 7432 7433