MVS TOOLS AND TRICKS OF THE TRADE FEBRUARY 2000 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. ASSEMBLER MACRO COLLECTIONS - PART 1 As a longtime practitioner in this field, it is my opinion that Systems Programmers should know how to program. Specifically, we should know something about programming in the mainframe Assembler Language. Assembler programming knowledge provides multiple benefits for the technician and the shop. It'll help you to better diagnose problems--you can read and understand machine code in load modules. (I first learned what a spin loop was, by looking at the looping code instructions in a system module.) It'll also help you to write, or modify, extra system utilities that are very necessary in doing our jobs. IBM doesn't provide us with quite enough tools to make us completely comfortable. We all know that we need more tools to do our normal work, than IBM provides us with. There are various degrees of skill and involvement in assembler programming. We systems programmers don't have to be the greatest programming experts, but we should be able to write a utility program, fix it, and write any system exits that are required or useful for the shop. On the other hand, experienced developers of system programs, who spend their entire days developing code, have different requirements. They need a more organized development environment, with their own appropriate tools in place. The most frequently used tools in an assembler programming development environment are collections of macros. Every assembler programmer, at any skill level, needs to know about macro instructions. Macros are pieces of user-written source code that are invoked by the programmer as though they were single instructions. Prototype macro definitions, which contain the code to accomplish specific tasks, are pre-coded and placed in macro libraries, or lie "internally" in the program itself, between MACRO and MEND instructions. At assembly time, the assembler looks at any "instruction" in the source code that isn't an actual instruction, and checks to see if it is a macro. If the assembler can "find" a macro definition prototype, and indeed, the "instruction" is a macro, the assembler proceeds to look at the macro definition prototype and expands the single macro instruction call into one, or many actual instructions. All this is for the purpose of accomplishing a given action, repetitively, in a simple way. What can be done by coding a macro in an assembler program? For example, you could code one macro, and print a message line. Or you could code a one-line macro to do all the preparation to start, or finish, the execution of a program. A macro can be used to accomplish any (simple or complicated) task in an easy way, as long as the macro definition prototype is pre-coded, in advance, and you've pointed your assembler JCL to the library containing this definition, using the SYSLIB DD statement. Macros make the life of an assembler programmer much simpler, because by the skillful use of macros, you don't have to repeatedly code all the instructions necessary to accomplish repetitive tasks. You just code an execution of one macro, over and over. In the MVS Operating System, macro invocations in assembler programs are a way of life. Access to MVS system facilities is often provided by IBM through documented macro calls. The macro definitions necessary to support these system facilities, are provided by IBM in partitioned datasets known as macro libraries. SYS1.MACLIB and SYS1.MODGEN are the most generally used macro libraries, but some specialized IBM products have their own separate macro libraries as well. To use these IBM macros, their macro libraries have to be concatenated into the SYSLIB DD statement of your assembly JCL. Assembler programmers have also created many of their own user macros, which perform repetitive functions that they don't want to code over and over again. One such example is a pair of user macros which takes care of the "housekeeping" involved in program entry and program exit. IBM's SAVE and RETURN macros, which help us to simplify these functions, aren't specialized enough to automatically establish the program's base registers and load them properly. Or, for writing a re-entrant program, we'd want such macros to GETMAIN a save area and FREEMAIN it afterwards. (GETMAIN and FREEMAIN are macros themselves, provided by IBM to obtain and free some main storage for a program's use.) Therefore many programmers have written their own macros to do this housekeeping job the way they'd like. I've seen pairs of user-written macros called ENTERR and EXIT, or PROLOG and EPILOG, and other similar sets, which do this job nicely, better than the IBM-provided macros do. I was once chairman of the SHARE Assembler committee. This group had the specific function of putting pressure on IBM to improve their Assembler H program, which at that time was IBM's standard Assembler for MVS and VM. Greg Mushial of the Stanford Linear Accelerator Center (called SLAC) had written about 50 enhancements to Assembler H. We (the users) and SLAC itself, wanted IBM to take these improvements over and support them. The eventual result was that IBM listened (after our long campaign) and created the High Level Assembler (HLASM) which incorporated Greg's enhancements, and which is their standard assembler today. In the course of those committee meetings, I had the occasion to talk to some high-powered Assembler developers, from both IBM and other commercial vendors. After one meeting, I took a walk with two authors of very famous products. The single topic of conversation which struck me the most, was that they talked about the absolute necessity of creating a good set of macros for themselves, to use in their development efforts. My own experience in programming, not as heavy as theirs, gave rise to a different view. If I'm modifying some program, not writing my own, I'm happy to work with the macros (if any) that the original author of the program used. These macros are part of the backbone of this author's code; I'm only modifying some particulars. Therefore, I don't usually want to change any of the basic program structure, and I'll normally leave his macros the way they are. I just might invoke them a few more times, if that's necessary for the job I have to do. The common thread in both these points of view, is that you have to know how to invoke macros, and you should have a good concept of how they work. If you're a developer, you might have to write a set of macros for yourself. If you work with someone else's code and use already-written macros, you still have to understand what they're good for, and how to properly invoke them. Today, I'm not going to talk about how to write macros, and how their internals work, using the conditional assembly. Carmine Cannatello's new book, "Advanced Assembler Language and MVS Interfaces" (John Wiley - ISBN 0-471-36176-3) has an excellent chapter on how to write macros. Rather, I'll describe some nice collections of user-written macros which people have written, and we'll get a better idea about what these collections can do for us. WHERE TO FIND MACROS Most of the non-IBM macros you can find, are user-written. An enormous collection of user-written MVS software can be found on the CBT MVS Utilities Tape and the CBT Overflow Tape, which have an online web site available for downloads. You can get to the "Online CBT Tape" web site, by starting from the "Members Area" of the NaSPA home page: www.naspa.net. The CBT Tapes, as I'll refer to both of them, contain large amounts of assembler language source code, which in turn include many assembler macros that you can look at, learn from, and use. In addition, most IBM products have been written using some specialized "internal user macros". Although the typical IBM macros that we normally use, are in SYS1.MACLIB and SYS1.MODGEN, some less common macros that were used for actual IBM product development, are available to us as "IBM Private Macros". Where are the IBM Private Macros? If you obtain machine-readable "Optional Materials" from IBM for a product, which contain source code for some of its programs, you'll find that one or more of the files on these tapes contain macros which were used in the development of that particular product. To spot a file containing macros, look for one file which contains a lot of wildly different member names, as opposed to files containing member names that are mostly very similar to each other. Today, you can't obtain as many of these IBM Private Macros as in the past. That's because many of IBM's products are now "OCO" (distributed to customers as "Object Code Only") and IBM doesn't let you see the source code any more. Nevertheless, quite a lot of the IBM Private Macros are still available today, especially for older products. Between this month and next month, we'll examine some different types of user-written macros that are commonly available, and we'll show you what they're for. The types we'll mention are "Structured Macros", "Internal Macros", "Entry and Exit Macros", and some other types. We'll also show you some miscellaneous collections of macros you can use for various purposes. Once you see a few examples of the enormous jobs that macros can do, you'll understand, by yourself, that there are many more possibilities. STRUCTURED MACROS Dan Snyder has been developing assembler code for almost 30 years, and he's recently donated the entire collection of the assembler macros he's written, to the CBT Tape. Dan's collection will soon appear on the CBT Tape as File 438. We'll end this month's column with a short description of Dan's "structured macros", and we'll continue next month with a description of some other macro types and macro collections. In addition to Dan Snyder's structured macros, there are other collections of structured macros on the CBT Tapes. The Clemson University Structured Macros collection is on Files 107 and 108 of the CBT MVS Utilities Tape. And the HAL collection of structured macros, from Yale University, is on File 188 of the CBT Overflow Tape. All of us probably know what "Structured Programming" means for higher level languages. Structured Programming is a way of keeping your code segmented and neat, often using some standard programming constructs, such as IF-THEN-ELSE segments and DO loops. In Structured Programming, you never branch out of one segment of code, into the middle of another segment. Writing programs in a structured manner makes them easier to debug and test, because many bugs can be isolated to a small segment of a large program. By it's normal nature, Assembler Language code is rather free-form. Practically speaking though, it's a good idea to code Assembler in segments, and not to branch the code out of the segments. But you don't have to. It's a completely different story to make an Assembler Language program look like a higher level language program, by coding IF-THEN-ELSE statements and DO loops, yet keeping the control of knowing what each instruction is doing. Dan Snyder's structured macro system makes it possible for an Assembler Language program look like a high level language program, while retaining the fine-grained control that an Assembler programmer is used to. Dan has written macros called IF, ENDIF, ELSE, ELSEIF, ENDELSE, DO, ENDO, ELSEDO, THENDO, FIRST, ENDFIRST, AFTER, ENDAFTER, NEXT, EVERY, and EDIT. These macros allow the coding of true Structured Programming constructs in Assembler programs, while retaining the traditional Assembler control and efficiency. A very simple example of the use of Dan Snyder's IF and ENDIF macros can be seen in Figure 1. You'll notice that the code generated by these macros is very efficient. If you're used to coding in Assembler, and you also have familiarity with structured coding in higher level languages, you'll definitely be interested in looking at this set of macros. In this same file, File 438, you can also find Dan Snyder's collection of macros to allow you to code an assembler program and make it look like a COBOL program. This second macro collection will help former COBOL programmers migrate their skills to the Assembler arena. Very interesting, curious, and helpful stuff, indeed! Before Version 423 of the CBT Tape will be released, you can download File 438 from: ftp://ftp.cbttape.org/pub/cbttape/adhoc/CBT438.zip . After the official release of Version 423 of the CBT Tape, File 438 will be available at: ftp://ftp.cbttape.org/pub/cbttape/cbt/CBT438.zip . Next month, we'll continue our discussion of user-written assembler macro collections further. I sincerely hope that this material will broaden your horizons. See you then! * * * * * * * * * * * * * * * * * * * * * * Figure 1. A simple illustration of the effect of Dan Snyder's IF and ENDIF macros. Dan Snyder wanted to make his IF macro as simple to use, but as general as possible. Therefore, its four operands are very close in format, to the assembler code that they generate. Its first operand is any instruction that sets the condition code. Its next two operands are the first operand and second operand of the instruction (as in the Principles of Operation manual). Finally, its fourth operand is whatever letter(s) you'd add to the "B" to make a branch mnemonic. For example, you'd code an E for the fourth operand, and the IF macro will generate a "BE" mnemonic instruction, or its functional equivalent. It works as follows: This is an example of how you code Dan Snyder's IF macro: PRINT GEN DISPLAY MACRO EXPANSIONS IF (CLC,FIELDA,FIELDB,E),THENDO MVC OUTPUT(20),FIELDA DO IF FIELDA = FIELDB ENDIF , In this example, the Assembler listing would look like: PRINT GEN DISPLAY MACRO EXPANSIONS IF (CLC,FIELDA,FIELDB,E),THENDO + CLC FIELDA,FIELDB + BNE $MDF0001 MVC OUTPUT(20),FIELDA DO IF FIELDA = FIELDB ENDIF , +$MDF0001 DC 0H'0'