Document revision date: 30 March 2001

## OpenVMS Utility Routines Manual

Previous | Contents | Index

This routine also returns any condition values returned by user-supplied routines.

## FILEIO

> The user-supplied FILEIO routine performs file I/O functions. Call it by specifying it as an argument in the EDT$EDIT routine. It cannot be called independently.

### Format

> FILEIO code ,stream ,record ,rhb

### RETURNS

> OpenVMS usage: | cond_value
> type: | longword (unsigned)
> access: | write only
> mechanism: | by value

> A status code that your FILEIO routine returns to EDT$EDIT. The fileio argument is a longword containing the status code. The only failure code that is normally returned is RMS$_EOF from a GET call. All other OpenVMS RMS errors are signaled, not returned. The RMS signal should include the file name and both longwords of the RMS status. Any errors detected with the FILEIO routine can be indicated by setting status to an error code. That special error code will be returned to the program by the EDT$EDIT routine. There is a special status value EDT$_NONSTDFIL for nonstandard file opening.

> Condition values are returned in R0.

### Arguments

> #### code

> OpenVMS usage: | longword_unsigned
> type: | longword (unsigned)
> access: | read only
> mechanism: | by reference

> A code from EDT that specifies what function the FILEIO routine is to perform. The code argument is the address of a longword integer containing this code. Following are the valid function codes:

> Function Code | Description
> --- | ---
> EDT$K_OPEN_INPUT | The record argument names a file to be opened for input. The rhb argument is the default file name.
> EDT$K_OPEN_OUTPUT_SEQ | The record argument names a file to be opened for output as a sequenced file. The rhb argument is the default file name.
> EDT$K_OPEN_OUTPUT_NOSEQ | The record argument names a file to be opened for output. The rhb argument is the default file name.
> EDT$K_OPEN_IN_OUT | The record argument names a file to be opened for both input and output. The rhb argument is the default file name.
> EDT$K_GET | The record argument is to be filled with data from the next record of the file. If the file has record prefixes, rhb is filled with the record prefix. If the file has no record prefixes, rhb is not written. When you attempt to read past the end of file, status is set to RMS$_EOF.
> EDT$K_PUT | The data in the record argument is to be written to the file as its next record. If the file has record prefixes, the record prefix is taken from the rhb argument. For a file opened for both input and output, EDT$K_PUT is valid only at the end of the file, indicating that the record is to be appended to the file.
> EDT$K_CLOSE_DEL | The file is to be closed and then deleted. The record and rhb arguments are not used in the call.
> EDT$K_CLOSE | The file is to be closed. The record and rhb arguments are not used in the call.

> #### stream

> OpenVMS usage: | longword_unsigned
> type: | longword (unsigned)
> access: | read only
> mechanism: | by reference

> A code from EDT that indicates which file is being used. The stream argument is the address of a longword integer containing the code. Following are the valid codes:

> Function Code | Description
> --- | ---
> EDT$K_COMMAND_FILE | The command file.
> EDT$K_INPUT_FILE | The primary input file.
> EDT$K_INCLUDE_FILE | The secondary input file. Such a file is opened in response to an INCLUDE command. It is closed when the INCLUDE command is complete and will be reused for subsequent INCLUDE commands.
> EDT$K_JOURNAL_FILE | The journal file. If bit 0 of the options is set, it is opened for both input and output and is read completely. Otherwise, it is opened for output only. After it is read or opened for output only, it is used for writing. On a successful termination of the editing session, the journal file is closed and deleted. EXIT/SAVE and QUIT/SAVE close the journal file without deleting it.
> EDT$K_OUTPUT_FILE | The primary output file. It is not opened until you enter the EXIT command.
> EDT$K_WRITE_FILE | The secondary output file. Such a file is opened in response to a WRITE or PRINT command. It is closed when the command is complete and will be reused for subsequent WRITE or PRINT commands.

> #### record

> OpenVMS usage: | char_string
> type: | character-coded text string
> access: | modify
> mechanism: | by descriptor

> Text record passed by descriptor from EDT to the user-supplied FILEIO routine; the code argument determines how the record argument is used. The record argument is the address of a descriptor pointing to this argument. When the code argument starts with EDT$K_OPEN, the record is a file name. When the code argument is EDT$K_GET, the record is a place to store the record that was read from the file. For code argument EDT$K_PUT, the record is a place to find the record to be written to the file. This argument is not used if the code argument starts with EDT$K_CLOSE.

