From: anders@lise11.lise.unit.no (Anders Christensen)
Subject: Re: Capturing System Command Output (was: SH Backquote)
Organization: /home/flipper/anders/.organization
Date: 20 Aug 92 06:50:53

In article <REXXLIST%92081920425567@UGA.CC.UGA.EDU> Dave Gomberg <GOMBERG@UCSFVM.BITNET> writes:

> Usage:   X = CAPTURE('system_command'[,[address][,'stemname.']])

It only handles output from commands; it don't handle input. And for
output, it only handles two special cases: 1) stack it in one
particular order; and 2) put it into a collection of compound
variables.  I think it needs more functionality, and to get more
functionality it need more parameters (or more functions). With more
parameters, it might become too difficult to use for new users.

The third parameter must be quoted, since it is the name of the
parameter that is interesting, not its value (if any). This will
somehow break with the syntax of clauses like PROCEDURE EXPOSE and
DROP, which takes unquoted stems. The difference is: they are clauses,
while CAPTURE() is a function ... but will that be obvious to new
users?

The same goes to some extent for the second parameter. Normally the
ADDRESS clause is called as  "ADDRESS COMMAND expr"  and the name of
the environment is not quoted, since Rexx does not expect an
expression there (unless it finds a special character.) In the
CAPTURE() function, the environment name would have to be quoted to
avoid any previous setting of the _variable_ COMMAND. Again, will this
subtle (?) difference be obvious to new users?

What about the the following syntax, which is a slightly reworked
version of what Ed Spire just posted. It also borrows inspiration from
some of the ideas that Otto Stolz posted. This is a all-in-one
solution, combining the current 'standard' way to do it with the need
for more control over the redirection of input and output. 

| ADDRESS [ envir [ exprc [ TO dest ] [ FROM src ] ] ]
|
|     <envir> is the name of the environment to which commands are
|             directed, and must be a symbol or literal string.
|
|     <exprc> is the command to be executed. One restriction applies,
|             "TO" and "FROM" are reserved words, and can not be 
|             used in unquoted form. 
|
|     <expre> an expression that evaluate to the name of an 
|             environment, as already in language level 4.00
|
|     <dest>  =  OUTPUT         output to standard output (default)
|                STEM name.     output to compound var with stem <name.>
|                VAR name       output to variable <name>
|                QUEUE          output is stacked FIFO
|                PUSH           output is stacked LIFO
|                NULL           output is discarded
|                STREAM id      output is connected to stream named <id>
|
|             All these should be self-explaining, except (maybe) the last, 
|             If it is used, the command is run in the background, and
|             and the output from the command can be read using the 
|             functions linein() and charin(), with stream identical to 
|             the <id> given to ADDRESS. <id> is an expr that describes
|             a particular stream, and can be used as first parameter
|             to linein(), lineout() etc.
|
|     <src> =    INPUT          input from standard input (default)
|                STEM name.     input from compound var with stem <name.>
|                VAR name       input from variable <name>
|                PULL           input is popped off the stack
|                NULL           input is empty
|                STREAM id      input is connected to stream named <id>
|
|             Here, STREAM is used the same way, but <id> is used as 
|             the name of the stream for writing input to the command 
|             running. And NULL is used to prohibit the command from 
|             reading input, any read will get End-Of-File.

It is rather large, but only two extra subkeywords to ADDRESS are what
is needed to hook it into standard Rexx. But most important, _all_
functionality needed for redirection is provided in _one_
construction: using the stack, streams or variables as the means for
communication.  I can't think of any example of redirection of
commands the during resent days that would not be handled with this
expanded ADDRESS clause.

Then there is the 'breakage' to consider. Old commands using 'to' and
'from' in commands. I can imagine a lot of old Rexx scripts having 
constructs like: 

    COPY from to 

to copy files or whatever. The actual order of the terms in the
syntax-specification can be rearranged to minimize breakage and
improve readability. If "TO" and "FROM" comes before <exprc>, then the
the streamid (if STREAM is chosen) can not be an expression, since it
would be difficult to differ between the streamid and <exprc>. _If_
breakage is a major problem, the order of the subkeywords and the
subkeywords themselves can be defined so that no breakage occurs.  I
am not completely pleased with the syntax, but at least the idea seems
OK, and the syntax above seems like a good start.

Then there are the ordinary commands, which are more or less just 
special cases of ADDRESS (not defined as so in TRL, but at least used
as such; omit the "ADDRESS <envir>", and you've got a command). If
the same changes are applies to commands (acknowledging "TO" and
"FROM" as subkeywords), Rexx would have full support for redirection
of output and input to commands.

However, it still does not handle the problem of error output. Any
error text that a command might write out should be possible to catch 
in some way. Maybe it could be fixed by adding a 'ERROR' subkeyword 
in addition to "TO" and "FROM"?

Comments, anyone?

-anders
Xref: sparky comp.lang.rexx:707 comp.os.os2.misc:27301