[GRASS-dev] Re: gis.m crashes on zoom to map existing in more than one mapset

Paul Kelly paul-grass at stjohnspoint.co.uk
Fri Jan 5 06:07:19 EST 2007


Hello Michael

On Thu, 4 Jan 2007, Michael Barton wrote:

[...]
>> Try this instead:
>>      if {![catch {open [concat "|g.region" "-ugp" $args "|&
>> $env(GISBASE)/etc/grocat"] r} input]} {
>>          while {[gets $input line] >= 0} {
>>              if { [regexp -nocase {^([a-z]+)=(.*)$} $line trash key value] }
>>              {
>> set parts($key) $value
>>              }
>>          }
>
> I can confirm that this works. What is grocat??

It's a little C program I wrote (with lots of hints from Glynn) that very 
simply copies its standard input to standard output. Tcl allows you to 
pipe both stdout and stderr to an external program (using the |& operator) 
but doesn't allow you to redirect stderr to stdout like you can do on the 
command-line. So we created this little program to combine stdout and 
stderr and write them to stdout.
It's source is in lib/gtcltk/grocat.c but it doesn't use any GRASS 
functions or libraries so is in effect standalone.

>> I am guessing that "catch" catches errors by seeing if anything is written
>> to stderr - if a warning is written to stderr will it incorrectly catch it
>> as an error?
>
> Yes, this is what seems to be happening. The program exits with the warning
> printed to the terminal.

Right. So catch isn't useful for GRASS commands then as in GRASS, a module 
writing to stderr is not equivalent to an error condition. Messages and 
warnings also go to stderr, and we need to use something like grocat to 
redirect these away from stderr and stop them making Tcl think there is an 
error.

>> I'm not sure, but merging stderr into stdout with the grocat
>> program will stop anything being written to stderr so will stop this. This
>> will work on Windows - in fact I wrote it specifically because the
>> previous way it was done (see my recent changes to
>> lib/gtcltk/gronsole.tcl) was Unix-specific - the grocat trick works on
>> Unix and Windows.
>
> OK. If you've tested this on Windows, then it should be OK. I'm just trying
> not to do anything that will jeopardize a native Windows build.

Yes, totally understand. It does look like a Unix command I know but it's 
contained within the GRASS source so will be available on any platform 
(it's very simple basic C, really only uses stdio.h).

>> Then within the while loop I've used an if to check the return value of
>> regexp - there are only two possible values - 1 if it matches the line and
>> 0 if it doesn't. So it won't match the Warning line, will return 0, and
>> thus stops you trying to assign non-existent values to key and value.
>
> OK. This works fine too. Thanks. After fixing stuff yesterday, I was
> thinking it might be simpler to switch to
>
> set key [string trim [lindex [split $line "="] 0]]
>
> I wonder if this could be made to test in a similar way?

I actually think using the regexp command is more powerful. Because the 
lindex construction above assumes that the output from the command is 
valid. But e.g. if there is a warning or an extra message, then not every 
line will be valid. The regexp is powerful because if the line doesn't 
match what you're expecting, then you're able to skip over it. I can't 
easily see a way to that with the set key... line above, although it might 
be possible I suppose with a lot of thinking.

> Thanks for your help.

No problem. Working around the inadequacies and limitations of Tcl would 
appear to be an interesting challenge but I'm sure there are more 
productive things we could be doing!

Paul




More information about the grass-dev mailing list