Use of command pipeline with open command - tcl

I was trying to understand the usage of command pipeline with the open command in TCL.
I read the following paragraph from the documentation :
" If write-only access is used (e.g. access is w), then standard output for the pipeline is directed to the current standard output unless overridden by the command. If read-only access is used (e.g. access is r), standard input for the pipeline is taken from the current standard input unless overridden by the command. "
I was unable to understand what it means , so i tried some code which was :
set f1 [open "| touch testFile.txt" w+]
set a {USA UK AUS IND JAP}
foreach country $a {
puts $f1 "Member of democratic alliance : $country"
}
close $f1
But when i checked the contents of file, there was nothing present.
Can somebody please explain that paragraph from the TCL documentation (with some exaples) and also point where am I doing mistake in my own
Thanks

The touch program does not read its standard input or normally write to its standard output. It just updates the access time of the file, creating it (as a zero length file) if necessary. If you provide standard input to it, it'll just ignore it.
For the purposes of learning about working with pipelines, you might instead prefer to use the tee program.
Although you haven't got there yet, with a bidirectional pipe (such as those made when you open them with the w+ mode) you need to be careful because of the potential for deadlock when both sides fill up their OS-level write buffers in the pipe and aren't reading from them. It's usually wisest to switch bidirectional pipes to non-blocking in Tcl. It probably is also a good idea to set them as no stricter than line buffered, or maybe even unbuffered. Or to use flush at the right times, but that's harder to get right.
fconfigure $f1 -blocking false -buffering none
These are fundamental issues caused by needing to have several programs work together, not by pipes themselves or the programming languages used; it's just that bidirectional pipelines are the place where programmers usually first observe them. They very much also apply to working with TCP sockets.

Related

Using write access in Open command in TCL

