Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Duplicate TCL-generated output to stdout to a logfile

519 views
Skip to first unread message

sam appleton

unread,
Dec 5, 2011, 2:42:28 PM12/5/11
to
Hi

I'm trying to introduce a logging function into an application that is
built on top of Tcl 8.5.8.
Our users have requested that *every* output that comes out of our
application, whether
we generate it or not (i.e. TCL-internally generated), gets logged to
a file as well as being
emitted to stdout & stderr.

I started looking at tclIO.c and DoWriteChars(), but I am asking "is
there a better way"
apart from extending TCL-internals?

Thanks to all of you for reading and I really appreciate your help

Very best

Sam Appleton
Ausdia Inc

Christian Gollwitzer

unread,
Dec 5, 2011, 3:26:19 PM12/5/11
to
On 05.12.2011 20:42, sam appleton wrote:
> I'm trying to introduce a logging function into an application that is
> built on top of Tcl 8.5.8.
> Our users have requested that *every* output that comes out of our
> application, whether
> we generate it or not (i.e. TCL-internally generated), gets logged to
> a file as well as being
> emitted to stdout& stderr.

Is it not enough to override puts? IOW when does Tcl generate output
other than you writing it, which you need to catch? IMHO it should be
sufficient to use something like

rename puts _orig_puts
proc puts {args} {
if {[llength $args]==1} {
_orig_puts $::protocolfd {*}$args
} else {
lassign $args fd msg
if {$fd=="stdout" || $fd=="stderr"} {
_orig_puts $::protocolfd $msg
}
}
_orig_puts {*}$args
}


(untested)

Christian

sam appleton

unread,
Dec 5, 2011, 3:31:57 PM12/5/11
to
Thanks for your response Christian. The request was that even this
kind of interactive sequence they enter into our "tclsh"-like
environment should be logged

(app) [1] > set $x
{ x y z }
(app) [2] > set x [list x2 y z]
{ x2 y z}

So they can see their entire running entry sequence and command
history in the logfile. I do not believe that overriding "puts" works
for this - we already
did that using a custom C command, and that only captures output
generated directly by calls to "puts".

Sam

Christian Gollwitzer

unread,
Dec 5, 2011, 3:54:08 PM12/5/11
to
On 05.12.2011 21:31, sam appleton wrote:
> Thanks for your response Christian. The request was that even this
> kind of interactive sequence they enter into our "tclsh"-like
> environment should be logged
>
> (app) [1]> set $x
> { x y z }
> (app) [2]> set x [list x2 y z]
> { x2 y z}
>
> So they can see their entire running entry sequence and command
> history in the logfile. I do not believe that overriding "puts" works
> for this

Well, somebody is responsible for this REPL. Your shell is strange
insofar that it quotes the output. Neither standard tclsh nor the
console used by windows wish do that. You must change your shell, then.
For such a kind of shell you could use tkcon - it's pure Tcl/Tk and it
should be trivial to modify it to log the output (in fact it does
memorize some output, which you can save to a file)

Christian

sam appleton

unread,
Dec 5, 2011, 4:24:19 PM12/5/11
to
I don't see this as non-standard. I just ran TCLSH and here's what I
got

[sam@bigdev04 disable]$ tclsh
% set x { x y z}
x y z
% set x
x y z
%

That mirrors exactly what our implementation does, with the exception
that
we set the "prompt" variables.

I'm asking if there is a way in the TCL core that I can add a logger
that
doesn't involve me changing the TCL core, or if there is some surgical
way
to do it. Switching shell implementations is not an option.

Christian Gollwitzer

unread,
Dec 5, 2011, 4:31:42 PM12/5/11
to
On 05.12.2011 22:24, sam appleton wrote:
>>> (app) [1]> set $x
>>> { x y z }
>>> (app) [2]> set x [list x2 y z]
>>> { x2 y z}

> I don't see this as non-standard. I just ran TCLSH and here's what I
> got
>
> [sam@bigdev04 disable]$ tclsh
> % set x { x y z}
> x y z
> % set x
> x y z
> %

The difference is the quoting; your example above outputs for
>list a b c
{ a b c }

which is nonstandard. Tclsh would output
a b c
without the braces.

> That mirrors exactly what our implementation does, with the exception
> that
> we set the "prompt" variables.
??
>
> I'm asking if there is a way in the TCL core that I can add a logger
> that
> doesn't involve me changing the TCL core, or if there is some surgical
> way
> to do it. Switching shell implementations is not an option.

It is your shell that writes the output! That's what I'm saying. At the
toplevel there must be the read-eval-print-loop, also called REPL.
Something like (simplified)
while {1} {
set line [gets]
puts [eval $line]
}

You need to access this "puts". It may not be Tcl, it may be C - it
depends on your non-standard shell, therefore nobody can tell you where
this "puts" is buried.

Christian

sam appleton

unread,
Dec 5, 2011, 6:56:59 PM12/5/11
to
My own quoting was incorrect. Our output is exactly the same as tclsh.
My shell is not writing the output. TCL is. Our output response to the
same command is exactly the same as TCLSH.

Andreas Leitgeb

unread,
Dec 6, 2011, 4:08:37 AM12/6/11
to
sam appleton <sam.s.a...@gmail.com> wrote:
> On Dec 5, 1:31 pm, Christian Gollwitzer <aurio...@gmx.de> wrote:
>> You need to access this "puts". It may not be Tcl, it may be C - it
>> depends on your non-standard shell, therefore nobody can tell you where
>> this "puts" is buried.
> My own quoting was incorrect. Our output is exactly the same as tclsh.
> My shell is not writing the output. TCL is. Our output response to the
> same command is exactly the same as TCLSH.

I may have missed a statement about platform.
If platform is anything unixoid, then there's probably available
a tool named "script" which can capture all the ouput (and echoed
input) as a wrapper to tclsh or your shell.

e.g. (for tclsh)
script -a -q -c tclsh logfile

This line can be wrapped into a sh-script, named as your shell was
previously (before renaming it to something with a -core postfix,
which is then passed to the "-c" option). There is some caveat with
passing arguments to the shell, though, which is non-trivial.
Maybe this approach is simpler than modifying the shell.

0 new messages