Document revision date: 30 March 2001

## OpenVMS Programming Concepts Manual

Previous | Contents | Index

## Part 5
I/O, System and Programming Routines

This part describes the I/O operations, and the system and programming routines used by run-time libraries and system services.

## Chapter 22
Run-Time Library Input/Output Operations

This chapter describes the different I/O programming capabilities provided by the run-time library and illustrates these capabilities with examples of common I/O tasks. This chapter contains the following sections:

Section 22.1 describes the input and output operations within a program.

Section 22.2 describes using SYS$INPUT and SYS$OUTPUT.

Section 22.3 describes using LIB$GET_INPUT and LIB$PUT_OUTPUT for simple user I/O.

Section 22.4 describes using the SMG$ run-time library routines for managing the appearance of terminal screens.

Section 22.5 describes using screen management input routines and the SYS$QIO and SYS$QIOW system services to perform special actions.

## 22.1 Choosing I/O Techniques

The operating system and its compilers provide the following methods for completing input and output operations within a program:

- DEC Text Processing Utility
- DECforms software
- Program language I/O statements
- OpenVMS Record Management Services (RMS) and Run-Time Library (RTL) routines
- SYS$QIO and SYS$QIOW system services
- Non-Compaq-supplied device drivers to control the I/O to the device itself

The DEC Text Processing Utility (DECTPU) is a text processor that can be used to create text editing interfaces. DECTPU has the following features:

- High-level procedure language with several data types, relational operators, error interception, looping, case language statements, and built-in procedures
- Compiler for the DECTPU procedure language
- Interpreter for the DECTPU procedure language
- Extensible Versatile Editor (EVE) editing interface which, in addition to the EVE keypad, provides EDT, VT100, WPS, and numeric keypad emulation

In addition, DECTPU offers the following special features:

- Multiple buffers
- Multiple windows
- Multiple subprocesses
- Text processing in batch mode
- Insert or overstrike text entry
- Free or bound cursor motion
- Learn sequences
- Pattern matching
- Key definition

The method you select for I/O operations depends on the task you want to accomplish, ease of use, speed, and level of control you want.

The Compaq DECforms for OpenVMS software is a forms management product for transaction processing. DECforms integrates text and graphics into forms and menus that application programs use as an interface to users. DECforms software offers application developers software development tools and a run-time environment for implementing interfaces.

DECforms software integrates with the Application Control and Management System (ACMS), a transaction process (TP) monitor that works with other Compaq commercial applications to provide complete customizable development and run-time environments for TP applications. An asynchronous call interface to ACMS allows a single DECforms run-time process to control multiple terminals simultaneously in a multithreaded way, resulting in an efficient use of memory. By using the ACMS Remote Access Option, DECforms software can be distributed to remote CPUs. This technique allows the host CPU to offload forms processing and distribute it as closely as possible to the end user.

In contrast to OpenVMS RMS, RTLs, SYS$QIOs, and device driver I/O, program language I/O statements have the slowest speed and lowest level of control, but they are the easiest to use and are highly portable.

OpenVMS RMS and RTL routines can perform most I/O operations for a high-level or assembly language program. For information about OpenVMS RMS, see the OpenVMS Record Management Services Reference Manual.

System services can complete any I/O operation and can access devices not supported within OpenVMS RMS. See Chapter 23 for a description of using I/O system services.

Writing a device driver provides the most control over I/O operations, but can be more complex to implement. For information about device drivers for VAX systems, see the OpenVMS VAX Device Support Manual. The OpenVMS VAX Device Support Manual has been archived but is available on the OpenVMS Documentation CD-ROM.

Several types of I/O operations can be performed within a program, including the following:

