Library of Standard COBOL Macros


Author:A J Marston
Date Created:September, 1984
Date Revised:February, 1993
Version:01.010.009

CONTENTS


1. Introduction

A macro (or pre-compiler directive) is a method of predefining a block of code, whether a single statement or a group of statements, so that the entire block can be incorporated into the program at compile time with a single statement in the source file. It is also possible to define variables within the macro, with particular values being supplied on the source statement. When the source is compiled each macro reference will be "expanded" into the relevant source statements, and any variables will be replaced by the specified parameter values.

A macro is defined with the "$DEFINE %name = ?" statement, which is followed by the contents of that macro and terminated by the # character (an alternative character may be specified if required).

The macro can be referenced anywhere in the program source by entering %name in the relevant place. Each macro must be defined in the source code before it can be referenced. If the macro requires parameters these must be supplied on the source statement in the specified sequence, as follows:

%NAME(parm1#,parm2#,parm3#,parm4#.......)

If the list of parameters is too large to fit on a single line then it should be split as follows:

%NAME(parameter1#,parameter2#,parameter3#
,parameter4#).

Note that each parameter value includes all the characters, including spaces, that occur between the delimiters "," and "#".

All the following macros (unless specified otherwise) are contained in a file called STDMACRO which can be incorporated into the program at compile time by specifying the $INCLUDE STDMACRO statement at the start of the program.

Where the first parameter is designated as Para# it signifies the paragraph name where that macro is being referenced within the program. If the code within the macro detects an error control will be passed to the standard UERROR routine which will include the paragraph name on the diagnostic report before it aborts.

Some of the following macros may call a subroutine to perform the actual processing - please refer to Library of Standard Utilities for more information regarding these routines.


2. General Purpose Macros

2.1 %ID(prog-id#,your-name#,date-written#).

This is for the IDENTIFICATION DIVISION.

2.2 %ED.

This is for the ENVIRONMENT DIVISION. If the compiler switch X1 is set ON then the SOURCE-COMPUTER statement will include the WITH DEBUGGING MODE clause. Any subsequent statements containing a "D" in column 7 will then be compiled into code instead of being left as a comment.

2.3 %BATCHINIT(Progname#,Description#).

This is for batch programs, and initialises the contents of the COMMON-LINKAGE area.

2.4 %DEBUG(Progname#).

If the compiler switch X1 is ON this will generate a series of debugging statements in the DECLARATIVES SECTION. If the program is then run with the ;PARM=1 option it will display a line on the $STDLIST device each time it passes through a section/paragraph while it is executing the code.

2.5 %VERSION(Progid#,Version#,Fix#).

This macro is contained within a separate additional file for each application as it contains hard-coded values that are unique for each application. It enables the program details to be included in the version number printing mechanism.


3. VPLUS screen processing

3.1 %SAVINITFORM(Para#,Formname#).

Load and initialise a new form.

3.2 %ACCEPTENTER(Para#).

Display current form and accept user's response. If a value is loaded into VIEW-FIELD-NAME then the cursor will be positioned on that field. If the ENTER key is pressed the VFIELDEDITS and VFINISHFORM processing will be performed. If the PRINT key is pressed the current screen contents will be printed. If the HELP key is pressed a help screen will be displayed.

3.3 %ACCEPTFUNCTION(Para#).

Display current form and accept user's response (function keys 1-8 only, the ENTER key is not allowed).

3.4 %VGETBUFFER(Para#,Buffername#).

Transfer current data buffer into the program's working storage area.

3.5 %VPUTBUFFER(Para#,Buffername#).

Transfer new data buffer to the screen area before it is displayed.

3.6 %SDVPUTFIELD(Para#).

Similar to VPUTBUFFER, but for a single field only.

3.7 %SCVSETERROR(Para#).

Set the error flag for a field on the current form. The field name must be loaded into VIEW-FIELD-NAME, and the error message must be loaded into VIEW-WINDOW.

3.8 %CONFIRMDATA(Para#,Fkey#,Revalidate#).

After successful validation this allows the user to confirm that the current data is correct (by pressing the specified function key) and should be processed. If the ENTER key is pressed the entire screen contents must be revalidated.

3.9 %CONFIRMDELETE(Para#,Fkey#).

Allows the user to continue or cancel the deletion.

3.10 %BLINKMSG(Para#).

Displays a message on the window line with the blink option set while some processing takes place (eg: a database update). The keyboard is locked until the next user response is required.

3.11 %VAUTOREAD(Para#).

Captures the current screen contents prior to a call to VGETBUFFER by simulating the ENTER key.

3.12 %SFAUTOREAD(Para#).

Same as %VAUTOREAD but includes calls to VFIELDEDITS and VFINISHFORM.

3.13 %SGVCHANGEFIELD(Para#).

Allows the characteristics (enhancement, field type, data type) of a field on the current form to be changed without the need for loading a new form. Please refer to Library of Standard Utilities for more details.

3.14 %USELECT(Reprompt#,Exit#).

Allows the user to select the next transaction by pressing a function key within the current transaction instead of having to exit back to a menu screen. If no selection is made the program should reprompt for input, otherwise it should exit. Please refer to Library of Standard Utilities for more details.

3.15 %USCREENOUT(Para#).

This dumps the current screen contents to a temporary disk file before the program exits back to the menu. See also %USCREENIN.

3.16 %USCREENIN(Para#).

This will reload the previous screen contents (created by %USCREENOUT) back into the program's working storage area when it is resumed. Please refer to Library of Standard Utilities for more details.

It should not be necessary to reference any of the following macros as they are used within the standard software (MENU, MENUSON and UVPLUS). They are included here for documentation purposes only.

3.17 %VPLUSERR(Para#).

Calls UERROR if VIEW-STATUS is unequal to zero. This is included in every macro for a VPLUS intrinsic.

3.18 %VOPENTERM(Para#).

This opens the terminal (VDU) device.

3.19 %OPENUSERFORM(Para#,Name#).

This opens the VPLUS formsfile identified by #Name.

3.20 %VPLUSOPEN(Para#).

Calls both VOPENTERM and VOPENFORMF.

3.21 %VCLOSETERM(Para#).

This closes the terminal (VDU) device.

3.22 %VCLOSEFORM(Para#).

Closes the current formsfile.

3.23 %VPLUSCLOSE(Para#).

Calls both VCLOSETERM and VCLOSEFORM.

3.24 %VSETKEYLABELS(Para#).

Load key labels into VPLUS area so that they can be displayed with the next %ACCEPTENTER or %ACCEPTFUNCTION.

3.25 %VTURNOFF(Para#).

Switches off block-mode processing without closing the terminal.

3.26 %VTURNON(Para#).

Returns to block-mode processing.


4. IMAGE Database accesses

4.1 %IMAGEERR(Para#,Base#,Call#).

Calls UERROR if IMAGE-COND not = zero. This is included in every IMAGE macro.

4.2 %DBOPEN(Para#,Basename#).

Opens the database in mode 1.

4.3 %DBOPEN5(Para#,Basename#).

Opens the database in mode 5.

4.4 %DBLOGGING(Para#,Base#).

Determines if IMAGE Transaction Logging has been turned on.

4.5 %DBCLOSE(Base#).

Close the entire database.

4.6 %DBCLOSE3(Para#,Base#,Dset#).

Reset dataset pointer prior to a serial read.

4.7 %DBFIND(Para#,Base#,Dset#,Item#,Arg#).

Finds a particular chain of entries on a detail dataset.

4.8 %DBFETCH(Para#,Base#,Dset#,Item#,Arg#).

Finds a chain on a detail dataset and reads the first record only.

4.9 %DBFETCHLAST(Para#,Base#,Dset#,Item#,Arg#).

Finds a chain on a detail dataset and reads the last record only.

4.10 %DBGET1(Para#,Base#,Dset#).

Re-read current record.

4.11 %DBGET2(Para#,Base#,Dset#).

Forward serial read.

4.12 %DBGET3(Para#,Base#,Dset#).

Backward serial read.

4.13 %DBGET4(Para#,Base#,Dset#,Arg#).

Directed read. Argument is the record pointer.

4.14 %DBGET5(Para#,Base#,Dset#).

Forward chained read.

4.15 %DBGET6(Para#,Base#,Dset#).

Backward chained read.

4.16 %DBGET5BC(Para#,Base#,Dset#).

Same as %DBGET5, but does not abort if IMAGE-BROKEN-CHAIN is found.

4.17 %DBGET6BC(Para#,Base#,Dset#).

Same as %DBGET6, but does not abort if IMAGE-BROKEN-CHAIN is found.

4.18 %DBGET7(Para#,Base#,Dset#,Arg#).

Calculated read.

4.19 %DBGET8(Para#,Base#,Dset#,Arg#).

Prime calculated read.

4.20 %SETLOCK(Number#,Dset#,Item#,Relop#,Value#).

Sets an entry in the lock descriptor array, which can contain up to 10 entries. The "number" parameter is used both as an index into the array, and the counter for the total number of entries within the array, therefore entries must be defined in strict ascending sequence. The locks will not actually be applied until the %DBLOCK macro is called.

4.21 %DBLOCK(Para#,Base#).

Lock the database using the contents of the lock descriptor array, which is defined using the %SETLOCK macro. This uses subprogram UDBLOCK.

4.22 %DBUNLOCK(Para#,Base#).

Release all locks on the database.

4.23 %DBBEGIN(Para#,Base#).

Identifies the start of a logical transaction (used only if IMAGE Transaction Logging is turned on).

4.24 %DBMEMO(Para#,Base#,Text#,Textlen#).

Allows text to be added to the IMAGE transaction log file (used only if IMAGE Transaction Logging is turned on).

4.25 %DBEND(Para#,Base#).

Identifies the end of a logical transaction (used only if IMAGE Transaction Logging is turned on).

4.26 %DBPUT(Para#,Base#,Dset#).

Adds a new record to the dataset.

4.27 %DBUPDATE(Para#,Base#,Dset#).

Updates the current record on the dataset.

4.28 %DBDELETE(Para#,Base#,Dset#).

Deletes the current record from the dataset.

4.29 %CAPCHECK(Para#,Base#,Dset#).

Calculates the remaining capacity on the dataset and puts the result in IMAGE-SPARE-CAP.

4.30 %DBCOMPAREM(Para#,Base#,Dset#,Arg#).

This will re-read a master record into a secondary area and compare it with the previous contents. To be used before updating. Requires the statement "COPY COMPARE IN STANDARD" to define the secondary area in the program's working storage section. VEDIT-ERRORS will be set if the compare fails, and an error message will be loaded into VIEW-WINDOW.

4.31 %DBCOMPARED(Para#,Base#,Dset#,Recno#).

This will re-read a detail record into a secondary area and compare it with the previous contents. To be used before updating. Requires the statement "COPY COMPARE IN STANDARD" to define the secondary area in the program's working storage section. VEDIT-ERRORS will be set if the compare fails, and an error message will be loaded into VIEW-WINDOW.


5. KSAM file accesses

5.1 %KSAMERR(Para#,File#).

Calls UERROR if KSAM-STATUS not = zero. This is included in every KSAM macro.

5.2 %CKSTART(Para#,file#,relop#,key#,keyloc#,keylen#).

Position pointer prior to a sequential read.

5.3 %CKREAD(Para#,file#).

Sequential read.

5.4 %CKLOCK(Para#,file#).

Lock the entire file.

5.5 %CKDELETE(Para#,file#).

Delete the current record.

5.6 %CKUNLOCK(Para#,File#).

Unlock the file.

5.7 %CKREADBYKEY(Para#,file#,key#,keyloc#,keylen#).

Read a record using the key value supplied.

5.8 %CKREWRITE(Para#,File#).

Update the current record.

5.9 %CKWRITE(Para#,File#).

Add a new record.

5.10 %CKOPEN(Para#,File#).

Open the file for exclusive access.

5.11 %CKOPENSHR(Para#,File#).

Open the file for shared access.

5.12 %CKCLOSE(Para#,File#).

Close the file.


6. Date Conversion

6.1 %DMY2YMD(Indate#,Outdate#).

Changes date from DD/MM/YY to CCYYMMDD.

6.2 %MDY2YMD(Indate#,Outdate#).

Changes date from MM/DD/YY to CCYYMMDD.

6.3 %YMD2DMY(Indate#,Outdate#).

Changes date from CCYYMMDD to DD/MM/YY.

6.4 %YMD2DDMMMYY(Indate#,Outdate#).

Changes date from CCYYMMDD to DDMMMYY (eg: 28JAN91).

6.5 %UDATEERR(Para#).

Calls UERROR if UDATE-STATUS is unequal to zero.

6.6 %TOJULIAN(Para#,Date#).

Convert date from CCYYMMDD to DDDDDDDDD, with result in JULIAN-DAYS. If UDATE-STATUS <> zero VIEW-WINDOW will contain an error message. This also sets UDATE-DAY-OF-WEEK to indicate the day name.

6.7 %TOGREGORIAN(Para#,Days#).

Convert date from DDDDDDDDD (JULIAN-DAYS) to CCYYMMDD, with result in GREGORIAN-DATE. Check UDATE-STATUS for possible errors.

6.8 %DAYOFWEEK(Para#,Date#).

Contains %TOJULIAN and %UDATEERR.

6.9 %UWEEK(Para#,Date#,PIC S9(4) COMP#).

This takes a date in the format CCYYMMDD and returns the corresponding week number in the format YYWW. According to international standards each week starts on a Monday, and week 1 of any year is the first week that contains a Thursday. These are the default values that have been defined in UDATE-DAY1-OF-WEEK and UDATE-WEEK1-CONTAINS, but these may be changed if required, using the value 0=SUN, 1=MON, 2=TUE, etc.

6.10 %WEEKENDING(Para#,Input Date#,Output Date#).

This takes a date in the format CCYYMMDD and sets GREGORIAN-DATE to the corresponding week-ending date. Uses UDATE-DAY1-OF-WEEK to show the first day of the week (default = 1 for Monday).


7. Number Conversion

The UNUMBER routines are used to convert a number in display format to a computational value so that it can be used within a program. The input value must have been validated and SET via a VPLUS screen. The output value must be large enough to contain the input value, and must be defined with the correct number of decimal places.

The BNUMBER routines are used to convert values which have not been input via a VPLUS screen, and therefore require a parameter to indicate the number of decimal places that the number should contain, and a status area to indicate invalid input.

7.1 %UNUMBER1(Input#,S9(4) COMP#).

Converts the input value to 1 word binary.

7.2 %UNUMBER2(Input#,S9(9) COMP#).

Converts the input value to 2 words binary.

7.3 %UNUMBER4(Input#,S9(18) COMP#).

Converts the input value to 4 words binary.

7.4 %UNUMBERP8(Input#,S9(7) COMP-3#).

Converts the input value to 3 words packed decimal.

7.5 %UNUMBERP12(Input#,S9(11) COMP-3#).

Converts the input value to 4 words packed decimal.

7.6 %BNUMBER1(Input#,S9(4) COMP#,Decimals#).

Converts the input value to 1 word binary.

7.7 %BNUMBER2(Input#,S9(9) COMP#,Decimals#).

Converts the input value to 2 words binary.

7.8 %BNUMBER3(Input#,S9(11) COMP-3#,Decimals#).

Converts the input value to 3 words packed decimal.

7.9 %BNUMBER4(Input#,S9(18) COMP#,Decimals#).

Converts the input value to 4 words binary.


8. Text Manipulation

The %UCENTER, %ULEFT, %URIGHT, %UPSHIFT and %DOWNSHIFT macros require the input string to be moved into UTEXT-INPUT beforehand. The result will be placed in the output area. The length must be in the range 1-80 characters.

8.1 %UCENTER(Length#,Output-area#).

Shift the characters into the centre of the string.

8.2 %ULEFT(Length#,Output-area#).

Shift the characters to the left of the string.

8.3 %URIGHT(Length#,Output-area#).

Shift the characters to the right of the string.

8.4 %UPSHIFT(Length#,Output-area#).

Change all lower case characters to upper case.

8.5 %DOWNSHIFT(Length#,Output-area#).

Change all upper case characters to lower case.

8.6 %SOUNDEX(String#,Key#).

This will produce a soundex value (format Annn) from an input string of up to 80 characters in length.

8.7 %USTRING(Data#,Maxlength#).

The macro and data areas are defined in copy library member USTRING. This is to be used before accessing a KSAM file to determine whether the user's selection criteria contains a trailing asterisk or not. A trailing asterisk signifies that a generic search is required rather than an exact match. The result will be contained in USTRING-STATUS.


9. Bit Manipulation

These routines allow individual bits within a 2-byte word to be set, unset, or examined. The bits are numbered 0 to 15, from left to right. Only one bit can be processed with each call.

9.1 %SETABIT(Target-word#,Bit-number#).

Ensures that the bit in the target word is set to 1 (ie: ON).

9.2 %UNSETABIT(Target-word#,Bit-number#).

Ensures that the bit in the target word is set to 0 (ie: OFF).

9.3 %TESTABIT(Target-word#,Bit-number#).

Checks to see if the specified bit in the target word is either ON or OFF. The result is returned in BIT-RESULT.


10. Miscellaneous

10.1 %COMMAND(commandname#).

Passes a string to the COMMAND intrinsic. The result will be returned in CMND-ERROR (0=OK, <0=WARNING, >0=ERROR).

10.2 %COMMANDERR(Para#).

If the COMMAND-CIERROR condition is set this will abort the program.

10.3 %SYSTEMERR(Para#).

This will cause the program to abort. A non-zero value should be placed in MENU-SYSTEM-ERROR, and an error message should be placed in VIEW-WINDOW.

10.4 %MPEFILEERROR(Para#,Filename#,Filenum#).

If an error occurs while using the MPE intrinsics to access a file this macro will call the UERROR routine to abort the program , with the diagnostic print containing the relevant error number and message.

See also %MPEFILESTATUS.

10.5 %UPAUSE(Para#,Seconds#).

This will cause the program to pause for the specified number of seconds.

10.6 %TIMESTAMP(HHMMSS#,HH:MM:SS#).

This will convert a time from HHMMSS to HH:MM:SS.

10.7 %PUTJCW(jcwname#,value#).

This will set the jcw (job control word) with the specified name to the specified value. The jcw name can be up to 72 characters. The jcw value must be in the range 0-9999.

10.8 %FINDJCW(jcwname#).

This will return the value associated with the specified jcw. The result is returned in JCW-VALUE. If the jcw name does not currently exist the value is set to zero.

10.9 %BYTEADDRESS(Item#,Address#).

This will return the byte address for the specified data item.

10.10 %WORDADDRESS(Item#,Address#).

This will return the word address for the specified data item.

10.11 %OPENUSERMSG(Para#,Name#).

This will open the message catalog with the specified name. It should be included in the USEROPEN routine.

10.12 %READUSERMSG(Para#,Buffer#,Buflen#).

This will retrieve a message from the message catalog. It is used within the UVPLUS routines to retrieve text for window messages and function key labels.

10.13 %CLOSEUSERMSG(Para#).

This will close the message catalog. It should be included in the USERCLOSE routine.

10.14 %OPENUSERHELP(Para#,Name#).

This will define the name of the application help catalog. It will not actually be opened until the HELP key is pressed, and will be closed when the user leaves the help subsystem.

10.15 %MPEFILESTATUS(Para#,Filename#,Status#).

This will decode the status value where an error occurs with a file that has the "FILE STATUS IS <dataname>" clause included in the SELECT statement. If the filename is a literal (ie: not a dataname) it must be included in quotes.


11. Accessing the Menu Database

Subprograms running under the MENUSON process cannot access the MENU database directly as it is opened only by the parent MENU process. The following macros will communicate with the parent MENU process which will access the database and return the results.

11.1 %GETMENUTRAN(Para#,Tran-code#).

Reads the M-TRAN dataset of the MENU database. Requires copy library member MENUMC IN STANDARD to be defined in working storage.

11.2 %GETMENUUSER(Para#,User-id#).

Reads the M-USER dataset of the MENU database. Requires copy library member MENUMD IN STANDARD to be defined in working storage.

11.3 %GETMENUPRINTER(Para#,Printer-id#).

Reads the M-PRINTER dataset of the MENU database. Requires copy library member MENUME IN STANDARD to be defined in working storage.

11.4 %USTREAMFIND(Para#).

This will transfer the specified jobstream from the command file on the MENU database to file $OLDPASS. Requires copy library member USTREAM IN STANDARD to be defined in working storage. If an error is found VIEW-NUMERRS will be set, and an error message will be placed in VIEW-WINDOW.

11.5 %USTREAMVALIDATE(Para#).

This follows the %USTREAMFIND macro. It validates the printer name and the parameter values entered by the user. If PRINTER-STATUS <> 0 then the printer name is invalid. If PARAM-STATUS <> 0 then the corresponding value supplied by the user is invalid. VIEW-WINDOW will contain the relevant error message.

11.6 %USTREAMXEQ(Para#).

This follows the %USTREAMVALIDATE macro. It will insert the user's parameter values into the jobstream and stream it. If an error is found USTREAM-CIERR will be set, and the relevant message will be placed in VIEW-WINDOW.


12. Accessing MSG/IPC Files

Message files (or Inter Process Communication files) provide a mechanism for one process, or even several processes, to communicate with another.

12.1 %MSGFILEDEFINE(Name#).

Defines all the data items required to access the MSG file. The file must be opened and closed within the same module as the file name and number are not passed around in USER-LINKAGE. The record layout must be appended to this area.

12.2 %MSGFILEDEFINE2(Name#).

Same as %MSGFILEDEFINE, but without the file name and number. These must be defined in USER-LINKAGE, which makes the file accessible to other modules.

12.3 %MSGFILEERROR(Para#,File#).

Calls the UERROR routine in the event of an error.

12.4 %MSGFILEOPENR(Para#,File#).

Opens the file for read access (single reader only). Sets the record length in <name>-RECLEN, and calls %MSGFILECOUNTERS.

12.5 %MSGFILECOUNTERS(Para#,File#).

Sets the following values for the specified MSG file:

<name>-RECORD-COUNT the number of records in the file
<name>-RECORD-LIMIT the file limit
<name>-WRITER-COUNT the number of current writers to the file
<name>-READER-COUNT the number of current readers of the file

12.6 %MSGFILECONTROL(Para#,File#,Option#,Value#).

Calls the FCONTROL intrinsic to set an option either ON or OFF. For example:

Option 45, value 1 do not return an END-OF-FILE condition even if the file is empty and there are no more write accessors (ie: continue waiting for input).
Option 45, value 0 allows an END-OF-FILE condition to be returned after the last record has been read and there are no more write accessors.
Option 47, value 1 set the next read to be non-destructive.
Option 47, value 0 set the next read to be destructive.

12.7 %MSGFILEOPENW(Para#,File#).

Opens the file for write access (multiple writers). Sets the record length in <name>-RECLEN, and calls %MSGFILECOUNTERS.

12.8 %MSGFILEOPENW2(Para#,File#).

Same as %MSGFILEOPENW, but does not abort if the FOPEN fails. This allows the program to deal with the error without aborting.

12.9 %MSGFILEWRITE(Para#,File#).

Writes a record to the MSG file, then calls FCONTROL option 6 to flush the buffer to ensure that no data is lost (by default the file system will wait until the buffer is full before it writes to disc, and if a system crash occurs the current buffer is lost).

12.10 %MSGFILEREAD(Para#,File#).

Reads the first available record from the file, and destroys it unless the non-destructive read has been set. All subsequent reads will retrieve the same record until the destructive read is set on. The END-OF-FILE condition is not returned until the file is empty and there are no more write accessors, but an FCONTROL option can be set to wait even though there are no more writers.

12.11 %MSGFILECLOSE(Para#,File#).

Closes the MSG file.

- END -

counter