@@ -32,12 +32,9 @@ namespace eval ::safe {
3232# Helper function to resolve the dual way of specifying staticsok (either
3333# by -noStatics or -statics 0)
3434proc ::safe::InterpStatics {} {
35- foreach v {Args statics noStatics} {
36- upvar $v $v
37- }
38- set flag [::tcl::OptProcArgGiven -noStatics]
39- if {$flag && (!$noStatics == !$statics )
40- && ([::tcl::OptProcArgGiven -statics])} {
35+ upvar 1 Args Args statics statics noStatics noStatics
36+ set flag [expr {" -noStatics" in $Args }]
37+ if {$flag && (!$noStatics == !$statics ) && (" -statics" in $Args )} {
4138 return -code error\
4239 " conflicting values given for -statics and -noStatics"
4340 }
@@ -51,14 +48,11 @@ proc ::safe::InterpStatics {} {
5148# Helper function to resolve the dual way of specifying nested loading
5249# (either by -nestedLoadOk or -nested 1)
5350proc ::safe::InterpNested {} {
54- foreach v {Args nested nestedLoadOk} {
55- upvar $v $v
56- }
57- set flag [::tcl::OptProcArgGiven -nestedLoadOk]
51+ upvar 1 Args Args nested nested nestedLoadOk nestedLoadOk
52+ set flag [expr {" -nestedLoadOk" in $Args }]
5853 # note that the test here is the opposite of the "InterpStatics" one
5954 # (it is not -noNested... because of the wanted default value)
60- if {$flag && (!$nestedLoadOk != !$nested )
61- && ([::tcl::OptProcArgGiven -nested])} {
55+ if {$flag && (!$nestedLoadOk != !$nested ) && (" -nested" in $Args )} {
6256 return -code error\
6357 " conflicting values given for -nested and -nestedLoadOk"
6458 }
@@ -85,7 +79,7 @@ proc ::safe::interpCreate {args} {
8579 set Args [::tcl::OptKeyParse ::safe::interpCreate $args ]
8680 RejectExcessColons $child
8781
88- set withAutoPath [::tcl::OptProcArgGiven -autoPath]
82+ set withAutoPath [expr { " -autoPath" in $Args } ]
8983 InterpCreate $child $accessPath \
9084 [InterpStatics] [InterpNested] $deleteHook $autoPath $withAutoPath
9185}
@@ -101,7 +95,7 @@ proc ::safe::interpInit {args} {
10195 }
10296 RejectExcessColons $child
10397
104- set withAutoPath [::tcl::OptProcArgGiven -autoPath]
98+ set withAutoPath [expr { " -autoPath" in $Args } ]
10599 InterpInit $child $accessPath \
106100 [InterpStatics] [InterpNested] $deleteHook $autoPath $withAutoPath
107101}
@@ -218,39 +212,33 @@ proc ::safe::interpConfigure {args} {
218212
219213 # Get the current (and not the default) values of whatever has
220214 # not been given:
221- if {![::tcl::OptProcArgGiven -accessPath] } {
215+ if {" -accessPath" ni $Args } {
222216 set doreset 0
223217 set accessPath $state(access_path)
224218 } else {
225219 set doreset 1
226220 }
227- if {(!$AutoPathSync ) && (![::tcl::OptProcArgGiven -autoPath] )} {
221+ if {(!$AutoPathSync ) && (" -autoPath" ni $Args )} {
228222 set autoPath $state(auto_path)
229223 } elseif {$AutoPathSync } {
230224 set autoPath {}
231225 } else {
232226 }
233- if {
234- ![::tcl::OptProcArgGiven -statics]
235- && ![::tcl::OptProcArgGiven -noStatics]
236- } then {
227+ if {(" -statics" ni $Args ) && (" -noStatics" ni $Args )} {
237228 set statics $state(staticsok)
238229 } else {
239230 set statics [InterpStatics]
240231 }
241- if {
242- [::tcl::OptProcArgGiven -nested] ||
243- [::tcl::OptProcArgGiven -nestedLoadOk]
244- } then {
232+ if {(" -nested" in $Args ) || (" -nestedLoadOk" in $Args )} {
245233 set nested [InterpNested]
246234 } else {
247235 set nested $state(nestedok)
248236 }
249- if {![::tcl::OptProcArgGiven -deleteHook] } {
237+ if {" -deleteHook" ni $Args } {
250238 set deleteHook $state(cleanupHook)
251239 }
252240 # Now reconfigure
253- set withAutoPath [::tcl::OptProcArgGiven -autoPath]
241+ set withAutoPath [expr { " -autoPath" in $Args } ]
254242 InterpSetConfig $child $accessPath $statics $nested $deleteHook $autoPath $withAutoPath
255243
256244 # auto_reset the child (to completely sync the new access_path) tests safe-9.8 safe-9.9
@@ -361,14 +349,13 @@ proc ::safe::InterpSetConfig {child access_path staticsok nestedok deletehook au
361349 set where [lsearch -exact $access_path [info library]]
362350 if {$where < 0} {
363351 # not found, add it.
364- set access_path [ linsert $access_path 0 [info library] ]
352+ ledit access_path 0 -1 [info library]
365353 Log $child " tcl_library was not in auto_path,\
366354 added it to child's access_path" NOTICE
367- } elseif {$where != 0} {
355+ } elseif {$where > 0} {
368356 # not first, move it first
369- set access_path [linsert \
370- [lreplace $access_path $where $where ] \
371- 0 [info library]]
357+ ledit access_path $where $where ; # Remove
358+ ledit access_path 0 -1 [info library]; # Insert at beginning
372359 Log $child " tcl_libray was not in first in auto_path,\
373360 moved it to front of child's access_path" NOTICE
374361 }
@@ -410,10 +397,10 @@ proc ::safe::InterpSetConfig {child access_path staticsok nestedok deletehook au
410397 set i 0
411398 foreach dir $access_path {
412399 set token [PathToken $i ]
413- lappend child_access_path $token
414- lappend map_access_path $token $dir
415- lappend remap_access_path $dir $token
416- lappend norm_access_path [file normalize $dir ]
400+ lappend child_access_path $token
401+ dict set map_access_path $token $dir
402+ dict set remap_access_path $dir $token
403+ lappend norm_access_path [file normalize $dir ]
417404 incr i
418405 }
419406
@@ -451,11 +438,11 @@ proc ::safe::InterpSetConfig {child access_path staticsok nestedok deletehook au
451438 }
452439
453440 set token [PathToken $i ]
454- lappend access_path $dir
455- lappend child_access_path $token
456- lappend map_access_path $token $dir
457- lappend remap_access_path $dir $token
458- lappend norm_access_path [file normalize $dir ]
441+ lappend access_path $dir
442+ lappend child_access_path $token
443+ dict set map_access_path $token $dir
444+ dict set remap_access_path $dir $token
445+ lappend norm_access_path [file normalize $dir ]
459446 if {$firstpass } {
460447 # $dir is in [::tcl::tm::list] and belongs in the child_tm_path.
461448 # Later passes handle subdirectories, which belong in the
@@ -503,15 +490,9 @@ proc ::safe::InterpSetConfig {child access_path staticsok nestedok deletehook au
503490proc ::safe::DetokPath {child tokenPath} {
504491 namespace upvar ::safe [VarName $child ] state
505492
506- set childPath {}
507- foreach token $tokenPath {
508- if {[dict exists $state(access_path,map) $token ]} {
509- lappend childPath [dict get $state(access_path,map) $token ]
510- } else {
511- lappend childPath $token
512- }
513- }
514- return $childPath
493+ return [lmap token $tokenPath {
494+ dict getdef $state(access_path,map) $token $token
495+ }]
515496}
516497
517498#
@@ -550,11 +531,11 @@ proc ::safe::interpAddToAccessPath {child path} {
550531 # new one, add it:
551532 set token [PathToken [llength $state(access_path) ]]
552533
553- lappend state(access_path) $path
554- lappend state(access_path,child) $token
555- lappend state(access_path,map) $token $path
556- lappend state(access_path,remap) $path $token
557- lappend state(access_path,norm) [file normalize $path ]
534+ lappend state(access_path) $path
535+ lappend state(access_path,child) $token
536+ dict set state(access_path,map) $token $path
537+ dict set state(access_path,remap) $path $token
538+ lappend state(access_path,norm) [file normalize $path ]
558539
559540 SyncAccessPath $child
560541 return $token
@@ -622,16 +603,16 @@ proc ::safe::InterpInit {
622603 # Source init.tcl and tm.tcl into the child, to get auto_load and
623604 # other procedures defined:
624605
625- if {[ catch {::interp eval $child {
606+ try {::interp eval $child {
626607 source [file join $tcl_library init.tcl]
627- }} msg opt] } {
608+ }} on error { msg opt} {
628609 Log $child " can't source init.tcl ($msg )"
629610 return -options $opt " can't source init.tcl into child $child ($msg )"
630611 }
631612
632- if {[ catch {::interp eval $child {
613+ try {::interp eval $child {
633614 source [file join $tcl_library tm.tcl]
634- }} msg opt] } {
615+ }} on error { msg opt} {
635616 Log $child " can't source tm.tcl ($msg )"
636617 return -options $opt " can't source tm.tcl into child $child ($msg )"
637618 }
@@ -905,7 +886,7 @@ proc ::safe::AliasGlob {child args} {
905886 return -code error " permission denied"
906887 }
907888 if {$got(--) } {
908- set cmd [ linsert $cmd end-1 -directory $dir ]
889+ ledit cmd end -1 -directory $dir
909890 } else {
910891 lappend cmd -directory $dir
911892 }
@@ -920,7 +901,7 @@ proc ::safe::AliasGlob {child args} {
920901
921902 # Apply the -join semantics ourselves (hence -join not copied to $cmd)
922903 if {$got(-join) } {
923- set args [ lreplace $args $ at end [join [lrange $args $at end] " /" ] ]
904+ ledit args $ at end [join [lrange $args $at end] " /" ]
924905 }
925906
926907 # Process the pattern arguments. If we've done a join there is only one
@@ -1042,17 +1023,17 @@ proc ::safe::AliasSource {child args} {
10421023 set file [lindex $args $at ]
10431024
10441025 # get the real path from the virtual one.
1045- if {[ catch {
1026+ try {
10461027 set realfile [TranslatePath $child $file ]
1047- } msg]} {
1028+ } on error msg {
10481029 Log $child $msg
10491030 return -code error " permission denied"
10501031 }
10511032
10521033 # check that the path is in the access path of that child
1053- if {[ catch {
1034+ try {
10541035 FileInAccessPath $child $realfile
1055- } msg]} {
1036+ } on error msg {
10561037 Log $child $msg
10571038 return -code error " permission denied"
10581039 }
@@ -1061,9 +1042,9 @@ proc ::safe::AliasSource {child args} {
10611042 # this -errorcode so that caller in tclPkgUnknown does not write a message
10621043 # to tclLog. Has no effect on other callers of ::source, which are in
10631044 # "package ifneeded" scripts.
1064- if {[ catch {
1045+ try {
10651046 CheckFileName $child $realfile
1066- } msg]} {
1047+ } on error msg {
10671048 Log $child " $realfile :$msg "
10681049 return -code error -errorcode {POSIX EACCES} $msg
10691050 }
@@ -1108,14 +1089,13 @@ proc ::safe::AliasLoad {child file args} {
11081089 return -code error $msg
11091090 }
11101091
1111- # prefix (can be empty if file is not).
1112- set prefix [lindex $args 0]
1113-
11141092 namespace upvar ::safe [VarName $child ] state
11151093
1094+ # prefix (can be empty if file is not).
1095+ lassign $args prefix target
1096+
11161097 # Determine where to load. load use a relative interp path and {}
11171098 # means self, so we can directly and safely use passed arg.
1118- set target [lindex $args 1]
11191099 if {$target ne " " } {
11201100 # we will try to load into a sub sub interp; check that we want to
11211101 # authorize that.
@@ -1164,7 +1144,7 @@ proc ::safe::AliasLoad {child file args} {
11641144 } on error msg {
11651145 # Some libraries return no error message.
11661146 set msg0 " load of library for prefix $prefix failed"
1167- if {$msg eq {} } {
1147+ if {$msg eq " " } {
11681148 set msg $msg0
11691149 } else {
11701150 set msg " $msg0 : $msg "
@@ -1228,16 +1208,12 @@ proc ::safe::BadSubcommand {child command subcommand args} {
12281208# AliasEncodingSystem is the target of the "encoding system" alias in safe
12291209# interpreters.
12301210proc ::safe::AliasEncodingSystem {child args} {
1231- try {
1232- # Must not pass extra arguments; safe interpreters may not set the
1233- # system encoding but they may read it.
1234- if {[llength $args ]} {
1235- return -code error -errorcode {TCL WRONGARGS} \
1236- " wrong # args: should be \" encoding system\" "
1237- }
1238- } on error {msg options} {
1211+ # Must not pass extra arguments; safe interpreters may not set the
1212+ # system encoding but they may read it.
1213+ if {[llength $args ]} {
1214+ set msg " wrong # args: should be \" encoding system\" "
12391215 Log $child $msg
1240- return -options $options $msg
1216+ return -code error -errorcode {TCL WRONGARGS} $msg
12411217 }
12421218 tailcall ::interp invokehidden $child tcl:encoding:system
12431219}
@@ -1282,14 +1258,14 @@ proc ::safe::AliasExeName {child} {
12821258
12831259proc ::safe::RejectExcessColons {child} {
12841260 set stripped [regsub -all -- {:::*} $child ::]
1285- if {[string range $stripped end-1 end] eq {::} } {
1261+ if {[string match *:: $stripped ] } {
12861262 return -code error {interpreter name must not end in " ::" }
12871263 }
12881264 if {$stripped ne $child } {
12891265 set msg {interpreter name has excess colons in namespace separators}
12901266 return -code error $msg
12911267 }
1292- if {[string range $stripped 0 1] eq {::} } {
1268+ if {[string match ::* $stripped ] } {
12931269 return -code error {interpreter name must not begin " ::" }
12941270 }
12951271 return
@@ -1374,31 +1350,35 @@ proc ::safe::Setup {} {
13741350proc ::safe::setSyncMode {args} {
13751351 variable AutoPathSync
13761352
1377- if {[llength $args ] == 0} {
1378- } elseif {[llength $args ] == 1} {
1379- set newValue [lindex $args 0]
1380- if {![string is boolean -strict $newValue ]} {
1381- return -code error " new value must be a valid boolean"
1353+ switch -integer -- [llength $args ] {
1354+ 0 {
1355+ return $AutoPathSync
13821356 }
1383- set args [expr {$newValue && $newValue }]
1384- if {([info vars ::safe::S*] ne {}) && ($args != $AutoPathSync )} {
1385- return -code error \
1386- " cannot set new value while Safe Base child interpreters exist"
1357+ 1 {
1358+ lassign $args newValue
1359+ if {![string is boolean -strict $newValue ]} {
1360+ return -code error " new value must be a valid boolean"
1361+ }
1362+ set newValue [expr {!!$newValue }]
1363+ if {([info vars ::safe::S*] ne {}) && ($newValue != $AutoPathSync )} {
1364+ return -code error \
1365+ " cannot set new value while Safe Base child interpreters exist"
1366+ }
1367+ if {$newValue != $AutoPathSync } {
1368+ set AutoPathSync $newValue
1369+ ::tcl::OptKeyDelete ::safe::interpCreate
1370+ ::tcl::OptKeyDelete ::safe::interpIC
1371+ set TmpLog [setLogCmd]
1372+ Setup
1373+ setLogCmd $TmpLog
1374+ }
1375+ return $AutoPathSync
13871376 }
1388- if {($args != $AutoPathSync )} {
1389- set AutoPathSync {*}$args
1390- ::tcl::OptKeyDelete ::safe::interpCreate
1391- ::tcl::OptKeyDelete ::safe::interpIC
1392- set TmpLog [setLogCmd]
1393- Setup
1394- setLogCmd $TmpLog
1377+ default {
1378+ set msg {wrong # args: should be " safe::setSyncMode ?newValue?" }
1379+ return -code error $msg
13951380 }
1396- } else {
1397- set msg {wrong # args: should be " safe::setSyncMode ?newValue?" }
1398- return -code error $msg
13991381 }
1400-
1401- return $AutoPathSync
14021382}
14031383
14041384namespace eval ::safe {
0 commit comments