scanxxx without tclx

TclX has some useful line-by-line file-scanning commands: scancontext, scanmatch and scanfile. Here's an implementation of them in pure Tcl:

    namespace eval scancontext {
        namespace export *
    }
    proc scancontext::scancontext {cmd args} {
        switch -- $cmd {
            "create" {
                uplevel 1 {
                    set __scan 0
                    while {1} {
                        incr __scan
                        variable scancontext$__scan
                        if {![array exists scancontext$__scan]} {
                            break
                        }
                    }
                    set scancontext[set __scan]() 1
                    return scancontext$__scan
                }
            }
            "delete" {
                variable [lindex $args 0]
                unset [lindex $args 0]
            }
        }
    }

    proc scancontext::scanmatch {scanid regexp script args} {
        if {[string match "-*" $scanid]} {
            set flags $scanid
            set scanid $regexp
            set regexp [list $flags $script]
            set script [lindex $args 0]
        } else {
            set regexp [list -- $regexp]
        }
        variable $scanid
        set ${scanid}($regexp) $script
        return $scanid
    }

    proc scancontext::scanfile {scanid fid} {
        variable $scanid
        upvar matchInfo m
        set m(linenum) 0
        set m(offset) 0
        set m(handle) $fid
        set names [array names $scanid]
        while {[set count [gets $fid m(line)]] >= 0} {
            incr m(linenum)
            incr m(offset) [expr {$count +1}]
            foreach reg $names {
                if {$reg == ""} {continue}
                if {[regexp [lindex $reg 0] [lindex $reg 1] $m(line) \
                  "" m(submatch0) m(submatch1) m(submatch2)]} {
                    incr m(offset) [expr {-[string length $m(submatch0)]}]
                    uplevel 1 [set ${scanid}($reg)]
                    incr m(offset) [string length $m(submatch0)]
                }
            }
        }
    }
    namespace import scancontext::*

AlphaTcl uses the scanXXX commands to scan for uses of proc when building tclIndex files (unlike the standard auto_mkindex, which mostly sources files and sees which commands get defined), and has very similar emulation code for the commands should TclX not be available: http://alphatcl.cvs.sourceforge.net/alphatcl/Tcl/SystemCode/Init/rebuilding.tcl?view=log