Last update: 12/13/2011
Frank Clarke's REXX Tools
Holicau! Look who's Mainframe Week's "Website of the Week" for 9 OCT 2002! Yup... you're lookin' at it.
Since being named WSOTW by MainframeWeek, I have received some disquieting
reports from abroad.
Specifically, some (most) of the routines use the U.S. dollar sign in variable names
and this apparently can cause non-USian users fits.
You may have to manually correct this if it seems to be a problem.
Secondly, it appears that "Save As..." will add the occasional blank line at the
end of the Saved-as text.
Routines which have embedded ISPF elements will fail because DEIMBED insists
the last line be "*/" and won't run if it isn't.
None of these routines have blank lines at the bottom;
if your copy has blank lines, those lines must be manually removed.
Secondly, it appears that "Save As..." will add the occasional blank line at the end of the Saved-as text. Routines which have embedded ISPF elements will fail because DEIMBED insists the last line be "*/" and won't run if it isn't. None of these routines have blank lines at the bottom; if your copy has blank lines, those lines must be manually removed.
I have created or collaborated
on a great deal of REXX code for MVS.
Much of it is cause for great pride
and I admit to having succumbed to it,
so much so that I now present some of that code for you to browse,
admire, and acquire for your own use.
(Not all of these routines were written by me;
a fair few are the work of
[and appear with the permission of]
Chris Lewis, The World's Laziest Programmer,
but I include them here because
or all of the above.)
or all of the above.)
Recently I have started blogging about some of the trickier code you'll find here. See REXXpertise.blogspot.com.
"The principal virtues of a programmer are Laziness, Impatience, and Hubris."
-- Larry Wall
These code elements won't necessarily run as-is, but they are fundamental elements of the working code below.
|DEIMBED||extracts embedded ISPF elements from REXX code. Embed panels and skeletons at the end of your source and use DEIMBED to extract them. End your reliance on external application-level ISPPLIB and ISPSLIB datasets. This makes maintenance and distribution much easier, too, since you have to deal with fewer libraries and fewer elements. Most routines become 100% self-contained. Many of the routines below rely on this.|
|REXXSKEL||The basis for all my MVS REXX software. Approximately 230 lines of diagnostic boilerplate providing a pro-forma HELP section, parsing subroutines, and initialization of environmental indicators.|
|"How to REXXSKEL"||An explanation/tutorial on the nature and uses of REXXSKEL.|
|TRAPOUT||captures REXXSKEL trace-output and spools it to a dataset for later review. Don't laugh... There have been many times when a truly intractable problem was solved only because the TRAPOUT dataset was allocated in CYLINDERS.|
These routines will run, almost all with no customization at all. In order to save space, however, the REXXSKEL back-end code has been removed so that you will, in fact, have to restore the contents of REXXSKEL (from BRANCH to the end of TOOLKIT_INIT) at the point where the comment says "REXXSKEL back-end removed".
|ADDCMDS||attaches your local command table to the in-storage copy of ISPCMDS. Your site doesn't implement 'USERCMDS'? Not a problem... with ADDCMDS.|
|ALIST||displays all (or selected) allocated DDNames and allows you to drop selected datasets from allocation or concatenation, edit, browse, view...|
|ARRANGE||demonstrates a technique for adding rows to an ISPF table in random order and maintaining that order over time.|
|ATTACH||This session customizer is designed to work in anyone's installation without modification. How? All the 'mods' are in an external dataset where you specify which files are to be enhanced or trimmed and which commands are to be executed as part of your logon processing. Customization: the instructions for adjusting the environment are expected to be found in [userid].ISPF.PROFILE(START) but if the dataset, member, or contents are missing ATTACH will still run -- although it will do nothing.|
|BLOX||block-letter writer; modeled on IEFSD095.|
|COMBINE||combines -n- files even if the DCBs are different.|
|COMMANDS||view and execute commands in a Command Table.|
|DUP||written by Chris Lewis based on my "CLONE". This lets you build a 2nd dataset based on another and fill it with the original's contents. This is so good I no longer use my own software.|
|FCCMDUPD||insert a command to a user's command table under program control|
|FIRSTIME||does a specified task only the first time (this day, week, month, year) it's called and skips it otherwise. Don't forget to take FTINIT, its required subroutine.|
|FLTTBL||converts any ISPF table to a flat-file|
|FTINIT||a required subroutine for FIRSTIME.|
|FTPERR||analyzes FTP return codes.|
|GENCARD||build control cards from parms|
|GETGDG||finds the n-th generation of a GDG|
|HSMLIST||makes management of HSM backups and migrated datasets much easier. You are prompted for a catalog level, then all the HSM material for that catalog level are presented for selection. Delete, Recall, and Recover functions are supported.|
|JOBCARDS||builds a 4-line stack of ISPF jobcard statements. May need some local customization.|
|JSPLIT||breaks JCL into one-phrase-per-line.|
|LA||performs a "LISTA ST" into the queue. Great for when you want to know the dataset names allocated to some particular DD and don't want to write the code for it.|
|LCOMM||inserts a line-comment right-justified for PL/I code.|
|LDOW||calculates the date of the nth-anyday. Feed it '3TU200306' and it will return the ISOdate of the 3rd Tuesday of June 2003.|
|LISTCSUM||extracts the output of an IDCAMS LISTCAT operation to an easily-parseable form. Built originally as an adjunct for improvements to Jim Connelley's VC.|
|MEMBERS||writes the directory of a PDS into the queue. Handles ALIASes (or not, you decide).|
|MERGETBL||merges two ISPF tables into one. One of the tables will be overwritten with the merged contents of both.|
|NEWALIAS||an easy way to create a dataset-alias.|
|PDSCOPYD||copies members between PO datasets when the DCBs are incompatible. Uses EXECIO for data-movement, and LM facilities to replicate the statistics so the two members look like exact duplicates, right down to the time-of-last-update.|
|POST||puts a message onto your ISPF log file. This is used by several of the routines but it's not actually necessary; you could stub it out if you wish.|
|PRINTME||prints the current dataset/member on a local printer. Customization: As presented, PRINTME uses PRINTDS to actually move the text to the printer. If your site does not use PRINTDS this will have to be adjusted and will possibly affect other parameters as well. The technique, nevertheless, should be adaptable.|
|PROFVARS||displays the contents of application profiles from ISPPROF. This is based heavily on Chris Lewis' PROFVARS but extends it in both directions by allowing the user to select multiple profiles from a list and adding a deeper level of detail for those profile variables which seem to have gotten off their leash. Jim Moore's version (which prompted this upgrade) is, unfortunately, a COBOL program and I don't have access to a COBOL compiler, so I had to build the function in REXX. (Hey, Jim, betcha mine runs as fast as yours ;-)|
|REALIAS||assigns member-aliases automatically for REXXSKEL-based code.|
|REPGEN||shamelessly stolen from Jim MacKean of Vancouver BC (thank you, Jim). This takes a mock-up of a report and creates PL/I declares for each line.|
|RSTTBL||restore an ISPF table flattened by FLTTBL.|
|RUNEXEC||runs the current REXX or CLIST code. Very useful for the early stages of development when iterative changes are being made to a routine.|
|SEIZE||an alternative to CREATE :-) A panel pops up to ask where you want the seizure stored. The advantage of SEIZE is that the member-statistics on the new copy will be identical to the original.|
|SPACERPT||builds a report showing DASD usage for specified groups of datasets.|
|SQRT||a callable square-root routine in REXX. Although I designed this entirely independently, I'm sure that it's somebody-or-other's algorithm. If you recognize it, let me know and I'll give credit where it's due.|
|SQUASH||submits a background IEBCOPY to compress the current dataset.|
|STRSORT||sorts a string of words either ascending or descending. Used only as a subroutine.|
|TBCOPY||makes a copy of an ISPF table with modifications. This routine is actually a pro-forma code block which provides the framework for doing the required table modifications.|
|TBLGEN||TBCREATE using the special Table Master Table from [TBLMSTR]. Customization: default value for "ISPTLIB" in LOCAL_PREINIT.|
|TBLMSTR||Create/Maintain a Table Master Table. This is a specific-instance of a generalized table-maintenance routine; it does a particular task but it's also a great tutorial on how to handle 'table maintenance'. Customization: default value for "ISPTLIB" in LOCAL_PREINIT.|
|TBLSORT||Sort an ISPF Table. Not REXX! It's a CLIST! REXX incurs too much overhead sorting large ISPF tables, so use this CLIST instead.|
|VCX||based heavily on (OK... stolen from) Jim Conneley's VC, this generates the IDCAMS DELETE/DEFINE statements that would have been used to create this KSDS, ESDS, RRDS, GDG, etc.|
These are pretty complex as edit macros go. Hopefully they are commented well enough to be understood and maintained.
|$$JFORM||aligns JCL for ease-of-reading. New and improved... Values for where-to-put-this-text are now kept in the ISPF profile. If there aren't any, you get prompted to adjust the default values to ones more to your taste. Start as "$$jform ((setup" whenever you wish to alter the values.|
|COMPSTAT||adds ISPF statistics to a saved PL/I compiler listing. Requires SHORTPG.|
|DC||'Dot Command'. David Visage built the original of this in CLIST (!); I recast it into REXX and added a few features. Put a dot-command on a line with a 'DSN=' and crank DC to have it do that function on that dataset. What a cool idea!|
|DEADCODE||finds portions of REXX code which are not called.|
|ELEMLEN||a required subroutine for PLIPOS, included here to make it easy to acquire it.|
|FIXSTATS||For those odd situations where you want the member-stats to reflect something other than 'this user, right now'...|
|PLILBLS||finds all the PROC statements (and their ENDs) and all labels and the CALLs and GOTOs which reference them. Helpful for seeing the overall flow of a program. Works on PL/I source and compiler listings. Requires STRSORT and SEGMENT.|
|PLIMSGS||operates on a compiler listing by copying the diagnostic messages to just before the referenced statement. Instead of bouncing back and forth between the source listing and the Diagnostic Messages sections, skip from one message to the next by "L NEXT SPECIAL".|
|PLIPOS||Are you frustrated by structure declares whose commentary neglects any mention of which data-columns are used by each element? This ISPF edit macro will insert an appropriate comment onto each line identifying the start and end position. (For LRECL>999 only the start position is shown.) (Make sure you also take ELEMLEN).|
|PLIXREF||operates on a compiler listing. Every CALL or GOTO is annotated with the statement number to which it refers. Every label or PROCEDURE statement is annotated with the statement number(s) which reference it. PLIXREF has lately become a driver for two routines: PLIXREFO (for the Optimizing Compiler) and PLIXREFE (for the Enterprise Compiler). Don't forget to pick up these two required subroutines when you grab PLIXREF.|
|PLIXREFE||The working code for Enterprise PL/I listings.|
|PLIXREFO||The working code for Optimizer PL/I listings.|
|QIO||operates on PL/I source and compiler listings. Pops out all the FILE DCLs and summarizes them in NOTELINEs at the top into INPUT, OUTPUT, UPDATE, VARIABLE, and ANY (files that don't specify INPUT, OUTPUT, or UPDATE in the DCL).|
|SEGMENT||assigns labels to particular lines in a saved PL/I compiler listing. This enables you to (e.g.) go directly to a certain portion of the listing via a simple LOCATE. Requires COMPSTAT.|
|SELMATCH||Matches ')SEL' and ')ENDSEL' by placing the SEL-condition on the ENDSEL-statement. This makes it easy to match them visually and is good documentation as well.|
|SETREFS||creates backward-references in JCL (DSN=*.IEBCOPY.SYSUT2...).|
|SHORTPG||The Enterprise PL/I Compiler adds a useless blank line at the bottom of every page of compiler output. When the default page-length is set just right, printing such a document causes an unnecessary page-eject after nearly every page resulting in one blank page for each printed page (double your normal paper usage). SHORTPG removes these blank lines.|
|SHOWFLOW||pops all the CALLs in a REXX routine and all the labels to which they refer. If you always end your subroutines with a comment that names the subroutine, you'll see that, too.|
|STRCHRT|| Create an indented structure report
for COBOL source.
There are three (3) ISPF edit macros here,
so you must partition this single item into three pieces.
It has been many years since I looked at or used these macros;
they worked the last time I tried them.
HELP-text is embedded.
The routines here deserve their own category because they are extraordinary in their capabilities and, consequently, in their complexity. Not for the faint-of-heart...
|FCXREF||does a member-cross-reference between [n] partitioned datasets. 3 listing formats; member-name masking; name-range selection.|
|RUNDATA||keeps persistent data for a process where it can be used by multiple users. I admit this isn't exactly the most useful piece of code I've ever written, but it's a pretty fair tutorial on manipulating extension variables in ISPF tables.|
|TBLOOK||examines and displays any ISPF table. Any ISPF table? Yes, any table. NEW! Now allows you to arrange and print selected columns.|
Other great REXX and MVS stuff:
David Alcock's REXX stuff
Mark Zelden's REXX stuff
Gabe Gargiulo's index
of manuals and tutorials