How can i use write ('w') and read ('r') access while using command pipeline in open command in TCL.
when i do something like :
set f1 [open "| ls -l" w]
it returns a file descriptor to write to , say file1.
Now I am confused how can I put this file descriptor to my use.
PS : My example might be wrong, and in that case it'd be ideal if answer includes a programming example so that it'll be more clear.
Thanks
In general, the key things you can do with a channel are write to it (using puts), read from it (using gets and read), and close it. Obviously, you can only write to it if it is writable, and only read from it if it is readable.
When you write to a channel that is implemented as a pipeline, you send data to the program on the other end of the pipe; that's usually consuming it as its standard input. Not all programs do that; ls is one of the ones that completely ignores its standard input.
But the other thing you can do, as I said above, is close the channel. When you close a pipeline, Tcl waits for all the subprocesses to terminate (if they haven't already) and collects their standard error output, which becomes an error message from close if there is anything. (The errors are just like those you can get from calling exec; the underlying machinery is shared.)
There's no real point in running ls in a pure writable pipeline, at least not unless you redirect its output. Its whole purpose is to produce output (the sorted list of files, together with extra details with the -l option). If you want to get the output, you'll need a readable channel (readable from the perspective of Tcl): open "| ls -l" r. Then you'll be able to use gets $f1 to read a line from the subprocess.
But since ls is entirely non-interactive and almost always has a very quick running time (unless your directories are huge or you pass the options to enable recursion), you might as well just use exec. This does not apply to other programs. Not necessarily anyway; you need to understand what's going on.
If you want to experiment with pipelines, try using sort -u as the subprocess. That takes input and produces output, and exhibits all sorts of annoying behaviour along the way! Understanding how to work with it will teach you a lot about how program automation can be tricky despite it really being very simple.

How to get immediate output in my IDE from a Tcl script?

I have just started to use the tcl language and I need to create a script with several functions triggered every 2 seconds. I have been searching an answer on the internet and found several topics about it. For instance, I found this code on StackOverlow (How do I use "after ms script" in TCL?):
#!/usr/bin/tclsh
proc async {countdown} {
puts $countdown
incr countdown -1
if {$countdown > 0} {
after 1000 "async $countdown"
} else {
after 1000 {puts Blastoff!; exit}
}
}
async 5
# Don't exit the program and let async requests
# finish.
vwait forever
This code could very easily be adapted to what I want to do but it doesn't work on my computer. When I copy paste it on my IDE, the code waits several second before giving all the outputs in one go.
I had the same problem with the other code I found on the internet.
It would be great if someone could help me.
Thanks a lot in advance.
I've just pasted the exact script that you gave into a tclsh (specifically 8.6) running in a terminal on macOS, and it works. I would anticipate that your script will work on any version from about Tcl 7.6 onwards, which is going back nearly 25 years.
It sounds instead like your IDE is somehow causing the output to be buffered. Within your Tcl script, you can probably fix that by either putting flush stdout after each puts call, or by the (much easier) option of putting this at the start of your script:
fconfigure stdout -buffering line
# Or do this if you're using partial line writes:
# fconfigure stdout -buffering none
The issue is that Tcl (in common with many other programs) detects whether its standard output is going to a terminal or some other destination (file or pipe or socket or …). When output is to a terminal, it sets the buffering mode to line and otherwise it is set to full. (By contrast, stderr always has none buffering by default so that whatever errors that occur make it out before a crash; there's nothing worse than losing debugging info by default.) When lots of output is being sent, it doesn't matter — the buffer is only a few kB long and this is a very good performance booster — but it's not what you want when only writing a very small amount at time. It sounds like the IDE is doing something (probably using a pipe) that's causing the guess to be wrong.
(The tcl_interactive global variable is formally unrelated; that's set when there's no script argument. The buffering rule applies even when you give a script as an argument.)
The truly correct way for the IDE to fix this, at least on POSIX systems, is for it to use virtual terminal to run scripts instead of a pipeline. But that's a much more complex topic!

Exec-ing a program within tcl with redirection

Within a tcl program I am trying to exec a program which takes input using <
puts [exec "./program < inputfile"]
However, this produces the error
couldn't execute "./program < inputfile": no such file or directory
Is there a way of doing this in tcl?
Tcl can process redirections itself, so you would write:
puts [exec ./program <inputfile]
Otherwise, it tries to interpret the whole thing as a single (somewhat strange) filename; legal (on Unix, not on Windows) but not what you wanted.
Alternatively, you can fire the whole thing off through the system shell:
puts [exec /bin/sh -c "./program < inputfile"]
That works, but has many caveats. In particular, quoting things for the shell is a non-trivial problem, and you're not portable to Windows (where the incantation for running things through the command-line processor is a bit different). You also have an extra process used, but that's not really a big problem in practice unless you're really stretching the limits of system resources.
The plus side is that you can use full shell syntax in there, which can do a few things that are downright awkward otherwise. It's also more widely known, so something I'd surface to users with a medium level of expertise. (New users should stick to canned stuff; real experts can write some Tcl scripts.)
I found out the answer, the command has to be written as
puts [exec "./program" < inputfile]

what is exactly an EOF?

is EOF a special byte sequence that lies in the end of every file, or is it kinda exception(interrupt) that is notified by the kernel?
Long ago on DOS machines it used to be indicated by ^Z, but nowadays it's the kernel reaching the end of the file and notifying the program when it tries to read further.
I've used the ASCII EOF character to separate data files into a human-readable header followed by binary data. This allowed everything the mechanical engineers needed from a test to be kept in one file, while keeping it small enough to fit a floppy. (This was years ago!) The EOF character told most text display programs to stop. Anyone wanting a quick peek at the file header could just use a "print" command (is that what it was?) in a command shell.
Mostly these days, the EOF character isn't used in files, at least in the small part of the world I inhabit. Practically none of the ASCII control characters have any use any more, beside NUL, ESC and CR/LF.
EOF may serve some purpose in some streaming protocols, but that's outside my expertise so I leave it to others to address that.
EOF is a special code returned by the C stdio library to denote that there's no more data to be read from a FILE. Different operating systems have their own way of recording the size/end of a file and their own way of returning that to a user program, which will be translated into an EOF return code by the C standard library implementation on that operating system.

Hidden Features of TCL/TK [closed]

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
I've been working with TCL/TK ,recently started to use TCL/TK with my automation applications and I'm hungry for knowledge.
To continue with the long line of Hidden Feature questions, I would like to know any hidden or handy features of TCL/TK or any easy method to achieve some big operations
My favorite "hidden or handy feature" is how quoting works in Tcl. I like to use the phrase "quoting is a tool, not a rule". I also like to say "you only need curly braces when you need curly braces"
While most languages have rules for which block delimiters must be used for certain things (for example, in C you must use {} to designate a block), Tcl is not so stringent.
With Tcl, you can choose whatever quoting characters give you the effect you need. There are certainly best practices, but in the end you get to pick the quoting character that best lets you get the job done.
That means, for example, you can define a procedure in many ways, including:
proc foo {args} {
.... body here ....
}
proc foo "args" "
.... body here ....
"
proc foo args [some code that returns the body]
... and so on. Same goes for conditional statements, loops and everything else. (for the uninitiated, curly braces are roughly equivalent to the shell single quote, double quotes are like the shell double quote, and square brackets are like the shell backtick. ).
Now, many people look at that and say WTF? but it really gives a lot of power to the programmer. We often get questions in comp.lang.tcl along the lines of "if I do 'this {and $that}', how do I get $that to be expanded?". The answer follows the old joke "patient: doctor, it hurts when I do this doctor: don't do that". That is, if you don't like the behavior you get with one set of delimiters, choose some other delimiter. Just because an if statement is normally constructed with curly braces doesn't mean it must be constructed with curly braces.
That's my favorite "hidden" feature of Tcl. It's not hidden -- it's right on the wonderfully complete yet concise Tcl(n) man page, but the ramifications aren't clear until you fully grok how Tcl works.
When a marketing guy at Sun declared that Tcl was "Enterprise Ready", the developers added the following feature:
$ tclsh
% clock format [clock seconds] -format %Q
Stardate 63473.2
Another non-obvious feature is that unrecognised commands fall through to a handler called "unknown" which you can redefine. Eg. to have unknown commands treated as expressions to evaluate:
$ tclsh
% 2+2
invalid command name "2+2"
% proc unknown args {uplevel 1 [linsert $args 0 expr]}
% 2+2
4
More examples can be found at the wiki page on Radical Language Modification
Tcl's [trace] command allows you to intercept reads and writes to any variable. This allows you to implement an observer on any variable, and to add automatic range checking of arbitrary complexity to any variable (as if you were accessing the variable via a setter/getter). You could also create auto-incrementing variables using this technique.
proc varlimit_re {re var key op} {
upvar $var v
if { [regexp -- $re $v] <= 0 } {
error "$var out of range"
}
}
trace add variable ::myvar {write} [list varlimit_re {^[A-H]\d{3}-[0-9a-f]+$}]`
If you try to set 'myvar' to anything that doesn't match the regular expression, you will get a runtime error.
A handy feature which is not hidden but tends not to be obvious to people coming from other languages is that you can define your own control structures (or even redefine the existing ones if you want to live dangerously). There are examples on the Tcl Wiki
All of Tcl's "keywords" are regular Tcl commands, including control structures like [for], [foreach], [while], etc. This means that you can extend the language by writing new control structures in pure Tcl code.
For example, the try/on/trap structure has been implemented in Tcl 8.6a using only Tcl code. Similarly tcllib contains control::do, a do/while control structure.
A lot of this is made possible through the [upvar] and [uplevel] commands, which allow you to access variables or execute code in a different stack frame.
Tcl is such a simple, open language there are very few hidden features. It's all exposed for the programmer to extend and adapt.
IMHO the greatest hidden feature of Tcl is its C API. Using this, it's really easy to wrap a core C program or subsystem and write a GUI or other functionality in Tcl. While this feature is not unique to Tcl, Tcl was designed to do this from the ground up and the C API is particularly easy to work with.
The second greatest hidden feature is the packer, the grand-daddy of all geometry managers. With this, a GUI can have sizeable windows with a surprisingly small amount of code. It's important to note that Tcl/Tk had geometry management at least 10 years before .net came out.
The third greatest feature of Tcl is the ability to exend the language, either through the C API or with commands defined in Tcl. Not quite LISP macros, but quite flexible nonetheless. Expect is a very good example of an application built around extending the basse Tcl language to make a domain-specific scripting language.
EDIT: well, bugger me, Xt really did have a geometry manager, although I agree with Nat in that it's somewhat more painful than pack ;-}
[array names] is one of the first questions newbies ask about how to iterate over an array
also, the fact that you can foreach {key1 key2} {$list1 $list2} {...} - even if the lists are of different size
you should not use comments between switch cases (this is not a cool feature but a problem most developers do not understand
the rename command can rename any function/proc
I think the time command is wonderful. It's not exactly hidden but that doesn't stop people from asking "which function is faster" once in a while in comp.lang.tcl.
Anytime you want to know "how long does this take?" or "which method is faster?" you just call it via the "time" command. No creating of objects, no math, no overhead, exceptionally simple. Other languages have a similar feature, though some are a bit less elegant.
The well documented C API also allowed easy integration in Perl. My experience with Tcl/Tk goes back to 1995, but in 2000 or so, I discovered Perl/Tk and never looked back.
And lately, the Tcl and Tkx Perl packages give us modern-looking GUI's. And the two aforementioned modules, while not trivial, involve relatively little code, considering what they allow one to do across language boundaries. And that can be directly attributable to the excellent API (and the power of Perl, obviously).