Version 0 of debug

Updated 2008-08-26 12:28:15 by CMcC
   # Debug - a debug narrative logger.
   #
   # Debugging areas of interest are represented by 'tokens' which have 
   # independantly settable levels of interest (an integer, higher is more detailed)
   #
   # Debug narrative is provided as a tcl script whose value is [subst]ed in the 
   # caller's scope if and only if the current level of interest matches or exceeds
   # the Debug call's level of detail.  This is useful, as one can place arbitrarily
   # complex narrative in code without unnecessarily evaluating it.
   #
   # TODO: potentially different streams for different areas of interest.
   # (currently only stderr is used.  there is some complexity in efficient
   # cross-threaded streams.)

   package provide Debug 2.0

   namespace eval Debug {
       variable detail
       variable level 0
       variable fds

       proc noop {args} {}

       proc debug {tag message {level 1}} {
           variable detail
           if {$detail($tag) >= $level} {
               variable fds
               set fd $fds($tag)

               set code [catch {
                   uplevel 1 ::subst -nobackslashes [list $message]
               } result eo]
               if {$code} {
                   set x [info level -1]
                   puts -nonewline $fd @@[string map {\n \\n \r \\r} "(DebugError from $tag [if {[string length $x] < 1000} {set x} else {set x "[string range $x 0 200]...[string range $x end-200 end]"}] ($eo)):"]
               } else {
                   if {[string length $result] > 4096} {
                       set result "[string range $result 0 4096]...(truncated) ... [string range $result end-4096 end]"
                   }
                   puts $fd "$tag @@[string map {\n \\n} $result]"
               }
           } else {
               #puts stderr "$tag @@@ $detail($tag) >= $level"
           }
       }

       # names - return names of debug tags
       proc names {} {
           variable detail
           return [lsort [array names detail]]
       }

       proc 2array {} {
           variable detail
           set result {}
           foreach n [lsort [array names detail]] {
               if {[interp alias {} Debug.$n] ne "::Debug::noop"} {
                   lappend result $n $detail($n)
               } else {
                   lappend result $n -$detail($n)
               }
           }
           return $result
       }

       # level - set level and fd for tag
       proc level {tag {level ""} {fd stderr}} {
           variable detail
           if {$level ne ""} {
               set detail($tag) $level
           }

           if {![info exists detail($tag)]} {
               set detail($tag) 1
           }

           variable fds
           set fds($tag) $fd

           return $detail($tag)
       }

       # turn on debugging for tag
       proc on {tag {level ""} {fd stderr}} {
           level $tag $level $fd
           interp alias {} Debug.$tag {} ::Debug::debug $tag
       }

       # turn off debugging for tag
       proc off {tag {level ""} {fd stderr}} {
           level $tag $level $fd
           interp alias {} Debug.$tag {} ::Debug::noop
       }

       namespace export -clear *
       namespace ensemble create -subcommands {}
   }

enter categories here