NAME

VMS::Librarian - Perl extension for LBR$ Utility routines.

SYNOPSIS

    #! perl -w

    use VMS::Librarian qw(VLIB_CREATE VLIB_READ VLIB_UPDATE) ;
    use VMS::Librarian::Object ;
    use VMS::Librarian::Text ;

    #
    # Demonstrate compatibility with Librarian created libraries.
    #

    $test_text1 = <<END;
    This is some text.
    And some more...

    Skipped a line.
	    Tabbed a line.
    END

    qx(create test1.txt);
    open F, ">>test1.txt" or die "error [$!][$^E] opening test1.txt";
    print F $test_text1;
    close F;

    qx(library/create/text test1 test1.txt);

    $libobj1 = new VMS::Librarian::Text (LIBNAME => 'test1.tlb');

    #
    # Get a list of the modules from the default index.
    #

    @lines = $libobj1->get_index() ;

    print "current Index = ",$libobj1->current_index()," ",$libobj1->name(),"\n" ;
    foreach (@lines)
    {
	print "    ",$_,"\n" ;
    }
    print "\n" ;

    #
    # Get modules from a non-existant index.
    #

    @lines = $libobj1->get_index(INDEX => 2) ;

    if (@lines)
    {
	#
	# this should never get executed.
	#

	print "Index = 2 in ",$libobj1->name(),"\n" ;
	foreach (@lines)
	{
	    print "    ",$_,"\n" ;
	}
	print "\n" ;
    }

    #
    # Get the library header.
    #

    $theHeader = $libobj1->get_header() ;

    print "Library header for ",$libobj1->name(),"\n" ;
    foreach (sort keys %$theHeader)
    {
	print "    ",$_," = ",$theHeader->{$_},"\n" ;
    }
    print "\n" ;

    #
    # Extract the specified module
    #

    @lines = $libobj1->get_module (KEY => 'test1');

    print "Module ",$libobj1->name,"(TEST1) is " ;
    if ($test_text1 ne (join "",@lines))
    {
	print "not " ;
    } ;
    print "equal to the test text\n" ;
    print "\n" ;

    #
    # Extract the specified module as scalar
    #

    $theLines = $libobj1->get_module (KEY => 'test1');

    print "Module ",$libobj1->name,"(TEST1) is " ;
    if ($test_text1 ne $theLines)
    {
	print "not " ;
    } ;
    print "equal to the test text\n" ;
    print "\n" ;

    #
    # Write the module and check for differences.
    #

    $theStatus = $libobj1->write_module(FILENAME=>'test1.txt', DATA=>\@lines) ;

    print "Module TEST1 ",($theStatus ? "wrote " : "did not write "),"correctly\n" ;
    print "\n" ;

    $theStatus = qx(diff test1.txt) ;

    print "Checking test1.txt for differences after write_module\n" ;
    print $theStatus ;
    print "\n" ;

    undef $libobj1 ;

    #
    # Delete a module and all its keys.
    # Use the factory interface to open the library.
    #

    $libobj1 = VMS::Librarian::factory(LIBNAME=>'test1.tlb', FUNCTION=>VLIB_UPDATE) ;

    print "factory ",(($libobj1 && (ref($libobj1) eq "VMS::Librarian::Text")) ? "returned" : "did not return")," a valid library object\n" ;
    print "\n" ;

    $status = $libobj1->delete_module(KEY => 'test1') ;

    print $libobj1->name(),"(TEST1) was ",($status ? "" : "not "),"deleted successfully\n" ;
    print "\n" ;

    if ($status)
    {
	my @theIndex = $libobj1->get_index() ;
	foreach (@theIndex)
	{
	    if ($_ eq "TEST1")
	    {
		print "Error: TEST1 not deleted properly from ",$libobj1->name(),"\n" ;
		print "\n" ;
		last ;
	    }
	}
    }

    undef $libobj1 ;

    while (unlink 'test1.tlb') {} ;
    while (unlink 'test1.txt') {} ;

    $test_text2 = <<END;
    This is some more text.
    And some more more text...

    No tab here...
    END

    @test_text2 = split "\n",$test_text2 ;

    #
    # Produce create options for a text library with two indices.
    #

    $creopt = VMS::Librarian::Text->creopt(IDXMAX=>2) ;

    $libobj2 = new VMS::Librarian::Text (LIBNAME => 'test2.tlb',FUNCTION=>VLIB_CREATE, CREOPT=>$creopt);

    if ($libobj2)
    {
	print $libobj2->name()," created successfully\n" ;
	print "\n" ;
    }

    #
    # Add the test data.
    #

    $status = $libobj2->add_module(KEY => 'TEST2', DATA => \@test_text2) ;

    print $libobj2->name(),"(TEST2) was ",($status ? "" : "not "),"added successfully.\n" ;
    print "\n" ;

    #
    # Get the module and verify it.
    #

    @lines = $libobj2->get_module (KEY => 'test2');

    print "Module ",$libobj2->name,"(TEST2) is " ;
    if ($test_text2 ne (join "",@lines))
    {
	print "not " ;
    } ;
    print "equal to the test text\n" ;
    print "\n" ;

    #
    # Add a couple of additional keys to the secondary index and link
    # them to a module.
    #

    @keys = ('TEST2A', 'TEST2B') ;

    $status = $libobj2->connect_indices(KEY=>'TEST2', INDEX=>2, KEYS => \@keys) ;

    print "Additional keys were ",($status ? "" : "not "),"added successfully.\n" ;
    print "\n" ;

    #
    # Get and verify the module by way of the secondary entry.
    #

    $libobj2->set_index(INDEX=>2) ;

    @lines = $libobj2->get_module (KEY => 'test2a');

    print "Module ",$libobj2->name,"(TEST2A) is " ;
    if ($test_text2 ne (join "",@lines))
    {
	print "not " ;
    } ;
    print "equal to the test text\n" ;
    print "\n" ;

    #
    # Get all keys in all indices for the TEST2B entry in the
    # secondary entry.
    #

    print "Getting modules keys for entry 'TEST2B'\n" ;

    @keys = $libobj2->get_keys(KEY=>'test2b') ;

    for ($i = 1; $i <= 8; $i++)
    {
	if (defined($keys[$i]))
	{
	    print "Index $i:\n" ;
	    foreach (@{$keys[$i]})
	    {
		print "    ",$_,"\n" ;
	    }
	}
    }
    print "\n" ;

    #
    # Add the test data using the string interface.
    #

    $status = $libobj2->add_module(KEY => 'TEST3', DATA => $test_text2) ;

    print $libobj2->name(),"(TEST3) was ",($status ? "" : "not "),"added successfully.\n" ;
    print "\n" ;

    #
    # Get the module and verify it.
    #

    $theLines = $libobj2->get_module (KEY => 'test3');

    print "Module ",$libobj2->name,"(TEST3) is " ;
    if ($test_text2 ne $theLines)
    {
	print "not " ;
    } ;
    print "equal to the test text\n" ;
    print "\n" ;

    undef $libobj2 ;

    while (unlink 'test2.tlb') {} ;

    #
    # Check package level debug flag.
    #

    print "Check package level debug flag.\n" ;

    $VMS::Librarian::DEBUG = 1 ;

    $libobj3 = new VMS::Librarian::Object(LIBNAME=>'sys$library:decc$crtl.olb',FUNCTION=>VLIB_READ) ;

    undef $libobj3 ;

    print "\n" ;

    $VMS::Librarian::DEBUG = 0 ;

    #
    # Check Object level override of debug flag.
    #

    print "Check object level override of debug flag.\n" ;

    $VMS::Librarian::DEBUG = 1 ;

    $libobj3 = new VMS::Librarian::Object(LIBNAME=>'sys$library:decc$crtl.olb',FUNCTION=>VLIB_READ,DEBUG=>0) ;

    $libobj3->set_index(INDEX=>2) ;

    undef $libobj3 ;

    $VMS::Librarian::DEBUG = 0 ;

    print "\n" ;

    #
    # Check member function level override of debug flag.
    #

    print "Check member function override of debug flag.\n" ;

    $libobj3 = new VMS::Librarian::Object(LIBNAME=>'sys$library:decc$crtl.olb',FUNCTION=>VLIB_READ,DEBUG=>1) ;

    $libobj3->set_index(INDEX=>2, DEBUG=>0) ;

    undef $libobj3 ;

    print "\n" ;

    #
    # Read the primary and secondary indices in DECC$CRTL and see
    # how many are there.
    #

    my $libobj3 = new VMS::Librarian::Object(LIBNAME=>'sys$library:decc$crtl.olb',FUNCTION=>VLIB_READ) ;

    $libobj3->set_index(INDEX=>2) ;
    @lines = $libobj3->get_index(INDEX=>1) ;

    print $libobj3->name()," has ",scalar(@lines)," keys in index 1\n" ;
    print "\n" ;

    @lines = $libobj3->get_index() ;

    print $libobj3->name()," has ",scalar(@lines)," keys in index ",$libobj3->current_index(),"\n" ;
    print "\n" ;

    #
    # Write the module and check for differences.
    #

    $theModule = 'C$WSTRINGS' ;

    print "Extracting ",$libobj3->name(),"($theModule)\n" ;
    print qx(libr/log/extract=$theModule/output=test3.obj sys\$library:decc\$crtl.olb) ;
    print "\n" ;

    $libobj3->set_index(INDEX => 1) ;

    @lines = $libobj3->get_module(KEY => $theModule) ;

    $theStatus = $libobj3->write_module(FILENAME=>'test3.obj', DATA=>\@lines) ;

    print 'Module C$WSTRINGS ',($theStatus ? "wrote " : "did not write "),"correctly\n" ;
    print "\n" ;

    $theStatus = qx(diff test3.obj) ;

    print "Checking test3.obj for differences after write_module\n" ;
    print $theStatus ;
    print "\n" ;

    @lines = $libobj3->read_module(FILENAME => 'test3.obj') ;

    print "File TEST3.OBJ ",(@lines ? "" : "did not "),"read correctly\n" ;
    print "\n" ;

    $theStatus = $libobj3->write_module(FILENAME=>'test3.obj', DATA=>\@lines) ;

    $theStatus = qx(diff test3.obj test3.obj;-2) ;

    print "Checking test3.obj for differences after read_module/write_module\n" ;
    print $theStatus ;
    print "\n" ;

    undef $libobj3 ;

    while (unlink 'test3.obj') {} ;

