Browse Source

Plan 9 from Bell Labs 2005-09-01

David du Colombier 18 years ago
parent
commit
2f21373f3d
55 changed files with 7104 additions and 1644 deletions
  1. 59 50
      dist/replica/_plan9.db
  2. 58 56
      dist/replica/plan9.db
  3. 60 0
      dist/replica/plan9.log
  4. 1 1
      sys/man/2/setjmp
  5. 22 25
      sys/man/8/ppp
  6. 41 31
      sys/src/9/port/chan.c
  7. 1 1
      sys/src/cmd/ip/ppp/ipaux.c
  8. 4 4
      sys/src/cmd/ip/ppp/ppp.c
  9. 5 5
      sys/src/cmd/ip/pppoe.c
  10. 16 6
      sys/src/cmd/seq.c
  11. 1 2
      sys/src/cmd/spin/README
  12. 56 20
      sys/src/cmd/spin/dstep.c
  13. 94 16
      sys/src/cmd/spin/flow.c
  14. 92 36
      sys/src/cmd/spin/guided.c
  15. 177 67
      sys/src/cmd/spin/main.c
  16. 28 15
      sys/src/cmd/spin/mesg.c
  17. 2 0
      sys/src/cmd/spin/mkfile
  18. 344 103
      sys/src/cmd/spin/pangen1.c
  19. 1110 30
      sys/src/cmd/spin/pangen1.h
  20. 279 112
      sys/src/cmd/spin/pangen2.c
  21. 116 115
      sys/src/cmd/spin/pangen2.h
  22. 22 18
      sys/src/cmd/spin/pangen3.c
  23. 106 85
      sys/src/cmd/spin/pangen3.h
  24. 42 37
      sys/src/cmd/spin/pangen4.c
  25. 19 19
      sys/src/cmd/spin/pangen4.h
  26. 100 115
      sys/src/cmd/spin/pangen5.c
  27. 14 13
      sys/src/cmd/spin/pangen5.h
  28. 2357 0
      sys/src/cmd/spin/pangen6.c
  29. 32 19
      sys/src/cmd/spin/pc_zpp.c
  30. 42 31
      sys/src/cmd/spin/ps_msc.c
  31. 140 0
      sys/src/cmd/spin/reprosrc.c
  32. 73 23
      sys/src/cmd/spin/run.c
  33. 171 79
      sys/src/cmd/spin/sched.c
  34. 89 38
      sys/src/cmd/spin/spin.h
  35. 101 24
      sys/src/cmd/spin/spin.y
  36. 781 43
      sys/src/cmd/spin/spinlex.c
  37. 55 15
      sys/src/cmd/spin/structs.c
  38. 25 19
      sys/src/cmd/spin/sym.c
  39. 8 6
      sys/src/cmd/spin/tl.h
  40. 40 48
      sys/src/cmd/spin/tl_buchi.c
  41. 11 7
      sys/src/cmd/spin/tl_cache.c
  42. 18 16
      sys/src/cmd/spin/tl_lex.c
  43. 22 20
      sys/src/cmd/spin/tl_main.c
  44. 8 6
      sys/src/cmd/spin/tl_mem.c
  45. 24 10
      sys/src/cmd/spin/tl_parse.c
  46. 12 25
      sys/src/cmd/spin/tl_rewrt.c
  47. 28 37
      sys/src/cmd/spin/tl_trans.c
  48. 27 28
      sys/src/cmd/spin/vars.c
  49. 1 1
      sys/src/cmd/spin/version.h
  50. 15 1
      sys/src/cmd/tar.c
  51. 3 2
      sys/src/cmd/tcs/utf.c
  52. 2 2
      sys/src/cmd/unix/spin/readme
  53. BIN
      sys/src/cmd/unix/spin/spin334.tar.gz
  54. BIN
      sys/src/cmd/unix/spin/spin425.tar.gz
  55. 150 162
      sys/src/games/memo.c

+ 59 - 50
dist/replica/_plan9.db

@@ -414,7 +414,7 @@
 386/bin/tail - 775 sys sys 1125346016 66169
 386/bin/tail - 775 sys sys 1125346016 66169
 386/bin/tar - 775 sys sys 1120014538 96347
 386/bin/tar - 775 sys sys 1120014538 96347
 386/bin/tbl - 775 sys sys 1125346017 113167
 386/bin/tbl - 775 sys sys 1125346017 113167
-386/bin/tcs - 775 sys sys 1115950118 256588
+386/bin/tcs - 775 sys sys 1125501123 256580
 386/bin/tee - 775 sys sys 1115950118 38428
 386/bin/tee - 775 sys sys 1115950118 38428
 386/bin/telco - 775 sys sys 1115950118 103315
 386/bin/telco - 775 sys sys 1115950118 103315
 386/bin/telnet - 775 sys sys 1125346017 80355
 386/bin/telnet - 775 sys sys 1125346017 80355
@@ -7513,7 +7513,7 @@ sys/man/2/seek - 664 sys sys 944959696 671
 sys/man/2/segattach - 664 sys sys 1015091526 4304
 sys/man/2/segattach - 664 sys sys 1015091526 4304
 sys/man/2/segbrk - 664 sys sys 944959696 825
 sys/man/2/segbrk - 664 sys sys 944959696 825
 sys/man/2/segflush - 664 sys sys 944959695 944
 sys/man/2/segflush - 664 sys sys 944959695 944
-sys/man/2/setjmp - 664 sys sys 944959696 1856
+sys/man/2/setjmp - 664 sys sys 1125540984 1857
 sys/man/2/sin - 664 sys sys 944959694 967
 sys/man/2/sin - 664 sys sys 944959694 967
 sys/man/2/sinh - 664 sys sys 944959694 360
 sys/man/2/sinh - 664 sys sys 944959694 360
 sys/man/2/sleep - 664 sys sys 944959694 984
 sys/man/2/sleep - 664 sys sys 944959694 984
@@ -7705,7 +7705,7 @@ sys/man/8/pem - 664 sys sys 1060263669 1189
 sys/man/8/ping - 664 sys sys 1084473185 3436
 sys/man/8/ping - 664 sys sys 1084473185 3436
 sys/man/8/plan9.ini - 664 sys sys 1117814755 21579
 sys/man/8/plan9.ini - 664 sys sys 1117814755 21579
 sys/man/8/pop3 - 664 sys sys 1063854676 2720
 sys/man/8/pop3 - 664 sys sys 1063854676 2720
-sys/man/8/ppp - 664 sys sys 1096036494 4424
+sys/man/8/ppp - 664 sys sys 1125530075 4414
 sys/man/8/prep - 664 sys sys 1079705872 13820
 sys/man/8/prep - 664 sys sys 1079705872 13820
 sys/man/8/qer - 664 sys sys 1067723129 4909
 sys/man/8/qer - 664 sys sys 1067723129 4909
 sys/man/8/reboot - 664 sys sys 969499895 414
 sys/man/8/reboot - 664 sys sys 969499895 414
@@ -8039,7 +8039,7 @@ sys/src/9/port/alloc.c - 664 sys sys 1102093389 5645
 sys/src/9/port/allocb.c - 664 sys sys 1123676437 3340
 sys/src/9/port/allocb.c - 664 sys sys 1123676437 3340
 sys/src/9/port/auth.c - 664 sys sys 1123647282 2392
 sys/src/9/port/auth.c - 664 sys sys 1123647282 2392
 sys/src/9/port/cache.c - 664 sys sys 1055688274 9241
 sys/src/9/port/cache.c - 664 sys sys 1055688274 9241
-sys/src/9/port/chan.c - 664 sys sys 1123647283 29928
+sys/src/9/port/chan.c - 664 sys sys 1125517669 30203
 sys/src/9/port/cis.c - 664 sys sys 1099761153 9248
 sys/src/9/port/cis.c - 664 sys sys 1099761153 9248
 sys/src/9/port/debugalloc.c - 664 sys sys 1014931171 10402
 sys/src/9/port/debugalloc.c - 664 sys sys 1014931171 10402
 sys/src/9/port/dev.c - 664 sys sys 1077896125 8247
 sys/src/9/port/dev.c - 664 sys sys 1077896125 8247
@@ -11976,17 +11976,17 @@ sys/src/cmd/ip/ppp/compress.c - 664 sys sys 1072729513 11774
 sys/src/cmd/ip/ppp/doclient - 775 sys sys 944961007 50
 sys/src/cmd/ip/ppp/doclient - 775 sys sys 944961007 50
 sys/src/cmd/ip/ppp/doserve - 775 sys sys 944961009 91
 sys/src/cmd/ip/ppp/doserve - 775 sys sys 944961009 91
 sys/src/cmd/ip/ppp/dotest - 775 sys sys 944961006 152
 sys/src/cmd/ip/ppp/dotest - 775 sys sys 944961006 152
-sys/src/cmd/ip/ppp/ipaux.c - 664 sys sys 1015090266 2326
+sys/src/cmd/ip/ppp/ipaux.c - 664 sys sys 1125529107 2328
 sys/src/cmd/ip/ppp/mkfile - 664 sys sys 1063897576 352
 sys/src/cmd/ip/ppp/mkfile - 664 sys sys 1063897576 352
 sys/src/cmd/ip/ppp/mppc.c - 664 sys sys 1015090267 16624
 sys/src/cmd/ip/ppp/mppc.c - 664 sys sys 1015090267 16624
-sys/src/cmd/ip/ppp/ppp.c - 664 sys sys 1125316087 59889
+sys/src/cmd/ip/ppp/ppp.c - 664 sys sys 1125530039 59897
 sys/src/cmd/ip/ppp/ppp.h - 664 sys sys 1091904423 8284
 sys/src/cmd/ip/ppp/ppp.h - 664 sys sys 1091904423 8284
 sys/src/cmd/ip/ppp/testppp.c - 664 sys sys 1045505281 3011
 sys/src/cmd/ip/ppp/testppp.c - 664 sys sys 1045505281 3011
 sys/src/cmd/ip/ppp/thw.c - 664 sys sys 1015090268 5962
 sys/src/cmd/ip/ppp/thw.c - 664 sys sys 1015090268 5962
 sys/src/cmd/ip/ppp/thwack.c - 664 sys sys 1015090268 8004
 sys/src/cmd/ip/ppp/thwack.c - 664 sys sys 1015090268 8004
 sys/src/cmd/ip/ppp/thwack.h - 664 sys sys 964662210 2052
 sys/src/cmd/ip/ppp/thwack.h - 664 sys sys 964662210 2052
 sys/src/cmd/ip/ppp/unthwack.c - 664 sys sys 1015090268 5883
 sys/src/cmd/ip/ppp/unthwack.c - 664 sys sys 1015090268 5883
-sys/src/cmd/ip/pppoe.c - 664 sys sys 1050360937 12507
+sys/src/cmd/ip/pppoe.c - 664 sys sys 1125530113 12516
 sys/src/cmd/ip/pptp.c - 664 sys sys 1050360938 16575
 sys/src/cmd/ip/pptp.c - 664 sys sys 1050360938 16575
 sys/src/cmd/ip/pptpd.c - 664 sys sys 1015701128 23548
 sys/src/cmd/ip/pptpd.c - 664 sys sys 1015701128 23548
 sys/src/cmd/ip/rarpd.c - 664 sys sys 1084470989 3389
 sys/src/cmd/ip/rarpd.c - 664 sys sys 1084470989 3389
@@ -12803,7 +12803,7 @@ sys/src/cmd/scuzz/scsireq.h - 664 sys sys 1113741890 5929
 sys/src/cmd/scuzz/scuzz.c - 664 sys sys 1121977163 37610
 sys/src/cmd/scuzz/scuzz.c - 664 sys sys 1121977163 37610
 sys/src/cmd/scuzz/sense.c - 664 sys sys 969510790 3901
 sys/src/cmd/scuzz/sense.c - 664 sys sys 969510790 3901
 sys/src/cmd/sed.c - 664 sys sys 1100962924 27001
 sys/src/cmd/sed.c - 664 sys sys 1100962924 27001
-sys/src/cmd/seq.c - 664 sys sys 1063854922 1484
+sys/src/cmd/seq.c - 664 sys sys 1125529033 1683
 sys/src/cmd/sh.C - 664 sys sys 1055701754 10303
 sys/src/cmd/sh.C - 664 sys sys 1055701754 10303
 sys/src/cmd/sha1sum.c - 664 sys sys 1014926229 1017
 sys/src/cmd/sha1sum.c - 664 sys sys 1014926229 1017
 sys/src/cmd/size.c - 664 sys sys 944961619 717
 sys/src/cmd/size.c - 664 sys sys 944961619 717
@@ -12830,43 +12830,45 @@ sys/src/cmd/spell/spell.rc - 775 sys sys 964457135 312
 sys/src/cmd/spell/sprog.c - 664 sys sys 964540731 23030
 sys/src/cmd/spell/sprog.c - 664 sys sys 964540731 23030
 sys/src/cmd/spell/stop - 664 sys sys 944961232 18702
 sys/src/cmd/spell/stop - 664 sys sys 944961232 18702
 sys/src/cmd/spin - 20000000775 sys sys 953242990 0
 sys/src/cmd/spin - 20000000775 sys sys 953242990 0
-sys/src/cmd/spin/README - 664 sys sys 953242984 344
-sys/src/cmd/spin/dstep.c - 664 sys sys 953242984 8805
-sys/src/cmd/spin/flow.c - 664 sys sys 953242984 15478
-sys/src/cmd/spin/guided.c - 664 sys sys 953242984 5899
-sys/src/cmd/spin/main.c - 664 sys sys 953242984 18700
-sys/src/cmd/spin/mesg.c - 664 sys sys 953242985 13596
-sys/src/cmd/spin/mkfile - 664 sys sys 953242985 669
-sys/src/cmd/spin/pangen1.c - 664 sys sys 953242985 23759
-sys/src/cmd/spin/pangen1.h - 664 sys sys 953242985 94543
-sys/src/cmd/spin/pangen2.c - 664 sys sys 956275776 66265
-sys/src/cmd/spin/pangen2.h - 664 sys sys 953242986 23128
-sys/src/cmd/spin/pangen3.c - 664 sys sys 953242986 8872
-sys/src/cmd/spin/pangen3.h - 664 sys sys 956275777 22057
-sys/src/cmd/spin/pangen4.c - 664 sys sys 953242986 8217
-sys/src/cmd/spin/pangen4.h - 664 sys sys 953242986 18957
-sys/src/cmd/spin/pangen5.c - 664 sys sys 953242986 16614
-sys/src/cmd/spin/pangen5.h - 664 sys sys 953242986 10852
-sys/src/cmd/spin/pc_zpp.c - 664 sys sys 956275778 8265
-sys/src/cmd/spin/ps_msc.c - 664 sys sys 953242987 11458
-sys/src/cmd/spin/run.c - 664 sys sys 953242987 13173
-sys/src/cmd/spin/sched.c - 664 sys sys 953242987 19359
-sys/src/cmd/spin/spin.h - 664 sys sys 953242987 10807
-sys/src/cmd/spin/spin.y - 664 sys sys 953242987 16731
-sys/src/cmd/spin/spinlex.c - 664 sys sys 953242987 13809
-sys/src/cmd/spin/structs.c - 664 sys sys 953242988 13364
-sys/src/cmd/spin/sym.c - 664 sys sys 953242988 11763
-sys/src/cmd/spin/tl.h - 664 sys sys 953242988 3254
-sys/src/cmd/spin/tl_buchi.c - 664 sys sys 953242988 13164
-sys/src/cmd/spin/tl_cache.c - 664 sys sys 953242988 5732
-sys/src/cmd/spin/tl_lex.c - 664 sys sys 953242988 3132
-sys/src/cmd/spin/tl_main.c - 664 sys sys 953242988 4331
-sys/src/cmd/spin/tl_mem.c - 664 sys sys 953242988 2592
-sys/src/cmd/spin/tl_parse.c - 664 sys sys 953242989 8007
-sys/src/cmd/spin/tl_rewrt.c - 664 sys sys 953242989 6257
-sys/src/cmd/spin/tl_trans.c - 664 sys sys 953242990 16758
-sys/src/cmd/spin/vars.c - 664 sys sys 953242990 8412
-sys/src/cmd/spin/version.h - 664 sys sys 956275780 54
+sys/src/cmd/spin/README - 664 sys sys 1125514858 311
+sys/src/cmd/spin/dstep.c - 664 sys sys 1125514858 9958
+sys/src/cmd/spin/flow.c - 664 sys sys 1125514858 17345
+sys/src/cmd/spin/guided.c - 664 sys sys 1125514858 6948
+sys/src/cmd/spin/main.c - 664 sys sys 1125514858 21713
+sys/src/cmd/spin/mesg.c - 664 sys sys 1125514858 13722
+sys/src/cmd/spin/mkfile - 664 sys sys 1125514859 696
+sys/src/cmd/spin/pangen1.c - 664 sys sys 1125514859 29801
+sys/src/cmd/spin/pangen1.h - 664 sys sys 1125514859 134192
+sys/src/cmd/spin/pangen2.c - 664 sys sys 1125514859 74348
+sys/src/cmd/spin/pangen2.h - 664 sys sys 1125514860 23109
+sys/src/cmd/spin/pangen3.c - 664 sys sys 1125514860 8941
+sys/src/cmd/spin/pangen3.h - 664 sys sys 1125514860 22484
+sys/src/cmd/spin/pangen4.c - 664 sys sys 1125514860 8180
+sys/src/cmd/spin/pangen4.h - 664 sys sys 1125514860 19033
+sys/src/cmd/spin/pangen5.c - 664 sys sys 1125514860 16851
+sys/src/cmd/spin/pangen5.h - 664 sys sys 1125514861 11145
+sys/src/cmd/spin/pangen6.c - 664 sys sys 1125514861 48633
+sys/src/cmd/spin/pc_zpp.c - 664 sys sys 1125514861 8737
+sys/src/cmd/spin/ps_msc.c - 664 sys sys 1125514861 11872
+sys/src/cmd/spin/reprosrc.c - 664 sys sys 1125514861 2978
+sys/src/cmd/spin/run.c - 664 sys sys 1125514862 14405
+sys/src/cmd/spin/sched.c - 664 sys sys 1125514862 21096
+sys/src/cmd/spin/spin.h - 664 sys sys 1125514862 12286
+sys/src/cmd/spin/spin.y - 664 sys sys 1125514862 18876
+sys/src/cmd/spin/spinlex.c - 664 sys sys 1125514862 30767
+sys/src/cmd/spin/structs.c - 664 sys sys 1125514863 14150
+sys/src/cmd/spin/sym.c - 664 sys sys 1125514863 11863
+sys/src/cmd/spin/tl.h - 664 sys sys 1125514863 3332
+sys/src/cmd/spin/tl_buchi.c - 664 sys sys 1125514863 13080
+sys/src/cmd/spin/tl_cache.c - 664 sys sys 1125514863 5831
+sys/src/cmd/spin/tl_lex.c - 664 sys sys 1125514863 3243
+sys/src/cmd/spin/tl_main.c - 664 sys sys 1125514863 4412
+sys/src/cmd/spin/tl_mem.c - 664 sys sys 1125514864 2670
+sys/src/cmd/spin/tl_parse.c - 664 sys sys 1125514864 8257
+sys/src/cmd/spin/tl_rewrt.c - 664 sys sys 1125514864 5962
+sys/src/cmd/spin/tl_trans.c - 664 sys sys 1125514864 16758
+sys/src/cmd/spin/vars.c - 664 sys sys 1125514864 8393
+sys/src/cmd/spin/version.h - 664 sys sys 1125514864 53
 sys/src/cmd/split.c - 664 sys sys 1116770353 3225
 sys/src/cmd/split.c - 664 sys sys 1116770353 3225
 sys/src/cmd/srv.c - 664 sys sys 1074452607 3885
 sys/src/cmd/srv.c - 664 sys sys 1074452607 3885
 sys/src/cmd/srvfs.c - 664 sys sys 1116770384 1702
 sys/src/cmd/srvfs.c - 664 sys sys 1116770384 1702
@@ -12923,7 +12925,7 @@ sys/src/cmd/tapefs/v10fs.c - 664 sys sys 1014926385 3754
 sys/src/cmd/tapefs/v6fs.c - 664 sys sys 1014926385 3971
 sys/src/cmd/tapefs/v6fs.c - 664 sys sys 1014926385 3971
 sys/src/cmd/tapefs/zip.h - 664 sys sys 1097914153 1428
 sys/src/cmd/tapefs/zip.h - 664 sys sys 1097914153 1428
 sys/src/cmd/tapefs/zipfs.c - 664 sys sys 1097900277 6803
 sys/src/cmd/tapefs/zipfs.c - 664 sys sys 1097900277 6803
-sys/src/cmd/tar.c - 664 sys sys 1119986000 21041
+sys/src/cmd/tar.c - 664 sys sys 1125515072 21269
 sys/src/cmd/tbl - 20000000775 sys sys 954038038 0
 sys/src/cmd/tbl - 20000000775 sys sys 954038038 0
 sys/src/cmd/tbl/mkfile - 664 sys sys 944961243 268
 sys/src/cmd/tbl/mkfile - 664 sys sys 944961243 268
 sys/src/cmd/tbl/t.h - 664 sys sys 944961244 3987
 sys/src/cmd/tbl/t.h - 664 sys sys 944961244 3987
@@ -12991,7 +12993,7 @@ sys/src/cmd/tcs/kuten212.h - 664 sys sys 944961287 94
 sys/src/cmd/tcs/mkfile - 664 sys sys 1036724422 532
 sys/src/cmd/tcs/mkfile - 664 sys sys 1036724422 532
 sys/src/cmd/tcs/plan9.h - 664 sys sys 944961287 751
 sys/src/cmd/tcs/plan9.h - 664 sys sys 944961287 751
 sys/src/cmd/tcs/tcs.c - 664 sys sys 1044661975 51805
 sys/src/cmd/tcs/tcs.c - 664 sys sys 1044661975 51805
-sys/src/cmd/tcs/utf.c - 664 sys sys 1044661976 7951
+sys/src/cmd/tcs/utf.c - 664 sys sys 1125501123 7962
 sys/src/cmd/tee.c - 664 sys sys 954970286 1062
 sys/src/cmd/tee.c - 664 sys sys 954970286 1062
 sys/src/cmd/telco - 20000000775 sys sys 1015701205 0
 sys/src/cmd/telco - 20000000775 sys sys 1015701205 0
 sys/src/cmd/telco/mkfile - 664 sys sys 944961290 201
 sys/src/cmd/telco/mkfile - 664 sys sys 944961290 201
@@ -13242,8 +13244,8 @@ sys/src/cmd/unix/netkey.c - 664 sys sys 1045152984 21761
 sys/src/cmd/unix/sam - 20000000775 sys sys 954263160 0
 sys/src/cmd/unix/sam - 20000000775 sys sys 954263160 0
 sys/src/cmd/unix/sam/README - 664 sys sys 1110289373 306
 sys/src/cmd/unix/sam/README - 664 sys sys 1110289373 306
 sys/src/cmd/unix/spin - 20000000775 sys sys 956275829 0
 sys/src/cmd/unix/spin - 20000000775 sys sys 956275829 0
-sys/src/cmd/unix/spin/readme - 664 sys sys 956275829 271
-sys/src/cmd/unix/spin/spin334.tar.gz - 664 sys sys 956275830 264112
+sys/src/cmd/unix/spin/readme - 664 sys sys 1125514575 247
+sys/src/cmd/unix/spin/spin425.tar.gz - 664 sys sys 1125514573 330078
 sys/src/cmd/unix/tcs.shar.Z - 664 sys sys 944961315 312440
 sys/src/cmd/unix/tcs.shar.Z - 664 sys sys 944961315 312440
 sys/src/cmd/unix/u9fs - 20000000775 sys sys 1015092354 0
 sys/src/cmd/unix/u9fs - 20000000775 sys sys 1015092354 0
 sys/src/cmd/unix/u9fs/authnone.c - 664 sys sys 1015092351 321
 sys/src/cmd/unix/u9fs/authnone.c - 664 sys sys 1015092351 321
@@ -13783,7 +13785,7 @@ sys/src/games/mahjongg/level.c - 664 sys sys 1095792293 2522
 sys/src/games/mahjongg/mahjongg.c - 664 sys sys 1095792293 3452
 sys/src/games/mahjongg/mahjongg.c - 664 sys sys 1095792293 3452
 sys/src/games/mahjongg/mahjongg.h - 664 sys sys 1095792293 1606
 sys/src/games/mahjongg/mahjongg.h - 664 sys sys 1095792293 1606
 sys/src/games/mahjongg/mkfile - 664 sys sys 1095792293 230
 sys/src/games/mahjongg/mkfile - 664 sys sys 1095792293 230
-sys/src/games/memo.c - 664 sys sys 1110436470 6837
+sys/src/games/memo.c - 664 sys sys 1125514848 6321
 sys/src/games/mkfile - 664 sys sys 1118672535 567
 sys/src/games/mkfile - 664 sys sys 1118672535 567
 sys/src/games/music - 20000000775 sys sys 1103793915 0
 sys/src/games/music - 20000000775 sys sys 1103793915 0
 sys/src/games/music/Readme - 664 sys sys 1103793914 488
 sys/src/games/music/Readme - 664 sys sys 1103793914 488
@@ -14959,3 +14961,10 @@ usr/glenda/lib/profile - 664 glenda glenda 1105128663 890
 usr/glenda/readme.acme - 664 glenda glenda 1019860628 4753
 usr/glenda/readme.acme - 664 glenda glenda 1019860628 4753
 usr/glenda/readme.rio - 664 glenda glenda 1019860628 6370
 usr/glenda/readme.rio - 664 glenda glenda 1019860628 6370
 usr/glenda/tmp - 20000000775 glenda glenda 1018802620 0
 usr/glenda/tmp - 20000000775 glenda glenda 1018802620 0
+386/bin/games/memo - 775 sys sys 1125544173 156892
+386/bin/seq - 775 sys sys 1125544174 38396
+386/bin/spin - 775 sys sys 1125544175 758333
+386/bin/ip/ppp - 775 sys sys 1125544173 218875
+386/bin/ip/pppoe - 775 sys sys 1125544173 77548
+386/bin/tar - 775 sys sys 1125544175 96517
+386/bin/tcs - 775 sys sys 1125544176 256580

+ 58 - 56
dist/replica/plan9.db

@@ -252,7 +252,7 @@
 386/bin/games/jukebox - 775 sys sys 1105589128 264821
 386/bin/games/jukebox - 775 sys sys 1105589128 264821
 386/bin/games/jukefs - 775 sys sys 1105589129 165320
 386/bin/games/jukefs - 775 sys sys 1105589129 165320
 386/bin/games/mahjongg - 775 sys sys 1125345978 164288
 386/bin/games/mahjongg - 775 sys sys 1125345978 164288
-386/bin/games/memo - 775 sys sys 1115950076 157374
+386/bin/games/memo - 775 sys sys 1125544173 156892
 386/bin/games/playlistfs - 775 sys sys 1105589129 148484
 386/bin/games/playlistfs - 775 sys sys 1105589129 148484
 386/bin/games/sokoban - 775 sys sys 1125345978 163379
 386/bin/games/sokoban - 775 sys sys 1125345978 163379
 386/bin/games/sudoku - 775 sys sys 1117249746 171666
 386/bin/games/sudoku - 775 sys sys 1117249746 171666
@@ -296,8 +296,8 @@
 386/bin/ip/imap4d - 775 sys sys 1125345987 236488
 386/bin/ip/imap4d - 775 sys sys 1125345987 236488
 386/bin/ip/ipconfig - 775 sys sys 1125345988 137742
 386/bin/ip/ipconfig - 775 sys sys 1125345988 137742
 386/bin/ip/ping - 775 sys sys 1116126319 77010
 386/bin/ip/ping - 775 sys sys 1116126319 77010
-386/bin/ip/ppp - 775 sys sys 1125345988 218875
-386/bin/ip/pppoe - 775 sys sys 1116126319 77535
+386/bin/ip/ppp - 775 sys sys 1125544173 218875
+386/bin/ip/pppoe - 775 sys sys 1125544173 77548
 386/bin/ip/pptp - 775 sys sys 1116126320 126658
 386/bin/ip/pptp - 775 sys sys 1116126320 126658
 386/bin/ip/pptpd - 775 sys sys 1125345988 125824
 386/bin/ip/pptpd - 775 sys sys 1125345988 125824
 386/bin/ip/rarpd - 775 sys sys 1125345990 111572
 386/bin/ip/rarpd - 775 sys sys 1125345990 111572
@@ -389,7 +389,7 @@
 386/bin/scp - 775 sys sys 1119496657 151927
 386/bin/scp - 775 sys sys 1119496657 151927
 386/bin/scuzz - 775 sys sys 1125346011 111604
 386/bin/scuzz - 775 sys sys 1125346011 111604
 386/bin/sed - 775 sys sys 1125346011 89514
 386/bin/sed - 775 sys sys 1125346011 89514
-386/bin/seq - 775 sys sys 1115950111 38206
+386/bin/seq - 775 sys sys 1125544174 38396
 386/bin/sha1sum - 775 sys sys 1115950111 61133
 386/bin/sha1sum - 775 sys sys 1115950111 61133
 386/bin/size - 775 sys sys 1119496658 76974
 386/bin/size - 775 sys sys 1119496658 76974
 386/bin/sleep - 775 sys sys 1085077097 3413
 386/bin/sleep - 775 sys sys 1085077097 3413
@@ -398,7 +398,7 @@
 386/bin/sniffer - 775 sys sys 1038443185 99028
 386/bin/sniffer - 775 sys sys 1038443185 99028
 386/bin/snoopy - 775 sys sys 1125346014 157537
 386/bin/snoopy - 775 sys sys 1125346014 157537
 386/bin/sort - 775 sys sys 1125346014 82276
 386/bin/sort - 775 sys sys 1125346014 82276
-386/bin/spin - 775 sys sys 1116903736 655162
+386/bin/spin - 775 sys sys 1125544175 758333
 386/bin/split - 775 sys sys 1125346015 75635
 386/bin/split - 775 sys sys 1125346015 75635
 386/bin/srv - 775 sys sys 1115950113 82387
 386/bin/srv - 775 sys sys 1115950113 82387
 386/bin/srvfs - 775 sys sys 1116903736 40065
 386/bin/srvfs - 775 sys sys 1116903736 40065
@@ -412,9 +412,9 @@
 386/bin/swap - 775 sys sys 1115950116 62094
 386/bin/swap - 775 sys sys 1115950116 62094
 386/bin/syscall - 775 sys sys 1115950116 73536
 386/bin/syscall - 775 sys sys 1115950116 73536
 386/bin/tail - 775 sys sys 1125346016 66169
 386/bin/tail - 775 sys sys 1125346016 66169
-386/bin/tar - 775 sys sys 1120014538 96347
+386/bin/tar - 775 sys sys 1125544175 96517
 386/bin/tbl - 775 sys sys 1125346017 113167
 386/bin/tbl - 775 sys sys 1125346017 113167
-386/bin/tcs - 775 sys sys 1115950118 256588
+386/bin/tcs - 775 sys sys 1125544176 256580
 386/bin/tee - 775 sys sys 1115950118 38428
 386/bin/tee - 775 sys sys 1115950118 38428
 386/bin/telco - 775 sys sys 1115950118 103315
 386/bin/telco - 775 sys sys 1115950118 103315
 386/bin/telnet - 775 sys sys 1125346017 80355
 386/bin/telnet - 775 sys sys 1125346017 80355
@@ -7513,7 +7513,7 @@ sys/man/2/seek - 664 sys sys 944959696 671
 sys/man/2/segattach - 664 sys sys 1015091526 4304
 sys/man/2/segattach - 664 sys sys 1015091526 4304
 sys/man/2/segbrk - 664 sys sys 944959696 825
 sys/man/2/segbrk - 664 sys sys 944959696 825
 sys/man/2/segflush - 664 sys sys 944959695 944
 sys/man/2/segflush - 664 sys sys 944959695 944
-sys/man/2/setjmp - 664 sys sys 944959696 1856
+sys/man/2/setjmp - 664 sys sys 1125540984 1857
 sys/man/2/sin - 664 sys sys 944959694 967
 sys/man/2/sin - 664 sys sys 944959694 967
 sys/man/2/sinh - 664 sys sys 944959694 360
 sys/man/2/sinh - 664 sys sys 944959694 360
 sys/man/2/sleep - 664 sys sys 944959694 984
 sys/man/2/sleep - 664 sys sys 944959694 984
@@ -7705,7 +7705,7 @@ sys/man/8/pem - 664 sys sys 1060263669 1189
 sys/man/8/ping - 664 sys sys 1084473185 3436
 sys/man/8/ping - 664 sys sys 1084473185 3436
 sys/man/8/plan9.ini - 664 sys sys 1117814755 21579
 sys/man/8/plan9.ini - 664 sys sys 1117814755 21579
 sys/man/8/pop3 - 664 sys sys 1063854676 2720
 sys/man/8/pop3 - 664 sys sys 1063854676 2720
-sys/man/8/ppp - 664 sys sys 1096036494 4424
+sys/man/8/ppp - 664 sys sys 1125530075 4414
 sys/man/8/prep - 664 sys sys 1079705872 13820
 sys/man/8/prep - 664 sys sys 1079705872 13820
 sys/man/8/qer - 664 sys sys 1067723129 4909
 sys/man/8/qer - 664 sys sys 1067723129 4909
 sys/man/8/reboot - 664 sys sys 969499895 414
 sys/man/8/reboot - 664 sys sys 969499895 414
@@ -8039,7 +8039,7 @@ sys/src/9/port/alloc.c - 664 sys sys 1102093389 5645
 sys/src/9/port/allocb.c - 664 sys sys 1123676437 3340
 sys/src/9/port/allocb.c - 664 sys sys 1123676437 3340
 sys/src/9/port/auth.c - 664 sys sys 1123647282 2392
 sys/src/9/port/auth.c - 664 sys sys 1123647282 2392
 sys/src/9/port/cache.c - 664 sys sys 1055688274 9241
 sys/src/9/port/cache.c - 664 sys sys 1055688274 9241
-sys/src/9/port/chan.c - 664 sys sys 1123647283 29928
+sys/src/9/port/chan.c - 664 sys sys 1125517669 30203
 sys/src/9/port/cis.c - 664 sys sys 1099761153 9248
 sys/src/9/port/cis.c - 664 sys sys 1099761153 9248
 sys/src/9/port/debugalloc.c - 664 sys sys 1014931171 10402
 sys/src/9/port/debugalloc.c - 664 sys sys 1014931171 10402
 sys/src/9/port/dev.c - 664 sys sys 1077896125 8247
 sys/src/9/port/dev.c - 664 sys sys 1077896125 8247
@@ -11976,17 +11976,17 @@ sys/src/cmd/ip/ppp/compress.c - 664 sys sys 1072729513 11774
 sys/src/cmd/ip/ppp/doclient - 775 sys sys 944961007 50
 sys/src/cmd/ip/ppp/doclient - 775 sys sys 944961007 50
 sys/src/cmd/ip/ppp/doserve - 775 sys sys 944961009 91
 sys/src/cmd/ip/ppp/doserve - 775 sys sys 944961009 91
 sys/src/cmd/ip/ppp/dotest - 775 sys sys 944961006 152
 sys/src/cmd/ip/ppp/dotest - 775 sys sys 944961006 152
-sys/src/cmd/ip/ppp/ipaux.c - 664 sys sys 1015090266 2326
+sys/src/cmd/ip/ppp/ipaux.c - 664 sys sys 1125529107 2328
 sys/src/cmd/ip/ppp/mkfile - 664 sys sys 1063897576 352
 sys/src/cmd/ip/ppp/mkfile - 664 sys sys 1063897576 352
 sys/src/cmd/ip/ppp/mppc.c - 664 sys sys 1015090267 16624
 sys/src/cmd/ip/ppp/mppc.c - 664 sys sys 1015090267 16624
-sys/src/cmd/ip/ppp/ppp.c - 664 sys sys 1125316087 59889
+sys/src/cmd/ip/ppp/ppp.c - 664 sys sys 1125530039 59897
 sys/src/cmd/ip/ppp/ppp.h - 664 sys sys 1091904423 8284
 sys/src/cmd/ip/ppp/ppp.h - 664 sys sys 1091904423 8284
 sys/src/cmd/ip/ppp/testppp.c - 664 sys sys 1045505281 3011
 sys/src/cmd/ip/ppp/testppp.c - 664 sys sys 1045505281 3011
 sys/src/cmd/ip/ppp/thw.c - 664 sys sys 1015090268 5962
 sys/src/cmd/ip/ppp/thw.c - 664 sys sys 1015090268 5962
 sys/src/cmd/ip/ppp/thwack.c - 664 sys sys 1015090268 8004
 sys/src/cmd/ip/ppp/thwack.c - 664 sys sys 1015090268 8004
 sys/src/cmd/ip/ppp/thwack.h - 664 sys sys 964662210 2052
 sys/src/cmd/ip/ppp/thwack.h - 664 sys sys 964662210 2052
 sys/src/cmd/ip/ppp/unthwack.c - 664 sys sys 1015090268 5883
 sys/src/cmd/ip/ppp/unthwack.c - 664 sys sys 1015090268 5883
-sys/src/cmd/ip/pppoe.c - 664 sys sys 1050360937 12507
+sys/src/cmd/ip/pppoe.c - 664 sys sys 1125530113 12516
 sys/src/cmd/ip/pptp.c - 664 sys sys 1050360938 16575
 sys/src/cmd/ip/pptp.c - 664 sys sys 1050360938 16575
 sys/src/cmd/ip/pptpd.c - 664 sys sys 1015701128 23548
 sys/src/cmd/ip/pptpd.c - 664 sys sys 1015701128 23548
 sys/src/cmd/ip/rarpd.c - 664 sys sys 1084470989 3389
 sys/src/cmd/ip/rarpd.c - 664 sys sys 1084470989 3389
@@ -12803,7 +12803,7 @@ sys/src/cmd/scuzz/scsireq.h - 664 sys sys 1113741890 5929
 sys/src/cmd/scuzz/scuzz.c - 664 sys sys 1121977163 37610
 sys/src/cmd/scuzz/scuzz.c - 664 sys sys 1121977163 37610
 sys/src/cmd/scuzz/sense.c - 664 sys sys 969510790 3901
 sys/src/cmd/scuzz/sense.c - 664 sys sys 969510790 3901
 sys/src/cmd/sed.c - 664 sys sys 1100962924 27001
 sys/src/cmd/sed.c - 664 sys sys 1100962924 27001
-sys/src/cmd/seq.c - 664 sys sys 1063854922 1484
+sys/src/cmd/seq.c - 664 sys sys 1125529033 1683
 sys/src/cmd/sh.C - 664 sys sys 1055701754 10303
 sys/src/cmd/sh.C - 664 sys sys 1055701754 10303
 sys/src/cmd/sha1sum.c - 664 sys sys 1014926229 1017
 sys/src/cmd/sha1sum.c - 664 sys sys 1014926229 1017
 sys/src/cmd/size.c - 664 sys sys 944961619 717
 sys/src/cmd/size.c - 664 sys sys 944961619 717
@@ -12830,43 +12830,45 @@ sys/src/cmd/spell/spell.rc - 775 sys sys 964457135 312
 sys/src/cmd/spell/sprog.c - 664 sys sys 964540731 23030
 sys/src/cmd/spell/sprog.c - 664 sys sys 964540731 23030
 sys/src/cmd/spell/stop - 664 sys sys 944961232 18702
 sys/src/cmd/spell/stop - 664 sys sys 944961232 18702
 sys/src/cmd/spin - 20000000775 sys sys 953242990 0
 sys/src/cmd/spin - 20000000775 sys sys 953242990 0
-sys/src/cmd/spin/README - 664 sys sys 953242984 344
-sys/src/cmd/spin/dstep.c - 664 sys sys 953242984 8805
-sys/src/cmd/spin/flow.c - 664 sys sys 953242984 15478
-sys/src/cmd/spin/guided.c - 664 sys sys 953242984 5899
-sys/src/cmd/spin/main.c - 664 sys sys 953242984 18700
-sys/src/cmd/spin/mesg.c - 664 sys sys 953242985 13596
-sys/src/cmd/spin/mkfile - 664 sys sys 953242985 669
-sys/src/cmd/spin/pangen1.c - 664 sys sys 953242985 23759
-sys/src/cmd/spin/pangen1.h - 664 sys sys 953242985 94543
-sys/src/cmd/spin/pangen2.c - 664 sys sys 956275776 66265
-sys/src/cmd/spin/pangen2.h - 664 sys sys 953242986 23128
-sys/src/cmd/spin/pangen3.c - 664 sys sys 953242986 8872
-sys/src/cmd/spin/pangen3.h - 664 sys sys 956275777 22057
-sys/src/cmd/spin/pangen4.c - 664 sys sys 953242986 8217
-sys/src/cmd/spin/pangen4.h - 664 sys sys 953242986 18957
-sys/src/cmd/spin/pangen5.c - 664 sys sys 953242986 16614
-sys/src/cmd/spin/pangen5.h - 664 sys sys 953242986 10852
-sys/src/cmd/spin/pc_zpp.c - 664 sys sys 956275778 8265
-sys/src/cmd/spin/ps_msc.c - 664 sys sys 953242987 11458
-sys/src/cmd/spin/run.c - 664 sys sys 953242987 13173
-sys/src/cmd/spin/sched.c - 664 sys sys 953242987 19359
-sys/src/cmd/spin/spin.h - 664 sys sys 953242987 10807
-sys/src/cmd/spin/spin.y - 664 sys sys 953242987 16731
-sys/src/cmd/spin/spinlex.c - 664 sys sys 953242987 13809
-sys/src/cmd/spin/structs.c - 664 sys sys 953242988 13364
-sys/src/cmd/spin/sym.c - 664 sys sys 953242988 11763
-sys/src/cmd/spin/tl.h - 664 sys sys 953242988 3254
-sys/src/cmd/spin/tl_buchi.c - 664 sys sys 953242988 13164
-sys/src/cmd/spin/tl_cache.c - 664 sys sys 953242988 5732
-sys/src/cmd/spin/tl_lex.c - 664 sys sys 953242988 3132
-sys/src/cmd/spin/tl_main.c - 664 sys sys 953242988 4331
-sys/src/cmd/spin/tl_mem.c - 664 sys sys 953242988 2592
-sys/src/cmd/spin/tl_parse.c - 664 sys sys 953242989 8007
-sys/src/cmd/spin/tl_rewrt.c - 664 sys sys 953242989 6257
-sys/src/cmd/spin/tl_trans.c - 664 sys sys 953242990 16758
-sys/src/cmd/spin/vars.c - 664 sys sys 953242990 8412
-sys/src/cmd/spin/version.h - 664 sys sys 956275780 54
+sys/src/cmd/spin/README - 664 sys sys 1125514858 311
+sys/src/cmd/spin/dstep.c - 664 sys sys 1125514858 9958
+sys/src/cmd/spin/flow.c - 664 sys sys 1125514858 17345
+sys/src/cmd/spin/guided.c - 664 sys sys 1125514858 6948
+sys/src/cmd/spin/main.c - 664 sys sys 1125514858 21713
+sys/src/cmd/spin/mesg.c - 664 sys sys 1125514858 13722
+sys/src/cmd/spin/mkfile - 664 sys sys 1125514859 696
+sys/src/cmd/spin/pangen1.c - 664 sys sys 1125514859 29801
+sys/src/cmd/spin/pangen1.h - 664 sys sys 1125514859 134192
+sys/src/cmd/spin/pangen2.c - 664 sys sys 1125514859 74348
+sys/src/cmd/spin/pangen2.h - 664 sys sys 1125514860 23109
+sys/src/cmd/spin/pangen3.c - 664 sys sys 1125514860 8941
+sys/src/cmd/spin/pangen3.h - 664 sys sys 1125514860 22484
+sys/src/cmd/spin/pangen4.c - 664 sys sys 1125514860 8180
+sys/src/cmd/spin/pangen4.h - 664 sys sys 1125514860 19033
+sys/src/cmd/spin/pangen5.c - 664 sys sys 1125514860 16851
+sys/src/cmd/spin/pangen5.h - 664 sys sys 1125514861 11145
+sys/src/cmd/spin/pangen6.c - 664 sys sys 1125514861 48633
+sys/src/cmd/spin/pc_zpp.c - 664 sys sys 1125514861 8737
+sys/src/cmd/spin/ps_msc.c - 664 sys sys 1125514861 11872
+sys/src/cmd/spin/reprosrc.c - 664 sys sys 1125514861 2978
+sys/src/cmd/spin/run.c - 664 sys sys 1125514862 14405
+sys/src/cmd/spin/sched.c - 664 sys sys 1125514862 21096
+sys/src/cmd/spin/spin.h - 664 sys sys 1125514862 12286
+sys/src/cmd/spin/spin.y - 664 sys sys 1125514862 18876
+sys/src/cmd/spin/spinlex.c - 664 sys sys 1125514862 30767
+sys/src/cmd/spin/structs.c - 664 sys sys 1125514863 14150
+sys/src/cmd/spin/sym.c - 664 sys sys 1125514863 11863
+sys/src/cmd/spin/tl.h - 664 sys sys 1125514863 3332
+sys/src/cmd/spin/tl_buchi.c - 664 sys sys 1125514863 13080
+sys/src/cmd/spin/tl_cache.c - 664 sys sys 1125514863 5831
+sys/src/cmd/spin/tl_lex.c - 664 sys sys 1125514863 3243
+sys/src/cmd/spin/tl_main.c - 664 sys sys 1125514863 4412
+sys/src/cmd/spin/tl_mem.c - 664 sys sys 1125514864 2670
+sys/src/cmd/spin/tl_parse.c - 664 sys sys 1125514864 8257
+sys/src/cmd/spin/tl_rewrt.c - 664 sys sys 1125514864 5962
+sys/src/cmd/spin/tl_trans.c - 664 sys sys 1125514864 16758
+sys/src/cmd/spin/vars.c - 664 sys sys 1125514864 8393
+sys/src/cmd/spin/version.h - 664 sys sys 1125514864 53
 sys/src/cmd/split.c - 664 sys sys 1116770353 3225
 sys/src/cmd/split.c - 664 sys sys 1116770353 3225
 sys/src/cmd/srv.c - 664 sys sys 1074452607 3885
 sys/src/cmd/srv.c - 664 sys sys 1074452607 3885
 sys/src/cmd/srvfs.c - 664 sys sys 1116770384 1702
 sys/src/cmd/srvfs.c - 664 sys sys 1116770384 1702
@@ -12923,7 +12925,7 @@ sys/src/cmd/tapefs/v10fs.c - 664 sys sys 1014926385 3754
 sys/src/cmd/tapefs/v6fs.c - 664 sys sys 1014926385 3971
 sys/src/cmd/tapefs/v6fs.c - 664 sys sys 1014926385 3971
 sys/src/cmd/tapefs/zip.h - 664 sys sys 1097914153 1428
 sys/src/cmd/tapefs/zip.h - 664 sys sys 1097914153 1428
 sys/src/cmd/tapefs/zipfs.c - 664 sys sys 1097900277 6803
 sys/src/cmd/tapefs/zipfs.c - 664 sys sys 1097900277 6803
-sys/src/cmd/tar.c - 664 sys sys 1119986000 21041
+sys/src/cmd/tar.c - 664 sys sys 1125515072 21269
 sys/src/cmd/tbl - 20000000775 sys sys 954038038 0
 sys/src/cmd/tbl - 20000000775 sys sys 954038038 0
 sys/src/cmd/tbl/mkfile - 664 sys sys 944961243 268
 sys/src/cmd/tbl/mkfile - 664 sys sys 944961243 268
 sys/src/cmd/tbl/t.h - 664 sys sys 944961244 3987
 sys/src/cmd/tbl/t.h - 664 sys sys 944961244 3987
@@ -12991,7 +12993,7 @@ sys/src/cmd/tcs/kuten212.h - 664 sys sys 944961287 94
 sys/src/cmd/tcs/mkfile - 664 sys sys 1036724422 532
 sys/src/cmd/tcs/mkfile - 664 sys sys 1036724422 532
 sys/src/cmd/tcs/plan9.h - 664 sys sys 944961287 751
 sys/src/cmd/tcs/plan9.h - 664 sys sys 944961287 751
 sys/src/cmd/tcs/tcs.c - 664 sys sys 1044661975 51805
 sys/src/cmd/tcs/tcs.c - 664 sys sys 1044661975 51805
-sys/src/cmd/tcs/utf.c - 664 sys sys 1044661976 7951
+sys/src/cmd/tcs/utf.c - 664 sys sys 1125501123 7962
 sys/src/cmd/tee.c - 664 sys sys 954970286 1062
 sys/src/cmd/tee.c - 664 sys sys 954970286 1062
 sys/src/cmd/telco - 20000000775 sys sys 1015701205 0
 sys/src/cmd/telco - 20000000775 sys sys 1015701205 0
 sys/src/cmd/telco/mkfile - 664 sys sys 944961290 201
 sys/src/cmd/telco/mkfile - 664 sys sys 944961290 201
@@ -13242,8 +13244,8 @@ sys/src/cmd/unix/netkey.c - 664 sys sys 1045152984 21761
 sys/src/cmd/unix/sam - 20000000775 sys sys 954263160 0
 sys/src/cmd/unix/sam - 20000000775 sys sys 954263160 0
 sys/src/cmd/unix/sam/README - 664 sys sys 1110289373 306
 sys/src/cmd/unix/sam/README - 664 sys sys 1110289373 306
 sys/src/cmd/unix/spin - 20000000775 sys sys 956275829 0
 sys/src/cmd/unix/spin - 20000000775 sys sys 956275829 0
-sys/src/cmd/unix/spin/readme - 664 sys sys 956275829 271
-sys/src/cmd/unix/spin/spin334.tar.gz - 664 sys sys 956275830 264112
+sys/src/cmd/unix/spin/readme - 664 sys sys 1125514575 247
+sys/src/cmd/unix/spin/spin425.tar.gz - 664 sys sys 1125514573 330078
 sys/src/cmd/unix/tcs.shar.Z - 664 sys sys 944961315 312440
 sys/src/cmd/unix/tcs.shar.Z - 664 sys sys 944961315 312440
 sys/src/cmd/unix/u9fs - 20000000775 sys sys 1015092354 0
 sys/src/cmd/unix/u9fs - 20000000775 sys sys 1015092354 0
 sys/src/cmd/unix/u9fs/authnone.c - 664 sys sys 1015092351 321
 sys/src/cmd/unix/u9fs/authnone.c - 664 sys sys 1015092351 321
@@ -13783,7 +13785,7 @@ sys/src/games/mahjongg/level.c - 664 sys sys 1095792293 2522
 sys/src/games/mahjongg/mahjongg.c - 664 sys sys 1095792293 3452
 sys/src/games/mahjongg/mahjongg.c - 664 sys sys 1095792293 3452
 sys/src/games/mahjongg/mahjongg.h - 664 sys sys 1095792293 1606
 sys/src/games/mahjongg/mahjongg.h - 664 sys sys 1095792293 1606
 sys/src/games/mahjongg/mkfile - 664 sys sys 1095792293 230
 sys/src/games/mahjongg/mkfile - 664 sys sys 1095792293 230
-sys/src/games/memo.c - 664 sys sys 1110436470 6837
+sys/src/games/memo.c - 664 sys sys 1125514848 6321
 sys/src/games/mkfile - 664 sys sys 1118672535 567
 sys/src/games/mkfile - 664 sys sys 1118672535 567
 sys/src/games/music - 20000000775 sys sys 1103793915 0
 sys/src/games/music - 20000000775 sys sys 1103793915 0
 sys/src/games/music/Readme - 664 sys sys 1103793914 488
 sys/src/games/music/Readme - 664 sys sys 1103793914 488

+ 60 - 0
dist/replica/plan9.log

@@ -21155,3 +21155,63 @@
 1125347550 230 c acme/bin/386/News - 775 sys sys 1125346044 128804
 1125347550 230 c acme/bin/386/News - 775 sys sys 1125346044 128804
 1125347550 231 c acme/bin/386/Wiki - 775 sys sys 1125346044 127380
 1125347550 231 c acme/bin/386/Wiki - 775 sys sys 1125346044 127380
 1125347550 232 c acme/bin/386/spout - 775 sys sys 1125346044 61608
 1125347550 232 c acme/bin/386/spout - 775 sys sys 1125346044 61608
+1125502264 0 c 386/bin/tcs - 775 sys sys 1125501123 256580
+1125502264 1 c sys/src/cmd/tcs/utf.c - 664 sys sys 1125501123 7962
+1125514868 0 c sys/src/cmd/spin/README - 664 sys sys 1125514858 311
+1125514868 1 c sys/src/cmd/spin/dstep.c - 664 sys sys 1125514858 9958
+1125514868 2 c sys/src/cmd/spin/flow.c - 664 sys sys 1125514858 17345
+1125514868 3 c sys/src/cmd/spin/guided.c - 664 sys sys 1125514858 6948
+1125514868 4 c sys/src/cmd/spin/main.c - 664 sys sys 1125514858 21713
+1125514868 5 c sys/src/cmd/spin/mesg.c - 664 sys sys 1125514858 13722
+1125514868 6 c sys/src/cmd/spin/mkfile - 664 sys sys 1125514859 696
+1125514868 7 c sys/src/cmd/spin/pangen1.c - 664 sys sys 1125514859 29801
+1125514868 8 c sys/src/cmd/spin/pangen1.h - 664 sys sys 1125514859 134192
+1125514868 9 c sys/src/cmd/spin/pangen2.c - 664 sys sys 1125514859 74348
+1125514868 10 c sys/src/cmd/spin/pangen2.h - 664 sys sys 1125514860 23109
+1125514868 11 c sys/src/cmd/spin/pangen3.c - 664 sys sys 1125514860 8941
+1125514868 12 c sys/src/cmd/spin/pangen3.h - 664 sys sys 1125514860 22484
+1125514868 13 c sys/src/cmd/spin/pangen4.c - 664 sys sys 1125514860 8180
+1125514868 14 c sys/src/cmd/spin/pangen4.h - 664 sys sys 1125514860 19033
+1125514868 15 c sys/src/cmd/spin/pangen5.c - 664 sys sys 1125514860 16851
+1125514868 16 c sys/src/cmd/spin/pangen5.h - 664 sys sys 1125514861 11145
+1125514868 17 a sys/src/cmd/spin/pangen6.c - 664 sys sys 1125514861 48633
+1125514868 18 c sys/src/cmd/spin/pc_zpp.c - 664 sys sys 1125514861 8737
+1125514868 19 c sys/src/cmd/spin/ps_msc.c - 664 sys sys 1125514861 11872
+1125514868 20 a sys/src/cmd/spin/reprosrc.c - 664 sys sys 1125514861 2978
+1125514868 21 c sys/src/cmd/spin/run.c - 664 sys sys 1125514862 14405
+1125514868 22 c sys/src/cmd/spin/sched.c - 664 sys sys 1125514862 21096
+1125514868 23 c sys/src/cmd/spin/spin.h - 664 sys sys 1125514862 12286
+1125514868 24 c sys/src/cmd/spin/spin.y - 664 sys sys 1125514862 18876
+1125514868 25 c sys/src/cmd/spin/spinlex.c - 664 sys sys 1125514862 30767
+1125514868 26 c sys/src/cmd/spin/structs.c - 664 sys sys 1125514863 14150
+1125514868 27 c sys/src/cmd/spin/sym.c - 664 sys sys 1125514863 11863
+1125514868 28 c sys/src/cmd/spin/tl.h - 664 sys sys 1125514863 3332
+1125514868 29 c sys/src/cmd/spin/tl_buchi.c - 664 sys sys 1125514863 13080
+1125514868 30 c sys/src/cmd/spin/tl_cache.c - 664 sys sys 1125514863 5831
+1125514868 31 c sys/src/cmd/spin/tl_lex.c - 664 sys sys 1125514863 3243
+1125514868 32 c sys/src/cmd/spin/tl_main.c - 664 sys sys 1125514863 4412
+1125514868 33 c sys/src/cmd/spin/tl_mem.c - 664 sys sys 1125514864 2670
+1125514868 34 c sys/src/cmd/spin/tl_parse.c - 664 sys sys 1125514864 8257
+1125514868 35 c sys/src/cmd/spin/tl_rewrt.c - 664 sys sys 1125514864 5962
+1125514868 36 c sys/src/cmd/spin/tl_trans.c - 664 sys sys 1125514864 16758
+1125514868 37 c sys/src/cmd/spin/vars.c - 664 sys sys 1125514864 8393
+1125514868 38 c sys/src/cmd/spin/version.h - 664 sys sys 1125514864 53
+1125514868 39 c sys/src/cmd/unix/spin/readme - 664 sys sys 1125514575 247
+1125514868 40 a sys/src/cmd/unix/spin/spin425.tar.gz - 664 sys sys 1125514573 330078
+1125514868 41 c sys/src/games/memo.c - 664 sys sys 1125514848 6321
+1125514868 42 d sys/src/cmd/unix/spin/spin334.tar.gz - 664 sys sys 956275830 0
+1125516669 0 c sys/src/cmd/tar.c - 664 sys sys 1125515072 21269
+1125518469 0 c sys/src/9/port/chan.c - 664 sys sys 1125517669 30203
+1125529271 0 c sys/src/cmd/ip/ppp/ipaux.c - 664 sys sys 1125529107 2328
+1125529271 1 c sys/src/cmd/seq.c - 664 sys sys 1125529033 1683
+1125531072 0 c sys/man/8/ppp - 664 sys sys 1125530075 4414
+1125531072 1 c sys/src/cmd/ip/ppp/ppp.c - 664 sys sys 1125530039 59897
+1125531072 2 c sys/src/cmd/ip/pppoe.c - 664 sys sys 1125530113 12516
+1125541873 0 c sys/man/2/setjmp - 664 sys sys 1125540984 1857
+1125545475 0 c 386/bin/games/memo - 775 sys sys 1125544173 156892
+1125545475 1 c 386/bin/seq - 775 sys sys 1125544174 38396
+1125545475 2 c 386/bin/spin - 775 sys sys 1125544175 758333
+1125545475 3 c 386/bin/ip/ppp - 775 sys sys 1125544173 218875
+1125545475 4 c 386/bin/ip/pppoe - 775 sys sys 1125544173 77548
+1125545475 5 c 386/bin/tar - 775 sys sys 1125544175 96517
+1125545475 6 c 386/bin/tcs - 775 sys sys 1125544176 256580

+ 1 - 1
sys/man/2/setjmp

@@ -81,7 +81,7 @@ setlabel(void)
 {
 {
 	label[JMPBUFPC] = ((ulong)f+JMPBUFDPC);
 	label[JMPBUFPC] = ((ulong)f+JMPBUFDPC);
 	/* -2 leaves room for old pc and new pc in frame */
 	/* -2 leaves room for old pc and new pc in frame */
-	label[JMPBUFSP =
+	label[JMPBUFSP] =
 	        (ulong)(&stack[NSTACK-2*sizeof(ulong*)]);
 	        (ulong)(&stack[NSTACK-2*sizeof(ulong*)]);
 }
 }
 .EE
 .EE

+ 22 - 25
sys/man/8/ppp

@@ -34,7 +34,19 @@ ppp, pppoe, pptp, pptpd \- point to point protocol
 .PP
 .PP
 .B ip/pppoe
 .B ip/pppoe
 [
 [
-.B -dP
+.B -Pd
+]
+[
+.B -A
+.I acname
+]
+[
+.B -S
+.I srvname
+]
+[
+.B -k
+.I keyspec
 ]
 ]
 [
 [
 .B -m
 .B -m
@@ -44,7 +56,9 @@ ppp, pppoe, pptp, pptpd \- point to point protocol
 .B -x
 .B -x
 .I pppnetmntpt
 .I pppnetmntpt
 ]
 ]
-.I etherdir
+[
+.I ether
+]
 .PP
 .PP
 .B ip/pptp
 .B ip/pptp
 [
 [
@@ -180,7 +194,9 @@ the ethernet device mounted at
 .I etherdir
 .I etherdir
 (default
 (default
 .BR /net/ether0 ).
 .BR /net/ether0 ).
-The options are:
+The 
+.I pppoe -specific
+options are:
 .TP
 .TP
 .B A
 .B A
 insist on an access concentrator named
 insist on an access concentrator named
@@ -198,30 +214,11 @@ and pass
 .B -d
 .B -d
 to 
 to 
 .I ppp
 .I ppp
-.TP
-.B m
-pass
-.B -m
-.I mtu
-to 
-.IR ppp ,
-default 1492
-.TP
-.B k
-pass
-.B -k
-.I keyspec
-to
-.I ppp
-.TP
-.B x
-pass
-.B -x
-.I pppnetmntpt
-to 
-.I ppp
 .PD
 .PD
 .PP
 .PP
+The other options are relayed to 
+.IR ppp .
+.PP
 .I Pptp
 .I Pptp
 is a client for a PPTP encrypted tunnel.
 is a client for a PPTP encrypted tunnel.
 .I Server
 .I Server

+ 41 - 31
sys/src/9/port/chan.c

@@ -77,11 +77,13 @@ typedef struct Elemlist Elemlist;
 
 
 struct Elemlist
 struct Elemlist
 {
 {
+	char	*aname;	/* original name */
 	char	*name;	/* copy of name, so '/' can be overwritten */
 	char	*name;	/* copy of name, so '/' can be overwritten */
 	int	nelems;
 	int	nelems;
 	char	**elems;
 	char	**elems;
 	int	*off;
 	int	*off;
 	int	mustbedir;
 	int	mustbedir;
+	int	nerror;
 };
 };
 
 
 #define SEP(c) ((c) == 0 || (c) == '/')
 #define SEP(c) ((c) == 0 || (c) == '/')
@@ -897,7 +899,7 @@ walk(Chan **cp, char **names, int nnames, int nomount, int *nerror)
 	cclose(*cp);
 	cclose(*cp);
 	*cp = c;
 	*cp = c;
 	if(nerror)
 	if(nerror)
-		*nerror = 0;
+		*nerror = nhave;
 	return 0;
 	return 0;
 }
 }
 
 
@@ -1015,6 +1017,7 @@ parsename(char *name, Elemlist *e)
 		*slash++ = '\0';
 		*slash++ = '\0';
 		name = slash;
 		name = slash;
 	}
 	}
+	e->off[e->nelems] = name - e->name;
 }
 }
 
 
 void*
 void*
@@ -1030,21 +1033,24 @@ memrchr(void *va, int c, long n)
 }
 }
 
 
 void
 void
-nameerror(char *name, char *error)
+namelenerror(char *aname, int len, char *err)
 {
 {
-	int len;
-	char tmperr[ERRMAX], *p;
+	char *name;
 
 
-	strcpy(tmperr, error);	/* error might be in genbuf or tmperr */
-	len = strlen(name);
-	if(len < ERRMAX/3 || (p=strrchr(name, '/'))==nil || p==name)
-		snprint(up->genbuf, sizeof up->genbuf, "%s", name);
+	if(len < ERRMAX/3 || (name=memrchr(aname, '/', len))==nil || name==aname)
+		snprint(up->genbuf, sizeof up->genbuf, "%.*s", len, aname);
 	else
 	else
-		snprint(up->genbuf, sizeof up->genbuf, "...%s", p);
-	snprint(up->errstr, ERRMAX, "%#q %s", up->genbuf, tmperr);
+		snprint(up->genbuf, sizeof up->genbuf, "...%.*s", (int)(len-(name-aname)), name);
+	snprint(up->errstr, ERRMAX, "%#q %s", up->genbuf, err);
 	nexterror();
 	nexterror();
 }
 }
 
 
+void
+nameerror(char *name, char *err)
+{
+	namelenerror(name, strlen(name), err);
+}
+
 /*
 /*
  * Turn a name into a channel.
  * Turn a name into a channel.
  * &name[0] is known to be a valid address.  It may be a kernel address.
  * &name[0] is known to be a valid address.  It may be a kernel address.
@@ -1064,7 +1070,7 @@ nameerror(char *name, char *error)
 Chan*
 Chan*
 namec(char *aname, int amode, int omode, ulong perm)
 namec(char *aname, int amode, int omode, ulong perm)
 {
 {
-	int n, t, nomount, npath;
+	int n, t, nomount;
 	Chan *c, *cnew;
 	Chan *c, *cnew;
 	Cname *cname;
 	Cname *cname;
 	Elemlist e;
 	Elemlist e;
@@ -1073,14 +1079,14 @@ namec(char *aname, int amode, int omode, ulong perm)
 	char *createerr, tmperrbuf[ERRMAX];
 	char *createerr, tmperrbuf[ERRMAX];
 	char *name;
 	char *name;
 
 
-	name = aname;
-	if(name[0] == '\0')
+	if(aname[0] == '\0')
 		error("empty file name");
 		error("empty file name");
-	name = validnamedup(name, 1);
+	aname = validnamedup(aname, 1);
 	if(waserror()){
 	if(waserror()){
-		free(name);
+		free(aname);
 		nexterror();
 		nexterror();
 	}
 	}
+	name = aname;
 
 
 	/*
 	/*
 	 * Find the starting off point (the current slash, the root of
 	 * Find the starting off point (the current slash, the root of
@@ -1134,17 +1140,24 @@ namec(char *aname, int amode, int omode, ulong perm)
 		break;
 		break;
 	}
 	}
 
 
+	e.aname = aname;
 	e.name = nil;
 	e.name = nil;
 	e.elems = nil;
 	e.elems = nil;
 	e.off = nil;
 	e.off = nil;
 	e.nelems = 0;
 	e.nelems = 0;
+	e.nerror = 0;
 	if(waserror()){
 	if(waserror()){
 		cclose(c);
 		cclose(c);
 		free(e.name);
 		free(e.name);
 		free(e.elems);
 		free(e.elems);
 		free(e.off);
 		free(e.off);
-//dumpmount();
-		nexterror();
+		/*
+		 * Prepare nice error, showing first e.nerror elements of name.
+		 */
+		if(e.nerror == 0)
+			nexterror();
+		strcpy(tmperrbuf, up->errstr);
+		namelenerror(aname, (name-aname)+e.off[e.nerror], tmperrbuf);
 	}
 	}
 
 
 	/*
 	/*
@@ -1158,8 +1171,8 @@ namec(char *aname, int amode, int omode, ulong perm)
 	if(amode == Acreate){
 	if(amode == Acreate){
 		/* perm must have DMDIR if last element is / or /. */
 		/* perm must have DMDIR if last element is / or /. */
 		if(e.mustbedir && !(perm&DMDIR)){
 		if(e.mustbedir && !(perm&DMDIR)){
-			npath = e.nelems;
-			nameerror(aname, "create without DMDIR");
+			e.nerror = e.nelems;
+			error("create without DMDIR");
 		}
 		}
 
 
 		/* don't try to walk the last path element just yet. */
 		/* don't try to walk the last path element just yet. */
@@ -1168,23 +1181,19 @@ namec(char *aname, int amode, int omode, ulong perm)
 		e.nelems--;
 		e.nelems--;
 	}
 	}
 
 
-	if(walk(&c, e.elems, e.nelems, nomount, &npath) < 0){
-		if(npath < 0 || npath > e.nelems){
-			print("namec %s walk error npath=%d\n", aname, npath);
-			nexterror();
+	if(walk(&c, e.elems, e.nelems, nomount, &e.nerror) < 0){
+		if(e.nerror < 0 || e.nerror > e.nelems){
+			print("namec %s walk error nerror=%d\n", aname, e.nerror);
+			e.nerror = 0;
 		}
 		}
-		nameerror(aname, up->errstr);
+		nexterror();
 	}
 	}
 
 
-	if(e.mustbedir && !(c->qid.type&QTDIR)){
-		npath = e.nelems;
-		nameerror(aname, "not a directory");
-	}
+	if(e.mustbedir && !(c->qid.type&QTDIR))
+		error("not a directory");
 
 
-	if(amode == Aopen && (omode&3) == OEXEC && (c->qid.type&QTDIR)){
-		npath = e.nelems;
+	if(amode == Aopen && (omode&3) == OEXEC && (c->qid.type&QTDIR))
 		error("cannot exec directory");
 		error("cannot exec directory");
-	}
 
 
 	switch(amode){
 	switch(amode){
 	case Abind:
 	case Abind:
@@ -1276,6 +1285,7 @@ if(c->umh != nil){
 		 * If omode&OEXCL is set, just give up.
 		 * If omode&OEXCL is set, just give up.
 		 */
 		 */
 		e.nelems++;
 		e.nelems++;
+		e.nerror++;
 		if(walk(&c, e.elems+e.nelems-1, 1, nomount, nil) == 0){
 		if(walk(&c, e.elems+e.nelems-1, 1, nomount, nil) == 0){
 			if(omode&OEXCL)
 			if(omode&OEXCL)
 				error(Eexist);
 				error(Eexist);

+ 1 - 1
sys/src/cmd/ip/ppp/ipaux.c

@@ -19,7 +19,7 @@ ptclbsum(uchar *addr, int len)
 	mdsum = 0;
 	mdsum = 0;
 
 
 	x = 0;
 	x = 0;
-	if((ulong)addr & 1) {
+	if((uintptr)addr & 1) {
 		if(len) {
 		if(len) {
 			hisum += addr[0];
 			hisum += addr[0];
 			len--;
 			len--;

+ 4 - 4
sys/src/cmd/ip/ppp/ppp.c

@@ -2892,13 +2892,13 @@ putndb(PPP *ppp, char *net)
 	p = seprint(p, e, "ip=%I ipmask=255.255.255.255 ipgw=%I\n", ppp->local,
 	p = seprint(p, e, "ip=%I ipmask=255.255.255.255 ipgw=%I\n", ppp->local,
 			ppp->remote);
 			ppp->remote);
 	if(validv4(ppp->dns[0]))
 	if(validv4(ppp->dns[0]))
-		p = seprint(p, e, "\tdns=%I", ppp->dns[0]);
+		p = seprint(p, e, "\tdns=%I\n", ppp->dns[0]);
 	if(validv4(ppp->dns[1]))
 	if(validv4(ppp->dns[1]))
-		p = seprint(p, e, "\tdns=%I", ppp->dns[1]);
+		p = seprint(p, e, "\tdns=%I\n", ppp->dns[1]);
 	if(validv4(ppp->wins[0]))
 	if(validv4(ppp->wins[0]))
-		p = seprint(p, e, "\twins=%I", ppp->wins[0]);
+		p = seprint(p, e, "\twins=%I\n", ppp->wins[0]);
 	if(validv4(ppp->wins[1]))
 	if(validv4(ppp->wins[1]))
-		p = seprint(p, e, "\twins=%I", ppp->wins[1]);
+		p = seprint(p, e, "\twins=%I\n", ppp->wins[1]);
 	seprint(file, file+sizeof file, "%s/ndb", net);
 	seprint(file, file+sizeof file, "%s/ndb", net);
 	fd = open(file, OWRITE);
 	fd = open(file, OWRITE);
 	if(fd < 0)
 	if(fd < 0)

+ 5 - 5
sys/src/cmd/ip/pppoe.c

@@ -17,7 +17,7 @@ void execppp(int);
 int alarmed;
 int alarmed;
 int debug;
 int debug;
 int sessid;
 int sessid;
-char *namesecret;
+char *keyspec;
 int primary;
 int primary;
 char *pppnetmtpt;
 char *pppnetmtpt;
 char *acname;
 char *acname;
@@ -32,7 +32,7 @@ int mtu = 1492;
 void
 void
 usage(void)
 usage(void)
 {
 {
-	fprint(2, "usage: pppoe [-Pd] [-S srvname] [-s name:pass] [-x pppnet] ether0\n");
+	fprint(2, "usage: pppoe [-Pd] [-A acname] [-S srvname] [-k keyspec] [-m mtu] [-x pppnet] [ether0]\n");
 	exits("usage");
 	exits("usage");
 }
 }
 
 
@@ -73,7 +73,7 @@ main(int argc, char **argv)
 		mtu = atoi(EARGF(usage()));
 		mtu = atoi(EARGF(usage()));
 		break;
 		break;
 	case 'k':
 	case 'k':
-		namesecret = EARGF(usage());
+		keyspec = EARGF(usage());
 		break;
 		break;
 	case 'x':
 	case 'x':
 		pppnetmtpt = EARGF(usage());
 		pppnetmtpt = EARGF(usage());
@@ -522,9 +522,9 @@ execppp(int fd)
 		argv[argc++] = "-x";
 		argv[argc++] = "-x";
 		argv[argc++] = pppnetmtpt;
 		argv[argc++] = pppnetmtpt;
 	}
 	}
-	if(namesecret){
+	if(keyspec){
 		argv[argc++] = "-k";
 		argv[argc++] = "-k";
-		argv[argc++] = namesecret;
+		argv[argc++] = keyspec;
 	}
 	}
 	argv[argc] = nil;
 	argv[argc] = nil;
 
 

+ 16 - 6
sys/src/cmd/seq.c

@@ -81,12 +81,22 @@ main(int argc, char *argv[]){
 	}
 	}
 	if(!format)
 	if(!format)
 		buildfmt();
 		buildfmt();
-	for(val = min; val <= max; val += incr){
-		n = sprint(buf, format, val);
-		if(constant)
-			for(j=0; buf[j]==' '; j++)
-				buf[j] ='0';
-		write(1, buf, n);
+	if(incr > 0){
+		for(val = min; val <= max; val += incr){
+			n = sprint(buf, format, val);
+			if(constant)
+				for(j=0; buf[j]==' '; j++)
+					buf[j] ='0';
+			write(1, buf, n);
+		}
+	}else{
+		for(val = min; val >= max; val += incr){
+			n = sprint(buf, format, val);
+			if(constant)
+				for(j=0; buf[j]==' '; j++)
+					buf[j] ='0';
+			write(1, buf, n);
+		}
 	}
 	}
 	exits(0);
 	exits(0);
 }
 }

+ 1 - 2
sys/src/cmd/spin/README

@@ -1,12 +1,11 @@
 the latest version of spin is always
 the latest version of spin is always
 available via:
 available via:
-	http://cm.bell-labs.com/cm/cs/what/spin/
+	http://spinroot.com/spin/whatispin.html
 
 
 to make the sources compile with the mkfile on plan 9
 to make the sources compile with the mkfile on plan 9
 the following changes were made:
 the following changes were made:
 
 
 	omitted memory.h from spin.h
 	omitted memory.h from spin.h
-	omitted malloc.h from ps_msc.c
 	changed /lib/cpp to /bin/cpp in main.c
 	changed /lib/cpp to /bin/cpp in main.c
 	simplified non_fatal() in main.c to remove
 	simplified non_fatal() in main.c to remove
 	use of yychar
 	use of yychar

+ 56 - 20
sys/src/cmd/spin/dstep.c

@@ -1,14 +1,13 @@
 /***** spin: dstep.c *****/
 /***** spin: dstep.c *****/
 
 
-/* Copyright (c) 1991-2000 by Lucent Technologies - Bell Laboratories     */
+/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories.     */
 /* All Rights Reserved.  This software is for educational purposes only.  */
 /* All Rights Reserved.  This software is for educational purposes only.  */
-/* Permission is given to distribute this code provided that this intro-  */
-/* ductory message is not removed and no monies are exchanged.            */
-/* No guarantee is expressed or implied by the distribution of this code. */
-/* Software written by Gerard J. Holzmann as part of the book:            */
-/* `Design and Validation of Computer Protocols,' ISBN 0-13-539925-4,     */
-/* Prentice Hall, Englewood Cliffs, NJ, 07632.                            */
-/* Send bug-reports and/or questions to: gerard@research.bell-labs.com    */
+/* No guarantee whatsoever is expressed or implied by the distribution of */
+/* this code.  Permission is given to distribute this code provided that  */
+/* this introductory message is not removed and no monies are exchanged.  */
+/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
+/*             http://spinroot.com/                                       */
+/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
 
 
 #include "spin.h"
 #include "spin.h"
 #ifdef PC
 #ifdef PC
@@ -26,7 +25,7 @@ static int	Tj=0, Jt=0, LastGoto=0;
 static int	Tojump[MAXDSTEP], Jumpto[MAXDSTEP], Special[MAXDSTEP];
 static int	Tojump[MAXDSTEP], Jumpto[MAXDSTEP], Special[MAXDSTEP];
 static void	putCode(FILE *, Element *, Element *, Element *, int);
 static void	putCode(FILE *, Element *, Element *, Element *, int);
 
 
-extern int	Pid, claimnr;
+extern int	Pid, claimnr, separate, OkBreak;
 
 
 static void
 static void
 Sourced(int n, int special)
 Sourced(int n, int special)
@@ -57,7 +56,7 @@ Dested(int n)
 
 
 static void
 static void
 Mopup(FILE *fd)
 Mopup(FILE *fd)
-{	int i, j; extern int OkBreak;
+{	int i, j;
 
 
 	for (i = 0; i < Jt; i++)
 	for (i = 0; i < Jt; i++)
 	{	for (j = 0; j < Tj; j++)
 	{	for (j = 0; j < Tj; j++)
@@ -172,10 +171,21 @@ CollectGuards(FILE *fd, Element *e, int inh)
 			fprintf(fd, "(1 /* else */)");
 			fprintf(fd, "(1 /* else */)");
 			break;
 			break;
 		case 'R':
 		case 'R':
+			if (inh++ > 0) fprintf(fd, " || ");
+			fprintf(fd, "("); TestOnly=1;
+			putstmnt(fd, ee->n, ee->seqno);
+			fprintf(fd, ")"); TestOnly=0;
+			break;
 		case 'r':
 		case 'r':
+			if (inh++ > 0) fprintf(fd, " || ");
+			fprintf(fd, "("); TestOnly=1;
+			putstmnt(fd, ee->n, ee->seqno);
+			fprintf(fd, ")"); TestOnly=0;
+			break;
 		case 's':
 		case 's':
 			if (inh++ > 0) fprintf(fd, " || ");
 			if (inh++ > 0) fprintf(fd, " || ");
 			fprintf(fd, "("); TestOnly=1;
 			fprintf(fd, "("); TestOnly=1;
+/* 4.2.1 */		if (Pid != claimnr) fprintf(fd, "(boq == -1) && ");
 			putstmnt(fd, ee->n, ee->seqno);
 			putstmnt(fd, ee->n, ee->seqno);
 			fprintf(fd, ")"); TestOnly=0;
 			fprintf(fd, ")"); TestOnly=0;
 			break;
 			break;
@@ -194,7 +204,7 @@ CollectGuards(FILE *fd, Element *e, int inh)
 }
 }
 
 
 int
 int
-putcode(FILE *fd, Sequence *s, Element *nxt, int justguards, int ln)
+putcode(FILE *fd, Sequence *s, Element *nxt, int justguards, int ln, int seqno)
 {	int isg=0; char buf[64];
 {	int isg=0; char buf[64];
 
 
 	NextLab[0] = "continue";
 	NextLab[0] = "continue";
@@ -203,13 +213,13 @@ putcode(FILE *fd, Sequence *s, Element *nxt, int justguards, int ln)
 	switch (s->frst->n->ntyp) {
 	switch (s->frst->n->ntyp) {
 	case UNLESS:
 	case UNLESS:
 		non_fatal("'unless' inside d_step - ignored", (char *) 0);
 		non_fatal("'unless' inside d_step - ignored", (char *) 0);
-		return putcode(fd, s->frst->n->sl->this, nxt, 0, ln);
+		return putcode(fd, s->frst->n->sl->this, nxt, 0, ln, seqno);
 	case NON_ATOMIC:
 	case NON_ATOMIC:
-		(void) putcode(fd, s->frst->n->sl->this, ZE, 1, ln);
+		(void) putcode(fd, s->frst->n->sl->this, ZE, 1, ln, seqno);
 		break;
 		break;
 	case IF:
 	case IF:
 		fprintf(fd, "if (!(");
 		fprintf(fd, "if (!(");
-		if (!CollectGuards(fd, s->frst, 0))
+		if (!CollectGuards(fd, s->frst, 0))	/* what about boq? */
 			fprintf(fd, "1");
 			fprintf(fd, "1");
 		fprintf(fd, "))\n\t\t\tcontinue;");
 		fprintf(fd, "))\n\t\t\tcontinue;");
 		isg = 1;
 		isg = 1;
@@ -224,12 +234,24 @@ putcode(FILE *fd, Sequence *s, Element *nxt, int justguards, int ln)
 		}
 		}
 		break;
 		break;
 	case 'R': /* <- can't really happen (it's part of a 'c') */
 	case 'R': /* <- can't really happen (it's part of a 'c') */
+		fprintf(fd, "if (!("); TestOnly=1;
+		putstmnt(fd, s->frst->n, s->frst->seqno);
+		fprintf(fd, "))\n\t\t\tcontinue;"); TestOnly=0;
+		break;
 	case 'r':
 	case 'r':
-	case 's':
 		fprintf(fd, "if (!("); TestOnly=1;
 		fprintf(fd, "if (!("); TestOnly=1;
 		putstmnt(fd, s->frst->n, s->frst->seqno);
 		putstmnt(fd, s->frst->n, s->frst->seqno);
 		fprintf(fd, "))\n\t\t\tcontinue;"); TestOnly=0;
 		fprintf(fd, "))\n\t\t\tcontinue;"); TestOnly=0;
 		break;
 		break;
+	case 's':
+		fprintf(fd, "if (");
+#if 1
+/* 4.2.1 */	if (Pid != claimnr) fprintf(fd, "(boq != -1) || ");
+#endif
+		fprintf(fd, "!("); TestOnly=1;
+		putstmnt(fd, s->frst->n, s->frst->seqno);
+		fprintf(fd, "))\n\t\t\tcontinue;"); TestOnly=0;
+		break;
 	case 'c':
 	case 'c':
 		fprintf(fd, "if (!(");
 		fprintf(fd, "if (!(");
 		if (Pid != claimnr) fprintf(fd, "boq == -1 && ");
 		if (Pid != claimnr) fprintf(fd, "boq == -1 && ");
@@ -237,26 +259,40 @@ putcode(FILE *fd, Sequence *s, Element *nxt, int justguards, int ln)
 		putstmnt(fd, s->frst->n->lft, s->frst->seqno);
 		putstmnt(fd, s->frst->n->lft, s->frst->seqno);
 		fprintf(fd, "))\n\t\t\tcontinue;"); TestOnly=0;
 		fprintf(fd, "))\n\t\t\tcontinue;"); TestOnly=0;
 		break;
 		break;
+	case ELSE:
+		fprintf(fd, "if (boq != -1 || (");
+		if (separate != 2) fprintf(fd, "trpt->");
+		fprintf(fd, "o_pm&1))\n\t\t\tcontinue;");
+		break;
 	case ASGN:	/* new 3.0.8 */
 	case ASGN:	/* new 3.0.8 */
 		fprintf(fd, "IfNotBlocked");
 		fprintf(fd, "IfNotBlocked");
 		break;
 		break;
 	}
 	}
 	if (justguards) return 0;
 	if (justguards) return 0;
 
 
-	fprintf(fd, "\n\t\tsv_save((char *)&now);\n");
-
+	fprintf(fd, "\n\t\tsv_save();\n\t\t");
+#if 1
+	fprintf(fd, "reached[%d][%d] = 1;\n\t\t", Pid, seqno);
+	fprintf(fd, "reached[%d][t->st] = 1;\n\t\t", Pid);	/* true next state */
+	fprintf(fd, "reached[%d][tt] = 1;\n", Pid);		/* true current state */
+#endif
 	sprintf(buf, "Uerror(\"block in d_step seq, line %d\")", ln);
 	sprintf(buf, "Uerror(\"block in d_step seq, line %d\")", ln);
 	NextLab[0] = buf;
 	NextLab[0] = buf;
 	putCode(fd, s->frst, s->extent, nxt, isg);
 	putCode(fd, s->frst, s->extent, nxt, isg);
 
 
 	if (nxt)
 	if (nxt)
-	{	if (FirstTime(nxt->Seqno)
+	{	extern Symbol *Fname;
+		extern int lineno;
+
+		if (FirstTime(nxt->Seqno)
 		&& (!(nxt->status & DONE2) || !(nxt->status & D_ATOM)))
 		&& (!(nxt->status & DONE2) || !(nxt->status & D_ATOM)))
 		{	fprintf(fd, "S_%.3d_0: /* 1 */\n", nxt->Seqno);
 		{	fprintf(fd, "S_%.3d_0: /* 1 */\n", nxt->Seqno);
 			nxt->status |= DONE2;
 			nxt->status |= DONE2;
 			LastGoto = 0;
 			LastGoto = 0;
 		}
 		}
 		Sourced(nxt->Seqno, 1);
 		Sourced(nxt->Seqno, 1);
+		lineno = ln;
+		Fname = nxt->n->fn;	
 		Mopup(fd);
 		Mopup(fd);
 	}
 	}
 	unskip(s->frst->seqno);
 	unskip(s->frst->seqno);
@@ -299,7 +335,7 @@ putCode(FILE *fd, Element *f, Element *last, Element *next, int isguard)
 				if (LastGoto) break;
 				if (LastGoto) break;
 				if (e->nxt)
 				if (e->nxt)
 				{	i = target( huntele(e->nxt,
 				{	i = target( huntele(e->nxt,
-						e->status))->Seqno;
+						e->status, -1))->Seqno;
 					fprintf(fd, "\t\tgoto S_%.3d_0;	", i);
 					fprintf(fd, "\t\tgoto S_%.3d_0;	", i);
 					fprintf(fd, "/* 'break' */\n");
 					fprintf(fd, "/* 'break' */\n");
 					Dested(i);
 					Dested(i);
@@ -316,7 +352,7 @@ putCode(FILE *fd, Element *f, Element *last, Element *next, int isguard)
 			case GOTO:
 			case GOTO:
 				if (LastGoto) break;
 				if (LastGoto) break;
 				i = huntele( get_lab(e->n,1),
 				i = huntele( get_lab(e->n,1),
-					e->status)->Seqno;
+					e->status, -1)->Seqno;
 				fprintf(fd, "\t\tgoto S_%.3d_0;	", i);
 				fprintf(fd, "\t\tgoto S_%.3d_0;	", i);
 				fprintf(fd, "/* 'goto' */\n");
 				fprintf(fd, "/* 'goto' */\n");
 				Dested(i);
 				Dested(i);

+ 94 - 16
sys/src/cmd/spin/flow.c

@@ -1,14 +1,13 @@
 /***** spin: flow.c *****/
 /***** spin: flow.c *****/
 
 
-/* Copyright (c) 1991-2000 by Lucent Technologies - Bell Laboratories     */
+/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories.     */
 /* All Rights Reserved.  This software is for educational purposes only.  */
 /* All Rights Reserved.  This software is for educational purposes only.  */
-/* Permission is given to distribute this code provided that this intro-  */
-/* ductory message is not removed and no monies are exchanged.            */
-/* No guarantee is expressed or implied by the distribution of this code. */
-/* Software written by Gerard J. Holzmann as part of the book:            */
-/* `Design and Validation of Computer Protocols,' ISBN 0-13-539925-4,     */
-/* Prentice Hall, Englewood Cliffs, NJ, 07632.                            */
-/* Send bug-reports and/or questions to: gerard@research.bell-labs.com    */
+/* No guarantee whatsoever is expressed or implied by the distribution of */
+/* this code.  Permission is given to distribute this code provided that  */
+/* this introductory message is not removed and no monies are exchanged.  */
+/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
+/*             http://spinroot.com/                                       */
+/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
 
 
 #include "spin.h"
 #include "spin.h"
 #ifdef PC
 #ifdef PC
@@ -97,6 +96,7 @@ int
 is_skip(Lextok *n)
 is_skip(Lextok *n)
 {
 {
 	return (n->ntyp == PRINT
 	return (n->ntyp == PRINT
+	||	n->ntyp == PRINTM
 	||	(n->ntyp == 'c'
 	||	(n->ntyp == 'c'
 		&& n->lft
 		&& n->lft
 		&& n->lft->ntyp == CONST
 		&& n->lft->ntyp == CONST
@@ -113,15 +113,19 @@ check_sequence(Sequence *s)
 	{	n = e->n;
 	{	n = e->n;
 		if (is_skip(n) && !has_lab(e, 0))
 		if (is_skip(n) && !has_lab(e, 0))
 		{	cnt++;
 		{	cnt++;
-			if (cnt > 1 && n->ntyp != PRINT)
+			if (cnt > 1
+			&&  n->ntyp != PRINT
+			&&  n->ntyp != PRINTM)
 			{	if (verbose&32)
 			{	if (verbose&32)
 					printf("spin: line %d %s, redundant skip\n",
 					printf("spin: line %d %s, redundant skip\n",
 						n->ln, n->fn->name);
 						n->ln, n->fn->name);
-				if (le)
+				if (e != s->frst
+				&&  e != s->last
+				&&  e != s->extent)
 				{	e->status |= DONE;	/* not unreachable */
 				{	e->status |= DONE;	/* not unreachable */
 					le->nxt = e->nxt;	/* remove it */
 					le->nxt = e->nxt;	/* remove it */
 					e = le;
 					e = le;
-				} /* else, can't happen */
+				}
 			}
 			}
 		} else
 		} else
 			cnt = 0;
 			cnt = 0;
@@ -309,6 +313,45 @@ has_chanref(Lextok *n)
 	return has_chanref(n->rgt);
 	return has_chanref(n->rgt);
 }
 }
 
 
+void
+loose_ends(void)	/* properly tie-up ends of sub-sequences */
+{	Element *e, *f;
+
+	for (e = Al_El; e; e = e->Nxt)
+	{	if (!e->n
+		||  !e->nxt)
+			continue;
+		switch (e->n->ntyp) {
+		case ATOMIC:
+		case NON_ATOMIC:
+		case D_STEP:
+			f = e->nxt;
+			while (f && f->n->ntyp == '.')
+				f = f->nxt;
+			if (0) printf("link %d, {%d .. %d} -> %d (ntyp=%d) was %d\n",
+				e->seqno,
+				e->n->sl->this->frst->seqno,
+				e->n->sl->this->last->seqno,
+				f?f->seqno:-1, f?f->n->ntyp:-1,
+				e->n->sl->this->last->nxt?e->n->sl->this->last->nxt->seqno:-1);
+			if (!e->n->sl->this->last->nxt)
+				e->n->sl->this->last->nxt = f;
+			else
+			{	if (e->n->sl->this->last->nxt->n->ntyp != GOTO)
+				{	if (!f || e->n->sl->this->last->nxt->seqno != f->seqno)
+					non_fatal("unexpected: loose ends", (char *)0);
+				} else
+					e->n->sl->this->last = e->n->sl->this->last->nxt;
+				/*
+				 * fix_dest can push a goto into the nxt position
+				 * in that case the goto wins and f is not needed
+				 * but the last fields needs adjusting
+				 */
+			}
+			break;
+	}	}
+}
+
 static Element *
 static Element *
 if_seq(Lextok *n)
 if_seq(Lextok *n)
 {	int	tok = n->ntyp;
 {	int	tok = n->ntyp;
@@ -547,6 +590,7 @@ get_lab(Lextok *n, int md)
 	for (l = labtab; l; l = l->nxt)
 	for (l = labtab; l; l = l->nxt)
 		if (s == l->s)
 		if (s == l->s)
 			return (l->e);
 			return (l->e);
+
 	lineno = n->ln;
 	lineno = n->ln;
 	Fname = n->fn;
 	Fname = n->fn;
 	if (md) fatal("undefined label %s", s->name);
 	if (md) fatal("undefined label %s", s->name);
@@ -586,12 +630,19 @@ mov_lab(Symbol *z, Element *e, Element *y)
 }
 }
 
 
 void
 void
-fix_dest(Symbol *c, Symbol *a)	/* label, proctype */
+fix_dest(Symbol *c, Symbol *a)		/* c:label name, a:proctype name */
 {	Label *l; extern Symbol *context;
 {	Label *l; extern Symbol *context;
 
 
+#if 0
+	printf("ref to label '%s' in proctype '%s', search:\n",
+		c->name, a->name);
+	for (l = labtab; l; l = l->nxt)
+		printf("	%s in	%s\n", l->s->name, l->c->name);
+#endif
+
 	for (l = labtab; l; l = l->nxt)
 	for (l = labtab; l; l = l->nxt)
 	{	if (strcmp(c->name, l->s->name) == 0
 	{	if (strcmp(c->name, l->s->name) == 0
-		&&  strcmp(a->name, l->c->name) == 0)
+		&&  strcmp(a->name, l->c->name) == 0)	/* ? */
 			break;
 			break;
 	}
 	}
 	if (!l)
 	if (!l)
@@ -622,6 +673,10 @@ fix_dest(Symbol *c, Symbol *a)	/* label, proctype */
 		l->e->nxt = y;		/* append the goto  */
 		l->e->nxt = y;		/* append the goto  */
 	}
 	}
 	l->e->status |= CHECK2;	/* treat as if global */
 	l->e->status |= CHECK2;	/* treat as if global */
+	if (l->e->status & (ATOM | L_ATOM | D_ATOM))
+	{	non_fatal("cannot reference label inside atomic or d_step (%s)",
+			c->name);
+	}
 }
 }
 
 
 int
 int
@@ -660,10 +715,28 @@ break_dest(void)
 
 
 void
 void
 make_atomic(Sequence *s, int added)
 make_atomic(Sequence *s, int added)
-{
+{	Element *f;
+
 	walk_atomic(s->frst, s->last, added);
 	walk_atomic(s->frst, s->last, added);
-	s->last->status &= ~ATOM;
-	s->last->status |= L_ATOM;
+
+	f = s->last;
+	switch (f->n->ntyp) {	/* is last step basic stmnt or sequence ? */
+	case NON_ATOMIC:
+	case ATOMIC:
+		/* redo and search for the last step of that sequence */
+		make_atomic(f->n->sl->this, added);
+		break;
+
+	case UNLESS:
+		/* escapes are folded into main sequence */
+		make_atomic(f->sub->this, added);
+		break;
+
+	default:
+		f->status &= ~ATOM;
+		f->status |= L_ATOM;
+		break;
+	}
 }
 }
 
 
 static void
 static void
@@ -699,6 +772,11 @@ mknonat:		f->n->ntyp = NON_ATOMIC; /* can jump here */
 			h = f->n->sl;
 			h = f->n->sl;
 			walk_atomic(h->this->frst, h->this->last, added);
 			walk_atomic(h->this->frst, h->this->last, added);
 			break;
 			break;
+		case UNLESS:
+			if (added)
+			{ printf("spin: error, line %3d %s, unless in d_step (ignored)\n",
+			 	 f->n->ln, f->n->fn->name);
+			}
 		}
 		}
 		for (h = f->sub; h; h = h->nxt)
 		for (h = f->sub; h; h = h->nxt)
 			walk_atomic(h->this->frst, h->this->last, added);
 			walk_atomic(h->this->frst, h->this->last, added);

+ 92 - 36
sys/src/cmd/spin/guided.c

@@ -1,14 +1,13 @@
 /***** spin: guided.c *****/
 /***** spin: guided.c *****/
 
 
-/* Copyright (c) 1991-2000 by Lucent Technologies - Bell Laboratories     */
+/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories.     */
 /* All Rights Reserved.  This software is for educational purposes only.  */
 /* All Rights Reserved.  This software is for educational purposes only.  */
-/* Permission is given to distribute this code provided that this intro-  */
-/* ductory message is not removed and no monies are exchanged.            */
-/* No guarantee is expressed or implied by the distribution of this code. */
-/* Software written by Gerard J. Holzmann as part of the book:            */
-/* `Design and Validation of Computer Protocols,' ISBN 0-13-539925-4,     */
-/* Prentice Hall, Englewood Cliffs, NJ, 07632.                            */
-/* Send bug-reports and/or questions to: gerard@research.bell-labs.com    */
+/* No guarantee whatsoever is expressed or implied by the distribution of */
+/* this code.  Permission is given to distribute this code provided that  */
+/* this introductory message is not removed and no monies are exchanged.  */
+/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
+/*             http://spinroot.com/                                       */
+/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
 
 
 #include "spin.h"
 #include "spin.h"
 #include <sys/types.h>
 #include <sys/types.h>
@@ -22,8 +21,8 @@
 extern RunList	*run, *X;
 extern RunList	*run, *X;
 extern Element	*Al_El;
 extern Element	*Al_El;
 extern Symbol	*Fname, *oFname;
 extern Symbol	*Fname, *oFname;
-extern int	verbose, lineno, xspin, jumpsteps, depth, merger;
-extern int	nproc, nstop, Tval, Rvous, m_loss, ntrail, columns;
+extern int	verbose, lineno, xspin, jumpsteps, depth, merger, cutoff;
+extern int	nproc, nstop, Tval, ntrail, columns;
 extern short	Have_claim, Skip_claim;
 extern short	Have_claim, Skip_claim;
 extern void ana_src(int, int);
 extern void ana_src(int, int);
 
 
@@ -60,35 +59,74 @@ hookup(void)
 {	Element *e;
 {	Element *e;
 
 
 	for (e = Al_El; e; e = e->Nxt)
 	for (e = Al_El; e; e = e->Nxt)
-		if (e->n && e->n->ntyp == ATOMIC
-		||  e->n && e->n->ntyp == NON_ATOMIC
-		||  e->n && e->n->ntyp == D_STEP)
+		if (e->n
+		&& (e->n->ntyp == ATOMIC
+		||  e->n->ntyp == NON_ATOMIC
+		||  e->n->ntyp == D_STEP))
 			(void) huntstart(e);
 			(void) huntstart(e);
 }
 }
 
 
+int
+not_claim(void)
+{
+	return (!Have_claim || !X || X->pid != 0);
+}
+
 void
 void
 match_trail(void)
 match_trail(void)
 {	int i, a, nst;
 {	int i, a, nst;
 	Element *dothis;
 	Element *dothis;
-	RunList *oX;
-	char snap[256];
+	char snap[512], *q;
+
+	/*
+	 * if source model name is leader.pml
+	 * look for the trail file under these names:
+	 *	leader.pml.trail
+	 *	leader.pml.tra
+	 *	leader.trail
+	 *	leader.tra
+	 */
 
 
 	if (ntrail)
 	if (ntrail)
 		sprintf(snap, "%s%d.trail", oFname->name, ntrail);
 		sprintf(snap, "%s%d.trail", oFname->name, ntrail);
 	else
 	else
 		sprintf(snap, "%s.trail", oFname->name);
 		sprintf(snap, "%s.trail", oFname->name);
-	if (!(fd = fopen(snap, "r")))
-	{	snap[strlen(snap)-2] = '\0';	/* .tra on some pc's */
-		if (!(fd = fopen(snap, "r")))
-		{	printf("spin: cannot find trail file\n");
+
+	if ((fd = fopen(snap, "r")) == NULL)
+	{	snap[strlen(snap)-2] = '\0';	/* .tra */
+		if ((fd = fopen(snap, "r")) == NULL)
+		{	if ((q = strchr(oFname->name, '.')) != NULL)
+			{	*q = '\0';
+				if (ntrail)
+					sprintf(snap, "%s%d.trail",
+						oFname->name, ntrail);
+				else
+					sprintf(snap, "%s.trail",
+						oFname->name);
+				*q = '.';
+
+				if ((fd = fopen(snap, "r")) != NULL)
+					goto okay;
+
+				snap[strlen(snap)-2] = '\0';	/* last try */
+				if ((fd = fopen(snap, "r")) != NULL)
+					goto okay;
+			}
+			printf("spin: cannot find trail file\n");
 			alldone(1);
 			alldone(1);
 	}	}
 	}	}
-			
+okay:		
 	if (xspin == 0 && newer(oFname->name, snap))
 	if (xspin == 0 && newer(oFname->name, snap))
 	printf("spin: warning, \"%s\" is newer than %s\n",
 	printf("spin: warning, \"%s\" is newer than %s\n",
 		oFname->name, snap);
 		oFname->name, snap);
 
 
-	Tval = m_loss = 1; /* timeouts and losses may be part of trail */
+	Tval = 1;
+
+	/*
+	 * sets Tval because timeouts may be part of trail
+	 * this used to also set m_loss to 1, but that is
+	 * better handled with the runtime -m flag
+	 */
 
 
 	hookup();
 	hookup();
 
 
@@ -104,6 +142,13 @@ match_trail(void)
 			}
 			}
 			continue;
 			continue;
 		}
 		}
+
+		if (cutoff > 0 && depth >= cutoff)
+		{	printf("-------------\n");
+			printf("depth-limit (-u%d steps) reached\n", cutoff);
+			break;
+		}
+
 		if (Skip_claim && pno == 0) continue;
 		if (Skip_claim && pno == 0) continue;
 
 
 		for (dothis = Al_El; dothis; dothis = dothis->Nxt)
 		for (dothis = Al_El; dothis; dothis = dothis->Nxt)
@@ -112,10 +157,12 @@ match_trail(void)
 		}
 		}
 		if (!dothis)
 		if (!dothis)
 		{	printf("%3d: proc %d, no matching stmnt %d\n",
 		{	printf("%3d: proc %d, no matching stmnt %d\n",
-				depth, pno, nst);
+				depth, pno - Have_claim, nst);
 			lost_trail();
 			lost_trail();
 		}
 		}
+
 		i = nproc - nstop + Skip_claim;
 		i = nproc - nstop + Skip_claim;
+
 		if (dothis->n->ntyp == '@')
 		if (dothis->n->ntyp == '@')
 		{	if (pno == i-1)
 		{	if (pno == i-1)
 			{	run = run->nxt;
 			{	run = run->nxt;
@@ -125,15 +172,19 @@ match_trail(void)
 					{	dotag(stdout, "<end>\n");
 					{	dotag(stdout, "<end>\n");
 						continue;
 						continue;
 					}
 					}
+					if (Have_claim && pno == 0)
+					printf("%3d: claim terminates\n",
+						depth);
+					else
 					printf("%3d: proc %d terminates\n",
 					printf("%3d: proc %d terminates\n",
-						depth, pno);
+						depth, pno - Have_claim);
 				}
 				}
 				continue;
 				continue;
 			}
 			}
 			if (pno <= 1) continue;	/* init dies before never */
 			if (pno <= 1) continue;	/* init dies before never */
 			printf("%3d: stop error, ", depth);
 			printf("%3d: stop error, ", depth);
 			printf("proc %d (i=%d) trans %d, %c\n",
 			printf("proc %d (i=%d) trans %d, %c\n",
-				pno, i, nst, dothis->n->ntyp);
+				pno - Have_claim, i, nst, dothis->n->ntyp);
 			lost_trail();
 			lost_trail();
 		}
 		}
 		for (X = run; X; X = X->nxt)
 		for (X = run; X; X = X->nxt)
@@ -141,20 +192,20 @@ match_trail(void)
 				break;
 				break;
 		}
 		}
 		if (!X)
 		if (!X)
-		{	printf("%3d: no process %d ", depth, pno);
+		{	printf("%3d: no process %d ", depth, pno - Have_claim);
 			printf("(state %d)\n", nst);
 			printf("(state %d)\n", nst);
 			lost_trail();
 			lost_trail();
 		}
 		}
 		X->pc  = dothis;
 		X->pc  = dothis;
 		lineno = dothis->n->ln;
 		lineno = dothis->n->ln;
 		Fname  = dothis->n->fn;
 		Fname  = dothis->n->fn;
-		oX = X;	/* a rendezvous could change it */
+
 		if (dothis->n->ntyp == D_STEP)
 		if (dothis->n->ntyp == D_STEP)
 		{	Element *g, *og = dothis;
 		{	Element *g, *og = dothis;
 			do {
 			do {
 				g = eval_sub(og);
 				g = eval_sub(og);
 				if (g && depth >= jumpsteps
 				if (g && depth >= jumpsteps
-				&& ((verbose&32) || (verbose&4)))
+				&& ((verbose&32) || ((verbose&4) && not_claim())))
 				{	if (columns != 2)
 				{	if (columns != 2)
 					{	p_talk(og, 1);
 					{	p_talk(og, 1);
 		
 		
@@ -171,18 +222,19 @@ match_trail(void)
 				}
 				}
 				og = g;
 				og = g;
 			} while (g && g != dothis->nxt);
 			} while (g && g != dothis->nxt);
-			X->pc = g?huntele(g, 0):g;
+			X->pc = g?huntele(g, 0, -1):g;
 		} else
 		} else
 		{
 		{
-keepgoing:		X->pc = eval_sub(dothis);
-			X->pc = huntele(X->pc, 0);
-			if (dothis->merge_start)
+keepgoing:		if (dothis->merge_start)
 				a = dothis->merge_start;
 				a = dothis->merge_start;
 			else
 			else
 				a = dothis->merge;
 				a = dothis->merge;
 
 
+			X->pc = eval_sub(dothis);
+			if (X->pc) X->pc = huntele(X->pc, 0, a);
+
 			if (depth >= jumpsteps
 			if (depth >= jumpsteps
-			&& ((verbose&32) || (verbose&4)))
+			&& ((verbose&32) || ((verbose&4) && not_claim())))	/* -v or -p */
 			{	if (columns != 2)
 			{	if (columns != 2)
 				{	p_talk(dothis, 1);
 				{	p_talk(dothis, 1);
 	
 	
@@ -201,12 +253,17 @@ keepgoing:		X->pc = eval_sub(dothis);
 				if (verbose&1) dumpglobals();
 				if (verbose&1) dumpglobals();
 				if (verbose&2) dumplocal(X);
 				if (verbose&2) dumplocal(X);
 				if (xspin) printf("\n");
 				if (xspin) printf("\n");
+
+				if (!X->pc)
+				{	X->pc = dothis;
+					printf("\ttransition failed\n");
+					a = 0;	/* avoid inf loop */
+				}
 			}
 			}
 			if (a && X->pc && X->pc->seqno != a)
 			if (a && X->pc && X->pc->seqno != a)
 			{	dothis = X->pc;
 			{	dothis = X->pc;
 				goto keepgoing;
 				goto keepgoing;
-			}
-		}
+		}	}
 
 
 		if (Have_claim && X && X->pid == 0
 		if (Have_claim && X && X->pid == 0
 		&&  dothis && dothis->n
 		&&  dothis && dothis->n
@@ -221,8 +278,7 @@ keepgoing:		X->pc = eval_sub(dothis);
 				printf("Never claim moves to line %d\t[", lastclaim);
 				printf("Never claim moves to line %d\t[", lastclaim);
 				comment(stdout, dothis->n, 0);
 				comment(stdout, dothis->n, 0);
 				printf("]\n");
 				printf("]\n");
-			}
-	}	}
+	}	}	}
 	printf("spin: trail ends after %d steps\n", depth);
 	printf("spin: trail ends after %d steps\n", depth);
 	wrapup(0);
 	wrapup(0);
 }
 }

+ 177 - 67
sys/src/cmd/spin/main.c

@@ -1,14 +1,13 @@
 /***** spin: main.c *****/
 /***** spin: main.c *****/
 
 
-/* Copyright (c) 1991-2000 by Lucent Technologies - Bell Laboratories     */
+/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories.     */
 /* All Rights Reserved.  This software is for educational purposes only.  */
 /* All Rights Reserved.  This software is for educational purposes only.  */
-/* Permission is given to distribute this code provided that this intro-  */
-/* ductory message is not removed and no monies are exchanged.            */
-/* No guarantee is expressed or implied by the distribution of this code. */
-/* Software written by Gerard J. Holzmann as part of the book:            */
-/* `Design and Validation of Computer Protocols,' ISBN 0-13-539925-4,     */
-/* Prentice Hall, Englewood Cliffs, NJ, 07632.                            */
-/* Send bug-reports and/or questions to: gerard@research.bell-labs.com    */
+/* No guarantee whatsoever is expressed or implied by the distribution of */
+/* this code.  Permission is given to distribute this code provided that  */
+/* this introductory message is not removed and no monies are exchanged.  */
+/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
+/*             http://spinroot.com/                                       */
+/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
 
 
 #include <stdlib.h>
 #include <stdlib.h>
 #include "spin.h"
 #include "spin.h"
@@ -19,6 +18,9 @@
 #ifdef PC
 #ifdef PC
 #include <io.h>
 #include <io.h>
 #include "y_tab.h"
 #include "y_tab.h"
+
+extern int unlink(const char *);
+
 #else
 #else
 #include <unistd.h>
 #include <unistd.h>
 #include "y.tab.h"
 #include "y.tab.h"
@@ -28,18 +30,26 @@ extern int	DstepStart, lineno, tl_terse;
 extern FILE	*yyin, *yyout, *tl_out;
 extern FILE	*yyin, *yyout, *tl_out;
 extern Symbol	*context;
 extern Symbol	*context;
 extern char	*claimproc;
 extern char	*claimproc;
+extern void	repro_src(void);
 extern void	qhide(int);
 extern void	qhide(int);
 
 
 Symbol	*Fname, *oFname;
 Symbol	*Fname, *oFname;
 
 
-int	Etimeouts=0;	/* nr timeouts in program */
-int	Ntimeouts=0;	/* nr timeouts in never claim */
-int	analyze=0, columns=0, dumptab=0, has_remote=0;
-int	interactive=0, jumpsteps=0, m_loss=0, nr_errs=0;
-int	s_trail=0, ntrail=0, verbose=0, xspin=0, no_print=0, no_wrapup = 0, Caccess=0;
-int	limited_vis=0, like_java=0;
-int	dataflow = 1, merger = 1, deadvar = 1, rvopt = 0, ccache = 1;
-int	separate = 0;	/* separate compilation option */
+int	Etimeouts;	/* nr timeouts in program */
+int	Ntimeouts;	/* nr timeouts in never claim */
+int	analyze, columns, dumptab, has_remote, has_remvar;
+int	interactive, jumpsteps, m_loss, nr_errs, cutoff;
+int	s_trail, ntrail, verbose, xspin, notabs, rvopt;
+int	no_print, no_wrapup, Caccess, limited_vis, like_java;
+int	separate;	/* separate compilation */
+int	export_ast;	/* pangen5.c */
+int	inlineonly;	/* show inlined code */
+int	seedy;		/* be verbose about chosen seed */
+
+int	dataflow = 1, merger = 1, deadvar = 1, ccache = 1;
+
+static int preprocessonly, SeedUsed;
+
 #if 0
 #if 0
 meaning of flags on verbose:
 meaning of flags on verbose:
 	1	-g global variable values
 	1	-g global variable values
@@ -51,8 +61,6 @@ meaning of flags on verbose:
 	64	-w very verbose
 	64	-w very verbose
 #endif
 #endif
 
 
-static Element	*Same;
-static int	IsAsgn = 0, OrIsAsgn = 0;
 static char	Operator[] = "operator: ";
 static char	Operator[] = "operator: ";
 static char	Keyword[]  = "keyword: ";
 static char	Keyword[]  = "keyword: ";
 static char	Function[] = "function-name: ";
 static char	Function[] = "function-name: ";
@@ -68,27 +76,35 @@ static void	explain(int);
 		/* OS2:		"spin -Picc -E/Pd+ -E/Q+"    */
 		/* OS2:		"spin -Picc -E/Pd+ -E/Q+"    */
 		/* Visual C++:	"spin -PCL  -E/E             */
 		/* Visual C++:	"spin -PCL  -E/E             */
 #ifdef PC
 #ifdef PC
-#define CPP	"cpp"		/*  or specify a full path    */
+#define CPP	"gcc -E -x c"	/* most systems have gcc anyway */
+				/* else use "cpp" */
 #else
 #else
 #ifdef SOLARIS
 #ifdef SOLARIS
 #define CPP	"/usr/ccs/lib/cpp"
 #define CPP	"/usr/ccs/lib/cpp"
 #else
 #else
-#ifdef __FreeBSD__
+#if defined(__FreeBSD__) || defined(__OpenBSD__)
 #define CPP	"cpp"
 #define CPP	"cpp"
 #else
 #else
-#define CPP	"/bin/cpp"
+#define CPP	"/bin/cpp"	/* classic Unix systems */
 #endif
 #endif
 #endif
 #endif
 #endif
 #endif
 
 
 #endif
 #endif
 static char	*PreProc = CPP;
 static char	*PreProc = CPP;
+extern int	depth; /* at least some steps were made */
 
 
 void
 void
 alldone(int estatus)
 alldone(int estatus)
 {
 {
-	if (strlen(out1) > 0)
+	if (preprocessonly == 0
+	&&  strlen(out1) > 0)
 		(void) unlink((const char *)out1);
 		(void) unlink((const char *)out1);
+
+	if (seedy && !analyze && !export_ast
+	&& !s_trail && !preprocessonly && depth > 0)
+		printf("seed used: %d\n", SeedUsed);
+
 	if (xspin && (analyze || s_trail))
 	if (xspin && (analyze || s_trail))
 	{	if (estatus)
 	{	if (estatus)
 			printf("spin: %d error(s) - aborting\n",
 			printf("spin: %d error(s) - aborting\n",
@@ -101,10 +117,10 @@ alldone(int estatus)
 
 
 void
 void
 preprocess(char *a, char *b, int a_tmp)
 preprocess(char *a, char *b, int a_tmp)
-{	char precmd[128], cmd[256]; int i;
+{	char precmd[512], cmd[1024]; int i;
 #ifdef PC
 #ifdef PC
 	extern int try_zpp(char *, char *);
 	extern int try_zpp(char *, char *);
-	if (try_zpp(a, b)) goto out;
+	if (PreCnt == 0 && try_zpp(a, b)) goto out;
 #endif
 #endif
 	strcpy(precmd, PreProc);
 	strcpy(precmd, PreProc);
 	for (i = 1; i <= PreCnt; i++)
 	for (i = 1; i <= PreCnt; i++)
@@ -115,9 +131,13 @@ preprocess(char *a, char *b, int a_tmp)
 	if (system((const char *)cmd))
 	if (system((const char *)cmd))
 	{	(void) unlink((const char *) b);
 	{	(void) unlink((const char *) b);
 		if (a_tmp) (void) unlink((const char *) a);
 		if (a_tmp) (void) unlink((const char *) a);
-		alldone(1); /* failed */
+		fprintf(stdout, "spin: preprocessing failed\n");	/* 4.1.2 was stderr */
+		alldone(1); /* no return, error exit */
 	}
 	}
-out:	if (a_tmp) (void) unlink((const char *) a);
+#ifdef PC
+out:
+#endif
+	if (a_tmp) (void) unlink((const char *) a);
 }
 }
 
 
 FILE *
 FILE *
@@ -142,10 +162,11 @@ usage(void)
 {
 {
 	printf("use: spin [-option] ... [-option] file\n");
 	printf("use: spin [-option] ... [-option] file\n");
 	printf("\tNote: file must always be the last argument\n");
 	printf("\tNote: file must always be the last argument\n");
+	printf("\t-A apply slicing algorithm\n");
 	printf("\t-a generate a verifier in pan.c\n");
 	printf("\t-a generate a verifier in pan.c\n");
 	printf("\t-B no final state details in simulations\n");
 	printf("\t-B no final state details in simulations\n");
 	printf("\t-b don't execute printfs in simulation\n");
 	printf("\t-b don't execute printfs in simulation\n");
-	printf("\t-C print channel access info (structview)\n");
+	printf("\t-C print channel access info (combine with -g etc.)\n");
 	printf("\t-c columnated -s -r simulation output\n");
 	printf("\t-c columnated -s -r simulation output\n");
 	printf("\t-d produce symbol-table information\n");
 	printf("\t-d produce symbol-table information\n");
 	printf("\t-Dyyy pass -Dyyy to the preprocessor\n");
 	printf("\t-Dyyy pass -Dyyy to the preprocessor\n");
@@ -155,7 +176,9 @@ usage(void)
 	printf("\t-F file  like -f, but with the LTL ");
 	printf("\t-F file  like -f, but with the LTL ");
 	printf("formula stored in a 1-line file\n");
 	printf("formula stored in a 1-line file\n");
 	printf("\t-g print all global variables\n");
 	printf("\t-g print all global variables\n");
+	printf("\t-h  at end of run, print value of seed for random nr generator used\n");
 	printf("\t-i interactive (random simulation)\n");
 	printf("\t-i interactive (random simulation)\n");
+	printf("\t-I show result of inlining and preprocessing\n");
 	printf("\t-J reverse eval order of nested unlesses\n");
 	printf("\t-J reverse eval order of nested unlesses\n");
 	printf("\t-jN skip the first N steps ");
 	printf("\t-jN skip the first N steps ");
 	printf("in simulation trail\n");
 	printf("in simulation trail\n");
@@ -165,16 +188,20 @@ usage(void)
 	printf("\t-N file use never claim stored in file\n");
 	printf("\t-N file use never claim stored in file\n");
 	printf("\t-nN seed for random nr generator\n");
 	printf("\t-nN seed for random nr generator\n");
 	printf("\t-o1 turn off dataflow-optimizations in verifier\n");
 	printf("\t-o1 turn off dataflow-optimizations in verifier\n");
-	printf("\t-o2 turn off dead variables elimination in verifier\n");
+	printf("\t-o2 don't hide write-only variables in verifier\n");
 	printf("\t-o3 turn off statement merging in verifier\n");
 	printf("\t-o3 turn off statement merging in verifier\n");
 	printf("\t-Pxxx use xxx for preprocessing\n");
 	printf("\t-Pxxx use xxx for preprocessing\n");
 	printf("\t-p print all statements\n");
 	printf("\t-p print all statements\n");
 	printf("\t-qN suppress io for queue N in printouts\n");
 	printf("\t-qN suppress io for queue N in printouts\n");
 	printf("\t-r print receive events\n");
 	printf("\t-r print receive events\n");
+	printf("\t-S1 and -S2 separate pan source for claim and model\n");
 	printf("\t-s print send events\n");
 	printf("\t-s print send events\n");
+	printf("\t-T do not indent printf output\n");
+	printf("\t-t[N] follow [Nth] simulation trail\n");
+	printf("\t-Uyyy pass -Uyyy to the preprocessor\n");
+	printf("\t-uN stop a simulation run after N steps\n");
 	printf("\t-v verbose, more warnings\n");
 	printf("\t-v verbose, more warnings\n");
 	printf("\t-w very verbose (when combined with -l or -g)\n");
 	printf("\t-w very verbose (when combined with -l or -g)\n");
-	printf("\t-t[N] follow [Nth] simulation trail\n");
 	printf("\t-[XYZ] reserved for use by xspin interface\n");
 	printf("\t-[XYZ] reserved for use by xspin interface\n");
 	printf("\t-V print version number and exit\n");
 	printf("\t-V print version number and exit\n");
 	alldone(1);
 	alldone(1);
@@ -226,9 +253,34 @@ optimizations(char nr)
 	}
 	}
 }
 }
 
 
+#if 0
+static int
+Rename(const char *old, char *new)
+{	FILE *fo, *fn;
+	char buf[1024];
+
+	if ((fo = fopen(old, "r")) == NULL)
+	{	printf("spin: cannot open %s\n", old);
+		return 1;
+	}
+	if ((fn = fopen(new, "w")) == NULL)
+	{	printf("spin: cannot create %s\n", new);
+		fclose(fo);
+		return 2;
+	}
+	while (fgets(buf, 1024, fo))
+		fputs(buf, fn);
+
+	fclose(fo);
+	fclose(fn);
+
+	return 0;	/* success */
+}
+#endif
+
 int
 int
 main(int argc, char *argv[])
 main(int argc, char *argv[])
-{	Symbol *s; int preprocessonly = 0;
+{	Symbol *s;
 	int T = (int) time((time_t *)0);
 	int T = (int) time((time_t *)0);
 	int usedopts = 0;
 	int usedopts = 0;
 	extern void ana_src(int, int);
 	extern void ana_src(int, int);
@@ -244,14 +296,15 @@ main(int argc, char *argv[])
 		/* generate code for separate compilation: S1 or S2 */
 		/* generate code for separate compilation: S1 or S2 */
 		case 'S': separate = atoi(&argv[1][2]);
 		case 'S': separate = atoi(&argv[1][2]);
 			  /* fall through */
 			  /* fall through */
-
 		case 'a': analyze  = 1; break;
 		case 'a': analyze  = 1; break;
+
+		case 'A': export_ast = 1; break;
 		case 'B': no_wrapup = 1; break;
 		case 'B': no_wrapup = 1; break;
 		case 'b': no_print = 1; break;
 		case 'b': no_print = 1; break;
 		case 'C': Caccess = 1; break;
 		case 'C': Caccess = 1; break;
 		case 'c': columns = 1; break;
 		case 'c': columns = 1; break;
 		case 'D': PreArg[++PreCnt] = (char *) &argv[1][0];
 		case 'D': PreArg[++PreCnt] = (char *) &argv[1][0];
-			  break;
+			  break;	/* define */
 		case 'd': dumptab =  1; break;
 		case 'd': dumptab =  1; break;
 		case 'E': PreArg[++PreCnt] = (char *) &argv[1][2];
 		case 'E': PreArg[++PreCnt] = (char *) &argv[1][2];
 			  break;
 			  break;
@@ -260,7 +313,9 @@ main(int argc, char *argv[])
 		case 'f': add_ltl = (char **) argv;
 		case 'f': add_ltl = (char **) argv;
 			  argc--; argv++; break;
 			  argc--; argv++; break;
 		case 'g': verbose +=  1; break;
 		case 'g': verbose +=  1; break;
+		case 'h': seedy = 1; break;
 		case 'i': interactive = 1; break;
 		case 'i': interactive = 1; break;
+		case 'I': inlineonly = 1; break;
 		case 'J': like_java = 1; break;
 		case 'J': like_java = 1; break;
 		case 'j': jumpsteps = atoi(&argv[1][2]); break;
 		case 'j': jumpsteps = atoi(&argv[1][2]); break;
 		case 'l': verbose +=  2; break;
 		case 'l': verbose +=  2; break;
@@ -278,16 +333,20 @@ main(int argc, char *argv[])
 			  break;
 			  break;
 		case 'r': verbose +=  8; break;
 		case 'r': verbose +=  8; break;
 		case 's': verbose += 16; break;
 		case 's': verbose += 16; break;
+		case 'T': notabs = 1; break;
 		case 't': s_trail  =  1;
 		case 't': s_trail  =  1;
 			  if (isdigit(argv[1][2]))
 			  if (isdigit(argv[1][2]))
 				ntrail = atoi(&argv[1][2]);
 				ntrail = atoi(&argv[1][2]);
 			  break;
 			  break;
+		case 'U': PreArg[++PreCnt] = (char *) &argv[1][0];
+			  break;	/* undefine */
+		case 'u': cutoff = atoi(&argv[1][2]); break;	/* new 3.4.14 */
 		case 'v': verbose += 32; break;
 		case 'v': verbose += 32; break;
 		case 'V': printf("%s\n", Version);
 		case 'V': printf("%s\n", Version);
 			  alldone(0);
 			  alldone(0);
 			  break;
 			  break;
 		case 'w': verbose += 64; break;
 		case 'w': verbose += 64; break;
-		case 'X': xspin = 1;
+		case 'X': xspin = notabs = 1;
 #ifndef PC
 #ifndef PC
 			  signal(SIGPIPE, alldone); /* not posix... */
 			  signal(SIGPIPE, alldone); /* not posix... */
 #endif
 #endif
@@ -316,20 +375,13 @@ main(int argc, char *argv[])
 	}
 	}
 	if (argc > 1)
 	if (argc > 1)
 	{	char cmd[128], out2[64];
 	{	char cmd[128], out2[64];
-#ifdef PC
-		strcpy(out1, "_tmp1_");
-		strcpy(out2, "_tmp2_");
-#else
-		/* extern char *tmpnam(char *);  in stdio.h */
+
+		/* must remain in current dir */
+		strcpy(out1, "pan.pre");
+
 		if (add_ltl || nvr_file)
 		if (add_ltl || nvr_file)
-		{	/* must remain in current dir */
-			strcpy(out1, "_tmp1_");
-			strcpy(out2, "_tmp2_");
-		} else
-		{	(void) tmpnam(out1);
-			(void) tmpnam(out2);
-		}
-#endif
+			strcpy(out2, "pan.___");
+
 		if (add_ltl)
 		if (add_ltl)
 		{	tl_out = cpyfile(argv[1], out2);
 		{	tl_out = cpyfile(argv[1], out2);
 			nr_errs = tl_main(2, add_ltl);	/* in tl_main.c */
 			nr_errs = tl_main(2, add_ltl);	/* in tl_main.c */
@@ -353,13 +405,8 @@ main(int argc, char *argv[])
 			preprocess(argv[1], out1, 0);
 			preprocess(argv[1], out1, 0);
 
 
 		if (preprocessonly)
 		if (preprocessonly)
-		{	(void) unlink("pan.pre"); /* remove old version */
-			if (rename((const char *) out1, "pan.pre") != 0)
-			{	printf("spin: rename %s failed\n", out1);
-				alldone(1);
-			}
 			alldone(0);
 			alldone(0);
-		}
+
 		if (!(yyin = fopen(out1, "r")))
 		if (!(yyin = fopen(out1, "r")))
 		{	printf("spin: cannot open %s\n", out1);
 		{	printf("spin: cannot open %s\n", out1);
 			alldone(1);
 			alldone(1);
@@ -372,7 +419,7 @@ main(int argc, char *argv[])
 			strcpy(cmd, argv[1]);
 			strcpy(cmd, argv[1]);
 		oFname = Fname = lookup(cmd);
 		oFname = Fname = lookup(cmd);
 		if (oFname->name[0] == '\"')
 		if (oFname->name[0] == '\"')
-		{	int i = strlen(oFname->name);
+		{	int i = (int) strlen(oFname->name);
 			oFname->name[i-1] = '\0';
 			oFname->name[i-1] = '\0';
 			oFname = lookup(&oFname->name[1]);
 			oFname = lookup(&oFname->name[1]);
 		}
 		}
@@ -401,19 +448,30 @@ main(int argc, char *argv[])
 	if (columns == 2 && limited_vis)
 	if (columns == 2 && limited_vis)
 		verbose += (1+4);
 		verbose += (1+4);
 	Srand(T);	/* defined in run.c */
 	Srand(T);	/* defined in run.c */
-	s = lookup("_");	s->type = PREDEF; /* a write only global var */
+	SeedUsed = T;
+	s = lookup("_");	s->type = PREDEF; /* write-only global var */
 	s = lookup("_p");	s->type = PREDEF;
 	s = lookup("_p");	s->type = PREDEF;
 	s = lookup("_pid");	s->type = PREDEF;
 	s = lookup("_pid");	s->type = PREDEF;
 	s = lookup("_last");	s->type = PREDEF;
 	s = lookup("_last");	s->type = PREDEF;
 	s = lookup("_nr_pr");	s->type = PREDEF; /* new 3.3.10 */
 	s = lookup("_nr_pr");	s->type = PREDEF; /* new 3.3.10 */
+
 	yyparse();
 	yyparse();
 	fclose(yyin);
 	fclose(yyin);
+	loose_ends();
+
+	if (inlineonly)
+	{	repro_src();
+		return 0;
+	}
+
 	chanaccess();
 	chanaccess();
-	if (!s_trail && (dataflow || merger))
-		ana_src(dataflow, merger);
-	sched();
-	alldone(nr_errs);
-	return 0;	/* can't get here */
+	if (!Caccess)
+	{	if (!s_trail && (dataflow || merger))
+			ana_src(dataflow, merger);
+		sched();
+		alldone(nr_errs);
+	}
+	return 0;
 }
 }
 
 
 int
 int
@@ -463,7 +521,7 @@ emalloc(int n)
 }
 }
 
 
 void
 void
-trapwonly(Lextok *n, char *s)
+trapwonly(Lextok *n, char *unused)
 {	extern int realread;
 {	extern int realread;
 	short i = (n->sym)?n->sym->type:0;
 	short i = (n->sym)?n->sym->type:0;
 
 
@@ -502,6 +560,7 @@ setaccess(Symbol *sp, Symbol *what, int cnt, int t)
 Lextok *
 Lextok *
 nn(Lextok *s, int t, Lextok *ll, Lextok *rl)
 nn(Lextok *s, int t, Lextok *ll, Lextok *rl)
 {	Lextok *n = (Lextok *) emalloc(sizeof(Lextok));
 {	Lextok *n = (Lextok *) emalloc(sizeof(Lextok));
+	static int warn_nn = 0;
 
 
 	n->ntyp = (short) t;
 	n->ntyp = (short) t;
 	if (s && s->fn)
 	if (s && s->fn)
@@ -558,6 +617,9 @@ nn(Lextok *s, int t, Lextok *ll, Lextok *rl)
 			}	}
 			}	}
 			forbidden = 0;
 			forbidden = 0;
 			break;
 			break;
+		case 'c':
+			AST_track(n, 0);	/* register as a slice criterion */
+			/* fall thru */
 		default:
 		default:
 			forbidden = 0;
 			forbidden = 0;
 			break;
 			break;
@@ -566,27 +628,62 @@ nn(Lextok *s, int t, Lextok *ll, Lextok *rl)
 		{	printf("spin: never, saw "); explain(t); printf("\n");
 		{	printf("spin: never, saw "); explain(t); printf("\n");
 			fatal("incompatible with separate compilation",(char *)0);
 			fatal("incompatible with separate compilation",(char *)0);
 		}
 		}
-	} else if (t == ENABLED || t == PC_VAL)
-	{	printf("spin: Warning, using %s outside never-claim\n",
+	} else if ((t == ENABLED || t == PC_VAL) && !(warn_nn&t))
+	{	printf("spin: Warning, using %s outside never claim\n",
 			(t == ENABLED)?"enabled()":"pc_value()");
 			(t == ENABLED)?"enabled()":"pc_value()");
+		warn_nn |= t;
 	} else if (t == NONPROGRESS)
 	} else if (t == NONPROGRESS)
-	{	fatal("spin: Error, using np_ outside never-claim\n", (char *)0);
+	{	fatal("spin: Error, using np_ outside never claim\n", (char *)0);
 	}
 	}
 	return n;
 	return n;
 }
 }
 
 
 Lextok *
 Lextok *
-rem_lab(Symbol *a, Lextok *b, Symbol *c)
+rem_lab(Symbol *a, Lextok *b, Symbol *c)	/* proctype name, pid, label name */
 {	Lextok *tmp1, *tmp2, *tmp3;
 {	Lextok *tmp1, *tmp2, *tmp3;
 
 
 	has_remote++;
 	has_remote++;
-	fix_dest(c, a);	/* in case target is jump */
+	c->type = LABEL;	/* refered to in global context here */
+	fix_dest(c, a);		/* in case target of rem_lab is jump */
 	tmp1 = nn(ZN, '?',   b, ZN); tmp1->sym = a;
 	tmp1 = nn(ZN, '?',   b, ZN); tmp1->sym = a;
 	tmp1 = nn(ZN, 'p', tmp1, ZN);
 	tmp1 = nn(ZN, 'p', tmp1, ZN);
 	tmp1->sym = lookup("_p");
 	tmp1->sym = lookup("_p");
 	tmp2 = nn(ZN, NAME,  ZN, ZN); tmp2->sym = a;
 	tmp2 = nn(ZN, NAME,  ZN, ZN); tmp2->sym = a;
 	tmp3 = nn(ZN, 'q', tmp2, ZN); tmp3->sym = c;
 	tmp3 = nn(ZN, 'q', tmp2, ZN); tmp3->sym = c;
 	return nn(ZN, EQ, tmp1, tmp3);
 	return nn(ZN, EQ, tmp1, tmp3);
+#if 0
+	      .---------------EQ-------.
+	     /                          \
+	   'p' -sym-> _p               'q' -sym-> c (label name)
+	   /                           /
+	 '?' -sym-> a (proctype)     NAME -sym-> a (proctype name)
+	 / 
+	b (pid expr)
+#endif
+}
+
+Lextok *
+rem_var(Symbol *a, Lextok *b, Symbol *c, Lextok *ndx)
+{	Lextok *tmp1;
+
+	has_remote++;
+	has_remvar++;
+	dataflow = 0;	/* turn off dead variable resets 4.2.5 */
+	tmp1 = nn(ZN, '?', b, ZN); tmp1->sym = a;
+	tmp1 = nn(ZN, 'p', tmp1, ndx);
+	tmp1->sym = c;
+	return tmp1;
+#if 0
+	cannot refer to struct elements
+	only to scalars and arrays
+
+	    'p' -sym-> c (variable name)
+	    / \______  possible arrayindex on c
+	   /
+	 '?' -sym-> a (proctype)
+	 / 
+	b (pid expr)
+#endif
 }
 }
 
 
 static void
 static void
@@ -594,8 +691,8 @@ explain(int n)
 {	FILE *fd = stdout;
 {	FILE *fd = stdout;
 	switch (n) {
 	switch (n) {
 	default:	if (n > 0 && n < 256)
 	default:	if (n > 0 && n < 256)
-				fprintf(fd, "%c' = '", n);
-			fprintf(fd, "%d", n);
+				fprintf(fd, "'%c' = '", n);
+			fprintf(fd, "%d'", n);
 			break;
 			break;
 	case '\b':	fprintf(fd, "\\b"); break;
 	case '\b':	fprintf(fd, "\\b"); break;
 	case '\t':	fprintf(fd, "\\t"); break;
 	case '\t':	fprintf(fd, "\\t"); break;
@@ -614,10 +711,16 @@ explain(int n)
 	case ASSERT:	fprintf(fd, "%sassert",	Function); break;
 	case ASSERT:	fprintf(fd, "%sassert",	Function); break;
 	case ATOMIC:	fprintf(fd, "%satomic",	Keyword); break;
 	case ATOMIC:	fprintf(fd, "%satomic",	Keyword); break;
 	case BREAK:	fprintf(fd, "%sbreak",	Keyword); break;
 	case BREAK:	fprintf(fd, "%sbreak",	Keyword); break;
+	case C_CODE:	fprintf(fd, "%sc_code",	Keyword); break;
+	case C_DECL:	fprintf(fd, "%sc_decl",	Keyword); break;
+	case C_EXPR:	fprintf(fd, "%sc_expr",	Keyword); break;
+	case C_STATE:	fprintf(fd, "%sc_state",Keyword); break;
+	case C_TRACK:	fprintf(fd, "%sc_track",Keyword); break;
 	case CLAIM:	fprintf(fd, "%snever",	Keyword); break;
 	case CLAIM:	fprintf(fd, "%snever",	Keyword); break;
 	case CONST:	fprintf(fd, "a constant"); break;
 	case CONST:	fprintf(fd, "a constant"); break;
 	case DECR:	fprintf(fd, "%s--",	Operator); break;
 	case DECR:	fprintf(fd, "%s--",	Operator); break;
 	case D_STEP:	fprintf(fd, "%sd_step",	Keyword); break;
 	case D_STEP:	fprintf(fd, "%sd_step",	Keyword); break;
+	case D_PROCTYPE: fprintf(fd, "%sd_proctype", Keyword); break;
 	case DO:	fprintf(fd, "%sdo",	Keyword); break;
 	case DO:	fprintf(fd, "%sdo",	Keyword); break;
 	case DOT:	fprintf(fd, "."); break;
 	case DOT:	fprintf(fd, "."); break;
 	case ELSE:	fprintf(fd, "%selse",	Keyword); break;
 	case ELSE:	fprintf(fd, "%selse",	Keyword); break;
@@ -630,11 +733,13 @@ explain(int n)
 	case GE:	fprintf(fd, "%s>=",	Operator); break;
 	case GE:	fprintf(fd, "%s>=",	Operator); break;
 	case GOTO:	fprintf(fd, "%sgoto",	Keyword); break;
 	case GOTO:	fprintf(fd, "%sgoto",	Keyword); break;
 	case GT:	fprintf(fd, "%s>",	Operator); break;
 	case GT:	fprintf(fd, "%s>",	Operator); break;
+	case HIDDEN:	fprintf(fd, "%shidden",	Keyword); break;
 	case IF:	fprintf(fd, "%sif",	Keyword); break;
 	case IF:	fprintf(fd, "%sif",	Keyword); break;
 	case INCR:	fprintf(fd, "%s++",	Operator); break;
 	case INCR:	fprintf(fd, "%s++",	Operator); break;
 	case INAME:	fprintf(fd, "inline name"); break;
 	case INAME:	fprintf(fd, "inline name"); break;
 	case INLINE:	fprintf(fd, "%sinline",	Keyword); break;
 	case INLINE:	fprintf(fd, "%sinline",	Keyword); break;
 	case INIT:	fprintf(fd, "%sinit",	Keyword); break;
 	case INIT:	fprintf(fd, "%sinit",	Keyword); break;
+	case ISLOCAL:	fprintf(fd, "%slocal",  Keyword); break;
 	case LABEL:	fprintf(fd, "a label-name"); break;
 	case LABEL:	fprintf(fd, "a label-name"); break;
 	case LE:	fprintf(fd, "%s<=",	Operator); break;
 	case LE:	fprintf(fd, "%s<=",	Operator); break;
 	case LEN:	fprintf(fd, "%slen",	Function); break;
 	case LEN:	fprintf(fd, "%slen",	Function); break;
@@ -655,15 +760,20 @@ explain(int n)
 	case PC_VAL:	fprintf(fd, "%spc_value",Function); break;
 	case PC_VAL:	fprintf(fd, "%spc_value",Function); break;
 	case PNAME:	fprintf(fd, "process name"); break;
 	case PNAME:	fprintf(fd, "process name"); break;
 	case PRINT:	fprintf(fd, "%sprintf",	Function); break;
 	case PRINT:	fprintf(fd, "%sprintf",	Function); break;
+	case PRINTM:	fprintf(fd, "%sprintm",	Function); break;
+	case PRIORITY:	fprintf(fd, "%spriority", Keyword); break;
 	case PROCTYPE:	fprintf(fd, "%sproctype",Keyword); break;
 	case PROCTYPE:	fprintf(fd, "%sproctype",Keyword); break;
+	case PROVIDED:	fprintf(fd, "%sprovided",Keyword); break;
 	case RCV:	fprintf(fd, "%s?",	Operator); break;
 	case RCV:	fprintf(fd, "%s?",	Operator); break;
 	case R_RCV:	fprintf(fd, "%s??",	Operator); break;
 	case R_RCV:	fprintf(fd, "%s??",	Operator); break;
 	case RSHIFT:	fprintf(fd, "%s>>",	Operator); break;
 	case RSHIFT:	fprintf(fd, "%s>>",	Operator); break;
 	case RUN:	fprintf(fd, "%srun",	Operator); break;
 	case RUN:	fprintf(fd, "%srun",	Operator); break;
 	case SEP:	fprintf(fd, "token: ::"); break;
 	case SEP:	fprintf(fd, "token: ::"); break;
 	case SEMI:	fprintf(fd, ";"); break;
 	case SEMI:	fprintf(fd, ";"); break;
+	case SHOW:	fprintf(fd, "%sshow", Keyword); break;
 	case SND:	fprintf(fd, "%s!",	Operator); break;
 	case SND:	fprintf(fd, "%s!",	Operator); break;
 	case STRING:	fprintf(fd, "a string"); break;
 	case STRING:	fprintf(fd, "a string"); break;
+	case TRACE:	fprintf(fd, "%strace", Keyword); break;
 	case TIMEOUT:	fprintf(fd, "%stimeout",Keyword); break;
 	case TIMEOUT:	fprintf(fd, "%stimeout",Keyword); break;
 	case TYPE:	fprintf(fd, "data typename"); break;
 	case TYPE:	fprintf(fd, "data typename"); break;
 	case TYPEDEF:	fprintf(fd, "%stypedef",Keyword); break;
 	case TYPEDEF:	fprintf(fd, "%stypedef",Keyword); break;

+ 28 - 15
sys/src/cmd/spin/mesg.c

@@ -1,14 +1,13 @@
 /***** spin: mesg.c *****/
 /***** spin: mesg.c *****/
 
 
-/* Copyright (c) 1991-2000 by Lucent Technologies - Bell Laboratories     */
+/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories.     */
 /* All Rights Reserved.  This software is for educational purposes only.  */
 /* All Rights Reserved.  This software is for educational purposes only.  */
-/* Permission is given to distribute this code provided that this intro-  */
-/* ductory message is not removed and no monies are exchanged.            */
-/* No guarantee is expressed or implied by the distribution of this code. */
-/* Software written by Gerard J. Holzmann as part of the book:            */
-/* `Design and Validation of Computer Protocols,' ISBN 0-13-539925-4,     */
-/* Prentice Hall, Englewood Cliffs, NJ, 07632.                            */
-/* Send bug-reports and/or questions to: gerard@research.bell-labs.com    */
+/* No guarantee whatsoever is expressed or implied by the distribution of */
+/* this code.  Permission is given to distribute this code provided that  */
+/* this introductory message is not removed and no monies are exchanged.  */
+/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
+/*             http://spinroot.com/                                       */
+/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
 
 
 #include "spin.h"
 #include "spin.h"
 #ifdef PC
 #ifdef PC
@@ -17,7 +16,9 @@
 #include "y.tab.h"
 #include "y.tab.h"
 #endif
 #endif
 
 
+#ifndef MAXQ
 #define MAXQ	2500		/* default max # queues  */
 #define MAXQ	2500		/* default max # queues  */
+#endif
 
 
 extern RunList	*X;
 extern RunList	*X;
 extern Symbol	*Fname;
 extern Symbol	*Fname;
@@ -58,7 +59,7 @@ int
 qmake(Symbol *s)
 qmake(Symbol *s)
 {	Lextok *m;
 {	Lextok *m;
 	Queue *q;
 	Queue *q;
-	int i; extern int analyze;
+	int i;
 
 
 	if (!s->ini)
 	if (!s->ini)
 		return 0;
 		return 0;
@@ -370,10 +371,13 @@ s_snd(Queue *q, Lextok *n)
 				||  strcmp(m->lft->sym->name, "_") != 0)
 				||  strcmp(m->lft->sym->name, "_") != 0)
 					i = eval(m->lft);
 					i = eval(m->lft);
 				else	i = 0;
 				else	i = 0;
+
+				if (verbose&8)
 				sr_talk(n_rem,i,"Recv ","<-",j,q_rem);
 				sr_talk(n_rem,i,"Recv ","<-",j,q_rem);
 			}
 			}
+			if (verbose&8)
 			for (i = j; i < q->nflds; i++)
 			for (i = j; i < q->nflds; i++)
-			sr_talk(n_rem, 0, "Recv ", "<-", j, q_rem);
+				sr_talk(n_rem, 0, "Recv ", "<-", j, q_rem);
 			if (columns == 2)
 			if (columns == 2)
 				putarrow(depth, depth);
 				putarrow(depth, depth);
 		}
 		}
@@ -385,7 +389,7 @@ s_snd(Queue *q, Lextok *n)
 
 
 void
 void
 channm(Lextok *n)
 channm(Lextok *n)
-{	char lbuf[256];
+{	char lbuf[512];
 
 
 	if (n->sym->type == CHAN)
 	if (n->sym->type == CHAN)
 		strcat(Buf, n->sym->name);
 		strcat(Buf, n->sym->name);
@@ -397,6 +401,7 @@ channm(Lextok *n)
 			r = findloc(r);
 			r = findloc(r);
 		ini_struct(r);
 		ini_struct(r);
 		printf("%s", r->name);
 		printf("%s", r->name);
+		strcpy(lbuf, "");
 		struct_name(n->lft, r, 1, lbuf);
 		struct_name(n->lft, r, 1, lbuf);
 		strcat(Buf, lbuf);
 		strcat(Buf, lbuf);
 	} else
 	} else
@@ -409,8 +414,7 @@ channm(Lextok *n)
 
 
 static void
 static void
 difcolumns(Lextok *n, char *tr, int v, int j, Queue *q)
 difcolumns(Lextok *n, char *tr, int v, int j, Queue *q)
-{	int cnt = 1; extern int pno;
-	Lextok *nn = ZN;
+{	extern int pno;
 
 
 	if (j == 0)
 	if (j == 0)
 	{	Buf[0] = '\0';
 	{	Buf[0] = '\0';
@@ -534,7 +538,7 @@ sr_talk(Lextok *n, int v, char *tr, char *a, int j, Queue *q)
 void
 void
 sr_buf(int v, int j)
 sr_buf(int v, int j)
 {	int cnt = 1; Lextok *n;
 {	int cnt = 1; Lextok *n;
-	char lbuf[128];
+	char lbuf[256];
 
 
 	for (n = Mtype; n && j; n = n->rgt, cnt++)
 	for (n = Mtype; n && j; n = n->rgt, cnt++)
 		if (cnt == v)
 		if (cnt == v)
@@ -594,7 +598,16 @@ nochan_manip(Lextok *p, Lextok *n, int d)
 {	int e = 1;
 {	int e = 1;
 
 
 	if (d == 0 && p->sym && p->sym->type == CHAN)
 	if (d == 0 && p->sym && p->sym->type == CHAN)
-		setaccess(p->sym, ZS, 0, 'L');
+	{	setaccess(p->sym, ZS, 0, 'L');
+
+		if (n && n->ntyp == CONST)
+			fatal("invalid asgn to chan", (char *) 0);
+
+		if (n && n->sym && n->sym->type == CHAN)
+		{	setaccess(n->sym, ZS, 0, 'V');
+			return;
+		}	
+	}
 
 
 	if (!n || n->ntyp == LEN || n->ntyp == RUN)
 	if (!n || n->ntyp == LEN || n->ntyp == RUN)
 		return;
 		return;

+ 2 - 0
sys/src/cmd/spin/mkfile

@@ -13,8 +13,10 @@ SPIN_OS=\
 	pangen3.$O\
 	pangen3.$O\
 	pangen4.$O\
 	pangen4.$O\
 	pangen5.$O\
 	pangen5.$O\
+	pangen6.$O\
 	pc_zpp.$O\
 	pc_zpp.$O\
 	ps_msc.$O\
 	ps_msc.$O\
+	reprosrc.$O\
 	run.$O\
 	run.$O\
 	sched.$O\
 	sched.$O\
 	spinlex.$O\
 	spinlex.$O\

+ 344 - 103
sys/src/cmd/spin/pangen1.c

@@ -1,14 +1,13 @@
 /***** spin: pangen1.c *****/
 /***** spin: pangen1.c *****/
 
 
-/* Copyright (c) 1991-2000 by Lucent Technologies - Bell Laboratories     */
+/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories.     */
 /* All Rights Reserved.  This software is for educational purposes only.  */
 /* All Rights Reserved.  This software is for educational purposes only.  */
-/* Permission is given to distribute this code provided that this intro-  */
-/* ductory message is not removed and no monies are exchanged.            */
-/* No guarantee is expressed or implied by the distribution of this code. */
-/* Software written by Gerard J. Holzmann as part of the book:            */
-/* `Design and Validation of Computer Protocols,' ISBN 0-13-539925-4,     */
-/* Prentice Hall, Englewood Cliffs, NJ, 07632.                            */
-/* Send bug-reports and/or questions to: gerard@research.bell-labs.com    */
+/* No guarantee whatsoever is expressed or implied by the distribution of */
+/* this code.  Permission is given to distribute this code provided that  */
+/* this introductory message is not removed and no monies are exchanged.  */
+/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
+/*             http://spinroot.com/                                       */
+/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
 
 
 #include "spin.h"
 #include "spin.h"
 #ifdef PC
 #ifdef PC
@@ -29,7 +28,9 @@ extern int	lineno, verbose, Pid, separate;
 extern int	nrRdy, nqs, mst, Mpars, claimnr, eventmapnr;
 extern int	nrRdy, nqs, mst, Mpars, claimnr, eventmapnr;
 extern short	has_sorted, has_random, has_provided;
 extern short	has_sorted, has_random, has_provided;
 
 
-int	Npars=0, u_sync=0, u_async=0;
+int	Npars=0, u_sync=0, u_async=0, hastrack = 1;
+short	has_io = 0;
+short	has_state=0;	/* code contains c_state */
 
 
 static Symbol	*LstSet=ZS;
 static Symbol	*LstSet=ZS;
 static int	acceptors=0, progressors=0, nBits=0;
 static int	acceptors=0, progressors=0, nBits=0;
@@ -56,7 +57,10 @@ void
 genheader(void)
 genheader(void)
 {	ProcList *p; int i;
 {	ProcList *p; int i;
 
 
-	if (separate == 2) goto here;
+	if (separate == 2)
+	{	putunames(th);
+		goto here;
+	}
 
 
 	fprintf(th, "#define SYNC	%d\n", u_sync);
 	fprintf(th, "#define SYNC	%d\n", u_sync);
 	fprintf(th, "#define ASYNC	%d\n\n", u_async);
 	fprintf(th, "#define ASYNC	%d\n\n", u_async);
@@ -82,29 +86,39 @@ here:
 
 
 	ntimes(th, 0, 1, Head0);
 	ntimes(th, 0, 1, Head0);
 
 
-	if (separate == 2)
-	{	ntimes(th, 0, 1, Head1);
-		LstSet = ZS;
-		(void) doglobal("", PUTV);
-		fprintf(th, "	uchar sv[VECTORSZ];\n");
-		fprintf(th, "} State;\n\n");
-	} else
-	{
+	if (separate != 2)
+	{	extern void c_add_stack(FILE *);
+
 		ntimes(th, 0, 1, Header);
 		ntimes(th, 0, 1, Header);
-		ntimes(th, 0, 1, Head1);
+		c_add_stack(th);
+		ntimes(th, 0, 1, Header0);
+	}
+	ntimes(th, 0, 1, Head1);
 
 
-		LstSet = ZS;
-		(void) doglobal("", PUTV);
-		fprintf(th, "	uchar sv[VECTORSZ];\n");
-		fprintf(th, "} State;\n\n");
+	LstSet = ZS;
+	(void) doglobal("", PUTV);
+
+	hastrack = c_add_sv(th);
+
+	fprintf(th, "	uchar sv[VECTORSZ];\n");
+	fprintf(th, "} State");
+#ifdef SOLARIS
+	fprintf(th,"\n#ifdef GCC\n");
+	fprintf(th, "\t__attribute__ ((aligned(8)))");
+	fprintf(th, "\n#endif\n\t");
+#endif
+	fprintf(th, ";\n\n");
+
+	fprintf(th, "#define HAS_TRACK	%d\n", hastrack);
+
+	if (separate != 2)
 		dohidden();
 		dohidden();
-	}
 }
 }
 
 
 void
 void
 genaddproc(void)
 genaddproc(void)
 {	ProcList *p;
 {	ProcList *p;
-	int i;
+	int i = 0;
 
 
 	if (separate ==2) goto shortcut;
 	if (separate ==2) goto shortcut;
 
 
@@ -117,7 +131,7 @@ genaddproc(void)
 	ntimes(tc, 0, 1, Addp1);
 	ntimes(tc, 0, 1, Addp1);
 
 
 	if (has_provided)
 	if (has_provided)
-	{	fprintf(tt, "\nint\nprovided(int II, int ot, ");
+	{	fprintf(tt, "\nint\nprovided(int II, unsigned char ot, ");
 		fprintf(tt, "int tt, Trans *t)\n");
 		fprintf(tt, "int tt, Trans *t)\n");
 		fprintf(tt, "{\n\tswitch(ot) {\n");
 		fprintf(tt, "{\n\tswitch(ot) {\n");
 	}
 	}
@@ -143,6 +157,14 @@ shortcut:
 	ntimes(tc, 0, 1, R8a);
 	ntimes(tc, 0, 1, R8a);
 }
 }
 
 
+void
+do_locinits(FILE *fd)
+{	ProcList *p;
+
+	for (p = rdy; p; p = p->nxt)
+		c_add_locinit(fd, p->tn, p->n->name);
+}
+
 void
 void
 genother(void)
 genother(void)
 {	ProcList *p;
 {	ProcList *p;
@@ -190,7 +212,9 @@ genother(void)
 	ntimes(th, nrRdy+1, nrRdy+2, R2); /* +1 for np_ */
 	ntimes(th, nrRdy+1, nrRdy+2, R2); /* +1 for np_ */
 
 
 	fprintf(tc, "	iniglobals();\n");
 	fprintf(tc, "	iniglobals();\n");
-	ntimes(tc, 0,     1, Code2);
+	ntimes(tc, 0,     1, Code2a);
+	ntimes(tc, 0,     1, Code2b);	/* bfs option */
+	ntimes(tc, 0,     1, Code2c);
 	ntimes(tc, 0,     nrRdy, R4);
 	ntimes(tc, 0,     nrRdy, R4);
 	fprintf(tc, "}\n\n");
 	fprintf(tc, "}\n\n");
 
 
@@ -245,7 +269,7 @@ end_labs(Symbol *s, int i)
 					ln[j].s);
 					ln[j].s);
 				goto complain;
 				goto complain;
 			}
 			}
-			if (l->e->status & ATOM)
+			if (j > 0 && (l->e->status & ATOM))
 			{	sprintf(foo, "%s label inside atomic",
 			{	sprintf(foo, "%s label inside atomic",
 					ln[j].s);
 					ln[j].s);
 		complain:	lineno = l->e->n->ln;
 		complain:	lineno = l->e->n->ln;
@@ -317,7 +341,7 @@ checktype(Symbol *sp, char *s)
 	} else if (!(sp->hidden&4))
 	} else if (!(sp->hidden&4))
 	{	if (!(verbose&32)) return;
 	{	if (!(verbose&32)) return;
 		sputtype(buf, sp->type);
 		sputtype(buf, sp->type);
-		i = strlen(buf);
+		i = (int) strlen(buf);
 		while (buf[--i] == ' ') buf[i] = '\0';
 		while (buf[--i] == ' ') buf[i] = '\0';
 		prehint(sp);
 		prehint(sp);
 		if (sp->context)
 		if (sp->context)
@@ -329,7 +353,7 @@ checktype(Symbol *sp, char *s)
 	} else if (sp->type != BYTE && !(sp->hidden&8))
 	} else if (sp->type != BYTE && !(sp->hidden&8))
 	{	if (!(verbose&32)) return;
 	{	if (!(verbose&32)) return;
 		sputtype(buf, sp->type);
 		sputtype(buf, sp->type);
-		i = strlen(buf);
+		i = (int) strlen(buf);
 		while (buf[--i] == ' ') buf[i] = '\0';
 		while (buf[--i] == ' ') buf[i] = '\0';
 		prehint(sp);
 		prehint(sp);
 		if (sp->context)
 		if (sp->context)
@@ -342,7 +366,7 @@ checktype(Symbol *sp, char *s)
 }
 }
 
 
 int
 int
-dolocal(FILE *ofd, char *pre, int dowhat, int p, char *s, char *how)
+dolocal(FILE *ofd, char *pre, int dowhat, int p, char *s)
 {	int h, j, k=0; extern int nr_errs;
 {	int h, j, k=0; extern int nr_errs;
 	Ordered *walk;
 	Ordered *walk;
 	Symbol *sp;
 	Symbol *sp;
@@ -364,7 +388,7 @@ dolocal(FILE *ofd, char *pre, int dowhat, int p, char *s, char *how)
 					break;
 					break;
 				sprintf(buf, "%s%s:", pre, s);
 				sprintf(buf, "%s%s:", pre, s);
 				{ sprintf(buf2, "\", ((P%d *)pptr(h))->", p);
 				{ sprintf(buf2, "\", ((P%d *)pptr(h))->", p);
-				  sprintf(buf3, ");\n", p);
+				  sprintf(buf3, ");\n");
 				}
 				}
 				do_var(ofd, dowhat, "", sp, buf, buf2, buf3);
 				do_var(ofd, dowhat, "", sp, buf, buf2, buf3);
 				break;
 				break;
@@ -385,6 +409,160 @@ dolocal(FILE *ofd, char *pre, int dowhat, int p, char *s, char *how)
 	return k;
 	return k;
 }
 }
 
 
+void
+c_chandump(FILE *fd)
+{	Queue *q;
+	char buf[256];
+	int i;
+
+	if (!qtab)
+	{	fprintf(fd, "void\nc_chandump(int unused) ");
+		fprintf(fd, "{ unused = unused++; /* avoid complaints */ }\n");
+		return;
+	}
+
+	fprintf(fd, "void\nc_chandump(int from)\n");
+	fprintf(fd, "{	uchar *z; int slot;\n");
+
+	fprintf(fd, "	from--;\n");
+	fprintf(fd, "	if (from >= (int) now._nr_qs || from < 0)\n");
+	fprintf(fd, "	{	printf(\"pan: bad qid %%d\\n\", from+1);\n");
+	fprintf(fd, "		return;\n");
+	fprintf(fd, "	}\n");
+	fprintf(fd, "	z = qptr(from);\n");
+	fprintf(fd, "	switch (((Q0 *)z)->_t) {\n");
+
+	for (q = qtab; q; q = q->nxt)
+	{	fprintf(fd, "	case %d:\n\t\t", q->qid);
+		sprintf(buf, "((Q%d *)z)->", q->qid);
+
+		fprintf(fd, "for (slot = 0; slot < %sQlen; slot++)\n\t\t", buf);
+		fprintf(fd, "{	printf(\" [\");\n\t\t");
+		for (i = 0; i < q->nflds; i++)
+		{	if (q->fld_width[i] == MTYPE)
+			{	fprintf(fd, "\tprintm(%scontents[slot].fld%d);\n\t\t",
+				buf, i);
+			} else
+			fprintf(fd, "\tprintf(\"%%d,\", %scontents[slot].fld%d);\n\t\t",
+				buf, i);
+		}
+		fprintf(fd, "	printf(\"],\");\n\t\t");
+		fprintf(fd, "}\n\t\t");
+		fprintf(fd, "break;\n");
+	}
+	fprintf(fd, "	}\n");
+	fprintf(fd, "	printf(\"\\n\");\n}\n");
+}
+
+void
+c_var(FILE *fd, char *pref, Symbol *sp)
+{	char buf[256];
+	int i;
+
+	switch (sp->type) {
+	case STRUCT:
+		/* c_struct(fd, pref, sp); */
+		fprintf(fd, "\t\tprintf(\"\t(struct %s)\\n\");\n",
+			sp->name);
+		sprintf(buf, "%s%s.", pref, sp->name);
+		c_struct(fd, buf, sp);
+		break;
+	case BIT:   case BYTE:
+	case SHORT: case INT:
+	case UNSIGNED:
+		sputtype(buf, sp->type);
+		if (sp->nel == 1)
+		fprintf(fd, "\tprintf(\"\t%s %s:\t%%d\\n\", %s%s);\n",
+			buf, sp->name, pref, sp->name);
+		else
+		for (i = 0; i < sp->nel; i++)
+		fprintf(fd, "\tprintf(\"\t%s %s[%d]:\t%%d\\n\", %s%s[%d]);\n",
+			buf, sp->name, i, pref, sp->name, i);
+		break;
+	case CHAN:
+		if (sp->nel == 1)
+		{  fprintf(fd, "\tprintf(\"\tchan %s (=%%d):\tlen %%d:\\t\", ",
+			sp->name);
+		   fprintf(fd, "%s%s, q_len(%s%s));\n",
+			pref, sp->name, pref, sp->name);
+		   fprintf(fd, "\tc_chandump(%s%s);\n", pref, sp->name);
+		} else
+		for (i = 0; i < sp->nel; i++)
+		{  fprintf(fd, "\tprintf(\"\tchan %s[%d] (=%%d):\tlen %%d:\\t\", ",
+			sp->name, i);
+		   fprintf(fd, "%s%s[%d], q_len(%s%s[%d]));\n",
+			pref, sp->name, i, pref, sp->name, i);
+		   fprintf(fd, "\tc_chandump(%s%s[%d]);\n",
+			pref, sp->name, i);
+		}
+		break;
+	}
+}
+
+void
+c_splurge(FILE *fd, ProcList *p)
+{	Ordered *walk;
+	Symbol *sp;
+	char pref[64];
+
+	if (strcmp(p->n->name, ":never:") != 0
+	&&  strcmp(p->n->name, ":trace:") != 0
+	&&  strcmp(p->n->name, ":notrace:") != 0)
+	for (walk = all_names; walk; walk = walk->next)
+	{	sp = walk->entry;
+		if (!sp->context
+		||  strcmp(sp->context->name, p->n->name) != 0
+		||  sp->owner || (sp->hidden&1)
+		|| (sp->type == MTYPE && ismtype(sp->name)))
+			continue;
+
+		sprintf(pref, "((P%d *)pptr(pid))->", p->tn);
+		c_var(fd, pref, sp);
+	}
+}
+
+void
+c_wrapper(FILE *fd)	/* allow pan.c to print out global sv entries */
+{	Ordered *walk;
+	ProcList *p;
+	Symbol *sp;
+	Lextok *n;
+	extern Lextok *Mtype;
+	int j;
+
+	fprintf(fd, "void\nc_globals(void)\n{\t/* int i; */\n");
+	fprintf(fd, "	printf(\"global vars:\\n\");\n");
+	for (walk = all_names; walk; walk = walk->next)
+	{	sp = walk->entry;
+		if (sp->context || sp->owner || (sp->hidden&1)
+		|| (sp->type == MTYPE && ismtype(sp->name)))
+			continue;
+
+		c_var(fd, "now.", sp);
+	}
+	fprintf(fd, "}\n");
+
+	fprintf(fd, "void\nc_locals(int pid, int tp)\n{\t/* int i; */\n");
+	fprintf(fd, "	switch(tp) {\n");
+	for (p = rdy; p; p = p->nxt)
+	{	fprintf(fd, "	case %d:\n", p->tn);
+		fprintf(fd, "	\tprintf(\"local vars proc %%d (%s):\\n\", pid);\n",
+			p->n->name);
+		c_splurge(fd, p);
+		fprintf(fd, "	\tbreak;\n");
+	}
+	fprintf(fd, "	}\n}\n");
+
+	fprintf(fd, "void\nprintm(int x)\n{\n");
+	fprintf(fd, "	switch (x) {\n");
+        for (n = Mtype, j = 1; n && j; n = n->rgt, j++)
+                fprintf(fd, "\tcase %d: Printf(\"%s\"); break;\n",
+			j, n->lft->sym->name);
+	fprintf(fd, "	default: Printf(\"%%d\", x);\n");
+	fprintf(fd, "	}\n");
+	fprintf(fd, "}\n");
+}
+
 static int
 static int
 doglobal(char *pre, int dowhat)
 doglobal(char *pre, int dowhat)
 {	Ordered *walk;
 {	Ordered *walk;
@@ -396,7 +574,6 @@ doglobal(char *pre, int dowhat)
 	{	sp = walk->entry;
 	{	sp = walk->entry;
 		if (!sp->context
 		if (!sp->context
 		&&  !sp->owner
 		&&  !sp->owner
-	/*	&&  !(sp->hidden&1)	*/
 		&&  sp->type == Types[j])
 		&&  sp->type == Types[j])
 		{	if (Types[j] != MTYPE || !ismtype(sp->name))
 		{	if (Types[j] != MTYPE || !ismtype(sp->name))
 			switch (dowhat) {
 			switch (dowhat) {
@@ -513,15 +690,29 @@ static void
 put_ptype(char *s, int i, int m0, int m1)
 put_ptype(char *s, int i, int m0, int m1)
 {	int k;
 {	int k;
 
 
+	if (strcmp(s, ":init:") == 0)
+		fprintf(th, "#define Pinit	((P%d *)this)\n", i);
+
+	if (strcmp(s, ":never:") != 0
+	&&  strcmp(s, ":trace:") != 0
+	&&  strcmp(s, ":notrace:") != 0
+	&&  strcmp(s, ":init:")  != 0
+	&&  strcmp(s, "_:never_template:_") != 0
+	&&  strcmp(s, "np_")     != 0)
+		fprintf(th, "#define P%s	((P%d *)this)\n", s, i);
+
 	fprintf(th, "typedef struct P%d { /* %s */\n", i, s);
 	fprintf(th, "typedef struct P%d { /* %s */\n", i, s);
 	fprintf(th, "	unsigned _pid : 8;  /* 0..255 */\n");
 	fprintf(th, "	unsigned _pid : 8;  /* 0..255 */\n");
 	fprintf(th, "	unsigned _t   : %d; /* proctype */\n", blog(m1));
 	fprintf(th, "	unsigned _t   : %d; /* proctype */\n", blog(m1));
 	fprintf(th, "	unsigned _p   : %d; /* state    */\n", blog(m0));
 	fprintf(th, "	unsigned _p   : %d; /* state    */\n", blog(m0));
 	LstSet = ZS;
 	LstSet = ZS;
 	nBits = 8 + blog(m1) + blog(m0);
 	nBits = 8 + blog(m1) + blog(m0);
-	k = dolocal(tc, "", PUTV, i, s, "");	/* includes pars */
+	k = dolocal(tc, "", PUTV, i, s);	/* includes pars */
+
+	c_add_loc(th, s);
+
 	fprintf(th, "} P%d;\n", i);
 	fprintf(th, "} P%d;\n", i);
-	if (!LstSet && k > 0)
+	if ((!LstSet && k > 0) || has_state)
 		fprintf(th, "#define Air%d	0\n", i);
 		fprintf(th, "#define Air%d	0\n", i);
 	else
 	else
 	{	fprintf(th, "#define Air%d	(sizeof(P%d) - ", i, i);
 	{	fprintf(th, "#define Air%d	(sizeof(P%d) - ", i, i);
@@ -531,15 +722,8 @@ put_ptype(char *s, int i, int m0, int m1)
 		}
 		}
 		if ((LstSet->type != BIT && LstSet->type != UNSIGNED)
 		if ((LstSet->type != BIT && LstSet->type != UNSIGNED)
 		||   LstSet->nel != 1)
 		||   LstSet->nel != 1)
-		{	fprintf(th, "Offsetof(P%d, %s%s) - %d*sizeof(",
-				i,
-				LstSet->name,
-#if 1
-				"",
-#else
-				(LstSet->nel > 1)?"[0]":"",
-#endif
-				LstSet->nel);
+		{	fprintf(th, "Offsetof(P%d, %s) - %d*sizeof(",
+				i, LstSet->name, LstSet->nel);
 		}
 		}
 		switch(LstSet->type) {
 		switch(LstSet->type) {
 		case UNSIGNED:
 		case UNSIGNED:
@@ -608,7 +792,7 @@ put_pinit(ProcList *P)
 	&&  separate == 2)
 	&&  separate == 2)
 		return;
 		return;
 
 
-	ini = huntele(e, e->status)->seqno;
+	ini = huntele(e, e->status, -1)->seqno;
 	fprintf(th, "#define start%d	%d\n", i, ini);
 	fprintf(th, "#define start%d	%d\n", i, ini);
 	if (i == claimnr)
 	if (i == claimnr)
 	fprintf(th, "#define start_claim	%d\n", ini);
 	fprintf(th, "#define start_claim	%d\n", ini);
@@ -648,7 +832,7 @@ put_pinit(ProcList *P)
 		{	if (full_name(tc, t, t->sym, 1))
 		{	if (full_name(tc, t, t->sym, 1))
 			{	lineno = t->ln;
 			{	lineno = t->ln;
 				Fname  = t->fn;
 				Fname  = t->fn;
-				fatal("hidden array in parameter, %s",
+				fatal("hidden array in parameter %s",
 				t->sym->name);
 				t->sym->name);
 			}
 			}
 		} else
 		} else
@@ -656,12 +840,17 @@ put_pinit(ProcList *P)
 		fprintf(tc, " = par%d;\n", j);
 		fprintf(tc, " = par%d;\n", j);
 	}
 	}
 	fprintf(tc, "\t\t/* locals: */\n");
 	fprintf(tc, "\t\t/* locals: */\n");
-	k = dolocal(tc, "", INIV, i, s->name, "");
+	k = dolocal(tc, "", INIV, i, s->name);
 	if (k > 0)
 	if (k > 0)
 	{	fprintf(tc, "#ifdef VAR_RANGES\n");
 	{	fprintf(tc, "#ifdef VAR_RANGES\n");
-		(void) dolocal(tc, "logval(\"", LOGV, i, s->name, "");
+		(void) dolocal(tc, "logval(\"", LOGV, i, s->name);
 		fprintf(tc, "#endif\n");
 		fprintf(tc, "#endif\n");
 	}
 	}
+
+	fprintf(tc, "#ifdef HAS_CODE\n");
+	fprintf(tc, "\t\tlocinit%d(h);\n", i);
+	fprintf(tc, "#endif\n");
+
 	dumpclaims(tc, i, s->name);
 	dumpclaims(tc, i, s->name);
 	fprintf(tc, "\t	break;\n");
 	fprintf(tc, "\t	break;\n");
 }
 }
@@ -669,28 +858,35 @@ put_pinit(ProcList *P)
 Element *
 Element *
 huntstart(Element *f)
 huntstart(Element *f)
 {	Element *e = f;
 {	Element *e = f;
+	Element *elast = (Element *) 0;
+	int cnt = 0;
+
+	while (elast != e && cnt++ < 20)	/* new 4.0.8 */
+	{	elast = e;
+		if (e->n)
+		{	if (e->n->ntyp == '.' && e->nxt)
+				e = e->nxt;
+			else if (e->n->ntyp == UNLESS)
+				e = e->sub->this->frst;
+	}	}
 
 
-	if (e->n)
-	{	if (e->n->ntyp == '.' && e->nxt)
-			e = e->nxt;
-		else if (e->n->ntyp == ATOMIC
-		     ||  e->n->ntyp == D_STEP
-		     ||  e->n->ntyp == NON_ATOMIC)
-			e->n->sl->this->last->nxt = e->nxt;
-		else if (e->n->ntyp == UNLESS)
-			return e->sub->this->frst;
-	}
+	if (cnt >= 20 || !e)
+		fatal("confusing control structure", (char *) 0);
 	return e;
 	return e;
 }
 }
 
 
 Element *
 Element *
-huntele(Element *f, int o)
+huntele(Element *f, int o, int stopat)
 {	Element *g, *e = f;
 {	Element *g, *e = f;
-	int cnt; /* a precaution against loops */
+	int cnt=0; /* a precaution against loops */
 
 
 	if (e)
 	if (e)
-	for (cnt=0; cnt < 10 && e->n; cnt++)
-	{	switch (e->n->ntyp) {
+	for (cnt = 0; cnt < 20 && e->n; cnt++)
+	{
+		if (e->seqno == stopat)
+			break;
+
+		switch (e->n->ntyp) {
 		case GOTO:
 		case GOTO:
 			g = get_lab(e->n,1);
 			g = get_lab(e->n,1);
 			cross_dsteps(e->n, g->n);
 			cross_dsteps(e->n, g->n);
@@ -702,19 +898,20 @@ huntele(Element *f, int o)
 			g = e->nxt;
 			g = e->nxt;
 			break;
 			break;
 		case UNLESS:
 		case UNLESS:
-			g = huntele(e->sub->this->frst, o);
+			g = huntele(e->sub->this->frst, o, stopat);
 			break;
 			break;
 		case D_STEP:
 		case D_STEP:
 		case ATOMIC:
 		case ATOMIC:
 		case NON_ATOMIC:
 		case NON_ATOMIC:
-			e->n->sl->this->last->nxt = e->nxt;
-		default:	/* fall through */
+		default:
 			return e;
 			return e;
 		}
 		}
 		if ((o & ATOM) && !(g->status & ATOM))
 		if ((o & ATOM) && !(g->status & ATOM))
 			return e;
 			return e;
 		e = g;
 		e = g;
 	}
 	}
+	if (cnt >= 20 || !e)
+		fatal("confusing control structure", (char *) 0);
 	return e;
 	return e;
 }
 }
 
 
@@ -743,6 +940,7 @@ typ2c(Symbol *sp)
 			nBits++;
 			nBits++;
 			break;
 			break;
 		} /* else fall through */
 		} /* else fall through */
+		if (!(sp->hidden&1) && (verbose&32))
 		printf("spin: warning: bit-array %s[%d] mapped to byte-array\n",
 		printf("spin: warning: bit-array %s[%d] mapped to byte-array\n",
 			sp->name, sp->nel);
 			sp->name, sp->nel);
 		nBits += 8*sp->nel; /* mapped onto array of uchars */
 		nBits += 8*sp->nel; /* mapped onto array of uchars */
@@ -768,6 +966,7 @@ typ2c(Symbol *sp)
 			sp->name);
 			sp->name);
 		LstSet = ZS;
 		LstSet = ZS;
 		break;
 		break;
+	case CODE_FRAG:
 	case PREDEF:
 	case PREDEF:
 		return;
 		return;
 	default:
 	default:
@@ -790,22 +989,49 @@ ncases(FILE *fd, int p, int n, int m, char *c[])
 	}
 	}
 }
 }
 
 
+void
+qlen_type(int qmax)
+{
+	fprintf(th, "\t");
+	if (qmax < 256)
+		fprintf(th, "uchar");
+	else if (qmax < 65535)
+		fprintf(th, "ushort");
+	else
+		fprintf(th, "uint");
+	fprintf(th, " Qlen;	/* q_size */\n");
+}
+
 void
 void
 genaddqueue(void)
 genaddqueue(void)
 {	char buf0[256];
 {	char buf0[256];
-	int j;
+	int j, qmax = 0;
 	Queue *q;
 	Queue *q;
 
 
 	ntimes(tc, 0, 1, Addq0);
 	ntimes(tc, 0, 1, Addq0);
+	if (has_io && !nqs)
+		fprintf(th, "#define NQS	1 /* nqs=%d, but has_io */\n", nqs);
+	else
+		fprintf(th, "#define NQS	%d\n", nqs);
 	fprintf(th, "short q_flds[%d];\n", nqs+1);
 	fprintf(th, "short q_flds[%d];\n", nqs+1);
 	fprintf(th, "short q_max[%d];\n", nqs+1);
 	fprintf(th, "short q_max[%d];\n", nqs+1);
+
+	for (q = qtab; q; q = q->nxt)
+		if (q->nslots > qmax)
+			qmax = q->nslots;
+
 	for (q = qtab; q; q = q->nxt)
 	for (q = qtab; q; q = q->nxt)
 	{	j = q->qid;
 	{	j = q->qid;
 		fprintf(tc, "\tcase %d: j = sizeof(Q%d);", j, j);
 		fprintf(tc, "\tcase %d: j = sizeof(Q%d);", j, j);
 		fprintf(tc, " q_flds[%d] = %d;", j, q->nflds);
 		fprintf(tc, " q_flds[%d] = %d;", j, q->nflds);
 		fprintf(tc, " q_max[%d] = %d;", j, max(1,q->nslots));
 		fprintf(tc, " q_max[%d] = %d;", j, max(1,q->nslots));
 		fprintf(tc, " break;\n");
 		fprintf(tc, " break;\n");
-		ntimes(th, j, j+1, R9);
+
+		fprintf(th, "typedef struct Q%d {\n", j);
+		qlen_type(qmax);	/* 4.2.2 */
+		fprintf(th, "	uchar _t;	/* q_type */\n");
+		fprintf(th, "	struct {\n");
+
 		for (j = 0; j < q->nflds; j++)
 		for (j = 0; j < q->nflds; j++)
 		{	switch (q->fld_width[j]) {
 		{	switch (q->fld_width[j]) {
 			case BIT:
 			case BIT:
@@ -832,7 +1058,12 @@ genaddqueue(void)
 		fprintf(th, "	} contents[%d];\n", max(1, q->nslots));
 		fprintf(th, "	} contents[%d];\n", max(1, q->nslots));
 		fprintf(th, "} Q%d;\n", q->qid);
 		fprintf(th, "} Q%d;\n", q->qid);
 	}
 	}
-	ntimes(th, 0, 1, R10);
+
+	fprintf(th, "typedef struct Q0 {\t/* generic q */\n");
+	qlen_type(qmax);	/* 4.2.2 */
+	fprintf(th, "	uchar _t;\n");
+	fprintf(th, "} Q0;\n");
+
 	ntimes(tc, 0, 1, Addq1);
 	ntimes(tc, 0, 1, Addq1);
 
 
 	if (has_random)
 	if (has_random)
@@ -866,6 +1097,7 @@ genaddqueue(void)
 		fprintf(tc, "}\n");
 		fprintf(tc, "}\n");
 	}
 	}
 
 
+	fprintf(tc, "#if NQS>0\n");
 	fprintf(tc, "void\nqsend(int into, int sorted");
 	fprintf(tc, "void\nqsend(int into, int sorted");
 	for (j = 0; j < Mpars; j++)
 	for (j = 0; j < Mpars; j++)
 		fprintf(tc, ", int fld%d", j);
 		fprintf(tc, ", int fld%d", j);
@@ -879,33 +1111,35 @@ genaddqueue(void)
 		if (q->nslots == 0)	/* reset handshake point */
 		if (q->nslots == 0)	/* reset handshake point */
 			fprintf(tc, "\t\t(trpt+2)->o_m = 0;\n");
 			fprintf(tc, "\t\t(trpt+2)->o_m = 0;\n");
 
 
-	if (has_sorted)
-	{	fprintf(tc, "\t\tif (!sorted) goto append%d;\n", q->qid);
-		fprintf(tc, "\t\tfor (j = 0; j < %sQlen; j++)\n", buf0);
-		fprintf(tc, "\t\t{\t/* find insertion point */\n");
-		sprintf(buf0, "((Q%d *)z)->contents[j].fld", q->qid);
-		for (j = 0; j < q->nflds; j++)
-		{	fprintf(tc, "\t\t\tif (fld%d > %s%d) continue;\n",
-					j, buf0, j);
-			fprintf(tc, "\t\t\tif (fld%d < %s%d) ", j, buf0, j);
-			fprintf(tc, "goto found%d;\n\n", q->qid);
-		}
-		fprintf(tc, "\t\t}\n");
-		fprintf(tc, "\tfound%d:\n", q->qid);
-		sprintf(buf0, "((Q%d *)z)->", q->qid);
-		fprintf(tc, "\t\tfor (k = %sQlen - 1; k >= j; k--)\n", buf0);
-		fprintf(tc, "\t\t{\t/* shift up */\n");
-		for (j = 0; j < q->nflds; j++)
-		{	fprintf(tc, "\t\t\t%scontents[k+1].fld%d = ",
-				buf0, j);
-			fprintf(tc, "%scontents[k].fld%d;\n",
-				buf0, j);
+		if (has_sorted)
+		{	fprintf(tc, "\t\tif (!sorted) goto append%d;\n", q->qid);
+			fprintf(tc, "\t\tfor (j = 0; j < %sQlen; j++)\n", buf0);
+			fprintf(tc, "\t\t{\t/* find insertion point */\n");
+			sprintf(buf0, "((Q%d *)z)->contents[j].fld", q->qid);
+			for (j = 0; j < q->nflds; j++)
+			{	fprintf(tc, "\t\t\tif (fld%d > %s%d) continue;\n",
+						j, buf0, j);
+				fprintf(tc, "\t\t\tif (fld%d < %s%d) ", j, buf0, j);
+				fprintf(tc, "goto found%d;\n\n", q->qid);
+			}
+			fprintf(tc, "\t\t}\n");
+			fprintf(tc, "\tfound%d:\n", q->qid);
+			sprintf(buf0, "((Q%d *)z)->", q->qid);
+			fprintf(tc, "\t\tfor (k = %sQlen - 1; k >= j; k--)\n", buf0);
+			fprintf(tc, "\t\t{\t/* shift up */\n");
+			for (j = 0; j < q->nflds; j++)
+			{	fprintf(tc, "\t\t\t%scontents[k+1].fld%d = ",
+					buf0, j);
+				fprintf(tc, "%scontents[k].fld%d;\n",
+					buf0, j);
+			}
+			fprintf(tc, "\t\t}\n");
+			fprintf(tc, "\tappend%d:\t/* insert in slot j */\n", q->qid);
 		}
 		}
-		fprintf(tc, "\t\t}\n");
-		fprintf(tc, "\tappend%d:\t/* insert in slot j */\n", q->qid);
-	}
 
 
-		fprintf(tc, "\t\t(trpt+1)->bup.oval = j;\n");
+		fprintf(tc, "#ifdef HAS_SORTED\n");
+		fprintf(tc, "\t\t(trpt+1)->ipt = j;\n");	/* ipt was bup.oval */
+		fprintf(tc, "#endif\n");
 		fprintf(tc, "\t\t%sQlen = %sQlen + 1;\n", buf0, buf0);
 		fprintf(tc, "\t\t%sQlen = %sQlen + 1;\n", buf0, buf0);
 		sprintf(buf0, "((Q%d *)z)->contents[j].fld", q->qid);
 		sprintf(buf0, "((Q%d *)z)->contents[j].fld", q->qid);
 		for (j = 0; j < q->nflds; j++)
 		for (j = 0; j < q->nflds; j++)
@@ -939,16 +1173,23 @@ genaddqueue(void)
 			fprintf(tc, "\t\t}\n");
 			fprintf(tc, "\t\t}\n");
 		}
 		}
 		fprintf(tc, "\t\tif (done)\n");
 		fprintf(tc, "\t\tif (done)\n");
-		fprintf(tc, "\t\t{	j = %sQlen;\n",  buf0);
-		fprintf(tc, "\t\t	%sQlen = --j;\n", buf0);
-		fprintf(tc, "\t\t	for (k=slot; k<j; k++)\n");
-		fprintf(tc, "\t\t	{\n");
-		sprintf(buf0, "\t\t\t((Q%d *)z)->contents", q->qid);
-		for (j = 0; j < q->nflds; j++)
-		{	fprintf(tc, "\t%s[k].fld%d = \n", buf0, j);
-			fprintf(tc, "\t\t%s[k+1].fld%d;\n", buf0, j);
-		}
-		fprintf(tc, "\t\t	}\n");
+		if (q->nslots == 0)
+		{	fprintf(tc, "\t\t{	j = %sQlen - 1;\n",  buf0);
+			fprintf(tc, "\t\t	%sQlen = 0;\n", buf0);
+			sprintf(buf0, "\t\t\t((Q%d *)z)->contents", q->qid);
+		} else
+	 	{	fprintf(tc, "\t\t{	j = %sQlen;\n",  buf0);
+			fprintf(tc, "\t\t	%sQlen = --j;\n", buf0);
+			fprintf(tc, "\t\t	for (k=slot; k<j; k++)\n");
+			fprintf(tc, "\t\t	{\n");
+			sprintf(buf0, "\t\t\t((Q%d *)z)->contents", q->qid);
+			for (j = 0; j < q->nflds; j++)
+			{	fprintf(tc, "\t%s[k].fld%d = \n", buf0, j);
+				fprintf(tc, "\t\t%s[k+1].fld%d;\n", buf0, j);
+			}
+			fprintf(tc, "\t\t	}\n");
+	 	}
+
 		for (j = 0; j < q->nflds; j++)
 		for (j = 0; j < q->nflds; j++)
 			fprintf(tc, "%s[j].fld%d = 0;\n", buf0, j);
 			fprintf(tc, "%s[j].fld%d = 0;\n", buf0, j);
 		fprintf(tc, "\t\t\tif (fld+1 != %d)\n\t\t\t", q->nflds);
 		fprintf(tc, "\t\t\tif (fld+1 != %d)\n\t\t\t", q->nflds);

File diff suppressed because it is too large
+ 1110 - 30
sys/src/cmd/spin/pangen1.h


File diff suppressed because it is too large
+ 279 - 112
sys/src/cmd/spin/pangen2.c


+ 116 - 115
sys/src/cmd/spin/pangen2.h

@@ -1,14 +1,13 @@
 /***** spin: pangen2.h *****/
 /***** spin: pangen2.h *****/
 
 
-/* Copyright (c) 1991-2000 by Lucent Technologies - Bell Laboratories     */
+/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories.     */
 /* All Rights Reserved.  This software is for educational purposes only.  */
 /* All Rights Reserved.  This software is for educational purposes only.  */
-/* Permission is given to distribute this code provided that this intro-  */
-/* ductory message is not removed and no monies are exchanged.            */
-/* No guarantee is expressed or implied by the distribution of this code. */
-/* Software written by Gerard J. Holzmann as part of the book:            */
-/* `Design and Validation of Computer Protocols,' ISBN 0-13-539925-4,     */
-/* Prentice Hall, Englewood Cliffs, NJ, 07632.                            */
-/* Send bug-reports and/or questions to: gerard@research.bell-labs.com    */
+/* No guarantee whatsoever is expressed or implied by the distribution of */
+/* this code.  Permission is given to distribute this code provided that  */
+/* this introductory message is not removed and no monies are exchanged.  */
+/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
+/*             http://spinroot.com/                                       */
+/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
 
 
 static char *Nvr1[] = {		/* allow separate compilation */
 static char *Nvr1[] = {		/* allow separate compilation */
 	"#ifdef VERI",
 	"#ifdef VERI",
@@ -18,20 +17,31 @@ static char *Nvr1[] = {		/* allow separate compilation */
 	"	if (st == endclaim)",
 	"	if (st == endclaim)",
 	"		uerror(\"claim violated!\");",
 	"		uerror(\"claim violated!\");",
 	"	if (stopstate[VERI][st])",
 	"	if (stopstate[VERI][st])",
-	"		uerror(\"endstate in claim reached\");",
+	"		uerror(\"end state in claim reached\");",
 	"}",
 	"}",
 	"#endif",
 	"#endif",
 	0,
 	0,
 };
 };
 
 
 static char *Pre0[] = {
 static char *Pre0[] = {
+"#ifdef SC",
+	"#define _FILE_OFFSET_BITS	64",	/* to allow file sizes greater than 2Gb */
+"#endif",
 	"#include <stdio.h>",
 	"#include <stdio.h>",
 	"#include <signal.h>",
 	"#include <signal.h>",
 	"#include <stdlib.h>",
 	"#include <stdlib.h>",
-	"#include <string.h>",	/* was strings.h -- string.h is ANSI */
-/* new */
+	"#include <stdarg.h>",
+	"#include <string.h>",
+	"#include <ctype.h>",
 	"#include <errno.h>",
 	"#include <errno.h>",
-/* end */
+"#ifdef SC",
+	"#include <sys/types.h>",	/* defines off_t */
+	"#include <sys/stat.h>",
+	"#include <fcntl.h>",
+	#ifndef PC
+	"#include <unistd.h>",
+	#endif
+"#endif",
 	"#define Offsetof(X, Y)	((unsigned long)(&(((X *)0)->Y)))",
 	"#define Offsetof(X, Y)	((unsigned long)(&(((X *)0)->Y)))",
 	"#ifndef max",
 	"#ifndef max",
 	"#define max(a,b) (((a)<(b)) ? (b) : (a))",
 	"#define max(a,b) (((a)<(b)) ? (b) : (a))",
@@ -64,6 +74,9 @@ static char *Preamble[] = {
 	"#endif",
 	"#endif",
 
 
 "#ifdef MA",
 "#ifdef MA",
+	"#undef onstack_now",
+	"#undef onstack_put",
+	"#undef onstack_zap",
 	"#define onstack_put()	;",
 	"#define onstack_put()	;",
 	"#define onstack_zap()	gstore((char *) &now, vsize, 4)",
 	"#define onstack_zap()	gstore((char *) &now, vsize, 4)",
 "#else",
 "#else",
@@ -102,7 +115,7 @@ static char *Preamble[] = {
 	"} **H_tab, **S_Tab;\n",
 	"} **H_tab, **S_Tab;\n",
 
 
 	"typedef struct Trail {",
 	"typedef struct Trail {",
-	"	short st;	/* current state */",
+	"	int   st;	/* current state */",
 	"	uchar pr;	/* process id */",
 	"	uchar pr;	/* process id */",
 	"	uchar tau;	/* 8 bit-flags */",
 	"	uchar tau;	/* 8 bit-flags */",
 	"	uchar o_pm;	/* 8 more bit-flags */",
 	"	uchar o_pm;	/* 8 more bit-flags */",
@@ -126,10 +139,13 @@ static char *Preamble[] = {
 	"	o_pm&64 -> the current proc applied rule2",
 	"	o_pm&64 -> the current proc applied rule2",
 	"	o_pm&128 -> a fairness, dummy move - all procs blocked",
 	"	o_pm&128 -> a fairness, dummy move - all procs blocked",
 	"#endif",
 	"#endif",
-	"#if defined(FULLSTACK) && defined(MA)",
+	"#if defined(FULLSTACK) && defined(MA) && !defined(BFS)",
 	"	uchar proviso;",
 	"	uchar proviso;",
 	"#endif",
 	"#endif",
-	"	char  o_n, o_ot, o_m;	/* to save locals */",
+	"#ifndef BFS",
+	"	uchar  o_n, o_ot;	/* to save locals */",
+	"#endif",
+	"	uchar  o_m;",
 	"#ifdef EVENT_TRACE",
 	"#ifdef EVENT_TRACE",
 		"#if nstates_event<256",
 		"#if nstates_event<256",
 	"	uchar o_event;",
 	"	uchar o_event;",
@@ -137,17 +153,27 @@ static char *Preamble[] = {
 	"	unsigned short o_event;",
 	"	unsigned short o_event;",
 		"#endif",
 		"#endif",
 	"#endif",
 	"#endif",
-	"	short o_tt, o_To;", /* used in new_state()  */
-	"#ifdef HAS_UNLESS",
-	"	short e_state;	/* if escape trans - state of origin */",
+	"	int o_tt;",
+	"#ifndef BFS",
+	"	short o_To;",
+		"#ifdef RANDOMIZE",
+	"	short oo_i;",
+		"#endif",
+	"#endif",
+	"#if defined(HAS_UNLESS) && !defined(BFS)",
+	"	int e_state;	/* if escape trans - state of origin */",
 	"#endif",
 	"#endif",
-	"#if defined(FULLSTACK) && !defined(MA)",
+	"#if (defined(FULLSTACK) && !defined(MA)) || defined(BFS)",
 	"	struct H_el *ostate;	/* pointer to stored state */",
 	"	struct H_el *ostate;	/* pointer to stored state */",
 	"#endif",
 	"#endif",
-	"#ifdef CNTRSTACK",
+	/* CNTRSTACK when !NOREDUCE && BITSTATE && SAFETY, uses LL[] */
+	"#if defined(CNTRSTACK) && !defined(BFS)",
 	"	long	j6, j7;",
 	"	long	j6, j7;",
 	"#endif",
 	"#endif",
 	"	Trans *o_t;",	/* transition fct, next state   */
 	"	Trans *o_t;",	/* transition fct, next state   */
+	"#ifdef HAS_SORTED",
+	"	short ipt;",	/* insertion slot in q */
+	"#endif",
 	"	union {",
 	"	union {",
 	"		int oval;",	/* single backup value of variable */
 	"		int oval;",	/* single backup value of variable */
 	"		int *ovals;",	/* ptr to multiple values */
 	"		int *ovals;",	/* ptr to multiple values */
@@ -158,18 +184,16 @@ static char *Preamble[] = {
 	"FILE	*efd;",
 	"FILE	*efd;",
 	"uchar	*this;",
 	"uchar	*this;",
 	"long	maxdepth=10000;",
 	"long	maxdepth=10000;",
+	"long	omaxdepth=10000;",
 	"#ifdef SC",	/* stack cycling */
 	"#ifdef SC",	/* stack cycling */
-	"long	omaxdepth;",
 	"char	*stackfile;",
 	"char	*stackfile;",
  	"#endif",
  	"#endif",
 	"uchar	*SS, *LL;",
 	"uchar	*SS, *LL;",
 	"uchar	HASH_NR = 0;",
 	"uchar	HASH_NR = 0;",
 	"",
 	"",
-	"#ifdef MEMCNT",
 	"double memcnt = (double) 0;",
 	"double memcnt = (double) 0;",
-	"double overhead = (double) 0;",
 	"double memlim = (double) (1<<30);",
 	"double memlim = (double) (1<<30);",
-	"#endif",
+	"",
 	"/* for emalloc: */",
 	"/* for emalloc: */",
 	"static char *have;",
 	"static char *have;",
 	"static long left = 0L;",
 	"static long left = 0L;",
@@ -197,29 +221,34 @@ static char *Preamble[] = {
 	"	0x273d1aa5,	0x8923b1dd,",
 	"	0x273d1aa5,	0x8923b1dd,",
 	"	0",
 	"	0",
 	"};",
 	"};",
-	"int	mreached=0, done=0, errors=0, Nrun=1, single=0;",
+	"int	mreached=0, done=0, errors=0, Nrun=1;",
 	"double	nstates=0, nlinks=0, truncs=0, truncs2=0;",
 	"double	nstates=0, nlinks=0, truncs=0, truncs2=0;",
 	"double	nlost=0, nShadow=0, hcmp=0, ngrabs=0;",
 	"double	nlost=0, nShadow=0, hcmp=0, ngrabs=0;",
+	"#ifdef BFS",
+	"double midrv=0, failedrv=0, revrv=0;",
+	"#endif",
 	"unsigned long	nr_states=0; /* nodes in DFA */",
 	"unsigned long	nr_states=0; /* nodes in DFA */",
 	"long	Fa=0, Fh=0, Zh=0, Zn=0;",
 	"long	Fa=0, Fh=0, Zh=0, Zn=0;",
 	"long	PUT=0, PROBE=0, ZAPS=0;",
 	"long	PUT=0, PROBE=0, ZAPS=0;",
 	"long	Ccheck=0, Cholds=0;",
 	"long	Ccheck=0, Cholds=0;",
-	"unsigned long mask;",
-	"int	a_cycles=0, upto=1, strict=0, verbose = 0;",
+	"int	a_cycles=0, upto=1, strict=0, verbose = 0, signoff = 0;",
+	"#ifdef HAS_CODE",
+	"int	gui = 0, coltrace = 0, readtrail = 0, whichtrail = 0, onlyproc = -1;",
+	"#endif",
 	"int	state_tables=0, fairness=0, no_rck=0, Nr_Trails=0;",
 	"int	state_tables=0, fairness=0, no_rck=0, Nr_Trails=0;",
+	"char	simvals[128];",
 	"#ifndef INLINE",
 	"#ifndef INLINE",
 	"int	TstOnly=0;",
 	"int	TstOnly=0;",
 	"#endif",
 	"#endif",
+	"unsigned long mask, nmask;",
 	"#ifdef BITSTATE",
 	"#ifdef BITSTATE",
-	"int	ssize=22;",
+	"int	ssize=23;	/* 1 Mb */",
 	"#else",
 	"#else",
-	"int	ssize=18;",
+	"int	ssize=19;	/* 512K slots */",
 	"#endif",
 	"#endif",
 	"int	hmax=0, svmax=0, smax=0;",
 	"int	hmax=0, svmax=0, smax=0;",
 	"int	Maxbody=0, XX;",
 	"int	Maxbody=0, XX;",
 	"uchar	*noptr;	/* used by macro Pptr(x) */",
 	"uchar	*noptr;	/* used by macro Pptr(x) */",
-	"State	A_Root;		/* root of acceptance cycles */",
-	"State	now;		/* the full state vector */",
 	"#ifdef VAR_RANGES",
 	"#ifdef VAR_RANGES",
 	"void logval(char *, int);",
 	"void logval(char *, int);",
 	"void dumpranges(void);",
 	"void dumpranges(void);",
@@ -228,27 +257,35 @@ static char *Preamble[] = {
 	"#ifdef MA",
 	"#ifdef MA",
 	"#define INLINE_REV",
 	"#define INLINE_REV",
 	"extern void dfa_init(unsigned short);",
 	"extern void dfa_init(unsigned short);",
-	"extern int  dfa_member(unsigned short);",
-	"extern int  dfa_store(unsigned char *);",
+	"extern int  dfa_member(unsigned long);",
+	"extern int  dfa_store(uchar *);",
 	"unsigned int	maxgs = 0;",
 	"unsigned int	maxgs = 0;",
 	"#endif",
 	"#endif",
 
 
-	"#if !defined(NOCOMP) || defined(BITSTATE)",
 	"State	comp_now;	/* compressed state vector */",
 	"State	comp_now;	/* compressed state vector */",
 	"State	comp_msk;",
 	"State	comp_msk;",
 	"uchar	*Mask = (uchar *) &comp_msk;",
 	"uchar	*Mask = (uchar *) &comp_msk;",
-	"#endif",
 	"#ifdef COLLAPSE",
 	"#ifdef COLLAPSE",
 	"State	comp_tmp;",
 	"State	comp_tmp;",
-	"char	*scratch = (char *) &comp_tmp;",
+	"static char	*scratch = (char *) &comp_tmp;",
 	"#endif",
 	"#endif",
 
 
 	"Stack	*stack; 	/* for queues, processes */",
 	"Stack	*stack; 	/* for queues, processes */",
 	"Svtack	*svtack;	/* for old state vectors */",
 	"Svtack	*svtack;	/* for old state vectors */",
-	"long	J1, J2, J3, J4, j1, j2, j3, j4;",
-	"long	A_depth = 0, depth = 0;",
-	"uchar	warned = 0, iterative = 0, like_java = 0, every_error = 0;",
-	"uchar	noasserts = 0, noends = 0;",
+	"#ifdef BITSTATE",
+	"static unsigned hfns = 3;	/* new default */",
+	"#endif",
+	"static unsigned long j1;",
+	"static unsigned long K1, K2;",
+	"static unsigned long j2, j3, j4;",
+	"#ifdef BITSTATE",
+#ifndef POWOW
+	"static long udmem;",
+#endif
+	"#endif",
+	"static long	A_depth = 0, depth = 0;",
+	"static uchar	warned = 0, iterative = 0, like_java = 0, every_error = 0;",
+	"static uchar	noasserts = 0, noends = 0, bounded = 0;",
 	"#if SYNC>0 && ASYNC==0",
 	"#if SYNC>0 && ASYNC==0",
 	"void set_recvs(void);",
 	"void set_recvs(void);",
 	"int  no_recvs(int);",
 	"int  no_recvs(int);",
@@ -260,6 +297,13 @@ static char *Preamble[] = {
 	"#define IfNotBlocked	/* cannot block */",
 	"#define IfNotBlocked	/* cannot block */",
 	"#define UnBlock     	/* don't bother */",
 	"#define UnBlock     	/* don't bother */",
 	"#endif\n",
 	"#endif\n",
+	"#ifdef BITSTATE",
+	"int (*bstore)(char *, int);",
+	"int bstore_reg(char *, int);",
+#ifndef POWOW
+	"int bstore_mod(char *, int);",
+#endif
+	"#endif",
 	"void active_procs(void);",
 	"void active_procs(void);",
 	"void cleanup(void);",
 	"void cleanup(void);",
 	"void do_the_search(void);",
 	"void do_the_search(void);",
@@ -267,10 +311,6 @@ static char *Preamble[] = {
 	"void iniglobals(void);",
 	"void iniglobals(void);",
 	"void stopped(int);",
 	"void stopped(int);",
 	"void wrapup(void);",
 	"void wrapup(void);",
-#if 0
-	"void bup_q(int, int);",
-	"void unbup_q(int, int);",
-#endif
 	"int *grab_ints(int);",
 	"int *grab_ints(int);",
 	"void ungrab_ints(int *, int);",
 	"void ungrab_ints(int *, int);",
 	0,
 	0,
@@ -344,45 +384,8 @@ static char *Tail[] = {
 	"	return 0;",
 	"	return 0;",
 	"}",
 	"}",
 	"#endif",
 	"#endif",
-/* new */
-	"uchar *visited;",
-	"void",
-	"dovisit(int n, int m, int is, uchar reach[])",
-	"{	Trans *z;",
-	"	if (is >= m || !trans[n][is]",
-	"	||  is <= 0 || visited[is])",
-	"		return;",
-	"	visited[is] = 1;",
-	"	for (z = trans[n][is]; z; z = z->nxt)",
-	"	{	int i, j;",
-	"		dovisit(n, m, z->st, reach);",
-	"#ifdef HAS_UNLESS",
-	"		for (i = 0; i < HAS_UNLESS; i++)",
-	"		{	j = trans[n][is]->escp[i];",
-	"			if (!j) break;",
-	"			dovisit(n, m, j, reach);",
-	"		}",
-	"#endif",
-	"	}",
-	"}",
-	"void",
-	"check_unreachable(int n, int m, int is, short srcln[], uchar reach[])",
-	"{	int i; static int oldm=0;",
-	"	if (m > oldm)	/* not much memory */",
-	"	{	visited = (uchar *) emalloc(m * sizeof(uchar));",
-	"		oldm = m;",
-	"	} else",
-	"		memset(visited, 0, m);",
-	"	dovisit(n, m, is, reach);",
-	"	for (i = 1; i < m; i++)",
-	"		if (!visited[i] && reach[i] == 0)",
-	"		{	if (0) printf(\"%%s: merged state %%d, line %%d\\n\",",
-	"				procname[n], i, srcln[i]);",
-	"			reach[i] = 1;",
-	"		}",
-	"}",
-
 	"int cnt;",
 	"int cnt;",
+	"#ifdef HAS_UNLESS",
 	"int",
 	"int",
 	"isthere(Trans *a, int b)", /* is b already in a's list? */
 	"isthere(Trans *a, int b)", /* is b already in a's list? */
 	"{	Trans *t;",
 	"{	Trans *t;",
@@ -391,10 +394,11 @@ static char *Tail[] = {
 	"			return 1;",
 	"			return 1;",
 	"	return 0;",
 	"	return 0;",
 	"}",
 	"}",
+	"#endif",
 	"#ifndef NOREDUCE",
 	"#ifndef NOREDUCE",
 	"int",
 	"int",
 	"mark_safety(Trans *t) /* for conditional safety */",
 	"mark_safety(Trans *t) /* for conditional safety */",
-	"{	int g = 0, h, i, j, k;",
+	"{	int g = 0, i, j, k;",
 	"",
 	"",
 	"	if (!t) return 0;",
 	"	if (!t) return 0;",
 	"	if (t->qu[0])",
 	"	if (t->qu[0])",
@@ -402,7 +406,7 @@ static char *Tail[] = {
 	"",
 	"",
 	"	for (i = 0; i < 2; i++)",
 	"	for (i = 0; i < 2; i++)",
 	"	{	j = srinc_set(t->tpe[i]);",
 	"	{	j = srinc_set(t->tpe[i]);",
-	"		if (j >= GLOBAL)",
+	"		if (j >= GLOBAL && j != ALPHA_F)",
 	"			return -1;",
 	"			return -1;",
 	"		if (j != LOCAL)",
 	"		if (j != LOCAL)",
 	"		{	k = srunc(t->tpe[i], j);",
 	"		{	k = srunc(t->tpe[i], j);",
@@ -420,7 +424,13 @@ static char *Tail[] = {
 	"retrans(int n, int m, int is, short srcln[], uchar reach[])",
 	"retrans(int n, int m, int is, short srcln[], uchar reach[])",
 	"	/* process n, with m states, is=initial state */",
 	"	/* process n, with m states, is=initial state */",
 	"{	Trans *T0, *T1, *T2, *T3;",
 	"{	Trans *T0, *T1, *T2, *T3;",
-	"	int i, j, k, p, h, g, aa;",
+	"	int i, k;",
+	"#ifndef NOREDUCE",
+	"	int g, h, j, aa;",
+	"#endif",
+	"#ifdef HAS_UNLESS",
+	"	int p;",
+	"#endif",
 	"	if (state_tables >= 4)",
 	"	if (state_tables >= 4)",
 	"	{	printf(\"STEP 1 proctype %%s\\n\", ",
 	"	{	printf(\"STEP 1 proctype %%s\\n\", ",
 	"			procname[n]);",
 	"			procname[n]);",
@@ -449,13 +459,13 @@ static char *Tail[] = {
 	"				if (!T3->nxt)",
 	"				if (!T3->nxt)",
 	"				{	T2->nxt = cpytr(T0);",
 	"				{	T2->nxt = cpytr(T0);",
 	"					T2 = T2->nxt;",
 	"					T2 = T2->nxt;",
-	"					imed(T2, T0->st, n);",
+	"					imed(T2, T0->st, n, i);",
 	"					continue;",
 	"					continue;",
 	"				}",
 	"				}",
 	"				do {	T3 = T3->nxt;",
 	"				do {	T3 = T3->nxt;",
 	"					T2->nxt = cpytr(T3);",
 	"					T2->nxt = cpytr(T3);",
 	"					T2 = T2->nxt;",
 	"					T2 = T2->nxt;",
-	"					imed(T2, T0->st, n);",
+	"					imed(T2, T0->st, n, i);",
 	"				} while (T3->nxt);",
 	"				} while (T3->nxt);",
 	"				cnt++;",
 	"				cnt++;",
 	"			}",
 	"			}",
@@ -481,7 +491,7 @@ static char *Tail[] = {
 	"			T0 = cpytr(trans[n][T1->st]);",
 	"			T0 = cpytr(trans[n][T1->st]);",
 	"			trans[n][i] = T0;",
 	"			trans[n][i] = T0;",
 	"			reach[T1->st] = 1;",
 	"			reach[T1->st] = 1;",
-	"			imed(T0, T1->st, n);",
+	"			imed(T0, T1->st, n, i);",
 	"			for (T1 = T1->nxt; T1; T1 = T1->nxt)",
 	"			for (T1 = T1->nxt; T1; T1 = T1->nxt)",
 	"			{",
 	"			{",
 	"#if 0",
 	"#if 0",
@@ -492,7 +502,7 @@ static char *Tail[] = {
 	"				T0->nxt = cpytr(trans[n][T1->st]);",
 	"				T0->nxt = cpytr(trans[n][T1->st]);",
 	"				T0 = T0->nxt;",
 	"				T0 = T0->nxt;",
 	"				reach[T1->st] = 1;",
 	"				reach[T1->st] = 1;",
-	"				imed(T0, T1->st, n);",
+	"				imed(T0, T1->st, n, i);",
 	"	}	}	}",
 	"	}	}	}",
 	"	if (state_tables >= 2)",
 	"	if (state_tables >= 2)",
 	"	{	printf(\"STEP 3 proctype %%s\\n\", ",
 	"	{	printf(\"STEP 3 proctype %%s\\n\", ",
@@ -576,8 +586,8 @@ static char *Tail[] = {
 	"			{	if (!(T0->atom&8))",
 	"			{	if (!(T0->atom&8))",
 	"					goto degrade;",
 	"					goto degrade;",
 	"				for (aa = 0; aa < 2; aa++)",
 	"				for (aa = 0; aa < 2; aa++)",
-	"				{	if (srinc_set(T0->tpe[aa])",
-	"					>=  GLOBAL)",
+	"				{	j = srinc_set(T0->tpe[aa]);",
+	"					if (j >= GLOBAL && j != ALPHA_F)",
 	"						goto degrade;",
 	"						goto degrade;",
 	"					if (T0->tpe[aa]",
 	"					if (T0->tpe[aa]",
 	"					&&  T0->tpe[aa]",
 	"					&&  T0->tpe[aa]",
@@ -602,13 +612,11 @@ static char *Tail[] = {
 	"			}	}	}",
 	"			}	}	}",
 	"			if (g > 6)",
 	"			if (g > 6)",
 	"			{	T1->qu[0] = 0;	/* turn it off */",
 	"			{	T1->qu[0] = 0;	/* turn it off */",
-	"#if 1",
 	"				printf(\"pan: warning, line %%d, \",",
 	"				printf(\"pan: warning, line %%d, \",",
 	"					srcln[i]);",
 	"					srcln[i]);",
 	"			 	printf(\"too many stmnt types (%%d)\",",
 	"			 	printf(\"too many stmnt types (%%d)\",",
 	"					g);",
 	"					g);",
 	"			  	printf(\" in selection\\n\");",
 	"			  	printf(\" in selection\\n\");",
-	"#endif",
 	"			  goto degrade;",
 	"			  goto degrade;",
 	"			}",
 	"			}",
 	"		}",
 	"		}",
@@ -628,27 +636,21 @@ static char *Tail[] = {
 	"		j = T1->tpe[0];",
 	"		j = T1->tpe[0];",
 	"		if (T1->nxt && T1->atom&8)",
 	"		if (T1->nxt && T1->atom&8)",
 	"		{ if (j == 5*DELTA)",
 	"		{ if (j == 5*DELTA)",
-	"		  {",
-	"#if 1",
-	"			printf(\"warning: line %%d \", srcln[i]);",
+	"		  {	printf(\"warning: line %%d \", srcln[i]);",
 	"			printf(\"mixed condition \");",
 	"			printf(\"mixed condition \");",
 	"			printf(\"(defeats reduction)\\n\");",
 	"			printf(\"(defeats reduction)\\n\");",
-	"#endif",
 	"			goto degrade;",
 	"			goto degrade;",
 	"		  }",
 	"		  }",
 	"		  for (T0 = T1; T0; T0 = T0->nxt)",
 	"		  for (T0 = T1; T0; T0 = T0->nxt)",
 	"		  for (aa = 0; aa < 2; aa++)",
 	"		  for (aa = 0; aa < 2; aa++)",
 	"		  if  (T0->tpe[aa] && T0->tpe[aa] != j)",
 	"		  if  (T0->tpe[aa] && T0->tpe[aa] != j)",
-	"		  {",
-	"#if 1",
-	"			printf(\"warning: line %%d \", srcln[i]);",
+	"		  {	printf(\"warning: line %%d \", srcln[i]);",
 	"			printf(\"[%%d-%%d] mixed %%stion \",",
 	"			printf(\"[%%d-%%d] mixed %%stion \",",
 	"				T0->tpe[aa], j, ",
 	"				T0->tpe[aa], j, ",
 	"				(j==5*DELTA)?\"condi\":\"selec\");",
 	"				(j==5*DELTA)?\"condi\":\"selec\");",
 	"			printf(\"(defeats reduction)\\n\");",
 	"			printf(\"(defeats reduction)\\n\");",
 	"			printf(\"	'%%s' <-> '%%s'\\n\",",
 	"			printf(\"	'%%s' <-> '%%s'\\n\",",
 	"				T1->tp, T0->tp);",
 	"				T1->tp, T0->tp);",
-	"#endif",
 	"			goto degrade;",
 	"			goto degrade;",
 	"		} }",
 	"		} }",
 	"	}",
 	"	}",
@@ -683,7 +685,7 @@ static char *Tail[] = {
 	"		  		printf(\"line %%d, state %%d: has un\",",
 	"		  		printf(\"line %%d, state %%d: has un\",",
 	"					srcln[i], i);",
 	"					srcln[i], i);",
 	"				printf(\"conditional self-loop\\n\");",
 	"				printf(\"conditional self-loop\\n\");",
-	"				exit(1);",
+	"				pan_exit(1);",
 	"		}	}",
 	"		}	}",
 	"		nrelse = 0;",
 	"		nrelse = 0;",
 	"		for (T0 = trans[n][i]; T0; T0 = T0->nxt)",
 	"		for (T0 = trans[n][i]; T0; T0 = T0->nxt)",
@@ -695,16 +697,16 @@ static char *Tail[] = {
 	"				procname[n]);",
 	"				procname[n]);",
 	"		  	printf(\" %%d, inherits %%d\", i, nrelse);",
 	"		  	printf(\" %%d, inherits %%d\", i, nrelse);",
 	"		  	printf(\" 'else' stmnts\\n\");",
 	"		  	printf(\" 'else' stmnts\\n\");",
-	"			exit(1);",
+	"			pan_exit(1);",
 	"	}	}",
 	"	}	}",
-	"	check_unreachable(n, m, is, srcln, reach);",
-	"}\n",
+	"}",
 	"void",
 	"void",
-	"imed(Trans *T, int v, int n)	/* set intermediate state */",
+	"imed(Trans *T, int v, int n, int j)	/* set intermediate state */",
 	"{	progstate[n][T->st] |= progstate[n][v];",
 	"{	progstate[n][T->st] |= progstate[n][v];",
 	"	accpstate[n][T->st] |= accpstate[n][v];",
 	"	accpstate[n][T->st] |= accpstate[n][v];",
 	"	stopstate[n][T->st] |= stopstate[n][v];",
 	"	stopstate[n][T->st] |= stopstate[n][v];",
-	"}\n",
+	"	mapstate[n][j] = T->st;",
+	"}",
 	"void",
 	"void",
 	"tagtable(int n, int m, int is, short srcln[], uchar reach[])",
 	"tagtable(int n, int m, int is, short srcln[], uchar reach[])",
 	"{	Trans *z;\n",
 	"{	Trans *z;\n",
@@ -716,7 +718,10 @@ static char *Tail[] = {
 	"	for (z = trans[n][is]; z; z = z->nxt)",
 	"	for (z = trans[n][is]; z; z = z->nxt)",
 	"		crack(n, is, z, srcln);",
 	"		crack(n, is, z, srcln);",
 	"	for (z = trans[n][is]; z; z = z->nxt)",
 	"	for (z = trans[n][is]; z; z = z->nxt)",
-	"	{	int i, j;",
+	"	{",
+	"#ifdef HAS_UNLESS",
+	"		int i, j;",
+	"#endif",
 	"		tagtable(n, m, z->st, srcln, reach);",
 	"		tagtable(n, m, z->st, srcln, reach);",
 	"#ifdef HAS_UNLESS",
 	"#ifdef HAS_UNLESS",
 	"		for (i = 0; i < HAS_UNLESS; i++)",
 	"		for (i = 0; i < HAS_UNLESS; i++)",
@@ -726,7 +731,7 @@ static char *Tail[] = {
 	"		}",
 	"		}",
 	"#endif",
 	"#endif",
 	"	}",
 	"	}",
-	"}\n",
+	"}",
 	"void",
 	"void",
 	"crack(int n, int j, Trans *z, short srcln[])",
 	"crack(int n, int j, Trans *z, short srcln[])",
 	"{	int i;\n",
 	"{	int i;\n",
@@ -757,9 +762,6 @@ static char *Tail[] = {
 	"			printf(\"\\\\n\");",
 	"			printf(\"\\\\n\");",
 	"		else",
 	"		else",
 	"			putchar(z->tp[i]);",
 	"			putchar(z->tp[i]);",
-	"#if 0",
-	"	printf(\"\\n\");",
-	"#else",
 	"	if (z->qu[0])",
 	"	if (z->qu[0])",
 	"	{	printf(\"\\t[\");",
 	"	{	printf(\"\\t[\");",
 	"		for (i = 0; i < 6; i++)",
 	"		for (i = 0; i < 6; i++)",
@@ -769,7 +771,6 @@ static char *Tail[] = {
 	"		printf(\"]\");",
 	"		printf(\"]\");",
 	"	}",
 	"	}",
 	"	printf(\"\\n\");",
 	"	printf(\"\\n\");",
-	"#endif",
 	"	fflush(stdout);",
 	"	fflush(stdout);",
 	"}",
 	"}",
 	"",
 	"",
@@ -778,7 +779,7 @@ static char *Tail[] = {
 	"",
 	"",
 	"typedef struct Vr_Ptr {",
 	"typedef struct Vr_Ptr {",
 	"	char	*nm;",
 	"	char	*nm;",
-	"	unsigned char vals[BYTESIZE];",
+	"	uchar	vals[BYTESIZE];",
 	"	struct Vr_Ptr *nxt;",
 	"	struct Vr_Ptr *nxt;",
 	"} Vr_Ptr;",
 	"} Vr_Ptr;",
 	"Vr_Ptr *ranges = (Vr_Ptr *) 0;",
 	"Vr_Ptr *ranges = (Vr_Ptr *) 0;",
@@ -800,7 +801,7 @@ static char *Tail[] = {
 	"}",
 	"}",
 	"",
 	"",
 	"void",
 	"void",
-	"dumpval(unsigned char X[], int range)",
+	"dumpval(uchar X[], int range)",
 	"{	int w, x, i, j = -1;",
 	"{	int w, x, i, j = -1;",
 	"",
 	"",
 	"	for (w = i = 0; w < range; w++)",
 	"	for (w = i = 0; w < range; w++)",

+ 22 - 18
sys/src/cmd/spin/pangen3.c

@@ -1,14 +1,13 @@
 /***** spin: pangen3.c *****/
 /***** spin: pangen3.c *****/
 
 
-/* Copyright (c) 1991-2000 by Lucent Technologies - Bell Laboratories     */
+/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories.     */
 /* All Rights Reserved.  This software is for educational purposes only.  */
 /* All Rights Reserved.  This software is for educational purposes only.  */
-/* Permission is given to distribute this code provided that this intro-  */
-/* ductory message is not removed and no monies are exchanged.            */
-/* No guarantee is expressed or implied by the distribution of this code. */
-/* Software written by Gerard J. Holzmann as part of the book:            */
-/* `Design and Validation of Computer Protocols,' ISBN 0-13-539925-4,     */
-/* Prentice Hall, Englewood Cliffs, NJ, 07632.                            */
-/* Send bug-reports and/or questions to: gerard@research.bell-labs.com    */
+/* No guarantee whatsoever is expressed or implied by the distribution of */
+/* this code.  Permission is given to distribute this code provided that  */
+/* this introductory message is not removed and no monies are exchanged.  */
+/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
+/*             http://spinroot.com/                                       */
+/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
 
 
 #include "spin.h"
 #include "spin.h"
 #ifdef PC
 #ifdef PC
@@ -109,7 +108,7 @@ putsrc(Element *e)	/* match states to source lines */
 		if (tmp->st == m)
 		if (tmp->st == m)
 		{	if (tmp->ln != n || tmp->fn != e->n->fn)
 		{	if (tmp->ln != n || tmp->fn != e->n->fn)
 			printf("putsrc mismatch %d - %d, file %s\n", n,
 			printf("putsrc mismatch %d - %d, file %s\n", n,
-				tmp->ln, tmp->fn);
+				tmp->ln, tmp->fn->name);
 			return;
 			return;
 		}
 		}
 	tmp = (SRC *) emalloc(sizeof(SRC));
 	tmp = (SRC *) emalloc(sizeof(SRC));
@@ -160,12 +159,6 @@ dumpsrc(int n, int m)
 		for (tmp = frst; tmp; lst = tmp, tmp = tmp->nxt)
 		for (tmp = frst; tmp; lst = tmp, tmp = tmp->nxt)
 			if (tmp->st == j)
 			if (tmp->st == j)
 			{	putnr(tmp->ln);
 			{	putnr(tmp->ln);
-#if 0
-				if (lst)
-					lst->nxt = tmp->nxt;
-				else
-					frst = tmp->nxt;
-#endif
 				break;
 				break;
 			}
 			}
 		if (!tmp)
 		if (!tmp)
@@ -321,9 +314,13 @@ comwork(FILE *fd, Lextok *now, int m)
 	case 'c':	Cat3("(", now->lft, ")");
 	case 'c':	Cat3("(", now->lft, ")");
 			break;
 			break;
 
 
-	case '?':	Cat3("( (", now->lft, ") -> ");
-			Cat3("(", now->rgt->lft, ") : ");
-			Cat3("(", now->rgt->rgt, ") )");
+	case '?':	if (now->lft)
+			{	Cat3("( (", now->lft, ") -> ");
+			}
+			if (now->rgt)
+			{	Cat3("(", now->rgt->lft, ") : ");
+				Cat3("(", now->rgt->rgt, ") )");
+			}
 			break;	
 			break;	
 
 
 	case ASGN:	comwork(fd,now->lft,m);
 	case ASGN:	comwork(fd,now->lft,m);
@@ -351,12 +348,19 @@ comwork(FILE *fd, Lextok *now, int m)
 			}
 			}
 			fprintf(fd, ")");
 			fprintf(fd, ")");
 			break;
 			break;
+	case PRINTM:	fprintf(fd, "printm(");
+			comwork(fd, now->lft, m);
+			fprintf(fd, ")");
+			break;
 	case NAME:	putname(fd, "", now, m, "");
 	case NAME:	putname(fd, "", now, m, "");
 			break;
 			break;
 	case   'p':	putremote(fd, now, m);
 	case   'p':	putremote(fd, now, m);
 			break;
 			break;
 	case   'q':	fprintf(fd, "%s", now->sym->name);
 	case   'q':	fprintf(fd, "%s", now->sym->name);
 			break;
 			break;
+	case C_EXPR:	
+	case C_CODE:	fprintf(fd, "{%s}", now->sym->name);
+			break;
 	case ASSERT:	Cat3("assert(", now->lft, ")");
 	case ASSERT:	Cat3("assert(", now->lft, ")");
 			break;
 			break;
 	case   '.':	fprintf(fd, ".(goto)"); break;
 	case   '.':	fprintf(fd, ".(goto)"); break;

+ 106 - 85
sys/src/cmd/spin/pangen3.h

@@ -1,16 +1,18 @@
 /***** spin: pangen3.h *****/
 /***** spin: pangen3.h *****/
 
 
-/* Copyright (c) 1991-2000 by Lucent Technologies - Bell Laboratories     */
+/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories.     */
 /* All Rights Reserved.  This software is for educational purposes only.  */
 /* All Rights Reserved.  This software is for educational purposes only.  */
-/* Permission is given to distribute this code provided that this intro-  */
-/* ductory message is not removed and no monies are exchanged.            */
-/* No guarantee is expressed or implied by the distribution of this code. */
-/* Software written by Gerard J. Holzmann as part of the book:            */
-/* `Design and Validation of Computer Protocols,' ISBN 0-13-539925-4,     */
-/* Prentice Hall, Englewood Cliffs, NJ, 07632.                            */
-/* Send bug-reports and/or questions to: gerard@research.bell-labs.com    */
+/* No guarantee whatsoever is expressed or implied by the distribution of */
+/* this code.  Permission is given to distribute this code provided that  */
+/* this introductory message is not removed and no monies are exchanged.  */
+/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
+/*             http://spinroot.com/                                       */
+/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
 
 
 static char *Head0[] = {
 static char *Head0[] = {
+	"#if defined(BFS) && defined(REACH)",
+	"#undef REACH",	/* redundant with bfs */
+	"#endif",
 	"#ifdef VERI",
 	"#ifdef VERI",
 		"#define BASE	1",
 		"#define BASE	1",
 	"#else",
 	"#else",
@@ -18,7 +20,6 @@ static char *Head0[] = {
 	"#endif",
 	"#endif",
 	"typedef struct Trans {",
 	"typedef struct Trans {",
 	"	short atom;	/* if &2 = atomic trans; if &8 local */",
 	"	short atom;	/* if &2 = atomic trans; if &8 local */",
-	"	short st;	/* the nextstate */",
 	"#ifdef HAS_UNLESS",
 	"#ifdef HAS_UNLESS",
 	"	short escp[HAS_UNLESS];	/* lists the escape states */",
 	"	short escp[HAS_UNLESS];	/* lists the escape states */",
 	"	short e_trans;	/* if set, this is an escp-trans */",
 	"	short e_trans;	/* if set, this is an escp-trans */",
@@ -30,6 +31,7 @@ static char *Head0[] = {
 	"	short om;	/* completion status of preselects */",
 	"	short om;	/* completion status of preselects */",
 	"#endif",
 	"#endif",
 	"	char *tp;	/* src txt of statement */",
 	"	char *tp;	/* src txt of statement */",
+	"	int st;		/* the nextstate */",
 	"	int t_id;	/* transition id, unique within proc */",
 	"	int t_id;	/* transition id, unique within proc */",
 	"	int forw;	/* index forward transition */",
 	"	int forw;	/* index forward transition */",
 	"	int back;	/* index return  transition */",
 	"	int back;	/* index return  transition */",
@@ -49,8 +51,12 @@ static char *Head0[] = {
 
 
 static char *Header[] = {
 static char *Header[] = {
 	"#ifdef VERBOSE",
 	"#ifdef VERBOSE",
+		"#ifndef CHECK",
 		"#define CHECK",
 		"#define CHECK",
+		"#endif",
+		"#ifndef DEBUG",
 		"#define DEBUG",
 		"#define DEBUG",
+		"#endif",
 	"#endif",
 	"#endif",
 	"#ifdef SAFETY",
 	"#ifdef SAFETY",
 		"#ifndef NOFAIR",
 		"#ifndef NOFAIR",
@@ -58,7 +64,9 @@ static char *Header[] = {
 		"#endif",
 		"#endif",
 	"#endif",
 	"#endif",
 	"#ifdef NOREDUCE",
 	"#ifdef NOREDUCE",
+		"#ifndef XUSAFE",
 		"#define XUSAFE",
 		"#define XUSAFE",
+		"#endif",
 		"#if !defined(SAFETY) && !defined(MA)",
 		"#if !defined(SAFETY) && !defined(MA)",
 			"#define FULLSTACK",
 			"#define FULLSTACK",
 		"#endif",
 		"#endif",
@@ -74,25 +82,20 @@ static char *Header[] = {
 		"#endif",
 		"#endif",
 	"#endif",
 	"#endif",
 	"#ifdef BITSTATE",
 	"#ifdef BITSTATE",
+		"#ifndef NOCOMP",
 		"#define NOCOMP",
 		"#define NOCOMP",
+		"#endif",
 		"#if !defined(LC) && defined(SC)",
 		"#if !defined(LC) && defined(SC)",
 		"#define LC",
 		"#define LC",
 		"#endif",
 		"#endif",
 	"#endif",
 	"#endif",
-	"#ifndef MEMCNT",
-		"#ifdef PC",
-		"#define MEMCNT	25	/* 32 Mb */",
-		"#else",
-		"#define MEMCNT	28",
-		"#endif",
-	"#endif",
-
 	"#if defined(COLLAPSE2) || defined(COLLAPSE3) || defined(COLLAPSE4)",
 	"#if defined(COLLAPSE2) || defined(COLLAPSE3) || defined(COLLAPSE4)",
 		"/* accept the above for backward compatibility */",
 		"/* accept the above for backward compatibility */",
 		"#define COLLAPSE",
 		"#define COLLAPSE",
 	"#endif",
 	"#endif",
 	"#ifdef HC",
 	"#ifdef HC",
-	"#define HC2",
+	"#undef HC",
+	"#define HC4",
 	"#endif",
 	"#endif",
 	"#ifdef HC0",	/* 32 bits */
 	"#ifdef HC0",	/* 32 bits */
 	"#define HC	0",
 	"#define HC	0",
@@ -147,12 +150,16 @@ static char *Header[] = {
 	"#if SYNC",
 	"#if SYNC",
 	"	short o_boq;",
 	"	short o_boq;",
 	"#endif",
 	"#endif",
+	0,
+};
+
+static char *Header0[] = {
 	"	char *body;",
 	"	char *body;",
 	"	struct Svtack *nxt;",
 	"	struct Svtack *nxt;",
 	"	struct Svtack *lst;",
 	"	struct Svtack *lst;",
 	"} Svtack;\n",
 	"} Svtack;\n",
 	"Trans ***trans;	/* 1 ptr per state per proctype */\n",
 	"Trans ***trans;	/* 1 ptr per state per proctype */\n",
-	"#if defined(FULLSTACK)",
+	"#if defined(FULLSTACK) || defined(BFS)",
 	"struct H_el *Lstate;",
 	"struct H_el *Lstate;",
 	"#endif",
 	"#endif",
 	"int depthfound = -1;	/* loop detection */",
 	"int depthfound = -1;	/* loop detection */",
@@ -216,7 +223,10 @@ static char *Head1[] = {
 
 
 static char *Addp0[] = {
 static char *Addp0[] = {
 	/* addproc(....parlist... */ ")",
 	/* addproc(....parlist... */ ")",
-	"{	int k, j, h = now._nr_pr;",
+	"{	int j, h = now._nr_pr;",
+	"#ifndef NOCOMP",
+	"	int k;",
+	"#endif",
 	"	uchar *o_this = this;\n",
 	"	uchar *o_this = this;\n",
 	"#ifndef INLINE",
 	"#ifndef INLINE",
 	"	if (TstOnly) return (h < MAXPROC);",
 	"	if (TstOnly) return (h < MAXPROC);",
@@ -258,12 +268,12 @@ static char *Addp1[] = {
 	"#endif",
 	"#endif",
 	"	now._nr_pr += 1;",
 	"	now._nr_pr += 1;",
 	"	if (fairness && ((int) now._nr_pr + 1 >= (8*NFAIR)/2))",
 	"	if (fairness && ((int) now._nr_pr + 1 >= (8*NFAIR)/2))",
-	"	{	printf(\"Error: too many processes -- current\");",
+	"	{	printf(\"pan: error: too many processes -- current\");",
 	"		printf(\" max is %%d procs (-DNFAIR=%%d)\\n\",",
 	"		printf(\" max is %%d procs (-DNFAIR=%%d)\\n\",",
 	"			(8*NFAIR)/2 - 2, NFAIR);",
 	"			(8*NFAIR)/2 - 2, NFAIR);",
 	"		printf(\"\\trecompile with -DNFAIR=%%d\\n\",",
 	"		printf(\"\\trecompile with -DNFAIR=%%d\\n\",",
 	"			NFAIR+1);",
 	"			NFAIR+1);",
-	"		exit(1);",
+	"		pan_exit(1);",
 	"	}",
 	"	}",
 
 
 	"	vsize += j;",
 	"	vsize += j;",
@@ -294,7 +304,10 @@ static char *Addp1[] = {
 static char *Addq0[] = {
 static char *Addq0[] = {
 	"int",
 	"int",
 	"addqueue(int n, int is_rv)",
 	"addqueue(int n, int is_rv)",
-	"{	int j=0, i = now._nr_qs, k;\n",
+	"{	int j=0, i = now._nr_qs;",
+	"#ifndef NOCOMP",
+	"	int k;",
+	"#endif",
 	"	if (i >= MAXQ)",
 	"	if (i >= MAXQ)",
 	"		Uerror(\"too many queues\");",
 	"		Uerror(\"too many queues\");",
 	"	switch (n) {",
 	"	switch (n) {",
@@ -309,9 +322,12 @@ static char *Addq1[] = {
 	"	else",
 	"	else",
 	"		q_skip[i] = 0;",
 	"		q_skip[i] = 0;",
 	"#ifndef NOCOMP",
 	"#ifndef NOCOMP",
-	"	k = vsize; if (is_rv) k += j;",
+	"	k = vsize;",
+	"#ifndef BFS",
+	"	if (is_rv) k += j;",
+	"#endif",
 	"	for (k += q_skip[i]; k > vsize; k--)",
 	"	for (k += q_skip[i]; k > vsize; k--)",
-	"		Mask[k-1] = 1; /* align */",
+	"		Mask[k-1] = 1;",
 	"#endif",
 	"#endif",
 	"	vsize += q_skip[i];",
 	"	vsize += q_skip[i];",
 	"	q_offset[i] = vsize;",
 	"	q_offset[i] = vsize;",
@@ -331,7 +347,10 @@ static char *Addq1[] = {
 };
 };
 
 
 static char *Addq11[] = {
 static char *Addq11[] = {
-	"{	int j, k; uchar *z;\n",
+	"{	int j; uchar *z;\n",
+	"#ifdef HAS_SORTED",
+	"	int k;",
+	"#endif",
 	"	if (!into--)",
 	"	if (!into--)",
 	"	uerror(\"ref to uninitialized chan name (sending)\");",
 	"	uerror(\"ref to uninitialized chan name (sending)\");",
 	"	if (into >= (int) now._nr_qs || into < 0)",
 	"	if (into >= (int) now._nr_qs || into < 0)",
@@ -350,12 +369,15 @@ static char *Addq2[] = {
 	"	if (in_s_scope(into+1))",
 	"	if (in_s_scope(into+1))",
 	"		require('s', into);",
 	"		require('s', into);",
 	"#endif",
 	"#endif",
-	"}\n",
+	"}",
+	"#endif\n",
 	"#if SYNC",
 	"#if SYNC",
 	"int",
 	"int",
 	"q_zero(int from)",
 	"q_zero(int from)",
 	"{	if (!from--)",
 	"{	if (!from--)",
-	"	uerror(\"ref to uninitialized chan name (q_zero)\");",
+	"	{	uerror(\"ref to uninitialized chan name (q_zero)\");",
+	"		return 0;",
+	"	}",
 	"	switch(((Q0 *)qptr(from))->_t) {",
 	"	switch(((Q0 *)qptr(from))->_t) {",
 	0,
 	0,
 };
 };
@@ -364,6 +386,7 @@ static char *Addq3[] = {
 	"	case 0: printf(\"queue %%d was deleted\\n\", from+1);",
 	"	case 0: printf(\"queue %%d was deleted\\n\", from+1);",
 	"	}",
 	"	}",
 	"	Uerror(\"bad queue q-zero\");",
 	"	Uerror(\"bad queue q-zero\");",
+	"	return -1;",
 	"}",
 	"}",
 	"int",
 	"int",
 	"not_RV(int from)",
 	"not_RV(int from)",
@@ -407,8 +430,10 @@ static char *Addq3[] = {
 	"	{	printf(\"pan: xs assertion violated: \");",
 	"	{	printf(\"pan: xs assertion violated: \");",
 	"		printf(\"access to chan <%%s> (%%d)\\npan: by \",",
 	"		printf(\"access to chan <%%s> (%%d)\\npan: by \",",
 	"			q_name[x], x-1);",
 	"			q_name[x], x-1);",
-	"		printf(\"%%s (proc %%d) and by %%s (proc %%d)\\n\",",
-	"			p_name[q_sender[x]-1], q_sender[x]-1,",
+	"		if (q_sender[x] > 0 && p_name[q_sender[x]-1])",
+	"			printf(\"%%s (proc %%d) and by \",",
+	"			p_name[q_sender[x]-1], q_sender[x]-1);",
+	"		printf(\"%%s (proc %%d)\\n\",",
 	"			p_name[who], who);",
 	"			p_name[who], who);",
 	"		uerror(\"error, partial order reduction invalid\");",
 	"		uerror(\"error, partial order reduction invalid\");",
 	"	}",
 	"	}",
@@ -431,11 +456,12 @@ static char *Addq3[] = {
 	"	} else",
 	"	} else",
 	"	if (q_recver[x] != who+1)",
 	"	if (q_recver[x] != who+1)",
 	"	{	printf(\"pan: xr assertion violated: \");",
 	"	{	printf(\"pan: xr assertion violated: \");",
-	"		printf(\"access to chan %%s (%%d)\\n\",",
+	"		printf(\"access to chan %%s (%%d)\\npan: \",",
 	"			q_name[x], x-1);",
 	"			q_name[x], x-1);",
-	"		printf(\"pan: by %%s (proc %%d) \",",
+	"		if (q_recver[x] > 0 && p_name[q_recver[x]-1])",
+	"			printf(\"by %%s (proc %%d) and \",",
 	"			p_name[q_recver[x]-1], q_recver[x]-1);",
 	"			p_name[q_recver[x]-1], q_recver[x]-1);",
-	"		printf(\"and by %%s (proc %%d)\\n\",",
+	"		printf(\"by %%s (proc %%d)\\n\",",
 	"			p_name[who], who);",
 	"			p_name[who], who);",
 	"		uerror(\"error, partial order reduction invalid\");",
 	"		uerror(\"error, partial order reduction invalid\");",
 	"	}",
 	"	}",
@@ -469,6 +495,7 @@ static char *Addq4[] = {
 	"	return !q_len(from) || q_full(from);",
 	"	return !q_len(from) || q_full(from);",
 	"}",
 	"}",
 	"#endif",
 	"#endif",
+	"#if NQS>0",
 	"int",
 	"int",
 	"qrecv(int from, int slot, int fld, int done)",
 	"qrecv(int from, int slot, int fld, int done)",
 	"{	uchar *z;",
 	"{	uchar *z;",
@@ -491,12 +518,13 @@ static char *Addq5[] = {
 	"	default: Uerror(\"bad queue - qrecv\");",
 	"	default: Uerror(\"bad queue - qrecv\");",
 	"	}",
 	"	}",
 	"	return r;",
 	"	return r;",
-	"}\n",
+	"}",
+	"#endif\n",
 	"#ifndef BITSTATE",
 	"#ifndef BITSTATE",
 	"#ifdef COLLAPSE",
 	"#ifdef COLLAPSE",
 	"long",
 	"long",
 	"col_q(int i, char *z)",
 	"col_q(int i, char *z)",
-	"{	int j, k;",
+	"{	int j=0, k;",
 	"	char *x, *y;",
 	"	char *x, *y;",
 	"	Q0 *ptr = (Q0 *) qptr(i);",
 	"	Q0 *ptr = (Q0 *) qptr(i);",
 	"	switch (ptr->_t) {",
 	"	switch (ptr->_t) {",
@@ -506,7 +534,7 @@ static char *Addq5[] = {
 static char *Code0[] = {
 static char *Code0[] = {
 	"void",
 	"void",
 	"run(void)",
 	"run(void)",
-	"{	int i;",
+	"{	/* int i; */",
 	"	memset((char *)&now, 0, sizeof(State));",
 	"	memset((char *)&now, 0, sizeof(State));",
 	"	vsize = sizeof(State) - VECTORSZ;",
 	"	vsize = sizeof(State) - VECTORSZ;",
 	"#ifndef NOVSZ",
 	"#ifndef NOVSZ",
@@ -528,6 +556,10 @@ static char *R0[] = {
 	"	progstate[%d] = (uchar *) emalloc(nstates%d);",
 	"	progstate[%d] = (uchar *) emalloc(nstates%d);",
 	"	stopstate[%d] = (uchar *) emalloc(nstates%d);",
 	"	stopstate[%d] = (uchar *) emalloc(nstates%d);",
 	"	visstate[%d] = (uchar *) emalloc(nstates%d);",
 	"	visstate[%d] = (uchar *) emalloc(nstates%d);",
+	"	mapstate[%d] = (short *) emalloc(nstates%d * sizeof(short));",
+	"#ifdef HAS_CODE",
+	"	NrStates[%d] = nstates%d;",
+	"#endif",
 	"	stopstate[%d][endstate%d] = 1;",
 	"	stopstate[%d][endstate%d] = 1;",
 	0,
 	0,
 };
 };
@@ -547,7 +579,7 @@ static char *R0b[] = {
 	"	  printf(\"      stmnt executed in each merge sequence is shown\\n\");",
 	"	  printf(\"      stmnt executed in each merge sequence is shown\\n\");",
 	"	  printf(\"      (use spin -a -o3 to disable statement merging)\\n\");",
 	"	  printf(\"      (use spin -a -o3 to disable statement merging)\\n\");",
 	"#endif",
 	"#endif",
-	"	  exit(0);",
+	"	  pan_exit(0);",
 	"	}",
 	"	}",
 	0,
 	0,
 };
 };
@@ -572,6 +604,10 @@ static char *R2[] = {
 	"uchar *reached[%d];",
 	"uchar *reached[%d];",
 	"uchar *stopstate[%d];",
 	"uchar *stopstate[%d];",
 	"uchar *visstate[%d];",
 	"uchar *visstate[%d];",
+	"short *mapstate[%d];",
+	"#ifdef HAS_CODE",
+	"int NrStates[%d];",
+	"#endif",
 	0,
 	0,
 };
 };
 static char *R3[] = {
 static char *R3[] = {
@@ -619,13 +655,12 @@ static char *R8a[] = {
 
 
 	"	for ( ; j > 0; j--, y++)",
 	"	for ( ; j > 0; j--, y++)",
 	"		if (!Mask[k++]) *x++ = *y;",
 	"		if (!Mask[k++]) *x++ = *y;",
-	"	if (z) return (long) (x - z);",
 
 
 	"	for (j = 0; j < WS-1; j++)",
 	"	for (j = 0; j < WS-1; j++)",
 	"		*x++ = 0;",
 	"		*x++ = 0;",
 	"	x -= j;",
 	"	x -= j;",
-
-	"	return ordinal(scratch, x-scratch, 2+ptr->_t);",
+	"	if (z) return (long) (x - z);",
+	"	return ordinal(scratch, x-scratch, (short) (2+ptr->_t));",
 	"}",
 	"}",
 	"#endif",
 	"#endif",
 	"#endif",
 	"#endif",
@@ -642,30 +677,18 @@ static char *R8b[] = {
 
 
 	"	for ( ; j > 0; j--, y++)",
 	"	for ( ; j > 0; j--, y++)",
 	"		if (!Mask[k++]) *x++ = *y;",
 	"		if (!Mask[k++]) *x++ = *y;",
-	"	if (z) return (long) (x - z);",
 
 
 	"	for (j = 0; j < WS-1; j++)",
 	"	for (j = 0; j < WS-1; j++)",
 	"		*x++ = 0;",
 	"		*x++ = 0;",
 	"	x -= j;",
 	"	x -= j;",
+	"	if (z) return (long) (x - z);",
 	"	return ordinal(scratch, x-scratch, 1); /* chan */",
 	"	return ordinal(scratch, x-scratch, 1); /* chan */",
 	"}",
 	"}",
 	"#endif",
 	"#endif",
 	"#endif",
 	"#endif",
 	0,
 	0,
 };
 };
-static char *R9[] = {
-	"typedef struct Q%d {",
-	"	uchar Qlen;	/* q_size */",
-	"	uchar _t;	/* q_type */",
-	"	struct {",
-	0,
-};
-static char *R10[] = {
-	"typedef struct Q0 {\t/* generic q */",
-	"	uchar Qlen, _t;",
-	"} Q0;",
-	0,
-};
+
 static char *R12[] = {
 static char *R12[] = {
 	"\t\tcase %d: r = ((Q%d *)z)->contents[slot].fld%d; break;",
 	"\t\tcase %d: r = ((Q%d *)z)->contents[slot].fld%d; break;",
 	0,
 	0,
@@ -673,7 +696,10 @@ static char *R12[] = {
 char *R13[] = {
 char *R13[] = {
 	"int ",
 	"int ",
 	"unsend(int into)",
 	"unsend(int into)",
-	"{	int m=0, j, k; uchar *z;\n",
+	"{	int _m=0, j; uchar *z;\n",
+	"#ifdef HAS_SORTED",
+	"	int k;",
+	"#endif",
 	"	if (!into--)",
 	"	if (!into--)",
 	"		uerror(\"ref to uninitialized chan (unsend)\");",
 	"		uerror(\"ref to uninitialized chan (unsend)\");",
 	"	z = qptr(into);",
 	"	z = qptr(into);",
@@ -685,7 +711,7 @@ char *R13[] = {
 char *R14[] = {
 char *R14[] = {
 	"	default: Uerror(\"bad queue - unsend\");",
 	"	default: Uerror(\"bad queue - unsend\");",
 	"	}",
 	"	}",
-	"	return m;",
+	"	return _m;",
 	"}\n",
 	"}\n",
 	"void",
 	"void",
 	"unrecv(int from, int slot, int fld, int fldvar, int strt)",
 	"unrecv(int from, int slot, int fld, int fldvar, int strt)",
@@ -714,13 +740,13 @@ static char *Proto[] = {
 	"int addqueue(int, int);",
 	"int addqueue(int, int);",
 	"/* int atoi(char *); */",
 	"/* int atoi(char *); */",
 	"int close(int);",
 	"int close(int);",
-#ifndef PC
+"#ifndef SC",
 	"int creat(char *, unsigned short);",
 	"int creat(char *, unsigned short);",
 	"int write(int, void *, unsigned);",
 	"int write(int, void *, unsigned);",
-#endif
+"#endif",
 	"int delproc(int, int);",
 	"int delproc(int, int);",
 	"int endstate(void);",
 	"int endstate(void);",
-	"int hstore(char *, int, short);",
+	"int hstore(char *, int);",
 "#ifdef MA",
 "#ifdef MA",
 	"int gstore(char *, int, uchar);",
 	"int gstore(char *, int, uchar);",
 "#endif",
 "#endif",
@@ -730,17 +756,23 @@ static char *Proto[] = {
 	"int q_zero(int);",
 	"int q_zero(int);",
 	"int qrecv(int, int, int, int);",
 	"int qrecv(int, int, int, int);",
 	"int unsend(int);",
 	"int unsend(int);",
-	"void *sbrk(int);",
+	"/* void *sbrk(int); */",
 	"void Uerror(char *);",
 	"void Uerror(char *);",
 	"void assert(int, char *, int, int, Trans *);",
 	"void assert(int, char *, int, int, Trans *);",
+	"void c_chandump(int);",
+	"void c_globals(void);",
+	"void c_locals(int, int);",
 	"void checkcycles(void);",
 	"void checkcycles(void);",
 	"void crack(int, int, Trans *, short *);",
 	"void crack(int, int, Trans *, short *);",
 	"void d_hash(uchar *, int);",
 	"void d_hash(uchar *, int);",
+	"void s_hash(uchar *, int);",
+	"void r_hash(uchar *, int);",
 	"void delq(int);",
 	"void delq(int);",
 	"void do_reach(void);",
 	"void do_reach(void);",
+	"void pan_exit(int);",
 	"void exit(int);",
 	"void exit(int);",
 	"void hinit(void);",
 	"void hinit(void);",
-	"void imed(Trans *, int, int);",
+	"void imed(Trans *, int, int, int);",
 	"void new_state(void);",
 	"void new_state(void);",
 	"void p_restor(int);",
 	"void p_restor(int);",
 	"void putpeg(int, int);",
 	"void putpeg(int, int);",
@@ -750,13 +782,12 @@ static char *Proto[] = {
 	"void settable(void);",
 	"void settable(void);",
 	"void setq_claim(int, int, char *, int, char *);",
 	"void setq_claim(int, int, char *, int, char *);",
 	"void sv_restor(void);",
 	"void sv_restor(void);",
-	"void sv_save(char *);",
+	"void sv_save(void);",
 	"void tagtable(int, int, int, short *, uchar *);",
 	"void tagtable(int, int, int, short *, uchar *);",
 	"void uerror(char *);",
 	"void uerror(char *);",
 	"void unrecv(int, int, int, int, int);",
 	"void unrecv(int, int, int, int, int);",
 	"void usage(FILE *);",
 	"void usage(FILE *);",
 	"void wrap_stats(void);",
 	"void wrap_stats(void);",
-	"void xrefsrc(int, S_F_MAP *, int, int);",
 	"#if defined(FULLSTACK) && defined(BITSTATE)",
 	"#if defined(FULLSTACK) && defined(BITSTATE)",
 	"int  onstack_now(void);",
 	"int  onstack_now(void);",
 	"void onstack_init(void);",
 	"void onstack_init(void);",
@@ -776,32 +807,23 @@ static char *Proto[] = {
 static char *SvMap[] = {
 static char *SvMap[] = {
 	"void",
 	"void",
 	"to_compile(void)",
 	"to_compile(void)",
-	"{	char ctd[1024], carg[64]; int n;",
+	"{	char ctd[1024], carg[64];",
 	"#ifdef BITSTATE",
 	"#ifdef BITSTATE",
 	"	strcpy(ctd, \"-DBITSTATE \");",
 	"	strcpy(ctd, \"-DBITSTATE \");",
 	"#else",
 	"#else",
 	"	strcpy(ctd, \"\");",
 	"	strcpy(ctd, \"\");",
 	"#endif",
 	"#endif",
-	"#ifdef PC",
-	"	strcat(ctd, \"-DPC \");",
-	"#endif",
 	"#ifdef NOVSZ",
 	"#ifdef NOVSZ",
 	"	strcat(ctd, \"-DNOVSZ \");",
 	"	strcat(ctd, \"-DNOVSZ \");",
 	"#endif",
 	"#endif",
-	"#ifdef MEMCNT",
-		"#ifdef PC",
-		"	n = 25;",
-		"#else",
-		"	n = 28;",
-		"#endif",
-	"	if (MEMCNT != n)",
-	"	{	sprintf(carg, \"-DMEMCNT=%%d \", MEMCNT);",
-	"		strcat(ctd, carg);",
-	"	}",
-	"#endif",
 	"#ifdef MEMLIM",
 	"#ifdef MEMLIM",
 	"	sprintf(carg, \"-DMEMLIM=%%d \", MEMLIM);",
 	"	sprintf(carg, \"-DMEMLIM=%%d \", MEMLIM);",
 	"	strcat(ctd, carg);",
 	"	strcat(ctd, carg);",
+	"#else",
+	"#ifdef MEMCNT",
+	"	sprintf(carg, \"-DMEMCNT=%%d \", MEMCNT);",
+	"	strcat(ctd, carg);",
+	"#endif",
 	"#endif",
 	"#endif",
 	"#ifdef NOCLAIM",
 	"#ifdef NOCLAIM",
 	"	strcat(ctd, \"-DNOCLAIM \");",
 	"	strcat(ctd, \"-DNOCLAIM \");",
@@ -878,6 +900,10 @@ static char *SvMap[] = {
 	"#ifdef COLLAPSE",
 	"#ifdef COLLAPSE",
 	"	strcat(ctd, \"-DCOLLAPSE \");",
 	"	strcat(ctd, \"-DCOLLAPSE \");",
 	"#endif",
 	"#endif",
+	"#ifdef MA",
+	"	sprintf(carg, \"-DMA=%%d \", MA);",
+	"	strcat(ctd, carg);",
+	"#endif",
 	"#ifdef SVDUMP",
 	"#ifdef SVDUMP",
 	"	strcat(ctd, \"-DSVDUMP \");",
 	"	strcat(ctd, \"-DSVDUMP \");",
 	"#endif",
 	"#endif",
@@ -897,14 +923,9 @@ static char *SvMap[] = {
 	"	strcat(ctd, \"-DSDUMP \");",
 	"	strcat(ctd, \"-DSDUMP \");",
 	"#endif",
 	"#endif",
 	"#ifdef COVEST",
 	"#ifdef COVEST",
-	"		strcat(ctd, \"-DCOVEST \");",
-	"#endif",
-	"		printf(\"Compiled as: cc -o pan %%span.c\", ctd);",
-	"#if defined(COVEST) && defined(BITSTATE)",
-	"		printf(\" -lm\\n\");",
-	"#else",
-	"		printf(\"\\n\");",
+	"	strcat(ctd, \"-DCOVEST \");",
 	"#endif",
 	"#endif",
+	"	printf(\"Compiled as: cc -o pan %%span.c\\n\", ctd);",
 	"}",
 	"}",
 	0,
 	0,
 };
 };

+ 42 - 37
sys/src/cmd/spin/pangen4.c

@@ -1,14 +1,13 @@
 /***** spin: pangen4.c *****/
 /***** spin: pangen4.c *****/
 
 
-/* Copyright (c) 1991-2000 by Lucent Technologies - Bell Laboratories     */
+/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories.     */
 /* All Rights Reserved.  This software is for educational purposes only.  */
 /* All Rights Reserved.  This software is for educational purposes only.  */
-/* Permission is given to distribute this code provided that this intro-  */
-/* ductory message is not removed and no monies are exchanged.            */
-/* No guarantee is expressed or implied by the distribution of this code. */
-/* Software written by Gerard J. Holzmann as part of the book:            */
-/* `Design and Validation of Computer Protocols,' ISBN 0-13-539925-4,     */
-/* Prentice Hall, Englewood Cliffs, NJ, 07632.                            */
-/* Send bug-reports and/or questions to: gerard@research.bell-labs.com    */
+/* No guarantee whatsoever is expressed or implied by the distribution of */
+/* this code.  Permission is given to distribute this code provided that  */
+/* this introductory message is not removed and no monies are exchanged.  */
+/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
+/*             http://spinroot.com/                                       */
+/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
 
 
 #include "spin.h"
 #include "spin.h"
 #ifdef PC
 #ifdef PC
@@ -18,16 +17,13 @@
 #endif
 #endif
 
 
 extern FILE	*tc, *tb;
 extern FILE	*tc, *tb;
-extern ProcList	*cur_proc;
 extern Queue	*qtab;
 extern Queue	*qtab;
 extern Symbol	*Fname;
 extern Symbol	*Fname;
-extern int	lineno, m_loss, Pid, eventmapnr, verbose, multi_oval;
-extern short	terse, nocast, has_provided, has_sorted;
-extern short	evalindex, withprocname, _isok;
+extern int	lineno, m_loss, Pid, eventmapnr, multi_oval;
+extern short	nocast, has_provided, has_sorted;
 extern char	*R13[], *R14[], *R15[];
 extern char	*R13[], *R14[], *R15[];
 
 
 static void	check_proc(Lextok *, int);
 static void	check_proc(Lextok *, int);
-extern int	dolocal(FILE *, char *, int, int, char *, char *);
 
 
 void
 void
 undostmnt(Lextok *now, int m)
 undostmnt(Lextok *now, int m)
@@ -52,9 +48,10 @@ undostmnt(Lextok *now, int m)
 	case FULL:	case EMPTY:	case 'R':
 	case FULL:	case EMPTY:	case 'R':
 	case NFULL:	case NEMPTY:	case ENABLED:
 	case NFULL:	case NEMPTY:	case ENABLED:
 	case '?':	case PC_VAL:	case '^':
 	case '?':	case PC_VAL:	case '^':
+	case C_EXPR:
 	case NONPROGRESS:
 	case NONPROGRESS:
-			putstmnt(tb, now, m);
-			break;
+		putstmnt(tb, now, m);
+		break;
 
 
 	case RUN:
 	case RUN:
 		fprintf(tb, "delproc(0, now._nr_pr-1)");
 		fprintf(tb, "delproc(0, now._nr_pr-1)");
@@ -64,12 +61,8 @@ undostmnt(Lextok *now, int m)
 		if (Pid == eventmapnr) break;
 		if (Pid == eventmapnr) break;
 
 
 		if (m_loss)
 		if (m_loss)
-		{	fprintf(tb, "if (m == 2) m = unsend");
-			putname(tb, "(", now->lft, m, ")");
-		} else
-		{	fprintf(tb, "m = unsend");
-			putname(tb, "(", now->lft, m, ")");
-		}
+			fprintf(tb, "if (_m == 2) ");
+		putname(tb, "_m = unsend(", now->lft, m, ")");
 		break;
 		break;
 
 
 	case 'r':
 	case 'r':
@@ -133,8 +126,11 @@ undostmnt(Lextok *now, int m)
 						jj++;
 						jj++;
 					break;
 					break;
 			}	}
 			}	}
-
 			jj = multi_oval - ii - 1;
 			jj = multi_oval - ii - 1;
+
+			if (now->val == 1 && multi_oval > 0)
+				jj++;	/* new 3.4.0 */
+
 			for (v = now->rgt, i = 0; v; v = v->rgt, i++)
 			for (v = now->rgt, i = 0; v; v = v->rgt, i++)
 			{	switch(v->lft->ntyp) {
 			{	switch(v->lft->ntyp) {
 				case CONST:
 				case CONST:
@@ -181,10 +177,16 @@ undostmnt(Lextok *now, int m)
 	case BREAK:
 	case BREAK:
 		break;
 		break;
 
 
+	case C_CODE:
+		fprintf(tb, "sv_restor();\n");
+		break;
+
 	case ASSERT:
 	case ASSERT:
 	case PRINT:
 	case PRINT:
 		check_proc(now, m);
 		check_proc(now, m);
 		break;
 		break;
+	case PRINTM:
+		break;
 
 
 	default:
 	default:
 		printf("spin: bad node type %d (.b)\n", now->ntyp);
 		printf("spin: bad node type %d (.b)\n", now->ntyp);
@@ -201,6 +203,7 @@ any_undo(Lextok *now)
 	case ASSERT:
 	case ASSERT:
 	case PRINT:	return any_oper(now, RUN);
 	case PRINT:	return any_oper(now, RUN);
 
 
+	case PRINTM:
 	case   '.':
 	case   '.':
 	case  GOTO:
 	case  GOTO:
 	case  ELSE:
 	case  ELSE:
@@ -240,29 +243,31 @@ genunio(void)
 	for (q = qtab; q; q = q->nxt)
 	for (q = qtab; q; q = q->nxt)
 	{	fprintf(tc, "\tcase %d:\n", q->qid);
 	{	fprintf(tc, "\tcase %d:\n", q->qid);
 
 
-	if (has_sorted)
-	{	sprintf(buf1, "((Q%d *)z)->contents", q->qid);
-		fprintf(tc, "\t\tj = trpt->bup.oval;\n");
-		fprintf(tc, "\t\tfor (k = j; k < ((Q%d *)z)->Qlen; k++)\n",
-			q->qid);
-		fprintf(tc, "\t\t{\n");
-		for (i = 0; i < q->nflds; i++)
-		fprintf(tc, "\t\t\t%s[k].fld%d = %s[k+1].fld%d;\n",
-			buf1, i, buf1, i);
-		fprintf(tc, "\t\t}\n");
-		fprintf(tc, "\t\tj = ((Q0 *)z)->Qlen;\n");
-	}
+		if (has_sorted)
+		{	sprintf(buf1, "((Q%d *)z)->contents", q->qid);
+			fprintf(tc, "#ifdef HAS_SORTED\n");
+			fprintf(tc, "\t\tj = trpt->ipt;\n");	/* ipt was bup.oval */
+			fprintf(tc, "#endif\n");
+			fprintf(tc, "\t\tfor (k = j; k < ((Q%d *)z)->Qlen; k++)\n",
+				q->qid);
+			fprintf(tc, "\t\t{\n");
+			for (i = 0; i < q->nflds; i++)
+			fprintf(tc, "\t\t\t%s[k].fld%d = %s[k+1].fld%d;\n",
+				buf1, i, buf1, i);
+			fprintf(tc, "\t\t}\n");
+			fprintf(tc, "\t\tj = ((Q0 *)z)->Qlen;\n");
+		}
 
 
 		sprintf(buf1, "((Q%d *)z)->contents[j].fld", q->qid);
 		sprintf(buf1, "((Q%d *)z)->contents[j].fld", q->qid);
 		for (i = 0; i < q->nflds; i++)
 		for (i = 0; i < q->nflds; i++)
 			fprintf(tc, "\t\t%s%d = 0;\n", buf1, i);
 			fprintf(tc, "\t\t%s%d = 0;\n", buf1, i);
 		if (q->nslots==0)
 		if (q->nslots==0)
 		{	/* check if rendezvous succeeded, 1 level down */
 		{	/* check if rendezvous succeeded, 1 level down */
-			fprintf(tc, "\t\tm = (trpt+1)->o_m;\n");
-			fprintf(tc, "\t\tif (m) (trpt-1)->o_pm |= 1;\n");
+			fprintf(tc, "\t\t_m = (trpt+1)->o_m;\n");
+			fprintf(tc, "\t\tif (_m) (trpt-1)->o_pm |= 1;\n");
 			fprintf(tc, "\t\tUnBlock;\n");
 			fprintf(tc, "\t\tUnBlock;\n");
 		} else
 		} else
-			fprintf(tc, "\t\tm = trpt->o_m;\n");
+			fprintf(tc, "\t\t_m = trpt->o_m;\n");
 
 
 		fprintf(tc, "\t\tbreak;\n");
 		fprintf(tc, "\t\tbreak;\n");
 	}
 	}

+ 19 - 19
sys/src/cmd/spin/pangen4.h

@@ -1,10 +1,13 @@
 /***** spin: pangen4.h *****/
 /***** spin: pangen4.h *****/
 
 
-/* Copyright (c) 1997-2000 by Lucent Technologies - Bell Laboratories.    */
+/* Copyright (c) 1997-2003 by Lucent Technologies, Bell Laboratories.     */
 /* All Rights Reserved.  This software is for educational purposes only.  */
 /* All Rights Reserved.  This software is for educational purposes only.  */
-/* Permission is given to distribute this code provided that this intro-  */
-/* ductory message is not removed and no monies are exchanged.            */
-/* No guarantee is expressed or implied by the distribution of this code. */
+/* No guarantee whatsoever is expressed or implied by the distribution of */
+/* this code.  Permission is given to distribute this code provided that  */
+/* this introductory message is not removed and no monies are exchanged.  */
+/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
+/*             http://spinroot.com/                                       */
+/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
 
 
 /* The DFA code below was written by Anuj Puri and Gerard J. Holzmann in  */
 /* The DFA code below was written by Anuj Puri and Gerard J. Holzmann in  */
 /* May 1997, and was inspired by earlier work on data compression using   */
 /* May 1997, and was inspired by earlier work on data compression using   */
@@ -29,7 +32,7 @@ static char *Dfa[] = {
 	"",
 	"",
 	"extern char	*emalloc(unsigned long);	/* imported routine  */",
 	"extern char	*emalloc(unsigned long);	/* imported routine  */",
 	"extern void	dfa_init(ushort);	/* 4 exported routines */",
 	"extern void	dfa_init(ushort);	/* 4 exported routines */",
-	"extern int	dfa_member(ushort);",
+	"extern int	dfa_member(ulong);",
 	"extern int	dfa_store(uchar *);",
 	"extern int	dfa_store(uchar *);",
 	"extern void	dfa_stats(void);",
 	"extern void	dfa_stats(void);",
 	"",
 	"",
@@ -53,9 +56,6 @@ static char *Dfa[] = {
 	"static Vertex	**layers;	/* one splay tree of nodes per layer */",
 	"static Vertex	**layers;	/* one splay tree of nodes per layer */",
 	"static Vertex	**path;		/* run of word in the DFA */",
 	"static Vertex	**path;		/* run of word in the DFA */",
 	"static Vertex	*R, *F, *NF;	/* Root, Final, Not-Final */",
 	"static Vertex	*R, *F, *NF;	/* Root, Final, Not-Final */",
-#if 0
-	"/* extern ulong nr_states=0;	/* number of nodes in the DFA */",
-#endif
 	"static uchar	*word, *lastword;/* string, and last string inserted */",
 	"static uchar	*word, *lastword;/* string, and last string inserted */",
 	"static int	dfa_depth, iv=0, nv=0, pfrst=0, Tally;",
 	"static int	dfa_depth, iv=0, nv=0, pfrst=0, Tally;",
 	"",
 	"",
@@ -204,7 +204,7 @@ static char *Dfa[] = {
 	"",
 	"",
 	"static Vertex *",
 	"static Vertex *",
 	"Delta(Vertex *v, int h)	/* v->delta[h] */",
 	"Delta(Vertex *v, int h)	/* v->delta[h] */",
-	"{	register Edge *e;",
+	"{	Edge *e;",
 	"",
 	"",
 	"	if (v->dst[0] && h >= v->from[0] && h <= v->to[0])",
 	"	if (v->dst[0] && h >= v->from[0] && h <= v->to[0])",
 	"		return v->dst[0];	/* oldest edge */",
 	"		return v->dst[0];	/* oldest edge */",
@@ -219,8 +219,8 @@ static char *Dfa[] = {
 	"",
 	"",
 	"static void",
 	"static void",
 	"numDelta(Vertex *v, int d)",
 	"numDelta(Vertex *v, int d)",
-	"{	register Edge *e;",
-	"	register ulong cnt;",
+	"{	Edge *e;",
+	"	ulong cnt;",
 	"	int i;",
 	"	int i;",
 	"",
 	"",
 	"	for (i = 0; i < 2; i++)",
 	"	for (i = 0; i < 2; i++)",
@@ -367,8 +367,8 @@ static char *Dfa[] = {
 	"",
 	"",
 	"static ulong",
 	"static ulong",
 	"mk_key(Vertex *v)	/* not sensitive to order */",
 	"mk_key(Vertex *v)	/* not sensitive to order */",
-	"{	register ulong m = 0, vk2 = 0;",
-	"	register Edge *e;",
+	"{	ulong m = 0, vk2 = 0;",
+	"	Edge *e;",
 	"",
 	"",
 	"	if (v->dst[0])",
 	"	if (v->dst[0])",
 	"	{	m += HASH(v->dst[0], v->to[0] - v->from[0] + 1);",
 	"	{	m += HASH(v->dst[0], v->to[0] - v->from[0] + 1);",
@@ -388,8 +388,8 @@ static char *Dfa[] = {
 	"",
 	"",
 	"static ulong",
 	"static ulong",
 	"mk_special(int sigma, Vertex *n, Vertex *v)",
 	"mk_special(int sigma, Vertex *n, Vertex *v)",
-	"{	register ulong m = 0, vk2 = 0;",
-	"	register Edge *f; Vertex *last = (Vertex *) 0;",
+	"{	ulong m = 0, vk2 = 0;",
+	"	Edge *f;",
 	"	int i;",
 	"	int i;",
 	"",
 	"",
 	"	for (i = 0; i < 2; i++)",
 	"	for (i = 0; i < 2; i++)",
@@ -471,7 +471,7 @@ static char *Dfa[] = {
 	"}",
 	"}",
 	"",
 	"",
 	"int",
 	"int",
-	"dfa_member(ushort n)",
+	"dfa_member(ulong n)",
 	"{	Vertex **p, **q;",
 	"{	Vertex **p, **q;",
 	"	uchar *w = &word[n];",
 	"	uchar *w = &word[n];",
 	"	int i;",
 	"	int i;",
@@ -495,20 +495,20 @@ static char *Dfa[] = {
 	"	memcpy(&lastword[pfrst], &sv[pfrst], dfa_depth-pfrst);",
 	"	memcpy(&lastword[pfrst], &sv[pfrst], dfa_depth-pfrst);",
 	"	if (pfrst > iv) pfrst = iv;",
 	"	if (pfrst > iv) pfrst = iv;",
 	"	if (pfrst > nv) pfrst = nv;",
 	"	if (pfrst > nv) pfrst = nv;",
-	"phase1:",
+	"/* phase1: */",
 	"	p = &path[pfrst]; q = (p+1); w = &word[pfrst];",
 	"	p = &path[pfrst]; q = (p+1); w = &word[pfrst];",
 	"	for (i = pfrst; i < dfa_depth; i++)",
 	"	for (i = pfrst; i < dfa_depth; i++)",
 	"		*q++ = Delta(*p++, *w++);	/* (*p)->delta[*w++]; */",
 	"		*q++ = Delta(*p++, *w++);	/* (*p)->delta[*w++]; */",
 	"",
 	"",
 	"	if (*p == F) return 1;	/* it's already there */",
 	"	if (*p == F) return 1;	/* it's already there */",
-	"phase2:",
+	"/* phase2: */",
 	"	iv = dfa_depth;",
 	"	iv = dfa_depth;",
 	"	do {	iv--;",
 	"	do {	iv--;",
 	"		old = new;",
 	"		old = new;",
 	"		new = find_it(path[iv], old, word[iv], iv);",
 	"		new = find_it(path[iv], old, word[iv], iv);",
 	"	} while (new && iv > 0);",
 	"	} while (new && iv > 0);",
 	"",
 	"",
-	"phase3:",
+	"/* phase3: */",
 	"	nv = k = 0; s = path[0];",
 	"	nv = k = 0; s = path[0];",
 	"	for (j = 1; j <= iv; ++j) ",
 	"	for (j = 1; j <= iv; ++j) ",
 	"		if (path[j]->num > 1)",
 	"		if (path[j]->num > 1)",

+ 100 - 115
sys/src/cmd/spin/pangen5.c

@@ -1,14 +1,15 @@
 /***** spin: pangen5.c *****/
 /***** spin: pangen5.c *****/
 
 
-/* Copyright (c) 1999-2000 by Lucent Technologies - Bell Laboratories     */
+/* Copyright (c) 1999-2003 by Lucent Technologies, Bell Laboratories.     */
 /* All Rights Reserved.  This software is for educational purposes only.  */
 /* All Rights Reserved.  This software is for educational purposes only.  */
-/* Permission is given to distribute this code provided that this intro-  */
-/* ductory message is not removed and no monies are exchanged.            */
-/* No guarantee is expressed or implied by the distribution of this code. */
-/* Written by Gerard J. Holzmann.                                         */
+/* No guarantee whatsoever is expressed or implied by the distribution of */
+/* this code.  Permission is given to distribute this code provided that  */
+/* this introductory message is not removed and no monies are exchanged.  */
+/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
+/*             http://spinroot.com/                                       */
+/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
 
 
 #include "spin.h"
 #include "spin.h"
-#include "version.h"
 #ifdef PC
 #ifdef PC
 #include "y_tab.h"
 #include "y_tab.h"
 #else
 #else
@@ -21,24 +22,28 @@ typedef struct BuildStack {
 } BuildStack;
 } BuildStack;
 
 
 extern ProcList	*rdy;
 extern ProcList	*rdy;
-extern int verbose, eventmapnr, claimnr, rvopt, xspin;
+extern int verbose, eventmapnr, claimnr, rvopt, export_ast, u_sync;
 extern Element *Al_El;
 extern Element *Al_El;
 
 
-static FSM_state *fsm;
 static FSM_state *fsm_free;
 static FSM_state *fsm_free;
 static FSM_trans *trans_free;
 static FSM_trans *trans_free;
-static FSM_use   *use_free;
 static BuildStack *bs, *bf;
 static BuildStack *bs, *bf;
-static FSM_state **fsm_tbl;
 static int max_st_id;
 static int max_st_id;
 static int cur_st_id;
 static int cur_st_id;
-static int o_max;
+int o_max;
+FSM_state *fsm;
+FSM_state **fsm_tbl;
+FSM_use   *use_free;
 
 
 static void ana_seq(Sequence *);
 static void ana_seq(Sequence *);
 static void ana_stmnt(FSM_trans *, Lextok *, int);
 static void ana_stmnt(FSM_trans *, Lextok *, int);
-extern int	has_global(Lextok *);
 
 
-void
+extern void AST_slice(void);
+extern void AST_store(ProcList *, int);
+extern int  has_global(Lextok *);
+extern void exit(int);
+
+static void
 fsm_table(void)
 fsm_table(void)
 {	FSM_state *f;
 {	FSM_state *f;
 	max_st_id += 2;
 	max_st_id += 2;
@@ -118,28 +123,8 @@ good_dead(Element *e, FSM_use *u)
 }
 }
 
 
 #if 0
 #if 0
-static int
-badjump(Element *e)
-{	Element *g;
-
-	/* e->n->ntyp == GOTO */
-	g = get_lab(e->n, 1);
-	g = huntele(g, e->status);
-	if (g && g->n) 
-	{	switch (g->n->ntyp) {
-		case ATOMIC:
-		case NON_ATOMIC:
-		case D_STEP:
-		case IF:
-		case DO:
-		case UNLESS:
-		case ELSE:
-			return 1;
-	}	}
-	return 0;
-}
-#endif
 static int howdeep = 0;
 static int howdeep = 0;
+#endif
 
 
 static int
 static int
 eligible(FSM_trans *v)
 eligible(FSM_trans *v)
@@ -155,9 +140,9 @@ eligible(FSM_trans *v)
 	||  (el->status&CHECK2)		/* remotely referenced */
 	||  (el->status&CHECK2)		/* remotely referenced */
 	||  lt->ntyp == ATOMIC
 	||  lt->ntyp == ATOMIC
 	||  lt->ntyp == NON_ATOMIC	/* used for inlines -- should be able to handle this */
 	||  lt->ntyp == NON_ATOMIC	/* used for inlines -- should be able to handle this */
-#if 1
 	||  lt->ntyp == IF
 	||  lt->ntyp == IF
-#endif
+	||  lt->ntyp == C_CODE
+	||  lt->ntyp == C_EXPR
 	||  has_lab(el, 0)		/* any label at all */
 	||  has_lab(el, 0)		/* any label at all */
 
 
 	||  lt->ntyp == DO
 	||  lt->ntyp == DO
@@ -169,48 +154,13 @@ eligible(FSM_trans *v)
 	||  lt->ntyp == 'r'
 	||  lt->ntyp == 'r'
 	||  lt->ntyp == 's')
 	||  lt->ntyp == 's')
 		return 0;
 		return 0;
-#if 0
-	if (lt && lt->ntyp == GOTO && badjump(el))
-		return 0;
-#endif
+
 	if (!(el->status&(2|4)))	/* not atomic */
 	if (!(el->status&(2|4)))	/* not atomic */
 	{	int unsafe = (el->status&I_GLOB)?1:has_global(el->n);
 	{	int unsafe = (el->status&I_GLOB)?1:has_global(el->n);
 		if (unsafe)
 		if (unsafe)
 			return 0;
 			return 0;
 	}
 	}
-#if 0
-	if (lt->ntyp == IF)
-	{	SeqList *h;
-		Element *g;
-		int cnt=0, has_else=0;
-
-		/* is it clearly deterministic? */
-
-		for (h = v->step->sub; h; h = h->nxt, cnt++)
-		{	g = huntstart(h->this->frst);
-			if (!g 	|| g->esc || !g->n)
-				return 0;
-			switch (g->n->ntyp) {
-			case ELSE:
-				has_else=1;
-				/* fall through */
-			case 'c':
-				break;
-			default:
-				return 0;
-			}
-		}
-		if (cnt != 2 || !has_else)
-			return 0;
-
-/* should also be no GOTO, BREAK, or ineligible stmnts in either sequence */
-
-printf("spin: %s:%d: may have handled if\n",
-	lt->fn?lt->fn->name:"", lt->ln);
 
 
-		return 0;
-	}
-#endif
 	return 1;
 	return 1;
 }
 }
 
 
@@ -266,14 +216,14 @@ static int
 build_step(FSM_trans *v)
 build_step(FSM_trans *v)
 {	FSM_state *f;
 {	FSM_state *f;
 	Element	*el = v->step;
 	Element	*el = v->step;
+#if 0
 	Lextok	*lt = ZN;
 	Lextok	*lt = ZN;
+#endif
 	int	st  = v->to;
 	int	st  = v->to;
 	int	r;
 	int	r;
 
 
 	if (!el) return -1;
 	if (!el) return -1;
 
 
-	lt = v->step->n;
-
 	if (v->step->merge)
 	if (v->step->merge)
 		return v->step->merge;	/* already done */
 		return v->step->merge;	/* already done */
 
 
@@ -285,6 +235,7 @@ build_step(FSM_trans *v)
 
 
 	f = fsm_tbl[st];
 	f = fsm_tbl[st];
 #if 0
 #if 0
+	lt = v->step->n;
 	if (verbose&32)
 	if (verbose&32)
 	{	if (++howdeep == 1)
 	{	if (++howdeep == 1)
 			printf("spin: %s, line %3d, merge:\n",
 			printf("spin: %s, line %3d, merge:\n",
@@ -299,7 +250,10 @@ build_step(FSM_trans *v)
 	v->step->merge = (r == -1) ? st : r;
 	v->step->merge = (r == -1) ? st : r;
 #if 0
 #if 0
 	if (verbose&32)
 	if (verbose&32)
+	{	printf("	merge value: %d (st=%d,r=%d, line %d)\n",
+			v->step->merge, st, r, el->n->ln);
 		howdeep--;
 		howdeep--;
+	}
 #endif
 #endif
 	popbuild();
 	popbuild();
 
 
@@ -307,7 +261,7 @@ build_step(FSM_trans *v)
 }
 }
 
 
 static void
 static void
-FSM_MERGER(char *pname)	/* find candidates for safely merging steps */
+FSM_MERGER(char *pname_unused)	/* find candidates for safely merging steps */
 {	FSM_state *f, *g;
 {	FSM_state *f, *g;
 	FSM_trans *t;
 	FSM_trans *t;
 	Lextok	*lt;
 	Lextok	*lt;
@@ -369,11 +323,19 @@ FSM_MERGER(char *pname)	/* find candidates for safely merging steps */
 			continue;
 			continue;
 
 
 		lt = t->step->n;
 		lt = t->step->n;
+#if 0
+	4.1.3:
+	an rv send operation inside an atomic, *loses* atomicity
+	when executed
+	and should therefore never be merged with a subsequent
+	statement within the atomic sequence
+	the same is not true for non-rv send operations
+#endif
 
 
-		if (lt->ntyp == 'c'
+		if (lt->ntyp == 'c'	/* potentially blocking stmnts */
 		||  lt->ntyp == 'r'
 		||  lt->ntyp == 'r'
-		||  lt->ntyp == 's')	/* blocking stmnts */
-		{	if (!canfill_in(t))
+		||  (lt->ntyp == 's' && u_sync == 0))	/* added !u_sync in 4.1.3 */
+		{	if (!canfill_in(t))		/* atomic, non-global, etc. */
 				continue;
 				continue;
 
 
 			g = fsm_tbl[t->to];
 			g = fsm_tbl[t->to];
@@ -420,6 +382,7 @@ FSM_ANA(void)
 			u->special = n+1;	/* means, reset to 0 after use */
 			u->special = n+1;	/* means, reset to 0 after use */
 	}
 	}
 
 
+	if (!export_ast)
 	for (f = fsm; f; f = f->nxt)
 	for (f = fsm; f; f = f->nxt)
 	for (t = f->t; t; t = t->nxt)
 	for (t = f->t; t; t = t->nxt)
 	for (n = 0; n < 2; n++)
 	for (n = 0; n < 2; n++)
@@ -430,7 +393,7 @@ FSM_ANA(void)
 				t->Val[n] = v;
 				t->Val[n] = v;
 			else
 			else
 				w->nxt = v;
 				w->nxt = v;
-#if 0
+#if q
 			if (verbose&32)
 			if (verbose&32)
 			{	printf("%s : %3d:  %d -> %d \t",
 			{	printf("%s : %3d:  %d -> %d \t",
 					t->step->n->fn->name,
 					t->step->n->fn->name,
@@ -453,7 +416,7 @@ FSM_ANA(void)
 	}	}
 	}	}
 }
 }
 
 
-static void
+void
 rel_use(FSM_use *u)
 rel_use(FSM_use *u)
 {
 {
 	if (!u) return;
 	if (!u) return;
@@ -519,12 +482,9 @@ mkstate(int s)
 	return f;
 	return f;
 }
 }
 
 
-static void
-FSM_EDGE(int from, int to, Element *e)
-{	FSM_state *f;
-	FSM_trans *t;
-
-	f = mkstate(from);	/* find it or else make it */
+static FSM_trans *
+get_trans(int to)
+{	FSM_trans *t;
 
 
 	if (trans_free)
 	if (trans_free)
 	{	t = trans_free;
 	{	t = trans_free;
@@ -532,7 +492,19 @@ FSM_EDGE(int from, int to, Element *e)
 		trans_free = trans_free->nxt;
 		trans_free = trans_free->nxt;
 	} else
 	} else
 		t = (FSM_trans *) emalloc(sizeof(FSM_trans));
 		t = (FSM_trans *) emalloc(sizeof(FSM_trans));
+
 	t->to = to;
 	t->to = to;
+	return t;
+}
+
+static void
+FSM_EDGE(int from, int to, Element *e)
+{	FSM_state *f;
+	FSM_trans *t;
+
+	f = mkstate(from);	/* find it or else make it */
+	t = get_trans(to);
+
 	t->step = e;
 	t->step = e;
 	t->nxt = f->t;
 	t->nxt = f->t;
 	f->t = t;
 	f->t = t;
@@ -540,6 +512,13 @@ FSM_EDGE(int from, int to, Element *e)
 	f = mkstate(to);
 	f = mkstate(to);
 	f->in++;
 	f->in++;
 
 
+	if (export_ast)
+	{	t = get_trans(from);
+		t->step = e;
+		t->nxt = f->p;	/* from is a predecessor of to */
+		f->p = t;
+	}
+
 	if (t->step)
 	if (t->step)
 		ana_stmnt(t, t->step->n, 0);
 		ana_stmnt(t, t->step->n, 0);
 }
 }
@@ -551,10 +530,13 @@ static void
 ana_var(FSM_trans *t, Lextok *now, int usage)
 ana_var(FSM_trans *t, Lextok *now, int usage)
 {	FSM_use *u, *v;
 {	FSM_use *u, *v;
 
 
-	if (!t
-	|| !now
-	|| !now->sym
-	||  now->sym->name[0] == '_')
+	if (!t || !now || !now->sym)
+		return;
+
+	if (now->sym->name[0] == '_'
+	&&  (strcmp(now->sym->name, "_") == 0
+	||   strcmp(now->sym->name, "_pid") == 0
+	||   strcmp(now->sym->name, "_last") == 0))
 		return;
 		return;
 
 
 	v = t->Val[usage];
 	v = t->Val[usage];
@@ -606,6 +588,8 @@ ana_stmnt(FSM_trans *t, Lextok *now, int usage)
 	case ATOMIC:
 	case ATOMIC:
 	case NON_ATOMIC:
 	case NON_ATOMIC:
 	case D_STEP:
 	case D_STEP:
+	case C_CODE:
+	case C_EXPR:
 		break;
 		break;
 
 
 	case '!':	
 	case '!':	
@@ -641,8 +625,8 @@ ana_stmnt(FSM_trans *t, Lextok *now, int usage)
 	case AND:
 	case AND:
 	case LSHIFT:
 	case LSHIFT:
 	case RSHIFT:
 	case RSHIFT:
-		ana_stmnt(t,now->lft, RVAL);
-		ana_stmnt(t,now->rgt, RVAL);
+		ana_stmnt(t, now->lft, RVAL);
+		ana_stmnt(t, now->rgt, RVAL);
 		break;
 		break;
 
 
 	case ASGN:
 	case ASGN:
@@ -656,6 +640,11 @@ ana_stmnt(FSM_trans *t, Lextok *now, int usage)
 			ana_stmnt(t, v->lft, RVAL);
 			ana_stmnt(t, v->lft, RVAL);
 		break;
 		break;
 
 
+	case PRINTM:
+		if (now->lft && !now->lft->ismtyp)
+			ana_stmnt(t, now->lft, RVAL);
+		break;
+
 	case 's':
 	case 's':
 		ana_stmnt(t, now->lft, RVAL);
 		ana_stmnt(t, now->lft, RVAL);
 		for (v = now->rgt; v; v = v->rgt)
 		for (v = now->rgt; v; v = v->rgt)
@@ -677,8 +666,10 @@ ana_stmnt(FSM_trans *t, Lextok *now, int usage)
 
 
 	case '?':
 	case '?':
 		ana_stmnt(t, now->lft, RVAL);
 		ana_stmnt(t, now->lft, RVAL);
-		ana_stmnt(t, now->rgt->lft, RVAL);
-		ana_stmnt(t, now->rgt->rgt, RVAL);
+		if (now->rgt)
+		{	ana_stmnt(t, now->rgt->lft, RVAL);
+			ana_stmnt(t, now->rgt->rgt, RVAL);
+		}
 		break;
 		break;
 
 
 	case NAME:
 	case NAME:
@@ -692,17 +683,18 @@ ana_stmnt(FSM_trans *t, Lextok *now, int usage)
 		break;
 		break;
 
 
 	default:
 	default:
-		printf("spin: bad node type %d (ana_stmnt)\n", now->ntyp);
+		printf("spin: bad node type %d line %d (ana_stmnt)\n", now->ntyp, now->ln);
 		fatal("aborting", (char *) 0);
 		fatal("aborting", (char *) 0);
 	}
 	}
 }
 }
 
 
 void
 void
-ana_src(int dataflow, int merger)
+ana_src(int dataflow, int merger)	/* called from main.c and guided.c */
 {	ProcList *p;
 {	ProcList *p;
 	Element *e;
 	Element *e;
+#if 0
 	int counter = 1;
 	int counter = 1;
-
+#endif
 	for (p = rdy; p; p = p->nxt)
 	for (p = rdy; p; p = p->nxt)
 	{	if (p->tn == eventmapnr
 	{	if (p->tn == eventmapnr
 		||  p->tn == claimnr)
 		||  p->tn == claimnr)
@@ -724,11 +716,14 @@ ana_src(int dataflow, int merger)
 		}
 		}
 		if (merger)
 		if (merger)
 		{	FSM_MERGER(p->n->name);
 		{	FSM_MERGER(p->n->name);
-			huntele(e, e->status)->merge_in = 1; /* start-state */
+			huntele(e, e->status, -1)->merge_in = 1; /* start-state */
 #if 0
 #if 0
 			printf("\n");
 			printf("\n");
 #endif
 #endif
 		}
 		}
+		if (export_ast)
+			AST_store(p, huntele(e, e->status, -1)->seqno);
+
 		FSM_DEL();
 		FSM_DEL();
 	}
 	}
 	for (e = Al_El; e; e = e->Nxt)
 	for (e = Al_El; e; e = e->Nxt)
@@ -742,24 +737,14 @@ ana_src(int dataflow, int merger)
 		}
 		}
 		e->status &= ~DONE;
 		e->status &= ~DONE;
 	}
 	}
+	if (export_ast)
+	{	AST_slice();
+		exit(0);
+	}
 }
 }
 
 
-#if 0
-void
-whichnodeis(int s)
-{	Element *e;
-	for (e = Al_El; e; e = e->Nxt)
-		if (e->seqno == s)
-		{	printf("\n\tnode %s:%d: ",
-				e->n->fn->name, e->n->ln);
-			comment(stdout, e->n, 0);
-			printf("\n");
-		}
-}
-#endif
-
 void
 void
-spit_recvs(FILE *f1, FILE *f2)
+spit_recvs(FILE *f1, FILE *f2)	/* called from pangen2.c */
 {	Element *e;
 {	Element *e;
 	Sequence *s;
 	Sequence *s;
 	extern int Unique;
 	extern int Unique;
@@ -849,10 +834,10 @@ ana_seq(Sequence *s)
 		} else 
 		} else 
 		{	if (e->n->ntyp == GOTO)
 		{	if (e->n->ntyp == GOTO)
 			{	g = get_lab(e->n, 1);
 			{	g = get_lab(e->n, 1);
-				g = huntele(g, e->status);
+				g = huntele(g, e->status, -1);
 				To = g->seqno;
 				To = g->seqno;
 			} else if (e->nxt)
 			} else if (e->nxt)
-			{	g = huntele(e->nxt, e->status);
+			{	g = huntele(e->nxt, e->status, -1);
 				To = g->seqno;
 				To = g->seqno;
 			} else
 			} else
 				To = 0;
 				To = 0;

+ 14 - 13
sys/src/cmd/spin/pangen5.h

@@ -1,14 +1,16 @@
 /***** spin: pangen5.h *****/
 /***** spin: pangen5.h *****/
 
 
-/* Copyright (c) 1997-2000 by Lucent Technologies - Bell Laboratories.    */
+/* Copyright (c) 1997-2003 by Lucent Technologies, Bell Laboratories.     */
 /* All Rights Reserved.  This software is for educational purposes only.  */
 /* All Rights Reserved.  This software is for educational purposes only.  */
-/* Permission is given to distribute this code provided that this intro-  */
-/* ductory message is not removed and no monies are exchanged.            */
-/* No guarantee is expressed or implied by the distribution of this code. */
-/* The checkpointing code below was written by Gerard J. Holzmann         */
+/* No guarantee whatsoever is expressed or implied by the distribution of */
+/* this code.  Permission is given to distribute this code provided that  */
+/* this introductory message is not removed and no monies are exchanged.  */
+/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
+/*             http://spinroot.com/                                       */
+/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
 
 
 static char *Xpt[] = {
 static char *Xpt[] = {
-	"#if defined(W_XPT) || defined(R_XPT)",
+	"#if defined(MA) && (defined(W_XPT) || defined(R_XPT))",
 	"static Vertex	**temptree;",
 	"static Vertex	**temptree;",
 	"static char	wbuf[4096];",
 	"static char	wbuf[4096];",
 	"static int	WCNT = 4096, wcnt=0;",
 	"static int	WCNT = 4096, wcnt=0;",
@@ -129,7 +131,6 @@ static char *Xpt[] = {
 	"static void",
 	"static void",
 	"x_remove(void)",
 	"x_remove(void)",
 	"{	Vertex *tmp; int i, s;",
 	"{	Vertex *tmp; int i, s;",
-	"#if 1",
 	"	int r, j;",
 	"	int r, j;",
 	"	/* double-check: */",
 	"	/* double-check: */",
 	"	stacker[dfa_depth-1] = 0; r = dfa_store(stacker);",
 	"	stacker[dfa_depth-1] = 0; r = dfa_store(stacker);",
@@ -141,7 +142,6 @@ static char *Xpt[] = {
 	"		printf(\" -- not a stackstate <o:%%d,4:%%d>\\n\", r, j);",
 	"		printf(\" -- not a stackstate <o:%%d,4:%%d>\\n\", r, j);",
 	"		return;",
 	"		return;",
 	"	}",
 	"	}",
-	"#endif",
 	"	stacker[dfa_depth-1] = 1;",
 	"	stacker[dfa_depth-1] = 1;",
 	"	s = dfa_member(dfa_depth-1);",
 	"	s = dfa_member(dfa_depth-1);",
 	"",
 	"",
@@ -291,7 +291,9 @@ static char *Xpt[] = {
 	"	yes = no = 0;",
 	"	yes = no = 0;",
 	"	for (i = 0; i < 2; i++)",
 	"	for (i = 0; i < 2; i++)",
 	"		if ((ulong) t->dst[i] == want)",
 	"		if ((ulong) t->dst[i] == want)",
-	"		{	if (t->from[i] <= 0 && t->to[i] >= 0)",
+	"		{	/* was t->from[i] <= 0 && t->to[i] >= 0 */",
+	"			/* but from and to are uchar */",
+	"			if (t->from[i] == 0)",
 	"				yes = 1;",
 	"				yes = 1;",
 	"			else",
 	"			else",
 	"			if (t->from[i] <= 4 && t->to[i] >= 4)",
 	"			if (t->from[i] <= 4 && t->to[i] >= 4)",
@@ -300,7 +302,8 @@ static char *Xpt[] = {
 	"",
 	"",
 	"	for (e = t->Succ; e; e = e->Nxt)",
 	"	for (e = t->Succ; e; e = e->Nxt)",
 	"		if ((ulong) e->Dst == want)",
 	"		if ((ulong) e->Dst == want)",
-	"		{	if (INRANGE(e, 0))",
+	"		{	/* was INRANGE(e,0) but From and To are uchar */",
+	"			if ((e->From == 0) || (e->s==1 && e->S==0))",
 	"				yes = 1;",
 	"				yes = 1;",
 	"			else if (INRANGE(e, 4))",
 	"			else if (INRANGE(e, 4))",
 	"				no = 1;",
 	"				no = 1;",
@@ -348,9 +351,7 @@ static char *Xpt[] = {
 	"",
 	"",
 	"static Vertex *",
 	"static Vertex *",
 	"x_cpy_rev(void)",
 	"x_cpy_rev(void)",
-	"{	Vertex *c, *v;",
-	"",
-	"	/* find 0 and !4 predecessor of F */",
+	"{	Vertex *c, *v;	/* find 0 and !4 predecessor of F */",
 	"",
 	"",
 	"	v = x_tail(temptree[dfa_depth-1], F->key);",
 	"	v = x_tail(temptree[dfa_depth-1], F->key);",
 	"	if (!v) return (Vertex *) 0;",
 	"	if (!v) return (Vertex *) 0;",

+ 2357 - 0
sys/src/cmd/spin/pangen6.c

@@ -0,0 +1,2357 @@
+/***** spin: pangen6.c *****/
+
+/* Copyright (c) 2000-2003 by Lucent Technologies, Bell Laboratories.     */
+/* All Rights Reserved.  This software is for educational purposes only.  */
+/* No guarantee whatsoever is expressed or implied by the distribution of */
+/* this code.  Permission is given to distribute this code provided that  */
+/* this introductory message is not removed and no monies are exchanged.  */
+/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
+/*             http://spinroot.com/                                       */
+/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
+
+/* Abstract syntax tree analysis / slicing (spin option -A) */
+/* AST_store stores the fsms's for each proctype            */
+/* AST_track keeps track of variables used in properties    */
+/* AST_slice starts the slicing algorithm                   */
+/*      it first collects more info and then calls          */
+/*      AST_criteria to process the slice criteria          */
+
+#include "spin.h"
+#ifdef PC
+#include "y_tab.h"
+#else
+#include "y.tab.h"
+#endif
+
+extern Ordered	 *all_names;
+extern FSM_use   *use_free;
+extern FSM_state **fsm_tbl;
+extern FSM_state *fsm;
+extern int	 verbose, o_max;
+
+static FSM_trans *cur_t;
+static FSM_trans *expl_par;
+static FSM_trans *expl_var;
+static FSM_trans *explicit;
+
+extern void rel_use(FSM_use *);
+
+#define ulong	unsigned long
+
+typedef struct Pair {
+	FSM_state	*h;
+	int		b;
+	struct Pair	*nxt;
+} Pair;
+
+typedef struct AST {
+	ProcList *p;		/* proctype decl */
+	int	i_st;		/* start state */
+	int	nstates, nwords;
+	int	relevant;
+	Pair	*pairs;		/* entry and exit nodes of proper subgraphs */
+	FSM_state *fsm;		/* proctype body */
+	struct AST *nxt;	/* linked list */
+} AST;
+
+typedef struct RPN {		/* relevant proctype names */
+	Symbol	*rn;
+	struct RPN *nxt;
+} RPN;
+
+typedef struct ALIAS {		/* channel aliasing info */
+	Lextok	*cnm;		/* this chan */
+	int	origin;		/* debugging - origin of the alias */
+	struct ALIAS	*alias;	/* can be an alias for these other chans */
+	struct ALIAS	*nxt;	/* linked list */
+} ALIAS;
+
+typedef struct ChanList {
+	Lextok *s;		/* containing stmnt */
+	Lextok *n;		/* point of reference - could be struct */
+	struct ChanList *nxt;	/* linked list */
+} ChanList;
+
+/* a chan alias can be created in one of three ways:
+	assignement to chan name
+		a = b -- a is now an alias for b
+	passing chan name as parameter in run
+		run x(b) -- proctype x(chan a)
+	passing chan name through channel
+		x!b -- x?a
+ */
+
+#define USE		1
+#define DEF		2
+#define DEREF_DEF	4
+#define DEREF_USE	8
+
+static AST	*ast;
+static ALIAS	*chalcur;
+static ALIAS	*chalias;
+static ChanList	*chanlist;
+static Slicer	*slicer;
+static Slicer	*rel_vars;	/* all relevant variables */
+static int	AST_Changes;
+static int	AST_Round;
+static FSM_state no_state;
+static RPN	*rpn;
+static int	in_recv = 0;
+
+static int	AST_mutual(Lextok *, Lextok *, int);
+static void	AST_dominant(void);
+static void	AST_hidden(void);
+static void	AST_setcur(Lextok *);
+static void	check_slice(Lextok *, int);
+static void	curtail(AST *);
+static void	def_use(Lextok *, int);
+static void	name_AST_track(Lextok *, int);
+static void	show_expl(void);
+
+static int
+AST_isini(Lextok *n)	/* is this an initialized channel */
+{	Symbol *s;
+
+	if (!n || !n->sym) return 0;
+
+	s = n->sym;
+
+	if (s->type == CHAN)
+		return (s->ini->ntyp == CHAN); /* freshly instantiated */
+
+	if (s->type == STRUCT && n->rgt)
+		return AST_isini(n->rgt->lft);
+
+	return 0;
+}
+
+static void
+AST_var(Lextok *n, Symbol *s, int toplevel)
+{
+	if (!s) return;
+
+	if (toplevel)
+	{	if (s->context && s->type)
+			printf(":%s:L:", s->context->name);
+		else
+			printf("G:");
+	}
+	printf("%s", s->name); /* array indices ignored */
+
+	if (s->type == STRUCT && n && n->rgt && n->rgt->lft)
+	{	printf(":");
+		AST_var(n->rgt->lft, n->rgt->lft->sym, 0);
+	}
+}
+
+static void
+name_def_indices(Lextok *n, int code)
+{
+	if (!n || !n->sym) return;
+
+	if (n->sym->nel != 1)
+		def_use(n->lft, code);		/* process the index */
+
+	if (n->sym->type == STRUCT		/* and possible deeper ones */
+	&&  n->rgt)
+		name_def_indices(n->rgt->lft, code);
+}
+
+static void
+name_def_use(Lextok *n, int code)
+{	FSM_use *u;
+
+	if (!n) return;
+
+	if ((code&USE)
+	&&  cur_t->step
+	&&  cur_t->step->n)
+	{	switch (cur_t->step->n->ntyp) {
+		case 'c': /* possible predicate abstraction? */
+			n->sym->colnr |= 2; /* yes */
+			break;
+		default:
+			n->sym->colnr |= 1; /* no  */
+			break;
+		}
+	}
+
+	for (u = cur_t->Val[0]; u; u = u->nxt)
+		if (AST_mutual(n, u->n, 1)
+		&&  u->special == code)
+			return;
+
+	if (use_free)
+	{	u = use_free;
+		use_free = use_free->nxt;
+	} else
+		u = (FSM_use *) emalloc(sizeof(FSM_use));
+	
+	u->n = n;
+	u->special = code;
+	u->nxt = cur_t->Val[0];
+	cur_t->Val[0] = u;
+
+	name_def_indices(n, USE|(code&(~DEF)));	/* not def, but perhaps deref */
+}
+
+static void
+def_use(Lextok *now, int code)
+{	Lextok *v;
+
+	if (now)
+	switch (now->ntyp) {
+	case '!':	
+	case UMIN:	
+	case '~':
+	case 'c':
+	case ENABLED:
+	case ASSERT:
+	case EVAL:
+		def_use(now->lft, USE|code);
+		break;
+
+	case LEN:
+	case FULL:
+	case EMPTY:
+	case NFULL:
+	case NEMPTY:
+		def_use(now->lft, DEREF_USE|USE|code);
+		break;
+
+	case '/':
+	case '*':
+	case '-':
+	case '+':
+	case '%':
+	case '&':
+	case '^':
+	case '|':
+	case LE:
+	case GE:
+	case GT:
+	case LT:
+	case NE:
+	case EQ:
+	case OR:
+	case AND:
+	case LSHIFT:
+	case RSHIFT:
+		def_use(now->lft, USE|code);
+		def_use(now->rgt, USE|code); 
+		break;
+
+	case ASGN:
+		def_use(now->lft, DEF|code);
+		def_use(now->rgt, USE|code);
+		break;
+
+	case TYPE:	/* name in parameter list */
+		name_def_use(now, code);
+		break;
+
+	case NAME:
+		name_def_use(now, code);
+		break;
+
+	case RUN:
+		name_def_use(now, USE);			/* procname - not really needed */
+		for (v = now->lft; v; v = v->rgt)
+			def_use(v->lft, USE);		/* params */
+		break;
+
+	case 's':
+		def_use(now->lft, DEREF_DEF|DEREF_USE|USE|code);
+		for (v = now->rgt; v; v = v->rgt)
+			def_use(v->lft, USE|code);
+		break;
+
+	case 'r':
+		def_use(now->lft, DEREF_DEF|DEREF_USE|USE|code);
+		for (v = now->rgt; v; v = v->rgt)
+		{	if (v->lft->ntyp == EVAL)
+				def_use(v->lft, code);	/* will add USE */
+			else if (v->lft->ntyp != CONST)
+				def_use(v->lft, DEF|code);
+		}
+		break;
+
+	case 'R':
+		def_use(now->lft, DEREF_USE|USE|code);
+		for (v = now->rgt; v; v = v->rgt)
+		{	if (v->lft->ntyp == EVAL)
+				def_use(v->lft, code); /* will add USE */
+		}
+		break;
+
+	case '?':
+		def_use(now->lft, USE|code);
+		if (now->rgt)
+		{	def_use(now->rgt->lft, code);
+			def_use(now->rgt->rgt, code);
+		}
+		break;	
+
+	case PRINT:
+		for (v = now->lft; v; v = v->rgt)
+			def_use(v->lft, USE|code);
+		break;
+
+	case PRINTM:
+		def_use(now->lft, USE);
+		break;
+
+	case CONST:
+	case ELSE:	/* ? */
+	case NONPROGRESS:
+	case PC_VAL:
+	case   'p':
+	case   'q':
+		break;
+
+	case   '.':
+	case  GOTO:
+	case BREAK:
+	case   '@':
+	case D_STEP:
+	case ATOMIC:
+	case NON_ATOMIC:
+	case IF:
+	case DO:
+	case UNLESS:
+	case TIMEOUT:
+	case C_CODE:
+	case C_EXPR:
+	default:
+		break;
+	}
+}
+
+static int
+AST_add_alias(Lextok *n, int nr)
+{	ALIAS *ca;
+	int res;
+
+	for (ca = chalcur->alias; ca; ca = ca->nxt)
+		if (AST_mutual(ca->cnm, n, 1))
+		{	res = (ca->origin&nr);
+			ca->origin |= nr;	/* 1, 2, or 4 - run, asgn, or rcv */
+			return (res == 0);	/* 0 if already there with same origin */
+		}
+
+	ca = (ALIAS *) emalloc(sizeof(ALIAS));
+	ca->cnm = n;
+	ca->origin = nr;
+	ca->nxt = chalcur->alias;
+	chalcur->alias = ca;
+	return 1;
+}
+
+static void
+AST_run_alias(char *pn, char *s, Lextok *t, int parno)
+{	Lextok *v;
+	int cnt;
+
+	if (!t) return;
+
+	if (t->ntyp == RUN)
+	{	if (strcmp(t->sym->name, s) == 0)
+		for (v = t->lft, cnt = 1; v; v = v->rgt, cnt++)
+			if (cnt == parno)
+			{	AST_add_alias(v->lft, 1); /* RUN */
+				break;
+			}
+	} else
+	{	AST_run_alias(pn, s, t->lft, parno);
+		AST_run_alias(pn, s, t->rgt, parno);
+	}
+}
+
+static void
+AST_findrun(char *s, int parno)
+{	FSM_state *f;
+	FSM_trans *t;
+	AST *a;
+
+	for (a = ast; a; a = a->nxt)		/* automata       */
+	for (f = a->fsm; f; f = f->nxt)		/* control states */
+	for (t = f->t; t; t = t->nxt)		/* transitions    */
+	{	if (t->step)
+		AST_run_alias(a->p->n->name, s, t->step->n, parno);
+	}
+}
+
+static void
+AST_par_chans(ProcList *p)	/* find local chan's init'd to chan passed as param */
+{	Ordered	*walk;
+	Symbol	*sp;
+
+	for (walk = all_names; walk; walk = walk->next)
+	{	sp = walk->entry;
+		if (sp
+		&&  sp->context
+		&&  strcmp(sp->context->name, p->n->name) == 0
+		&&  sp->Nid >= 0	/* not itself a param */
+		&&  sp->type == CHAN
+		&&  sp->ini->ntyp == NAME)	/* != CONST and != CHAN */
+		{	Lextok *x = nn(ZN, 0, ZN, ZN);
+			x->sym = sp;
+			AST_setcur(x);
+			AST_add_alias(sp->ini, 2);	/* ASGN */
+	}	}
+}
+
+static void
+AST_para(ProcList *p)
+{	Lextok *f, *t, *c;
+	int cnt = 0;
+
+	AST_par_chans(p);
+
+	for (f = p->p; f; f = f->rgt) 		/* list of types */
+	for (t = f->lft; t; t = t->rgt)
+	{	if (t->ntyp != ',')
+			c = t;
+		else
+			c = t->lft;	/* expanded struct */
+
+		cnt++;
+		if (Sym_typ(c) == CHAN)
+		{	ALIAS *na = (ALIAS *) emalloc(sizeof(ALIAS));
+
+			na->cnm = c;
+			na->nxt = chalias;
+			chalcur = chalias = na;
+#if 0
+			printf("%s -- (par) -- ", p->n->name);
+			AST_var(c, c->sym, 1);
+			printf(" => <<");
+#endif
+			AST_findrun(p->n->name, cnt);
+#if 0
+			printf(">>\n");
+#endif
+		}
+	}
+}
+
+static void
+AST_haschan(Lextok *c)
+{
+	if (!c) return;
+	if (Sym_typ(c) == CHAN)
+	{	AST_add_alias(c, 2);	/* ASGN */
+#if 0
+		printf("<<");
+		AST_var(c, c->sym, 1);
+		printf(">>\n");
+#endif
+	} else
+	{	AST_haschan(c->rgt);
+		AST_haschan(c->lft);
+	}
+}
+
+static int
+AST_nrpar(Lextok *n) /* 's' or 'r' */
+{	Lextok *m;
+	int j = 0;
+
+	for (m = n->rgt; m; m = m->rgt)
+		j++;
+	return j;
+}
+
+static int
+AST_ord(Lextok *n, Lextok *s)
+{	Lextok *m;
+	int j = 0;
+
+	for (m = n->rgt; m; m = m->rgt)
+	{	j++;
+		if (s->sym == m->lft->sym)
+			return j;
+	}
+	return 0;
+}
+
+#if 0
+static void
+AST_ownership(Symbol *s)
+{
+	if (!s) return;
+	printf("%s:", s->name);
+	AST_ownership(s->owner);
+}
+#endif
+
+static int
+AST_mutual(Lextok *a, Lextok *b, int toplevel)
+{	Symbol *as, *bs;
+
+	if (!a && !b) return 1;
+
+	if (!a || !b) return 0;
+
+	as = a->sym;
+	bs = b->sym;
+
+	if (!as || !bs) return 0;
+
+	if (toplevel && as->context != bs->context)
+		return 0;
+
+	if (as->type != bs->type)
+		return 0;
+
+	if (strcmp(as->name, bs->name) != 0)
+		return 0;
+
+	if (as->type == STRUCT
+	&&  a && a->rgt && b && b->rgt)
+		return AST_mutual(a->rgt->lft, b->rgt->lft, 0);
+
+	return 1;
+}
+
+static void
+AST_setcur(Lextok *n)	/* set chalcur */
+{	ALIAS *ca;
+
+	for (ca = chalias; ca; ca = ca->nxt)
+		if (AST_mutual(ca->cnm, n, 1))	/* if same chan */
+		{	chalcur = ca;
+			return;
+		}
+
+	ca = (ALIAS *) emalloc(sizeof(ALIAS));
+	ca->cnm = n;
+	ca->nxt = chalias;
+	chalcur = chalias = ca;
+}
+
+static void
+AST_other(AST *a)	/* check chan params in asgns and recvs */
+{	FSM_state *f;
+	FSM_trans *t;
+	FSM_use *u;
+	ChanList *cl;
+
+	for (f = a->fsm; f; f = f->nxt)		/* control states */
+	for (t = f->t; t; t = t->nxt)		/* transitions    */
+	for (u = t->Val[0]; u; u = u->nxt)	/* def/use info   */
+		if (Sym_typ(u->n) == CHAN
+		&&  (u->special&DEF))		/* def of chan-name  */
+		{	AST_setcur(u->n);
+			switch (t->step->n->ntyp) {
+			case ASGN:
+				AST_haschan(t->step->n->rgt);
+				break;
+			case 'r':
+				/* guess sends where name may originate */
+				for (cl = chanlist; cl; cl = cl->nxt)	/* all sends */
+				{	int a = AST_nrpar(cl->s);
+					int b = AST_nrpar(t->step->n);
+					if (a != b)	/* matching nrs of params */
+						continue;
+
+					a = AST_ord(cl->s, cl->n);
+					b = AST_ord(t->step->n, u->n);
+					if (a != b)	/* same position in parlist */
+						continue;
+
+					AST_add_alias(cl->n, 4); /* RCV assume possible match */
+				}
+				break;
+			default:
+				printf("type = %d\n", t->step->n->ntyp);
+				non_fatal("unexpected chan def type", (char *) 0);
+				break;
+		}	}
+}
+
+static void
+AST_aliases(void)
+{	ALIAS *na, *ca;
+
+	for (na = chalias; na; na = na->nxt)
+	{	printf("\npossible aliases of ");
+		AST_var(na->cnm, na->cnm->sym, 1);
+		printf("\n\t");
+		for (ca = na->alias; ca; ca = ca->nxt)
+		{	if (!ca->cnm->sym)
+				printf("no valid name ");
+			else
+				AST_var(ca->cnm, ca->cnm->sym, 1);
+			printf("<");
+			if (ca->origin & 1) printf("RUN ");
+			if (ca->origin & 2) printf("ASGN ");
+			if (ca->origin & 4) printf("RCV ");
+			printf("[%s]", AST_isini(ca->cnm)?"Initzd":"Name");
+			printf(">");
+			if (ca->nxt) printf(", ");
+		}
+		printf("\n");
+	}
+	printf("\n");
+}
+
+static void
+AST_indirect(FSM_use *uin, FSM_trans *t, char *cause, char *pn)
+{	FSM_use *u;
+
+	/* this is a newly discovered relevant statement */
+	/* all vars it uses to contribute to its DEF are new criteria */
+
+	if (!(t->relevant&1)) AST_Changes++;
+
+	t->round = AST_Round;
+	t->relevant = 1;
+
+	if ((verbose&32) && t->step)
+	{	printf("\tDR %s [[ ", pn);
+		comment(stdout, t->step->n, 0);
+		printf("]]\n\t\tfully relevant %s", cause);
+		if (uin) { printf(" due to "); AST_var(uin->n, uin->n->sym, 1); }
+		printf("\n");
+	}
+	for (u = t->Val[0]; u; u = u->nxt)
+		if (u != uin
+		&& (u->special&(USE|DEREF_USE)))
+		{	if (verbose&32)
+			{	printf("\t\t\tuses(%d): ", u->special);
+				AST_var(u->n, u->n->sym, 1);
+				printf("\n");
+			}
+			name_AST_track(u->n, u->special);	/* add to slice criteria */
+		}
+}
+
+static void
+def_relevant(char *pn, FSM_trans *t, Lextok *n, int ischan)
+{	FSM_use *u;
+	ALIAS *na, *ca;
+	int chanref;
+
+	/* look for all DEF's of n
+	 *	mark those stmnts relevant
+	 *	mark all var USEs in those stmnts as criteria
+	 */
+
+	if (n->ntyp != ELSE)
+	for (u = t->Val[0]; u; u = u->nxt)
+	{	chanref = (Sym_typ(u->n) == CHAN);
+
+		if (ischan != chanref			/* no possible match  */
+		|| !(u->special&(DEF|DEREF_DEF)))	/* not a def */
+			continue;
+
+		if (AST_mutual(u->n, n, 1))
+		{	AST_indirect(u, t, "(exact match)", pn);
+			continue;
+		}
+
+		if (chanref)
+		for (na = chalias; na; na = na->nxt)
+		{	if (!AST_mutual(u->n, na->cnm, 1))
+				continue;
+			for (ca = na->alias; ca; ca = ca->nxt)
+				if (AST_mutual(ca->cnm, n, 1)
+				&&  AST_isini(ca->cnm))	
+				{	AST_indirect(u, t, "(alias match)", pn);
+					break;
+				}
+			if (ca) break;
+	}	}	
+}
+
+static void
+AST_relevant(Lextok *n)
+{	AST *a;
+	FSM_state *f;
+	FSM_trans *t;
+	int ischan;
+
+	/* look for all DEF's of n
+	 *	mark those stmnts relevant
+	 *	mark all var USEs in those stmnts as criteria
+	 */
+
+	if (!n) return;
+	ischan = (Sym_typ(n) == CHAN);
+
+	if (verbose&32)
+	{	printf("<<ast_relevant (ntyp=%d) ", n->ntyp);
+		AST_var(n, n->sym, 1);
+		printf(">>\n");
+	}
+
+	for (t = expl_par; t; t = t->nxt)	/* param assignments */
+	{	if (!(t->relevant&1))
+		def_relevant(":params:", t, n, ischan);
+	}
+
+	for (t = expl_var; t; t = t->nxt)
+	{	if (!(t->relevant&1))		/* var inits */
+		def_relevant(":vars:", t, n, ischan);
+	}
+
+	for (a = ast; a; a = a->nxt)		/* all other stmnts */
+	{	if (strcmp(a->p->n->name, ":never:") != 0
+		&&  strcmp(a->p->n->name, ":trace:") != 0
+		&&  strcmp(a->p->n->name, ":notrace:") != 0)
+		for (f = a->fsm; f; f = f->nxt)
+		for (t = f->t; t; t = t->nxt)
+		{	if (!(t->relevant&1))
+			def_relevant(a->p->n->name, t, n, ischan);
+	}	}
+}
+
+static int
+AST_relpar(char *s)
+{	FSM_trans *t, *T;
+	FSM_use *u;
+
+	for (T = expl_par; T; T = (T == expl_par)?expl_var: (FSM_trans *) 0)
+	for (t = T; t; t = t->nxt)
+	{	if (t->relevant&1)
+		for (u = t->Val[0]; u; u = u->nxt)
+		{	if (u->n->sym->type
+			&&  u->n->sym->context
+			&&  strcmp(u->n->sym->context->name, s) == 0)
+			{
+				if (verbose&32)
+				{	printf("proctype %s relevant, due to symbol ", s);
+					AST_var(u->n, u->n->sym, 1);
+					printf("\n");
+				}
+				return 1;
+	}	}	}
+	return 0;
+}
+
+static void
+AST_dorelevant(void)
+{	AST *a;
+	RPN *r;
+
+	for (r = rpn; r; r = r->nxt)
+	{	for (a = ast; a; a = a->nxt)
+			if (strcmp(a->p->n->name, r->rn->name) == 0)
+			{	a->relevant |= 1;
+				break;
+			}
+		if (!a)
+		fatal("cannot find proctype %s", r->rn->name);
+	}		
+}
+
+static void
+AST_procisrelevant(Symbol *s)
+{	RPN *r;
+	for (r = rpn; r; r = r->nxt)
+		if (strcmp(r->rn->name, s->name) == 0)
+			return;
+	r = (RPN *) emalloc(sizeof(RPN));
+	r->rn = s;
+	r->nxt = rpn;
+	rpn = r;
+}
+
+static int
+AST_proc_isrel(char *s)
+{	AST *a;
+
+	for (a = ast; a; a = a->nxt)
+		if (strcmp(a->p->n->name, s) == 0)
+			return (a->relevant&1);
+	non_fatal("cannot happen, missing proc in ast", (char *) 0);
+	return 0;
+}
+
+static int
+AST_scoutrun(Lextok *t)
+{
+	if (!t) return 0;
+
+	if (t->ntyp == RUN)
+		return AST_proc_isrel(t->sym->name);
+	return (AST_scoutrun(t->lft) || AST_scoutrun(t->rgt));
+}
+
+static void
+AST_tagruns(void)
+{	AST *a;
+	FSM_state *f;
+	FSM_trans *t;
+
+	/* if any stmnt inside a proctype is relevant
+	 * or any parameter passed in a run
+	 * then so are all the run statements on that proctype
+	 */
+
+	for (a = ast; a; a = a->nxt)
+	{	if (strcmp(a->p->n->name, ":never:") == 0
+		||  strcmp(a->p->n->name, ":trace:") == 0
+		||  strcmp(a->p->n->name, ":notrace:") == 0
+		||  strcmp(a->p->n->name, ":init:") == 0)
+		{	a->relevant |= 1;	/* the proctype is relevant */
+			continue;
+		}
+		if (AST_relpar(a->p->n->name))
+			a->relevant |= 1;
+		else
+		{	for (f = a->fsm; f; f = f->nxt)
+			for (t = f->t; t; t = t->nxt)
+				if (t->relevant)
+					goto yes;
+yes:			if (f)
+				a->relevant |= 1;
+		}
+	}
+
+	for (a = ast; a; a = a->nxt)
+	for (f = a->fsm; f; f = f->nxt)
+	for (t = f->t; t; t = t->nxt)
+		if (t->step
+		&&  AST_scoutrun(t->step->n))
+		{	AST_indirect((FSM_use *)0, t, ":run:", a->p->n->name);
+			/* BUT, not all actual params are relevant */
+		}
+}
+
+static void
+AST_report(AST *a, Element *e)	/* ALSO deduce irrelevant vars */
+{
+	if (!(a->relevant&2))
+	{	a->relevant |= 2;
+		printf("spin: redundant in proctype %s (for given property):\n",
+			a->p->n->name);
+	}
+	printf("      line %3d %s (state %d)",
+		e->n?e->n->ln:-1,
+		e->n?e->n->fn->name:"-",
+		e->seqno);
+	printf("	[");
+	comment(stdout, e->n, 0);
+	printf("]\n");
+}
+
+static int
+AST_always(Lextok *n)
+{
+	if (!n) return 0;
+
+	if (n->ntyp == '@'	/* -end */
+	||  n->ntyp == 'p')	/* remote reference */
+		return 1;
+	return AST_always(n->lft) || AST_always(n->rgt);
+}
+
+static void
+AST_edge_dump(AST *a, FSM_state *f)
+{	FSM_trans *t;
+	FSM_use *u;
+
+	for (t = f->t; t; t = t->nxt)	/* edges */
+	{
+		if (t->step && AST_always(t->step->n))
+			t->relevant |= 1;	/* always relevant */
+
+		if (verbose&32)
+		{	switch (t->relevant) {
+			case  0: printf("     "); break;
+			case  1: printf("*%3d ", t->round); break;
+			case  2: printf("+%3d ", t->round); break;
+			case  3: printf("#%3d ", t->round); break;
+			default: printf("? "); break;
+			}
+	
+			printf("%d\t->\t%d\t", f->from, t->to);
+			if (t->step)
+				comment(stdout, t->step->n, 0);
+			else
+				printf("Unless");
+	
+			for (u = t->Val[0]; u; u = u->nxt)
+			{	printf(" <");
+				AST_var(u->n, u->n->sym, 1);
+				printf(":%d>", u->special);
+			}
+			printf("\n");
+		} else
+		{	if (t->relevant)
+				continue;
+
+			if (t->step)
+			switch(t->step->n->ntyp) {
+			case ASGN:
+			case 's':
+			case 'r':
+			case 'c':
+				if (t->step->n->lft->ntyp != CONST)
+					AST_report(a, t->step);
+				break;
+
+			case PRINT:	/* don't report */
+			case PRINTM:
+			case ASSERT:
+			case C_CODE:
+			case C_EXPR:
+			default:
+				break;
+	}	}	}
+}
+
+static void
+AST_dfs(AST *a, int s, int vis)
+{	FSM_state *f;
+	FSM_trans *t;
+
+	f = fsm_tbl[s];
+	if (f->seen) return;
+
+	f->seen = 1;
+	if (vis) AST_edge_dump(a, f);
+
+	for (t = f->t; t; t = t->nxt)
+		AST_dfs(a, t->to, vis);
+}
+
+static void
+AST_dump(AST *a)
+{	FSM_state *f;
+
+	for (f = a->fsm; f; f = f->nxt)
+	{	f->seen = 0;
+		fsm_tbl[f->from] = f;
+	}
+
+	if (verbose&32)
+		printf("AST_START %s from %d\n", a->p->n->name, a->i_st);
+
+	AST_dfs(a, a->i_st, 1);
+}
+
+static void
+AST_sends(AST *a)
+{	FSM_state *f;
+	FSM_trans *t;
+	FSM_use *u;
+	ChanList *cl;
+
+	for (f = a->fsm; f; f = f->nxt)		/* control states */
+	for (t = f->t; t; t = t->nxt)		/* transitions    */
+	{	if (t->step
+		&&  t->step->n
+		&&  t->step->n->ntyp == 's')
+		for (u = t->Val[0]; u; u = u->nxt)
+		{	if (Sym_typ(u->n) == CHAN
+			&&  ((u->special&USE) && !(u->special&DEREF_USE)))
+			{
+#if 0
+				printf("%s -- (%d->%d) -- ",
+					a->p->n->name, f->from, t->to);
+				AST_var(u->n, u->n->sym, 1);
+				printf(" -> chanlist\n");
+#endif
+				cl = (ChanList *) emalloc(sizeof(ChanList));
+				cl->s = t->step->n;
+				cl->n = u->n;
+				cl->nxt = chanlist;
+				chanlist = cl;
+}	}	}	}
+
+static ALIAS *
+AST_alfind(Lextok *n)
+{	ALIAS *na;
+
+	for (na = chalias; na; na = na->nxt)
+		if (AST_mutual(na->cnm, n, 1))
+			return na;
+	return (ALIAS *) 0;
+}
+
+static void
+AST_trans(void)
+{	ALIAS *na, *ca, *da, *ea;
+	int nchanges;
+
+	do {
+		nchanges = 0;
+		for (na = chalias; na; na = na->nxt)
+		{	chalcur = na;
+			for (ca = na->alias; ca; ca = ca->nxt)
+			{	da = AST_alfind(ca->cnm);
+				if (da)
+				for (ea = da->alias; ea; ea = ea->nxt)
+				{	nchanges += AST_add_alias(ea->cnm,
+							ea->origin|ca->origin);
+		}	}	}
+	} while (nchanges > 0);
+
+	chalcur = (ALIAS *) 0;
+}
+
+static void
+AST_def_use(AST *a)
+{	FSM_state *f;
+	FSM_trans *t;
+
+	for (f = a->fsm; f; f = f->nxt)		/* control states */
+	for (t = f->t; t; t = t->nxt)		/* all edges */
+	{	cur_t = t;
+		rel_use(t->Val[0]);		/* redo Val; doesn't cover structs */
+		rel_use(t->Val[1]);
+		t->Val[0] = t->Val[1] = (FSM_use *) 0;
+
+		if (!t->step) continue;
+
+		def_use(t->step->n, 0);		/* def/use info, including structs */
+	}
+	cur_t = (FSM_trans *) 0;
+}
+
+static void
+name_AST_track(Lextok *n, int code)
+{	extern int nr_errs;
+#if 0
+	printf("AST_name: ");
+	AST_var(n, n->sym, 1);
+	printf(" -- %d\n", code);
+#endif
+	if (in_recv && (code&DEF) && (code&USE))
+	{	printf("spin: error: DEF and USE of same var in rcv stmnt: ");
+		AST_var(n, n->sym, 1);
+		printf(" -- %d\n", code);
+		nr_errs++;
+	}
+	check_slice(n, code);
+}
+
+void
+AST_track(Lextok *now, int code)	/* called from main.c */
+{	Lextok *v; extern int export_ast;
+
+	if (!export_ast) return;
+
+	if (now)
+	switch (now->ntyp) {
+	case LEN:
+	case FULL:
+	case EMPTY:
+	case NFULL:
+	case NEMPTY:
+		AST_track(now->lft, DEREF_USE|USE|code);
+		break;
+
+	case '/':
+	case '*':
+	case '-':
+	case '+':
+	case '%':
+	case '&':
+	case '^':
+	case '|':
+	case LE:
+	case GE:
+	case GT:
+	case LT:
+	case NE:
+	case EQ:
+	case OR:
+	case AND:
+	case LSHIFT:
+	case RSHIFT:
+		AST_track(now->rgt, USE|code);
+		/* fall through */
+	case '!':	
+	case UMIN:	
+	case '~':
+	case 'c':
+	case ENABLED:
+	case ASSERT:
+		AST_track(now->lft, USE|code);
+		break;
+
+	case EVAL:
+		AST_track(now->lft, USE|(code&(~DEF)));
+		break;
+
+	case NAME:
+		name_AST_track(now, code);
+		if (now->sym->nel != 1)
+			AST_track(now->lft, USE|code);	/* index */
+		break;
+
+	case 'R':
+		AST_track(now->lft, DEREF_USE|USE|code);
+		for (v = now->rgt; v; v = v->rgt)
+			AST_track(v->lft, code); /* a deeper eval can add USE */
+		break;
+
+	case '?':
+		AST_track(now->lft, USE|code);
+		if (now->rgt)
+		{	AST_track(now->rgt->lft, code);
+			AST_track(now->rgt->rgt, code);
+		}
+		break;
+
+/* added for control deps: */
+	case TYPE:	
+		name_AST_track(now, code);
+		break;
+	case ASGN:
+		AST_track(now->lft, DEF|code);
+		AST_track(now->rgt, USE|code);
+		break;
+	case RUN:
+		name_AST_track(now, USE);
+		for (v = now->lft; v; v = v->rgt)
+			AST_track(v->lft, USE|code);
+		break;
+	case 's':
+		AST_track(now->lft, DEREF_DEF|DEREF_USE|USE|code);
+		for (v = now->rgt; v; v = v->rgt)
+			AST_track(v->lft, USE|code);
+		break;
+	case 'r':
+		AST_track(now->lft, DEREF_DEF|DEREF_USE|USE|code);
+		for (v = now->rgt; v; v = v->rgt)
+		{	in_recv++;
+			AST_track(v->lft, DEF|code);
+			in_recv--;
+		}
+		break;
+	case PRINT:
+		for (v = now->lft; v; v = v->rgt)
+			AST_track(v->lft, USE|code);
+		break;
+	case PRINTM:
+		AST_track(now->lft, USE);
+		break;
+/* end add */
+	case   'p':
+#if 0
+			   'p' -sym-> _p
+			   /
+			 '?' -sym-> a (proctype)
+			 /
+			b (pid expr)
+#endif
+		AST_track(now->lft->lft, USE|code);
+		AST_procisrelevant(now->lft->sym);
+		break;
+
+	case CONST:
+	case ELSE:
+	case NONPROGRESS:
+	case PC_VAL:
+	case   'q':
+		break;
+
+	case   '.':
+	case  GOTO:
+	case BREAK:
+	case   '@':
+	case D_STEP:
+	case ATOMIC:
+	case NON_ATOMIC:
+	case IF:
+	case DO:
+	case UNLESS:
+	case TIMEOUT:
+	case C_CODE:
+	case C_EXPR:
+		break;
+
+	default:
+		printf("AST_track, NOT EXPECTED ntyp: %d\n", now->ntyp);
+		break;
+	}
+}
+
+static int
+AST_dump_rel(void)
+{	Slicer *rv;
+	Ordered *walk;
+	char buf[64];
+	int banner=0;
+
+	if (verbose&32)
+	{	printf("Relevant variables:\n");
+		for (rv = rel_vars; rv; rv = rv->nxt)
+		{	printf("\t");
+			AST_var(rv->n, rv->n->sym, 1);
+			printf("\n");
+		}
+		return 1;
+	}
+	for (rv = rel_vars; rv; rv = rv->nxt)
+		rv->n->sym->setat = 1;	/* mark it */
+
+	for (walk = all_names; walk; walk = walk->next)
+	{	Symbol *s;
+		s = walk->entry;
+		if (!s->setat
+		&&  (s->type != MTYPE || s->ini->ntyp != CONST)
+		&&  s->type != STRUCT	/* report only fields */
+		&&  s->type != PROCTYPE
+		&&  !s->owner
+		&&  sputtype(buf, s->type))
+		{	if (!banner)
+			{	banner = 1;
+				printf("spin: redundant vars (for given property):\n");
+			}
+			printf("\t");
+			symvar(s);
+	}	}
+	return banner;
+}
+
+static void
+AST_suggestions(void)
+{	Symbol *s;
+	Ordered *walk;
+	FSM_state *f;
+	FSM_trans *t;
+	AST *a;
+	int banner=0;
+	int talked=0;
+
+	for (walk = all_names; walk; walk = walk->next)
+	{	s = walk->entry;
+		if (s->colnr == 2	/* only used in conditionals */
+		&&  (s->type == BYTE
+		||   s->type == SHORT
+		||   s->type == INT
+		||   s->type == MTYPE))
+		{	if (!banner)
+			{	banner = 1;
+				printf("spin: consider using predicate");
+				printf(" abstraction to replace:\n");
+			}
+			printf("\t");
+			symvar(s);
+	}	}
+
+	/* look for source and sink processes */
+
+	for (a = ast; a; a = a->nxt)		/* automata       */
+	{	banner = 0;
+		for (f = a->fsm; f; f = f->nxt)	/* control states */
+		for (t = f->t; t; t = t->nxt)	/* transitions    */
+		{	if (t->step)
+			switch (t->step->n->ntyp) {
+			case 's':
+				banner |= 1;
+				break;
+			case 'r':
+				banner |= 2;
+				break;
+			case '.':
+			case D_STEP:
+			case ATOMIC:
+			case NON_ATOMIC:
+			case IF:
+			case DO:
+			case UNLESS:
+			case '@':
+			case GOTO:
+			case BREAK:
+			case PRINT:
+			case PRINTM:
+			case ASSERT:
+			case C_CODE:
+			case C_EXPR:
+				break;
+			default:
+				banner |= 4;
+				goto no_good;
+			}
+		}
+no_good:	if (banner == 1 || banner == 2)
+		{	printf("spin: proctype %s defines a %s process\n",
+				a->p->n->name,
+				banner==1?"source":"sink");
+			talked |= banner;
+		} else if (banner == 3)
+		{	printf("spin: proctype %s mimics a buffer\n",
+				a->p->n->name);
+			talked |= 4;
+		}
+	}
+	if (talked&1)
+	{	printf("\tto reduce complexity, consider merging the code of\n");
+		printf("\teach source process into the code of its target\n");
+	}
+	if (talked&2)
+	{	printf("\tto reduce complexity, consider merging the code of\n");
+		printf("\teach sink process into the code of its source\n");
+	}
+	if (talked&4)
+		printf("\tto reduce complexity, avoid buffer processes\n");
+}
+
+static void
+AST_preserve(void)
+{	Slicer *sc, *nx, *rv;
+
+	for (sc = slicer; sc; sc = nx)
+	{	if (!sc->used)
+			break;	/* done */
+
+		nx = sc->nxt;
+
+		for (rv = rel_vars; rv; rv = rv->nxt)
+			if (AST_mutual(sc->n, rv->n, 1))
+				break;
+
+		if (!rv) /* not already there */
+		{	sc->nxt = rel_vars;
+			rel_vars = sc;
+	}	}
+	slicer = sc;
+}
+
+static void
+check_slice(Lextok *n, int code)
+{	Slicer *sc;
+
+	for (sc = slicer; sc; sc = sc->nxt)
+		if (AST_mutual(sc->n, n, 1)
+		&&  sc->code == code)
+			return;	/* already there */
+
+	sc = (Slicer *) emalloc(sizeof(Slicer));
+	sc->n = n;
+
+	sc->code = code;
+	sc->used = 0;
+	sc->nxt = slicer;
+	slicer = sc;
+}
+
+static void
+AST_data_dep(void)
+{	Slicer *sc;
+
+	/* mark all def-relevant transitions */
+	for (sc = slicer; sc; sc = sc->nxt)
+	{	sc->used = 1;
+		if (verbose&32)
+		{	printf("spin: slice criterion ");
+			AST_var(sc->n, sc->n->sym, 1);
+			printf(" type=%d\n", Sym_typ(sc->n));
+		}
+		AST_relevant(sc->n);
+	}
+	AST_tagruns();	/* mark 'run's relevant if target proctype is relevant */
+}
+
+static int
+AST_blockable(AST *a, int s)
+{	FSM_state *f;
+	FSM_trans *t;
+
+	f = fsm_tbl[s];
+
+	for (t = f->t; t; t = t->nxt)
+	{	if (t->relevant&2)
+			return 1;
+
+		if (t->step && t->step->n)
+		switch (t->step->n->ntyp) {
+		case IF:
+		case DO:
+		case ATOMIC:
+		case NON_ATOMIC:
+		case D_STEP:
+			if (AST_blockable(a, t->to))
+			{	t->round = AST_Round;
+				t->relevant |= 2;
+				return 1;
+			}
+			/* else fall through */
+		default:
+			break;
+		}
+		else if (AST_blockable(a, t->to))	/* Unless */
+		{	t->round = AST_Round;
+			t->relevant |= 2;
+			return 1;
+		}
+	}
+	return 0;
+}
+
+static void
+AST_spread(AST *a, int s)
+{	FSM_state *f;
+	FSM_trans *t;
+
+	f = fsm_tbl[s];
+
+	for (t = f->t; t; t = t->nxt)
+	{	if (t->relevant&2)
+			continue;
+
+		if (t->step && t->step->n)
+			switch (t->step->n->ntyp) {
+			case IF:
+			case DO:
+			case ATOMIC:
+			case NON_ATOMIC:
+			case D_STEP:
+				AST_spread(a, t->to);
+				/* fall thru */
+			default:
+				t->round = AST_Round;
+				t->relevant |= 2;
+				break;
+			}
+		else	/* Unless */
+		{	AST_spread(a, t->to);
+			t->round = AST_Round;
+			t->relevant |= 2;
+		}
+	}
+}
+
+static int
+AST_notrelevant(Lextok *n)
+{	Slicer *s;
+
+	for (s = rel_vars; s; s = s->nxt)
+		if (AST_mutual(s->n, n, 1))
+			return 0;
+	for (s = slicer; s; s = s->nxt)
+		if (AST_mutual(s->n, n, 1))
+			return 0;
+	return 1;
+}
+
+static int
+AST_withchan(Lextok *n)
+{
+	if (!n) return 0;
+	if (Sym_typ(n) == CHAN)
+		return 1;
+	return AST_withchan(n->lft) || AST_withchan(n->rgt);
+}
+
+static int
+AST_suspect(FSM_trans *t)
+{	FSM_use *u;
+	/* check for possible overkill */
+	if (!t || !t->step || !AST_withchan(t->step->n))
+		return 0;
+	for (u = t->Val[0]; u; u = u->nxt)
+		if (AST_notrelevant(u->n))
+			return 1;
+	return 0;
+}
+
+static void
+AST_shouldconsider(AST *a, int s)
+{	FSM_state *f;
+	FSM_trans *t;
+
+	f = fsm_tbl[s];
+	for (t = f->t; t; t = t->nxt)
+	{	if (t->step && t->step->n)
+			switch (t->step->n->ntyp) {
+			case IF:
+			case DO:
+			case ATOMIC:
+			case NON_ATOMIC:
+			case D_STEP:
+				AST_shouldconsider(a, t->to);
+				break;
+			default:
+				AST_track(t->step->n, 0);
+/*
+	AST_track is called here for a blockable stmnt from which
+	a relevant stmnmt was shown to be reachable
+	for a condition this makes all USEs relevant
+	but for a channel operation it only makes the executability
+	relevant -- in those cases, parameters that aren't already
+	relevant may be replaceable with arbitrary tokens
+ */
+				if (AST_suspect(t))
+				{	printf("spin: possibly redundant parameters in: ");
+					comment(stdout, t->step->n, 0);
+					printf("\n");
+				}
+				break;
+			}
+		else	/* an Unless */
+			AST_shouldconsider(a, t->to);
+	}
+}
+
+static int
+FSM_critical(AST *a, int s)
+{	FSM_state *f;
+	FSM_trans *t;
+
+	/* is a 1-relevant stmnt reachable from this state? */
+
+	f = fsm_tbl[s];
+	if (f->seen)
+		goto done;
+	f->seen = 1;
+	f->cr   = 0;
+	for (t = f->t; t; t = t->nxt)
+		if ((t->relevant&1)
+		||  FSM_critical(a, t->to))
+		{	f->cr = 1;
+
+			if (verbose&32)
+			{	printf("\t\t\t\tcritical(%d) ", t->relevant);
+				comment(stdout, t->step->n, 0);
+				printf("\n");
+			}
+			break;
+		}
+#if 0
+	else {
+		if (verbose&32)
+		{ printf("\t\t\t\tnot-crit ");
+		  comment(stdout, t->step->n, 0);
+	 	  printf("\n");
+		}
+	}
+#endif
+done:
+	return f->cr;
+}
+
+static void
+AST_ctrl(AST *a)
+{	FSM_state *f;
+	FSM_trans *t;
+	int hit;
+
+	/* add all blockable transitions
+	 * from which relevant transitions can be reached
+	 */
+	if (verbose&32)
+		printf("CTL -- %s\n", a->p->n->name);
+
+	/* 1 : mark all blockable edges */
+	for (f = a->fsm; f; f = f->nxt)
+	{	if (!(f->scratch&2))		/* not part of irrelevant subgraph */
+		for (t = f->t; t; t = t->nxt)
+		{	if (t->step && t->step->n)
+			switch (t->step->n->ntyp) {
+			case 'r':
+			case 's':
+			case 'c':
+			case ELSE:
+				t->round = AST_Round;
+				t->relevant |= 2;	/* mark for next phases */
+				if (verbose&32)
+				{	printf("\tpremark ");
+					comment(stdout, t->step->n, 0);
+					printf("\n");
+				}
+				break;
+			default:
+				break;
+	}	}	}
+
+	/* 2: keep only 2-marked stmnts from which 1-marked stmnts can be reached */
+	for (f = a->fsm; f; f = f->nxt)
+	{	fsm_tbl[f->from] = f;
+		f->seen = 0;	/* used in dfs from FSM_critical */
+	}
+	for (f = a->fsm; f; f = f->nxt)
+	{	if (!FSM_critical(a, f->from))
+		for (t = f->t; t; t = t->nxt)
+			if (t->relevant&2)
+			{	t->relevant &= ~2;	/* clear mark */
+				if (verbose&32)
+				{	printf("\t\tnomark ");
+					comment(stdout, t->step->n, 0);
+					printf("\n");
+	}		}	}
+
+	/* 3 : lift marks across IF/DO etc. */
+	for (f = a->fsm; f; f = f->nxt)
+	{	hit = 0;
+		for (t = f->t; t; t = t->nxt)
+		{	if (t->step && t->step->n)
+			switch (t->step->n->ntyp) {
+			case IF:
+			case DO:
+			case ATOMIC:
+			case NON_ATOMIC:
+			case D_STEP:
+				if (AST_blockable(a, t->to))
+					hit = 1;
+				break;
+			default:
+				break;
+			}
+			else if (AST_blockable(a, t->to))	/* Unless */
+				hit = 1;
+
+			if (hit) break;
+		}
+		if (hit)	/* at least one outgoing trans can block */
+		for (t = f->t; t; t = t->nxt)
+		{	t->round = AST_Round;
+			t->relevant |= 2;	/* lift */
+			if (verbose&32)
+			{	printf("\t\t\tliftmark ");
+				comment(stdout, t->step->n, 0);
+				printf("\n");
+			}
+			AST_spread(a, t->to);	/* and spread to all guards */
+	}	}
+
+	/* 4: nodes with 2-marked out-edges contribute new slice criteria */
+	for (f = a->fsm; f; f = f->nxt)
+	for (t = f->t; t; t = t->nxt)
+		if (t->relevant&2)
+		{	AST_shouldconsider(a, f->from);
+			break;	/* inner loop */
+		}
+}
+
+static void
+AST_control_dep(void)
+{	AST *a;
+
+	for (a = ast; a; a = a->nxt)
+		if (strcmp(a->p->n->name, ":never:") != 0
+		&&  strcmp(a->p->n->name, ":trace:") != 0
+		&&  strcmp(a->p->n->name, ":notrace:") != 0)
+			AST_ctrl(a);
+}
+
+static void
+AST_prelabel(void)
+{	AST *a;
+	FSM_state *f;
+	FSM_trans *t;
+
+	for (a = ast; a; a = a->nxt)
+	{	if (strcmp(a->p->n->name, ":never:") != 0
+		&&  strcmp(a->p->n->name, ":trace:") != 0
+		&&  strcmp(a->p->n->name, ":notrace:") != 0)
+		for (f = a->fsm; f; f = f->nxt)
+		for (t = f->t; t; t = t->nxt)
+		{	if (t->step
+			&&  t->step->n
+			&&  t->step->n->ntyp == ASSERT
+			)
+			{	t->relevant |= 1;
+	}	}	}
+}
+
+static void
+AST_criteria(void)
+{	/*
+	 * remote labels are handled separately -- by making
+	 * sure they are not pruned away during optimization
+	 */
+	AST_Changes = 1;	/* to get started */
+	for (AST_Round = 1; slicer && AST_Changes; AST_Round++)
+	{	AST_Changes = 0;
+		AST_data_dep();
+		AST_preserve();		/* moves processed vars from slicer to rel_vars */
+		AST_dominant();		/* mark data-irrelevant subgraphs */
+		AST_control_dep();	/* can add data deps, which add control deps */
+
+		if (verbose&32)
+			printf("\n\nROUND %d -- changes %d\n",
+				AST_Round, AST_Changes);
+	}
+}
+
+static void
+AST_alias_analysis(void)		/* aliasing of promela channels */
+{	AST *a;
+
+	for (a = ast; a; a = a->nxt)
+		AST_sends(a);		/* collect chan-names that are send across chans */
+
+	for (a = ast; a; a = a->nxt)
+		AST_para(a->p);		/* aliasing of chans thru proctype parameters */
+
+	for (a = ast; a; a = a->nxt)
+		AST_other(a);		/* chan params in asgns and recvs */
+
+	AST_trans();			/* transitive closure of alias table */
+
+	if (verbose&32)
+		AST_aliases();		/* show channel aliasing info */
+}
+
+void
+AST_slice(void)
+{	AST *a;
+	int spurious = 0;
+
+	if (!slicer)
+	{	non_fatal("no slice criteria (or no claim) specified",
+		(char *) 0);
+		spurious = 1;
+	}
+	AST_dorelevant();		/* mark procs refered to in remote refs */
+
+	for (a = ast; a; a = a->nxt)
+		AST_def_use(a);		/* compute standard def/use information */
+
+	AST_hidden();			/* parameter passing and local var inits */
+
+	AST_alias_analysis();		/* channel alias analysis */
+
+	AST_prelabel();			/* mark all 'assert(...)' stmnts as relevant */
+	AST_criteria();			/* process the slice criteria from
+					 * asserts and from the never claim
+					 */
+	if (!spurious || (verbose&32))
+	{	spurious = 1;
+		for (a = ast; a; a = a->nxt)
+		{	AST_dump(a);		/* marked up result */
+			if (a->relevant&2)	/* it printed something */
+				spurious = 0;
+		}
+		if (!AST_dump_rel()		/* relevant variables */
+		&&  spurious)
+			printf("spin: no redundancies found (for given property)\n");
+	}
+	AST_suggestions();
+
+	if (verbose&32)
+		show_expl();
+}
+
+void
+AST_store(ProcList *p, int start_state)
+{	AST *n_ast;
+
+	if (strcmp(p->n->name, ":never:") != 0
+	&&  strcmp(p->n->name, ":trace:") != 0
+	&&  strcmp(p->n->name, ":notrace:") != 0)
+	{	n_ast = (AST *) emalloc(sizeof(AST));
+		n_ast->p = p;
+		n_ast->i_st = start_state;
+		n_ast->relevant = 0;
+		n_ast->fsm = fsm;
+		n_ast->nxt = ast;
+		ast = n_ast;
+	}
+	fsm = (FSM_state *) 0;	/* hide it from FSM_DEL */
+}
+
+static void
+AST_add_explicit(Lextok *d, Lextok *u)
+{	FSM_trans *e = (FSM_trans *) emalloc(sizeof(FSM_trans));
+
+	e->to = 0;			/* or start_state ? */
+	e->relevant = 0;		/* to be determined */
+	e->step = (Element *) 0;	/* left blank */
+	e->Val[0] = e->Val[1] = (FSM_use *) 0;
+
+	cur_t = e;
+
+	def_use(u, USE);
+	def_use(d, DEF);
+
+	cur_t = (FSM_trans *) 0;
+
+	e->nxt = explicit;
+	explicit = e;
+}
+
+static void
+AST_fp1(char *s, Lextok *t, Lextok *f, int parno)
+{	Lextok *v;
+	int cnt;
+
+	if (!t) return;
+
+	if (t->ntyp == RUN)
+	{	if (strcmp(t->sym->name, s) == 0)
+		for (v = t->lft, cnt = 1; v; v = v->rgt, cnt++)
+			if (cnt == parno)
+			{	AST_add_explicit(f, v->lft);
+				break;
+			}
+	} else
+	{	AST_fp1(s, t->lft, f, parno);
+		AST_fp1(s, t->rgt, f, parno);
+	}
+}
+
+static void
+AST_mk1(char *s, Lextok *c, int parno)
+{	AST *a;
+	FSM_state *f;
+	FSM_trans *t;
+
+	/* concoct an extra FSM_trans *t with the asgn of
+	 * formal par c to matching actual pars made explicit
+	 */
+
+	for (a = ast; a; a = a->nxt)		/* automata       */
+	for (f = a->fsm; f; f = f->nxt)		/* control states */
+	for (t = f->t; t; t = t->nxt)		/* transitions    */
+	{	if (t->step)
+		AST_fp1(s, t->step->n, c, parno);
+	}
+}
+
+static void
+AST_par_init(void)	/* parameter passing -- hidden assignments */
+{	AST *a;
+	Lextok *f, *t, *c;
+	int cnt;
+
+	for (a = ast; a; a = a->nxt)
+	{	if (strcmp(a->p->n->name, ":never:") == 0
+		||  strcmp(a->p->n->name, ":trace:") == 0
+		||  strcmp(a->p->n->name, ":notrace:") == 0
+		||  strcmp(a->p->n->name, ":init:") == 0)
+			continue;			/* have no params */
+
+		cnt = 0;
+		for (f = a->p->p; f; f = f->rgt)	/* types */
+		for (t = f->lft; t; t = t->rgt)		/* formals */
+		{	cnt++;				/* formal par count */
+			c = (t->ntyp != ',')? t : t->lft;	/* the formal parameter */
+			AST_mk1(a->p->n->name, c, cnt);		/* all matching run statements */
+	}	}
+}
+
+static void
+AST_var_init(void)		/* initialized vars (not chans) - hidden assignments */
+{	Ordered	*walk;
+	Lextok *x;
+	Symbol	*sp;
+	AST *a;
+
+	for (walk = all_names; walk; walk = walk->next)	
+	{	sp = walk->entry;
+		if (sp
+		&&  !sp->context		/* globals */
+		&&  sp->type != PROCTYPE
+		&&  sp->ini
+		&& (sp->type != MTYPE || sp->ini->ntyp != CONST) /* not mtype defs */
+		&&  sp->ini->ntyp != CHAN)
+		{	x = nn(ZN, TYPE, ZN, ZN);
+			x->sym = sp;
+			AST_add_explicit(x, sp->ini);
+	}	}
+
+	for (a = ast; a; a = a->nxt)
+	{	if (strcmp(a->p->n->name, ":never:") != 0
+		&&  strcmp(a->p->n->name, ":trace:") != 0
+		&&  strcmp(a->p->n->name, ":notrace:") != 0)	/* claim has no locals */
+		for (walk = all_names; walk; walk = walk->next)	
+		{	sp = walk->entry;
+			if (sp
+			&&  sp->context
+			&&  strcmp(sp->context->name, a->p->n->name) == 0
+			&&  sp->Nid >= 0	/* not a param */
+			&&  sp->type != LABEL
+			&&  sp->ini
+			&&  sp->ini->ntyp != CHAN)
+			{	x = nn(ZN, TYPE, ZN, ZN);
+				x->sym = sp;
+				AST_add_explicit(x, sp->ini);
+	}	}	}
+}
+
+static void
+show_expl(void)
+{	FSM_trans *t, *T;
+	FSM_use *u;
+
+	printf("\nExplicit List:\n");
+	for (T = expl_par; T; T = (T == expl_par)?expl_var: (FSM_trans *) 0)
+	{	for (t = T; t; t = t->nxt)
+		{	if (!t->Val[0]) continue;
+			printf("%s", t->relevant?"*":" ");
+			printf("%3d", t->round);
+			for (u = t->Val[0]; u; u = u->nxt)
+			{	printf("\t<");
+				AST_var(u->n, u->n->sym, 1);
+				printf(":%d>, ", u->special);
+			}
+			printf("\n");
+		}
+		printf("==\n");
+	}
+	printf("End\n");
+}
+
+static void
+AST_hidden(void)			/* reveal all hidden assignments */
+{
+	AST_par_init();
+	expl_par = explicit;
+	explicit = (FSM_trans *) 0;
+
+	AST_var_init();
+	expl_var = explicit;
+	explicit = (FSM_trans *) 0;
+}
+
+#define BPW	(8*sizeof(ulong))			/* bits per word */
+
+static int
+bad_scratch(FSM_state *f, int upto)
+{	FSM_trans *t;
+#if 0
+	1. all internal branch-points have else-s
+	2. all non-branchpoints have non-blocking out-edge
+	3. all internal edges are non-relevant
+	subgraphs like this need NOT contribute control-dependencies
+#endif
+
+	if (!f->seen
+	||  (f->scratch&4))
+		return 0;
+
+	if (f->scratch&8)
+		return 1;
+
+	f->scratch |= 4;
+
+	if (verbose&32) printf("X[%d:%d:%d] ", f->from, upto, f->scratch);
+
+	if (f->scratch&1)
+	{	if (verbose&32)
+			printf("\tbad scratch: %d\n", f->from);
+bad:		f->scratch &= ~4;
+	/*	f->scratch |=  8;	 wrong */
+		return 1;
+	}
+
+	if (f->from != upto)
+	for (t = f->t; t; t = t->nxt)
+		if (bad_scratch(fsm_tbl[t->to], upto))
+			goto bad;
+
+	return 0;
+}
+
+static void
+mark_subgraph(FSM_state *f, int upto)
+{	FSM_trans *t;
+
+	if (f->from == upto
+	||  !f->seen
+	||  (f->scratch&2))
+		return;
+
+	f->scratch |= 2;
+
+	for (t = f->t; t; t = t->nxt)
+		mark_subgraph(fsm_tbl[t->to], upto);
+}
+
+static void
+AST_pair(AST *a, FSM_state *h, int y)
+{	Pair *p;
+
+	for (p = a->pairs; p; p = p->nxt)
+		if (p->h == h
+		&&  p->b == y)
+			return;
+
+	p = (Pair *) emalloc(sizeof(Pair));
+	p->h = h;
+	p->b = y;
+	p->nxt = a->pairs;
+	a->pairs = p;
+}
+
+static void
+AST_checkpairs(AST *a)
+{	Pair *p;
+
+	for (p = a->pairs; p; p = p->nxt)
+	{	if (verbose&32)
+			printf("	inspect pair %d %d\n", p->b, p->h->from);
+		if (!bad_scratch(p->h, p->b))	/* subgraph is clean */
+		{	if (verbose&32)
+				printf("subgraph: %d .. %d\n", p->b, p->h->from);
+			mark_subgraph(p->h, p->b);
+		}
+	}
+}
+
+static void
+subgraph(AST *a, FSM_state *f, int out)
+{	FSM_state *h;
+	int i, j;
+	ulong *g;
+#if 0
+	reverse dominance suggests that this is a possible
+	entry and exit node for a proper subgraph
+#endif
+	h = fsm_tbl[out];
+
+	i = f->from / BPW;
+	j = f->from % BPW;
+	g = h->mod;
+
+	if (verbose&32)
+		printf("possible pair %d %d -- %d\n",
+			f->from, h->from, (g[i]&(1<<j))?1:0);
+	
+	if (g[i]&(1<<j))		/* also a forward dominance pair */
+		AST_pair(a, h, f->from);	/* record this pair */
+}
+
+static void
+act_dom(AST *a)
+{	FSM_state *f;
+	FSM_trans *t;
+	int i, j, cnt;
+
+	for (f = a->fsm; f; f = f->nxt)
+	{	if (!f->seen) continue;
+#if 0
+		f->from is the exit-node of a proper subgraph, with
+		the dominator its entry-node, if:
+		a. this node has more than 1 reachable predecessor
+		b. the dominator has more than 1 reachable successor
+		   (need reachability - in case of reverse dominance)
+		d. the dominator is reachable, and not equal to this node
+#endif
+		for (t = f->p, i = 0; t; t = t->nxt)
+			i += fsm_tbl[t->to]->seen;
+		if (i <= 1) continue;					/* a. */
+
+		for (cnt = 1; cnt < a->nstates; cnt++)	/* 0 is endstate */
+		{	if (cnt == f->from
+			||  !fsm_tbl[cnt]->seen)
+				continue;				/* c. */
+
+			i = cnt / BPW;
+			j = cnt % BPW;
+			if (!(f->dom[i]&(1<<j)))
+				continue;
+
+			for (t = fsm_tbl[cnt]->t, i = 0; t; t = t->nxt)
+				i += fsm_tbl[t->to]->seen;
+			if (i <= 1)
+				continue;				/* b. */
+
+			if (f->mod)			/* final check in 2nd phase */
+				subgraph(a, f, cnt);	/* possible entry-exit pair */
+		}
+	}
+}
+
+static void
+reachability(AST *a)
+{	FSM_state *f;
+
+	for (f = a->fsm; f; f = f->nxt)
+		f->seen = 0;		/* clear */
+	AST_dfs(a, a->i_st, 0);		/* mark 'seen' */
+}
+
+static int
+see_else(FSM_state *f)
+{	FSM_trans *t;
+
+	for (t = f->t; t; t = t->nxt)
+	{	if (t->step
+		&&  t->step->n)
+		switch (t->step->n->ntyp) {
+		case ELSE:
+			return 1;
+		case IF:
+		case DO:
+		case ATOMIC:
+		case NON_ATOMIC:
+		case D_STEP:
+			if (see_else(fsm_tbl[t->to]))
+				return 1;
+		default:
+			break;
+		}
+	}
+	return 0;
+}
+
+static int
+is_guard(FSM_state *f)
+{	FSM_state *g;
+	FSM_trans *t;
+
+	for (t = f->p; t; t = t->nxt)
+	{	g = fsm_tbl[t->to];
+		if (!g->seen)
+			continue;
+
+		if (t->step
+		&&  t->step->n)
+		switch(t->step->n->ntyp) {
+		case IF:
+		case DO:
+			return 1;
+		case ATOMIC:
+		case NON_ATOMIC:
+		case D_STEP:
+			if (is_guard(g))
+				return 1;
+		default:
+			break;
+		}
+	}
+	return 0;
+}
+
+static void
+curtail(AST *a)
+{	FSM_state *f, *g;
+	FSM_trans *t;
+	int i, haselse, isrel, blocking;
+#if 0
+	mark nodes that do not satisfy these requirements:
+	1. all internal branch-points have else-s
+	2. all non-branchpoints have non-blocking out-edge
+	3. all internal edges are non-data-relevant
+#endif
+	if (verbose&32)
+		printf("Curtail %s:\n", a->p->n->name);
+
+	for (f = a->fsm; f; f = f->nxt)
+	{	if (!f->seen
+		||  (f->scratch&(1|2)))
+			continue;
+
+		isrel = haselse = i = blocking = 0;
+
+		for (t = f->t; t; t = t->nxt)
+		{	g = fsm_tbl[t->to];
+
+			isrel |= (t->relevant&1);	/* data relevant */
+			i += g->seen;
+
+			if (t->step
+			&&  t->step->n)
+			{	switch (t->step->n->ntyp) {
+				case IF:
+				case DO:
+					haselse |= see_else(g);
+					break;
+				case 'c':
+				case 's':
+				case 'r':
+					blocking = 1;
+					break;
+		}	}	}
+#if 0
+		if (verbose&32)
+			printf("prescratch %d -- %d %d %d %d -- %d\n",
+				f->from, i, isrel, blocking, haselse, is_guard(f));
+#endif
+		if (isrel			/* 3. */		
+		||  (i == 1 && blocking)	/* 2. */
+		||  (i >  1 && !haselse))	/* 1. */
+		{	if (!is_guard(f))
+			{	f->scratch |= 1;
+				if (verbose&32)
+				printf("scratch %d -- %d %d %d %d\n",
+					f->from, i, isrel, blocking, haselse);
+			}
+		}
+	}
+}
+
+static void
+init_dom(AST *a)
+{	FSM_state *f;
+	int i, j, cnt;
+#if 0
+	(1)  D(s0) = {s0}
+	(2)  for s in S - {s0} do D(s) = S
+#endif
+
+	for (f = a->fsm; f; f = f->nxt)
+	{	if (!f->seen) continue;
+
+		f->dom = (ulong *)
+			emalloc(a->nwords * sizeof(ulong));
+
+		if (f->from == a->i_st)
+		{	i = a->i_st / BPW;
+			j = a->i_st % BPW;
+			f->dom[i] = (1<<j);			/* (1) */
+		} else						/* (2) */
+		{	for (i = 0; i < a->nwords; i++)
+				f->dom[i] = (ulong) ~0;			/* all 1's */
+
+			if (a->nstates % BPW)
+			for (i = a->nstates % BPW; i < BPW; i++)
+				f->dom[a->nwords-1] &= ~(1<<i);	/* clear tail */
+
+			for (cnt = 0; cnt < a->nstates; cnt++)
+				if (!fsm_tbl[cnt]->seen)
+				{	i = cnt / BPW;
+					j = cnt % BPW;
+					f->dom[i] &= ~(1<<j);
+	}	}		}
+}
+
+static int
+dom_perculate(AST *a, FSM_state *f)
+{	static ulong *ndom = (ulong *) 0;
+	static int on = 0;
+	int i, j, cnt = 0;
+	FSM_state *g;
+	FSM_trans *t;
+
+	if (on < a->nwords)
+	{	on = a->nwords;
+		ndom = (ulong *)
+			emalloc(on * sizeof(ulong));
+	}
+
+	for (i = 0; i < a->nwords; i++)
+		ndom[i] = (ulong) ~0;
+
+	for (t = f->p; t; t = t->nxt)	/* all reachable predecessors */
+	{	g = fsm_tbl[t->to];
+		if (g->seen)
+		for (i = 0; i < a->nwords; i++)
+			ndom[i] &= g->dom[i];	/* (5b) */
+	}
+
+	i = f->from / BPW;
+	j = f->from % BPW;
+	ndom[i] |= (1<<j);			/* (5a) */
+
+	for (i = 0; i < a->nwords; i++)
+		if (f->dom[i] != ndom[i])
+		{	cnt++;
+			f->dom[i] = ndom[i];
+		}
+
+	return cnt;
+}
+
+static void
+dom_forward(AST *a)
+{	FSM_state *f;
+	int cnt;
+
+	init_dom(a);						/* (1,2) */
+	do {
+		cnt = 0;
+		for (f = a->fsm; f; f = f->nxt)
+		{	if (f->seen
+			&&  f->from != a->i_st)			/* (4) */
+				cnt += dom_perculate(a, f);	/* (5) */
+		}
+	} while (cnt);						/* (3) */
+	dom_perculate(a, fsm_tbl[a->i_st]);
+}
+
+static void
+AST_dominant(void)
+{	FSM_state *f;
+	FSM_trans *t;
+	AST *a;
+	int oi;
+#if 0
+	find dominators
+	Aho, Sethi, & Ullman, Compilers - principles, techniques, and tools
+	Addison-Wesley, 1986, p.671.
+
+	(1)  D(s0) = {s0}
+	(2)  for s in S - {s0} do D(s) = S
+
+	(3)  while any D(s) changes do
+	(4)    for s in S - {s0} do
+	(5)	D(s) = {s} union  with intersection of all D(p)
+		where p are the immediate predecessors of s
+
+	the purpose is to find proper subgraphs
+	(one entry node, one exit node)
+#endif
+	if (AST_Round == 1)	/* computed once, reused in every round */
+	for (a = ast; a; a = a->nxt)
+	{	a->nstates = 0;
+		for (f = a->fsm; f; f = f->nxt)
+		{	a->nstates++;				/* count */
+			fsm_tbl[f->from] = f;			/* fast lookup */
+			f->scratch = 0;				/* clear scratch marks */
+		}
+		for (oi = 0; oi < a->nstates; oi++)
+			if (!fsm_tbl[oi])
+				fsm_tbl[oi] = &no_state;
+
+		a->nwords = (a->nstates + BPW - 1) / BPW;	/* round up */
+
+		if (verbose&32)
+		{	printf("%s (%d): ", a->p->n->name, a->i_st);
+			printf("states=%d (max %d), words = %d, bpw %d, overflow %d\n",
+				a->nstates, o_max, a->nwords,
+				(int) BPW, (int) (a->nstates % BPW));
+		}
+
+		reachability(a);
+		dom_forward(a);		/* forward dominance relation */
+
+		curtail(a);		/* mark ineligible edges */
+		for (f = a->fsm; f; f = f->nxt)
+		{	t = f->p;
+			f->p = f->t;
+			f->t = t;	/* invert edges */
+
+			f->mod = f->dom;
+			f->dom = (ulong *) 0;
+		}
+		oi = a->i_st;
+		if (fsm_tbl[0]->seen)	/* end-state reachable - else leave it */
+			a->i_st = 0;	/* becomes initial state */
+	
+		dom_forward(a);		/* reverse dominance -- don't redo reachability! */
+		act_dom(a);		/* mark proper subgraphs, if any */
+		AST_checkpairs(a);	/* selectively place 2 scratch-marks */
+
+		for (f = a->fsm; f; f = f->nxt)
+		{	t = f->p;
+			f->p = f->t;
+			f->t = t;	/* restore */
+		}
+		a->i_st = oi;	/* restore */
+	} else
+		for (a = ast; a; a = a->nxt)
+		{	for (f = a->fsm; f; f = f->nxt)
+			{	fsm_tbl[f->from] = f;
+				f->scratch &= 1; /* preserve 1-marks */
+			}
+			for (oi = 0; oi < a->nstates; oi++)
+				if (!fsm_tbl[oi])
+					fsm_tbl[oi] = &no_state;
+
+			curtail(a);		/* mark ineligible edges */
+
+			for (f = a->fsm; f; f = f->nxt)
+			{	t = f->p;
+				f->p = f->t;
+				f->t = t;	/* invert edges */
+			}
+	
+			AST_checkpairs(a);	/* recompute 2-marks */
+
+			for (f = a->fsm; f; f = f->nxt)
+			{	t = f->p;
+				f->p = f->t;
+				f->t = t;	/* restore */
+		}	}
+}

+ 32 - 19
sys/src/cmd/spin/pc_zpp.c

@@ -1,13 +1,16 @@
 /***** spin: pc_zpp.c *****/
 /***** spin: pc_zpp.c *****/
 
 
-/* Copyright (c) 1997-2000 by Lucent Technologies - Bell Laboratories     */
+/* Copyright (c) 1997-2003 by Lucent Technologies, Bell Laboratories.     */
 /* All Rights Reserved.  This software is for educational purposes only.  */
 /* All Rights Reserved.  This software is for educational purposes only.  */
-/* Permission is given to distribute this code provided that this intro-  */
-/* ductory message is not removed and no monies are exchanged.            */
-/* No guarantee is expressed or implied by the distribution of this code. */
-/* Software written by Gerard J. Holzmann, gerard@research.bell-labs.com  */
-/* pc_zpp.c is only used in the PC version of Spin, to avoid too great a  */
-/* reliance on the cpp command.                                           */
+/* No guarantee whatsoever is expressed or implied by the distribution of */
+/* this code.  Permission is given to distribute this code provided that  */
+/* this introductory message is not removed and no monies are exchanged.  */
+/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
+/*             http://spinroot.com/                                       */
+/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
+
+/* pc_zpp.c is only used in the PC version of Spin                        */
+/* it is included to avoid too great a reliance on an external cpp        */
 
 
 #include <stdlib.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <stdio.h>
@@ -20,16 +23,17 @@ enum cstate { PLAIN, IN_STRING, IN_QUOTE, S_COMM, COMMENT, E_COMM };
 #define MAXNEST	32
 #define MAXNEST	32
 #define MAXDEF	128
 #define MAXDEF	128
 #define MAXLINE	512
 #define MAXLINE	512
+#define GENEROUS 4096
 
 
 #define debug(x,y)	if (verbose) printf(x,y)
 #define debug(x,y)	if (verbose) printf(x,y)
 
 
-static FILE *outpp = stdout;
+static FILE *outpp /* = stdout */;
 
 
 static int if_truth[MAXNEST];
 static int if_truth[MAXNEST];
 static int printing[MAXNEST];
 static int printing[MAXNEST];
 static int if_depth, nr_defs, verbose = 0;
 static int if_depth, nr_defs, verbose = 0;
 static enum cstate state = PLAIN;
 static enum cstate state = PLAIN;
-static char Out1[4096], Out2[4096];
+static char Out1[GENEROUS], Out2[GENEROUS];
 
 
 static struct Defines {
 static struct Defines {
 	int exists;
 	int exists;
@@ -39,6 +43,8 @@ static struct Defines {
 static int process(char *, int, char *);
 static int process(char *, int, char *);
 static int zpp_do(char *);
 static int zpp_do(char *);
 
 
+extern char *emalloc(int);	/* main.c */
+
 static int
 static int
 do_define(char *p)
 do_define(char *p)
 {	char *q, *r, *s;
 {	char *q, *r, *s;
@@ -73,8 +79,8 @@ do_define(char *p)
 adddef:		for (j = 0; j < nr_defs; j++)
 adddef:		for (j = 0; j < nr_defs; j++)
 			if (!strcmp(d[j].src, q))
 			if (!strcmp(d[j].src, q))
 				d[j].exists = 0;
 				d[j].exists = 0;
-		d[nr_defs].src = malloc(strlen(q)+1);
-		d[nr_defs].trg = malloc(strlen(s)+1);
+		d[nr_defs].src = emalloc(strlen(q)+1);
+		d[nr_defs].trg = emalloc(strlen(s)+1);
 		strcpy(d[nr_defs].src, q);
 		strcpy(d[nr_defs].src, q);
 		strcpy(d[nr_defs].trg, s);
 		strcpy(d[nr_defs].trg, s);
 		d[nr_defs++].exists = 1;
 		d[nr_defs++].exists = 1;
@@ -98,7 +104,7 @@ apply(char *p0)
 
 
 	for (i = nr_defs-1; i >= 0; i--)
 	for (i = nr_defs-1; i >= 0; i--)
 	{	if (!d[i].exists) continue;
 	{	if (!d[i].exists) continue;
-		j = strlen(d[i].src);
+		j = (int) strlen(d[i].src);
 more:		in2 = strstr(startat, d[i].src);
 more:		in2 = strstr(startat, d[i].src);
 		if (!in2)	/* no more matches */
 		if (!in2)	/* no more matches */
 		{	startat = in1;
 		{	startat = in1;
@@ -107,6 +113,13 @@ more:		in2 = strstr(startat, d[i].src);
 		if ((in2 == in1 || !isvalid(*(in2-1)))
 		if ((in2 == in1 || !isvalid(*(in2-1)))
 		&&  (in2+j == '\0' || !isvalid(*(in2+j))))
 		&&  (in2+j == '\0' || !isvalid(*(in2+j))))
 		{	*in2 = '\0';
 		{	*in2 = '\0';
+
+			if (strlen(in1)+strlen(d[i].trg)+strlen(in2+j) >= GENEROUS)
+			{
+				printf("spin: circular macro expansion %s -> %s ?\n",
+					d[i].src, d[i].trg);
+				return in1;
+			}
 			strcat(out, in1);
 			strcat(out, in1);
 			strcat(out, d[i].trg);
 			strcat(out, d[i].trg);
 			strcat(out, in2+j);
 			strcat(out, in2+j);
@@ -217,7 +230,7 @@ do_if(char *p)
 }
 }
 
 
 static int
 static int
-do_else(char *p)
+do_else(char *unused)
 {
 {
 	if_truth[if_depth] = 1-if_truth[if_depth];
 	if_truth[if_depth] = 1-if_truth[if_depth];
 	printing[if_depth] = printing[if_depth-1]&&if_truth[if_depth];
 	printing[if_depth] = printing[if_depth-1]&&if_truth[if_depth];
@@ -304,13 +317,13 @@ zpp_do(char *fnm)
 	FILE *inp; int lno = 0, nw_lno = 0;
 	FILE *inp; int lno = 0, nw_lno = 0;
 
 
 	if ((inp = fopen(fnm, "r")) == NULL)
 	if ((inp = fopen(fnm, "r")) == NULL)
-	{	debug("error: cannot open %s\n", fnm);
-		return 0;
+	{	fprintf(stdout, "spin: error, '%s': No such file\n", fnm);
+		return 0;	/* 4.1.2 was stderr */
 	}
 	}
 	printing[0] = if_truth[0] = 1;
 	printing[0] = if_truth[0] = 1;
 	fprintf(outpp, "#line %d \"%s\"\n", lno+1, fnm);
 	fprintf(outpp, "#line %d \"%s\"\n", lno+1, fnm);
 	while (fgets(buf, MAXLINE, inp))
 	while (fgets(buf, MAXLINE, inp))
-	{	lno++; n = strlen(buf);
+	{	lno++; n = (int) strlen(buf);
 		on = 0; nw_lno = 0;
 		on = 0; nw_lno = 0;
 		while (n > 2 && buf[n-2] == '\\')
 		while (n > 2 && buf[n-2] == '\\')
 		{	buf[n-2] = '\0';
 		{	buf[n-2] = '\0';
@@ -324,7 +337,7 @@ feedme:			if (!fgets(buf2, MAXLINE, inp))
 				return 0;
 				return 0;
 			}
 			}
 			strcat(buf, buf2);
 			strcat(buf, buf2);
-			n = strlen(buf);
+			n = (int) strlen(buf);
 		}
 		}
 		if (in_comment(&buf[on]))
 		if (in_comment(&buf[on]))
 		{	buf[n-1] = '\0'; /* eat newline */
 		{	buf[n-1] = '\0'; /* eat newline */
@@ -348,8 +361,8 @@ int
 try_zpp(char *fnm, char *onm)
 try_zpp(char *fnm, char *onm)
 {	int r;
 {	int r;
 	if ((outpp = fopen(onm, "w")) == NULL)
 	if ((outpp = fopen(onm, "w")) == NULL)
-		return 0;
-	r = zpp_do(fnm);
+		return 0;
+	r = zpp_do(fnm);
 	fclose(outpp);
 	fclose(outpp);
 	return r;	/* 1 = ok; 0 = use cpp */
 	return r;	/* 1 = ok; 0 = use cpp */
 }
 }

+ 42 - 31
sys/src/cmd/spin/ps_msc.c

@@ -1,10 +1,13 @@
 /***** spin: ps_msc.c *****/
 /***** spin: ps_msc.c *****/
 
 
-/* Copyright (c) 1997-2000 by Lucent Technologies - Bell Laboratories.    */
+/* Copyright (c) 1997-2003 by Lucent Technologies, Bell Laboratories.     */
 /* All Rights Reserved.  This software is for educational purposes only.  */
 /* All Rights Reserved.  This software is for educational purposes only.  */
-/* Permission is given to distribute this code provided that this intro-  */
-/* ductory message is not removed and no monies are exchanged.            */
-/* No guarantee is expressed or implied by the distribution of this code. */
+/* No guarantee whatsoever is expressed or implied by the distribution of */
+/* this code.  Permission is given to distribute this code provided that  */
+/* this introductory message is not removed and no monies are exchanged.  */
+/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
+/*             http://spinroot.com/                                       */
+/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
 
 
 /* The Postscript generation code below was written by Gerard J. Holzmann */
 /* The Postscript generation code below was written by Gerard J. Holzmann */
 /* in June 1997. Parts of the prolog template are based on similar boiler */
 /* in June 1997. Parts of the prolog template are based on similar boiler */
@@ -14,6 +17,10 @@
 #include "spin.h"
 #include "spin.h"
 #include "version.h"
 #include "version.h"
 
 
+#ifdef PC
+extern void free(void *);
+#endif
+
 static char *PsPre[] = {
 static char *PsPre[] = {
 	"%%%%Pages: (atend)",
 	"%%%%Pages: (atend)",
 	"%%%%PageOrder: Ascend",
 	"%%%%PageOrder: Ascend",
@@ -121,10 +128,10 @@ static char	**L;		/* text labels */
 static char	*ProcLine;	/* active processes */
 static char	*ProcLine;	/* active processes */
 static int	pspno = 0;	/* postscript page */
 static int	pspno = 0;	/* postscript page */
 static int	ldepth = 1;
 static int	ldepth = 1;
-static int	maxx, TotSteps = 4096; /* max nr of steps, about 40 pages */
+static int	maxx, TotSteps = 2*4096; /* max nr of steps, about 40 pages */
 static float	Scaler = (float) 1.0;
 static float	Scaler = (float) 1.0;
 
 
-extern int	nproc, nstop, ntrail, s_trail, pno, depth;
+extern int	ntrail, s_trail, pno, depth;
 extern Symbol	*oFname;
 extern Symbol	*oFname;
 extern void	exit(int);
 extern void	exit(int);
 void putpages(void);
 void putpages(void);
@@ -151,7 +158,7 @@ startpage(void)
 	fprintf(pfd, "%%%%Page: %d %d\n", pspno, pspno);
 	fprintf(pfd, "%%%%Page: %d %d\n", pspno, pspno);
 	putlegend();
 	putlegend();
 
 
-	for (i = 255; i >= 0; i--)
+	for (i = TotSteps-1; i >= 0; i--)
 	{	if (!I[i]) continue;
 	{	if (!I[i]) continue;
 		spitbox(i, RH, -PH, I[i]);
 		spitbox(i, RH, -PH, I[i]);
 	}
 	}
@@ -161,11 +168,7 @@ startpage(void)
 	fprintf(pfd, "%d %d lineto\n", RH+MW, LH+oMH+5);
 	fprintf(pfd, "%d %d lineto\n", RH+MW, LH+oMH+5);
 	fprintf(pfd, "%d %d lineto\n", RH+MW, LH);
 	fprintf(pfd, "%d %d lineto\n", RH+MW, LH);
 	fprintf(pfd, "10 %d lineto\n", LH);
 	fprintf(pfd, "10 %d lineto\n", LH);
-#if 0
-	fprintf(pfd, "closepath\n");
-#else
 	fprintf(pfd, "closepath clip newpath\n");
 	fprintf(pfd, "closepath clip newpath\n");
-#endif
 	fprintf(pfd, "%f %f translate\n",
 	fprintf(pfd, "%f %f translate\n",
 		(float) RH, (float) LH);
 		(float) RH, (float) LH);
 	memset(ProcLine, 0, 256*sizeof(char));
 	memset(ProcLine, 0, 256*sizeof(char));
@@ -189,9 +192,9 @@ putprelude(void)
 
 
 	if (s_trail)
 	if (s_trail)
 	{	if (ntrail)
 	{	if (ntrail)
-		sprintf(snap, "%s%d.trail", oFname->name, ntrail);
+		sprintf(snap, "%s%d.trail", oFname?oFname->name:"msc", ntrail);
 		else
 		else
-		sprintf(snap, "%s.trail", oFname->name);
+		sprintf(snap, "%s.trail", oFname?oFname->name:"msc");
 		if (!(fd = fopen(snap, "r")))
 		if (!(fd = fopen(snap, "r")))
 		{	snap[strlen(snap)-2] = '\0';
 		{	snap[strlen(snap)-2] = '\0';
 			if (!(fd = fopen(snap, "r")))
 			if (!(fd = fopen(snap, "r")))
@@ -206,8 +209,8 @@ putprelude(void)
 	M = (short *) emalloc(TotSteps * sizeof(short));
 	M = (short *) emalloc(TotSteps * sizeof(short));
 	T = (short *) emalloc(TotSteps * sizeof(short));
 	T = (short *) emalloc(TotSteps * sizeof(short));
 	L = (char **) emalloc(TotSteps * sizeof(char *));
 	L = (char **) emalloc(TotSteps * sizeof(char *));
-	I = (char **) emalloc(256 * sizeof(char *));
-	ProcLine = (char *) emalloc(256 * sizeof(char));
+	I = (char **) emalloc(TotSteps * sizeof(char *));
+	ProcLine = (char *) emalloc(1024 * sizeof(char));
 	startpage();
 	startpage();
 }
 }
 
 
@@ -226,13 +229,10 @@ putpostlude(void)
 }
 }
 void
 void
 psline(int x0, int iy0, int x1, int iy1, float r, float g, float b, int w)
 psline(int x0, int iy0, int x1, int iy1, float r, float g, float b, int w)
-{
-	int y0 = MH-iy0;
+{	int y0 = MH-iy0;
 	int y1 = MH-iy1;
 	int y1 = MH-iy1;
-	int dx = 5;
 
 
 	if (y1 > y0) y1 -= MH;
 	if (y1 > y0) y1 -= MH;
-	if (x0 > x1) dx = -5;
 
 
 	fprintf(pfd, "gsave\n");
 	fprintf(pfd, "gsave\n");
 	fprintf(pfd, "%d %d moveto\n", x0*WW, y0);
 	fprintf(pfd, "%d %d moveto\n", x0*WW, y0);
@@ -268,13 +268,15 @@ putgrid(int p)
 }
 }
 
 
 void
 void
-putarrow(int from, int to) { T[D[from]] = D[to]; }
+putarrow(int from, int to)
+{
+	T[D[from]] = D[to];
+}
 
 
 void
 void
 stepnumber(int i)
 stepnumber(int i)
 {	int y = MH-(i*HH)%MH;
 {	int y = MH-(i*HH)%MH;
 
 
-/*	if (y == MH) y -= 5; */
 	fprintf(pfd, "gsave\n");
 	fprintf(pfd, "gsave\n");
 	fprintf(pfd, "/Courier-Bold findfont 6 scalefont ");
 	fprintf(pfd, "/Courier-Bold findfont 6 scalefont ");
 	fprintf(pfd, "ISOEncode setfont\n");
 	fprintf(pfd, "ISOEncode setfont\n");
@@ -318,11 +320,11 @@ spitbox(int x, int dx, int y, char *s)
 	} else
 	} else
 	{	r = (float) 1.; g = (float) 1.; b = (float) 0.;
 	{	r = (float) 1.; g = (float) 1.; b = (float) 0.;
 		if (!dx
 		if (!dx
-		&&  sscanf(s, "%d:%s", &a, &d) == 2
-		&&  a >= 0 && a <= 255)
+		&&  sscanf(s, "%d:%s", &a, d) == 2	/* was &d */
+		&&  a >= 0 && a < TotSteps)
 		{	if (!I[a]
 		{	if (!I[a]
 			||  strlen(I[a]) <= strlen(s))
 			||  strlen(I[a]) <= strlen(s))
-				I[a] = emalloc(strlen(s)+1);
+				I[a] = emalloc((int) strlen(s)+1);
 			strcpy(I[a], s);
 			strcpy(I[a], s);
 	}	}
 	}	}
 	colbox(x*WW+dx, MH-(y*HH)%MH, (int) bw, 4, r,g,b);
 	colbox(x*WW+dx, MH-(y*HH)%MH, (int) bw, 4, r,g,b);
@@ -338,7 +340,6 @@ spitbox(int x, int dx, int y, char *s)
 void
 void
 putpages(void)
 putpages(void)
 {	int i, lasti=0; float nmh;
 {	int i, lasti=0; float nmh;
-/*	extern int free(void *); */
 
 
 	if (maxx*WW > MW-RH/2)
 	if (maxx*WW > MW-RH/2)
 	{	Scaler = (float) (MW-RH/2) / (float) (maxx*WW);
 	{	Scaler = (float) (MW-RH/2) / (float) (maxx*WW);
@@ -346,7 +347,7 @@ putpages(void)
 		nmh = (float) MH; nmh /= Scaler; MH = (int) nmh;
 		nmh = (float) MH; nmh /= Scaler; MH = (int) nmh;
 	}
 	}
 
 
-	for (i = 255; i >= 0; i--)
+	for (i = TotSteps-1; i >= 0; i--)
 	{	if (!I[i]) continue;
 	{	if (!I[i]) continue;
 		spitbox(i, 0, 0, I[i]);
 		spitbox(i, 0, 0, I[i]);
 	}
 	}
@@ -397,7 +398,7 @@ putbox(int x)
 {
 {
 	if (ldepth >= TotSteps)
 	if (ldepth >= TotSteps)
 	{	putpostlude();
 	{	putpostlude();
-		fprintf(stderr, "max length of %d steps exceeded",
+		fprintf(stderr, "max length of %d steps exceeded\n",
 			TotSteps);
 			TotSteps);
 		fatal("postscript file truncated", (char *) 0);
 		fatal("postscript file truncated", (char *) 0);
 	}
 	}
@@ -407,13 +408,19 @@ putbox(int x)
 
 
 void
 void
 pstext(int x, char *s)
 pstext(int x, char *s)
-{	char *tmp = emalloc(strlen(s)+1);
+{	char *tmp = emalloc((int) strlen(s)+1);
 
 
 	strcpy(tmp, s);
 	strcpy(tmp, s);
 	if (depth == 0)
 	if (depth == 0)
 		I[x] = tmp;
 		I[x] = tmp;
 	else
 	else
 	{	putbox(x);
 	{	putbox(x);
+		if (depth >= TotSteps || ldepth >= TotSteps)
+		{	fprintf(stderr, "max nr of %d steps exceeded\n",
+				TotSteps);
+			fatal("aborting", (char *) 0);
+		}
+
 		D[depth] = ldepth;
 		D[depth] = ldepth;
 		R[ldepth] = depth;
 		R[ldepth] = depth;
 		L[ldepth] = tmp;
 		L[ldepth] = tmp;
@@ -423,15 +430,19 @@ pstext(int x, char *s)
 
 
 void
 void
 dotag(FILE *fd, char *s)
 dotag(FILE *fd, char *s)
-{	extern int columns; extern RunList *X;
+{	extern int columns, notabs; extern RunList *X;
 	int i = (!strncmp(s, "MSC: ", 5))?5:0;
 	int i = (!strncmp(s, "MSC: ", 5))?5:0;
 	int pid = s_trail ? pno : (X?X->pid:0);
 	int pid = s_trail ? pno : (X?X->pid:0);
 
 
 	if (columns == 2)
 	if (columns == 2)
 		pstext(pid, &s[i]);
 		pstext(pid, &s[i]);
 	else
 	else
-	{	for (i = 0; i < pid; i++)
-			printf("\t");
+	{	if (!notabs)
+		{	printf("  ");
+			for (i = 0; i <= pid; i++)
+				printf("    ");
+		}
 		fprintf(fd, "%s", s);
 		fprintf(fd, "%s", s);
+		fflush(fd);
 	}
 	}
 }
 }

+ 140 - 0
sys/src/cmd/spin/reprosrc.c

@@ -0,0 +1,140 @@
+/***** spin: reprosrc.c *****/
+
+/* Copyright (c) 2002-2003 by Lucent Technologies, Bell Laboratories.     */
+/* All Rights Reserved.  This software is for educational purposes only.  */
+/* No guarantee whatsoever is expressed or implied by the distribution of */
+/* this code.  Permission is given to distribute this code provided that  */
+/* this introductory message is not removed and no monies are exchanged.  */
+/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
+/*             http://spinroot.com/                                       */
+/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
+
+#include <stdio.h>
+#include "spin.h"
+#ifdef PC
+#include "y_tab.h"
+#else
+#include "y.tab.h"
+#endif
+
+static int indent = 1;
+
+extern ProcList	*rdy;
+void repro_seq(Sequence *);
+
+void
+doindent(void)
+{	int i;
+	for (i = 0; i < indent; i++)
+		printf("   ");
+}
+
+void
+repro_sub(Element *e)
+{
+	doindent();
+	switch (e->n->ntyp) {
+	case D_STEP:
+		printf("d_step {\n");
+		break;
+	case ATOMIC:
+		printf("atomic {\n");
+		break;
+	case NON_ATOMIC:
+		printf(" {\n");
+		break;
+	}
+	indent++;
+	repro_seq(e->n->sl->this);
+	indent--;
+
+	doindent();
+	printf(" };\n");
+}
+
+void
+repro_seq(Sequence *s)
+{	Element *e;
+	Symbol *v;
+	SeqList *h;
+
+	for (e = s->frst; e; e = e->nxt)
+	{
+		v = has_lab(e, 0);
+		if (v) printf("%s:\n", v->name);
+
+		if (e->n->ntyp == UNLESS)
+		{	printf("/* normal */ {\n");
+			repro_seq(e->n->sl->this);
+			doindent();
+			printf("} unless {\n");
+			repro_seq(e->n->sl->nxt->this);
+			doindent();
+			printf("}; /* end unless */\n");
+		} else if (e->sub)
+		{
+			switch (e->n->ntyp) {
+			case DO: doindent(); printf("do\n"); indent++; break;
+			case IF: doindent(); printf("if\n"); indent++; break;
+			}
+
+			for (h = e->sub; h; h = h->nxt)
+			{	indent--; doindent(); indent++; printf("::\n");
+				repro_seq(h->this);
+				printf("\n");
+			}
+
+			switch (e->n->ntyp) {
+			case DO: indent--; doindent(); printf("od;\n"); break;
+			case IF: indent--; doindent(); printf("fi;\n"); break;
+			}
+		} else
+		{	if (e->n->ntyp == ATOMIC
+			||  e->n->ntyp == D_STEP
+			||  e->n->ntyp == NON_ATOMIC)
+				repro_sub(e);
+			else if (e->n->ntyp != '.'
+			     &&  e->n->ntyp != '@'
+			     &&  e->n->ntyp != BREAK)
+			{
+				doindent();
+				if (e->n->ntyp == C_CODE)
+				{	printf("c_code ");
+					plunk_inline(stdout, e->n->sym->name, 1);
+				} else if (e->n->ntyp == 'c'
+				       &&  e->n->lft->ntyp == C_EXPR)
+				{	printf("c_expr { ");
+					plunk_expr(stdout, e->n->lft->sym->name);
+					printf("} ->\n");
+				} else
+				{	comment(stdout, e->n, 0);
+					printf(";\n");
+			}	}
+		}
+		if (e == s->last)
+			break;
+	}
+}
+
+void
+repro_proc(ProcList *p)
+{
+	if (!p) return;
+	if (p->nxt) repro_proc(p->nxt);
+
+	if (p->det) printf("D");	/* deterministic */
+	printf("proctype %s()", p->n->name);
+	if (p->prov)
+	{	printf(" provided ");
+		comment(stdout, p->prov, 0);
+	}
+	printf("\n{\n");
+	repro_seq(p->s);
+	printf("}\n");
+}
+
+void
+repro_src(void)
+{
+	repro_proc(rdy);
+}

+ 73 - 23
sys/src/cmd/spin/run.c

@@ -1,14 +1,13 @@
 /***** spin: run.c *****/
 /***** spin: run.c *****/
 
 
-/* Copyright (c) 1991-2000 by Lucent Technologies - Bell Laboratories     */
+/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories.     */
 /* All Rights Reserved.  This software is for educational purposes only.  */
 /* All Rights Reserved.  This software is for educational purposes only.  */
-/* Permission is given to distribute this code provided that this intro-  */
-/* ductory message is not removed and no monies are exchanged.            */
-/* No guarantee is expressed or implied by the distribution of this code. */
-/* Software written by Gerard J. Holzmann as part of the book:            */
-/* `Design and Validation of Computer Protocols,' ISBN 0-13-539925-4,     */
-/* Prentice Hall, Englewood Cliffs, NJ, 07632.                            */
-/* Send bug-reports and/or questions to: gerard@research.bell-labs.com    */
+/* No guarantee whatsoever is expressed or implied by the distribution of */
+/* this code.  Permission is given to distribute this code provided that  */
+/* this introductory message is not removed and no monies are exchanged.  */
+/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
+/*             http://spinroot.com/                                       */
+/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
 
 
 #include <stdlib.h>
 #include <stdlib.h>
 #include "spin.h"
 #include "spin.h"
@@ -52,7 +51,7 @@ rev_escape(SeqList *e)
 	if (!e)
 	if (!e)
 		return (Element *) 0;
 		return (Element *) 0;
 
 
-	if (r = rev_escape(e->nxt)) /* reversed order */
+	if ((r = rev_escape(e->nxt)) != ZE) /* reversed order */
 		return r;
 		return r;
 
 
 	return eval_sub(e->this->frst);		
 	return eval_sub(e->this->frst);		
@@ -84,7 +83,7 @@ eval_sub(Element *e)
 	} else if (e->sub)	/* true for IF, DO, and UNLESS */
 	} else if (e->sub)	/* true for IF, DO, and UNLESS */
 	{	Element *has_else = ZE;
 	{	Element *has_else = ZE;
 		Element *bas_else = ZE;
 		Element *bas_else = ZE;
-		int nr_else, nr_choices = 0;
+		int nr_else = 0, nr_choices = 0;
 
 
 		if (interactive
 		if (interactive
 		&& !MadeChoice && !E_Check
 		&& !MadeChoice && !E_Check
@@ -174,8 +173,21 @@ eval_sub(Element *e)
 					continue;
 					continue;
 				}
 				}
 			}
 			}
+			if (z->this->frst
+			&&  ((z->this->frst->n->ntyp == ATOMIC
+			  ||  z->this->frst->n->ntyp == D_STEP)
+			  &&  z->this->frst->n->sl->this->frst->n->ntyp == ELSE))
+			{	bas_else = z->this->frst->n->sl->this->frst;
+				has_else = (Rvous)?ZE:bas_else->nxt;
+				if (!interactive || depth < jumpsteps
+				|| Escape_Check
+				|| (e->status&(D_ATOM)))
+				{	z = (z->nxt)?z->nxt:e->sub;
+					continue;
+				}
+			}
 			if (i >= k)
 			if (i >= k)
-			{	if (f = eval_sub(z->this->frst))
+			{	if ((f = eval_sub(z->this->frst)) != ZE)
 					return f;
 					return f;
 				else if (interactive && depth >= jumpsteps
 				else if (interactive && depth >= jumpsteps
 				&& !(e->status&(D_ATOM)))
 				&& !(e->status&(D_ATOM)))
@@ -222,11 +234,13 @@ eval_sub(Element *e)
 				}
 				}
 				printf("\n");
 				printf("\n");
 			}
 			}
-
+#if 0
 			if (!(e->status & D_ATOM))	/* escapes don't reach inside d_steps */
 			if (!(e->status & D_ATOM))	/* escapes don't reach inside d_steps */
+			/* 4.2.4: only the guard of a d_step can have an escape */
+#endif
 			{	Escape_Check++;
 			{	Escape_Check++;
 				if (like_java)
 				if (like_java)
-				{	if (g = rev_escape(e->esc))
+				{	if ((g = rev_escape(e->esc)) != ZE)
 					{	if (verbose&4)
 					{	if (verbose&4)
 							printf("\tEscape taken\n");
 							printf("\tEscape taken\n");
 						Escape_Check--;
 						Escape_Check--;
@@ -234,7 +248,7 @@ eval_sub(Element *e)
 					}
 					}
 				} else
 				} else
 				{	for (x = e->esc; x; x = x->nxt)
 				{	for (x = e->esc; x; x = x->nxt)
-					{	if (g = eval_sub(x->this->frst))
+					{	if ((g = eval_sub(x->this->frst)) != ZE)
 						{	if (verbose&4)
 						{	if (verbose&4)
 								printf("\tEscape taken\n");
 								printf("\tEscape taken\n");
 							Escape_Check--;
 							Escape_Check--;
@@ -245,7 +259,8 @@ eval_sub(Element *e)
 		
 		
 			switch (e->n->ntyp) {
 			switch (e->n->ntyp) {
 			case TIMEOUT: case RUN:
 			case TIMEOUT: case RUN:
-			case PRINT:
+			case PRINT: case PRINTM:
+			case C_CODE: case C_EXPR:
 			case ASGN: case ASSERT:
 			case ASGN: case ASSERT:
 			case 's': case 'r': case 'c':
 			case 's': case 'r': case 'c':
 				/* toplevel statements only */
 				/* toplevel statements only */
@@ -350,7 +365,7 @@ eval(Lextok *now)
 	case   '?': return (eval(now->lft) ? eval(now->rgt->lft)
 	case   '?': return (eval(now->lft) ? eval(now->rgt->lft)
 					   : eval(now->rgt->rgt));
 					   : eval(now->rgt->rgt));
 
 
-	case     'p': return remotevar(now);	/* only _p allowed */
+	case     'p': return remotevar(now);	/* _p for remote reference */
 	case     'q': return remotelab(now);
 	case     'q': return remotelab(now);
 	case     'R': return qrecv(now, 0);	/* test only    */
 	case     'R': return qrecv(now, 0);	/* test only    */
 	case     LEN: return qlen(now);
 	case     LEN: return qlen(now);
@@ -372,7 +387,18 @@ eval(Lextok *now)
 	case   'r': return qrecv(now, 1);	/* receive or poll */
 	case   'r': return qrecv(now, 1);	/* receive or poll */
 	case   'c': return eval(now->lft);	/* condition    */
 	case   'c': return eval(now->lft);	/* condition    */
 	case PRINT: return TstOnly?1:interprint(stdout, now);
 	case PRINT: return TstOnly?1:interprint(stdout, now);
+	case PRINTM: return TstOnly?1:printm(stdout, now);
 	case  ASGN: return assign(now);
 	case  ASGN: return assign(now);
+
+	case C_CODE: printf("%s:\t", now->sym->name);
+		     plunk_inline(stdout, now->sym->name, 0);
+		     return 1; /* uninterpreted */
+
+	case C_EXPR: printf("%s:\t", now->sym->name);
+		     plunk_expr(stdout, now->sym->name);
+		     printf("\n");
+		     return 1; /* uninterpreted */
+
 	case ASSERT: if (TstOnly || eval(now->lft)) return 1;
 	case ASSERT: if (TstOnly || eval(now->lft)) return 1;
 		     non_fatal("assertion violated", (char *) 0);
 		     non_fatal("assertion violated", (char *) 0);
 			printf("spin: text of failed assertion: assert(");
 			printf("spin: text of failed assertion: assert(");
@@ -392,6 +418,25 @@ eval(Lextok *now)
 	return 0;
 	return 0;
 }
 }
 
 
+int
+printm(FILE *fd, Lextok *n)
+{	extern char Buf[];
+	int j;
+
+	Buf[0] = '\0';
+	if (!no_print)
+	if (!s_trail || depth >= jumpsteps) {
+		if (n->lft->ismtyp)
+			j = n->lft->val;
+		else
+			j = eval(n->lft);
+		Buf[0] = '\0';
+		sr_buf(j, 1);
+		dotag(fd, Buf);
+	}
+	return 1;
+}
+
 int
 int
 interprint(FILE *fd, Lextok *n)
 interprint(FILE *fd, Lextok *n)
 {	Lextok *tmp = n->lft;
 {	Lextok *tmp = n->lft;
@@ -465,22 +510,24 @@ Enabled1(Lextok *n)
 		/* else fall through */
 		/* else fall through */
 	default:	/* side-effect free */
 	default:	/* side-effect free */
 		verbose = 0;
 		verbose = 0;
-E_Check++;
+		E_Check++;
 		i = eval(n);
 		i = eval(n);
-E_Check--;
+		E_Check--;
 		verbose = v;
 		verbose = v;
 		return i;
 		return i;
 
 
-	case PRINT: case  ASGN: case ASSERT:
+	case C_CODE: case C_EXPR:
+	case PRINT: case PRINTM:
+	case   ASGN: case ASSERT:
 		return 1;
 		return 1;
 
 
 	case 's':
 	case 's':
 		if (q_is_sync(n))
 		if (q_is_sync(n))
 		{	if (Rvous) return 0;
 		{	if (Rvous) return 0;
 			TstOnly = 1; verbose = 0;
 			TstOnly = 1; verbose = 0;
-E_Check++;
+			E_Check++;
 			i = eval(n);
 			i = eval(n);
-E_Check--;
+			E_Check--;
 			TstOnly = 0; verbose = v;
 			TstOnly = 0; verbose = v;
 			return i;
 			return i;
 		}
 		}
@@ -489,9 +536,9 @@ E_Check--;
 		if (q_is_sync(n))
 		if (q_is_sync(n))
 			return 0;	/* it's never a user-choice */
 			return 0;	/* it's never a user-choice */
 		n->ntyp = 'R'; verbose = 0;
 		n->ntyp = 'R'; verbose = 0;
-E_Check++;
+		E_Check++;
 		i = eval(n);
 		i = eval(n);
-E_Check--;
+		E_Check--;
 		n->ntyp = 'r'; verbose = v;
 		n->ntyp = 'r'; verbose = v;
 		return i;
 		return i;
 	}
 	}
@@ -545,6 +592,9 @@ pc_enabled(Lextok *n)
 	int result = 0;
 	int result = 0;
 	RunList *Y, *oX;
 	RunList *Y, *oX;
 
 
+	if (pid == X->pid)
+		fatal("used: enabled(pid=thisproc) [%s]", X->n->name);
+
 	for (Y = run; Y; Y = Y->nxt)
 	for (Y = run; Y; Y = Y->nxt)
 		if (--i == pid)
 		if (--i == pid)
 		{	oX = X; X = Y;
 		{	oX = X; X = Y;

+ 171 - 79
sys/src/cmd/spin/sched.c

@@ -1,14 +1,13 @@
 /***** spin: sched.c *****/
 /***** spin: sched.c *****/
 
 
-/* Copyright (c) 1991-2000 by Lucent Technologies - Bell Laboratories     */
+/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories.     */
 /* All Rights Reserved.  This software is for educational purposes only.  */
 /* All Rights Reserved.  This software is for educational purposes only.  */
-/* Permission is given to distribute this code provided that this intro-  */
-/* ductory message is not removed and no monies are exchanged.            */
-/* No guarantee is expressed or implied by the distribution of this code. */
-/* Software written by Gerard J. Holzmann as part of the book:            */
-/* `Design and Validation of Computer Protocols,' ISBN 0-13-539925-4,     */
-/* Prentice Hall, Englewood Cliffs, NJ, 07632.                            */
-/* Send bug-reports and/or questions to: gerard@research.bell-labs.com    */
+/* No guarantee whatsoever is expressed or implied by the distribution of */
+/* this code.  Permission is given to distribute this code provided that  */
+/* this introductory message is not removed and no monies are exchanged.  */
+/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
+/*             http://spinroot.com/                                       */
+/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
 
 
 #include <stdlib.h>
 #include <stdlib.h>
 #include "spin.h"
 #include "spin.h"
@@ -23,8 +22,9 @@ extern char	*claimproc, *eventmap, Buf[];
 extern Ordered	*all_names;
 extern Ordered	*all_names;
 extern Symbol	*Fname, *context;
 extern Symbol	*Fname, *context;
 extern int	lineno, nr_errs, dumptab, xspin, jumpsteps, columns;
 extern int	lineno, nr_errs, dumptab, xspin, jumpsteps, columns;
-extern int	u_sync, Elcnt, interactive, TstOnly;
-extern short	has_enabled, has_provided;
+extern int	u_sync, Elcnt, interactive, TstOnly, cutoff;
+extern short	has_enabled;
+extern int	limited_vis;
 
 
 RunList		*X   = (RunList  *) 0;
 RunList		*X   = (RunList  *) 0;
 RunList		*run = (RunList  *) 0;
 RunList		*run = (RunList  *) 0;
@@ -46,11 +46,20 @@ runnable(ProcList *p, int weight, int noparams)
 
 
 	r->n  = p->n;
 	r->n  = p->n;
 	r->tn = p->tn;
 	r->tn = p->tn;
-	r->pid = ++nproc-nstop-1;
-	r->pc = huntele(p->s->frst, p->s->frst->status);
+	r->pid = nproc++ - nstop + Skip_claim;
+
+	if ((verbose&4) || (verbose&32))
+		printf("Starting %s with pid %d\n", p->n->name, r->pid);
+
+	if (!p->s)
+		fatal("parsing error, no sequence %s", p->n?p->n->name:"--");
+
+	r->pc = huntele(p->s->frst, p->s->frst->status, -1);
 	r->ps = p->s;
 	r->ps = p->s;
-	if (p->s && p->s->last)
-		p->s->last->status |= ENDSTATE; /* normal endstate */
+
+	if (p->s->last)
+		p->s->last->status |= ENDSTATE; /* normal end state */
+
 	r->nxt = run;
 	r->nxt = run;
 	r->prov = p->prov;
 	r->prov = p->prov;
 	r->priority = weight;
 	r->priority = weight;
@@ -120,22 +129,22 @@ announce(char *w)
 		firstrow = 1;
 		firstrow = 1;
 		if (columns == 2)
 		if (columns == 2)
 		{	sprintf(Buf, "%d:%s",
 		{	sprintf(Buf, "%d:%s",
-			run->pid, run->n->name);
-			pstext(run->pid, Buf);
+			run->pid - Have_claim, run->n->name);
+			pstext(run->pid - Have_claim, Buf);
 		} else
 		} else
 			printf("proc %d = %s\n",
 			printf("proc %d = %s\n",
 			run->pid - Have_claim, run->n->name);
 			run->pid - Have_claim, run->n->name);
 		return;
 		return;
 	}
 	}
-#if 1
+
 	if (dumptab
 	if (dumptab
 	||  analyze
 	||  analyze
 	||  s_trail
 	||  s_trail
 	|| !(verbose&4))
 	|| !(verbose&4))
 		return;
 		return;
-#endif
+
 	if (w)
 	if (w)
-		printf("  0:	proc - (%s) ", w);
+		printf("  0:	proc  - (%s) ", w);
 	else
 	else
 		whoruns(1);
 		whoruns(1);
 	printf("creates proc %2d (%s)",
 	printf("creates proc %2d (%s)",
@@ -146,6 +155,10 @@ announce(char *w)
 	printf("\n");
 	printf("\n");
 }
 }
 
 
+#ifndef MAXP
+#define MAXP	255	/* matches max nr of processes in verifier */
+#endif
+
 int
 int
 enable(Lextok *m)
 enable(Lextok *m)
 {	ProcList *p;
 {	ProcList *p;
@@ -155,11 +168,15 @@ enable(Lextok *m)
 	if (m->val < 1) m->val = 1;	/* minimum priority */
 	if (m->val < 1) m->val = 1;	/* minimum priority */
 	for (p = rdy; p; p = p->nxt)
 	for (p = rdy; p; p = p->nxt)
 		if (strcmp(s->name, p->n->name) == 0)
 		if (strcmp(s->name, p->n->name) == 0)
-		{	runnable(p, m->val, 0);
+		{	if (nproc-nstop >= MAXP)
+			{	printf("spin: too many processes (%d max)\n", MAXP);
+				break;
+			}
+			runnable(p, m->val, 0);
 			announce((char *) 0);
 			announce((char *) 0);
 			setparams(run, p, n);
 			setparams(run, p, n);
 			setlocals(run); /* after setparams */
 			setlocals(run); /* after setparams */
-			return run->pid - Have_claim;	/* pid */
+			return run->pid - Have_claim + Skip_claim; /* effective simu pid */
 		}
 		}
 	return 0; /* process not found */
 	return 0; /* process not found */
 }
 }
@@ -179,7 +196,7 @@ start_claim(int n)
 	Skip_claim = 1;
 	Skip_claim = 1;
 	goto done;
 	goto done;
 found:
 found:
-	/* move claim to far end of runlist, with pid 0 */
+	/* move claim to far end of runlist, and reassign it pid 0 */
 	if (columns == 2)
 	if (columns == 2)
 	{	depth = 0;
 	{	depth = 0;
 		pstext(0, "0::never:");
 		pstext(0, "0::never:");
@@ -190,23 +207,42 @@ found:
 				r->pid+1, r->n->name);
 				r->pid+1, r->n->name);
 			pstext(r->pid+1, Buf);
 			pstext(r->pid+1, Buf);
 	}	}
 	}	}
-	if (run->pid == 0) return;	/* already there */
+
+	if (run->pid == 0) return; /* it is the first process started */
 
 
 	q = run; run = run->nxt;
 	q = run; run = run->nxt;
-	q->pid = 0; q->nxt = (RunList *) 0;
+	q->pid = 0; q->nxt = (RunList *) 0;	/* remove */
 done:
 done:
+	Have_claim = 1;
 	for (r = run; r; r = r->nxt)
 	for (r = run; r; r = r->nxt)
-	{	r->pid = r->pid+1;
+	{	r->pid = r->pid+Have_claim;	/* adjust */
 		if (!r->nxt)
 		if (!r->nxt)
 		{	r->nxt = q;
 		{	r->nxt = q;
 			break;
 			break;
 	}	}
 	}	}
-	Have_claim = 1;
+}
+
+int
+f_pid(char *n)
+{	RunList *r;
+	int rval = -1;
+
+	for (r = run; r; r = r->nxt)
+		if (strcmp(n, r->n->name) == 0)
+		{	if (rval >= 0)
+			{	printf("spin: remote ref to proctype %s, ", n);
+				printf("has more than one match: %d and %d\n",
+					rval, r->pid);
+			} else
+				rval = r->pid;
+		}
+	return rval;
 }
 }
 
 
 void
 void
 wrapup(int fini)
 wrapup(int fini)
 {
 {
+	limited_vis = 0;
 	if (columns)
 	if (columns)
 	{	extern void putpostlude(void);
 	{	extern void putpostlude(void);
 		if (columns == 2) putpostlude();
 		if (columns == 2) putpostlude();
@@ -217,7 +253,7 @@ wrapup(int fini)
 		goto short_cut;
 		goto short_cut;
 	if (nproc != nstop)
 	if (nproc != nstop)
 	{	int ov = verbose;
 	{	int ov = verbose;
-		printf("#processes: %d\n", nproc-nstop);
+		printf("#processes: %d\n", nproc-nstop - Have_claim + Skip_claim);
 		verbose &= ~4;
 		verbose &= ~4;
 		dumpglobals();
 		dumpglobals();
 		verbose = ov;
 		verbose = ov;
@@ -227,7 +263,9 @@ wrapup(int fini)
 			talk(X);
 			talk(X);
 		verbose = ov;	/* restore */
 		verbose = ov;	/* restore */
 	}
 	}
-	printf("%d processes created\n", nproc);
+	printf("%d process%s created\n",
+		nproc - Have_claim + Skip_claim,
+		(xspin || nproc!=1)?"es":"");
 short_cut:
 short_cut:
 	if (xspin) alldone(0);	/* avoid an abort from xspin */
 	if (xspin) alldone(0);	/* avoid an abort from xspin */
 	if (fini)  alldone(1);
 	if (fini)  alldone(1);
@@ -237,7 +275,7 @@ static char is_blocked[256];
 
 
 static int
 static int
 p_blocked(int p)
 p_blocked(int p)
-{	register int i, j;
+{	int i, j;
 
 
 	is_blocked[p%256] = 1;
 	is_blocked[p%256] = 1;
 	for (i = j = 0; i < nproc - nstop; i++)
 	for (i = j = 0; i < nproc - nstop; i++)
@@ -276,7 +314,7 @@ static void
 pickproc(void)
 pickproc(void)
 {	SeqList *z; Element *has_else;
 {	SeqList *z; Element *has_else;
 	short Choices[256];
 	short Choices[256];
-	int j, k, nr_else;
+	int j, k, nr_else = 0;
 
 
 	if (nproc <= nstop+1)
 	if (nproc <= nstop+1)
 	{	X = run;
 	{	X = run;
@@ -422,7 +460,7 @@ sched(void)
 {	Element *e;
 {	Element *e;
 	RunList *Y=0;	/* previous process in run queue */
 	RunList *Y=0;	/* previous process in run queue */
 	RunList *oX;
 	RunList *oX;
-	int go, notbeyond;
+	int go, notbeyond = 0;
 #ifdef PC
 #ifdef PC
 	int bufmax = 100;
 	int bufmax = 100;
 #endif
 #endif
@@ -450,11 +488,8 @@ sched(void)
 	if (eventmap)
 	if (eventmap)
 	printf("warning: trace assertion not used in random simulation\n");
 	printf("warning: trace assertion not used in random simulation\n");
 
 
-/*	if (interactive) Tval = 1; */
-
 	X = run;
 	X = run;
 	pickproc();
 	pickproc();
-	notbeyond = 0;
 
 
 	while (X)
 	while (X)
 	{	context = X->n;
 	{	context = X->n;
@@ -462,19 +497,25 @@ sched(void)
 		{	lineno = X->pc->n->ln;
 		{	lineno = X->pc->n->ln;
 			Fname  = X->pc->n->fn;
 			Fname  = X->pc->n->fn;
 		}
 		}
+		if (cutoff > 0 && depth >= cutoff)
+		{	printf("-------------\n");
+			printf("depth-limit (-u%d steps) reached\n", cutoff);
+			break;
+		}
 #ifdef PC
 #ifdef PC
 		if (xspin && !interactive && --bufmax <= 0)
 		if (xspin && !interactive && --bufmax <= 0)
-		{	/* avoid buffer overflow on pc's */
+		{	int c; /* avoid buffer overflow on pc's */
 			printf("spin: type return to proceed\n");
 			printf("spin: type return to proceed\n");
 			fflush(stdout);
 			fflush(stdout);
-			getc(stdin);
+			c = getc(stdin);
+			if (c == 'q') wrapup(0);
 			bufmax = 100;
 			bufmax = 100;
 		}
 		}
 #endif
 #endif
 		depth++; LastStep = ZE;
 		depth++; LastStep = ZE;
 		oX = X;	/* a rendezvous could change it */
 		oX = X;	/* a rendezvous could change it */
 		go = 1;
 		go = 1;
-		if (X && X->prov
+		if (X && X->prov && X->pc
 		&& !(X->pc->status & D_ATOM)
 		&& !(X->pc->status & D_ATOM)
 		&& !eval(X->prov))
 		&& !eval(X->prov))
 		{	if (!xspin && ((verbose&32) || (verbose&4)))
 		{	if (!xspin && ((verbose&32) || (verbose&4)))
@@ -487,6 +528,7 @@ sched(void)
 		{	if (depth >= jumpsteps
 		{	if (depth >= jumpsteps
 			&& ((verbose&32) || (verbose&4)))
 			&& ((verbose&32) || (verbose&4)))
 			{	if (X == oX)
 			{	if (X == oX)
+				if (!(e->status & D_ATOM) || (verbose&32)) /* no talking in d_steps */
 				{	p_talk(X->pc, 1);
 				{	p_talk(X->pc, 1);
 					printf("	[");
 					printf("	[");
 					if (!LastStep) LastStep = X->pc;
 					if (!LastStep) LastStep = X->pc;
@@ -495,17 +537,23 @@ sched(void)
 				}
 				}
 				if (verbose&1) dumpglobals();
 				if (verbose&1) dumpglobals();
 				if (verbose&2) dumplocal(X);
 				if (verbose&2) dumplocal(X);
-				if (xspin) printf("\n");
+
+				if (!(e->status & D_ATOM))
+				if (xspin)
+					printf("\n");
+			}
+			if (oX != X)
+			{	e = silent_moves(e);
+				notbeyond = 0;
 			}
 			}
-			if (oX != X)  e = silent_moves(e);
 			oX->pc = e; LastX = X;
 			oX->pc = e; LastX = X;
 
 
 			if (!interactive) Tval = 0;
 			if (!interactive) Tval = 0;
 			memset(is_blocked, 0, 256);
 			memset(is_blocked, 0, 256);
 
 
-			if ((X->pc->status & (ATOM|L_ATOM))
-			&&  notbeyond == 0)
-			{	if (X->pc->status & L_ATOM)
+			if (X->pc && (X->pc->status & (ATOM|L_ATOM))
+			&&  (notbeyond == 0 || oX != X))
+			{	if ((X->pc->status & L_ATOM))
 					notbeyond = 1;
 					notbeyond = 1;
 				continue; /* no process switch */
 				continue; /* no process switch */
 			}
 			}
@@ -535,8 +583,11 @@ sched(void)
 				{	if (Tval) break;
 				{	if (Tval) break;
 					Tval = 1;
 					Tval = 1;
 					if (depth >= jumpsteps)
 					if (depth >= jumpsteps)
+					{	oX = X;
+						X = (RunList *) 0; /* to suppress indent */
 						dotag(stdout, "timeout\n");
 						dotag(stdout, "timeout\n");
-		}	}	}
+						X = oX;
+		}	}	}	}
 		Y = X;
 		Y = X;
 		pickproc();
 		pickproc();
 		notbeyond = 0;
 		notbeyond = 0;
@@ -738,6 +789,20 @@ findloc(Symbol *s)
 	return r;
 	return r;
 }
 }
 
 
+int
+in_bound(Symbol *r, int n)
+{
+	if (!r)	return 0;
+
+	if (n >= r->nel || n < 0)
+	{	printf("spin: indexing %s[%d] - size is %d\n",
+			r->name, n, r->nel);
+		non_fatal("indexing array \'%s\'", r->name);
+		return 0;
+	}
+	return 1;
+}
+
 int
 int
 getlocal(Lextok *sn)
 getlocal(Lextok *sn)
 {	Symbol *r, *s = sn->sym;
 {	Symbol *r, *s = sn->sym;
@@ -746,14 +811,8 @@ getlocal(Lextok *sn)
 	r = findloc(s);
 	r = findloc(s);
 	if (r && r->type == STRUCT)
 	if (r && r->type == STRUCT)
 		return Rval_struct(sn, r, 1); /* 1 = check init */
 		return Rval_struct(sn, r, 1); /* 1 = check init */
-	if (r)
-	{	if (n >= r->nel || n < 0)
-		{	printf("spin: indexing %s[%d] - size is %d\n",
-				s->name, n, r->nel);
-			non_fatal("indexing array \'%s\'", s->name);
-		} else
-		{	return cast_val(r->type, r->val[n], r->nbits);
-	}	}
+	if (in_bound(r, n))
+		return cast_val(r->type, r->val[n], r->nbits);
 	return 0;
 	return 0;
 }
 }
 
 
@@ -762,19 +821,18 @@ setlocal(Lextok *p, int m)
 {	Symbol *r = findloc(p->sym);
 {	Symbol *r = findloc(p->sym);
 	int n = eval(p->lft);
 	int n = eval(p->lft);
 
 
-	if (!r) return 1;
-
-	if (n >= r->nel || n < 0)
-	{	printf("spin: indexing %s[%d] - size is %d\n",
-			r->name, n, r->nel);
-		non_fatal("indexing array \'%s\'", r->name);
-	} else
+	if (in_bound(r, n))
 	{	if (r->type == STRUCT)
 	{	if (r->type == STRUCT)
 			(void) Lval_struct(p, r, 1, m); /* 1 = check init */
 			(void) Lval_struct(p, r, 1, m); /* 1 = check init */
 		else
 		else
-		{	if (r->nbits > 0)
-				m = (m & ((1<<r->nbits)-1));	
+		{
+#if 0
+			if (r->nbits > 0)
+				m = (m & ((1<<r->nbits)-1));
 			r->val[n] = m;
 			r->val[n] = m;
+#else
+			r->val[n] = cast_val(r->type, m, r->nbits);
+#endif
 			r->setat = depth;
 			r->setat = depth;
 	}	}
 	}	}
 
 
@@ -817,12 +875,14 @@ p_talk(Element *e, int lnr)
 	&&  lastnever != newnever && e)
 	&&  lastnever != newnever && e)
 	{	if (xspin)
 	{	if (xspin)
 		{	printf("MSC: ~G line %d\n", newnever);
 		{	printf("MSC: ~G line %d\n", newnever);
-			printf("%3d:	proc 0 (NEVER) line   %d \"never\" ",
+#if 0
+			printf("%3d:	proc  - (NEVER) line   %d \"never\" ",
 				depth, newnever);
 				depth, newnever);
 			printf("(state 0)\t[printf('MSC: never\\\\n')]\n");
 			printf("(state 0)\t[printf('MSC: never\\\\n')]\n");
 		} else
 		} else
-		{	printf("%3d:	proc 0 (NEVER) line   %d \"never\"\n",
+		{	printf("%3d:	proc  - (NEVER) line   %d \"never\"\n",
 				depth, newnever);
 				depth, newnever);
+#endif
 		}
 		}
 		lastnever = newnever;
 		lastnever = newnever;
 	}
 	}
@@ -835,7 +895,7 @@ p_talk(Element *e, int lnr)
 			e->seqno);
 			e->seqno);
 		if (!xspin
 		if (!xspin
 		&&  ((e->status&ENDSTATE) || has_lab(e, 2)))	/* 2=end */
 		&&  ((e->status&ENDSTATE) || has_lab(e, 2)))	/* 2=end */
-		{	printf(" <valid endstate>");
+		{	printf(" <valid end state>");
 		}
 		}
 	}
 	}
 }
 }
@@ -846,8 +906,10 @@ remotelab(Lextok *n)
 
 
 	lineno = n->ln;
 	lineno = n->ln;
 	Fname  = n->fn;
 	Fname  = n->fn;
-	if (n->sym->type)
+	if (n->sym->type != 0 && n->sym->type != LABEL)
+	{	printf("spin: error, type: %d\n", n->sym->type);
 		fatal("not a labelname: '%s'", n->sym->name);
 		fatal("not a labelname: '%s'", n->sym->name);
+	}
 	if (n->indstep >= 0)
 	if (n->indstep >= 0)
 	{	fatal("remote ref to label '%s' inside d_step",
 	{	fatal("remote ref to label '%s' inside d_step",
 			n->sym->name);
 			n->sym->name);
@@ -859,29 +921,40 @@ remotelab(Lextok *n)
 
 
 int
 int
 remotevar(Lextok *n)
 remotevar(Lextok *n)
-{	int prno, i, trick=0;
-	RunList *Y;
+{	int prno, i, added=0;
+	RunList *Y, *oX;
+	Lextok *onl;
+	Symbol *os;
 
 
 	lineno = n->ln;
 	lineno = n->ln;
 	Fname  = n->fn;
 	Fname  = n->fn;
+
 	if (!n->lft->lft)
 	if (!n->lft->lft)
-	{	non_fatal("missing pid in %s", n->sym->name);
-		return 0;
-	}
+		prno = f_pid(n->lft->sym->name);
+	else
+	{	prno = eval(n->lft->lft); /* pid - can cause recursive call */
+#if 0
+		if (n->lft->lft->ntyp == CONST)	/* user-guessed pid */
+#endif
+		{	prno += Have_claim;
+			added = Have_claim;
+	}	}
 
 
-	prno = eval(n->lft->lft); /* pid - can cause recursive call */
-TryAgain:
+	if (prno < 0)
+		return 0;	/* non-existing process */
+#if 0
+	i = nproc - nstop;
+	for (Y = run; Y; Y = Y->nxt)
+	{	--i;
+		printf("	%s: i=%d, prno=%d, ->pid=%d\n", Y->n->name, i, prno, Y->pid);
+	}
+#endif
 	i = nproc - nstop;
 	i = nproc - nstop;
 	for (Y = run; Y; Y = Y->nxt)
 	for (Y = run; Y; Y = Y->nxt)
 	if (--i == prno)
 	if (--i == prno)
 	{	if (strcmp(Y->n->name, n->lft->sym->name) != 0)
 	{	if (strcmp(Y->n->name, n->lft->sym->name) != 0)
-		{	if (!trick && Have_claim)
-			{	trick = 1; prno++;
-				/* assumes user guessed the pid */
-				goto TryAgain;
-			}
-			printf("spin: remote reference error on '%s[%d]'\n",
-				n->lft->sym->name, prno-trick);
+		{	printf("spin: remote reference error on '%s[%d]'\n",
+				n->lft->sym->name, prno-added);
 			non_fatal("refers to wrong proctype '%s'", Y->n->name);
 			non_fatal("refers to wrong proctype '%s'", Y->n->name);
 		}
 		}
 		if (strcmp(n->sym->name, "_p") == 0)
 		if (strcmp(n->sym->name, "_p") == 0)
@@ -890,9 +963,28 @@ TryAgain:
 			/* harmless, can only happen with -t */
 			/* harmless, can only happen with -t */
 			return 0;
 			return 0;
 		}
 		}
+#if 1
+		/* new 4.0 allow remote variables */
+		oX = X;
+		X = Y;
+
+		onl = n->lft;
+		n->lft = n->rgt;
+
+		os = n->sym;
+		n->sym = findloc(n->sym);
+
+		i = getval(n);
+
+		n->sym = os;
+		n->lft = onl;
+		X = oX;
+		return i;
+#else
 		break;
 		break;
+#endif
 	}
 	}
-	printf("remote ref: %s[%d] ", n->lft->sym->name, prno-trick);
+	printf("remote ref: %s[%d] ", n->lft->sym->name, prno-added);
 	non_fatal("%s not found", n->sym->name);
 	non_fatal("%s not found", n->sym->name);
 	printf("have only:\n");
 	printf("have only:\n");
 	i = nproc - nstop - 1;
 	i = nproc - nstop - 1;

+ 89 - 38
sys/src/cmd/spin/spin.h

@@ -1,18 +1,22 @@
 /***** spin: spin.h *****/
 /***** spin: spin.h *****/
 
 
-/* Copyright (c) 1991-2000 by Lucent Technologies - Bell Laboratories     */
+/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories.     */
 /* All Rights Reserved.  This software is for educational purposes only.  */
 /* All Rights Reserved.  This software is for educational purposes only.  */
-/* Permission is given to distribute this code provided that this intro-  */
-/* ductory message is not removed and no monies are exchanged.            */
-/* No guarantee is expressed or implied by the distribution of this code. */
-/* Software written by Gerard J. Holzmann as part of the book:            */
-/* `Design and Validation of Computer Protocols,' ISBN 0-13-539925-4,     */
-/* Prentice Hall, Englewood Cliffs, NJ, 07632.                            */
-/* Send bug-reports and/or questions to: gerard@research.bell-labs.com    */
+/* No guarantee whatsoever is expressed or implied by the distribution of */
+/* this code.  Permission is given to distribute this code provided that  */
+/* this introductory message is not removed and no monies are exchanged.  */
+/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
+/*             http://spinroot.com/                                       */
+/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
+
+#ifndef SEEN_SPIN_H
+#define SEEN_SPIN_H
 
 
 #include <stdio.h>
 #include <stdio.h>
 #include <string.h>
 #include <string.h>
 #include <ctype.h>
 #include <ctype.h>
+#ifndef PC
+#endif
 
 
 typedef struct Lextok {
 typedef struct Lextok {
 	unsigned short	ntyp;	/* node type */
 	unsigned short	ntyp;	/* node type */
@@ -27,6 +31,13 @@ typedef struct Lextok {
 	struct Lextok	*lft, *rgt; /* children in parse tree */
 	struct Lextok	*lft, *rgt; /* children in parse tree */
 } Lextok;
 } Lextok;
 
 
+typedef struct Slicer {
+	Lextok	*n;		/* global var, usable as slice criterion */
+	short	code;		/* type of use: DEREF_USE or normal USE */
+	short	used;		/* set when handled */
+	struct Slicer *nxt;	/* linked list */
+} Slicer;
+
 typedef struct Access {
 typedef struct Access {
 	struct Symbol	*who;	/* proctype name of accessor */
 	struct Symbol	*who;	/* proctype name of accessor */
 	struct Symbol	*what;	/* proctype name of accessed */
 	struct Symbol	*what;	/* proctype name of accessed */
@@ -44,18 +55,18 @@ typedef struct Symbol {
 				  16=formal par, 32=inline par,
 				  16=formal par, 32=inline par,
 				  64=treat as if local
 				  64=treat as if local
 				 */
 				 */
-	unsigned char	colnr;	/* for use with xspin */
-	int	nbits;		/* an optional width specifier */
+	unsigned char	colnr;	/* for use with xspin during simulation */
+	int	nbits;		/* optional width specifier */
 	int	nel;		/* 1 if scalar, >1 if array   */
 	int	nel;		/* 1 if scalar, >1 if array   */
 	int	setat;		/* last depth value changed   */
 	int	setat;		/* last depth value changed   */
 	int	*val;		/* runtime value(s), initl 0  */
 	int	*val;		/* runtime value(s), initl 0  */
-	struct Lextok	**Sval;	/* values for structures */
+	Lextok	**Sval;	/* values for structures */
 
 
 	int	xu;		/* exclusive r or w by 1 pid  */
 	int	xu;		/* exclusive r or w by 1 pid  */
 	struct Symbol	*xup[2];  /* xr or xs proctype  */
 	struct Symbol	*xup[2];  /* xr or xs proctype  */
 	struct Access	*access;/* e.g., senders and receives of chan */
 	struct Access	*access;/* e.g., senders and receives of chan */
-	struct Lextok	*ini;	/* initial value, or chan-def */
-	struct Lextok	*Slst;	/* template for structure if struct */
+	Lextok	*ini;	/* initial value, or chan-def */
+	Lextok	*Slst;	/* template for structure if struct */
 	struct Symbol	*Snm;	/* name of the defining struct */
 	struct Symbol	*Snm;	/* name of the defining struct */
 	struct Symbol	*owner;	/* set for names of subfields in typedefs */
 	struct Symbol	*owner;	/* set for names of subfields in typedefs */
 	struct Symbol	*context; /* 0 if global, or procname */
 	struct Symbol	*context; /* 0 if global, or procname */
@@ -69,8 +80,8 @@ typedef struct Ordered {	/* links all names in Symbol table */
 
 
 typedef struct Queue {
 typedef struct Queue {
 	short	qid;		/* runtime q index */
 	short	qid;		/* runtime q index */
-	short	qlen;		/* nr messages stored */
-	short	nslots, nflds;	/* capacity, flds/slot */
+	int	qlen;		/* nr messages stored */
+	int	nslots, nflds;	/* capacity, flds/slot */
 	int	setat;		/* last depth value changed */
 	int	setat;		/* last depth value changed */
 	int	*fld_width;	/* type of each field */
 	int	*fld_width;	/* type of each field */
 	int	*contents;	/* the values stored */
 	int	*contents;	/* the values stored */
@@ -78,26 +89,33 @@ typedef struct Queue {
 	struct Queue	*nxt;	/* linked list */
 	struct Queue	*nxt;	/* linked list */
 } Queue;
 } Queue;
 
 
-typedef struct FSM_use {	/* used in pangen5.c - dataflow */
-	Symbol *var;
-	int special;
-	struct FSM_use *nxt;
-} FSM_use;
+typedef struct FSM_state {	/* used in pangen5.c - dataflow */
+	int from;		/* state number */
+	int seen;		/* used for dfs */
+	int in;			/* nr of incoming edges */
+	int cr;			/* has reachable 1-relevant successor */
+	int scratch;
+	unsigned long *dom, *mod; /* to mark dominant nodes */
+	struct FSM_trans *t;	/* outgoing edges */
+	struct FSM_trans *p;	/* incoming edges, predecessors */
+	struct FSM_state *nxt;	/* linked list of all states */
+} FSM_state;
 
 
 typedef struct FSM_trans {	/* used in pangen5.c - dataflow */
 typedef struct FSM_trans {	/* used in pangen5.c - dataflow */
 	int to;
 	int to;
-	FSM_use *Val[2];	/* 0=reads, 1=writes */
+	short	relevant;	/* when sliced */
+	short	round;		/* ditto: iteration when marked */
+	struct FSM_use *Val[2];	/* 0=reads, 1=writes */
 	struct Element *step;
 	struct Element *step;
 	struct FSM_trans *nxt;
 	struct FSM_trans *nxt;
 } FSM_trans;
 } FSM_trans;
 
 
-typedef struct FSM_state {	/* used in pangen5.c - dataflow */
-	int from;		/* state number */
-	int seen;		/* used for dfs */
-	int in;			/* nr of incoming edges */
-	FSM_trans *t;		/* outgoing edges list */
-	struct FSM_state *nxt;	/* linked list of all states */
-} FSM_state;
+typedef struct FSM_use {	/* used in pangen5.c - dataflow */
+	Lextok *n;
+	Symbol *var;
+	int special;
+	struct FSM_use *nxt;
+} FSM_use;
 
 
 typedef struct Element {
 typedef struct Element {
 	Lextok	*n;		/* defines the type & contents */
 	Lextok	*n;		/* defines the type & contents */
@@ -132,7 +150,7 @@ typedef struct Label {
 	Symbol	*s;
 	Symbol	*s;
 	Symbol	*c;
 	Symbol	*c;
 	Element	*e;
 	Element	*e;
-	int	visible;	/* label referenced in claim */
+	int	visible;	/* label referenced in claim (slice relevant) */
 	struct Label	*nxt;
 	struct Label	*nxt;
 } Label;
 } Label;
 
 
@@ -182,11 +200,14 @@ typedef	Lextok *Lexptr;
 
 
 #define Nhash	255    		/* slots in symbol hash-table */
 #define Nhash	255    		/* slots in symbol hash-table */
 
 
-#define XR	  1		/* non-shared receive-only */
-#define XS	  2		/* non-shared send-only    */
-#define XX	  4		/* overrides XR or XS tag  */
+#define XR	  	1	/* non-shared receive-only */
+#define XS	  	2	/* non-shared send-only    */
+#define XX	  	4	/* overrides XR or XS tag  */
+
+#define CODE_FRAG	2	/* auto-numbered code-fragment */
+#define CODE_DECL	4	/* auto-numbered c_decl */
+#define PREDEF	  	3	/* predefined name: _p, _last */
 
 
-#define PREDEF	  3		/* predefined names: _p, _last */
 #define UNSIGNED  5		/* val defines width in bits */
 #define UNSIGNED  5		/* val defines width in bits */
 #define BIT	  1		/* also equal to width in bits */
 #define BIT	  1		/* also equal to width in bits */
 #define BYTE	  8		/* ditto */
 #define BYTE	  8		/* ditto */
@@ -195,6 +216,9 @@ typedef	Lextok *Lexptr;
 #define	CHAN	 64		/* not */
 #define	CHAN	 64		/* not */
 #define STRUCT	128		/* user defined structure name */
 #define STRUCT	128		/* user defined structure name */
 
 
+#define SOMETHINGBIG	65536
+#define RATHERSMALL	512
+
 #ifndef max
 #ifndef max
 #define max(a,b) (((a)<(b)) ? (b) : (a))
 #define max(a,b) (((a)<(b)) ? (b) : (a))
 #endif
 #endif
@@ -204,7 +228,7 @@ enum	{ INIV, PUTV, LOGV };	/* for pangen[14].c */
 /***** prototype definitions *****/
 /***** prototype definitions *****/
 Element	*eval_sub(Element *);
 Element	*eval_sub(Element *);
 Element	*get_lab(Lextok *, int);
 Element	*get_lab(Lextok *, int);
-Element	*huntele(Element *, int);
+Element	*huntele(Element *, int, int);
 Element	*huntstart(Element *);
 Element	*huntstart(Element *);
 Element	*target(Element *);
 Element	*target(Element *);
 
 
@@ -214,6 +238,7 @@ Lextok	*getuname(Symbol *);
 Lextok	*mk_explicit(Lextok *, int, int);
 Lextok	*mk_explicit(Lextok *, int, int);
 Lextok	*nn(Lextok *, int, Lextok *, Lextok *);
 Lextok	*nn(Lextok *, int, Lextok *, Lextok *);
 Lextok	*rem_lab(Symbol *, Lextok *, Symbol *);
 Lextok	*rem_lab(Symbol *, Lextok *, Symbol *);
+Lextok	*rem_var(Symbol *, Lextok *, Symbol *, Lextok *);
 Lextok	*tail_add(Lextok *, Lextok *);
 Lextok	*tail_add(Lextok *, Lextok *);
 
 
 ProcList *ready(Symbol *, Lextok *, Sequence *, int, Lextok *);
 ProcList *ready(Symbol *, Lextok *, Sequence *, int, Lextok *);
@@ -223,14 +248,16 @@ Sequence *close_seq(int);
 
 
 Symbol	*break_dest(void);
 Symbol	*break_dest(void);
 Symbol	*findloc(Symbol *);
 Symbol	*findloc(Symbol *);
-Symbol	*lookup(char *);
 Symbol	*has_lab(Element *, int);
 Symbol	*has_lab(Element *, int);
+Symbol	*lookup(char *);
+Symbol	*prep_inline(Symbol *, Lextok *);
 
 
 char	*emalloc(int);
 char	*emalloc(int);
 long	Rand(void);
 long	Rand(void);
 
 
 int	any_oper(Lextok *, int);
 int	any_oper(Lextok *, int);
 int	any_undo(Lextok *);
 int	any_undo(Lextok *);
+int	c_add_sv(FILE *);
 int	cast_val(int, int, int);
 int	cast_val(int, int, int);
 int	checkvar(Symbol *, int);
 int	checkvar(Symbol *, int);
 int	Cnt_flds(Lextok *);
 int	Cnt_flds(Lextok *);
@@ -244,8 +271,11 @@ int	find_maxel(Symbol *);
 int	full_name(FILE *, Lextok *, Symbol *, int);
 int	full_name(FILE *, Lextok *, Symbol *, int);
 int	getlocal(Lextok *);
 int	getlocal(Lextok *);
 int	getval(Lextok *);
 int	getval(Lextok *);
+int	glob_inline(char *);
 int	has_typ(Lextok *, int);
 int	has_typ(Lextok *, int);
+int	in_bound(Symbol *, int);
 int	interprint(FILE *, Lextok *);
 int	interprint(FILE *, Lextok *);
+int	printm(FILE *, Lextok *);
 int	ismtype(char *);
 int	ismtype(char *);
 int	isproctype(char *);
 int	isproctype(char *);
 int	isutype(char *);
 int	isutype(char *);
@@ -253,7 +283,7 @@ int	Lval_struct(Lextok *, Symbol *, int, int);
 int	main(int, char **);
 int	main(int, char **);
 int	pc_value(Lextok *);
 int	pc_value(Lextok *);
 int	proper_enabler(Lextok *);
 int	proper_enabler(Lextok *);
-int	putcode(FILE *, Sequence *, Element *, int, int);
+int	putcode(FILE *, Sequence *, Element *, int, int, int);
 int	q_is_sync(Lextok *);
 int	q_is_sync(Lextok *);
 int	qlen(Lextok *);
 int	qlen(Lextok *);
 int	qfull(Lextok *);
 int	qfull(Lextok *);
@@ -273,15 +303,28 @@ int	yyparse(void);
 int	yywrap(void);
 int	yywrap(void);
 int	yylex(void);
 int	yylex(void);
 
 
+void	AST_track(Lextok *, int);
 void	add_seq(Lextok *);
 void	add_seq(Lextok *);
 void	alldone(int);
 void	alldone(int);
 void	announce(char *);
 void	announce(char *);
+void	c_state(Symbol *, Symbol *, Symbol *);
+void	c_add_def(FILE *);
+void	c_add_loc(FILE *, char *);
+void	c_add_locinit(FILE *, int, char *);
+void	c_add_use(FILE *);
+void	c_chandump(FILE *);
+void	c_preview(void);
+void	c_struct(FILE *, char *, Symbol *);
+void	c_track(Symbol *, Symbol *, Symbol *);
+void	c_var(FILE *, char *, Symbol *);
+void	c_wrapper(FILE *);
 void	chanaccess(void);
 void	chanaccess(void);
 void	checkrun(Symbol *, int);
 void	checkrun(Symbol *, int);
 void	comment(FILE *, Lextok *, int);
 void	comment(FILE *, Lextok *, int);
 void	cross_dsteps(Lextok *, Lextok *);
 void	cross_dsteps(Lextok *, Lextok *);
 void	doq(Symbol *, int, RunList *);
 void	doq(Symbol *, int, RunList *);
 void	dotag(FILE *, char *);
 void	dotag(FILE *, char *);
+void	do_locinits(FILE *);
 void	do_var(FILE *, int, char *, Symbol *, char *, char *, char *);
 void	do_var(FILE *, int, char *, Symbol *, char *, char *, char *);
 void	dump_struct(Symbol *, char *, RunList *);
 void	dump_struct(Symbol *, char *, RunList *);
 void	dumpclaims(FILE *, int, char *);
 void	dumpclaims(FILE *, int, char *);
@@ -289,27 +332,33 @@ void	dumpglobals(void);
 void	dumplabels(void);
 void	dumplabels(void);
 void	dumplocal(RunList *);
 void	dumplocal(RunList *);
 void	dumpsrc(int, int);
 void	dumpsrc(int, int);
-/* void	exit(int);	in stdlib.h */
 void	fatal(char *, char *);
 void	fatal(char *, char *);
 void	fix_dest(Symbol *, Symbol *);
 void	fix_dest(Symbol *, Symbol *);
 void	genaddproc(void);
 void	genaddproc(void);
 void	genaddqueue(void);
 void	genaddqueue(void);
+void	gencodetable(FILE *);
 void	genheader(void);
 void	genheader(void);
 void	genother(void);
 void	genother(void);
 void	gensrc(void);
 void	gensrc(void);
 void	gensvmap(void);
 void	gensvmap(void);
 void	genunio(void);
 void	genunio(void);
 void	ini_struct(Symbol *);
 void	ini_struct(Symbol *);
+void	loose_ends(void);
 void	make_atomic(Sequence *, int);
 void	make_atomic(Sequence *, int);
 void	match_trail(void);
 void	match_trail(void);
+void	no_side_effects(char *);
 void	nochan_manip(Lextok *, Lextok *, int);
 void	nochan_manip(Lextok *, Lextok *, int);
 void	non_fatal(char *, char *);
 void	non_fatal(char *, char *);
 void	ntimes(FILE *, int, int, char *c[]);
 void	ntimes(FILE *, int, int, char *c[]);
 void	open_seq(int);
 void	open_seq(int);
 void	p_talk(Element *, int);
 void	p_talk(Element *, int);
 void	pickup_inline(Symbol *, Lextok *);
 void	pickup_inline(Symbol *, Lextok *);
+void	plunk_c_decls(FILE *);
+void	plunk_c_fcts(FILE *);
+void	plunk_expr(FILE *, char *);
+void	plunk_inline(FILE *, char *, int);
 void	prehint(Symbol *);
 void	prehint(Symbol *);
-void	prep_inline(Symbol *, Lextok *);
+void	preruse(FILE *, Lextok *);
 void	prune_opts(Lextok *);
 void	prune_opts(Lextok *);
 void	pstext(int, char *);
 void	pstext(int, char *);
 void	pushbreak(void);
 void	pushbreak(void);
@@ -334,6 +383,7 @@ void	Srand(unsigned);
 void	start_claim(int);
 void	start_claim(int);
 void	struct_name(Lextok *, Symbol *, int, char *);
 void	struct_name(Lextok *, Symbol *, int, char *);
 void	symdump(void);
 void	symdump(void);
+void	symvar(Symbol *);
 void	trackchanuse(Lextok *, Lextok *, int);
 void	trackchanuse(Lextok *, Lextok *, int);
 void	trackvar(Lextok *, Lextok *);
 void	trackvar(Lextok *, Lextok *);
 void	trackrun(Lextok *);
 void	trackrun(Lextok *);
@@ -347,3 +397,4 @@ void	varcheck(Element *, Element *);
 void	whoruns(int);
 void	whoruns(int);
 void	wrapup(int);
 void	wrapup(int);
 void	yyerror(char *, ...);
 void	yyerror(char *, ...);
+#endif

+ 101 - 24
sys/src/cmd/spin/spin.y

@@ -1,14 +1,13 @@
 /***** spin: spin.y *****/
 /***** spin: spin.y *****/
 
 
-/* Copyright (c) 1991-2000 by Lucent Technologies - Bell Laboratories     */
+/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories.     */
 /* All Rights Reserved.  This software is for educational purposes only.  */
 /* All Rights Reserved.  This software is for educational purposes only.  */
-/* Permission is given to distribute this code provided that this intro-  */
-/* ductory message is not removed and no monies are exchanged.            */
-/* No guarantee is expressed or implied by the distribution of this code. */
-/* Software written by Gerard J. Holzmann as part of the book:            */
-/* `Design and Validation of Computer Protocols,' ISBN 0-13-539925-4,     */
-/* Prentice Hall, Englewood Cliffs, NJ, 07632.                            */
-/* Send bug-reports and/or questions to: gerard@research.bell-labs.com    */
+/* No guarantee whatsoever is expressed or implied by the distribution of */
+/* this code.  Permission is given to distribute this code provided that  */
+/* this introductory message is not removed and no monies are exchanged.  */
+/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
+/*             http://spinroot.com/                                       */
+/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
 
 
 %{
 %{
 #include "spin.h"
 #include "spin.h"
@@ -20,6 +19,8 @@
 extern  Symbol	*context, *owner;
 extern  Symbol	*context, *owner;
 extern  int	u_sync, u_async, dumptab;
 extern  int	u_sync, u_async, dumptab;
 extern	short	has_sorted, has_random, has_enabled, has_pcvalue, has_np;
 extern	short	has_sorted, has_random, has_enabled, has_pcvalue, has_np;
+extern	short	has_code, has_state, has_io;
+extern	void	count_runs(Lextok *);
 extern	void	validref(Lextok *, Lextok *);
 extern	void	validref(Lextok *, Lextok *);
 extern	char	yytext[];
 extern	char	yytext[];
 
 
@@ -33,7 +34,8 @@ static	int	Embedded = 0, inEventMap = 0, has_ini = 0;
 
 
 %}
 %}
 
 
-%token	ASSERT PRINT
+%token	ASSERT PRINT PRINTM
+%token	C_CODE C_DECL C_EXPR C_STATE C_TRACK
 %token	RUN LEN ENABLED EVAL PC_VAL
 %token	RUN LEN ENABLED EVAL PC_VAL
 %token	TYPEDEF MTYPE INLINE LABEL OF
 %token	TYPEDEF MTYPE INLINE LABEL OF
 %token	GOTO BREAK ELSE SEMI
 %token	GOTO BREAK ELSE SEMI
@@ -80,6 +82,7 @@ unit	: proc		/* proctype { }       */
 	| events	/* event assertions   */
 	| events	/* event assertions   */
 	| one_decl	/* variables, chans   */
 	| one_decl	/* variables, chans   */
 	| utype		/* user defined types */
 	| utype		/* user defined types */
+	| c_fcts	/* c functions etc.   */
 	| ns		/* named sequence     */
 	| ns		/* named sequence     */
 	| SEMI		/* optional separator */
 	| SEMI		/* optional separator */
 	| error
 	| error
@@ -121,14 +124,17 @@ inst	: /* empty */	{ $$ = ZN; }
 	| ACTIVE	{ $$ = nn(ZN,CONST,ZN,ZN); $$->val = 1; }
 	| ACTIVE	{ $$ = nn(ZN,CONST,ZN,ZN); $$->val = 1; }
 	| ACTIVE '[' CONST ']' {
 	| ACTIVE '[' CONST ']' {
 			  $$ = nn(ZN,CONST,ZN,ZN); $$->val = $3->val;
 			  $$ = nn(ZN,CONST,ZN,ZN); $$->val = $3->val;
+			  if ($3->val > 255)
+				non_fatal("max nr of processes is 255\n", "");
 			}
 			}
 	| ACTIVE '[' NAME ']' {
 	| ACTIVE '[' NAME ']' {
 			  $$ = nn(ZN,CONST,ZN,ZN);
 			  $$ = nn(ZN,CONST,ZN,ZN);
 			  $$->val = 0;
 			  $$->val = 0;
 			  if (!$3->sym->type)
 			  if (!$3->sym->type)
-				non_fatal("undeclared variable %s", $3->sym->name);
+				non_fatal("undeclared variable %s",
+					$3->sym->name);
 			  else if ($3->sym->ini->ntyp != CONST)
 			  else if ($3->sym->ini->ntyp != CONST)
-				non_fatal("constant initializer required for %s\n",
+				non_fatal("need constant initializer for %s\n",
 					$3->sym->name);
 					$3->sym->name);
 			  else
 			  else
 				$$->val = $3->sym->ini->val;
 				$$->val = $3->sym->ini->val;
@@ -183,7 +189,63 @@ nm	: NAME			{ $$ = $1; }
 	;
 	;
 
 
 ns	: INLINE nm '('		{ NamesNotAdded++; }
 ns	: INLINE nm '('		{ NamesNotAdded++; }
-	  args ')'		{ prep_inline($2->sym, $5); NamesNotAdded--; }
+	  args ')'		{ prep_inline($2->sym, $5);
+				  NamesNotAdded--;
+				}
+	;
+
+c_fcts	: ccode			{ /* leaves pseudo-inlines with sym of
+				   * type CODE_FRAG or CODE_DECL in global context
+				   */
+				}
+	| cstate
+	;
+
+cstate	: C_STATE STRING STRING	{
+				  c_state($2->sym, $3->sym, ZS);
+				  has_code = has_state = 1;
+				}
+	| C_TRACK STRING STRING {
+				  c_track($2->sym, $3->sym, ZS);
+				  has_code = has_state = 1;
+				}
+	| C_STATE STRING STRING	STRING {
+				  c_state($2->sym, $3->sym, $4->sym);
+				  has_code = has_state = 1;
+				}
+	| C_TRACK STRING STRING STRING {
+				  c_track($2->sym, $3->sym, $4->sym);
+				  has_code = has_state = 1;
+				}
+	;
+
+ccode	: C_CODE		{ Symbol *s;
+				  NamesNotAdded++;
+				  s = prep_inline(ZS, ZN);
+				  NamesNotAdded--;
+				  $$ = nn(ZN, C_CODE, ZN, ZN);
+				  $$->sym = s;
+				  has_code = 1;
+				}
+	| C_DECL		{ Symbol *s;
+				  NamesNotAdded++;
+				  s = prep_inline(ZS, ZN);
+				  NamesNotAdded--;
+				  s->type = CODE_DECL;
+				  $$ = nn(ZN, C_CODE, ZN, ZN);
+				  $$->sym = s;
+				  has_code = 1;
+				}
+	;
+cexpr	: C_EXPR		{ Symbol *s;
+				  NamesNotAdded++;
+				  s = prep_inline(ZS, ZN);
+				  NamesNotAdded--;
+				  $$ = nn(ZN, C_EXPR, ZN, ZN);
+				  $$->sym = s;
+				  no_side_effects(s->name);
+				  has_code = 1;
+				}
 	;
 	;
 
 
 body	: '{'			{ open_seq(1); }
 body	: '{'			{ open_seq(1); }
@@ -197,6 +259,8 @@ sequence: step			{ if ($1) add_seq($1); }
 
 
 step    : one_decl		{ $$ = ZN; }
 step    : one_decl		{ $$ = ZN; }
 	| XU vref_lst		{ setxus($2, $1->val); $$ = ZN; }
 	| XU vref_lst		{ setxus($2, $1->val); $$ = ZN; }
+	| NAME ':' one_decl	{ fatal("label preceding declaration,", (char *)0); }
+	| NAME ':' XU		{ fatal("label predecing xr/xs claim,", 0); }
 	| stmnt			{ $$ = $1; }
 	| stmnt			{ $$ = $1; }
 	| stmnt UNLESS stmnt	{ $$ = do_unless($1, $3); }
 	| stmnt UNLESS stmnt	{ $$ = do_unless($1, $3); }
 	;
 	;
@@ -269,6 +333,11 @@ ch_init : '[' CONST ']' OF
 
 
 vardcl  : NAME  		{ $1->sym->nel = 1; $$ = $1; }
 vardcl  : NAME  		{ $1->sym->nel = 1; $$ = $1; }
 	| NAME ':' CONST	{ $1->sym->nbits = $3->val;
 	| NAME ':' CONST	{ $1->sym->nbits = $3->val;
+				  if ($3->val >= 8*sizeof(long))
+				  {	non_fatal("width-field %s too large",
+						$1->sym->name);
+					$3->val = 8*sizeof(long)-1;
+				  }
 				  $1->sym->nel = 1; $$ = $1;
 				  $1->sym->nel = 1; $$ = $1;
 				}
 				}
 	| NAME '[' CONST ']'	{ $1->sym->nel = $3->val; $$ = $1; }
 	| NAME '[' CONST ']'	{ $1->sym->nel = $3->val; $$ = $1; }
@@ -311,12 +380,12 @@ stmnt	: Special		{ $$ = $1; }
 	;
 	;
 
 
 Special : varref RCV		{ Expand_Ok++; }
 Special : varref RCV		{ Expand_Ok++; }
-	  rargs			{ Expand_Ok--;
+	  rargs			{ Expand_Ok--; has_io++;
 				  $$ = nn($1,  'r', $1, $4);
 				  $$ = nn($1,  'r', $1, $4);
 				  trackchanuse($4, ZN, 'R');
 				  trackchanuse($4, ZN, 'R');
 				}
 				}
 	| varref SND		{ Expand_Ok++; }
 	| varref SND		{ Expand_Ok++; }
-	  margs			{ Expand_Ok--;
+	  margs			{ Expand_Ok--; has_io++;
 				  $$ = nn($1, 's', $1, $4);
 				  $$ = nn($1, 's', $1, $4);
 				  $$->val=0; trackchanuse($4, ZN, 'S');
 				  $$->val=0; trackchanuse($4, ZN, 'S');
 				}
 				}
@@ -370,32 +439,35 @@ Stmnt	: varref ASGN expr	{ $$ = nn($1, ASGN, $1, $3);
 				}
 				}
 	| PRINT	'(' STRING	{ realread = 0; }
 	| PRINT	'(' STRING	{ realread = 0; }
 	  prargs ')'		{ $$ = nn($3, PRINT, $5, ZN); realread = 1; }
 	  prargs ')'		{ $$ = nn($3, PRINT, $5, ZN); realread = 1; }
-	| ASSERT full_expr    	{ $$ = nn(ZN, ASSERT, $2, ZN); }
+	| PRINTM '(' varref ')'	{ $$ = nn(ZN, PRINTM, $3, ZN); }
+	| PRINTM '(' CONST ')'	{ $$ = nn(ZN, PRINTM, $3, ZN); }
+	| ASSERT full_expr    	{ $$ = nn(ZN, ASSERT, $2, ZN); AST_track($2, 0); }
+	| ccode			{ $$ = $1; }
 	| varref R_RCV		{ Expand_Ok++; }
 	| varref R_RCV		{ Expand_Ok++; }
-	  rargs			{ Expand_Ok--;
+	  rargs			{ Expand_Ok--; has_io++;
 				  $$ = nn($1,  'r', $1, $4);
 				  $$ = nn($1,  'r', $1, $4);
 				  $$->val = has_random = 1;
 				  $$->val = has_random = 1;
 				  trackchanuse($4, ZN, 'R');
 				  trackchanuse($4, ZN, 'R');
 				}
 				}
 	| varref RCV		{ Expand_Ok++; }
 	| varref RCV		{ Expand_Ok++; }
-	  LT rargs GT		{ Expand_Ok--;
+	  LT rargs GT		{ Expand_Ok--; has_io++;
 				  $$ = nn($1, 'r', $1, $5);
 				  $$ = nn($1, 'r', $1, $5);
 				  $$->val = 2;	/* fifo poll */
 				  $$->val = 2;	/* fifo poll */
 				  trackchanuse($5, ZN, 'R');
 				  trackchanuse($5, ZN, 'R');
 				}
 				}
 	| varref R_RCV		{ Expand_Ok++; }
 	| varref R_RCV		{ Expand_Ok++; }
-	  LT rargs GT		{ Expand_Ok--;	/* rrcv poll */
+	  LT rargs GT		{ Expand_Ok--; has_io++;	/* rrcv poll */
 				  $$ = nn($1, 'r', $1, $5);
 				  $$ = nn($1, 'r', $1, $5);
 				  $$->val = 3; has_random = 1;
 				  $$->val = 3; has_random = 1;
 				  trackchanuse($5, ZN, 'R');
 				  trackchanuse($5, ZN, 'R');
 				}
 				}
 	| varref O_SND		{ Expand_Ok++; }
 	| varref O_SND		{ Expand_Ok++; }
-	  margs			{ Expand_Ok--;
+	  margs			{ Expand_Ok--; has_io++;
 				  $$ = nn($1, 's', $1, $4);
 				  $$ = nn($1, 's', $1, $4);
 				  $$->val = has_sorted = 1;
 				  $$->val = has_sorted = 1;
 				  trackchanuse($4, ZN, 'S');
 				  trackchanuse($4, ZN, 'S');
 				}
 				}
-	| full_expr		{ $$ = nn(ZN, 'c', $1, ZN); }
+	| full_expr		{ $$ = nn(ZN, 'c', $1, ZN); count_runs($$); }
 	| ELSE  		{ $$ = nn(ZN,ELSE,ZN,ZN);
 	| ELSE  		{ $$ = nn(ZN,ELSE,ZN,ZN);
 				}
 				}
 	| ATOMIC   '{'   	{ open_seq(0); }
 	| ATOMIC   '{'   	{ open_seq(0); }
@@ -485,15 +557,16 @@ expr    : '(' expr ')'		{ $$ = $2; }
 				  has_enabled++;
 				  has_enabled++;
 				}
 				}
 	| varref RCV		{ Expand_Ok++; }
 	| varref RCV		{ Expand_Ok++; }
-	  '[' rargs ']'		{ Expand_Ok--;
+	  '[' rargs ']'		{ Expand_Ok--; has_io++;
 				  $$ = nn($1, 'R', $1, $5);
 				  $$ = nn($1, 'R', $1, $5);
 				}
 				}
 	| varref R_RCV		{ Expand_Ok++; }
 	| varref R_RCV		{ Expand_Ok++; }
-	  '[' rargs ']'		{ Expand_Ok--;
+	  '[' rargs ']'		{ Expand_Ok--; has_io++;
 				  $$ = nn($1, 'R', $1, $5);
 				  $$ = nn($1, 'R', $1, $5);
 				  $$->val = has_random = 1;
 				  $$->val = has_random = 1;
 				}
 				}
 	| varref		{ $$ = $1; trapwonly($1, "varref"); }
 	| varref		{ $$ = $1; trapwonly($1, "varref"); }
+	| cexpr			{ $$ = $1; }
 	| CONST 		{ $$ = nn(ZN,CONST,ZN,ZN);
 	| CONST 		{ $$ = nn(ZN,CONST,ZN,ZN);
 				  $$->ismtyp = $1->ismtyp;
 				  $$->ismtyp = $1->ismtyp;
 				  $$->val = $1->val;
 				  $$->val = $1->val;
@@ -505,8 +578,12 @@ expr    : '(' expr ')'		{ $$ = $2; }
 	| PC_VAL '(' expr ')'	{ $$ = nn(ZN, PC_VAL, $3, ZN);
 	| PC_VAL '(' expr ')'	{ $$ = nn(ZN, PC_VAL, $3, ZN);
 				  has_pcvalue++;
 				  has_pcvalue++;
 				}
 				}
-	| PNAME '[' expr ']' '@'
-	  NAME			{ $$ = rem_lab($1->sym, $3, $6->sym); }
+	| PNAME '[' expr ']' '@' NAME
+	  			{ $$ = rem_lab($1->sym, $3, $6->sym); }
+	| PNAME '[' expr ']' ':' pfld
+	  			{ $$ = rem_var($1->sym, $3, $6->sym, $6->lft); }
+	| PNAME '@' NAME	{ $$ = rem_lab($1->sym, ZN, $3->sym); }
+	| PNAME ':' pfld	{ $$ = rem_var($1->sym, ZN, $3->sym, $3->lft); }
 	;
 	;
 
 
 Opt_priority:	/* none */	{ $$ = ZN; }
 Opt_priority:	/* none */	{ $$ = ZN; }

File diff suppressed because it is too large
+ 781 - 43
sys/src/cmd/spin/spinlex.c


+ 55 - 15
sys/src/cmd/spin/structs.c

@@ -1,14 +1,13 @@
 /***** spin: structs.c *****/
 /***** spin: structs.c *****/
 
 
-/* Copyright (c) 1991-2000 by Lucent Technologies - Bell Laboratories     */
+/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories.     */
 /* All Rights Reserved.  This software is for educational purposes only.  */
 /* All Rights Reserved.  This software is for educational purposes only.  */
-/* Permission is given to distribute this code provided that this intro-  */
-/* ductory message is not removed and no monies are exchanged.            */
-/* No guarantee is expressed or implied by the distribution of this code. */
-/* Software written by Gerard J. Holzmann as part of the book:            */
-/* `Design and Validation of Computer Protocols,' ISBN 0-13-539925-4,     */
-/* Prentice Hall, Englewood Cliffs, NJ, 07632.                            */
-/* Send bug-reports and/or questions to: gerard@research.bell-labs.com    */
+/* No guarantee whatsoever is expressed or implied by the distribution of */
+/* this code.  Permission is given to distribute this code provided that  */
+/* this introductory message is not removed and no monies are exchanged.  */
+/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
+/*             http://spinroot.com/                                       */
+/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
 
 
 #include "spin.h"
 #include "spin.h"
 #ifdef PC
 #ifdef PC
@@ -23,8 +22,6 @@ typedef struct UType {
 	struct UType *nxt;	/* linked list */
 	struct UType *nxt;	/* linked list */
 } UType;
 } UType;
 
 
-extern	Symbol	*context;
-extern	RunList	*X;
 extern	Symbol	*Fname;
 extern	Symbol	*Fname;
 extern	int	lineno, depth, Expand_Ok;
 extern	int	lineno, depth, Expand_Ok;
 
 
@@ -254,7 +251,7 @@ is_lst:
 	for (tl = fp->lft; tl; tl = tl->rgt)
 	for (tl = fp->lft; tl; tl = tl->rgt)
 	{	if (tl->sym->type == STRUCT)
 	{	if (tl->sym->type == STRUCT)
 		{	if (tl->sym->nel != 1)
 		{	if (tl->sym->nel != 1)
-				fatal("hidden array in parameter, %s",
+				fatal("array of structures in param list, %s",
 					tl->sym->name);
 					tl->sym->name);
 			cnt += Cnt_flds(tl->sym->Slst);
 			cnt += Cnt_flds(tl->sym->Slst);
 		}  else
 		}  else
@@ -275,7 +272,7 @@ Sym_typ(Lextok *t)
 	if (!t->rgt
 	if (!t->rgt
 	||  !t->rgt->ntyp == '.'
 	||  !t->rgt->ntyp == '.'
 	||  !t->rgt->lft)
 	||  !t->rgt->lft)
-		fatal("unexpected struct layout %s", s->name);
+		return STRUCT;	/* not a field reference */
 
 
 	return Sym_typ(t->rgt->lft);
 	return Sym_typ(t->rgt->lft);
 }
 }
@@ -386,7 +383,7 @@ void
 struct_name(Lextok *n, Symbol *v, int xinit, char *buf)
 struct_name(Lextok *n, Symbol *v, int xinit, char *buf)
 {	Symbol *tl;
 {	Symbol *tl;
 	Lextok *tmp;
 	Lextok *tmp;
-	char lbuf[128];
+	char lbuf[512];
 
 
 	if (!n || !(tl = do_same(n, v, xinit)))
 	if (!n || !(tl = do_same(n, v, xinit)))
 		return;
 		return;
@@ -447,10 +444,37 @@ walk_struct(FILE *ofd, int dowhat, char *s, Symbol *z, char *a, char *b, char *c
 	}	}
 	}	}
 }
 }
 
 
+void
+c_struct(FILE *fd, char *ipref, Symbol *z)
+{	Lextok *fp, *tl;
+	char pref[256], eprefix[256];
+	int ix;
+
+	ini_struct(z);
+
+	for (ix = 0; ix < z->nel; ix++)
+	for (fp = z->Sval[ix]; fp; fp = fp->rgt)
+	for (tl = fp->lft; tl; tl = tl->rgt)
+	{	strcpy(eprefix, ipref);
+		if (z->nel > 1)
+		{	/* insert index before last '.' */
+			eprefix[strlen(eprefix)-1] = '\0';
+			sprintf(pref, "[ %d ].", ix);
+			strcat(eprefix, pref);
+		}
+		if (tl->sym->type == STRUCT)
+		{	strcat(eprefix, tl->sym->name);
+			strcat(eprefix, ".");
+			c_struct(fd, eprefix, tl->sym);
+		} else
+			c_var(fd, eprefix, tl->sym);
+	}
+}
+
 void
 void
 dump_struct(Symbol *z, char *prefix, RunList *r)
 dump_struct(Symbol *z, char *prefix, RunList *r)
 {	Lextok *fp, *tl;
 {	Lextok *fp, *tl;
-	char eprefix[128];
+	char eprefix[256];
 	int ix, jx;
 	int ix, jx;
 
 
 	ini_struct(z);
 	ini_struct(z);
@@ -464,7 +488,7 @@ dump_struct(Symbol *z, char *prefix, RunList *r)
 		for (fp = z->Sval[ix]; fp; fp = fp->rgt)
 		for (fp = z->Sval[ix]; fp; fp = fp->rgt)
 		for (tl = fp->lft; tl; tl = tl->rgt)
 		for (tl = fp->lft; tl; tl = tl->rgt)
 		{	if (tl->sym->type == STRUCT)
 		{	if (tl->sym->type == STRUCT)
-			{	char pref[128];
+			{	char pref[256];
 				strcpy(pref, eprefix);
 				strcpy(pref, eprefix);
 				strcat(pref, ".");
 				strcat(pref, ".");
 				strcat(pref, tl->sym->name);
 				strcat(pref, tl->sym->name);
@@ -562,6 +586,22 @@ mk_explicit(Lextok *n, int Ok, int Ntyp)
 	||  is_explicit(n))
 	||  is_explicit(n))
 		return n;
 		return n;
 
 
+	if (n->rgt
+	&&  n->rgt->ntyp == '.'
+	&&  n->rgt->lft
+	&&  n->rgt->lft->sym
+	&&  n->rgt->lft->sym->type == STRUCT)
+	{	Lextok *y;
+		bld = mk_explicit(n->rgt->lft, Ok, Ntyp);
+		for (x = bld; x; x = x->rgt)
+		{	y = cpnn(n, 1, 0, 0);
+			y->rgt = nn(ZN, '.', x->lft, ZN);
+			x->lft = y;
+		}
+
+		return bld;
+	}
+
 	if (!Ok || !n->sym->Slst)
 	if (!Ok || !n->sym->Slst)
 	{	if (IArgs) return n;
 	{	if (IArgs) return n;
 		printf("spin: saw '");
 		printf("spin: saw '");

+ 25 - 19
sys/src/cmd/spin/sym.c

@@ -1,14 +1,13 @@
 /***** spin: sym.c *****/
 /***** spin: sym.c *****/
 
 
-/* Copyright (c) 1991-2000 by Lucent Technologies - Bell Laboratories     */
+/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories.     */
 /* All Rights Reserved.  This software is for educational purposes only.  */
 /* All Rights Reserved.  This software is for educational purposes only.  */
-/* Permission is given to distribute this code provided that this intro-  */
-/* ductory message is not removed and no monies are exchanged.            */
-/* No guarantee is expressed or implied by the distribution of this code. */
-/* Software written by Gerard J. Holzmann as part of the book:            */
-/* `Design and Validation of Computer Protocols,' ISBN 0-13-539925-4,     */
-/* Prentice Hall, Englewood Cliffs, NJ, 07632.                            */
-/* Send bug-reports and/or questions to: gerard@research.bell-labs.com    */
+/* No guarantee whatsoever is expressed or implied by the distribution of */
+/* this code.  Permission is given to distribute this code provided that  */
+/* this introductory message is not removed and no monies are exchanged.  */
+/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
+/*             http://spinroot.com/                                       */
+/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
 
 
 #include "spin.h"
 #include "spin.h"
 #ifdef PC
 #ifdef PC
@@ -68,7 +67,7 @@ lookup(char *s)
 			return sp;		/* global */
 			return sp;		/* global */
 
 
 	sp = (Symbol *) emalloc(sizeof(Symbol));
 	sp = (Symbol *) emalloc(sizeof(Symbol));
-	sp->name = (char *) emalloc(strlen(s) + 1);
+	sp->name = (char *) emalloc((int) strlen(s) + 1);
 	strcpy(sp->name, s);
 	strcpy(sp->name, s);
 	sp->nel = 1;
 	sp->nel = 1;
 	sp->setat = depth;
 	sp->setat = depth;
@@ -155,7 +154,7 @@ checkrun(Symbol *parnm, int posno)
 	{	if (!(verbose&32)) return;
 	{	if (!(verbose&32)) return;
 		strcpy(buf2, (!(res&4))?"bit":"byte");
 		strcpy(buf2, (!(res&4))?"bit":"byte");
 		sputtype(buf, parnm->type);
 		sputtype(buf, parnm->type);
-		i = strlen(buf);
+		i = (int) strlen(buf);
 		while (buf[--i] == ' ') buf[i] = '\0';
 		while (buf[--i] == ' ') buf[i] = '\0';
 		if (strcmp(buf, buf2) == 0) return;
 		if (strcmp(buf, buf2) == 0) return;
 		prehint(parnm);
 		prehint(parnm);
@@ -331,7 +330,8 @@ setmtype(Lextok *m)
 			n->lft->sym->ini = nn(ZN,CONST,ZN,ZN);
 			n->lft->sym->ini = nn(ZN,CONST,ZN,ZN);
 			n->lft->sym->ini->val = cnt;
 			n->lft->sym->ini->val = cnt;
 		} else if (n->lft->sym->ini->val != cnt)
 		} else if (n->lft->sym->ini->val != cnt)
-			fatal("cannot happen: setmtype", (char *) 0);
+			non_fatal("name %s appears twice in mtype declaration",
+				n->lft->sym->name);
 	}
 	}
 	lineno = oln;
 	lineno = oln;
 	if (cnt > 256)
 	if (cnt > 256)
@@ -382,7 +382,7 @@ puttype(int m)
 	return 0;
 	return 0;
 }
 }
 
 
-static void
+void
 symvar(Symbol *sp)
 symvar(Symbol *sp)
 {	Lextok *m;
 {	Lextok *m;
 
 
@@ -402,10 +402,10 @@ symvar(Symbol *sp)
 		printf("\t%d", eval(sp->ini));
 		printf("\t%d", eval(sp->ini));
 
 
 	if (sp->owner)
 	if (sp->owner)
-		printf("\t<struct-field>");
+		printf("\t<:struct-field:>");
 	else
 	else
 	if (!sp->context)
 	if (!sp->context)
-		printf("\t<global>");
+		printf("\t<:global:>");
 	else
 	else
 		printf("\t<%s>", sp->context->name);
 		printf("\t<%s>", sp->context->name);
 
 
@@ -419,7 +419,10 @@ symvar(Symbol *sp)
 			i++;
 			i++;
 		printf("\t%d\t", i);
 		printf("\t%d\t", i);
 		for (m = sp->ini->rgt; m; m = m->rgt)
 		for (m = sp->ini->rgt; m; m = m->rgt)
-		{	(void) puttype(m->ntyp);
+		{	if (m->ntyp == STRUCT)
+				printf("struct %s", m->sym->name);
+			else
+				(void) puttype(m->ntyp);
 			if (m->rgt) printf("\t");
 			if (m->rgt) printf("\t");
 		}
 		}
 	}
 	}
@@ -496,6 +499,7 @@ chanaccess(void)
 {	Ordered *walk;
 {	Ordered *walk;
 	char buf[128];
 	char buf[128];
 	extern int Caccess, separate;
 	extern int Caccess, separate;
+	extern short has_code;
 
 
 	for (walk = all_names; walk; walk = walk->next)
 	for (walk = all_names; walk; walk = walk->next)
 	{	if (!walk->entry->owner)
 	{	if (!walk->entry->owner)
@@ -512,10 +516,13 @@ chanaccess(void)
 			if ((walk->entry->hidden&32))
 			if ((walk->entry->hidden&32))
 				continue;
 				continue;
 
 
-			if (!separate && !walk->entry->context && deadvar)
+			if (!separate
+			&&  !walk->entry->context
+			&&  !has_code
+			&&   deadvar)
 				walk->entry->hidden |= 1; /* auto-hide */
 				walk->entry->hidden |= 1; /* auto-hide */
 
 
-			if (!(verbose&32)) continue;
+			if (!(verbose&32) || has_code) continue;
 
 
 			printf("spin: warning, %s, ", Fname->name);
 			printf("spin: warning, %s, ", Fname->name);
 			sputtype(buf, walk->entry->type);
 			sputtype(buf, walk->entry->type);
@@ -526,6 +533,5 @@ chanaccess(void)
 				printf("global");
 				printf("global");
 			printf(", '%s%s' variable is never used\n",
 			printf(", '%s%s' variable is never used\n",
 				buf, walk->entry->name);
 				buf, walk->entry->name);
-		}
-	}
+	}	}
 }
 }

+ 8 - 6
sys/src/cmd/spin/tl.h

@@ -1,14 +1,16 @@
 /***** tl_spin: tl.h *****/
 /***** tl_spin: tl.h *****/
 
 
-/* Copyright (c) 1995-2000 by Lucent Technologies - Bell Laboratories     */
+/* Copyright (c) 1995-2003 by Lucent Technologies, Bell Laboratories.     */
 /* All Rights Reserved.  This software is for educational purposes only.  */
 /* All Rights Reserved.  This software is for educational purposes only.  */
-/* Permission is given to distribute this code provided that this intro-  */
-/* ductory message is not removed and no monies are exchanged.            */
-/* No guarantee is expressed or implied by the distribution of this code. */
-/* Written by Gerard J. Holzmann, Bell Laboratories, U.S.A.               */
+/* No guarantee whatsoever is expressed or implied by the distribution of */
+/* this code.  Permission is given to distribute this code provided that  */
+/* this introductory message is not removed and no monies are exchanged.  */
+/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
+/*             http://spinroot.com/                                       */
+/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
+
 /* Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper, */
 /* Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper, */
 /* presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995.   */
 /* presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995.   */
-/* Send bug-reports and/or questions to: gerard@research.bell-labs.com    */
 
 
 #include <stdio.h>
 #include <stdio.h>
 #include <string.h>
 #include <string.h>

+ 40 - 48
sys/src/cmd/spin/tl_buchi.c

@@ -1,14 +1,16 @@
 /***** tl_spin: tl_buchi.c *****/
 /***** tl_spin: tl_buchi.c *****/
 
 
-/* Copyright (c) 1995-2000 by Lucent Technologies - Bell Laboratories     */
+/* Copyright (c) 1995-2003 by Lucent Technologies, Bell Laboratories.     */
 /* All Rights Reserved.  This software is for educational purposes only.  */
 /* All Rights Reserved.  This software is for educational purposes only.  */
-/* Permission is given to distribute this code provided that this intro-  */
-/* ductory message is not removed and no monies are exchanged.            */
-/* No guarantee is expressed or implied by the distribution of this code. */
-/* Written by Gerard J. Holzmann, Bell Laboratories, U.S.A.               */
+/* No guarantee whatsoever is expressed or implied by the distribution of */
+/* this code.  Permission is given to distribute this code provided that  */
+/* this introductory message is not removed and no monies are exchanged.  */
+/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
+/*             http://spinroot.com/                                       */
+/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
+
 /* Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper, */
 /* Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper, */
 /* presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995.   */
 /* presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995.   */
-/* Send bug-reports and/or questions to: gerard@research.bell-labs.com    */
 
 
 #include "tl.h"
 #include "tl.h"
 
 
@@ -77,12 +79,6 @@ Prune(Node *p)
 		if (!p->rgt)
 		if (!p->rgt)
 			return p->lft;
 			return p->lft;
 		return p;
 		return p;
-#if 0
-/* 3.3.9 */
-	case V_OPER:
-		releasenode(1, p->lft);
-		return Prune(p->rgt);
-#endif
 	}
 	}
 	releasenode(1, p);
 	releasenode(1, p);
 	return ZN;
 	return ZN;
@@ -118,7 +114,7 @@ Dfs(State *b)
 	b->reachable = 1;
 	b->reachable = 1;
 
 
 	if (b->redundant)
 	if (b->redundant)
-		printf("spin: internal error, Dfs hits redundant state %s\n",
+		printf("/* redundant state %s */\n",
 			b->name->name);
 			b->name->name);
 	for (t = b->trans; t; t = t->nxt)
 	for (t = b->trans; t; t = t->nxt)
 	{	if (!t->redundant)
 	{	if (!t->redundant)
@@ -140,12 +136,8 @@ retarget(char *from, char *to)
 
 
 	for (b = never; b; b = b->nxt)
 	for (b = never; b; b = b->nxt)
 	{	if (!strcmp(b->name->name, from))
 	{	if (!strcmp(b->name->name, from))
-		{	b->redundant = 1;
-			for (t = b->trans; t; t = t->nxt)
-			{	/* releasenode(1, t->cond); */
-				t->cond = ZN;
-			}
-		} else
+			b->redundant = 1;
+		else
 		for (t = b->trans; t; t = t->nxt)
 		for (t = b->trans; t; t = t->nxt)
 		{	if (!strcmp(t->name->name, from))
 		{	if (!strcmp(t->name->name, from))
 				t->name = To;
 				t->name = To;
@@ -189,7 +181,7 @@ combination(Node *s, Node *t)
 #ifdef NXT
 #ifdef NXT
 	Node *a = nonxt(s);
 	Node *a = nonxt(s);
 	Node *b = nonxt(t);
 	Node *b = nonxt(t);
-#if 1
+
 	if (tl_verbose)
 	if (tl_verbose)
 	{	printf("\tnonxtA: "); dump(a);
 	{	printf("\tnonxtA: "); dump(a);
 		printf("\n\tnonxtB: "); dump(b);
 		printf("\n\tnonxtB: "); dump(b);
@@ -200,22 +192,6 @@ combination(Node *s, Node *t)
 		nc = True;
 		nc = True;
 	else
 	else
 		nc = tl_nn(OR, a, b);
 		nc = tl_nn(OR, a, b);
-#else
-	if (!a)
-	{	releasenode(1, s);
-		if (!b)
-		{	releasenode(1, t);
-			nc = False;
-		} else
-		{	nc = b;
-		}
-	} else if (!b)
-	{	releasenode(1, t);
-		nc = a;
-	} else
-	{	nc = tl_nn(OR, a, b);
-	}
-#endif
 #else
 #else
 	nc = tl_nn(OR, s, t);
 	nc = tl_nn(OR, s, t);
 #endif
 #endif
@@ -309,7 +285,7 @@ showtrans(State *a)
 }
 }
 
 
 static int
 static int
-mergetrans(int v)
+mergetrans(void)
 {	State *b;
 {	State *b;
 	Transition *s, *t;
 	Transition *s, *t;
 	Node *nc; int cnt = 0;
 	Node *nc; int cnt = 0;
@@ -389,7 +365,11 @@ done:
 		s->marked = 0;
 		s->marked = 0;
 	return result;
 	return result;
 }
 }
+
+#ifndef NO_OPT
 #define BUCKY
 #define BUCKY
+#endif
+
 #ifdef BUCKY
 #ifdef BUCKY
 static int
 static int
 all_bucky(State *a, State *b)
 all_bucky(State *a, State *b)
@@ -477,7 +457,12 @@ buckyballs(void)
 					}
 					}
 
 
 					if (a->accepting && !b->accepting)
 					if (a->accepting && !b->accepting)
-					{	c = b; d = a;
+					{	if (strcmp(b->name->name, "T0_init") == 0)
+						{	c = a; d = b;
+							b->accepting = 1;
+						} else
+						{	c = b; d = a;
+						}
 					} else
 					} else
 					{	c = a; d = b;
 					{	c = a; d = b;
 					}
 					}
@@ -501,10 +486,10 @@ static int
 mergestates(int v)
 mergestates(int v)
 {	State *a, *b;
 {	State *a, *b;
 	int m, cnt=0;
 	int m, cnt=0;
-#if 1
+
 	if (tl_verbose)
 	if (tl_verbose)
 		return 0;
 		return 0;
-#endif
+
 	do {
 	do {
 		m = 0; cnt++;
 		m = 0; cnt++;
 		for (a = never; a; a = a->nxt)
 		for (a = never; a; a = a->nxt)
@@ -538,7 +523,8 @@ mergestates(int v)
 #if 0
 #if 0
 				else if (tl_verbose)
 				else if (tl_verbose)
 				{	printf("\n%d: state %s differs from state %s [%d,%d]\n",
 				{	printf("\n%d: state %s differs from state %s [%d,%d]\n",
-					cnt, a->name->name, b->name->name, a->accepting, b->accepting);
+						cnt, a->name->name, b->name->name,
+						a->accepting, b->accepting);
 					showtrans(a);
 					showtrans(a);
 					printf("==\n");
 					printf("==\n");
 					showtrans(b);
 					showtrans(b);
@@ -574,6 +560,12 @@ printstate(State *b)
 	b->reachable = 0;	/* print only once */
 	b->reachable = 0;	/* print only once */
 	fprintf(tl_out, "%s:\n", b->name->name);
 	fprintf(tl_out, "%s:\n", b->name->name);
 
 
+	if (tl_verbose)
+	{	fprintf(tl_out, "	/* ");
+		dump(b->colors->Other);
+		fprintf(tl_out, " */\n");
+	}
+
 	if (strncmp(b->name->name, "accept", 6) == 0
 	if (strncmp(b->name->name, "accept", 6) == 0
 	&&  Max_Red == 0)
 	&&  Max_Red == 0)
 		fprintf(tl_out, "T0%s:\n", &(b->name->name[6]));
 		fprintf(tl_out, "T0%s:\n", &(b->name->name[6]));
@@ -595,11 +587,11 @@ addtrans(Graph *col, char *from, Node *op, char *to)
 	t->name = tl_lookup(to);
 	t->name = tl_lookup(to);
 	t->cond = Prune(dupnode(op));
 	t->cond = Prune(dupnode(op));
 
 
-if (tl_verbose)
-{ printf("\n<<\t"); dump(op);
-  printf("\n\t"); dump(t->cond);
-  printf(">> %s\n", t->name->name);
-}
+	if (tl_verbose)
+	{	printf("\n%s <<\t", from); dump(op);
+		printf("\n\t"); dump(t->cond);
+		printf(">> %s\n", t->name->name);
+	}
 	if (t->cond) t->cond = rewrite(t->cond);
 	if (t->cond) t->cond = rewrite(t->cond);
 
 
 	for (b = never; b; b = b->nxt)
 	for (b = never; b; b = b->nxt)
@@ -647,7 +639,7 @@ fsm_print(void)
 	do {
 	do {
 		clr_reach();
 		clr_reach();
 		Dfs(b);
 		Dfs(b);
-		cnt1 = mergetrans(1);
+		cnt1 = mergetrans();
 		cnt2 = mergestates(1);
 		cnt2 = mergestates(1);
 		if (tl_verbose)
 		if (tl_verbose)
 			printf("/* >>%d,%d<< */\n", cnt1, cnt2);
 			printf("/* >>%d,%d<< */\n", cnt1, cnt2);
@@ -658,7 +650,7 @@ fsm_print(void)
 	clr_reach();
 	clr_reach();
 	Dfs(b);
 	Dfs(b);
 #endif
 #endif
-	if (Max_Red == 0)
+	if (b && b->accepting)
 		fprintf(tl_out, "accept_init:\n");
 		fprintf(tl_out, "accept_init:\n");
 
 
 	if (!b && !never)
 	if (!b && !never)

+ 11 - 7
sys/src/cmd/spin/tl_cache.c

@@ -1,14 +1,16 @@
 /***** tl_spin: tl_cache.c *****/
 /***** tl_spin: tl_cache.c *****/
 
 
-/* Copyright (c) 1995-2000 by Lucent Technologies - Bell Laboratories     */
+/* Copyright (c) 1995-2003 by Lucent Technologies, Bell Laboratories.     */
 /* All Rights Reserved.  This software is for educational purposes only.  */
 /* All Rights Reserved.  This software is for educational purposes only.  */
-/* Permission is given to distribute this code provided that this intro-  */
-/* ductory message is not removed and no monies are exchanged.            */
-/* No guarantee is expressed or implied by the distribution of this code. */
-/* Written by Gerard J. Holzmann, Bell Laboratories, U.S.A.               */
+/* No guarantee whatsoever is expressed or implied by the distribution of */
+/* this code.  Permission is given to distribute this code provided that  */
+/* this introductory message is not removed and no monies are exchanged.  */
+/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
+/*             http://spinroot.com/                                       */
+/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
+
 /* Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper, */
 /* Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper, */
 /* presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995.   */
 /* presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995.   */
-/* Send bug-reports and/or questions to: gerard@research.bell-labs.com    */
 
 
 #include "tl.h"
 #include "tl.h"
 
 
@@ -26,6 +28,7 @@ static int	ismatch(Node *, Node *);
 extern void fatal(char *, char *);
 extern void fatal(char *, char *);
 int	sameform(Node *, Node *);
 int	sameform(Node *, Node *);
 
 
+#if 0
 void
 void
 cache_dump(void)
 cache_dump(void)
 {	Cache *d; int nr=0;
 {	Cache *d; int nr=0;
@@ -38,6 +41,7 @@ cache_dump(void)
 	}
 	}
 	printf("============\n");
 	printf("============\n");
 }
 }
+#endif
 
 
 Node *
 Node *
 in_cache(Node *n)
 in_cache(Node *n)
@@ -58,7 +62,7 @@ cached(Node *n)
 	Node *m;
 	Node *m;
 
 
 	if (!n) return n;
 	if (!n) return n;
-	if (m = in_cache(n))
+	if ((m = in_cache(n)) != ZN)
 		return m;
 		return m;
 
 
 	Caches++;
 	Caches++;

+ 18 - 16
sys/src/cmd/spin/tl_lex.c

@@ -1,14 +1,16 @@
 /***** tl_spin: tl_lex.c *****/
 /***** tl_spin: tl_lex.c *****/
 
 
-/* Copyright (c) 1995-2000 by Lucent Technologies - Bell Laboratories     */
+/* Copyright (c) 1995-2003 by Lucent Technologies, Bell Laboratories.     */
 /* All Rights Reserved.  This software is for educational purposes only.  */
 /* All Rights Reserved.  This software is for educational purposes only.  */
-/* Permission is given to distribute this code provided that this intro-  */
-/* ductory message is not removed and no monies are exchanged.            */
-/* No guarantee is expressed or implied by the distribution of this code. */
-/* Written by Gerard J. Holzmann, Bell Laboratories, U.S.A.               */
+/* No guarantee whatsoever is expressed or implied by the distribution of */
+/* this code.  Permission is given to distribute this code provided that  */
+/* this introductory message is not removed and no monies are exchanged.  */
+/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
+/*             http://spinroot.com/                                       */
+/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
+
 /* Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper, */
 /* Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper, */
 /* presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995.   */
 /* presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995.   */
-/* Send bug-reports and/or questions to: gerard@research.bell-labs.com    */
 
 
 #include <stdlib.h>
 #include <stdlib.h>
 #include <ctype.h>
 #include <ctype.h>
@@ -23,7 +25,7 @@ extern char	yytext[];
 #define Token(y)        tl_yylval = tl_nn(y,ZN,ZN); return y
 #define Token(y)        tl_yylval = tl_nn(y,ZN,ZN); return y
 
 
 static void
 static void
-getword(int first, int (*tst)(int))
+tl_getword(int first, int (*tst)(int))
 {	int i=0; char c;
 {	int i=0; char c;
 
 
 	yytext[i++]= (char ) first;
 	yytext[i++]= (char ) first;
@@ -34,7 +36,7 @@ getword(int first, int (*tst)(int))
 }
 }
 
 
 static int
 static int
-follow(int tok, int ifyes, int ifno)
+tl_follow(int tok, int ifyes, int ifno)
 {	int c;
 {	int c;
 	char buf[32];
 	char buf[32];
 	extern int tl_yychar;
 	extern int tl_yychar;
@@ -73,7 +75,7 @@ tl_lex(void)
 	} while (c == ' ');	/* '\t' is removed in tl_main.c */
 	} while (c == ' ');	/* '\t' is removed in tl_main.c */
 
 
 	if (islower(c))
 	if (islower(c))
-	{	getword(c, isalnum_);
+	{	tl_getword(c, isalnum_);
 		if (strcmp("true", yytext) == 0)
 		if (strcmp("true", yytext) == 0)
 		{	Token(TRUE);
 		{	Token(TRUE);
 		}
 		}
@@ -102,12 +104,12 @@ tl_lex(void)
 	}
 	}
 
 
 	switch (c) {
 	switch (c) {
-	case '/' : c = follow('\\', AND, '/'); break;
-	case '\\': c = follow('/', OR, '\\'); break;
-	case '&' : c = follow('&', AND, '&'); break;
-	case '|' : c = follow('|', OR, '|'); break;
-	case '[' : c = follow(']', ALWAYS, '['); break;
-	case '-' : c = follow('>', IMPLIES, '-'); break;
+	case '/' : c = tl_follow('\\', AND, '/'); break;
+	case '\\': c = tl_follow('/', OR, '\\'); break;
+	case '&' : c = tl_follow('&', AND, '&'); break;
+	case '|' : c = tl_follow('|', OR, '|'); break;
+	case '[' : c = tl_follow(']', ALWAYS, '['); break;
+	case '-' : c = tl_follow('>', IMPLIES, '-'); break;
 	case '!' : c = NOT; break;
 	case '!' : c = NOT; break;
 	case 'U' : c = U_OPER; break;
 	case 'U' : c = U_OPER; break;
 	case 'V' : c = V_OPER; break;
 	case 'V' : c = V_OPER; break;
@@ -129,7 +131,7 @@ tl_lookup(char *s)
 			return sp;
 			return sp;
 
 
 	sp = (Symbol *) tl_emalloc(sizeof(Symbol));
 	sp = (Symbol *) tl_emalloc(sizeof(Symbol));
-	sp->name = (char *) tl_emalloc(strlen(s) + 1);
+	sp->name = (char *) tl_emalloc((int) strlen(s) + 1);
 	strcpy(sp->name, s);
 	strcpy(sp->name, s);
 	sp->next = symtab[h];
 	sp->next = symtab[h];
 	symtab[h] = sp;
 	symtab[h] = sp;

+ 22 - 20
sys/src/cmd/spin/tl_main.c

@@ -1,14 +1,16 @@
 /***** tl_spin: tl_main.c *****/
 /***** tl_spin: tl_main.c *****/
 
 
-/* Copyright (c) 1995-2000 by Lucent Technologies - Bell Laboratories     */
+/* Copyright (c) 1995-2003 by Lucent Technologies, Bell Laboratories.     */
 /* All Rights Reserved.  This software is for educational purposes only.  */
 /* All Rights Reserved.  This software is for educational purposes only.  */
-/* Permission is given to distribute this code provided that this intro-  */
-/* ductory message is not removed and no monies are exchanged.            */
-/* No guarantee is expressed or implied by the distribution of this code. */
-/* Written by Gerard J. Holzmann, Bell Laboratories, U.S.A.               */
+/* No guarantee whatsoever is expressed or implied by the distribution of */
+/* this code.  Permission is given to distribute this code provided that  */
+/* this introductory message is not removed and no monies are exchanged.  */
+/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
+/*             http://spinroot.com/                                       */
+/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
+
 /* Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper, */
 /* Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper, */
 /* presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995.   */
 /* presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995.   */
-/* Send bug-reports and/or questions to: gerard@research.bell-labs.com    */
 
 
 #include "tl.h"
 #include "tl.h"
 
 
@@ -24,8 +26,8 @@ unsigned long	All_Mem = 0;
 static char	uform[4096];
 static char	uform[4096];
 static int	hasuform=0, cnt=0;
 static int	hasuform=0, cnt=0;
 
 
-static void	tl_stats(void);
-static void	non_fatal(char *, char *);
+extern void cache_stats(void);
+extern void a_stats(void);
 
 
 int
 int
 tl_Getchar(void)
 tl_Getchar(void)
@@ -48,6 +50,15 @@ tl_UnGetchar(void)
 	if (cnt > 0) cnt--;
 	if (cnt > 0) cnt--;
 }
 }
 
 
+static void
+tl_stats(void)
+{	extern int Stack_mx;
+	printf("total memory used: %9ld\n", All_Mem);
+	printf("largest stack sze: %9d\n", Stack_mx);
+	cache_stats();
+	a_stats();
+}
+
 int
 int
 tl_main(int argc, char *argv[])
 tl_main(int argc, char *argv[])
 {	int i;
 {	int i;
@@ -67,7 +78,7 @@ tl_main(int argc, char *argv[])
 						argv[1][i] = ' ';
 						argv[1][i] = ' ';
 				}
 				}
 				strcpy(uform, argv[1]);
 				strcpy(uform, argv[1]);
-				hasuform = strlen(uform);
+				hasuform = (int) strlen(uform);
 				break;
 				break;
 		case 'v':	tl_verbose++;
 		case 'v':	tl_verbose++;
 				break;
 				break;
@@ -90,15 +101,6 @@ nogood:		printf("usage:\tspin [-v] [-n] -f formula\n");
 	return tl_errs;
 	return tl_errs;
 }
 }
 
 
-static void
-tl_stats(void)
-{	extern int Stack_mx;
-	printf("total memory used: %9ld\n", All_Mem);
-	printf("largest stack sze: %9d\n", Stack_mx);
-	cache_stats();
-	a_stats();
-}
-
 #define Binop(a)		\
 #define Binop(a)		\
 		fprintf(tl_out, "(");	\
 		fprintf(tl_out, "(");	\
 		dump(n->lft);		\
 		dump(n->lft);		\
@@ -174,7 +176,7 @@ tl_explain(int n)
 }
 }
 
 
 static void
 static void
-non_fatal(char *s1, char *s2)
+tl_non_fatal(char *s1, char *s2)
 {	extern int tl_yychar;
 {	extern int tl_yychar;
 	int i;
 	int i;
 
 
@@ -205,7 +207,7 @@ tl_yyerror(char *s1)
 void
 void
 Fatal(char *s1, char *s2)
 Fatal(char *s1, char *s2)
 {
 {
-	non_fatal(s1, s2);
+	tl_non_fatal(s1, s2);
 	/* tl_stats(); */
 	/* tl_stats(); */
 	exit(1);
 	exit(1);
 }
 }

+ 8 - 6
sys/src/cmd/spin/tl_mem.c

@@ -1,14 +1,16 @@
 /***** tl_spin: tl_mem.c *****/
 /***** tl_spin: tl_mem.c *****/
 
 
-/* Copyright (c) 1995-2000 by Lucent Technologies - Bell Laboratories     */
+/* Copyright (c) 1995-2003 by Lucent Technologies, Bell Laboratories.     */
 /* All Rights Reserved.  This software is for educational purposes only.  */
 /* All Rights Reserved.  This software is for educational purposes only.  */
-/* Permission is given to distribute this code provided that this intro-  */
-/* ductory message is not removed and no monies are exchanged.            */
-/* No guarantee is expressed or implied by the distribution of this code. */
-/* Written by Gerard J. Holzmann, Bell Laboratories, U.S.A.               */
+/* No guarantee whatsoever is expressed or implied by the distribution of */
+/* this code.  Permission is given to distribute this code provided that  */
+/* this introductory message is not removed and no monies are exchanged.  */
+/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
+/*             http://spinroot.com/                                       */
+/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
+
 /* Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper, */
 /* Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper, */
 /* presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995.   */
 /* presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995.   */
-/* Send bug-reports and/or questions to: gerard@research.bell-labs.com    */
 
 
 #include "tl.h"
 #include "tl.h"
 
 

+ 24 - 10
sys/src/cmd/spin/tl_parse.c

@@ -1,14 +1,16 @@
 /***** tl_spin: tl_parse.c *****/
 /***** tl_spin: tl_parse.c *****/
 
 
-/* Copyright (c) 1995-2000 by Lucent Technologies - Bell Laboratories     */
+/* Copyright (c) 1995-2003 by Lucent Technologies, Bell Laboratories.     */
 /* All Rights Reserved.  This software is for educational purposes only.  */
 /* All Rights Reserved.  This software is for educational purposes only.  */
-/* Permission is given to distribute this code provided that this intro-  */
-/* ductory message is not removed and no monies are exchanged.            */
-/* No guarantee is expressed or implied by the distribution of this code. */
-/* Written by Gerard J. Holzmann, Bell Laboratories, U.S.A.               */
+/* No guarantee whatsoever is expressed or implied by the distribution of */
+/* this code.  Permission is given to distribute this code provided that  */
+/* this introductory message is not removed and no monies are exchanged.  */
+/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
+/*             http://spinroot.com/                                       */
+/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
+
 /* Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper, */
 /* Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper, */
 /* presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995.   */
 /* presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995.   */
-/* Send bug-reports and/or questions to: gerard@research.bell-labs.com    */
 
 
 #include "tl.h"
 #include "tl.h"
 
 
@@ -48,7 +50,7 @@ tl_factor(void)
 		tl_yychar = tl_yylex();
 		tl_yychar = tl_yylex();
 
 
 		ptr = tl_factor();
 		ptr = tl_factor();
-
+#ifndef NO_OPT
 		if (ptr->ntyp == FALSE
 		if (ptr->ntyp == FALSE
 		||  ptr->ntyp == TRUE)
 		||  ptr->ntyp == TRUE)
 			break;	/* [] false == false */
 			break;	/* [] false == false */
@@ -59,7 +61,7 @@ tl_factor(void)
 
 
 			ptr = ptr->rgt;	/* [] (p V q) = [] q */
 			ptr = ptr->rgt;	/* [] (p V q) = [] q */
 		}
 		}
-
+#endif
 		ptr = tl_nn(V_OPER, False, ptr);
 		ptr = tl_nn(V_OPER, False, ptr);
 		break;
 		break;
 #ifdef NXT
 #ifdef NXT
@@ -75,6 +77,7 @@ tl_factor(void)
 		tl_yychar = tl_yylex();
 		tl_yychar = tl_yylex();
 
 
 		ptr = tl_factor();
 		ptr = tl_factor();
+#ifndef NO_OPT
 		if (ptr->ntyp == TRUE
 		if (ptr->ntyp == TRUE
 		||  ptr->ntyp == FALSE)
 		||  ptr->ntyp == FALSE)
 			break;	/* <> true == true */
 			break;	/* <> true == true */
@@ -88,7 +91,7 @@ tl_factor(void)
 			ptr = ptr->rgt;
 			ptr = ptr->rgt;
 			/* fall thru */
 			/* fall thru */
 		}
 		}
-
+#endif
 		ptr = tl_nn(U_OPER, True, ptr);
 		ptr = tl_nn(U_OPER, True, ptr);
 
 
 		break;
 		break;
@@ -118,6 +121,7 @@ bin_simpler(Node *ptr)
 	if (ptr)
 	if (ptr)
 	switch (ptr->ntyp) {
 	switch (ptr->ntyp) {
 	case U_OPER:
 	case U_OPER:
+#ifndef NO_OPT
 		if (ptr->rgt->ntyp == TRUE
 		if (ptr->rgt->ntyp == TRUE
 		||  ptr->rgt->ntyp == FALSE
 		||  ptr->rgt->ntyp == FALSE
 		||  ptr->lft->ntyp == FALSE)
 		||  ptr->lft->ntyp == FALSE)
@@ -150,9 +154,11 @@ bin_simpler(Node *ptr)
 					ptr->lft->lft,
 					ptr->lft->lft,
 					ptr->rgt->lft), ZN);
 					ptr->rgt->lft), ZN);
 		}
 		}
+#endif
 #endif
 #endif
 		break;
 		break;
 	case V_OPER:
 	case V_OPER:
+#ifndef NO_OPT
 		if (ptr->rgt->ntyp == FALSE
 		if (ptr->rgt->ntyp == FALSE
 		||  ptr->rgt->ntyp == TRUE
 		||  ptr->rgt->ntyp == TRUE
 		||  ptr->lft->ntyp == TRUE)
 		||  ptr->lft->ntyp == TRUE)
@@ -177,20 +183,25 @@ bin_simpler(Node *ptr)
 			ptr->rgt = ptr->rgt->rgt;
 			ptr->rgt = ptr->rgt->rgt;
 			break;
 			break;
 		}
 		}
+#endif
 		break;
 		break;
 	case IMPLIES:
 	case IMPLIES:
+#ifndef NO_OPT
 		if (isequal(ptr->lft, ptr->rgt))
 		if (isequal(ptr->lft, ptr->rgt))
 		{	ptr = True;
 		{	ptr = True;
 			break;
 			break;
 		}
 		}
+#endif
 		ptr = tl_nn(OR, Not(ptr->lft), ptr->rgt);
 		ptr = tl_nn(OR, Not(ptr->lft), ptr->rgt);
 		ptr = rewrite(ptr);
 		ptr = rewrite(ptr);
 		break;
 		break;
 	case EQUIV:
 	case EQUIV:
+#ifndef NO_OPT
 		if (isequal(ptr->lft, ptr->rgt))
 		if (isequal(ptr->lft, ptr->rgt))
 		{	ptr = True;
 		{	ptr = True;
 			break;
 			break;
 		}
 		}
+#endif
 		a = rewrite(tl_nn(AND,
 		a = rewrite(tl_nn(AND,
 			dupnode(ptr->lft),
 			dupnode(ptr->lft),
 			dupnode(ptr->rgt)));
 			dupnode(ptr->rgt)));
@@ -201,6 +212,7 @@ bin_simpler(Node *ptr)
 		ptr = rewrite(ptr);
 		ptr = rewrite(ptr);
 		break;
 		break;
 	case AND:
 	case AND:
+#ifndef NO_OPT
 		/* p && (q U p) = p */
 		/* p && (q U p) = p */
 		if (ptr->rgt->ntyp == U_OPER
 		if (ptr->rgt->ntyp == U_OPER
 		&&  isequal(ptr->rgt->rgt, ptr->lft))
 		&&  isequal(ptr->rgt->rgt, ptr->lft))
@@ -275,9 +287,11 @@ bin_simpler(Node *ptr)
 		{	ptr = ptr->lft;
 		{	ptr = ptr->lft;
 			break;
 			break;
 		}
 		}
+#endif
 		break;
 		break;
 
 
 	case OR:
 	case OR:
+#ifndef NO_OPT
 		/* p || (q U p) == q U p */
 		/* p || (q U p) == q U p */
 		if (ptr->rgt->ntyp == U_OPER
 		if (ptr->rgt->ntyp == U_OPER
 		&&  isequal(ptr->rgt->rgt, ptr->lft))
 		&&  isequal(ptr->rgt->rgt, ptr->lft))
@@ -331,7 +345,7 @@ bin_simpler(Node *ptr)
 		{	ptr = ptr->rgt;
 		{	ptr = ptr->rgt;
 			break;
 			break;
 		}		
 		}		
-
+#endif
 		break;
 		break;
 	}
 	}
 	return ptr;
 	return ptr;

+ 12 - 25
sys/src/cmd/spin/tl_rewrt.c

@@ -1,14 +1,16 @@
 /***** tl_spin: tl_rewrt.c *****/
 /***** tl_spin: tl_rewrt.c *****/
 
 
-/* Copyright (c) 1995-2000 by Lucent Technologies - Bell Laboratories     */
+/* Copyright (c) 1995-2003 by Lucent Technologies, Bell Laboratories.     */
 /* All Rights Reserved.  This software is for educational purposes only.  */
 /* All Rights Reserved.  This software is for educational purposes only.  */
-/* Permission is given to distribute this code provided that this intro-  */
-/* ductory message is not removed and no monies are exchanged.            */
-/* No guarantee is expressed or implied by the distribution of this code. */
-/* Written by Gerard J. Holzmann, Bell Laboratories, U.S.A.               */
+/* No guarantee whatsoever is expressed or implied by the distribution of */
+/* this code.  Permission is given to distribute this code provided that  */
+/* this introductory message is not removed and no monies are exchanged.  */
+/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
+/*             http://spinroot.com/                                       */
+/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
+
 /* Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper, */
 /* Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper, */
 /* presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995.   */
 /* presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995.   */
-/* Send bug-reports and/or questions to: gerard@research.bell-labs.com    */
 
 
 #include "tl.h"
 #include "tl.h"
 
 
@@ -40,7 +42,7 @@ canonical(Node *n)
 {	Node *m;	/* assumes input is right_linked */
 {	Node *m;	/* assumes input is right_linked */
 
 
 	if (!n) return n;
 	if (!n) return n;
-	if (m = in_cache(n))
+	if ((m = in_cache(n)) != ZN)
 		return m;
 		return m;
 
 
 	n->rgt = canonical(n->rgt);
 	n->rgt = canonical(n->rgt);
@@ -127,11 +129,7 @@ addcan(int tok, Node *n)
 		addcan(tok, n->lft);
 		addcan(tok, n->lft);
 		return;
 		return;
 	}
 	}
-#if 0
-	if ((tok == AND && n->ntyp == TRUE)
-	||  (tok == OR  && n->ntyp == FALSE))
-		return;
-#endif
+
 	N = dupnode(n);
 	N = dupnode(n);
 	if (!can)	
 	if (!can)	
 	{	can = N;
 	{	can = N;
@@ -196,7 +194,7 @@ Canonical(Node *n)
 
 
 	can = ZN;
 	can = ZN;
 	addcan(tok, n);
 	addcan(tok, n);
-#if 1
+#if 0
 	Debug("\nA0: "); Dump(can); 
 	Debug("\nA0: "); Dump(can); 
 	Debug("\nA1: "); Dump(n); Debug("\n");
 	Debug("\nA1: "); Dump(n); Debug("\n");
 #endif
 #endif
@@ -233,11 +231,6 @@ Canonical(Node *n)
 			{	marknode(AND, p);
 			{	marknode(AND, p);
 				continue;
 				continue;
 			}
 			}
-			if (k2->ntyp == U_OPER
-			&&  anywhere(AND, k2->rgt, can))
-			{	marknode(AND, p);
-				continue;
-			}	/* q && (p U q) = q */
 	}	}
 	}	}
 	if (tok == OR)
 	if (tok == OR)
 	{	for (m = can; m; m = (m->ntyp == OR) ? m->rgt : ZN)
 	{	for (m = can; m; m = (m->ntyp == OR) ? m->rgt : ZN)
@@ -269,12 +262,6 @@ Canonical(Node *n)
 			{	marknode(OR, p);
 			{	marknode(OR, p);
 				continue;
 				continue;
 			}
 			}
-			if (k2->ntyp == V_OPER
-			&&  k2->lft->ntyp == FALSE
-			&&  anywhere(AND, k2->rgt, can))
-			{	marknode(OR, p);
-				continue;
-			}	/* p || (F V p) = p */
 	}	}
 	}	}
 	for (m = can, prev = ZN; m; )	/* remove marked nodes */
 	for (m = can, prev = ZN; m; )	/* remove marked nodes */
 	{	if (m->ntyp == -1)
 	{	if (m->ntyp == -1)
@@ -301,7 +288,7 @@ Canonical(Node *n)
 		m = m->rgt;
 		m = m->rgt;
 	}
 	}
 out:
 out:
-#if 1
+#if 0
 	Debug("A2: "); Dump(can); Debug("\n");
 	Debug("A2: "); Dump(can); Debug("\n");
 #endif
 #endif
 	if (!can)
 	if (!can)

+ 28 - 37
sys/src/cmd/spin/tl_trans.c

@@ -1,14 +1,16 @@
 /***** tl_spin: tl_trans.c *****/
 /***** tl_spin: tl_trans.c *****/
 
 
-/* Copyright (c) 1995-2000 by Lucent Technologies - Bell Laboratories     */
+/* Copyright (c) 1995-2003 by Lucent Technologies, Bell Laboratories.     */
 /* All Rights Reserved.  This software is for educational purposes only.  */
 /* All Rights Reserved.  This software is for educational purposes only.  */
-/* Permission is given to distribute this code provided that this intro-  */
-/* ductory message is not removed and no monies are exchanged.            */
-/* No guarantee is expressed or implied by the distribution of this code. */
-/* Written by Gerard J. Holzmann, Bell Laboratories, U.S.A.               */
+/* No guarantee whatsoever is expressed or implied by the distribution of */
+/* this code.  Permission is given to distribute this code provided that  */
+/* this introductory message is not removed and no monies are exchanged.  */
+/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
+/*             http://spinroot.com/                                       */
+/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
+
 /* Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper, */
 /* Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper, */
 /* presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995.   */
 /* presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995.   */
-/* Send bug-reports and/or questions to: gerard@research.bell-labs.com    */
 
 
 #include "tl.h"
 #include "tl.h"
 
 
@@ -40,7 +42,7 @@ static int	set_prefix(char *, int, Graph *);
 static void	Addout(char *, char *);
 static void	Addout(char *, char *);
 static void	fsm_trans(Graph *, int, char *);
 static void	fsm_trans(Graph *, int, char *);
 static void	mkbuchi(void);
 static void	mkbuchi(void);
-static void	expand(Graph *);
+static void	expand_g(Graph *);
 static void	fixinit(Node *);
 static void	fixinit(Node *);
 static void	liveness(Node *);
 static void	liveness(Node *);
 static void	mk_grn(Node *);
 static void	mk_grn(Node *);
@@ -131,6 +133,7 @@ mk_grn(Node *n)
 {	Graph *p;
 {	Graph *p;
 
 
 	n = right_linked(n);
 	n = right_linked(n);
+more:
 	for (p = Nodes_Set; p; p = p->nxt)
 	for (p = Nodes_Set; p; p = p->nxt)
 		if (p->outgoing
 		if (p->outgoing
 		&&  has_clause(AND, p, n))
 		&&  has_clause(AND, p, n))
@@ -138,6 +141,11 @@ mk_grn(Node *n)
 				(unsigned char) Red_cnt;
 				(unsigned char) Red_cnt;
 			Lab_cnt++;
 			Lab_cnt++;
 		}
 		}
+
+	if (n->ntyp == U_OPER)	/* 3.4.0 */
+	{	n = n->rgt;
+		goto more;
+	}
 }
 }
 
 
 static void
 static void
@@ -347,6 +355,14 @@ fsm_trans(Graph *p, int count, char *curnm)
 			sprintf(nwnm, "%s_%s", prefix, s->name);
 			sprintf(nwnm, "%s_%s", prefix, s->name);
 		} else
 		} else
 			strcpy(nwnm, "accept_all");
 			strcpy(nwnm, "accept_all");
+
+		if (tl_verbose)
+		{	printf("maxred=%d, count=%d, curnm=%s, nwnm=%s ",
+				Max_Red, count, curnm, nwnm);
+			printf("(greencnt=%d,%d, redcnt=%d,%d)\n",
+				r->grncnt, r->isgrn[0],
+				r->redcnt, r->isred[0]);
+		}
 		addtrans(p, curnm, r->Old, nwnm);
 		addtrans(p, curnm, r->Old, nwnm);
 	}
 	}
 }
 }
@@ -625,10 +641,9 @@ not_new(Graph *g)
 }
 }
 
 
 static void
 static void
-expand(Graph *g)
+expand_g(Graph *g)
 {	Node *now, *n1, *n2, *nx;
 {	Node *now, *n1, *n2, *nx;
 	int can_release;
 	int can_release;
-	extern void cache_dump(void);
 
 
 	if (!g->New)
 	if (!g->New)
 	{	Debug2("\nDone with %s", g->name->name);
 	{	Debug2("\nDone with %s", g->name->name);
@@ -681,14 +696,7 @@ expand(Graph *g)
 	g->New = g->New->nxt;
 	g->New = g->New->nxt;
 	now->nxt = ZN;
 	now->nxt = ZN;
 
 
-	if (now->ntyp != TRUE
-#if 1
-/* 3.4.0 */
-		)
-#else
-/* 3.3.9 */
-	&&  now->ntyp != FALSE)
-#endif
+	if (now->ntyp != TRUE)
 	{	if (g->Old)
 	{	if (g->Old)
 		{	for (n1 = g->Old; n1->nxt; n1 = n1->nxt)
 		{	for (n1 = g->Old; n1->nxt; n1 = n1->nxt)
 				if (isequal(now, n1))
 				if (isequal(now, n1))
@@ -702,24 +710,7 @@ expand(Graph *g)
 out:
 out:
 	switch (now->ntyp) {
 	switch (now->ntyp) {
 	case FALSE:
 	case FALSE:
-#if 1
-/* 3.4.0 */
-push_stack(g);
-#else
-		releasenode(1, now);
-		for (n1 = g->Old; n1; n1 = n2)
-		{	n2 = n1->nxt;
-			releasenode(1, n1);
-		}
-		for (n1 = g->New; n1; n1 = n2)
-		{	n2 = n1->nxt;
-			releasenode(1, n1);
-		}
-		for (n1 = g->Next; n1; n1 = n2)
-		{	n2 = n1->nxt;
-			releasenode(1, n1);
-		}
-#endif
+		push_stack(g);
 		break;
 		break;
 	case TRUE:
 	case TRUE:
 		releasenode(1, now);
 		releasenode(1, now);
@@ -863,9 +854,9 @@ trans(Node *p)
 	op = dupnode(p);
 	op = dupnode(p);
 
 
 	ng(ZS, getsym(tl_lookup("init")), p, ZN, ZN);
 	ng(ZS, getsym(tl_lookup("init")), p, ZN, ZN);
-	while (g = Nodes_Stack)
+	while ((g = Nodes_Stack) != (Graph *) 0)
 	{	Nodes_Stack = g->nxt;
 	{	Nodes_Stack = g->nxt;
-		expand(g);
+		expand_g(g);
 	}
 	}
 	if (newstates)
 	if (newstates)
 		return;
 		return;

+ 27 - 28
sys/src/cmd/spin/vars.c

@@ -1,14 +1,13 @@
 /***** spin: vars.c *****/
 /***** spin: vars.c *****/
 
 
-/* Copyright (c) 1991-2000 by Lucent Technologies - Bell Laboratories     */
+/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories.     */
 /* All Rights Reserved.  This software is for educational purposes only.  */
 /* All Rights Reserved.  This software is for educational purposes only.  */
-/* Permission is given to distribute this code provided that this intro-  */
-/* ductory message is not removed and no monies are exchanged.            */
-/* No guarantee is expressed or implied by the distribution of this code. */
-/* Software written by Gerard J. Holzmann as part of the book:            */
-/* `Design and Validation of Computer Protocols,' ISBN 0-13-539925-4,     */
-/* Prentice Hall, Englewood Cliffs, NJ, 07632.                            */
-/* Send bug-reports and/or questions to: gerard@research.bell-labs.com    */
+/* No guarantee whatsoever is expressed or implied by the distribution of */
+/* this code.  Permission is given to distribute this code provided that  */
+/* this introductory message is not removed and no monies are exchanged.  */
+/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
+/*             http://spinroot.com/                                       */
+/* Send all bug-reports and/or questions to: bugs@spinroot.com            */
 
 
 #include "spin.h"
 #include "spin.h"
 #ifdef PC
 #ifdef PC
@@ -23,7 +22,7 @@ extern Symbol	*Fname;
 extern char	Buf[];
 extern char	Buf[];
 extern int	lineno, depth, verbose, xspin, limited_vis;
 extern int	lineno, depth, verbose, xspin, limited_vis;
 extern int	analyze, jumpsteps, nproc, nstop, columns;
 extern int	analyze, jumpsteps, nproc, nstop, columns;
-extern short	no_arrays, Have_claim, Skip_claim;
+extern short	no_arrays, Have_claim;
 extern void	sr_mesg(FILE *, int, int);
 extern void	sr_mesg(FILE *, int, int);
 extern void	sr_buf(int, int);
 extern void	sr_buf(int, int);
 
 
@@ -96,12 +95,9 @@ checkvar(Symbol *s, int n)
 {	int	i, oln = lineno;	/* calls on eval() change it */
 {	int	i, oln = lineno;	/* calls on eval() change it */
 	Symbol	*ofnm = Fname;
 	Symbol	*ofnm = Fname;
 
 
-	if (n >= s->nel || n < 0)
-	{	printf("spin: indexing %s[%d] - size is %d\n",
-			s->name, n, s->nel);
-		non_fatal("indexing array \'%s\'", s->name);
+	if (!in_bound(s, n))
 		return 0;
 		return 0;
-	}
+
 	if (s->type == 0)
 	if (s->type == 0)
 	{	non_fatal("undecl var %s (assuming int)", s->name);
 	{	non_fatal("undecl var %s (assuming int)", s->name);
 		s->type = INT;
 		s->type = INT;
@@ -139,19 +135,20 @@ getglobal(Lextok *sn)
 
 
 int
 int
 cast_val(int t, int v, int w)
 cast_val(int t, int v, int w)
-{	int i=0; short s=0; unsigned char u=0;
+{	int i=0; short s=0; unsigned int u=0;
 
 
-	if (t == INT || t == CHAN) i = v;
+	if (t == PREDEF || t == INT || t == CHAN) i = v;	/* predef means _ */
 	else if (t == SHORT) s = (short) v;
 	else if (t == SHORT) s = (short) v;
 	else if (t == BYTE || t == MTYPE)  u = (unsigned char)v;
 	else if (t == BYTE || t == MTYPE)  u = (unsigned char)v;
 	else if (t == BIT)   u = (unsigned char)(v&1);
 	else if (t == BIT)   u = (unsigned char)(v&1);
 	else if (t == UNSIGNED)
 	else if (t == UNSIGNED)
 	{	if (w == 0)
 	{	if (w == 0)
 			fatal("cannot happen, cast_val", (char *)0);
 			fatal("cannot happen, cast_val", (char *)0);
-		u = (unsigned char)(v& ((1<<w)-1));
+	/*	u = (unsigned)(v& ((1<<w)-1));		problem when w=32	*/
+		u = (unsigned)(v& (~0u>>(8*sizeof(unsigned)-w)));	/* doug */
 	}
 	}
 
 
-	if (v != i+s+u)
+	if (v != i+s+ (int) u)
 	{	char buf[32]; sprintf(buf, "%d->%d (%d)", v, i+s+u, t);
 	{	char buf[32]; sprintf(buf, "%d->%d (%d)", v, i+s+u, t);
 		non_fatal("value (%s) truncated in assignment", buf);
 		non_fatal("value (%s) truncated in assignment", buf);
 	}
 	}
@@ -166,9 +163,7 @@ setglobal(Lextok *v, int m)
 	else
 	else
 	{	int n = eval(v->lft);
 	{	int n = eval(v->lft);
 		if (checkvar(v->sym, n))
 		if (checkvar(v->sym, n))
-		{	if (v->sym->nbits > 0)
-				m = (m & ((1<<v->sym->nbits)-1));	
-			v->sym->val[n] = m;
+		{	v->sym->val[n] = cast_val(v->sym->type, m, v->sym->nbits);
 			v->sym->setat = depth;
 			v->sym->setat = depth;
 	}	}
 	}	}
 	return 1;
 	return 1;
@@ -208,14 +203,18 @@ dumpclaims(FILE *fd, int pid, char *s)
 void
 void
 dumpglobals(void)
 dumpglobals(void)
 {	Ordered *walk;
 {	Ordered *walk;
-	Lextok *dummy;
+	static Lextok *dummy = ZN;
 	Symbol *sp;
 	Symbol *sp;
 	int j;
 	int j;
 
 
+	if (!dummy)
+		dummy = nn(ZN, NAME, nn(ZN,CONST,ZN,ZN), ZN);
+
 	for (walk = all_names; walk; walk = walk->next)
 	for (walk = all_names; walk; walk = walk->next)
 	{	sp = walk->entry;
 	{	sp = walk->entry;
 		if (!sp->type || sp->context || sp->owner
 		if (!sp->type || sp->context || sp->owner
-		||  sp->type == PROCTYPE || sp->type == PREDEF
+		||  sp->type == PROCTYPE  || sp->type == PREDEF
+		||  sp->type == CODE_FRAG || sp->type == CODE_DECL
 		||  (sp->type == MTYPE && ismtype(sp->name)))
 		||  (sp->type == MTYPE && ismtype(sp->name)))
 			continue;
 			continue;
 
 
@@ -233,7 +232,6 @@ dumpglobals(void)
 			&&  (sp->setat < depth
 			&&  (sp->setat < depth
 			&&   jumpsteps != depth))
 			&&   jumpsteps != depth))
 				continue;
 				continue;
-			dummy = nn(ZN, NAME, nn(ZN,CONST,ZN,ZN), ZN);
 			dummy->sym = sp;
 			dummy->sym = sp;
 			dummy->lft->val = j;
 			dummy->lft->val = j;
 			/* in case of cast_val warnings, do this first: */
 			/* in case of cast_val warnings, do this first: */
@@ -279,10 +277,13 @@ dumpglobals(void)
 
 
 void
 void
 dumplocal(RunList *r)
 dumplocal(RunList *r)
-{	Lextok *dummy;
+{	static Lextok *dummy = ZN;
 	Symbol *z, *s = r->symtab;
 	Symbol *z, *s = r->symtab;
 	int i;
 	int i;
 
 
+	if (!dummy)
+		dummy = nn(ZN, NAME, nn(ZN,CONST,ZN,ZN), ZN);
+
 	for (z = s; z; z = z->next)
 	for (z = s; z; z = z->next)
 	{	if (z->type == STRUCT)
 	{	if (z->type == STRUCT)
 		{	dump_struct(z, z->name, r);
 		{	dump_struct(z, z->name, r);
@@ -298,7 +299,6 @@ dumplocal(RunList *r)
 			&&   jumpsteps != depth))
 			&&   jumpsteps != depth))
 				continue;
 				continue;
 
 
-			dummy = nn(ZN, NAME, nn(ZN,CONST,ZN,ZN), ZN);
 			dummy->sym = z;
 			dummy->sym = z;
 			dummy->lft->val = i;
 			dummy->lft->val = i;
 
 
@@ -306,8 +306,7 @@ dumplocal(RunList *r)
 				r->n->name, r->pid, z->name);
 				r->n->name, r->pid, z->name);
 			if (z->nel > 1) printf("[%d]", i);
 			if (z->nel > 1) printf("[%d]", i);
 			printf(" = ");
 			printf(" = ");
-			sr_mesg(stdout, getval(dummy),
-				z->type == MTYPE);
+			sr_mesg(stdout, getval(dummy), z->type == MTYPE);
 			printf("\n");
 			printf("\n");
 			if (limited_vis && (z->hidden&2))
 			if (limited_vis && (z->hidden&2))
 			{	int colpos;
 			{	int colpos;

+ 1 - 1
sys/src/cmd/spin/version.h

@@ -1 +1 @@
-#define Version	"Spin Version 3.4.0 -- 27 March 2000"
+#define Version	"Spin Version 4.2.5 -- 2 April 2005"

+ 15 - 1
sys/src/cmd/tar.c

@@ -804,6 +804,20 @@ mkpdirs(char *s)
 	}
 	}
 }
 }
 
 
+/* Call access but preserve the error string. */
+static int
+xaccess(char *name, int mode)
+{
+	char err[ERRMAX];
+	int rv;
+
+	err[0] = 0;
+	errstr(err, sizeof err);
+	rv = access(name, mode);
+	errstr(err, sizeof err);
+	return rv;
+}
+
 /* copy a file from the archive into the filesystem */
 /* copy a file from the archive into the filesystem */
 /* fname is result of name(), so has two extra bytes at beginning */
 /* fname is result of name(), so has two extra bytes at beginning */
 static void
 static void
@@ -858,7 +872,7 @@ extract1(int ar, Hdr *hp, char *fname)
 					fd = create(fname, rw, mode);
 					fd = create(fname, rw, mode);
 				}
 				}
 				if (fd < 0 &&
 				if (fd < 0 &&
-				    (!dir || access(fname, AEXIST) < 0))
+				    (!dir || xaccess(fname, AEXIST) < 0))
 					fprint(2, "%s: can't create %s: %r\n",
 					fprint(2, "%s: can't create %s: %r\n",
 						argv0, fname);
 						argv0, fname);
 			}
 			}

+ 3 - 2
sys/src/cmd/tcs/utf.c

@@ -39,15 +39,16 @@ utf_in(int fd, long *notused, struct convert *out)
 		tot += n;
 		tot += n;
 		for(i=j=0; i<tot; ){
 		for(i=j=0; i<tot; ){
 			c = our_mbtowc(&l, buf+i, tot-i);
 			c = our_mbtowc(&l, buf+i, tot-i);
-			if(c == -1)
+			if(c == -2)
 				break;
 				break;
-			if(c == -2){
+			if(c == -1){
 				if(squawk)
 				if(squawk)
 					EPR "%s: bad UTF sequence near byte %ld in input\n", argv0, ninput+i);
 					EPR "%s: bad UTF sequence near byte %ld in input\n", argv0, ninput+i);
 				if(clean)
 				if(clean)
 					continue;
 					continue;
 				nerrors++;
 				nerrors++;
 				l = Runeerror;
 				l = Runeerror;
+				c = 1;
 			}
 			}
 			runes[j++] = l;
 			runes[j++] = l;
 			i += c;
 			i += c;

+ 2 - 2
sys/src/cmd/unix/spin/readme

@@ -1,4 +1,4 @@
 the latest version of sources, documentation, newsletters,
 the latest version of sources, documentation, newsletters,
 workshop announcements, etc., for the Spin system can always
 workshop announcements, etc., for the Spin system can always
-be found online at: http://netlib.bell-labs.com/netlib/spin/whatispin.html
-online references live at: http://cm.bell-labs.com/cm/cs/what/spin/Man.html
+be found online at: http://spinroot.com/spin/whatispin.html
+online references live at: http://spinroot.com/spin/Man/index.html

BIN
sys/src/cmd/unix/spin/spin334.tar.gz


BIN
sys/src/cmd/unix/spin/spin425.tar.gz


+ 150 - 162
sys/src/games/memo.c

@@ -4,6 +4,8 @@
 #include <draw.h>
 #include <draw.h>
 #include <event.h>
 #include <event.h>
 
 
+void memoinit(void);
+void redraw(void);
 void eresized(int);
 void eresized(int);
 void resize(int i);
 void resize(int i);
 void afaces(void);
 void afaces(void);
@@ -11,22 +13,25 @@ void allocblocks(void);
 Image *openface(char *path);
 Image *openface(char *path);
 
 
 Image *face[18];
 Image *face[18];
-Rectangle brect[36];
 char buf[100];
 char buf[100];
 ushort winflag, level;
 ushort winflag, level;
+Image *back;
+Image *fore;
 
 
-typedef enum{
-	ninit,
-	hide,
-	disc
-}bflag;
+enum
+{
+	Eninit,
+	Eshow,
+	Ehide,
+	Edisc,
+};
 
 
-struct Block
+struct
 {
 {
-	ushort nr;
-	ushort nc;
-	bflag flag;
-} block[36];
+	Image *face;
+	Rectangle r;
+	int	flag;
+}block[36];
 
 
 char *buttons[] =
 char *buttons[] =
 {
 {
@@ -47,11 +52,13 @@ main(int argc, char *argv[])
 {
 {
 	Mouse m;
 	Mouse m;
 	int i, j;
 	int i, j;
-	ushort ran, score, attempt, prev, br[2], c[2];
+	ushort ran, score, attempt, prev, br[2];
+	Image *c[2];
 	char *fmt;
 	char *fmt;
 
 
-	level=16;
-	fmt = "you win in %d attempts!";
+	level = 16;
+	fmt = "win in %d attempts!";
+
 	ARGBEGIN{
 	ARGBEGIN{
 	default:
 	default:
 		goto Usage;
 		goto Usage;
@@ -59,14 +66,16 @@ main(int argc, char *argv[])
 		level=36;
 		level=36;
 		break;
 		break;
 	}ARGEND
 	}ARGEND
+
 	if(argc){
 	if(argc){
-	Usage:
+    Usage:
 		fprint(2, "usage: %s [-h]\n", argv0);
 		fprint(2, "usage: %s [-h]\n", argv0);
 		exits("usage");
 		exits("usage");
 	}
 	}
 	if(initdraw(0,0,"memo") < 0)
 	if(initdraw(0,0,"memo") < 0)
 		sysfatal("initdraw failed: %r");
 		sysfatal("initdraw failed: %r");
 	srand(time(0));
 	srand(time(0));
+	memoinit();
 	einit(Emouse);
 	einit(Emouse);
 
 
     Start:
     Start:
@@ -74,46 +83,41 @@ main(int argc, char *argv[])
 	winflag=0;
 	winflag=0;
 	prev=level+1;
 	prev=level+1;
 	score=attempt=0;
 	score=attempt=0;
-	for(i=0;i!=level;i++){
-		block[i].nr=i;
-		block[i].nc=20;
-		block[i].flag=ninit;
-	}
+	for(i=0;i!=level;i++)
+		block[i].flag = Eninit;
+
 	for(i=0;i!=level/2;i++){
 	for(i=0;i!=level/2;i++){
 		for(j=0;j!=2;){
 		for(j=0;j!=2;){
-			ran=rand()%level;
-			if(block[ran].nc==20){
-				block[ran].nc=i;
+			ran = rand()%level;
+			if(block[ran].flag == Eninit){
+				block[ran].face = face[i];
+				block[ran].flag = Eshow;
 				j++;
 				j++;
 			}
 			}
 		}
 		}
 	}
 	}
 	eresized(0);
 	eresized(0);
-	for(;;){
-		m=emouse();
+	for(;;m=emouse())
 		if(m.buttons)
 		if(m.buttons)
 			break;
 			break;
-	}
+
 	for(i=0;i!=level;i++)
 	for(i=0;i!=level;i++)
-		block[i].flag=hide;
-	eresized(0);
-	j=0;
+		block[i].flag = Ehide;
+
+	redraw();
+	j = 0;
 	for(;; m=emouse()){
 	for(;; m=emouse()){
 		switch(m.buttons){
 		switch(m.buttons){
 		case 1:
 		case 1:
 			while(m.buttons){
 			while(m.buttons){
 				for(i=0;i!=level;i++){
 				for(i=0;i!=level;i++){
-					if(i!=prev && ptinrect(m.xy,brect[i])){
-						if(block[i].flag == hide  && j<2){
-							draw(	screen,
-								brect[i],
-								face[block[i].nc],
-								nil,
-								ZP);
-							c[j]=block[i].nc;
-							br[j]=i;
+					if(i!=prev && ptinrect(m.xy,block[i].r)){
+						if(block[i].flag==Ehide  && j<2){
+							block[i].flag = Eshow;
+							draw(screen, block[i].r, block[i].face, nil, ZP);
+							c[j] = block[i].face;
+							br[j] = prev = i;
 							j++;
 							j++;
-							prev=i;
 						}
 						}
 						break;
 						break;
 					}
 					}
@@ -123,120 +127,102 @@ main(int argc, char *argv[])
 			break;
 			break;
 		case 4:
 		case 4:
 			switch(emenuhit(3, &m, &menu)) {
 			switch(emenuhit(3, &m, &menu)) {
-				case 0:	/* restart */
-					goto Start;
-					break;
-				case 1:
-					level=16;
-					goto Start;
-					break;
-				case 2:
-					level=36;
-					goto Start;
-					break;
-				case 3:
-					exits(0);
-					break;
+			case 0:	/* restart */
+				goto Start;
+				break;
+			case 1:
+				level=16;
+				goto Start;
+				break;
+			case 2:
+				level=36;
+				goto Start;
+				break;
+			case 3:
+				exits(0);
+				break;
 			}
 			}
 		}
 		}
 		if(j==2){
 		if(j==2){
 			attempt++;
 			attempt++;
-			prev=level+1;
-			j=0;
-			if(c[0]==c[1]){
+			prev = level+1;
+			j = 0;
+			if(c[0] == c[1]){
 				score++;
 				score++;
-				block[br[0]].flag=disc;
-				block[br[1]].flag=disc;
-				draw(	screen,
-					brect[br[0]],
-					allocimagemix(display,DPalebluegreen,DWhite),
-					nil,
-					ZP);
-				draw(	screen,
-					brect[br[1]],
-					allocimagemix(display,DPalebluegreen,DWhite),
-					nil,
-					ZP);
-			}else{
-				draw(	screen,
-					brect[br[0]],
-					allocimagemix(display, 0x00DDDDFF, 0x00DDDDFF),
-					nil,
-					ZP);
-				draw(	screen,
-					brect[br[1]],
-					allocimagemix(display, 0x00DDDDFF, 0x00DDDDFF),
-					nil,
-					ZP);
+				block[br[0]].flag = Edisc;
+				block[br[1]].flag = Edisc;
+			} else{
+				block[br[0]].flag = Ehide;
+				block[br[1]].flag = Ehide;
 			}
 			}
+			redraw();
+			continue;
 		}
 		}
-		if(score==level/2){
-			winflag=1;
+		if(score == level/2){
+			winflag = 1;
 			sprint(buf, fmt, attempt);
 			sprint(buf, fmt, attempt);
-			eresized(0);
-			for(;;){
-				m=emouse();
-				if((m.buttons & 1) || (m.buttons & 4))
-				break;
-			}
+			redraw();
+			for(;;m=emouse())
+				if(m.buttons&1 || m.buttons&4)
+					break;
 			goto Start;
 			goto Start;
 		}
 		}
 	}
 	}
 }
 }
 
 
 void
 void
-eresized(int new)
+memoinit(void)
 {
 {
-	ushort i, nx, ny;
-	Point p;
-	Rectangle wr;
+	back = allocimagemix(display, DPalebluegreen,DWhite);
+	fore = allocimagemix(display, 0x00DDDDFF, 0x00DDDDFF);
+}
 
 
+void
+eresized(int new)
+{
 	if(new && getwindow(display, Refnone) < 0){
 	if(new && getwindow(display, Refnone) < 0){
 		fprint(2, "can't reattach to window");
 		fprint(2, "can't reattach to window");
 		exits("resized");
 		exits("resized");
 	}
 	}
-
 	allocblocks();
 	allocblocks();
-	draw(screen, screen->r, allocimagemix(display, DPalebluegreen,DWhite), nil, ZP);
+	draw(screen, screen->r, back, nil, ZP);
+	redraw();
+}
+
+void
+redraw(void)
+{
+	int i, nx, ny;
+	Rectangle r;
+	Point p;
+
 	if(winflag == 1){
 	if(winflag == 1){
-		nx=screen->r.max.x/8;
-		ny=screen->r.max.y/4;
-		wr=Rect(screen->r.min.x+nx,
-			screen->r.min.y+ny,
-			screen->r.max.x-nx,
-			screen->r.max.y-ny);
-		draw(screen, wr, allocimagemix(display, 0x00DDDDFF, 0x00DDDDFF), nil, ZP);
-		p=addpt(wr.min, Pt(5,5));
-		draw(screen,
-		     Rpt(p, addpt(p, stringsize(font,buf))),
-		     allocimagemix(display,0x00DDDDFF,0x00DDDDFFF),
-		     nil,p);
+		p = Pt(Dx(screen->r)/8, Dy(screen->r)/4);
+		r = screen->r;
+		r.min = addpt(r.min, p);
+		r.max = subpt(r.max, p);
+		draw(screen, r, fore, nil, ZP);
+		p=addpt(r.min, Pt(5,5));
 		string(screen,p,display->black,ZP,font,buf);
 		string(screen,p,display->black,ZP,font,buf);
-	}else{
-		for(i=0;i!=level;i++){
-			switch(block[i].flag){
-			case ninit:
-				draw(screen,brect[i],face[block[i].nc],nil,ZP);
-				break;
-			case disc:
-				draw(	screen,
-					brect[i],
-					allocimagemix(display,DPalebluegreen,DWhite),
-					nil,
-					ZP);
-				break;
-			case hide:
-				draw(	screen,
-					brect[i],
-					allocimagemix(display, 0x00DDDDFF, 0x00DDDDFF),
-					nil,
-				    	ZP);
-				break;
-			default:
-				fprint(2, "something went wrong!");
-				exits("wrong");
-				break;
-			}
+		return;
+	}
+
+	for(i=0;i!=level;i++){
+		r = block[i].r;
+		switch(block[i].flag){
+		case Eshow:
+			draw(screen, r,block[i].face,nil,ZP);
+			break;
+		case Edisc:
+			draw(screen, r, back, nil, ZP);
+			break;
+		case Ehide:
+			draw(screen, r, fore, nil, ZP);
+			break;
+		default:
+			fprint(2, "something went wrong!");
+			exits("wrong");
+			break;
 		}
 		}
 	}
 	}
 }
 }
@@ -245,7 +231,7 @@ char *facepaths[] = {
 	/* logos */
 	/* logos */
 	"/lib/face/48x48x4/g/glenda.1",
 	"/lib/face/48x48x4/g/glenda.1",
 	"/lib/face/48x48x2/p/pjw+9ball.2",
 	"/lib/face/48x48x2/p/pjw+9ball.2",
-	
+
 	/* /sys/doc/9.ms authors */
 	/* /sys/doc/9.ms authors */
 	"/lib/face/48x48x2/k/ken.1",
 	"/lib/face/48x48x2/k/ken.1",
 	"/lib/face/48x48x4/b/bobf.1",
 	"/lib/face/48x48x4/b/bobf.1",
@@ -253,7 +239,7 @@ char *facepaths[] = {
 	"/lib/face/48x48x4/p/presotto.1",
 	"/lib/face/48x48x4/p/presotto.1",
 	"/lib/face/48x48x4/r/rob.1",
 	"/lib/face/48x48x4/r/rob.1",
 	"/lib/face/48x48x4/s/sean.1",
 	"/lib/face/48x48x4/s/sean.1",
-	
+
 	/* additional authors and luminaries for harder levels */
 	/* additional authors and luminaries for harder levels */
 	"/lib/face/48x48x4/b/bwk.1",
 	"/lib/face/48x48x4/b/bwk.1",
 	"/lib/face/48x48x4/c/cyoung.1",
 	"/lib/face/48x48x4/c/cyoung.1",
@@ -271,40 +257,17 @@ void
 afaces(void)
 afaces(void)
 {
 {
 	int i;
 	int i;
-	
+
 	for(i=0; i<18; i++)
 	for(i=0; i<18; i++)
 		face[i] = openface(facepaths[i]);
 		face[i] = openface(facepaths[i]);
 }
 }
 
 
-void
-allocblocks(void)
-{
-	Rectangle r, b;
-	ushort i, x, y, sq;
-
-	sq=sqrt(level);
-	resize(48*sq+sq*4+17);
-	r=insetrect(screen->r, 5);
-	r=Rect(r.min.x, r.min.y, r.min.x+48*sq+sq*4-1, r.min.y+48*sq+sq*4-1);
-	b.max.y=r.min.y;
-	for(i=level-1, y=0; y!=sq; y++){
-		b.min.y=b.max.y;
-		b.max.y=r.min.y+(r.max.y-r.min.y)*(y+1)/sq;
-		b.max.x=r.min.x;
-		for(x=0; x!=sq; x++, i--){
-			b.min.x=b.max.x;
-			b.max.x=r.min.x+(r.max.x-r.min.x)*(x+1)/sq;
-			brect[i]=insetrect(b, 2 );
-		}
-	}
-}
-
 void
 void
 resize(int i)
 resize(int i)
 {
 {
 	int fd;
 	int fd;
 
 
-	fd=open("/dev/wctl", OWRITE);
+	fd = open("/dev/wctl", OWRITE);
 	if(fd >= 0){
 	if(fd >= 0){
 		fprint(fd, "resize -dx %d -dy %d", i, i);
 		fprint(fd, "resize -dx %d -dy %d", i, i);
 		close(fd);
 		close(fd);
@@ -317,17 +280,42 @@ openimage(char *path)
 	Image *i;
 	Image *i;
 	int fd;
 	int fd;
 
 
-	fd=open(path, OREAD);
+	fd = open(path, OREAD);
 	if(fd < 0)
 	if(fd < 0)
 		sysfatal("open %s: %r", path);
 		sysfatal("open %s: %r", path);
-	i=readimage(display, fd, 0);
+	i = readimage(display, fd, 0);
 	if(i == nil)
 	if(i == nil)
 		sysfatal("readimage %s: %r", path);
 		sysfatal("readimage %s: %r", path);
 	close(fd);
 	close(fd);
 	return i;
 	return i;
 }
 }
 
 
-enum { Facesize = 48 };
+enum { 
+	Facesize = 48 };
+
+void
+allocblocks(void)
+{
+	Rectangle r, b;
+	ushort i, x, y, sq;
+
+	sq = sqrt(level);
+	resize(Facesize*sq+sq*4+17);
+	r = insetrect(screen->r, 5);
+	r.max.x = r.min.x+Facesize*sq+sq*4-1;
+	r.max.y = r.min.y+Facesize*sq+sq*4-1;
+	b.max.y = r.min.y;
+	for(i=level-1, y=0; y!=sq; y++){
+		b.min.y = b.max.y;
+		b.max.y = r.min.y+Dy(r)*(y+1)/sq;
+		b.max.x = r.min.x;
+		for(x=0; x!=sq; x++, i--){
+			b.min.x = b.max.x;
+			b.max.x = r.min.x+Dx(r)*(x+1)/sq;
+			block[i].r = insetrect(b, 2 );
+		}
+	}
+}
 
 
 Image*
 Image*
 readbit(int fd, ulong chan, char *path)
 readbit(int fd, ulong chan, char *path)
@@ -370,6 +358,7 @@ readbit(int fd, ulong chan, char *path)
 	img = allocimage(display, Rect(0,0,Facesize,Facesize), chan, 0, 0);
 	img = allocimage(display, Rect(0,0,Facesize,Facesize), chan, 0, 0);
 	if(img == nil)
 	if(img == nil)
 		return nil;
 		return nil;
+
 	loadimage(img, img->r, data, ndata);
 	loadimage(img, img->r, data, ndata);
 	return img;
 	return img;
 }
 }
@@ -379,7 +368,7 @@ openface(char *path)
 {
 {
 	char *p;
 	char *p;
 	int fd, n;
 	int fd, n;
-	
+
 	p = strstr(path, "48x48x");
 	p = strstr(path, "48x48x");
 	if(p == nil)
 	if(p == nil)
 		return openimage(path);
 		return openimage(path);
@@ -391,4 +380,3 @@ openface(char *path)
 	}
 	}
 	return openimage(path);
 	return openimage(path);
 }
 }
-

Some files were not shown because too many files changed in this diff