Click here for RAC Consulting sponsor message |
Using COBOL Macros
By Shawn M.
Gordon
By Shawn Gordon
For those of you who were waiting and waiting for this
issue, your patience is finally rewarded. I am at long last going to
uncover the mystery of COBOL macros for you. I personally found out about
macros by reading a column in a magazine around 10 years ago, and have been
in love with them ever since.
There are still a huge number of people that dont know what they are, let alone how to use them. I recently had to fill about 10 contract programmer slots for a client, and in the process of interviewing about 40 people only found three that had ever heard of or used COBOL macros. So if this topic is new to you, dont feel bad youre in good company.
What are COBOL macros? Well, they are an HP extension to the ANSI COBOL standard. Since they are an HP extension, it means that you wont see them in any other COBOL out there. On the upside, our very own SIGCOBOL special interest group has gotten pretty involved with the COBOL ANSI committee, and are pushing very hard to get the macros put into the COBOL standard. So hopefully in the next couple of years you will see this wonderful extension added to the standard.
Basically, a COBOL macro is a way to predefine code that can accept replacement parameters. This code is then resolved inline at compile time. The upside to this versus using a paragraph is that the code is inline and no branching takes place to execute it so you get slightly lower overhead and faster execution speeds. The downside is that your compiled listing can bloat up enormously over your source listing.
I will typically have a 1,500 line program easily double in size in the compile listing but then I use macros for everything: from database calls, to terminal IO to system intrinsic usage. Basically I put all of my reusable routines inside macros instead of in paragraphs. Here is a simple example of using a macro to display information:
$DEFINE %MYDISPLAY=
DISPLAY !1 NO ADVANCING#
%MYDISPLAY(This is some text#).
The major thing to get out of this example is the $DEFINE must take place in column 7. The compiler sees a $ in column 7 as a compile time directive. The name of your macro can be anything, but must start with a %, unless you have redefined it, which I will get into in a moment. The macro definition can be as many lines as you want all you need to do is use a # at the end of the last line to terminate it.
Now the period terminator creates an interesting problem for us. Keeping in mind that the text is literally replaced, if you use a period inside the macro then you probably wont be able to use the macro in an IF statement. However, if you leave the period out of the macro you will need to put a period at the end of the use of the macro, as I did in the above example.
Now in the use of the macro, we use the same %MYDISPLAY, and then in parenthesis we put in our replacement parameters. Each replacement parameter is delimited by a # sign and is positional, so the first parameter will replace !1 in the macro, the second parameter will replace !2, and so on.
The above example doesnt illustrate this very well
so how about we define a DBGET and DBEXPLAIN to illustrate two
points? The first point is using multiple replacement parameters, the
second point will be how to call one macro from inside another macro.
$DEFINE %DBEXPLAIN=
DISPLAY `Error location: !1
CALL DBEXPLAIN USING !2#
$PREPROCESSOR PARMCHAR=^, DELIMITER=@
$DEFINE %DBGET=
CALL DBGET USING ^1,
^2,
^3,
^4,
ALL-LIST,
^5,
^6@
IF NOT DB-CALL-OK
%DBEXPLAIN(!7#,!4#)
END-IF#
$PREPROCESSOR PARMCHAR=!, DELIMITER=#
%DBGET(MYBASE#,MYSET#,MODE7#,DB-STATUS-AREA#,MYBUFF#,MYARGUE#
,B1000: Getting MYSET#).
Take note of one thing in the use of the DBGET macro: When
we have to continue on another line, the comma must precede the argument on
the next line it cant be left trailing on the previous line. I
never found out why this was true, and have ceased to care.
Now take a look at the $PREPROCESSOR statement. This allows us to redefine what characters are used inside of a macro to indicate the various delimiters. This is important if you want to call one macro from within another macro that takes parameters. If it doesnt take parameters then it doesnt matter.
One last item on macros to keep in mind is that they can be defined anywhere you want. That means that you could put your DBGET macro definition in the WORKING STORAGE section, or IDENTIFICATION DIVISION, or even before the $CONTROL line. I personally define them at the top of the PROCEDURE DIVISION. Also remember that you can use them for anything, this means you can also do something like;
$DEFINE %MAXCHAR=50#
01 FIRST-NAME PIC X(%MAXCHAR#) VALUE SPACES.
I havent personally found this useful, but I have
seen other people do it.
Well, thats it for this month I hope it was
worth the wait. Keep those cards and letters coming, and earn yourself a
free 3000 Always Online hat for tips you submit, either to the NewsWire or
to me at smga@compuserve.com.
Shawn Gordon, whose S.M. Gordon & Associates firm
supplies HP 3000 utilities, has worked with 3000s since 1983.Shawn M.
Gordon, whose S.M. Gordon & Associates firm supplies HP 3000 utilities,
has worked with 3000s since 1983.
Copyright 1998, The 3000 NewsWire. All rights
reserved.