- RTL routines allow you either to read simple input from a user or send simple output to a user. One RTL routine allows you to specify a string to prompt for input from the current input device, defined by SYS$INPUT. Another RTL routine allows you to write a string to the current output device, defined by SYS$OUTPUT. See Section 22.2 and Section 22.3 for more information.
- RTL routines allow you either to read complex input from a user or to send complex output to a user. By providing an extensive number of screen management (SMG$) routines, the RTL allows you either to read multiple lines of input from users or to send complex output to users. The SMG$ routines also allow you to create and modify complicated displays that accept input and produce output. See Section 22.4 for more information.
- RTL routines allow you to use programming language I/O statements to send data to and receive data from files. Program language I/O statements call OpenVMS RMS routines to complete most file I/O. You can also use OpenVMS RMS directly in your programs for accomplishing file I/O. See Chapter 28 for more information.
- The SYS$QIO and SYS$QIOW system services allow you to send data to and from devices with the most flexibility and control. You can use system services to access devices not supported by your programming language or by OpenVMS RMS.
  You can perform other special I/O actions, such as using interrupts, controlling echo, handling unsolicited input, using the type-ahead buffer, using case conversion, and sending sytem broadcast messges, by using SMG$ routines or, for example, by using SYS$BRKTHRU system service to broadcast messages. See Section 22.5 for more information.

## 22.2 Using SYS$INPUT and SYS$OUTPUT

Typically, you set up your program so that the user is the invoker. The user starts the program either by entering a DCL command associated with the program or by using the RUN command.

### 22.2.1 Default Input and Output Devices

The user's input and output devices are defined by the logical names SYS$INPUT and SYS$OUTPUT, which are initially set to the values listed in Table 22-1.

Table 22-1 SYS$INPUT and SYS$OUTPUT Values
Logical Name | User Mode | Equivalence Device or File
--- | --- | ---
SYS$INPUT | Interactive | Terminal at which the user is logged in
| Batch job | Data lines following the invocation of the program
| Command procedure | Data lines following the invocation of the program
SYS$OUTPUT | Interactive | Terminal at which the user is logged in
| Batch job | Batch log file
| Command procedure | Terminal at which the user is logged in

Generally, use of SYS$INPUT and SYS$OUTPUT as the primary input and output devices is recommended. A user of the program can redefine SYS$INPUT and SYS$OUTPUT to redirect input and output as desired. For example, the interactive user might redefine SYS$OUTPUT as a file name to save output in a file rather than display it on the terminal.

### 22.2.2 Reading and Writing to Alternate Devices and External Files

Alternatively, you can design your program to read input from and write output to a file or a device other than the user's terminal. Files may be useful for writing large amounts of data, for writing data that the user might want to save, and for writing data that can be reused as input. If you use files or devices other than SYS$INPUT and SYS$OUTPUT, you should provide the names of the files or devices (best form is to use logical names) and any conventions for their use. You can specify such information by having the program write it to the terminal, by creating a help file, or by providing user documentation.

## 22.3 Working with Simple User I/O

Usually, you can request information from or provide information to the user with little regard for formatting. For such simple I/O, use either LIB$GET_INPUT and LIB$PUT_OUTPUT or the I/O statements for your programming language.

To provide complex screen displays for input or output, use the screen management facility described in Section 22.4.

### 22.3.1 Default Devices for Simple I/O

The LIB$GET_INPUT and LIB$PUT_OUTPUT routines read from SYS$INPUT and write to SYS$OUTPUT, respectively. The logical names SYS$INPUT and SYS$OUTPUT are implicit to the routines, because you need only call the routine to access the I/O unit (device or file) associated with SYS$INPUT and SYS$OUTPUT. You cannot use these routines to access an I/O unit other than the one associated with SYS$INPUT or SYS$OUTPUT.

### 22.3.2 Getting a Line of Input

A read operation transfers one record from the input unit to a variable or variables of your choice. At a terminal, the user ends a record by pressing a terminator. The terminators are the ASCII characters NUL through US (0 through 31) except for LF, VT, FF, TAB, and BS. The usual terminator is CR (carriage return), which is generated by pressing the Return key.

If you are reading character data, LIB$GET_INPUT is a simple way of prompting for and reading the data. If you are reading noncharacter data, programming language I/O statements are preferable since they allow you to translate the data to a format of your choice.

For example, Fortran offers the ACCEPT statement, which reads data from SYS$INPUT, and the READ statement, which reads data from an I/O unit of your choice.

Make sure the variables that you specify can hold the largest number of characters the user of your program might enter, unless you want to truncate the input deliberately. Overflowing the input variable using LIB$GET_INPUT causes the fatal error LIB$_INPSTRTRU (defined in $LIBDEF); overflowing the input variable using language I/O statements may not cause an error but does truncate your data.

