Search code examples
tclmodelsimghdlquestasimriviera-pro

Redirecting output of tcl proc to file and output (like tee) Part 2


I am using tee from https://wiki.tcl-lang.org/page/Tee to redirect file output from my procedures. I need to redirect both stdout and stderr to the file.

Using the input from Redirecting output of tcl proc to file and output (like tee) I arrived at doing the following:

    set LogFile  [open ${LogFileName} w]
    tee channel stderr $LogFile
    tee channel stdout $LogFile
    set BuildErrorCode [catch {LocalBuild $BuildName $Path_Or_File} BuildErrMsg]
    set BuildErrorInfo $::errorInfo
    
    # Restore stdout and stderr 
    chan pop stdout
    chan pop stderr

   # Handle errors from Build ...

I am testing this on three different EDA tools and I have three different issues.

  1. When I run from tclsh (on MSYS2 running on Windows 10) and run either the open source simulator GHDL, ModelSim, or QuestaSim, all the even characters are the NUL character.
  2. If I run ModelSim or QuestaSim from the GUI, I miss the output of each command. Shouldn't that be going to either stdout or stderr?
  3. In Riviera-PRO, I am getting extraneous characters that were previously printed. They are generally the second half of a word.

Am I doing something wrong? I tested out the above code using:

set LogFile  [open test_tee.log w]
tee channel stderr $LogFile
tee channel stdout $LogFile

puts "Hello, World!"
puts stderr "Error Channel"
puts stdout "Output Channel"

chan pop stdout
chan pop stderr

And this works well.

I am hoping to find something that works in the general case for all tools rather than having to write a different handler for each tool.

============ Update =============
For #1 above, with @Shawn's suggestion, I tried the following and it did not work.

    set LogFile  [open ${LogFileName} w]
    chan configure $LogFile -encoding ascii
    . . .

I also tried the following and it did not work.

    set LogFile  [open ${LogFileName} w]
    fconfigure $LogFile -encoding ascii
    . . .

Then I tried updating the write in tee to the following and it did not work:

proc tee::write {fd handle buffer} {
    puts -nonewline $fd [encoding convertto ascii $buffer]
    return $buffer
}

Any other hints solutions appreciated

============ Update2 =============
I have successfully removed the nul characters by doing the following, except now I have an extra newline. Still not a solution.

proc tee::write {fd handle buffer} {
    puts -nonewline $fd [regsub -all \x00 $buffer ""]
    return $buffer
}

Solution

  • The extra NUL bytes are probably because the stdout ahd steer channels are being written in UTF-16 (the main use for that encoding is the console on Windows). The tee interceptors you are using come after the data being written is encoded. There's a few ways to fix it, but the easiest is to open the file with the right encoding when reading it.

    The output of the commands is not necessarily written to those channels. Code written in C or C++ is entirely free to write directly, and Tcl code cannot see that; it's all happening behind our back. Command results can be intercepted using execution traces, but that cannot see anything that the commands internally print that aren't routed via the Tcl library somehow. (There are a few more options on Unix due to the different ways that the OS handles I/O.)

    Don't know what's happening with the extra characters. I can tell you that you are getting what goes through the channel, but there are too many tricks (especially in interactive use!) for a useful guess on that front.