> Note that for EDT$K_GET, EDT uses a dynamic or varying string descriptor; otherwise, EDT has no way of knowing the length of the record being read. EDT uses only string descriptors that can be handled by the Run-Time Library routine STR$COPY_DX.

> #### rhb

> OpenVMS usage: | char_string
> type: | character-coded text string
> access: | modify
> mechanism: | by descriptor

> Text record passed by descriptor from EDT to the user-supplied FILEIO routine; the code argument determines how the rhb argument is used. When the code argument starts with EDT$K_OPEN, the rhb argument is the default file name. When the code is EDT$K_GET and the file has record prefixes, the prefixes are put in this argument. When the code is EDT$K_PUT and the file has record prefixes, the prefixes are taken from this argument. Like the record argument, EDT uses a dynamic or varying string descriptor for EDT$K_GET and uses only string descriptors that can be handled by the Run-Time Library routine STR$COPY_DX.

### Description

> If you do not need to intercept any file I/O, you can use the entry point EDT$FILEIO for this argument or you can omit it. If you need to intercept only some file I/O, call the EDT$FILEIO routine for the other cases.

> When you use EDT$FILEIO as a value for the fileio argument, files are opened as follows:

> - The record argument is always the RMS file name.
> - The rhb argument is always the RMS default file name.
> - There is no related name for the input file.
> - The related name for the output file is the input file with OFP (output file parse). EDT passes the input file name, the output file name, or the name from the EXIT command in the record argument.
> - The related name for the journal file is the input file name with the OFP RMS bit set.
> - The related name for the INCLUDE file is the input file name with the OFP set. This is unusual because the file is being opened for input.

> EDT contains support for VFC files. Normally, EDT will zero the length of the RHB field if the file is not a VFC file. However, when the user supplies the FILEIO routines, they are responsible for performing this operation.

> EDT checks for a VFC file with the following algorithm:

>     IF FAB$B_RFM = FAB$C_VFC
>     AND FAB$B_RAT <> FAB$M_PRN
>     THEN
>             VFC file
>     ELSE
>             not VFC file, zero out RHB descriptor length field.

### Condition Values Returned

> SS$_NORMAL | Normal successful completion.
> EDT$_NONSTDFIL | File is not in standard text format.
> RMS$_EOF | End of file on a GET.

## WORKIO

> The user-supplied WORKIO routine is called by EDT when it needs temporary storage for the file being edited. Call it by specifying it as an argument in the EDT$EDIT routine. It cannot be called independently.

### Format

> WORKIO code ,recordno ,record

### RETURNS

> OpenVMS usage: | cond_value
> type: | longword (unsigned)
> access: | write only
> mechanism: | by immediate value

> Longword value returned as a status code. It is generally a success code, because all OpenVMS RMS errors should be signaled. The signal should include the file name and both longwords of the RMS status. Any errors detected within work I/O can be indicated by setting status to an error code, which will be returned by the EDT$EDIT routine.

> The condition value is returned in R0.

### Arguments

> #### code

> OpenVMS usage: | longword_unsigned
> type: | longword (unsigned)
> access: | read only
> mechanism: | by reference

> A code from EDT that specifies the operation to be performed. The code argument is the address of a longword integer containing this argument. The valid function codes are as follows:

> Function Code | Description
> --- | ---
> EDT$K_OPEN_IN_OUT | Open the work file for both input and output. Neither the record nor recordno argument is used.
> EDT$K_GET | Read a record. The recordno argument is the number of the record to be read. The record argument gives the location where the record is to be stored.
> EDT$K_PUT | Write a record. The recordno argument is the number of the record to be written. The record argument tells the location of the record to be written.
> EDT$K_CLOSE_DEL | Close the work file. After a successful close, the file is deleted. Neither the record nor recordno argument is used.

> #### recordno

> OpenVMS usage: | longword_signed
> type: | longword integer (signed)
> access: | read only
> mechanism: | by reference

> Number of the record to be read or written. The recordno argument is the address of a longword integer containing this argument. EDT always writes a record before reading that record. This argument is not used for open or close calls.

> #### record

> OpenVMS usage: | char_string
> type: | character string
> access: | modify
> mechanism: | by descriptor

> Location of the record to be read or written. This argument always refers to a 512-byte string during GET and PUT calls. This argument is not used for open or close calls.

### Description

> Work file records are addressed only by number and are always 512 bytes long. If you do not need to intercept work file I/O, you can use the entry point EDT$WORKIO for this argument or you can omit it.

### Condition Value Returned

> SS$_NORMAL | Normal successful completion.

## XLATE

