Skip to content

Commit

Permalink
First commit
Browse files Browse the repository at this point in the history
  • Loading branch information
davenicolette committed Jan 18, 2021
0 parents commit ea16a51
Show file tree
Hide file tree
Showing 19 changed files with 682 additions and 0 deletions.
33 changes: 33 additions & 0 deletions CPSEQFR-notes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# CPSEQFR.CBL

This sample demonstrates how to read and write sequential datasets (files) that have fixed record lengths.

## Notes

A variety of dataset types exist, and each is handled in its own way. This example pertains to sequential datasets handled by the Queued Sequential Access Method (QSAM). This is the most common basic sequential dataset type on the mainframe system. It is an extension of the older Basic Sequential Access Method (BSAM) that uses a simple buffering mechanism to improve the efficiency of I/O operations.

Records in QSAM datasets are not delimited by newline characters like text files on other systems. Instead, they contain a string of bytes with no delimiters or markers embedded in the data. For QSAM files with fixed-length logical records, we tell our program the length of a logical record for a given dataset. I/O processing presents each logical record to our program based on the length we specify.

Open the sample files INFILE1 and OUTFILE1 to see this sort of content. Now compare the contents of INFILE1 with the specifications under the FD for INFILE1 in program CPSEQFR. The relevant statements are:

```
RECORD CONTAINS 40 CHARACTERS
RECORDING MODE IS F
BLOCK CONTAINS 0 RECORDS.
```

Here we are telling our program that this file contains logical records 40 characters long. The "recording mode" of "F" means "fixed-length records." The maximum allowed length of a logical record for fixed-length datasets is 32,760. For variable-length datasets, the limit is 32,752. For fixed-length datasets, you can omit the RECORD CONTAINS clause and let the system determine the logical record size based on JCL or on the length of the 01-level item under the FD that describes the record layout.

A _block_ consists of one or more logical records that the system handles in a single I/O operation. The block size is the number of bytes read or written physically, while the logical record size is the number of bytes our program treats as a "record."

When we specify block size zero in Cobol, it means we want the system to determine the block size and our program doesn't care what it is. This is the usual specification in Cobol programs, as it allows the organization the flexibility to change block sizes of files for efficiency without causing Cobol applications to fail. In rare cases, your program may depend on a file having a particular block size. You can specify that size in the BLOCK CONTAINS clause.

## Additional information

