Browse Source

vendor updates - twapi tcllib

master
Julian Noble 3 months ago
parent
commit
131499a07c
  1. 2
      src/vendorlib_tcl8/twapi-5.0b1/LICENSE
  2. 73
      src/vendorlib_tcl8/twapi-5.0b1/README.md
  3. 2
      src/vendorlib_tcl8/twapi-5.0b1/account.tcl
  4. 0
      src/vendorlib_tcl8/twapi-5.0b1/adsi.tcl
  5. 4
      src/vendorlib_tcl8/twapi-5.0b1/apputil.tcl
  6. 11
      src/vendorlib_tcl8/twapi-5.0b1/base.tcl
  7. 0
      src/vendorlib_tcl8/twapi-5.0b1/clipboard.tcl
  8. 2
      src/vendorlib_tcl8/twapi-5.0b1/com.tcl
  9. 0
      src/vendorlib_tcl8/twapi-5.0b1/console.tcl
  10. 3
      src/vendorlib_tcl8/twapi-5.0b1/crypto.tcl
  11. 0
      src/vendorlib_tcl8/twapi-5.0b1/device.tcl
  12. 0
      src/vendorlib_tcl8/twapi-5.0b1/etw.tcl
  13. 0
      src/vendorlib_tcl8/twapi-5.0b1/eventlog.tcl
  14. 0
      src/vendorlib_tcl8/twapi-5.0b1/evt.tcl
  15. 0
      src/vendorlib_tcl8/twapi-5.0b1/handle.tcl
  16. 0
      src/vendorlib_tcl8/twapi-5.0b1/input.tcl
  17. 29
      src/vendorlib_tcl8/twapi-5.0b1/msi.tcl
  18. 0
      src/vendorlib_tcl8/twapi-5.0b1/mstask.tcl
  19. 0
      src/vendorlib_tcl8/twapi-5.0b1/multimedia.tcl
  20. 0
      src/vendorlib_tcl8/twapi-5.0b1/namedpipe.tcl
  21. 0
      src/vendorlib_tcl8/twapi-5.0b1/network.tcl
  22. 0
      src/vendorlib_tcl8/twapi-5.0b1/nls.tcl
  23. 2
      src/vendorlib_tcl8/twapi-5.0b1/os.tcl
  24. 0
      src/vendorlib_tcl8/twapi-5.0b1/pdh.tcl
  25. 100
      src/vendorlib_tcl8/twapi-5.0b1/pkgIndex.tcl
  26. 0
      src/vendorlib_tcl8/twapi-5.0b1/power.tcl
  27. 0
      src/vendorlib_tcl8/twapi-5.0b1/printer.tcl
  28. 2
      src/vendorlib_tcl8/twapi-5.0b1/process.tcl
  29. 0
      src/vendorlib_tcl8/twapi-5.0b1/rds.tcl
  30. 0
      src/vendorlib_tcl8/twapi-5.0b1/registry.tcl
  31. 0
      src/vendorlib_tcl8/twapi-5.0b1/resource.tcl
  32. 11
      src/vendorlib_tcl8/twapi-5.0b1/security.tcl
  33. 2
      src/vendorlib_tcl8/twapi-5.0b1/service.tcl
  34. 0
      src/vendorlib_tcl8/twapi-5.0b1/share.tcl
  35. 2
      src/vendorlib_tcl8/twapi-5.0b1/shell.tcl
  36. 0
      src/vendorlib_tcl8/twapi-5.0b1/sspi.tcl
  37. 0
      src/vendorlib_tcl8/twapi-5.0b1/storage.tcl
  38. 0
      src/vendorlib_tcl8/twapi-5.0b1/synch.tcl
  39. 23
      src/vendorlib_tcl8/twapi-5.0b1/tls.tcl
  40. 11
      src/vendorlib_tcl8/twapi-5.0b1/twapi.tcl
  41. 2
      src/vendorlib_tcl8/twapi-5.0b1/ui.tcl
  42. 0
      src/vendorlib_tcl8/twapi-5.0b1/win.tcl
  43. BIN
      src/vendorlib_tcl8/twapi-5.0b1/win32-ix86/tcl9twapi50b1.dll
  44. BIN
      src/vendorlib_tcl8/twapi-5.0b1/win32-ix86/twapi50b1t.dll
  45. BIN
      src/vendorlib_tcl8/twapi-5.0b1/win32-x86_64/tcl9twapi50b1.dll
  46. BIN
      src/vendorlib_tcl8/twapi-5.0b1/win32-x86_64/twapi50b1t.dll
  47. 0
      src/vendorlib_tcl8/twapi-5.0b1/winlog.tcl
  48. 0
      src/vendorlib_tcl8/twapi-5.0b1/winsta.tcl
  49. 0
      src/vendorlib_tcl8/twapi-5.0b1/wmi.tcl
  50. 64
      src/vendorlib_tcl8/twapi-5.0b1/wts.tcl
  51. 605
      src/vendorlib_tcl8/twapi4.7.2/metoo.tcl
  52. 119
      src/vendorlib_tcl8/twapi4.7.2/pkgIndex.tcl
  53. BIN
      src/vendorlib_tcl8/twapi4.7.2/twapi472.dll
  54. 11
      src/vendorlib_tcl8/twapi4.7.2/twapi_entry.tcl
  55. 8
      src/vendorlib_tcl9/tcllib2.0/0compatibility/pkgIndex.tcl
  56. 625
      src/vendorlib_tcl9/tcllib2.0/aes/aes.tcl
  57. 5
      src/vendorlib_tcl9/tcllib2.0/aes/pkgIndex.tcl
  58. 1960
      src/vendorlib_tcl9/tcllib2.0/amazon-s3/S3.tcl
  59. 9
      src/vendorlib_tcl9/tcllib2.0/amazon-s3/pkgIndex.tcl
  60. 254
      src/vendorlib_tcl9/tcllib2.0/amazon-s3/xsxp.tcl
  61. 1580
      src/vendorlib_tcl9/tcllib2.0/asn/asn.tcl
  62. 4
      src/vendorlib_tcl9/tcllib2.0/asn/pkgIndex.tcl
  63. 180
      src/vendorlib_tcl9/tcllib2.0/base32/base32.tcl
  64. 254
      src/vendorlib_tcl9/tcllib2.0/base32/base32_c.tcl
  65. 73
      src/vendorlib_tcl9/tcllib2.0/base32/base32_tcl.tcl
  66. 134
      src/vendorlib_tcl9/tcllib2.0/base32/base32core.tcl
  67. 182
      src/vendorlib_tcl9/tcllib2.0/base32/base32hex.tcl
  68. 254
      src/vendorlib_tcl9/tcllib2.0/base32/base32hex_c.tcl
  69. 79
      src/vendorlib_tcl9/tcllib2.0/base32/base32hex_tcl.tcl
  70. 4
      src/vendorlib_tcl9/tcllib2.0/base32/pkgIndex.tcl
  71. 270
      src/vendorlib_tcl9/tcllib2.0/base64/ascii85.tcl
  72. 411
      src/vendorlib_tcl9/tcllib2.0/base64/base64.tcl
  73. 19
      src/vendorlib_tcl9/tcllib2.0/base64/base64c.tcl
  74. 5
      src/vendorlib_tcl9/tcllib2.0/base64/pkgIndex.tcl
  75. 337
      src/vendorlib_tcl9/tcllib2.0/base64/uuencode.tcl
  76. 309
      src/vendorlib_tcl9/tcllib2.0/base64/yencode.tcl
  77. 999
      src/vendorlib_tcl9/tcllib2.0/bee/bee.tcl
  78. 4
      src/vendorlib_tcl9/tcllib2.0/bee/pkgIndex.tcl
  79. 556
      src/vendorlib_tcl9/tcllib2.0/bench/bench.tcl
  80. 162
      src/vendorlib_tcl9/tcllib2.0/bench/bench_read.tcl
  81. 101
      src/vendorlib_tcl9/tcllib2.0/bench/bench_wcsv.tcl
  82. 165
      src/vendorlib_tcl9/tcllib2.0/bench/bench_wtext.tcl
  83. 561
      src/vendorlib_tcl9/tcllib2.0/bench/libbench.tcl
  84. 7
      src/vendorlib_tcl9/tcllib2.0/bench/pkgIndex.tcl
  85. 501
      src/vendorlib_tcl9/tcllib2.0/bibtex/bibtex.tcl
  86. 2
      src/vendorlib_tcl9/tcllib2.0/bibtex/pkgIndex.tcl
  87. 755
      src/vendorlib_tcl9/tcllib2.0/blowfish/blowfish.tcl
  88. 5
      src/vendorlib_tcl9/tcllib2.0/blowfish/pkgIndex.tcl
  89. 185
      src/vendorlib_tcl9/tcllib2.0/cache/async.tcl
  90. 3
      src/vendorlib_tcl9/tcllib2.0/cache/pkgIndex.tcl
  91. 2227
      src/vendorlib_tcl9/tcllib2.0/clay/clay.tcl
  92. 3
      src/vendorlib_tcl9/tcllib2.0/clay/pkgIndex.tcl
  93. 280
      src/vendorlib_tcl9/tcllib2.0/clock/iso8601.tcl
  94. 3
      src/vendorlib_tcl9/tcllib2.0/clock/pkgIndex.tcl
  95. 214
      src/vendorlib_tcl9/tcllib2.0/clock/rfc2822.tcl
  96. 933
      src/vendorlib_tcl9/tcllib2.0/cmdline/cmdline.tcl
  97. 2
      src/vendorlib_tcl9/tcllib2.0/cmdline/pkgIndex.tcl
  98. 1806
      src/vendorlib_tcl9/tcllib2.0/comm/comm.tcl
  99. 2
      src/vendorlib_tcl9/tcllib2.0/comm/pkgIndex.tcl
  100. 72
      src/vendorlib_tcl9/tcllib2.0/control/ascaller.tcl
  101. Some files were not shown because too many files have changed in this diff Show More

2
src/vendorlib_tcl8/twapi4.7.2/LICENSE → src/vendorlib_tcl8/twapi-5.0b1/LICENSE

@ -1,4 +1,4 @@
Copyright (c) 2003-2012, Ashok P. Nadkarni Copyright (c) 2003-2024, Ashok P. Nadkarni
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without

73
src/vendorlib_tcl8/twapi-5.0b1/README.md

@ -0,0 +1,73 @@
# Tcl Windows API (TWAPI) extension
The Tcl Windows API (TWAPI) extension provides access to the Windows API from
within the Tcl scripting language.
* Project source repository is at https://github.com/apnadkarni/twapi
* Documentation is at https://twapi.magicsplat.com
* Binary distribution is at https://sourceforge.net/projects/twapi/files/Current%20Releases/Tcl%20Windows%20API/
## Supported platforms
TWAPI 5.0 requires
* Windows 7 SP1 or later
* Tcl 8.6.10+ or Tcl 9.x
### Binary distribution
The single binary distribution supports Tcl 8.6 and Tcl 9 for both 32- and
64-bit platforms.
It requires the VC++ runtime to already be installed
on the system. Download from https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist if necessary.
Windows 7 and 8.x also require the Windows UCRT runtime to be installed if not
present. Download from https://support.microsoft.com/en-gb/topic/update-for-universal-c-runtime-in-windows-c0514201-7fe6-95a3-b0a5-287930f3560c.
In most cases, both the above should already be present on the system.
Note that the *modular* and single file *bin* in 4.x distributions are no longer
available and will not be supported in 5.0.
## TWAPI Summary
The Tcl Windows API (TWAPI) extension provides access to the Windows API from
within the Tcl scripting language.
Functions in the following areas are implemented:
* System functions including OS and CPU information,
shutdown and message formatting
* User and group management
* COM client and server support
* Security and resource access control
* Window management
* User input: generate key/mouse input and hotkeys
* Basic sound playback functions
* Windows services
* Windows event log access
* Windows event tracing
* Process and thread management
* Directory change monitoring
* Lan Manager and file and print shares
* Drive information, file system types etc.
* Network configuration and statistics
* Network connection monitoring and control
* Named pipes
* Clipboard access
* Taskbar icons and notifications
* Console mode functions
* Window stations and desktops
* Internationalization
* Task scheduling
* Shell functions
* Registry
* Windows Management Instrumentation
* Windows Installer
* Synchronization
* Power management
* Device I/O and management
* Crypto API and certificates
* SSL/TLS
* Windows Performance Counters

2
src/vendorlib_tcl8/twapi4.7.2/account.tcl → src/vendorlib_tcl8/twapi-5.0b1/account.tcl

@ -39,7 +39,7 @@ proc twapi::new_user {username args} {
system.arg \ system.arg \
password.arg \ password.arg \
comment.arg \ comment.arg \
[list priv.arg "user" [array names twapi::priv_level_map]] \ [list priv.arg "user" [array names ::twapi::priv_level_map]] \
home_dir.arg \ home_dir.arg \
script_path.arg \ script_path.arg \
] \ ] \

0
src/vendorlib_tcl8/twapi4.7.2/adsi.tcl → src/vendorlib_tcl8/twapi-5.0b1/adsi.tcl

4
src/vendorlib_tcl8/twapi4.7.2/apputil.tcl → src/vendorlib_tcl8/twapi-5.0b1/apputil.tcl

@ -63,9 +63,9 @@ proc twapi::delete_inifile_key {section key args} {
} -maxleftover 0] } -maxleftover 0]
if {[info exists opts(inifile)]} { if {[info exists opts(inifile)]} {
WritePrivateProfileString $section $key $twapi::nullptr $opts(inifile) WritePrivateProfileString $section $key $::twapi::nullptr $opts(inifile)
} else { } else {
WriteProfileString $section $key $twapi::nullptr WriteProfileString $section $key $::twapi::nullptr
} }
} }

11
src/vendorlib_tcl8/twapi4.7.2/base.tcl → src/vendorlib_tcl8/twapi-5.0b1/base.tcl

@ -8,6 +8,7 @@
namespace eval twapi { namespace eval twapi {
# Map of Sid integer type to Sid type name # Map of Sid integer type to Sid type name
variable sid_type_names
array set sid_type_names { array set sid_type_names {
1 user 1 user
2 group 2 group
@ -803,8 +804,9 @@ proc twapi::lookup_account_name {name args} {
lappend result -domain $domain lappend result -domain $domain
} }
if {$opts(all) || $opts(type)} { if {$opts(all) || $opts(type)} {
if {[info exists twapi::sid_type_names($type)]} { variable sid_type_names
lappend result -type $twapi::sid_type_names($type) if {[info exists sid_type_names($type)]} {
lappend result -type $sid_type_names($type)
} else { } else {
# Could be the "logonid" dummy type we added above # Could be the "logonid" dummy type we added above
lappend result -type $type lappend result -type $type
@ -869,8 +871,9 @@ proc twapi::lookup_account_sid {sid args} {
lappend result -domain $domain lappend result -domain $domain
} }
if {$opts(all) || $opts(type)} { if {$opts(all) || $opts(type)} {
if {[info exists twapi::sid_type_names($type)]} { variable sid_type_names
lappend result -type $twapi::sid_type_names($type) if {[info exists sid_type_names($type)]} {
lappend result -type $sid_type_names($type)
} else { } else {
lappend result -type $type lappend result -type $type
} }

0
src/vendorlib_tcl8/twapi4.7.2/clipboard.tcl → src/vendorlib_tcl8/twapi-5.0b1/clipboard.tcl

2
src/vendorlib_tcl8/twapi4.7.2/com.tcl → src/vendorlib_tcl8/twapi-5.0b1/com.tcl

@ -1211,7 +1211,7 @@ proc twapi::_resolve_iid {name_or_iid} {
namespace eval twapi { namespace eval twapi {
# Enable use of TclOO for new Tcl versions. To override setting # Enable use of TclOO for new Tcl versions. To override setting
# applications should define and set before sourcing this file. # applications should define and set before sourcing this file.
variable use_tcloo_for_com variable use_tcloo_for_com 1
if {![info exists use_tcloo_for_com]} { if {![info exists use_tcloo_for_com]} {
set use_tcloo_for_com [package vsatisfies [package require Tcl] 8.6b2] set use_tcloo_for_com [package vsatisfies [package require Tcl] 8.6b2]
} }

0
src/vendorlib_tcl8/twapi4.7.2/console.tcl → src/vendorlib_tcl8/twapi-5.0b1/console.tcl

3
src/vendorlib_tcl8/twapi4.7.2/crypto.tcl → src/vendorlib_tcl8/twapi-5.0b1/crypto.tcl

@ -3304,8 +3304,7 @@ proc twapi::_pem_decode {pem_or_der enc {pemtype 6}} {
if {$enc eq "der"} { if {$enc eq "der"} {
return $pem_or_der return $pem_or_der
} }
if {$enc eq "pem" || if {$enc eq "pem" || [_is_pem $pem_or_der]} {
[regexp -nocase {^\s*-----\s*BEGIN\s+} $pem_or_der]} {
return [CryptStringToBinary $pem_or_der $pemtype] return [CryptStringToBinary $pem_or_der $pemtype]
} }
return $pem_or_der return $pem_or_der

0
src/vendorlib_tcl8/twapi4.7.2/device.tcl → src/vendorlib_tcl8/twapi-5.0b1/device.tcl

0
src/vendorlib_tcl8/twapi4.7.2/etw.tcl → src/vendorlib_tcl8/twapi-5.0b1/etw.tcl

0
src/vendorlib_tcl8/twapi4.7.2/eventlog.tcl → src/vendorlib_tcl8/twapi-5.0b1/eventlog.tcl

0
src/vendorlib_tcl8/twapi4.7.2/evt.tcl → src/vendorlib_tcl8/twapi-5.0b1/evt.tcl

0
src/vendorlib_tcl8/twapi4.7.2/handle.tcl → src/vendorlib_tcl8/twapi-5.0b1/handle.tcl

0
src/vendorlib_tcl8/twapi4.7.2/input.tcl → src/vendorlib_tcl8/twapi-5.0b1/input.tcl

29
src/vendorlib_tcl8/twapi4.7.2/msi.tcl → src/vendorlib_tcl8/twapi-5.0b1/msi.tcl

@ -66,90 +66,119 @@ namespace eval windowsinstaller {
} }
# Enum MsiUILevel # Enum MsiUILevel
variable MsiUILevel
array set MsiUILevel {msiUILevelNoChange 0 msiUILevelDefault 1 msiUILevelNone 2 msiUILevelBasic 3 msiUILevelReduced 4 msiUILevelFull 5 msiUILevelHideCancel 32 msiUILevelProgressOnly 64 msiUILevelEndDialog 128 msiUILevelSourceResOnly 256} array set MsiUILevel {msiUILevelNoChange 0 msiUILevelDefault 1 msiUILevelNone 2 msiUILevelBasic 3 msiUILevelReduced 4 msiUILevelFull 5 msiUILevelHideCancel 32 msiUILevelProgressOnly 64 msiUILevelEndDialog 128 msiUILevelSourceResOnly 256}
# Enum MsiReadStream # Enum MsiReadStream
variable MsiReadStream
array set MsiReadStream {msiReadStreamInteger 0 msiReadStreamBytes 1 msiReadStreamAnsi 2 msiReadStreamDirect 3} array set MsiReadStream {msiReadStreamInteger 0 msiReadStreamBytes 1 msiReadStreamAnsi 2 msiReadStreamDirect 3}
# Enum MsiRunMode # Enum MsiRunMode
variable MsiRunMode
array set MsiRunMode {msiRunModeAdmin 0 msiRunModeAdvertise 1 msiRunModeMaintenance 2 msiRunModeRollbackEnabled 3 msiRunModeLogEnabled 4 msiRunModeOperations 5 msiRunModeRebootAtEnd 6 msiRunModeRebootNow 7 msiRunModeCabinet 8 msiRunModeSourceShortNames 9 msiRunModeTargetShortNames 10 msiRunModeWindows9x 12 msiRunModeZawEnabled 13 msiRunModeScheduled 16 msiRunModeRollback 17 msiRunModeCommit 18} array set MsiRunMode {msiRunModeAdmin 0 msiRunModeAdvertise 1 msiRunModeMaintenance 2 msiRunModeRollbackEnabled 3 msiRunModeLogEnabled 4 msiRunModeOperations 5 msiRunModeRebootAtEnd 6 msiRunModeRebootNow 7 msiRunModeCabinet 8 msiRunModeSourceShortNames 9 msiRunModeTargetShortNames 10 msiRunModeWindows9x 12 msiRunModeZawEnabled 13 msiRunModeScheduled 16 msiRunModeRollback 17 msiRunModeCommit 18}
# Enum MsiDatabaseState # Enum MsiDatabaseState
variable MsiDatabaseState
array set MsiDatabaseState {msiDatabaseStateRead 0 msiDatabaseStateWrite 1} array set MsiDatabaseState {msiDatabaseStateRead 0 msiDatabaseStateWrite 1}
# Enum MsiViewModify # Enum MsiViewModify
variable MsiViewModify
array set MsiViewModify {msiViewModifySeek -1 msiViewModifyRefresh 0 msiViewModifyInsert 1 msiViewModifyUpdate 2 msiViewModifyAssign 3 msiViewModifyReplace 4 msiViewModifyMerge 5 msiViewModifyDelete 6 msiViewModifyInsertTemporary 7 msiViewModifyValidate 8 msiViewModifyValidateNew 9 msiViewModifyValidateField 10 msiViewModifyValidateDelete 11} array set MsiViewModify {msiViewModifySeek -1 msiViewModifyRefresh 0 msiViewModifyInsert 1 msiViewModifyUpdate 2 msiViewModifyAssign 3 msiViewModifyReplace 4 msiViewModifyMerge 5 msiViewModifyDelete 6 msiViewModifyInsertTemporary 7 msiViewModifyValidate 8 msiViewModifyValidateNew 9 msiViewModifyValidateField 10 msiViewModifyValidateDelete 11}
# Enum MsiColumnInfo # Enum MsiColumnInfo
variable MsiColumnInfo
array set MsiColumnInfo {msiColumnInfoNames 0 msiColumnInfoTypes 1} array set MsiColumnInfo {msiColumnInfoNames 0 msiColumnInfoTypes 1}
# Enum MsiTransformError # Enum MsiTransformError
variable MsiTransformError
array set MsiTransformError {msiTransformErrorNone 0 msiTransformErrorAddExistingRow 1 msiTransformErrorDeleteNonExistingRow 2 msiTransformErrorAddExistingTable 4 msiTransformErrorDeleteNonExistingTable 8 msiTransformErrorUpdateNonExistingRow 16 msiTransformErrorChangeCodePage 32 msiTransformErrorViewTransform 256} array set MsiTransformError {msiTransformErrorNone 0 msiTransformErrorAddExistingRow 1 msiTransformErrorDeleteNonExistingRow 2 msiTransformErrorAddExistingTable 4 msiTransformErrorDeleteNonExistingTable 8 msiTransformErrorUpdateNonExistingRow 16 msiTransformErrorChangeCodePage 32 msiTransformErrorViewTransform 256}
# Enum MsiEvaluateCondition # Enum MsiEvaluateCondition
variable MsiEvaluateCondition
array set MsiEvaluateCondition {msiEvaluateConditionFalse 0 msiEvaluateConditionTrue 1 msiEvaluateConditionNone 2 msiEvaluateConditionError 3} array set MsiEvaluateCondition {msiEvaluateConditionFalse 0 msiEvaluateConditionTrue 1 msiEvaluateConditionNone 2 msiEvaluateConditionError 3}
# Enum MsiTransformValidation # Enum MsiTransformValidation
variable MsiTransformValidation
array set MsiTransformValidation {msiTransformValidationNone 0 msiTransformValidationLanguage 1 msiTransformValidationProduct 2 msiTransformValidationPlatform 4 msiTransformValidationMajorVer 8 msiTransformValidationMinorVer 16 msiTransformValidationUpdateVer 32 msiTransformValidationLess 64 msiTransformValidationLessOrEqual 128 msiTransformValidationEqual 256 msiTransformValidationGreaterOrEqual 512 msiTransformValidationGreater 1024 msiTransformValidationUpgradeCode 2048} array set MsiTransformValidation {msiTransformValidationNone 0 msiTransformValidationLanguage 1 msiTransformValidationProduct 2 msiTransformValidationPlatform 4 msiTransformValidationMajorVer 8 msiTransformValidationMinorVer 16 msiTransformValidationUpdateVer 32 msiTransformValidationLess 64 msiTransformValidationLessOrEqual 128 msiTransformValidationEqual 256 msiTransformValidationGreaterOrEqual 512 msiTransformValidationGreater 1024 msiTransformValidationUpgradeCode 2048}
# Enum MsiDoActionStatus # Enum MsiDoActionStatus
variable MsiDoActionStatus
array set MsiDoActionStatus {msiDoActionStatusNoAction 0 msiDoActionStatusSuccess 1 msiDoActionStatusUserExit 2 msiDoActionStatusFailure 3 msiDoActionStatusSuspend 4 msiDoActionStatusFinished 5 msiDoActionStatusWrongState 6 msiDoActionStatusBadActionData 7} array set MsiDoActionStatus {msiDoActionStatusNoAction 0 msiDoActionStatusSuccess 1 msiDoActionStatusUserExit 2 msiDoActionStatusFailure 3 msiDoActionStatusSuspend 4 msiDoActionStatusFinished 5 msiDoActionStatusWrongState 6 msiDoActionStatusBadActionData 7}
# Enum MsiMessageStatus # Enum MsiMessageStatus
variable MsiMessageStatus
array set MsiMessageStatus {msiMessageStatusError -1 msiMessageStatusNone 0 msiMessageStatusOk 1 msiMessageStatusCancel 2 msiMessageStatusAbort 3 msiMessageStatusRetry 4 msiMessageStatusIgnore 5 msiMessageStatusYes 6 msiMessageStatusNo 7} array set MsiMessageStatus {msiMessageStatusError -1 msiMessageStatusNone 0 msiMessageStatusOk 1 msiMessageStatusCancel 2 msiMessageStatusAbort 3 msiMessageStatusRetry 4 msiMessageStatusIgnore 5 msiMessageStatusYes 6 msiMessageStatusNo 7}
# Enum MsiMessageType # Enum MsiMessageType
variable MsiMessageType
array set MsiMessageType {msiMessageTypeFatalExit 0 msiMessageTypeError 16777216 msiMessageTypeWarning 33554432 msiMessageTypeUser 50331648 msiMessageTypeInfo 67108864 msiMessageTypeFilesInUse 83886080 msiMessageTypeResolveSource 100663296 msiMessageTypeOutOfDiskSpace 117440512 msiMessageTypeActionStart 134217728 msiMessageTypeActionData 150994944 msiMessageTypeProgress 167772160 msiMessageTypeCommonData 184549376 msiMessageTypeOk 0 msiMessageTypeOkCancel 1 msiMessageTypeAbortRetryIgnore 2 msiMessageTypeYesNoCancel 3 msiMessageTypeYesNo 4 msiMessageTypeRetryCancel 5 msiMessageTypeDefault1 0 msiMessageTypeDefault2 256 msiMessageTypeDefault3 512} array set MsiMessageType {msiMessageTypeFatalExit 0 msiMessageTypeError 16777216 msiMessageTypeWarning 33554432 msiMessageTypeUser 50331648 msiMessageTypeInfo 67108864 msiMessageTypeFilesInUse 83886080 msiMessageTypeResolveSource 100663296 msiMessageTypeOutOfDiskSpace 117440512 msiMessageTypeActionStart 134217728 msiMessageTypeActionData 150994944 msiMessageTypeProgress 167772160 msiMessageTypeCommonData 184549376 msiMessageTypeOk 0 msiMessageTypeOkCancel 1 msiMessageTypeAbortRetryIgnore 2 msiMessageTypeYesNoCancel 3 msiMessageTypeYesNo 4 msiMessageTypeRetryCancel 5 msiMessageTypeDefault1 0 msiMessageTypeDefault2 256 msiMessageTypeDefault3 512}
# Enum MsiInstallState # Enum MsiInstallState
variable MsiInstallState
array set MsiInstallState {msiInstallStateNotUsed -7 msiInstallStateBadConfig -6 msiInstallStateIncomplete -5 msiInstallStateSourceAbsent -4 msiInstallStateInvalidArg -2 msiInstallStateUnknown -1 msiInstallStateBroken 0 msiInstallStateAdvertised 1 msiInstallStateRemoved 1 msiInstallStateAbsent 2 msiInstallStateLocal 3 msiInstallStateSource 4 msiInstallStateDefault 5} array set MsiInstallState {msiInstallStateNotUsed -7 msiInstallStateBadConfig -6 msiInstallStateIncomplete -5 msiInstallStateSourceAbsent -4 msiInstallStateInvalidArg -2 msiInstallStateUnknown -1 msiInstallStateBroken 0 msiInstallStateAdvertised 1 msiInstallStateRemoved 1 msiInstallStateAbsent 2 msiInstallStateLocal 3 msiInstallStateSource 4 msiInstallStateDefault 5}
# Enum MsiCostTree # Enum MsiCostTree
variable MsiCostTree
array set MsiCostTree {msiCostTreeSelfOnly 0 msiCostTreeChildren 1 msiCostTreeParents 2} array set MsiCostTree {msiCostTreeSelfOnly 0 msiCostTreeChildren 1 msiCostTreeParents 2}
# Enum MsiReinstallMode # Enum MsiReinstallMode
variable MsiReinstallMode
array set MsiReinstallMode {msiReinstallModeFileMissing 2 msiReinstallModeFileOlderVersion 4 msiReinstallModeFileEqualVersion 8 msiReinstallModeFileExact 16 msiReinstallModeFileVerify 32 msiReinstallModeFileReplace 64 msiReinstallModeMachineData 128 msiReinstallModeUserData 256 msiReinstallModeShortcut 512 msiReinstallModePackage 1024} array set MsiReinstallMode {msiReinstallModeFileMissing 2 msiReinstallModeFileOlderVersion 4 msiReinstallModeFileEqualVersion 8 msiReinstallModeFileExact 16 msiReinstallModeFileVerify 32 msiReinstallModeFileReplace 64 msiReinstallModeMachineData 128 msiReinstallModeUserData 256 msiReinstallModeShortcut 512 msiReinstallModePackage 1024}
# Enum MsiInstallType # Enum MsiInstallType
variable MsiInstallType
array set MsiInstallType {msiInstallTypeDefault 0 msiInstallTypeNetworkImage 1 msiInstallTypeSingleInstance 2} array set MsiInstallType {msiInstallTypeDefault 0 msiInstallTypeNetworkImage 1 msiInstallTypeSingleInstance 2}
# Enum MsiInstallMode # Enum MsiInstallMode
variable MsiInstallMode
array set MsiInstallMode {msiInstallModeNoSourceResolution -3 msiInstallModeNoDetection -2 msiInstallModeExisting -1 msiInstallModeDefault 0} array set MsiInstallMode {msiInstallModeNoSourceResolution -3 msiInstallModeNoDetection -2 msiInstallModeExisting -1 msiInstallModeDefault 0}
# Enum MsiSignatureInfo # Enum MsiSignatureInfo
variable MsiSignatureInfo
array set MsiSignatureInfo {msiSignatureInfoCertificate 0 msiSignatureInfoHash 1} array set MsiSignatureInfo {msiSignatureInfoCertificate 0 msiSignatureInfoHash 1}
# Enum MsiInstallContext # Enum MsiInstallContext
variable MsiInstallContext
array set MsiInstallContext {msiInstallContextFirstVisible 0 msiInstallContextUserManaged 1 msiInstallContextUser 2 msiInstallContextMachine 4 msiInstallContextAllUserManaged 8} array set MsiInstallContext {msiInstallContextFirstVisible 0 msiInstallContextUserManaged 1 msiInstallContextUser 2 msiInstallContextMachine 4 msiInstallContextAllUserManaged 8}
# Enum MsiInstallSourceType # Enum MsiInstallSourceType
variable MsiInstallSourceType
array set MsiInstallSourceType {msiInstallSourceTypeUnknown 0 msiInstallSourceTypeNetwork 1 msiInstallSourceTypeURL 2 msiInstallSourceTypeMedia 4} array set MsiInstallSourceType {msiInstallSourceTypeUnknown 0 msiInstallSourceTypeNetwork 1 msiInstallSourceTypeURL 2 msiInstallSourceTypeMedia 4}
# Enum MsiAssemblyType # Enum MsiAssemblyType
variable MsiAssemblyType
array set MsiAssemblyType {msiProvideAssemblyNet 0 msiProvideAssemblyWin32 1} array set MsiAssemblyType {msiProvideAssemblyNet 0 msiProvideAssemblyWin32 1}
# Enum MsiProductScriptInfo # Enum MsiProductScriptInfo
variable MsiProductScriptInfo
array set MsiProductScriptInfo {msiProductScriptInfoProductCode 0 msiProductScriptInfoProductLanguage 1 msiProductScriptInfoProductVersion 2 msiProductScriptInfoProductName 3 msiProductScriptInfoPackageName 4} array set MsiProductScriptInfo {msiProductScriptInfoProductCode 0 msiProductScriptInfoProductLanguage 1 msiProductScriptInfoProductVersion 2 msiProductScriptInfoProductName 3 msiProductScriptInfoPackageName 4}
# Enum MsiAdvertiseProductContext # Enum MsiAdvertiseProductContext
variable MsiAdvertiseProductContext
array set MsiAdvertiseProductContext {msiAdvertiseProductMachine 0 msiAdvertiseProductUser 1} array set MsiAdvertiseProductContext {msiAdvertiseProductMachine 0 msiAdvertiseProductUser 1}
# Enum Constants # Enum Constants
variable Constants
array set Constants {msiDatabaseNullInteger -2147483648} array set Constants {msiDatabaseNullInteger -2147483648}
# Enum MsiOpenDatabaseMode # Enum MsiOpenDatabaseMode
variable MsiOpenDatabaseMode
array set MsiOpenDatabaseMode {msiOpenDatabaseModeReadOnly 0 msiOpenDatabaseModeTransact 1 msiOpenDatabaseModeDirect 2 msiOpenDatabaseModeCreate 3 msiOpenDatabaseModeCreateDirect 4 msiOpenDatabaseModePatchFile 32} array set MsiOpenDatabaseMode {msiOpenDatabaseModeReadOnly 0 msiOpenDatabaseModeTransact 1 msiOpenDatabaseModeDirect 2 msiOpenDatabaseModeCreate 3 msiOpenDatabaseModeCreateDirect 4 msiOpenDatabaseModePatchFile 32}
# Enum MsiSignatureOption # Enum MsiSignatureOption
variable MsiSignatureOption
array set MsiSignatureOption {msiSignatureOptionInvalidHashFatal 1} array set MsiSignatureOption {msiSignatureOptionInvalidHashFatal 1}
# Enum MsiAdvertiseProductPlatform # Enum MsiAdvertiseProductPlatform
variable MsiAdvertiseProductPlatform
array set MsiAdvertiseProductPlatform {msiAdvertiseCurrentPlatform 0 msiAdvertiseX86Platform 1 msiAdvertiseIA64Platform 2 msiAdvertiseX64Platform 4} array set MsiAdvertiseProductPlatform {msiAdvertiseCurrentPlatform 0 msiAdvertiseX86Platform 1 msiAdvertiseIA64Platform 2 msiAdvertiseX64Platform 4}
# Enum MsiAdvertiseProductOptions # Enum MsiAdvertiseProductOptions
variable MsiAdvertiseProductOptions
array set MsiAdvertiseProductOptions {msiAdvertiseDefault 0 msiAdvertiseSingleInstance 1} array set MsiAdvertiseProductOptions {msiAdvertiseDefault 0 msiAdvertiseSingleInstance 1}
# Enum MsiAdvertiseScriptFlags # Enum MsiAdvertiseScriptFlags
variable MsiAdvertiseScriptFlags
array set MsiAdvertiseScriptFlags {msiAdvertiseScriptCacheInfo 1 msiAdvertiseScriptShortcuts 4 msiAdvertiseScriptMachineAssign 8 msiAdvertiseScriptConfigurationRegistration 32 msiAdvertiseScriptValidateTransformsList 64 msiAdvertiseScriptClassInfoRegistration 128 msiAdvertiseScriptExtensionInfoRegistration 256 msiAdvertiseScriptAppInfo 384 msiAdvertiseScriptRegData 416} array set MsiAdvertiseScriptFlags {msiAdvertiseScriptCacheInfo 1 msiAdvertiseScriptShortcuts 4 msiAdvertiseScriptMachineAssign 8 msiAdvertiseScriptConfigurationRegistration 32 msiAdvertiseScriptValidateTransformsList 64 msiAdvertiseScriptClassInfoRegistration 128 msiAdvertiseScriptExtensionInfoRegistration 256 msiAdvertiseScriptAppInfo 384 msiAdvertiseScriptRegData 416}
} }

0
src/vendorlib_tcl8/twapi4.7.2/mstask.tcl → src/vendorlib_tcl8/twapi-5.0b1/mstask.tcl

0
src/vendorlib_tcl8/twapi4.7.2/multimedia.tcl → src/vendorlib_tcl8/twapi-5.0b1/multimedia.tcl

0
src/vendorlib_tcl8/twapi4.7.2/namedpipe.tcl → src/vendorlib_tcl8/twapi-5.0b1/namedpipe.tcl

0
src/vendorlib_tcl8/twapi4.7.2/network.tcl → src/vendorlib_tcl8/twapi-5.0b1/network.tcl

0
src/vendorlib_tcl8/twapi4.7.2/nls.tcl → src/vendorlib_tcl8/twapi-5.0b1/nls.tcl

2
src/vendorlib_tcl8/twapi4.7.2/os.tcl → src/vendorlib_tcl8/twapi-5.0b1/os.tcl

@ -707,7 +707,7 @@ proc twapi::find_domain_controller {args} {
# Set preferred bits. # Set preferred bits.
foreach req $opts(prefer) { foreach req $opts(prefer) {
if {[string is integer $req]} { if {[string is integer -strict $req]} {
setbits flags $req setbits flags $req
} else { } else {
switch -exact -- $req { switch -exact -- $req {

0
src/vendorlib_tcl8/twapi4.7.2/pdh.tcl → src/vendorlib_tcl8/twapi-5.0b1/pdh.tcl

100
src/vendorlib_tcl8/twapi-5.0b1/pkgIndex.tcl

@ -0,0 +1,100 @@
if {$::tcl_platform(platform) ne "windows"} {
return
}
package ifneeded twapi_base 5.0b1 \
[list apply [list {dir} {
package require platform
set packageVer [string map {. {}} 5.0b1]
if {[package vsatisfies [package require Tcl] 9]} {
set baseDllName "tcl9twapi50b1.dll"
} else {
set baseDllName "twapi50b1t.dll"
}
set package "twapi"
set package_ns ::$package
namespace eval $package_ns {}
set package_init_name [string totitle $package]
# Try to load from current directory and if that fails try from
# platform-specific directories. Note on failure to load when the DLL
# exists, we do not try to load from other locations as twapi modules
# may have been partially set up.
set dllFound false
foreach platform [linsert [::platform::patterns [platform::identify]] 0 .] {
if {$platform eq "tcl"} continue
set path [file join $dir $platform $baseDllName]
if {[file exists $path]} {
uplevel #0 [list load $path $package_init_name]
set dllFound true
break
}
}
if {!$dllFound} {
error "Could not locate TWAPI dll."
}
# Load was successful
set ${package_ns}::dllPath [file normalize $path]
set ${package_ns}::packageDir $dir
source [file join $dir twapi.tcl]
package provide twapi_base 5.0b1
}] $dir]
set __twapimods {
com
msi
power
printer
synch
security
account
apputil
clipboard
console
crypto
device
etw
eventlog
mstask
multimedia
namedpipe
network
nls
os
pdh
process
rds
registry
resource
service
share
shell
storage
ui
input
winsta
wmi
}
foreach __twapimod $__twapimods {
package ifneeded twapi_$__twapimod 5.0b1 \
[list apply [list {dir mod} {
package require twapi_base 5.0b1
source [file join $dir $mod.tcl]
package provide twapi_$mod 5.0b1
}] $dir $__twapimod]
}
package ifneeded twapi 5.0b1 \
[list apply [list {dir mods} {
package require twapi_base 5.0b1
foreach mod $mods {
package require twapi_$mod 5.0b1
}
package provide twapi 5.0b1
}] $dir $__twapimods]
unset __twapimod
unset __twapimods

0
src/vendorlib_tcl8/twapi4.7.2/power.tcl → src/vendorlib_tcl8/twapi-5.0b1/power.tcl

0
src/vendorlib_tcl8/twapi4.7.2/printer.tcl → src/vendorlib_tcl8/twapi-5.0b1/printer.tcl

2
src/vendorlib_tcl8/twapi4.7.2/process.tcl → src/vendorlib_tcl8/twapi-5.0b1/process.tcl

@ -1732,7 +1732,7 @@ proc twapi::_get_process_name_path_helper {pid {type name} args} {
{noaccess.arg "(unknown)"} {noaccess.arg "(unknown)"}
} -maxleftover 0] } -maxleftover 0]
if {![string is integer $pid]} { if {![string is integer -strict $pid]} {
error "Invalid non-numeric pid $pid" error "Invalid non-numeric pid $pid"
} }
if {[is_system_pid $pid]} { if {[is_system_pid $pid]} {

0
src/vendorlib_tcl8/twapi4.7.2/rds.tcl → src/vendorlib_tcl8/twapi-5.0b1/rds.tcl

0
src/vendorlib_tcl8/twapi4.7.2/registry.tcl → src/vendorlib_tcl8/twapi-5.0b1/registry.tcl

0
src/vendorlib_tcl8/twapi4.7.2/resource.tcl → src/vendorlib_tcl8/twapi-5.0b1/resource.tcl

11
src/vendorlib_tcl8/twapi4.7.2/security.tcl → src/vendorlib_tcl8/twapi-5.0b1/security.tcl

@ -10,6 +10,7 @@
namespace eval twapi { namespace eval twapi {
# Map privilege level mnemonics to priv level # Map privilege level mnemonics to priv level
variable priv_level_map
array set priv_level_map {guest 0 user 1 admin 2} array set priv_level_map {guest 0 user 1 admin 2}
# TBD - the following are not used, enhancements needed ? # TBD - the following are not used, enhancements needed ?
@ -969,7 +970,7 @@ proc twapi::sort_aces {aces} {
_init_ace_type_symbol_to_code_map _init_ace_type_symbol_to_code_map
foreach type [array names twapi::_ace_type_symbol_to_code_map] { foreach type [array names ::twapi::_ace_type_symbol_to_code_map] {
set direct_aces($type) [list ] set direct_aces($type) [list ]
set inherited_aces($type) [list ] set inherited_aces($type) [list ]
} }
@ -1294,6 +1295,12 @@ proc twapi::set_security_descriptor_dacl {secd acl {defaulted 0}} {
return [list $control $owner $group $acl $sacl] return [list $control $owner $group $acl $sacl]
} }
proc twapi::protect_security_descriptor_dacl {secd} {
lassign $secd control owner group dacl sacl
set control [expr {$control | 0x1000}]; # SE_DACL_PROTECTED
return [list $control $owner $group $dacl $sacl]
}
# Return the SACL in a security descriptor # Return the SACL in a security descriptor
proc twapi::get_security_descriptor_sacl {secd} { proc twapi::get_security_descriptor_sacl {secd} {
if {[_null_secd $secd]} { if {[_null_secd $secd]} {
@ -1834,7 +1841,7 @@ proc twapi::_init_ace_type_symbol_to_code_map {} {
# Map a resource symbol type to value # Map a resource symbol type to value
proc twapi::_map_resource_symbol_to_type {sym {named true}} { proc twapi::_map_resource_symbol_to_type {sym {named true}} {
if {[string is integer $sym]} { if {[string is integer -strict $sym]} {
return $sym return $sym
} }

2
src/vendorlib_tcl8/twapi4.7.2/service.tcl → src/vendorlib_tcl8/twapi-5.0b1/service.tcl

@ -531,7 +531,7 @@ proc twapi::set_service_configuration {name args} {
foreach opt {command loadordergroup dependencies account password displayname} { foreach opt {command loadordergroup dependencies account password displayname} {
if {![info exists opts($opt)]} { if {![info exists opts($opt)]} {
set winparams($opt) $twapi::nullptr set winparams($opt) $::twapi::nullptr
} }
} }

0
src/vendorlib_tcl8/twapi4.7.2/share.tcl → src/vendorlib_tcl8/twapi-5.0b1/share.tcl

2
src/vendorlib_tcl8/twapi4.7.2/shell.tcl → src/vendorlib_tcl8/twapi-5.0b1/shell.tcl

@ -60,7 +60,7 @@ proc twapi::get_shell_folder {csidl args} {
} }
} }
if {![string is integer $csidl]} { if {![string is integer -strict $csidl]} {
set csidl_key [string toupper $csidl] set csidl_key [string toupper $csidl]
if {![info exists csidl_lookup($csidl_key)]} { if {![info exists csidl_lookup($csidl_key)]} {
# Try by adding a CSIDL prefix # Try by adding a CSIDL prefix

0
src/vendorlib_tcl8/twapi4.7.2/sspi.tcl → src/vendorlib_tcl8/twapi-5.0b1/sspi.tcl

0
src/vendorlib_tcl8/twapi4.7.2/storage.tcl → src/vendorlib_tcl8/twapi-5.0b1/storage.tcl

0
src/vendorlib_tcl8/twapi4.7.2/synch.tcl → src/vendorlib_tcl8/twapi-5.0b1/synch.tcl

23
src/vendorlib_tcl8/twapi4.7.2/tls.tcl → src/vendorlib_tcl8/twapi-5.0b1/tls.tcl

@ -398,6 +398,7 @@ proc twapi::tls::watch {chan watchmask} {
dict set _channels($chan) WatchMask $watchmask dict set _channels($chan) WatchMask $watchmask
if {"read" in $watchmask} { if {"read" in $watchmask} {
debuglog "[info level 0]: read"
# Post a read even if we already have input or if the # Post a read even if we already have input or if the
# underlying socket has gone away. # underlying socket has gone away.
# TBD - do we have a mechanism for continuously posting # TBD - do we have a mechanism for continuously posting
@ -411,6 +412,7 @@ proc twapi::tls::watch {chan watchmask} {
} }
if {"write" in [dict get $_channels($chan) WatchMask]} { if {"write" in [dict get $_channels($chan) WatchMask]} {
debuglog "[info level 0]: write"
if {[dict get $_channels($chan) State] in {OPEN NEGOTIATING CLOSED} } { if {[dict get $_channels($chan) State] in {OPEN NEGOTIATING CLOSED} } {
_post_write_event $chan _post_write_event $chan
} }
@ -870,6 +872,7 @@ proc twapi::tls::_so_write_handler {chan} {
variable _channels variable _channels
if {[info exists _channels($chan)]} { if {[info exists _channels($chan)]} {
debuglog "[info level 0]: channel exists"
dict with _channels($chan) {} dict with _channels($chan) {}
# If we are not actually asked to generate write events, # If we are not actually asked to generate write events,
@ -877,23 +880,30 @@ proc twapi::tls::_so_write_handler {chan} {
# Once it runs, we never want it again else it will keep triggering # Once it runs, we never want it again else it will keep triggering
# as sockets are always writable # as sockets are always writable
if {"write" ni $WatchMask} { if {"write" ni $WatchMask} {
debuglog "[info level 0]: write not in writemask"
if {[info exists Socket]} { if {[info exists Socket]} {
chan event $Socket writable {} chan event $Socket writable {}
} }
} }
if {$State in {SERVERINIT CLIENTINIT NEGOTIATING}} { if {$State in {SERVERINIT CLIENTINIT NEGOTIATING}} {
debuglog "[info level 0]: Calling _negotiate_from_handler, State=$State"
if {![_negotiate_from_handler $chan]} { if {![_negotiate_from_handler $chan]} {
# TBD - should we throw so bgerror gets run? # TBD - should we throw so bgerror gets run?
debuglog "[info level 0]: _negotiate_from_handler returned non-zero."
return return
} }
} }
debuglog "[info level 0]: State = $State, newstate=[dict get $_channels($chan) State]"
# Do not use local var $State because _negotiate might have updated it # Do not use local var $State because _negotiate might have updated it
if {"write" in $WatchMask && [dict get $_channels($chan) State] eq "OPEN"} { if {"write" in $WatchMask && [dict get $_channels($chan) State] eq "OPEN"} {
debuglog "[info level 0]: posting write event"
_post_write_event $chan _post_write_event $chan
} else {
debuglog "[info level 0]: NOT posting write event"
} }
} }
debuglog "[info level 0]: returning"
return return
} }
@ -929,16 +939,19 @@ proc twapi::tls::_negotiate2 {chan} {
dict with _channels($chan) {}; # dict -> local vars dict with _channels($chan) {}; # dict -> local vars
debuglog [info level 0] debuglog "[info level 0]: State=$State"
switch $State { switch $State {
NEGOTIATING { NEGOTIATING {
if {$Blocking && ![info exists AcceptCallback]} { if {$Blocking && ![info exists AcceptCallback]} {
debuglog "[info level 0]: Blocking"
return [_blocking_negotiate_loop $chan] return [_blocking_negotiate_loop $chan]
} }
set data [chan read $Socket] set data [chan read $Socket]
if {[string length $data] == 0} { if {[string length $data] == 0} {
debuglog "[info level 0]: No data from socket"
if {[chan eof $Socket]} { if {[chan eof $Socket]} {
debuglog "[info level 0]: EOF on socket"
throw {TWAPI TLS NEGOTIATE EOF} "Unexpected EOF during TLS negotiation (NEGOTIATING)" throw {TWAPI TLS NEGOTIATE EOF} "Unexpected EOF during TLS negotiation (NEGOTIATING)"
} else { } else {
# No data yet, just keep waiting # No data yet, just keep waiting
@ -946,7 +959,9 @@ proc twapi::tls::_negotiate2 {chan} {
return return
} }
} else { } else {
debuglog "[info level 0]: Read data from socket"
lassign [sspi_step $SspiContext $data] status outdata leftover lassign [sspi_step $SspiContext $data] status outdata leftover
debuglog "[info level 0]: sspi_step returned $status"
debuglog "sspi_step returned status $status with [string length $outdata] bytes" debuglog "sspi_step returned status $status with [string length $outdata] bytes"
if {[string length $outdata]} { if {[string length $outdata]} {
chan puts -nonewline $Socket $outdata chan puts -nonewline $Socket $outdata
@ -976,12 +991,14 @@ proc twapi::tls::_negotiate2 {chan} {
CLIENTINIT { CLIENTINIT {
if {$Blocking} { if {$Blocking} {
debuglog "[info level 0]: CLIENTINIT - blocking negotiate"
_client_blocking_negotiate $chan _client_blocking_negotiate $chan
} else { } else {
dict set _channels($chan) State NEGOTIATING dict set _channels($chan) State NEGOTIATING
set SspiContext [sspi_client_context $Credentials -usesuppliedcreds $UseSuppliedCreds -stream 1 -target $PeerSubject -manualvalidation [expr {[llength $Verifier] > 0}]] set SspiContext [sspi_client_context $Credentials -usesuppliedcreds $UseSuppliedCreds -stream 1 -target $PeerSubject -manualvalidation [expr {[llength $Verifier] > 0}]]
dict set _channels($chan) SspiContext $SspiContext dict set _channels($chan) SspiContext $SspiContext
lassign [sspi_step $SspiContext] status outdata lassign [sspi_step $SspiContext] status outdata
debuglog "[info level 0]: sspi_step returned $status"
if {[string length $outdata]} { if {[string length $outdata]} {
chan puts -nonewline $Socket $outdata chan puts -nonewline $Socket $outdata
chan flush $Socket chan flush $Socket
@ -1051,7 +1068,7 @@ proc twapi::tls::_negotiate2 {chan} {
error "Internal error: _negotiate called in state [dict get $_channels($chan) State]" error "Internal error: _negotiate called in state [dict get $_channels($chan) State]"
} }
} }
debuglog "[info level 0]: returning with state [dict get $_channels($chan) State]"
return return
} }

11
src/vendorlib_tcl8/twapi4.7.2/twapi.tcl → src/vendorlib_tcl8/twapi-5.0b1/twapi.tcl

@ -6,7 +6,7 @@
# General definitions and procs used by all TWAPI modules # General definitions and procs used by all TWAPI modules
package require Tcl 8.5 package require Tcl 8.6-
package require registry package require registry
namespace eval twapi { namespace eval twapi {
@ -129,9 +129,6 @@ namespace eval twapi {
} }
} }
# Make twapi versions the same as the base module versions
set twapi::version(twapi) $::twapi::version(twapi_base)
# #
# log for tracing / debug messages. # log for tracing / debug messages.
proc twapi::debuglog_clear {} { proc twapi::debuglog_clear {} {
@ -258,11 +255,11 @@ proc twapi::get_version {args} {
variable version variable version
array set opts [parseargs args {patchlevel}] array set opts [parseargs args {patchlevel}]
if {$opts(patchlevel)} { if {$opts(patchlevel)} {
return $version(twapi) return $version
} else { } else {
# Only return major, minor # Only return major, minor
set ver $version(twapi) set ver $version
regexp {^([[:digit:]]+\.[[:digit:]]+)[.ab]} $version(twapi) - ver regexp {^([[:digit:]]+\.[[:digit:]]+)[.ab]} $version - ver
return $ver return $ver
} }
} }

2
src/vendorlib_tcl8/twapi4.7.2/ui.tcl → src/vendorlib_tcl8/twapi-5.0b1/ui.tcl

@ -1162,7 +1162,7 @@ proc twapi::_get_gui_thread_info {tid args} {
# if $hwin corresponds to a null window handle, returns an empty string # if $hwin corresponds to a null window handle, returns an empty string
proc twapi::_return_window {hwin} { proc twapi::_return_window {hwin} {
if {[pointer_null? $hwin HWND]} { if {[pointer_null? $hwin HWND]} {
return $twapi::null_hwin return $::twapi::null_hwin
} }
return $hwin return $hwin
} }

0
src/vendorlib_tcl8/twapi4.7.2/win.tcl → src/vendorlib_tcl8/twapi-5.0b1/win.tcl

BIN
src/vendorlib_tcl8/twapi-5.0b1/win32-ix86/tcl9twapi50b1.dll

Binary file not shown.

BIN
src/vendorlib_tcl8/twapi-5.0b1/win32-ix86/twapi50b1t.dll

Binary file not shown.

BIN
src/vendorlib_tcl8/twapi-5.0b1/win32-x86_64/tcl9twapi50b1.dll

Binary file not shown.

BIN
src/vendorlib_tcl8/twapi-5.0b1/win32-x86_64/twapi50b1t.dll

Binary file not shown.

0
src/vendorlib_tcl8/twapi4.7.2/winlog.tcl → src/vendorlib_tcl8/twapi-5.0b1/winlog.tcl

0
src/vendorlib_tcl8/twapi4.7.2/winsta.tcl → src/vendorlib_tcl8/twapi-5.0b1/winsta.tcl

0
src/vendorlib_tcl8/twapi4.7.2/wmi.tcl → src/vendorlib_tcl8/twapi-5.0b1/wmi.tcl

64
src/vendorlib_tcl8/twapi-5.0b1/wts.tcl

@ -0,0 +1,64 @@
# Copyright (c) 2021 Ashok P. Nadkarni
# All rights reserved.
#
# See the file LICENSE for license
namespace eval twapi {
variable _wts_session_monitors
set _wts_session_monitors [dict create]
}
proc twapi::start_wts_session_monitor {script args} {
variable _wts_session_monitors
parseargs args {
all
} -maxleftover 0 -setvars]
set script [lrange $script 0 end]; # Verify syntactically a list
set id "wts#[TwapiId]"
if {[dict size $_wts_session_monitors] == 0} {
# No monitoring in progress. Start it
# 0x2B1 -> WM_WTSSESSION_CHANGE
Twapi_WTSRegisterSessionNotification $all
_register_script_wm_handler 0x2B1 [list [namespace current]::_wts_session_change_handler] 0
}
dict set _wts_session_monitors $id $script
return $id
}
proc twapi::stop_wts_session_monitor {id} {
variable _wts_session_monitors
if {![dict exists $_wts_session_monitors $id]} {
return
}
dict unset _wts_session_monitors $id
if {[dict size $_wts_session_monitors] == 0} {
# 0x2B1 -> WM_WTSSESSION_CHANGE
_unregister_script_wm_handler 0x2B1 [list [namespace current]::_wts_session_handler]
Twapi_WTSUnRegisterSessionNotification
}
}
proc twapi::_wts_session_change_handler {msg change session_id msgpos ticks} {
variable _wts_session_monitors
if {[dict size $_wts_session_monitors] == 0} {
return; # Not an error, could have deleted while already queued
}
dict for {id script} $_wts_session_monitors {
set code [catch {uplevel #0 [linsert $script end $change $session_id]} msg]
if {$code == 1} {
# Error - put in background but we do not abort
after 0 [list error $msg $::errorInfo $::errorCode]
}
}
return
}

605
src/vendorlib_tcl8/twapi4.7.2/metoo.tcl

@ -1,605 +0,0 @@
# MeTOO stands for "MeTOO Emulates TclOO" (at a superficial syntactic level)
#
# Implements a *tiny*, but useful, subset of TclOO, primarily for use
# with Tcl 8.4. Intent is that if you write code using MeToo, it should work
# unmodified with TclOO in 8.5/8.6. Obviously, don't try going the other way!
#
# Emulation is superficial, don't try to be too clever in usage.
# Doing funky, or even non-funky, things with object namespaces will
# not work as you would expect.
#
# See the metoo::demo proc for sample usage. Calling this proc
# with parameter "oo" will use the TclOO commands. Else the metoo::
# commands. Note the demo code remains the same for both.
#
# The following fragment uses MeToo only if TclOO is not available:
# if {[llength [info commands oo::*]]} {
# namespace import oo::*
# } else {
# source metoo.tcl
# namespace import metoo::class
# }
# class create C {...}
#
# Summary of the TclOO subset implemented - see TclOO docs for detail :
#
# Creating a new class:
# metoo::class create CLASSNAME CLASSDEFINITION
#
# Destroying a class:
# CLASSNAME destroy
# - this also destroys objects of that class and recursively destroys
# child classes. NOTE: deleting the class namespace or renaming
# the CLASSNAME command to "" will NOT call object destructors.
#
# CLASSDEFINITION: Following may appear in CLASSDEFINTION
# method METHODNAME params METHODBODY
# - same as TclOO
# constructor params METHODBODY
# - same syntax as TclOO
# destructor METHODBODY
# - same syntax as TclOO
# unknown METHODNAME ARGS
# - if defined, called when an undefined method is invoked
# superclass SUPER
# - inherits from SUPER. Unlike TclOO, only single inheritance. Also
# no checks for inheritance loops. You'll find out quickly enough!
# All other commands within a CLASSDEFINITION will either raise error or
# work differently from TclOO. Actually you can use pretty much any
# Tcl command inside CLASSDEFINITION but the results may not be what you
# expect. Best to avoid this.
#
# METHODBODY: The following method-internal TclOO commands are available:
# my METHODNAME ARGS
# - to call another method METHODNAME
# my variable VAR1 ?VAR2...?
# - brings object-specific variables into scope
# next ?ARGS?
# - calls the superclass method of the same name
# self
# self object
# - returns the object name (usable as a command)
# self class
# - returns class of this object
# self namespace
# - returns namespace of this object
#
# Creating objects:
# CLASSNAME create OBJNAME ?ARGS?
# - creates object OBJNAME of class CLASSNAME, passing ARGS to constructor
# Returns the fully qualified object name that can be used as a command.
# CLASSNAME new ?ARGS?
# - creates a new object with an auto-generated name
#
# Destroying objects
# OBJNAME destroy
# - destroys the object calling destructors
# rename OBJNAME ""
# - same as above
#
# Renaming an object
# rename OBJNAME NEWNAME
# - the object can now be invoked using the new name. Note this is unlike
# classes which should not be renamed.
#
#
# Introspection (though different from TclOO)
# metoo::introspect object isa OBJECT ?CLASSNAME?
# - returns 1 if OBJECT is a metoo object and is of the specified class
# if CLASSNAME is specified. Returns 0 otherwise.
# metoo::introspect object list
# - returns list of all objects
# metoo::introspect class ancestors CLASSNAME
# - returns list of ancestors for a class
#
# Differences and missing features from TclOO: Everything not listed above
# is missing. Some notable differences:
# - MeTOO is class-based, not object based like TclOO, thus class instances
# (objects) cannot be modified by adding instance-specific methods etc..
# Also a class is not itself an object.
# - Renaming classes does not work and will fail in mysterious ways
# - does not support class refinement/definition
# - no variable command at class level for automatically bringing variables
# into scope
# - no filters, forwarding, multiple-inheritance
# - no private methods (all methods are exported).
# NOTE: file must be sourced at global level since metoo namespace is expected
# to be top level namespace
# DO NOT DO THIS. ELSE TESTS FAIL BECAUSE they define tests in the
# metoo namespace which then get deleted by the line below when
# the package is lazy auto-loaded
# catch {namespace delete metoo}
# TBD - variable ("my variable" is done, "variable" in method or
# class definition is not)
# TBD - default constructor and destructor to "next" (or maybe that
# is already taken care of by the inheritance code
namespace eval metoo {
variable next_id 0
variable _objects; # Maps objects to its namespace
array set _objects {}
}
# Namespace in which commands in a class definition block are called
namespace eval metoo::define {
proc method {class_ns name params body} {
# Methods are defined in the methods subspace of the class namespace.
# We prefix with _m_ to prevent them from being directly called
# as procs, for example if the method is a Tcl command like "set"
# The first parameter to a method is always the object namespace
# denoted as the paramter "_this"
namespace eval ${class_ns}::methods [list proc _m_$name [concat [list _this] $params] $body]
}
proc superclass {class_ns superclass} {
if {[info exists ${class_ns}::super]} {
error "Only one superclass allowed for a class"
}
set sup [uplevel 3 "namespace eval $superclass {namespace current}"]
set ${class_ns}::super $sup
# We store the subclass in the super so it can be destroyed
# if the super is destroyed.
set ${sup}::subclasses($class_ns) 1
}
proc constructor {class_ns params body} {
method $class_ns constructor $params $body
}
proc destructor {class_ns body} {
method $class_ns destructor {} $body
}
proc export {args} {
# Nothing to do, all methods are exported anyways
# Command is here for compatibility only
}
}
# Namespace in which commands used in objects methods are defined
# (self, my etc.)
namespace eval metoo::object {
proc next {args} {
upvar 1 _this this; # object namespace
# Figure out what class context this is executing in. Note
# we cannot use _this in caller since that is the object namespace
# which is not necessarily related to the current class namespace.
set class_ns [namespace parent [uplevel 1 {namespace current}]]
# Figure out the current method being called
set methodname [namespace tail [lindex [uplevel 1 {info level 0}] 0]]
# Find the next method in the class hierarchy and call it
while {[info exists ${class_ns}::super]} {
set class_ns [set ${class_ns}::super]
if {[llength [info commands ${class_ns}::methods::$methodname]]} {
return [uplevel 1 [list ${class_ns}::methods::$methodname $this] $args]
}
}
error "'next' command has no receiver in the hierarchy for method $methodname"
}
proc self {{what object}} {
upvar 1 _this this
switch -exact -- $what {
class { return [namespace parent $this] }
namespace { return $this }
object { return [set ${this}::_(name)] }
default {
error "Argument '$what' not understood by self method"
}
}
}
proc my {methodname args} {
# We insert the object namespace as the first parameter to the command.
# This is passed as the first parameter "_this" to methods. Since
# "my" can be only called from methods, we can retrieve it fro
# our caller.
upvar 1 _this this; # object namespace
set class_ns [namespace parent $this]
set meth [::metoo::_locate_method $class_ns $methodname]
if {$meth ne ""} {
# We need to invoke in the caller's context so upvar etc. will
# not be affected by this intermediate method dispatcher
return [uplevel 1 [list $meth $this] $args]
}
# It is ok for constructor or destructor to be undefined. For
# the others, invoke "unknown" if it exists
if {$methodname eq "constructor" || $methodname eq "destructor"} {
return
}
set meth [::metoo::_locate_method $class_ns "unknown"]
if {$meth ne ""} {
# We need to invoke in the caller's context so upvar etc. will
# not be affected by this intermediate method dispatcher
return [uplevel 1 [list $meth $this $methodname] $args]
}
error "Unknown method $methodname"
}
}
# Given a method name, locate it in the class hierarchy. Returns
# fully qualified method if found, else an empty string
proc metoo::_locate_method {class_ns methodname} {
# See if there is a method defined in this class.
# Breakage if method names with wildcard chars. Too bad
if {[llength [info commands ${class_ns}::methods::_m_$methodname]]} {
# We need to invoke in the caller's context so upvar etc. will
# not be affected by this intermediate method dispatcher
return ${class_ns}::methods::_m_$methodname
}
# No method here, check for super class.
while {[info exists ${class_ns}::super]} {
set class_ns [set ${class_ns}::super]
if {[llength [info commands ${class_ns}::methods::_m_$methodname]]} {
return ${class_ns}::methods::_m_$methodname
}
}
return ""; # Not found
}
proc metoo::_new {class_ns cmd args} {
# class_ns expected to be fully qualified
variable next_id
# IMPORTANT:
# object namespace *must* be child of class namespace.
# Saves a bit of bookkeeping. Putting it somewhere else will require
# changes to many other places in the code.
set objns ${class_ns}::o#[incr next_id]
switch -exact -- $cmd {
create {
if {[llength $args] < 1} {
error "Insufficient args, should be: class create CLASSNAME ?args?"
}
# TBD - check if command already exists
# Note objname must always be fully qualified. Note cannot
# use namespace which here because the commmand does not
# yet exist.
set args [lassign $args objname]
if {[string compare :: [string range $objname 0 1]]} {
# Not fully qualified. Qualify based on caller namespace
set objname [uplevel 1 "namespace current"]::$objname
}
# Trip excess ":" - can happen in both above cases
set objname ::[string trimleft $objname :]
}
new {
set objname $objns
}
default {
error "Unknown command '$cmd'. Should be create or new."
}
}
# Create the namespace. The array _ is used to hold private information
namespace eval $objns {
variable _
}
set ${objns}::_(name) $objname
# When invoked by its name, call the dispatcher.
interp alias {} $objname {} ${class_ns}::_call $objns
# Register the object. We do this BEFORE running the constructor
variable _objects
set _objects($objname) $objns
# Invoke the constructor
if {[catch {
$objname constructor {*}$args
} msg]} {
# Undo what we did
set erinfo $::errorInfo
set ercode $::errorCode
rename $objname ""
namespace delete $objns
error $msg $erinfo $ercode
}
# TBD - does tracing cause a slowdown ?
# Set up trace to track when the object is renamed/destroyed
trace add command $objname {rename delete} [list [namespace current]::_trace_object_renames $objns]
return $objname
}
proc metoo::_trace_object_renames {objns oldname newname op} {
# Note the trace command fully qualifies oldname and newname
if {$op eq "rename"} {
variable _objects
set _objects($newname) $_objects($oldname)
unset _objects($oldname)
set ${objns}::_(name) $newname
} else {
$oldname destroy
}
}
proc metoo::_class_cmd {class_ns cmd args} {
switch -exact -- $cmd {
create -
new {
return [uplevel 1 [list [namespace current]::_new $class_ns $cmd] $args]
}
destroy {
# Destroy all objects belonging to this class
foreach objns [namespace children ${class_ns} o#*] {
[set ${objns}::_(name)] destroy
}
# Destroy all classes that inherit from this
foreach child_ns [array names ${class_ns}::subclasses] {
# Child namespace is also subclass command
$child_ns destroy
}
trace remove command $class_ns {rename delete} [list ::metoo::_trace_class_renames]
namespace delete ${class_ns}
rename ${class_ns} ""
}
default {
error "Unknown command '$cmd'. Should be create, new or destroy."
}
}
}
proc metoo::class {cmd cname definition} {
variable next_id
if {$cmd ne "create"} {
error "Syntax: class create CLASSNAME DEFINITION"
}
if {[uplevel 1 "namespace exists $cname"]} {
error "can't create class '$cname': namespace already exists with that name."
}
# Resolve cname into a namespace in the caller's context
set class_ns [uplevel 1 "namespace eval $cname {namespace current}"]
if {[llength [info commands $class_ns]]} {
# Delete the namespace we just created
namespace delete $class_ns
error "can't create class '$cname': command already exists with that name."
}
# Define the commands/aliases that are used inside a class definition
foreach procname [info commands [namespace current]::define::*] {
interp alias {} ${class_ns}::[namespace tail $procname] {} $procname $class_ns
}
# Define the built in commands callable within class instance methods
foreach procname [info commands [namespace current]::object::*] {
interp alias {} ${class_ns}::methods::[namespace tail $procname] {} $procname
}
# Define the destroy method for the class object instances
namespace eval $class_ns {
method destroy {} {
set retval [my destructor]
# Remove trace on command rename/deletion.
# ${_this}::_(name) contains the object's current name on
# which the trace is set.
set me [set ${_this}::_(name)]
trace remove command $me {rename delete} [list ::metoo::_trace_object_renames $_this]
rename $me ""
unset -nocomplain ::metoo::_objects($me)
namespace delete $_this
return $retval
}
method variable {args} {
if {[llength $args]} {
set cmd [list upvar 0]
foreach varname $args {
lappend cmd ${_this}::$varname $varname
}
uplevel 1 $cmd
}
}
}
# Define the class. Note we do this *after* the standard
# definitions (destroy etc.) above so that they can
# be overridden by the class definition.
if {[catch {
namespace eval $class_ns $definition
} msg ]} {
namespace delete $class_ns
error $msg $::errorInfo $::errorCode
}
# Also define the call dispatcher within the class.
# TBD - not sure this is actually necessary any more
namespace eval ${class_ns} {
proc _call {objns methodname args} {
# Note this duplicates the "my" code but cannot call that as
# it adds another frame level which interferes with uplevel etc.
set class_ns [namespace parent $objns]
# We insert the object namespace as the first param to the command.
# This is passed as the first parameter "_this" to methods.
set meth [::metoo::_locate_method $class_ns $methodname]
if {$meth ne ""} {
# We need to invoke in the caller's context so upvar etc. will
# not be affected by this intermediate method dispatcher
return [uplevel 1 [list $meth $objns] $args]
}
# It is ok for constructor or destructor to be undefined. For
# the others, invoke "unknown" if it exists
if {$methodname eq "constructor" || $methodname eq "destructor"} {
return
}
set meth [::metoo::_locate_method $class_ns "unknown"]
if {$meth ne ""} {
# We need to invoke in the caller's context so upvar etc. will
# not be affected by this intermediate method dispatcher
return [uplevel 1 [list $meth $objns $methodname] $args]
}
error "Unknown method $methodname"
}
}
# The namespace is also a command used to create class instances
# TBD - check if command of that name already exists
interp alias {} $class_ns {} [namespace current]::_class_cmd $class_ns
# Set up trace to track when the class command is renamed/destroyed
trace add command $class_ns [list rename delete] ::metoo::_trace_class_renames
return $class_ns
}
proc metoo::_trace_class_renames {oldname newname op} {
if {$op eq "rename"} {
# TBD - this does not actually work. The rename succeeds anyways
error "MetOO classes may not be renamed"
} else {
$oldname destroy
}
}
proc metoo::introspect {type info args} {
switch -exact -- $type {
"object" {
variable _objects
switch -exact -- $info {
"isa" {
if {[llength $args] == 0 || [llength $args] > 2} {
error "wrong # args: should be \"metoo::introspect $type $info OBJNAME ?CLASS?\""
}
set objname [uplevel 1 [list namespace which -command [lindex $args 0]]]
if {![info exists _objects($objname)]} {
return 0
}
if {[llength $args] == 1} {
# No class specified
return 1
}
# passed classname assumed to be fully qualified
set objclass [namespace parent $_objects($objname)]
if {[string equal $objclass [lindex $args 1]]} {
# Direct hit
return 1
}
# No direct hit, check ancestors
if {[lindex $args 1] in [ancestors $objclass]} {
return 1
}
return 0
}
"list" {
if {[llength $args] > 1} {
error "wrong # args: should be \"metoo::introspect $type $info ?CLASS?"
}
variable _objects
if {[llength $args] == 0} {
return [array names _objects]
}
set objs {}
foreach obj [array names _objects] {
if {[introspect object isa $obj [lindex $args 0]]} {
lappend objs $obj
}
}
return $objs
}
default {
error "$info subcommand not supported for $type introspection"
}
}
}
"class" {
switch -exact -- $info {
"ancestors" {
if {[llength $args] != 1} {
error "wrong # args: should be \"metoo::introspect $type $info CLASSNAME"
}
return [ancestors [lindex $args 0]]
}
default {
error "$info subcommand not supported for $type introspection"
}
}
}
default {
error "$type introspection not supported"
}
}
}
proc metoo::ancestors {class_ns} {
# Returns ancestors of a class
set ancestors [list ]
while {[info exists ${class_ns}::super]} {
lappend ancestors [set class_ns [set ${class_ns}::super]]
}
return $ancestors
}
namespace eval metoo { namespace export class }
# Simple sample class showing all capabilities. Anything not shown here will
# probably not work. Call as "demo" to use metoo, or "demo oo" to use TclOO.
# Output should be same in both cases.
proc ::metoo::demo {{ns metoo}} {
${ns}::class create Base {
constructor {x y} { puts "Base constructor ([self object]): $x, $y"
}
method m {} { puts "Base::m called" }
method n {args} { puts "Base::n called: [join $args {, }]"; my m }
method unknown {methodname args} { puts "Base::unknown called for $methodname [join $args {, }]"}
destructor { puts "Base::destructor ([self object])" }
}
${ns}::class create Derived {
superclass Base
constructor {x y} { puts "Derived constructor ([self object]): $x, $y" ; next $x $y }
destructor { puts "Derived::destructor called ([self object])" ; next }
method n {args} { puts "Derived::n ([self object]): [join $args {, }]"; next {*}$args}
method put {val} {my variable var ; set var $val}
method get {varname} {my variable var ; upvar 1 $varname retvar; set retvar $var}
}
Base create b dum dee; # Create named object
Derived create d fee fi; # Create derived object
set o [Derived new fo fum]; # Create autonamed object
$o put 10; # Use of instance variable
$o get v; # Verify correct frame level ...
puts "v:$v"; # ...when calling methods
b m; # Direct method
b n; # Use of my to call another method
$o m; # Inherited method
$o n; # Overridden method chained to inherited
$o nosuchmethod arg1 arg2; # Invoke unknown
$o destroy; # Explicit destroy
rename b ""; # Destroy through rename
Base destroy; # Should destroy object d, Derived, Base
}
# Hack to work with the various build configuration.
if {[info commands ::twapi::get_version] ne ""} {
package provide metoo [::twapi::get_version -patchlevel]
}

119
src/vendorlib_tcl8/twapi4.7.2/pkgIndex.tcl

@ -1,119 +0,0 @@
#
# Tcl package index file
#
namespace eval twapi {
variable scriptdir
proc set_scriptdir dir {variable scriptdir ; set scriptdir $dir}
}
package ifneeded twapi_base 4.7.2 \
[list load [file join $dir twapi472.dll] twapi_base]
package ifneeded twapi_com 4.7.2 \
{load {} twapi_com}
package ifneeded metoo 4.7.2 \
[list source [file join $dir metoo.tcl]]
package ifneeded twapi_com 4.7.2 \
{load {} twapi_com}
package ifneeded twapi_msi 4.7.2 \
[list source [file join $dir msi.tcl]]
package ifneeded twapi_power 4.7.2 \
[list source [file join $dir power.tcl]]
package ifneeded twapi_printer 4.7.2 \
[list source [file join $dir printer.tcl]]
package ifneeded twapi_synch 4.7.2 \
[list source [file join $dir synch.tcl]]
package ifneeded twapi_security 4.7.2 \
{load {} twapi_security}
package ifneeded twapi_account 4.7.2 \
{load {} twapi_account}
package ifneeded twapi_apputil 4.7.2 \
{load {} twapi_apputil}
package ifneeded twapi_clipboard 4.7.2 \
{load {} twapi_clipboard}
package ifneeded twapi_console 4.7.2 \
{load {} twapi_console}
package ifneeded twapi_crypto 4.7.2 \
{load {} twapi_crypto}
package ifneeded twapi_device 4.7.2 \
{load {} twapi_device}
package ifneeded twapi_etw 4.7.2 \
{load {} twapi_etw}
package ifneeded twapi_eventlog 4.7.2 \
{load {} twapi_eventlog}
package ifneeded twapi_mstask 4.7.2 \
{load {} twapi_mstask}
package ifneeded twapi_multimedia 4.7.2 \
{load {} twapi_multimedia}
package ifneeded twapi_namedpipe 4.7.2 \
{load {} twapi_namedpipe}
package ifneeded twapi_network 4.7.2 \
{load {} twapi_network}
package ifneeded twapi_nls 4.7.2 \
{load {} twapi_nls}
package ifneeded twapi_os 4.7.2 \
{load {} twapi_os}
package ifneeded twapi_pdh 4.7.2 \
{load {} twapi_pdh}
package ifneeded twapi_process 4.7.2 \
{load {} twapi_process}
package ifneeded twapi_rds 4.7.2 \
{load {} twapi_rds}
package ifneeded twapi_resource 4.7.2 \
{load {} twapi_resource}
package ifneeded twapi_service 4.7.2 \
{load {} twapi_service}
package ifneeded twapi_share 4.7.2 \
{load {} twapi_share}
package ifneeded twapi_shell 4.7.2 \
{load {} twapi_shell}
package ifneeded twapi_storage 4.7.2 \
{load {} twapi_storage}
package ifneeded twapi_ui 4.7.2 \
{load {} twapi_ui}
package ifneeded twapi_input 4.7.2 \
{load {} twapi_input}
package ifneeded twapi_winsta 4.7.2 \
{load {} twapi_winsta}
package ifneeded twapi_wmi 4.7.2 \
{load {} twapi_wmi}
package ifneeded twapi 4.7.2 [subst {
twapi::set_scriptdir [list $dir]
package require twapi_base 4.7.2
source [list [file join $dir twapi_entry.tcl]]
package require metoo 4.7.2
package require twapi_com 4.7.2
package require twapi_msi 4.7.2
package require twapi_power 4.7.2
package require twapi_printer 4.7.2
package require twapi_synch 4.7.2
package require twapi_security 4.7.2
package require twapi_account 4.7.2
package require twapi_apputil 4.7.2
package require twapi_clipboard 4.7.2
package require twapi_console 4.7.2
package require twapi_crypto 4.7.2
package require twapi_device 4.7.2
package require twapi_etw 4.7.2
package require twapi_eventlog 4.7.2
package require twapi_mstask 4.7.2
package require twapi_multimedia 4.7.2
package require twapi_namedpipe 4.7.2
package require twapi_network 4.7.2
package require twapi_nls 4.7.2
package require twapi_os 4.7.2
package require twapi_pdh 4.7.2
package require twapi_process 4.7.2
package require twapi_rds 4.7.2
package require twapi_resource 4.7.2
package require twapi_service 4.7.2
package require twapi_share 4.7.2
package require twapi_shell 4.7.2
package require twapi_storage 4.7.2
package require twapi_ui 4.7.2
package require twapi_input 4.7.2
package require twapi_winsta 4.7.2
package require twapi_wmi 4.7.2
package provide twapi 4.7.2
}]

BIN
src/vendorlib_tcl8/twapi4.7.2/twapi472.dll

Binary file not shown.

11
src/vendorlib_tcl8/twapi4.7.2/twapi_entry.tcl

@ -1,11 +0,0 @@
# -*- tcl -*-
namespace eval twapi {
variable version
set version(twapi) 4.7.2
variable patchlevel 4.7.2
variable package_name twapi
variable dll_base_name twapi[string map {. {}} 4.7.2]
variable scriptdir [file dirname [info script]]
}
source [file join $twapi::scriptdir twapi.tcl]

8
src/vendorlib_tcl9/tcllib2.0/0compatibility/pkgIndex.tcl

@ -0,0 +1,8 @@
# Compatibility wrapper for deprecated packages.
##
# Stages
# [D1] Next Release - Noted deprecated, with redirection wrappers
# [D2] Release After - Wrappers become Blockers, throwing error noting redirection
# [D3] Release Beyond - All removed.
##
# Currently in deprecation [[NONE]]

625
src/vendorlib_tcl9/tcllib2.0/aes/aes.tcl

@ -0,0 +1,625 @@
# aes.tcl -
#
# Copyright (c) 2005 Thorsten Schloermann
# Copyright (c) 2005 Pat Thoyts <patthoyts@users.sourceforge.net>
# Copyright (c) 2013 Andreas Kupries
#
# A Tcl implementation of the Advanced Encryption Standard (US FIPS PUB 197)
#
# AES is a block cipher with a block size of 128 bits and a variable
# key size of 128, 192 or 256 bits.
# The algorithm works on each block as a 4x4 state array. There are 4 steps
# in each round:
# SubBytes a non-linear substitution step using a predefined S-box
# ShiftRows cyclic transposition of rows in the state matrix
# MixColumns transformation upon columns in the state matrix
# AddRoundKey application of round specific sub-key
#
# -------------------------------------------------------------------------
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
# -------------------------------------------------------------------------
package require Tcl 8.5 9
namespace eval ::aes {
variable uid
if {![info exists uid]} { set uid 0 }
namespace export aes
# constants
# S-box
variable sbox {
0x63 0x7c 0x77 0x7b 0xf2 0x6b 0x6f 0xc5 0x30 0x01 0x67 0x2b 0xfe 0xd7 0xab 0x76
0xca 0x82 0xc9 0x7d 0xfa 0x59 0x47 0xf0 0xad 0xd4 0xa2 0xaf 0x9c 0xa4 0x72 0xc0
0xb7 0xfd 0x93 0x26 0x36 0x3f 0xf7 0xcc 0x34 0xa5 0xe5 0xf1 0x71 0xd8 0x31 0x15
0x04 0xc7 0x23 0xc3 0x18 0x96 0x05 0x9a 0x07 0x12 0x80 0xe2 0xeb 0x27 0xb2 0x75
0x09 0x83 0x2c 0x1a 0x1b 0x6e 0x5a 0xa0 0x52 0x3b 0xd6 0xb3 0x29 0xe3 0x2f 0x84
0x53 0xd1 0x00 0xed 0x20 0xfc 0xb1 0x5b 0x6a 0xcb 0xbe 0x39 0x4a 0x4c 0x58 0xcf
0xd0 0xef 0xaa 0xfb 0x43 0x4d 0x33 0x85 0x45 0xf9 0x02 0x7f 0x50 0x3c 0x9f 0xa8
0x51 0xa3 0x40 0x8f 0x92 0x9d 0x38 0xf5 0xbc 0xb6 0xda 0x21 0x10 0xff 0xf3 0xd2
0xcd 0x0c 0x13 0xec 0x5f 0x97 0x44 0x17 0xc4 0xa7 0x7e 0x3d 0x64 0x5d 0x19 0x73
0x60 0x81 0x4f 0xdc 0x22 0x2a 0x90 0x88 0x46 0xee 0xb8 0x14 0xde 0x5e 0x0b 0xdb
0xe0 0x32 0x3a 0x0a 0x49 0x06 0x24 0x5c 0xc2 0xd3 0xac 0x62 0x91 0x95 0xe4 0x79
0xe7 0xc8 0x37 0x6d 0x8d 0xd5 0x4e 0xa9 0x6c 0x56 0xf4 0xea 0x65 0x7a 0xae 0x08
0xba 0x78 0x25 0x2e 0x1c 0xa6 0xb4 0xc6 0xe8 0xdd 0x74 0x1f 0x4b 0xbd 0x8b 0x8a
0x70 0x3e 0xb5 0x66 0x48 0x03 0xf6 0x0e 0x61 0x35 0x57 0xb9 0x86 0xc1 0x1d 0x9e
0xe1 0xf8 0x98 0x11 0x69 0xd9 0x8e 0x94 0x9b 0x1e 0x87 0xe9 0xce 0x55 0x28 0xdf
0x8c 0xa1 0x89 0x0d 0xbf 0xe6 0x42 0x68 0x41 0x99 0x2d 0x0f 0xb0 0x54 0xbb 0x16
}
# inverse S-box
variable xobs {
0x52 0x09 0x6a 0xd5 0x30 0x36 0xa5 0x38 0xbf 0x40 0xa3 0x9e 0x81 0xf3 0xd7 0xfb
0x7c 0xe3 0x39 0x82 0x9b 0x2f 0xff 0x87 0x34 0x8e 0x43 0x44 0xc4 0xde 0xe9 0xcb
0x54 0x7b 0x94 0x32 0xa6 0xc2 0x23 0x3d 0xee 0x4c 0x95 0x0b 0x42 0xfa 0xc3 0x4e
0x08 0x2e 0xa1 0x66 0x28 0xd9 0x24 0xb2 0x76 0x5b 0xa2 0x49 0x6d 0x8b 0xd1 0x25
0x72 0xf8 0xf6 0x64 0x86 0x68 0x98 0x16 0xd4 0xa4 0x5c 0xcc 0x5d 0x65 0xb6 0x92
0x6c 0x70 0x48 0x50 0xfd 0xed 0xb9 0xda 0x5e 0x15 0x46 0x57 0xa7 0x8d 0x9d 0x84
0x90 0xd8 0xab 0x00 0x8c 0xbc 0xd3 0x0a 0xf7 0xe4 0x58 0x05 0xb8 0xb3 0x45 0x06
0xd0 0x2c 0x1e 0x8f 0xca 0x3f 0x0f 0x02 0xc1 0xaf 0xbd 0x03 0x01 0x13 0x8a 0x6b
0x3a 0x91 0x11 0x41 0x4f 0x67 0xdc 0xea 0x97 0xf2 0xcf 0xce 0xf0 0xb4 0xe6 0x73
0x96 0xac 0x74 0x22 0xe7 0xad 0x35 0x85 0xe2 0xf9 0x37 0xe8 0x1c 0x75 0xdf 0x6e
0x47 0xf1 0x1a 0x71 0x1d 0x29 0xc5 0x89 0x6f 0xb7 0x62 0x0e 0xaa 0x18 0xbe 0x1b
0xfc 0x56 0x3e 0x4b 0xc6 0xd2 0x79 0x20 0x9a 0xdb 0xc0 0xfe 0x78 0xcd 0x5a 0xf4
0x1f 0xdd 0xa8 0x33 0x88 0x07 0xc7 0x31 0xb1 0x12 0x10 0x59 0x27 0x80 0xec 0x5f
0x60 0x51 0x7f 0xa9 0x19 0xb5 0x4a 0x0d 0x2d 0xe5 0x7a 0x9f 0x93 0xc9 0x9c 0xef
0xa0 0xe0 0x3b 0x4d 0xae 0x2a 0xf5 0xb0 0xc8 0xeb 0xbb 0x3c 0x83 0x53 0x99 0x61
0x17 0x2b 0x04 0x7e 0xba 0x77 0xd6 0x26 0xe1 0x69 0x14 0x63 0x55 0x21 0x0c 0x7d
}
}
# aes::Init --
#
# Initialise our AES state and calculate the key schedule. An initialization
# vector is maintained in the state for modes that require one. The key must
# be binary data of the correct size and the IV must be 16 bytes.
#
# Nk: columns of the key-array
# Nr: number of rounds (depends on key-length)
# Nb: columns of the text-block, is always 4 in AES
#
proc ::aes::Init {mode key iv} {
switch -exact -- $mode {
ecb - cbc { }
cfb - ofb {
return -code error "$mode mode not implemented"
}
default {
return -code error "invalid mode \"$mode\":\
must be one of ecb or cbc."
}
}
set size [expr {[string length $key] << 3}]
switch -exact -- $size {
128 {set Nk 4; set Nr 10; set Nb 4}
192 {set Nk 6; set Nr 12; set Nb 4}
256 {set Nk 8; set Nr 14; set Nb 4}
default {
return -code error "invalid key size \"$size\":\
must be one of 128, 192 or 256."
}
}
variable uid
set Key [namespace current]::[incr uid]
upvar #0 $Key state
if {[binary scan $iv Iu4 state(I)] != 1} {
return -code error "invalid initialization vector: must be 16 bytes"
}
array set state [list M $mode K $key Nk $Nk Nr $Nr Nb $Nb W {}]
ExpandKey $Key
return $Key
}
# aes::Reset --
#
# Reset the initialization vector for the specified key. This permits the
# key to be reused for encryption or decryption without the expense of
# re-calculating the key schedule.
#
proc ::aes::Reset {Key iv} {
upvar #0 $Key state
if {[binary scan $iv Iu4 state(I)] != 1} {
return -code error "invalid initialization vector: must be 16 bytes"
}
return
}
# aes::Final --
#
# Clean up the key state
#
proc ::aes::Final {Key} {
# FRINK: nocheck
unset $Key
}
# -------------------------------------------------------------------------
# 5.1 Cipher: Encipher a single block of 128 bits.
proc ::aes::EncryptBlock {Key block} {
upvar #0 $Key state
if {[binary scan $block Iu4 data] != 1} {
return -code error "invalid block size: blocks must be 16 bytes"
}
if {$state(M) eq {cbc}} {
# Loop unrolled.
lassign $data d0 d1 d2 d3
lassign $state(I) s0 s1 s2 s3
set data [list \
[expr {$d0 ^ $s0}] \
[expr {$d1 ^ $s1}] \
[expr {$d2 ^ $s2}] \
[expr {$d3 ^ $s3}] ]
}
set data [AddRoundKey $Key 0 $data]
for {set n 1} {$n < $state(Nr)} {incr n} {
set data [AddRoundKey $Key $n [MixColumns [ShiftRows [SubBytes $data]]]]
}
set data [AddRoundKey $Key $n [ShiftRows [SubBytes $data]]]
# Bug 2993029:
# Force all elements of data into the 32bit range.
# Loop unrolled
set res [Clamp32 $data]
set state(I) $res
binary format Iu4 $res
}
# 5.3: Inverse Cipher: Decipher a single 128 bit block.
proc ::aes::DecryptBlock {Key block} {
upvar #0 $Key state
if {[binary scan $block Iu4 data] != 1} {
return -code error "invalid block size: block must be 16 bytes"
}
set iv $data
set n $state(Nr)
set data [AddRoundKey $Key $state(Nr) $data]
for {incr n -1} {$n > 0} {incr n -1} {
set data [InvMixColumns [AddRoundKey $Key $n [InvSubBytes [InvShiftRows $data]]]]
}
set data [AddRoundKey $Key $n [InvSubBytes [InvShiftRows $data]]]
if {$state(M) eq {cbc}} {
lassign $data d0 d1 d2 d3
lassign $state(I) s0 s1 s2 s3
set data [list \
[expr {($d0 ^ $s0) & 0xffffffff}] \
[expr {($d1 ^ $s1) & 0xffffffff}] \
[expr {($d2 ^ $s2) & 0xffffffff}] \
[expr {($d3 ^ $s3) & 0xffffffff}] ]
} else {
# Bug 2993029:
# The integrated clamping we see above only happens for CBC mode.
set data [Clamp32 $data]
}
set state(I) $iv
binary format Iu4 $data
}
proc ::aes::Clamp32 {data} {
# Force all elements into 32bit range.
lassign $data d0 d1 d2 d3
list \
[expr {$d0 & 0xffffffff}] \
[expr {$d1 & 0xffffffff}] \
[expr {$d2 & 0xffffffff}] \
[expr {$d3 & 0xffffffff}]
}
# 5.2: KeyExpansion
proc ::aes::ExpandKey {Key} {
upvar #0 $Key state
set Rcon [list 0x00000000 0x01000000 0x02000000 0x04000000 0x08000000 \
0x10000000 0x20000000 0x40000000 0x80000000 0x1b000000 \
0x36000000 0x6c000000 0xd8000000 0xab000000 0x4d000000]
# Split the key into Nk big-endian words
binary scan $state(K) I* W
set max [expr {$state(Nb) * ($state(Nr) + 1)}]
set i $state(Nk)
set h [expr {$i - 1}]
set j 0
for {} {$i < $max} {incr i; incr h; incr j} {
set temp [lindex $W $h]
if {($i % $state(Nk)) == 0} {
set sub [SubWord [RotWord $temp]]
set rc [lindex $Rcon [expr {$i/$state(Nk)}]]
set temp [expr {$sub ^ $rc}]
} elseif {$state(Nk) > 6 && ($i % $state(Nk)) == 4} {
set temp [SubWord $temp]
}
lappend W [expr {[lindex $W $j] ^ $temp}]
}
set state(W) $W
}
# 5.2: Key Expansion: Apply S-box to each byte in the 32 bit word
proc ::aes::SubWord {w} {
variable sbox
set s3 [lindex $sbox [expr {($w >> 24) & 255}]]
set s2 [lindex $sbox [expr {($w >> 16) & 255}]]
set s1 [lindex $sbox [expr {($w >> 8 ) & 255}]]
set s0 [lindex $sbox [expr { $w & 255}]]
return [expr {($s3 << 24) | ($s2 << 16) | ($s1 << 8) | $s0}]
}
proc ::aes::InvSubWord {w} {
variable xobs
set s3 [lindex $xobs [expr {($w >> 24) & 255}]]
set s2 [lindex $xobs [expr {($w >> 16) & 255}]]
set s1 [lindex $xobs [expr {($w >> 8 ) & 255}]]
set s0 [lindex $xobs [expr { $w & 255}]]
return [expr {($s3 << 24) | ($s2 << 16) | ($s1 << 8) | $s0}]
}
# 5.2: Key Expansion: Rotate a 32bit word by 8 bits
proc ::aes::RotWord {w} {
return [expr {(($w << 8) | (($w >> 24) & 0xff)) & 0xffffffff}]
}
# 5.1.1: SubBytes() Transformation
proc ::aes::SubBytes {words} {
lassign $words w0 w1 w2 w3
list [SubWord $w0] [SubWord $w1] [SubWord $w2] [SubWord $w3]
}
# 5.3.2: InvSubBytes() Transformation
proc ::aes::InvSubBytes {words} {
lassign $words w0 w1 w2 w3
list [InvSubWord $w0] [InvSubWord $w1] [InvSubWord $w2] [InvSubWord $w3]
}
# 5.1.2: ShiftRows() Transformation
proc ::aes::ShiftRows {words} {
for {set n0 0} {$n0 < 4} {incr n0} {
set n1 [expr {($n0 + 1) % 4}]
set n2 [expr {($n0 + 2) % 4}]
set n3 [expr {($n0 + 3) % 4}]
lappend r [expr {( [lindex $words $n0] & 0xff000000)
| ([lindex $words $n1] & 0x00ff0000)
| ([lindex $words $n2] & 0x0000ff00)
| ([lindex $words $n3] & 0x000000ff)
}]
}
return $r
}
# 5.3.1: InvShiftRows() Transformation
proc ::aes::InvShiftRows {words} {
for {set n0 0} {$n0 < 4} {incr n0} {
set n1 [expr {($n0 + 1) % 4}]
set n2 [expr {($n0 + 2) % 4}]
set n3 [expr {($n0 + 3) % 4}]
lappend r [expr {( [lindex $words $n0] & 0xff000000)
| ([lindex $words $n3] & 0x00ff0000)
| ([lindex $words $n2] & 0x0000ff00)
| ([lindex $words $n1] & 0x000000ff)
}]
}
return $r
}
# 5.1.3: MixColumns() Transformation
proc ::aes::MixColumns {words} {
set r {}
foreach w $words {
set r0 [expr {(($w >> 24) & 255)}]
set r1 [expr {(($w >> 16) & 255)}]
set r2 [expr {(($w >> 8 ) & 255)}]
set r3 [expr {( $w & 255)}]
set s0 [expr {[GFMult2 $r0] ^ [GFMult3 $r1] ^ $r2 ^ $r3}]
set s1 [expr {$r0 ^ [GFMult2 $r1] ^ [GFMult3 $r2] ^ $r3}]
set s2 [expr {$r0 ^ $r1 ^ [GFMult2 $r2] ^ [GFMult3 $r3]}]
set s3 [expr {[GFMult3 $r0] ^ $r1 ^ $r2 ^ [GFMult2 $r3]}]
lappend r [expr {($s0 << 24) | ($s1 << 16) | ($s2 << 8) | $s3}]
}
return $r
}
# 5.3.3: InvMixColumns() Transformation
proc ::aes::InvMixColumns {words} {
set r {}
foreach w $words {
set r0 [expr {(($w >> 24) & 255)}]
set r1 [expr {(($w >> 16) & 255)}]
set r2 [expr {(($w >> 8 ) & 255)}]
set r3 [expr {( $w & 255)}]
set s0 [expr {[GFMult0e $r0] ^ [GFMult0b $r1] ^ [GFMult0d $r2] ^ [GFMult09 $r3]}]
set s1 [expr {[GFMult09 $r0] ^ [GFMult0e $r1] ^ [GFMult0b $r2] ^ [GFMult0d $r3]}]
set s2 [expr {[GFMult0d $r0] ^ [GFMult09 $r1] ^ [GFMult0e $r2] ^ [GFMult0b $r3]}]
set s3 [expr {[GFMult0b $r0] ^ [GFMult0d $r1] ^ [GFMult09 $r2] ^ [GFMult0e $r3]}]
lappend r [expr {($s0 << 24) | ($s1 << 16) | ($s2 << 8) | $s3}]
}
return $r
}
# 5.1.4: AddRoundKey() Transformation
proc ::aes::AddRoundKey {Key round words} {
upvar #0 $Key state
set r {}
set n [expr {$round * $state(Nb)}]
foreach w $words {
lappend r [expr {$w ^ [lindex $state(W) $n]}]
incr n
}
return $r
}
# -------------------------------------------------------------------------
# ::aes::GFMult*
#
# some needed functions for multiplication in a Galois-field
#
proc ::aes::GFMult2 {number} {
# this is a tabular representation of xtime (multiplication by 2)
# it is used instead of calculation to prevent timing attacks
set xtime {
0x00 0x02 0x04 0x06 0x08 0x0a 0x0c 0x0e 0x10 0x12 0x14 0x16 0x18 0x1a 0x1c 0x1e
0x20 0x22 0x24 0x26 0x28 0x2a 0x2c 0x2e 0x30 0x32 0x34 0x36 0x38 0x3a 0x3c 0x3e
0x40 0x42 0x44 0x46 0x48 0x4a 0x4c 0x4e 0x50 0x52 0x54 0x56 0x58 0x5a 0x5c 0x5e
0x60 0x62 0x64 0x66 0x68 0x6a 0x6c 0x6e 0x70 0x72 0x74 0x76 0x78 0x7a 0x7c 0x7e
0x80 0x82 0x84 0x86 0x88 0x8a 0x8c 0x8e 0x90 0x92 0x94 0x96 0x98 0x9a 0x9c 0x9e
0xa0 0xa2 0xa4 0xa6 0xa8 0xaa 0xac 0xae 0xb0 0xb2 0xb4 0xb6 0xb8 0xba 0xbc 0xbe
0xc0 0xc2 0xc4 0xc6 0xc8 0xca 0xcc 0xce 0xd0 0xd2 0xd4 0xd6 0xd8 0xda 0xdc 0xde
0xe0 0xe2 0xe4 0xe6 0xe8 0xea 0xec 0xee 0xf0 0xf2 0xf4 0xf6 0xf8 0xfa 0xfc 0xfe
0x1b 0x19 0x1f 0x1d 0x13 0x11 0x17 0x15 0x0b 0x09 0x0f 0x0d 0x03 0x01 0x07 0x05
0x3b 0x39 0x3f 0x3d 0x33 0x31 0x37 0x35 0x2b 0x29 0x2f 0x2d 0x23 0x21 0x27 0x25
0x5b 0x59 0x5f 0x5d 0x53 0x51 0x57 0x55 0x4b 0x49 0x4f 0x4d 0x43 0x41 0x47 0x45
0x7b 0x79 0x7f 0x7d 0x73 0x71 0x77 0x75 0x6b 0x69 0x6f 0x6d 0x63 0x61 0x67 0x65
0x9b 0x99 0x9f 0x9d 0x93 0x91 0x97 0x95 0x8b 0x89 0x8f 0x8d 0x83 0x81 0x87 0x85
0xbb 0xb9 0xbf 0xbd 0xb3 0xb1 0xb7 0xb5 0xab 0xa9 0xaf 0xad 0xa3 0xa1 0xa7 0xa5
0xdb 0xd9 0xdf 0xdd 0xd3 0xd1 0xd7 0xd5 0xcb 0xc9 0xcf 0xcd 0xc3 0xc1 0xc7 0xc5
0xfb 0xf9 0xff 0xfd 0xf3 0xf1 0xf7 0xf5 0xeb 0xe9 0xef 0xed 0xe3 0xe1 0xe7 0xe5
}
lindex $xtime $number
}
proc ::aes::GFMult3 {number} {
# multliply by 2 (via GFMult2) and add the number again on the result (via XOR)
expr {$number ^ [GFMult2 $number]}
}
proc ::aes::GFMult09 {number} {
# 09 is: (02*02*02) + 01
expr {[GFMult2 [GFMult2 [GFMult2 $number]]] ^ $number}
}
proc ::aes::GFMult0b {number} {
# 0b is: (02*02*02) + 02 + 01
#return [expr [GFMult2 [GFMult2 [GFMult2 $number]]] ^ [GFMult2 $number] ^ $number]
#set g0 [GFMult2 $number]
expr {[GFMult09 $number] ^ [GFMult2 $number]}
}
proc ::aes::GFMult0d {number} {
# 0d is: (02*02*02) + (02*02) + 01
set temp [GFMult2 [GFMult2 $number]]
expr {[GFMult2 $temp] ^ ($temp ^ $number)}
}
proc ::aes::GFMult0e {number} {
# 0e is: (02*02*02) + (02*02) + 02
set temp [GFMult2 [GFMult2 $number]]
expr {[GFMult2 $temp] ^ ($temp ^ [GFMult2 $number])}
}
# -------------------------------------------------------------------------
# aes::Encrypt --
#
# Encrypt a blocks of plain text and returns blocks of cipher text.
# The input data must be a multiple of the block size (16).
#
proc ::aes::Encrypt {Key data} {
set len [string length $data]
if {($len % 16) != 0} {
return -code error "invalid block size: AES requires 16 byte blocks"
}
set result {}
for {set i 0} {$i < $len} {incr i 1} {
set block [string range $data $i [incr i 15]]
append result [EncryptBlock $Key $block]
}
return $result
}
# aes::Decrypt --
#
# Decrypt blocks of cipher text and returns blocks of plain text.
# The input data must be a multiple of the block size (16).
#
proc ::aes::Decrypt {Key data} {
set len [string length $data]
if {($len % 16) != 0} {
return -code error "invalid block size: AES requires 16 byte blocks"
}
set result {}
for {set i 0} {$i < $len} {incr i 1} {
set block [string range $data $i [incr i 15]]
append result [DecryptBlock $Key $block]
}
return $result
}
# -------------------------------------------------------------------------
# chan event handler for chunked file reading.
#
proc ::aes::Chunk {Key in {out {}} {chunksize 4096}} {
upvar #0 $Key state
#puts ||CHUNK.X||i=$in|o=$out|c=$chunksize|eof=[eof $in]
if {[eof $in]} {
chan event $in readable {}
set state(reading) 0
}
set data [read $in $chunksize]
#puts ||CHUNK.R||i=$in|o=$out|c=$chunksize|eof=[eof $in]||[string length $data]||$data||
# Do nothing when data was read at all.
if {$data eq {}} return
if {[eof $in]} {
#puts CHUNK.Z
set data [Pad $data 16]
}
#puts ||CHUNK.P||i=$in|o=$out|c=$chunksize|eof=[eof $in]||[string length $data]||$data||
if {$out eq {}} {
append state(output) [$state(cmd) $Key $data]
} else {
puts -nonewline $out [$state(cmd) $Key $data]
}
}
proc ::aes::SetOneOf {lst item} {
set ndx [lsearch -glob $lst "${item}*"]
if {$ndx == -1} {
set err [join $lst ", "]
return -code error "invalid mode \"$item\": must be one of $err"
}
lindex $lst $ndx
}
proc ::aes::CheckSize {what size thing} {
if {[string length $thing] != $size} {
return -code error "invalid value for $what: must be $size bytes long"
}
return $thing
}
proc ::aes::Pad {data blocksize {fill \0}} {
set len [string length $data]
if {$len == 0} {
set data [string repeat $fill $blocksize]
} elseif {($len % $blocksize) != 0} {
set pad [expr {$blocksize - ($len % $blocksize)}]
append data [string repeat $fill $pad]
}
return $data
}
proc ::aes::Pop {varname {nth 0}} {
upvar 1 $varname args
set r [lindex $args $nth]
set args [lreplace $args $nth $nth]
return $r
}
proc ::aes::aes {args} {
array set opts {-dir encrypt -mode cbc -key {} -in {} -out {} -chunksize 4096 -hex 0}
set opts(-iv) [string repeat \0 16]
set modes {ecb cbc}
set dirs {encrypt decrypt}
while {([llength $args] > 1) && [string match -* [set option [lindex $args 0]]]} {
switch -exact -- $option {
-mode { set opts(-mode) [SetOneOf $modes [Pop args 1]] }
-dir { set opts(-dir) [SetOneOf $dirs [Pop args 1]] }
-iv { set opts(-iv) [CheckSize -iv 16 [Pop args 1]] }
-key { set opts(-key) [Pop args 1] }
-in { set opts(-in) [Pop args 1] }
-out { set opts(-out) [Pop args 1] }
-chunksize { set opts(-chunksize) [Pop args 1] }
-hex { set opts(-hex) 1 }
-- { Pop args ; break }
default {
set err [join [lsort [array names opts]] ", "]
return -code error "bad option \"$option\":\
must be one of $err"
}
}
Pop args
}
if {$opts(-key) eq {}} {
return -code error "no key provided: the -key option is required"
}
set r {}
if {$opts(-in) eq {}} {
if {[llength $args] != 1} {
return -code error "wrong \# args:\
should be \"aes ?options...? -key keydata plaintext\""
}
set data [Pad [lindex $args 0] 16]
set Key [Init $opts(-mode) $opts(-key) $opts(-iv)]
if {[string equal $opts(-dir) "encrypt"]} {
set r [Encrypt $Key $data]
} else {
set r [Decrypt $Key $data]
}
if {$opts(-out) ne {}} {
puts -nonewline $opts(-out) $r
set r {}
}
Final $Key
} else {
if {[llength $args] != 0} {
return -code error "wrong \# args:\
should be \"aes ?options...? -key keydata -in channel\""
}
set Key [Init $opts(-mode) $opts(-key) $opts(-iv)]
set readcmd [list [namespace origin Chunk] \
$Key $opts(-in) $opts(-out) \
$opts(-chunksize)]
upvar 1 $Key state
set state(reading) 1
if {[string equal $opts(-dir) "encrypt"]} {
set state(cmd) Encrypt
} else {
set state(cmd) Decrypt
}
set state(output) ""
chan event $opts(-in) readable $readcmd
if {[info commands ::tkwait] != {}} {
tkwait variable [subst $Key](reading)
} else {
vwait [subst $Key](reading)
}
if {$opts(-out) == {}} {
set r $state(output)
}
Final $Key
}
if {$opts(-hex)} {
binary scan $r H* r
}
return $r
}
# -------------------------------------------------------------------------
package provide aes 1.2.2
# -------------------------------------------------------------------------
# Local variables:
# mode: tcl
# indent-tabs-mode: nil
# End:

5
src/vendorlib_tcl9/tcllib2.0/aes/pkgIndex.tcl

@ -0,0 +1,5 @@
if {![package vsatisfies [package provide Tcl] 8.5 9]} {
# PRAGMA: returnok
return
}
package ifneeded aes 1.2.2 [list source [file join $dir aes.tcl]]

1960
src/vendorlib_tcl9/tcllib2.0/amazon-s3/S3.tcl

File diff suppressed because it is too large Load Diff

9
src/vendorlib_tcl9/tcllib2.0/amazon-s3/pkgIndex.tcl

@ -0,0 +1,9 @@
# pkgIndex.tcl --
# Copyright (c) 2006 Darren New
# This is for the Amazon S3 web service packages.
if {![package vsatisfies [package provide Tcl] 8.5 9]} {return}
package ifneeded xsxp 1.1 [list source [file join $dir xsxp.tcl]]
package ifneeded S3 1.0.5 [list source [file join $dir S3.tcl]]

254
src/vendorlib_tcl9/tcllib2.0/amazon-s3/xsxp.tcl

@ -0,0 +1,254 @@
# xsxp.tcl --
#
###Abstract
# Extremely Simple XML Parser
#
# This is pretty lame, but I needed something like this for S3,
# and at the time, TclDOM would not work with the new 8.5 Tcl
# due to version number problems.
#
# In addition, this is a pure-value implementation. There is no
# garbage to clean up in the event of a thrown error, for example.
# This simplifies the code for sufficiently small XML documents,
# which is what Amazon's S3 guarantees.
#
###Copyright
# Copyright (c) 2006 Darren New.
# All Rights Reserved.
# NO WARRANTIES OF ANY TYPE ARE PROVIDED.
# COPYING OR USE INDEMNIFIES THE AUTHOR IN ALL WAYS.
# See the license terms in LICENSE.txt
#
###Revision String
# SCCS: %Z% %M% %I% %E% %U%
# xsxp::parse $xml
# Returns a parsed XML, or PXML. A pxml is a list.
# The first element is the name of the tag.
# The second element is a list of name/value pairs of the
# associated attribues, if any.
# The third thru final values are recursively PXML values.
# If the first element (element zero, that is) is "%PCDATA",
# then the attributes will be emtpy and the third element
# will be the text of the element.
# xsxp::fetch $pxml $path ?$part?
# $pxml is a parsed XML, as returned from xsxp::parse.
# $path is a list of elements. Each element is the name of
# a child to look up, optionally followed by a hash ("#")
# and a string of digits. An emtpy list or an initial empty
# element selects $pxml. If no hash sign is present, the
# behavior is as if "#0" had been appended to that element.
# An element of $path scans the children at the indicated
# level for the n'th instance of a child whose tag matches
# the part of the element before the hash sign. If an element
# is simply "#" followed by digits, that indexed child is
# selected, regardless of the tags in the children. So
# an element of #3 will always select the fourth child
# of the node under consideration.
# $part defaults to %ALL. It can be one of the following:
# %ALL - returns the entire selected element.
# %TAGNAME - returns lindex 0 of the selected element.
# %ATTRIBUTES - returns lindex 1 of the selected element.
# %CHILDREN - returns lrange 2 through end of the selected element,
# resulting in a list of elements being returned.
# %PCDATA - returns a concatenation of all the bodies of
# direct children of this node whose tag is %PCDATA.
# Throws an error if no such children are found. That
# is, part=%PCDATA means return the textual content found
# in that node but not its children nodes.
# %PCDATA? - like %PCDATA, but returns an empty string if
# no PCDATA is found.
# xsxp::fetchall $pxml_list $path ?$part?
# Iterates over each PXML in $pxml_list, selecting the indicated
# path from it, building a new list with the selected data, and
# returning that new list. For example, $pxml_list might be
# the %CHILDREN of a particular element, and the $path and $part
# might select from each child a sub-element in which we're interested.
# xsxp::only $pxml $tagname
# Iterates over the direct children of $pxml and selects only
# those with $tagname as their tag. Returns a list of matching
# elements.
# xsxp::prettyprint $pxml
# Outputs to stdout a nested-list notation of the parsed XML.
package require xml
package provide xsxp 1.1
namespace eval xsxp {
variable Stack
variable Cur
proc Characterdatacommand {characterdata} {
variable Cur
# puts "characterdatacommand $characterdata"
set x [list %PCDATA {} $characterdata]
lappend Cur $x
}
proc Elementstartcommand {name attlist args} {
# puts "elementstart $name {$attlist} $args"
variable Stack
variable Cur
lappend Stack $Cur
set Cur [list $name $attlist]
}
proc Elementendcommand {args} {
# puts "elementend $args"
variable Stack
variable Cur
set x [lindex $Stack end]
lappend x $Cur
set Cur $x
set Stack [lrange $Stack 0 end-1]
}
proc parse {xml} {
variable Cur
variable Stack
set Cur {}
set Stack {}
set parser [::xml::parser \
-characterdatacommand [namespace code Characterdatacommand] \
-elementstartcommand [namespace code Elementstartcommand] \
-elementendcommand [namespace code Elementendcommand] \
-ignorewhitespace 1 -final 1
]
$parser parse $xml
$parser free
# The following line is needed because the close of the last element
# appends the outermost element to the item on the top of the stack.
# Since there's nothing on the top of the stack at the close of the
# last element, we append the current element to an empty list.
# In essence, since we don't really have a terminating condition
# on the recursion, an empty stack is still treated like an element.
set Cur [lindex $Cur 0]
set Cur [Normalize $Cur]
return $Cur
}
proc Normalize {pxml} {
# This iterates over pxml recursively, finding entries that
# start with multiple %PCDATA elements, and coalesces their
# content, so if an element contains only %PCDATA, it is
# guaranteed to have only one child.
# Not really necessary, given definition of part=%PCDATA
# However, it makes pretty-prints nicer (for AWS at least)
# and ends up with smaller lists. I have no idea why they
# would put quotes around an MD5 hash in hex, tho.
set dupl 1
while {$dupl} {
set first [lindex $pxml 2]
set second [lindex $pxml 3]
if {[lindex $first 0] eq "%PCDATA" && [lindex $second 0] eq "%PCDATA"} {
set repl [list %PCDATA {} [lindex $first 2][lindex $second 2]]
set pxml [lreplace $pxml 2 3 $repl]
} else {
set dupl 0
for {set i 2} {$i < [llength $pxml]} {incr i} {
set pxml [lreplace $pxml $i $i [Normalize [lindex $pxml $i]]]
}
}
}
return $pxml
}
proc prettyprint {pxml {chan stdout} {indent 0}} {
puts -nonewline $chan [string repeat " " $indent]
if {[lindex $pxml 0] eq "%PCDATA"} {
puts $chan "%PCDATA: [lindex $pxml 2]"
return
}
puts -nonewline $chan "[lindex $pxml 0]"
foreach {name val} [lindex $pxml 1] {
puts -nonewline $chan " $name='$val'"
}
puts $chan ""
foreach node [lrange $pxml 2 end] {
prettyprint $node $chan [expr $indent+1]
}
}
proc fetch {pxml path {part %ALL}} {
set path [string trim $path /]
if {-1 != [string first / $path]} {
set path [split $path /]
}
foreach element $path {
if {$pxml eq ""} {return ""}
foreach {tag count} [split $element #] {
if {$tag ne ""} {
if {$count eq ""} {set count 0}
set pxml [lrange $pxml 2 end]
while {0 <= $count && 0 != [llength $pxml]} {
if {$tag eq [lindex $pxml 0 0]} {
incr count -1
if {$count < 0} {
# We're done. Go on to next element.
set pxml [lindex $pxml 0]
} else {
# Not done yet. Throw this away.
set pxml [lrange $pxml 1 end]
}
} else {
# Not what we want.
set pxml [lrange $pxml 1 end]
}
}
} else { # tag eq ""
if {$count eq ""} {
# Just select whole $pxml
} else {
set pxml [lindex $pxml [expr {2+$count}]]
}
}
break
} ; # done the foreach [split] loop
} ; # done all the elements.
if {$part eq "%ALL"} {return $pxml}
if {$part eq "%ATTRIBUTES"} {return [lindex $pxml 1]}
if {$part eq "%TAGNAME"} {return [lindex $pxml 0]}
if {$part eq "%CHILDREN"} {return [lrange $pxml 2 end]}
if {$part eq "%PCDATA" || $part eq "%PCDATA?"} {
set res "" ; set found 0
foreach elem [lrange $pxml 2 end] {
if {"%PCDATA" eq [lindex $elem 0]} {
append res [lindex $elem 2]
set found 1
}
}
if {$found || $part eq "%PCDATA?"} {
return $res
} else {
error "xsxp::fetch did not find requested PCDATA"
}
}
return $pxml ; # Don't know what he's after
}
proc only {pxml tag} {
set res {}
foreach element [lrange $pxml 2 end] {
if {[lindex $element 0] eq $tag} {
lappend res $element
}
}
return $res
}
proc fetchall {pxml_list path {part %ALL}} {
set res [list]
foreach pxml $pxml_list {
lappend res [fetch $pxml $path $part]
}
return $res
}
}
namespace export xsxp parse prettyprint fetch

1580
src/vendorlib_tcl9/tcllib2.0/asn/asn.tcl

File diff suppressed because it is too large Load Diff

4
src/vendorlib_tcl9/tcllib2.0/asn/pkgIndex.tcl

@ -0,0 +1,4 @@
# Tcl package index file, version 1.1
if {![package vsatisfies [package provide Tcl] 8.5 9]} {return}
package ifneeded asn 0.8.5 [list source [file join $dir asn.tcl]]

180
src/vendorlib_tcl9/tcllib2.0/base32/base32.tcl

@ -0,0 +1,180 @@
# -*- tcl -*-
# This code is hereby put into the public domain.
# ### ### ### ######### ######### #########
## Overview
# Base32 encoding and decoding of small strings.
#
# Management code for switching between Tcl and C accelerated
# implementations.
# @mdgen EXCLUDE: base32_c.tcl
package require Tcl 8.5 9
namespace eval ::base32 {}
# ### ### ### ######### ######### #########
## Management of base32 std implementations.
# ::base32::LoadAccelerator --
#
# Loads a named implementation, if possible.
#
# Arguments:
# key Name of the implementation to load.
#
# Results:
# A boolean flag. True if the implementation
# was successfully loaded; and False otherwise.
proc ::base32::LoadAccelerator {key} {
variable accel
set isok 0
switch -exact -- $key {
critcl {
# Critcl implementation of base32 requires Tcl 8.4.
if {![package vsatisfies [package provide Tcl] 8.4]} {return 0}
if {[catch {package require tcllibc}]} {return 0}
set isok [llength [info commands ::base32::critcl_encode]]
}
tcl {
variable selfdir
if {[catch {source [file join $selfdir base32_tcl.tcl]}]} {return 0}
set isok [llength [info commands ::base32::tcl_encode]]
}
default {
return -code error "invalid accelerator $key:\
must be one of [join [KnownImplementations] {, }]"
}
}
set accel($key) $isok
return $isok
}
# ::base32::SwitchTo --
#
# Activates a loaded named implementation.
#
# Arguments:
# key Name of the implementation to activate.
#
# Results:
# None.
proc ::base32::SwitchTo {key} {
variable accel
variable loaded
if {[string equal $key $loaded]} {
# No change, nothing to do.
return
} elseif {![string equal $key ""]} {
# Validate the target implementation of the switch.
if {![info exists accel($key)]} {
return -code error "Unable to activate unknown implementation \"$key\""
} elseif {![info exists accel($key)] || !$accel($key)} {
return -code error "Unable to activate missing implementation \"$key\""
}
}
# Deactivate the previous implementation, if there was any.
if {![string equal $loaded ""]} {
foreach c {encode decode} {
rename ::base32::$c ::base32::${loaded}_$c
}
}
# Activate the new implementation, if there is any.
if {![string equal $key ""]} {
foreach c {encode decode} {
rename ::base32::${key}_$c ::base32::$c
}
}
# Remember the active implementation, for deactivation by future
# switches.
set loaded $key
return
}
# ::base32::Implementations --
#
# Determines which implementations are
# present, i.e. loaded.
#
# Arguments:
# None.
#
# Results:
# A list of implementation keys.
proc ::base32::Implementations {} {
variable accel
set res {}
foreach n [array names accel] {
if {!$accel($n)} continue
lappend res $n
}
return $res
}
# ::base32::KnownImplementations --
#
# Determines which implementations are known
# as possible implementations.
#
# Arguments:
# None.
#
# Results:
# A list of implementation keys. In the order
# of preference, most prefered first.
proc ::base32::KnownImplementations {} {
return {critcl tcl}
}
proc ::base32::Names {} {
return {
critcl {tcllibc based}
tcl {pure Tcl}
}
}
# ### ### ### ######### ######### #########
## Initialization: Data structures.
namespace eval ::base32 {
variable selfdir [file dirname [info script]]
variable loaded {}
variable accel
array set accel {tcl 0 critcl 0}
}
# ### ### ### ######### ######### #########
## Initialization: Choose an implementation,
## most prefered first. Loads only one of the
## possible implementations. And activates it.
namespace eval ::base32 {
variable e
foreach e [KnownImplementations] {
if {[LoadAccelerator $e]} {
SwitchTo $e
break
}
}
unset e
namespace export encode decode
}
# ### ### ### ######### ######### #########
## Ready
package provide base32 0.2

254
src/vendorlib_tcl9/tcllib2.0/base32/base32_c.tcl

@ -0,0 +1,254 @@
# base32c.tcl --
#
# Implementation of a base32 (std) de/encoder for Tcl.
#
# Public domain
#
# RCS: @(#) $Id: base32_c.tcl,v 1.3 2008/01/28 22:58:18 andreas_kupries Exp $
package require critcl
package require Tcl 8.5 9
namespace eval ::base32 {
# Supporting code for the main command.
catch {
#critcl::cheaders -g
#critcl::debug memory symbols
}
# Main commands, encoder & decoder
critcl::ccommand critcl_encode {dummy interp objc objv} {
/* Syntax -*- c -*-
* critcl_encode string
*/
unsigned char* buf;
Tcl_Size nbuf;
unsigned char* out;
unsigned char* at;
int nout;
/*
* The array used for encoding
*/ /* 123456789 123456789 123456789 12 */
static const char map[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
#define USAGEE "bitstring"
if (objc != 2) {
Tcl_WrongNumArgs (interp, 1, objv, USAGEE); /* OK tcl9 */
return TCL_ERROR;
}
buf = Tcl_GetBytesFromObj (interp, objv[1], &nbuf); /* OK tcl9 */
if (buf == NULL) return TCL_ERROR;
nout = ((nbuf+4)/5)*8;
out = (unsigned char*) Tcl_Alloc (nout*sizeof(char));
for (at = out; nbuf >= 5; nbuf -= 5, buf += 5) {
*(at++) = map [ (buf[0]>>3) ];
*(at++) = map [ 0x1f & ((buf[0]<<2) | (buf[1]>>6)) ];
*(at++) = map [ 0x1f & (buf[1]>>1) ];
*(at++) = map [ 0x1f & ((buf[1]<<4) | (buf[2]>>4)) ];
*(at++) = map [ 0x1f & ((buf[2]<<1) | (buf[3]>>7)) ];
*(at++) = map [ 0x1f & (buf[3]>>2) ];
*(at++) = map [ 0x1f & ((buf[3]<<3) | (buf[4]>>5)) ];
*(at++) = map [ 0x1f & (buf[4]) ];
}
if (nbuf > 0) {
/* Process partials at end. */
switch (nbuf) {
case 1:
/* |01234567| 2, padding 6
* xxxxx
* xxx 00
*/
*(at++) = map [ (buf[0]>>3) ];
*(at++) = map [ 0x1f & (buf[0]<<2) ];
*(at++) = '=';
*(at++) = '=';
*(at++) = '=';
*(at++) = '=';
*(at++) = '=';
*(at++) = '=';
break;
case 2: /* x3/=4 */
/* |01234567|01234567| 4, padding 4
* xxxxx
* xxx xx
* xxxxx
* x 0000
*/
*(at++) = map [ (buf[0]>>3) ];
*(at++) = map [ 0x1f & ((buf[0]<<2) | (buf[1]>>6)) ];
*(at++) = map [ 0x1f & (buf[1]>>1) ];
*(at++) = map [ 0x1f & (buf[1]<<4) ];
*(at++) = '=';
*(at++) = '=';
*(at++) = '=';
*(at++) = '=';
break;
case 3:
/* |01234567|01234567|01234567| 5, padding 3
* xxxxx
* xxx xx
* xxxxx
* x xxxx
* xxxx 0
*/
*(at++) = map [ (buf[0]>>3) ];
*(at++) = map [ 0x1f & ((buf[0]<<2) | (buf[1]>>6)) ];
*(at++) = map [ 0x1f & (buf[1]>>1) ];
*(at++) = map [ 0x1f & ((buf[1]<<4) | (buf[2]>>4)) ];
*(at++) = map [ 0x1f & (buf[2]<<1) ];
*(at++) = '=';
*(at++) = '=';
*(at++) = '=';
break;
case 4:
/* |01234567|01234567|01234567|012334567| 7, padding 1
* xxxxx
* xxx xx
* xxxxx
* x xxxx
* xxxx
* xxxxx
* xxxx 0
*/
*(at++) = map [ (buf[0]>>3) ];
*(at++) = map [ 0x1f & ((buf[0]<<2) | (buf[1]>>6)) ];
*(at++) = map [ 0x1f & (buf[1]>>1) ];
*(at++) = map [ 0x1f & ((buf[1]<<4) | (buf[2]>>4)) ];
*(at++) = map [ 0x1f & ((buf[2]<<1) | (buf[3]>>7)) ];
*(at++) = map [ 0x1f & (buf[3]>>2) ];
*(at++) = map [ 0x1f & (buf[3]<<3) ];
*(at++) = '=';
break;
}
}
Tcl_SetObjResult (interp, Tcl_NewStringObj ((char*)out, nout)); /* OK tcl9 */
Tcl_Free ((char*) out);
return TCL_OK;
}
critcl::ccommand critcl_decode {dummy interp objc objv} {
/* Syntax -*- c -*-
* critcl_decode estring
*/
unsigned char* buf;
Tcl_Size nbuf;
unsigned char* out;
unsigned char* at;
unsigned char x [8];
int nout;
int i, j, a, pad, nx;
/*
* An array for translating single base-32 characters into a value.
* Disallowed input characters have a value of 64. Upper and lower
* case is the same. Only 128 chars, as everything above char(127)
* is 64.
*/
static const char map [] = {
/* \00 */ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
/* DLE */ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
/* SPC */ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
/* '0' */ 64, 64, 26, 27, 28, 29, 30, 31, 64, 64, 64, 64, 64, 64, 64, 64,
/* '@' */ 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
/* 'P' */ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64,
/* '`' */ 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
/* 'p' */ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64
};
#define USAGED "estring"
if (objc != 2) {
Tcl_WrongNumArgs (interp, 1, objv, USAGED); /* OK tcl9 */
return TCL_ERROR;
}
buf = (unsigned char*) Tcl_GetStringFromObj (objv[1], &nbuf); /* OK tcl9 */
if (nbuf % 8) {
Tcl_SetObjResult (interp, Tcl_NewStringObj ("Length is not a multiple of 8", -1)); /* OK tcl9 */
return TCL_ERROR;
}
nout = (nbuf/8)*5 *TCL_UTF_MAX;
out = (unsigned char*) Tcl_Alloc (nout*sizeof(char));
#define HIGH(x) (((x) & 0x80) != 0)
#define BADC(x) ((x) == 64)
#define BADCHAR(a,j) (HIGH ((a)) || BADC (x [(j)] = map [(a)]))
for (pad = 0, i=0, at = out; i < nbuf; i += 8, buf += 8){
for (j=0; j < 8; j++){
a = buf [j];
if (a == '=') {
x[j] = 0;
pad++;
continue;
} else if (pad) {
char msg [120];
sprintf (msg,
"Invalid character at index %d: \"=\" (padding found in the middle of the input)",
j-1);
Tcl_Free ((char*) out);
Tcl_SetObjResult (interp, Tcl_NewStringObj (msg, -1)); /* OK tcl9 */
return TCL_ERROR;
}
if (BADCHAR (a,j)) {
char msg [100];
sprintf (msg,"Invalid character at index %d: \"%c\"",j,a);
Tcl_Free ((char*) out);
Tcl_SetObjResult (interp, Tcl_NewStringObj (msg, -1)); /* OK tcl9 */
return TCL_ERROR;
}
}
*(at++) = (x[0]<<3) | (x[1]>>2) ;
*(at++) = (x[1]<<6) | (x[2]<<1) | (x[3]>>4);
*(at++) = (x[3]<<4) | (x[4]>>1) ;
*(at++) = (x[4]<<7) | (x[5]<<2) | (x[6]>>3);
*(at++) = (x[6]<<5) | x[7] ;
}
if (pad) {
if (pad == 1) {
at -= 1;
} else if (pad == 3) {
at -= 2;
} else if (pad == 4) {
at -= 3;
} else if (pad == 6) {
at -= 4;
} else {
char msg [100];
sprintf (msg,"Invalid padding of length %d",pad);
Tcl_Free ((char*) out);
Tcl_SetObjResult (interp, Tcl_NewStringObj (msg, -1)); /* OK tcl9 */
return TCL_ERROR;
}
}
Tcl_SetObjResult (interp, Tcl_NewByteArrayObj (out, at-out)); /* OK tcl9 */
Tcl_Free ((char*) out);
return TCL_OK;
}
}
# ### ### ### ######### ######### #########
## Ready

73
src/vendorlib_tcl9/tcllib2.0/base32/base32_tcl.tcl

@ -0,0 +1,73 @@
# -*- tcl -*-
# This code is hereby put into the public domain.
# ### ### ### ######### ######### #########
## Overview
# Base32 encoding and decoding of small strings.
# ### ### ### ######### ######### #########
## Notes
# A binary string is split into groups of 5 bits (2^5 == 32), and each
# group is converted into a printable character as is specified in RFC
# 3548.
# ### ### ### ######### ######### #########
## Requisites
package require base32::core
namespace eval ::base32 {}
# ### ### ### ######### ######### #########
## API & Implementation
proc ::base32::tcl_encode {bitstring} {
variable forward
binary scan $bitstring B* bits
set len [string length $bits]
set rem [expr {$len % 5}]
if {$rem} {append bits =/$rem}
#puts "($bitstring) => <$bits>"
return [string map $forward $bits]
}
proc ::base32::tcl_decode {estring} {
variable backward
variable invalid
if {![core::valid $estring $invalid msg]} {
return -code error $msg
}
#puts "I<$estring>"
#puts "M<[string map $backward $estring]>"
return [binary format B* [string map $backward [string toupper $estring]]]
}
# ### ### ### ######### ######### #########
## Data structures
namespace eval ::base32 {
# Initialize the maps
variable forward
variable backward
variable invalid
core::define {
0 A 9 J 18 S 27 3
1 B 10 K 19 T 28 4
2 C 11 L 20 U 29 5
3 D 12 M 21 V 30 6
4 E 13 N 22 W 31 7
5 F 14 O 23 X
6 G 15 P 24 Y
7 H 16 Q 25 Z
8 I 17 R 26 2
} forward backward invalid ; # {}
# puts ///$forward///
# puts ///$backward///
}
# ### ### ### ######### ######### #########
## Ok

134
src/vendorlib_tcl9/tcllib2.0/base32/base32core.tcl

@ -0,0 +1,134 @@
# -*- tcl -*-
# This code is hereby put into the public domain.
# ### ### ### ######### ######### #########
#= Overview
# Fundamental handling of base32 conversion tables. Expansion of a
# basic mapping into a full mapping and its inverse mapping.
# ### ### ### ######### ######### #########
#= Requisites
namespace eval ::base32::core {}
# ### ### ### ######### ######### #########
#= API & Implementation
proc ::base32::core::define {map fv bv iv} {
variable bits
upvar 1 $fv forward $bv backward $iv invalid
# bytes - bits - padding - tail | bits - padding - tail
# 0 - 0 - "" - "xxxxxxxx" | 0 - "" - ""
# 1 - 8 - "======" - "xx======" | 3 - "======" - "x======"
# 2 - 16 - "====" - "xxxx====" | 1 - "====" - "x===="
# 3 - 24 - "===" - "xxxxx===" | 4 - "===" - "x==="
# 4 - 32 - "=" - "xxxxxxx=" | 2 - "=" - "x="
array set _ $bits
set invalid "\[^="
set forward {}
set btmp {}
foreach {code char} $map {
set b $_($code)
append invalid [string tolower $char][string toupper $char]
# 5 bit remainder
lappend forward $b $char
lappend btmp [list $char $b]
# 4 bit remainder
if {$code%2} continue
set b [string range $b 0 end-1]
lappend forward ${b}=/4 ${char}===
lappend btmp [list ${char}=== $b]
# 3 bit remainder
if {$code%4} continue
set b [string range $b 0 end-1]
lappend forward ${b}=/3 ${char}======
lappend btmp [list ${char}====== $b]
# 2 bit remainder
if {$code%8} continue
set b [string range $b 0 end-1]
lappend forward ${b}=/2 ${char}=
lappend btmp [list ${char}= $b]
# 1 bit remainder
if {$code%16} continue
set b [string range $b 0 end-1]
lappend forward ${b}=/1 ${char}====
lappend btmp [list ${char}==== $b]
}
set backward {}
foreach item [lsort -index 0 -decreasing $btmp] {
foreach {c b} $item break
lappend backward $c $b
}
append invalid "\]"
return
}
proc ::base32::core::valid {estring pattern mv} {
upvar 1 $mv message
if {[string length $estring] % 8} {
set message "Length is not a multiple of 8"
return 0
} elseif {[regexp -indices $pattern $estring where]} {
foreach {s e} $where break
set message "Invalid character at index $s: \"[string index $estring $s]\""
return 0
} elseif {[regexp {(=+)$} $estring -> pad]} {
set padlen [string length $pad]
if {
($padlen != 6) &&
($padlen != 4) &&
($padlen != 3) &&
($padlen != 1)
} {
set message "Invalid padding of length $padlen"
return 0
}
}
# Remove the brackets and ^= from the pattern, to construct the
# class of valid characters which must not follow the padding.
set badp "=\[[string range $pattern 3 end-1]\]"
if {[regexp -indices $badp $estring where]} {
foreach {s e} $where break
set message "Invalid character at index $s: \"[string index $estring $s]\" (padding found in the middle of the input)"
return 0
}
return 1
}
# ### ### ### ######### ######### #########
## Data structures
namespace eval ::base32::core {
namespace export define valid
variable bits {
0 00000 1 00001 2 00010 3 00011
4 00100 5 00101 6 00110 7 00111
8 01000 9 01001 10 01010 11 01011
12 01100 13 01101 14 01110 15 01111
16 10000 17 10001 18 10010 19 10011
20 10100 21 10101 22 10110 23 10111
24 11000 25 11001 26 11010 27 11011
28 11100 29 11101 30 11110 31 11111
}
}
# ### ### ### ######### ######### #########
#= Registration
package provide base32::core 0.2

182
src/vendorlib_tcl9/tcllib2.0/base32/base32hex.tcl

@ -0,0 +1,182 @@
# -*- tcl -*-
# This code is hereby put into the public domain.
# ### ### ### ######### ######### #########
## Overview
# Base32 encoding and decoding of small strings.
#
# Management code for switching between Tcl and C accelerated
# implementations.
#
# RCS: @(#) $Id: base32hex.tcl,v 1.3 2008/03/22 23:46:42 andreas_kupries Exp $
# @mdgen EXCLUDE: base32hex_c.tcl
package require Tcl 8.5 9
namespace eval ::base32::hex {}
# ### ### ### ######### ######### #########
## Management of base32 std implementations.
# ::base32::hex::LoadAccelerator --
#
# Loads a named implementation, if possible.
#
# Arguments:
# key Name of the implementation to load.
#
# Results:
# A boolean flag. True if the implementation
# was successfully loaded; and False otherwise.
proc ::base32::hex::LoadAccelerator {key} {
variable accel
set isok 0
switch -exact -- $key {
critcl {
# Critcl implementation of base32 requires Tcl 8.4.
if {![package vsatisfies [package provide Tcl] 8.4]} {return 0}
if {[catch {package require tcllibc}]} {return 0}
set isok [llength [info commands ::base32::hex::critcl_encode]]
}
tcl {
variable selfdir
if {[catch {source [file join $selfdir base32hex_tcl.tcl]}]} {return 0}
set isok [llength [info commands ::base32::hex::tcl_encode]]
}
default {
return -code error "invalid accelerator $key:\
must be one of [join [KnownImplementations] {, }]"
}
}
set accel($key) $isok
return $isok
}
# ::base32::hex::SwitchTo --
#
# Activates a loaded named implementation.
#
# Arguments:
# key Name of the implementation to activate.
#
# Results:
# None.
proc ::base32::hex::SwitchTo {key} {
variable accel
variable loaded
if {[string equal $key $loaded]} {
# No change, nothing to do.
return
} elseif {![string equal $key ""]} {
# Validate the target implementation of the switch.
if {![info exists accel($key)]} {
return -code error "Unable to activate unknown implementation \"$key\""
} elseif {![info exists accel($key)] || !$accel($key)} {
return -code error "Unable to activate missing implementation \"$key\""
}
}
# Deactivate the previous implementation, if there was any.
if {![string equal $loaded ""]} {
foreach c {encode decode} {
rename ::base32::hex::$c ::base32::hex::${loaded}_$c
}
}
# Activate the new implementation, if there is any.
if {![string equal $key ""]} {
foreach c {encode decode} {
rename ::base32::hex::${key}_$c ::base32::hex::$c
}
}
# Remember the active implementation, for deactivation by future
# switches.
set loaded $key
return
}
# ::base32::hex::Implementations --
#
# Determines which implementations are
# present, i.e. loaded.
#
# Arguments:
# None.
#
# Results:
# A list of implementation keys.
proc ::base32::hex::Implementations {} {
variable accel
set res {}
foreach n [array names accel] {
if {!$accel($n)} continue
lappend res $n
}
return $res
}
# ::base32::hex::KnownImplementations --
#
# Determines which implementations are known
# as possible implementations.
#
# Arguments:
# None.
#
# Results:
# A list of implementation keys. In the order
# of preference, most prefered first.
proc ::base32::hex::KnownImplementations {} {
return {critcl tcl}
}
proc ::base32::hex::Names {} {
return {
critcl {tcllibc based}
tcl {pure Tcl}
}
}
# ### ### ### ######### ######### #########
## Initialization: Data structures.
namespace eval ::base32::hex {
variable selfdir [file dirname [info script]]
variable loaded {}
variable accel
array set accel {tcl 0 critcl 0}
}
# ### ### ### ######### ######### #########
## Initialization: Choose an implementation,
## most prefered first. Loads only one of the
## possible implementations. And activates it.
namespace eval ::base32::hex {
variable e
foreach e [KnownImplementations] {
if {[LoadAccelerator $e]} {
SwitchTo $e
break
}
}
unset e
namespace export encode decode
}
# ### ### ### ######### ######### #########
## Ready
package provide base32::hex 0.2

254
src/vendorlib_tcl9/tcllib2.0/base32/base32hex_c.tcl

@ -0,0 +1,254 @@
# base32hexc.tcl --
#
# Implementation of a base32 (extended hex) de/encoder for Tcl.
#
# Public domain
#
# RCS: @(#) $Id: base32hex_c.tcl,v 1.3 2008/01/28 22:58:18 andreas_kupries Exp $
package require critcl
package require Tcl 8.5 9
namespace eval ::base32::hex {
# Supporting code for the main command.
catch {
#critcl::cheaders -g
#critcl::debug memory symbols
}
# Main commands, encoder & decoder
critcl::ccommand critcl_encode {dummy interp objc objv} {
/* Syntax -*- c -*-
* critcl_encode string
*/
unsigned char* buf;
Tcl_Size nbuf;
unsigned char* out;
unsigned char* at;
int nout;
/*
* The array used for encoding
*/ /* 123456789 123456789 123456789 12 */
static const char map[] = "0123456789ABCDEFGHIJKLMNOPQRSTUV";
#define USAGEE "bitstring"
if (objc != 2) {
Tcl_WrongNumArgs (interp, 1, objv, USAGEE); /* OK tcl9 */
return TCL_ERROR;
}
buf = Tcl_GetBytesFromObj (interp, objv[1], &nbuf); /* OK tcl9 */
if (buf == NULL) return TCL_ERROR;
nout = ((nbuf+4)/5)*8;
out = (unsigned char*) Tcl_Alloc (nout*sizeof(char));
for (at = out; nbuf >= 5; nbuf -= 5, buf += 5) {
*(at++) = map [ (buf[0]>>3) ];
*(at++) = map [ 0x1f & ((buf[0]<<2) | (buf[1]>>6)) ];
*(at++) = map [ 0x1f & (buf[1]>>1) ];
*(at++) = map [ 0x1f & ((buf[1]<<4) | (buf[2]>>4)) ];
*(at++) = map [ 0x1f & ((buf[2]<<1) | (buf[3]>>7)) ];
*(at++) = map [ 0x1f & (buf[3]>>2) ];
*(at++) = map [ 0x1f & ((buf[3]<<3) | (buf[4]>>5)) ];
*(at++) = map [ 0x1f & (buf[4]) ];
}
if (nbuf > 0) {
/* Process partials at end. */
switch (nbuf) {
case 1:
/* |01234567| 2, padding 6
* xxxxx
* xxx 00
*/
*(at++) = map [ (buf[0]>>3) ];
*(at++) = map [ 0x1f & (buf[0]<<2) ];
*(at++) = '=';
*(at++) = '=';
*(at++) = '=';
*(at++) = '=';
*(at++) = '=';
*(at++) = '=';
break;
case 2: /* x3/=4 */
/* |01234567|01234567| 4, padding 4
* xxxxx
* xxx xx
* xxxxx
* x 0000
*/
*(at++) = map [ (buf[0]>>3) ];
*(at++) = map [ 0x1f & ((buf[0]<<2) | (buf[1]>>6)) ];
*(at++) = map [ 0x1f & (buf[1]>>1) ];
*(at++) = map [ 0x1f & (buf[1]<<4) ];
*(at++) = '=';
*(at++) = '=';
*(at++) = '=';
*(at++) = '=';
break;
case 3:
/* |01234567|01234567|01234567| 5, padding 3
* xxxxx
* xxx xx
* xxxxx
* x xxxx
* xxxx 0
*/
*(at++) = map [ (buf[0]>>3) ];
*(at++) = map [ 0x1f & ((buf[0]<<2) | (buf[1]>>6)) ];
*(at++) = map [ 0x1f & (buf[1]>>1) ];
*(at++) = map [ 0x1f & ((buf[1]<<4) | (buf[2]>>4)) ];
*(at++) = map [ 0x1f & (buf[2]<<1) ];
*(at++) = '=';
*(at++) = '=';
*(at++) = '=';
break;
case 4:
/* |01234567|01234567|01234567|012334567| 7, padding 1
* xxxxx
* xxx xx
* xxxxx
* x xxxx
* xxxx
* xxxxx
* xxxx 0
*/
*(at++) = map [ (buf[0]>>3) ];
*(at++) = map [ 0x1f & ((buf[0]<<2) | (buf[1]>>6)) ];
*(at++) = map [ 0x1f & (buf[1]>>1) ];
*(at++) = map [ 0x1f & ((buf[1]<<4) | (buf[2]>>4)) ];
*(at++) = map [ 0x1f & ((buf[2]<<1) | (buf[3]>>7)) ];
*(at++) = map [ 0x1f & (buf[3]>>2) ];
*(at++) = map [ 0x1f & (buf[3]<<3) ];
*(at++) = '=';
break;
}
}
Tcl_SetObjResult (interp, Tcl_NewStringObj ((char*)out, nout)); /* OK tcl9 */
Tcl_Free ((char*) out);
return TCL_OK;
}
critcl::ccommand critcl_decode {dummy interp objc objv} {
/* Syntax -*- c -*-
* critcl_decode estring
*/
unsigned char* buf;
Tcl_Size nbuf;
unsigned char* out;
unsigned char* at;
unsigned char x [8];
int nout;
int i, j, a, pad, nx;
/*
* An array for translating single base-32 characters into a value.
* Disallowed input characters have a value of 64. Upper and lower
* case is the same. Only 128 chars, as everything above char(127)
* is 64.
*/
static const char map [] = {
/* \00 */ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
/* DLE */ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
/* SPC */ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
/* '0' */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 64, 64, 64, 64, 64, 64,
/* '@' */ 64, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
/* 'P' */ 25, 26, 27, 28, 29, 30, 31, 64, 64, 64, 64, 64, 64, 64, 64, 64,
/* '`' */ 64, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
/* 'p' */ 25, 26, 27, 28, 29, 30, 31, 64, 64, 64, 64, 64, 64, 64, 64, 64
};
#define USAGED "estring"
if (objc != 2) {
Tcl_WrongNumArgs (interp, 1, objv, USAGED); /* OK tcl9 */
return TCL_ERROR;
}
buf = (unsigned char*) Tcl_GetStringFromObj (objv[1], &nbuf); /* OK tcl9 */
if (nbuf % 8) {
Tcl_SetObjResult (interp, Tcl_NewStringObj ("Length is not a multiple of 8", -1)); /* OK tcl9 */
return TCL_ERROR;
}
nout = (nbuf/8)*5 *TCL_UTF_MAX;
out = (unsigned char*) Tcl_Alloc (nout*sizeof(char));
#define HIGH(x) (((x) & 0x80) != 0)
#define BADC(x) ((x) == 64)
#define BADCHAR(a,j) (HIGH ((a)) || BADC (x [(j)] = map [(a)]))
for (pad = 0, i=0, at = out; i < nbuf; i += 8, buf += 8){
for (j=0; j < 8; j++){
a = buf [j];
if (a == '=') {
x[j] = 0;
pad++;
continue;
} else if (pad) {
char msg [120];
sprintf (msg,
"Invalid character at index %d: \"=\" (padding found in the middle of the input)",
j-1);
Tcl_Free ((char*) out);
Tcl_SetObjResult (interp, Tcl_NewStringObj (msg, -1)); /* OK tcl9 */
return TCL_ERROR;
}
if (BADCHAR (a,j)) {
char msg [100];
sprintf (msg,"Invalid character at index %d: \"%c\"",j,a);
Tcl_Free ((char*) out);
Tcl_SetObjResult (interp, Tcl_NewStringObj (msg, -1)); /* OK tcl9 */
return TCL_ERROR;
}
}
*(at++) = (x[0]<<3) | (x[1]>>2) ;
*(at++) = (x[1]<<6) | (x[2]<<1) | (x[3]>>4);
*(at++) = (x[3]<<4) | (x[4]>>1) ;
*(at++) = (x[4]<<7) | (x[5]<<2) | (x[6]>>3);
*(at++) = (x[6]<<5) | x[7] ;
}
if (pad) {
if (pad == 1) {
at -= 1;
} else if (pad == 3) {
at -= 2;
} else if (pad == 4) {
at -= 3;
} else if (pad == 6) {
at -= 4;
} else {
char msg [100];
sprintf (msg,"Invalid padding of length %d",pad);
Tcl_Free ((char*) out);
Tcl_SetObjResult (interp, Tcl_NewStringObj (msg, -1)); /* OK tcl9 */
return TCL_ERROR;
}
}
Tcl_SetObjResult (interp, Tcl_NewByteArrayObj (out, at-out)); /* OK tcl9 */
Tcl_Free ((char*) out);
return TCL_OK;
}
}
# ### ### ### ######### ######### #########
## Ready

79
src/vendorlib_tcl9/tcllib2.0/base32/base32hex_tcl.tcl

@ -0,0 +1,79 @@
# -*- tcl -*-
# This code is hereby put into the public domain.
# ### ### ### ######### ######### #########
## Overview
# Base32 encoding and decoding of small strings.
# ### ### ### ######### ######### #########
## Notes
# A binary string is split into groups of 5 bits (2^5 == 32), and each
# group is converted into a printable character as is specified in RFC
# 3548 for the extended hex encoding.
# ### ### ### ######### ######### #########
## Requisites
package require base32::core
namespace eval ::base32::hex {}
# ### ### ### ######### ######### #########
## API & Implementation
proc ::base32::hex::tcl_encode {bitstring} {
variable forward
binary scan $bitstring B* bits
set len [string length $bits]
set rem [expr {$len % 5}]
if {$rem} {append bits =/$rem}
#puts "($bitstring) => <$bits>"
return [string map $forward $bits]
}
proc ::base32::hex::tcl_decode {estring} {
variable backward
variable invalid
if {![core::valid $estring $invalid msg]} {
return -code error $msg
}
#puts "I<$estring>"
#puts "M<[string map $backward $estring]>"
return [binary format B* [string map $backward [string toupper $estring]]]
}
# ### ### ### ######### ######### #########
## Data structures
namespace eval ::base32::hex {
namespace eval core {
namespace import ::base32::core::define
namespace import ::base32::core::valid
}
namespace export encode decode
# Initialize the maps
variable forward
variable backward
variable invalid
core::define {
0 0 9 9 18 I 27 R
1 1 10 A 19 J 28 S
2 2 11 B 20 K 29 T
3 3 12 C 21 L 30 U
4 4 13 D 22 M 31 V
5 5 14 E 23 N
6 6 15 F 24 O
7 7 16 G 25 P
8 8 17 H 26 Q
} forward backward invalid ; # {}
# puts ///$forward///
# puts ///$backward///
}
# ### ### ### ######### ######### #########
## Ok

4
src/vendorlib_tcl9/tcllib2.0/base32/pkgIndex.tcl

@ -0,0 +1,4 @@
if {![package vsatisfies [package provide Tcl] 8.5 9]} return
package ifneeded base32 0.2 [list source [file join $dir base32.tcl]]
package ifneeded base32::hex 0.2 [list source [file join $dir base32hex.tcl]]
package ifneeded base32::core 0.2 [list source [file join $dir base32core.tcl]]

270
src/vendorlib_tcl9/tcllib2.0/base64/ascii85.tcl

@ -0,0 +1,270 @@
# ascii85.tcl --
#
# Encode/Decode ascii85 for a string
#
# Copyright (c) Emiliano Gavilan
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
package require Tcl 8.5 9
namespace eval ascii85 {
namespace export encode encodefile decode
# default values for encode options
variable options
array set options [list -wrapchar \n -maxlen 76]
}
# ::ascii85::encode --
#
# Ascii85 encode a given string.
#
# Arguments:
# args ?-maxlen maxlen? ?-wrapchar wrapchar? string
#
# If maxlen is 0, the output is not wrapped.
#
# Results:
# A Ascii85 encoded version of $string, wrapped at $maxlen characters
# by $wrapchar.
proc ascii85::encode {args} {
variable options
set alen [llength $args]
if {$alen != 1 && $alen != 3 && $alen != 5} {
return -code error "wrong # args:\
should be \"[lindex [info level 0] 0]\
?-maxlen maxlen?\
?-wrapchar wrapchar? string\""
}
set data [lindex $args end]
array set opts [array get options]
array set opts [lrange $args 0 end-1]
foreach key [array names opts] {
if {[lsearch -exact [array names options] $key] == -1} {
return -code error "unknown option \"$key\":\
must be -maxlen or -wrapchar"
}
}
##nagelfar ignore
if {![string is integer -strict $opts(-maxlen)]
|| $opts(-maxlen) < 0} {
return -code error "expected positive integer but got\
\"$opts(-maxlen)\""
}
# perform this check early
if {[string length $data] == 0} {
return ""
}
# shorten the names, and normalize numeric values.
set ml [format %d $opts(-maxlen)]
set wc $opts(-wrapchar)
# if maxlen is zero, don't wrap the output
if {$ml == 0} {
set wc ""
}
set encoded {}
binary scan $data c* X
set len [llength $X]
set rest [expr {$len % 4}]
set lastidx [expr {$len - $rest - 1}]
foreach {b1 b2 b3 b4} [lrange $X 0 $lastidx] {
# calculate the 32 bit value
# this is an inlined version of the [encode4bytes] proc
# included here for performance reasons
set val [expr {
( (($b1 & 0xff) << 24)
|(($b2 & 0xff) << 16)
|(($b3 & 0xff) << 8)
| ($b4 & 0xff)
) & 0xffffffff }]
if {$val == 0} {
# four \0 bytes encodes as "z" instead of "!!!!!"
append current "z"
} else {
# no magic numbers here.
# 52200625 -> 85 ** 4
# 614125 -> 85 ** 3
# 7225 -> 85 ** 2
append current [binary format ccccc \
[expr { ( $val / 52200625) + 33 }] \
[expr { (($val % 52200625) / 614125) + 33 }] \
[expr { (($val % 614125) / 7225) + 33 }] \
[expr { (($val % 7225) / 85) + 33 }] \
[expr { ( $val % 85) + 33 }]]
}
if {[string length $current] >= $ml} {
append encoded [string range $current 0 [expr {$ml - 1}]] $wc
set current [string range $current $ml end]
}
}
if { $rest } {
# there are remaining bytes.
# pad with \0 and encode not using the "z" convention.
# finally, add ($rest + 1) chars.
set val 0
foreach {b1 b2 b3 b4} [pad [lrange $X [incr lastidx] end] 4 0] break
append current [string range [encode4bytes $b1 $b2 $b3 $b4] 0 $rest]
}
append encoded [regsub -all -- ".{$ml}" $current "&$wc"]
return $encoded
}
proc ascii85::encode4bytes {b1 b2 b3 b4} {
set val [expr {
( (($b1 & 0xff) << 24)
|(($b2 & 0xff) << 16)
|(($b3 & 0xff) << 8)
| ($b4 & 0xff)
) & 0xffffffff }]
return [binary format ccccc \
[expr { ( $val / 52200625) + 33 }] \
[expr { (($val % 52200625) / 614125) + 33 }] \
[expr { (($val % 614125) / 7225) + 33 }] \
[expr { (($val % 7225) / 85) + 33 }] \
[expr { ( $val % 85) + 33 }]]
}
# ::ascii85::encodefile --
#
# Ascii85 encode the contents of a file using default values
# for maxlen and wrapchar parameters.
#
# Arguments:
# fname The name of the file to encode.
#
# Results:
# An Ascii85 encoded version of the contents of the file.
# This is a convenience command
proc ascii85::encodefile {fname} {
set fd [open $fname rb]
return [encode [read $fd]][close $fd]
}
# ::ascii85::decode --
#
# Ascii85 decode a given string.
#
# Arguments:
# string The string to decode.
# Leading spaces and tabs are removed, along with trailing newlines
#
# Results:
# The decoded value.
proc ascii85::decode {data} {
# get rid of leading spaces/tabs and trailing newlines
set data [string map [list \n {} \t {} { } {}] $data]
set len [string length $data]
# perform this ckeck early
if {! $len} {
return ""
}
set decoded {}
set count 0
set group [list]
binary scan $data c* X
foreach char $X {
# we must check that every char is in the allowed range
if {$char < 33 || $char > 117 } {
# "z" is an exception
if {$char == 122} {
if {$count == 0} {
# if a "z" char appears at the beggining of a group,
# it decodes as four null bytes
append decoded \x00\x00\x00\x00
continue
} else {
# if not, is an error
return -code error \
"error decoding data: \"z\" char misplaced"
}
}
# char is not in range and not a "z" at the beggining of a group
return -code error \
"error decoding data: chars outside the allowed range"
}
lappend group $char
incr count
if {$count == 5} {
# this is an inlined version of the [decode5chars] proc
# included here for performance reasons
set val [expr {
([lindex $group 0] - 33) * wide(52200625) +
([lindex $group 1] - 33) * 614125 +
([lindex $group 2] - 33) * 7225 +
([lindex $group 3] - 33) * 85 +
([lindex $group 4] - 33) }]
if {$val > 0xffffffff} {
return -code error "error decoding data: decoded group overflow"
} else {
append decoded [binary format I $val]
incr count -5
set group [list]
}
}
}
set len [llength $group]
switch -- $len {
0 {
# all input has been consumed
# do nothing
}
1 {
# a single char is a condition error, there should be at least 2
return -code error \
"error decoding data: trailing char"
}
default {
# pad with "u"s, decode and add ($len - 1) bytes
append decoded [string range \
[decode5chars [pad $group 5 122]] \
0 \
[expr {$len - 2}]]
}
}
return $decoded
}
proc ascii85::decode5chars {group} {
set val [expr {
([lindex $group 0] - 33) * wide(52200625) +
([lindex $group 1] - 33) * 614125 +
([lindex $group 2] - 33) * 7225 +
([lindex $group 3] - 33) * 85 +
([lindex $group 4] - 33) }]
if {$val > 0xffffffff} {
return -code error "error decoding data: decoded group overflow"
}
return [binary format I $val]
}
proc ascii85::pad {chars len padchar} {
while {[llength $chars] < $len} {
lappend chars $padchar
}
return $chars
}
package provide ascii85 1.1.1

411
src/vendorlib_tcl9/tcllib2.0/base64/base64.tcl

@ -0,0 +1,411 @@
# base64.tcl --
#
# Encode/Decode base64 for a string
# Stephen Uhler / Brent Welch (c) 1997 Sun Microsystems
# The decoder was done for exmh by Chris Garrigues
#
# Copyright (c) 1998-2000 by Ajuba Solutions.
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
# Version 1.0 implemented Base64_Encode, Base64_Decode
# Version 2.0 uses the base64 namespace
# Version 2.1 fixes various decode bugs and adds options to encode
# Version 2.2 is much faster, Tcl8.0 compatible
# Version 2.2.1 bugfixes
# Version 2.2.2 bugfixes
# Version 2.3 bugfixes and extended to support Trf
# Version 2.4.x bugfixes
# @mdgen EXCLUDE: base64c.tcl
package require Tcl 8.5 9
namespace eval ::base64 {
namespace export encode decode
}
package provide base64 2.6.1
if {[package vsatisfies [package require Tcl] 8.6 9]} {
proc ::base64::encode {args} {
binary encode base64 -maxlen 76 {*}$args
}
proc ::base64::decode {string} {
# Tcllib is strict with respect to end of input, yet lax for
# invalid characters outside of that.
regsub -all -- {[^ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/]} $string {} string
binary decode base64 -strict $string
}
return
}
if {![catch {package require Trf 2.0}]} {
# Trf is available, so implement the functionality provided here
# in terms of calls to Trf for speed.
# ::base64::encode --
#
# Base64 encode a given string.
#
# Arguments:
# args ?-maxlen maxlen? ?-wrapchar wrapchar? string
#
# If maxlen is 0, the output is not wrapped.
#
# Results:
# A Base64 encoded version of $string, wrapped at $maxlen characters
# by $wrapchar.
proc ::base64::encode {args} {
# Set the default wrapchar and maximum line length to match
# the settings for MIME encoding (RFC 3548, RFC 2045). These
# are the settings used by Trf as well. Various RFCs allow for
# different wrapping characters and wraplengths, so these may
# be overridden by command line options.
set wrapchar "\n"
set maxlen 76
if { [llength $args] == 0 } {
error "wrong # args: should be \"[lindex [info level 0] 0]\
?-maxlen maxlen? ?-wrapchar wrapchar? string\""
}
set optionStrings [list "-maxlen" "-wrapchar"]
for {set i 0} {$i < [llength $args] - 1} {incr i} {
set arg [lindex $args $i]
set index [lsearch -glob $optionStrings "${arg}*"]
if { $index == -1 } {
error "unknown option \"$arg\": must be -maxlen or -wrapchar"
}
incr i
if { $i >= [llength $args] - 1 } {
error "value for \"$arg\" missing"
}
set val [lindex $args $i]
# The name of the variable to assign the value to is extracted
# from the list of known options, all of which have an
# associated variable of the same name as the option without
# a leading "-". The [string range] command is used to strip
# of the leading "-" from the name of the option.
#
# FRINK: nocheck
set [string range [lindex $optionStrings $index] 1 end] $val
}
# [string is] requires Tcl8.2; this works with 8.0 too
if {[catch {expr {$maxlen % 2}}]} {
return -code error "expected integer but got \"$maxlen\""
} elseif {$maxlen < 0} {
return -code error "expected positive integer but got \"$maxlen\""
}
set string [lindex $args end]
set result [::base64 -mode encode -- $string]
# Trf's encoder implicitly uses the settings -maxlen 76,
# -wrapchar \n for its output. We may have to reflow this for
# the settings chosen by the user. A second difference is that
# Trf closes the output with the wrap char sequence,
# always. The code here doesn't. Therefore 'trimright' is
# needed in the fast cases.
if {($maxlen == 76) && [string equal $wrapchar \n]} {
# Both maxlen and wrapchar are identical to Trf's
# settings. This is the super-fast case, because nearly
# nothing has to be done. Only thing to do is strip a
# terminating wrapchar.
set result [string trimright $result]
} elseif {$maxlen == 76} {
# wrapchar has to be different here, length is the
# same. We can use 'string map' to transform the wrap
# information.
set result [string map [list \n $wrapchar] \
[string trimright $result]]
} elseif {$maxlen == 0} {
# Have to reflow the output to no wrapping. Another fast
# case using only 'string map'. 'trimright' is not needed
# here.
set result [string map [list \n ""] $result]
} else {
# Have to reflow the output from 76 to the chosen maxlen,
# and possibly change the wrap sequence as well.
# Note: After getting rid of the old wrap sequence we
# extract the relevant segments from the string without
# modifying the string. Modification, i.e. removal of the
# processed part, means 'shifting down characters in
# memory', making the algorithm O(n^2). By avoiding the
# modification we stay in O(n).
set result [string map [list \n ""] $result]
set l [expr {[string length $result]-$maxlen}]
for {set off 0} {$off < $l} {incr off $maxlen} {
append res [string range $result $off [expr {$off+$maxlen-1}]] $wrapchar
}
append res [string range $result $off end]
set result $res
}
return $result
}
# ::base64::decode --
#
# Base64 decode a given string.
#
# Arguments:
# string The string to decode. Characters not in the base64
# alphabet are ignored (e.g., newlines)
#
# Results:
# The decoded value.
proc ::base64::decode {string} {
regsub -all {\s} $string {} string
::base64 -mode decode -- $string
}
} else {
# Without Trf use a pure tcl implementation
namespace eval base64 {
variable base64 {}
variable base64_en {}
# We create the auxiliary array base64_tmp, it will be unset later.
variable base64_tmp
variable i
variable i 0
variable char
foreach char {A B C D E F G H I J K L M N O P Q R S T U V W X Y Z \
a b c d e f g h i j k l m n o p q r s t u v w x y z \
0 1 2 3 4 5 6 7 8 9 + /} {
set base64_tmp($char) $i
lappend base64_en $char
incr i
}
#
# Create base64 as list: to code for instance C<->3, specify
# that [lindex $base64 67] be 3 (C is 67 in ascii); non-coded
# ascii chars get a {}. we later use the fact that lindex on a
# non-existing index returns {}, and that [expr {} < 0] is true
#
# the last ascii char is 'z'
variable char
variable len
variable val
scan z %c len
for {set i 0} {$i <= $len} {incr i} {
set char [format %c $i]
set val {}
if {[info exists base64_tmp($char)]} {
set val $base64_tmp($char)
} else {
set val {}
}
lappend base64 $val
}
# code the character "=" as -1; used to signal end of message
scan = %c i
set base64 [lreplace $base64 $i $i -1]
# remove unneeded variables
unset base64_tmp i char len val
namespace export encode decode
}
# ::base64::encode --
#
# Base64 encode a given string.
#
# Arguments:
# args ?-maxlen maxlen? ?-wrapchar wrapchar? string
#
# If maxlen is 0, the output is not wrapped.
#
# Results:
# A Base64 encoded version of $string, wrapped at $maxlen characters
# by $wrapchar.
proc ::base64::encode {args} {
set base64_en $::base64::base64_en
# Set the default wrapchar and maximum line length to match
# the settings for MIME encoding (RFC 3548, RFC 2045). These
# are the settings used by Trf as well. Various RFCs allow for
# different wrapping characters and wraplengths, so these may
# be overridden by command line options.
set wrapchar "\n"
set maxlen 76
if { [llength $args] == 0 } {
error "wrong # args: should be \"[lindex [info level 0] 0]\
?-maxlen maxlen? ?-wrapchar wrapchar? string\""
}
set optionStrings [list "-maxlen" "-wrapchar"]
for {set i 0} {$i < [llength $args] - 1} {incr i} {
set arg [lindex $args $i]
set index [lsearch -glob $optionStrings "${arg}*"]
if { $index == -1 } {
error "unknown option \"$arg\": must be -maxlen or -wrapchar"
}
incr i
if { $i >= [llength $args] - 1 } {
error "value for \"$arg\" missing"
}
set val [lindex $args $i]
# The name of the variable to assign the value to is extracted
# from the list of known options, all of which have an
# associated variable of the same name as the option without
# a leading "-". The [string range] command is used to strip
# of the leading "-" from the name of the option.
#
# FRINK: nocheck
set [string range [lindex $optionStrings $index] 1 end] $val
}
# [string is] requires Tcl8.2; this works with 8.0 too
if {[catch {expr {$maxlen % 2}}]} {
return -code error "expected integer but got \"$maxlen\""
} elseif {$maxlen < 0} {
return -code error "expected positive integer but got \"$maxlen\""
}
set string [lindex $args end]
set result {}
set state 0
set length 0
# Process the input bytes 3-by-3
binary scan $string c* X
foreach {x y z} $X {
ADD [lindex $base64_en [expr {($x >>2) & 0x3F}]]
if {$y != {}} {
ADD [lindex $base64_en [expr {(($x << 4) & 0x30) | (($y >> 4) & 0xF)}]]
if {$z != {}} {
ADD [lindex $base64_en [expr {(($y << 2) & 0x3C) | (($z >> 6) & 0x3)}]]
ADD [lindex $base64_en [expr {($z & 0x3F)}]]
} else {
set state 2
break
}
} else {
set state 1
break
}
}
if {$state == 1} {
ADD [lindex $base64_en [expr {(($x << 4) & 0x30)}]]
ADD =
ADD =
} elseif {$state == 2} {
ADD [lindex $base64_en [expr {(($y << 2) & 0x3C)}]]
ADD =
}
return $result
}
proc ::base64::ADD {x} {
# The line length check is always done before appending so
# that we don't get an extra newline if the output is a
# multiple of $maxlen chars long.
upvar 1 maxlen maxlen length length result result wrapchar wrapchar
if {$maxlen && $length >= $maxlen} {
append result $wrapchar
set length 0
}
append result $x
incr length
return
}
# ::base64::decode --
#
# Base64 decode a given string.
#
# Arguments:
# string The string to decode. Characters not in the base64
# alphabet are ignored (e.g., newlines)
#
# Results:
# The decoded value.
proc ::base64::decode {string} {
if {[string length $string] == 0} {return ""}
set base64 $::base64::base64
set output "" ; # Fix for [Bug 821126]
set nums {}
binary scan $string c* X
lappend X 61 ;# force a terminator
foreach x $X {
set bits [lindex $base64 $x]
if {$bits >= 0} {
if {[llength [lappend nums $bits]] == 4} {
foreach {v w z y} $nums break
set a [expr {($v << 2) | ($w >> 4)}]
set b [expr {(($w & 0xF) << 4) | ($z >> 2)}]
set c [expr {(($z & 0x3) << 6) | $y}]
append output [binary format ccc $a $b $c]
set nums {}
}
} elseif {$bits == -1} {
# = indicates end of data. Output whatever chars are
# left, if any.
if {![llength $nums]} break
# The encoding algorithm dictates that we can only
# have 1 or 2 padding characters. If x=={}, we must
# (*) have 12 bits of input (enough for 1 8-bit
# output). If x!={}, we have 18 bits of input (enough
# for 2 8-bit outputs).
#
# (*) If we don't then the input is broken (bug 2976290).
foreach {v w z} $nums break
# Bug 2976290
if {$w == {}} {
return -code error "Not enough data to process padding"
}
set a [expr {($v << 2) | (($w & 0x30) >> 4)}]
if {$z == {}} {
append output [binary format c $a ]
} else {
set b [expr {(($w & 0xF) << 4) | (($z & 0x3C) >> 2)}]
append output [binary format cc $a $b]
}
break
} else {
# RFC 2045 says that line breaks and other characters not part
# of the Base64 alphabet must be ignored, and that the decoder
# can optionally emit a warning or reject the message. We opt
# not to do so, but to just ignore the character.
continue
}
}
return $output
}
}
# # ## ### ##### ######## ############# #####################
return

19
src/vendorlib_tcl9/tcllib2.0/base64/base64c.tcl

@ -0,0 +1,19 @@
# base64c - Copyright (C) 2003 Pat Thoyts <patthoyts@users.sourceforge.net>
#
# This package is a place-holder for the critcl enhanced code present in
# the tcllib base64 module.
#
# Normally this code will become part of the tcllibc library.
#
# @sak notprovided base64c
package require critcl
package provide base64c 0.1.1
namespace eval ::base64c {
variable base64c_rcsid {$Id: base64c.tcl,v 1.5 2008/03/25 07:15:35 andreas_kupries Exp $}
critcl::ccode {
/* no code required in this file */
}
}

5
src/vendorlib_tcl9/tcllib2.0/base64/pkgIndex.tcl

@ -0,0 +1,5 @@
if {![package vsatisfies [package provide Tcl] 8.5 9]} {return}
package ifneeded base64 2.6.1 [list source [file join $dir base64.tcl]]
package ifneeded uuencode 1.1.6 [list source [file join $dir uuencode.tcl]]
package ifneeded yencode 1.1.4 [list source [file join $dir yencode.tcl]]
package ifneeded ascii85 1.1.1 [list source [file join $dir ascii85.tcl]]

337
src/vendorlib_tcl9/tcllib2.0/base64/uuencode.tcl

@ -0,0 +1,337 @@
# uuencode - Copyright (C) 2002 Pat Thoyts <patthoyts@users.sourceforge.net>
#
# Provide a Tcl only implementation of uuencode and uudecode.
#
# -------------------------------------------------------------------------
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
# -------------------------------------------------------------------------
package require Tcl 8.5 9; # tcl minimum version
# Try and get some compiled helper package.
if {[catch {package require tcllibc}]} {
catch {package require Trf}
}
namespace eval ::uuencode {
namespace export encode decode uuencode uudecode
}
proc ::uuencode::Enc {c} {
return [format %c [expr {($c != 0) ? (($c & 0x3f) + 0x20) : 0x60}]]
}
proc ::uuencode::Encode {s} {
set r {}
binary scan $s c* d
foreach {c1 c2 c3} $d {
if {$c1 == {}} {set c1 0}
if {$c2 == {}} {set c2 0}
if {$c3 == {}} {set c3 0}
append r [Enc [expr {$c1 >> 2}]]
append r [Enc [expr {(($c1 << 4) & 0o060) | (($c2 >> 4) & 0o017)}]]
append r [Enc [expr {(($c2 << 2) & 0o074) | (($c3 >> 6) & 0o003)}]]
append r [Enc [expr {($c3 & 0o077)}]]
}
return $r
}
proc ::uuencode::Decode {s} {
if {[string length $s] == 0} {return ""}
set r {}
binary scan [pad $s] c* d
foreach {c0 c1 c2 c3} $d {
append r [format %c [expr {((($c0-0x20)&0x3F) << 2) & 0xFF
| ((($c1-0x20)&0x3F) >> 4) & 0xFF}]]
append r [format %c [expr {((($c1-0x20)&0x3F) << 4) & 0xFF
| ((($c2-0x20)&0x3F) >> 2) & 0xFF}]]
append r [format %c [expr {((($c2-0x20)&0x3F) << 6) & 0xFF
| (($c3-0x20)&0x3F) & 0xFF}]]
}
return $r
}
# -------------------------------------------------------------------------
# C coded version of the Encode/Decode functions for base64c package.
# -------------------------------------------------------------------------
if {[package provide critcl] != {}} {
namespace eval ::uuencode {
critcl::ccode {
#include <string.h>
static unsigned char Enc(unsigned char c) {
return (c != 0) ? ((c & 0x3f) + 0x20) : 0x60;
}
}
critcl::ccommand CEncode {dummy interp objc objv} {
Tcl_Obj *inputPtr, *resultPtr;
Tcl_Size len, rlen, xtra;
unsigned char *input, *p, *r;
if (objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, "data"); /* OK tcl9 */
return TCL_ERROR;
}
inputPtr = objv[1];
input = Tcl_GetBytesFromObj(interp, inputPtr, &len); /* OK tcl9 */
if (input == NULL) return TCL_ERROR;
if ((xtra = (3 - (len % 3))) != 3) {
if (Tcl_IsShared(inputPtr))
inputPtr = Tcl_DuplicateObj(inputPtr);
input = Tcl_SetByteArrayLength(inputPtr, len + xtra); /* OK tcl9 */
memset(input + len, 0, xtra);
len += xtra;
}
rlen = (len / 3) * 4;
resultPtr = Tcl_NewObj();
r = Tcl_SetByteArrayLength(resultPtr, rlen); /* OK tcl9 */
memset(r, 0, rlen);
for (p = input; p < input + len; p += 3) {
char a, b, c;
a = *p; b = *(p+1), c = *(p+2);
*r++ = Enc(a >> 2);
*r++ = Enc(((a << 4) & 060) | ((b >> 4) & 017));
*r++ = Enc(((b << 2) & 074) | ((c >> 6) & 003));
*r++ = Enc(c & 077);
}
Tcl_SetObjResult(interp, resultPtr);
return TCL_OK;
}
critcl::ccommand CDecode {dummy interp objc objv} {
Tcl_Obj *inputPtr, *resultPtr;
Tcl_Size len, rlen, xtra;
unsigned char *input, *p, *r;
if (objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, "data"); /* OK tcl9 */
return TCL_ERROR;
}
/* if input is not mod 4, extend it with nuls */
inputPtr = objv[1];
input = Tcl_GetBytesFromObj(interp, inputPtr, &len); /* OK tcl9 */
if (input == NULL) return TCL_ERROR;
if ((xtra = (4 - (len % 4))) != 4) {
if (Tcl_IsShared(inputPtr))
inputPtr = Tcl_DuplicateObj(inputPtr);
input = Tcl_SetByteArrayLength(inputPtr, len + xtra); /* OK tcl9 */
memset(input + len, 0, xtra);
len += xtra;
}
/* output will be 1/3 smaller than input and a multiple of 3 */
rlen = (len / 4) * 3;
resultPtr = Tcl_NewObj();
r = Tcl_SetByteArrayLength(resultPtr, rlen); /* OK tcl9 */
memset(r, 0, rlen);
for (p = input; p < input + len; p += 4) {
char a, b, c, d;
a = *p; b = *(p+1), c = *(p+2), d = *(p+3);
*r++ = (((a - 0x20) & 0x3f) << 2) | (((b - 0x20) & 0x3f) >> 4);
*r++ = (((b - 0x20) & 0x3f) << 4) | (((c - 0x20) & 0x3f) >> 2);
*r++ = (((c - 0x20) & 0x3f) << 6) | (((d - 0x20) & 0x3f) );
}
Tcl_SetObjResult(interp, resultPtr);
return TCL_OK;
}
}
}
# -------------------------------------------------------------------------
# Description:
# Permit more tolerant decoding of invalid input strings by padding to
# a multiple of 4 bytes with nulls.
# Result:
# Returns the input string - possibly padded with uuencoded null chars.
#
proc ::uuencode::pad {s} {
if {[set mod [expr {[string length $s] % 4}]] != 0} {
append s [string repeat "`" [expr {4 - $mod}]]
}
return $s
}
# -------------------------------------------------------------------------
# If the Trf package is available then we shall use this by default but the
# Tcllib implementations are always visible if needed (ie: for testing)
if {[info commands ::uuencode::CDecode] != {}} {
# tcllib critcl package
interp alias {} ::uuencode::encode {} ::uuencode::CEncode
interp alias {} ::uuencode::decode {} ::uuencode::CDecode
} elseif {[package provide Trf] != {}} {
proc ::uuencode::encode {s} {
return [::uuencode -mode encode -- $s]
}
proc ::uuencode::decode {s} {
return [::uuencode -mode decode -- [pad $s]]
}
} else {
# pure-tcl then
interp alias {} ::uuencode::encode {} ::uuencode::Encode
interp alias {} ::uuencode::decode {} ::uuencode::Decode
}
# -------------------------------------------------------------------------
proc ::uuencode::uuencode {args} {
array set opts {mode 0o0644 filename {} name {}}
set wrongargs "wrong \# args: should be\
\"uuencode ?-name string? ?-mode octal?\
(-file filename | ?--? string)\""
while {[string match -* [lindex $args 0]]} {
switch -glob -- [lindex $args 0] {
-f* {
if {[llength $args] < 2} {
return -code error $wrongargs
}
set opts(filename) [lindex $args 1]
set args [lreplace $args 0 0]
}
-m* {
if {[llength $args] < 2} {
return -code error $wrongargs
}
set opts(mode) [lindex $args 1]
set args [lreplace $args 0 0]
}
-n* {
if {[llength $args] < 2} {
return -code error $wrongargs
}
set opts(name) [lindex $args 1]
set args [lreplace $args 0 0]
}
-- {
set args [lreplace $args 0 0]
break
}
default {
return -code error "bad option [lindex $args 0]:\
must be -file, -mode, or -name"
}
}
set args [lreplace $args 0 0]
}
if {$opts(name) == {}} {
set opts(name) $opts(filename)
}
if {$opts(name) == {}} {
set opts(name) "data.dat"
}
if {$opts(filename) != {}} {
set f [open $opts(filename) r]
fconfigure $f -translation binary
set data [read $f]
close $f
} else {
if {[llength $args] != 1} {
return -code error $wrongargs
}
set data [lindex $args 0]
}
set r {}
append r [format "begin %o %s" $opts(mode) $opts(name)] "\n"
for {set n 0} {$n < [string length $data]} {incr n 45} {
set s [string range $data $n [expr {$n + 44}]]
append r [Enc [string length $s]]
append r [encode $s] "\n"
}
append r "`\nend"
return $r
}
# -------------------------------------------------------------------------
# Description:
# Perform uudecoding of a file or data. A file may contain more than one
# encoded data section so the result is a list where each element is a
# three element list of the provided filename, the suggested mode and the
# data itself.
#
proc ::uuencode::uudecode {args} {
array set opts {mode 0o0644 filename {}}
set wrongargs "wrong \# args: should be \"uudecode (-file filename | ?--? string)\""
while {[string match -* [lindex $args 0]]} {
switch -glob -- [lindex $args 0] {
-f* {
if {[llength $args] < 2} {
return -code error $wrongargs
}
set opts(filename) [lindex $args 1]
set args [lreplace $args 0 0]
}
-- {
set args [lreplace $args 0 0]
break
}
default {
return -code error "bad option [lindex $args 0]:\
must be -file"
}
}
set args [lreplace $args 0 0]
}
if {$opts(filename) != {}} {
set f [open $opts(filename) r]
set data [read $f]
close $f
} else {
if {[llength $args] != 1} {
return -code error $wrongargs
}
set data [lindex $args 0]
}
set state false
set result {}
foreach {line} [split $data "\n"] {
switch -exact -- $state {
false {
if {[regexp {^begin ([0-7]+) ([^\s]*)} $line \
-> opts(mode) opts(name)]} {
set state true
set r {}
}
}
true {
if {[string match "end" $line]} {
set state false
lappend result [list $opts(name) $opts(mode) $r]
} else {
scan $line %c c
set n [expr {($c - 0x21)}]
append r [string range \
[decode [string range $line 1 end]] 0 $n]
}
}
}
}
return $result
}
# -------------------------------------------------------------------------
package provide uuencode 1.1.6
# -------------------------------------------------------------------------
#
# Local variables:
# mode: tcl
# indent-tabs-mode: nil
# End:

309
src/vendorlib_tcl9/tcllib2.0/base64/yencode.tcl

@ -0,0 +1,309 @@
# yencode.tcl - Copyright (C) 2002 Pat Thoyts <patthoyts@users.sourceforge.net>
#
# Provide a Tcl only implementation of yEnc encoding algorithm
#
# -------------------------------------------------------------------------
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
# -------------------------------------------------------------------------
# FUTURE: Rework to allow switching between the tcl/critcl implementations.
package require Tcl 8.5 9; # tcl minimum version
catch {package require crc32}; # tcllib 1.1
catch {package require tcllibc}; # critcl enhancements for tcllib
namespace eval ::yencode {
namespace export encode decode yencode ydecode
}
# -------------------------------------------------------------------------
proc ::yencode::Encode {s} {
set r {}
binary scan $s c* d
foreach {c} $d {
set v [expr {($c + 42) % 256}]
if {$v == 0x00 || $v == 0x09 || $v == 0x0A
|| $v == 0x0D || $v == 0x3D} {
append r "="
set v [expr {($v + 64) % 256}]
}
append r [format %c $v]
}
return $r
}
proc ::yencode::Decode {s} {
if {[string length $s] == 0} {return ""}
set r {}
set esc 0
binary scan $s c* d
foreach c $d {
if {$c == 61 && $esc == 0} {
set esc 1
continue
}
set v [expr {($c - 42) % 256}]
if {$esc} {
set v [expr {($v - 64) % 256}]
set esc 0
}
append r [format %c $v]
}
return $r
}
# -------------------------------------------------------------------------
# C coded versions for critcl built base64c package
# -------------------------------------------------------------------------
if {[package provide critcl] != {}} {
namespace eval ::yencode {
critcl::ccode {
#include <string.h>
}
critcl::ccommand CEncode {dummy interp objc objv} {
Tcl_Obj *inputPtr, *resultPtr;
Tcl_Size len, rlen, xtra;
unsigned char *input, *p, *r, v;
if (objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, "data"); /* OK tcl9 */
return TCL_ERROR;
}
/* fetch the input data */
inputPtr = objv[1];
input = Tcl_GetBytesFromObj(interp, inputPtr, &len); /* OK tcl9 */
if (input == NULL) return TCL_ERROR;
/* calculate the length of the encoded result */
rlen = len;
for (p = input; p < input + len; p++) {
v = (*p + 42) % 256;
if (v == 0 || v == 9 || v == 0x0A || v == 0x0D || v == 0x3D)
rlen++;
}
/* allocate the output buffer */
resultPtr = Tcl_NewObj();
r = Tcl_SetByteArrayLength(resultPtr, rlen); /* OK tcl9 */
/* encode the input */
for (p = input; p < input + len; p++) {
v = (*p + 42) % 256;
if (v == 0 || v == 9 || v == 0x0A || v == 0x0D || v == 0x3D) {
*r++ = '=';
v = (v + 64) % 256;
}
*r++ = v;
}
Tcl_SetObjResult(interp, resultPtr);
return TCL_OK;
}
critcl::ccommand CDecode {dummy interp objc objv} {
Tcl_Obj *inputPtr, *resultPtr;
Tcl_Size len, rlen, esc;
unsigned char *input, *p, *r, v;
if (objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, "data"); /* OK tcl9 */
return TCL_ERROR;
}
/* fetch the input data */
inputPtr = objv[1];
input = Tcl_GetBytesFromObj(interp, inputPtr, &len); /* OK tcl9 */
if (input == NULL) return TCL_ERROR;
/* allocate the output buffer */
resultPtr = Tcl_NewObj();
r = Tcl_SetByteArrayLength(resultPtr, len); /* OK tcl9 */
/* encode the input */
for (p = input, esc = 0, rlen = 0; p < input + len; p++) {
if (*p == 61 && esc == 0) {
esc = 1;
continue;
}
v = (*p - 42) % 256;
if (esc) {
v = (v - 64) % 256;
esc = 0;
}
*r++ = v;
rlen++;
}
Tcl_SetByteArrayLength(resultPtr, rlen); /* OK tcl9 */
Tcl_SetObjResult(interp, resultPtr);
return TCL_OK;
}
}
}
if {[info commands ::yencode::CEncode] != {}} {
interp alias {} ::yencode::encode {} ::yencode::CEncode
interp alias {} ::yencode::decode {} ::yencode::CDecode
} else {
interp alias {} ::yencode::encode {} ::yencode::Encode
interp alias {} ::yencode::decode {} ::yencode::Decode
}
# -------------------------------------------------------------------------
# Description:
# Pop the nth element off a list. Used in options processing.
#
proc ::yencode::Pop {varname {nth 0}} {
upvar $varname args
set r [lindex $args $nth]
set args [lreplace $args $nth $nth]
return $r
}
# -------------------------------------------------------------------------
proc ::yencode::yencode {args} {
array set opts {mode 0644 filename {} name {} line 128 crc32 1}
while {[string match -* [lindex $args 0]]} {
switch -glob -- [lindex $args 0] {
-f* { set opts(filename) [Pop args 1] }
-m* { set opts(mode) [Pop args 1] }
-n* { set opts(name) [Pop args 1] }
-l* { set opts(line) [Pop args 1] }
-c* { set opts(crc32) [Pop args 1] }
-- { Pop args ; break }
default {
set options [join [lsort [array names opts]] ", -"]
return -code error "bad option [lindex $args 0]:\
must be -$options"
}
}
Pop args
}
if {$opts(name) == {}} {
set opts(name) $opts(filename)
}
if {$opts(name) == {}} {
set opts(name) "data.dat"
}
if {! [string is boolean $opts(crc32)]} {
return -code error "bad option -crc32: argument must be true or false"
}
if {$opts(filename) != {}} {
set f [open $opts(filename) rb]
fconfigure $f -translation binary
set data [read $f]
close $f
} else {
if {[llength $args] != 1} {
return -code error "wrong \# args: should be\
\"yencode ?options? -file name | data\""
}
set data [lindex $args 0]
}
set opts(size) [string length $data]
set r {}
append r [format "=ybegin line=%d size=%d name=%s" \
$opts(line) $opts(size) $opts(name)] "\n"
set ndx 0
while {$ndx < $opts(size)} {
set pln [string range $data $ndx [expr {$ndx + $opts(line) - 1}]]
set enc [encode $pln]
incr ndx [string length $pln]
append r $enc "\r\n"
}
append r [format "=yend size=%d" $ndx]
if {$opts(crc32)} {
append r " crc32=" [crc::crc32 -format %x $data]
}
return $r
}
# -------------------------------------------------------------------------
# Description:
# Perform ydecoding of a file or data. A file may contain more than one
# encoded data section so the result is a list where each element is a
# three element list of the provided filename, the file size and the
# data itself.
#
proc ::yencode::ydecode {args} {
array set opts {mode 0644 filename {} name default.bin}
while {[string match -* [lindex $args 0]]} {
switch -glob -- [lindex $args 0] {
-f* { set opts(filename) [Pop args 1] }
-- { Pop args ; break; }
default {
set options [join [lsort [array names opts]] ", -"]
return -code error "bad option [lindex $args 0]:\
must be -$opts"
}
}
Pop args
}
if {$opts(filename) != {}} {
set f [open $opts(filename) r]
set data [read $f]
close $f
} else {
if {[llength $args] != 1} {
return -code error "wrong \# args: should be\
\"ydecode ?options? -file name | data\""
}
set data [lindex $args 0]
}
set state false
set result {}
foreach {line} [split $data "\n"] {
set line [string trimright $line "\r\n"]
switch -exact -- $state {
false {
if {[string match "=ybegin*" $line]} {
regexp {line=(\d+)} $line -> opts(line)
regexp {size=(\d+)} $line -> opts(size)
regexp {name=(\d+)} $line -> opts(name)
if {$opts(name) == {}} {
set opts(name) default.bin
}
set state true
set r {}
}
}
true {
if {[string match "=yend*" $line]} {
set state false
lappend result [list $opts(name) $opts(size) $r]
} else {
append r [decode $line]
}
}
}
}
return $result
}
# -------------------------------------------------------------------------
package provide yencode 1.1.4
# -------------------------------------------------------------------------
#
# Local variables:
# mode: tcl
# indent-tabs-mode: nil
# End:

999
src/vendorlib_tcl9/tcllib2.0/bee/bee.tcl

@ -0,0 +1,999 @@
# bee.tcl --
#
# BitTorrent Bee de- and encoder.
#
# Copyright (c) 2004 by Andreas Kupries <andreas_kupries@users.sourceforge.net>
# See the file license.terms.
package require Tcl 8.5 9
namespace eval ::bee {
# Encoder commands
namespace export \
encodeString encodeNumber \
encodeListArgs encodeList \
encodeDictArgs encodeDict
# Decoder commands.
namespace export \
decode \
decodeChannel \
decodeCancel \
decodePush
# Channel decoders, reference to state information, keyed by
# channel handle.
variable bee
array set bee {}
# Counter for generation of names for the state variables.
variable count 0
# State information for the channel decoders.
# stateN, with N an integer number counting from 0 on up.
# ...(chan) Handle of channel the decoder is for.
# ...(cmd) Command prefix, completion callback
# ...(exact) Boolean flag, set for exact processing.
# ...(read) Buffer for new characters to process.
# ...(type) Type of current value (integer, string, list, dict)
# ...(value) Buffer for assembling the current value.
# ...(pend) Stack of pending 'value' buffers, for nested
# containers.
# ...(state) Current state of the decoding state machine.
# States of the finite automaton ...
# intro - One char, type of value, or 'e' as stop of container.
# signum - sign or digit, for integer.
# idigit - digit, for integer, or 'e' as stop
# ldigit - digit, for length of string, or :
# data - string data, 'get' characters.
# Containers via 'pend'.
#Debugging help, nesting level
#variable X 0
}
# ::bee::encodeString --
#
# Encode a string to bee-format.
#
# Arguments:
# string The string to encode.
#
# Results:
# The bee-encoded form of the string.
proc ::bee::encodeString {string} {
return "[string length $string]:$string"
}
# ::bee::encodeNumber --
#
# Encode an integer number to bee-format.
#
# Arguments:
# num The integer number to encode.
#
# Results:
# The bee-encoded form of the integer number.
proc ::bee::encodeNumber {num} {
##nagelfar ignore
if {![string is integer -strict $num]} {
return -code error "Expected integer number, got \"$num\""
}
# The reformatting deals with hex, octal and other tcl
# representation of the value. In other words we normalize the
# string representation of the input value.
set num [format %d $num]
return "i${num}e"
}
# ::bee::encodeList --
#
# Encode a list of bee-coded values to bee-format.
#
# Arguments:
# list The list to encode.
#
# Results:
# The bee-encoded form of the list.
proc ::bee::encodeList {list} {
return "l[join $list ""]e"
}
# ::bee::encodeListArgs --
#
# Encode a variable list of bee-coded values to bee-format.
#
# Arguments:
# args The values to encode.
#
# Results:
# The bee-encoded form of the list of values.
proc ::bee::encodeListArgs {args} {
return [encodeList $args]
}
# ::bee::encodeDict --
#
# Encode a dictionary of keys and bee-coded values to bee-format.
#
# Arguments:
# dict The dictionary to encode.
#
# Results:
# The bee-encoded form of the dictionary.
proc ::bee::encodeDict {dict} {
if {([llength $dict] % 2) == 1} {
return -code error "Expected even number of elements, got \"[llength $dict]\""
}
set temp [list]
foreach {k v} $dict {
lappend temp [list $k $v]
}
set res "d"
foreach item [lsort -index 0 $temp] {
foreach {k v} $item break
append res [encodeString $k]$v
}
append res "e"
return $res
}
# ::bee::encodeDictArgs --
#
# Encode a variable dictionary of keys and bee-coded values to bee-format.
#
# Arguments:
# args The keys and values to encode.
#
# Results:
# The bee-encoded form of the dictionary.
proc ::bee::encodeDictArgs {args} {
return [encodeDict $args]
}
# ::bee::decode --
#
# Decode a bee-encoded value and returns the embedded tcl
# value. For containers this recurses into the contained value.
#
# Arguments:
# value The string containing the bee-encoded value to decode.
# evar Optional. If set the name of the variable to store the
# index of the first character after the decoded value to.
# start Optional. If set the index of the first character of the
# value to decode. Defaults to 0, i.e. the beginning of the
# string.
#
# Results:
# The tcl value embedded in the encoded string.
proc ::bee::decode {value {evar {}} {start 0}} {
#variable X
#puts -nonewline "[string repeat " " $X]decode @$start" ; flush stdout
if {$evar ne ""} {upvar 1 $evar end} else {set end _}
if {[string length $value] < ($start+2)} {
# This checked that the 'start' index is still in the string,
# and the end of the value most likely as well. Note that each
# encoded value consists of at least two characters (the
# bracketing characters for integer, list, and dict, and for
# string at least one digit length and the colon).
#puts \t[string length $value]\ <\ ($start+2)
return -code error "String not large enough for value"
}
set type [string index $value $start]
#puts -nonewline " $type=" ; flush stdout
if {$type eq "i"} {
# Extract integer
#puts -nonewline integer ; flush stdout
incr start ; # Skip over intro 'i'.
set end [string first e $value $start]
if {$end < 0} {
return -code error "End of integer number not found"
}
incr end -1 ; # Get last character before closing 'e'.
set num [string range $value $start $end]
##nagelfar ignore
if {
[regexp {^-0+$} $num] ||
![string is integer -strict $num] ||
(([string length $num] > 1) && [string match 0* $num])
} {
return -code error "Expected integer number, got \"$num\""
}
incr end 2 ; # Step after closing 'e' to the beginning of
# ........ ; # the next bee-value behind the current one.
#puts " ($num) @$end"
return [format %d $num]
} elseif {($type eq "l") || ($type eq "d")} {
#puts -nonewline $type\n ; flush stdout
# Extract list or dictionary, recursively each contained
# element. From the perspective of the decoder this is the
# same, the tcl representation of both is a list, and for a
# dictionary keys and values are also already in the correct
# order.
set result [list]
incr start ; # Step over intro 'e' to beginning of the first
# ........ ; # contained value, or behind the container (if
# ........ ; # empty).
set end $start
#incr X
while {[string index $value $start] ne "e"} {
lappend result [decode $value end $start]
set start $end
}
#incr X -1
incr end
#puts "[string repeat " " $X]($result) @$end"
if {$type eq "d" && ([llength $result] % 2 == 1)} {
return -code error "Dictionary has to be of even length"
}
return $result
} elseif {[string match {[0-9]} $type]} {
#puts -nonewline string ; flush stdout
# Extract string. First the length, bounded by a colon, then
# the appropriate number of characters.
set end [string first : $value $start]
if {$end < 0} {
return -code error "End of string length not found"
}
incr end -1
set length [string range $value $start $end]
incr end 2 ;# Skip to beginning of the string after the colon
##nagelfar ignore
if {![string is integer -strict $length]} {
return -code error "Expected integer number for string length, got \"$length\""
} elseif {$length < 0} {
# This cannot happen. To happen "-" has to be first character,
# and this is caught as unknown bee-type.
return -code error "Illegal negative string length"
} elseif {($end + $length) > [string length $value]} {
return -code error "String not large enough for value"
}
#puts -nonewline \[$length\] ; flush stdout
set length [format %d $length]
if {$length > 0} {
set start $end
incr end $length
incr end -1
set result [string range $value $start $end]
incr end
} else {
set result ""
}
#puts " ($result) @$end"
return $result
} else {
return -code error "Unknown bee-type \"$type\""
}
}
# ::bee::decodeIndices --
#
# Similar to 'decode', but does not return the decoded tcl values,
# but a structure containing the start- and end-indices for all
# values in the structure.
#
# Arguments:
# value The string containing the bee-encoded value to decode.
# evar Optional. If set the name of the variable to store the
# index of the first character after the decoded value to.
# start Optional. If set the index of the first character of the
# value to decode. Defaults to 0, i.e. the beginning of the
# string.
#
# Results:
# The structure of the value, with indices and types for all
# contained elements.
proc ::bee::decodeIndices {value {evar {}} {start 0}} {
#variable X
#puts -nonewline "[string repeat " " $X]decode @$start" ; flush stdout
if {$evar ne ""} {upvar 1 $evar end} else {set end _}
if {[string length $value] < ($start+2)} {
# This checked that the 'start' index is still in the string,
# and the end of the value most likely as well. Note that each
# encoded value consists of at least two characters (the
# bracketing characters for integer, list, and dict, and for
# string at least one digit length and the colon).
#puts \t[string length $value]\ <\ ($start+2)
return -code error "String not large enough for value"
}
set type [string index $value $start]
#puts -nonewline " $type=" ; flush stdout
if {$type eq "i"} {
# Extract integer
#puts -nonewline integer ; flush stdout
set begin $start
incr start ; # Skip over intro 'i'.
set end [string first e $value $start]
if {$end < 0} {
return -code error "End of integer number not found"
}
incr end -1 ; # Get last character before closing 'e'.
set num [string range $value $start $end]
##nagelfar ignore
if {
[regexp {^-0+$} $num] ||
![string is integer -strict $num] ||
(([string length $num] > 1) && [string match 0* $num])
} {
return -code error "Expected integer number, got \"$num\""
}
incr end
set stop $end
incr end 1 ; # Step after closing 'e' to the beginning of
# ........ ; # the next bee-value behind the current one.
#puts " ($num) @$end"
return [list integer $begin $stop]
} elseif {$type eq "l"} {
#puts -nonewline $type\n ; flush stdout
# Extract list, recursively each contained element.
set result [list]
lappend result list $start @
incr start ; # Step over intro 'e' to beginning of the first
# ........ ; # contained value, or behind the container (if
# ........ ; # empty).
set end $start
#incr X
set contained [list]
while {[string index $value $start] ne "e"} {
lappend contained [decodeIndices $value end $start]
set start $end
}
lappend result $contained
#incr X -1
set stop $end
incr end
#puts "[string repeat " " $X]($result) @$end"
return [lreplace $result 2 2 $stop]
} elseif {($type eq "l") || ($type eq "d")} {
#puts -nonewline $type\n ; flush stdout
# Extract dictionary, recursively each contained element.
set result [list]
lappend result dict $start @
incr start ; # Step over intro 'e' to beginning of the first
# ........ ; # contained value, or behind the container (if
# ........ ; # empty).
set end $start
set atkey 1
#incr X
set contained [list]
set val [list]
while {[string index $value $start] ne "e"} {
if {$atkey} {
lappend contained [decode $value {} $start]
lappend val [decodeIndices $value end $start]
set atkey 0
} else {
lappend val [decodeIndices $value end $start]
lappend contained $val
set val [list]
set atkey 1
}
set start $end
}
lappend result $contained
#incr X -1
set stop $end
incr end
#puts "[string repeat " " $X]($result) @$end"
if {[llength $result] % 2 == 1} {
return -code error "Dictionary has to be of even length"
}
return [lreplace $result 2 2 $stop]
} elseif {[string match {[0-9]} $type]} {
#puts -nonewline string ; flush stdout
# Extract string. First the length, bounded by a colon, then
# the appropriate number of characters.
set end [string first : $value $start]
if {$end < 0} {
return -code error "End of string length not found"
}
incr end -1
set length [string range $value $start $end]
incr end 2 ;# Skip to beginning of the string after the colon
##nagelfar ignore
if {![string is integer -strict $length]} {
return -code error "Expected integer number for string length, got \"$length\""
} elseif {$length < 0} {
# This cannot happen. To happen "-" has to be first character,
# and this is caught as unknown bee-type.
return -code error "Illegal negative string length"
} elseif {($end + $length) > [string length $value]} {
return -code error "String not large enough for value"
}
set length [format %d $length]
#puts -nonewline \[$length\] ; flush stdout
incr end -1
if {$length > 0} {
incr end $length
set stop $end
} else {
set stop $end
}
incr end
#puts " ($result) @$end"
return [list string $start $stop]
} else {
return -code error "Unknown bee-type \"$type\""
}
}
# ::bee::decodeChannel --
#
# Attach decoder for a bee-value to a channel. See the
# documentation for details.
#
# Arguments:
# chan Channel to attach to.
# -command cmdprefix Completion callback. Required.
# -exact Keep running after completion.
# -prefix data Seed for decode buffer.
#
# Results:
# A token to use when referring to the decoder.
# For example when canceling it.
proc ::bee::decodeChannel {chan args} {
variable bee
if {[info exists bee($chan)]} {
return -code error "bee-Decoder already active for channel"
}
# Create state and token.
variable count
variable [set st state$count]
array set $st {}
set bee($chan) $st
upvar 0 $st state
incr count
# Initialize the decoder state, process the options. When
# encountering errors here destroy the half-baked state before
# throwing the message.
set state(chan) $chan
array set state {
exact 0
type ?
read {}
value {}
pend {}
state intro
get 1
}
while {[llength $args]} {
set option [lindex $args 0]
set args [lrange $args 1 end]
if {$option eq "-command"} {
if {![llength $args]} {
unset bee($chan)
unset state
return -code error "Missing value for option -command."
}
set state(cmd) [lindex $args 0]
set args [lrange $args 1 end]
} elseif {$option eq "-prefix"} {
if {![llength $args]} {
unset bee($chan)
unset state
return -code error "Missing value for option -prefix."
}
set state(read) [lindex $args 0]
set args [lrange $args 1 end]
} elseif {$option eq "-exact"} {
set state(exact) 1
} else {
unset bee($chan)
unset state
return -code error "Illegal option \"$option\",\
expected \"-command\", \"-prefix\", or \"-keep\""
}
}
if {![info exists state(cmd)]} {
unset bee($chan)
unset state
return -code error "Missing required completion callback."
}
# Set up the processing of incoming data.
fileevent $chan readable [list ::bee::Process $chan $bee($chan)]
# Return the name of the state array as token.
return $bee($chan)
}
# ::bee::Parse --
#
# Internal helper. Fileevent handler for a decoder.
# Parses input and handles both error and eof conditions.
#
# Arguments:
# token The decoder to run on its input.
#
# Results:
# None.
proc ::bee::Process {chan token} {
if {[catch {Parse $token} msg]} {
# Something failed. Destroy and report.
Command $token error $msg
return
}
if {[eof $chan]} {
# Having data waiting, either in the input queue, or in the
# output stack (of nested containers) is a failure. Report
# this instead of the eof.
variable $token
upvar 0 $token state
if {
[string length $state(read)] ||
[llength $state(pend)] ||
[string length $state(value)] ||
($state(state) ne "intro")
} {
Command $token error "Incomplete value at end of channel"
} else {
Command $token eof
}
}
return
}
# ::bee::Parse --
#
# Internal helper. Reading from the channel and parsing the input.
# Uses a hardwired state machine.
#
# Arguments:
# token The decoder to run on its input.
#
# Results:
# None.
proc ::bee::Parse {token} {
variable $token
upvar 0 $token state
upvar 0 state(state) current
upvar 0 state(read) input
upvar 0 state(type) type
upvar 0 state(value) value
upvar 0 state(pend) pend
upvar 0 state(exact) exact
upvar 0 state(get) get
set chan $state(chan)
#puts Parse/$current
if {!$exact} {
# Add all waiting characters to the buffer so that we can process as
# much as is possible in one go.
append input [read $chan]
} else {
# Exact reading. Usually one character, but when in the data
# section for a string value we know for how many characters
# we are looking for.
append input [read $chan $get]
}
# We got nothing, do nothing.
if {![string length $input]} return
if {$current eq "data"} {
# String data, this can be done faster, as we read longer
# sequences of characters for this.
set l [string length $input]
if {$l < $get} {
# Not enough, wait for more.
append value $input
incr get -$l
return
} elseif {$l == $get} {
# Got all, exactly. Prepare state machine for next value.
if {[Complete $token $value$input]} return
set current intro
set get 1
set value ""
set input ""
return
} else {
# Got more than required (only for !exact).
incr get -1
if {[Complete $token $value[string range $input 0 $get]]} {return}
incr get
set input [string range $input $get end]
set get 1
set value ""
set current intro
# This now falls into the loop below.
}
}
set where 0
set n [string length $input]
#puts Parse/$n
while {$where < $n} {
# Hardwired state machine. Get current character.
set ch [string index $input $where]
#puts Parse/@$where/$current/$ch/
if {$current eq "intro"} {
# First character of a value.
if {$ch eq "i"} {
# Begin reading integer.
set type integer
set current signum
} elseif {$ch eq "l"} {
# Begin a list.
set type list
lappend pend list {}
#set current intro
} elseif {$ch eq "d"} {
# Begin a dictionary.
set type dict
lappend pend dict {}
#set current intro
} elseif {$ch eq "e"} {
# Close a container. Throw an error if there is no
# container to close.
if {![llength $pend]} {
return -code error "End of container outside of container."
}
set v [lindex $pend end]
set t [lindex $pend end-1]
set pend [lrange $pend 0 end-2]
if {$t eq "dict" && ([llength $v] % 2 == 1)} {
return -code error "Dictionary has to be of even length"
}
if {[Complete $token $v]} {return}
set current intro
} elseif {[string match {[0-9]} $ch]} {
# Begin reading a string, length section first.
set type string
set current ldigit
set value $ch
} else {
# Unknown type. Throw error.
return -code error "Unknown bee-type \"$ch\""
}
# To next character.
incr where
} elseif {$current eq "signum"} {
# Integer number, a minus sign, or a digit.
if {[string match {[-0-9]} $ch]} {
append value $ch
set current idigit
} else {
return -code error "Syntax error in integer,\
expected sign or digit, got \"$ch\""
}
incr where
} elseif {$current eq "idigit"} {
# Integer number, digit or closing 'e'.
if {[string match {[-0-9]} $ch]} {
append value $ch
} elseif {$ch eq "e"} {
# Integer closes. Validate and report.
#puts validate
##nagelfar ignore
if {
[regexp {^-0+$} $value] ||
![string is integer -strict $value] ||
(([string length $value] > 1) && [string match 0* $value])
} {
return -code error "Expected integer number, got \"$value\""
}
set value [format %d $value]
if {[Complete $token $value]} {return}
set value ""
set current intro
} else {
return -code error "Syntax error in integer,\
expected digit, or 'e', got \"$ch\""
}
incr where
} elseif {$current eq "ldigit"} {
# String, length section, digit, or :
if {[string match {[-0-9]} $ch]} {
append value $ch
} elseif {$ch eq ":"} {
# Length section closes, validate,
# then perform data processing.
set num $value
##nagelfar ignore
if {
[regexp {^-0+$} $num] ||
![string is integer -strict $num] ||
(([string length $num] > 1) && [string match 0* $num])
} {
return -code error "Expected integer number as string length, got \"$num\""
}
set num [format %d $num]
set value ""
# We may have already part of the data in
# memory. Process that piece before looking for more.
incr where
set have [expr {$n - $where}]
if {$num < $have} {
# More than enough in the buffer.
set end $where
incr end $num
incr end -1
if {[Complete $token [string range $input $where $end]]} {return}
set where $end ;# Further processing behind the string.
set current intro
} elseif {$num == $have} {
# Just enough.
if {[Complete $token [string range $input $where end]]} {return}
set where $n
set current intro
} else {
# Not enough. Initialize value with the data we
# have (after the colon) and stop processing for
# now.
set value [string range $input $where end]
set current data
set get $num
set input ""
return
}
} else {
return -code error "Syntax error in string length,\
expected digit, or ':', got \"$ch\""
}
incr where
} else {
# unknown state = internal error
return -code error "Unknown decoder state \"$current\", internal error"
}
}
set input ""
return
}
# ::bee::Command --
#
# Internal helper. Runs the decoder command callback.
#
# Arguments:
# token The decoder invoking its callback
# how Which method to invoke (value, error, eof)
# args Arguments for the method.
#
# Results:
# A boolean flag. Set if further processing has to stop.
proc ::bee::Command {token how args} {
variable $token
upvar 0 $token state
#puts Report/$token/$how/$args/
set cmd $state(cmd)
set chan $state(chan)
# We catch the fileevents because they will fail when this is
# called from the 'Close'. The channel will already be gone in
# that case.
set stop 0
if {($how eq "error") || ($how eq "eof")} {
variable bee
set stop 1
fileevent $chan readable {}
unset bee($chan)
unset state
if {$how eq "eof"} {
#puts \tclosing/$chan
close $chan
}
}
lappend cmd $how $token
foreach a $args {lappend cmd $a}
uplevel #0 $cmd
if {![info exists state]} {
# The decoder token was killed by the callback, stop
# processing.
set stop 1
}
#puts /$stop/[file channels]
return $stop
}
# ::bee::Complete --
#
# Internal helper. Reports a completed value.
#
# Arguments:
# token The decoder reporting the value.
# value The value to report.
#
# Results:
# A boolean flag. Set if further processing has to stop.
proc ::bee::Complete {token value} {
variable $token
upvar 0 $token state
upvar 0 state(pend) pend
if {[llength $pend]} {
# The value is part of a container. Add the value to its end
# and keep processing.
set pend [lreplace $pend end end \
[linsert [lindex $pend end] end \
$value]]
# Don't stop.
return 0
}
# The value is at the top, report it. The callback determines if
# we keep processing.
return [Command $token value $value]
}
# ::bee::decodeCancel --
#
# Destroys the decoder referenced by the token.
#
# Arguments:
# token The decoder to destroy.
#
# Results:
# None.
proc ::bee::decodeCancel {token} {
variable bee
variable $token
upvar 0 $token state
unset bee($state(chan))
unset state
return
}
# ::bee::decodePush --
#
# Push data into the decoder input buffer.
#
# Arguments:
# token The decoder to extend.
# string The characters to add.
#
# Results:
# None.
proc ::bee::decodePush {token string} {
variable $token
upvar 0 $token state
append state(read) $string
return
}
package provide bee 0.3

4
src/vendorlib_tcl9/tcllib2.0/bee/pkgIndex.tcl

@ -0,0 +1,4 @@
# Tcl package index file, version 1.1
if {![package vsatisfies [package provide Tcl] 8.5 9]} {return}
package ifneeded bee 0.3 [list source [file join $dir bee.tcl]]

556
src/vendorlib_tcl9/tcllib2.0/bench/bench.tcl

@ -0,0 +1,556 @@
# bench.tcl --
#
# Management of benchmarks.
#
# Copyright (c) 2005-2008 by Andreas Kupries <andreas_kupries@users.sourceforge.net>
# library derived from runbench.tcl application (C) Jeff Hobbs.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
# ### ### ### ######### ######### ######### ###########################
## Requisites - Packages and namespace for the commands and data.
package require Tcl 8.5 9
package require logger
package require csv
package require struct::matrix
package require report
namespace eval ::bench {}
namespace eval ::bench::out {}
# @mdgen OWNER: libbench.tcl
# ### ### ### ######### ######### ######### ###########################
## Public API - Benchmark execution
# ::bench::run --
#
# Run a series of benchmarks.
#
# Arguments:
# ...
#
# Results:
# Dictionary.
proc ::bench::run {args} {
log::debug [linsert $args 0 ::bench::run]
# -errors 0|1 default 1, propagate errors in benchmarks
# -threads <num> default 0, no threads, #threads to use
# -match <pattern> only run tests matching this pattern
# -rmatch <pattern> only run tests matching this pattern
# -iters <num> default 1000, max#iterations for any benchmark
# -pkgdir <dir> Defaults to nothing, regular bench invokation.
# interps - dict (path -> version)
# files - list (of files)
# Process arguments ......................................
# Defaults first, then overides by the user
set errors 1 ; # Propagate errors
set threads 0 ; # Do not use threads
set match {} ; # Do not exclude benchmarks based on glob pattern
set rmatch {} ; # Do not exclude benchmarks based on regex pattern
set iters 1000 ; # Limit #iterations for any benchmark
set pkgdirs {} ; # List of dirs to put in front of auto_path in the
# bench interpreters. Default: nothing.
while {[string match "-*" [set opt [lindex $args 0]]]} {
set val [lindex $args 1]
switch -exact -- $opt {
-errors {
if {![string is boolean -strict $val]} {
return -code error "Expected boolean, got \"$val\""
}
set errors $val
}
-threads {
##nagelfar ignore
if {![string is integer -strict $val] || ($val < 0)} {
return -code error "Expected int >= 0, got \"$val\""
}
set threads [format %d $val]
}
-match {
set match [lindex $args 1]
}
-rmatch {
set rmatch [lindex $args 1]
}
-iters {
##nagelfar ignore
if {![string is integer -strict $val] || ($val <= 0)} {
return -code error "Expected int > 0, got \"$val\""
}
set iters [format %d $val]
}
-pkgdir {
CheckPkgDirArg $val
lappend pkgdirs $val
}
default {
return -code error "Unknown option \"$opt\", should -errors, -threads, -match, -rmatch, or -iters"
}
}
set args [lrange $args 2 end]
}
if {[llength $args] != 2} {
return -code error "wrong\#args, should be: ?options? interp files"
}
foreach {interps files} $args break
# Run the benchmarks .....................................
array set DATA {}
if {![llength $pkgdirs]} {
# No user specified package directories => Simple run.
foreach {ip ver} $interps {
Invoke $ip $ver {} ;# DATA etc passed via upvar.
}
} else {
# User specified package directories.
foreach {ip ver} $interps {
foreach pkgdir $pkgdirs {
Invoke $ip $ver $pkgdir ;# DATA etc passed via upvar.
}
}
}
# Benchmark data ... Structure, dict (key -> value)
#
# Key || Value
# ============ ++ =========================================
# interp IP -> Version. Shell IP was used to run benchmarks. IP is
# the path to the shell.
#
# desc DESC -> "". DESC is description of an executed benchmark.
#
# usec DESC IP -> Result. Result of benchmark DESC when run by the
# shell IP. Usually time in microseconds, but can be
# a special code as well (ERR, BAD_RES).
# ============ ++ =========================================
return [array get DATA]
}
# ::bench::locate --
#
# Locate interpreters on the pathlist, based on a pattern.
#
# Arguments:
# ...
#
# Results:
# List of paths.
proc ::bench::locate {pattern paths} {
# Cache of executables already found.
array set var {}
set res {}
foreach path $paths {
foreach ip [glob -nocomplain [file join $path $pattern]] {
set ip [file normalize $ip]
# Follow soft-links to the actual executable.
while {[string equal link [file type $ip]]} {
set link [file readlink $ip]
if {[string match relative [file pathtype $link]]} {
set ip [file join [file dirname $ip] $link]
} else {
set ip $link
}
}
if {
[file executable $ip] && ![info exists var($ip)]
} {
if {[catch {exec $ip << "exit"} dummy]} {
log::debug "$ip: $dummy"
continue
}
set var($ip) .
lappend res $ip
}
}
}
return $res
}
# ::bench::versions --
#
# Take list of interpreters, find their versions.
# Removes all interps for which it cannot do so.
#
# Arguments:
# List of interpreters (paths)
#
# Results:
# dictionary: interpreter -> version.
proc ::bench::versions {interps} {
set res {}
foreach ip $interps {
if {[catch {
exec $ip << {puts [info patchlevel] ; exit}
} patchlevel]} {
log::debug "$ip: $patchlevel"
continue
}
lappend res [list $patchlevel $ip]
}
# -uniq 8.4-ism, replaced with use of array.
array set tmp {}
set resx {}
foreach item [lsort -dictionary -decreasing -index 0 $res] {
foreach {p ip} $item break
if {[info exists tmp($p)]} continue
set tmp($p) .
lappend resx $ip $p
}
return $resx
}
# ::bench::merge --
#
# Take the data of several benchmark runs and merge them into
# one data set.
#
# Arguments:
# One or more data sets to merge
#
# Results:
# The merged data set.
proc ::bench::merge {args} {
if {[llength $args] == 1} {
return [lindex $args 0]
}
array set DATA {}
foreach data $args {
array set DATA $data
}
return [array get DATA]
}
# ::bench::norm --
#
# Normalize the time data in the dataset, using one of the
# columns as reference.
#
# Arguments:
# Data to normalize
# Index of reference column
#
# Results:
# The normalized data set.
proc ::bench::norm {data col} {
##nagelfar ignore
if {![string is integer -strict $col]} {
return -code error "Ref.column: Expected integer, but got \"$col\""
}
set col [format %d $col]
if {$col < 1} {
return -code error "Ref.column out of bounds"
}
array set DATA $data
set ipkeys [array names DATA interp*]
if {$col > [llength $ipkeys]} {
return -code error "Ref.column out of bounds"
}
incr col -1
set refip [lindex [lindex [lsort -dict $ipkeys] $col] 1]
foreach key [array names DATA] {
if {[string match "desc*" $key]} continue
if {[string match "interp*" $key]} continue
foreach {_ desc ip} $key break
if {[string equal $ip $refip]} continue
set v $DATA($key)
if {![string is double -strict $v]} continue
if {![info exists DATA([list usec $desc $refip])]} {
# We cannot normalize, we do not keep the time value.
# The row will be shown, empty.
set DATA($key) ""
continue
}
set vref $DATA([list usec $desc $refip])
if {![string is double -strict $vref]} continue
set DATA($key) [expr {$v/double($vref)}]
}
foreach key [array names DATA [list * $refip]] {
if {![string is double -strict $DATA($key)]} continue
set DATA($key) 1
}
return [array get DATA]
}
# ::bench::edit --
#
# Change the 'path' of an interp to a user-defined value.
#
# Arguments:
# Data to edit
# Index of column to change
# The value replacing the current path
#
# Results:
# The changed data set.
proc ::bench::edit {data col new} {
##nagelfar ignore
if {![string is integer -strict $col]} {
return -code error "Ref.column: Expected integer, but got \"$col\""
}
set col [format %d $col]
if {$col < 1} {
return -code error "Ref.column out of bounds"
}
array set DATA $data
set ipkeys [array names DATA interp*]
if {$col > [llength $ipkeys]} {
return -code error "Ref.column out of bounds"
}
incr col -1
set refip [lindex [lindex [lsort -dict $ipkeys] $col] 1]
if {[string equal $new $refip]} {
# No change, quick return
return $data
}
set refkey [list interp $refip]
set DATA([list interp $new]) $DATA($refkey)
unset DATA($refkey)
foreach key [array names DATA [list * $refip]] {
if {![string equal [lindex $key 0] "usec"]} continue
foreach {__ desc ip} $key break
set DATA([list usec $desc $new]) $DATA($key)
unset DATA($key)
}
return [array get DATA]
}
# ::bench::del --
#
# Remove the data for an interp.
#
# Arguments:
# Data to edit
# Index of column to remove
#
# Results:
# The changed data set.
proc ::bench::del {data col} {
##nagelfar ignore
if {![string is integer -strict $col]} {
return -code error "Ref.column: Expected integer, but got \"$col\""
}
set col [format %d $col]
if {$col < 1} {
return -code error "Ref.column out of bounds"
}
array set DATA $data
set ipkeys [array names DATA interp*]
if {$col > [llength $ipkeys]} {
return -code error "Ref.column out of bounds"
}
incr col -1
set refip [lindex [lindex [lsort -dict $ipkeys] $col] 1]
unset DATA([list interp $refip])
# Do not use 'array unset'. Keep 8.2 clean.
foreach key [array names DATA [list * $refip]] {
if {![string equal [lindex $key 0] "usec"]} continue
unset DATA($key)
}
return [array get DATA]
}
# ### ### ### ######### ######### ######### ###########################
## Public API - Result formatting.
# ::bench::out::raw --
#
# Format the result of a benchmark run.
# Style: Raw data.
#
# Arguments:
# DATA dict
#
# Results:
# String containing the formatted DATA.
proc ::bench::out::raw {data} {
return $data
}
# ### ### ### ######### ######### ######### ###########################
## Internal commands
proc ::bench::CheckPkgDirArg {path {expected {}}} {
# Allow empty string, special.
if {![string length $path]} return
if {![file isdirectory $path]} {
return -code error \
"The path \"$path\" is not a directory."
}
if {![file readable $path]} {
return -code error \
"The path \"$path\" is not readable."
}
}
proc ::bench::Invoke {ip ver pkgdir} {
variable self
# Import remainder of the current configuration/settings.
upvar 1 DATA DATA match match rmatch rmatch \
iters iters errors errors threads threads \
files files
if {[string length $pkgdir]} {
log::info "Benchmark $ver ($pkgdir) $ip"
set idstr "$ip ($pkgdir)"
} else {
log::info "Benchmark $ver $ip"
set idstr $ip
}
set DATA([list interp $idstr]) $ver
set cmd [list $ip [file join $self libbench.tcl] \
-match $match \
-rmatch $rmatch \
-iters $iters \
-interp $ip \
-errors $errors \
-threads $threads \
-pkgdir $pkgdir \
]
# Determine elapsed time per file, logged.
set start [clock seconds]
array set tmp {}
if {$threads} {
foreach f $files { lappend cmd $f }
if {[catch {
close [Process [open |$cmd r+]]
} output]} {
if {$errors} {
error $::errorInfo
}
}
} else {
foreach file $files {
log::info [file tail $file]
if {[catch {
close [Process [open |[linsert $cmd end $file] r+]]
} output]} {
if {$errors} {
error $::errorInfo
} else {
continue
}
}
}
}
foreach desc [array names tmp] {
set DATA([list desc $desc]) {}
set DATA([list usec $desc $idstr]) $tmp($desc)
}
unset tmp
set elapsed [expr {[clock seconds] - $start}]
set hour [expr {$elapsed / 3600}]
set min [expr {$elapsed / 60}]
set sec [expr {$elapsed % 60}]
log::info " [format %.2d:%.2d:%.2d $hour $min $sec] elapsed"
return
}
proc ::bench::Process {pipe} {
while {1} {
if {[eof $pipe]} break
if {[gets $pipe line] < 0} break
# AK: FUTURE: Log all lines?!
#puts |$line|
set line [string trim $line]
if {[string equal $line ""]} continue
Result
Feedback
# Unknown lines are printed. Future: Callback?!
log::info $line
}
return $pipe
}
proc ::bench::Result {} {
upvar 1 line line
if {[lindex $line 0] ne "RESULT"} return
upvar 2 tmp tmp
foreach {_ desc result} $line break
set tmp($desc) $result
return -code continue
}
proc ::bench::Feedback {} {
upvar 1 line line
if {[lindex $line 0] ne "LOG"} return
# AK: Future - Run through callback?!
log::info [lindex $line 1]
return -code continue
}
# ### ### ### ######### ######### ######### ###########################
## Initialize internal data structures.
namespace eval ::bench {
variable self [file join [pwd] [file dirname [info script]]]
logger::init bench
logger::import -force -all -namespace log bench
}
# ### ### ### ######### ######### ######### ###########################
## Ready to run
package provide bench 0.6

162
src/vendorlib_tcl9/tcllib2.0/bench/bench_read.tcl

@ -0,0 +1,162 @@
# bench_read.tcl --
#
# Management of benchmarks, reading results in various formats.
#
# Copyright (c) 2005 by Andreas Kupries <andreas_kupries@users.sourceforge.net>
# library derived from runbench.tcl application (C) Jeff Hobbs.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: bench_read.tcl,v 1.3 2006/06/13 23:20:30 andreas_kupries Exp $
# ### ### ### ######### ######### ######### ###########################
## Requisites - Packages and namespace for the commands and data.
package require Tcl 8.5 9
package require csv
namespace eval ::bench::in {}
# ### ### ### ######### ######### ######### ###########################
## Public API - Result reading
# ::bench::in::read --
#
# Read a bench result in any of the raw/csv/text formats
#
# Arguments:
# path to file to read
#
# Results:
# DATA dictionary, internal representation of the bench results.
proc ::bench::in::read {file} {
set f [open $file r]
set head [gets $f]
if {![string match "# -\\*- tcl -\\*- bench/*" $head]} {
return -code error "Bad file format, not a benchmark file"
} else {
regexp {bench/(.*)$} $head -> format
switch -exact -- $format {
raw - csv - text {
set res [RD$format $f]
}
default {
return -code error "Bad format \"$val\", expected text, csv, or raw"
}
}
}
close $f
return $res
}
# ### ### ### ######### ######### ######### ###########################
## Internal commands
proc ::bench::in::RDraw {chan} {
return [string trimright [::read $chan]]
}
proc ::bench::in::RDcsv {chan} {
# Lines Format
# First line is number of interpreters #n. int
# Next to 1+n is interpreter data. id,ver,path
# Beyond is benchmark results. id,desc,res1,...,res#n
array set DATA {}
# #Interp ...
set nip [lindex [csv::split [gets $chan]] 0]
# Interp data ...
set iplist {}
for {set i 0} {$i < $nip} {incr i} {
foreach {__ ver ip} [csv::split [gets $chan]] break
set DATA([list interp $ip]) $ver
lappend iplist $ip
}
# Benchmark data ...
while {[gets $chan line] >= 0} {
set line [string trim $line]
if {$line == {}} break
set line [csv::split $line]
set desc [lindex $line 1]
set DATA([list desc $desc]) {}
foreach val [lrange $line 2 end] ip $iplist {
if {$val == {}} continue
set DATA([list usec $desc $ip]) $val
}
}
return [array get DATA]
}
proc ::bench::in::RDtext {chan} {
array set DATA {}
# Interp data ...
# Empty line - ignore
# "id: ver path" - interp data.
# Empty line - separator before benchmark data.
set n 0
set iplist {}
while {[gets $chan line] >= 0} {
set line [string trim $line]
if {$line == {}} {
incr n
if {$n == 2} break
continue
}
regexp {[^:]+: ([^ ]+) (.*)$} $line -> ver ip
set DATA([list interp $ip]) $ver
lappend iplist $ip
}
# Benchmark data ...
# '---' -> Ignore.
# '|' column separators. Remove spaces around it. Then treat line
# as CSV data with a particular separator.
# Ignore the INTERP line.
while {[gets $chan line] >= 0} {
set line [string trim $line]
if {$line == {}} continue
if {[string match "+---*" $line]} continue
if {[string match "*INTERP*" $line]} continue
regsub -all "\\| +" $line {|} line
regsub -all " +\\|" $line {|} line
set line [csv::split [string trim $line |] |]
set desc [lindex $line 1]
set DATA([list desc $desc]) {}
foreach val [lrange $line 2 end] ip $iplist {
if {$val == {}} continue
set DATA([list usec $desc $ip]) $val
}
}
return [array get DATA]
}
# ### ### ### ######### ######### ######### ###########################
## Initialize internal data structures.
# ### ### ### ######### ######### ######### ###########################
## Ready to run
package provide bench::in 0.2

101
src/vendorlib_tcl9/tcllib2.0/bench/bench_wcsv.tcl

@ -0,0 +1,101 @@
# bench_wtext.tcl --
#
# Management of benchmarks, formatted text.
#
# Copyright (c) 2005 by Andreas Kupries <andreas_kupries@users.sourceforge.net>
# library derived from runbench.tcl application (C) Jeff Hobbs.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: bench_wcsv.tcl,v 1.4 2007/01/21 23:29:06 andreas_kupries Exp $
# ### ### ### ######### ######### ######### ###########################
## Requisites - Packages and namespace for the commands and data.
package require Tcl 8.5 9
package require csv
namespace eval ::bench::out {}
# ### ### ### ######### ######### ######### ###########################
## Public API - Benchmark execution
# ### ### ### ######### ######### ######### ###########################
## Public API - Result formatting.
# ::bench::out::csv --
#
# Format the result of a benchmark run.
# Style: CSV
#
# Arguments:
# DATA dict
#
# Results:
# String containing the formatted DATA.
proc ::bench::out::csv {data} {
array set DATA $data
set CSV {}
# 1st record: #shells
# 2nd record to #shells+1: Interpreter data (id, version, path)
# #shells+2 to end: Benchmark data (id,desc,result1,...,result#shells)
# --- --- ----
# #interpreters used
set ipkeys [array names DATA interp*]
lappend CSV [csv::join [list [llength $ipkeys]]]
# --- --- ----
# Table 1: Interpreter information.
set n 1
set iplist {}
foreach key [lsort -dict $ipkeys] {
set ip [lindex $key 1]
lappend CSV [csv::join [list $n $DATA($key) $ip]]
set DATA($key) $n
incr n
lappend iplist $ip
}
# --- --- ----
# Table 2: Benchmark information
set dlist {}
foreach key [lsort -dict -index 1 [array names DATA desc*]] {
lappend dlist [lindex $key 1]
}
set n 1
foreach desc $dlist {
set record {}
lappend record $n
lappend record $desc
foreach ip $iplist {
if {[catch {
lappend record $DATA([list usec $desc $ip])
}]} {
lappend record {}
}
}
lappend CSV [csv::join $record]
incr n
}
return [join $CSV \n]
}
# ### ### ### ######### ######### ######### ###########################
## Internal commands
# ### ### ### ######### ######### ######### ###########################
## Initialize internal data structures.
# ### ### ### ######### ######### ######### ###########################
## Ready to run
package provide bench::out::csv 0.1.3

165
src/vendorlib_tcl9/tcllib2.0/bench/bench_wtext.tcl

@ -0,0 +1,165 @@
# bench_wtext.tcl --
#
# Management of benchmarks, formatted text.
#
# Copyright (c) 2005 by Andreas Kupries <andreas_kupries@users.sourceforge.net>
# library derived from runbench.tcl application (C) Jeff Hobbs.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: bench_wtext.tcl,v 1.4 2007/01/21 23:29:06 andreas_kupries Exp $
# ### ### ### ######### ######### ######### ###########################
## Requisites - Packages and namespace for the commands and data.
package require Tcl 8.5 9
package require struct::matrix
package require report
namespace eval ::bench::out {}
# ### ### ### ######### ######### ######### ###########################
## Public API - Result formatting.
# ::bench::out::text --
#
# Format the result of a benchmark run.
# Style: TEXT
#
# General structure like CSV, but nicely formatted and aligned
# columns.
#
# Arguments:
# DATA dict
#
# Results:
# String containing the formatted DATA.
proc ::bench::out::text {data} {
array set DATA $data
set LINES {}
# 1st line to #shells: Interpreter data (id, version, path)
# #shells+1 to end: Benchmark data (id,desc,result1,...,result#shells)
lappend LINES {}
# --- --- ----
# Table 1: Interpreter information.
set ipkeys [array names DATA interp*]
set n 1
set iplist {}
set vlen 0
foreach key [lsort -dict $ipkeys] {
lappend iplist [lindex $key 1]
incr n
set l [string length $DATA($key)]
if {$l > $vlen} {set vlen $l}
}
set idlen [string length $n]
set dlist {}
set n 1
foreach key [lsort -dict -index 1 [array names DATA desc*]] {
lappend dlist [lindex $key 1]
incr n
}
set didlen [string length $n]
set n 1
set record [list "" INTERP]
foreach ip $iplist {
set v $DATA([list interp $ip])
lappend LINES " [PADL $idlen $n]: [PADR $vlen $v] $ip"
lappend record $n
incr n
}
lappend LINES {}
# --- --- ----
# Table 2: Benchmark information
set m [struct::matrix m]
$m add columns [expr {2 + [llength $iplist]}]
$m add row $record
set n 1
foreach desc $dlist {
set record [list $n]
lappend record $desc
foreach ip $iplist {
if {[catch {
set val $DATA([list usec $desc $ip])
}]} {
set val {}
}
if {[string is double -strict $val]} {
lappend record [format %.2f $val]
} else {
lappend record [format %s $val]
}
}
$m add row $record
incr n
}
::report::defstyle simpletable {} {
data set [split "[string repeat "| " [columns]]|"]
top set [split "[string repeat "+ - " [columns]]+"]
bottom set [top get]
top enable
bottom enable
set c [columns]
justify 0 right
pad 0 both
if {$c > 1} {
justify 1 left
pad 1 both
}
for {set i 2} {$i < $c} {incr i} {
justify $i right
pad $i both
}
}
::report::defstyle captionedtable {{n 1}} {
simpletable
topdata set [data get]
topcapsep set [top get]
topcapsep enable
tcaption $n
}
set r [report::report r [$m columns] style captionedtable]
lappend LINES [$m format 2string $r]
$m destroy
$r destroy
return [join $LINES \n]
}
# ### ### ### ######### ######### ######### ###########################
## Internal commands
proc ::bench::out::PADL {max str} {
format "%${max}s" $str
#return "[PAD $max $str]$str"
}
proc ::bench::out::PADR {max str} {
format "%-${max}s" $str
#return "$str[PAD $max $str]"
}
# ### ### ### ######### ######### ######### ###########################
## Initialize internal data structures.
# ### ### ### ######### ######### ######### ###########################
## Ready to run
package provide bench::out::text 0.1.3

561
src/vendorlib_tcl9/tcllib2.0/bench/libbench.tcl

@ -0,0 +1,561 @@
# -*- tcl -*-
# libbench.tcl ?(<option> <value>)...? <benchFile>...
#
# This file has to have code that works in any version of Tcl that
# the user would want to benchmark.
#
# RCS: @(#) $Id: libbench.tcl,v 1.4 2008/07/02 23:34:06 andreas_kupries Exp $
#
# Copyright (c) 2000-2001 Jeffrey Hobbs.
# Copyright (c) 2007 Andreas Kupries
#
# This code provides the supporting commands for the execution of a
# benchmark files. It is actually an application and is exec'd by the
# management code.
# Options:
# -help Print usage message.
# -rmatch <regexp-pattern> Run only tests whose description matches the pattern.
# -match <glob-pattern> Run only tests whose description matches the pattern.
# -interp <name> Name of the interp running the benchmarks.
# -thread <num> Invoke threaded benchmarks, number of threads to use.
# -errors <boolean> Throw errors, or not.
# Note: If both -match and -rmatch are specified then _both_
# apply. I.e. a benchmark will be run if and only if it matches both
# patterns.
# Application activity and results are communicated to the highlevel
# management via text written to stdout. Each line written is a list
# and has one of the following forms:
#
# __THREADED <version> - Indicates threaded mode, and version
# of package Thread in use.
#
# Sourcing {<desc>: <res>} - Benchmark <desc> has started.
# <res> is the result from executing
# it once (compilation of body.)
#
# Sourcing <file> - Benchmark file <file> starts execution.
#
# <desc> <res> - Result of a benchmark.
#
# The above implies that no benchmark may use the strings 'Sourcing'
# or '__THREADED' as their description.
# We will put our data into these named globals.
global BENCH bench
# 'BENCH' contents:
#
# - ERRORS : Boolean flag. If set benchmark output mismatches are
# reported by throwing an error. Otherwise they are simply
# listed as BAD_RES. Default true. Can be set/reset via
# option -errors.
#
# - MATCH : Match pattern, see -match, default empty, aka everything
# matches.
#
# - RMATCH : Match pattern, see -rmatch, default empty, aka
# everything matches.
#
# - OUTFILE : Name of output file, default is special value "stdout".
# - OUTFID : Channel for output.
#
# The outfile cannot be set by the caller, thus output is always
# written to stdout.
#
# - FILES : List of benchmark files to run.
#
# - ITERS : Number of iterations to run a benchmark body, default
# 1000. Can be overridden by the individual benchmarks.
#
# - THREADS : Number of threads to use. 0 signals no threading.
# Limited to number of files if there are less files than
# requested threads.
#
# - EXIT : Boolean flag. True when appplication is run by wish, for
# special exit processing. ... Actually always true.
#
# - INTERP : Name of the interpreter running the benchmarks. Is the
# executable running this code. Can be overridden via the
# command line option -interp.
#
# - uniqid : Counter for 'bench_tmpfile' to generate unique names of
# tmp files.
#
# - us : Thread id of main thread.
#
# - inuse : Number of threads active, present and relevant only in
# threaded mode.
#
# - file : Currently executed benchmark file. Relevant only in
# non-threaded mode.
#
# 'bench' contents.
# Benchmark results, mapping from the benchmark descriptions to their
# results. Usually time in microseconds, but the following special
# values can occur:
#
# - BAD_RES - Result from benchmark body does not match expectations.
# - ERR - Benchmark body aborted with an error.
# - Any string - Forced by error code 666 to pass to management.
#
# We claim all procedures starting with bench*
#
# bench_tmpfile --
#
# Return a temp file name that can be modified at will
#
# Arguments:
# None
#
# Results:
# Returns file name
#
proc bench_tmpfile {} {
global tcl_platform env BENCH
if {![info exists BENCH(uniqid)]} { set BENCH(uniqid) 0 }
set base "tclbench[incr BENCH(uniqid)].dat"
if {[info exists tcl_platform(platform)]} {
if {$tcl_platform(platform) == "unix"} {
return "/tmp/$base"
} elseif {$tcl_platform(platform) == "windows"} {
return [file join $env(TEMP) $base]
} else {
return $base
}
} else {
# The Good Ol' Days (?) when only Unix support existed
return "/tmp/$base"
}
}
# bench_rm --
#
# Remove a file silently (no complaining)
#
# Arguments:
# args Files to delete
#
# Results:
# Returns nothing
#
proc bench_rm {args} {
foreach file $args {
if {[info tclversion] > 7.4} {
catch {file delete $file}
} else {
catch {exec /bin/rm $file}
}
}
}
proc bench_puts {args} {
eval [linsert $args 0 FEEDBACK]
return
}
# bench --
#
# Main bench procedure.
# The bench test is expected to exit cleanly. If an error occurs,
# it will be thrown all the way up. A bench proc may return the
# special code 666, which says take the string as the bench value.
# This is usually used for N/A feature situations.
#
# Arguments:
#
# -pre script to run before main timed body
# -body script to run as main timed body
# -post script to run after main timed body
# -ipre script to run before timed body, per iteration of the body.
# -ipost script to run after timed body, per iteration of the body.
# -desc message text
# -iterations <#>
#
# Note:
#
# Using -ipre and/or -ipost will cause us to compute the average
# time ourselves, i.e. 'time body 1' n times. Required to ensure
# that prefix/post operation are executed, yet not timed themselves.
#
# Results:
#
# Returns nothing
#
# Side effects:
#
# Sets up data in bench global array
#
proc bench {args} {
global BENCH bench errorInfo errorCode
# -pre script
# -body script
# -desc msg
# -post script
# -ipre script
# -ipost script
# -iterations <#>
array set opts {
-pre {}
-body {}
-desc {}
-post {}
-ipre {}
-ipost {}
}
set opts(-iter) $BENCH(ITERS)
while {[llength $args]} {
set key [lindex $args 0]
switch -glob -- $key {
-res* { set opts(-res) [lindex $args 1] }
-pr* { set opts(-pre) [lindex $args 1] }
-po* { set opts(-post) [lindex $args 1] }
-ipr* { set opts(-ipre) [lindex $args 1] }
-ipo* { set opts(-ipost) [lindex $args 1] }
-bo* { set opts(-body) [lindex $args 1] }
-de* { set opts(-desc) [lindex $args 1] }
-it* {
# Only change the iterations when it is smaller than
# the requested default
set val [lindex $args 1]
if {$opts(-iter) > $val} { set opts(-iter) $val }
}
default {
error "unknown option $key"
}
}
set args [lreplace $args 0 1]
}
FEEDBACK "Running <$opts(-desc)>"
if {($BENCH(MATCH) != "") && ![string match $BENCH(MATCH) $opts(-desc)]} {
return
}
if {($BENCH(RMATCH) != "") && ![regexp $BENCH(RMATCH) $opts(-desc)]} {
return
}
if {$opts(-pre) != ""} {
uplevel \#0 $opts(-pre)
}
if {$opts(-body) != ""} {
# always run it once to remove compile phase confusion
if {$opts(-ipre) != ""} {
uplevel \#0 $opts(-ipre)
}
set code [catch {uplevel \#0 $opts(-body)} res]
if {$opts(-ipost) != ""} {
uplevel \#0 $opts(-ipost)
}
if {!$code && [info exists opts(-res)] \
&& [string compare $opts(-res) $res]} {
if {$BENCH(ERRORS)} {
return -code error "Result was:\n$res\nResult\
should have been:\n$opts(-res)"
} else {
set res "BAD_RES"
}
#set bench($opts(-desc)) $res
RESULT $opts(-desc) $res
} else {
if {($opts(-ipre) != "") || ($opts(-ipost) != "")} {
# We do the averaging on our own, to allow untimed
# pre/post execution per iteration. We catch and
# handle problems in the pre/post code as if
# everything was executed as one block (like it would
# be in the other path). We are using floating point
# to avoid integer overflow, easily happening when
# accumulating a high number (iterations) of large
# integers (microseconds).
set total 0.0
for {set i 0} {$i < $opts(-iter)} {incr i} {
set code 0
if {$opts(-ipre) != ""} {
set code [catch {uplevel \#0 $opts(-ipre)} res]
if {$code} break
}
set code [catch {uplevel \#0 [list time $opts(-body) 1]} res]
if {$code} break
set total [expr {$total + [lindex $res 0]}]
if {$opts(-ipost) != ""} {
set code [catch {uplevel \#0 $opts(-ipost)} res]
if {$code} break
}
}
if {!$code} {
set res [list [expr {int ($total/$opts(-iter))}] microseconds per iteration]
}
} else {
set code [catch {uplevel \#0 \
[list time $opts(-body) $opts(-iter)]} res]
}
if {!$BENCH(THREADS)} {
if {$code == 0} {
# Get just the microseconds value from the time result
set res [lindex $res 0]
} elseif {$code != 666} {
# A 666 result code means pass it through to the bench
# suite. Otherwise throw errors all the way out, unless
# we specified not to throw errors (option -errors 0 to
# libbench).
if {$BENCH(ERRORS)} {
return -code $code -errorinfo $errorInfo \
-errorcode $errorCode
} else {
set res "ERR"
}
}
#set bench($opts(-desc)) $res
RESULT $opts(-desc) $res
} else {
# Threaded runs report back asynchronously
thread::send $BENCH(us) \
[list thread_report $opts(-desc) $code $res]
}
}
}
if {($opts(-post) != "") && [catch {uplevel \#0 $opts(-post)} err] \
&& $BENCH(ERRORS)} {
return -code error "post code threw error:\n$err"
}
return
}
proc RESULT {desc time} {
global BENCH
puts $BENCH(OUTFID) [list RESULT $desc $time]
return
}
proc FEEDBACK {text} {
global BENCH
puts $BENCH(OUTFID) [list LOG $text]
return
}
proc usage {} {
set me [file tail [info script]]
puts stderr "Usage: $me ?options?\
\n\t-help # print out this message\
\n\t-rmatch <regexp> # only run tests matching this pattern\
\n\t-match <glob> # only run tests matching this pattern\
\n\t-interp <name> # name of interp (tries to get it right)\
\n\t-thread <num> # number of threads to use\
\n\tfileList # files to benchmark"
exit 1
}
#
# Process args
#
if {[catch {set BENCH(INTERP) [info nameofexec]}]} {
set BENCH(INTERP) $argv0
}
foreach {var val} {
ERRORS 1
MATCH {}
RMATCH {}
OUTFILE stdout
FILES {}
ITERS 1000
THREADS 0
PKGDIR {}
EXIT "[info exists tk_version]"
} {
if {![info exists BENCH($var)]} {
set BENCH($var) [subst $val]
}
}
set BENCH(EXIT) 1
if {[llength $argv]} {
while {[llength $argv]} {
set key [lindex $argv 0]
switch -glob -- $key {
-help* { usage }
-err* { set BENCH(ERRORS) [lindex $argv 1] }
-int* { set BENCH(INTERP) [lindex $argv 1] }
-rmat* { set BENCH(RMATCH) [lindex $argv 1] }
-mat* { set BENCH(MATCH) [lindex $argv 1] }
-iter* { set BENCH(ITERS) [lindex $argv 1] }
-thr* { set BENCH(THREADS) [lindex $argv 1] }
-pkg* { set BENCH(PKGDIR) [lindex $argv 1] }
default {
foreach arg $argv {
if {![file exists $arg]} { usage }
lappend BENCH(FILES) $arg
}
break
}
}
set argv [lreplace $argv 0 1]
}
}
if {[string length $BENCH(PKGDIR)]} {
set auto_path [linsert $auto_path 0 $BENCH(PKGDIR)]
}
if {$BENCH(THREADS)} {
# We have to be able to load threads if we want to use threads, and
# we don't want to create more threads than we have files.
if {[catch {package require Thread}]} {
set BENCH(THREADS) 0
} elseif {[llength $BENCH(FILES)] < $BENCH(THREADS)} {
set BENCH(THREADS) [llength $BENCH(FILES)]
}
}
rename exit exit.true
proc exit args {
error "called \"exit $args\" in benchmark test"
}
if {[string compare $BENCH(OUTFILE) stdout]} {
set BENCH(OUTFID) [open $BENCH(OUTFILE) w]
} else {
set BENCH(OUTFID) stdout
}
#
# Everything that gets output must be in pairwise format, because
# the data will be collected in via an 'array set'.
#
if {$BENCH(THREADS)} {
# Each file must run in it's own thread because of all the extra
# header stuff they have.
#set DEBUG 1
proc thread_one {{id 0}} {
global BENCH
set file [lindex $BENCH(FILES) 0]
set BENCH(FILES) [lrange $BENCH(FILES) 1 end]
if {[file exists $file]} {
incr BENCH(inuse)
FEEDBACK [list Sourcing $file]
if {$id} {
set them $id
} else {
set them [thread::create]
thread::send -async $them { load {} Thread }
thread::send -async $them \
[list array set BENCH [array get BENCH]]
thread::send -async $them \
[list proc bench_tmpfile {} [info body bench_tmpfile]]
thread::send -async $them \
[list proc bench_rm {args} [info body bench_rm]]
thread::send -async $them \
[list proc bench {args} [info body bench]]
}
if {[info exists ::DEBUG]} {
FEEDBACK "SEND [clock seconds] thread $them $file INUSE\
$BENCH(inuse) of $BENCH(THREADS)"
}
thread::send -async $them [list source $file]
thread::send -async $them \
[list thread::send $BENCH(us) [list thread_ready $them]]
#thread::send -async $them { thread::unwind }
}
}
proc thread_em {} {
global BENCH
while {[llength $BENCH(FILES)]} {
if {[info exists ::DEBUG]} {
FEEDBACK "THREAD ONE [lindex $BENCH(FILES) 0]"
}
thread_one
if {$BENCH(inuse) >= $BENCH(THREADS)} {
break
}
}
}
proc thread_ready {id} {
global BENCH
incr BENCH(inuse) -1
if {[llength $BENCH(FILES)]} {
if {[info exists ::DEBUG]} {
FEEDBACK "SEND ONE [clock seconds] thread $id"
}
thread_one $id
} else {
if {[info exists ::DEBUG]} {
FEEDBACK "UNWIND thread $id"
}
thread::send -async $id { thread::unwind }
}
}
proc thread_report {desc code res} {
global BENCH bench errorInfo errorCode
if {$code == 0} {
# Get just the microseconds value from the time result
set res [lindex $res 0]
} elseif {$code != 666} {
# A 666 result code means pass it through to the bench suite.
# Otherwise throw errors all the way out, unless we specified
# not to throw errors (option -errors 0 to libbench).
if {$BENCH(ERRORS)} {
return -code $code -errorinfo $errorInfo \
-errorcode $errorCode
} else {
set res "ERR"
}
}
#set bench($desc) $res
RESULT $desc $res
}
proc thread_finish {{delay 4000}} {
global BENCH bench
set val [expr {[llength [thread::names]] > 1}]
#set val [expr {$BENCH(inuse)}]
if {$val} {
after $delay [info level 0]
} else {
if {0} {foreach desc [array names bench] {
RESULT $desc $bench($desc)
}}
if {$BENCH(EXIT)} {
exit.true ; # needed for Tk tests
}
}
}
set BENCH(us) [thread::id]
set BENCH(inuse) 0 ; # num threads in use
FEEDBACK [list __THREADED [package provide Thread]]
thread_em
thread_finish
vwait forever
} else {
foreach BENCH(file) $BENCH(FILES) {
if {[file exists $BENCH(file)]} {
FEEDBACK [list Sourcing $BENCH(file)]
source $BENCH(file)
}
}
if {0} {foreach desc [array names bench] {
RESULT $desc $bench($desc)
}}
if {$BENCH(EXIT)} {
exit.true ; # needed for Tk tests
}
}

7
src/vendorlib_tcl9/tcllib2.0/bench/pkgIndex.tcl

@ -0,0 +1,7 @@
if {![package vsatisfies [package provide Tcl] 8.5 9]} {
return
}
package ifneeded bench 0.6 [list source [file join $dir bench.tcl]]
package ifneeded bench::out::text 0.1.3 [list source [file join $dir bench_wtext.tcl]]
package ifneeded bench::out::csv 0.1.3 [list source [file join $dir bench_wcsv.tcl]]
package ifneeded bench::in 0.2 [list source [file join $dir bench_read.tcl]]

501
src/vendorlib_tcl9/tcllib2.0/bibtex/bibtex.tcl

@ -0,0 +1,501 @@
#####
#
# "BibTeX parser"
# http://wiki.tcl.tk/13719
#
# Tcl code harvested on: 7 Mar 2005, 23:55 GMT
# Wiki page last updated: ???
#
#####
# bibtex.tcl --
#
# A basic parser for BibTeX bibliography databases.
#
# Copyright (c) 2005 Neil Madden.
# Copyright (c) 2005 Andreas Kupries.
# License: Tcl/BSD style.
### NOTES
###
### Need commands to introspect parser state. Especially the string
### map (for testing of 'addStrings', should be useful in general as
### well).
# ### ### ### ######### ######### #########
## Requisites
package require Tcl 8.5 9
package require cmdline
# ### ### ### ######### ######### #########
## Implementation: Public API
namespace eval ::bibtex {}
# bibtex::parse --
#
# Parse a bibtex file.
#
# parse ?options? ?bibtex?
proc ::bibtex::parse {args} {
variable data
variable id
# Argument processing
if {[llength $args] < 1} {
set err "[lindex [info level 0] 0] ?options? ?bibtex?"
return -code error "wrong # args: should be \"$err\""
}
array set state {}
GetOptions $args state
# Initialize the parser state from the options, fill in default
# values, and handle the input according the specified mode.
set token bibtex[incr id]
foreach {k v} [array get state] {
set data($token,$k) $v
}
if {$state(stream)} {
# Text not in memory
if {!$state(bg)} {
# Text from a channel, no async processing. We read everything
# into memory and the handle it as before.
set blockmode [fconfigure $state(-channel) -blocking]
fconfigure $state(-channel) -blocking 1
set data($token,buffer) [read $state(-channel)]
fconfigure $state(-channel) -blocking $blockmode
# Tell upcoming processing that the text is in memory.
set state(stream) 0
} else {
# Text from a channel, and processing is async. Create an
# event handler for the incoming data.
set data($token,done) 0
fileevent $state(-channel) readable \
[list ::bibtex::ReadChan $token]
# Initialize the parser internal result buffer if we use plain
# -command, and not the SAX api.
if {!$state(sax)} {
set data($token,result) {}
}
}
}
# Initialize the string mappings (none known), and the result
# accumulator.
set data($token,strings) {}
set data($token,result) {}
if {!$state(stream)} {
ParseRecords $token 1
if {$state(sax)} {
set result $token
} else {
set result $data($token,result)
destroy $token
}
return $result
}
# Assert: Processing is in background.
return $token
}
# Cleanup a parser, cancelling any callbacks etc.
proc ::bibtex::destroy {token} {
variable data
if {![info exists data($token,stream)]} {
return -code error "Illegal bibtex parser \"$token\""
}
if {$data($token,stream)} {
fileevent $data($token,-channel) readable {}
}
array unset data $token,*
return
}
proc ::bibtex::wait {token} {
variable data
if {![info exists data($token,stream)]} {
return -code error "Illegal bibtex parser \"$token\""
}
vwait ::bibtex::data($token,done)
return
}
# bibtex::addStrings --
#
# Add strings to the map for a particular parser. All strings are
# expanded at parse time.
proc ::bibtex::addStrings {token strings} {
variable data
eval [linsert $strings 0 lappend data($token,strings)]
return
}
# ### ### ### ######### ######### #########
## Implementation: Private utility routines
proc ::bibtex::AddRecord {token type key recdata} {
variable data
lappend data($token,result) [list $type $key $recdata]
return
}
proc ::bibtex::GetOptions {argv statevar} {
upvar 1 $statevar state
# Basic processing of the argument list
# and the options found therein.
set opts [lrange [::cmdline::GetOptionDefaults {
{command.arg {}}
{channel.arg {}}
{recordcommand.arg {}}
{preamblecommand.arg {}}
{stringcommand.arg {}}
{commentcommand.arg {}}
{progresscommand.arg {}}
{casesensitivestrings.arg {}}
} result] 2 end] ;# Remove ? and help.
set argc [llength $argv]
while {[set err [::cmdline::getopt argv $opts opt arg]]} {
if {$err < 0} {
set olist ""
foreach o [lsort $opts] {
if {[string match *.arg $o]} {
set o [string range $o 0 end-4]
}
lappend olist -$o
}
return -code error "bad option \"$opt\",\
should be one of\
[linsert [join $olist ", "] end-1 or]"
}
set state(-$opt) $arg
}
# Check the information gained so far
# for inconsistencies and/or missing
# pieces.
set sax [expr {
[info exists state(-recordcommand)] ||
[info exists state(-preamblecommand)] ||
[info exists state(-stringcommand)] ||
[info exists state(-commentcommand)] ||
[info exists state(-progresscommand)]
}] ; # {}
set bg [info exists state(-command)]
if {$sax && $bg} {
# Sax callbacks and channel completion callback exclude each
# other.
return -code error "The options -command and -TYPEcommand exclude each other"
}
set stream [info exists state(-channel)]
if {$stream} {
# Channel is present, a text is not allowed.
if {[llength $argv]} {
return -code error "Option -channel and text exclude each other"
}
# The channel has to exist as well.
if {[lsearch -exact [file channels] $state(-channel)] < 0} {
return -code error "Illegal channel handle \"$state(-channel)\""
}
} else {
# Channel is not present, we have to have a text, and only
# exactly one. And a general -command callback is not allowed.
if {![llength $argv]} {
return -code error "Neither -channel nor text specified"
} elseif {[llength $argv] > 1} {
return -code error "wrong # args: [lindex [info level 1] 0] ?options? ?bibtex?"
}
# Channel completion callback is not allowed if we are not
# reading from a channel.
if {$bg} {
return -code error "Option -command and text exclude each other"
}
set state(buffer) [lindex $argv 0]
}
set state(stream) $stream
set state(sax) $sax
set state(bg) [expr {$sax || $bg}]
if {![info exists state(-stringcommand)]} {
set state(-stringcommand) [list ::bibtex::addStrings]
}
if {![info exists state(-recordcommand)] && (!$sax)} {
set state(-recordcommand) [list ::bibtex::AddRecord]
}
if {[info exists state(-casesensitivestrings)] &&
$state(-casesensitivestrings)
} {
set state(casesensitivestrings) 1
} else {
set state(casesensitivestrings) 0
}
return
}
proc ::bibtex::Callback {token type args} {
variable data
#puts stdout "Callback ($token $type ($args))"
if {[info exists data($token,-${type}command)]} {
eval $data($token,-${type}command) [linsert $args 0 $token]
}
return
}
proc ::bibtex::ReadChan {token} {
variable data
# Read the waiting characters into our buffer and process
# them. The records are saved either through a user supplied
# record callback, or the standard callback for our non-sax
# processing.
set chan $data($token,-channel)
append data($token,buffer) [read $chan]
if {[eof $chan]} {
# Final processing. In non-SAX mode we have to deliver the
# completed result before destroying the parser.
ParseRecords $token 1
set data($token,done) 1
if {!$data($token,sax)} {
Callback $token {} $data($token,result)
}
return
}
# Processing of partial data.
ParseRecords $token 0
return
}
proc ::bibtex::Tidy {str} {
return [string tolower [string trim $str]]
}
proc ::bibtex::ParseRecords {token eof} {
# A rough BibTeX grammar (case-insensitive):
#
# Database ::= (Junk '@' Entry)*
# Junk ::= .*?
# Entry ::= Record
# | Comment
# | String
# | Preamble
# Comment ::= "comment" [^\n]* \n -- ignored
# String ::= "string" '{' Field* '}'
# Preamble ::= "preamble" '{' .* '}' -- (balanced)
# Record ::= Type '{' Key ',' Field* '}'
# | Type '(' Key ',' Field* ')' -- not handled
# Type ::= Name
# Key ::= Name
# Field ::= Name '=' Value
# Name ::= [^\s\"#%'(){}]*
# Value ::= [0-9]+
# | '"' ([^'"']|\\'"')* '"'
# | '{' .* '}' -- (balanced)
# " - Fixup emacs hilit confusion from the grammar above.
variable data
set bibtex $data($token,buffer)
# Split at each @ character which is at the beginning of a line,
# modulo whitespace. This is a heuristic to distinguish the @'s
# starting a new record from the @'s occuring inside a record, as
# part of email addresses. Empty pices at beginning or end are
# stripped before the split.
regsub -line -all {^[\n\r\f\t ]*@} $bibtex \000 bibtex
set db [split [string trim $bibtex \000] \000]
if {$eof} {
set total [llength $db]
set step [expr {double($total) / 100.0}]
set istep [expr {$step > 1 ? int($step) : 1}]
set count 0
} else {
if {[llength $db] < 2} {
# Nothing to process, or data which ay be incomplete.
return
}
set data($token,buffer) [lindex $db end]
set db [lrange $db 0 end-1]
# Fake progress meter.
set count -1
}
foreach block $db {
if {$count < 0} {
Callback $token progress -1
} elseif {([incr count] % $istep) == 0} {
Callback $token progress [expr {int($count / $step)}]
}
if {[regexp -nocase {\s*comment([^\n])*\n(.*)} $block \
-> cmnt rest]} {
# Are @comments blocks, or just 1 line?
# Does anyone care?
Callback $token comment $cmnt
} elseif {[regexp -nocase {^\s*string[^\{]*\{(.*)\}[^\}]*} \
$block -> rest]} {
# string macro defs
if {$data($token,casesensitivestrings)} {
Callback $token string [ParseString $rest]
} else {
Callback $token string [ParseBlock $rest]
}
} elseif {[regexp -nocase {\s*preamble[^\{]*\{(.*)\}[^\}]*} \
$block -> rest]} {
Callback $token preamble $rest
} elseif {[regexp {([^\{]+)\{([^,]*),(.*)\}[^\}]*} \
$block -> type key rest]} {
# Do any @string mappings
if {$data($token,casesensitivestrings)} {
# puts $data($token,strings)
set rest [string map $data($token,strings) $rest]
} else {
set rest [string map -nocase $data($token,strings) $rest]
}
Callback $token record [Tidy $type] [string trim $key] \
[ParseBlock $rest]
} else {
## FUTURE: Use a logger.
puts stderr "Skipping: $block"
}
}
}
proc ::bibtex::ParseString {block} {
regexp {(\S+)[^=]*=(.*)} $block -> key rest
return [list $key $rest]
}
proc ::bibtex::ParseBlock {block} {
set ret [list]
set index 0
while {
[regexp -start $index -indices -- \
{(\S+)\s*=(.*)} $block -> key rest]
} {
foreach {ks ke} $key break
set k [Tidy [string range $block $ks $ke]]
foreach {rs re} $rest break
foreach {v index} \
[ParseBibString $rs [string range $block $rs $re]] \
break
lappend ret $k $v
}
return $ret
}
proc ::bibtex::ParseBibString {index str} {
set count 0
set retstr ""
set escape 0
set string 0
foreach char [split $str ""] {
incr index
if {$escape} {
set escape 0
} else {
if {$char eq "\{"} {
incr count
continue
} elseif {$char eq "\}"} {
incr count -1
if {$count < 0} {incr index -1; break}
continue
} elseif {$char eq ","} {
if {$count == 0} break
} elseif {$char eq "\\"} {
set escape 1
continue
} elseif {$char eq "\""} {
# Handling the case where str is surrounded by
# quotation marks instead of braces (as some journals
# may, perhaps erroneously, print some field. e.g.:
# https://www.epj.org/)
if {$count == 0} {
incr count
} elseif {$count == 1} {
incr count -1
}
continue
}
# else: Nothing
}
append retstr $char
}
regsub -all {\s+} $retstr { } retstr
return [list [string trim $retstr] $index]
}
# ### ### ### ######### ######### #########
## Internal. Package configuration and state.
namespace eval bibtex {
# Counter for the generation of parser tokens.
variable id 0
# State of all parsers. Keys for each parser are prefixed with the
# parser token.
variable data
array set data {}
# Keys and their meaning (listed without token prefix)
##
# buffer
# eof
# channel <-\/- Difference ?
# strings |
# -async |
# -blocksize |
# -channel <-/
# -recordcommand -- callback for each record
# -preamblecommand -- callback for @preamble blocks
# -stringcommand -- callback for @string macros
# -commentcommand -- callback for @comment blocks
# -progresscommand -- callback to indicate progress of parse
##
}
# ### ### ### ######### ######### #########
## Ready to go
package provide bibtex 0.8
# EOF

2
src/vendorlib_tcl9/tcllib2.0/bibtex/pkgIndex.tcl

@ -0,0 +1,2 @@
if {![package vsatisfies [package provide Tcl] 8.5 9]} {return}
package ifneeded bibtex 0.8 [list source [file join $dir bibtex.tcl]]

755
src/vendorlib_tcl9/tcllib2.0/blowfish/blowfish.tcl

@ -0,0 +1,755 @@
# blowfish.tcl -
#
# Pure-Tcl implementation of the Blowfish algorithm.
#
# See http://www.schneier.com/blowfish.html for information about the
# Blowfish algorithm.
#
# The implementation is derived from Paul Kocher's implementation,
# available at http://www.schneier.com/blowfish-download.html
#
# Copyright (C) 2004 Frank Pilhofer
# Copyright (C) 2004 Pat Thoyts <patthoyts@users.sourceforge.net>
#
# -------------------------------------------------------------------------
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
# -------------------------------------------------------------------------
#
package require Tcl 8.5 9
namespace eval blowfish {
variable uid
if {![info exists uid]} { set uid 0 }
variable accel
array set accel {trf 0}
namespace export blowfish
variable ORIG_P {
0x243F6A88 0x85A308D3 0x13198A2E 0x03707344
0xA4093822 0x299F31D0 0x082EFA98 0xEC4E6C89
0x452821E6 0x38D01377 0xBE5466CF 0x34E90C6C
0xC0AC29B7 0xC97C50DD 0x3F84D5B5 0xB5470917
0x9216D5D9 0x8979FB1B
}
variable ORIG_S {
0xD1310BA6 0x98DFB5AC 0x2FFD72DB 0xD01ADFB7
0xB8E1AFED 0x6A267E96 0xBA7C9045 0xF12C7F99
0x24A19947 0xB3916CF7 0x0801F2E2 0x858EFC16
0x636920D8 0x71574E69 0xA458FEA3 0xF4933D7E
0x0D95748F 0x728EB658 0x718BCD58 0x82154AEE
0x7B54A41D 0xC25A59B5 0x9C30D539 0x2AF26013
0xC5D1B023 0x286085F0 0xCA417918 0xB8DB38EF
0x8E79DCB0 0x603A180E 0x6C9E0E8B 0xB01E8A3E
0xD71577C1 0xBD314B27 0x78AF2FDA 0x55605C60
0xE65525F3 0xAA55AB94 0x57489862 0x63E81440
0x55CA396A 0x2AAB10B6 0xB4CC5C34 0x1141E8CE
0xA15486AF 0x7C72E993 0xB3EE1411 0x636FBC2A
0x2BA9C55D 0x741831F6 0xCE5C3E16 0x9B87931E
0xAFD6BA33 0x6C24CF5C 0x7A325381 0x28958677
0x3B8F4898 0x6B4BB9AF 0xC4BFE81B 0x66282193
0x61D809CC 0xFB21A991 0x487CAC60 0x5DEC8032
0xEF845D5D 0xE98575B1 0xDC262302 0xEB651B88
0x23893E81 0xD396ACC5 0x0F6D6FF3 0x83F44239
0x2E0B4482 0xA4842004 0x69C8F04A 0x9E1F9B5E
0x21C66842 0xF6E96C9A 0x670C9C61 0xABD388F0
0x6A51A0D2 0xD8542F68 0x960FA728 0xAB5133A3
0x6EEF0B6C 0x137A3BE4 0xBA3BF050 0x7EFB2A98
0xA1F1651D 0x39AF0176 0x66CA593E 0x82430E88
0x8CEE8619 0x456F9FB4 0x7D84A5C3 0x3B8B5EBE
0xE06F75D8 0x85C12073 0x401A449F 0x56C16AA6
0x4ED3AA62 0x363F7706 0x1BFEDF72 0x429B023D
0x37D0D724 0xD00A1248 0xDB0FEAD3 0x49F1C09B
0x075372C9 0x80991B7B 0x25D479D8 0xF6E8DEF7
0xE3FE501A 0xB6794C3B 0x976CE0BD 0x04C006BA
0xC1A94FB6 0x409F60C4 0x5E5C9EC2 0x196A2463
0x68FB6FAF 0x3E6C53B5 0x1339B2EB 0x3B52EC6F
0x6DFC511F 0x9B30952C 0xCC814544 0xAF5EBD09
0xBEE3D004 0xDE334AFD 0x660F2807 0x192E4BB3
0xC0CBA857 0x45C8740F 0xD20B5F39 0xB9D3FBDB
0x5579C0BD 0x1A60320A 0xD6A100C6 0x402C7279
0x679F25FE 0xFB1FA3CC 0x8EA5E9F8 0xDB3222F8
0x3C7516DF 0xFD616B15 0x2F501EC8 0xAD0552AB
0x323DB5FA 0xFD238760 0x53317B48 0x3E00DF82
0x9E5C57BB 0xCA6F8CA0 0x1A87562E 0xDF1769DB
0xD542A8F6 0x287EFFC3 0xAC6732C6 0x8C4F5573
0x695B27B0 0xBBCA58C8 0xE1FFA35D 0xB8F011A0
0x10FA3D98 0xFD2183B8 0x4AFCB56C 0x2DD1D35B
0x9A53E479 0xB6F84565 0xD28E49BC 0x4BFB9790
0xE1DDF2DA 0xA4CB7E33 0x62FB1341 0xCEE4C6E8
0xEF20CADA 0x36774C01 0xD07E9EFE 0x2BF11FB4
0x95DBDA4D 0xAE909198 0xEAAD8E71 0x6B93D5A0
0xD08ED1D0 0xAFC725E0 0x8E3C5B2F 0x8E7594B7
0x8FF6E2FB 0xF2122B64 0x8888B812 0x900DF01C
0x4FAD5EA0 0x688FC31C 0xD1CFF191 0xB3A8C1AD
0x2F2F2218 0xBE0E1777 0xEA752DFE 0x8B021FA1
0xE5A0CC0F 0xB56F74E8 0x18ACF3D6 0xCE89E299
0xB4A84FE0 0xFD13E0B7 0x7CC43B81 0xD2ADA8D9
0x165FA266 0x80957705 0x93CC7314 0x211A1477
0xE6AD2065 0x77B5FA86 0xC75442F5 0xFB9D35CF
0xEBCDAF0C 0x7B3E89A0 0xD6411BD3 0xAE1E7E49
0x00250E2D 0x2071B35E 0x226800BB 0x57B8E0AF
0x2464369B 0xF009B91E 0x5563911D 0x59DFA6AA
0x78C14389 0xD95A537F 0x207D5BA2 0x02E5B9C5
0x83260376 0x6295CFA9 0x11C81968 0x4E734A41
0xB3472DCA 0x7B14A94A 0x1B510052 0x9A532915
0xD60F573F 0xBC9BC6E4 0x2B60A476 0x81E67400
0x08BA6FB5 0x571BE91F 0xF296EC6B 0x2A0DD915
0xB6636521 0xE7B9F9B6 0xFF34052E 0xC5855664
0x53B02D5D 0xA99F8FA1 0x08BA4799 0x6E85076A
0x4B7A70E9 0xB5B32944 0xDB75092E 0xC4192623
0xAD6EA6B0 0x49A7DF7D 0x9CEE60B8 0x8FEDB266
0xECAA8C71 0x699A17FF 0x5664526C 0xC2B19EE1
0x193602A5 0x75094C29 0xA0591340 0xE4183A3E
0x3F54989A 0x5B429D65 0x6B8FE4D6 0x99F73FD6
0xA1D29C07 0xEFE830F5 0x4D2D38E6 0xF0255DC1
0x4CDD2086 0x8470EB26 0x6382E9C6 0x021ECC5E
0x09686B3F 0x3EBAEFC9 0x3C971814 0x6B6A70A1
0x687F3584 0x52A0E286 0xB79C5305 0xAA500737
0x3E07841C 0x7FDEAE5C 0x8E7D44EC 0x5716F2B8
0xB03ADA37 0xF0500C0D 0xF01C1F04 0x0200B3FF
0xAE0CF51A 0x3CB574B2 0x25837A58 0xDC0921BD
0xD19113F9 0x7CA92FF6 0x94324773 0x22F54701
0x3AE5E581 0x37C2DADC 0xC8B57634 0x9AF3DDA7
0xA9446146 0x0FD0030E 0xECC8C73E 0xA4751E41
0xE238CD99 0x3BEA0E2F 0x3280BBA1 0x183EB331
0x4E548B38 0x4F6DB908 0x6F420D03 0xF60A04BF
0x2CB81290 0x24977C79 0x5679B072 0xBCAF89AF
0xDE9A771F 0xD9930810 0xB38BAE12 0xDCCF3F2E
0x5512721F 0x2E6B7124 0x501ADDE6 0x9F84CD87
0x7A584718 0x7408DA17 0xBC9F9ABC 0xE94B7D8C
0xEC7AEC3A 0xDB851DFA 0x63094366 0xC464C3D2
0xEF1C1847 0x3215D908 0xDD433B37 0x24C2BA16
0x12A14D43 0x2A65C451 0x50940002 0x133AE4DD
0x71DFF89E 0x10314E55 0x81AC77D6 0x5F11199B
0x043556F1 0xD7A3C76B 0x3C11183B 0x5924A509
0xF28FE6ED 0x97F1FBFA 0x9EBABF2C 0x1E153C6E
0x86E34570 0xEAE96FB1 0x860E5E0A 0x5A3E2AB3
0x771FE71C 0x4E3D06FA 0x2965DCB9 0x99E71D0F
0x803E89D6 0x5266C825 0x2E4CC978 0x9C10B36A
0xC6150EBA 0x94E2EA78 0xA5FC3C53 0x1E0A2DF4
0xF2F74EA7 0x361D2B3D 0x1939260F 0x19C27960
0x5223A708 0xF71312B6 0xEBADFE6E 0xEAC31F66
0xE3BC4595 0xA67BC883 0xB17F37D1 0x018CFF28
0xC332DDEF 0xBE6C5AA5 0x65582185 0x68AB9802
0xEECEA50F 0xDB2F953B 0x2AEF7DAD 0x5B6E2F84
0x1521B628 0x29076170 0xECDD4775 0x619F1510
0x13CCA830 0xEB61BD96 0x0334FE1E 0xAA0363CF
0xB5735C90 0x4C70A239 0xD59E9E0B 0xCBAADE14
0xEECC86BC 0x60622CA7 0x9CAB5CAB 0xB2F3846E
0x648B1EAF 0x19BDF0CA 0xA02369B9 0x655ABB50
0x40685A32 0x3C2AB4B3 0x319EE9D5 0xC021B8F7
0x9B540B19 0x875FA099 0x95F7997E 0x623D7DA8
0xF837889A 0x97E32D77 0x11ED935F 0x16681281
0x0E358829 0xC7E61FD6 0x96DEDFA1 0x7858BA99
0x57F584A5 0x1B227263 0x9B83C3FF 0x1AC24696
0xCDB30AEB 0x532E3054 0x8FD948E4 0x6DBC3128
0x58EBF2EF 0x34C6FFEA 0xFE28ED61 0xEE7C3C73
0x5D4A14D9 0xE864B7E3 0x42105D14 0x203E13E0
0x45EEE2B6 0xA3AAABEA 0xDB6C4F15 0xFACB4FD0
0xC742F442 0xEF6ABBB5 0x654F3B1D 0x41CD2105
0xD81E799E 0x86854DC7 0xE44B476A 0x3D816250
0xCF62A1F2 0x5B8D2646 0xFC8883A0 0xC1C7B6A3
0x7F1524C3 0x69CB7492 0x47848A0B 0x5692B285
0x095BBF00 0xAD19489D 0x1462B174 0x23820E00
0x58428D2A 0x0C55F5EA 0x1DADF43E 0x233F7061
0x3372F092 0x8D937E41 0xD65FECF1 0x6C223BDB
0x7CDE3759 0xCBEE7460 0x4085F2A7 0xCE77326E
0xA6078084 0x19F8509E 0xE8EFD855 0x61D99735
0xA969A7AA 0xC50C06C2 0x5A04ABFC 0x800BCADC
0x9E447A2E 0xC3453484 0xFDD56705 0x0E1E9EC9
0xDB73DBD3 0x105588CD 0x675FDA79 0xE3674340
0xC5C43465 0x713E38D8 0x3D28F89E 0xF16DFF20
0x153E21E7 0x8FB03D4A 0xE6E39F2B 0xDB83ADF7
0xE93D5A68 0x948140F7 0xF64C261C 0x94692934
0x411520F7 0x7602D4F7 0xBCF46B2E 0xD4A20068
0xD4082471 0x3320F46A 0x43B7D4B7 0x500061AF
0x1E39F62E 0x97244546 0x14214F74 0xBF8B8840
0x4D95FC1D 0x96B591AF 0x70F4DDD3 0x66A02F45
0xBFBC09EC 0x03BD9785 0x7FAC6DD0 0x31CB8504
0x96EB27B3 0x55FD3941 0xDA2547E6 0xABCA0A9A
0x28507825 0x530429F4 0x0A2C86DA 0xE9B66DFB
0x68DC1462 0xD7486900 0x680EC0A4 0x27A18DEE
0x4F3FFEA2 0xE887AD8C 0xB58CE006 0x7AF4D6B6
0xAACE1E7C 0xD3375FEC 0xCE78A399 0x406B2A42
0x20FE9E35 0xD9F385B9 0xEE39D7AB 0x3B124E8B
0x1DC9FAF7 0x4B6D1856 0x26A36631 0xEAE397B2
0x3A6EFA74 0xDD5B4332 0x6841E7F7 0xCA7820FB
0xFB0AF54E 0xD8FEB397 0x454056AC 0xBA489527
0x55533A3A 0x20838D87 0xFE6BA9B7 0xD096954B
0x55A867BC 0xA1159A58 0xCCA92963 0x99E1DB33
0xA62A4A56 0x3F3125F9 0x5EF47E1C 0x9029317C
0xFDF8E802 0x04272F70 0x80BB155C 0x05282CE3
0x95C11548 0xE4C66D22 0x48C1133F 0xC70F86DC
0x07F9C9EE 0x41041F0F 0x404779A4 0x5D886E17
0x325F51EB 0xD59BC0D1 0xF2BCC18F 0x41113564
0x257B7834 0x602A9C60 0xDFF8E8A3 0x1F636C1B
0x0E12B4C2 0x02E1329E 0xAF664FD1 0xCAD18115
0x6B2395E0 0x333E92E1 0x3B240B62 0xEEBEB922
0x85B2A20E 0xE6BA0D99 0xDE720C8C 0x2DA2F728
0xD0127845 0x95B794FD 0x647D0862 0xE7CCF5F0
0x5449A36F 0x877D48FA 0xC39DFD27 0xF33E8D1E
0x0A476341 0x992EFF74 0x3A6F6EAB 0xF4F8FD37
0xA812DC60 0xA1EBDDF8 0x991BE14C 0xDB6E6B0D
0xC67B5510 0x6D672C37 0x2765D43B 0xDCD0E804
0xF1290DC7 0xCC00FFA3 0xB5390F92 0x690FED0B
0x667B9FFB 0xCEDB7D9C 0xA091CF0B 0xD9155EA3
0xBB132F88 0x515BAD24 0x7B9479BF 0x763BD6EB
0x37392EB3 0xCC115979 0x8026E297 0xF42E312D
0x6842ADA7 0xC66A2B3B 0x12754CCC 0x782EF11C
0x6A124237 0xB79251E7 0x06A1BBE6 0x4BFB6350
0x1A6B1018 0x11CAEDFA 0x3D25BDD8 0xE2E1C3C9
0x44421659 0x0A121386 0xD90CEC6E 0xD5ABEA2A
0x64AF674E 0xDA86A85F 0xBEBFE988 0x64E4C3FE
0x9DBC8057 0xF0F7C086 0x60787BF8 0x6003604D
0xD1FD8346 0xF6381FB0 0x7745AE04 0xD736FCCC
0x83426B33 0xF01EAB71 0xB0804187 0x3C005E5F
0x77A057BE 0xBDE8AE24 0x55464299 0xBF582E61
0x4E58F48F 0xF2DDFDA2 0xF474EF38 0x8789BDC2
0x5366F9C3 0xC8B38E74 0xB475F255 0x46FCD9B9
0x7AEB2661 0x8B1DDF84 0x846A0E79 0x915F95E2
0x466E598E 0x20B45770 0x8CD55591 0xC902DE4C
0xB90BACE1 0xBB8205D0 0x11A86248 0x7574A99E
0xB77F19B6 0xE0A9DC09 0x662D09A1 0xC4324633
0xE85A1F02 0x09F0BE8C 0x4A99A025 0x1D6EFE10
0x1AB93D1D 0x0BA5A4DF 0xA186F20F 0x2868F169
0xDCB7DA83 0x573906FE 0xA1E2CE9B 0x4FCD7F52
0x50115E01 0xA70683FA 0xA002B5C4 0x0DE6D027
0x9AF88C27 0x773F8641 0xC3604C06 0x61A806B5
0xF0177A28 0xC0F586E0 0x006058AA 0x30DC7D62
0x11E69ED7 0x2338EA63 0x53C2DD94 0xC2C21634
0xBBCBEE56 0x90BCB6DE 0xEBFC7DA1 0xCE591D76
0x6F05E409 0x4B7C0188 0x39720A3D 0x7C927C24
0x86E3725F 0x724D9DB9 0x1AC15BB4 0xD39EB8FC
0xED545578 0x08FCA5B5 0xD83D7CD3 0x4DAD0FC4
0x1E50EF5E 0xB161E6F8 0xA28514D9 0x6C51133C
0x6FD5C7E7 0x56E14EC4 0x362ABFCE 0xDDC6C837
0xD79A3234 0x92638212 0x670EFA8E 0x406000E0
0x3A39CE37 0xD3FAF5CF 0xABC27737 0x5AC52D1B
0x5CB0679E 0x4FA33742 0xD3822740 0x99BC9BBE
0xD5118E9D 0xBF0F7315 0xD62D1C7E 0xC700C47B
0xB78C1B6B 0x21A19045 0xB26EB1BE 0x6A366EB4
0x5748AB2F 0xBC946E79 0xC6A376D2 0x6549C2C8
0x530FF8EE 0x468DDE7D 0xD5730A1D 0x4CD04DC6
0x2939BBDB 0xA9BA4650 0xAC9526E8 0xBE5EE304
0xA1FAD5F0 0x6A2D519A 0x63EF8CE2 0x9A86EE22
0xC089C2B8 0x43242EF6 0xA51E03AA 0x9CF2D0A4
0x83C061BA 0x9BE96A4D 0x8FE51550 0xBA645BD6
0x2826A2F9 0xA73A3AE1 0x4BA99586 0xEF5562E9
0xC72FEFD3 0xF752F7DA 0x3F046F69 0x77FA0A59
0x80E4A915 0x87B08601 0x9B09E6AD 0x3B3EE593
0xE990FD5A 0x9E34D797 0x2CF0B7D9 0x022B8B51
0x96D5AC3A 0x017DA67D 0xD1CF3ED6 0x7C7D2D28
0x1F9F25CF 0xADF2B89B 0x5AD6B472 0x5A88F54C
0xE029AC71 0xE019A5E6 0x47B0ACFD 0xED93FA9B
0xE8D3C48D 0x283B57CC 0xF8D56629 0x79132E28
0x785F0191 0xED756055 0xF7960E44 0xE3D35E8C
0x15056DD4 0x88F46DBA 0x03A16125 0x0564F0BD
0xC3EB9E15 0x3C9057A2 0x97271AEC 0xA93A072A
0x1B3F6D9B 0x1E6321F5 0xF59C66FB 0x26DCF319
0x7533D928 0xB155FDF5 0x03563482 0x8ABA3CBB
0x28517711 0xC20AD9F8 0xABCC5167 0xCCAD925F
0x4DE81751 0x3830DC8E 0x379D5862 0x9320F991
0xEA7A90C2 0xFB3E7BCE 0x5121CE64 0x774FBE32
0xA8B6E37E 0xC3293D46 0x48DE5369 0x6413E680
0xA2AE0810 0xDD6DB224 0x69852DFD 0x09072166
0xB39A460A 0x6445C0DD 0x586CDECF 0x1C20C8AE
0x5BBEF7DD 0x1B588D40 0xCCD2017F 0x6BB4E3BB
0xDDA26A7E 0x3A59FF45 0x3E350A44 0xBCB4CDD5
0x72EACEA8 0xFA6484BB 0x8D6612AE 0xBF3C6F47
0xD29BE463 0x542F5D9E 0xAEC2771B 0xF64E6370
0x740E0D8D 0xE75B1357 0xF8721671 0xAF537D5D
0x4040CB08 0x4EB4E2CC 0x34D2466A 0x0115AF84
0xE1B00428 0x95983A1D 0x06B89FB4 0xCE6EA048
0x6F3F3B82 0x3520AB82 0x011A1D4B 0x277227F8
0x611560B1 0xE7933FDC 0xBB3A792B 0x344525BD
0xA08839E1 0x51CE794B 0x2F32C9B7 0xA01FBAC9
0xE01CC87E 0xBCC7D1F6 0xCF0111C3 0xA1E8AAC7
0x1A908749 0xD44FBD9A 0xD0DADECB 0xD50ADA38
0x0339C32A 0xC6913667 0x8DF9317C 0xE0B12B4F
0xF79E59B7 0x43F5BB3A 0xF2D519FF 0x27D9459C
0xBF97222C 0x15E6FC2A 0x0F91FC71 0x9B941525
0xFAE59361 0xCEB69CEB 0xC2A86459 0x12BAA8D1
0xB6C1075E 0xE3056A0C 0x10D25065 0xCB03A442
0xE0EC6E0E 0x1698DB3B 0x4C98A0BE 0x3278E964
0x9F1F9532 0xE0D392DF 0xD3A0342B 0x8971F21E
0x1B0A7441 0x4BA3348C 0xC5BE7120 0xC37632D8
0xDF359F8D 0x9B992F2E 0xE60B6F47 0x0FE3F11D
0xE54CDA54 0x1EDAD891 0xCE6279CF 0xCD3E7E6F
0x1618B166 0xFD2C1D05 0x848FD2C5 0xF6FB2299
0xF523F357 0xA6327623 0x93A83531 0x56CCCD02
0xACF08162 0x5A75EBB5 0x6E163697 0x88D273CC
0xDE966292 0x81B949D0 0x4C50901B 0x71C65614
0xE6C6C7BD 0x327A140A 0x45E1D006 0xC3F27B9A
0xC9AA53FD 0x62A80F00 0xBB25BFE2 0x35BDD2F6
0x71126905 0xB2040222 0xB6CBCF7C 0xCD769C2B
0x53113EC0 0x1640E3D3 0x38ABBD60 0x2547ADF0
0xBA38209C 0xF746CE76 0x77AFA1C5 0x20756060
0x85CBFE4E 0x8AE88DD8 0x7AAAF9B0 0x4CF9AA7E
0x1948C25C 0x02FB8A8C 0x01C36AE4 0xD6EBE1F9
0x90D4F869 0xA65CDEA0 0x3F09252D 0xC208E69F
0xB74E6132 0xCE77E25B 0x578FDFE3 0x3AC372E6
}
}
proc ::blowfish::intEncrypt {P S xl xr} {
for {set i 0} {$i < 16} {incr i} {
set xl [expr {$xl ^ [lindex $P $i]}]
set S0a [lindex $S [expr { ($xl >> 24) & 0xff}]]
set S1b [lindex $S [expr {(($xl >> 16) & 0xff) + 256}]]
set S2c [lindex $S [expr {(($xl >> 8) & 0xff) + 512}]]
set S3d [lindex $S [expr { ($xl & 0xff) + 768}]]
set xr [expr {(((($S0a + $S1b) ^ $S2c) + $S3d) & 0xffffffff) ^ $xr}]
set temp $xl ; set xl $xr ; set xr $temp
}
set temp $xl ; set xl $xr ; set xr $temp
return [list [expr {$xl ^ [lindex $P 17]}] [expr {$xr ^ [lindex $P 16]}]]
}
proc ::blowfish::intDecrypt {P S xl xr} {
for {set i 17} {$i > 1} {incr i -1} {
set xl [expr {$xl ^ [lindex $P $i]}]
set S0a [lindex $S [expr { ($xl >> 24) & 0xff}]]
set S1b [lindex $S [expr {(($xl >> 16) & 0xff) + 256}]]
set S2c [lindex $S [expr {(($xl >> 8) & 0xff) + 512}]]
set S3d [lindex $S [expr { ($xl & 0xff) + 768}]]
set xr [expr {(((($S0a + $S1b) ^ $S2c) + $S3d) & 0xffffffff) ^ $xr}]
set temp $xl ; set xl $xr ; set xr $temp
}
set temp $xl ; set xl $xr ; set xr $temp
return [list [expr {$xl ^ [lindex $P 0]}] [expr {$xr ^ [lindex $P 1]}]]
}
proc ::blowfish::Init {mode key iv} {
variable ORIG_S
variable ORIG_P
variable uid
set S $ORIG_S
set P [list]
set kl [string length $key]
binary scan $key c* kc
set j 0
for {set i 0} {$i < 18} {incr i} {
set data 0
for {set k 0} {$k < 4} {incr k} {
set data [expr {(($data << 8) | ([lindex $kc $j] & 0xff)) & 0xffffffff}]
if {[incr j] >= $kl} {
set j 0
}
}
set OPi [lindex $ORIG_P $i]
lappend P [expr {$OPi ^ $data}]
}
set datal 0
set datar 0
for {set i 0} {$i < 18} {incr i} {
set ed [intEncrypt $P $S $datal $datar]
set datal [lindex $ed 0]
set datar [lindex $ed 1]
set P [lreplace $P $i [incr i] $datal $datar]
}
for {set i 0} {$i < 4} {incr i} {
for {set j 0} {$j < 256} {incr j 2} {
set ed [intEncrypt $P $S $datal $datar]
set datal [lindex $ed 0]
set datar [lindex $ed 1]
set t [expr {$i * 256 + $j}]
set S [lreplace $S $t [incr t] $datal $datar]
}
}
set token [namespace current]::[incr uid]
variable $token
upvar #0 $token state
array set state [list P $P S $S M $mode I $iv]
return $token
}
proc ::blowfish::Reset {token iv} {
upvar #0 $token state
set state(I) $iv
return
}
proc ::blowfish::Final {token} {
# PRAGMA: nocheck
variable $token
unset $token
}
proc ::blowfish::EncryptBlock {token block} {
upvar #0 $token state
if {[binary scan $block II xl xr] != 2} {
error "block must be 8 bytes"
}
set xl [expr {$xl & 0xffffffff}]
set xr [expr {$xr & 0xffffffff}]
set d [intEncrypt $state(P) $state(S) $xl $xr]
return [binary format I2 $d]
}
proc ::blowfish::Encrypt {Key data} {
upvar #0 $Key state
set P $state(P)
set S $state(S)
set cbc_mode [string equal "cbc" $state(M)]
if {[binary scan $state(I) II s0 s1] != 2} {
return -code error "invalid initialization vector: must be 8 bytes"
}
set len [string length $data]
if {($len % 8) != 0} {
return -code error "invalid block size: blocks must be 8 bytes"
}
set s0 [expr {$s0 & 0xffffffff}]
set s1 [expr {$s1 & 0xffffffff}]
set result ""
for {set i 0} {$i < $len} {incr i 8} {
if {[binary scan $data @[set i]II xl xr] != 2} {
return -code error "oops"
}
if {$cbc_mode} {
set xl [expr {($xl & 0xffffffff) ^ $s0}]
set xr [expr {($xr & 0xffffffff) ^ $s1}]
}
set d [intEncrypt $P $S $xl $xr]
if {$cbc_mode} {
set s0 [lindex $d 0]
set s1 [lindex $d 1]
}
append result [binary format I2 $d]
}
if {$cbc_mode} {
set state(I) [binary format II $s0 $s1]
}
return $result
}
proc ::blowfish::DecryptBlock {Key block} {
upvar #0 $Key state
if {[binary scan $block II xl xr] != 2} {
return -code error "invalid block size: block must be 8 bytes"
}
set xl [expr {$xl & 0xffffffff}]
set xr [expr {$xr & 0xffffffff}]
set d [intDecrypt $state(P) $state(S) $xl $xr]
return [binary format I2 $d]
}
proc ::blowfish::Decrypt {token data} {
upvar #0 $token state
set P $state(P)
set S $state(S)
set cbc_mode [string equal "cbc" $state(M)]
if {[binary scan $state(I) II s0 s1] != 2} {
return -code error "initialization vector must be 8 bytes"
}
set len [string length $data]
if {($len % 8) != 0} {
return -code error "block size invalid"
}
set s0 [expr {$s0 & 0xffffffff}]
set s1 [expr {$s1 & 0xffffffff}]
set result ""
for {set i 0} {$i < $len} {incr i 8} {
if {[binary scan $data @[set i]II xl xr] != 2} {
error "oops"
}
set xl [expr {$xl & 0xffffffff}]
set xr [expr {$xr & 0xffffffff}]
set d [intDecrypt $P $S $xl $xr]
if {$cbc_mode} {
set d0 [lindex $d 0]
set d1 [lindex $d 1]
set c0 [expr {$d0 ^ $s0}]
set c1 [expr {$d1 ^ $s1}]
set s0 $xl
set s1 $xr
append result [binary format II $c0 $c1]
} else {
append result [binary format I2 $d]
}
}
if {$cbc_mode} {
set state(I) [binary format II $s0 $s1]
}
return $result
}
# -------------------------------------------------------------------------
# Fileevent handler for chunked file reading.
#
proc ::blowfish::Chunk {Key in {out {}} {chunksize 4096} {pad \0}} {
upvar #0 $Key state
if {[eof $in]} {
fileevent $in readable {}
set state(reading) 0
set data $state(remainder)
# Only pad at the end of the stream.
if {[string length $pad] > 0} {
set data [Pad $data 8 $pad]
}
} else {
set data [read $in $chunksize]
#puts "Chunk: reading [string len $data] bytes"
set data $state(remainder)$data
# If data is not a multiple of 8, state(remainder) will hold
# excess bytes for the next round.
set pagedlen [expr {([string length $data] / 8) * 8}]
set state(remainder) [string range $data $pagedlen end]
incr pagedlen -1
set data [string range $data 0 $pagedlen]
}
if {![string length $data]} return
if {[set code [catch {
set cipher [$state(cmd) $Key $data]
} msg]]} {
fileevent $in readable {}
set state(reading) 0
set state(err) [list $code $msg]
return
}
if {$out == {}} {
append state(output) $cipher
} else {
puts -nonewline $out $cipher
}
}
# -------------------------------------------------------------------------
# LoadAccelerator --
#
# This package can make use of a number of compiled extensions to
# accelerate the digest computation. This procedure manages the
# use of these extensions within the package. During normal usage
# this should not be called, but the test package manipulates the
# list of enabled accelerators.
#
proc ::blowfish::LoadAccelerator {name} {
variable accel
set r 0
switch -exact -- $name {
trf {
if {![catch {package require Trfcrypt}]} {
set block [string repeat \0 8]
set r [expr {![catch {::blowfish -dir enc -mode ecb -key $block $block} msg]}]
}
}
default {
return -code error "invalid accelerator package:\
must be one of [join [array names accel] {, }]"
}
}
set accel($name) $r
}
# -------------------------------------------------------------------------
proc ::blowfish::Hex {data} {
binary scan $data H* r
return $r
}
proc ::blowfish::SetOneOf {lst item} {
set ndx [lsearch -glob $lst "${item}*"]
if {$ndx == -1} {
set err [join $lst ", "]
return -code error "invalid mode \"$item\": must be one of $err"
}
return [lindex $lst $ndx]
}
proc ::blowfish::CheckSize {what size thing} {
if {[string length $thing] != $size} {
return -code error "invalid value for $what: must be $size bytes long"
}
return $thing
}
proc ::blowfish::CheckPad {char} {
if {[string length $char] > 1} {
return -code error "invalid value: should be a char or empty string"
}
return $char
}
proc ::blowfish::Pad {data blocksize {fill \0}} {
set len [string length $data]
if {$len == 0} {
# do not pad an empty string
} elseif {($len % $blocksize) != 0} {
set pad [expr {$blocksize - ($len % $blocksize)}]
append data [string repeat $fill $pad]
}
return $data
}
# Description:
# Pop the nth element off a list. Used in options processing.
#
proc ::blowfish::Pop {varname {nth 0}} {
upvar $varname args
set r [lindex $args $nth]
set args [lreplace $args $nth $nth]
return $r
}
proc ::blowfish::blowfish {args} {
variable accel
array set opts {-dir encrypt -mode cbc -key {} -in {} -out {} -hex 0 -pad \0}
set opts(-chunksize) 4096
set opts(-iv) [string repeat \0 8]
set modes {ecb cbc}
set dirs {encrypt decrypt}
while {[string match -* [set option [lindex $args 0]]]} {
switch -exact -- $option {
-mode { set opts(-mode) [SetOneOf $modes [Pop args 1]] }
-dir { set opts(-dir) [SetOneOf $dirs [Pop args 1]] }
-iv { set opts(-iv) [CheckSize -iv 8 [Pop args 1]] }
-key { set opts(-key) [Pop args 1] }
-in { set opts(-in) [Pop args 1] }
-out { set opts(-out) [Pop args 1] }
-chunksize { set opts(-chunksize) [Pop args 1] }
-hex { set opts(-hex) 1 }
-pad { set opts(-pad) [CheckPad [Pop args 1]] }
-- { Pop args; break }
default {
if {[string length $opts(-in)] == 0 && [llength $args] == 1} break
set err [join [lsort [array names opts]] ", "]
return -code error "bad option \"$option\":\
must be one of $err"
}
}
Pop args
}
if {$opts(-key) == {}} {
return -code error "no key provided: the -key option is required"
}
set r {}
if {$opts(-in) == {}} {
# Immediate data (plain text is argument).
if {[llength $args] != 1} {
return -code error "wrong \# args:\
should be \"blowfish ?options...? -key keydata plaintext\""
}
set data [lindex $args 0]
if {[string length $opts(-pad)] > 0} {
set data [Pad [lindex $args 0] 8 $opts(-pad)]
}
if {$accel(trf)} {
set r [::blowfish -dir $opts(-dir) -mode $opts(-mode) \
-key $opts(-key) -iv $opts(-iv) -- $data]
} else {
set Key [Init $opts(-mode) $opts(-key) $opts(-iv)]
if {[string equal $opts(-dir) "encrypt"]} {
set r [Encrypt $Key $data]
} else {
set r [Decrypt $Key $data]
}
Final $Key
}
if {$opts(-out) != {}} {
puts -nonewline $opts(-out) $r
set r {}
}
} else {
# Channel data (plain text is read from a binary channel).
if {[llength $args] != 0} {
return -code error "wrong \# args:\
should be \"blowfish ?options...? -key keydata -in channel\""
}
set Key [Init $opts(-mode) $opts(-key) $opts(-iv)]
upvar $Key state
set state(reading) 1
if {[string equal $opts(-dir) "encrypt"]} {
set state(cmd) Encrypt
} else {
set state(cmd) Decrypt
}
set state(output) ""
set state(remainder) ""
fileevent $opts(-in) readable \
[list [namespace origin Chunk] \
$Key $opts(-in) $opts(-out) $opts(-chunksize) $opts(-pad)]
if {[info commands ::tkwait] != {}} {
tkwait variable [subst $Key](reading)
} else {
vwait [subst $Key](reading)
}
if {[info exists state(err)]} {
foreach {code msg} $state(err) break
return -code $code $msg
}
if {$opts(-out) == {}} {
set r $state(output)
}
Final $Key
}
if {$opts(-hex)} {
set r [Hex $r]
}
return $r
}
# -------------------------------------------------------------------------
# Try and load a compiled extension to help.
namespace eval ::blowfish {
variable e {}
foreach e {trf} {
if {[LoadAccelerator $e]} break
}
unset e
}
package provide blowfish 1.0.6
# -------------------------------------------------------------------------
#
# Local Variables:
# mode: tcl
# indent-tabs-mode: nil
# End:

5
src/vendorlib_tcl9/tcllib2.0/blowfish/pkgIndex.tcl

@ -0,0 +1,5 @@
if {![package vsatisfies [package provide Tcl] 8.5 9]} {
# PRAGMA: returnok
return
}
package ifneeded blowfish 1.0.6 [list source [file join $dir blowfish.tcl]]

185
src/vendorlib_tcl9/tcllib2.0/cache/async.tcl vendored

@ -0,0 +1,185 @@
## -*- tcl -*-
# ### ### ### ######### ######### #########
# Copyright (c) 2008 Andreas Kupries <andreas_kupries@users.sourceforge.net>
# Aynchronous in-memory cache. Queries of the cache generate
# asynchronous requests for data for unknown parts, with asynchronous
# result return. Data found in the cache may return fully asynchronous
# as well, or semi-synchronous. The latter meaning that the regular
# callbacks are used, but invoked directly, and not decoupled through
# events. The cache can be pre-filled synchronously.
# ### ### ### ######### ######### #########
## Requisites
package require Tcl 8.5 9 ; #
package require snit ; #
# ### ### ### ######### ######### #########
##
snit::type cache::async {
# ### ### ### ######### ######### #########
## Unknown methods and options are forwared to the object actually
## providing the cached data, making the cache a proper facade for
## it.
delegate method * to myprovider
delegate option * to myprovider
# ### ### ### ######### ######### #########
## API
option -full-async-results -default 1 -type snit::boolean
constructor {provider args} {
set myprovider $provider
$self configurelist $args
return
}
method get {key donecmd} {
# Register request
lappend mywaiting($key) $donecmd
# Check if the request can be satisfied from the cache. If yes
# then that is done.
if {[info exists mymiss($key)]} {
$self NotifyUnset 1 $key
return
} elseif {[info exists myhit($key)]} {
$self NotifySet 1 $key
return
}
# We have to ask our provider if there is data or
# not. however, if a request for this key is already in flight
# then we have to do nothing more. Our registration at the
# beginning ensures that we will get notified when the
# requested information comes back.
if {[llength $mywaiting($key)] > 1} return
# This is the first query for this key, ask the provider.
after idle [linsert $myprovider end get $key $self]
return
}
method clear {args} {
# Note: This method cannot interfere with async queries caused
# by 'get' invokations. If the data is present, and now
# removed, all 'get' invokations before this call were
# satisfied from the cache and only invokations coming after
# it can trigger async queries of the provider. If the data is
# not present the state will not change, and queries in flight
# simply refill the cache as they would do anyway without the
# 'clear'.
if {![llength $args]} {
array unset myhit *
array unset mymiss *
} elseif {[llength $args] == 1} {
set key [lindex $args 0]
unset -nocomplain myhit($key)
unset -nocomplain mymiss($key)
} else {
WrongArgs ?key?
}
return
}
method exists {key} {
return [expr {[info exists myhit($key)] || [info exists mymiss($key)]}]
}
method set {key value} {
# Add data to the cache, and notify all outstanding queries.
# Nothing is done if the key is already known and has the same
# value.
# This is the method invoked by the provider in response to
# queries, and also the method to use to prefill the cache
# with data.
if {
[info exists myhit($key)] &&
($value eq $myhit($key))
} return
set myhit($key) $value
unset -nocomplain mymiss($key)
$self NotifySet 0 $key
return
}
method unset {key} {
# Add hole to the cache, and notify all outstanding queries.
# This is the method invoked by the provider in response to
# queries, and also the method to use to prefill the cache
# with holes.
unset -nocomplain myhit($key)
set mymiss($key) .
$self NotifyUnset 0 $key
return
}
method NotifySet {found key} {
if {![info exists mywaiting($key)] || ![llength $mywaiting($key)]} return
set pending $mywaiting($key)
unset mywaiting($key)
set value $myhit($key)
if {$found && !$options(-full-async-results)} {
foreach donecmd $pending {
uplevel \#0 [linsert $donecmd end set $key $value]
}
} else {
foreach donecmd $pending {
after idle [linsert $donecmd end set $key $value]
}
}
return
}
method NotifyUnset {found key} {
if {![info exists mywaiting($key)] || ![llength $mywaiting($key)]} return
set pending $mywaiting($key)
unset mywaiting($key)
if {$found && !$options(-full-async-results)} {
foreach donecmd $pending {
uplevel \#0 [linsert $donecmd end unset $key]
}
} else {
foreach donecmd $pending {
after idle [linsert $donecmd end unset $key]
}
}
return
}
proc WrongArgs {expected} {
return -code error "wrong#args: Expected $expected"
}
# ### ### ### ######### ######### #########
## State
variable myprovider ; # Command prefix providing the data to cache.
variable myhit -array {} ; # Cache array mapping keys to values.
variable mymiss -array {} ; # Cache array mapping keys to holes.
variable mywaiting -array {} ; # Map of keys pending to notifier commands.
# ### ### ### ######### ######### #########
}
# ### ### ### ######### ######### #########
## Ready
package provide cache::async 0.3.2

3
src/vendorlib_tcl9/tcllib2.0/cache/pkgIndex.tcl vendored

@ -0,0 +1,3 @@
if {![package vsatisfies [package provide Tcl] 8.5 9]} {return}
package ifneeded cache::async 0.3.2 [list source [file join $dir async.tcl]]

2227
src/vendorlib_tcl9/tcllib2.0/clay/clay.tcl

File diff suppressed because it is too large Load Diff

3
src/vendorlib_tcl9/tcllib2.0/clay/pkgIndex.tcl

@ -0,0 +1,3 @@
if {![package vsatisfies [package provide Tcl] 8.6 9]} {return}
package ifneeded clay 0.8.8 [list source [file join $dir clay.tcl]]

280
src/vendorlib_tcl9/tcllib2.0/clock/iso8601.tcl

@ -0,0 +1,280 @@
## -*- tcl -*-
# # ## ### ##### ######## ############# #####################
## Copyright (c) 2004 Kevin Kenny
## Origin http://wiki.tcl.tk/13094
## Modified for Tcl 8.5 only (eval -> {*}).
# # ## ### ##### ######## ############# #####################
## Requisites
package require Tcl 8.5 9
package provide clock::iso8601 0.2
namespace eval ::clock::iso8601 {}
# # ## ### ##### ######## ############# #####################
## API
# iso8601::parse_date --
#
# Parse an ISO8601 date/time string in an unknown variant.
#
# Parameters:
# string -- String to parse
# args -- Arguments as for [clock scan]; may include any of
# the '-base', '-gmt', '-locale' or '-timezone options.
#
# Results:
# Returns the given date in seconds from the Posix epoch.
proc ::clock::iso8601::parse_date { string args } {
variable DatePatterns
variable Repattern
foreach { regex interpretation } $DatePatterns {
if { [regexp "^$regex\$" $string] } {
#puts A|$string|\t|$regex|\t|$interpretation|
# For incomplete dates (month and/or day missing), we have
# to set our own default values to overcome clock scan's
# settings. We do this by switching to a different pattern
# and extending the input properly for that pattern.
if {[dict exists $Repattern $interpretation]} {
lassign [dict get $Repattern $interpretation] interpretation adjust modifier
{*}$modifier
# adjust irrelevant here, see parse_time for use.
}
#puts B|$string|\t|$regex|\t|$interpretation|
return [clock scan $string -format $interpretation {*}$args]
}
}
return -code error "not an iso8601 date string"
}
# iso8601::parse_time --
#
# Parse a point-in-time in ISO8601 format
#
# Parameters:
# string -- String to parse
# args -- Arguments as for [clock scan]; may include any of
# the '-base', '-gmt', '-locale' or '-timezone options.
#
# Results:
# Returns the given time in seconds from the Posix epoch.
proc ::clock::iso8601::parse_time { string args } {
variable DatePatterns
variable Repattern
if {![MatchTime $string field]} {
return -code error "not an iso8601 time string"
}
#parray field
#puts A|$string|
set pattern {}
foreach {regex interpretation} $DatePatterns {
if {[Has $interpretation tstart]} {
append pattern $interpretation
}
}
if {[dict exists $Repattern $pattern]} {
lassign [dict get $Repattern $pattern] interpretation adjust modifier
{*}$modifier
incr tstart $adjust
}
append pattern [Get T len]
incr tstart $len
if {[Has %H tstart]} {
append pattern %H [Get Hcolon len]
incr tstart $len
if {[Has %M tstart]} {
append pattern %M [Get Mcolon len]
incr tstart $len
if {[Has %S tstart]} {
append pattern %S
} else {
# No seconds, default to start of minute.
append pattern %S
Insert string $tstart 00
}
} else {
# No minutes, nor seconds, default to start of hour.
append pattern %M%S
Insert string $tstart 0000
}
} else {
# No time information, default to midnight.
append pattern %H%M%S
Insert string $tstart 000000
}
if {[Has %Z _]} {
append pattern %Z
}
#puts B|$string|\t|$pattern|
return [clock scan $string -format $pattern {*}$args]
}
# # ## ### ##### ######## ############# #####################
proc ::clock::iso8601::Get {x lv} {
upvar 1 field field string string $lv len
lassign $field($x) s e
if {($s >= 0) && ($e >= 0)} {
set len [expr {$e - $s + 1}]
return [string range $string $s $e]
}
set len 0
return ""
}
proc ::clock::iso8601::Has {x nv} {
upvar 1 field field string string $nv next
lassign $field($x) s e
if {($s >= 0) && ($e >= 0)} {
set next $e
incr next
return 1
}
return 0
}
proc ::clock::iso8601::Insert {sv index str} {
upvar 1 $sv string
append r [string range $string 0 ${index}-1]
append r $str
append r [string range $string $index end]
set string $r
return
}
# # ## ### ##### ######## ############# #####################
## State
namespace eval ::clock::iso8601 {
namespace export parse_date parse_time
namespace ensemble create
# Enumerate the patterns that we recognize for an ISO8601 date as both
# the regexp patterns that match them and the [clock] patterns that scan
# them.
variable DatePatterns {
{\d\d\d\d-\d\d-\d\d} {%Y-%m-%d}
{\d\d\d\d\d\d\d\d} {%Y%m%d}
{\d\d\d\d-\d\d\d} {%Y-%j}
{\d\d\d\d\d\d\d} {%Y%j}
{\d\d-\d\d-\d\d} {%y-%m-%d}
{\d\d\d\d-\d\d} {%Y-%m}
{\d\d\d\d\d\d} {%y%m%d}
{\d\d-\d\d\d} {%y-%j}
{\d\d\d\d\d} {%y%j}
{--\d\d-\d\d} {--%m-%d}
{--\d\d\d\d} {--%m%d}
{--\d\d\d} {--%j}
{---\d\d} {---%d}
{\d\d\d\d-W\d\d-\d} {%G-W%V-%u}
{\d\d\d\dW\d\d\d} {%GW%V%u}
{\d\d-W\d\d-\d} {%g-W%V-%u}
{\d\dW\d\d\d} {%gW%V%u}
{\d\d\d\d-W\d\d} {%G-W%V}
{\d\d\d\dW\d\d} {%GW%V}
{-W\d\d-\d} {-W%V-%u}
{-W\d\d\d} {-W%V%u}
{-W-\d} {%u}
{\d\d\d\d} {%Y}
}
# Dictionary of the patterns requiring modifications to the input
# for proper month and/or day defaults.
variable Repattern {
%Y-%m {%Y-%m-%d 3 {Insert string 7 -01}}
%Y {%Y-%m-%d 5 {Insert string 4 -01-01}}
%G-W%V {%G-W%V-%u 1 {Insert string 8 -1}}
%GW%V {%GW%V%u 1 {Insert string 6 1}}
}
}
# # ## ### ##### ######## ############# #####################
## Initialization
apply {{} {
# MatchTime -- (constructed procedure)
#
# Match an ISO8601 date/time string and indicate how it matched.
#
# Parameters:
# string -- String to match.
# fieldArray -- Name of an array in caller's scope that will receive
# parsed fields of the time.
#
# Results:
# Returns 1 if the time was scanned successfully, 0 otherwise.
#
# Side effects:
# Initializes the field array. The keys that are significant:
# - Any date pattern in 'DatePatterns' indicates that the
# corresponding value, if non-empty, contains a date string
# in the given format.
# - The patterns T, Hcolon, and Mcolon indicate a literal
# T preceding the time, a colon following the hour, or
# a colon following the minute.
# - %H, %M, %S, and %Z indicate the presence of the
# corresponding parts of the time.
variable DatePatterns
set cmd {regexp -indices -expanded -nocase -- {PATTERN} $timeString ->}
set re \(?:\(?:
set sep {}
foreach {regex interpretation} $DatePatterns {
append re $sep \( $regex \)
append cmd " " [list field($interpretation)]
set sep |
}
append re \) {(T|[[:space:]]+)} \)?
append cmd { field(T)}
append re {(\d\d)(?:(:?)(\d\d)(?:(:?)(\d\d)?))?}
append cmd { field(%H) field(Hcolon) } {field(%M) field(Mcolon) field(%S)}
append re {[[:space:]]*(Z|[-+]\d\d:?\d\d)?}
append cmd { field(%Z)}
set cmd [string map [list {{PATTERN}} [list $re]] \
$cmd]
proc MatchTime { timeString fieldArray } "
upvar 1 \$fieldArray field
$cmd
"
#puts [info body MatchTime]
} ::clock::iso8601}
# # ## ### ##### ######## ############# #####################
return
# Usage examples, disabled.
if { [info exists ::argv0] && ( $::argv0 eq [info script] ) } {
puts "::clock::iso8601::parse_date"
puts [::clock::iso8601::parse_date 1970-01-02 -timezone :UTC]
puts [::clock::iso8601::parse_date 1970-W01-5 -timezone :UTC]
puts [time {::clock::iso8601::parse_date 1970-01-02 -timezone :UTC} 1000]
puts [time {::clock::iso8601::parse_date 1970-W01-5 -timezone :UTC} 1000]
puts "::clock::iso8601::parse_time"
puts [clock format [::clock::iso8601::parse_time 2004-W33-2T18:52:24Z] \
-format {%X %x %z} -locale system]
puts [clock format [::clock::iso8601::parse_time 18:52:24Z] \
-format {%X %x %z} -locale system]
puts [time {::clock::iso8601::parse_time 2004-W33-2T18:52:24Z} 1000]
puts [time {::clock::iso8601::parse_time 18:52:24Z} 1000]
}

3
src/vendorlib_tcl9/tcllib2.0/clock/pkgIndex.tcl

@ -0,0 +1,3 @@
if {![package vsatisfies [package provide Tcl] 8.5 9]} {return}
package ifneeded clock::rfc2822 0.2 [list source [file join $dir rfc2822.tcl]]
package ifneeded clock::iso8601 0.2 [list source [file join $dir iso8601.tcl]]

214
src/vendorlib_tcl9/tcllib2.0/clock/rfc2822.tcl

@ -0,0 +1,214 @@
## -*- tcl -*-
# # ## ### ##### ######## ############# #####################
## Copyright (c) 2004 Kevin Kenny
## Origin http://wiki.tcl.tk/24074
# # ## ### ##### ######## ############# #####################
## Requisites
package require Tcl 8.5 9
package provide clock::rfc2822 0.2
namespace eval ::clock::rfc2822 {}
# # ## ### ##### ######## ############# #####################
## API
# ::clock::rfc2822::parse_date --
#
# Parses a date expressed in RFC2822 format
#
# Parameters:
# date - The date to parse
#
# Results:
# Returns the date expressed in seconds from the Epoch, or throws
# an error if the date could not be parsed.
proc ::clock::rfc2822::parse_date { date } {
variable datepats
# Strip comments and excess whitespace from the date field
regsub -all -expanded {
\( # open parenthesis
(:?
[^()[.\.]] # character other than ()\
|\\. # or backslash escape
)* # any number of times
\) # close paren
} $date {} date
set date [string trim $date]
# Match the patterns in order of preference, returning the first success
foreach {regexp pat} $datepats {
if { [regexp -nocase $regexp $date] } {
return [clock scan $date -format $pat]
}
}
return -code error -errorcode {CLOCK RFC2822 BADDATE} \
"expected an RFC2822 date, got \"$date\""
}
# # ## ### ##### ######## ############# #####################
## Internals, transient, removed after initialization.
# AddDatePat --
#
# Internal procedure that adds a date pattern to the pattern list
#
# Parameters:
# wpat - Regexp pattern that matches the weekday
# wgrp - Format group that matches the weekday
# ypat - Regexp pattern that matches the year
# ygrp - Format group that matches the year
# mdpat - Regexp pattern that matches month and day
# mdgrp - Format group that matches month and day
# spat - Regexp pattern that matches the seconds of the minute
# sgrp - Format group that matches the seconds of the minute
# zpat - Regexp pattern that matches the time zone
# zgrp - Format group that matches the time zone
#
# Results:
# None
#
# Side effects:
# Adds a complete regexp and a complete [clock scan] pattern to
# 'datepats'
proc ::clock::rfc2822::AddDatePat { wpat wgrp ypat ygrp mdpat mdgrp
spat sgrp zpat zgrp } {
variable datepats
set regexp {^[[:space:]]*}
set pat {}
append regexp $wpat $mdpat {[[:space:]]+} $ypat
append pat $wgrp $mdgrp $ygrp
append regexp {[[:space:]]+\d\d?:\d\d} $spat
append pat { %H:%M} $sgrp
append regexp $zpat
append pat $zgrp
append regexp {[[:space:]]*$}
lappend datepats $regexp $pat
return
}
# InitDatePats --
#
# Internal procedure that initializes the set of date patterns
# allowed in an RFC2822 date
#
# Parameters:
# permissible - 1 if erroneous (but common) time zones are to be
# allowed, 0 if they are to be rejected
#
# Results:
# None.
#
# Side effects:
proc ::clock::rfc2822::InitDatePats { permissible } {
# Produce formats for the observed variants of RFC 2822 dates.
# Permissible variants come first in the list; impermissible ones
# come later.
# The month and day may be "%b %d" or "%d %b"
foreach mdpat {{[[:alpha:]]+[[:space:]]+\d\d?}
{\d\d?[[:space:]]+[[:alpha:]]+}} \
mdgrp {{%b %d} {%d %b}} \
mdperm {0 1} {
# The year may be two digits, or four. Four digit year is
# done first.
foreach ypat {{\d\d\d\d} {\d\d}} ygrp {%Y %y} {
# The seconds of the minute may be provided, or
# omitted.
foreach spat {{:\d\d} {}} sgrp {:%S {}} {
# The weekday may be provided or omitted. It is
# common but impermissible to omit the comma after
# the weekday name.
foreach wpat {
{(?:Mon|T(?:ue|hu)|Wed|Fri|S(?:at|un)),[[:space:]]+}
{(?:Mon|T(?:ue|hu)|Wed|Fri|S(?:at|un))[[:space:]]+}
{}
} wgrp {
{%a, }
{%a }
{}
} wperm {
1
0
1
} {
# Time zone is defined as +/- hhmm, or as a
# named time zone. Other common but buggy
# formats are GMT+-hh:mm, a time zone name in
# quotation marks, and complete omission of
# the time zone.
foreach zpat {
{[[:space:]]+(?:[-+]\d\d\d\d|[[:alpha:]]+)}
{[[:space:]]+GMT[-+]\d\d:?\d\d}
{[[:space:]]+"[[:alpha:]]+"}
{}
} zgrp {
{ %Z}
{ GMT%Z}
{ "%Z"}
{}
} zperm {
1
0
0
0
} {
if { ($zperm && $wperm && $mdperm)
== $permissible } {
AddDatePat $wpat $wgrp $ypat $ygrp \
$mdpat $mdgrp \
$spat $sgrp $zpat $zgrp
}
}
}
}
}
}
return
}
# # ## ### ##### ######## ############# #####################
## State
namespace eval ::clock::rfc2822 {
namespace export parse_date
namespace ensemble create
variable datepats {}
}
# # ## ### ##### ######## ############# #####################
# Initialize the date patterns
namespace eval ::clock::rfc2822 {
InitDatePats 1
InitDatePats 0
rename AddDatePat {}
rename InitDatePats {}
#puts [join $datepats \n]
}
# # ## ### ##### ######## ############# #####################
return
# Usage example, disabled
if {![info exists ::argv0] || [info script] ne $::argv0} return
puts [clock format \
[::clock::rfc2822::parse_date {Mon(day), 23 Aug(ust) 2004 01:23:45 UT}]]
puts [clock format \
[::clock::rfc2822::parse_date "Tue, Jul 21 2009 19:37:47 GMT-0400"]]

933
src/vendorlib_tcl9/tcllib2.0/cmdline/cmdline.tcl

@ -0,0 +1,933 @@
# cmdline.tcl --
#
# This package provides a utility for parsing command line
# arguments that are processed by our various applications.
# It also includes a utility routine to determine the
# application name for use in command line errors.
#
# Copyright (c) 1998-2000 by Ajuba Solutions.
# Copyright (c) 2001-2015 by Andreas Kupries <andreas_kupries@users.sf.net>.
# Copyright (c) 2003 by David N. Welton <davidw@dedasys.com>
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
package require Tcl 8.5 9
package provide cmdline 1.5.3
namespace eval ::cmdline {
namespace export getArgv0 getopt getKnownOpt getfiles getoptions \
getKnownOptions usage
}
# ::cmdline::getopt --
#
# The cmdline::getopt works in a fashion like the standard
# C based getopt function. Given an option string and a
# pointer to an array or args this command will process the
# first argument and return info on how to proceed.
#
# Arguments:
# argvVar Name of the argv list that you
# want to process. If options are found the
# arg list is modified and the processed arguments
# are removed from the start of the list.
# optstring A list of command options that the application
# will accept. If the option ends in ".arg" the
# getopt routine will use the next argument as
# an argument to the option. Otherwise the option
# is a boolean that is set to 1 if present.
# optVar The variable pointed to by optVar
# contains the option that was found (without the
# leading '-' and without the .arg extension).
# valVar Upon success, the variable pointed to by valVar
# contains the value for the specified option.
# This value comes from the command line for .arg
# options, otherwise the value is 1.
# If getopt fails, the valVar is filled with an
# error message.
#
# Results:
# The getopt function returns 1 if an option was found, 0 if no more
# options were found, and -1 if an error occurred.
proc ::cmdline::getopt {argvVar optstring optVar valVar} {
upvar 1 $argvVar argsList
upvar 1 $optVar option
upvar 1 $valVar value
set result [getKnownOpt argsList $optstring option value]
if {$result < 0} {
# Collapse unknown-option error into any-other-error result.
set result -1
}
return $result
}
# ::cmdline::getKnownOpt --
#
# The cmdline::getKnownOpt works in a fashion like the standard
# C based getopt function. Given an option string and a
# pointer to an array or args this command will process the
# first argument and return info on how to proceed.
#
# Arguments:
# argvVar Name of the argv list that you
# want to process. If options are found the
# arg list is modified and the processed arguments
# are removed from the start of the list. Note that
# unknown options and the args that follow them are
# left in this list.
# optstring A list of command options that the application
# will accept. If the option ends in ".arg" the
# getopt routine will use the next argument as
# an argument to the option. Otherwise the option
# is a boolean that is set to 1 if present.
# optVar The variable pointed to by optVar
# contains the option that was found (without the
# leading '-' and without the .arg extension).
# valVar Upon success, the variable pointed to by valVar
# contains the value for the specified option.
# This value comes from the command line for .arg
# options, otherwise the value is 1.
# If getopt fails, the valVar is filled with an
# error message.
#
# Results:
# The getKnownOpt function returns 1 if an option was found,
# 0 if no more options were found, -1 if an unknown option was
# encountered, and -2 if any other error occurred.
proc ::cmdline::getKnownOpt {argvVar optstring optVar valVar} {
upvar 1 $argvVar argsList
upvar 1 $optVar option
upvar 1 $valVar value
# default settings for a normal return
set value ""
set option ""
set result 0
# check if we're past the end of the args list
if {[llength $argsList] != 0} {
# if we got -- or an option that doesn't begin with -, return (skipping
# the --). otherwise process the option arg.
switch -glob -- [set arg [lindex $argsList 0]] {
"--" {
set argsList [lrange $argsList 1 end]
}
"--*" -
"-*" {
set option [string range $arg 1 end]
if {[string equal [string range $option 0 0] "-"]} {
set option [string range $arg 2 end]
}
# support for format: [-]-option=value
set idx [string first "=" $option 1]
if {$idx != -1} {
set _val [string range $option [expr {$idx+1}] end]
set option [string range $option 0 [expr {$idx-1}]]
}
if {[lsearch -exact $optstring $option] != -1} {
# Booleans are set to 1 when present
set value 1
set result 1
set argsList [lrange $argsList 1 end]
} elseif {[lsearch -exact $optstring "$option.arg"] != -1} {
set result 1
set argsList [lrange $argsList 1 end]
if {[info exists _val]} {
set value $_val
} elseif {[llength $argsList]} {
set value [lindex $argsList 0]
set argsList [lrange $argsList 1 end]
} else {
set value "Option \"$option\" requires an argument"
set result -2
}
} else {
# Unknown option.
set value "Illegal option \"-$option\""
set result -1
}
}
default {
# Skip ahead
}
}
}
return $result
}
# ::cmdline::getoptions --
#
# Process a set of command line options, filling in defaults
# for those not specified. This also generates an error message
# that lists the allowed flags if an incorrect flag is specified.
#
# Arguments:
# argvVar The name of the argument list, typically argv.
# We remove all known options and their args from it.
# In other words, after the call to this command the
# referenced variable contains only the non-options,
# and unknown options.
# optlist A list-of-lists where each element specifies an option
# in the form:
# (where flag takes no argument)
# flag comment
#
# (or where flag takes an argument)
# flag default comment
#
# If flag ends in ".arg" then the value is taken from the
# command line. Otherwise it is a boolean and appears in
# the result if present on the command line. If flag ends
# in ".secret", it will not be displayed in the usage.
# usage Text to include in the usage display. Defaults to
# "options:"
#
# Results
# Name value pairs suitable for using with array set.
# A modified `argvVar`.
proc ::cmdline::getoptions {argvVar optlist {usage options:}} {
upvar 1 $argvVar argv
set opts [GetOptionDefaults $optlist result]
set argc [llength $argv]
while {[set err [getopt argv $opts opt arg]]} {
if {$err < 0} {
set result(?) ""
break
}
set result($opt) $arg
}
if {[info exist result(?)] || [info exists result(help)]} {
Error [usage $optlist $usage] USAGE
}
return [array get result]
}
# ::cmdline::getKnownOptions --
#
# Process a set of command line options, filling in defaults
# for those not specified. This ignores unknown flags, but generates
# an error message that lists the correct usage if a known option
# is used incorrectly.
#
# Arguments:
# argvVar The name of the argument list, typically argv. This
# We remove all known options and their args from it.
# In other words, after the call to this command the
# referenced variable contains only the non-options,
# and unknown options.
# optlist A list-of-lists where each element specifies an option
# in the form:
# flag default comment
# If flag ends in ".arg" then the value is taken from the
# command line. Otherwise it is a boolean and appears in
# the result if present on the command line. If flag ends
# in ".secret", it will not be displayed in the usage.
# usage Text to include in the usage display. Defaults to
# "options:"
#
# Results
# Name value pairs suitable for using with array set.
# A modified `argvVar`.
proc ::cmdline::getKnownOptions {argvVar optlist {usage options:}} {
upvar 1 $argvVar argv
set opts [GetOptionDefaults $optlist result]
# As we encounter them, keep the unknown options and their
# arguments in this list. Before we return from this procedure,
# we'll prepend these args to the argList so that the application
# doesn't lose them.
set unknownOptions [list]
set argc [llength $argv]
while {[set err [getKnownOpt argv $opts opt arg]]} {
if {$err == -1} {
# Unknown option.
# Skip over any non-option items that follow it.
# For now, add them to the list of unknownOptions.
lappend unknownOptions [lindex $argv 0]
set argv [lrange $argv 1 end]
while {([llength $argv] != 0) \
&& ![string match "-*" [lindex $argv 0]]} {
lappend unknownOptions [lindex $argv 0]
set argv [lrange $argv 1 end]
}
} elseif {$err == -2} {
set result(?) ""
break
} else {
set result($opt) $arg
}
}
# Before returning, prepend the any unknown args back onto the
# argList so that the application doesn't lose them.
set argv [concat $unknownOptions $argv]
if {[info exist result(?)] || [info exists result(help)]} {
Error [usage $optlist $usage] USAGE
}
return [array get result]
}
# ::cmdline::GetOptionDefaults --
#
# This internal procedure processes the option list (that was passed to
# the getopt or getKnownOpt procedure). The defaultArray gets an index
# for each option in the option list, the value of which is the option's
# default value.
#
# Arguments:
# optlist A list-of-lists where each element specifies an option
# in the form:
# flag default comment
# If flag ends in ".arg" then the value is taken from the
# command line. Otherwise it is a boolean and appears in
# the result if present on the command line. If flag ends
# in ".secret", it will not be displayed in the usage.
# defaultArrayVar The name of the array in which to put argument defaults.
#
# Results
# Name value pairs suitable for using with array set.
proc ::cmdline::GetOptionDefaults {optlist defaultArrayVar} {
upvar 1 $defaultArrayVar result
set opts {? help}
foreach opt $optlist {
set name [lindex $opt 0]
if {[regsub -- {\.secret$} $name {} name] == 1} {
# Need to hide this from the usage display and getopt
}
lappend opts $name
if {[regsub -- {\.arg$} $name {} name] == 1} {
# Set defaults for those that take values.
set default [lindex $opt 1]
set result($name) $default
} else {
# The default for booleans is false
set result($name) 0
}
}
return $opts
}
# ::cmdline::usage --
#
# Generate an error message that lists the allowed flags.
#
# Arguments:
# optlist As for cmdline::getoptions
# usage Text to include in the usage display. Defaults to
# "options:"
#
# Results
# A formatted usage message
proc ::cmdline::usage {optlist {usage {options:}}} {
set str "[getArgv0] $usage\n"
set longest 20
set lines {}
foreach opt [concat $optlist \
{{- "Forcibly stop option processing"} {help "Print this message"} {? "Print this message"}}] {
set name "-[lindex $opt 0]"
if {[regsub -- {\.secret$} $name {} name] == 1} {
# Hidden option
continue
}
if {[regsub -- {\.arg$} $name {} name] == 1} {
append name " value"
set desc "[lindex $opt 2] <[lindex $opt 1]>"
} else {
set desc "[lindex $opt 1]"
}
set n [string length $name]
if {$n > $longest} { set longest $n }
# max not available before 8.5 - set longest [expr {max($longest, )}]
lappend lines $name $desc
}
foreach {name desc} $lines {
append str "[string trimright [format " %-*s %s" $longest $name $desc]]\n"
}
return $str
}
# ::cmdline::getfiles --
#
# Given a list of file arguments from the command line, compute
# the set of valid files. On windows, file globbing is performed
# on each argument. On Unix, only file existence is tested. If
# a file argument produces no valid files, a warning is optionally
# generated.
#
# This code also uses the full path for each file. If not
# given it prepends [pwd] to the filename. This ensures that
# these files will never conflict with files in our zip file.
#
# Arguments:
# patterns The file patterns specified by the user.
# quiet If this flag is set, no warnings will be generated.
#
# Results:
# Returns the list of files that match the input patterns.
proc ::cmdline::getfiles {patterns quiet} {
set result {}
if {$::tcl_platform(platform) == "windows"} {
foreach pattern $patterns {
set pat [file join $pattern]
set files [glob -nocomplain -- $pat]
if {$files == {}} {
if {! $quiet} {
puts stdout "warning: no files match \"$pattern\""
}
} else {
foreach file $files {
lappend result $file
}
}
}
} else {
set result $patterns
}
set files {}
foreach file $result {
# Make file an absolute path so that we will never conflict
# with files that might be contained in our zip file.
set fullPath [file join [pwd] $file]
if {[file isfile $fullPath]} {
lappend files $fullPath
} elseif {! $quiet} {
puts stdout "warning: no files match \"$file\""
}
}
return $files
}
# ::cmdline::getArgv0 --
#
# This command returns the "sanitized" version of argv0. It will strip
# off the leading path and remove the ".bin" extensions that our apps
# use because they must be wrapped by a shell script.
#
# Arguments:
# None.
#
# Results:
# The application name that can be used in error messages.
proc ::cmdline::getArgv0 {} {
global argv0
set name [file tail $argv0]
return [file rootname $name]
}
##
# ### ### ### ######### ######### #########
##
# Now the typed versions of the above commands.
##
# ### ### ### ######### ######### #########
##
# typedCmdline.tcl --
#
# This package provides a utility for parsing typed command
# line arguments that may be processed by various applications.
#
# Copyright (c) 2000 by Ross Palmer Mohn.
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: cmdline.tcl,v 1.28 2011/02/23 17:41:52 andreas_kupries Exp $
namespace eval ::cmdline {
namespace export typedGetopt typedGetoptions typedUsage
# variable cmdline::charclasses --
#
# Create regexp list of allowable character classes
# from "string is" error message.
#
# Results:
# String of character class names separated by "|" characters.
variable charclasses
#checker exclude badKey
catch {string is . .} charclasses
variable dummy
regexp -- {must be (.+)$} $charclasses dummy charclasses
regsub -all -- {, (or )?} $charclasses {|} charclasses
unset dummy
}
# ::cmdline::typedGetopt --
#
# The cmdline::typedGetopt works in a fashion like the standard
# C based getopt function. Given an option string and a
# pointer to a list of args this command will process the
# first argument and return info on how to proceed. In addition,
# you may specify a type for the argument to each option.
#
# Arguments:
# argvVar Name of the argv list that you want to process.
# If options are found, the arg list is modified
# and the processed arguments are removed from the
# start of the list.
#
# optstring A list of command options that the application
# will accept. If the option ends in ".xxx", where
# xxx is any valid character class to the tcl
# command "string is", then typedGetopt routine will
# use the next argument as a typed argument to the
# option. The argument must match the specified
# character classes (e.g. integer, double, boolean,
# xdigit, etc.). Alternatively, you may specify
# ".arg" for an untyped argument.
#
# optVar Upon success, the variable pointed to by optVar
# contains the option that was found (without the
# leading '-' and without the .xxx extension). If
# typedGetopt fails the variable is set to the empty
# string. SOMETIMES! Different for each -value!
#
# argVar Upon success, the variable pointed to by argVar
# contains the argument for the specified option.
# If typedGetopt fails, the variable is filled with
# an error message.
#
# Argument type syntax:
# Option that takes no argument.
# foo
#
# Option that takes a typeless argument.
# foo.arg
#
# Option that takes a typed argument. Allowable types are all
# valid character classes to the tcl command "string is".
# Currently must be one of alnum, alpha, ascii, control,
# boolean, digit, double, false, graph, integer, lower, print,
# punct, space, true, upper, wordchar, or xdigit.
# foo.double
#
# Option that takes an argument from a list.
# foo.(bar|blat)
#
# Argument quantifier syntax:
# Option that takes an optional argument.
# foo.arg?
#
# Option that takes a list of arguments terminated by "--".
# foo.arg+
#
# Option that takes an optional list of arguments terminated by "--".
# foo.arg*
#
# Argument quantifiers work on all argument types, so, for
# example, the following is a valid option specification.
# foo.(bar|blat|blah)?
#
# Argument syntax miscellany:
# Options may be specified on the command line using a unique,
# shortened version of the option name. Given that program foo
# has an option list of {bar.alpha blah.arg blat.double},
# "foo -b fob" returns an error, but "foo -ba fob"
# successfully returns {bar fob}
#
# Results:
# The typedGetopt function returns one of the following:
# 1 a valid option was found
# 0 no more options found to process
# -1 invalid option
# -2 missing argument to a valid option
# -3 argument to a valid option does not match type
#
# Known Bugs:
# When using options which include special glob characters,
# you must use the exact option. Abbreviating it can cause
# an error in the "cmdline::prefixSearch" procedure.
proc ::cmdline::typedGetopt {argvVar optstring optVar argVar} {
variable charclasses
upvar $argvVar argsList
upvar $optVar retvar
upvar $argVar optarg
# default settings for a normal return
set optarg ""
set retvar ""
set retval 0
# check if we're past the end of the args list
if {[llength $argsList] != 0} {
# if we got -- or an option that doesn't begin with -, return (skipping
# the --). otherwise process the option arg.
switch -glob -- [set arg [lindex $argsList 0]] {
"--" {
set argsList [lrange $argsList 1 end]
}
"-*" {
# Create list of options without their argument extensions
set optstr ""
foreach str $optstring {
lappend optstr [file rootname $str]
}
set _opt [string range $arg 1 end]
set i [prefixSearch $optstr [file rootname $_opt]]
if {$i != -1} {
set opt [lindex $optstring $i]
set quantifier "none"
if {[regexp -- {\.[^.]+([?+*])$} $opt dummy quantifier]} {
set opt [string range $opt 0 end-1]
}
if {[string first . $opt] == -1} {
set retval 1
set retvar $opt
set argsList [lrange $argsList 1 end]
} elseif {[regexp -- "\\.(arg|$charclasses)\$" $opt dummy charclass]
|| [regexp -- {\.\(([^)]+)\)} $opt dummy charclass]} {
if {[string equal arg $charclass]} {
set type arg
} elseif {[regexp -- "^($charclasses)\$" $charclass]} {
set type class
} else {
set type oneof
}
set argsList [lrange $argsList 1 end]
set opt [file rootname $opt]
while {1} {
if {[llength $argsList] == 0
|| [string equal "--" [lindex $argsList 0]]} {
if {[string equal "--" [lindex $argsList 0]]} {
set argsList [lrange $argsList 1 end]
}
set oneof ""
if {$type == "arg"} {
set charclass an
} elseif {$type == "oneof"} {
set oneof ", one of $charclass"
set charclass an
}
if {$quantifier == "?"} {
set retval 1
set retvar $opt
set optarg ""
} elseif {$quantifier == "+"} {
set retvar $opt
if {[llength $optarg] < 1} {
set retval -2
set optarg "Option requires at least one $charclass argument$oneof -- $opt"
} else {
set retval 1
}
} elseif {$quantifier == "*"} {
set retval 1
set retvar $opt
} else {
set optarg "Option requires $charclass argument$oneof -- $opt"
set retvar $opt
set retval -2
}
set quantifier ""
} elseif {($type == "arg")
|| (($type == "oneof")
&& [string first "|[lindex $argsList 0]|" "|$charclass|"] != -1)
|| (($type == "class")
&& [string is $charclass [lindex $argsList 0]])} {
set retval 1
set retvar $opt
lappend optarg [lindex $argsList 0]
set argsList [lrange $argsList 1 end]
} else {
set oneof ""
if {$type == "arg"} {
set charclass an
} elseif {$type == "oneof"} {
set oneof ", one of $charclass"
set charclass an
}
set optarg "Option requires $charclass argument$oneof -- $opt"
set retvar $opt
set retval -3
if {$quantifier == "?"} {
set retval 1
set optarg ""
}
set quantifier ""
}
if {![regexp -- {[+*]} $quantifier]} {
break;
}
}
} else {
Error \
"Illegal option type specification: must be one of $charclasses" \
BAD OPTION TYPE
}
} else {
set optarg "Illegal option -- $_opt"
set retvar $_opt
set retval -1
}
}
default {
# Skip ahead
}
}
}
return $retval
}
# ::cmdline::typedGetoptions --
#
# Process a set of command line options, filling in defaults
# for those not specified. This also generates an error message
# that lists the allowed options if an incorrect option is
# specified.
#
# Arguments:
# argvVar The name of the argument list, typically argv
# optlist A list-of-lists where each element specifies an option
# in the form:
#
# option default comment
#
# Options formatting is as described for the optstring
# argument of typedGetopt. Default is for optionally
# specifying a default value. Comment is for optionally
# specifying a comment for the usage display. The
# options "--", "-help", and "-?" are automatically included
# in optlist.
#
# Argument syntax miscellany:
# Options formatting and syntax is as described in typedGetopt.
# There are two additional suffixes that may be applied when
# passing options to typedGetoptions.
#
# You may add ".multi" as a suffix to any option. For options
# that take an argument, this means that the option may be used
# more than once on the command line and that each additional
# argument will be appended to a list, which is then returned
# to the application.
# foo.double.multi
#
# If a non-argument option is specified as ".multi", it is
# toggled on and off for each time it is used on the command
# line.
# foo.multi
#
# If an option specification does not contain the ".multi"
# suffix, it is not an error to use an option more than once.
# In this case, the behavior for options with arguments is that
# the last argument is the one that will be returned. For
# options that do not take arguments, using them more than once
# has no additional effect.
#
# Options may also be hidden from the usage display by
# appending the suffix ".secret" to any option specification.
# Please note that the ".secret" suffix must be the last suffix,
# after any argument type specification and ".multi" suffix.
# foo.xdigit.multi.secret
#
# Results
# Name value pairs suitable for using with array set.
proc ::cmdline::typedGetoptions {argvVar optlist {usage options:}} {
variable charclasses
upvar 1 $argvVar argv
set opts {? help}
foreach opt $optlist {
set name [lindex $opt 0]
if {[regsub -- {\.secret$} $name {} name] == 1} {
# Remove this extension before passing to typedGetopt.
}
if {[regsub -- {\.multi$} $name {} name] == 1} {
# Remove this extension before passing to typedGetopt.
regsub -- {\..*$} $name {} temp
set multi($temp) 1
}
lappend opts $name
if {[regsub -- "\\.(arg|$charclasses|\\(.+).?\$" $name {} name] == 1} {
# Set defaults for those that take values.
# Booleans are set just by being present, or not
set dflt [lindex $opt 1]
if {$dflt != {}} {
set defaults($name) $dflt
}
}
}
set argc [llength $argv]
while {[set err [typedGetopt argv $opts opt arg]]} {
if {$err == 1} {
if {[info exists result($opt)]
&& [info exists multi($opt)]} {
# Toggle boolean options or append new arguments
if {$arg == ""} {
unset result($opt)
} else {
set result($opt) "$result($opt) $arg"
}
} else {
set result($opt) "$arg"
}
} elseif {($err == -1) || ($err == -3)} {
Error [typedUsage $optlist $usage] USAGE
} elseif {$err == -2 && ![info exists defaults($opt)]} {
Error [typedUsage $optlist $usage] USAGE
}
}
if {[info exists result(?)] || [info exists result(help)]} {
Error [typedUsage $optlist $usage] USAGE
}
foreach {opt dflt} [array get defaults] {
if {![info exists result($opt)]} {
set result($opt) $dflt
}
}
return [array get result]
}
# ::cmdline::typedUsage --
#
# Generate an error message that lists the allowed flags,
# type of argument taken (if any), default value (if any),
# and an optional description.
#
# Arguments:
# optlist As for cmdline::typedGetoptions
#
# Results
# A formatted usage message
proc ::cmdline::typedUsage {optlist {usage {options:}}} {
variable charclasses
set str "[getArgv0] $usage\n"
set longest 20
set lines {}
foreach opt [concat $optlist \
{{help "Print this message"} {? "Print this message"}}] {
set name "-[lindex $opt 0]"
if {[regsub -- {\.secret$} $name {} name] == 1} {
# Hidden option
continue
}
if {[regsub -- {\.multi$} $name {} name] == 1} {
# Display something about multiple options
}
if {[regexp -- "\\.(arg|$charclasses)\$" $name dummy charclass] ||
[regexp -- {\.\(([^)]+)\)} $opt dummy charclass]
} {
regsub -- "\\..+\$" $name {} name
append name " $charclass"
set desc [lindex $opt 2]
set default [lindex $opt 1]
if {$default != ""} {
append desc " <$default>"
}
} else {
set desc [lindex $opt 1]
}
lappend accum $name $desc
set n [string length $name]
if {$n > $longest} { set longest $n }
# max not available before 8.5 - set longest [expr {max($longest, [string length $name])}]
}
foreach {name desc} $accum {
append str "[string trimright [format " %-*s %s" $longest $name $desc]]\n"
}
return $str
}
# ::cmdline::prefixSearch --
#
# Search a Tcl list for a pattern; searches first for an exact match,
# and if that fails, for a unique prefix that matches the pattern
# (i.e, first "lsearch -exact", then "lsearch -glob $pattern*"
#
# Arguments:
# list list of words
# pattern word to search for
#
# Results:
# Index of found word is returned. If no exact match or
# unique short version is found then -1 is returned.
proc ::cmdline::prefixSearch {list pattern} {
# Check for an exact match
if {[set pos [::lsearch -exact $list $pattern]] > -1} {
return $pos
}
# Check for a unique short version
set slist [lsort $list]
if {[set pos [::lsearch -glob $slist $pattern*]] > -1} {
# What if there is nothing for the check variable?
set check [lindex $slist [expr {$pos + 1}]]
if {[string first $pattern $check] != 0} {
return [::lsearch -exact $list [lindex $slist $pos]]
}
}
return -1
}
# ::cmdline::Error --
#
# Internal helper to throw errors with a proper error-code attached.
#
# Arguments:
# message text of the error message to throw.
# args additional parts of the error code to use,
# with CMDLINE as basic prefix added by this command.
#
# Results:
# An error is thrown, always.
proc ::cmdline::Error {message args} {
return -code error -errorcode [linsert $args 0 CMDLINE] $message
}

2
src/vendorlib_tcl9/tcllib2.0/cmdline/pkgIndex.tcl

@ -0,0 +1,2 @@
if {![package vsatisfies [package provide Tcl] 8.5 9]} {return}
package ifneeded cmdline 1.5.3 [list source [file join $dir cmdline.tcl]]

1806
src/vendorlib_tcl9/tcllib2.0/comm/comm.tcl

File diff suppressed because it is too large Load Diff

2
src/vendorlib_tcl9/tcllib2.0/comm/pkgIndex.tcl

@ -0,0 +1,2 @@
if {![package vsatisfies [package provide Tcl] 8.5 9]} {return}
package ifneeded comm 4.7.3 [list source [file join $dir comm.tcl]]

72
src/vendorlib_tcl9/tcllib2.0/control/ascaller.tcl

@ -0,0 +1,72 @@
# ascaller.tcl -
#
# A few utility procs that manage the evaluation of a command
# or a script in the context of a caller, taking care of all
# the ugly details of proper return codes, errorcodes, and
# a good stack trace in ::errorInfo as appropriate.
# -------------------------------------------------------------------------
#
# RCS: @(#) $Id: ascaller.tcl,v 1.3 2004/01/15 06:36:12 andreas_kupries Exp $
namespace eval ::control {
proc CommandAsCaller {cmdVar resultVar {where {}} {codeVar code}} {
set x [expr {[string equal "" $where]
? {} : [subst -nobackslashes {\n ($where)}]}]
set script [subst -nobackslashes -nocommands {
set $codeVar [catch {uplevel 1 $$cmdVar} $resultVar]
if {$$codeVar > 1} {
return -code $$codeVar $$resultVar
}
if {$$codeVar == 1} {
if {[string equal {"uplevel 1 $$cmdVar"} \
[lindex [split [set ::errorInfo] \n] end]]} {
set $codeVar [join \
[lrange [split [set ::errorInfo] \n] 0 \
end-[expr {4+[llength [split $$cmdVar \n]]}]] \n]
} else {
set $codeVar [join \
[lrange [split [set ::errorInfo] \n] 0 end-1] \n]
}
return -code error -errorcode [set ::errorCode] \
-errorinfo "$$codeVar$x" $$resultVar
}
}]
return $script
}
proc BodyAsCaller {bodyVar resultVar codeVar {where {}}} {
set x [expr {[string equal "" $where]
? {} : [subst -nobackslashes -nocommands \
{\n ($where[string map {{ ("uplevel"} {}} \
[lindex [split [set ::errorInfo] \n] end]]}]}]
set script [subst -nobackslashes -nocommands {
set $codeVar [catch {uplevel 1 $$bodyVar} $resultVar]
if {$$codeVar == 1} {
if {[string equal {"uplevel 1 $$bodyVar"} \
[lindex [split [set ::errorInfo] \n] end]]} {
set ::errorInfo [join \
[lrange [split [set ::errorInfo] \n] 0 end-2] \n]
}
set $codeVar [join \
[lrange [split [set ::errorInfo] \n] 0 end-1] \n]
return -code error -errorcode [set ::errorCode] \
-errorinfo "$$codeVar$x" $$resultVar
}
}]
return $script
}
proc ErrorInfoAsCaller {find replace} {
set info $::errorInfo
set i [string last "\n (\"$find" $info]
if {$i == -1} {return $info}
set result [string range $info 0 [incr i 6]] ;# keep "\n (\""
append result $replace ;# $find -> $replace
incr i [string length $find]
set j [string first ) $info [incr i]] ;# keep rest of parenthetical
append result [string range $info $i $j]
return $result
}
}

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

Loading…
Cancel
Save