> The user-supplied XLATE routine is called by EDT when it encounters the nokeypad command XLATE. You cause it to be called by specifying it as an argument in the EDT$EDIT routine. It cannot be called independently.

### Format

> XLATE string

### RETURNS

> OpenVMS usage: | cond_value
> type: | longword (unsigned)
> access: | write only
> mechanism: | by value

> Longword value returned as a status code. It is generally a success code. If the XLATE routine cannot process the passed string for some reason, it sets status to an error code. Returning an error code from the XLATE routine aborts the current key execution and displays the appropriate error message.

> The condition value is returned in R0.

### Argument

> #### string

> OpenVMS usage: | char_string
> type: | character-coded text string
> access: | modify
> mechanism: | by descriptor

> Text string passed to the nokeypad command XLATE. You can use the nokeypad command XLATE by defining a key to include the following command in its definition:

>     XLATEtext^Z

> The text is passed by the string argument. The string argument can be handled by the Run-Time Library routine STR$COPY_DX.

> This argument is also a text string returned to EDT. The string is made up of nokeypad commands that EDT is to execute.

### Description

> The nokeypad command XLATE allows you to gain control of the EDT session. (See the OpenVMS EDT Reference Manual1 for more information about the XLATE command.) If you do not need to gain control of EDT during the editing session, you can use the entry point EDT$XLATE for this argument or you can omit it.

### Condition Value Returned

> SS$_NORMAL | Normal successful completion.

Note ##### 1 This manual has been archived but is available on the OpenVMS Documentation CD-ROM.

## Chapter 10
File Definition Language (FDL) Routines

This chapter describes the File Definition Language (FDL) routines. These routines perform many of the functions of the File Definition Language that define file characteristics. Typically, you use FDL to perform the following operations:

- Specify file characteristics otherwise unavailable from your language.
- Examine or modify the file characteristics of an existing data file to improve program or system interaction with that file.

## 10.1 Introduction to FDL Routines

You specify FDL attributes for a data file when you use FDL to create the data file, set the desired file characteristics, and close the file. You can then use the appropriate language statement to reopen the file. Because the data file is closed between the time the FDL attributes are set and the time your program accesses the file, you cannot use FDL to specify run-time attributes (attributes that are ignored or deleted when the associated data file is closed).

The FDL$CREATE routine is the one most likely to be called from a high-level language. It creates a file from an FDL specification and then closes the file. The following Compaq Fortran program segment creates an empty data file named INCOME93.DAT using the file characteristics specified by the FDL file INCOME.FDL. The STATEMENT variable contains the number of the last FDL statement processed by FDL$CREATE; this argument is useful for debugging an FDL file.

    INTEGER STATEMENT
    INTEGER STATUS,
    2       FDL$CREATE

    STATUS = FDL$CREATE ('INCOME.FDL',
    2                    'INCOME93.DAT',
    2                    ,,,,
    2                    STATEMENT,
    2                    ,,)
    IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS))
       .
       .
       .

The following three FDL routines provide a way to specify all the options OpenVMS RMS allows when it executes create, open, or connect operations. They also allow you to specify special processing options required for your applications.

- The FDL$GENERATE routine produces an FDL specification by interpreting a set of RMS control blocks in an existing data file. It then writes the FDL specification either to an FDL file or to a character string. If your programming language does not provide language statements that access RMS control blocks (for example, Compaq Fortran), you must use FDL$GENERATE from within the context of a user-open routine to generate an FDL file.
- The FDL$PARSE routine parses an FDL specification, allocates RMS control blocks, and fills in the relevant fields.
- The FDL$RELEASE routine deallocates the virtual memory used by the RMS control blocks created by FDL$PARSE.

These routines cannot be called from asynchronous system trap (AST) level. In addition, in order to function properly, these routines require ASTs to remain enabled.

An FDL specification can be in either a file or a character string. When specifying an FDL specification in a character string, use semicolons to delimit the statements of the FDL specification.

## 10.2 Using the FDL Routines: Examples

This section provides examples that demonstrate the use of the FDL routines in various programming scenarios.

- Example 10-1 shows how to use the FDL$CREATE routine in a Fortran program.
- Example 10-2 shows how to use the FDL$PARSE and FDL$RELEASE routines in a C program.
- Example 10-3 shows a Compaq Pascal program that uses the FDL$PARSE routine to fill in the RMS control blocks in a data file. The program then uses the FDL$GENERATE routine to create an FDL file using the information in the control blocks.