DESCRIPTION

VMS::Librarian provides an object oriented Perl interface to OpenVMS librarys. Using this interface any type of library (macro, text, object, help, and user defined) may be created and/or manipulated.

All routines accept a variable number of parameters using hash notation, e.g.,

$object->routine(P1=>value, P2=> value, ...) ;

Omitted required parameters cause an error message and your Perl code to terminate.

VMS::Librarian is shipped with derived classes that provide specialized support for image, macro, object, and text libraries.

Class Functions

factory
    $theObject = VMS::Librarian::factory(LIBNAME=>string,
					 FUNCTION=>integer)

The factory returns an appropriately typed object for processing a library. The library must already exist. If the library is not of a known type, then the returned object will be undefined.

Accessors

Accessors provide read-only access to some of the internal state of the library object.

current_index

Return the current key index. VMS::Librarian keeps track of the current key index and makes sure that it remains current across calls to the various external interfaces.

The contents of the library header as returned by get_header. If get_header hasn't been called, then header returns an undefined value.

library_index

The LBR$ routine library index for this library object.

name

The name of the library.

type

The type of the library. This is an integer value. The corresponding library type symbol can be found in LBRDEF.H.

Member Functions

All member functions accept an optional DEBUG parameter. The DEBUG parameter is a bit map. Bit 0 enables debug information from the Perl side of the interface. Bit 1 enables debug information from the XS side of the interface.

