|
|
1.1 ! root 1: ! 2: #@package: TclX-ArrayProcedures for_array_keys ! 3: ! 4: proc for_array_keys {varName arrayName codeFragment} { ! 5: upvar $varName enumVar $arrayName enumArray ! 6: ! 7: if ![info exists enumArray] { ! 8: error "\"$arrayName\" isn't an array" ! 9: } ! 10: ! 11: set searchId [array startsearch enumArray] ! 12: while {[array anymore enumArray $searchId]} { ! 13: set enumVar [array nextelement enumArray $searchId] ! 14: uplevel $codeFragment ! 15: } ! 16: array donesearch enumArray $searchId ! 17: } ! 18: ! 19: #@package: TclX-assign_fields assign_fields ! 20: ! 21: proc assign_fields {list args} { ! 22: foreach varName $args { ! 23: set value [lvarpop list] ! 24: uplevel "set $varName [list $value]" ! 25: } ! 26: } ! 27: ! 28: #@package: TclX-developer_utils saveprocs edprocs ! 29: ! 30: proc saveprocs {fileName args} { ! 31: set fp [open $fileName w] ! 32: puts $fp "# tcl procs saved on [fmtclock [getclock]]\n" ! 33: puts $fp [eval "showprocs $args"] ! 34: close $fp ! 35: } ! 36: ! 37: proc edprocs {args} { ! 38: global env ! 39: ! 40: set tmpFilename /tmp/tcldev.[id process] ! 41: ! 42: set fp [open $tmpFilename w] ! 43: puts $fp "\n# TEMP EDIT BUFFER -- YOUR CHANGES ARE FOR THIS SESSION ONLY\n" ! 44: puts $fp [eval "showprocs $args"] ! 45: close $fp ! 46: ! 47: if [info exists env(EDITOR)] { ! 48: set editor $env(EDITOR) ! 49: } else { ! 50: set editor vi ! 51: } ! 52: ! 53: set startMtime [file mtime $tmpFilename] ! 54: system "$editor $tmpFilename" ! 55: ! 56: if {[file mtime $tmpFilename] != $startMtime} { ! 57: source $tmpFilename ! 58: echo "Procedures were reloaded." ! 59: } else { ! 60: echo "No changes were made." ! 61: } ! 62: unlink $tmpFilename ! 63: return ! 64: } ! 65: ! 66: #@package: TclX-forfile for_file ! 67: ! 68: proc for_file {var filename code} { ! 69: upvar $var line ! 70: set fp [open $filename r] ! 71: while {[gets $fp line] >= 0} { ! 72: uplevel $code ! 73: } ! 74: close $fp ! 75: } ! 76: ! 77: ! 78: #@package: TclX-forrecur for_recursive_glob ! 79: ! 80: proc for_recursive_glob {var globlist code {depth 1}} { ! 81: upvar $depth $var myVar ! 82: foreach globpat $globlist { ! 83: foreach file [glob -nocomplain $globpat] { ! 84: if [file isdirectory $file] { ! 85: for_recursive_glob $var $file/* $code [expr {$depth + 1}] ! 86: } ! 87: set myVar $file ! 88: uplevel $depth $code ! 89: } ! 90: } ! 91: } ! 92: ! 93: #@package: TclX-globrecur recursive_glob ! 94: ! 95: proc recursive_glob {globlist} { ! 96: set result "" ! 97: foreach pattern $globlist { ! 98: foreach file [glob -nocomplain $pattern] { ! 99: lappend result $file ! 100: if [file isdirectory $file] { ! 101: set result [concat $result [recursive_glob $file/*]] ! 102: } ! 103: } ! 104: } ! 105: return $result ! 106: } ! 107: ! 108: #@package: TclX-help help helpcd helppwd apropos ! 109: ! 110: ! 111: proc help:flattenPath {pathName} { ! 112: set newPath {} ! 113: foreach element [split $pathName /] { ! 114: if {"$element" == "."} { ! 115: continue ! 116: } ! 117: if {"$element" == ".."} { ! 118: if {[llength [join $newPath /]] == 0} { ! 119: error "Help: name goes above subject directory root"} ! 120: lvarpop newPath [expr [llength $newPath]-1] ! 121: continue ! 122: } ! 123: lappend newPath $element ! 124: } ! 125: set newPath [join $newPath /] ! 126: ! 127: ! 128: if {("$newPath" == "") && [string match "/*" $pathName]} { ! 129: set newPath "/"} ! 130: ! 131: return $newPath ! 132: } ! 133: ! 134: ! 135: proc help:EvalPath {pathName} { ! 136: global TCLENV ! 137: ! 138: if {![string match "/*" $pathName]} { ! 139: if {"$pathName" == ""} { ! 140: return $TCLENV(help:curDir)} ! 141: if {"$TCLENV(help:curDir)" == "/"} { ! 142: set pathName "/$pathName" ! 143: } else { ! 144: set pathName "$TCLENV(help:curDir)/$pathName" ! 145: } ! 146: } ! 147: set pathName [help:flattenPath $pathName] ! 148: if {[string match "*/" $pathName] && ($pathName != "/")} { ! 149: set pathName [csubstr $pathName 0 [expr [length $pathName]-1]]} ! 150: ! 151: return $pathName ! 152: } ! 153: ! 154: ! 155: proc help:Display {line} { ! 156: global TCLENV ! 157: if {$TCLENV(help:lineCnt) >= 23} { ! 158: set TCLENV(help:lineCnt) 0 ! 159: puts stdout ":" nonewline ! 160: flush stdout ! 161: gets stdin response ! 162: if {![lempty $response]} { ! 163: return 0} ! 164: } ! 165: puts stdout $line ! 166: incr TCLENV(help:lineCnt) ! 167: } ! 168: ! 169: ! 170: proc help:DisplayFile {filepath} { ! 171: ! 172: set inFH [open $filepath r] ! 173: while {[gets $inFH fileBuf] >= 0} { ! 174: if {![help:Display $fileBuf]} { ! 175: break} ! 176: } ! 177: close $inFH ! 178: ! 179: } ! 180: ! 181: ! 182: proc help:ListDir {dirPath} { ! 183: set dirList {} ! 184: set fileList {} ! 185: if {[catch {set dirFiles [glob $dirPath/*]}] != 0} { ! 186: error "No files in subject directory: $dirPath"} ! 187: foreach fileName $dirFiles { ! 188: if [file isdirectory $fileName] { ! 189: lappend dirList "[file tail $fileName]/" ! 190: } else { ! 191: lappend fileList [file tail $fileName] ! 192: } ! 193: } ! 194: return [list [lsort $dirList] [lsort $fileList]] ! 195: } ! 196: ! 197: ! 198: proc help:DisplayColumns {nameList} { ! 199: set count 0 ! 200: set outLine "" ! 201: foreach name $nameList { ! 202: if {$count == 0} { ! 203: append outLine " "} ! 204: append outLine $name ! 205: if {[incr count] < 4} { ! 206: set padLen [expr 17-[clength $name]] ! 207: if {$padLen < 3} { ! 208: set padLen 3} ! 209: append outLine [replicate " " $padLen] ! 210: } else { ! 211: if {![help:Display $outLine]} { ! 212: return} ! 213: set outLine "" ! 214: set count 0 ! 215: } ! 216: } ! 217: if {$count != 0} { ! 218: help:Display $outLine} ! 219: return ! 220: } ! 221: ! 222: ! 223: ! 224: proc help {{subject {}}} { ! 225: global TCLENV ! 226: ! 227: set TCLENV(help:lineCnt) 0 ! 228: ! 229: ! 230: if {($subject == "help") || ($subject == "?")} { ! 231: help:DisplayFile "$TCLENV(help:root)/help" ! 232: return ! 233: } ! 234: ! 235: set request [help:EvalPath $subject] ! 236: set requestPath "$TCLENV(help:root)$request" ! 237: ! 238: if {![file exists $requestPath]} { ! 239: error "Help:\"$request\" does not exist"} ! 240: ! 241: if [file isdirectory $requestPath] { ! 242: set dirList [help:ListDir $requestPath] ! 243: set subList [lindex $dirList 0] ! 244: set fileList [lindex $dirList 1] ! 245: if {[llength $subList] != 0} { ! 246: help:Display "\nSubjects available in $request:" ! 247: help:DisplayColumns $subList ! 248: } ! 249: if {[llength $fileList] != 0} { ! 250: help:Display "\nHelp files available in $request:" ! 251: help:DisplayColumns $fileList ! 252: } ! 253: } else { ! 254: help:DisplayFile $requestPath ! 255: } ! 256: return ! 257: } ! 258: ! 259: ! 260: ! 261: proc helpcd {{dir /}} { ! 262: global TCLENV ! 263: ! 264: set request [help:EvalPath $dir] ! 265: set requestPath "$TCLENV(help:root)$request" ! 266: ! 267: if {![file exists $requestPath]} { ! 268: error "Helpcd: \"$request\" does not exist"} ! 269: ! 270: if {![file isdirectory $requestPath]} { ! 271: error "Helpcd: \"$request\" is not a directory"} ! 272: ! 273: set TCLENV(help:curDir) $request ! 274: return ! 275: } ! 276: ! 277: ! 278: proc helppwd {} { ! 279: global TCLENV ! 280: echo "Current help subject directory: $TCLENV(help:curDir)" ! 281: } ! 282: ! 283: ! 284: proc apropos {name} { ! 285: global TCLENV ! 286: ! 287: set TCLENV(help:lineCnt) 0 ! 288: ! 289: set aproposCT [scancontext create] ! 290: scanmatch -nocase $aproposCT $name { ! 291: set path [lindex $matchInfo(line) 0] ! 292: set desc [lrange $matchInfo(line) 1 end] ! 293: if {![help:Display [format "%s - %s" $path $desc]]} { ! 294: return} ! 295: } ! 296: foreach brief [glob -nocomplain $TCLENV(help:root)/*.brf] { ! 297: set briefFH [open $brief] ! 298: scanfile $aproposCT $briefFH ! 299: close $briefFH ! 300: } ! 301: scancontext delete $aproposCT ! 302: } ! 303: ! 304: global TCLENV TCLPATH ! 305: ! 306: set TCLENV(help:root) [searchpath $TCLPATH help] ! 307: set TCLENV(help:curDir) "/" ! 308: set TCLENV(help:outBuf) {} ! 309: ! 310: #@package: TclX-packages packages autoprocs ! 311: ! 312: proc packages {{option {}}} { ! 313: global TCLENV ! 314: set packList {} ! 315: foreach key [array names TCLENV] { ! 316: if {[string match "PKG:*" $key]} { ! 317: lappend packList [string range $key 4 end] ! 318: } ! 319: } ! 320: if [lempty $option] { ! 321: return $packList ! 322: } else { ! 323: if {$option != "-location"} { ! 324: error "Unknow option \"$option\", expected \"-location\"" ! 325: } ! 326: set locList {} ! 327: foreach pack $packList { ! 328: set fileId [lindex $TCLENV(PKG:$pack) 0] ! 329: ! 330: lappend locList [list $pack [concat $TCLENV($fileId) \ ! 331: [lrange $TCLENV(PKG:$pack) 1 2]]] ! 332: } ! 333: return $locList ! 334: } ! 335: } ! 336: ! 337: proc autoprocs {} { ! 338: global TCLENV ! 339: set procList {} ! 340: foreach key [array names TCLENV] { ! 341: if {[string match "PROC:*" $key]} { ! 342: lappend procList [string range $key 5 end] ! 343: } ! 344: } ! 345: return $procList ! 346: } ! 347: ! 348: #@package: TclX-directory_stack pushd popd dirs ! 349: ! 350: global TCLENV(dirPushList) ! 351: ! 352: set TCLENV(dirPushList) "" ! 353: ! 354: proc pushd {args} { ! 355: global TCLENV ! 356: ! 357: if {[llength $args] > 1} { ! 358: error "bad # args: pushd [dir_to_cd_to]" ! 359: } ! 360: set TCLENV(dirPushList) [linsert $TCLENV(dirPushList) 0 [pwd]] ! 361: ! 362: if {[llength $args] != 0} { ! 363: cd [glob $args] ! 364: } ! 365: } ! 366: ! 367: proc popd {} { ! 368: global TCLENV ! 369: ! 370: if [llength $TCLENV(dirPushList)] { ! 371: cd [lvarpop TCLENV(dirPushList)] ! 372: pwd ! 373: } else { ! 374: error "directory stack empty" ! 375: } ! 376: } ! 377: ! 378: proc dirs {} { ! 379: global TCLENV ! 380: echo [pwd] $TCLENV(dirPushList) ! 381: } ! 382: ! 383: #@package: TclX-set_functions union intersect intersect3 lrmdups ! 384: ! 385: proc union {lista listb} { ! 386: set full_list [lsort [concat $lista $listb]] ! 387: set check_element [lindex $full_list 0] ! 388: set outlist $check_element ! 389: foreach element [lrange $full_list 1 end] { ! 390: if {$check_element == $element} continue ! 391: lappend outlist $element ! 392: set check_element $element ! 393: } ! 394: return $outlist ! 395: } ! 396: ! 397: proc lrmdups {list} { ! 398: set list [lsort $list] ! 399: set result [lvarpop list] ! 400: lappend last $result ! 401: foreach element $list { ! 402: if {$last != $element} { ! 403: lappend result $element ! 404: set last $element ! 405: } ! 406: } ! 407: return $result ! 408: } ! 409: ! 410: ! 411: proc intersect3 {list1 list2} { ! 412: set list1Result "" ! 413: set list2Result "" ! 414: set intersectList "" ! 415: ! 416: set list1 [lrmdups $list1] ! 417: set list2 [lrmdups $list2] ! 418: ! 419: while {1} { ! 420: if [lempty $list1] { ! 421: if ![lempty $list2] { ! 422: set list2Result [concat $list2Result $list2] ! 423: } ! 424: break ! 425: } ! 426: if [lempty $list2] { ! 427: set list1Result [concat $list1Result $list1] ! 428: break ! 429: } ! 430: set compareResult [string compare [lindex $list1 0] [lindex $list2 0]] ! 431: ! 432: if {$compareResult < 0} { ! 433: lappend list1Result [lvarpop list1] ! 434: continue ! 435: } ! 436: if {$compareResult > 0} { ! 437: lappend list2Result [lvarpop list2] ! 438: continue ! 439: } ! 440: lappend intersectList [lvarpop list1] ! 441: lvarpop list2 ! 442: } ! 443: return [list $list1Result $intersectList $list2Result] ! 444: } ! 445: ! 446: proc intersect {list1 list2} { ! 447: set intersectList "" ! 448: ! 449: set list1 [lsort $list1] ! 450: set list2 [lsort $list2] ! 451: ! 452: while {1} { ! 453: if {[lempty $list1] || [lempty $list2]} break ! 454: ! 455: set compareResult [string compare [lindex $list1 0] [lindex $list2 0]] ! 456: ! 457: if {$compareResult < 0} { ! 458: lvarpop list1 ! 459: continue ! 460: } ! 461: ! 462: if {$compareResult > 0} { ! 463: lvarpop list2 ! 464: continue ! 465: } ! 466: ! 467: lappend intersectList [lvarpop list1] ! 468: lvarpop list2 ! 469: } ! 470: return $intersectList ! 471: } ! 472: ! 473: ! 474: ! 475: #@package: TclX-show_procedures showproc showprocs ! 476: ! 477: proc showproc {procname} { ! 478: if [lempty [info procs $procname]] {demand_load $procname} ! 479: set arglist [info args $procname] ! 480: set nargs {} ! 481: while {[llength $arglist] > 0} { ! 482: set varg [lvarpop arglist 0] ! 483: if [info default $procname $varg defarg] { ! 484: lappend nargs [list $varg $defarg] ! 485: } else { ! 486: lappend nargs $varg ! 487: } ! 488: } ! 489: format "proc %s \{%s\} \{%s\}\n" $procname $nargs [info body $procname] ! 490: } ! 491: ! 492: proc showprocs {args} { ! 493: if [lempty $args] { set args [info procs] } ! 494: set out "" ! 495: ! 496: foreach i $args { ! 497: foreach j $i { append out [showproc $j] "\n"} ! 498: } ! 499: return $out ! 500: } ! 501: ! 502: ! 503: #@package: TclX-stringfile_functions read_file write_file ! 504: ! 505: proc read_file {fileName {numBytes {}}} { ! 506: set fp [open $fileName] ! 507: if {$numBytes != ""} { ! 508: set result [read $fp $numBytes] ! 509: } else { ! 510: set result [read $fp] ! 511: } ! 512: close $fp ! 513: return $result ! 514: } ! 515: ! 516: proc write_file {fileName args} { ! 517: set fp [open $fileName w] ! 518: foreach string $args { ! 519: puts $fp $string ! 520: } ! 521: close $fp ! 522: } ! 523: ! 524: ! 525: #@package: TclX-Compatibility execvp ! 526: ! 527: proc execvp {progname args} { ! 528: execl $progname $args ! 529: } ! 530: ! 531: #@package: TclX-convertlib convert_lib ! 532: ! 533: proc convert_lib {tclIndex packageLib {ignore {}}} { ! 534: if {[file tail $tclIndex] != "tclIndex"} { ! 535: error "Tail file name numt be `tclIndex': $tclIndex"} ! 536: set srcDir [file dirname $tclIndex] ! 537: ! 538: if {[file extension $packageLib] != ".tlib"} { ! 539: append packageLib ".tlib"} ! 540: ! 541: ! 542: set tclIndexFH [open $tclIndex r] ! 543: while {[gets $tclIndexFH line] >= 0} { ! 544: if {([cindex $line 0] == "#") || ([llength $line] != 2)} { ! 545: continue} ! 546: if {[lsearch $ignore [lindex $line 1]] >= 0} { ! 547: continue} ! 548: lappend entryTable([lindex $line 1]) [lindex $line 0] ! 549: } ! 550: close $tclIndexFH ! 551: ! 552: set libFH [open $packageLib w] ! 553: foreach srcFile [array names entryTable] { ! 554: set srcFH [open $srcDir/$srcFile r] ! 555: puts $libFH "#@package: $srcFile $entryTable($srcFile)\n" ! 556: copyfile $srcFH $libFH ! 557: close $srcFH ! 558: } ! 559: close $libFH ! 560: buildpackageindex $packageLib ! 561: } ! 562: ! 563: #@package: TclX-profrep profrep ! 564: ! 565: proc profrep:summarize {profDataVar stackDepth sumProfDataVar} { ! 566: upvar $profDataVar profData $sumProfDataVar sumProfData ! 567: ! 568: if {(![info exists profData]) || ([catch {array size profData}] != 0)} { ! 569: error "`profDataVar' must be the name of an array returned by the `profile off' command" ! 570: } ! 571: set maxNameLen 0 ! 572: foreach procStack [array names profData] { ! 573: if {[llength $procStack] < $stackDepth} { ! 574: set sigProcStack $procStack ! 575: } else { ! 576: set sigProcStack [lrange $procStack 0 [expr {$stackDepth - 1}]] ! 577: } ! 578: set maxNameLen [max $maxNameLen [clength $sigProcStack]] ! 579: if [info exists sumProfData($sigProcStack)] { ! 580: set cur $sumProfData($sigProcStack) ! 581: set add $profData($procStack) ! 582: set new [expr [lindex $cur 0]+[lindex $add 0]] ! 583: lappend new [expr [lindex $cur 1]+[lindex $add 1]] ! 584: lappend new [expr [lindex $cur 2]+[lindex $add 2]] ! 585: set $sumProfData($sigProcStack) $new ! 586: } else { ! 587: set sumProfData($sigProcStack) $profData($procStack) ! 588: } ! 589: } ! 590: return $maxNameLen ! 591: } ! 592: ! 593: proc profrep:sort {sumProfDataVar sortKey} { ! 594: upvar $sumProfDataVar sumProfData ! 595: ! 596: case $sortKey { ! 597: {calls} {set keyIndex 0} ! 598: {real} {set keyIndex 1} ! 599: {cpu} {set keyIndex 2} ! 600: default { ! 601: error "Expected a sort of: `calls', `cpu' or ` real'"} ! 602: } ! 603: ! 604: ! 605: foreach procStack [array names sumProfData] { ! 606: set key [format "%016d" [lindex $sumProfData($procStack) $keyIndex]] ! 607: lappend keyProcList [list $key $procStack] ! 608: } ! 609: set keyProcList [lsort $keyProcList] ! 610: ! 611: ! 612: for {set idx [expr [llength $keyProcList]-1]} {$idx >= 0} {incr idx -1} { ! 613: lappend sortedProcList [lindex [lindex $keyProcList $idx] 1] ! 614: } ! 615: return $sortedProcList ! 616: } ! 617: ! 618: ! 619: proc profrep:print {sumProfDataVar sortedProcList maxNameLen outFile ! 620: userTitle} { ! 621: upvar $sumProfDataVar sumProfData ! 622: ! 623: if {$outFile == ""} { ! 624: set outFH stdout ! 625: } else { ! 626: set outFH [open $outFile w] ! 627: } ! 628: ! 629: ! 630: set stackTitle "Procedure Call Stack" ! 631: set maxNameLen [max $maxNameLen [clength $stackTitle]] ! 632: set hdr [format "%-${maxNameLen}s %10s %10s %10s" $stackTitle \ ! 633: "Calls" "Real Time" "CPU Time"] ! 634: if {$userTitle != ""} { ! 635: puts $outFH [replicate - [clength $hdr]] ! 636: puts $outFH $userTitle ! 637: } ! 638: puts $outFH [replicate - [clength $hdr]] ! 639: puts $outFH $hdr ! 640: puts $outFH [replicate - [clength $hdr]] ! 641: ! 642: ! 643: foreach procStack $sortedProcList { ! 644: set data $sumProfData($procStack) ! 645: puts $outFH [format "%-${maxNameLen}s %10d %10d %10d" $procStack \ ! 646: [lindex $data 0] [lindex $data 1] [lindex $data 2]] ! 647: } ! 648: if {$outFile != ""} { ! 649: close $outFH ! 650: } ! 651: } ! 652: ! 653: ! 654: proc profrep {profDataVar sortKey stackDepth {outFile {}} {userTitle {}}} { ! 655: upvar $profDataVar profData ! 656: ! 657: set maxNameLen [profrep:summarize profData $stackDepth sumProfData] ! 658: set sortedProcList [profrep:sort sumProfData $sortKey] ! 659: profrep:print sumProfData $sortedProcList $maxNameLen $outFile $userTitle ! 660: ! 661: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.