This part treats some more advanced or specialized topics. The production of
multiple reports, and the development of user-written extensions (
functions and file handlers) are also described.
Multiple Reports
COBOL Report Writer provides a means for producing either one physical file from
several reports, or several physical files from one report description. The following sections describe each case:
Several Reports to One Physical File
This is indicated when you write the clause
REPORTS ARE report-name-1 report-name-2 ...
|
in the FD entry for the report file. The different reports may be written either
successively, alternately, or concurrently to the
file.
Successive Reports
This describes the case when each successive report is processed through from
INITIATE to the final TERMINATE and is then not accessed again:
INITIATE report-name-1
GENERATE report groups in report-name-1
...
TERMINATE report-name-1
INITIATE report-name-2
GENERATE report groups in report-name-2
...
TERMINATE report-name-2
|
This method is free of complications and has useful applications. One example is the case where a report has a front section or a trailing section, too complex too
describe as a REPORT HEADING or REPORT FOOTING:
very complex "report heading"
| < Instead of automatically using
< a REPORT HEADING, remember
< that this could be a report in
its own right. |
| |
| |
body of report
|
|
| |
| |
very complex "report footing"
| < This might also be a
< separate "report".
|
| |
The "Report Heading" might have several parts, and the "Report Footing" might have many complex parts, totals, etc. You might instinctively try to describe this complex layout using
a single RD, because it has been designed as a single report. Remembering that a "report file" may be composed of several "logical reports", you now re-code the
layout using three RDs:
FD print-file
...
REPORTS ARE HEADING-REPORT, MAIN-REPORT, TRAILING-REPORT.
...
RD HEADING-REPORT
...
RD MAIN-REPORT
...
RD TRAILING-REPORT
...
|
and code the INITIATE, all the GENERATEs and the TERMINATE for each report in tandem. Assuming that each RD has a
PAGE clause, each report
will begin on a new page, as required.
This example assumes that you have no page numbering in the "Report Heading" or "Report Footing", and that you start with a page number of
one in the main
report. If you do require page numbering throughout, remember that each report has its own separate
PAGE-COUNTER. Assuming that the page numbers are to run in sequence
throughout the report, you must carry forward the PAGE-COUNTER after each TERMINATE, as follows:
PROCEDURE DIVISION.
...
INITIATE HEADING-REPORT
GENERATE heading-groups ...
TERMINATE HEADING-REPORT
*
INITIATE MAIN-REPORT
ADD 1 PAGE-COUNTER IN HEADING-REPORT GIVING PAGE-COUNTER IN MAIN-REPORT
(process main report)
TERMINATE MAIN-REPORT
*
INITIATE TRAILING-REPORT
ADD 1 PAGE-COUNTER IN MAIN-REPORT GIVING PAGE-COUNTER IN TRAILING-REPORT
GENERATE trailing-groups ...
TERMINATE TRAILING-REPORT
|
Alternating-Page-Format Reports
You may encounter the case where a report consists of two or more alternating page formats, such as details of area A...summary page for area A details
of area B...summary page for area B..., where each page format begins on a fresh page and has different PAGE HEADING, PAGE FOOTING and body groups from the others:
Page Heading for detailed report
AREA A
DETAILED REPORT
| < Detailed report headings are
< problem.
|
. . . . . . . . . . . . . . . . . | |
. . . . . . . . . . . . . . . . . | |
: | |
Page Heading for summary report
SUMMARY FOR AREA A
SUMMARY REPORT
| < You cannot code this page as a
< CONTROL FOOTING because the
page headings are completely
different.
|
| |
Page
Heading for detailed report
AREA B
DETAILED REPORT
| < Here the page headings return
< to the first layout.
|
. . . . . . . . . . . . . . . . . | |
. . . . . . . . . . . . . . . . . | |
: | |
Page Heading for summary report
SUMMARY FOR AREA A
SUMMARY REPORT
|
|
When approaching this problem, keep in mind the points made under Successive Reports above. This time, we keep
both reports initiated. (If not, the
page numbering will return to 1 after each INITIATE, and there will be problems if, say, we want to produce grand totals at the end of the reports.) The following
is one possible solution.
FD print-file ...
REPORTS ARE DETAILED-REPORT, SUMMARY-REPORT.
...
RD DETAILED-REPORT
...
RD SUMMARY-REPORT
...
*
PROCEDURE DIVISION.
...
INITIATE DETAILED-REPORT, SUMMARY-REPORT
obtain first input record
PERFORM UNTIL end-of-file
GENERATE detailed-groups ...
IF change in AREA code
MOVE PAGE-COUNTER IN DETAILED-REPORT
TO PAGE-COUNTER IN SUMMARY-REPORT
GENERATE summary-groups
MOVE PAGE-COUNTER IN SUMMARY-REPORT
TO PAGE-COUNTER IN DETAILED-REPORT
END-IF
obtain next input-record
END-PERFORM
TERMINATE DETAILED-REPORT, SUMMARY-REPORT
|
(An alternative solution is to use an expression made up from both PAGE-COUNTERs, for example:
05 COL 100 "PAGE:".
05 COL + 2 PAGE-COUNTER IN DETAILED-REPORT +
PAGE-COUNTER IN SUMMARY-REPORT - 1.)
|
Because you are not doing a TERMINATE and INITIATE on each occasion that you "switch reports", they will not necessarily always resume on a fresh page.
Consider each report separately and decide how you would make it resume on a fresh page if the other report were not there. For example, you might begin after each "switch" with a
GENERATE of a DETAIL group with a low absolute LINE number; or you might use the
NEXT GROUP NEXT PAGE clause in a dummy CONTROL HEADING;
or you might simply code MOVE footing-integer TO LINE-COUNTER IN next-report-name before resuming.
Concurrent Reports
There are two quite unconnected cases to discuss here:
a. One report built up from several alternating RD's.
Here, you GENERATE output via two or more RDs associated with the same report file without necessarily waiting for a page advance before switching from one report to another.
It can be difficult to use this method, because each report keeps its own LINE-COUNTER and control break information. Each report will therefore act as though it alone had
control of the page format. Although no serious breakdown is likely at run time, you will have to take special steps to ensure that pages terminate at the correct point. To do this,
you will need to MOVE one LINE-COUNTER to another in much the same way that the PAGE-COUNTERs are dovetailed in the section on "Successive Reports" above.
If you specify the same control-ids in each report, remember that each possible control break will occur in each report separately, when it is GENERATEd.
b. Distinct reports spooled to the same file.
Here, several reports are written to the same file but are distinguished by means of the CODE (see CODE Clause). This technique was commonly
used in the past when print data was spooled onto tape or disk. Several reports could be written to the same spool file by marking the print records of each report with an identifying
character, characters, or identifier of any length. De-spooling software then passed through the spool file, each time selecting only those print records beginning with a certain
identifying character. (It was possible to sort the records, but this is usually much less efficient.) As example, you might have had two reports:
FD PRINT-FILE ...
REPORTS ARE REPORT-A REPORT-B.
...
RD REPORT-A ...
CODE IS "A" ...
*or: CODE IS mnemonic-name
*and put in SPECIAL-NAMES: "A" IS mnemonic-name
01 ...
...
RD REPORT-B ...
CODE IS "B" ...
01 ...
...
|
The reports were both written to the same file, but you there was no problem in separating them as the reports eventually appeared as separate outputs, thanks to their distinguishing codes.
A utility to separate and print the physical reports is not provided as a part of the report writer software, and users who developed a utility program to handle the output produced by
OS/VS and DOS/VS COBOL's built-in report writer with a CODE clause should use the same program to handle the output from report writer.
Several Outputs From the Same RD
There are two cases to be reviewed for this topic:
a. Identical copies of the same physical report.
Following the ANS-74/85 standards, report writer does not allow you to assign your report to more than one file. This is more restrictive than the ANS-68
standard used in OS/VS and DOS/VS COBOL, which allows up to two files. If you require two or more identical copies of the same physical report, you should try
to achieve this through Operating System commands, or you should write an Independent Report File Handler (see 5.3) that executes a WRITE for each of several files for each
report line.
b. Different reports with similar formats going to different files.
In a program with several reports, you may find that two or more report layouts are
identical, or nearly so, and you naturally want to avoid duplication of code. The
DUPLICATED clause is designed for this purpose. The following diagram shows a case with three files.
+---
------------------------+
|  
|
| similar report format |
| (one
Report Description) |
|  
|
+---------------------------+
/ |
\
+-----------------+ +-----------------+ +-----------------+
| | |
| | |
| report number 1 | | report number 2 | | report number 3 |
| | |
| | |
+-----------------+ +-----------------+ +-----------------+ |
Although the layouts are similar, the contents of the reports may be quite different (as distinct from case a where all output is simply printed
twice). The DUPLICATED clause (see Report Files) sets up the given number of separate report control areas, each with its own PAGE-COUNTER, LINE-COUNTER
, totals, control break indicators, Page Buffer, etc. They are distinguished by the value of the special register
REPORT-NUMBER which is defined by
report writer in every program that has a DUPLICATED clause. You may "switch" output to your selected report by storing a value from 1 to the maximum number of duplicates in REPORT-NUMBER.
Output goes to only one of the reports at any given time. Although there are several separate physical files, only
one SELECT clause and one FD entry are
coded, and one OPEN and CLOSE is executed. Despite your own OPEN statement, a file is actually opened only when the report whose number is held in REPORT-NUMBER
is first INITIATEd.
If REPORT-NUMBER is zero when the INITIATE is executed, all the reports are INITIATEd. The
CLOSE operation
(not the TERMINATEs) closes all the files that were opened. The value of REPORT-NUMBER is immaterial when you OPEN and CLOSE. You may
MOVE ZERO to REPORT-NUMBER and do a single TERMINATE. This will TERMINATE all the reports that were INITIATEd. If REPORT-NUMBER is not zero when a TERMINATE is executed, only the corresponding
report is terminated.
The report layouts need not be identical in all respects. You may vary the entries "present" from one report to the next by using the
PRESENT WHEN clause, and you
may vary the contents by the same means or by using SOURCE identifiers subscripted by REPORT-NUMBER. The DETAIL groups may even be different for each of the reports, since
you can of course choose at any time which DETAIL groups to GENERATE. Therefore the
DUPLICATED clause may still save you coding time even if there are notable differences
in the layouts of the report groups.
At run time, report writer will vary the for each of your multiple print files by appending to it the two digits
01 (for the first file) up to nn for the last file, where nn is the integer in your DUPLICATED clause. If you specify a DDname of more than six characters, characters 7 and 8 of your DDname
are overwritten. For example:
SELECT FILEA ASSIGN TO LST DUPLICATED
3 TIMES
|
expects your to be LST01, LST02 and LST03, and
SELECT...ASSIGN TO LISTINGF DUPLICATED 16
TIMES
|
expects your to be LISTIN01 through LISTIN16.
The following sample of coding shows how these techniques are used:
FILE-CONTROL.
SELECT REPORT-FILE ASSIGN TO PRINTF
DUPLICATED 3 TIMES.
...
FD REPORT-FILE
...
REPORT IS STOCK-REPORT.
...
REPORT SECTION.
RD STOCK-REPORT ... .
01 STOCK-LINES TYPE DE.
03 LINE + 2.
...
*The following is a subheading that is different in each report:
05 COL 120 PIC X(20) SOURCE WS-DESCRIPTION (REPORT-NUMBER).
*The following line is not generated in report #1:
03 LINE ABSENT WHEN REPORT-NUMBER = 1.
...
PROCEDURE DIVISION.
...
*Report file is opened only once
*even though it represents 3 potential files
OPEN OUTPUT REPORT-FILE *> intercepted by report writer
...
*If report #1 is required during this run:
MOVE 1 TO REPORT-NUMBER
INITIATE STOCK-REPORT
...
*and, in general, if report #n is required:
MOVE n TO REPORT-NUMBER
INITIATE STOCK-REPORT
...
*When output is sent to report #1, for example:
MOVE 1 TO REPORT-NUMBER
GENERATE STOCK-LINES
...
*and, in general, when output is sent to report #n:
MOVE n TO REPORT-NUMBER
GENERATE STOCK-LINES
...
*to terminate all of the 3 reports that may have been initiated:
MOVE 0 TO REPORT-NUMBER
TERMINATE STOCK-REPORT
...
*or, to terminate just report #1:
MOVE 1 TO REPORT-NUMBER
TERMINATE STOCK-REPORT
...
CLOSE REPORT-FILE.
|
If you refer to LINE-COUNTER, PAGE-COUNTER, a total field, or any of the other special registers within the Report Control Area, the actual location
accessed will be the one belonging to the report for which the most recent INITIATE, GENERATE, or TERMINATE was performed. For example, if you wish to reset PAGE-COUNTER in each
of your reports in the multiple set, you should define a dummy DETAIL group (one having no LINEs) and code the following:
MOVE 1 TO REPORT-NUMBER
GENERATE DUMMY-GROUP *>needed to make Report #1 current
MOVE 0 TO PAGE-COUNTER
MOVE 2 TO REPORT-NUMBER
GENERATE DUMMY-GROUP
... etc. ...
|
If you use a procedural statement, such as a MOVE, to store a value directly into a named field in one of your REPORT SECTION lines, the new contents will take effect for all the
reports of the multiple set, because the report lines produced by report writer are shared by each of them.
Developing User-Written Functions
The Need for Functions
The FUNCTION clause, which is described from the user's point of view under 3.7 FUNCTION Clause, allows you to develop your own function routines as well
as to use certain built-in functions, such as DAY, MDATE, and TIME. A user-written function allows you to display report data in a way peculiar
to your installation.
User-written
functions are especially effective when needed in many separate programs, as they provide a standard way of displaying certain codes or other items of information peculiar
to the user site. Indeed a commitment to "think functionally" may greatly improve efficiency throughout a programming department. To convince yourself of this, consider the
following scenario, before the introduction of functions:
Many report programs require the programmer to code a table of descriptions or names directly into the Working-Storage of the program. Perhaps at first only a few
report programs of this type are written, so that, even when some extra codes are added to the table and all those programs have to be re-compiled, no one objects too strongly.
Suddenly a large number of new programs are written that require the same names. Some programmers code the table from scratch; others prefer to take a copy from a working program.
Business conditions then change and many new codes are added to the table. Dozens of programs have to be changed. Any change requires retesting of whole suites of programs. Each
program has its own particular way of encoding the table, so an amendment becomes a major undertaking. At the end of it, no one is absolutely sure that all the programs affected have been
found and amended.
When the next major change becomes necessary, some one decides that from now on all the codes will be held in a static "table file". New programs are guaranteed to be independent
of the codes and names, but there is a penalty to be paid in each program, because of all the extra steps needed to OPEN, READ and CLOSE the file in the program.
Later, there might be a general change from traditional files to a database, so all the programs have to be amended again.
Through the use of functions from the outset, programs can be made independent of all these changes. The program will be shorter and the programmer need not worry about how
the report field is created. Control over specification and change becomes more assured.
How To Write a Function Routine
As designer of a function routine, you have a free hand to transform the data in any desired way, provided that the print data that results fits within the limits of the print
field described by the programmer in the associated PICTURE clause.
Most function routines are COBOL subprograms with a standard LINKAGE SECTION, but they may also be written in any programming language that can be CALLed by COBOL. The use
of COBOL normally prevents the number of parameters passed to the FUNCTION from being variable (a minor benefit). Since they are "normal" programs, function routines may
use any files or databases that are available to other programs, may CALL other subprograms, and may store intermediate results in their own Working-Storage.
The number of relevant characters returned in the output (report) field may
vary, thus enabling the same function routine to handle different sizes and formats, for example
"date" formats with different arrangements of day, month, and year. The size and format of the user-coded parameters (if any) are usually prescribed by
the function routine and cannot vary, unless the designer decides to specify an additional parameter to indicate which of a choice of formats the input is in. All parameters are passed
"by reference" so, although they normally pass data only into the function routine, they may also be used to pass updated data
back to the user program.
The function routine is used in the program via the FUNCTION Clause (see 3.7), and the programmer need not be aware of the precise mode of operation of the function
routine. The description of the built-in functions is also given in 3.7 - FUNCTION Clause. User-written functions may be similarly specified and added to this publication
in an appropriate place.
The program name of the function routine should be Rnxxxxxx, where xxxxxx is the mnemonic name of the function of no more than 6 alphanumeric characters
and n is the number of parameters to the function. For example, if the function is called
COUNTY and takes one parameter, you must write a function module with the
program-id: R1COUNTY otherwise. If the same function has a variable number of parameters, separate function routines must be written (although they may all call a
common subordinate routine).
The parameters to the function routine are as follows:
Parameter 1: Function Control Area, consisting of:
2 bytes binary: number of user-coded parameters present in FUNCTION
clause, i.e. excluding internal parameters 1 and 2;
2 bytes binary: total size of field, in bytes, or, if field is
edited, its equivalent de-edited size;
2 bytes binary: size in bytes of parameter #1 of FUNCTION, if any
2 bytes binary: size in bytes of parameter #2 of FUNCTION, etc.
Parameter 2: report field; if edited, de-edited intermediate field;
Parameters 3,4... (optional) parameters as defined in FUNCTION clause.
Sample COBOL Function Routine
IDENTIFICATION DIVISION.
PROGRAM-ID. R1DEPOT.
*
*COBOL Report Writer user function
*Converts internal depot code 'L', 'B', or 'N'
*to full name for printing in report
*Available report field sizes:
* 4 = short form ('LNDN', 'BHAM', 'NCSL', ETC.)
* 12 = long form ('LONDON', 'BIRMINGHAM', 'NEWCASTLE' ETC.)
*
*To use, write: FUNC DEPOT (DEPOT-CODE) instead of SOURCE...
*
*This function may be converted later to hold depot names in a
*file or database table without impact on the programs.
*
ENVIRONMENT DIVISION.
DATA DIVISION.
*
WORKING-STORAGE SECTION.
01 WS-FIELDS.
*table of short names
03 SHORT-NAME-TAB VALUE "LNDNBHAMNCSL????".
05 SHORT-NAME PIC X(4) OCCURS 4.
*table of long names
03 LONG-NAME-TAB VALUE
"LONDON BIRMINGHAM NEWCASTLE UNKNOWN ".
05 LONG-NAME PIC X(12) OCCURS 4.
03 W-DEPOT-NUMBER PIC S9(4) COMP.
03 W-PARAM-ERR PIC X.
*
LINKAGE SECTION.
*Param (1): Function Control Area
01 L-FUNC-CTL.
*No. of parameters to function:
03 L-PARAM-CNT PIC S9(4) COMP.
*Length of output field in bytes:
03 L-OP-LEN PIC S9(4) COMP.
*Length of parameter in bytes:
03 L-PM1-LEN PIC S9(4) COMP.
*
*Param (2): output area
01 L-OP-FLD.
03 L-OP-CH PIC X OCCURS 1 TO 12
DEPENDING ON L-OP-LEN.
*Param (3): input depot code
01 L-DEPOT-CODE PIC X.
*
PROCEDURE DIVISION USING L-FUNC-CTL, L-OP-FLD, L-DEPOT-CODE.
FUNCTION-ENTRY.
PERFORM PARAMETER-CHECK
IF W-PARAM-ERR = "N"
PERFORM CONVERT-CODE.
FUNCTION-EXIT.
EXIT PROGRAM.
*Routine to check parameters:
PARAMETER-CHECK.
MOVE "N" TO W-PARAM-ERR
*Check correct parameter specification
IF L-PARAM-CNT NOT = 1
OR L-PM1-LEN NOT = 1
DISPLAY
"R1DEPOT ERROR CRW-651: INVALID PARAMETERS"
MOVE "Y" TO W-PARAM-ERR.
*Check report field is correct size
IF L-OP-LEN NOT = 4 AND NOT = 12
DISPLAY
"R1DEPOT ERROR CRW-652: INVALID REPORT FIELD SIZE"
MOVE "Y" TO W-PARAM-ERR.
*Routine to convert depot code:
CONVERT-CODE.
*Check input depot code, convert to integer 1-3, or 4 if unknown
IF L-DEPOT-CODE = "L"
MOVE 1 TO W-DEPOT-NUMBER
ELSE IF L-DEPOT-CODE = "B"
MOVE 2 TO W-DEPOT-NUMBER
ELSE IF L-DEPOT-CODE = "N"
MOVE 3 TO W-DEPOT-NUMBER
ELSE MOVE 4 TO W-DEPOT-NUMBER.
IF L-OP-LEN = 4
MOVE SHORT-NAME (W-DEPOT-NUMBER) TO L-OP-FLD
ELSE MOVE LONG-NAME (W-DEPOT-NUMBER) TO L-OP-FLD.
|
Independent Report File Handlers
Introduction
An Independent Report File Handler (or file handler) is a separately-compiled program routine that takes over all the functions of the normal COBOL
OPEN-WRITE-CLOSE protocol for a particular report. The source program, as written, is identical in all respects to a regular batch print program, except that the
SELECT...ASSIGN
clause for the file to which the report is directed carries the additional sub-clause
MODE IS... (see Report Files), and that there may also be a CODE
clause (see CODE Clause) in the RD. (The MODE sub-clause can also be "forced" by default onto any report file does not have a MODE by an external option setting - see Installation
and Operation.)
File handlers monitor the results of any i/o operations they perform and pass any error codes back in the
FILE STATUS field in the usual way, or, if no FILE STATUS is specified,
they display a suitable message and, if the error is irrecoverable, abort the run.
COBOL Report Writer
comes with some built-in file handlers and these are listed below. Any number of others may be written by users to similar standards. File handlers can
be written in COBOL or another language.
Supplied File Handlers
The following list explains the function of each of the built-in file handlers and gives the MODE mnemonic you require to invoke each.
MODE PRNT Purpose: basic printing.
This file handler performs the same basic print functions as when no file handler is used at all. Unless you already specify a MODE clause, it will be used automatically when any
of the following features is used:
¶ PAGE BUFFER clause in SELECT
¶ DUPLICATED clause in SELECT
¶ STYLE clause
¶ UPON option of INITIATE
¶ CODEs of unequal length for RDs of same file.
Effect of CODE: Placed at start of print line, as in ANS standards. It is output
after any carriage control characters.
MODE NOPF Purpose: basic printing without using page feeds.
This file handler fills each page entirely using line feeds.
Effect of CODE: Placed in print line after the carriage control.
MODE MODL Purpose: for use in a modular system.
This file handler may be used by more than one separately compiled program in a run unit. Each program may thus write to the same report file. See listing below.
Effect of CODE: Placed in print line after the carriage control.
MODE MULT Purpose: write to more than one file simultaneously.
This file handler must be used if a program using a file handler requires to have more than one report file open simultaneously. It is needed if the DUPLICATED phrase is used.
Effect of CODE: Placed in print line after the carriage control.
MODE CHAN Purpose: make optimal use of any printer channels.
The channel positions are fed into the file handler at run time, as described in Installation and Operation. The file handler automatically uses channel skips to get as near
as possible to each target line. The RD does not change.
Effect of CODE: Placed in print line after the carriage control.
MODE DUPL Purpose: emulate OS/VS and DOS/VS COBOL's ability to write to two files simultaneously.
The file handler performs the OPEN, WRITE, CLOSE as appropriate for each file in turn.
Effect of CODE: Placed in print line after the carriage control.
MODE NOCC Purpose: print without any carriage control characters. Blank lines are written as space lines. This file handler is useful for small
demonstrations that will be viewed on a screen rather than printed.
Effect of CODE: Placed at start of print line.
MODE S370 Purpose: write lines using system-370 type carriage control characters. This file handler may be used for compatibility with VisualAge COBOL's
print format.
Effect of CODE: Placed at start of print line.
User-Written File Handlers
An Independent Report File Handler is not usually developed as part of one program, but
separately so that it can be used by all the report programs
in a project. Only a brief specification is normally required, similar to those in the table of built-in file handlers below.
Any application will then be able to use
the file handler.
The file handler has a fixed LINKAGE SECTION, and the areas and their various locations are given in COBOL format below. For use in a language other than COBOL, translate
the data-names and PICTUREs as appropriate.
The program-name of the file handler is related to the name of the MODE mnemonic. Full details are given in Operation and Installation.
Possible Uses of a File Handler
In this section we list some possible uses to which you might put a file handler.
Using COBOL Report Writer for Non-Report Output
Provided your program's "report lines" contain no COMPUTATIONAL entries, you might adapt your file handler to produce output which is not intended for printing but instead for passing
on to another program. Then, if you decide to ignore all LINE numbers, so that each "line" is another record irrespective of the "line advance", your file handler would simple do a WRITE
without ADVANCING.
Output to Database
Your program may be required to send its printed output to a database rather than in a sequential file.
Private STYLEs
If the printer has advanced features that require special programming, you can designate certain STYLEs as
PRIVATE. The processing of such STYLEs is then
left to your file handler. Full details are in Installation and Operation.
Output to Multiple Files
Your file handler may write to several files simultaneously, as outlined above (see 5.1.3) and under
MODE DUPL above.
Using CODE
In a "batch" report, the CODE is a "literal" prefixed to every print line. However, with a file handler you can designate the CODE clause for the
passing of any additional information from the program to the file handler. Normally this is to control the output, rather than for output as part of the data. For example, given the
necessary hardware and software prerequisites, you might decide to develop a file handler, and use the CODE clause, as follows:
Your possible file handler: Likely use of CODE:
Microfiche
output Key for fiche indexing.
Remote transmission Identifier for remote printer.
Spooled restart system Key, page number, etc., for restart.
The contents of the program's CODE operand appears in the file handler as the LINKAGE SECTION item
L-RCA-CODE-VAL, as described later in this section.
Actions of an Independent Report File Handler
A file handler must perform certain mandatory housekeeping functions in order to execute correctly in combination with the report writer code. However, the method by which the report
data is physically output is left entirely to the file handler.
If the file handler may be required to service more than one report file or INITIATEd report simultaneously, or be required to be usable by more than one program simultaneously,
it should store its intermediate results in the File Control Area or Report Control Area, where certain locations have been reserved for discretionary use by the file handler.
The following are the mandatory housekeeping actions that must be performed by every file handler. The standard locations referred to are described later in this section.
1. If the location L-FCA-ACT-IND is anything other than "0" or "9",
"OPEN" the report "file". The file handler may interpret the OPEN
function and the nature of the "file" in any way it wishes. The value of L-FCA-ACT-IND indicates the type of OPEN required (OUTPUT, EXTEND, or other).
2. If the location L-RCA-ACT-IND is "6", "INITIATE" the report. The file handler may perform the INITIATE action in any way it wishes.
3. If there is data to output, indicated by the field L-PRC-BYTE-CNT being non-zero,
"print" the data. The exact nature of the "printing" activity is left
entirely to the file handler and may differ widely from a "batch" WRITE statement. The following locations will be needed to accomplish this:
L-RCA-VERT-POSN contains the current vertical position or zero. If it is zero the file handler should execute a "form feed". This action should be omitted
if L-RCA-PAGE-LIM is zero, indicating that the report is not divided into pages.
L-FCA-SUPP-PFD, if set to 1, indicates that the program has a FIRST PAGE NO ADVANCING clause in the SELECT...ASSIGN. If so, the "form
feed" is not done and instead the current position is assumed to be "line 1". It is cleared automatically by the control routine.
L-RCA-LINE-CNTR contains the target vertical position. By subtracting L-RCA-VERT-POSN from this, you obtain the distance to be advanced.
4. If the location L-RCA-ACT-IND is "8", "TERMINATE" the report. The file handler may perform the TERMINATE action in any way it wishes.
5. If the location L-FCA-ACT-IND is "9", "CLOSE" the report "file". The file handler may interpret the CLOSE function in any way it wishes.
By convention, there will never be more than one action from the possibilities OPEN, INITIATE, "print", TERMINATE, and CLOSE on any entry.
File Handler LINKAGE Areas
All the information required by the file handler is passed to it via optional user parameters and three standard LINKAGE areas, of which source copies are provided with this product.
Optional Leading Parameters: User-Defined Parameters
There may be any number of parameters at the start of the LINKAGE SECTION pre-determined by the user and specified through the
USING phrase of the MODE clause. See
Report Files for a description of this phrase.
Parameter 1: File Control Area
The File Control Area contains information relating to the current report file. A File Control Area is set up for each report file that has a MODE clause.
01 L-FCA-CNTRL-AREA.
*Maximum length in bytes of CODEs for this file.
*= 0 if CODE clause is not present for any reports in file.
03 L-FCA-CODE-LEN PIC S9(4) COMP.
*Maximum record length in bytes for File.
03 L-FCA-REC-LEN PIC S9(4) COMP.
*Action indicator byte.
*Action performed is open to interpretation by the designer.
*"0" = no action against file
*"1" = file to be opened output
*"2" = file to be opened extend
*"5" = file to be opened in irregular manner
*"9" = file to be closed
03 L-FCA-ACT-IND PIC X.
*File status indicator.
*Initial value = low-values (hex '00')
*"0" = file not opened
*"1" = file opened output
*"2" = file opened extend
*"5" = file opened in irregular manner
*"9" = file closed
03 L-FCA-STAT-IND PIC X.
*Count of reports initiated for this file.
*Incremented by 1 on INITIATE, decremented by 1 on TERMINATE;
*initially zero, must never become negative;
*used to warn on CLOSE if some report(s) still initiated
03 L-FCA-REPS-INT PIC S9(4) COMP.
*MODE mnemonic name:
*up to 4 characters (padded with spaces) from the MODE clause
03 L-FCA-MODE-MNEM PIC X(4).
*File Status:
*If L-FCA-FS-IND (below) = "1", file handler control routine will
*always pass back any file status here without abandoning the run;
*Otherwise, file handler control routine will abandon the run with
*an error message if a serious error is indicated in File Status.
03 L-FCA-STATUS PIC XX.
*File Status indicator: set if SELECT has a FILE STATUS clause.
03 L-FCA-FS-IND PIC X.
*Unassigned:
03 FILLER PIC X.
*Locations reserved for communication between file handler
*and report writer:
*integer of DUPLICATED clause if present; zero if no such clause
03 L-FCA-DUP-FACT PIC S9(4) COMP.
*Recording mode = "F", "V", "U", "S" or space if not specified
*taken from RECORDING MODE clause of the FD;
*may be taken into account or ignored by the file handler
*(report record is always variable-length; (see 2.2.3))
03 L-FCA-REC-MODE PIC X.
*Indicator set = "1" if PAGE BUFFER clause present:
03 L-FCA-PBUF-IND PIC X.
*First four characters of file name:
03 L-FCA-FILE-PFIX PIC X(4).
*Locations reserved for use by file-handler:
*Address of block of DUPLICATED FCA's, if applicable
03 L-FCA-DUP-ADR PIC X(4).
*General-purpose location used as by file handler
03 L-FCA-GEN-LOCN PIC S9(4) COMP.
*Suppress page feed indicator:
*Set = "1" if next page feed (always the first since OPEN) is
*to be ignored.
03 L-FCA-SUPP-PFD PIC X.
*Data-written indicator:
*Set = "1" if something has been written to the file
03 L-FCA-WRITE-IND PIC X.
*Unassigned:
03 FILLER PIC X(4).
*Reserved for general use by File Handler:
03 L-FCA-WORK-AREA PIC X(20).
*DDname from SELECT...ASSIGN statement:
*May be altered by user program by storing value in
*field DDNAME in File Control Area
03 L-FCA-DDNAME PIC X(8).
*Alternative details of file name:
03 L-FCA-FN-BLK REDEFINES L-FCA-DDNAME.
*Length in bytes of file-name
05 L-FCA-FN-LEN PIC S9(4) COMP.
*Binary zero:
05 L-FCA-FN-SLACK PIC X.
05 FILLER PIC X.
*Address of file-name
05 L-FCA-FN-ADR PIC X(4).
*End of File Control Area
|
Parameter 2: Report Control Area
The Report Control Area is set up by the Precompiler for each report that is directed to a file that has a
MODE clause. In the user program, the Report Control
Area is identified by the report-name.
01 L-RCA-CNTRL-AREA.
*PAGE-COUNTER, referred to in program as
*PAGE-COUNTER [IN report-name]:
03 L-RCA-PAGE-CNTR PIC S9(9) COMP.
*LINE-COUNTER, referred to in program as
*LINE-COUNTER [IN report-name]
*Shows the desired position for this report line:
03 L-RCA-LINE-CNTR PIC S9(9) COMP.
*Vertical position pointer.
*Shows the actual current position vertically on the page.
*diff. between this field and LINE-COUNTER gives desired advance;
*If this location is zero, a form feed is required first.
03 L-RCA-VERT-POSN PIC S9(9) COMP.
*Line byte count override;
*Used internally only. Will = -1 in file handler.
03 L-RCA-LINE-SIZE PIC S9(4) COMP.
*Line Limit; i.e. the logical size of the report line
*from the LINE LIMIT clause in the RD, or its default:
03 L-RCA-LINE-LMT PIC S9(4) COMP.
*Action indicator byte:
*"0" = no change to report status
*"6" = report to be initiated
*"7" reserved
*"8" = report to be terminated
03 L-RCA-ACT-IND PIC X.
*Report status indicator:
*"0" = report never initiated
*"6" = report initiated
*"8" = report terminated
03 L-RCA-STAT-IND PIC X.
*Report-name from RD statement:
03 L-RCA-REP-NAME PIC X(30).
*Print record format indicator: always = "0"
03 L-RCA-PRT-FMT PIC X.
*Line column width override: (1 byte binary held as character)
03 L-RCA-COL-WIDTH PIC X.
*Page Limit from PAGE LIMIT clause RD; zero if no PAGE clause.
03 L-RCA-PAGE-LIM PIC S9(4) COMP.
*Length of CODE, or zero if no CODE clause.
*The length of the CODE is determined from the length of the CODE
*"literal" or, if the "identifier" form of CODE clause is used,
*from the difference between the record length of the report file
*(as given in the RECORD or BLOCK CONTAINS clause of the FD)
*and the LINE LIMIT (or its default value),
*allowing for the normal carriage control characters.
03 L-RCA-CODE-LEN PIC S9(4) COMP.
*Error flag: zero = no error.
*May be set by file handler to non-zero value representing a
*standard error condition for reporting via a subroutine.
*If it is given a value which does not correspond with a known
*error message, the message UNKNOWN ERROR TYPE will be output
*together with information that usually accompanies any message.
03 L-RCA-ERR-FLG PIC S9(4) COMP.
*Error code detected by file handler:
03 L-RCA-FH-ERR PIC S9(4) COMP.
*Report Number from REPORT-NUMBER location
*zero if DUPLICATED clause not in use.
03 L-RCA-REP-NUM PIC S9(4) COMP.
*Location reserved for future communication between file handler
*and report writer.
03 L-RCA-COMM-AREA PIC X(8).
*Location reserved for internal use (not by file handler):
*Data items used by Page Buffer:
*Current margin offset established by SET COLUMN (1 = no margin).
03 L-RCA-MARG PIC S9(4) COMP.
*Forced absolute line number set up by SET LINE TO integer.
03 L-RCA-ABS-LNO PIC S9(4) COMP.
*Indicator set to "H" "HOLD" status, otherwise space.
03 L-RCA-HOLD-IND PIC X.
*General locations used by file handlers:
03 FILLER PIC X(11).
*Data items used by Page Buffer: (not required by file handler)
*Current physical position;
03 L-RCA-PHYS-POSN PIC S9(4) COMP.
*Lowest line no. having line buffered.
03 L-RCA-STL-LOW PIC S9(4) COMP.
*Highest line no. having line buffered.
03 L-RCA-STL-HIGH PIC S9(4) COMP.
*Maximum value permitted for LINE-COUNTER.
03 L-RCA-MAX-LCT PIC S9(4) COMP.
*Maximum physical size in bytes of "line" of data;
*this is the largest value that can ever be held in "byte count"
*(L-PRC-BYTE-CNT) of any print line.
*It differs from the line limit (L-RCA-LINE-LMT) in that
*(a) the line limit is a maximum for checking purposes only and
*may never be attained in any actual line of the report,
*(b) lines may contain formatting characters that do not occupy
*a column of print, e.g.
*start- and end-sequence of a "style" (underline, bold etc.)
*shift out and shift in characters used by Kanjii (DBCS)
03 L-RCA-BYTE-LMT PIC S9(4) COMP.
*Number of purely formatting characters override; if non-zero, the
*value (L-PRC-BYTE-CNT - L-RCA-FMT-CNT) overrides L-PRC-END-COL;
*it must always be cleared by file handler.
03 L-RCA-FMT-CNT PIC S9(4) COMP.
*Indicators, for general use by file handler.
03 L-RCA-WORK-IND PIC X OCCURS 4.
*Code Value; zero length if no CODE clause in RD
*initial value set from CODE clause.
*May be referred to in user program as CODE-VALUE [IN report-name]
03 L-RCA-CODE-VAL.
05 L-RCA-CODE-CHA PIC X
OCCURS 0 TO 4095 TIMES DEPENDING ON L-RCA-CODE-LEN.
*End of report control area.
|
Parameter 3: Report Data
This parameter contains the data to be written. For OPEN, INITIATE, TERMINATE and CLOSE operations, this parameter is a dummy with a value of zero in the
counter L-PRC-BYTE-CNT. The number of bytes to be written may be reduced to the value in L-RCA-LINE-SIZE when it is non-negative.
01 L-PRC-PRINT-REC.
*Physical byte count, not including this 4-byte header;
*will be zero when no data is to be output;
*gives no. of bytes to be written, unless overridden by
*L-RCA-LINE-SIZE set non-negative.
03 L-PRC-BYTE-CNT PIC S9(4) COMP.
03 L-PRC-HEAD.
*Indicator bits, layout is as follows:
*bit 0-3: unused
*bit 4: set if data contains unresolved STYLE sequence(s)
*bit 5: set if data consists only of formatting (STYLE) characters
*bit 6: reserved
*bit 7: set if print data must be flushed to spaces.
*2nd byte is reserved.
05 L-PRC-HEAD-BYTES PIC S9(4) COMP.
*Data to be written;
03 L-PRC-DATA.
05 L-PRC-DATA-CHA PIC X
OCCURS 0 TO 256 TIMES DEPENDING ON L-PRC-BYTE-CNT.
|
Sample Independent Report File Handler
The following is the complete code of the standard MODL file handler (used for writing to a single report file from a modular system). This file handler is one of
the simplest, and so it may be used as a model for your own user-written file handlers, which will require almost all the code that follows, except perhaps for the incrementing and decrementing
of the "nest depth" (W-OPEN-NEST) which is peculiar to this file handler.
At least one file handler is supplied in source form with this product, giving you a machine-readable copy of most of this coding.
IDENTIFICATION DIVISION.
*
*Independent Report Writer file handler for use in modular program
*
*Purpose:
* Used when several separately-compiled modules need to access
* the same report file without continually opening and closing.
* This file handler does not currently handle more than 1 file.
*
*Method of use:
* 1. The control program does one OPEN at start of processing
* and one CLOSE at very end of all processing.
* (To satisfy the syntax it should have a minimal
* REPORT SECTION which is not used.)
* 2. Each subprogram including control module has an FD
* & does OPEN, some GENERATEs and CLOSE each time it is
* CALLed, as though it were the only module using the file.
*
* This file handler ignores all "nested" OPENs and CLOSEs.
* Typical sequence of operations:
*
* a. Control program does OPEN OUTPUT which is actioned.
* b. Subprogram does OPEN which is ignored.
* c. Subprogram does INITIATE, several GENERATE's & TERMINATE.
* d. Subprogram does CLOSE which is ignored.
* e. Many other subprogram CALLs occur in same way.
* f. Control program does CLOSE which is actioned.
*
* Subprograms have to do the (dummy) OPEN and CLOSE as Report
* Writer requires that every program be logically complete.
ENVIRONMENT DIVISION.
*
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT PRINT-FILE
* is always overwritten by name specified in program
ASSIGN TO RPFILE
FILE STATUS IS W-FCA-STATUS.
DATA DIVISION.
FILE SECTION.
FD PRINT-FILE
LABEL RECORDS STANDARD.
*THIS FILE MAY ALSO BE DESIGNATED "RECORDING MODE V"
01 F-PRINT-RECORD.
05 F-PRINT-DATA.
07 F-PRINT-CHAR PIC X OCCURS 512.
WORKING-STORAGE SECTION.
*General locations:
01 WS-GENERAL.
05 W-FEED PIC S9(4) COMP.
*This location contains the "nest" level of OPEN/CLOSE statements:
05 W-OPEN-NEST PIC S9(4) COMP VALUE ZERO.
*Pointer to record data:
05 W-PTR PIC S9(4) COMP.
*Indicator set = "Y" if a the given line of data has been printed:
05 W-DATA-PRINTED PIC X.
*Indicator set = "1" if an error occurs on writing.
05 W-PRINT-ERROR PIC X.
*File status:
05 W-FCA-STATUS PIC XX.
*Standard Linkage:
LINKAGE SECTION.
*Parameter 1: File Control Area
COPY RWFCACOM.
*Parameter 2: Report Control Area
COPY RWRCACOM.
*Parameter 3: Print Line
COPY RWPLNCOM.
PROCEDURE DIVISION USING L-FCA-CNTRL-AREA
L-RCA-CNTRL-AREA
L-PRC-PRINT-REC.
*
FILE-HANDLER-CONTROL SECTION.
FHC-ENTRY.
*Assume successful operation:
MOVE "00" TO W-FCA-STATUS
*Open file if indicated:
IF L-FCA-ACT-IND > "0" AND < "9"
PERFORM OPEN-FILE.
*Initiate report if indicated:
IF L-RCA-ACT-IND = "6"
PERFORM INITIATE-REPORT.
*Print data if any data present:
IF L-PRC-BYTE-CNT NOT = 0
PERFORM PRINT-DATA.
*Terminate report if indicated:
IF L-RCA-ACT-IND = "8"
PERFORM TERMINATE-REPORT.
*Close file if indicated:
IF L-FCA-ACT-IND = "9"
PERFORM CLOSE-FILE.
MOVE W-FCA-STATUS TO L-FCA-STATUS.
FHC-EXIT.
EXIT PROGRAM.
*Main sections to print the data line.
*
PRINT-DATA SECTION.
PDA-ENTRY.
*check not too many characters for print line:
IF L-PRC-BYTE-CNT > 512
DISPLAY "CRFHMODL Error: Line too long - truncated".
MOVE "N" TO W-DATA-PRINTED
*If vertical position is zero in paged report, page feed required:
IF L-RCA-VERT-POSN = 0
AND L-RCA-PAGE-LIM NOT = 0
AND W-PRINT-ERROR = "0"
*If FIRST PAGE NO ADVANCING was coded in SELECT statement
*omit first page advance (this ind. is reset by control s/r)
IF L-FCA-SUPP-PFD = "1"
MOVE 1 TO L-RCA-VERT-POSN
ELSE PERFORM TOP-OF-PAGE.
*Now write data after advancing required distance, unless it was
*written on line 1 when we advanced to top of page:
IF W-DATA-PRINTED = "N"
AND W-PRINT-ERROR = 0
PERFORM AFTER-ADVANCING.
*Routine to print at top-of-page.
TOP-OF-PAGE SECTION.
TOP-ENTRY.
*If LINE-COUNTER = 1 we can print data at top-of-form,
*otherwise we print blank lines first;
IF L-RCA-LINE-CNTR > 1
MOVE SPACES TO F-PRINT-DATA
ELSE PERFORM FILL-RECORD
MOVE "Y" TO W-DATA-PRINTED.
WRITE F-PRINT-RECORD AFTER ADVANCING PAGE
*If bad File Status, set indicator to prevent further writing
*in case user program has FILE STATUS which is not exemined.
IF L-FCA-STATUS NOT = "00"
MOVE "1" TO W-PRINT-ERROR.
MOVE 1 TO L-RCA-VERT-POSN.
*Routine to print with appropriate advance (if any)
AFTER-ADVANCING SECTION.
ADV-ENTRY.
PERFORM FILL-RECORD
SUBTRACT L-RCA-VERT-POSN FROM L-RCA-LINE-CNTR GIVING W-FEED
WRITE F-PRINT-RECORD AFTER ADVANCING W-FEED.
IF L-FCA-STATUS NOT = "00"
MOVE "1" TO W-PRINT-ERROR.
*Move data into record, allowing fir possible CODE
FILL-RECORD SECTION.
FLR-ENTRY.
IF L-RCA-CODE-LEN = 0
AND L-RCA-MARG NOT > 1
MOVE L-PRC-DATA TO F-PRINT-RECORD
ELSE MOVE 1 TO W-PTR
IF L-RCA-CODE-LEN > 0
MOVE L-RCA-CODE-VAL TO F-PRINT-RECORD
ADD L-RCA-CODE-LEN TO W-PTR
ELSE MOVE SPACES TO F-PRINT-RECORD
END-IF
IF L-RCA-MARG > 0
ADD L-RCA-MARG TO W-PTR
SUBTRACT 1 FROM W-PTR
END-IF
STRING L-PRC-DATA DELIMITED BY SIZE INTO F-PRINT-RECORD
WITH POINTER W-PTR.
*OPEN the report file
OPEN-FILE SECTION.
OPF-ENTRY.
*If OPEN not OUTPUT or EXTEND, signal error 44 and assume OUTPUT:
IF L-FCA-ACT-IND = "5"
MOVE 44 TO L-RCA-ERR-FLG
MOVE "1" TO L-FCA-ACT-IND.
*Does not really OPEN the file if the OPEN is "nested".
IF W-OPEN-NEST = 0
*Get name of print file
IF RETURN-CODE = 0
*OPEN OUTPUT or EXTEND, depending on the Action Indicator.
IF L-FCA-ACT-IND = "1"
OPEN OUTPUT PRINT-FILE
ELSE OPEN EXTEND PRINT-FILE
END-IF
END-IF
IF L-FCA-STATUS NOT = "00"
MOVE "1" TO W-PRINT-ERROR.
*Increment nest level:
ADD 1 TO W-OPEN-NEST.
*Initiate the report
INITIATE-REPORT SECTION.
INT-ENTRY.
*In this section we do any action consistent with INITIATing
*the report. In this routine nothing need be done.
*Terminate the report
TERMINATE-REPORT SECTION.
TRM-ENTRY.
*In this section we do any action consistent with TERMINATing
*the report. In this routine nothing need be done.
*Close the report file
CLOSE-FILE SECTION.
CLF-ENTRY.
*Does not really CLOSE the file if the CLOSE is "nested".
SUBTRACT 1 FROM W-OPEN-NEST
IF W-OPEN-NEST = 0
CLOSE PRINT-FILE.
MOVE "0" TO W-PRINT-ERROR.
*End of file handler. |