add_module
    $theStatus = $l->add_module(KEY   => name,
			        DATA  => array reference)

Add a module to the library. The module key is added to the current index. The data to be added is contained in an array. The size of the individual elements of the array varies depending upon the type of the library, but the maximum length is 65535 bytes.

The key must not exist in the library.

If the module is inserted correctly, add_module returns true, otherwise it returns false. In the event of an error, additional information is in $! and $^E.

close
$theStatus = $l->close()

Close the library and disconnect the object from the library. Once a library has been closed, the object may no longer be used for library access. To close and dispose of the object, use undef, e.g.,

undef $l

If the library closes properly the member function returns true, otherwise it returns false. If an error occurs, additional information is in $! and $^E.

connect_indices
    $theStatus = $l->connect_indices(KEY	=> string,
				     INDEX	=> integer,
				     KEYS	=> array reference)

Connect the KEYS in the INDEX to the module KEY in the current index. The module KEY must exist in the library prior to calling connect_indices. The KEYS must not exist in the specified index. If the keys are properly inserted the member function returns true, otherwise it returns false. If an error occurs, additional information is in $! and $^E.

creopt
    $theCreopt = VMS::Librarian->creopt(TYPE   => library type,
					KEYLEN => integer,
					ALLOC  => integer,
					IDXMAX => integer,
					UHDMAX => integer,
					ENTALL => integer,
					LUHMAX => integer,
					VERTYP => integer,
					IDXOPT => bitmap)

creopt returns a hash reference containing the creation options used to create a new library.

The above are defined fully in the LBR$ Utility routine documentation and credef.h. All arguments to this routine are optional. Each specialization of VMS::Librarian is required to implement a creopt routine. Values specified in the parameters to creopt override any defaults specified by creopt.

Symbolic constants for TYPE, VERTYP, and IDXOPT are exported by VMS::Librarian (although not yet by any specializations of VMS::Librarian). See below for a list of the exported constants.

delete_module
$theStatus = $l->delete_module(KEY=>string or array reference)

Delete one or more modules from a library. The specified keys must exist in the current index. All secondary keys are removed for each module deleted. delete_module returns true if all modules have been successfully deleted. If an error of any type occurs, delete_module returns. If a set of modules was to be delete, any modules following the error will not have been deleted.

