|
HP OpenVMS Utility Routines Manual
13.2 Using the LBR Routines: Examples
This section provides programming examples that call LBR routines.
Although the examples do not illustrate all the LBR routines, they do
provide an introduction to the various data structures and the calling
syntax.
The program examples are written in HP Pascal and the subroutine
examples are written in HP Fortran. The listing of each program example
contains comments and is followed by notes about the program. The
highlighted numbers in the notes are keyed to the highlighted numbers
in the examples.
Each sample program calls the LBR$INI_CONTROL routine and the LBR$OPEN
routine before calling any other routine.
Note
The one exception is that when you call the LBR$OUTPUT_HELP routine,
you need not call the LBR$INI_CONTROL routine and the LBR$OPEN routine.
|
The sample programs require access to various symbols derived from
definition macros. Use the INHERIT attribute to access these symbols
from definition macros in SYS$LIBRARY:STARLET.PEN.
The LBR$INI_CONTROL routine sets up a control index; do not confuse
this with a library index. The control index is used in subsequent LBR
routine calls to identify the applicable library (because you may want
your program to work with more than one library at a time).
Note
Do not alter the control index value.
|
LBR$INI_CONTROL specifies the library function, which can be to either
create and update a new library (LIB$C_CREATE), modify an existing
library (LIB$C_UPDATE), or read an existing library without updating it
(LIB$C_READ).
Upon completion of the LBR$INI_CONTROL routine, call the LBR$OPEN
routine to open the library. Open an existing library, or create and
open a new library, in either the UPDATE or READ mode, checking for an
error status value of RMS$_FNF. If this error occurs, open the library
in CREATE mode.
When you open the library, specify the library type and pass the file
specification or partial file specification of the library file.
If you are creating a new library, pass the create options array. The
CRE symbols identify the significant longwords of the array by their
byte offsets into the array. Convert these values to subscripts for an
array of integers (longwords) by dividing by 4 and adding 1. If you do
not load the significant longwords before calling LBR$INI_CONTROL, the
library may be corrupted upon creation.
Finally, pass any defaults for the file specification. If you omit the
device and directory parts of the file specification, the current
default device and directory are used.
When you finish working with a library, call LBR$CLOSE to close the
library by providing the control index value. You must close a library
explicitly before updates can be posted.
Remember to call LBR$INI_CONTROL again if you want to reopen the
library. LBR$CLOSE deallocates all the memory associated with the
library, including the control index.
The order in which you call the routines between LBR$OPEN and LBR$CLOSE
depends upon the library operations you need to perform. You may want
to call LBR$LOOKUP_KEY or LBR$GET_INDEX to find a key, then perform
some operation on the module associated with the key. You can think of
a module as being both the module itself and its associated keys. To
access a module, you first need to access a key that points to it; to
delete a module, you first need to delete any keys that point to it.
Note
Do not use LBR$INI_CONTROL, LBR$OPEN, and LBR$CLOSE for writing help
text with LBR$OUTPUT_HELP. Simply invoke LBR$OUTPUT_HELP.
|
13.2.1 Creating, Opening, and Closing a Text Library
Example 13-1 is a sample HP Pascal program that creates, opens, and
then closes a text library. The program is summarized in the following
steps:
- Initialize the library---Call LBR$INI_CONTROL to initialize the
library.
- Open the library---Call LBR$OPEN to open the library.
- Close the library---Call LBR$CLOSE to close the library.
Example 13-1 Creating a New Library Using HP
Pascal |
PROGRAM createlib(INPUT,OUTPUT);
(*This program creates a text library*)
TYPE (*Data type of*)
Create_Array = ARRAY [1..20] OF INTEGER; (*create options array*)
VAR (*Constants and return status error
codes for LBR$_OPEN & LBR$INI_CONTROL.
These are defined in $LBRDEF macro*)
LBR$C_CREATE,LBR$C_TYP_TXT,LBR$_ILLCREOPT,LBR$_ILLCTL, (1)
LBR$_ILLFMT,LBR$_NOFILNAM,LBR$_OLDMISMCH,LBR$_TYPMISMCH :
[EXTERNAL] INTEGER;
(*Create options array codes. These
are defined in $CREDEF macro*)
CRE$L_TYPE,CRE$L_KEYLEN,CRE$L_ALLOC,CRE$L_IDXMAX,CRE$L_ENTALL,
CRE$L_LUHMAX,CRE$L_VERTYP,CRE$L_IDXOPT,CRE$C_MACTXTCAS,
CRE$C_VMSV3 : [EXTERNAL]INTEGER;
Lib_Name : VARYING [128] OF CHAR; (*Name of library to create*)
Options : Create_Array; (*Create options array*)
File_Type : PACKED ARRAY [1..4] (*Character string that is default*)
OF CHAR := '.TLB'; (*file type of created lib file*)
lib_index_ptr : UNSIGNED; (*Value returned in library init*)
status : UNSIGNED; (*Return Status for function calls*)
(*-*-*-*-Function and Procedure Definitions-*-*-*-*)
(*Function that returns library
control index used by Librarian*)
FUNCTION LBR$INI_CONTROL (VAR library_index: UNSIGNED; (2)
func: UNSIGNED;
typ: UNSIGNED;
VAR namblk: ARRAY[l..u:INTEGER]
OF INTEGER := %IMMED 0):
INTEGER; EXTERN;
(*Function that creates/opens library*)
FUNCTION LBR$OPEN (library_index: UNSIGNED;
fns: [class_s]PACKED ARRAY[l..u:INTEGER] OF CHAR;
create_options: Create_Array;
dns: [CLASS_S] PACKED ARRAY [l3..u3:INTEGER] OF CHAR;
rlfna: ARRAY [l4..u4:INTEGER] OF INTEGER := %IMMED 0;
rns: [CLASS_S] PACKED ARRAY [l5..u5:INTEGER] OF CHAR :=
%IMMED 0;
VAR rnslen: INTEGER := %IMMED 0):
INTEGER; EXTERN;
(*Function that closes library*)
FUNCTION LBR$CLOSE (library_index: UNSIGNED):
INTEGER; EXTERN;
(*Error handler to check error codes
if open/create not successful*)
|
PROCEDURE Open_Error; (3)
BEGIN
WRITELN('Open Not Successful'); (*Now check specific error codes*)
IF status = IADDRESS(LBR$_ILLCREOPT) THEN
WRITELN(' Create Options Not Valid Or Not Supplied');
IF status = IADDRESS(LBR$_ILLCTL) THEN
WRITELN(' Invalid Library Index');
IF status = IADDRESS(LBR$_ILLFMT) THEN
WRITELN(' Library Not In Correct Format');
IF status = IADDRESS(LBR$_NOFILNAM) THEN
WRITELN(' Library Name Not Supplied');
IF status = IADDRESS(LBR$_OLDMISMCH) THEN
WRITELN(' Old Library Conflict');
IF status = IADDRESS(LBR$_TYPMISMCH) THEN
WRITELN(' Library Type Mismatch')
END; (*of procedure Open_Error*)
BEGIN (* *************** DECLARATIONS COMPLETE *************************
*************** MAIN PROGRAM BEGINS HERE ********************** *)
(*Prompt for Library Name*)
WRITE('Library Name: '); READLN(Lib_Name);
(*Fill Create Options Array. Divide
by 4 and add 1 to get proper subscript*)
Options[IADDRESS(CRE$L_TYPE) DIV 4 + 1] := IADDRESS(LBR$C_TYP_TXT);
Options[IADDRESS(CRE$L_KEYLEN) DIV 4 + 1] := 31; (4)
Options[IADDRESS(CRE$L_ALLOC) DIV 4 + 1] := 8;
Options[IADDRESS(CRE$L_IDXMAX) DIV 4 + 1] := 1;
Options[IADDRESS(CRE$L_ENTALL) DIV 4 + 1] := 96;
Options[IADDRESS(CRE$L_LUHMAX) DIV 4 + 1] := 20;
Options[IADDRESS(CRE$L_VERTYP) DIV 4 + 1] := IADDRESS(CRE$C_VMSV3);
Options[IADDRESS(CRE$L_IDXOPT) DIV 4 + 1] := IADDRESS(CRE$C_MACTXTCAS);
(*Initialize library control index*)
status := LBR$INI_CONTROL (lib_index_ptr, (5)
IADDRESS(LBR$C_CREATE), (*Create access*)
IADDRESS(LBR$C_TYP_TXT)); (*Text library*)
IF NOT ODD(status) THEN (*Check return status*)
WRITELN('Initialization Failed')
ELSE (*Initialization was successful*)
BEGIN (*Create and open the library*)
status := LBR$OPEN (lib_index_ptr,
Lib_Name,
Options, (6)
File_Type);
IF NOT ODD(status) THEN (*Check return status*)
Open_Error (*Call error handler*) (7)
ELSE (*Open/create was successful*)
BEGIN (*Close the library*)
status := LBR$CLOSE(lib_index_ptr);
IF NOT ODD(status) THEN (*Check return status*)
WRITELN('Close Not Successful')
END
END
END. (*of program creatlib*)
|
Each item in the following list corresponds to a number highlighted in
Example 13-1:
- Use the INHERIT attribute to access the LBR
and CRE symbols from SYS$LIBRARY:STARLET.PEN.
- Start the declarations of the LBR routines
that are used by the program. Each argument to be passed to the
Librarian is specified on a separate line and includes the name (which
just acts as a placeholder) and data type (for example: UNSIGNED, which
means an unsigned integer value, and PACKED ARRAY OF CHAR, which means
a character string). If the argument is preceded by VAR, then a value
for that argument is returned by the LBR to the program.
- Declare the procedure Open_Error, which is
called in the executable section if the Librarian returns an error when
LBR$OPEN is called. Open_Error checks the Librarian's return status
value to determine the specific cause of the error. The return status
values for each routine are listed in the descriptions of the routines.
- Initialize the array called Options with the
values the Librarian needs to create the library.
- Call LBR$INI_CONTROL, specifying that the
function to be performed is create and that the library type is text.
- Call LBR$OPEN to create and open the library;
pass the Options array initialized in item 5 to the Librarian.
- If the call to LBR$OPEN was unsuccessful,
call the procedure Open_Error (see item 4) to determine the cause of
the error.
13.2.2 Inserting a Module
Example 13-2 illustrates the insertion of a module into a library from
a HP Pascal program. The program is summarized in the following steps:
- Ensure that the module does not already exist by calling
LBR$LOOKUP_KEY. The return status should be LBR$_KEYNOTFND. This step
is optional.
- Construct the module by calling LBR$PUT_RECORD once for each record
going into the module. Pass the contents of the record as the second
argument. LBR$PUT_RECORD returns the record file address (RFA) in the
library file as the third argument on the first call. On subsequent
calls, you pass the RFA as the third argument, so do not alter its
value between calls.
- Call LBR$PUT_END after the last call to LBR$PUT_RECORD.
- Call LBR$INSERT_KEY to catalog the records you have just put in the
library. The second argument is the name of the module.
To replace an existing module, save the RFA of the module header
returned by LBR$LOOKUP_KEY in Step 1 in one variable and the new RFA
returned by the first call to LBR$PUT_RECORD (Step 2) in another
variable. In Step 4, invoke LBR$REPLACE_KEY instead of LBR$INSERT_KEY,
pass the old RFA as the third argument, and the new RFA as the fourth
argument.
Example 13-2 Inserting a Module into a
Library Using HP Pascal |
PROGRAM insertmod(INPUT,OUTPUT);
(*This program inserts a module into a library*)
TYPE
Rfa_Ptr = ARRAY [0..1] OF INTEGER; (*Data type of RFA of module*)
VAR
LBR$C_UPDATE, (*Constants for LBR$INI_CONTROL*)
LBR$C_TYP_TXT, (*Defined in $LBRDEF macro*)
LBR$_KEYNOTFND : [EXTERNAL] INTEGER;(*Error code for LBR$LOOKUP_KEY*)
Lib_Name : VARYING [128] OF CHAR; (*Name of library receiving module*)
Module_Name : VARYING [31] OF CHAR; (*Name of module to insert*)
Text_Data_Record : VARYING [255] OF CHAR; (*Record in new module*)
Textin : FILE OF VARYING [255] OF CHAR; (*File containing new module*)
lib_index_ptr : UNSIGNED; (*Value returned in library init*)
status : UNSIGNED; (*Return status for function calls*)
txtrfa_ptr : Rfa_Ptr; (*For key lookup and insertion*)
Key_Not_Found : BOOLEAN := FALSE; (*True if new mod not already in lib*)
(*-*-*-*-Function Definitions-*-*-*-*)
(*Function that returns library
control index used by Librarian*)
FUNCTION LBR$INI_CONTROL (VAR library_index: UNSIGNED;
func: UNSIGNED;
typ: UNSIGNED;
VAR namblk: ARRAY[l..u:INTEGER]
OF INTEGER := %IMMED 0):
INTEGER; EXTERN;
(*Function that creates/opens library*)
FUNCTION LBR$OPEN (library_index: UNSIGNED;
fns: [class_s]PACKED ARRAY[l..u:INTEGER] OF CHAR;
create_options: ARRAY [l2..u2:INTEGER] OF INTEGER :=
%IMMED 0;
dns: [CLASS_S] PACKED ARRAY [l3..u3:INTEGER] OF CHAR
:= %IMMED 0;
rlfna: ARRAY [l4..u4:INTEGER] OF INTEGER := %IMMED 0;
rns: [CLASS_S] PACKED ARRAY [l5..u5:INTEGER] OF CHAR :=
%IMMED 0;
VAR rnslen: INTEGER := %IMMED 0):
INTEGER; EXTERN;
(*Function that finds a key in index*)
FUNCTION LBR$LOOKUP_KEY (library_index: UNSIGNED;
key_name:[CLASS_S] PACKED ARRAY [l..u:INTEGER] OF
CHAR;
VAR txtrfa: Rfa_Ptr):
INTEGER; EXTERN;
(*Function that inserts key in index*)
FUNCTION LBR$INSERT_KEY (library_index: UNSIGNED;
key_name:[CLASS_S] PACKED ARRAY [l..u:INTEGER] OF
CHAR;
txtrfa: Rfa_Ptr):
INTEGER; EXTERN;
(*Function that writes data records*)
|
FUNCTION LBR$PUT_RECORD (library_index: UNSIGNED; (*to modules*)
textline:[CLASS_S] PACKED ARRAY [l..u:INTEGER] OF
CHAR;
txtrfa: Rfa_Ptr):
INTEGER; EXTERN;
(*Function that marks end of a module*)
FUNCTION LBR$PUT_END (library_index: UNSIGNED):
INTEGER; EXTERN;
(*Function that closes library*)
FUNCTION LBR$CLOSE (library_index: UNSIGNED):
INTEGER; EXTERN;
BEGIN (* *************** DECLARATIONS COMPLETE *************************
*************** MAIN PROGRAM BEGINS HERE ********************** *)
(*Prompt for library name and
module to insert*)
WRITE('Library Name: '); READLN(Lib_Name);
WRITE('Module Name: '); READLN(Module_Name);
(*Initialize lib for update access*)
status := LBR$INI_CONTROL (lib_index_ptr, (1)
IADDRESS(LBR$C_UPDATE), (*Update access*)
IADDRESS(LBR$C_TYP_TXT)); (*Text library*)
IF NOT ODD(status) THEN (*Check error status*)
WRITELN('Initialization Failed')
ELSE (*Initialization was successful*)
BEGIN
status := LBR$OPEN (lib_index_ptr, (*Open the library*)
Lib_Name);
IF NOT ODD(status) THEN (*Check error status*)
WRITELN('Open Not Successful')
ELSE (*Open was successful*)
BEGIN (*Is module already in the library?*)
status := LBR$LOOKUP_KEY (lib_index_ptr, (2)
Module_Name,
txtrfa_ptr);
IF ODD(status) THEN (*Check status. Should not be odd*)
WRITELN('Lookup key was successful.',
'The module is already in the library.')
ELSE (*Did lookup key fail because key not found?*)
IF status = IADDRESS(LBR$_KEYNOTFND) THEN (3)
Key_Not_Found := TRUE
END
END;
|
(******If LBR$LOOKUP_KEY failed because the key was not found
(as expected), we can open the file containing the new module,
and write the module's records to the library file*******)
IF Key_Not_Found THEN
BEGIN
OPEN(Textin,Module_Name,old);
RESET(Textin);
WHILE NOT EOF(Textin) DO (*Repeat until end of file*)
BEGIN (4)
READ(Textin,Text_Data_Record); (*Read record from
external file*)
status := LBR$PUT_RECORD (lib_index_ptr, (*Write*)
Text_Data_Record, (*record to*)
txtrfa_ptr); (*library*)
IF NOT ODD(status) THEN
WRITELN('Put Record Routine Not Successful')
END; (*of WHILE statement*)
IF ODD(status) THEN (*True if all the records have been
successfully written into the library*)
BEGIN
status := LBR$PUT_END (lib_index_ptr); (*Write end of
module record*)
IF NOT ODD(status) THEN
WRITELN('Put End Routine Not Successful')
ELSE (*Insert key for new module*)
BEGIN (5)
status := LBR$INSERT_KEY (lib_index_ptr,
Module_Name,
txtrfa_ptr);
IF NOT ODD(status) THEN
WRITELN('Insert Key Not Successful')
END
END
END;
status := LBR$CLOSE(lib_index_ptr);
IF NOT ODD(status) THEN
WRITELN('Close Not Successful')
END. (*of program insertmod*)
|
Each item in the following list corresponds to a number highlighted in
Example 13-2:
- Call LBR$INI_CONTROL, specifying that the
function to be performed is update and that the library type is text.
- Call LBR$LOOKUP_KEY to see whether the module
to be inserted is already in the library.
- Call LBR$LOOKUP_KEY to see whether the lookup
key failed because the key was not found. (In this case, the status
value is LBR$_KEYNOTFND.)
- Read a record from the input file, then use
LBR$PUT_RECORD to write the record to the library. When all the records
have been written to the library, use LBR$PUT_END to write an
end-of-module record.
- Use LBR$INSERT_KEY to insert a key for the
module into the current index.
13.2.3 Extracting a Module
Example 13-3 illustrates the extraction of a library module from a HP
Pascal program. The program is summarized in the following steps:
- Call LBR$LOOKUP_KEY to locate the module. Specify the name of the
module as the second argument. LBR$LOOKUP_KEY returns the RFA of the
module as the third argument; do not alter this value.
- Call LBR$GET_RECORD once for each record in the module. Specify a
character string to receive the extracted record as the second
argument. LBR$GET_RECORD returns a status value of RMS$_EOF after the
last record in the module is extracted.
Example 13-3 Extracting a Module from a
Library Using HP Pascal |
PROGRAM extractmod(INPUT,OUTPUT,Textout);
(*This program extracts a module from a library*)
TYPE
Rfa_Ptr = ARRAY [0..1] OF INTEGER; (*Data type of RFA of module*)
VAR
LBR$C_UPDATE, (*Constants for LBR$INI_CONTROL*)
LBR$C_TYP_TXT, (*Defined in $LBRDEF macro*)
RMS$_EOF : [EXTERNAL] INTEGER; (*RMS return status; defined in
$RMSDEF macro*)
Lib_Name : VARYING [128] OF CHAR; (*Name of library receiving module*)
Module_Name : VARYING [31] OF CHAR; (*Name of module to insert*)
Extracted_File : VARYING [31] OF CHAR; (*Name of file to hold
extracted module*)
Outtext : PACKED ARRAY [1..255] OF CHAR; (*Extracted mod put here,*)
Outtext2 : VARYING [255] OF CHAR; (* then moved to here*)
i : INTEGER; (*For loop control*)
Textout : FILE OF VARYING [255] OF CHAR; (*File containing extracted
module*)
nullstring : CHAR; (*nullstring, pos, and len used to*)
pos, len : INTEGER; (*find string in extracted file recd*)
lib_index_ptr : UNSIGNED; (*Value returned in library init*)
status : UNSIGNED; (*Return status for function calls*)
txtrfa_ptr : Rfa_Ptr; (*For key lookup and insertion*)
(*-*-*-*-Function Definitions-*-*-*-*)
(*Function that returns library
control index used by Librarian*)
FUNCTION LBR$INI_CONTROL (VAR library_index: UNSIGNED;
func: UNSIGNED;
typ: UNSIGNED;
VAR namblk: ARRAY[l..u:INTEGER]
OF INTEGER := %IMMED 0):
INTEGER; EXTERN;
(*Function that creates/opens library*)
FUNCTION LBR$OPEN (library_index: UNSIGNED;
fns: [class_s]PACKED ARRAY[l..u:INTEGER] OF CHAR;
create_options: ARRAY [l2..u2:INTEGER] OF INTEGER :=
%IMMED 0;
dns: [CLASS_S] PACKED ARRAY [l3..u3:INTEGER] OF CHAR
:= %IMMED 0;
rlfna: ARRAY [l4..u4:INTEGER] OF INTEGER := %IMMED 0;
rns: [CLASS_S] PACKED ARRAY [l5..u5:INTEGER] OF CHAR :=
%IMMED 0;
VAR rnslen: INTEGER := %IMMED 0):
INTEGER; EXTERN;
(*Function that finds a key in an index*)
FUNCTION LBR$LOOKUP_KEY (library_index: UNSIGNED;
key_name:[CLASS_S] PACKED ARRAY [l..u:INTEGER] OF
CHAR;
VAR txtrfa: Rfa_Ptr):
INTEGER; EXTERN;
|
(*Function that retrieves records from modules*)
FUNCTION LBR$GET_RECORD (library_index: UNSIGNED;
var textline:[CLASS_S] PACKED ARRAY [l..u:INTEGER] OF
CHAR):
INTEGER;
EXTERN;
(*Function that closes library*)
FUNCTION LBR$CLOSE (library_index: UNSIGNED):
INTEGER; EXTERN;
BEGIN (* *************** DECLARATIONS COMPLETE *************************
*************** MAIN PROGRAM BEGINS HERE ********************** *)
(* Get Library Name, Module To Extract, And File To Hold Extracted Module *)
WRITE('Library Name: '); READLN(Lib_Name);
WRITE('Module Name: '); READLN(Module_Name);
WRITE('Extract Into File: '); READLN(Extracted_File);
status := LBR$INI_CONTROL (lib_index_ptr, (1)
IADDRESS(LBR$C_UPDATE),
IADDRESS(LBR$C_TYP_TXT));
IF NOT ODD(status) THEN
WRITELN('Initialization Failed')
ELSE
BEGIN
status := LBR$OPEN (lib_index_ptr,
Lib_Name);
IF NOT ODD(status) THEN
WRITELN('Open Not Successful')
ELSE
BEGIN (2)
status := LBR$LOOKUP_KEY (lib_index_ptr,
Module_Name,
txtrfa_ptr);
IF NOT ODD(status) THEN
WRITELN('Lookup Key Not Successful')
ELSE
BEGIN (3)
OPEN(Textout,Extracted_File,new);
REWRITE(Textout)
END
END
END;
WHILE ODD(status) DO
BEGIN
nullstring := ''(0);
FOR i := 1 TO 255 DO (4)
Outtext[i] := nullstring;
status := LBR$GET_RECORD (lib_index_ptr,
Outtext);
IF NOT ODD(status) THEN
BEGIN (5)
IF status = IADDRESS(RMS$_EOF) THEN
WRITELN(' RMS end of file')
END
|
ELSE
BEGIN (6)
pos := INDEX(Outtext, nullstring); (*find first null
in Outtext*)
len := pos - 1; (*length of Outtext to first null*)
IF len >= 1 THEN
BEGIN
Outtext2 := SUBSTR(Outtext,1,LEN);
WRITE(Textout,Outtext2)
END
END
END; (*of WHILE*)
status := LBR$CLOSE(lib_index_ptr);
IF NOT ODD(status) THEN
WRITELN('Close Not Successful')
END. (*of program extractmod*)
|
|