Wednesday, November 9, 2011

Invoking an ISPF-dependent routine from READY

So you've written this peachy routine that uses all sorts of ISPF facilities.  It runs great from any command line just about anywhere within ISPF, but when you try invoking it from READY, it crashes because there is not an ISPF environment available.  You could simply start ISPF whenever you want to run it, run it from the primary option panel, and flush ISPF when it's done...

...or you could rig it so that it will run from READY as easily as it does from within ISPF.  That way, you never have to remember which of your routines need ISPF and which don't.  The ones that do will pave their own road ahead of their need for it.

WARNING: the code that follows presumes you have all the capability provided by REXXSKEL.  For more information about REXXSKEL and what it does, pop on over to my REXX page and take a look at the write-up titled "How To REXXSKEL".  Of particular interest in that regard is the subroutine SWITCH and the flow of control from the mainline to TOOLKIT_INIT through LOCAL_PREINIT.

TOOLKIT_INIT in a REXXSKEL-enabled routine sets, among other things, "sw.inispf" which tells us whether or not an ISPF environment exists.  (Yes, I know it should be "sw.0inispf", but REXXSKEL was built a long, long time ago in a galaxy far away...)  When an ISPF environment does not exist, we can generate one via ISPSTART, but we have to be prepared to rip it down when we're done with it.  During the early mainline of your well-structured program, you will need to restart the routine in a newly-invoked ISPF environment and to halt the current execution as soon as that restarted execution completes:

if /sw.inispf  then do                 /* after TOOLKIT_INIT return  */
   arg line
   line = line "((  RESTART"           /* tell the next invocation   */
   "ISPSTART CMD("exec_name line")"    /* Invoke ISPF...             */
   exit 4                              /* ...then bail out           */

When the restarted routine ends, it should end with a non-zero return code to skip processing for any generated LOG or LIST datasets written by the newly-invoked ISPF environment:

if sw.0Restarted then,                 /* just after DUMP_QUEUE      */
   exit 4

To determine whether or not this execution was restarted, LOCAL_PREINIT (part of initialization, but customized routine by routine) has checked the parameter string for the presence of the token "RESTART":

   sw.0Restarted = SWITCH("RESTART")

That's it.  That's all there is to it.  When you fire this routine from READY, it discovers that it is not in ISPF, restarts itself (via ISPSTART).  The restarted invocation ends non-zero, and returns to its calling point in the original, whereupon the original exits back to the operating system.

No comments:

Post a Comment