HP OpenVMS Systems Documentation

Content starts here

OpenVMS Programming Concepts Manual


Previous Contents Index

24.2.5 Disabling and Enabling Control Characters

Two run-time library routines, LIB$ENABLE_CTRL and LIB$DISABLE_CTRL, allow you to call the CLI to enable or disable control characters. These routines take a longword bit mask argument that specifies the control characters to be disabled or enabled. Acceptable values for this argument are LIB$M_CLI_CTRLY and LIB$M_CLI_CTRLT.

LIB$DISABLE_CTRL Disables CLI interception of control characters.

This routine performs the same function as the DCL command SET NOCONTROL= n, where n is T or Y.

It prevents the currently active CLI from intercepting the control character specified during an interactive session.

For example, you might use LIB$DISABLE_CTRL to disable CLI interception of Ctrl/Y. Normally, Ctrl/Y interrupts the current command, command procedure, or image. If LIB$DISABLE_CTRL is called with LIB$M_CLI_CTRLY specified as the control character to be disabled, Ctrl/Y is treated like Ctrl/U followed by a carriage return.

LIB$ENABLE_CTRL Enables CLI interception of control characters.

This routine performs the same function as the DCL command SET CONTROL= n, where n is T or Y.

LIB$ENABLE_CTRL restores the normal operation of Ctrl/Y or Ctrl/T.

24.2.6 Creating and Connecting to a Subprocess

You can use LIB$SPAWN and LIB$ATTACH together to spawn a subprocess and attach the terminal to that subprocess. These routines execute correctly only if the current CLI is DCL. For more information on the SPAWN and ATTACH commands, see the OpenVMS DCL Dictionary. For more information on creating processes, see Chapter 2.

LIB$SPAWN Spawns a subprocess.

This routine is equivalent to the DCL command SPAWN. It requests the CLI to spawn a subprocess for executing CLI commands.

LIB$ATTACH Attaches the terminal to another process.

This routine is equivalent to the DCL command ATTACH. It requests the CLI to detach the terminal from the current process and reattach it to a different process.

24.3 Access to VAX Machine Instructions

The VAX instruction set was designed for efficient use by high-level languages and, therefore, contains many functions that are directly useful in your programs. However, some of these functions cannot be used directly by high-level languages.

The run-time library provides routines that allow your high-level language program to use most VAX machine instructions that are otherwise unavailable. On Alpha machines, these routines execute a series of Alpha instructions that emulate the operation of the VAX instructions. In most cases, these routines simply execute the instruction, using the arguments you provide. Some routines that accept string arguments, however, provide some additional functions that make them easier to use.

These routines fall into the following categories:

The VAX Architecture Reference Manual describes the VAX instruction set in detail.

24.3.1 Variable-Length Bit Field Instruction Routines

The variable-length bit field is a VAX data type used to store small integers packed together in a larger data structure. It is often used to store single flag bits.

The run-time library contains five routines for performing operations on variable-length bit fields. These routines give higher-level languages that do not have the inherent ability to manipulate bit fields direct access to the bit field instructions in the VAX instruction set. Further, if a program calls a routine written in a different language to perform some function that also involves bit manipulation, the called routine can include a call to the run-time library to perform the bit manipulation.

Table 24-3 lists the run-time library variable-length bit field routines.

Table 24-3 Variable-Length Bit Field Routines
Entry Point Function
LIB$EXTV Extracts a field from the specified variable-length bit field and returns it in sign-extended longword form.
LIB$EXTZV Extracts a field from the specified variable-length bit field and returns it in zero-extended longword form.
LIB$FFC Searches the specified field for the first clear bit. If it finds one, it returns SS$_NORMAL and the bit position ( find-pos argument) of the clear bit. If not, it returns a failure status and sets the find-pos argument to the start position plus the size.
LIB$FFS Searches the specified field for the first set bit. If it finds one, it returns SS$_NORMAL and the bit position ( find-pos argument) of the set bit. If not, it returns a failure status and sets the find-pos argument to the start position plus the size.
LIB$INSV Replaces the specified field with bits 0 through [ size -1] of the source ( src argument). If the size argument is 0, nothing is inserted.

