TIP: Click on subject to list as thread! ANSI
echo: os2rexx
to: Steve McCrystal
from: David Noon
date: 1999-09-26 20:23:00
subject: Classic REXX files?

In a message dated 09-22-99, Jack Stein said to Steve Mccrystal about
"Classic REXX files?"

Hi Steve,

JS>For example, to load my 4OS2 alias file a regular cmd file would have:

JS>ALIAS /r e:\4os2301\os2alias

JS>REXX has no clue what "ALIAS" is, so he passes ALIAS to CMD.EXE.  The 
JS>paramaters however are very confusing to REXX, since it 
JS>recognizes some of the symbols, such as "/", and "\".  
JS>Because of this, you must quote the parameters so REXX 
JS>doesn't try to divide something by r, for example, so the 
JS>line looks like this in a REXX script:

JS>ALIAS '/r e:\4os2301\os2alias'

A more idiomatic approach would be to code it as:

   "ALIAS /r e:\4os2301\os2alias"

or better still:

   ADDRESS 'CMD' "ALIAS /r e:\4os2301\os2alias"

JS>Also, to make a directory, the same thing applies:

JS>md "z:\xpress"

There is a perfectly good REXXUTIL function called SysMkDir that will do
this without requiring "shelling out" to run MD. The preferred way is:

     CALL SysMkDir "z:\xpress"

However, this is predicated on you having registered the REXXUTIL functions
before calling SysMkDir. And as Jack rightly says ...

JS> In short, it's OK not to start up the extended utilities 
JS>in your startup.cmd, but it's not OK to not know why you 
JS>got the errors.:-)

But to continue on theme of not "shelling out", you should avoid assumptions
whenever you are writing code. Invoking an external command through a shell
nearly always involves _assuming_ that your current subcommand handler is
CMD.EXE (or some moral equivalent). This assumption is not always valid!

[Sidebar: When the REXX interpreter encounters some "statement" it cannot
comprehend, that statement is treated as a subcommand and its text is passed
to the default subcommand handler. This is what is happening with Jack's
ALIAS statement, above.]

Some of us like to use REXX to customize terminal programs (e.g. ZOC), text
editors (e.g. EPM, LPEX) and other programs. In such a context, the program
being customized will often become the default subcommand handler. Thus,
should you code an OS/2 command in your REXX program it will be passed to
whatever program established itself as the subcommand handler, not directly
to CMD.EXE (or whatever you have in OS2_SHELL). The subcommand handler is
then responsible for passing it along to CMD.EXE. This often involves
creating a separate address space in which to run CMD.EXE.

You can pass your commands directly to CMD.EXE if you bypass the default and
use an explicit ADDRESS statement, as I did above with Jack's ALIAS command.
If CMD.EXE is not your shell then this will still create a separate address
space in which to run the command, but it will avoid having to go through
some intermediary.

Creating a separate address space is generally an undesirable arrangement.
Firstly, it is slow. Secondly, it alters the semantics of many commands.
There are situations where it is unavoidable, though. Specifically, any
command that is actually a external program must be run in a separate
address space anyway. However, it is the semantic differences that usually
bite the REXX programmer.

The classic example is using the CD (or CHDIR) command to change the current
working directory. A lot of newbie (and some experienced) REXX programmers
code:

    "CD \dir\subdir"

to change the directory and then find that, apparently, nothing happened.
What actually happened was that a new address space was created to run
CMD.EXE, the working directory for that new address space was changed, and
then the address space terminated, returning control to the REXX program.

Instead, the programmer should have coded:

     CALL DIRECTORY "\dir\subdir"

to use the built-in DIRECTORY function. This is always executed within the
current address space, so its results "stick".

Similarly, one should use the VALUE built-in function to query and set
environment variables. This function always runs within the current address
space and use that address space's environment block.

The general moral to my story is that one should use REXX functions calls
whenever and wherever they are available, as the results are predictable.
Shelling out to run external commands often produces very unexpected
results. The upshot is that one should always check to see if REXX or
REXXUTIL offers a built-in feature before shelling out to run a command.

Regards

Dave

___
 * MR/2 2.25 #353 * "Who is #1?"  "You are, #6."

--- Maximus/2 3.01
267/200
45
* Origin: Air Applewood, OS/2 Gateway to Essex 44-1279-792300 (2:257/609)

SOURCE: echoes via The OS/2 BBS

Email questions or comments to sysop@ipingthereforeiam.com
All parts of this website painstakingly hand-crafted in the U.S.A.!
IPTIA BBS/MUD/Terminal/Game Server List, © 2025 IPTIA Consulting™.