LIB$GET_INPUT places the characters read in a variable of your choice. You must define the variable type as a character. Optionally, LIB$GET_INPUT places the number of characters read in another variable of your choice. For input at a terminal, LIB$GET_INPUT optionally writes a prompt before reading the input. The prompt is suppressed automatically for an operation not taking place at a terminal.

Example 22-1 uses LIB$GET_INPUT to read a line of input.

Example 22-1 Reading a Line of Data

    INTEGER*4     STATUS,
    2             LIB$GET_INPUT
    INTEGER*2     INPUT_SIZE
    CHARACTER*512 INPUT
    STATUS = LIB$GET_INPUT (INPUT,           ! Input value
    2                       'Input value: ', ! Prompt (optional)
    2                       INPUT_SIZE)      ! Input size (optional)
    IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))

### 22.3.3 Getting Several Lines of Input

The usual technique for obtaining a variable number of input records---either values for which you are prompting or data records from a file---is to read and process records until the end-of-file. End-of-file means one of the following:

- Terminal---The user has pressed Ctrl/Z. To ensure that the convention is followed, you might first write a message telling the user to press Ctrl/Z to terminate the input sequence.
- Command procedure---The end of a sequence of data lines has been reached. That is, a sequence of data lines ends at the next DCL command (a line in the procedure beginning with a dollar sign [$]) or at the end of the command procedure file.
- File---The end of an actual file has been reached.

Process the records in a loop (one record per iteration) and terminate the loop on end-of-file. LIB$GET_INPUT returns the error RMS$_EOF (defined in $RMSDEF) when end-of-file occurs.

Example 22-2 uses a Fortran READ statement in a loop to read a sequence of integers from SYS$INPUT.

Example 22-2 Reading a Varying Number of Input Records

    ! Return status and error codes
    INTEGER   STATUS,
    2         IOSTAT,
    3         STATUS_OK,
    4         IOSTAT_OK
    PARAMETER (STATUS_OK = 1,
    2          IO_OK = 0)
    INCLUDE   '($FORDEF)'
    ! Data record read on each iteration
    INTEGER   INPUT_NUMBER
    ! Accumulated data records
    INTEGER   STORAGE_COUNT,
    2         STORAGE_MAX
    PARAMETER (STORAGE_MAX = 255)
    INTEGER    STORAGE_NUMBER (STORAGE_MAX)
    ! Write instructions to interactive user
    TYPE *,
    2 'Enter values below. Press CTRL/Z when done.'
    ! Get first input value
    WRITE (UNIT=*,
    2      FMT='(A,$)') ' Input value: '
    READ (UNIT=*,
    2     IOSTAT=IOSTAT,
    2     FMT='(BN,I)') INPUT_NUMBER
    IF (IOSTAT .EQ. IO_OK) THEN
      STATUS = STATUS_OK
    ELSE
      CALL ERRSNS (,,,,STATUS)
    END IF
    ! Process each input value until end-of-file
    DO WHILE ((STATUS .NE. FOR$_ENDDURREA) .AND.
              (STORAGE_COUNT .LT. STORAGE_MAX))
      ! Keep repeating on conversion error
      DO WHILE (STATUS .EQ. FOR$_INPCONERR)
        WRITE (UNIT=*,
    2          FMT='(A,$)') ' Try again: '
        READ (UNIT=*,
    2         IOSTAT=IOSTAT,
    2         FMT='(BN,I)') INPUT_NUMBER
        IF (IOSTAT .EQ. IO_OK) THEN
          STATUS = STATUS_OK
        ELSE
          CALL ERRSNS (,,,,STATUS)
        END IF
      END DO
      ! Continue if end-of-file not entered
      IF (STATUS .NE. FOR$_ENDDURREA) THEN
        ! Status check on last read
        IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
        ! Store input numbers in input array
        STORAGE_COUNT = STORAGE_COUNT + 1
        STORAGE_NUMBER (STORAGE_COUNT) = INPUT_NUMBER
        ! Get next input value
        WRITE (UNIT=*,
    2          FMT='(A,$)') ' Input value: '
        READ (UNIT=*,
    2         IOSTAT=IOSTAT,
    2         FMT='(BN,I)') INPUT_NUMBER
        IF (IOSTAT .EQ. IO_OK) THEN
          STATUS = STATUS_OK
        ELSE
          CALL ERRSNS (,,,,STATUS)
        END IF
      END IF
    END DO

### 22.3.4 Writing Simple Output

