MVS TOOLS AND TRICKS OF THE TRADE MARCH 2007 Sam Golob MVS Systems Programmer P.O. Box 906 Tallman, New York 10982 Sam Golob is a Senior Systems Programmer. He also participates in library tours and book signings with his wife, author Courtney Taylor. Sam can be contacted at sbgolob@cbttape.org. Information about the CBT MVS Tapes can be found on the web, at http://www.cbttape.org. SANITY CHECKS AND PROGRAMMING ENHANCEMENTS Back when I was looking for my first programming job, you practically couldn't get anywhere if you didn't know how to write a FLOWCHART. I don't know how much flowcharts are used nowadays, so I don't know how familiar the readership is with them. But they can be basically characterized as "program logic diagrams" in a certain format, which describe each logical step that a program takes, together with a mapping of the logical flow and relationship between the steps. Hence the name "flowchart". It charts the program logic flow. If you have the privilege of looking at the old IBM MVS logic manuals, you will see many flowcharts there. In one of my programming interviews a long time ago, the head man asked me to flowchart a candy vending machine. You put in some coins, and out comes a candy bar. The job was to write a logic diagram, in flowchart format, to accurately describe what happens in the machine, from the time you put in the coins, to the time you get the candy. The boss told me (afterwards) that his head programmer, when asked to do this, produced a diagram with over 100 boxes, describing each step and decision in excruciating detail, and anticipating many possible problems. Of course the boss was very proud of him, and he hired him. Detail in anticipating a logic problem in a program, is often (nowadays) called a "sanity check". I don't remember hearing the term "sanity check" when I first started. It may be a relatively new word. But it does describe the concept of putting some extra code into a program, so as to circumvent a possible future problem. It's like putting an extra box or two into a flowchart. I think that many sanity checks are necessary, and even more often, they cause more problems than they solve. My (pure) mathematics background reminds me to emphasize what mathematicians call "elegance". This means "simplicity" in the sense of doing only what's essential. In other words, an "elegant" solution to a problem involves doing ONLY what is necessary, cutting through ALL the crap, getting EXACTLY to the point, and eliminating ANYTHING extra. Another term which is approximately equivalent to an "elegant solution" is a "tight solution", but elegance also implies aesthetic "prettiness" in addition to the "tightness" of the code. EXTRA BOXES IN MVS UTILITIES That brings us closer to today's topic. In the MVS world, we use "tried and true" utilities to do much of our work. IBM, over the years, has endeavored to make sure that their utilities will not produce problems when you go from earlier MVS operating systems to later ones. But once in a while, you'll get snagged by something, albeit rarely. I've been snagged in the past, by IEBGENER. At one point, IEBGENER was made to do something (by default) that disturbed my operation, namely, it reblocked tape files to large blocksizes without telling you it did so. Undoing that effect in IEBGENER's behavior is not so simple. To do it system-wide, you have to set a keyword in the DEVSUPxx member of PARMLIB, and IPL. (With z/OS 1.8 you won't have to IPL.) Or, in an individual run, you have to code some extra parms in your IEBGENER JCL. My simple circumvention to all this, was to get an old version of IEBGENER which didn't do any automatic reblocking, rename it to IEBGEOLD, and run it on a later version of MVS. That solution has (so far) worked out well for me. But now, it seems, I might have been similarly snagged by IEBCOPY. I'm still (at the time of this writing) in the midst of wrestling with the IEBCOPY controversy, so I can't tell you any conclusive answer about that. But I already see that I can't use the simple solution of running a backleveled IEBCOPY load module. IEBCOPY is so "bound" to other parameters in the system, and to system level indicators, that you can't run one level of IEBCOPY anymore on a different level of MVS. If your shop can afford it, it sometimes pays to buy a non-IBM utility like PDSFAST to substitute for IEBCOPY, just to get away from the crazy system dependencies that IEBCOPY has grown to have. MAKING UTILITIES (TOO) DEPENDENT ON THE SYSTEM The basic thrust of what we're talking about today, is the question of "how cute and fine-grained" can you get while enhancing a program, without introducing one or more harmful errors? Sometimes it's best to keep it simple and avoid the errors. Other times, you just have to introduce the extra complexity. But there's more to this problem. In certain instances, the difficulty may simply be whether the utility is "IBM" or "not IBM". I think that IBM, being "the owners of the operating system", are guilty of introducing many unnecessary system dependencies into their utilities. For example, IBM's DFDSS (program ADRDSSU) DASD backup and restore utility, may look to see how a dataset is cataloged before deciding whether or not to back it up. FDR, a similar utility NOT written by IBM, just backs up the tracks and doesn't ask too many questions. Therefore, you can use FDR to back up and restore VM packs, which you certainly cannot do using DFDSS. And on MVS packs too, FDR will usually do a more hassle-free job of backing all the datasets up and getting the job done. The non-IBM vendors, being less privy to the system's innards, can oftentimes think more clearly about the essence of what their utility is supposed to do, and they'll come up with much more elegant code than IBM will. Another example of this concerns the limitation of the amount of output produced by the XMIT or TRANSMIT TSO utility, which of course, was written by IBM. We discussed in a previous column (May 2006 - "Why Control Blocks?") that the XMIT command is completely dependent on quantities in IBM-controlled common storage, to determine its operating characteristics. If you or I would write an equivalent to the TRANSMIT utility, we would most probably control its output with either a PARM or a SYSIN keyword that is external to the system. But IBM, being IBM, simply won't do it that way. Still another example concerns the formatting of the TSO Broadcast Dataset, which used to be known simply as SYS1.BRODCAST. When you format a new Broadcast Dataset, using IBM's ACCOUNT and SYNC TSO commands, the number of global Notices records in the new dataset is determined by a binary quantity that has been hard-coded into an IBM load module. To change this quantity (globally--it's the only way), you have to zap the load module and (maybe) IPL. At the very least, MAYBE you can get away with refreshing LLA. I wrote a utility to do this same job, for my forthcoming commercial Broadcast Dataset management package, and it is driven by a SYSIN keyword. You have the flexibility to change the number of global Notices with a SYSIN keyword, so you can do it differently each time you invoke the utility. My question is then: "How could IBM have designed this arrangement so inflexibly?" I think the answer is: Because they controlled the system, and they weren't forced to think about how they could do the job more flexibly to help the users. They didn't force themselves do the job ELEGANTLY. They just got it done THEIR way. And if it wasn't a design that would allow the users to control the situation better, they just didn't bother. It's similar to the situation with the old Linkage Editor, where for 30 years IBM never corrected the artificial limitation that the Object Deck blocksize can't be bigger than 3200. It's a simple correction, and we have zaps to do it (see CBT Tape File 257), but IBM themselves didn't address the problem until they formally rewrote the Linkage Editor to create the BINDER. Most of us lived with that limitation for over 30 years! SANITY CHECKS CAN BE USEFUL TOO One of my own programs is a good example of a large collection of sanity checks, introduced into old and simple code. This is the practical and useful COPYMODS program (CBT Tape File 229) that was originally called COPYTAPE and written by Paul Tokheim. (He is a great grandson of the man who invented the old gasoline pumps.) BTW, you can get anything in the vast CBT Tape collection for free from the CBT Tape website, whose URL can be found by doing a www.google.com search on keywords "CBT Tape" and looking near the top of the list of results. The COPYMODS program works on a very simple principle, designed by Tokheim. Read a block from the tape (using EXCP) into a big buffer that is included in the program. Then write out the contents of this buffer to one or more output tapes (Paul coded up to 10 output tapes--I extended that to 16. Art Tansky, in his modification (see CBT File 229) extended it to 100), if you have that many drives. If you read a tape mark on the input tape, then write a tape mark on all the OPEN output tapes. After two consecutive tape marks, stop the action and CLOSE all the tapes. This seems simple enough, but I had a big problem using COPYMODS on Standard Labeled tapes. Namely (think about it), if you have an SL tape file with no data in it (say, it was created as an IEBCOPY backup of a pds with no members), then after the HDR1 label there is one tape mark, and before the EOF1 label there is another tape mark, and there is no other data in between those two tape marks. So COPYMODS action, seeing those two consecutive tape marks, will stop right there in the middle of the file, and will not go farther to reach the end of the input tape. To solve this, I had to "teach" the COPYMODS program about Standard Labels, and that it should not stop if it "knew" it was in the middle of an SL file, yet it saw two tape marks without seeing any real data yet. I eventually extended this to ASCII tapes with ASCII labels. While I was at it, I realized that I had access to all the tape data as it was passing by, so I could introduce more and more (optional) sanity checks to read, print, measure, and limit copying of the data, if I so wished. To control the many options, I wrote a "PARM and SYSIN parser" that can read keywords to set up to 80 option bits, either singly or in combination. And what eventually happened is, that the entire program, albeit being very useful, became one huge collection of sanity checks. COPYMODS is now at Level 081, up from Level 002. And this was done almost purely by adding more and more sanity checks to it. SUMMARY I think that the programming of utilities, whether you do it, or whether a vendor does it, should adhere to the KISS (Keep It Simple, Stupid) principle as much as possible. Nevertheless, the program's requirements and the necessity of the situation may require the addition of extra code here and there, so the program should work right. IBM, in their programming of (their) utilities, often takes the liberty of realizing that they "own" the MVS operating system. So IBM will often make their utility very dependent on quantities that are present in control blocks, which THEY have put into common storage. This kind of programming, in my opinion, makes many of their utilities less useful, less flexible, and far more "operating system dependent" than is really necessary for proper functioning. I think that IBM would be better served in the long run, if they didn't go "hog wild" in implementing such dependencies. They should code them only if they are really essential for the proper action of the utility. If the customers are really annoyed by this IBM practice, and they can afford it, I'd even go so far as to suggest that they selectively buy non-IBM utility products instead of IBM products. Sanity checks, which are extra blocks of code that are introduced into a program to take care of a contingency, are sometimes needed, but in my opionion, they should be avoided when they are not really necessary. Clean elegant code is usually the most error-free code. Nevertheless, sanity checks, if they make the program work correctly, can be a very useful solution, and if they are coded carefully enough, they can even constitute useful program enhancements. I think that even though this month's topic concerns the writing of code, and not all of us write code, all of us can nevertheless benefit from the effort involved in cleaning and neatening up our thinking. I wish all of you a happy, healthy, and prosperous month, and I'm looking forward to seeing you here again next time.