2012-07-25 80 views
1

我正在寻找一些Tcl代码,它会复制puts命令发送到某个日志文件的stdout。是的,可以改变所有呼叫以放入某个自定义功能。但我希望尽可能透明。 我有这样的试验代码,但它并没有真正的工作都顺利:示例代码使put日志输出

set pass_log_output "0" 

rename puts _puts 
proc puts { args } { 
    global pass_log_output 

    if {[info exists pass_log_output]} { 
     # There can be several cases: 
     # -nonewline parameter, stdout specified or not 
     set stdout_dest [ lsearch $args stdout ] 
     set nonewline [ lsearch $args -nonewline ] 
     if { $stdout_dest != -1 } { 
      log_low_level "" [lindex $args [expr $stdout_dest + 1]] "" 
     } elseif { $nonewline != -1 && [ llength $args ] > 1} { 
      log_low_level "" [lindex $args [expr $nonewline + 1]] "" 
     } else { 
      log_low_level "" [lindex $args 0] "" 
     } 
    } 

    if { [ catch { eval _puts $args } err ] } { 
     return -code error $err 
    } 
} 

log_low_level功能只是存储在文件传递的字符串。 到目前为止,我得到这个错误:

Tcl Interpreter Error: too many nested evaluations (infinite loop?) 

回答

3

是否log_low_level使用puts?那可能是你的无限循环。

如果是这样,请尝试更改为使用_puts

+0

就是这样,这就是问题所在。谢谢。 – user1476056 2012-07-25 18:13:00

1

由于puts有极少数的选择,可能会更容易考虑给定参数的个数数。此外,您应该将原始_puts的所有用途都包含在新的投放处理程序中 - 即使对于您的代码,这个新投标应该也是透明的。

我以为你只是想记录的东西你写到标准输出

rename puts _orig_puts 
proc puts {args} { 
    switch -exact [llength $args] { 
     3 { 
      # both -newline and a channelId are given 
      set do_log [expr {[lindex $args 1] eq "stdout"}] 
     } 
     2 { 
      # only log if not writing to stdout 
      set chan [lindex $args 0] 
      set do_log [expr {$chan eq "-nonewline" || $chan eq "stdout"}] 
     } 
     1 { 
      set do_log true 
     } 
     default { 
      error {wrong # args: should be "puts ?-nonewline? ?channelId? string"} 
     } 
    } 
    if {$do_log} { 
     set chan [open $::mylogfile a] 
     _orig_puts $chan [lindex $args end] 
     close $chan 
    } 
    _orig_puts {*}$args 
} 
2

感谢您的点。我只想发布最后的工作代码以供参考。它甚至可以正确地使用-www标志来处理存储行。

set pass_log_output "0" 
set last_call_nonewline 0 

rename puts _orig_puts 
proc puts { args } { 
    global pass_log_output 
    global g_log_file 
    global last_call_nonewline 

    if {[info exists pass_log_output]} { 
     # Check if the logging was initialized 
     if {![info exists g_log_file]} { 
      _orig_puts "Log file wasn't initialized!" 
      return 
     } 

     # There can be several cases: 
     # -nonewline parameter, stdout specified or not 
     set stdout_dest [ lsearch $args stdout ] 
     set nonewline [ lsearch $args -nonewline ] 
     if {[ llength $args ] > 3} { 
      return -code error "wrong # args: should be puts ?-nonewline? ?channelId? string" 
     } elseif { $stdout_dest != -1 } { 
      set message [lindex $args end] 
     } elseif { $nonewline != -1 && [ llength $args ] == 2} { 
      set message [lindex $args [expr $nonewline + 1]] 
     } elseif {[ llength $args ] == 1} { 
      set message [lindex $args 0] 
     } 

     # Store the message in the file, if needed. 
     # Take into account if the last call was with -nonewline 
     if {[info exists message]} { 
      if {$last_call_nonewline == 0} { 
       _orig_puts -nonewline $g_log_file [clock format [clock seconds] -format "%T - "] 
      } 
      if {$nonewline != -1} { 
       set last_call_nonewline 1 
       _orig_puts -nonewline $g_log_file "$message" 
      } else { 
       set last_call_nonewline 0 
       _orig_puts $g_log_file "$message" 
      } 
      flush $g_log_file 
     } 
    } 

    if { [ catch { eval _orig_puts $args } err ] } { 
     return -code error $err 
    } 
}