You can use LIB$PUT_OUTPUT to write character data. If you are writing noncharacter data, programming language I/O statements are preferable because they allow you to translate the data to a format of your choice.

LIB$PUT_OUTPUT writes one record of output to SYS$OUTPUT. Typically, you should avoid writing records that exceed the device width. The width of a terminal is 80 or 132 characters, depending on the setting of the physical characteristics of the device. The width of a line printer is 132 characters. If your output record exceeds the width of the device, the excess characters are either truncated or wrapped to the next line, depending on the setting of the physical characteristics.

You must define a value (a variable, constant, or expression) to be written. The value must be expressed in characters. You should specify the exact number of characters being written and not include the trailing portion of a variable.

The following example writes a character expression to SYS$OUTPUT:

    INTEGER*4    STATUS,
    2            LIB$PUT_OUTPUT
    CHARACTER*40 ANSWER
    INTEGER*4    ANSWER_SIZE
       .
       .
       .
    STATUS = LIB$PUT_OUTPUT ('Answer: ' // ANSWER (1:ANSWER_SIZE))
    IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))

## 22.4 Working with Complex User I/O

The following sections present Compaq DECwindows Motif for OpenVMS (DECwindows Motif), and the SMG$ run-time library routines that enable complex screen display I/O.

### 22.4.1 Compaq DECwindows Motif

The Compaq DECwindows Motif environment provides a consistent user interface for developing software applications. It also includes an extensive set of programming libraries and tools. The following Compaq DECwindows Motif software allows you to build a graphical user interface:

- Toolkit composed on graphical user interface objects, such as widgets and gadgets. Widgets provide advanced programming capabilities that permit you to create graphic applications easily; gadgets, similar to widgets, require less memory to create labels, buttons, and separators.
- Language to describe visual aspects of objects, such as menus, labels, and forms, and to specify changes resulting from user interaction.
- OSF/Motif Window Manager to allow you to customize the interface.

Compaq DECwindows Motif environment also makes available the LinkWorks services for creating, managing, and traversing informational links between different application-specific data. Along with the LinkWorks Manager application, LinkWorks services help organize information into a hyperinformation environment. LinkWorks Developer's Tools provide a development environment for creating, modifying, and maintaining hyperapplications.

#### 22.4.1.1 DECwindows Server Height or Width Exceeding 32767 (VAX Only)

On OpenVMS VAX systems, when an X application sends the display server a width or height greater than 32767, the application may terminate with a BadValue error similar to the following:

     X error event received from server: BadValue (integer parameter out of
     range for operation)
       Major opcode of failed request: 61 (X_ClearArea)
       Value in failed request: 0xffff****
       Serial number of failed request: ###
       Current serial number in output stream: ###

The following calls can cause this problem:

> CopyArea()
> CreateWindow ()
> PutImage()
> GetImage()
> CopyPlane()
> ClearArea()

This is due to the width and height being defined as a signed word by the display server when it should be defined as an unsigned word (CARD16) that allows for values up to 65536.

To modify the default operation, perform the following steps:

1. Set the logical name DECW$CARD16_VALIDATE to TRUE as follows:

        $DEFINE/TABLE=DECW$SERVER0_TABLE   DECW$CARD16_VALIDATE  TRUE

2. Exit the session and log back in.
   Exiting the session causes the display server to reset using the new value of the logical name DECW$CARD16_VALIDATE. The server will now accept values that are greater than 32767 without generating an error.

To make this a permanent change, add the command from step 1 to the file SYS$MANAGER:DECW$PRIVATE_SERVER_SETUP.COM.

#### 22.4.1.2 SET DISPLAY Used to Create WSA Pseudo Workstation Devices

When creating WSA pseudo workstation devices using the SET DISPLAY command, be careful not to create WSA devices that are never destroyed. For example, this DCL command procedure is wrong:

     $LOOP:
     $  SET DISPLAY/CREATE/NODE=remote
     $  RUN SYS$SYSTEM:DECW$CLOCK
     $  IF $STATUS THEN GOTO DONE
     $  WAIT 0:0:5
     $  GOTO LOOP
     $DONE:

If the clock cannot be started for some reason, one WSA device will be created for each failed attempt. These WSA devices will use up non-paged dynamic memory, and eventually the process will exceed its BYTLM quota and enter a resource wait state (if resource waiting is enabled, as it is by default).