Three scalar attributes define a variable bit field:

  • Base address---The address of the byte in memory that serves as a reference point for locating the bit field.
  • Bit position---The signed longword containing the displacement of the least significant bit of the field with respect to bit 0 of the base address.
  • Size---A byte integer indicating the size of the bit field in bits (in the range 0 <= size <= 32). That is, a bit field can be no more than one longword in length.

Figure 24-1 shows the format of a variable-length bit field. The shaded area indicates the field.

Figure 24-1 Format of a Variable-Length Bit Field


Bit fields are zero-origin, which means that the routine regards the first bit in the field as being the zero position. For more detailed information about VAX bit numbering and data formats, see the VAX Architecture Reference Manual.

The attributes of the bit field are passed to an RTL routine in the form of three arguments in the following order:

pos

Operating system usage: longword_signed
type: longword integer (signed)
access: read only
mechanism: by reference
Bit position relative to the base address. The pos argument is the address of a signed longword integer that contains this bit position.

size

Operating system usage: byte_unsigned
type: byte (unsigned)
access: read only
mechanism: by reference
Size of the bit field. The size argument is the address of an unsigned byte that contains this size.

base

Operating system usage: longword_unsigned
type: longword (unsigned)
access: read only
mechanism: by reference
Base address. The base argument contains the address of the base address.

Example

The following BASIC example illustrates three RTL routines. It opens the terminal as a file and specifies HEX> as the prompt. This prompt allows you to obtain input from the terminal without the question mark that VAX BASIC normally adds to the prompt in an INPUT statement. The program calls OTS$CVT_TZ_L to convert the character string input to a longword. It then calls LIB$EXTZV once for each position in the longword to extract the bit in that position. Because LIB$EXTVZ is called with a function reference within the PRINT statement, the bits are displayed.


10      EXTERNAL LONG FUNCTION
                OTS$CVT_TZ_L,           ! Convert hex text to LONG
                LIB$EXTZV               ! Extract zero-ended bit field

20      OPEN "TT:" FOR INPUT AS FILE #1%     ! Open terminal as a file
        INPUT #1%, "HEX>"; HEXIN$            ! Prompt for input
        STAT%=OTS$CVT_TZ_L(HEXIN$, BINARY%)   ! Convert to longword
        IF (STAT% AND 1%) <> 1%               ! Failed?
        THEN
                PRINT "Conversion failed, decimal status ";STAT%
                GO TO 20                      ! Try again
        ELSE
                PRINT HEXIN$,
                PRINT STR$(LIB$EXTZV(N%, 1%, BINARY%));
                        FOR N%=31% to 0% STEP -1%

24.3.2 Integer and Floating-Point Routines

Integer and floating-point routines give a high-level language program access to the corresponding machine instructions. For a complete description of these instructions, see the VAX Architecture Reference Manual. Table 24-4 lists the integer and floating-point routines once up front.

Table 24-4 Integer and Floating-Point Routines
Entry Point Function
LIB$EMUL Multiplies integers with extended precision
LIB$EDIV Divides integers with extended precision

24.3.3 Queue Access Routines

A queue is a doubly linked list. A run-time library routine specifies a queue entry by its address. Two longwords, a forward link and a backward link, define the location of the entry in relation to the preceding and succeeding entries. A self-relative queue is a queue in which the links between entries are displacements; the two longwords represent the displacements of the current entry's predecessor and successor. The VAX instructions INSQHI, INSQTI, REMQHI, and REMQTI allow you to insert and remove an entry at the head or tail of a self-relative queue. Each queue instruction has a corresponding RTL routine.

The self-relative queue instructions are interlocked and cannot be interrupted, so that other processes cannot insert or remove queue entries while the current program is doing so. Because the operation requires changing two pointers at the same time, a high-level language cannot perform this operation without calling the RTL queue access routines.

When you use these routines, cooperating processes can communicate without further synchronization and without danger of being interrupted, either on a single processor or in a multiprocessor environment. The queue access routines are also useful in an AST environment; they allow you to add or remove an entry from a queue without being interrupted by an asynchronous system trap.

The remove queue instructions (REMQHI or REMQTI) return the address of the removed entry. Some languages, such as BASIC, COBOL, and Fortran, do not provide a mechanism for accessing an address returned from a routine. Further, BASIC and COBOL do not allow routines to be arguments.

