Operation [ COBOL/HP-UX Operating Guide for the Series 700 and 800 ] MPE/iX 5.0 Documentation
COBOL/HP-UX Operating Guide for the Series 700 and 800
Operation
The COBOL syntax defining a file, consisting of a SELECT statement and an
FD statement, causes the compiler to create a number of data areas to
define the file and to hold the file records. The principal item is the
File Control Description
(FCD) which defines the essential properties of the file. For indexed
files, an additional area, the
Key Definition Block, is allocated to define the
key structure. An area is allocated to hold the file-name, and an area
to hold the record being processed.
Each COBOL I/O statement is compiled into a call to the file handler.
To use the file handler directly, you can create your own data areas to
define the file, and write calls to the file handler instead of using
COBOL syntax. Alternatively, you can use COBOL syntax to define the file
and perform some of the I/O operations, and use the
FCDREG compiler directive to gain access to the compiler-generated file
definitions, allowing you to alter the file definition, or handle some of
the I/O operations by calls to the file handler.
Your Own File Handler
To link your own file handler(s) to the RTS, you must use the -m option
on the cob command line. See Chapter 2 , COBOL System Interface for
details of this command.
Calling the File Handler from Other Languages
The file handler can be called from other languages to operate on
COBOL-format files. If you wish to share COBOL-format files between
languages, you need to be aware that different languages use different
data types. You should, therefore, avoid using a data type, when
creating the file, that cannot be processed by the reading language.
Opening a File More Than Once
With the file handler you can assign several COBOL files to the same
physical file (by specifying it in the ASSIGN clauses of their SELECT
statements) and have them all open at the same time.
The operating system will count it as just one open file.
The physical file will not be closed until every COBOL file assigned to
it has been closed.
Accessing the FCD from a Program
Each FCD created from the COBOL syntax can be accessed from within your
program. If you compile your program with the FCDREG directive, you can
access the FCD and key areas for each file. FCDs of files using the file
handler can be read or changed by the program, using the definitions
supplied in this chapter, or can be used in calls to the file handler.
To access the FCD, set up a definition of the FCD in the Linkage Section.
This definition (which takes up no physical memory) can then be mapped
onto the FCD you wish to read or alter using the following SET statement
in your program:
set address of fcd to address of fh--fcd of indexfile
where:
fcd is the Linkage Section definition of the FCD
fh--fcd of indexfile
(note the double hyphen) is the pointer special
register allocated to the file with FD name
indexfile.
Following this SET operation, the data items defined in the Linkage
Section group item fcd will be the fields of the FCD of the file
referenced in the SET statement.
Similarly, you can access the Key Definition Block by:
set address of kdb
to address of fh--keydef of indexfile
where:
kdb is the Linkage Section definition of the Key
Definition Block
fh--keydef of indexfile
is the pointer special register allocated to the
file with FD name indexfile to point to its Key
Definition Block.
Example
The following program turns on key compression in a file by setting bits
in the file's Key Definition Block.
$set fcdreg
select masterfile
assign to .....
organization is indexed
record key is rec-key
alternate key is m-alt-key-1 with duplicates
alternate key is m-alt-key-2
alternate key is m-alt-key-3 with duplicates.
select indexfile
assign to .....
organization is indexed
record key is rec-key
alternate key is t-alt-key-1 with duplicates.
. . .
. . .
working-storage section.
. . .
linkage section.
01 key-def-block.
03 filler pic x(6).
03 key-count pic 9(4) comp-x.
03 filler pic x(6).
03 key-def occurs 1 to 4 times
depending on key-count.
05 filler pic x(5).
05 key-compression pic 9(2) comp-x.
05 filler pic x(10).
. . .
procedure division.
* set appropriate key compressions:
*
* +-- trailing space compression
* |+-- leading character compression
* ||+-- duplicate key compression
* |||
* 7 = 00000111 - all compressions
* 6 = 00000110 - leading character & trailing space
* 2 = 00000010 - leading character compression
* 1 = 00000001 - duplicate key compression
set address of key-def-block
to address of fh--keydef of masterfile
move 4 to key-count
move 6 to key-compression (1)
move 7 to key-compression (2)
move 6 to key-compression (3)
move 7 to key-compression (4)
open I/O masterfile
. . .
set address of key-def-block
to address of fh--keydef of indexfile
move 2 to key-count
move 4 to key-compression (1)
move 1 to key-compression (2)
open input indexfile
. . .
Sparse Keys
A Sparse keys is a key for which no index entry is stored for the given
key value. For example, if the given value for a key is spaces, there is
no entry for that key. Sparse keys can be defined only for Micro Focus
format files.
Normally, when the file handler stores an indexed record, the key value
is stored in the index file for each key defined. If an alternate key is
defined as a sparse key and the key value is the specified sparse value,
the key value is not stored. However, enough information is stored for
the record to be read via the normal primary key path. Only alternate
keys that allow duplicates can be sparse.
Using this feature results in smaller index files. The larger your
key(s) and the more records you have for which the alternate key has the
given value, the larger your disk savings.
Sparse keys are defined using the SUPPRESS phrase in the WITH DUPLICATES
phrase of the ALTERNATE KEY clause in the SELECT statement (see your
Language Reference for the syntax).
Example
input-output section.
file-control.
select out-file
assign to "outfile"
organization is indexed
access mode is dynamic
record key is out-key
alternate record key is alt-key
with duplicates
suppress when all "A"
*
* Hence, if we write a record whose alternate key has value all
* "A", the actual key value will not be stored in the index file
*
file status is file-status.
data division.
file section.
fd out-file
record is varying from 30 to 50 characters depending on rec-size.
01 out-rec.
05 out-key pic 9(10).
05 alt-key pic x(20).
05 rec-data pic x(20).
working-storage section.
01 file-status pic xx.
01 rec-size pic 99.
procedure division.
open output out-file
if file-status not = "00"
* < code to abort >
end-if
move 35 to rec-size.
perform varying out-key from 1 by 1
until out-key > 10
move all "A" to alt-key
write out-rec
invalid key
* < code to abort >
end-write
end-perform
close out-file
stop run.
If you examine the index file created, you will not see the alternate key
information because the File Handler was instructed, by the SUPPRESS
clause, to suppress storage of those alternate keys containing all "A".
However, a COBOL program reading the file sequentially using the prime
key will read each record correctly.
Creating a New Index
A set of operations is provided that enable you to recreate the index
file or a variable record length of an IDXFORMAT(4) indexed file using
only the information in the data file.
To recreate the index file, your program must open the file using the
open-new-index operation, and reads records from it using the
get-next-rec operation. Your program creates the index from each
separate record, using the add-index operation.
Example
78 close-file value x"fa80".
78 open-new-index value x"0007".
78 get-next-rec value x"0008".
78 add-key-value value x"0009".
. . .
. . .
move open-new-index to fh-opcode
perform extfh-op
move get-next-rec to fh-opcode
perform extfh-op
perform until fcd-status (1:1) not = "0"
perform varying fcd-key-id from 0 by 1
until fcd-key-id = key-count
move add-key-value to fh-opcode
perform extfh-op
end-perform
move get-next-rec to fh-opcode
perform extfh-op
end-perform
move close-file to fh-opcode
perform extfh-op
. . .
. . .
extfh-op.
call "EXTFH" using fh-opcode, fcd
if fcd-status of fcd (1:1) = or < or > "1"
move 1 to return-code
go to exit-prog
end-if.
File Status Conversion
You can convert all file status "9" codes in your program before they are
returned to your program by setting the "Q" File Status Error
switch.
By setting the file status error switch on, all status "9" file errors
reported in your code are mapped, by means of an internal RTS table, to a
status which conforms to the statuses returned in the COBOL dialect of
your choice. You can configure the COBOL dialect you want to use. See
Chapter 18 , File Status for details of how to do this. Any undefined
or unrecognized status values are mapped onto status "30", permanent I/O
error. See your Language Reference for full details on file status
errors.
By default, this switch is set off as follows:
COBSW=-Q
You can set it on as follows:
COBSW=+Q
File Compression Routines
The file compression routines documented in Chapter 12 , COBOL File
Handling, are also callable. The following sections describe the call
interface to these routines.
Data Compression.
The routine that the Callable File Handler uses to compress data is a
standalone module. This means that you can use it in your own
applications, or alternatively get the Callable File Handler to use your
own data compression routine.
To use data compression, you can either call the data compression routine
to be used from within your program, or you can include the compression
routine in a $SET statement within your program.
There can be up to 127 Micro Focus compression routines, and up to 127
user-supplied compression routines.
Micro Focus routines are stored in files called CBLDCnnn.gnt, where nnn
can be 001 through 127.
To use Micro Focus data compression routines, you specify the
DATACOMPRESS
compiler directive with a value from 001 through 127, inclusive. This
tells the Callable File Handler to look for a file with the name
CBLDCnnn.gnt. Specifying a value of 000 (the default) disables data
compression. See the section Micro Focus Compression Routine CBLDC001
for details of calling the 001 data compression routine.
User-supplied compression routines must be stored in files called
USRDCnnn.gnt, where nnn can be 128 through 255. When you use the
DATACOMPRESS compiler directive, you specify the number 128 through 255
of the routine you want to use, and the compiler knows to look for a file
of the name USRDCnnn.gnt.
To make your compression routine available to this COBOL system, you
must:
* For COBOL compression routines, compile the routine and then
rebuild your run-time system using the following command:
cob -xvo rts32 -e "" -d routine-name
where:
routine-name is the name of your compression routine.
* For non-COBOL routines, create an object module from the source of
your compression routine and link this to the RTS using the
following command:
cob -xvo rts32 -e "" routine-name.o
where:
routine-name.o is the name of the object module produced from the
source of your compression routine.
Notes:
* Your compression routines must not make any calls to the Callable
File Handler, as this would result in a loop. If you need file
access, use byte-stream file I/O.
* Once you have enabled data compression for a file, you must always
subsequently specify the same type of compression for that file.
If you do not, you will receive a run-time status error.
* Data compression has no effect on files other than those in
indexed or record sequential format and is ignored at compile time
for files that do not support it.
You then call either of the data compression routines from a program
other than the Callable File Handler.
Calling a Micro Focus Data Compression Routine.
To call a Micro Focus data compression routine use
:
call "CBLDCnnn" using input-buffer,
input-buffer-size,
output-buffer,
output-buffer-size,
compression-type
where:
nnn is a data compression routine in the range 001 to
127
input-buffer is a PIC X (size) data-item and is the input to the
routine; maximum size is 65535.
input-buffer-size is a PIC XX COMP-5 data-item and outputs the length
of data in the input-buffer.
output-buffer is a PIC X (size) data-item and is the buffer to
contain the resulting data.
output-buffer-size is a PIC XX COMP-5 data-item. On entry to the
routine this field must contain the size of the
output buffer available; on exit this field will
contain the length of the data in the buffer.
compression-type is a PIC X COMP-X data-item. This specifies if the
input data is to be compressed or decompressed.
0 - compress
1 - decompress
The RETURN-CODE special register indicates whether the operation
succeeded or not. Compression or decompression fails only if the output
buffer is too small to accept the results.
0 - success
1 - failure.
To call a user-supplied routine, use the same statement, but use the
filename USRDCnnn instead of CBLDCnnn where, for user-supplied routines,
nnn can be a value in the range 128 to 255.
Calls to data compression routines in programs from previous UNIX COBOL
systems, can be mapped to the new calls using the cob option:
-m CBL_DATA_COMPRESS_nnn=CBLDCnnn
Micro Focus Compression Routine CBLDC001
The Micro Focus compression routine CBLDC001 uses a form of run length
encoding. This is a method of compression that detects strings (runs) of
the same character and reduces them to an identifier, a count, and one
occurrence of the character.
CBLDC001 places special emphasis on runs of spaces, binary zeros, and
character zeros, which can be reduced to a single character, and of
printable characters, which are reduced to two characters consisting of a
count followed by the repeated character. Runs of other characters can
also be reduced.
In the compressed file, bytes have the following meaning:
* 20-7F (most printable characters) have their normal ASCII meaning.
* 80-9F indicate 1-32 spaces respectively.
* A0-BF indicate 1-32 binary zeros respectively.
* C0-DF indicate 1-32 character zeros respectively.
* E0-FF indicate 1-32 occurrences of the character following.
* 00-1F indicate 1-32 occurrences of the character following, and
that it should be interpreted literally, not as a compression
code. This is used when characters in the range 00-1F, 80-9F,
A0-BF, C0-DF or E0-FF occur in the original data. (Thus one such
character will be expanded to two bytes; otherwise, no penalty is
incurred by the compression.)
Data Compression using a $SET Statement.
For indexed or record sequential files, you can specify the DATACOMPRESS
directive in a $SET statement, which enables you to set data compression
on an individual file basis. The $SET statement resets the default
compression which will be in force for all subsequent ISAM files until
any subsequent $SET DATACOMPRESS statement is reached. A $SET
DATACOMPRESS statement must not appear within the scope of a SELECT
statement; if it does, you will receive an error on compilation. The
final $SET DATACOMPRESS statement within the source file sets the type of
data compression used for all files within that program, unless
subsequent settings are explicitly stated for each file.
Consider the following example:
$SET DATACOMPRESS"1"
select myfile assign ...
$SET DATACOMPRESS"0"
select myfile2 assign...
This results in the data in myfile1 being compressed, whereas the data in
myfile2 is not.
Key Compression.
For indexed files, you specify the KEYCOMPRESS compiler directive
in a $SET statement. This enables you to set key compression on
individual keys. Key compression gives a reduction in disk requirements
for application files and improves key access.
There are three key compression routines, specified as a single integer,
and must be the sum of one or more of:
1 enables duplicate compression. This causes
duplicate key values to be compressed when stored.
2 enables leading compression. This causes leading
values that are the same in one or more key entries
to be compressed.
4 enables trailing compression. This causes
redundant spaces at the end of keys to be
compressed.
Consider the following examples:
$SET KEYCOMPRESS"7"
select myfile assign ...
record key is key-1
alternate record key is key-2
$SET KEYCOMPRESS"0"
select myfile1 assign ...
alternate record key is key-3
results in key-1 and key-2 being compressed and using all three
compression types and key-3 having no compression.
select myfile assign ...
record key is prime-key
$SET KEYCOMPRESS"4"
alternate record key is alt-key-1 with duplicates
$SET KEYCOMPRESS"0"
alternate record key is alt-key-2
alternate record key is alt-key-3
results in alt-key-2 and alt-key-3 having no compressing, whereas
alt-key-1 has trailing space compression.
When a $SET KEYCOMPRESS statement is reached, it remains in effect until
a subsequent $SET KEYCOMPRESS is reached. You can place a $SET
KEYCOMPRESS statement anywhere in your code.
Notes:
* Once you have created a file with a type of key compression
enabled, that type of key compression is always associated with
that file. Any attempt to specify an alternative type of key
compression (including no compression) for that file is ignored.
* You should not specify duplicate key compression for a key that
does not allow duplicates. Any attempt to do so causes the
duplicate compression setting to be ignored.
* If you specify duplicate key compression for a prime key, this is
ignored.
Relative Byte Addressing
Relative byte addressing is only available for variable record length
files when using the call interface to EXTFH. See the section "Callable
File Handler Call Interface" later in this chapter for details.
When you read or write a record in any variable record length file, you
obtain its relative byte address. Using this address, you can reread or
rewrite it without using keys and indices. This is a fast method of
accessing records, but has limitations of which you should be aware:
* A normal relative byte address operation will not change the
current record pointer in the file. Therefore, a READ NEXT after
a relative byte addressing operation returns the record after the
last one accessed using normal access methods. It does not return
you the record after the one you accessed using relative byte
addressing.
It is possible, however, to update the current record pointer so
that it points to the record you accessed using relative byte
addressing. A subsequent READ NEXT returns you to the record
after the one you accessed using the relative byte address
operation.
To update the current record pointer, you should set Bit 5 of the
configuration-flags (offset 93) in the FCD before calling EXTFH to
perform the relative byte address operation.
* Relative byte operations update the index when a record is
rewritten or deleted.
* If the record has been deleted since the relative byte address was
obtained, then the read or write using relative byte addressing
will usually fail. However, it is possible for it to have been
replaced by a different record, which will not be detected.
Record locking still works with this mode of operation.
Obtaining the Relative Address.
The relative record address is returned on all operations on the files
that involve specific records. If the operation is unsuccessful, the
value in the relative record address is undefined.
Using the Relative Address.
Once you have obtained the relative address of one or more records, there
are a number of operations you can perform on specific records in the
file. These are outlined in the following sections.
Using the Relative Address to Read a Record
There are two ways to read a specific record from a file using the
relative address:
1. Put the relative address in the Relative Address field of the FCD
(offset 72) and set bit 6 of the configuration flags in the FCD
(offset 93).
If you want to update the current record pointer to this record,
set bit 5 of the configuration flags (offset 93).
Perform a READ (random) WITH NO LOCK, READ (random) WITH LOCK,
READ (random) WITH KEPT LOCK or READ (random) operation on the
file.
2. The READ (direct) operations work in the same way as described in
1. above but do not require certain Bits in the FCD to be set.
The READ (direct) operations always return the record at the
address given in the relative address field of the FCD and update
the current record pointer to this record.
Both of the above methods provide a way of switching the current key of
reference to a different key. Thus if READ NEXT operations are performed
via the prime key, you can start reading via the first alternate key from
the current record using the following operations:
1. Read the next record in the file (the address of this record is in
the FCD relative address field)
2. Put the new key-of-reference in the Key-Of-Reference field in the
FCD (offset 52)
3. Return the record at this address and changes the key-of-reference
to the new one
4. Read the next record in the file, which is the new
key-of-reference
Using the Relative Address to Rewrite a Record
You can REWRITE a record to a specific address by putting the relative
address of the place where the record is to be rewritten in the Relative
Address field of the FCD and setting bit 6 of the configuration flags in
the FCD (offset 72).
If you want to update the current record pointer to this record, set bit
5 of the configuration flags in the FCD (offset 93).
You then perform a REWRITE operation.
Using the Relative Address to Delete a Record
You can delete a record at a specific address by putting the address of
the record to be deleted in the Relative Address field of the FCD (offset
72) and setting bit 6 of the configuration flags in the FCD (offset 93).
You then perform a DELETE operation.
MPE/iX 5.0 Documentation