FLOD exits: Difference between revisions

From m204wiki
Jump to navigation Jump to search
mNo edit summary
m (more conversion cleanup)
 
(11 intermediate revisions by 3 users not shown)
Line 1: Line 1:
==Overview==
==Overview==
<p>The <var class="product">Model&nbsp;204</var> File Load utility enables you to load raw data from a sequential data set into <var class="product">Model&nbsp;204</var>. The heart of the File Load utility, the FLOD program, allows you to manipulate the data as it is being loaded. FLOD (or FILELOAD) Exits allow for much more sophisticated data manipulation including performing edit checks, creating derived fields, and merging data from multiple data sets.</p>
<p>
<p>FLOD Exits are programs much like E15 Sort Exits. They add the capability to exit the FLOD program, passing control to a "FLOD Exit" COBOL or Assembler program. </p>
The <var class="product">Model&nbsp;204</var> File Load utility enables you to load raw data from a sequential data set into <var class="product">Model&nbsp;204</var>. The heart of the File Load utility, the <var>FLOD</var> program, allows you to manipulate the data as it is being loaded. <var>FLOD</var> (or <var>FILELOAD</var>) exits allow for much more sophisticated data manipulation including performing edit checks, creating derived fields, and merging data from multiple data sets.</p>
<p>FLOD Exit allows the FLOD or FILELOAD command to read from another source besides the TAPEI file normally required for FLOD and FILELOAD. This allows you to use more than one input file for FLOD or FILELOAD processing. </p>
<p>
<p>FLOD Exits are normally run as batch applications.</p>
<var>FLOD</var> exits are programs much like E15 Sort exits. They add the capability to exit the <var>FLOD</var> program, passing control to a "FLOD exit" COBOL or Assembler program. </p>
<p>
The <var>FLOD</var> exit allows the <var>FLOD</var> or <var>FILELOAD</var> command to read from another source besides the <code>TAPEI</code> file normally required for <var>FLOD</var> and <var>FILELOAD</var>. This allows you to use more than one input file for <var>FLOD</var> or <var>FILELOAD</var> processing. </p>
<p>
<var>FLOD</var> exits are normally run as batch applications.</p>
 
