Not sure if this is helpful or not but I write software that allows
users to create their own subroutines that plug into my architecture.
Users can forget to catalog or have other issues with their subroutine.
So, I require the user subroutine to accept an argument called 'mode'.
In my system, mode=2 means 'test mode'. If a user subroutine is called
with mode set to 2, then it should set test data and when processing is
complete, output the string /%%validated%%/ to standard out.
In my program where I will be calling the subroutine, I reference it
twice. First to validate the subroutine and second to actually call the
subroutine. I use the EXECUTE/CAPTURING on the first pass using a
special test executable to validate the subroutine then if I find
%%validated%% in the captured output, then I mke the second pass and
actually call the subroutine with CALL @. On the first pass, I EXECUTE
using my validator program so that even if the subroutine fails or dies,
only that execute levels is affected. i.e., you can execute a program
that calls a failing subroutine and the main program that executed will
carry on after the failure. I leveraged this behavior to mitigate the
chance that a user subroutine would cause my main program to abort.
Yes, I understand the EXECUTE is expensive but it's less expensive than
me having to spend my time helping a user restart my process because one
of their subroutines failed. This technique might be used in
combination with the global catalog checker to provide a richer level
of validation. Here are some code fragments is case anyone finds this
technique useful:
*The Main Program*
userSubroutineName = \MY.SUBROUTINE.NAME\
* check the subroutine to make sure it is valid before calling
EXECUTE \bpixmlize.validateSubroutine \:userSubroutineName CAPTURING result
* check result to see if the subroutine responded cordially
IF (INDEX(reuslt, \%%validated%%\, 1) THEN
* yep, the subroutine is alive and well, it's okay to call it.
itemId=\\
mode=1; * 1 means 'run' mode
error = \\
CALL @userSubroutineName(itemId, mode, error)
END ELSE
* not sure what happened but subroutine is not playing nicely
CRT \So sorry, but \:userSubroutineName:\ does not appear to be valid\
CRT \result=\:result
END
------------------------------------------------------------------------
* The subroutine validator program*
*bpixmlize.validateSubroutine
*a executable program that will attempt to call subroutine or error if not
*to be executed in a basic program with captured output. Evaluate the
captured
*result and it should contain the string %%validated%% otherwise it's a bad
*or invalid subroutine. The prevents the caller from crashing with
object not
*found so that it can wrap-up normally. It's the job of the called
subroutine
*to output %%validated%% or something agreed by the caller in order to
validate
*the subroutine. Since this is executed and not called, it will fail
but return
*control to the calling program after failing.
*
------------------------------------------------------------------------------
INCLUDE bpi.xml.bp bpixmlize.common ; * to get common variables
GOSUB ParseSentence
GOSUB Validate
GOTO Exit
*
------------------------------------------------------------------------------
Validate:
IF subroutine.name NE \\ THEN
item.id = \\; mode=2; error = \\
CALL @subroutine.name( item.id, mode, error)
END
RETURN
*
ParseSentence:
pgm.id = \bpixmlize.validateSubroutine\
start = @FALSE
sentence = CHANGE( @SENTENCE, SPACE(1), @AM)
max.words = DCOUNT( sentence, @AM)
subroutine.name = \\
FOR i = 1 to max.words
BEGIN CASE
CASE start
BEGIN CASE
CASE subroutine.name EQ \\
subroutine.name = sentence< i >
CASE @TRUE
* ignore
END CASE
CASE sentence<i> EQ pgm.id
start = @TRUE
CASE @TRUE
* ignore
END CASE
NEXT i
RETURN
*
Exit:
STOP
------------------------------------------------------------------------
*
**A sample user subroutine:*
SUBROUTINE MY.SUBROUTINE.NAME(item.id, mode, error)
* Copyright (c) 2013 by Blue Prairie, Inc.
* All Rights Reserved
*
* item.id is the item ID of the main file to process
* mode If caller sets mode=2, then subroutine will simply
output
* string '%%validated%%\ and return. This is so that the
* caller can use the subroutine test program to
validate that
* the subroutine name is valid and callable before
actually
* calling it. If the subroutine sets mode to zero,
the calling
* program should consider this a signal that
something is wrong
* and it should stop processing. The caller should
normally set
* mode to 1 for normal processing.
* error is an error code to be returned to caller.
*-------------------------------------------------------------------------------
*
INCLUDE bpi.xml.bp bpixmlize.common ; * to get common variables
BEGIN CASE
CASE UNASSIGNED(mode)
mode = 1
CASE mode EQ 2
GOSUB Validate
GOTO Exit
CASE @TRUE
* allow to drop through
END CASE
*
pgm.id = \MY.SUBROUTINE.NAME\
*
GOSUB DoSomethingUseful
GOTO Exit
*-------------------------------------------------------------------------------
DoSomethingUseful:
* here is where we do the main task of this subroutine
RETURN
*
Validate:
*do some sanity checks, make sure subroutine can function (i.e.,
open files, etc)
*then if all looks good, simply output th %%validated%% string
CRT \%%validated%%\
RETURN
*
Exit:
RETURN
------------------------------------------------------------------------
Bruce Decker
Blue Prairie, Inc.
http://www.bluepinc.com
720.733.0459
On 1/30/2014 8:13 AM, Daniel McGrath wrote:
In particular, when using the CALL @ syntax to dynamically call something.
Dan
-----Original Message-----
From: [email protected]
[mailto:[email protected]] On Behalf Of Ross Ferris
Sent: Wednesday, January 29, 2014 10:56 PM
To: U2 Users List
Subject: Re: [U2] [UV] Programmatic Verification of Globally Cataloged
Subroutine
Knowing how many arguments a subroutine is expecting is a good way to
check/confirm that the call you are about to make isn't going to blow up in
your face!
Ross Ferris
Stamina Software
Visage > Better by Design!
-----Original Message-----
From: [email protected]
[mailto:[email protected]] On Behalf Of Wjhonson
Sent: Wednesday, January 29, 2014 10:15 AM
To: [email protected]
Subject: Re: [U2] [UV] Programmatic Verification of Globally Cataloged
Subroutine
I was just trying to think of a reason why I'd want specifically to know how
many arguments the subroutine has.
That is, why was this particular fact chosen as the returned status code ?
-----Original Message-----
From: Keith Johnson [DATACOM] <[email protected]>
To: '[email protected]' <[email protected]>
Sent: Tue, Jan 28, 2014 3:10 pm
Subject: Re: [U2] [UV] Programmatic Verification of Globally Cataloged
Subroutine
Hi,
LeRoy Dreyfuss said that you would have to change 52 to 12 for EXIST to work.
The globally cataloged programs have an extra 40 characters put on the front,
so that would cause a problem.
@RECORD[1,4] is a count of the number of times the program has been used.
@RECORD[5,8] is who cataloged it
@RECORD[13,4] are the date and time (I think)
Regards, Keith
_______________________________________________
U2-Users mailing list
[email protected]
http://listserver.u2ug.org/mailman/listinfo/u2-users
_______________________________________________
U2-Users mailing list
[email protected]
http://listserver.u2ug.org/mailman/listinfo/u2-users
_______________________________________________
U2-Users mailing list
[email protected]
http://listserver.u2ug.org/mailman/listinfo/u2-users
_______________________________________________
U2-Users mailing list
[email protected]
http://listserver.u2ug.org/mailman/listinfo/u2-users
_______________________________________________
U2-Users mailing list
[email protected]
http://listserver.u2ug.org/mailman/listinfo/u2-users