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

Reply via email to