Table 24-5 lists the queue access routines.

Table 24-5 Queue Access Routines
Entry Point Function
LIB$INSQHI Inserts queue entry at head
LIB$INSQTI Inserts queue entry at tail
LIB$REMQHI Removes queue entry at head
LIB$REMQTI Removes queue entry at tail

Examples

LIB$INSQHI

In BASIC and Fortran, queues can be quadword aligned in a named COMMON block by using a linker option file to specify alignment of program sections. The LIB$GET_VM routine returns memory that is quadword aligned. Therefore, you should use LIB$GET_VM to allocate the virtual memory for a queue. For instance, to create a COMMON block called QUEUES, use the LINK command with the FILE/OPTIONS qualifier, where FILE.OPT is a linker option file containing the line:


PSECT = QUEUES, QUAD

A Fortran application using processor-shared memory follows:


INTEGER*4 FUNCTION INSERT_Q (QENTRY)
COMMON/QUEUES/QHEADER
INTEGER*4 QENTRY(10), QHEADER(2)
INSERT_Q = LIB$INSQHI (QENTRY, QHEADER)
RETURN
END

A BASIC application using processor-shared memory follows:


     COM (QUEUES) QENTRY%(9), QHEADER%(1)
     EXTERNAL INTEGER FUNCTION LIB$INSQHI
     IF LIB$INSQHI (QENTRY%() BY REF, QHEADER%() BY REF) AND 1%
          THEN GOTO 1000
             .
             .
             .
1000 REM  INSERTED OK

LIB$REMQHI

In Fortran, the address of the removed queue entry can be passed to another routine as an array using the %VAL built-in function.

In the following example, queue entries are 10 longwords, including the two longword pointers at the beginning of each entry:


COMMON/QUEUES/QHEADER
INTEGER*4 QHEADER(2), ISTAT
ISTAT = LIB$REMQHI (QHEADER, ADDR)
IF (ISTAT) THEN
        CALL PROC (%VAL (ADDR)) ! Process removed entry
        GO TO ...
ELSE IF (ISTAT .EQ. %LOC(LIB$_QUEWASEMP)) THEN
                GO TO ...       ! Queue was empty
                ELSE IF
                        ...     ! Secondary interlock failed
END IF
   .
   .
   .
END
SUBROUTINE PROC (QENTRY)
INTEGER*4 QENTRY(10)
   .
   .
   .
RETURN
END

24.3.4 Character String Routines

The character string routines listed in Table 24-6 give a high-level language program access to the corresponding VAX machine instructions. For a complete description of these instructions, see the VAX Architecture Reference Manual. For each instruction, the VAX Architecture Reference Manual specifies the contents of all the registers after the instruction executes. The corresponding RTL routines do not make the contents of all the registers available to the calling program.

Table 24-6 lists the LIB$ character string routines and their functions.

Table 24-6 Character String Routines
Entry Point Function
LIB$LOCC Locates a character in a string
LIB$MATCHC Returns the relative position of a substring
LIB$SCANC Scans characters
LIB$SKPC Skips characters
LIB$SPANC Spans characters
LIB$MOVC3 Moves characters
LIB$MOVC5 Moves characters and fills
LIB$MOVTC Moves translated characters
LIB$MOVTUC Move translated characters until specified character is found

The OpenVMS RTL String Manipulation (STR$) Manual describes STR$ string manipulation routines.

Example

This COBOL program uses LIB$LOCC to return the position of a given letter of the alphabet.



IDENTIFICATION DIVISION.
PROGRAM-ID.        LIBLOC.

ENVIRONMENT DIVISION.

DATA DIVISION.

WORKING-STORAGE SECTION.

01   SEARCH-STRING  PIC X(26)
                    VALUE "ABCDEFGHIJKLMNOPQRSTUVWXYZ".
01   SEARCH-CHAR    PIC X.
01   IND-POS        PIC 9(9) USAGE IS COMP.
01   DISP-IND       PIC 9(9).

ROUTINE DIVISION.