Example 10-1 Using FDL$CREATE in a Fortran Program

    *       This program calls the FDL$CREATE routine.  It
    *       creates an indexed output file named NEW_MASTER.DAT
    *       from the specifications in the FDL file named
    *       INDEXED.FDL.  You can also supply a default filename
    *       and a result name (that receives the name of the
    *       created file).  The program also returns all the
    *       statistics.
    *
            IMPLICIT        INTEGER*4       (A - Z)
            EXTERNAL        LIB$GET_LUN,    FDL$CREATE
            CHARACTER       IN_FILE*11      /'INDEXED.FDL'/,
            1               OUT_FILE*14     /'NEW_MASTER.DAT'/,
            1               DEF_FILE*11     /'DEFAULT.FDL'/,
            1               RES_FILE*50
            INTEGER*4       FIDBLK(3)       /0,0,0/
            I = 1
            STATUS = FDL$CREATE (IN_FILE,OUT_FILE,
                     DEF_FILE,RES_FILE,FIDBLK,,)
            IF (.NOT. STATUS) CALL LIB$STOP (%VAL(STATUS))

            STATUS=LIB$GET_LUN(LOG_UNIT)
            OPEN (UNIT=LOG_UNIT,FILE=RES_FILE,STATUS='OLD')
            CLOSE (UNIT=LOG_UNIT, STATUS='KEEP')

            WRITE (6,1000) (RES_FILE)
            WRITE (6,2000) (FIDBLK (I), I=1,3)

    1000    FORMAT  (1X,'The result filename is: ',A50)

    2000    FORMAT  (/1X,'FID-NUM: ',I5/,
            1         1X,'FID-SEQ: ',I5/,
            1         1X,'FID-RVN: ',I5)

            END

Example 10-2 shows how to use the FDL$PARSE and FDL$RELEASE routines in a C program.

Example 10-2 Using FDL$PARSE and FDL$RELEASE in a C Program

    /*  FDLEXAM.C
    **  This program calls the FDL utility routines FDL$PARSE and
    **  FDL$RELEASE.  First, FDL$PARSE parses the FDL specification
    **  PART.FDL.  Then the data file named in PART.FDL is accessed
    **  using the primary key.  Last, the control blocks allocated
    **  by FDL$PARSE are released by FDL$RELEASE.
    **  Note; to try this program use the following command on any
    **  file with textual data:  $ANALYZE/RMS/FDL/OUT=PART.FDL
    */

    #include <descrip>
    #include <rms>
    #define REC_SIZE 80     /* as appropriate for files used */

    FDLEXAM ()
    {

    struct FAB *fab_ptr;  /* variable to hold pointer to FAB structure */
    struct RAB *rab_ptr;  /* variable to hold pointer to RAB structure */
    $DESCRIPTOR (fdl_file, "PART.FDL");         /* free choice of name */
    char record_buffer[REC_SIZE+1];       /* allow for null terminator */
    int stat;

    /*
    ** Read and parse FDL file allocating and initializing RAB and
    ** and FAB accordingly, returning pointers to the FAB & RAB.
    */
    stat = FDL$PARSE ( &fdl_file, &fab_ptr, &rab_ptr );
    if (!(stat & 1)) LIB$STOP ( stat );

    /*
    ** Try to open file as described by information in the FAB.
    ** Signal open errors. Note the usage of STAT, instead of
    ** FAB_PTR->FAB$L_STS because just in case the FAB is invalid,
    ** the only status returned is STAT.
    */
    stat = SYS$OPEN ( fab_ptr );
    if (!(stat & 1)) LIB$STOP ( stat, fab_ptr->fab$l_stv );

    stat = SYS$CONNECT ( rab_ptr );
    if (!(stat & 1)) LIB$STOP ( stat, rab_ptr->rab$l_stv );

    /*
    ** Opened the file and connect some internal buffers.
    ** Fill in the record output buffer information which is the only
    ** missing information in the RAB that was created for us by FDL.
    ** Print a header recod and perform the initial $GET.
    */
    rab_ptr->rab$w_usz = REC_SIZE;
    rab_ptr->rab$l_ubf = record_buffer;
    printf ("------------------- start of records -------------- \n");
    stat = SYS$GET ( rab_ptr );
    while (stat & 1)      /* As long as the $GET is successful */
        {
        record_buffer[rab_ptr->rab$w_rsz] = 0;  /* Terminate for printf */
        printf ("%s\n", record_buffer);     /* Current record */
        stat = SYS$GET ( rab_ptr );      /* Try to get next one */
        }

    /*
    ** At this point in the execution, the status should be EOF indicating
    ** Successfully read the file to end. If not, signal real error.
    */
    if (stat != RMS$_EOF) LIB$STOP ( rab_ptr->rab$l_sts, rab_ptr->rab$l_stv );

    printf ("-------------------- end of records --------------- \n");
    stat = SYS$CLOSE ( fab_ptr );  /* implicit $DISCONNECT */
    if (!(stat & 1)) LIB$STOP ( fab_ptr->fab$l_sts, fab_ptr->fab$l_stv );

    /*
    ** Allow FDL to release the FAB and RAB structures and any other
    ** structures (XAB) that it allocated on behalf of the program.
    ** Return with its status as final status (success or failure).
    */
    return FDL$RELEASE ( &fab_ptr, &rab_ptr );
    }