A better version of this command procedure is the following:

     $  SET DISPLAY/CREATE/NODE=remote
     $LOOP:
     $  RUN SYS$SYSTEM:DECW$CLOCK
     $  IF $STATUS THEN GOTO DONE
     $  WAIT 0:0:5
     $  GOTO LOOP
     $DONE:
     $  SET DISPLAY/DELETE 'F$TRNLNM("DECW$DISPLAY")'

The SET DISPLAY/DELETE command deletes the WSA device that was created at the beginning of the command procedure; the logical name DECW$DISPLAY contains the name of the WSA device that was created.

For information about using OpenVMS Compaq DECwindows Motif, see the Overview of DECwindows Motif for OpenVMS Documentation and the DECwindows Motif Guide to Application Programming.

### 22.4.2 SMG$ Run-Time Routines

The SMG$ run-time library routines provide a simple, device-independent interface for managing the appearance of the terminal screen. The SMG$ routines are primarily for use with video terminals; however, they can be used with files or hardcopy terminals.

To use the screen management facility for output, do the following:

1. Create a pasteboard---A pasteboard is a logical, two-dimensional area on which you place virtual displays. Use the SMG$CREATE_PASTEBOARD routine to create a pasteboard, and associate it with a physical device. When you refer to the pasteboard, SMG performs the necessary I/O operation to the device.
2. Create a virtual display---A virtual display is a logical, two-dimensional area in which you place the information to be displayed. Use the SMG$CREATE_VIRTUAL_DISPLAY routine to create a virtual display.
3. Paste virtual displays to the pasteboard---To make a virtual display visible, map (or paste) it to the pasteboard using the SMG$PASTE_VIRTUAL_DISPLAY routine. You can reference a virtual display regardless of whether that display is currently pasted to a pasteboard.
4. Create a viewport for a virtual display---A viewport is a rectangular viewing area that can be moved around on a buffer to view different pieces of the buffer. The viewport is associated with a virtual display.

Example 22-3 associates a pasteboard with the terminal, creates a virtual display the size of the terminal screen, and pastes the display to the pasteboard. When text is written to the virtual display, the text appears on the terminal screen.

Example 22-3 Associating a Pasteboard with a Terminal

       .
       .
       .
    ! Screen management control structures
    INTEGER*4 PBID,   ! Pasteboard ID
    2         VDID,   ! Virtual display ID
    2         ROWS,   ! Rows on screen
    2         COLS    ! Columns on screen
    ! Status variable and routines called as functions
    INTEGER*4 STATUS,
    2         SMG$CREATE_PASTEBOARD,
    2         SMG$CREATE_VIRTUAL_DISPLAY,
    2         SMG$PASTE_VIRTUAL_DISPLAY
    ! Set up SYS$OUTPUT for screen management
    ! and get the number of rows and columns on the screen
    STATUS = SMG$CREATE_PASTEBOARD (PBID,    ! Return value
    2                               'SYS$OUTPUT',
    2                               ROWS,    ! Return value
    2                               COLUMNS) ! Return value
    IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
    ! Create virtual display that pastes to the full screen size
    STATUS = SMG$CREATE_VIRTUAL_DISPLAY (ROWS,
    2                                    COLUMNS,
    2                                    VDID) ! Return value
    IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
    ! Paste virtual display to pasteboard
    STATUS = SMG$PASTE_VIRTUAL_DISPLAY (VDID,
    2                                   PBID,
    2                                   1, ! Starting at row 1 and
    2                                   1) ! column 1 of the screen
    IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS))
       .
       .
       .

To use the SMG$ routines for input, you associate a virtual keyboard with a physical device or file using the SMG$CREATE_VIRTUAL_KEYBOARD routine. The SMG$ input routines can be used alone or with the output routines. This section assumes that you are using the input routines with the output routines. Section 22.5 describes how to use the input routines without the output routines.

The screen management facility keeps an internal representation of the screen contents; therefore, it is important that you do not mix SMG$ routines with other forms of terminal I/O. The following subsections contain guidelines for using most of the SMG$ routines; for more details, see the OpenVMS RTL Screen Management (SMG$) Manual.

Previous | Next | Contents | Index

| privacy and legal statement |
5841PRO_057.HTML