REXX debugger - REXX
This is a discussion on REXX debugger - REXX ; Back in the day, there used to be an IBM Employee Written Software (EWS)
REXX debugger. It ran on OS/2, and was fairly limited--especially since
it was a 16-bit app compiled with the small memory model...but I digress.
I have ...
-
REXX debugger
Back in the day, there used to be an IBM Employee Written Software (EWS)
REXX debugger. It ran on OS/2, and was fairly limited--especially since
it was a 16-bit app compiled with the small memory model...but I digress.
I have a big-iron clusterized electromagnetic simulator that consists of
two C++ programs, the clusterized number cruncher and a single-threaded
postprocessor, and a fairly gigantic REXX script that understands a nice
human-friendly command language and runs all the rest, including
generating DXF files of the simulation geometry, doing optimization, and
so forth. It works very well--it's fast and powerful, and coding the
front end in REXX has meant that I can add features quickly and easily.
The front-end script has got up to about 11k lines at this point, which
is a bit big for a REXX program, and I'm now finding that adding
functions has a tendency to break things. (Classic REXX isn't the most
structured language in the world.) I've spent some time chasing stupid
stuff like inconsistent EXPOSE lists, when adding a feature means I need
access to a global stem down in some function that didn't previously
need it.
TRACE ?I isn't the friendliest thing in the world for this--I can only
check things that the interpreter is actually evaluating at the time,
which makes it more like printf() than like Visual Studio or even ddd.
So I need a REXX debugger. I found S/REXX on the Web, but it doesn't
look that compelling--it looks like a mildly-glorified TRACE ?.
Is there a better one?
Thanks,
Phil Hobbs
-
Re: REXX debugger
On Thu, 20 Sep 2007 15:14:14 -0400, Phil Hobbs
<pcdh@SpamMeSenseless.pergamos.net> wrote:
<46F2C686.2000309@SpamMeSenseless.pergamos.net>
>So I need a REXX debugger. I found S/REXX on the Web, but it doesn't
>look that compelling--it looks like a mildly-glorified TRACE ?.
>
>Is there a better one?
Some years back when I started writing fairly elaborate REXX routines (1988 or
so), I settled on a protocol in which I pass operational parms left of a
double-open-paren ("((") and diagnostic parms to the right.
The diagnostics are all parsed out in a subroutine which is called VERY early in
the process (i.e.: FIRST). One of the parms it recognizes is "TRAPOUT". When
the parsing routine finds token "TRAPOUT" it does this:
if SWITCH("TRAPOUT") then do
"TRAPOUT" exec_name parms "(( TRACE R" info
exit
end
That is, it fires up an external routine called TRAPOUT:
--------------------------------------------------------------------------
/* Rexx */ /* This is REXX EXEC "TRAPOUT" to trap line output */
address TSO
rc = trace("O")
"EXECUTIL TE"
Parse arg TSOCMD /* A TSO Command will be the input parm */
rc = Outtrap("OUT.") /* Turn on outtrap, to rexx stem OUT. */
(TSOCMD) "(( TRACE R" /* Do the command */
rc = Outtrap("OFF")
If OUT.0 > 0 Then Do /* If any output, write to the file */
dsdate = Right(date("S"),6) /* 950118 maybe */
dstime = time()
parse var dstime th ":" tm ":" ts .
dstime = Right(th,2,0)Right(tm,2,0)Right(ts,2,0)
dsn = "@@TRAP.D"dsdate".T"dstime".LIST"
X = Msg("OFF");"DEL" dsn ;X= Msg("ON")
"ALLOC FI(TRAPOUT) DA("dsn") NEW CATALOG REU SP(5,5) CYL ",
"RECFM(V B) LRECL(255) BLKSIZE(0)"
"EXECIO" out.0 "DISKW TRAPOUT (STEM OUT. FINIS"
"FREE FI(TRAPOUT)"
end
--------------------------------------------------------------------------
TRAPOUT sets up a SYSOUTTRAP and re-invokes the original routine with all
parameters except "TRAPOUT" but with "TRACE R". When the routine completes, the
contents of the trap are spilled onto a real dataset.
Notice that the dataset is allocated "SPACE(5,5) CYL". There have been more
instances than I'm comfortable acknowledging where this was barely enough. This
solves a problem where the program fails at output-line 112,387 because of an
error at output-line 2,559. There is no other way you would ever find that.
(I just this instant noticed an error here: the code to invoke TRAPOUT specifies
"TRACE R" and TRAPOUT itself does it again. One of these is redundant (the
specification in TRAPOUT).)
You can see several examples of code which implements this protocol at
http://web.tampabay.rr.com/mvsrexx/REXX/. Good luck.
(change Arabic number to Roman numeral to email)
-
Re: REXX debugger
Phil Hobbs <pcdh@SpamMeSenseless.pergamos.net> wrote in
news:46F2C686.2000309@SpamMeSenseless.pergamos.net:
>
> The front-end script has got up to about 11k lines at this point, which
> is a bit big for a REXX program, and I'm now finding that adding
> functions has a tendency to break things. (Classic REXX isn't the most
> structured language in the world.) I've spent some time chasing stupid
> stuff like inconsistent EXPOSE lists, when adding a feature means I
need
> access to a global stem down in some function that didn't previously
> need it.
>
I support an app that consists of hundreds of classic REXX programs, some
>13k lines. To avoid the problems you describe with EXPOSE lists we
adopted a few simple standards.
The start of each program sets a variable "globals" to the variables or
stems to be exposed i.e.
globals = '$. cust. foo.'
Then each subroutine has "procedure expose (globals)"
Any variable that is to be global starts wth a $. -- $.0fileName,
$.0returnCode etc.
We use lots of stems to sorta kinda simulate objects. For example all
the information about a customer is in the "cust." stem -- cust.0name
cust.0address etc. By prefixing the second token with a 0 we don't have
to worry about "cust.name" getting stomped on if someone decides to use
"name" as alocal variable.
If you find a good debugger let us know.
-
Re: REXX debugger
Phil Hobbs wrote:
> The front-end script has got up to about 11k lines at this point, which
> is a bit big for a REXX program, and I'm now finding that adding
> functions has a tendency to break things. (Classic REXX isn't the most
> structured language in the world.) I've spent some time chasing stupid
> stuff like inconsistent EXPOSE lists, when adding a feature means I need
> access to a global stem down in some function that didn't previously
> need it.
Well, one suggestion (which won't help you with your debugging) is to
put all truly global variables into a common stem and ensure that you
expose that everywhere you use "procedure".
My chosen common stem is "C." and the tails always start with a "0" (to
ensure that they are immutably constant). So the debug flag, c.0debug is
available throughout my code.
I cannot type the sequence "procedure expose" without my fingers wanting
to add "c."
Many of my routines start with:
If symbol(C.0debug) = 'VAR'
then call exit "C.0debug is undefined at line" sigl
This requires that I expose "sigl" as well, if this is in a routine
which starts with "procedure"
Alternatively, if you want global variables without exposing them, you
could use environment variables, but I normally restrict this to
desperate measures, for performance reasons.
--
Steve Swift
http://www.swiftys.org.uk/swifty.html
http://www.ringers.org.uk
-
Re: REXX debugger
On Sep 21, 12:29 am, Steve Swift <Steve.J.Sw...@gmail.com> wrote:
> Phil Hobbs wrote:
> > The front-end script has got up to about 11k lines at this point, which
> > is a bit big for a REXX program, and I'm now finding that adding
> > functions has a tendency to break things. (Classic REXX isn't the most
> > structured language in the world.) I've spent some time chasing stupid
> > stuff like inconsistent EXPOSE lists, when adding a feature means I need
> > access to a global stem down in some function that didn't previously
> > need it.
>
> Well, one suggestion (which won't help you with your debugging) is to
> put all truly global variables into a common stem and ensure that you
> expose that everywhere you use "procedure".
>
> My chosen common stem is "C." and the tails always start with a "0" (to
> ensure that they are immutably constant). So the debug flag, c.0debug is
> available throughout my code.
>
> I cannot type the sequence "procedure expose" without my fingers wanting
> to add "c."
>
> Many of my routines start with:
>
> If symbol(C.0debug) = 'VAR'
> then call exit "C.0debug is undefined at line" sigl
>
> This requires that I expose "sigl" as well, if this is in a routine
> which starts with "procedure"
>
> Alternatively, if you want global variables without exposing them, you
> could use environment variables, but I normally restrict this to
> desperate measures, for performance reasons.
>
> --
> Steve Swifthttp://www.swiftys.org.uk/swifty.htmlhttp://www.ringers.org.uk
Funny, in 20 years of coding nothing but Rexx, I have never had the
remotest desire to put a PROCEDURE statement on any of my called
routines.
Mickey
-
Re: REXX debugger
Steve Swift wrote:
> Phil Hobbs wrote:
>> The front-end script has got up to about 11k lines at this point,
>> which is a bit big for a REXX program, and I'm now finding that adding
>> functions has a tendency to break things. (Classic REXX isn't the
>> most structured language in the world.) I've spent some time chasing
>> stupid stuff like inconsistent EXPOSE lists, when adding a feature
>> means I need access to a global stem down in some function that didn't
>> previously need it.
>
> Well, one suggestion (which won't help you with your debugging) is to
> put all truly global variables into a common stem and ensure that you
> expose that everywhere you use "procedure".
>
> My chosen common stem is "C." and the tails always start with a "0" (to
> ensure that they are immutably constant). So the debug flag, c.0debug is
> available throughout my code.
>
> I cannot type the sequence "procedure expose" without my fingers wanting
> to add "c."
>
> Many of my routines start with:
>
> If symbol(C.0debug) = 'VAR'
> then call exit "C.0debug is undefined at line" sigl
>
> This requires that I expose "sigl" as well, if this is in a routine
> which starts with "procedure"
>
> Alternatively, if you want global variables without exposing them, you
> could use environment variables, but I normally restrict this to
> desperate measures, for performance reasons.
>
My life also improved a good deal when I found out about PROCEDURE
EXPOSE (globallist). I use c-like ASSERT and ABORT functions (complete
with checking ndebug). Making abort() optionally divide by zero causes
a traceback so I can at least figure out the call stack post-mortem,
which is often a huge help--but nowhere near what even a poor debugger
would provide.
Cheers,
Phil hobbs
---------------------------------------------
abort:
AbortErrcode=arg(1)
AbortErrtext= arg(2)
do i=3 to 100
if arg(i) = '' then leave
AbortErrtext = AbortErrtext arg(i)
end /* do */
if datatype(AbortErrcode) <> 'NUM' then do
AbortErrtext = AbortErrcode AbortErrtext
AbortErrcode = -9999
end /* if */
call lineout 'stderr', '('AbortErrcode')' AbortErrtext
call lineout 'stderr'
if global.7debug > 0 then traceback=1/0; /* cause trace-back */
exit(AbortErrcode);
return
assert: /* uses the caller's variable names--can also supply the value
as a second argument */
/* Usage: call assert "x < y"
* call assert "X must be less than Y", x < y
* call assert x" is greater than "y, x < y
*/
if ndebug=1 then return 0;
_assrtexpr = strip(arg(1),'b',' ');
_assrtval = arg(2);
if datatype(_assrtval) <> 'NUM' then do
interpret('_assrtval = ('_assrtexpr')')
if datatype(_assrtval) <> "NUM" then
call abort -1, "Assert error: non-numeric expression
"_assrtexpr"'";
end /* if */
if 0 = _assrtval then do
if ErText <> 'ERTEXT' then say ErText;
call abort -2, "Assertion failure: '"_assrtexpr"'";
end
return '';
-
Re: REXX debugger
Mickey wrote:
> On Sep 21, 12:29 am, Steve Swift <Steve.J.Sw...@gmail.com> wrote:
>> Phil Hobbs wrote:
>>> The front-end script has got up to about 11k lines at this point, which
>>> is a bit big for a REXX program, and I'm now finding that adding
>>> functions has a tendency to break things. (Classic REXX isn't the most
>>> structured language in the world.) I've spent some time chasing stupid
>>> stuff like inconsistent EXPOSE lists, when adding a feature means I need
>>> access to a global stem down in some function that didn't previously
>>> need it.
>> Well, one suggestion (which won't help you with your debugging) is to
>> put all truly global variables into a common stem and ensure that you
>> expose that everywhere you use "procedure".
>>
>> My chosen common stem is "C." and the tails always start with a "0" (to
>> ensure that they are immutably constant). So the debug flag, c.0debug is
>> available throughout my code.
>>
>> I cannot type the sequence "procedure expose" without my fingers wanting
>> to add "c."
>>
>> Many of my routines start with:
>>
>> If symbol(C.0debug) = 'VAR'
>> then call exit "C.0debug is undefined at line" sigl
>>
>> This requires that I expose "sigl" as well, if this is in a routine
>> which starts with "procedure"
>>
>> Alternatively, if you want global variables without exposing them, you
>> could use environment variables, but I normally restrict this to
>> desperate measures, for performance reasons.
>>
>> --
>> Steve Swifthttp://www.swiftys.org.uk/swifty.htmlhttp://www.ringers.org.uk
>
> Funny, in 20 years of coding nothing but Rexx, I have never had the
> remotest desire to put a PROCEDURE statement on any of my called
> routines.
>
> Mickey
>
Well, either you write simple programs exclusively, or you have an
amazing head for details. Calling a function from inside a loop and
having a 'local' variable clobber your loop counter gets old after awhile.
There are a couple of places in my simulator front end where I really
really need to execute in the caller's context--that's very typical when
you're using INTERPRET, for instance, or when you want to be able to
pull a file into a stem in Classic REXX. I write the routine as usual,
then use search-and-replace to add an eyecatcher to all the variable
names, to avoid clobbering anyone. As they said in 'Stalag 17', "crude
but effective."
Cheers,
Phil Hobbs
(*) Just so we don't get into the INTERPRET wars again, I use it as a
macro processor.
-
Re: REXX debugger
> Well, either you write simple programs exclusively, or you have an
> amazing head for details. Calling a function from inside a loop and
> having a 'local' variable clobber your loop counter gets old after awhile.
Having been raised on FORTRAN I find it impossible to use anything other
than I,J,K,L,M or N as the counter in do loops. I have procedures nested
at least 8 levels deep calling other procedures from inside loops, so
I'd rapidly run out of counters if I didn't use "procedure".
I'll admit that it's probably faster without the "procedure", if you can
manage it. I wouldn't last 10 minutes.
--
Steve Swift
http://www.swiftys.org.uk/swifty.html
http://www.ringers.org.uk
-
Re: REXX debugger
In Message-ID:<46f565c3@news.greennet.net>,
Steve Swift <Steve.J.Swift@gmail.com> wrote:
>Having been raised on FORTRAN I find it impossible to use anything other
>than I,J,K,L,M or N as the counter in do loops.
About the same here, though I've been known to go to
2-character names, when forced (i1 or ii).
"God is real, unless declared integer."
--
Arthur T. - ar23hur "at" intergate "dot" com
Looking for a z/OS (IBM mainframe) systems programmer position
-
Re: REXX debugger
On Sep 21, 11:43 am, Phil Hobbs
<pcdhSpamMeSensel...@electrooptical.net> wrote:
> Mickey wrote:
> > On Sep 21, 12:29 am, Steve Swift <Steve.J.Sw...@gmail.com> wrote:
> >> Phil Hobbs wrote:
> >>> The front-end script has got up to about 11k lines at this point, which
> >>> is a bit big for a REXX program, and I'm now finding that adding
> >>> functions has a tendency to break things. (Classic REXX isn't the most
> >>> structured language in the world.) I've spent some time chasing stupid
> >>> stuff like inconsistent EXPOSE lists, when adding a feature means I need
> >>> access to a global stem down in some function that didn't previously
> >>> need it.
> >> Well, one suggestion (which won't help you with your debugging) is to
> >> put all truly global variables into a common stem and ensure that you
> >> expose that everywhere you use "procedure".
>
> >> My chosen common stem is "C." and the tails always start with a "0" (to
> >> ensure that they are immutably constant). So the debug flag, c.0debug is
> >> available throughout my code.
>
> >> I cannot type the sequence "procedure expose" without my fingers wanting
> >> to add "c."
>
> >> Many of my routines start with:
>
> >> If symbol(C.0debug) = 'VAR'
> >> then call exit "C.0debug is undefined at line" sigl
>
> >> This requires that I expose "sigl" as well, if this is in a routine
> >> which starts with "procedure"
>
> >> Alternatively, if you want global variables without exposing them, you
> >> could use environment variables, but I normally restrict this to
> >> desperate measures, for performance reasons.
>
> >> --
> >> Steve Swifthttp://www.swiftys.org.uk/swifty.htmlhttp://www.ringers.org.uk
>
> > Funny, in 20 years of coding nothing but Rexx, I have never had the
> > remotest desire to put a PROCEDURE statement on any of my called
> > routines.
>
> > Mickey
>
> Well, either you write simple programs exclusively, or you have an
> amazing head for details. Calling a function from inside a loop > and having a 'local' variable clobber your loop counter gets old > after awhile.
In this case, the latter. I have some Rexx programs that are 10k lines
(don't ask, the details are brutal), but I pay close attention to loop
counters and indecies for input and output files.
Mickey
Similar Threads
-
By Application Development in forum REXX
Replies: 7
Last Post: 02-17-2007, 10:13 PM
-
By Application Development in forum REXX
Replies: 0
Last Post: 08-15-2006, 07:46 AM
-
By Application Development in forum REXX
Replies: 7
Last Post: 05-16-2006, 02:08 AM
-
By Application Development in forum REXX
Replies: 30
Last Post: 06-22-2005, 10:40 PM
-
By Application Development in forum REXX
Replies: 3
Last Post: 01-14-2005, 05:01 AM