Example 10-3 shows a Compaq Pascal program that uses the FDL$PARSE routine to fill in the RMS control blocks in a data file, and then uses the FDL$GENERATE routine to create an FDL file.

Example 10-3 Using FDL$PARSE and FDL$GENERATE in a Compaq Pascal Program

    [INHERIT ('SYS$LIBRARY:STARLET')]
    PROGRAM FDLexample (input,output,order_master);

    (* This program fills in its own FAB, RAB, and        *)
    (* XABs by calling FDL$PARSE and then generates       *)
    (* an FDL specification describing them.              *)
    (* It requires an existing input FDL file             *)
    (* (TESTING.FDL) for FDL$PARSE to parse.              *)
    TYPE
    (*+                                                   *)
    (* FDL CALL INTERFACE CONTROL FLAGS                   *)
    (*-                                                   *)
            $BIT1 = [BIT(1),UNSAFE] BOOLEAN;

            FDL2$TYPE = RECORD CASE INTEGER OF
            1: (FDL$_FDLDEF_BITS : [BYTE(1)] RECORD END;
                );
            2: (FDL$V_SIGNAL : [POS(0)] $BIT1;
                  (* Signal errors; don't return          *)
                FDL$V_FDL_STRING : [POS(1)] $BIT1;
                  (* Main FDL spec is a char string       *)
                FDL$V_DEFAULT_STRING : [POS(2)] $BIT1;
                  (* Default FDL spec is a char string    *)
                FDL$V_FULL_OUTPUT : [POS(3)] $BIT1;
                  (* Produce a complete FDL spec          *)
                FDL$V_$CALLBACK : [POS(4)] $BIT1;
                  (* Used by EDIT/FDL on input (DEC only) *)
                )
            END;

        mail_order =  RECORD
                      order_num : [KEY(0)] INTEGER;
                      name : PACKED ARRAY[1..20] OF CHAR;
                      address : PACKED ARRAY[1..20] OF CHAR;
                      city : PACKED ARRAY[1..19] OF CHAR;
                      state : PACKED ARRAY[1..2] OF CHAR;
                      zip_code : [KEY(1)] PACKED ARRAY[1..5]
                           OF CHAR;
                      item_num : [KEY(2)] INTEGER;
                      shipping : REAL;
                      END;

        order_file  = [UNSAFE] FILE OF mail_order;
        ptr_to_FAB  = ^FAB$TYPE;
        ptr_to_RAB  = ^RAB$TYPE;
        byte = 0..255;

    VAR
        order_master : order_file;
        flags        : FDL2$TYPE;
        order_rec    : mail_order;
        temp_FAB     : ptr_to_FAB;
        temp_RAB     : ptr_to_RAB;
        status       : integer;

    FUNCTION FDL$PARSE
        (%STDESCR FDL_FILE : PACKED ARRAY [L..U:INTEGER]
             OF CHAR;
        VAR FAB_PTR : PTR_TO_FAB;
        VAR RAB_PTR : PTR_TO_RAB) : INTEGER; EXTERN;

    FUNCTION FDL$GENERATE
        (%REF FLAGS : FDL2$TYPE;
        FAB_PTR : PTR_TO_FAB;
        RAB_PTR : PTR_TO_RAB;
        %STDESCR FDL_FILE_DST : PACKED ARRAY [L..U:INTEGER]
             OF CHAR) : INTEGER;
        EXTERN;

    BEGIN

        status := FDL$PARSE ('TESTING',TEMP_FAB,TEMP_RAB);
        flags::byte := 0;
        status := FDL$GENERATE (flags,
                                temp_FAB,
                                temp_RAB,
                                'SYS$OUTPUT:');

    END.

Previous | Next | Contents | Index

| privacy and legal statement |
4493PRO_017.HTML