===File Load XG statement===
===File Load XG statement===
<p>The FLOD or FILELOAD command uses the XG statement to pass control to the FLOD Exit. The XG statement is discussed in detail on [[#XG statement|XG statement]].</p>
<p>
===FLOD Exits and Sort Exits===
The <var>FLOD</var> or <var>FILELOAD</var> command uses the <var>XG</var> statement to pass control to the <var>FLOD</var> exit. The <var>XG</var> statement is discussed in detail on [[#XG statement|XG statement]].</p>
<p>FLOD Exits are modeled on Sort Exits similar to the IBM DFSORT. FLOD Exit programs are similar to E15 Sort Exit programs. For more information about E15 Sort Exits, see the documentation for your sort package. </p>
 
<p>E32 and E35 types of Sort Exits (which allow you to modify records already modified by an E15 Exit) are not supported.</p>
===FLOD exits and Sort exits===
==Data sources for FLOD Exits==
<p>
<p>FLOD Exits are capable of using data from two sources:</p>
<var>FLOD</var> exits are modeled on Sort exits similar to the IBM DFSORT. <var>FLOD</var> exit programs are similar to E15 Sort exit programs. For more information about E15 Sort exits, see the documentation for your sort package. </p>
<p>
E32 and E35 types of Sort exits (which allow you to modify records already modified by an E15 exit) are not supported.</p>
 
==Data sources for FLOD exits==
<p>
<var>FLOD</var> exits are capable of using data from two sources:</p>
<ul>
<ul>
<li>TAPEI data passed to the Exit</li>
<li>TAPEI data passed to the exit</li>
<li>Data accessed by the FLOD Exit </li>
<li>Data accessed by the <var>FLOD</var> exit </li>
</ul>
</ul>
<p>The data source you select depends on the purpose of the FLOD Exit program. The data source argument specified on the XG statement determines whether or not TAPEI records are to be passed to the FLOD Exit. Other data accessed by the FLOD Exit can always be used to generate records for insertion.</p>
<p>
<p>The return codes within FLOD Exits vary both according to the source of the data and to the language in which the Exit is written. FLOD Exits involving each data source are discussed separately in the following sections.</p>
The data source you select depends on the purpose of the <var>FLOD</var> exit program. The data source argument specified on the XG statement determines whether or not TAPEI records are to be passed to the <var>FLOD</var> exit. Other data accessed by the <var>FLOD</var> exit can always be used to generate records for insertion.</p>
<p>
The return codes within <var>FLOD</var> exits vary both according to the source of the data and to the language in which the exit is written. <var>FLOD</var> exits involving each data source are discussed separately in the following sections.</p>
 
===Passing records from TAPEI===
===Passing records from TAPEI===
<p>Pass records to a FLOD Exit from TAPEI when you do not want to code I/O logic into the FLOD Exit or when you want general purpose FLOD Exits. For example, if your site has a number of input files, all of which have the same record format, one FLOD Exit can manipulate the data in any of the files.</p>
<p>
<p>The path taken by the data using this method is shown in [[#Passing records from TAPEI|Passing records from TAPEI]].</p>
Pass records to a <var>FLOD</var> exit from TAPEI when you do not want to code I/O logic into the <var>FLOD</var> exit or when you want general purpose <var>FLOD</var> exits. For example, if your site has a number of input files, all of which have the same record format, one <var>FLOD</var> exit can manipulate the data in any of the files.</p>
<b>Passing TAPEI Records To FLOD Exit</b>
<p>
[[File:_FLOD_Exits_2.gif]]
The path taken by the data using this method is shown in "Passing TAPEI records to FLOD exit":</p>
 
<p class="caption" style="width:300px">Passing TAPEI records to FLOD exit</p>
<p class="figure">[[File:Passing TAPEI records to FLOD exit.gif]]</p>
 
===Inserting records read from alternate data sets===
===Inserting records read from alternate data sets===
<p>Use this FLOD Exit feature when you want to read records from multiple data sets. The FLOD Exit is responsible for defining and accessing all alternate data sets.</p>
<p>
<p>This method is shown in [[#Inserting records read from alternate data sets|Inserting records read from alternate data sets]].</p>
Use this <var>FLOD</var> exit feature when you want to read records from multiple data sets. The <var>FLOD</var> exit is responsible for defining and accessing all alternate data sets.</p>
<b>FLOD Exit Inserting Records Read From Alternate Data Sets</b>
<p>
[[File:_FLOD_Exits_3.gif]]
This method is shown in the following figure:</p>
 
<p class="caption" style="width:338px">FLOD exit to insert records from alternate data sets</p>
<p class="figure">[[File:FLOD exit inserting records read from alt data sets.gif]]</p>
 
==Storage requirements==
==Storage requirements==
<p>To ensure that FLOD Exit has enough working storage space, SPCORE requires:</p>
<p>
<p class="code">80 bytes + the size of the modified record buffer + any storage acquired by the Exit
To ensure that a <var>FLOD</var> exit has enough working storage space, <var>[[SPCORE parameter|SPCORE]]</var> requires:</p>
<p class="code">80 bytes + the size of the modified record buffer + any storage acquired by the exit
</p>
</p>
<p>For information about the modified record buffer, see [[#XG statement|XG statement]].</p>
<p>
<p>If the FLOD Exit program does not have enough space, it might terminate the <var class="product">Model&nbsp;204</var> run.</p>
For information about the modified record buffer, see [[#XG statement|XG statement]].</p>
===Using FLOD Exits in z/OS environment===
<p>
<p>In the z/OS environment, control is transferred to a FLOD Exit in 24-bit addressing mode through a BALR 14,15 instruction. All addresses, including the parameter list address passed in Register 1, are 24-bit addresses (bits 25-31 are 0).</p>
If the <var>FLOD</var> exit program does not have enough space, it might terminate the <var class="product">Model&nbsp;204</var> run.</p>
<p>When a FLOD Exit passes a new record to FLOD (using an INSERT or ALTER/REPLACE return code), the address of the new record is treated as a valid 31-bit address and might, therefore, reside above the 16M line.</p>
 
<p>Because a BALR 14,15 instruction stores link information in the high-order byte of Register 14 when executed in 24-bit mode, a FLOD Exit using 31-bit processing mode must clear the high-order byte of the address in Register 14 before issuing a BR 14 instruction. </p>
===Using FLOD exits in z/OS environment===
<p>
In the z/OS environment, control is transferred to a <var>FLOD</var> exit in 24-bit addressing mode through a <code>BALR 14,15</code> instruction. All addresses, including the parameter list address passed in Register 1, are 24-bit addresses (bits 25-31 are 0).</p>
<p>
When a <var>FLOD</var> exit passes a new record to <var>FLOD</var> (using an <code>INSERT</code> or <code>ALTER/REPLACE</code> return code), the address of the new record is treated as a valid 31-bit address and might, therefore, reside above the 16M line.</p>
<p>
Because a <code>BALR 14,15</code> instruction stores link information in the high-order byte of Register 14 when executed in 24-bit mode, a FLOD exit using 31-bit processing mode must clear the high-order byte of the address in Register 14 before issuing a BR 14 instruction. </p>
 
==XG statement==
==XG statement==
<p>Within a FLOD program, the XG statement is an enhanced G statement. It returns a new input record for processing. If no more input records remain, the file load program terminates and <var class="product">Model&nbsp;204</var> goes on to the command that follows the END statement.</p>
<p>
<p>The order and content of input records returned to FLOD is determined by the FLOD Exit. The XG statement allows you to call a specific FLOD Exit program and process records in the format of your choice.</p>
Within a <var>FLOD</var> program, the <var>XG</var> statement is an enhanced <var>G</var> statement. It returns a new input record for processing. If no more input records remain, the file load program terminates and <var class="product">Model&nbsp;204</var> goes on to the command that follows the <var>END</var> statement.</p>
<p>The XG statement can be specified as often as needed in a FLOD program. However, <var class="product">Model&nbsp;204</var> only processes the syntax of the first XG statement that it compiles, and that syntax is used for any further calls to a FLOD Exit within that FLOD program. </p>
<p>
<p>The syntax for the XG statement is:</p>
The order and content of input records returned to <var>FLOD</var> is determined by the <var>FLOD</var> exit. The <var>XG</var> statement allows you to call a specific <var>FLOD</var> exit program and process records in the format of your choice.</p>
<b>Syntax</b>
<p>
<p class="code">XG [n] [,[c] [,[r] [,[s]]]]
The <var>XG</var> statement can be specified as often as needed in a <var>FLOD</var> program. However, <var class="product">Model&nbsp;204</var> only processes the syntax of the first <var>XG</var> statement that it compiles, and that syntax is used for any further calls to a <var>FLOD</var> exit within that <var>FLOD</var> program. </p>
 
===Syntax===
<p>
The syntax for the <var>XG</var> statement is:</p>
 
<p class="syntax">XG [<span class="term">n</span>] [,[<span class="term">c</span>] [,[<span class="term">r</span>] [,[<span class="term">s</span>]]]]
</p>
</p>
<p>where:</p>
<p>
<p>n is the number of a FLOD Exit program that has been linked into <var class="product">Model&nbsp;204</var>. FLOD Exit programs must be named FLODXT<var class="term">n</var>, where n is a number from 0 to 19. Up to 20 FLOD Exit programs can exist (FLODXT0 to FLODXT19) at any time. </p>
Where:</p>
<p>If you try to call a nonexistent FLOD Exit program, <var class="product">Model&nbsp;204</var> detects it before executing the first FLOD statement, and issues an appropriate error message.</p>
<p>The default FLOD Exit program is 0 (FLOD Exit program FLODXT0).</p>
<p>c specifies the language of the calling convention such as COBOL or Assembler, that modifies the record image FLOD or FILELOAD operates on.</p>
<p>The valid settings for the calling conventions are:</p>
<ul>
<ul>
<li>1, the default, for COBOL. You cannot use the DYNAM option in COBOL.</li>
<li><var class="term">n</var> is the number of a <var>FLOD</var> exit program that has been linked into <var class="product">Model&nbsp;204</var>. <var>FLOD</var> exit programs must be named <var>FLODXT</var><var class="term">n</var>, where <var class="term">n</var> is a number from 0 to 19. Up to 20 <var>FLOD</var> exit programs can exist (<code>FLODXT0</code> to <code>FLODXT19</code>) at any time.
<p>
If you try to call a nonexistent <var>FLOD</var> exit program, <var class="product">Model&nbsp;204</var> detects it before executing the first <var>FLOD</var> statement, and issues an appropriate error message.</p>
<p>
The default <var>FLOD</var> exit program is 0 (<var>FLOD</var> exit program <code>FLODXT0</code>).</p></li>
 
<li><var class="term">c</var> specifies the language of the calling convention such as COBOL or Assembler, that modifies the record image <var>FLOD</var> or <var>FILELOAD</var>operates on.
<p>
The valid settings for the calling conventions are:</p>
<ul>
<li>1, the default, for COBOL. You cannot use the <code>DYNAM</code> option in COBOL.</li>
<li>2 for Assembler </li>
<li>2 for Assembler </li>
</ul>
</ul>
<p>The default is COBOL.</p>
<p>
<p>Any language that uses the same calling conventions as COBOL or Assembler can be used to call the FLOD Exit. Specify the calling convention that is similar to the language of the FLODXTn program.</p>
The default is COBOL.</p>
<p>r specifies the length of the modified record buffer to be allocated by <var class="product">Model&nbsp;204</var>. The possible settings for this argument are:</p>
<p>
Any language that uses the same calling conventions as COBOL or Assembler can be used to call the <var>FLOD</var> exit. Specify the calling convention that is similar to the language of the <var>FLODXT<i>n</i></var> program.</p></li>
 
<li><var class="term">r</var> specifies the length of the modified record buffer to be allocated by <var class="product">Model&nbsp;204</var>. The possible settings for this argument are:
<ul>
<ul>
<li>Negative number indicates that a modified record buffer is not allocated.</li>
<li>Negative number indicates that a modified record buffer is not allocated.</li>
<li>Zero, the default, indicates that the number of bytes to allocate is TAPEI's lrecl.</li>
 
<li>Positive number specifies the length in bytes of the modified record buffer. The author of the FLOD Exit is responsible for including 4 bytes of variable record overhead and 4 bytes of block overhead (totaling 8 bytes) in the space requirements.</li>
<li>Zero, the default, indicates that the number of bytes to allocate is TAPEI's <code>LRECL</code>.</li>
 
<li>Positive number specifies the length in bytes of the modified record buffer. The author of the <var>FLOD</var> exit is responsible for including 4 bytes of variable record overhead and 4 bytes of block overhead (totaling 8 bytes) in the space requirements.</li>
</ul>
<p>
For Assembler-style exits, this parameter is ignored. These exits must provide their own modified record buffer if modified records are to be returned or additional records inserted.</p>
<p>
For COBOL-style exits, a modified record buffer is required for <code>INSERT</code> and <code>ALTER/REPLACE</code> operations. You must specify a positive value if you are not passing TAPEI records to the exit. </p></li>
<li><var class="term">s</var> specifies the source of the data:
<ul>
<li>0, the default, indicates that <var>FLOD</var> supplies the data from TAPEI to the <var>FLOD</var> exit. The <var>FLOD</var> exit receives and returns fixed- or variable-length records depending on the record format of TAPEI.</li>
 
<li>1 indicates that <var>FLOD</var> does not pass records to the exit and that the exit returns (<code>INSERT</code>) fixed-length records to <var>FLOD</var>.</li>
 
<li>2 indicates that <var>FLOD</var> does not pass records to the exit and that the exit returns (<code>INSERT</code>) variable-length records to <var>FLOD</var>.</li>
</ul>
</ul>
<p>For Assembler-style Exits, this parameter is ignored. These Exits must provide their own modified record buffer if modified records are to be returned or additional records inserted.</p>
<p>
<p>For COBOL-style Exits, a modified record buffer is required for INSERT and ALTER/REPLACE operations. You must specify a positive value if you are not passing TAPEI records to the Exit. </p>
If TAPEI records are not passed, the initial condition is reflected as an EOF condition on TAPEI. </p></li>
<p>s specifies the source of the data.</p>
</ul>
<p>0, the default, indicates that FLOD supplies the data from TAPEI to the FLOD Exit. The FLOD Exit receives and returns fixed- or variable-length records depending on the record format of TAPEI.</p>
 
<p>1 indicates that FLOD does not pass records to the Exit and that the Exit returns (INSERT) fixed-length records to FLOD.</p>
<p>2 indicates that FLOD does not pass records to the Exit and that the Exit returns (INSERT) variable-length records to FLOD.</p>
<p>If TAPEI records are not passed, the initial condition is reflected as an EOF condition on TAPEI. </p>
==XG statement logic flow==
==XG statement logic flow==
<p>The following example shows the flow of the XG statement logic. </p>
<p>
<b>XG statement logic flow</b>
The following example shows the flow of the <var>XG</var> statement logic: </p>
 
<p class="code">If Passing TAPEI Data
<p class="code">If Passing TAPEI Data
   If Previous Return Code Not INSERT
   If Previous Return Code Not INSERT
Line 120: Line 177:
Repeat Logic (Entered Only For DELETE)
Repeat Logic (Entered Only For DELETE)
</p>
</p>
<b>Note</b>
<p class="note"><b>Note:</b>
<p>Modified TAPEI records can be returned to FLOD through ACCEPT and DONE return codes only through Assembler Style Exits.</p>
Modified TAPEI records can be returned to <var>FLOD</var> through <code>ACCEPT</code> and <code>DONE</code> return codes only through Assembler-style exits.</p>
==Writing Assembler-style FLOD Exits==
 
<p>With Assembler-style FLOD Exits, the address of a parameter list, one word long and aligned on the fullword boundary, is placed in Register 1. The first byte of the parameter list is X'00' and the last three bytes contain the address of the record.</p>
==Writing Assembler-style FLOD exits==
<p>A zero address in Register 1 indicates an EOF condition. This means either that all TAPEI records have been passed, or that there were no records to pass. A zero address is the initial condition when TAPEI records are not passed.</p>
<p>
<p>When the FLOD Exit has finished processing the record, store the appropriate return code (see[[#Assembler return codes|Assembler return codes]]) in Register 15. Depending on the return code you specify, Register 1 might point to a record, either modified or unmodified.</p>
With Assembler-style <var>FLOD</var>  exits, the address of a parameter list, one word long and aligned on the fullword boundary, is placed in Register 1. The first byte of the parameter list is X'00' and the last three bytes contain the address of the record.</p>
<p>When variable-length records are returned to FLOD with Assembler-style FLOD Exits, the first four bytes of the record must contain a Record Descriptor Word that gives the length of the record.</p>
<p>
<b>Note</b>
A zero address in Register 1 indicates an EOF condition. This means either that all TAPEI records have been passed, or that there were no records to pass. A zero address is the initial condition when TAPEI records are not passed.</p>
<p>Do not modify either input parameters or the parameter list itself. Instead, copy the TAPEI record to a work area before modifying it.</p>
<p>
When the <var>FLOD</var>  exit has finished processing the record, store the appropriate return code (see [[#Assembler return codes|Assembler return codes]]) in Register 15. Depending on the return code you specify, Register 1 might point to a record, either modified or unmodified.</p>
<p>
When variable-length records are returned to <var>FLOD</var>  with Assembler-style <var>FLOD</var>  exits, the first four bytes of the record must contain a Record Descriptor Word that gives the length of the record.</p>
<p class="note"><b>Note:</b>
Do not modify either input parameters or the parameter list itself. Instead, copy the TAPEI record to a work area before modifying it.</p>
 
===Assembler register conventions===
===Assembler register conventions===
<p>Assembler-Style FLOD Exits must follow these register conventions:</p>
<p>
Assembler-Style FLOD exits must follow these register conventions:</p>
<table>
<table>
<tr class="head">
<tr class="head">
Line 138: Line 202:
<tr>
<tr>
<td align="right">1</td>
<td align="right">1</td>
<td> FLOD Exit parameter list upon entrance. This register might point to a record upon return.</td>
<td>FLOD-exit parameter list upon entrance. This register might point to a record upon return.</td>
</tr>
</tr>
<tr>
<tr>
<td align="right">13</td>
<td align="right">13</td>
<td>18- word area in which registers can be saved. This register is used for linkage.</td>
<td>18-word area in which registers can be saved. This register is used for linkage.</td>
</tr>
</tr>
<tr>
<tr>
<td align="right">14</td>
<td align="right">14</td>
<td>FLOD's return.</td>
<td>FLOD's return.</td>
</tr>
</tr>
<tr>
<tr>
<td align="right">15</td>
<td align="right">15</td>
Line 153: Line 220:
</tr>
</tr>
</table>
</table>
<p>Registers 2-12 must be preserved by the FLOD Exit upon return.</p>
<p>
Registers 2-12 must be preserved by the FLOD exit upon return.</p>
 
===Assembler return codes===
===Assembler return codes===
<p>The return codes within the FLOD Exit program give FLOD explicit instructions about how to handle each record. Return codes are defined in [[#Assembler return codes|Assembler return codes]].</p>
<p>
The return codes within the <var>FLOD</var>  exit program give <var>FLOD</var>  explicit instructions about how to handle each record. Return codes are defined in [[#Assembler return codes|Assembler return codes]].</p>
<table>
<table>
<caption>Assembler return codes for FLOD Exits</caption>
<caption>Assembler return codes for FLOD exits</caption>
<tr class="head">
<tr class="head">
<th>Return code</th>
<th>Return code</th>
<th>Meaning</th>
<th>Meaning</th>
</tr>
</tr>
<tr>
<tr>
<td align="right">0</td>
<td align="right">0</td>
<td>
<td><code>ACCEPT</code> record from TAPEI. Return code 0 is invalid for an EOF condition (where either EOF is reached or no records are passed from TAPEI).
<p>ACCEPT record from TAPEI. Return code 0 is invalid for an EOF condition (where either EOF is reached or no records are passed from TAPEI).</p>
<p>Send the record to <var>FLOD</var>. Load record address into Register 1.</p>
<p>Send the record to FLOD. Load record address into Register 1.</p>
</td></tr>
</td>
 
</tr>
<tr>
<tr>
<td align="right">4</td>
<td align="right">4</td>
<td>
<td><code>DELETE</code> record from TAPEI. Return code 4 is invalid for an EOF condition.
<p>DELETE record from TAPEI. Return code 4 is invalid for an EOF condition.</p>
<p>
<p>Read the next record from TAPEI, then call FLOD Exit. Do not exit the XG statement.</p>
Read the next record from TAPEI, then call <var>FLOD</var> exit. Do not exit the <var>XG</var> statement.</p>
<p>A record with the 4 return code is not sent to FLOD. You do not need to load the address into Register 1.</p>
<p>
</td>
A record with the 4 return code is not sent to <var>FLOD</var>. You do not need to load the address into Register 1.</p></td></tr>
</tr>
 
<tr>
<tr>
<td align="right">8</td>
<td align="right">8</td>
<td>
<td><code>DONE</code> &ndash; do not return to this exit. This return code is always valid.
<p>DONE - do not return to this Exit. This return code is always valid.</p>
<p>
<p>The 8 return code returns control to FLOD for the remainder of the FLOD program. You must pass the 8 return code at EOF unless you are inserting records after the original data.</p>
Return code 8 returns control to <var>FLOD</var> for the remainder of the <var>FLOD</var> program. You must pass the 8 return code at EOF unless you are inserting records after the original data.</p>
<p>If the FLOD Exit passes an 8 return code to FLOD before EOF, ACCEPT processing is performed for the current record to which Register 1 points. Subsequent executions of the XG statement perform like a G statement. Thus, the remaining TAPEI records are accepted on behalf of the Exit.</p>
<p>
</td>
If the <var>FLOD</var> exit passes an 8 return code to <var>FLOD</var> before EOF, <code>ACCEPT</code> processing is performed for the current record to which Register 1 points. Subsequent executions of the <var>XG</var> statement perform like a <var>G</var> statement. Thus, the remaining TAPEI records are accepted on behalf of the exit.</p>
</tr>
</td></tr>
 
<tr>
<tr>
<td align="right">12</td>
<td align="right">12</td>
<td>
<td><code>INSERT</code> record in <var>FLOD</var>. This return code is always valid.
<p>INSERT record in FLOD. This return code is always valid.</p>
<p>
<p>The 12 return code sends the record to FLOD, but does not advance TAPEI. Load the address into Register 1.</p>
The 12 return code sends the record to <var>FLOD</var>, but does not advance TAPEI. Load the address into Register 1.</p>
<p>This return code does not move the TAPEI record pointer to the next record. If FLOD is not an EOF, the FLOD Exit must ACCEPT or DELETE the current TAPEI record before another TAPEI record is passed.</p>
<p>
<p>In Assembler FLOD Exits, the 12 return code does not perform a check for modified record buffer overflow.</p>
This return code does not move the TAPEI record pointer to the next record. If <var>FLOD</var> is not an EOF, the <var>FLOD</var> exit must <code>ACCEPT</code> or <code>DELETE</code> the current TAPEI record before another TAPEI record is passed.</p>
</td>
<p>
</tr>
In Assembler <var>FLOD</var> exits, the 12 return code does not perform a check for modified record buffer overflow.</p></td></tr>
 
<tr>
<tr>
<td align="right">16</td>
<td align="right">16</td>
<td>
<td><code>TERMINATE</code> abnormally. This return code is always valid.
<p>TERMINATE abnormally. This return code is always valid.</p>
<p>
<p>The FLOD program is abnormally terminated. Use this return code to abort the FLOD program when the Exit determines a fatal error has occurred. You do not need to load the address into Register 1.</p>
The <var>FLOD</var> program is abnormally terminated. Use this return code to abort the <var>FLOD</var> program when the exit determines a fatal error has occurred. You do not need to load the address into Register 1.</p>
</td>
</td></tr>
</tr>
</table>
</table>
===Assembler/TAPEI example===
===Assembler/TAPEI example===
<p>In the following sample Assembler program, variable-length records are passed from FLOD to the FLOD Exit. The FLOD Exit checks each record for a minimum length. Any record that is at least the expected length can be accepted, modified, or deleted. Any record that is to be modified cannot exceed the modified record buffer length that is allocated in the Assembler Exit. If a length error is detected, the FLOD program is terminated.</p>
<p>
<p>All records, including the first record passed, are altered, deleted, or accepted. If the DEPT-ID field is 11111, it is altered to 33333. If the DEPT-ID field is 22222, the record is deleted (that is, are not passed to FLOD). All other records are accepted (that is, are passed to FLOD unmodified).</p>
In the following sample Assembler program, variable-length records are passed from <var>FLOD</var> to the <var>FLOD</var> exit. The <var>FLOD</var> exit checks each record for a minimum length. Any record that is at least the expected length can be accepted, modified, or deleted. Any record that is to be modified cannot exceed the modified record buffer length that is allocated in the Assembler exit. If a length error is detected, the <var>FLOD</var> program is terminated.</p>
<b>Note</b>
<p>
<p>This FLOD Exit must be modified to handle fixed-length records passed from FLOD. Assume that TAPEI has a variable-length record format. The syntax to invoke this FLOD Exit is:</p>
All records, including the first record passed, are altered, deleted, or accepted. If the <code>DEPT-ID</code> field is 11111, it is altered to 33333. If the <code>DEPT-ID</code> field is 22222, the record is deleted (that is, are not passed to <var>FLOD</var>). All other records are accepted (that is, are passed to <var>FLOD</var> unmodified).</p>
<p><var>XG 2,2,-1,0</var> </p>
<blockquote class="note">
<b>FLOD Exit using Assembler and TAPEI</b>
<p><b>Note:</b>
This <var>FLOD</var> exit must be modified to handle fixed-length records passed from <var>FLOD</var>. Assume that TAPEI has a variable-length record format. The syntax to invoke this <var>FLOD</var> exit is:</p>
<p class="syntax">XG 2,2,-1,0</p>
</blockquote>
 
<b>FLOD exit using Assembler and TAPEI</b>
<p class="code">FLODXT2  CSECT
<p class="code">FLODXT2  CSECT
R1      EQU  1
R1      EQU  1
Line 263: Line 340:
         END
         END
</p>
</p>
==Writing COBOL-style FLOD Exits==
 
===Parameters for COBOL-style FLOD Exits===
==Writing COBOL-style FLOD exits==
<p>Each time a COBOL-Style FLOD Exit is called, FLOD supplies the following parameter list:</p>
 
===Parameters for COBOL-style FLOD exits===
<p>
Each time a COBOL-style <var>FLOD</var> exit is called, <var>FLOD</var> supplies the following parameter list:</p>
<ul>
<ul>
<li>RECORD-FLAGS</li>
<li>RECORD-FLAGS</li>
Line 273: Line 353:
<li>MODIFIED-RECORD-LEN</li>
<li>MODIFIED-RECORD-LEN</li>
</ul>
</ul>
<p>These parameters are discussed in detail in the following sections.</p>
<p>
<b>RECORD-FLAGS</b>
These parameters are discussed in detail in the following table:</p>
<p>A pointer to a fullword specifying the TAPEI record being passed. This input parameter contains a X'00000000' when the first TAPEI record is passed and a X'00000004' when any other TAPEI record is passed.</p>
<table class="thJustBold">
<p>The value X'00000008' reflects an EOF condition and indicates that FLOD is not passing a TAPEI record. Either all TAPEI records have already been passed and accepted or deleted, or there were no records to pass. This is the initial condition when FLOD is not passing TAPEI records.</p>
<tr><th>RECORD-FLAGS</th>
<b>TAPEI-RECORD</b>
<td>A pointer to a fullword specifying the TAPEI record being passed. This input parameter contains a X'00000000' when the first TAPEI record is passed and a X'00000004' when any other TAPEI record is passed.
<p>A pointer to the current TAPEI record being passed. This pointer is zero when an EOF condition is found. This pointer is for system use only. This input parameter contains the record returned to FLOD when the RETURN-CODE is set to ACCEPT or the record to be ignored when the RETURN-CODE is set to DELETE.</p>
<p>
<p>This input parameter also contains the record returned to FLOD when the RETURN-CODE is set to DONE and an EOF condition is not found.</p>
The value X'00000008' reflects an EOF condition and indicates that <var>FLOD</var> is not passing a TAPEI record. Either all TAPEI records have already been passed and accepted or deleted, or there were no records to pass. This is the initial condition when <var>FLOD</var> is not passing TAPEI records.</p></td></tr>
<b>MODIFIED-RECORD</b>
 
<p>A pointer to the modified record buffer allocated by FLOD on behalf of the FLOD Exit. For variable-length records, this pointer is 4 bytes into the buffer to allow a record descriptor word to be built. If the XG statement did not request that a modified record buffer be allocated, this pointer is zero and is invalid to use. This parameter contains the record returned to FLOD when the RETURN-CODE is set to INSERT or ALTER/REPLACE.</p>
<tr><th>TAPEI-RECORD</th>
<b>TAPEI-RECORD-LEN</b>
<td>A pointer to the current TAPEI record being passed. This pointer is zero when an EOF condition is found. This pointer is for system use only. This input parameter contains the record returned to <var>FLOD</var> when the <code>RETURN-CODE</code> is set to <code>ACCEPT</code> or the record to be ignored when the <code>RETURN-CODE</code> is set to <code>DELETE</code>.
<p>A pointer to a fullword specifying the length of the current TAPEI record being passed. If an EOF condition is reflected, the length is zero. This input parameter contains the length of the record returned to FLOD when the RETURN-CODE is set to ACCEPT, or DONE when an EOF condition is not reflected.</p>
<p>
<b>MODIFIED-RECORD-LEN</b>
This input parameter also contains the record returned to <var>FLOD</var> when the <code>RETURN-CODE</code> is set to <code>DONE</code> and an EOF condition is not found.</p></td></tr>
<p>A pointer to a fullword specifying the length of the modified record. This parameter is set initially to the usable length of the modified record buffer or 0 if none was allocated. For variable-length records, this length must not exceed the size of the modified record buffer minus the 4 bytes required to build the record descriptor word (that is, usable length for variable-length records). This parameter is used to build the record descriptor word and contains the length of the variable-length record returned to FLOD when the RETURN-CODE is set to INSERT or ALTER/REPLACE. Modifying this parameter has no effect when fixed-length records are being processed. </p>
 
<b>Using COBOL-style FLOD Exit parameters</b>
<tr><th>MODIFIED-RECORD</th>
<p>When processing variable-length records with COBOL-style Exits, all length and record parameters do not include the 4-byte record descriptor. This is managed by FLOD for the Exit.</p>
<td>A pointer to the modified record buffer allocated by <var>FLOD</var> on behalf of the <var>FLOD</var> exit. For variable-length records, this pointer is 4 bytes into the buffer to allow a record descriptor word to be built. If the <var>XG</var> statement did not request that a modified record buffer be allocated, this pointer is zero and is invalid to use. This parameter contains the record returned to <var>FLOD</var> when the <code>RETURN-CODE</code> is set to <code>INSERT</code> or <code>ALTER/REPLACE</code>.</td></tr>
<p>Do not modify either input parameters or the parameter list itself. Copy the TAPEI record to a work area before modifying it.</p>
 
<p>Output parameters are given initial values but are not modified by FLOD. The Exit can depend on output parameters being preserved.</p>
<tr><th>TAPEI-RECORD-LEN</th>
<p>The parameter list is static except for the TAPEI-RECORD pointer. All input parameters are static for an EOF condition.</p>
<td>A pointer to a fullword specifying the length of the current TAPEI record being passed. If an EOF condition is reflected, the length is zero. This input parameter contains the length of the record returned to <var>FLOD</var> when the <code>RETURN-CODE</code> is set to <code>ACCEPT</code>, or to <code>DONE</code> when an EOF condition is not reflected.</td></tr>
<b>Note</b>
 
<p>You can choose to have an Assembler program be called with the COBOL-style convention to take advantage of the extended parameter list. However, this program must not modify input parameters nor the parameter list itself.</p>
<tr><th nowrap>MODIFIED-RECORD-LEN</th>
<td>A pointer to a fullword specifying the length of the modified record. This parameter is set initially to the usable length of the modified record buffer or 0 if none was allocated. For variable-length records, this length must not exceed the size of the modified record buffer minus the 4 bytes required to build the record descriptor word (that is, usable length for variable-length records). This parameter is used to build the record descriptor word and contains the length of the variable-length record returned to <var>FLOD</var> when the <code>RETURN-CODE</code> is set to <code>INSERT</code> or <code>ALTER/REPLACE</code>. Modifying this parameter has no effect when fixed-length records are being processed. </td></tr>
</table>
 
<b>Using COBOL-style FLOD-exit parameters</b>
<p>
When processing variable-length records with COBOL-style exits, all length and record parameters do not include the 4-byte record descriptor. This is managed by <var>FLOD</var> for the exit.</p>
<p>
Do not modify either input parameters or the parameter list itself. Copy the TAPEI record to a work area before modifying it.</p>
<p>
Output parameters are given initial values but are not modified by <var>FLOD</var>. The exit can depend on output parameters being preserved.</p>
<p>
The parameter list is static except for the <var>TAPEI-RECORD</var> pointer. All input parameters are static for an EOF condition.</p>
<p class="note"><b>Note:</b>
You can choose to have an Assembler program be called with the COBOL-style convention to take advantage of the extended parameter list. However, this program must not modify input parameters nor the parameter list itself.</p>
 
===COBOL return codes===
===COBOL return codes===
<p>The return codes within the FLOD Exit program give FLOD explicit instructions about how to handle each record. The return code is moved to the RETURN-CODE special register. Return codes are described in Table 12-2.</p>
<p>
The return codes within the <var>FLOD</var> exit program give <var>FLOD</var> explicit instructions about how to handle each record. The return code is moved to the <code>RETURN-CODE</code> special register. Return codes are described in the following table:</p>
<table>
<table>
<caption>Return codes for COBOL-style FLOD Exits</caption>
<caption>Return codes for COBOL-style FLOD exits</caption>
<tr class="head">
<tr class="head">
<th>Return code</th>
<th>Return code</th>
<th>Meaning</th>
<th>Meaning</th>
</tr>
</tr>
<tr>
<tr>
<td align="right">0</td>
<td align="right">0</td>
<td>
<td>ACCEPT record from TAPEI. This return code is invalid for an EOF condition (where either EOF is reached or no records are passed from TAPEI).
<p>ACCEPT record from TAPEI. This return code is invalid for an EOF condition (where either EOF is reached or no records are passed from TAPEI).</p>
<p>
<p>Send the unmodified record (TAPEI-RECORD) to FLOD.</p>
Send the unmodified record (TAPEI-RECORD) to <var>FLOD</var>.</p></td></tr>
</td>
 
</tr>
<tr>
<tr>
<td align="right">4</td>
<td align="right">4</td>
<td>
<td>DELETE record from TAPEI. This return code is invalid for an EOF condition.
<p>DELETE record from TAPEI. This return code is invalid for an EOF condition.</p>
<p>
<p>Read next record from TAPEI, then call FLOD Exit. Do not exit the XG statement.</p>
Read next record from TAPEI, then call <var>FLOD</var> exit. Do not exit the <code>XG</code> statement.</p>
<p>The 4 return code does not send a record to FLOD.</p>
<p>
</td>
The 4 return code does not send a record to <var>FLOD</var>.</p></td></tr>
</tr>
 
<tr>
<tr>
<td align="right">8</td>
<td align="right">8</td>
<td>
<td>DONE &ndash; do not return to this exit. This return code is always valid.
<p>DONE-do not return to this Exit. This return code is always valid.</p>
<p>
<p>The 8 return code returns control to FLOD for the remainder of the FLOD program. You must pass the 8 return code at EOF unless you are inserting records after the original data.</p>
The 8 return code returns control to <var>FLOD</var> for the remainder of the <var>FLOD</var> program. You must pass the 8 return code at EOF unless you are inserting records after the original data.</p>
<p>If the FLOD Exit passes an 8 return code to FLOD before EOF is reached, ACCEPT processing is performed for the current TAPEI record. Subsequent executions of the XG statement perform like a G statement. Thus, the remaining TAPEI records are accepted on behalf of the Exit.</p>
<p>
</td>
If the <var>FLOD</var> exit passes an 8 return code to <var>FLOD</var> before EOF is reached, ACCEPT processing is performed for the current TAPEI record. Subsequent executions of the XG statement perform like a <code>G</code> statement. Thus, the remaining TAPEI records are accepted on behalf of the exit.</p></td></tr>
</tr>
 
<tr>
<tr>
<td align="right">12</td>
<td align="right">12</td>
<td>
<td>INSERT record in FLOD. This return code is always valid.
<p>INSERT record in FLOD. This return code is always valid.</p>
<p>
<p>This return code sends the record to FLOD, but does not advance TAPEI. Move the record to the MODIFIED-RECORD parameter and move the length of this record to the MODIFIED-RECORD-LEN parameter.</p>
This return code sends the record to <var>FLOD</var>, but does not advance TAPEI. Move the record to the <var>MODIFIED-RECORD</var> parameter and move the length of this record to the <var>MODIFIED-RECORD-LEN</var> parameter.</p>
<p>The 12 return code keeps the TAPEI-RECORD pointer at the same location. If there is no EOF condition, the FLOD Exit must ACCEPT, DELETE, or ALTER/REPLACE the current TAPEI record before the next TAPEI record is passed.</p>
<p>
<p>The 12 return code performs a check (for COBOL-style Exits) for modified record buffer overflow with variable-length records by comparing the MODIFIED-RECORD-LEN parameter against its maximum value.</p>
The 12 return code keeps the <var>TAPEI-RECORD</var> pointer at the same location. If there is no EOF condition, the <var>FLOD</var> exit must ACCEPT, DELETE, or ALTER/REPLACE the current TAPEI record before the next TAPEI record is passed.</p>
</td>
<p>
</tr>
The 12 return code performs a check (for COBOL-style exits) for modified record buffer overflow with variable-length records by comparing the <var>MODIFIED-RECORD-LEN</var> parameter against its maximum value.</p>
</td></tr>
 
<tr>
<tr>
<td align="right">16</td>
<td align="right">16</td>
<td>
<td>TERMINATE Abnormally. This return code is always valid.
<p>TERMINATE Abnormally. This return code is always valid.</p>
<p>
<p>The FLOD program is abnormally terminated. Use this return code to alert the FLOD program when the Exit determines a fatal error has occurred.</p>
The <var>FLOD</var> program is abnormally terminated. Use this return code to alert the <var>FLOD</var> program when the exit determines a fatal error has occurred.</p></td></tr>
</td>
 
</tr>
<tr>
<tr>
<td align="right">20</td>
<td align="right">20</td>
<td>
<td>ALTER/REPLACE record. This return code is invalid for an EOF condition.
<p>ALTER/REPLACE record. This return code is invalid for an EOF condition.</p>
<p>
<p>Move the record to the MODIFIED-RECORD parameter and move the length of this record to the MODIFIED-RECORD-LEN parameter.</p>
Move the record to the <var>MODIFIED-RECORD</var> parameter and move the length of this record to the <var>MODIFIED-RECORD-LEN</var> parameter.</p>
<p>The 20 return code (only valid from COBOL-style Exits) causes a check for modified record buffer overflow for variable-length records by comparing the MODIFIED-RECORD-LEN parameter against its maximum value.</p>
<p>
</td>
The 20 return code (only valid from COBOL-style exits) causes a check for modified record buffer overflow for variable-length records by comparing the <var>MODIFIED-RECORD-LEN</var> parameter against its maximum value.</p></td></tr>
</tr>
</table>
</table>
===Diagram of COBOL-style FLOD Exits===
 
<p>[[#Structure of COBOL-style FLOD Exits|Structure of COBOL-style FLOD Exits]] shows the structure of the COBOL interface to FLOD Exit functions.</p>
===Diagram of COBOL-style FLOD exits===
====Structure of COBOL-style FLOD Exits====
<p>
[[File:_FLOD_Exits_4.gif]]
The following figure shows the structure of the COBOL interface to FLOD exit functions:</p>
 
<p class="caption" style="width:563px">Structure of COBOL-style FLOD exits</p>
<p class="figure">[[File:COBOL-style FLOD exits.gif]]</p>
 
===LINKAGE SECTION and PROCEDURE DIVISION issues===
===LINKAGE SECTION and PROCEDURE DIVISION issues===
<p>The LINKAGE SECTION and PROCEDURE DIVISION are required in COBOL FLOD Exit programs. The LINKAGE SECTION identifies what gets passed to the FLOD Exit; the parameters are repeated in the USING option of the PROCEDURE DIVISION.</p>
<p>
<p>In the USING option, specify each 01-level name in the LINKAGE SECTION. Specify each name in order up to the last one you plan to use, even if you do not use all the names.</p>
The LINKAGE SECTION and PROCEDURE DIVISION are required in COBOL <var>FLOD</var> exit programs. The LINKAGE SECTION identifies what gets passed to the <var>FLOD</var> exit; the parameters are repeated in the <code>USING</code> option of the PROCEDURE DIVISION.</p>
<p>You must use the GOBACK statement to return control to FLOD.</p>
<p>
In the <code>USING</code> option, specify each 01-level name in the LINKAGE SECTION. Specify each name in order up to the last one you plan to use, even if you do not use all the names.</p>
<p>
You must use the <code>GOBACK</code> statement to return control to FLOD.</p>
 
===COBOL/TAPEI example===
===COBOL/TAPEI example===
<p>In the following sample COBOL program, variable-length records are passed from FLOD to the FLOD Exit.</p>
<p>
<p>When the first record is passed, the usable size of the modified record buffer is checked against the maximum allowed for in the COBOL Exit. The FLOD program is terminated if the modified record buffer cannot hold the largest record that the COBOL Exit can handle. In addition, all TAPEI record lengths are verified against the maximum allowed length. Any length violations detected cause the FLOD program to terminate. No check is provided to verify the minimum length of a record. (This can easily be added.)</p>
In the following sample COBOL program, variable-length records are passed from <var>FLOD</var> to the <var>FLOD</var> exit.</p>
<p>All records, including the first record passed, are either altered, deleted, or accepted. If the DEPT-ID field is 11111, it is altered to 33333. If the DEPT-ID field is 22222, the record is deleted (that is, not passed to FLOD). All other records are accepted that is, passed to FLOD unmodified).</p>
<p>
<b>Note</b>
When the first record is passed, the usable size of the modified record buffer is checked against the maximum allowed for in the COBOL exit. The <var>FLOD</var> program is terminated if the modified record buffer cannot hold the largest record that the COBOL exit can handle. In addition, all TAPEI record lengths are verified against the maximum allowed length. Any length violations detected cause the <var>FLOD</var> program to terminate. No check is provided to verify the minimum length of a record. (This can easily be added.)</p>
<p>This FLOD Exit need not be modified to handle fixed-length records passed from FLOD. In either case, this COBOL Exit can be invoked with:</p>
<p>
<p><var>XG 3,1,84,0 </var></p>
All records, including the first record passed, are either altered, deleted, or accepted. If the <code>DEPT-ID</code> field is 11111, it is altered to 33333. If the <code>DEPT-ID</code> field is 22222, the record is deleted (that is, not passed to <var>FLOD</var>). All other records are accepted that is, passed to FLOD unmodified).</p>
<b>Sample COBOL/TAPEI FLOD Exit</b>
<blockquote class="note">
<p><b>Note:</b>
This <var>FLOD</var> exit need not be modified to handle fixed-length records passed from <var>FLOD</var>. In either case, this COBOL exit can be invoked with:</p>
<p class="code">XG 3,1,84,0 </p>
</blockquote>
 
<b>Sample COBOL/TAPEI FLOD exit</b>
<p class="code">IDENTIFICATION DIVISION.
<p class="code">IDENTIFICATION DIVISION.
  PROGRAM-ID.      FLODXT3.
  PROGRAM-ID.      FLODXT3.
Line 457: Line 567:
     GOBACK.
     GOBACK.
</p>
</p>
===COBOL/TAPEI/alternate data set example===
===COBOL/TAPEI/alternate data set example===
<p>In the following sample COBOL program, variable-length TAPEI records can be passed from FLOD to the FLOD Exit. The FLOD Exit also processes records from another data set. Variable-length records are returned to FLOD. An output file is produced for debugging purposes. Rocket Software suggests that you use debugging statements when testing FLOD Exits, which you can later comment out, after the Exit is performing as expected.</p>
<p>
<b>Sample COBOL/TAPEI FLOD Exit with alternate data sets</b>
In the following sample COBOL program, variable-length TAPEI records can be passed from <var>FLOD</var> to the <var>FLOD</var> exit. The <var>FLOD</var> exit also processes records from another data set. Variable-length records are returned to <var>FLOD</var>. An output file is produced for debugging purposes. Rocket Software suggests that you use debugging statements when testing <var>FLOD</var> exits, which you can later comment out, after the exit is performing as expected.</p>
 
<b>Sample COBOL/TAPEI FLOD exit with alternate data sets</b>
<p class="code">IDENTIFICATION DIVISION.
<p class="code">IDENTIFICATION DIVISION.
PROGRAM-ID.  FLODXT1.
PROGRAM-ID.  FLODXT1.
Line 641: Line 754:


  **************************************************************
  **************************************************************
  More


READ-FILE.
READ-FILE.
Line 716: Line 827:
  **************************************************************
  **************************************************************


</p>
[[Category:File loading and reorganization]]
<p>&nbsp;</p>
[[Category:File manager]]
[[Category:File Management]]

Latest revision as of 22:04, 12 January 2015

Overview

The Model 204 File Load utility enables you to load raw data from a sequential data set into Model 204. The heart of the File Load utility, the FLOD program, allows you to manipulate the data as it is being loaded. FLOD (or FILELOAD) exits allow for much more sophisticated data manipulation including performing edit checks, creating derived fields, and merging data from multiple data sets.

FLOD exits are programs much like E15 Sort exits. They add the capability to exit the FLOD program, passing control to a "FLOD exit" COBOL or Assembler program.

The FLOD exit allows the FLOD or FILELOAD command to read from another source besides the TAPEI file normally required for FLOD and FILELOAD. This allows you to use more than one input file for FLOD or FILELOAD processing.

FLOD exits are normally run as batch applications.

File Load XG statement

The FLOD or FILELOAD command uses the XG statement to pass control to the FLOD exit. The XG statement is discussed in detail on XG statement.

FLOD exits and Sort exits

FLOD exits are modeled on Sort exits similar to the IBM DFSORT. FLOD exit programs are similar to E15 Sort exit programs. For more information about E15 Sort exits, see the documentation for your sort package.

E32 and E35 types of Sort exits (which allow you to modify records already modified by an E15 exit) are not supported.

Data sources for FLOD exits

FLOD exits are capable of using data from two sources:

  • TAPEI data passed to the exit
  • Data accessed by the FLOD exit

The data source you select depends on the purpose of the FLOD exit program. The data source argument specified on the XG statement determines whether or not TAPEI records are to be passed to the FLOD exit. Other data accessed by the FLOD exit can always be used to generate records for insertion.

The return codes within FLOD exits vary both according to the source of the data and to the language in which the exit is written. FLOD exits involving each data source are discussed separately in the following sections.

Passing records from TAPEI

Pass records to a FLOD exit from TAPEI when you do not want to code I/O logic into the FLOD exit or when you want general purpose FLOD exits. For example, if your site has a number of input files, all of which have the same record format, one FLOD exit can manipulate the data in any of the files.

The path taken by the data using this method is shown in "Passing TAPEI records to FLOD exit":

Passing TAPEI records to FLOD exit

Inserting records read from alternate data sets

Use this FLOD exit feature when you want to read records from multiple data sets. The FLOD exit is responsible for defining and accessing all alternate data sets.

This method is shown in the following figure:

FLOD exit to insert records from alternate data sets

Storage requirements

To ensure that a FLOD exit has enough working storage space, SPCORE requires:

80 bytes + the size of the modified record buffer + any storage acquired by the exit

For information about the modified record buffer, see XG statement.

If the FLOD exit program does not have enough space, it might terminate the Model 204 run.

Using FLOD exits in z/OS environment

In the z/OS environment, control is transferred to a FLOD exit in 24-bit addressing mode through a BALR 14,15 instruction. All addresses, including the parameter list address passed in Register 1, are 24-bit addresses (bits 25-31 are 0).

When a FLOD exit passes a new record to FLOD (using an INSERT or ALTER/REPLACE return code), the address of the new record is treated as a valid 31-bit address and might, therefore, reside above the 16M line.

Because a BALR 14,15 instruction stores link information in the high-order byte of Register 14 when executed in 24-bit mode, a FLOD exit using 31-bit processing mode must clear the high-order byte of the address in Register 14 before issuing a BR 14 instruction.

XG statement

Within a FLOD program, the XG statement is an enhanced G statement. It returns a new input record for processing. If no more input records remain, the file load program terminates and Model 204 goes on to the command that follows the END statement.

The order and content of input records returned to FLOD is determined by the FLOD exit. The XG statement allows you to call a specific FLOD exit program and process records in the format of your choice.

The XG statement can be specified as often as needed in a FLOD program. However, Model 204 only processes the syntax of the first XG statement that it compiles, and that syntax is used for any further calls to a FLOD exit within that FLOD program.

Syntax

The syntax for the XG statement is:

XG [n] [,[c] [,[r] [,[s]]]]

Where:

  • n is the number of a FLOD exit program that has been linked into Model 204. FLOD exit programs must be named FLODXTn, where n is a number from 0 to 19. Up to 20 FLOD exit programs can exist (FLODXT0 to FLODXT19) at any time.

    If you try to call a nonexistent FLOD exit program, Model 204 detects it before executing the first FLOD statement, and issues an appropriate error message.

    The default FLOD exit program is 0 (FLOD exit program FLODXT0).

  • c specifies the language of the calling convention such as COBOL or Assembler, that modifies the record image FLOD or FILELOADoperates on.

    The valid settings for the calling conventions are:

    • 1, the default, for COBOL. You cannot use the DYNAM option in COBOL.
    • 2 for Assembler

    The default is COBOL.

    Any language that uses the same calling conventions as COBOL or Assembler can be used to call the FLOD exit. Specify the calling convention that is similar to the language of the FLODXTn program.

  • r specifies the length of the modified record buffer to be allocated by Model 204. The possible settings for this argument are:
    • Negative number indicates that a modified record buffer is not allocated.
    • Zero, the default, indicates that the number of bytes to allocate is TAPEI's LRECL.
    • Positive number specifies the length in bytes of the modified record buffer. The author of the FLOD exit is responsible for including 4 bytes of variable record overhead and 4 bytes of block overhead (totaling 8 bytes) in the space requirements.

    For Assembler-style exits, this parameter is ignored. These exits must provide their own modified record buffer if modified records are to be returned or additional records inserted.

    For COBOL-style exits, a modified record buffer is required for INSERT and ALTER/REPLACE operations. You must specify a positive value if you are not passing TAPEI records to the exit.

  • s specifies the source of the data:
    • 0, the default, indicates that FLOD supplies the data from TAPEI to the FLOD exit. The FLOD exit receives and returns fixed- or variable-length records depending on the record format of TAPEI.
    • 1 indicates that FLOD does not pass records to the exit and that the exit returns (INSERT) fixed-length records to FLOD.
    • 2 indicates that FLOD does not pass records to the exit and that the exit returns (INSERT) variable-length records to FLOD.

    If TAPEI records are not passed, the initial condition is reflected as an EOF condition on TAPEI.

XG statement logic flow

The following example shows the flow of the XG statement logic:

If Passing TAPEI Data If Previous Return Code Not INSERT Read Next TAPEI Data If EOF Set EOF State in Parmlist If Previous Return Code Is DONE Return EOF Condition To FLOD Program End If Clear TAPEI Information In Parmlist Else If Previous Return Code Is DONE Return Unmodified TAPEI Record To FLOD Program End If Store New TAPEI Information In Parmlist End If End If End If Call FLOD Exit Program If Not EOF State In Parmlist Set MIDDLE-REC State In Parmlist End If Select On Return Code: When ACCEPT Error If EOF State In Parmlist Return (Un)Modified TAPEI Record To FLOD Program* When DELETE Error If EOF State In Parmlist When DONE If EOF State In Parmlist Return EOF Condition To FLOD Program Else Return (Un)Modified TAPEI Record To FLOD Program* End If When INSERT Error If Modified Record Length > Buffer Size (COBOL Only) Return Insert Record To FLOD Program When TERMINATE Error When ALTER/REPLACE Error If EOF State In Parmlist Error If Assembler Error If Modified Record Length > Buffer Size (COBOL Only) Return Modified TAPEI Record To FLOD Program Select End Repeat Logic (Entered Only For DELETE)

Note: Modified TAPEI records can be returned to FLOD through ACCEPT and DONE return codes only through Assembler-style exits.

Writing Assembler-style FLOD exits

With Assembler-style FLOD exits, the address of a parameter list, one word long and aligned on the fullword boundary, is placed in Register 1. The first byte of the parameter list is X'00' and the last three bytes contain the address of the record.

A zero address in Register 1 indicates an EOF condition. This means either that all TAPEI records have been passed, or that there were no records to pass. A zero address is the initial condition when TAPEI records are not passed.

When the FLOD exit has finished processing the record, store the appropriate return code (see Assembler return codes) in Register 15. Depending on the return code you specify, Register 1 might point to a record, either modified or unmodified.

When variable-length records are returned to FLOD with Assembler-style FLOD exits, the first four bytes of the record must contain a Record Descriptor Word that gives the length of the record.

Note: Do not modify either input parameters or the parameter list itself. Instead, copy the TAPEI record to a work area before modifying it.

Assembler register conventions

Assembler-Style FLOD exits must follow these register conventions:

Register Address of...
1 FLOD-exit parameter list upon entrance. This register might point to a record upon return.
13 18-word area in which registers can be saved. This register is used for linkage.
14 FLOD's return.
15 Exit program's entry point. This register must contain the return code upon return.

Registers 2-12 must be preserved by the FLOD exit upon return.

Assembler return codes

The return codes within the FLOD exit program give FLOD explicit instructions about how to handle each record. Return codes are defined in Assembler return codes.

Assembler return codes for FLOD exits
Return code Meaning
0 ACCEPT record from TAPEI. Return code 0 is invalid for an EOF condition (where either EOF is reached or no records are passed from TAPEI).

Send the record to FLOD. Load record address into Register 1.

4 DELETE record from TAPEI. Return code 4 is invalid for an EOF condition.

Read the next record from TAPEI, then call FLOD exit. Do not exit the XG statement.

A record with the 4 return code is not sent to FLOD. You do not need to load the address into Register 1.

8 DONE – do not return to this exit. This return code is always valid.

Return code 8 returns control to FLOD for the remainder of the FLOD program. You must pass the 8 return code at EOF unless you are inserting records after the original data.

If the FLOD exit passes an 8 return code to FLOD before EOF, ACCEPT processing is performed for the current record to which Register 1 points. Subsequent executions of the XG statement perform like a G statement. Thus, the remaining TAPEI records are accepted on behalf of the exit.

12 INSERT record in FLOD. This return code is always valid.

The 12 return code sends the record to FLOD, but does not advance TAPEI. Load the address into Register 1.

This return code does not move the TAPEI record pointer to the next record. If FLOD is not an EOF, the FLOD exit must ACCEPT or DELETE the current TAPEI record before another TAPEI record is passed.

In Assembler FLOD exits, the 12 return code does not perform a check for modified record buffer overflow.

16 TERMINATE abnormally. This return code is always valid.

The FLOD program is abnormally terminated. Use this return code to abort the FLOD program when the exit determines a fatal error has occurred. You do not need to load the address into Register 1.

Assembler/TAPEI example

In the following sample Assembler program, variable-length records are passed from FLOD to the FLOD exit. The FLOD exit checks each record for a minimum length. Any record that is at least the expected length can be accepted, modified, or deleted. Any record that is to be modified cannot exceed the modified record buffer length that is allocated in the Assembler exit. If a length error is detected, the FLOD program is terminated.

All records, including the first record passed, are altered, deleted, or accepted. If the DEPT-ID field is 11111, it is altered to 33333. If the DEPT-ID field is 22222, the record is deleted (that is, are not passed to FLOD). All other records are accepted (that is, are passed to FLOD unmodified).

Note: This FLOD exit must be modified to handle fixed-length records passed from FLOD. Assume that TAPEI has a variable-length record format. The syntax to invoke this FLOD exit is:

XG 2,2,-1,0

FLOD exit using Assembler and TAPEI

FLODXT2 CSECT R1 EQU 1 R2 EQU 2 R12 EQU 12 R13 EQU 13 R14 EQU 14 R15 EQU 15 STM R14,R12,12(R13) STANDARD SAVE CONVENTION LR R12,R15 SET UP BASE REGISTER USING FLODXT2,R12 PROVIDE ADDRESSABILITY SPACE SLR R15,R15 DEFAULT RC=0 L R1,0(,R1) R1 := PTR TO RECORD LTR R1,R1 CHECK TAPEI RECORD PTR BZ DONE IF EOF, THEN DONE LH R2,0(,R1) R2 := LENGTH FROM RDW C R2,MINLEN CHECK LENGTH BL ERROR ERROR IF BELOW MINIMUM CLC DELDEPT,DEPTID-RDW(R1) CHECK IF DEPT TO DELETE BE DELETE IF EQUAL, THEN DELETE CLC CHGDEPT,DEPTID-RDW(R1) CHECK IF DEPT TO CHANGE BNE RETURN IF NOT EQUAL, THEN ACCEPT C R2,MAXLEN CHECK LENGTH BH ERROR ERROR IF ABOVE BUFFER MAXIMUM BCTR R2,0 DECREMENT FOR EX MVC EX R2,MOVEREC MVC RDW(0),0(R1) LA R1,RDW R1 := PTR TO MODIFIED RECORD MVC DEPTID,NEWDEPT SAVE NEW DEPT ID SPACE RETURN LM R2,R12,4*4+12(R13) RESTORE ONLY REGISTERS 2-12 BR R14 RETURN TO FLOD SPACE MOVEREC MVC RDW(*-*),0(R1) MOVE RECORD INTO BUFFER SPACE ERROR LA R15,8(,R15) RESULTANT RC=16 DONE LA R15,4(,R15) RESULTANT RC=8 DELETE LA R15,4(,R15) RESULTANT RC=4 B RETURN COMMON EXIT SPACE DC 0D'0' ALIGN STORAGE ON DOUBLEWORD MINLEN DC A(DEPTNAME-RDW+1) NAME MUST BE AT LEAST 1 BYTE MAXLEN DC A(BUFFEND-RDW) VARIABLE LENGTH RECORD MAX DC CL8'FLXTMRBF' EYE-CATCHER FOR DEBUGGING RDW DC Y(0,0) RECORD DESCRIPTOR WORD DEPTID DC CL5' ' DEPT ID ALWAYS PRESENT DEPTNAME DC CL75' ' DEPT NAME IS 1 TO 75 BYTES BUFFEND DS 0C END OF MODIFIED RECORD BUFFER SPACE CHGDEPT DC CL5'11111' DEPT ID TO CHANGE TO NEW DEPT DELDEPT DC CL5'22222' DEPT ID TO DELETE NEWDEPT DC CL5'33333' NEW DEPT ID FOR CHGDEPT DROP R12 DROP ADDRESSABILITY TO EXIT END

Writing COBOL-style FLOD exits

Parameters for COBOL-style FLOD exits

Each time a COBOL-style FLOD exit is called, FLOD supplies the following parameter list:

  • RECORD-FLAGS
  • TAPEI-RECORD
  • MODIFIED-RECORD
  • TAPEI-RECORD-LEN
  • MODIFIED-RECORD-LEN

These parameters are discussed in detail in the following table:

RECORD-FLAGS A pointer to a fullword specifying the TAPEI record being passed. This input parameter contains a X'00000000' when the first TAPEI record is passed and a X'00000004' when any other TAPEI record is passed.

The value X'00000008' reflects an EOF condition and indicates that FLOD is not passing a TAPEI record. Either all TAPEI records have already been passed and accepted or deleted, or there were no records to pass. This is the initial condition when FLOD is not passing TAPEI records.

TAPEI-RECORD A pointer to the current TAPEI record being passed. This pointer is zero when an EOF condition is found. This pointer is for system use only. This input parameter contains the record returned to FLOD when the RETURN-CODE is set to ACCEPT or the record to be ignored when the RETURN-CODE is set to DELETE.

This input parameter also contains the record returned to FLOD when the RETURN-CODE is set to DONE and an EOF condition is not found.

MODIFIED-RECORD A pointer to the modified record buffer allocated by FLOD on behalf of the FLOD exit. For variable-length records, this pointer is 4 bytes into the buffer to allow a record descriptor word to be built. If the XG statement did not request that a modified record buffer be allocated, this pointer is zero and is invalid to use. This parameter contains the record returned to FLOD when the RETURN-CODE is set to INSERT or ALTER/REPLACE.
TAPEI-RECORD-LEN A pointer to a fullword specifying the length of the current TAPEI record being passed. If an EOF condition is reflected, the length is zero. This input parameter contains the length of the record returned to FLOD when the RETURN-CODE is set to ACCEPT, or to DONE when an EOF condition is not reflected.
MODIFIED-RECORD-LEN A pointer to a fullword specifying the length of the modified record. This parameter is set initially to the usable length of the modified record buffer or 0 if none was allocated. For variable-length records, this length must not exceed the size of the modified record buffer minus the 4 bytes required to build the record descriptor word (that is, usable length for variable-length records). This parameter is used to build the record descriptor word and contains the length of the variable-length record returned to FLOD when the RETURN-CODE is set to INSERT or ALTER/REPLACE. Modifying this parameter has no effect when fixed-length records are being processed.

Using COBOL-style FLOD-exit parameters

When processing variable-length records with COBOL-style exits, all length and record parameters do not include the 4-byte record descriptor. This is managed by FLOD for the exit.

Do not modify either input parameters or the parameter list itself. Copy the TAPEI record to a work area before modifying it.

Output parameters are given initial values but are not modified by FLOD. The exit can depend on output parameters being preserved.

The parameter list is static except for the TAPEI-RECORD pointer. All input parameters are static for an EOF condition.

Note: You can choose to have an Assembler program be called with the COBOL-style convention to take advantage of the extended parameter list. However, this program must not modify input parameters nor the parameter list itself.

COBOL return codes

The return codes within the FLOD exit program give FLOD explicit instructions about how to handle each record. The return code is moved to the RETURN-CODE special register. Return codes are described in the following table:

Return codes for COBOL-style FLOD exits
Return code Meaning
0 ACCEPT record from TAPEI. This return code is invalid for an EOF condition (where either EOF is reached or no records are passed from TAPEI).

Send the unmodified record (TAPEI-RECORD) to FLOD.

4 DELETE record from TAPEI. This return code is invalid for an EOF condition.

Read next record from TAPEI, then call FLOD exit. Do not exit the XG statement.

The 4 return code does not send a record to FLOD.

8 DONE – do not return to this exit. This return code is always valid.

The 8 return code returns control to FLOD for the remainder of the FLOD program. You must pass the 8 return code at EOF unless you are inserting records after the original data.

If the FLOD exit passes an 8 return code to FLOD before EOF is reached, ACCEPT processing is performed for the current TAPEI record. Subsequent executions of the XG statement perform like a G statement. Thus, the remaining TAPEI records are accepted on behalf of the exit.

12 INSERT record in FLOD. This return code is always valid.

This return code sends the record to FLOD, but does not advance TAPEI. Move the record to the MODIFIED-RECORD parameter and move the length of this record to the MODIFIED-RECORD-LEN parameter.

The 12 return code keeps the TAPEI-RECORD pointer at the same location. If there is no EOF condition, the FLOD exit must ACCEPT, DELETE, or ALTER/REPLACE the current TAPEI record before the next TAPEI record is passed.

The 12 return code performs a check (for COBOL-style exits) for modified record buffer overflow with variable-length records by comparing the MODIFIED-RECORD-LEN parameter against its maximum value.

16 TERMINATE Abnormally. This return code is always valid.

The FLOD program is abnormally terminated. Use this return code to alert the FLOD program when the exit determines a fatal error has occurred.

20 ALTER/REPLACE record. This return code is invalid for an EOF condition.

Move the record to the MODIFIED-RECORD parameter and move the length of this record to the MODIFIED-RECORD-LEN parameter.

The 20 return code (only valid from COBOL-style exits) causes a check for modified record buffer overflow for variable-length records by comparing the MODIFIED-RECORD-LEN parameter against its maximum value.

Diagram of COBOL-style FLOD exits

The following figure shows the structure of the COBOL interface to FLOD exit functions:

Structure of COBOL-style FLOD exits

LINKAGE SECTION and PROCEDURE DIVISION issues

The LINKAGE SECTION and PROCEDURE DIVISION are required in COBOL FLOD exit programs. The LINKAGE SECTION identifies what gets passed to the FLOD exit; the parameters are repeated in the USING option of the PROCEDURE DIVISION.

In the USING option, specify each 01-level name in the LINKAGE SECTION. Specify each name in order up to the last one you plan to use, even if you do not use all the names.

You must use the GOBACK statement to return control to FLOD.

COBOL/TAPEI example

In the following sample COBOL program, variable-length records are passed from FLOD to the FLOD exit.

When the first record is passed, the usable size of the modified record buffer is checked against the maximum allowed for in the COBOL exit. The FLOD program is terminated if the modified record buffer cannot hold the largest record that the COBOL exit can handle. In addition, all TAPEI record lengths are verified against the maximum allowed length. Any length violations detected cause the FLOD program to terminate. No check is provided to verify the minimum length of a record. (This can easily be added.)

All records, including the first record passed, are either altered, deleted, or accepted. If the DEPT-ID field is 11111, it is altered to 33333. If the DEPT-ID field is 22222, the record is deleted (that is, not passed to FLOD). All other records are accepted that is, passed to FLOD unmodified).

Note: This FLOD exit need not be modified to handle fixed-length records passed from FLOD. In either case, this COBOL exit can be invoked with:

XG 3,1,84,0

Sample COBOL/TAPEI FLOD exit

IDENTIFICATION DIVISION. PROGRAM-ID. FLODXT3. COMMENTS. VARIABLE OR FIXED LENGTH RECORDS ARE PASSED. ENVIRONMENT DIVISION. DATA DIVISION. WORKING-STORAGE SECTION. 01 DEPT-RECORD. 05 DEPT-ID PIC 9(5). 88 CHG-DEPT VALUE 11111. 88 DEL-DEPT VALUE 22222. 05 DEPT-NAME OCCURS 1 TO 75 TIMES DEPENDING ON DEPT-NAME-LEN PIC X. 01 DEPT-NAME-LEN PIC 9(4) COMP. 01 RETCODES. 05 ACCEPT-TAPEI PIC 9(4) COMP VALUE 00. 05 DELETE-TAPEI PIC 9(4) COMP VALUE 04. 05 DO-NOT-RETURN PIC 9(4) COMP VALUE 08. 05 INSERT-RECORD PIC 9(4) COMP VALUE 12. 05 TERMINATE-FLOD PIC 9(4) COMP VALUE 16. 05 ALTER-REPLACE PIC 9(4) COMP VALUE 20. 01 CONSTANTS. 05 MAXLEN PIC 9(4) COMP VALUE 80. 05 NEW-DEPT PIC 9(5) VALUE 33333. LINKAGE SECTION. 01 RECORD-FLAGS PIC 9(8) COMP. 88 FIRST-TAPEI VALUE 00. 88 OTHER-TAPEI VALUE 04. 88 EOF VALUE 08. 01 TAPEI-RECORD. 05 TRB OCCURS 1 TO 80 TIMES DEPENDING ON TAPEI-RECORD-LEN PIC X. 01 MODIFIED-RECORD. 05 MRB OCCURS 1 TO 80 TIMES DEPENDING ON MODIFIED-RECORD-LEN PIC X. 01 TAPEI-RECORD-LEN PIC 9(8) COMP. 01 MODIFIED-RECORD-LEN PIC 9(8) COMP. PROCEDURE DIVISION USING RECORD-FLAGS, TAPEI-RECORD, MODIFIED-RECORD, TAPEI-RECORD-LEN, MODIFIED-RECORD-LEN. *********************************************************** MAIN-LOGIC. IF FIRST-TAPEI IF MODIFIED-RECORD-LEN IS LESS THAN MAXLEN PERFORM TERMINATE-LOGIC. IF NOT EOF IF TAPEI-RECORD-LEN IS GREATER THAN MAXLEN PERFORM TERMINATE-LOGIC ELSE SUBTRACT 5 FROM TAPEI-RECORD-LEN GIVING DEPT-NAME-LEN MOVE TAPEI-RECORD TO DEPT-RECORD IF CHG-DEPT PERFORM ALTER-LOGIC ELSE IF DEL-DEPT PERFORM DELETE-LOGIC ELSE PERFORM ACCEPT-LOGIC ELSE PERFORM EOJ-LOGIC. TERMINATE-LOGIC. MOVE TERMINATE-FLOD TO RETURN-CODE. GOBACK. ALTER-LOGIC. MOVE NEW-DEPT TO DEPT-ID. MOVE TAPEI-RECORD-LEN TO MODIFIED-RECORD-LEN. MOVE DEPT-RECORD TO MODIFIED-RECORD. MOVE ALTER-REPLACE TO RETURN-CODE. GOBACK. ACCEPT-LOGIC. MOVE ACCEPT-TAPEI TO RETURN-CODE. GOBACK. DELETE-LOGIC. MOVE DELETE-TAPEI TO RETURN-CODE. GOBACK. EOJ-LOGIC. MOVE DO-NOT-RETURN TO RETURN-CODE. GOBACK.

COBOL/TAPEI/alternate data set example

In the following sample COBOL program, variable-length TAPEI records can be passed from FLOD to the FLOD exit. The FLOD exit also processes records from another data set. Variable-length records are returned to FLOD. An output file is produced for debugging purposes. Rocket Software suggests that you use debugging statements when testing FLOD exits, which you can later comment out, after the exit is performing as expected.

Sample COBOL/TAPEI FLOD exit with alternate data sets

IDENTIFICATION DIVISION. PROGRAM-ID. FLODXT1. COMMENTS. FIXED LENGTH RECORDS ARE READ BY EXIT AND PASSED TO FLOD AS VARIABLE LENGTH RECORDS. THIS EXIT CAN BE INVOKED WITH: XG 1,1,84,2 VARIABLE LENGTH RECORDS MAY ALSO BE PASSED BY FLOD. IF THIS EXIT IS INVOKED WITH THE FOLLOWING STATEMENT, THE RECFM OF TAPEI MUST BE VARIABLE LENGTH. XG 1,1,84,0 BECAUSE ALL RECORDS ARE MOVED INTO WORKING STORAGE, THE MAXIMUM DATA LENGTH THAT CAN BE PROCESSED IS 80 BYTES (SEE WORK-RECORD). THE DATA PORTIONS OF THE VARIABLE LENGTH RECORDS READ BY THE EXIT AND PASSED BY FLOD ARE ASSUMED TO BE 3 TO 80 BYTES LONG WHERE THE FIRST 2 BYTES IS A ZONED DECIMAL LENGTH FOLLOWED BY A 1 TO 78 BYTE STRING THAT IS TO BE TRUNCATED OR PADDED WITH ZEROES TO THE LENGTH SPECIFIED IN THE FIRST 2 BYTES. A TRUNCATED OR PADDED STRING OF 0 TO 80 BYTES IS RETURNED TO FLOD. THE FOLLOWING EXAMPLE SHOWS THE HEXADECIMAL REPRESENTATION OF DATA: INPUT OUTPUT OUTPUT FLOD DATA DATA LEN RECORD F0F2C140 C140 00000002 00020000C140 F0F2C140C2 C140 00000002 00020000C140 F0F2C1 C140 00000002 00020000C140 NOTE: FLOD WILL BUILD A 4 BYTE R DW PRECEDING THE MODIFIED RECORD. THUS THE FOLLOWING FLOD PROGRAM WILL PRINT THE PROCESSED RECORDS: FILELOAD -1,-1,0 XG 1,1,84,0 * INVOKE FLOD EXIT I 1,1,2,-4 * CALCULATE DATA LENGTH P 5,0|1 * PRINT DATA PORTION END IF THE EXAMPLE DATA WERE USED, THE LETTER 'A' FOLLOWED BY A SPACE WOULD BE PRINTED FOR ALL 3 RECORDS. ENVIRONMENT DIVISION. CONFIGURATION SECTION. INPUT-OUTPUT SECTION. FILE-CONTROL. SELECT IN-FILE ASSIGN TO UT-S-FLODXIN STATUS IN-STATUS. SELECT OUT-FILE ASSIGN TO UT-S-FLODXOUT STATUS OUT-STATUS. DATA DIVISION. FILE SECTION. FD IN-FILE LABEL RECORD OMITTED BLOCK CONTAINS 0 RECORDS RECORD CONTAINS 80 CHARACTERS. 01 IN-RECORD PIC X(80). FD OUT-FILE LABEL RECORD OMITTED BLOCK CONTAINS 0 RECORDS RECORD CONTAINS 28 TO 105 CHARACTERS. 01 OUT-RECORD. 05 OUT-COMMENT PIC X(25). 05 OREC. 10 OCHAR OCCURS 3 TO 80 TIMES DEPENDING ON OREC-LEN PIC X. WORKING-STORAGE SECTION. 01 IN-STATUS PIC 9(2). 01 OUT-STATUS PIC 9(2). 01 OREC-LEN PIC 9(8) COMP. 01 WREC-LEN PIC 9(8) COMP. 01 WMAX-LEN PIC 9(8) COMP VALUE 80. 01 FLAGS. 05 INIT-FLAG PIC X VALUE "1". 88 FIRST-TIME-THROUGH VALUE "1". 88 EOF-ON-INPUT VALUE "2". 01 WORK-RECORD. 05 WLEN PIC 9(2). 05 WREC. 10 WCHAR OCCURS 1 TO 78 TIMES DEPENDING ON WREC-LEN PIC X. 01 RETCODES. 05 ACCEPT-REC PIC 9(8) COMP VALUE 00. 05 DELETE-REC PIC 9(8) COMP VALUE 04. 05 DO-NOT-RETURN PIC 9(8) COMP VALUE 08. 05 INSERT-REC PIC 9(8) COMP VALUE 12. 05 TERMINATE-FLOD PIC 9(8) COMP VALUE 16. 05 ALTER-REPLACE-REC PIC 9(8) COMP VALUE 20. LINKAGE SECTION. 01 RECORD-FLAGS PIC 9(8) COMP. 88 FIRST-TAPEI-REC VALUE 00. 88 OTHER-TAPEI-REC VALUE 04. 88 EOF-ON-TAPEI VALUE 08. 01 TAPEI-RECORD. 05 TREC OCCURS 1 TO 80 TIMES DEPENDING ON TAPEI-RECORD-LEN PIC X. 01 MODIFIED-RECORD. 05 MREC OCCURS 1 TO 80 TIMES DEPENDING ON MODIFIED-RECORD-LEN PIC X. 01 TAPEI-RECORD-LEN PIC 9(8) COMP. 01 MODIFIED-RECORD-LEN PIC 9(8) COMP. PROCEDURE DIVISION USING RECORD-FLAGS, TAPEI-RECORD, MODIFIED-RECORD, TAPEI-RECORD-LEN, MODIFIED-RECORD-LEN. *************************************************************** MAIN-LOGIC. IF FIRST-TIME-THROUGH PERFORM OPEN-FILE. IF NOT EOF-ON-INPUT PERFORM READ-FILE. IF NOT EOF-ON-TAPEI PERFORM READ-TAPEI. PERFORM EOJ-RTN. *************************************************************** OPEN-FILE. MOVE "0" TO INIT-FLAG. OPEN INPUT IN-FILE. OPEN OUTPUT OUT-FILE. MOVE "OPEN-FILE: RECORD-FLAGS " TO OUT-COMMENT. MOVE 25 TO OREC-LEN. IF FIRST-TAPEI-REC MOVE "FIRST-TAPEI-REC " TO OREC ELSE IF EOF-ON-TAPEI MOVE "EOF-ON-TAPEI " TO OREC ELSE IF OTHER-TAPEI-REC MOVE "*** OTHER-TAPEI-REC *** " TO OREC PERFORM TERMINATE-RTN ELSE MOVE "*** UNDEFINED VALUE *** " TO OREC PERFORM TERMINATE-RTN. WRITE OUT-RECORD. MOVE "INPUT FILE STATUS: " TO OUT-COMMENT. MOVE 2 TO OREC-LEN. MOVE IN-STATUS TO OREC. WRITE OUT-RECORD. MOVE "OUTPUT FILE STATUS: " TO OUT-COMMENT. MOVE OUT-STATUS TO OREC. WRITE OUT-RECORD. IF MODIFIED-RECORD-LEN IS LESS THAN WMAX-LEN MOVE "MODIFIED-RECORD BUFFER: " TO OUT-COMMENT MOVE 25 TO OREC-LEN MOVE "*** TOO SMALL *** " TO OREC PERFORM TERMINATE-RTN. ************************************************************** CLOSE-FILE. MOVE "CLOSE-FILE: RECORD-FLAGS " TO OUT-COMMENT. MOVE 25 TO OREC-LEN. IF EOF-ON-TAPEI MOVE "EOF-ON-TAPEI " TO OREC ELSE MOVE "*** NOT EOF-ON-TAPEI *** " TO OREC. WRITE OUT-RECORD. CLOSE IN-FILE. CLOSE OUT-FILE. ************************************************************** READ-FILE. MOVE 78 TO WREC-LEN. READ IN-FILE RECORD INTO WORK-RECORD AT END MOVE 2 TO INIT-FLAG. MOVE "READ-FILE: WORK-RECORD " TO OUT-COMMENT. IF EOF-ON-INPUT MOVE 25 TO OREC-LEN MOVE "EOF-ON-INPUT " TO OREC WRITE OUT-RECORD ELSE MOVE WREC-LEN TO OREC-LEN MOVE WORK-RECORD TO OREC WRITE OUT-RECORD MOVE INSERT-REC TO RETURN-CODE PERFORM WORK-SEND. ************************************************************** WORK-SEND. MOVE WLEN TO WREC-LEN. IF WREC-LEN IS GREATER THAN WMAX-LEN MOVE "WORK-SEND: WREC-LEN " TO OUT-COMMENT MOVE 25 TO OREC-LEN MOVE "*** TOO LARGE *** " TO OREC PERFORM TERMINATE-RTN. MOVE WREC-LEN TO OREC-LEN. MOVE "WORK-SEND: WREC " TO OUT-COMMENT. MOVE WREC TO OREC. WRITE OUT-RECORD. MOVE WREC-LEN TO MODIFIED-RECORD-LEN. MOVE WREC TO MODIFIED-RECORD. PERFORM RETURN-TO-FLOD. ************************************************************** READ-TAPEI. IF TAPEI-RECORD-LEN IS GREATER THAN WMAX-LEN MOVE "READ-TAPEI: TAPEI-RECORD " TO OUT-COMMENT MOVE 25 TO OREC-LEN MOVE "*** TOO LARGE *** " TO OREC PERFORM TERMINATE-RTN. MOVE "READ-TAPEI: TAPEI-RECORD " TO OUT-COMMENT. MOVE TAPEI-RECORD-LEN TO OREC-LEN. MOVE TAPEI-RECORD TO OREC. WRITE OUT-RECORD. MOVE 78 TO WREC-LEN. MOVE TAPEI-RECORD TO WORK-RECORD. MOVE ALTER-REPLACE-REC TO RETURN-CODE. PERFORM WORK-SEND. ************************************************************** RETURN-TO-FLOD. GOBACK. ************************************************************** EOJ-RTN. PERFORM CLOSE-FILE. MOVE DO-NOT-RETURN TO RETURN-CODE. PERFORM RETURN-TO-FLOD. ************************************************************** TERMINATE-RTN. WRITE OUT-RECORD. PERFORM CLOSE-FILE. MOVE TERMINATE-FLOD TO RETURN-CODE. PERFORM RETURN-TO-FLOD. **************************************************************