home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 18 REXX
/
18-REXX.zip
/
calldll.zip
/
README
< prev
Wrap
Text File
|
1996-02-05
|
22KB
|
506 lines
CALLDLL.ZIP contains 3 DLL's that allow you to do I/O on Micro Focus
indexed (VSAM) files using REXX. The files can be ASCII or EBCDIC,
fixed or variable.
You can also create 16 bit DLL's using Micro Focus COBOL, and use this
package to call them from REXX.
CALLDLL.ZIP is a shareware package. You are free to try it for a while. If
it meets your need, the cost is $29.00 for a single PC, or $199.00 for a
site license. To register your copy, please send a check of money order to:
GCH Software
300 Walnut, #52
Des Moines, IA 50309
Include the following information:
Package: CALLDLL.ZIP
Company: _______________________________
Name: _______________________________
Address: _______________________________
City: _______________________________
State: _______________________________
Zip: _______________________________
E-MAIL: _______________________________
Until you register your copy, the following message will appear each time
you load the DLL's into REXX:
/***************************/
/* CALLDLL - Version 1.0 */
/* */
/* Unregistered copy */
/* */
/* Functions loaded */
/***************************/
If you include your e-mail address when registering, instructions for
disabling the nag screen will be sent via e-mail. If you do not include
your e-mail address, instructions will be sent via snail mail.
If you purchase a site license, your are free to distribute any or all
of the files in the package to anyone at your site. If you do not
purchase a site license, you are free to distribute the package to others
provided you distribute the entire package including the including the
readme file, the DLL's, and examples.
If you have any questions about the package or want to report a bug,
please send e-mail to ghandy@dsmnet.com.
Here is the disclaimer:
This package is distributed as is, without any warranty or guarantees
of any kind, either expressed or implied. You are solely responsible
for the results of the use of this package. Should the package prove
defective, you assume the entire cost of all necessary servicing,
repair, or correction.
The author shall not be liable for any direct, indirect, consequential,
or incidental damages arising out of the use or inability to use this
package.
The following programs and files are included in CALLDLL.ZIP:
README - the file you are reading now
CALLDLL.DLL - you register and call this DLL in your REXX programs
CTOCOBOL.DLL - called by CALLDLL.DLL as an interface to COBOL programs
INDEXIO.DLL - called by CTOCOBOL.DLL to do I/O on indexed files
EXAMPLE.CBL - source for a COBOL program that can be called by CALLDLL
EXAMPLE.CMD - uses Micro Focus COBOL to compile EXAMPLE.CBL into a DLL
EXAMPLE.DLL - DLL created by running EXAMPLE.CMD to compile EXAMPLE.CBL
DIVIDE.CMD - uses CALLDLL.DLL to call EXAMPLE.DLL
ASCFIXED.CMD - example of I/O on ASCII, fixed, indexed files
ASCFIXED.DAT - an ASCII, fixed, indexed file used by ASCFIXED.CMD
ASCFIXED.IDX - the index for ASCFIXED.DAT
EBCFIXED.CMD - example of I/O on EBCDIC, fixed, indexed files
EBCFIXED.DAT - an EBCDIC, fixed, indexed file used by EBCFIXED.CMD
EBCFIXED.IDX - the index for EBCFIXED.DAT
ASCVARBL.CMD - example of I/O on ASCII, variable, indexed files
ASCVARBL.DAT - an ASCII, variable, indexed file used by ASCVARBL.DAT
ASCVARBL.IDX - the index for ASCVARBL.DAT
EBCVARBL.CMD - example of I/O on EBCDIC, variable, indexed files
EBCVARBL.DAT - an EBCDIC, variable, indexed file used by EBCVARBL.DAT
EBCVARBL.IDX - the index for EBCVARBL.DAT
You must place CALLDLL.DLL, CTOCOBOL.DLL, and INDEXIO.DLL in a directory
specified in the LIBPATH statement of your CONFIG.SYS file. If you cannot
find a better place, you can put them in your C:\OS2\DLL directory. If
you would like to try EXAMPLE.DLL it must also be placed in a LIBPATH
directory.
CALLDLL.DLL and CTOCOBOL.DLL are the nucleus of this package. They allow
Rexx to call 16 bit DLL's created with Micro Focus COBOL. INDEXIO is a
16 bit DLL that was created with Micro Focus COBOL. It allows you to
perform I/O on a Micro Focus indexed file.
The source code for INDEXIO is not included in this package, however,
EXAMPLE.CBL is provided as an example of a COBOL program that can be
compiled into a 16 bit DLL and called from REXX by CALLDLL.DLL.
EXAMPLE.CMD will compile EXAMPLE.CBL into EXAMPLE.DLL using Micro
Focus COBOL. DIVIDE.CMD uses CALLDLL to call EXAMPLE.DLL.
Note: Version 4.0 of Micro Focus COBOL is a 32 bit system. Prior
versions are 16 bit systems. A version of this package that
supports 32 bit DLL's will be release later. Registered users
of the 16 bit version may use the 32 bit version for no
additional charge.
ASCFIXED.CMD, EBCFIXED.CMD, ASCVARBL.CMD, and EBCVARBL.CMD are examples
of REXX command files that use INDEXIO.DLL to do I/O on Micro Focus
indexed files. The 4 command files are very similar. Each contains
examples of opens, reads, writes, rewrites, erases, positions, sequential
reads, and closes. They each do I/O on a different type of file:
ASCFIXED.CMD - does I/O on an ASCII fixed block file
ASCVARBL.CMD - does I/O on an ASCII variable block file
EBCFIXED.CMD - does I/O on an EBCDIC fixed block file
EBCVARBL.CMD - does I/O on an EBCDIC variable block file
ASCFIXED.CMD, EBCFIXED.CMD, ASCVARBL.CMD, and EBCVARBL.CMD are ready
to run. Just make sure the DLL's are in a LIBPATH directory, and make
sure the following files are in the current directory:
ASCFIXED.DAT
ASCFIXED.IDX
EBCFIXED.DAT
EBCFIXED.IDX
ASCVARBL.DAT
ASCVARBL.IDX
EBCVARBL.DAT
EBCVARBL.IDX
Prior to calling a 16 bit COBOL program, you must register CALLDLL.DLL
with REXX:
if RXFUNCQUERY('CallDLLLoadFuncs') then do
call RXFUNCADD 'CallDLLLoadFuncs', 'CALLDLL', 'CallDLLLoadFuncs'
call CallDLLLoadFuncs
end
Note: 'CallDLLLoadFuncs' must be entered exactly as shown above, or it can
be entered in all caps. Other combinations of upper and lower case
letters are not valid.
You can unregister CALLDLL.DLL by making the following call from your
REXX program
call CallDLLDropFuncs
Note: 'CallDLLDropFuncs' must be entered exactly as shown above, or it can
be entered in all caps. Other combinations of upper and lower case
letters are not valid.
CALLDLL.DLL takes 3 parameters: the name of the 16 bit DLL to call, and
the names of two parameters. For example:
call CallDLL 'INDEXIO', 'ComArea', 'VSAMRecord'
Another example would be:
call CallDLL 'EXAMPLE', 'FirstParameter', 'SecondParameter'
Note that 'ComArea', 'VSAMRecord', 'FirstParameter', and 'SecondParameter'
are in quotes. You are passing the names of the parameters to CALLDLL,
not the parameters themselves. CALLDLL gets the parameters by calling
the RexxVariablePool function. It then calls the 16 bit DLL, passing
the parameters. After the 16 bit DLL ends, CALLDLL uses the
RexxVariablePool function to put the parameters returned from the DLL
back into the REXX variables.
Prior to doing any I/O on an indexed file, the file must be opened. Here
is an example of an open call:
ComArea = '00' || left('ASCFIXED.DAT', 100) || 'F'
call CallDLL 'INDEXIO', 'ComArea', 'VSAMRecord'
The first parameter (ComArea) tells INDEXIO what type of I/O you would
like to perform. In this case you are telling INDEXIO to open the fixed
block file "ASCFIXED.DAT" for input.
After opening the file, you could use the following code to read a record:
key = left('Sue', 100)
ComArea = '20' || left('ASCFIXED.DAT', 100) || 'F' || key
VSAMRecord = left('', 80)
call CallDLL 'INDEXIO', 'ComArea', 'VSAMRecord'
This time, the first parameter (ComArea) tells INDEXIO to perform a random
read on "ASCFIXED.DAT". The record with a key of "Sue" is read and placed
into the REXX variable "VSAMRecord". After making the call, you could use
the REXX command "SAY" to write the record to the screen:
say 'The record returned from the random read was' VSAMRecord
It is always good to close the file after doing I/O. The file will
remain open until it is closed, or until the session that opened the
file is closed. A file that was opened for I/O will be tied up until
the file is closed: you will not be able to rename or delete the file,
and you will not be able to modify the file using the Micro Focus Data
File Editor. However, other COBOL programs, such as INDEXIO.DLL can
update the file while another process has it open for I/O.
The following statements close the ASCFIXED.DAT file:
ComArea = '90' || left('ASCFIXED.DAT', 100) || 'F'
call CallDLL 'INDEXIO', 'ComArea', 'VSAMRecord'
Looking at the examples above, notice that when opening the file, the
first byte of the ComArea was "0". When doing a random read, the first
byte of the ComArea was "2". When closing the file, the first byte of
the ComArea was "9". The first byte of the ComArea is referred to as
the call code. Here are the currently supported call codes that can
be passed to INDEXIO.DLL:
0 - Open for input
Q - Open for I/O
2 - Random read
4 - Write or Rewrite
5 - Rewrite or Write
E - Erase
P - Position (greater than or equal to key)
1 - Read sequential (from beginning of file, or the last position)
9 - Close file that was opened for input or I/O
The call codes are case sensitive. A "P" call code is valid, but a
"p" call code is not. The call codes are explained in more detail
later in this document.
The second byte of the ComArea is the return code. It is set by
INDEXIO.DLL and indicates the success or failure of the attempted
operation. It is a good idea to check the return code after each
call to INDEXIO.DLL and take appropriate action if the call was
unsuccessful. Here are the possible return codes:
0 - Request successfully processed
9 - Attempting to read past end of file on a sequential read
B - Key definition block for the file is too big
F - File not found
G - Error reading file header
I - Invalid info passed in the ComArea
N - Record not found on random read or erase
O - Error opening file
E - Other error
Normally, you will only receive the B, F, G, and O return codes when
opening the file. The 9 return code should only occur on a sequential
read. The N return code should only occur for random reads, positions,
or erases. The 0, I, or E return codes can occur on any type of call.
Bytes 3 through 102 (100 bytes total) of the ComArea is the name of
the file to perform the I/O on. If no path is specified, the current
directory will be assumed. The file name must be name of the data
portion of the indexed file, not the name of the index portion. The
file name may be entered in upper or lower case. If the file name is
less than 100 bytes, it must be padded with spaces on the right. An
easy way to pad a file name with spaces is:
FileName = 'C:\FILES\MYFILE.DAT'
FileName = left(FileName, 100)
Byte 103 of the ComArea is either "F" if you are doing I/O on a
fixed block file, or "V" if you are doing I/O on a variable block
file. If you pass in any other value, an "I" call code will be
returned. When reading variable block files, INDEXIO appends the
5 byte record length to the beginning of the record prior to passing
the record back to REXX. For example:
00038Taunya 9876 3rd St. Dallas TX
When writing or rewriting variable block records, you must append
the 5 byte record length to the beginning of the record prior to
calling CALLDLL. For example:
0038Taunya 9876 3rd St. Dallas TX
An easy way to append the record length is:
VSAMRecord = 'Taunya 9876 3rd St. Dallas TX'
VSAMRecord = right(length(VSAMRecord), 5, '0') || VSAMRecord
Bytes 104 through 203 (100 bytes total) is the key of the record.
The key is case sensitive. You must pass in a key for the following
call codes:
2 - Random read
E - Erase
P - Position (greater than or equal to key)
If the key is less than 100 bytes, it must be padded with spaces on
the right. An easy way to pad the key with spaces is:
key = 'Taunya'
key = left(key, 100)
The last byte in the ComArea (byte 204) tells INDEXIO.DLL if the
file is ASCII or EBCDIC. Set byte 204 to "Y" for EBCDIC files, or
some other value of ASCII files. Since REXX expects data to be
ASCII, INDEXIO will be automatically convert data between ASCII
and EBCDIC when appropriate. For example, when writing a record
to an EBCDIC file, INDEXIO will convert the record to EBCDIC prior
to writing to the file. When doing a random read, INDEXIO will
convert the record to ASCII prior to passing it back to the REXX
program.
Note: The ASCII/EBCDIC switch must be in byte 204. If you are
doing a sequential read on an EBCDIC file, you would not normally
pass a key. However, if you do not, the EBCDIC/ASCII switch will
not be in column 204. So, it is necessary to pass in a key when
doing sequential reads on an EBCDIC file to ensure the ASCII/EBCDIC
switch is in byte 204.
Following is a more detailed description of the call codes. The
call code is case sensitive. The call code "P" is valid, but the
call code "p" is not.
The "0" call code opens a file for input. Opening for input will not
tie up the file. Use the "0" call code to open files if you are only
going to read the file. Opening the file for input, allows you to
do random reads, positions, or sequential reads, but it will not
allow you to do writes, rewrites, or erases.
The "Q" call code opens a file for input or output. Opening a
file for input/output (I/O), allows you to do random reads, positions
sequential reads, writes, rewrites, or erases. Opening a file for I/O
will tie up the file. While the file is opened for I/O, COBOL program
running in other sessions (including INDEXIO.DLL) can update the file,
but the Micro Focus Data File Editor cannot be used to update the file.
For this reason, you should always close files that were open for I/O,
even if an error condition occurs when processing the file.
The "2" call code does a random read on the file. You must open the
file for input or I/O prior to doing a random read. When doing a
random read, you pass the key of the record to be read. A random read
returns the record if the call was successful, or a nonzero return
code if the call was unsuccessful. For example, if you try to read a
record that does not exist, you will get an "N" return code.
The "4" call code writes a new record to the file. If the write is
unsuccessful (most likely because the record already exists in the
file), a rewrite will be attempted. If the rewrite is also unsuccessful,
the return code will be set to "E". Prior to doing a "4" call code, the
file must be opened for I/O.
The "5" call code rewrites a record that already exists in the file.
If the rewrite is unsuccessful (most likely because the record does
not exists in the file), a write will be attempted. If the write is
also unsuccessful, the return code will be set to "E". Prior to doing
a "5" call code, the file must be opened for I/O.
The '4' and '5' call codes are almost interchangeable. You can use
either to do a write or a rewrite. However, performance will be a
little better if you select the correct call code based on whether
the record already exists in the file or not.
The "E" call code erases a record. You pass the key of the record to
be erased in the ComArea. If the record does not exist, the return
code will be set to "N". Prior to doing an "E" call code, the file must
be opened for I/O.
The "P" call code returns the record that is greater than or equal to
the key, and it sets the sequential pointer to the next record in the
file. After positioning, sequential reads will return records that come
after the record that was positioned on. Prior to doing a "P" call code,
you must open the file for input or I/O. The "P" call code is similar
to a random read because it returns a record. However, a random read
requires that you specify the exact key that you want to read, while
the position allows you to specify the first few bytes of the key.
The '1' call code reads sequentially through the file. If you do not
do a position prior to the sequential read, the first record in the file
will be returned. Subsequent sequential reads will return subsequent
records in the file. If you do a position prior to a sequential read,
the record returned will be the record that comes after the record that
was positioned on. After all records in the file have been read, the
next sequential read will result in a "9" return code. Prior to doing
a "1" call code, you must open the file for input or I/O.
The "9" call code closes files that were opened for input or I/O. It
is very important that you close files because the files remain open
until they are closed, or until you close the session that opened the
file. If you do not close a file that was opened I/O, the Micro Focus
Data File Editor cannot be use to update the file until it is closed,
however, COBOL programs (such as INDEXIO.DLL) running in other sessions
can update the files.
Some things to remember about INDEXIO.DLL:
When you read a variable length record, INDEXIO appends the 5 byte
record length to the beginning of the record prior to passing it
back to your REXX program. For example:
00090Taunya 9876 3rd St. Dallas TX
When you write or rewrite a variable length record, the REXX program
must append the 5 byte record length to the beginning of the record
prior to calling INDEXIO. For example:
00038Taunya 9876 3rd St. Dallas TX
The length function can be used to simplify the task of appending
the record length:
VSAMRecord = 'Taunya 9876 3rd St. Dallas TX'
VSAMRecord = right(length(VSAMRecord), 5, '0') || VSAMRecord
A position returns a record and sets the sequential pointer to the
record after the record that was positioned on.
When doing I/O on EBCDIC files, the REXX program always works with
ASCII data. INDEXIO does the converting from EBCDIC to ASCII and
ASCII to EBCDIC.
It is very important that you close the files after you have finished
performing I/O on them.
A REXX command file can do I/O on only 1 indexed file at a time.
If you need to perform I/O on two different files within the same
command file, you must open, process, and close the first file
before processing the second file.
Performance is pretty good. INDEXIO takes approximately 0.04
seconds to perform a random read, and about 0.07 seconds to do
a write or a rewrite. Opening a file takes around 0.3 seconds.
These numbers are based on a 486/33 processor with the files on
the local drive.
As mentioned above, you can compile a COBOL program into a 16 bit DLL
using Micro Focus COBOL (version 3.2 or earlier) and call it using
CALLDLL.DLL.
Prior to calling a 16 bit COBOL program, you must register CALLDLL.DLL
with REXX:
if RXFUNCQUERY('CallDLLLoadFuncs') then do
call RXFUNCADD 'CallDLLLoadFuncs', 'CALLDLL', 'CallDLLLoadFuncs'
call CallDLLLoadFuncs
end
Note: 'CallDLLLoadFuncs' must be entered exactly as shown above, or it can
be entered in all caps. Other combinations of upper and lower case
letters are not valid.
You can unregister CALLDLL.DLL by making the following call from your
REXX program
call CallDLLDropFuncs
Note: 'CallDLLDropFuncs' must be entered exactly as shown above, or it can
be entered in all caps. Other combinations of upper and lower case
letters are not valid.
EXAMPLE.CBL is included in this package as an example of a COBOL program
that can be called from REXX using CALLDLL. The COBOL program must have
two 01 level records in the linkage section. The 01 level records can
contain PIC X fields or PIC 9 fields. They should not contain COMP-3
fields or COMP fields because they are difficult to work with in REXX
programs.
The REXX program that calls the DLL should format the fields in the
exact format that the COBOL program is expecting them. For example,
if the COBOL program is expecting the first 01 level record to contain
a 5 digit number, followed by a space, followed by another 5 digit number,
the REXX program might do something like this:
FirstParameter = '00100 00030'
If the COBOL program is expecting the second 01 level record to contain
a 20 byte first name and a 20 byte last name, you might do something
like the following:
SecondParameter = left('Bob', 20) || left('Smith', 20)
You should always initialize both parameters to the correct length
prior to calling CALLDLL. This ensures that REXX has allocated
enough space for the parameters and you will not be overwriting
space that does not belong to your application.
After initializing both parameters, the REXX program should call
CALLDLL, passing the name of the COBOL DLL to call, and the names
of the parameters. For example
call CallDLL 'EXAMPLE', 'FirstParameter', 'SecondParameter'
CALLDLL will retrieve the parameters by calling the RexxVariablePool
function, then pass the parameters to the COBOL DLL. The COBOL DLL
is free to change either of the two 01 level records, and CALLDLL will
updated the REXX variables prior to returning to REXX.
See DIVIDE.CMD for an example. It calls EXAMPLE.DLL, passing two
numbers in the first parameter. The two number are divided and the
quotient and remainder are put into the second parameter.