- [IBM Documentation: Dataset Record Formats](https://www.ibm.com/support/knowledgecenter/zosbasics/com.ibm.zos.zconcepts/zconcepts_159.htm)
- [IBM Documentation: Processing QSAM files in Cobol](https://www.ibm.com/support/knowledgecenter/en/SS6SG3_4.2.0/com.ibm.entcobol.doc_4.2/PGandLR/tasks/tpqsm01.htm)
- [IBM Documentation: QSAM in an Application](https://www.ibm.com/support/knowledgecenter/en/SSLTBW_2.1.0/com.ibm.zos.v2r1.idad400/inanap.htm)
- [IBM Documentation: Logical Record Length](https://www.ibm.com/support/knowledgecenter/SSXJAV_13.1.0/com.ibm.filemanager.doc_13.1/base/fmnu1134.html)
[Columbus State University: Sequential File Processing](http://csc.columbusstate.edu/woolbright/QSAM.HTM)


19 changes: 19 additions & 0 deletions CPSEQVR-notes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# CPSEQVR.CBL

This sample demonstrates how to read and write sequential datasets (files) that have variable-length records.

## Notes

This example pertains to processing QSAM datasets that have variable-length logical records. Each block is preceded by a _block descriptor word_ (BDW) that contains the length of the block, and each logical record within a block is preceded by a _record descriptor word_ (RDW) that contains the length of the logical record. The BDW and RDW are not included in the record layout specified in a Cobol program. They are handled by the system. Only the logical records themselves are visible to a Cobol program.

The record layout under the FD defines a logical record of the maximum length. A separate numeric data item defined in the Working-Storage section will be populated with the logical record length when the program READs a record from an input file. The program sets the length of output records before it WRITEs a variable-length record.

## Additional information

- [IBM Documentation: Dataset Record Formats](https://www.ibm.com/support/knowledgecenter/zosbasics/com.ibm.zos.zconcepts/zconcepts_159.htm)
- [IBM Documentation: Processing QSAM files in Cobol](https://www.ibm.com/support/knowledgecenter/en/SS6SG3_4.2.0/com.ibm.entcobol.doc_4.2/PGandLR/tasks/tpqsm01.htm)
- [IBM Documentation: QSAM in an Application](https://www.ibm.com/support/knowledgecenter/en/SSLTBW_2.1.0/com.ibm.zos.v2r1.idad400/inanap.htm)
- [IBM Documentation: Logical Record Length](https://www.ibm.com/support/knowledgecenter/SSXJAV_13.1.0/com.ibm.filemanager.doc_13.1/base/fmnu1134.html)
[Columbus State University: Sequential File Processing](http://csc.columbusstate.edu/woolbright/QSAM.HTM)


29 changes: 29 additions & 0 deletions HELLO-notes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# HELLO.CBL

This sample demonstrates how to handle variable-length text data using the Cobol verbs INSPECT and STRING and the intrinsic function REVERSE.

## Notes

The program prompts the user to enter a name. We don't know the length of the name the user might enter. The name may contain embedded spaces.

We want to find the end of the name so we can append the exclamation point immediately after the last character in the name.

There is no such thing as a zero-delimited string in (mainframe) Cobol. References to a Data Division item with Picture X always operate on the full length of the item. If we concatenate the greeting, name, and exclamation point, the result will have spaces in between the name and the exclamation point. We want to have no intervening spaces.

To do this, we use the INSPECT verb. It can count the number of leading spaces in an alphanumeric value.

To avoid stopping when we encounter an embedded space, we count backward from the end of the WS-FRIEND field.

To count backward, we combine the intrinsic function REVERSE with the INSPECT verb. The REVERSE function doesn't actually cause INSPECT to work backward; it just reverses the order of characters in the field. Then, INSPECT goes "forward" and counts the bytes until it finds a character other than SPACE.

We can then use the LENGTH OF special name to get the length of the WS-FRIEND field, and subtract from that the number of trailing spaces we found with the INSPECT verb.

Then we can use STRING to concatenate the greeting message, name, and exclamation point with no intervening spaces.

## Additional information

- [IBM Documentation: Cobol ACCEPT statement](https://www.ibm.com/support/knowledgecenter/en/SS6SG3_4.2.0/com.ibm.entcobol.doc_4.2/PGandLR/ref/rlpsacce.htm)
- [IBM Documentation: Cobol DISPLAY statement](https://www.ibm.com/support/knowledgecenter/en/SS6SG3_4.2.0/com.ibm.entcobol.doc_4.2/PGandLR/ref/rlpsdisp.htm)
- [IBM Documentation: Cobol INSPECT statement](https://www.ibm.com/support/knowledgecenter/en/SS6SG3_4.2.0/com.ibm.entcobol.doc_4.2/PGandLR/ref/rlpsinsp.htm)
- [IBM Documentation: Cobol STRING statement](https://www.ibm.com/support/knowledgecenter/en/SS6SG3_4.2.0/com.ibm.entcobol.doc_4.2/PGandLR/ref/rlpsstri.htm)
- [IBM Documentation: Cobol REVERSE function](https://www.ibm.com/support/knowledgecenter/en/SS6SG3_4.2.0/com.ibm.entcobol.doc_4.2/PGandLR/tasks/tpstr19b.htm)
Binary file added HEX2TEXT
Binary file not shown.
Binary file added HEX2TEXT.so
Binary file not shown.
1 change: 1 addition & 0 deletions INFILE1
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
AAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDEEEEEEEEEEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
Binary file added MOVEME
Binary file not shown.
84 changes: 84 additions & 0 deletions MOVEME-notes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# MOVEME.CBL

This sample demonstrates the effect of the Cobol MOVE statement on values in memory for various PICTURE and USAGE specifications.

## Notes

The program executes MOVE statements to assign values to Data Division items that have various different PICTURE and USAGE clauses, and displays the results of the MOVE statements as text or hexadecimal values on stdout (SYSOUT). Hexadecimal text values will be displayed in ASCII if you are running the examples on an ASCII-based system, and in EBCDIC if on an EBCDIC-based system.

#### Example 1: Alphanumeric MOVE

Example 1 is a MOVE statement of an alphanumeric literal to an item defined as PICTURE X USAGE DISPLAY.

#### Example 2: Numeric MOVE, 32-bit binary (USAGE COMP)

Example 2 is a MOVE statement of a numeric literal to an item defined as PIC S9(09) COMP (or USAGE IS COMPUTATIONAL). It illustrates the fact an item defined this way takes up four bytes in memory.

#### Example 3: Numeric MOVE, 64-bit binary (USAGE COMP)

Example 3 is a MOVE statement of a numeric literal to an item defined as PIC S9(16) COMP (or USAGE IS COMPUTATIONAL). It illustrates the fact an item defined this way takes up eight bytes in memory.

### Example 4: Overwrite binary value with SPACES (USAGE COMP)

Example 4 shows the effect of a MOVE statement that overwrites a COMPUTATIONAL item with spaces. For a COMPUTATIONAL item, the system treats the binary representation of "spaces" as if it were a binary number. This is not usually the programmer's intent, but it does happen. The result is that computations using the item yield incorrect results.

USAGE COMPUTATIONAL-4 or COMP-4 is the same as COMPUTATIONAL or COMP.

#### Example 5: Numeric MOVE, single-precision floating point (USAGE COMP-1)

Example 5 shows the effect of a MOVE statement of a numeric literal expressed in scientific notation to an item defined as COMP-1 or COMPUTATIONAL-1. This is the IEEE single-precision floating-point format, which takes up 32 bits (4 bytes) of memory. Note that the PICTURE clause is omitted, as this format is always the same internally.

Floating point values are not common in business applications.

#### Example 6: Numeric MOVE, double-precision floating point (USAGE COMP-2)

Example 6 shows the effect of a MOVE statement of a numeric literal expressed in scientific notation to an item defined as COMP-2 or COMPUTATIONAL-2. This is the IEEE double-precision floating-point format, which takes up 64 bits (8 bytes) of memory. Note that the PICTURE clause is omitted, as this format is always the same internally.

Floating point values are not common in business applications.

#### Example 7: Numeric MOVE, packed decimal format (USAGE COMP-3)

Example 7 is a MOVE statement of a numeric literal to an item defined as PIC S9(04)V9(03) COMP-3 (or USAGE IS COMPUTATIONAL-3). In IBM Enterprise Cobol, COMP-3 denotes a Packed Decimal item. The example illustrates the following:
- a seven-digit Packed Decimal item takes up four bytes in memory
- the implied decimal point (the "V" in the PICTURE clause) is not represented in memory
- the contents of a packed decimal field consist of _binary coded decimal_ (BCD) digits in each nybble except the last nybble, which contains the sign. The hexadecimal value "C" represents the positive sign, "D" the negative sign, and "F" means "unsigned."

#### Example 8: Overwrite packed decimal value with SPACES (USAGE COMP-3)

Example 8 shows the effect of a MOVE statement that overwrites a Packed Decimal item with spaces. The system does not complain about this, but as the low-order nybble does not contain a valid Packed Decimal sign, when the item is used in an arithmetic operation such as ADD, SUBTRACT, or COMPUTE, the result will be a Data Exception runtime error (reported as error code S0C7 or "sock seven" on z/OS and as "Data Exception" on z/VSE).

Moving spaces into a Packed Decimal field is the cause of the majority of runtime errors Cobol programmers create. When the field is used as the "depending on" variable for a variable-length Cobol table, the system will overwrite a large swath of memory with spaces, extending beyond the boundary of the program's working storage area, and wiping out other programs' data and possibly system control blocks. In the CICS environment, this is the most common cause of Storage Violation errors.

#### Example 9: Numeric MOVE to Display Numeric Signed (PIC 9, USAGE DISPLAY)

This example shows the effect of moving a numeric value to an item defined as PICTURE 9(...) and USAGE DISPLAY.

#### Example 10: Numeric MOVE to Display Numeric with formatting (PIC -ZZ,ZZ9.99, USAGE DISPLAY)

This example shows the effect of moving a numeric value to an item defined with special formatting symbols for output.

#### Example 11: Numeric MOVE to Display Numeric with formatting for a currency value

Similar to Example 10, but the format specification includes a floating currency symbol: PICTURE -$$,$$9.99.

#### Example 12: Numeric MOVE to external floating-point item with formatting for output

This example shows the effect of moving a numeric value to an "external" floating-point item with a PICTURE clause to format the value for output: PIC -9V(9)E-99 (with implicit USAGE DISPLAY).

Note this example is commented-out. This form of the PICTURE clause is not supported on GnuCOBOL. If you are running the examples on a system that supports this feature, you can un-comment the relevant lines in MOVEMENT.CBL.

#### Examples 13 and 14: Initializing a group item

Example 13 shows the effect of using the INITIALIZE statement to initialize all the data items defined under a group item, WS-GROUP-ITEM. Each alphanumeric item is filled with spaces, and each numeric items is assigned "zero" in the appropriate format.

Example 14 shows a common programming mistake whereby a group item is initialized by moving SPACES to it. You can see that memory is overwritten well beyond the length of the group item, and numeric fields are assigned values that can lead to incorrect results or run time errors.

## Additional information

- [IBM Documentation: Formats for Numeric Data](https://www.ibm.com/support/knowledgecenter/en/SS6SG3_4.2.0/com.ibm.entcobol.doc_4.2/PGandLR/concepts/cpari09.htm)
- [IBM Documentation: Numeric Data and Internal Representation](https://www.ibm.com/support/knowledgecenter/en/SS6SG3_4.2.0/com.ibm.entcobol.doc_4.2/PGandLR/concepts/cpari20e.htm)
- [IBM Documentation: Displaying Numeric Data](https://www.ibm.com/support/knowledgecenter/en/SS6SG3_4.2.0/com.ibm.entcobol.doc_4.2/PGandLR/tasks/tpari06.htm)
- [IBM Documentation: Internal Floating-Point (COMP-1 and COMP-2) items](https://www.ibm.com/support/knowledgecenter/en/ssw_ibm_i_71/rzase/sc092540205.htm)
- [IBM Documentation: External Floating-Point (USAGE DISPLAY) Items](https://www.ibm.com/support/knowledgecenter/en/ssw_ibm_i_71/rzase/sc092540205.htm)
- [IBM Documentation: Initializing a Table at the Group Level](https://www.ibm.com/support/knowledgecenter/en/SS6SG3_4.2.0/com.ibm.entcobol.doc_4.2/PGandLR/tasks/tptbl21b.htm)
- [IBM Documentation: Cobol Initialize Statement](https://www.ibm.com/support/knowledgecenter/en/SS6SG3_4.2.0/com.ibm.entcobol.doc_4.2/PGandLR/ref/rlpsinit.htm)
1 change: 1 addition & 0 deletions OUTFILE1
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBAAAAAAAAAADDDDDDDDDDDDDDDDDDDDDDDDDDDDDDCCCCCCCCCCFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEEEEEEEEEE
31 changes: 31 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Cobol Samples

Short sample programs that illustrate how to carry out various programming tasks in Cobol.

## How to run the sample programs

On z/OS, compile-link-go. HEX2TEXT is a subprogram. The other samples are main programs.

On Linux, Unix, Windows, or OS X, install a Cobol compiler that offers source-level compatibility with IBM Enterprise Cobol. Compile HEX2TEXT as a subprogram (.so or .dll), and the other sample programs as main programs.

## Using basic Cobol statements

### How can I...

- [MOVEME](MOVEME-notes.md) assign values to Data Division items?

## Working with datasets

#### How can I...

- [CPSEQFR](CPSEQFR-notes.md) read and write sequential (QSAM) files with fixed-length records?
- [CPSEQVR](CPSEQVR-notes.md) read and write sequential (QSAM) files with variable-length records ?

## Working with text data

#### How can I...

- [HELLO](HELLO-notes.md) eliminate trailing spaces in variable-length text data?

## Working with numeric data

Binary file added TESTIO2.Output.bin
Binary file not shown.
Binary file added VARFILE1
Binary file not shown.
Binary file added VARFILE2
Binary file not shown.
85 changes: 85 additions & 0 deletions src/main/cobol/CPSEQFR.CBL
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
*****************************************************************
* Program name: CPSEQFR
* Original author: Dave Nicolette
*
* Demonstrates:
*
* How to read and write sequential datasets with fixed-length
* records.
*
* This program copies INFILE to OUTFILE and reverses the two
* fields in each record. It also counts the number of records
* processed.
*****************************************************************
IDENTIFICATION DIVISION.
PROGRAM-ID. CPSEQFR.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT INFILE ASSIGN TO 'INFILE1'
FILE STATUS IS INPUT-FILE-STATUS.
SELECT OUTFILE ASSIGN TO 'OUTFILE1'
FILE STATUS IS OUTPUT-FILE-STATUS.
DATA DIVISION.
FILE SECTION.
FD INFILE
LABEL RECORDS ARE STANDARD
DATA RECORD IS INPUT-RECORD
RECORD CONTAINS 40 CHARACTERS
RECORDING MODE IS F
BLOCK CONTAINS 0 RECORDS.
01 INPUT-RECORD.
05 INPUT-FIRST-10 PIC X(10).
05 INPUT-LAST-30 PIC X(30).

FD OUTFILE
LABEL RECORDS ARE STANDARD
DATA RECORD IS OUTPUT-RECORD
RECORD CONTAINS 40 CHARACTERS
RECORDING MODE IS F
BLOCK CONTAINS 0 RECORDS.
01 OUTPUT-RECORD.
05 OUTPUT-FIRST-30 PIC X(30).
05 OUTPUT-LAST-10 PIC X(10).

WORKING-STORAGE SECTION.
01 WorkAreas.
05 INPUT-FILE-STATUS PIC X(02).
88 GOOD-READ VALUE '00'.
88 END-OF-INPUT VALUE '10'.
05 OUTPUT-FILE-STATUS PIC X(02).
88 GOOD-WRITE VALUE '00'.
05 RECORD-COUNT PIC S9(5) COMP-3.

PROCEDURE DIVISION.
OPEN INPUT INFILE
IF NOT GOOD-READ
DISPLAY 'STATUS ON INFILE OPEN: ' INPUT-FILE-STATUS
GO TO END-OF-PROGRAM
END-IF
OPEN OUTPUT OUTFILE
IF NOT GOOD-WRITE
DISPLAY 'STATUS ON OUTFILE OPEN: ' OUTPUT-FILE-STATUS
END-IF
PERFORM UNTIL END-OF-INPUT
READ INFILE
IF GOOD-READ
MOVE INPUT-FIRST-10 TO OUTPUT-LAST-10
MOVE INPUT-LAST-30 TO OUTPUT-FIRST-30
WRITE OUTPUT-RECORD
IF GOOD-WRITE
ADD 1 TO RECORD-COUNT
ELSE
DISPLAY 'STATUS ON OUTFILE WRITE: '
OUTPUT-FILE-STATUS
GO TO END-OF-PROGRAM
END-IF
END-IF
END-PERFORM
.
END-OF-PROGRAM.
DISPLAY 'NUMBER OF RECORDS PROCESSED: ' RECORD-COUNT
CLOSE INFILE
CLOSE OUTFILE
GOBACK.

Loading

0 comments on commit ea16a51

Please sign in to comment.