001-MAIN.
        MOVE SPACE TO SEARCH-CHAR.
        DISPLAY " ".
        DISPLAY "ENTER SEARCH CHARACTER: " WITH NO ADVANCING.
        ACCEPT SEARCH-CHAR.
        CALL "LIB$LOCC"
            USING BY DESCRIPTOR SEARCH-CHAR, SEARCH-STRING
            GIVING IND-POS.
        IF IND-POS = ZERO
            DISPLAY
                "CHAR ENTERED (" SEARCH-CHAR ") NOT A VALID SEARCH CHAR"
            STOP RUN.
        MOVE IND-POS TO DISP-IND.
        DISPLAY
             "SEARCH CHAR (" SEARCH-CHAR ") WAS FOUND IN POSITION "
             DISP-IND.
        GO TO 001-MAIN.


24.3.5 Miscellaneous Instruction Routines

Table 24-7 lists additional routines that you can use.

Table 24-7 Miscellaneous Instruction Routines
Entry Point Function
LIB$CALLG Calls a routine using an array argument list
LIB$CRC Computes a cyclic redundancy check
LIB$CRC_TABLE Constructs a table for a cyclic redundancy check

LIB$CALLG

The LIB$CALLG routine gives your program access to the CALLG instruction. This instruction calls a routine using an argument list stored as an array in memory, as opposed to the CALLS instruction, in which the argument list is pushed on the stack.

LIB$CRC

The LIB$CRC routine allows your high-level language program to use the CRC instruction, which calculates the cyclic redundancy check. This instruction checks the integrity of a data stream by comparing its state at the sending point and the receiving point. Each character in the data stream is used to generate a value based on a polynomial. The values for each character are then added together. This operation is performed at both ends of the data transmission, and the two result values are compared. If the results disagree, then an error occurred during the transmission.

LIB$CRC_TABLE

The LIB$CRC_TABLE routine takes a polynomial as its input and builds the table that LIB$CRC uses to calculate the CRC. You must specify the polynomial to be used.

For more details, see the VAX Architecture Reference Manual.

24.4 Processwide Resource Allocation Routines

This section discusses routines that allocate processwide resources to a single operating system process. The processwide resources discussed here are:

  • Local event flags
  • BASIC and Fortran logical unit numbers (LUNs)

The resource allocation routines are provided so that user routines can use the processwide resources without conflicting with one another.

In general, you must use run-time library resource allocation routines when your program needs processwide resources. This allows RTL routines supplied by Compaq, and user routines that you write to perform together within a process.

If your called routine includes a call to any RTL routine that frees a processwide resource, and that called routine fails to execute normally, the resource will not be freed. Thus, your routine should establish a condition handler that frees the allocated resource before resignaling or unwinding. For information about condition handling, see Chapter 9.

Table 24-8 list routines that perform processwide resource allocation.

Table 24-8 Processwide Resource Allocation Routines
Entry Point Function
LIB$FREE_LUN Deallocates a specific logical unit number
LIB$GET_LUN Allocates next arbitrary logical unit number
LIB$FREE_EF Frees a local event flag
LIB$GET_EF Allocates a local event flag
LIB$RESERVE_EF Reserves a local event flag

24.4.1 Allocating Logical Unit Numbers

BASIC and Fortran use a logical unit number (LUN) to define the file or device a program uses to perform input and output. For a routine to be modular, it does not need to know the LUNs being used by other routines that are running at the same time. For this reason, logical units are allocated and deallocated at run time. You can use LIB$GET_LUN and LIB$FREE_LUN to obtain the next available number. This ensures that your BASIC or Fortran routine does not use a logical unit that is already being used by a calling program. Therefore, you should use this routine whenever your program calls or is called by another program that also allocates LUNs. Logical unit numbers 100 to 119 are available to modular routines through these entry points.

To allocate an LUN, call LIB$GET_LUN and use the value returned as the LUN for your I/O statements. If no LUNs are available, an error status is returned and the logical unit is set to -1 . When the program unit exits, it should use LIB$FREE_LUN to free any LUNs that have been allocated by LIB$GET_LUN. If it does not free any LUNs, the available pool of numbers is freed for use.

If your called routine contains a call to LIB$FREE_LUN to free the LUNs upon exit, and your routine fails to execute normally, the LUNs will not be freed. For this reason, you should make sure to establish a condition handler to call LIB$FREE_LUN before resignaling or unwinding. Otherwise, the allocated LUN is lost until the image exits.


Previous Next Contents Index