Additional error information is available in $! and $^E.

get_header
$theHeader = $l->get_header()
@theHeader = $l->get_header()

Return a hash reference containing the library header. The current library header is also stored in the library object and may be retrieved using the header accessor.

If an empty value is returned, additional error information is available in $! and $^E.

In array context, the array version of the hash is returned.

get_index
@theKeys = $l->get_index(INDEX => integer)

Return an array containing the modules for the specified index. If the INDEX parameter is omitted, the current index is used. If an empty value is returned additional error information is available in $! and $^E.

get_keys
@theKeys = $l->get_keys(KEY => string)

An array of arrays, containing all keys in all indices for the specified module. The array indices (1 to 8) match the library key indices in the returned array. If called in scalar context, an array reference is returned. If an empty value is returned, additional error information is found in $! and $^E.

get_module
@theData = $l->get_module(KEY => string)
$theData = $l->get_module(KEY => string)

The data for the specified module is returned. If an empty value is returned, additional error information is available in $! and $^E.

This member function is overriden for libraries containing text to allow addition of a newline character to make the data more "consistent" with Perl expectations. The default implementation of get_header in VMS::Librarian does not modify the data.

In array context, get_module returns an array of data records. In scalar context, get_module returns a string containing the concatenation of all the data records.

new
    $l = new VMS::Librarian(LIBNAME  => string,
			   [FUNCTION => integer],
			   [TYPE     => integer,]
			   [CREOPT   => hash reference])

Create a new library object and connect it to a library. The library TYPE is only required if a new library is to be created. In all other circumstances, VMS::Librarian can figure out the necessary additional library type information. If the FUNCTION parameter is omitted, it defaults to read access. If a library is to be created and the default creation options are not appropriate, a creation options hash (see creopt, above) can be provided for use. If an error occurs nothing will be returned by the new function and additional error information will be available in $! anbd $^E.

replace_module
    $theStatus = $l->replace_module(KEY   => name,
				    DATA  => array reference)

replace_module is syntactic sugar. It calls delete_module before calling add_module. The specified module must exist. If it doesn't, you should just call add_module.

set_index
$theStatus = $l->set_index(INDEX => integer)

Set the current index for the library. VMS::Librarian will maintain this across calls to its member functions. If an error occurs when setting the index (and empty value is returned) additional information will be available in $! and $^E.

write_module
    $theStatus = $l->write_module(FILENAME => string,
				  DATA => array reference)

Write the data to the specified file. By default the output file contains binary data stored in variable length records.

Exported Constants

Library Function Type
VLIB_CREATE
VLIB_READ
VLIB_UPDATE
Library Type
VLIB_UNKNOWN
VLIB_ALPHA_OBJECT
VLIB_VAX_OBJECT
VLIB_OBJECT
VLIB_MACRO
VLIB_HELP
VLIB_TEXT
VLIB_ALPHA_IMAGE
VLIB_VAX_IMAGE
VLIB_IMAGE
Library Creation Constants
VLIB_CRE_VMSV2
VLIB_CRE_VMSV3
VLIB_CRE_NOCASECMP
VLIB_CRE_NOCASENTR
VLIB_CRE_UPCASNTRY
VLIB_CRE_HLPCASING
VLIB_CRE_OBJCASING
VLIB_CRE_MACTXTCAS

Derived Classes

Shipped with VMS::Librarian are a number of additional classes. These classes provide support for the standard set of OpenVMS libraries. These are:

VMS::Librarian::Help
VMS::Librarian::Macro
VMS::Librarian::Object
VMS::Librarian::Text

When creating a new standard library, just create a new object of the appropriate type with the VLIB_CREATE function.

These object encapsulate all the details of creating and managing data in these specialized libraries. See the individual class module documentation (if any) for details.

AUTHOR

The original author of this module was Brad Hughes. It has been completely rewritten by Dick Munroe (munroe@csworks.com). Any support questions or fixes should be send to Dick Munroe at the above address.

On another note, I'm looking for work (contract or permanent). My resume is available at:

http://www.csworks.com/resume

my CV (much more detailed, but too long for general distribution) is available at:

http://www.csworks.com/cv

I do a lot more than hack the web and Perl so take a look and if you think there's a match, drop me a note and let us see if we can't work something out.

SEE ALSO

VMS::Librarian may be downloaded as a zip file from:

http://www.csworks.com/download/vms-librarian-1_06.zip

3 POD Errors

The following errors were encountered while parsing the POD:

Around line 1297:

=back doesn't take any parameters, but you said =back 4

Around line 1331:

=back doesn't take any parameters, but you said =back 4

Around line 1557:

=back doesn't take any parameters, but you said =back 4