As far as producing a trace-back, I use SIGNAL _ABEND_, which causes
"error 16: Label not found" and a trace-back after all of my own
debugging code completes. The label you signal doesn't have to be
_ABEND_, it can be any symbol which is not an actual label.
So the improvement to the sample code below would be to substitute
SIGNAL _ABEND_ for the EXIT 16. This is also superior from the
viewpoint of how REXX handles this if the failing routine is external:
EXIT 16 returns a value to the calling routine, whereas SIGNAL _ABEND_
stops all processing.
-----Original Message-----
From: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] On Behalf
Of Paul Gilmartin
Sent: Thu 20 Sep 2007 14:50
To: TSO-...@VM.MARIST.EDU
Subject: Re: [TSO-REXX] SIGNAL ON NOVALUE
In a recent note, Cruz, Robert said:
> Date: Thu, 20 Sep 2007 11:18:46 -0700
>
> The only problem with merely turning on SIGNAL ON NOVALUE is that it
> will not tell you which undefined variable is causing trouble. Here's
> a simple piece of code you can add at the end of your execs to fix
> that
> shortcoming:
>
> RETURN /* prevents us from falling into the NOVALUE code
> unintentionally */
>
(I'd just put it after my last subroutine and let that RETURN serve both
purposes.)
> NOVALUE: /* Action to take when NOVALUE condition is raised */
> SAY '==> NOVALUE condition raised in line' SIGL
> SAY '==> The derived name of the variable whose ' ,
> || 'attempted reference caused the NOVALUE condition is `' ,
> || "CONDITION"( 'D' )'`'
> EXIT 16
>
The only problem with that is that it suppresses the call stack trace.
Most of my NOVALUE errors (at least the hardest to
debug) arise from unintended effects of a PROCEDURE EXPOSE,
and for those the stack trace is precious.
Is there any way to get a stack trace electively? Should I just force a
syntax error?
(A support programmer whose code I must use puts SIGNAL ON SYNTAX and a
diagnostic routine in every EXEC he writes. Infuriating! AFAICT, this
provides less useful information than Rexx would provide if he left
SYNTAX untrapped.)
-- gil
--
StorageTek
INFORMATION made POWERFUL
----------------------------------------------------------------------
For TSO-REXX subscribe / signoff / archive access instructions, send
email to LIST...@VM.MARIST.EDU with the message: INFO TSO-REXX
----------------------------------------------------------------------
For TSO-REXX subscribe / signoff / archive access instructions,
send email to LIST...@VM.MARIST.EDU with the message: INFO TSO-REXX
> Date: Thu, 20 Sep 2007 16:58:30 -0700
>
> As far as producing a trace-back, I use SIGNAL _ABEND_, which causes
> "error 16: Label not found" and a trace-back after all of my own
> debugging code completes. The label you signal doesn't have to be
> _ABEND_, it can be any symbol which is not an actual label.
>
Thanks for the suggestion. Do these things work in compiled Rexx?
I understand it fails undefined labels in the compilation step.
Of course, my further wish is to be able to generate a stack
trace-back and continue processing. No hope, I suspect.
Thanks again,
I imagine:
SIGNAL VALUE _ABEND_
would pass muster with the compiler and produce what you want.
>Of course, my further wish is to be able to generate a stack
>trace-back and continue processing. No hope, I suspect.
None that I can imagine, alas...
...phsiii
I have benchmarked my REXX framework with and without the diagnostic code to
see if the "light-weight" code is really that much faster. I only saw a 5%
difference. When the difference is only 5 percent, I don't see the value
and risk in running without the safety net... This is reminiscent of our
thread on comment style a few years ago <grin>.
If this was still the mid-1980's with 308x boxes, I might be singing a
different tune, but today, 5 percent is the cost of doing business.
Rob
In a message dated 9/21/2007 7:30:24 AM US Mountain Standard Time,
Frank....@NATIONALCITY.COM writes:
But on the other hand, in another life was a consultant and knowing a
large percentage of the individual's taking over the code would make the
common mistakes that are talked about on this list-server. I would try
to ease their pain in debugging when they would have to modify the code.
Being out of consulting for 7 years I still receive emails and calls
from former clients asking for advice. I have never known a piece a
code that didn't have to be modified during its life cycle.
Frank
-----Original Message-----
From: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] On Behalf
Of Mickey Bee
Sent: Friday, September 21, 2007 10:11 AM
To: TSO-...@VM.MARIST.EDU
Subject: Re: SIGNAL ON NOVALUE -- Traceback for debugging
For me, it has to do with the fact that I work as a consultant. As such,
I write a great deal of code which will outlive my presense at a
location. Simply trapping errors then is not sufficient, I have to make
100% sure I account for any condition and avoid all possible errors.
Mickey
-------------- Original message ----------------------
From: "Sikich, Frank J." <Frank....@NATIONALCITY.COM>
> These discussions are fun because as you can see it is a personal
> preference and it fun to see other individual's viewpoints on the
> language and coding styles. As we all know it a coding style and as
> long as you are consistent the person following your code will
> understand your style.
>
> Frank
>
> -----Original Message-----
> From: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] On
Behalf
> Of Mickey Bee
> Sent: Friday, September 21, 2007 9:53 AM
> To: TSO-...@VM.MARIST.EDU
> Subject: Re: SIGNAL ON NOVALUE -- Traceback for debugging
>
> I couldn't agree more. I never put traps in my Rexx programs, as I
code
> to make sure they are never needed. The ONLY errors I trap are those
> arising from externals I call, such as dialog manager code or TSO
calls.
>
> Mickey
>
> -------------- Original message ----------------------
> From: "Ryerse, Robin" <robin....@EDS.COM>
> > SIGNAL ON NOVALUE is a debugging aid. It should never be included in
a
> > productive exec. Once set, it degrades the performance of the
routine
> > and at best helps identify a coding error. A thouroughly tested exec
> can
> > never raise a NOVALUE condition. For those who would say "what about
> > INTERPRET?", I suggest that the routine must be tested for all data
it
> > is supposed to handle as well as all logic paths. If an INTERPRET
> fails
> > on NOVALUE it is a user error not a program error.
> >
> >
> > Robin Ryerse
> >
> >
> >
> >
> > -----Original Message-----
> > From: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] On
> Behalf
> > Of Cruz, Robert
> > Sent: September 20, 2007 7:59 PM
> > To: TSO-...@VM.MARIST.EDU
> > Subject: Re: SIGNAL ON NOVALUE -- Traceback for debugging
> >
> > That's a good point, Gil. I was only trying to lay the basis for
> > NOVALUE handling. My own error handling code is much more
complicated
> > (too much so for a single post, if I were to include discussion of
the
> > features). However, I'm happy to tackle these issues one at a time
> (in
> > byte-size pieces, as it were ;-)
> >
> > As far as producing a trace-back, I use SIGNAL _ABEND_, which causes
> > "error 16: Label not found" and a trace-back after all of my own
> > debugging code completes. The label you signal doesn't have to be
> > _ABEND_, it can be any symbol which is not an actual label.
> >
> > So the improvement to the sample code below would be to substitute
> > SIGNAL _ABEND_ for the EXIT 16. This is also superior from the
> > viewpoint of how REXX handles this if the failing routine is
external:
> > EXIT 16 returns a value to the calling routine, whereas SIGNAL
_ABEND_
> > stops all processing.
> >
> > -----Original Message-----
> > From: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] On
> Behalf
> > Of Paul Gilmartin
> > Sent: Thu 20 Sep 2007 14:50
> > To: TSO-...@VM.MARIST.EDU
> > Subject: Re: [TSO-REXX] SIGNAL ON NOVALUE
> >
> >
> > In a recent note, Cruz, Robert said:
> >
> > -- gil
> > --
> > StorageTek
> > INFORMATION made POWERFUL
> >
> >
----------------------------------------------------------------------
> > For TSO-REXX subscribe / signoff / archive access instructions, send
> > email to LIST...@VM.MARIST.EDU with the message: INFO TSO-REXX
> >
> >
----------------------------------------------------------------------
> > For TSO-REXX subscribe / signoff / archive access instructions,
> > send email to LIST...@VM.MARIST.EDU with the message: INFO TSO-REXX
> >
> >
----------------------------------------------------------------------
> > For TSO-REXX subscribe / signoff / archive access instructions,
> > send email to LIST...@VM.MARIST.EDU with the message: INFO TSO-REXX
>
> ----------------------------------------------------------------------
> For TSO-REXX subscribe / signoff / archive access instructions,
> send email to LIST...@VM.MARIST.EDU with the message: INFO TSO-REXX
>
>
>
------------------------------------------------------------------------
--------
> -----------
> ***National City made the following annotations
>
------------------------------------------------------------------------
--------
> -----------
> This communication is a confidential and proprietary business
communication.
> It is intended solely for the use of the designated recipient(s). If
this
> communication is received in error, please contact the sender and
delete
> this communication.
>
========================================================================
========
> ===========
>
> ----------------------------------------------------------------------
> For TSO-REXX subscribe / signoff / archive access instructions,
> send email to LIST...@VM.MARIST.EDU with the message: INFO TSO-REXX
----------------------------------------------------------------------
For TSO-REXX subscribe / signoff / archive access instructions,
send email to LIST...@VM.MARIST.EDU with the message: INFO TSO-REXX
----------------------------------------------------------------------
For TSO-REXX subscribe / signoff / archive access instructions,
send email to LIST...@VM.MARIST.EDU with the message: INFO TSO-REXX
************************************** See what's new at http://www.aol.com
Thanks,
Rob
In a message dated 9/21/2007 6:30:22 AM US Mountain Standard Time,
bst...@PROTECHPTS.COM writes:
I am happy to post my production-quality, cross-platform
enabled RXERROR: routine if anyone wants to start using it.
> Date: Fri, 21 Sep 2007 08:15:40 -0400
>
> SIGNAL ON NOVALUE is a debugging aid. It should never be included in a
> productive exec. Once set, it degrades the performance of the routine
> and at best helps identify a coding error. A thouroughly tested exec can
> never raise a NOVALUE condition. For those who would say "what about
> INTERPRET?", I suggest that the routine must be tested for all data it
> is supposed to handle as well as all logic paths. If an INTERPRET fails
> on NOVALUE it is a user error not a program error.
>
I view SIGNAL ON NOVALUE as akin to a circuit breaker in hardware. Once
installed, the circuit breaker degrades preformance of the system by
whatever impedance it adds to the power supply. A thoroughly tested
electrical system can never malfunction, so once the designer is satisfied
that all tests have been passed, the circuit breakers should be removed
from the system.
-- gil
--
StorageTek
INFORMATION made POWERFUL
----------------------------------------------------------------------
(-:
But I know what you mean.
> -----Original Message-----
> From: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] On
Behalf
> Of Paul Gilmartin
> Sent: 21. syyskuuta 2007 18:44
> To: TSO-...@VM.MARIST.EDU
(1) the analogy assumes that none of the internal components (resistors,
capacitors, etc) can fail. We all know that this sometimes happens, and
the presence of a fuse/circuit breaker is necessary to protect the
safety of those operating the hardware
(2) software is subject to frequent changes. If your hardware had
sockets of some sort for plug-in accessories which could come from a
third party, wouldn't you include the fuse/circuit breaker because you
could lose control of the conditions in the machine?
(3) What if your device were used in an environment where the external
conditions (quality of power, signal timing, etc) might change in the
future? Wouldn't prudence dictate the provision of fuses to guard
against fires or other disastrous side effects?
Most of these points have been made before. To sum it up, it seems to
me that the basic argument against SIGNAL ON SYNTAX has been that
"perfect" REXX can be produced. This is possible (but not guaranteed)
only for the most trivial programs. Furthermore, external factors (the
operating environment and modification by others) could cause a
"perfect" program to fail. Often, the preconditions promised by
potential users turn out to be incomplete, inaccurate, or just plain
wrong. Finally, I rarely see circumstances that permit enough time to
code and test to perfection.
The worst possible outcome from a program with an undefined variable but
without SIGNAL ON NOVALUE isn't really bad output, its bad output which
can be mistaken for good!
While SIGNAL ON NOVALUE does not guarantee a correct program, it helps
weed out the incorrect ones. I'll gladly pay the small penalty for
that.
-----Original Message-----
From: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] On Behalf
Of Paul Gilmartin
Sent: Fri 21 Sep 2007 08:44
To: TSO-...@VM.MARIST.EDU
Subject: Re: [TSO-REXX] SIGNAL ON NOVALUE -- Traceback for debugging
In a recent note, Ryerse, Robin said:
> Date: Fri, 21 Sep 2007 08:15:40 -0400
>
> SIGNAL ON NOVALUE is a debugging aid. It should never be included in a
> productive exec. Once set, it degrades the performance of the routine
> and at best helps identify a coding error. A thouroughly tested exec
> can never raise a NOVALUE condition. For those who would say "what
> about INTERPRET?", I suggest that the routine must be tested for all
> data it is supposed to handle as well as all logic paths. If an
> INTERPRET fails on NOVALUE it is a user error not a program error.
>
> Date: Fri, 21 Sep 2007 09:30:00 -0400
>
> - People will change my code after I have debugged it, and introduce new
> errors.
>
Alas, the second thing such a revisionist is apt to do is to delete the
pesky SIGNAL ON NOVALUE that caused the line of code he just added
to fail.
> While I have not benchmarked the difference between running with and without
> SIGNAL ON NOVALUE, I doubt that it introduces overhead in the "normal" case,
> where the variable HAS a value. In the exceptional case, where the variable
> does not exist, it must run through my error handler, yes, that is more
> overhead, as the program writes out diagnostics and terminates.
>
Makes sense. If the test for SIGNAL enabled is in the branch where the
variable has already been found to be uninitialized, correct code will
never execute it. May we neglect the I/O bandwidth to read the extra
line, and the cost of parsing it?
> I don't really like the REXX feature where "uninitialized variables get a
> default value of their own name in upper case". In my code, uninitialized
> variables are typographical errors.
>
Me too (and I'd prefer case ASIS for the Q&D). And that should apply likewise
to uninitialized variables in compound tails.
> I think more code SHOULD use SIGNAL ON NOVALUE. The only place I don't use
> it is in my "RexxTry", because there I am just doing quick and dirty
> experiments and can afford to be a bit crufty.
>
I have something similar, in which I also omit SIGNAL ON NOVALUE.
For the performance-obsessed, a colleague once found empirically that
IF RC==0 is detectably faster than IF RC=0 (intuitively reasonable).
I wonder how many programmers exploit this optimization?
I do trap some errors, but I trap them by testing for the expected values, and branching to an error routine. I find this forces those coming in behind me to do the same. It is the same reason I put a comment on every line of code. That way, someone adding code will feel a need to do the same. It has been my experience that, at the VERY best, external documentation is only valid the day a program goes live. People RARELY in ever go back and update external docs for each change, but internal documentation they will, if you code in such a way as to make it obvious who did NOT comment his/her code :)
Mickey
-------------- Original message ----------------------
From: Robert Zenuk <Robz...@AOL.COM>
> Also being a part-time consultant, I don't understand why you wouldn't want
> the safety net. Case in point; recently, we had a z/OS change introduced
> somewhere between z/OS 1.6 and z/OS 1.8 (we went directly from 1.6 to 1.8)
> where
> something that had worked for 10 years started failing. It was a new SMS
> behavior with multi-tiered storage groups used for mapping VIO datasets. The
> net effect was something started failing. I was VERY happy that my traps and
> diagnostic code in my previously "bullet-proof" code reported the condition
> (and the fallout).
>
> I have benchmarked my REXX framework with and without the diagnostic code to
> see if the "light-weight" code is really that much faster. I only saw a 5%
> difference. When the difference is only 5 percent, I don't see the value
> and risk in running without the safety net... This is reminiscent of our
> thread on comment style a few years ago <grin>.
>
> If this was still the mid-1980's with 308x boxes, I might be singing a
> different tune, but today, 5 percent is the cost of doing business.
>
> Rob
>
>
>
> In a message dated 9/21/2007 7:30:24 AM US Mountain Standard Time,
> Frank....@NATIONALCITY.COM writes:
>
> But on the other hand, in another life was a consultant and knowing a
> large percentage of the individual's taking over the code would make the
> common mistakes that are talked about on this list-server. I would try
> to ease their pain in debugging when they would have to modify the code.
> Being out of consulting for 7 years I still receive emails and calls
> from former clients asking for advice. I have never known a piece a
> code that didn't have to be modified during its life cycle.
>
> Frank
>
> -----Original Message-----
> From: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] On Behalf
> Of Mickey Bee
> Sent: Friday, September 21, 2007 10:11 AM
> To: TSO-...@VM.MARIST.EDU
> Subject: Re: SIGNAL ON NOVALUE -- Traceback for debugging
>
> For me, it has to do with the fact that I work as a consultant. As such,
> I write a great deal of code which will outlive my presense at a
> location. Simply trapping errors then is not sufficient, I have to make
> 100% sure I account for any condition and avoid all possible errors.
>
> Mickey
>
> -------------- Original message ----------------------
> From: "Sikich, Frank J." <Frank....@NATIONALCITY.COM>
> > These discussions are fun because as you can see it is a personal
> > preference and it fun to see other individual's viewpoints on the
> > language and coding styles. As we all know it a coding style and as
> > long as you are consistent the person following your code will
> > understand your style.
> >
> > Frank
> >
> > -----Original Message-----
> > From: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] On
> Behalf
> > Of Mickey Bee
> > Sent: Friday, September 21, 2007 9:53 AM
> > To: TSO-...@VM.MARIST.EDU
> > Subject: Re: SIGNAL ON NOVALUE -- Traceback for debugging
> >
> > I couldn't agree more. I never put traps in my Rexx programs, as I
> code
> > to make sure they are never needed. The ONLY errors I trap are those
> > arising from externals I call, such as dialog manager code or TSO
> calls.
> >
> > Mickey
> >
> > -------------- Original message ----------------------
> > From: "Ryerse, Robin" <robin....@EDS.COM>
> > > SIGNAL ON NOVALUE is a debugging aid. It should never be included in
> a
> > > productive exec. Once set, it degrades the performance of the
> routine
> > > and at best helps identify a coding error. A thouroughly tested exec
> > can
> > > never raise a NOVALUE condition. For those who would say "what about
> > > INTERPRET?", I suggest that the routine must be tested for all data
> it
> > > is supposed to handle as well as all logic paths. If an INTERPRET
> > fails
> > > on NOVALUE it is a user error not a program error.
> > >
> > >
> > > Robin Ryerse
> > >
> > >
> > >
> > >
> > > -----Original Message-----
> > > From: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] On
> > Behalf
> > > -----Original Message-----
> > > From: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] On
> > Behalf
> > > Of Paul Gilmartin
> > > Sent: Thu 20 Sep 2007 14:50
> > > To: TSO-...@VM.MARIST.EDU
> > > Subject: Re: [TSO-REXX] SIGNAL ON NOVALUE
> > >
> > >
> > > -- gil
> > > --
> > > StorageTek
> > > INFORMATION made POWERFUL
> > >
> > >
> ----------------------------------------------------------------------
> > > For TSO-REXX subscribe / signoff / archive access instructions, send
> > > email to LIST...@VM.MARIST.EDU with the message: INFO TSO-REXX
> > >
> > >
> ----------------------------------------------------------------------
> > > For TSO-REXX subscribe / signoff / archive access instructions,
> > > send email to LIST...@VM.MARIST.EDU with the message: INFO TSO-REXX
> > >
> > >
> ----------------------------------------------------------------------
> > > For TSO-REXX subscribe / signoff / archive access instructions,
> > > send email to LIST...@VM.MARIST.EDU with the message: INFO TSO-REXX
> >
> > ----------------------------------------------------------------------
> > For TSO-REXX subscribe / signoff / archive access instructions,
> > send email to LIST...@VM.MARIST.EDU with the message: INFO TSO-REXX
> >
> >
> >
> ------------------------------------------------------------------------
> --------
> > -----------
> > ***National City made the following annotations
> >
> ------------------------------------------------------------------------
> --------
> > -----------
> > This communication is a confidential and proprietary business
> communication.
> > It is intended solely for the use of the designated recipient(s). If
> this
> > communication is received in error, please contact the sender and
> delete
> > this communication.
> >
> ========================================================================
> ========
> > ===========
> >
> > ----------------------------------------------------------------------
> > For TSO-REXX subscribe / signoff / archive access instructions,
> > send email to LIST...@VM.MARIST.EDU with the message: INFO TSO-REXX
>
> ----------------------------------------------------------------------
> For TSO-REXX subscribe / signoff / archive access instructions,
> send email to LIST...@VM.MARIST.EDU with the message: INFO TSO-REXX
>
> ----------------------------------------------------------------------
> For TSO-REXX subscribe / signoff / archive access instructions,
> send email to LIST...@VM.MARIST.EDU with the message: INFO TSO-REXX
>
>
>
>
>
>
> ************************************** See what's new at http://www.aol.com
>
> Date: Fri, 21 Sep 2007 17:50:16 +0200
>
> Reminds me of when I was a boy and a fuse would burn out. If we didn't
> have an extra one, we'd put a penny in and screw the bad fuse back in.
> (-:
> But I know what you mean.
>
No, that's the case where the test has failed.
This code is from a template ("skeleton") I use to create new EXECs.
I replace all instances of the string of six question marks with the
module ID.
This code has evolved over time, so some of it may be archaic.
This code is supposed to work on most platforms (CMS, XEDIT, MVS, and
PC).
The symbols <max_cc> and <_abend> are used as-is if they have values.
ERRMSG is an external routine which issues a message in accordance with
the current platform. You could substitute SAY, if you like. SAY is
used here where I don't think I can rely on ERRMSG being available.
The symbol <_call_stack> contains traceback information maintained by
the program itself.
While this is a lot of work, it may be necessary for programs with
extreme problems.
It must be EXPOSED in every internal closed routine, and pass it to
external routines.
At the beginning of the mainline, _call_stack is initialized to the name
of the program (and its parameter values, if needed).
The stem _call_hist. is a circular buffer which retains the last
_hist_bufsz call stacks, for those occasions where the underlying error
occurs prior to the symptom. They are initialized as:
_call_hist. = ''
_hist_bufsz = 100 /* entries numbered 0..99 */
_hist_ptr = 0
_call_hist.0 = '0->1' /* main program called from external
environment */
In each procedure, the prologue is:
/* func.0 Debugging Prologue */
_called_from = SIGL
_save_stack = _call_stack
_call_stack = 'Internal_Function?? invoked in line' _called_from 'of'
_call_stack
_hist_ptr = ( _hist_ptr + 1 ) // _hist_bufsz /* 0..(_hist_bufsz-1)
*/
_call_hist._hist_ptr = _called_from'->'LineNum()
The epilogue is:
_call_stack = _save_stack
_hist_ptr = ( _hist_ptr + 1 ) // _hist_bufsz /* 0..(_hist_bufsz-1)
*/
_call_hist._hist_ptr = _called_from'<-'LineNum()+3
SIGL = _called_from
Note that SIGL must also be exposed in all internal closed routines.
I have also included the code for the routine EXHIBIT. While its not
used here, you may find it handy for dumping variables (similar to PL/I
PUT DATA). You pass it the names of the variables to be dumped, as
quoted strings.
I think that's everything. Just let me know if something is unclear.
Here's the debugging portion of the template:
________________________________________________________________________
__________________________
/*********************************************************************/
/* */
/* 8. CONDITION TRAPS */
/* */
/* Handle language-defined error conditions encountered during */
/* execution. */
/* */
/* Error numbers: 87x, 88x, 89x */
/* */
/*********************************************************************/
/* 8.1 Intercept SYNTAX conditions... */
SYNTAX: /* invalid source statement interpreted */
/* Machine state -- */
/* Sigl = source line number where detected */
/* Condition(ConditionName) = `SYNTAX` */
/* Condition(Description ) = `` */
/* Condition(Instruction ) = `SIGNAL` */
/* Condition(Status ) = `OFF` */
/* RC = syntax error number */
/* Result = not set */
/* Sigl = number of line where SYNTAX raised */
/* SourceLine(Sigl) = source of line where SYNTAX raised */
/* ErrorText(rc) = description of syntax error */
/* NOTE: SYNTAX errors include #40, "Incorrect call to routine" */
SIGNAL OFF SYNTAX /* prevent recursion */
_CondNm = 'SYNTAX' /* Name of error condition */
_LineNr = SIGL /* Number of error sourceline */
_Err = RC /* Save error number */
_RC = RC /* Save return code */
SIGNAL Trapped /* continue with common code */
/* 8.2 Intercept NOVALUE conditions... */
NOVALUE: /* undefined variable referenced */
/* Machine state -- */
/* Sigl = source line number where detected */
/* Condition(ConditionName) = `NOVALUE` */
/* Condition(Description ) = name of undefined symbol */
/* Condition(Instruction ) = `SIGNAL` */
/* Condition(Status ) = `OFF` */
/* RC = not set */
/* Result = not set */
/* Sigl = number of line where NOVALUE raised */
/* SourceLine(Sigl) = source of line where NOVALUE raised */
/* ErrorText(16) = `Label not found` */
SIGNAL OFF NOVALUE /* prevent recursion */
_CondNm = 'NOVALUE' /* Name of error condition */
_LineNr = SIGL /* Number of error sourceline */
_Err = 16 /* Save error number */
_RC = '' /* Save return code */
SIGNAL Trapped /* continue with common code */
/* 8.3 Intercept HALT conditions... */
HALT: /* Program interrupted by user */
/* You may to use TS in order to look around */
/* Machine state -- */
/* Sigl = source line number where halted */
/* Condition(ConditionName) = `HALT` */
/* Condition(Description ) = `` */
/* Condition(Instruction ) = `SIGNAL` */
/* Condition(Status ) = `OFF` */
/* RC = not set */
/* Result = not set */
/* Sigl = number of line where HALT raised */
/* SourceLine(Sigl) = source of line where HALT raised */
/* ErrorText( 4) = `Program interrupted` */
SIGNAL OFF HALT /* prevent recursion */
_CondNm = 'HALT' /* Name of error condition */
_LineNr = SIGL /* Number of error sourceline */
_Err = 4 /* Save error number */
_RC = RC /* Save return code */
SIGNAL Trapped /* continue with common code */
/* 8.4 Intercept FAILURE conditions... */
FAILURE: /* Error detected by Environment addressed */
/* You may to use TS in order to look around */
/* Machine state -- */
/* Sigl = source line number where failed */
/* Condition(ConditionName) = `FAILURE` */
/* Condition(Description ) = source line where FAILURE raised */
/* Condition(Instruction ) = `SIGNAL` */
/* Condition(Status ) = `OFF` */
/* RC = return code from command */
/* Result = not set */
/* Sigl = number of line where FAILURE raised */
/* SourceLine(Sigl) = source of line where FAILURE raised */
/* ErrorText( ) = not applicable */
/* NOTE: Failing command should have issued its own message(s) */
/* NOTE: FAILURE is raised by negative return codes from the */
/* external environment or the command issued. */
SIGNAL OFF FAILURE /* prevent recursion */
_CondNm = 'FAILURE' /* Name of error condition */
_LineNr = SIGL /* Number of error sourceline */
_Err = '' /* Set error number */
_RC = RC /* Save return code */
SIGNAL Trapped /* continue with common code */
/* 8.5 Intercept ERROR conditions... */
ERROR: /* Command returned an error indication */
/* You may to use TS in order to look around */
/* Machine state -- */
/* Sigl = source line number where detected */
/* Condition(ConditionName) = `ERROR` */
/* Condition(Description ) = source line where ERROR raised */
/* Condition(Instruction ) = `SIGNAL` */
/* Condition(Status ) = `OFF` */
/* RC = return code from command */
/* Result = not set */
/* Sigl = number of line where ERROR raised */
/* SourceLine(Sigl) = source of line where ERROR raised */
/* ErrorText( ) = not applicable */
/* NOTE: Command should have issued its own error message(s) */
/* NOTE: ERROR is raised by a positive return code from command, */
/* *and* negative return codes when FAILURE is OFF. */
SIGNAL OFF ERROR /* prevent recursion */
_CondNm = 'ERROR' /* Name of error condition */
_LineNr = SIGL /* Number of error sourceline */
_Err = '' /* Set error number */
_RC = RC /* Save return code */
SIGNAL Trapped /* continue with common code */
/* 8.6 Intercept USER Wrong_Number_Args conditions... */
Abend: /* User Abend */
/* Machine state -- */
/* Sigl = source line number where detected */
/* Condition(ConditionName) = '' */
/* Condition(Description ) = '' */
/* Condition(Instruction ) = '' */
/* Condition(Status ) = '' */
/* RC = undefined */
/* Result = undefined */
/* Sigl = number of line where SIGNAL executed*/
/* SourceLine(Sigl) = source of line where SIGNAL executed*/
/* ErrorText( ) = not applicable */
/* NOTE: This is an internal error. */
/* NOTE: Abend is raised by program logic. */
_CondNm = 'USER Abend' /* Name of error condition */
_LineNr = SIGL /* Number of error sourceline */
_Err = '' /* Set error number */
_RC = '' /* Set return code */
SIGNAL Trapped /* continue with common code */
/* 8.7 Common condition handling... */
Trapped: /* common error handling */
/* NOTE: SIGNALling a user-defined label sets only SIGL, */
/* that is, CONDITION(*), RC, and Result retain their */
/* previous values. */
IF SYMBOL( '_abend' ) <> 'VAR'
THEN DO
CALL ErrMsg '??????870E Symbol "_abend" is undefined! -- using 1'
_abend = 1
END
IF SYMBOL( 'max_cc' ) <> 'VAR'
THEN DO
CALL ErrMsg '??????870E Symbol "max_cc" is undefined! -- using 16'
max_cc = 16
END
/* 8.7.1 Determine execution environment... */
PARSE SOURCE _OpSys . _srcpgm ,
(1) . . _fn _ft _fm _asfn . /* for CMS */ ,
(1) . . _pgmname _ddn _dsn . /* for TSO */
SELECT /* Case of _OpSys */
WHEN _OpSys = 'CMS'
THEN _ProgName = _fn _ft _fm '(invoked as' _asfn')'
WHEN _OpSys = 'TSO'
THEN _ProgName = 'DD:'_ddn', DSN='_dsn'('_pgmname')'
OTHERWISE /* OS/2, DOS, Linux, AIX, Windows, etc */ _ProgName =
_srcpgm
END /* Case of _OpSys */
PARSE VERSION _Impl _LangLevel . /* Get impl name & lang level */
/* Note: the CMS error messages for REXX lie in the range */
/* DMS449E to DMS492E. There is no simple rule mapping the */
/* REXX errors (RC) to these message numbers. */
/* 8.7.2 Display the condition raised... */
SAY '??????970E' _CondNm 'condition raised in line' _LineNr ,
|| ', while running' _ProgName
IF _Err = '' THEN DO
IF _RC <> '' THEN DO
SAY '??????988E' _CondNm 'condition raised due to ' ,
|| 'return code' _RC 'from command'
END
END
ELSE SAY '??????971E Error' _Err':' ERRORTEXT(_Err)
/* 8.7.3 Display information about program state when the */
/* condition was raised... */
IF _asfn <> '' & _asfn <> '?'
THEN SAY '??????972I Program was invoked as "'_asfn'"'
/* 8.7.3.1 Display call stack we maintain ourselves... */
IF SYMBOL( '_call_stack' ) = 'VAR'
THEN /* _call_stack is a variable */ DO
IF _call_stack <> ''
THEN SAY '??????888I Call stack: ' _call_stack
END /* _call_stack is a variable */
ELSE max_cc = MAX( max_cc, ,
/* 8.7.3.2 Display call stack maintained by Regina... */
IF ABBREV( _Impl, 'REXX-Regina' )
THEN /* Regina facilities available */ DO
SAY '??????963I Call Traceback: '
CALL Traceback
END /* Regina facilities available */
/* 8.7.3.3 Display call history we maintain ourselves... */
IF SYMBOL( '_hist_ptr' ) = 'VAR' ,
& SYMBOL( '_call_hist.' ) = 'VAR'
THEN /* both _hist_ptr and _call_hist are variables */ DO
SAY '??????872I Call History (most recent to oldest):'
_ii = _hist_ptr
_line = ' '
DO WHILE _call_hist._ii <> '' ,
& _ii <> ( _hist_ptr + 1 ) // _hist_bufsz
IF LENGTH( _line _ii':'_call_hist._ii ) > 79
THEN DO
SAY _line
_line = ' '
END
_line = _line _ii':'_call_hist._ii
_ii = ( _hist_bufsz + _ii - 1 ) // _hist_bufsz
END /* WHILE more history in buffer */
IF _line <> ''
THEN SAY _line
END /* both _hist_ptr and _call_hist are variables */
ELSE max_cc = MAX( max_cc, ,
ErrMsg( '??????870E Symbol(s) "_call_hist" and/or
"_hist_ptr" is/are undefined!' ) )
/* 8.7.4 Display the source line(s) containing the instruction */
/* which raised the condition... */
IF SOURCELINE() <> 0
THEN /* source lines available */ DO
IF SYMBOL( '_lineNr' ) = 'VAR'
THEN /* _lineNr is a variable */ DO
SAY '??????981I Source line(s) containing the start of the ' ,
|| 'offending instruction:'
/* Note: actually, the statement may span several lines, or*/
/* it may be one of several statements on a single */
/* line, but a rigorous treatment is too complicated */
/* for this routine. Instead, we settle for an */
/* approach which works pretty well most of the time. */
/* This logic assumes: (a) there are no nested */
/* comments, and (b) there are no semicolons in any */
/* non-trailing comment. */
/* Perhaps this logic should use CONDITION('D') */
/* when the condition raised is ERROR or FAILURE?! */
DO _ii = _LineNr TO SOURCELINE() ,
UNTIL( \ _continued )
SAY ':'RIGHT( _ii, 7, '0' )': ' SOURCELINE( _ii )
_sourceline = STRIP( SOURCELINE( _ii ), 'T' )
DO WHILE( RIGHT( _sourceline, 2 ) = '*/' )
/* Remove trailing comment */
_jj = LASTPOS( '/*', _sourceline )
_sourceline = STRIP( LEFT( _sourceline, _jj - 1 ), 'T' )
END
_continued = ( POS( ';', _sourceline ) = 0 ,
& RIGHT( _sourceline, 1 ) = ',' )
END _ii
END /* _lineNr is a variable */
ELSE max_cc = MAX( max_cc, ,
ErrMsg( '??????870E Symbol "_lineNr" is
undefined!' ) )
END /* source lines available */
/* 8.7.5 Display the description of the condition which was raised*/
IF _LangLevel > 3.45 THEN DO /* CONDITION BIF is supported */
cond_name = "CONDITION"( 'C' ) /* Get condition name */
cond_desc = "CONDITION"( 'D' ) /* Get condition description */
/* NOTE: the differences between CONDITION('Description') and */
/* SOURCELINE( sigl ) when used with the ERROR and */
/* FAILURE conditions are: */
/* (1) CONDITION('D') returns only the offending instruction,*/
/* whereas SOURCELINE(sigl) returns the entire line, */
/* which may contain multiple statements and comments; */
/* (2) the S/370 REXX compiler should support CONDITION('D')*/
/* even when compiled with the NOSOURCE option; and */
/* (3) CONDITION('D') shows the fully-substituted command, */
/* whereas SOURCELINE(sigl) shows the REXX expression */
/* which *became* the command. */
SELECT /* Case of condition raised */
WHEN cond_name = 'ERROR'
THEN SAY '??????973I The string that processed and resulted in '
,
|| 'the error is `'cond_desc'`'
WHEN cond_name = 'FAILURE'
THEN SAY '??????974I The string that processed and resulted in '
,
|| 'the failure is `'cond_desc'`'
WHEN cond_name = 'HALT'
THEN IF cond_desc <> ''
THEN SAY '??????975I The string associated with the HALT '
,
|| 'request is `'cond_desc'`'
WHEN cond_name = 'LOSTDIGITS'
THEN IF cond_desc <> ''
THEN SAY '??????983I The number with excessive digits that
' ,
|| 'caused the LOSTDIGITS condition to be raised
is `' ,
|| cond_desc'`'
WHEN cond_name = 'NOMETHOD'
THEN IF cond_desc <> ''
THEN SAY '??????984I The name of the method that could not
' ,
|| 'be found, causing the NOMETHOD condition to be
' ,
|| 'raised, is `'cond_desc'`'
WHEN cond_name = 'NOSTRING'
THEN IF cond_desc <> ''
THEN SAY '??????985I The readable string representation of
' ,
|| 'the object causing the NOSTRING condition is
`' ,
|| cond_desc'`'
WHEN cond_name = 'NOTREADY'
THEN IF cond_desc <> ''
THEN SAY '??????986I The name of the stream being
manipulated' ,
|| ' when the error occurred and the NOTREADY ' ,
|| 'condition was raised is `'cond_desc'`'
WHEN cond_name = 'NOVALUE'
THEN SAY '??????976I The derived name of the variable whose ' ,
|| 'attempted reference caused the NOVALUE condition is
`' ,
|| cond_desc'`'
WHEN cond_name = 'SYNTAX'
THEN IF cond_desc <> ''
THEN SAY '??????977I The string associated with the SYNTAX
' ,
|| 'condition is `'cond_desc'`'
WHEN cond_name = 'USER'
THEN IF cond_desc <> ''
THEN SAY '??????987I The string specified by the
DESCRIPTION' ,
|| 'option of the RAISE instruction that raised
the ' ,
|| cond_name 'condition is `'cond_desc'`'
WHEN cond_name = ''
THEN /* raised by SIGNAL instruction */
SAY '??????979I The condition was raised by an internal ' ,
|| 'SIGNAL instruction'
OTHERWISE
SAY '??????980I Unrecognized condition, "'cond_name ,
|| '", with a description of "'cond_desc'" has been raised'
END /* Case of condition raised */
END /* CONDITION BIF is supported */
/* 8.7.6 Display built-in symbols at time the condition was raised*/
IF SYMBOL( 'RESULT' ) = 'VAR'
THEN SAY '??????966I Value of the special variable RESULT at the ' ,
|| 'time the condition was raised is "'result'"'
ELSE SAY '??????965I The special variable RESULT had no value at ' ,
|| 'the time the condition was raised'
IF _RC = ''
THEN IF SYMBOL( 'RC' ) = 'VAR'
THEN SAY '??????968I Value of the special variable RC at the '
,
|| 'time the condition was raised is "'RC'"'
ELSE SAY '??????967I The special variable RC had no value at '
,
|| 'the time the condition was raised'
/* 8.7.7 Display arguments at time of SIGNAL... */
SAY '??????982I The most recent call at the time the condition ' ,
|| 'was raised had' ARG() 'argument'COPIES( 's', ARG() <> 1 )
DO _ii = 1 TO ARG()
SAY '??????989I Value of ARG('_ii') at the time the condition ' ,
|| 'was raised is "'ARG(_ii)'"'
END _ii
/* 8.7.8 Enable interactive debugging if possible... */
IF ABBREV( _Impl, 'REXXC' )
THEN _Term = 0 /* Compiled code cannot be traced interactively */
ELSE /* NOT a compiled program.. */ DO
/* 8.7.8.1 Determine whether or not a user console exists... */
SELECT /* Case of operating system */
WHEN _OpSys = 'CMS'
THEN _Term = ( LINESIZE() > 0 )
OTHERWISE _Term = 0 /* Assume there is no console */
END /* Case of operating system */
END /* NOT a compiled program */
/* 8.7.8.2 Enable interactive debug if a user console was found */
IF ( _Term ) THEN /* a terminal is available */ DO
SAY '??????964A You can look around now...' /* Alert user */
SAY '??????964A+ Enter TRACE OFF to discontinue tracing'
SAY '??????964A+ Enter TRACE ? to continue tracing without pauses'
TRACE ?R /* Interactive tracing */
NOP /* and stop here. */
END /* a terminal is available */
ELSE /* NO terminal is available */ DO
IF ABBREV( _Impl, 'REXX-Regina' )
THEN /* Regina facilities available */ DO
SAY '??????959I Variable pool dump: '
CALL DumpVars
END /* Regina facilities available */
END /* NO terminal is available */
/* 8.7.9 Determine return code... */
IF DATATYPE( _RC ) = 'NUM'
THEN _abcode = _RC
ELSE IF DATATYPE( _Err ) = 'NUM'
THEN _abcode = _Err
ELSE _abcode = 253
IF _OpSys = 'CMS'
THEN _abcode = 20000 + _abcode
max_cc = MAX( max_cc, _abcode )
/* 8.7.10 If possible, attempt cleanup... */
/* If the error did not occur while abending, give the program */
/* logic a chance to close open files, and otherwise clean up. */
IF _abend = 0
THEN SIGNAL Wind_Down
CALL Die _abcode /* Get the heck out of here!! */
SIGNAL _LOGIC_ERROR_ /* Should never get here! */
/*********************************************************************/
/* */
/* Exhibit: Dump REXX variable(s) ... */
/* */
/* SYNTAX: */
/* CALL Exhibit 'varname1'<, 'varname2'>... */
/* */
/*********************************************************************/
Exhibit: /* Open subroutine */
/*ALL MAINTENANCE CHANGES TO THIS MUST ALSO BE MADE TO EMBEDDED
COPIES!*/
TRACE N /* don't trace this routine, even if tracing caller */
/* Remember that compound symbols may have imbedded spaces in */
/* their names. */
SAY '*** Value of variable symbol(s) in line' sigl':'
DO sigl = 1 TO ARG( )
SELECT /* Case of SYMBOL( ARG( sigl ) ) */
WHEN SYMBOL( ARG(sigl) ) = 'VAR' THEN
SAY ' Variable <'ARG(sigl) || '> (' ,
|| LENGTH( VALUE( STRIP( ARG(sigl) ) ) ) ,
|| ' bytes) = `' || VALUE( STRIP( ARG(sigl) ) ) || '`' ,
|| COPIES( " = '"C2X( VALUE( ARG( sigl) ) )"'X", ,
VERIFY( VALUE( ARG( sigl ) ), ,
'ABCDEFGHIJKLMNOPQRSTUVWXYZ' ,
|| '~!@#$%^&*()_+{}|:"<>?' ,
|| "abcdefghijklmnopqrstuvwxyz" ,
|| "`1234567890-=[]\;',./" ) > 0 )
WHEN SYMBOL( ARG(sigl) ) = 'LIT' THEN
SAY ' Literal (' || LENGTH( ARG(sigl) ) ,
|| ' bytes): `' || ARG(sigl) || '`' ,
|| COPIES( " = '"C2X( VALUE( ARG( sigl) ) )"'X", ,
VERIFY( VALUE( ARG( sigl ) ), ,
'ABCDEFGHIJKLMNOPQRSTUVWXYZ' ,
|| '~!@#$%^&*()_+{}|:"<>?' ,
|| "abcdefghijklmnopqrstuvwxyz" ,
|| "`1234567890-=[]\;',./" ) > 0 )
WHEN SYMBOL( ARG(sigl) ) = 'BAD' THEN
SAY ' Not a Symbol (' || LENGTH( ARG(sigl) ) ,
|| ' bytes): `' || ARG(sigl) || '`' ,
|| COPIES( " = '"C2X( VALUE( ARG( sigl) ) )"'X", ,
VERIFY( VALUE( ARG( sigl ) ), ,
'ABCDEFGHIJKLMNOPQRSTUVWXYZ' ,
|| '~!@#$%^&*()_+{}|:"<>?' ,
|| "abcdefghijklmnopqrstuvwxyz" ,
|| "`1234567890-=[]\;',./" ) > 0 )
END /* Case of SYMBOL( ARG( sigl ) ) */
END sigl
IF SYMBOL( 'RESULT' ) = 'VAR'
THEN RETURN result
ELSE RETURN
/*********************************************************************/
/* */
/* linenum: returns caller's source line number */
/* */
/*********************************************************************/
linenum: RETURN sigl
/*********************************************************************/
/* */
/* DIE: Terminate this program and any which called it */
/* */
/*********************************************************************/
DIE:
PARSE SOURCE . how_invoked .
SELECT /* Case of <how_invoked> */
WHEN how_invoked = 'COMMAND'
THEN EXIT ARG(1) /* May raise ERROR or FAILURE */
WHEN how_invoked = 'FUNCTION'
THEN EXIT /* causes Error 44: Function did not return data */
WHEN how_invoked = 'SUBROUTINE'
THEN SIGNAL _ABEND_ /* causes Error 16: Label not found */
OTHERWISE /* unexpected */ EXIT
END /* Case of <how_invoked> */
-----Original Message-----
From: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] On Behalf
Of Robert Zenuk
Sent: Fri 21 Sep 2007 08:27
To: TSO-...@VM.MARIST.EDU
Subject: Re: [TSO-REXX] SIGNAL ON NOVALUE -- Traceback for debugging
Can you post this? It is always interesting seeing how others do this.
Thanks,
Rob
In a message dated 9/21/2007 6:30:22 AM US Mountain Standard Time,
bst...@PROTECHPTS.COM writes:
I am happy to post my production-quality, cross-platform enabled
RXERROR: routine if anyone wants to start using it.
************************************** See what's new at
http://www.aol.com
----------------------------------------------------------------------
What I have posted is the QA test routine that I use to test fixes to
RXERROR. It has a copy of RXERROR in it. This will allow people to play
around with it to see how it works in various situations.
There is DOC in RXERROR itself that explains how to use it.
RXERROR is pasted in by my RXCOPY edit macro, which will surely be the topic
of some other thread. Suffice it to say that I have no problems managing
pieces of internal subroutines pasted into REXX execs anymore.
Someone else asked if the routine can be external. Parts of it cannot, such
as calls to sourceline() and references to variables such as RC. I have an
internal/external pair of error handlers that I use in ooRexx/ObjREXX, where
the external portion is loaded from a requires file, while the internal
version is pasted in by my windows version of RXCOPY. You could do a similar
scheme in TSO/REXX, by passing all of the required bits to an external
routine that did all the formatting. I just never really needed to do that.
Regards,
Bob Stark
ProTech - When you're serious about Systems Management
Consulting, Software, and Training for z/OS, UNIX and Internet
www.protechtraining.com 800-373-9188 x150 412-445-8072
-----Original Message-----
From: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] On Behalf Of
Robert Zenuk
Sent: Friday, September 21, 2007 11:27 AM
To: TSO-...@VM.MARIST.EDU
Subject: Re: SIGNAL ON NOVALUE -- Traceback for debugging
Can you post this? It is always interesting seeing how others do this.
Thanks,
Rob
/* REXX exec to QA test the RXERROR internal error handler routine. */
/* To select conditions to test, change "IF 0 THEN" to "IF 1 THEN" */
/* for the section to be tested. */
TRACE N
IF 0 THEN
DO
Say; Say "This test forces a recoverable ERROR condition"
CALL ON FAILURE NAME RXERROR
ok = 'ALL'
ADDRESS TSO dir foo
Say 'rc='rc
Drop ok
END
IF 0 THEN
DO
Say; Say 'This test should get 12 "panel not found" and die'
CALL ON ERROR NAME RXERROR
ok = '0'
ADDRESS ISPEXEC "CONTROL ERRORS RETURN" /* Capture all ISPF RCs */
ADDRESS ISPEXEC "DISPLAY PANEL(ISR@FOO)"
Drop ok
END
IF 0 THEN
DO
Say; Say 'This test forces a notready condition (file not found)'
SIGNAL ON NOTREADY NAME RXERROR
SAY LINEIN(foo.txt)
END
IF 1 THEN
DO
Say; Say 'This test forces a NOVALUE condition'
rc=42 /* Tests show that obsolete RC is carried over for NOVALUE*/
drop rc
SIGNAL ON NOVALUE NAME RXERROR
x = foo
END
IF 0 THEN
DO
Say; Say 'This test forces a HALT condition'
Say '(press Ctrl-Break or PA1 3270 key to test)'
SIGNAL ON HALT NAME RXERROR
DO FOREVER; i = 1; END
END
IF 0 THEN
DO
Say; Say 'This test forces a SYNTAX condition'
SIGNAL ON SYNTAX NAME RXERROR
/* Interpret is used to keep entire EXEC from failing in ObjREXX. */
INTERPRET "IF 'a' == 'a' THEN a = = 1"
END
/* The following conditions are only valid in Object REXX */
IF 0 THEN
DO
Say 'Force a lostdigits condition, which is new in Object REXX'
/* Interpret is used to hide this statement from OPS/REXX compiler */
Interpret "SIGNAL ON LOSTDIGITS NAME RXERROR"
m = COPIES('9',DIGITS())
n = LEFT(COPIES('123456789',10),DIGITS()+2)
m = m + n
m = m + 1
END
IF 0 THEN
DO
Say "Raise a user condition. This doesn't seem to work at all"
TRACE I
Interpret "SIGNAL ON USER BOGUS NAME RXERROR"
Interpret "RAISE USER BOGUS ARRAY('YOUR', 'PROGRAM', 'BLEW', 'UP')",
"DESCRIPTION('This is the description')"
END
EXIT:
EXIT 0
/*RXCOPY RXERROR NODUP 129 LINES COPIED ON 09-21-07 AT 12:13----------*/
/*START OF RXERROR--------------------------------------Version-01.07-*/
/*:RXERROR SUBROUTINE: Generic REXX error condition handler. This */
/* routine gets control when a condition is raised, and: */
/* a. Validates that the condition is ok, and returns quietly, or */
/* b. Issues diagnostic messages about the error & where it occured. */
/* */
/* To use this routine, code the following near the top of your exec: */
/* Call On Error Name rxError /* Host cmd rc<>0 Error handling */ */
/* Signal On Syntax Name rxError /* REXX syntax error handling */ */
/* Signal On Novalue Name rxError /* Handle Undefined variables */ */
/* */
/* In addition, set the variable 'ok' to any return code values */
/* that are acceptable for host commands. For example: */
/* */
/* ok=4; ADDRESS TSO 'GETVARL GLOBAL_*'; DROP ok */
/* ok='4 8';"host cmd"; DROP ok <-- return codes 4 or 8 are ok */
/* ok='all';"host cmd"; DROP ok <-- all return codes are acceptable */
/* */
/* The first example permits GETVARL to get rc 4 and not fail or */
/* issue any error messages. Note that "ok=0" is always implied */
/* because the REXX ERROR condition is not raised if rc=0. */
/*------------------------------------------------------------------- */
/*NOTES: This subroutine does not use the PROCEDURE instruction, so */
/* variable names used within it must be _hidden. */
/* */
/* If an error occurs that's not one of the 'OK' values, */
/* execution will fall thru this subroutine and any statements */
/* following it will be executed. This is a good place to put */
/* cleanup logic, or a signal to your "cleanup-and-exit" label. */
/* */
/* Variables _RXERRORMSG1 and _RXERRORMSG2 are created when */
/* RXERROR falls thru, and may be used to send error msgs to */
/* other destinations, such as a GUI MSGBOX or ADDRESS AXC WTXC.*/
/* */
/* As a side effect, RXERROR sets ISPF "CONTROL ERRORS RETURN". */
/* If your routine doesn't run this way, you'll need to restore */
/* your ISPF CONTROL ERRORS setting. */
/* Copyright (C) 1996,2007 ProTech. All rights reserved. */
/*--------------------------------------------------------------------*/
rxError: Trace N /* Turn off tracing for this func. */
_sigl = sigl
rxError1: Trace N /* Turn off tracing for this func. */
Call Off Error
Signal Off Syntax
If Symbol('rc') = 'VAR' Then _rc = rc
Else _rc = 'n/a'
Parse Source _ex_env . _ex_name . . . . _ex_addrspc .
If pos(condition('C'),'ERROR FAILURE') > 0 Then /* Error or Failure? */
/* Yes. Were we CALLed? */
If condition('I') = 'CALL' | _ex_env = 'OPS/REXX' THEN
If symbol('OK') = 'VAR' Then /* Yes. Is OK a variable? */
If wordpos(_rc,ok)>0 | translate(ok)='ALL' Then /* Is error ok? */
Do /* Yes, return */
Call On Error Name rxError /* Restore the */
Signal On Syntax Name rxError /* Error handler */
Drop zerrlm /* Toss any ISPF error msg */
rc = _rc /* Restore orig RC for caller */
Return /* Return to point of error */
End
If symbol('_errtext') = 'LIT'
Then _errtext = ''; /* Initialize error text */
If condition('C') = 'SYNTAX' Then /* If a REXX syntax error, */
If _rc >= 0 & _rc < 100 /* and rc is within valid range, */
Then _errtext = ' ('errortext(_rc)')';/* then get REXX error text. */
Else Nop;
Else
If condition('C') = 'NOVALUE' Then /* See if undefined variable */
Do
_errtext = ' (No value for variable 'condition('D')')';
_rc = 'n/a'; /* RC not set for NOVALUE */
End
Else
If pos(condition('C'),'ERROR FAILURE') > 0 Then /*Hostcmd problem?*/
Do /* Extract host cmd name... */
_cmd = strip(strip(word(condition('D'),1),'B','"'),'B',"'")
_errtext = ' (Host command '_cmd')'
_addr = address() /* Find environment of failing cmd */
If _sigl <= sourceline() Then/* Is source code avail? */
If translate(word(sourceline(_sigl),1)) = 'ADDRESS'
Then _addr = translate(word(sourceline(_sigl),2))
_addr = strip(translate(_addr,,'!@#$%&*()_-+=;:,./?"'"'",' '))
If _addr = 'PPQ' & symbol('PPQ.ERROR') = 'VAR'
Then _errtext = ' (Host command PPQ, 'ppq.error')'
If _addr = 'VOX' & symbol('VOX.ERROR') = 'VAR'
Then _errtext = ' (Host command VOX, 'vox.error')'
If _addr = 'ASODDE' | symbol('ASODDE.ERROR') = 'VAR'
Then _errtext = ' (Host command ASODDE, 'asodde.error')'
If symbol('SQLCODE') = 'VAR'
Then _errtext = ' ( SQLCODE=' sqlcode')'
End
Else If condition('C') <> '' Then
_errtext = ' (Condition='condition('C')', Description=',
condition('D')')'
_rxerrormsg1 = "RXERROR Error RC "_rc""_errtext" at line "_sigl,
"in EXEC" _ex_name
If _sigl <= sourceline() /* Is source code avail? */
Then _rxerrormsg2 = "RXERROR Line "_sigl": "STRIP(SOURCELINE(_sigl))
Else _rxerrormsg2 = ""
If _ex_addrspc = 'ISPF' Then /* Running under ISPF? */
Do /* Yes, issue short & long msgs... */
Address ISPEXEC "CONTROL ERRORS RETURN" /* Capture all ISPF RCs */
zedsmsg = '' /* Format ISPF short message */
zedlmsg = "Error RC "_rc""_errtext" at line "_sigl" in EXEC" _ex_name
If _sigl <= sourceline() /* Is source code avail? */
Then zedlmsg = left(zedlmsg': ',78)strip(sourceline(_sigl))
If symbol('ZERRLM') = 'VAR'
Then zedlmsg = left(zedlmsg,156) 'ISPF Error: 'STRIP(ZERRLM)
Address ISPEXEC "SETMSG MSG(ISRZ001)"
If rc = 12 Then /* ISPMLIB MESSAGE found? */
Do /* No, use SAY instead. */
Say 'RXERROR ISPMLIB Message ISRZ001 Not Found'
Signal _SAY_ERRMSG;
End
Signal _say_sqlmsg;
End
_SAY_ERRMSG:
Say _rxerrormsg1; If _rxerrormsg2 <> '' Then Say _rxerrormsg2; Say ''
_SAY_SQLMSG:
If symbol('SQLCODE') = 'VAR' & queued() > 0 Then
IF wordpos(sqlcode,'0 100') = 0 Then
Do _i = 1 BY 1 WHILE queued() > 0
Pull _stack
Say 'SQL STACK:'right(_i,2)':'_stack
End
/*END OF RXERROR------------------------------------------------------*/
/* We have fallen through the bottom of the error handler. This is */
/* where we would normally SIGNAL EXIT */
Parse Upper Version vers .
If pos(vers,'OBJREXX OOREXX') = 0
Then Signal Exit
/* 'A' = additional info from Object REXX - classic REXX stay out! */
SAY "CONDITION('A') = "CONDITION('A')
IF CONDITION('A') <> .nil THEN
DO
SAY "CONDITION('A') information:"
DO _o OVER CONDITION('A')
SAY _o
END
END
/* 'O' = error information object provided by Object REXX */
IF CONDITION('O') <> .nil THEN
DO
SAY "CONDITION('O') information:"
SAY "Condition information:"
DO _o OVER CONDITION('O')
INTERPRET "SAY 'CONDITION(O)~'_o'='CONDITION('O')~"_o
END
END
Interpret "x = CONDITION('O')~TRACEBACK"
IF x <> .nil THEN
DO
SAY
SAY "TRACEBACK Information:"
Interpret "DO _o OVER CONDITION('O')~TRACEBACK; Say _o; End _o"
END
Signal Exit
>SIGNAL ON NOVALUE is a debugging aid. It should never be
>included in a
>productive exec. Once set, it degrades the performance of
>the routine
>and at best helps identify a coding error. A thouroughly
>tested exec can
>never raise a NOVALUE condition.
This reminds me so much of the people who want array
range checking in (Cobol? Pl/1?) programs turned off in
production.
1. In modern processors, performance is not usually a big
issue.
2. It's most often better to get an abend than to get
wrong output that you don't know is wrong. Once the wrong
output *is* noticed, how many days (months, years) worth of
reruns does it take to wipe out whatever minimal
performance gain was saved by not performing a
verification?
--
I cannot receive mail at the address this was sent from.
To reply directly, send to ar23hur "at" intergate "dot" com
Mickey
It's true that blowing up is better than producing bad data that isn't
obviously bad. But it isn't true that an uninitialized and untrapped
variable can do only the former, not the latter; it isn't even very
unlikely.
---
Bob Bridges, rhb...@attglobal.net, cell 336 382-7313
Robert...@westfieldgrp.com, 330 791-6576
/* When you internalize an author whose vision or philosophy is both rich
and out of fashion, you gain a certain immunity from the pressures of the
contemporary....Great literature can help us remain fad-proof. -from
"Reading Old Books" by Joseph Sobran, 1999 */
-----Original Message-----
From: Mickey Bee
Sent: Friday, September 21, 2007 14:01
But a no value condition wouldn't create bad output, it would just blow the
Rexx up, which is a good thing, as it would then force someone code it
correctly.
-------------- Original message ----------------------
From: "Arthur T." <tso...@INTERGATE.COM>
This reminds me so much of the people who want array range checking in
(Cobol? Pl/1?) programs turned off in production.
1. In modern processors, performance is not usually a big issue.
2. It's most often better to get an abend than to get wrong output that you
don't know is wrong. Once the wrong output *is* noticed, how many days
(months, years) worth of reruns does it take to wipe out whatever minimal
performance gain was saved by not performing a verification?
--- robin....@EDS.COM (Ryerse, Robin) wrote 21 Sep 2007 05:15:59 -0700:
SIGNAL ON NOVALUE is a debugging aid. It should never be included in a
productive exec. Once set, it degrades the performance of the routine and
at best helps identify a coding error. A thouroughly tested exec can never
raise a NOVALUE condition.
----------------------------------------------------------------------
>Depends on what you mean. If you're saying "when you test for no-value,
>the condition will cause the program to abend rather than put out bad
>information" then I agree. But that's what Arthur said, and it sounds to
>me like you were trying to disagree with Arthur, so I suspect you meant to
>say "a no-value condition, if you don't trap it, won't produce bad data;
>it'll just blow up, which is a good thing".
>
>It's true that blowing up is better than producing bad data that isn't
>obviously bad. But it isn't true that an uninitialized and untrapped
>variable can do only the former, not the latter; it isn't even very
>unlikely.
But don't we, as programmers, spend most of our time contemplating the 'worst
case scenario'? The 80-20 rule says that we write 20% of our code to handle 80%
of the data, and the other 80% of the code to handle the remaining 20% of the
data.
If a variable has a value I don't know about/expect, oh, pleaseplease let the
routine blow up. It's better that it blows up in test so I can correct it, but
in a pinch I'll accept a blow-up in production at 2am...
(change Arabic number to Roman numeral to email)
Sorry for the late reply, but it's been a busy time for me.
I have to disagree strongly with that statement. Performance IS a big
issue. For large shops with literally thousands of overnight batch jobs,
performance is critical, even on the largest processors in multi-CEC plexes.
The overnight batch window is strained at best and shrinking, and every
ounce and second of performance is needed to make it work at all. When your
program is dealing with millions or more of input transactions, small
improvements are greatly magnified.
It is significantly more efficient to ensure that all table-using programs
check the remaining capacity of their tables at the point in the code where
they add an element, giving a SYSOUT warning message at 80% full and
deliberately abending on table overflow, than it is to turn on
compiler-based bounds checking for all table references.
> 2. It's most often better to get an abend than to get
> wrong output that you don't know is wrong. Once the wrong
> output *is* noticed, how many days (months, years) worth of
> reruns does it take to wipe out whatever minimal
> performance gain was saved by not performing a
> verification?
That I can agree with. Undetected wrong output (i.e., your customer finds
it first) is a Bad Thing (tm).
Peter
This message and any attachments are intended only for the use of the addressee and
may contain information that is privileged and confidential. If the reader of the
message is not the intended recipient or an authorized representative of the
intended recipient, you are hereby notified that any dissemination of this
communication is strictly prohibited. If you have received this communication in
error, please notify us immediately by e-mail and delete the message and any
attachments from your system.
You have a strong point about the shrinking batch
window. But, I disagree about range checking.
One big benefit of automation is that you do
something right, once, and it's hard to screw it up,
thereafter. The compiler and/or library has very
well-tested routines to do range checking. You're asking
me to trust that every single programmer, in every program
that uses tables, will correctly code the check at every
appropriate point. You're also suggesting that all of this
extra coding in a high-level language is more efficient
than the built-in range checking.
It may be that you can prove that last assertion. If
so, I would suggest opening a Share requirement to make
such checking more efficient. When is the last time you
bench-marked it? I'd be interested to know run-time and
CPU-time differences.
But, I think it's counter-productive to ask every
programmer to add code which checks for errors in that same
programmers other code.
I was also perplexed by your phrase, "at the point in
the code where they add an element". Many times tables are
used as random access, so *every* time an element is used,
either for reference or for update, is a possible
"addition" of an element.
--
I cannot receive mail at the address this was sent from.
To reply directly, send to ar23hur "at" intergate "dot" com
----------------------------------------------------------------------
I am, because in my experience read references are far more common than
additions to a table. Coding the check at the (single) paragraph or
procedure where new additions are entered in a given table is thus far more
efficient than all the range-check code added by compilers at EVERY
reference, whether read or write.
Of course, this opinion presupposes enforced coding standards that mandate
such application coding practice.
> It may be that you can prove that last assertion. If
> so, I would suggest opening a Share requirement to make
> such checking more efficient. When is the last time you
> bench-marked it? I'd be interested to know run-time and
> CPU-time differences.
I can't quote actual benchmarks, as I don't have any. My opinion is based
on prior experiences over 35+ years. I do not deny that compiler-generated
bounds-checking code is accurate and well-tested, and may even be somewhat
efficient, but checking EVERY read reference to a table/array in a large
program can add SIGNIFICANT overhead, especially with large volumes of
input.
> But, I think it's counter-productive to ask every
> programmer to add code which checks for errors in that same
> programmers other code.
Not if that coding practice is the shop standard, and is enforced by peer
code reviews. Such standards and reviews are of course even more critical
in this age of outsourced coding.
> I was also perplexed by your phrase, "at the point in
> the code where they add an element". Many times tables are
> used as random access, so *every* time an element is used,
> either for reference or for update, is a possible
> "addition" of an element.
IMHO, not in a properly designed and written program. Additions or updates
to any table should be isolated and separated from the code that references
the table, and performed/called where appropriate.
In addition, coding HLL statements to check table capacity at the point
where entries are added offers the additional benefit of permitting key
information (current record number/key values, status of process, etc.) to
be displayed before forcing an abend on table overflow. This allows
application-specific analysis of WHY a table overflowed and how much (if
any) it needs to be increased to resolve the problem. Sometime unexpected
or undetected erroneous input is the cause rather than a simple lack of
table/array capacity.
Of course, much of what I have said here does not apply as well to REXX
code, where tables (i.e., stems) are created and used very differently than
in 3GL programming languages like COBOL or PL/1.
OTOH, HLL compiler-generated bounds-checking abends may be easier to
intercept with error handler(s) in this age of Language Environment common
substrate under the HLL's, and thus may well be able to provide the
application-specific information to aid debugging a table overflow as well
as application-written bounds-checking can do.
Not having investigated that path, I cannot say if it is possible or not.
Compiler-generated bounds-checking cannot warn you that a table is
approaching it's capacity as your input volume increases. This is a
valuable tool to prevent abends in the first place by giving the application
programmer a chance to increase table capacity proactively.
Peter
This message and any attachments are intended only for the use of the addressee and
may contain information that is privileged and confidential. If the reader of the
message is not the intended recipient or an authorized representative of the
intended recipient, you are hereby notified that any dissemination of this
communication is strictly prohibited. If you have received this communication in
error, please notify us immediately by e-mail and delete the message and any
attachments from your system.
----------------------------------------------------------------------
That having been said, it would have been a VERY cold day in hell when I would have needed an external process to make sure I didn't add a 51st row to an internal table I created with an OCCURS 50 TIMES.
That's what code reviews are for.
Mickey
-------------- Original message ----------------------
From: "Arthur T." <tso...@INTERGATE.COM>
> On 1 Oct 2007 07:19:53 -0700, in bit.listserv.tsorexx
> (Message-ID:<A217F9A4D7684B4DB03E3F76269FDEE21774281C@jsqexpo2>)
> Peter....@BROADRIDGE.COM (Farley, Peter x23353) wrote:
>
> >>-----Original Message-----
> >>From: Arthur T. [mailto:tso...@INTERGATE.COM]
> >>Sent: Friday, September 21, 2007 1:18 PM
> >>To: TSO-...@VM.MARIST.EDU
> >>Subject: Re: [TSO-REXX] SIGNAL ON NOVALUE -- Traceback
> >>for debugging
> ><Snipped>
> >> This reminds me so much of the people who want
> >> array
> >>range checking in (Cobol? Pl/1?) programs turned off in
> >>production.
> >>
> >>1. In modern processors, performance is not usually a
> >>big
> >>issue.
> >
> >Sorry for the late reply, but it's been a busy time for
> >me.
> >
> It may be that you can prove that last assertion. If
> so, I would suggest opening a Share requirement to make
> such checking more efficient. When is the last time you
> bench-marked it? I'd be interested to know run-time and
> CPU-time differences.
>
> But, I think it's counter-productive to ask every
> programmer to add code which checks for errors in that same
> programmers other code.
>
> I was also perplexed by your phrase, "at the point in
> the code where they add an element". Many times tables are
> used as random access, so *every* time an element is used,
> either for reference or for update, is a possible
> "addition" of an element.
>
>
> --
> I cannot receive mail at the address this was sent from.
> To reply directly, send to ar23hur "at" intergate "dot" com
>
If by "external process" you mean compiler-generated bounds-checks, I agree
completely.
Code review by someone besides your own self is a valuable, even critical
human process to improve code quality. Don't install code into production
without it.
Peter
This message and any attachments are intended only for the use of the addressee and
may contain information that is privileged and confidential. If the reader of the
message is not the intended recipient or an authorized representative of the
intended recipient, you are hereby notified that any dissemination of this
communication is strictly prohibited. If you have received this communication in
error, please notify us immediately by e-mail and delete the message and any
attachments from your system.
----------------------------------------------------------------------
> Date: Mon, 1 Oct 2007 12:18:58 -0400
>
> I am, because in my experience read references are far more common than
> additions to a table. Coding the check at the (single) paragraph or
> procedure where new additions are entered in a given table is thus far more
> efficient than all the range-check code added by compilers at EVERY
> reference, whether read or write.
>
But are you saying that the incorrect results in consequence of
an out-of-range fetch reference are more tolerable that the
incorrect results in consequence of an out-of-range store?
-- gil
--
StorageTek
INFORMATION made POWERFUL
----------------------------------------------------------------------
OK, you caught me on that one. No, I really can't say that. Out-of-range
fetch references are certainly at least as (if not more than) capable of
producing undetected incorrect output as out-of-range write references.
BTDT.
HOWEVER, out-of-range fetch references don't corrupt unaffiliated storage,
and sometimes that is MUCH more difficult to debug than an out-of-range
fetch reference. The only (application-mode, non-GTF, non-sysprog-only)
debugging tool I've ever used that supported "watching" a piece of storage
for changes after each instruction executed is TRACE390 from CBT. Many
debug tools can check for a changed value at a breakpoint, but not globally
after each instruction. Tracking down out-of-range write references is much
harder as a consequence.
Compiler-generated range-checks can certainly catch out-of-range fetch
references, but IMHO the performance cost is too high. Especially for
tables/arrays that include packed decimal elements, such references will
frequently lead to S0C7's, or as often as not a S0C4 for fetching from an
unallocated page of storage and thus lead to discovery of the range problem.
At an abend due to a fetch reference, at least the problem solution is
obvious at the point of the abend. An abend or incorrect output because
unaffiliated storage was changed by code far from the usage point of the
unafilliated storage is very hard to track down.
Hence the concentration on eliminating out-of-range write references. The
cost of finding them is more than high enough to justify the cost of
write-reference bounds checks.
I admit, though, that there is probably no application coding practice that
can detect out-of-range fetch references better than compiler-generated
range-checks.
I just don't think the performance cost is worth it. I guess I will have to
run some benchmarks one of these days when the round tuits show up again. I
must also admit I haven't done that in quite a long time, so my "experience"
may be a bit out of step with current capabilities.
Peter
This message and any attachments are intended only for the use of the addressee and
may contain information that is privileged and confidential. If the reader of the
message is not the intended recipient or an authorized representative of the
intended recipient, you are hereby notified that any dissemination of this
communication is strictly prohibited. If you have received this communication in
error, please notify us immediately by e-mail and delete the message and any
attachments from your system.
----------------------------------------------------------------------
I realize you've mostly moved on from the original topic (ahem, and from relevance to this list), but for the record:
SIGNAL ON NOVALUE has *NO* performance cost. The checking is in the uninitialized variable reference code, so it only matters when you've already screwed up. This was well established 20+ years ago, when folks wanted to be able to trace modifications to specific variables, and IBM made it clear why they didn't want to do that (plus the source is available to prove it).
And I can't resist adding, for the folks who say they don't need SIGNAL ON NOVALUE: I'm thrilled that you've solved the bug-free code issue that the rest of the industry hasn't been able to achieve. Maybe you should publish the solution, or at least patent it...
...phsiii
<*Blush*> Sorry for the OT drift, it seemed relevant at the start...
I'm glad to know that SIGNAL ON NOVALUE has no performance cost. The
EXCELLENT code skeletons that were published in this thread will be going
into my REXX toolkit, as I have not solved the bug-free-code problem in my
personal coding life.
Peter
This message and any attachments are intended only for the use of the addressee and
may contain information that is privileged and confidential. If the reader of the
message is not the intended recipient or an authorized representative of the
intended recipient, you are hereby notified that any dissemination of this
communication is strictly prohibited. If you have received this communication in
error, please notify us immediately by e-mail and delete the message and any
attachments from your system.
----------------------------------------------------------------------
I stand by my assertion that SIGNAL ON NOVALUE is a debugging tool.
Raising the SIGNAL ON NOVALUE condition means that you have coded a
variable name incorrectly. That condition can and should be
tested/eliminated before delivery of an application into production.
Failure to perform the testing is a matter of professionalism.
Robin Ryerse
-----Original Message-----
From: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] On Behalf
Of Phil Smith III
Sent: October 2, 2007 8:28 AM
To: TSO-...@VM.MARIST.EDU
> Date: Tue, 2 Oct 2007 09:08:41 -0400
>
> Your sarcasm is irksome.
>
I do perceive a hint of sarcasm there, but I suspect it arises
more from exasperation than from narcissism.
> I stand by my assertion that SIGNAL ON NOVALUE is a debugging tool.
> Raising the SIGNAL ON NOVALUE condition means that you have coded a
> variable name incorrectly. That condition can and should be
> tested/eliminated before delivery of an application into production.
> Failure to perform the testing is a matter of professionalism.
>
Picayunish correction to the Previous Poster: SIGNAL ON NOVALUE does
have a cost: the I/O bandwidth to read the statement, and the CPU
cycles to interpret the statement _once_per_program_.
You didn't say whether you were advocating removing the "debugging tool"
when (you say) it has served its purpose. I suspect that programmers
who remove it do so either because of a misunderstanding of its
miniscule cost or for the bravado of performing without a safety net,
notwithstanding the possibility of unforseen conditions, particularly
uncontrolled modification by less capable successor programmers.
> "Farley, Peter x23353" <Peter....@BROADRIDGE.COM> wrote about COBOL
> bounds checking.
>
> SIGNAL ON NOVALUE has *NO* performance cost. The checking is in the
> uninitialized variable reference code, ...
>
> And I can't resist adding, for the folks who say they don't need SIGNAL
> ON NOVALUE: I'm thrilled that you've solved the bug-free code issue that
> the rest of the industry hasn't been able to achieve. Maybe you should
> publish the solution, or at least patent it...
-- gil
--
StorageTek
INFORMATION made POWERFUL
----------------------------------------------------------------------
From: Ryerse, Robin
Sent: Tue 10/2/2007 9:08 AM
To: TSO-...@VM.MARIST.EDU
Subject: Re: SIGNAL ON NOVALUE -- Traceback for debugging
I stand by my assertion that SIGNAL ON NOVALUE is a debugging tool.
Raising the SIGNAL ON NOVALUE condition means that you have coded a
variable name incorrectly. That condition can and should be
tested/eliminated before delivery of an application into production.
Failure to perform the testing is a matter of professionalism.
----------------------------------------------------------------------
Patent what? Initializing all variables before using them? I believe this is older than I am, and that's saying a bit.
Mickey
I TEST
Mickey
-------------- Original message ----------------------
From: "Ryerse, Robin" <robin....@EDS.COM>
> Your sarcasm is irksome.
>
> I stand by my assertion that SIGNAL ON NOVALUE is a debugging tool.
> Raising the SIGNAL ON NOVALUE condition means that you have coded a
> variable name incorrectly. That condition can and should be
> tested/eliminated before delivery of an application into production.
> Failure to perform the testing is a matter of professionalism.
>
>
> Robin Ryerse
>
>
>
>
> -----Original Message-----
> From: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] On Behalf
> Of Phil Smith III
> Sent: October 2, 2007 8:28 AM
> To: TSO-...@VM.MARIST.EDU
> Subject: Re: SIGNAL ON NOVALUE -- Traceback for debugging
>
> "Farley, Peter x23353" <Peter....@BROADRIDGE.COM> wrote about COBOL
> bounds checking.
>
> I realize you've mostly moved on from the original topic (ahem, and from
> relevance to this list), but for the record:
> SIGNAL ON NOVALUE has *NO* performance cost. The checking is in the
> uninitialized variable reference code, so it only matters when you've
> already screwed up. This was well established 20+ years ago, when folks
> wanted to be able to trace modifications to specific variables, and IBM
> made it clear why they didn't want to do that (plus the source is
> available to prove it).
>
> And I can't resist adding, for the folks who say they don't need SIGNAL
> ON NOVALUE: I'm thrilled that you've solved the bug-free code issue that
> the rest of the industry hasn't been able to achieve. Maybe you should
> publish the solution, or at least patent it...
>
> ...phsiii
or because they never put it in there to begin with?
A novalue condition can ONLY arise from POOR coding. I initialize ALL variables EXCEPT those which are initialized by an external process, such as " X = SYSDSN(mydsn)", where X will ALWAYS have a value, unless TSO has died, in which case any issues with my Rexx will be of minor concern.
Mickey
While this MAY be true, it isn't really relevant here. We aren't talking about trapping FAILURE or SYNTAX, but rather, NOVALUE, which can ONLY arise due to VERY poor coding standards. It has NEVER happened to me, and I suspect I have written ore Rexx code than any 3 people here combined. It is what I do, it is ALL that I do, and it has been for over 15 years now. In all that time, I have never had a program fail due to a novalue condition. That isn't a miracle, or a sign of brilliance, but rather just a sign of good training and dilligence.
Mickey
>
>
>
> From: Ryerse, Robin
> Sent: Tue 10/2/2007 9:08 AM
> To: TSO-...@VM.MARIST.EDU
> Subject: Re: SIGNAL ON NOVALUE -- Traceback for debugging
>
>
> I stand by my assertion that SIGNAL ON NOVALUE is a debugging tool.
> Raising the SIGNAL ON NOVALUE condition means that you have coded a
> variable name incorrectly. That condition can and should be
> tested/eliminated before delivery of an application into production.
> Failure to perform the testing is a matter of professionalism.
>
-----Original Message-----
From: Mickey Bee
Sent: Tuesday, October 02, 2007 3:17 PM
To: TSO-...@VM.MARIST.EDU
Subject: Re: SIGNAL ON NOVALUE -- Traceback for debugging
A novalue condition can ONLY arise from POOR coding.
----------------------------------------------------------------------
Having spent most of the past three decades in software QA, I believe
that such situations are rare.
Many companies place a higher premium on meeting deadlines than
squeezing out the last bug. I have waged
extended campaigns to remove a defect which program management just
wanted to let out the door, only to be labelled as uncooperative.
Anything a programmer can do to guard against the unexpected (NOVALUE in
REXX, SUBSCRIPTRANGE in PL/I, etc) has the potential to prevent bad
output from being delivered to clients. There are any number of reasons
in addition to a coding defect (w/r/t the initial design) which can
cause trouble: invalid data slipping past other programs,
misunderstanding of the program by others, situations which the
requirements don't cover, etc. Those things with small probabilities
only tend to occur in large volumes of (e.g. production) data.
I believe it is prudent to allow for our own fallibility as well as the
unexpected in production situations (in addition to business constraints
on the testing effort). So I support the small cost of additional
checking during execution.
P.S. If anyone tells you its too costly to check during production, ask
them about the cost of delivering bad product!
-----Original Message-----
From: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] On Behalf
Of Mickey Bee
Sent: Tue 02 Oct 2007 12:14
To: TSO-...@VM.MARIST.EDU
Subject: Re: [TSO-REXX] SIGNAL ON NOVALUE -- Traceback for debugging
Amen. I have never used it, and I have also never had an issue where
using it would have done an iota of good. I test, I test, I test some
more, I re-test, and then, just to make sure....
I TEST
Mickey
-------------- Original message ----------------------
From: "Ryerse, Robin" <robin....@EDS.COM>
> Your sarcasm is irksome.
>
> I stand by my assertion that SIGNAL ON NOVALUE is a debugging tool.
> Raising the SIGNAL ON NOVALUE condition means that you have coded a
> variable name incorrectly. That condition can and should be
> tested/eliminated before delivery of an application into production.
> Failure to perform the testing is a matter of professionalism.
>
>
> Robin Ryerse
>
>
>
>
> -----Original Message-----
> From: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] On
> Behalf Of Phil Smith III
> Sent: October 2, 2007 8:28 AM
> To: TSO-...@VM.MARIST.EDU
> Subject: Re: SIGNAL ON NOVALUE -- Traceback for debugging
>
> "Farley, Peter x23353" <Peter....@BROADRIDGE.COM> wrote about COBOL
> bounds checking.
>
> I realize you've mostly moved on from the original topic (ahem, and
> from relevance to this list), but for the record: SIGNAL ON NOVALUE
> has *NO* performance cost. The checking is in the uninitialized
> variable reference code, so it only matters when you've already
> screwed up. This was well established 20+ years ago, when folks
> wanted to be able to trace modifications to specific variables, and
> IBM made it clear why they didn't want to do that (plus the source is
> available to prove it).
>
> And I can't resist adding, for the folks who say they don't need
> SIGNAL ON NOVALUE: I'm thrilled that you've solved the bug-free code
> issue that the rest of the industry hasn't been able to achieve.
> Maybe you should publish the solution, or at least patent it...
>
> ...phsiii
>
TSO REXX Discussion List <TSO-...@VM.MARIST.EDU> wrote on 10/02/2007
02:21:12 PM:
> -------------- Original message ----------------------
> From: "Vitonis, Anthony J" <Anthony...@CA.COM>
> > Every single programmer and tester is fallible, and should be
> humble enough to
> > acknowledge that errors may slip into production regardless of how
> thorough his
> > testing suite is, or of how "professionally" he behaves. To
> believe otherwise
> > is to be a slave to some unobtainable ideal.
>
> While this MAY be true, it isn't really relevant here. We aren't
> talking about trapping FAILURE or SYNTAX, but rather, NOVALUE, which
> can ONLY arise due to VERY poor coding standards. It has NEVER
> happened to me, and I suspect I have written ore Rexx code than any
> 3 people here combined. It is what I do, it is ALL that I do, and it
> has been for over 15 years now. In all that time, I have never had a
> program fail due to a novalue condition. That isn't a miracle, or a
> sign of brilliance, but rather just a sign of good training and
dilligence.
imareallygoodtypist = ('0' = '0')
say imaraellygoodtypist
Oops! Maybe SIGNAL ON NOVALUE owuld have been helpful here.
Mark L. Wheeler, 3M Company
“Extraordinary claims require extraordinary evidence." Carl Sagan
>
> Mickey
This issue also arises when abbreviations are used. If the original
coder used "stud_name" and I've also been working on a program where
that coder used "stdt_name", I might get confused and use the wrong one.
SIGNAL ON NOVALUE would help in these situations.
-----Original Message-----
From: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] On Behalf
Of Mark Wheeler
Sent: Tue 02 Oct 2007 13:25
To: TSO-...@VM.MARIST.EDU
Subject: Re: [TSO-REXX] SIGNAL ON NOVALUE -- Traceback for debugging
>
> Mickey
----------------------------------------------------------------------
While this MAY be true, it isn't really relevant here. We aren't talking
about trapping FAILURE or SYNTAX, but rather, NOVALUE, which can ONLY arise
due to VERY poor coding standards. It has NEVER happened to me, and I
suspect I have written ore Rexx code than any 3 people here combined. It is
what I do, it is ALL that I do, and it has been for over 15 years now. In
all that time, I have never had a program fail due to a novalue condition.
That isn't a miracle, or a sign of brilliance, but rather just a sign of
good training and dilligence.
Mickey
I wouldn't a farthing on that 'any three people' if I were you, I've been
writing Rexx since 1983 and I'm not the oldest far.. I mean fellow on here.
However, I'm with you on the NOVALUE thing; I can't recall ever falling over
it. Other coding inanities? Well, how much time have you got?
The Royal Bank of Scotland plc, Registered in Scotland No. 90312. Registered Office: 36 St Andrew Square, Edinburgh EH2 2YB
Authorised and regulated by the Financial Services Authority.
This e-mail message is confidential and for use by the addressee only. If the message is received by anyone other than the addressee, please return the message to the sender by replying to it and then delete the message from your computer. Internet e-mails are not necessarily secure. The Royal Bank of Scotland plc does not accept responsibility for changes made to this message after it was sent.
Whilst all reasonable care has been taken to avoid the transmission of viruses, it is the responsibility of the recipient to ensure that the onward transmission, opening or use of this message and any attachments will not adversely affect its systems or data. No responsibility is accepted by The Royal Bank of Scotland plc in this regard and the recipient should carry out such virus and other checks as it considers appropriate.
Wal-Mart
Ford
G.E.
G.M.
IBM
IRS
VISA
Southern Company
AT&T
Verizon
Blue Cross
I could go on, but why bother? I test what needs to be tested, and I account for the rest. How much testing do I need to make sure I have no un-initialized variables?
Mickey
> Sent: Tue 02 Oct 2007 12:14
> To: TSO-...@VM.MARIST.EDU
> Subject: Re: [TSO-REXX] SIGNAL ON NOVALUE -- Traceback for debugging
>
>
> Amen. I have never used it, and I have also never had an issue where
> using it would have done an iota of good. I test, I test, I test some
> more, I re-test, and then, just to make sure....
>
> I TEST
>
> Mickey
>
So would testing... and CNTL-C/CNTL-V would also prevent these issues.
Mickey
>
> -----Original Message-----
> From: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] On Behalf
> Of Mark Wheeler
> Sent: Tue 02 Oct 2007 13:25
> To: TSO-...@VM.MARIST.EDU
> Subject: Re: [TSO-REXX] SIGNAL ON NOVALUE -- Traceback for debugging
>
>
>
>
>
> TSO REXX Discussion List <TSO-...@VM.MARIST.EDU> wrote on 10/02/2007
> 02:21:12 PM:
>
> > -------------- Original message ----------------------
> > From: "Vitonis, Anthony J" <Anthony...@CA.COM>
> > > Every single programmer and tester is fallible, and should be
> > humble enough to
> > > acknowledge that errors may slip into production regardless of how
> > thorough his
> > > testing suite is, or of how "professionally" he behaves. To
> > believe otherwise
> > > is to be a slave to some unobtainable ideal.
> >
> > While this MAY be true, it isn't really relevant here. We aren't
> > talking about trapping FAILURE or SYNTAX, but rather, NOVALUE, which
> > can ONLY arise due to VERY poor coding standards. It has NEVER
> > happened to me, and I suspect I have written ore Rexx code than any 3
> > people here combined. It is what I do, it is ALL that I do, and it has
>
> > been for over 15 years now. In all that time, I have never had a
> > program fail due to a novalue condition. That isn't a miracle, or a
> > sign of brilliance, but rather just a sign of good training and
> dilligence.
>
> imareallygoodtypist = ('0' = '0')
> say imaraellygoodtypist
>
> Oops! Maybe SIGNAL ON NOVALUE owuld have been helpful here.
>
> Mark L. Wheeler, 3M Company
>
> "Extraordinary claims require extraordinary evidence." Carl Sagan
>
> >
> > Mickey
>
Of course it has never happened to you, if you don't trap the error, REXX
defaults the value. REXX will never raise a NOVALUE error by itself. And
if you think that a NOVALUE condition can only arise from poor programming
practices, you haven't been the real world. I am another person who has
been programming in REXX longer than you and I program real products for
real customers. No matter how much you test your program, you find
customers that use your product in ways you never dreamed of. It's these
uses that bring out the bugs in your "perfect" code that you never dreamed
would happen and thus never dreamed of testing.
The problem is that if you don't trap NOVALUE conditions, REXX merely
defaults the value and your program continues on it's merry way. If you
lucky, a real failure of your program may result subsequent to the NOVALUE
condition. If you not so lucky, incorrect results may be generated that
might not be detected for a long time.
My point is that a NOVALUE condition can be brought on by external data.
That data may be anything. In order to avoid errors in your program, you
have to test thoroughly for every possibility. Once you start doing that,
performance characteristics suffer dramatically.
My approach has always been do reasonable validation of the input and then
capture and display needed and useful information in the condition trapping
exit, including NOVALUE.
It's like saying "I'm too good of a driver to ever get in a car accident, so
why wear seatbelts."
Thanks,
John Bodoh
Senior Designer
John_...@infrawise.com
919-460-4721
The infraWise/IRC Group of Companies
3500 Regency Parkway
Cary, North Carolina, USA
NC 27518
www.infraWise.com
>
> While this MAY be true, it isn't really relevant here. We aren't talking
> about trapping FAILURE or SYNTAX, but rather, NOVALUE, which can ONLY
> arise due to VERY poor coding standards. It has NEVER happened to me, and
> I suspect I have written ore Rexx code than any 3 people here combined. It
> is what I do, it is ALL that I do, and it has been for over 15 years now.
> In all that time, I have never had a program fail due to a novalue
> condition. That isn't a miracle, or a sign of brilliance, but rather just
> a sign of good training and dilligence.
>
> Mickey
>
----------------------------------------------------------------------
Touche. True. Though the total time spent reading/parsing all the SIGNAL ON NOVALUEs ever written is probably less than what we've spent on this thread ;-)
Of course you test, test, and retest your code, but we know that's still imperfect: you cannot test every condition in every code path. And that means typos may lurk (not to mention logic errors). For those who claim their code has never failed due to an uninitialized variable: I've never used my house insurance, either, but I still pay the premiums...it's cheaper than taking the risk. I guess I don't understand the objection to a(n almost) cost-free safety net.
So yes, Paul, I leave the SIGNAL ON NOVALUE in the code when it goes production. And it never gets triggered (at least, not yet), including servers that process 250,000 pieces of email per day, servers that provision and manage Linux virtual machines, my own utilities, and a few million other lines of code. But I sleep better at night knowing it's there.
...phsiii
WHAT?????
This may come close to qualifying as the WORST analogy I have ever heard. Nothing you can do can prevent someone ELSE from hitting you. However, un-assigned variables, those I most certainly CAN and DO control. Furthermore, you assertion that an error trap for data coming from external sources is BETTER than actually checking the validity of that data is about as bad a concept as I have heard in the last 20 years. I won't even begin to address your claim of having coded Rexx longer than I, as it is quite absurd. And as to your statement about your having coded "real" products for "real" customers, exactly what Rexx code do you think I have been coding for the last 25+ years?
Mickey
Now this is the ONLY good reason I have heard so far. Sleep is nice, I do it for at least 12-15 hours a week :)
But as you said, you have never actually trapped an error with it, meaning that you code and test the way I code and test :))))
...
> > So yes, Paul, I leave the SIGNAL ON NOVALUE in the code
> when it goes production.
> > And it never gets triggered (at least, not yet), including
> servers that process
> > 250,000 pieces of email per day, servers that provision and
> manage Linux virtual
> > machines, my own utilities, and a few million other lines
> of code. But I sleep
> > better at night knowing it's there.
>
> Now this is the ONLY good reason I have heard so far. Sleep
> is nice, I do it for at least 12-15 hours a week :)
>
> But as you said, you have never actually trapped an error
> with it, meaning that you code and test the way I code and test :))))
>
> Mickey
You can never prove (or in practice presume) that a program is error free
by testing it.
I thought that this was an established fact since around 1940.
Thomas
_____________________________________________________________
Thomas Berg Specialist IT Utveckling Swedbank AB (Publ)
Some think we might be getting close to 'integrating' the human brain
with the mechanical. Who would ever have conceived of someone sailing a
ship at 28 knots through a field of fog shrouded icebergs and no one
would ever have suggested a test of it. On the inside of a door from a
test lab was the sign "Don't worry; our customers will do the Final
Test."
bobh
Original msg from Thomas:
Sorry if I ruffled your feathers. But I take offense at someone accusing me
of bad programming practices because I happen to code for the unlikely
possibility of a NOVALUE condition. I personally think it is extremely poor
programming practice NOT to code for that possibility.
When you write a program that is supposed to process many millions of
records from a database, each having hundreds of fields, and run within
specific time limits, you pay very close attention to which instructions are
necessary and which are not. Of these millions of records there may be less
than one one-hundredth of a percent that one of the hundreds of fields has
invalid data. I think it is very inefficient to have mainline code that
wastes precious time doing data validation that is only necessary a tiny
fraction of the time. I believe that is far better, when considering
performance, to handle these extremely rare error conditions asynchronously.
For example, the rule might be that an input field is supposed to be
numeric. You could waste time validating that the field is number for the
millions of records being processed or you could presume it to be numeric
and an error occurs because when you try to use the field in an arithmetic
operation, a signal on exit puts out a message saying the field is not
numeric for the record. Maybe I'm missing something, but my methods have
always worked for me and those who have reviewed my code (remember code
inspections) approve of my designs.
You may be happy with the way you code and I am happy with the way I code
and we may never agree. But, I cannot idly let personal attacks go
unchallenged.
Thanks,
Be Wise with iWiseT
John Bodoh
Senior Designer
John_...@infrawise.com
919-460-4721
The infraWise/IRC Group of Companies
3500 Regency Parkway
Cary, North Carolina, USA
NC 27518
www.infraWise.com
> -----Original Message-----
> From: Mickey Bee [mailto:mic...@COMCAST.NET]
> Sent: Wednesday, October 03, 2007 8:52 AM
> To: TSO-...@VM.MARIST.EDU
Example:
I have a machine that FLAWLESSLY produces ping pong balls. Now, I test 1,000,000 of these ping pong balls by dropping them from a height of 36 inches, and each and every one bounces back 22 inches. Now, should I test the 1,000,0001st ping pong ball? Why certainly, as the gravitational co-efficient of the universe may have altered between ping pong balls. But I will not code for such eventualities, as their number is legion, and I would spend my life coding to trap errors that are so obscure as to be irrelevant.
Second example:
My current location has a process, part Rexx, part assembler that check JCL (like JOBSCAN or !JCK). Today, it blew up with an 878 (getmain failure). It turns out that the person who got this error was checking a jobstream he generated from a program which was 47,000+ lines long and contained HUNDREDS of JOB cards, and his TSO session ran out of storage. Now, could I trap this error? Sure, I could write hooks to determine his region size at logon and check storage available every few lines read in. Will I? Not on a bet, for 2 reasons. The first is that I will not force everyone to wait while these checks take place to accomodate one idiot. Secondly, I INTENTIONALLY do not trap the kinds of errors that occur due to an idiot behind the keyboard. I refuse to do so, as it is MY OPINION that this serves only to encourage the hiring of more idiots and the powers that be have seen fit to provide us with more than enough idiots as it is.
Just my 3 cents worth (adjusted for inflation), and YMMV.
Mickey
I am writing a program to parse a series of
segments from a single string. To prevent parsing
problems due to possible binary values in the string,
I am working with it in hex representation (i.e., c2x)
Each segment is preceded by a 2 byte RDW, which becomes
four bytes in hex representation (4 hex nybbles).
Therefore, I wrote this to parse my record one segment at a time:
parse var xrecord xlen +4 xsegment +(x2d(xlen)*2-4) xrecord
I was surprised to see this statement raise a novalue error.
The Rexx doc clearly states you may use a variable
in a relative positional pattern, and that variable may be
set earlier in the parse statement.
Apparently, however, expressions are not allowed in
relative positional parsing. 'Trace i' was no help in
figuring this out because it does not trace the "evaluation"
of the relative positional value. I only figured it out by
trial and error, eventually getting a syntax error with a
simpler expression inside the parentheses. So why do I get
a novalue error instead of a syntax error with my original
statement (above)?
I have my code working now by breaking my single parse into 3
statements:
parse var xrecord xlen +4 .
len = x2d(xlen) * 2 /* convert RDW to x-string length */
parse var xrecord xsegment +(len) xrecord
This may be easier to follow when I look at it again
in a few months. But it's not as elegant - parsing
the same (long) xrecord twice offends me. Any comments or
suggestions?
Thanks in advance,
Mark Vitale
Product Manager, PerfMan for DB2, CICS TS, and Tape Libraries
Telephone 610.865.0300 (ext. 138)
ISM - The power behind great IT decisions
Visit us at www.perfman.com
Your second example sounds like you agree with me. That is, don't waste
time checking for the rare idiot behind the keyboard. As long as the rare
idiot bug is caught somewhere, don't check it explicitly. That's why I use
NOVALUE checking. It's the idiot behind the keyboard that may cause a
variable not to be set. Without a NOVALUE check, the error caused by the
idiot might never be detected. And if you can't expose the idiots, they
will continue to pollute the gene pool.
Your first example doesn't seem relevant.
Thanks,
Be Wise with iWiseT
John Bodoh
Senior Designer
John_...@infrawise.com
919-460-4721
The infraWise/IRC Group of Companies
3500 Regency Parkway
Cary, North Carolina, USA
NC 27518
www.infraWise.com
> -----Original Message-----
> From: Mickey Bee [mailto:mic...@COMCAST.NET]
> Sent: Wednesday, October 03, 2007 9:48 AM
> To: TSO-...@VM.MARIST.EDU
> Subject: Re: SIGNAL ON NOVALUE -- Traceback for debugging
>
The first example was a symbolic. There are some issues you CAN trap, but really shouldn't waste your time coding for (such as a change in the gavitational constant of the universe). As to issues raised by an IBK, I check incoming data to ensure valid values, and as such avoid ever rasing a novalue condition. I do use SIGNAL SYNTAX and SIGNAL FAILURE, as I find those MUCH more likely. For example, I am parsing a dataset/member name combo, and code DSN = SubStr(Dataset,1,POS('(',Dataset)-1). This will fail if the IBK suuplied the dataset but no member name. Now, I could code it as:
XP = POS('(',Dataset)
If XP > 0 Then
DSN = SubStr(Dataset,1,XP-1)
Else
Say "You pinhead, I need a member to process"
This would avoid the issue, but should I forget, I make sure I trap it.
Robin Ryerse
-----Original Message-----
From: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] On Behalf
I agree somewhat. However, I mostly code in ooREXX. And it's not like I
"code" for anything. Usually, I code SIGNAL ON ANY NAME TRAP at the
beginning of a program and somewhere near the bottom of the program I code
either:
RAISE PROPAGATE DESCRIPION(error_handler(CONDITION("O"),me,sigl));
if it's a subroutine or:
SAY error_handler(CONDITION("O"),me,sigl);
if it's a main program.
The handling of the error is in a separate function so it is done once.
All new program I code use a skeleton which has these two lines it it
anyway. So, most of the time I really don't do any extra coding to handle
errors. As you may probably guess, the common error handler merely gathers
generic information about the error. In some cases, I need perform special
processing. For example, I have a special error handler for when I am
actually processing external database records. If an error occurs while
processing a record, I gather and display record information, skip the
record, and continue with the next record.
So, I guess my point is that the common error handler was originally coded
to handle NOVALUE conditions. For me, to not code for NOVALUE would require
me to remove code that already exists. In my day-to-day programming, I
mostly don't specifically code for any errors, it's already there.
> -----Original Message-----
> From: TSO REXX Discussion List
> [mailto:TSO-...@VM.MARIST.EDU] On Behalf Of Ryerse, Robin
> Sent: Wednesday, October 03, 2007 11:13 AM
> To: TSO-...@VM.MARIST.EDU
> Subject: Re: relative positional parsing question
>
> You can accomplish what you want with one parse
> parse var xrecord xlen 5 xsegment
> +(c2d(left(xrecord,4)-4) xrecord This works because all
> operative variables in the parse statement have an
> established value before the parse is executed.
"This works because... before the parse is executed."
But according to The Rexx Language (Cowlishaw), a variable
in a relative positional pattern does NOT need to be
established BEFORE the parse is executed - it can be assigned
a value (by parsing) earlier in the same parse statement.
So I still don't understand why your parse works but mine
gets a novalue error.
> Note that I
> have difficulty interpretting what you mean by RDW. You say
> it is 2 bytes (4
> nibbles) yet your parse steps over it with +4.
I step over it with +4 because the RDW is two bytes (e.g. x'0050')
in the original string but four bytes (e.g. '0050') in the converted
(c2x) string I'm parsing.
> I suspect RDW
> is 4 bytes of which the high order 2 byes are insignificant.
> Using RDW as a fullword, "x2d" must be changed to "c2d". I
> also don't understand the multiplication by 2. If RDW is the
> length of the segment, why multiply it by 2?
Because I'm not working with the original hex, but with a converted
string (c2x).
-Mark
ooRexx is an area I am as of yet, mostly unfamilliar with. However, I can understand that the PC environment in and of itself leaves many more holes through which an error might enter a process. I suspect that were I to take up coding Rexx on a PC, I also might be more likely to use NOVALUE. My Rexx coding is almost 100% MVS (still refuse to call it z/OS) based, so the number of possible permutations is far more limited.
Mickey
-------------- Original message ----------------------
From: John R bodoh <john_...@INFRAWISE.COM>
> Mickey,
>
> > Sent: Wednesday, October 03, 2007 10:52 AM
> > To: TSO-...@VM.MARIST.EDU
> > > > Sent: Wednesday, October 03, 2007 9:48 AM
> > > > To: TSO-...@VM.MARIST.EDU
> > > > > > Sent: Wednesday, October 03, 2007 8:52 AM
> > > > > > To: TSO-...@VM.MARIST.EDU
> > > > > > For TSO-REXX subscribe / signoff / archive access instructions,
> > > > > > send email to LIST...@VM.MARIST.EDU with the message: INFO TSO-
> > REXX
> > > > >
> > > > > --------------------------------------------------------------------
> Date: Wed, 3 Oct 2007 09:01:53 -0500
>
> I am writing a program to parse a series of
> segments from a single string. To prevent parsing
> problems due to possible binary values in the string,
> I am working with it in hex representation (i.e., c2x)
>
Actually, Rexx is blessedly free of problems due to binary values in
strings, in contrast to (Yuccccch!) the "C" Standard Library. I'm
quite comfortable working with raw binary strings and using c2d()
when I need to realize a numeric field. I suppose an exception is
that when I have tracing on it's easier to understand values logged
in hex than raw binary.
-- gil
--
StorageTek
INFORMATION made POWERFUL
Hence I, too, always pass binary values in hex format. E.g.
CALL ExtCmd c2x(binfield)
Rather than
CALL ExtCmd binfield
-----Original Message-----
From: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] On Behalf
Of Paul Gilmartin
Sent: Wed 03 Oct 2007 09:38
To: TSO-...@VM.MARIST.EDU
parse value x2d(substr(xrecord,1,2)-4 substr(xrecord,4) with xlen
xsegment +(xlen) xrecord
Thanks,
Be Wise with iWiseT
John Bodoh
Senior Designer
John_...@infrawise.com
919-460-4721
The infraWise/IRC Group of Companies
3500 Regency Parkway
Cary, North Carolina, USA
NC 27518
www.infraWise.com
> -----Original Message-----
> From: Mark Vitale [mailto:mark....@PERFMAN.COM]
> Sent: Wednesday, October 03, 2007 10:02 AM
> To: TSO-...@VM.MARIST.EDU
> Subject: relative positional parsing question
>
Note that his *relative* position of +4 is equivalent to your *absolute*
position of 5 (because the starting position of 1, once the relative
advance of +4 is added, yields 5)
The multiplication by 2 is necessary because the length of the string
(as stored in xlen) is in bytes, whereas the parse is of hex digits
("nibbles") and there are two nibbles for every byte.
-----Original Message-----
From: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] On Behalf
Of Ryerse, Robin
Sent: Wed 03 Oct 2007 08:13
To: TSO-...@VM.MARIST.EDU
Subject: Re: [TSO-REXX] relative positional parsing question
You can accomplish what you want with one parse
parse var xrecord xlen 5 xsegment +(c2d(left(xrecord,4)-4)
xrecord This works because all operative variables in the parse
statement have an established value before the parse is executed. Note
that I have difficulty interpretting what you mean by RDW. You say it is
2 bytes (4
nibbles) yet your parse steps over it with +4. I suspect RDW is 4 bytes
of which the high order 2 byes are insignificant. Using RDW as a
fullword, "x2d" must be changed to "c2d". I also don't understand the
multiplication by 2. If RDW is the length of the segment, why multiply
it by 2?
Robin Ryerse
-----Original Message-----
From: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] On Behalf
> Date: Wed, 3 Oct 2007 09:46:10 -0700
>
> Binary values as arguments to external functions can be troublesome,
> because they are processed by the operating system. I have encountered
> problems where escape and line-end characters in binary parameters have
> caused trouble (although this was not on the MVS/TSO platform, I wonder
> what would happen if '15'X is part of the string).
>
But please distinguish between calls to external Rexx functions where
no such problems occur, and commands ADDRESSed to a commmand processing
subsystem, where such problems are likely.
> Hence I, too, always pass binary values in hex format. E.g.
>
> CALL ExtCmd c2x(binfield)
>
> Rather than
>
> CALL ExtCmd binfield
>
Either ought to be safe; the hazard is with:
address TSO CALL ExtCmd binfield.
(BTW, I'd need to do:
address TSO 'CALL' ExtCmd binfield.
.. because I always have SIGNAL ON NOVALUE in effect. But that's a
different thread.)
Example:
READY
rexx trace R; call c2x "hello"'0001150203'x; say result
1 *-* call c2x "hello"'0001150203'x
>>> "hello?????"
>>> "88859393960001150203"
*-* say result
>>> "88859393960001150203"
88859393960001150203
READY
Sorry about the confusion :-(
-----Original Message-----
From: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] On Behalf
Of Paul Gilmartin
Sent: Wed 03 Oct 2007 10:19
To: TSO-...@VM.MARIST.EDU
Subject: Re: [TSO-REXX] relative positional parsing question
> Date: Wed, 3 Oct 2007 10:21:23 -0700
>
> You're absolutely correct. My examples were wrong. They should have
> omitted the "CALL":
> "ExtCmd" c2x(binfield)
>
> Sorry about the confusion :-(
>
No need for "Sorry"; the confusion is built in to Rexx. Consider:
call ExtCmd c2x(binfield)
.. which is a call to a Rexx function named ExtCmd, versus:
"call" ExtCmd c2x(binfield)
.. which is a command whose name is the value of the variable ExtCmd,
ADDRESSed to something, presumably in context of this list, TSO. One
place where the Astonishment Factor sneaked past MFC. I had to test my
first form to reassure myself I had it right.
Funny this, as I was about to say Address 'TSO'.
I always put the ENV portion of the address in aposts, just in case someone shows up later on and creates a variable called ISPEXEC :)
Mickey
Which proves that if you build a better mousetrap, you end up breeding smarter rats.
The pattern "+(x2d(xlen)*2-4)" looks good at first, but is actually
invalid. The REXX manual states:
A relative positional pattern is a number with a plus (+) or minus
(-) sign preceding it. It can also be
a variable within parentheses, with a plus (+) or minus (-) sign
preceding the left parenthesis; ...
Note that only a single variable is permitted, *not* an expression.
Your approach would work if the length was in decimal format (assuming
you simplified the expression down to just the variable containing the
length prefix).
Hope that helps!
-----Original Message-----
From: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] On Behalf
Dear Rexx-perts,
Thanks in advance,
----------------------------------------------------------------------
I figured expressions were invalid, as I said in my OP.
But other responders have also volunteered examples of
relative positions containing expressions, so
I'm not the only one who is confused. However, what I
really found confusing was the error raised was
NOVALUE rather than SYNTAX. No one has addressed
that point yet.
-Mark Vitale
> -----Original Message-----
> From: TSO REXX Discussion List
> [mailto:TSO-...@VM.MARIST.EDU] On Behalf Of Cruz, Robert
> Sent: Wednesday, October 03, 2007 4:43 PM
> To: TSO-...@VM.MARIST.EDU
> Subject: Re: relative positional parsing question
>
> The problem here is a misunderstanding of what REXX allows
> for a relative position in a template.
>
> The pattern "+(x2d(xlen)*2-4)" looks good at first, but is
> actually invalid. The REXX manual states:
>
> A relative positional pattern is a number with a plus (+) or minus
> (-) sign preceding it. It can also be
> a variable within parentheses, with a plus (+) or minus
> (-) sign preceding the left parenthesis; ...
>
> Note that only a single variable is permitted, *not* an expression.
> Your approach would work if the length was in decimal format
> (assuming you simplified the expression down to just the
> variable containing the length prefix).
>
> Hope that helps!
----------------------------------------------------------------------
bobh
IRX0046I Error running REXXTRY, line 2: Invalid variable reference
Other implementations may give:
... Error ... Running ..., line nn: Invalid template or pattern
-----Original Message-----
From: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] On Behalf
Of Mark Vitale
Sent: Wed 03 Oct 2007 13:53
To: TSO-...@VM.MARIST.EDU
> Date: Wed, 3 Oct 2007 15:53:12 -0500
>
> I'm not the only one who is confused. However, what I
> really found confusing was the error raised was
> NOVALUE rather than SYNTAX. No one has addressed
> that point yet.
>
Let me try: does this give you any insight?:
rexx "signal on novalue; say +(x2d)"
1 +++ /* REXX Useful! */ interpret arg(1)
+++ "NOVALUE"
IRX0016I Error running /mvsoeecc/sppg/bin/rexx, line 1: Label not found
SPPG@LSTC3MVS:129$
It tells me what I already pretty well suspected: Rexx's parser
is ad-hoc and somewhat chaotic.
> > -----Original Message-----
> > From: TSO REXX Discussion List
> > [mailto:TSO-...@VM.MARIST.EDU] On Behalf Of Cruz, Robert
> > Sent: Wednesday, October 03, 2007 4:43 PM
> >
> > The pattern "+(x2d(xlen)*2-4)" looks good at first, but is
> > actually invalid. The REXX manual states:
> >
> > A relative positional pattern is a number with a plus (+) or minus
> > (-) sign preceding it. It can also be
> > a variable within parentheses, with a plus (+) or minus
> > (-) sign preceding the left parenthesis; ...
> >
> > Note that only a single variable is permitted, *not* an expression.
-- gil
--
StorageTek
INFORMATION made POWERFUL
----------------------------------------------------------------------
-----Original Message-----
From: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] On Behalf
Of Paul Gilmartin
Sent: Wed 03 Oct 2007 14:08
To: TSO-...@VM.MARIST.EDU
Subject: Re: [TSO-REXX] relative positional parsing question
---
Bob Bridges, rhb...@attglobal.net, cell 336 382-7313
Robert...@westfieldgrp.com, 330 791-6576
/* The liar's punishment is not in the least that he is not believed, but
that he cannot believe anyone else. -George Bernard Shaw */
-----Original Message-----
From: Cruz, Robert
Sent: Wednesday, October 3, 2007 16:43
The problem here is a misunderstanding of what REXX allows for a relative
position in a template. The pattern "+(x2d(xlen)*2-4)" looks good at
first, but is actually invalid. The REXX manual states "A relative
positional pattern is a number with a plus (+) or minus (-) sign preceding
it. It can also be a variable within parentheses, with a plus (+) or minus
(-) sign preceding the left parenthesis...."
Note that only a single variable is permitted, *not* an expression.
Your approach would work if the length was in decimal format (assuming
you simplified the expression down to just the variable containing the
length prefix).
----------------------------------------------------------------------
Mark, I ran into the same problem a few years ago and came to the same
conclusion. I've never had any reason since then to change my mind, but if
we can get one of these guys to notice the question maybe they'll
straighten us out. Robin, you say it's possible, but then you talked about
establishing variables as though you missed his question too. But I'd like
to know how to do it, if it's possible.
---
Bob Bridges, rhb...@attglobal.net, cell 336 382-7313
Robert...@westfieldgrp.com, 330 791-6576
/* Q: What do you get when you cross a fighter with an aircraft carrier?
A: Debris. */
-----Original Message-----
From: John R bodoh
Sent: Wednesday, October 3, 2007 12:29
How about:
parse value x2d(substr(xrecord,1,2)-4 substr(xrecord,4),
with xlen xsegment +(xlen) xrecord
> -----Original Message-----
> From: Ryerse, Robin
> Sent: Wednesday, October 03, 2007 11:13 AM
>
> You can accomplish what you want with one parse
>
> parse var xrecord xlen 5 xsegment +(c2d(left(xrecord,4)-4) xrecord
>
> This works because all operative variables in the parse statement have an
> established value before the parse is executed.
----------------------------------------------------------------------
(Some time in the late '70s I read the comments of a young lady -- well, I
was young, back then, too -- who was complaining about a conflict in, I
don't know, somewhere in southern Africa I think. Her comment was "Didn't
we learn anything from Viet Nam?!". I SAID she was young.
"Viet Nam"?, I thought. How about the Korean conflict, WWII, the
Spanish-American war, the American revolution? If we didn't learn anything
from the Crusades, the Norman invasion or Cain vs Abel, why would Viet Nam
be any different? Programming has been around only seventy years or so,
but it won't be any different. Everyone has to learn for himself.)
---
Bob Bridges, rhb...@attglobal.net, cell 336 382-7313
Robert...@westfieldgrp.com, 330 791-6576
/* When you internalize an author whose vision or philosophy is both rich
and out of fashion, you gain a certain immunity from the pressures of the
contemporary....Great literature can help us remain fad-proof. -from
"Reading Old Books" by Joseph Sobran, 1999 */
-----Original Message-----
From: Thomas Berg
Sent: Wednesday, October 3, 2007 09:07
You can never prove (or in practice presume) that a program is error free
by testing it. I thought that this was an established fact since around
1940.
> -----Ursprungligt meddelande-----
> Från: Mickey Bee
> Skickat: den 3 oktober 2007 14:54
>
> Now this is the ONLY good reason I have heard so far. Sleep
> is nice, I do it for at least 12-15 hours a week :)
>
> But as you said, you have never actually trapped an error
> with it, meaning that you code and test the way I code and test :))))>
1. The NOVALUE condition is not depending on the expression restriction
in Parse. It happens to me also when "reusing" a variable in a Parse.
(It was fixed by setting the variable to whatever before the Parse.)
2. One solution is to use the Interpret instruction. This is of course
neiter elegant or easier to follow...
_____________________________________________________________
Thomas Berg Specialist IT Utveckling Swedbank AB (Publ)
> -----Ursprungligt meddelande-----
> Från: TSO REXX Discussion List
> [mailto:TSO-...@VM.MARIST.EDU] För Mark Vitale
> Skickat: den 3 oktober 2007 16:02
> Till: TSO-...@VM.MARIST.EDU
> Ämne: [TSO-REXX] relative positional parsing question
>
> Dear Rexx-perts,
>
...
> parse var xrecord xlen +4 xsegment +(x2d(xlen)*2-4) xrecord
>
> I was surprised to see this statement raise a novalue error.
> The Rexx doc clearly states you may use a variable
> in a relative positional pattern, and that variable may be
> set earlier in the parse statement.
> Apparently, however, expressions are not allowed in
> relative positional parsing. 'Trace i' was no help in
> figuring this out because it does not trace the "evaluation"
> of the relative positional value. I only figured it out by
> trial and error, eventually getting a syntax error with a
> simpler expression inside the parentheses. So why do I get
> a novalue error instead of a syntax error with my original
> statement (above)?
>
> I have my code working now by breaking my single parse into 3
> statements:
>
> parse var xrecord xlen +4 .
> len = x2d(xlen) * 2 /* convert RDW to x-string length */
> parse var xrecord xsegment +(len) xrecord
>
> This may be easier to follow when I look at it again
> in a few months. But it's not as elegant - parsing
> the same (long) xrecord twice offends me. Any comments or
> suggestions?
>
> Thanks in advance,
>
> Mark Vitale
Mickey
> -----Ursprungligt meddelande-----
> Från: TSO REXX Discussion List
> [mailto:TSO-...@VM.MARIST.EDU] För Mickey
> Skickat: den 4 oktober 2007 12:57
> Till: TSO-...@VM.MARIST.EDU
> Ämne: Re: [TSO-REXX] SIGNAL ON NOVALUE -- Traceback for debugging
>
> I was once also an established fact that the universe
> revolved around the
> earth. It was once an established fact that the earth was
> flat. Those were
> as correct as the established fact that a program cannot be
> error free.
>
> Mickey
>
> ----- Original Message -----
> From: "Bob Bridges" <rhb...@ATTGLOBAL.NET>
> To: <TSO-...@VM.MARIST.EDU>
> Sent: Wednesday, October 03, 2007 11:51 PM
> Subject: [TSO-REXX] SIGNAL ON NOVALUE -- Traceback for debugging
>
----------------------------------------------------------------------
The other question is why I get a NOVALUE error instead of SYNTAX.
In perfect hindsight, I wish I'd simplfied my
example and avoided the other baggage (hex
representation, RDW, doubled lengths) that I was
working with at the time. They were the reason
I wanted to use an expression, but they are all
red herrings. So let's try again:
trace i
signal on novalue
signal on syntax
doober = 'onetwo'
three = '03'x
say c2x(three)
/* intend to split into doob_1 = 'one' and doob_2 = 'two' */
parse var doober doob_1 +(c2x(three)) doob_2
exit
novalue:
say 'novalue'
exit
syntax:
say 'syntax'
exit
This fails with NOVALUE on the parse line, not SYNTAX as "expected"
(expected, that is, once you realize expressions are not allowed,
only a simple variable).
The actual error message (after disabling the traps) is:
IRX0046I Error running DEMOPARS, line nnn: Invalid variable reference
Now that I see the actual error message, I can see why this might be
classified as NOVALUE rather than SYNTAX, but the astonishment factor
is high on several counts.
-mark
> -----Original Message-----
> From: TSO REXX Discussion List
> [mailto:TSO-...@VM.MARIST.EDU] On Behalf Of Bob Bridges
> Sent: Wednesday, October 03, 2007 11:52 PM
> To: TSO-...@VM.MARIST.EDU
> Subject: Re: relative positional parsing question
>
> Isn't anyone listening to this guy? His question isn't about
> properly aligning the parse, nor about using variables in a
> parse; he's asking whether it's possible to use an EXPRESSION
> in a parse.
>
> Mark, I ran into the same problem a few years ago and came to
> the same conclusion. I've never had any reason since then to
> change my mind, but if we can get one of these guys to notice
> the question maybe they'll straighten us out. Robin, you say
> it's possible, but then you talked about establishing
> variables as though you missed his question too. But I'd
> like to know how to do it, if it's possible.
>
----------------------------------------------------------------------
-mark
> -----Original Message-----
> From: TSO REXX Discussion List
> [mailto:TSO-...@VM.MARIST.EDU] On Behalf Of Mark Vitale
> Sent: Thursday, October 04, 2007 9:10 AM
> To: TSO-...@VM.MARIST.EDU
> Subject: Re: relative positional parsing question
>
----------------------------------------------------------------------
> Date: Thu, 4 Oct 2007 08:10:13 -0500
>
> Yes, that's one of the questions: can I (or why
> can't I) use expresssions in a relative position
> spec for a parse statement?
>
No.
I suspect the code implementing the PARSE instruction is non-reentrant,
or that the design wanted to preclude modification of the subject or
the pattern by a possible side effect of a function call during PARSE.
> The other question is why I get a NOVALUE error instead of SYNTAX.
>
If you haven't yet answered your own question, here's an informative
pair of examples:
user@MVS:128$ rexx "signal on novalue; parse value 2 with . +(x2d(0)) ."
1 +++ /* REXX Useful! */ interpret arg(1)
+++ "NOVALUE"
IRX0016I Error running /mvsoeecc/sppg/bin/rexx, line 1: Label not found
.. versus:
user@MVS:129$ rexx "signal on novalue; x2d = 1; parse value 2 with . +(x2d(0)) ."
1 +++ parse value 2 with . +(x2d(0)) .
1 +++ /* REXX Useful! */ interpret arg(1)
IRX0046I Error running /mvsoeecc/sppg/bin/rexx, line 1: Invalid variable reference
-- gil
--
StorageTek
INFORMATION made POWERFUL
----------------------------------------------------------------------
/* Rexx parse testing */
the_string = '....+....1....+....2....+....3...'
parse var the_string 20 two +1 =(two * 2) residual
say two residual
exit
When run with EXECUTIL TS, the exec aborts:
line 3: Invalid variable reference
When run with SIGNAL ON SYNTAX (without SIGNAL ON NOVALUE), the ON
SYNTAX condition is raised.
When run with SIGNAL ON SYNTAX and SIGNAL ON NOVALUE, the ON NOVALUE
condition is raised. This is regardless the order of SIGNAL statements.
There is one other test I performed which is quite interesting. While
running under EXECUTIL TS (or TRACE '?R'), if I enter the exact same
parse statement interactively (as opposed to letting it execute/fail
from the exec's source), the parse fails:
+++ Interactive trace. Error 46: Invalid variable reference.
+++
but the interesting fact is that the variable named TWO is established
and assigned the value 2. This assignment does not happen in any other
test scenario.
Another observation is that nether EXECUTIL TS nor TRACE '?R' will
preserve the interactive debug session when the incorrect parse
statement is executed (from the exec)
Robin Ryerse
-----Original Message-----
From: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] On Behalf
---- Mark Vitale <mark....@PERFMAN.COM> schrieb:
> Yes, that's one of the questions: can I (or why
> can't I) use expresssions in a relative position
> spec for a parse statement?
>
> The other question is why I get a NOVALUE error instead of SYNTAX.
>
> -mark
>
> > -----Original Message-----
> > From: TSO REXX Discussion List
> > [mailto:TSO-...@VM.MARIST.EDU] On Behalf Of Bob Bridges
> > Sent: Wednesday, October 03, 2007 11:52 PM
> > To: TSO-...@VM.MARIST.EDU
> > Subject: Re: relative positional parsing question
> >
> > Isn't anyone listening to this guy? His question isn't about
> > properly aligning the parse, nor about using variables in a
> > parse; he's asking whether it's possible to use an EXPRESSION
> > in a parse.
> >
> > Mark, I ran into the same problem a few years ago and came to
> > the same conclusion. I've never had any reason since then to
> > change my mind, but if we can get one of these guys to notice
> > the question maybe they'll straighten us out. Robin, you say
> > it's possible, but then you talked about establishing
> > variables as though you missed his question too. But I'd
> > like to know how to do it, if it's possible.
> >
>
Robin Ryerse
-----Original Message-----
From: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] On Behalf
Of Bob Bridges
Sent: October 3, 2007 11:52 PM
To: TSO-...@VM.MARIST.EDU
Subject: Re: relative positional parsing question
..besides that I don't know of "a program cannot be error free" as
an *established fact*.
But to be OT: "You can't prove a program to be error free by testing"
IS an *established fact*.
_____________________________________________________________
Thomas Berg Specialist IT Utveckling Swedbank AB (Publ)
> -----Ursprungligt meddelande-----
> Från: TSO REXX Discussion List
> [mailto:TSO-...@VM.MARIST.EDU] För Mickey
> Skickat: den 4 oktober 2007 13:15
> Till: TSO-...@VM.MARIST.EDU
> Ämne: Re: [TSO-REXX] SV: [TSO-REXX] SIGNAL ON NOVALUE --
Now, if you'd like to, you can spend the rest of your natural life trying to work out a way for this program to fail, OTHER than having MVS crash in mid executing, but frankly, I have far better ways to waste my time, as I KNOW FOR A FACT that it cannot.
Mickey
-------------- Original message ----------------------
From: Thomas Berg <thoma...@SWEDBANK.SE>
> Your argument overwhelms me.
>
> ..besides that I don't know of "a program cannot be error free" as
> an *established fact*.
>
> But to be OT: "You can't prove a program to be error free by testing"
> IS an *established fact*.
>
> _____________________________________________________________
> Thomas Berg Specialist IT Utveckling Swedbank AB (Publ)
>
> > -----Ursprungligt meddelande-----
> > Fren: TSO REXX Discussion List
> > [mailto:TSO-...@VM.MARIST.EDU] Fvr Mickey
> > Skickat: den 4 oktober 2007 13:15
> > Till: TSO-...@VM.MARIST.EDU
> > Dmne: Re: [TSO-REXX] SV: [TSO-REXX] SIGNAL ON NOVALUE --
> > Traceback for debugging
> >
> > Ah, so you are still of the opinion that the earth is flat?
> > Might I suggest
> > the flat-earth society, you will find lots of friends there.
> >
> > Mickey
> >
> > ----- Original Message -----
> > From: "Thomas Berg" <thoma...@SWEDBANK.SE>
> > To: <TSO-...@VM.MARIST.EDU>
> > Sent: Thursday, October 04, 2007 7:01 AM
> > Subject: [TSO-REXX] SV: [TSO-REXX] SIGNAL ON NOVALUE -- Traceback for
> > debugging
> >
> >
> > No.
> >
> > > -----Ursprungligt meddelande-----
> > > Fren: TSO REXX Discussion List
> > > [mailto:TSO-...@VM.MARIST.EDU] Fvr Mickey
> > > Skickat: den 4 oktober 2007 12:57
> > > Till: TSO-...@VM.MARIST.EDU
> > > Dmne: Re: [TSO-REXX] SIGNAL ON NOVALUE -- Traceback for debugging
First: MVS doesn’t like the backslash
14 +++ If Datatype(Infield) :
5 +++ Call doubleit 123
IRX0013I Error running BEE, line 14: Invalid character in program
***
So I made the first fix
/* REXX ********************************************************
*
*
****************************************************************
Call doubleit 9e999999999
Exit
DoubleIt: Procedure
Arg infield
If Infield = '' Then
Do
Say "Oops, no data"
Exit
End
If Datatype(Infield) <> 'NUM' Then
Do
Say 'Oops, I need a number to double'
Exit
End
Doubled = Infield * 2
Say Infield 'Doubled is = to' Doubled
Return
Then I tried a few and got:
19 +++ Doubled = Infield * 2
5 +++ Call doubleit 9e999999999
IRX0042I Error running BEE, line 19: Arithmetic overflow/underflow
Fair enough?
---- Mickey Bee <mic...@COMCAST.NET> schrieb:
>/*Rexx DoubleIt */
>Arg infield
>If Infield = '' Then
> Do
> Say "Oops, no data"
> Exit
> End
>If Datatype(Infield) \= 'NUM' Then
> Do
> Say 'Oops, I need a number to double'
> Exit
> End
>Doubled = Infield * 2
>Say Infield 'Doubled is = to' Doubled
>Exit
>
>
>Now, if you'd like to, you can spend the rest of your
>natural life trying to work out a way for this program to
>fail, OTHER than having MVS crash in mid executing, but
>frankly, I have far better ways to waste my time, as I
>KNOW FOR A FACT that it cannot.
Even IEFBR14 has had APARs, and you don't get much
simpler than that.
I ran your program with odd input. I got it to crash
and, worse, I got it to give incorrect results:
5E2333333333333333333 Doubled is = to 1.0E-605465258
It said that doubling an enormous number yields an
infinitesimal result. I didn't play around a lot to find
the boundary condition between good results and
ill. Surprisingly, removing digits of the exponent yields
this crash:
>11:19 Thu 2007-10-04 F:\>d -5e2333333333333333
> 14 +++ Doubled = Infield * 2
>Error 42 running "F:\D.REX", line 14: Arithmetic
>overflow/underflow
It's likely this is an error in the REXX
implementation. However, if you want to have a
bullet-proof program, you have to know and check for the
limitations of your language and implementation. I'd be
interested to see it tested on MVS.
I run:
REXX-Regina_3.3(MT) 5.00 25 Apr 2004
Microsoft Windows 2000 [Version 5.00.2195]
--
I cannot receive mail at the address this was sent from.
To reply directly, send to ar23hur "at" intergate "dot" com
Also:
doublit 9e9999999999999999999999
Oops, I need a number to double
Mark Wheeler, 3M Company