2012-07-25 78 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 
    } 
}