Kednos PL/I for OpenVMS Systems
Reference Manual


Previous Contents Index

9.3.2.1 File Positioning Following a WRITE Statement

If the file has the UPDATE attribute, the current record is set to designate the record just written, and the next record is set to designate the record following the record just written. If there is no such record following the record just written, the next record is set to the end-of-file.

Examples


TRUNC: PROCEDURE; 
DECLARE INREC CHARACTER(80) VARYING, 
        OUTREC CHARACTER(80), 
        ENDED BIT(1) STATIC INIT('0'B), 
        (INFILE,OUTFILE) FILE; 
 
      OPEN FILE (INFILE) RECORD INPUT 
              TITLE('RECFILE.DAT'); 
      OPEN FILE (OUTFILE) RECORD OUTPUT 
              TITLE('TRUNCFILE.DAT') 
              ENVIRONMENT(FIXED_LENGTH_RECORDS, 
                          MAXIMUM_RECORD_SIZE(80)); 
 
      ON ENDFILE(INFILE) ENDED = '1'B; 
 
      READ FILE(INFILE) INTO (INREC); 
      DO WHILE (^ENDED); 
              OUTREC = INREC; 
              WRITE FILE (OUTFILE) FROM (OUTREC); 
              READ FILE (INFILE) INTO (INREC); 
              END; 
      CLOSE FILE(INFILE); 
      CLOSE FILE(OUTFILE); 
      RETURN; 
      END; 

This program reads a file with variable-length records into a character string with the VARYING attribute and creates a sequential output file in which each record has a fixed length of 80 characters.

The ENVIRONMENT attribute for the file OUTFILE specifies the record format and length of each fixed-length record.

When records are written to a file with fixed-length records, the variable specified in the FROM option must have the same length as the records in the target output file. Otherwise, the ERROR condition is signaled. Thus, in this example, each record read from the input file is copied into a fixed-length character-string variable for output.

Each time this program is executed, it creates a new version of the file TRUNCFILE.DAT.


ADD_EMPLOYEE: PROCEDURE; 
 
DECLARE 1 EMPLOYEE, 
          2 NAME, 
            3 LAST CHAR(30), 
            3 FIRST CHAR(20), 
            3 MIDDLE_INIT CHAR(1), 
          2 DEPARTMENT CHAR(4), 
          2 SALARY FIXED DECIMAL (6,2), 
      EMP_FILE FILE; 
 
DECLARE MORE_INPUT BIT(1) STATIC INIT('1'B), 
      NUMBER FIXED DECIMAL (5,0); 
 
      OPEN FILE(EMP_FILE) DIRECT UPDATE; 
 
      DO WHILE (MORE_INPUT); 
         PUT SKIP LIST('Employee Number'); 
         GET LIST (NUMBER); 
 
         PUT SKIP LIST 
          ('Name (Last, First, Middle Initial)'); 
         GET LIST 
          (EMPLOYEE.NAME.LAST,EMPLOYEE.NAME.FIRST, 
              EMPLOYEE.NAME.MIDDLE_INIT); 
 
         PUT SKIP LIST('Department'); 
         GET LIST (EMPLOYEE.DEPARTMENT); 
 
         PUT SKIP LIST('Starting salary'); 
         GET LIST(EMPLOYEE.SALARY); 
 
         WRITE FILE (EMP_FILE) 
             FROM (EMPLOYEE) KEYFROM(NUMBER); 
 
         PUT SKIP LIST('More?'); 
         GET LIST(MORE_INPUT); 
         END; 
      CLOSE FILE(EMP_FILE); 
      RETURN; 
      END; 

This procedure adds records to the existing relative file EMP_FILE. The file is organized by employee numbers, and each record occupies the relative record number in the file that corresponds to the employee number.

The file is opened with the DIRECT and UPDATE attributes, because records to be written will be chosen by key number. Within the DO-group, the program prompts for data for each new record that will be written to the file. After the data is input, the WRITE statement specifies the KEYFROM option to designate the relative record number. The number itself is not a part of the record but will be used to retrieve the record when the file is accessed for keyed input.

9.3.3 DELETE Statement

The DELETE statement deletes a record from a file. This record can be the current record, the record specified by the KEY option, or the record specified by the RECORD_ID option. The file must have the UPDATE attribute.

The format of the DELETE statement is:

DELETE FILE(file-reference) [KEY (expression)] [OPTIONS(option,...)]; 

FILE(file-reference)

A reference to the file from which the specified record is to be deleted. If the file is not currently opened, PL/I opens the file with the implied attributes RECORD and UPDATE; these attributes are merged with the attributes specified in the file's declaration.

KEY (expression)

An option specifying that the record to be deleted will be located by the key specified in the expression. The file must have the KEYED attribute.

The nature of the key depends on the file's organization, as follows:

OPTIONS(option,...)

An option giving one or more of the following DELETE statement options:
FAST_DELETE  
INDEX_NUMBER (expression)  
MATCH_GREATER  
MATCH_GREATER_EQUAL  
MATCH_NEXT  
MATCH_NEXT_EQUAL  
RECORD_ID (expression)  

Multiple options must be separated by commas.

All these options except INDEX_NUMBER remain in effect for the current statement only.

These options are described fully in the Kednos PL/I for OpenVMS Systems User Manual.

9.3.3.1 File Positioning Following a DELETE Statement

The next record is set to denote the record following the deleted record. The current record is undefined.

Examples

The program BAD_RECORD, below, deletes an erroneous record in an indexed sequential file containing data about states. The primary key in the file is the name of a state.


BAD_RECORD: PROCEDURE OPTIONS(MAIN); 
 
DECLARE STATE_FILE FILE KEYED UPDATE; 
      OPEN FILE(STATE_FILE) TITLE('STATEDATA.DAT') ENVIRONMENT(INDEXED); 
      DELETE FILE(STATE_FILE) KEY('Arklansas'); 
      CLOSE FILE(STATE_FILE); 
RETURN; 
END; 

The file is opened with the UPDATE attribute, and the OPEN statement gives the file specification of the file from which the record is to be deleted.

9.3.4 REWRITE Statement

The REWRITE statement replaces a record in a file. The record is either the current record or the record specified by the KEY option. The file must have the UPDATE attribute. The format of the REWRITE statement is:

FILE(file-reference)

The file that contains the record to be replaced. If the file is not open, it is opened with the implied attributes RECORD and UPDATE; these attributes are merged with the attributes specified in the file's declaration.

FROM (variable-reference)

An option giving the variable that contains the data needed to rewrite the record. The variable must be an addressable variable.

If the FROM option is not specified, there must be a currently allocated buffer from an immediately preceding READ statement that specifies the SET option, and this file must have the SEQUENTIAL attribute. In this case, the record is rewritten from the buffer containing the record that was read. Note that if the file organization is sequential, the record being rewritten must be the same length as the one read.

If the variable has the VARYING or the AREA attribute and the file does not have the attribute ENVIRONMENT(SCALARVARYING), the REWRITE statement writes only the current value of the varying string or area into the specified record. In all other cases, the REWRITE statement writes the variable's entire storage.

KEY (expression)

An option specifying that the record to be rewritten is to be located using the key specified by expression. The file must have the KEYED attribute. The expression must have a computational data type. The FROM option must be specified.

The nature of the key depends on the file's organization, as follows:

OPTIONS (option,...)

An option giving one or more of the following REWRITE statement options. Multiple options must be separated by commas.
FIXED_CONTROL_FROM (variable-reference)  
INDEX_NUMBER (expression)  
MATCH_GREATER  
MATCH_GREATER_EQUAL  
MATCH_NEXT  
MATCH_NEXT_EQUAL  
RECORD_ID (expression)  
RECORD_ID_TO (variable-reference)  

All these options except INDEX_NUMBER remain in effect for the current statement only.

These options are described fully in the Kednos PL/I for OpenVMS Systems User Manual.

9.3.4.1 File Positioning Following a REWRITE Statement

The next record position is set to denote the record immediately following the record that was rewritten or, if there is no following record, the end-of-file.

The current record is set to designate the record just rewritten.

Examples

The procedure NEW_SALARY, below, updates the salary field in a relative file containing employee records. The procedure receives two input parameters: the employee number and the new salary. The employee number is the key value for the records in the relative file.


NEW_SALARY: PROCEDURE (EMPLOYEE_NUMBER,PAY); 
 
DECLARE EMPLOYEE_NUMBER FIXED DECIMAL(5,0), 
     PAY FIXED DECIMAL (6,2); 
 
DECLARE 1 EMPLOYEE, 
          2 NAME, 
            3 LAST CHAR(30), 
            3 FIRST CHAR(20), 
            3 MIDDLE_INIT CHAR(1), 
         2 DEPARTMENT CHAR(4), 
         2 SALARY FIXED DECIMAL (6,2), 
    EMP_FILE FILE; 
 
    OPEN FILE(EMP_FILE) DIRECT UPDATE; 
    READ FILE(EMP_FILE) INTO(EMPLOYEE) 
         KEY (EMPLOYEE_NUMBER); 
    EMPLOYEE.SALARY = PAY; 
    REWRITE FILE(EMP_FILE) FROM(EMPLOYEE) 
         KEY(EMPLOYEE_NUMBER); 
    CLOSE FILE(EMP_FILE); 
    RETURN; 
    END; 

In this example, the KEY option is specified in the READ statement that obtains the record of interest and in the REWRITE statement that replaces the record, with its new information, in the file. The FROM and KEY options must both be specified on the REWRITE statement.

The sample program CHANGE_HEADER, below, changes the contents of the first record in the sequentially organized file TITLE_PAGE. The file consists of 80-byte, fixed-length records.


CHANGE_HEADER: PROCEDURE OPTIONS(MAIN); 
 
DECLARE TITLE_PAGE FILE SEQUENTIAL UPDATE, 
        INREC CHARACTER(80) BASED(P), 
        P POINTER; 
 
     OPEN FILE(TITLE_PAGE); 
     READ FILE(TITLE_PAGE) SET(P); 
 
     INREC = 'Summary of Courses for Fall 1980'; 
     REWRITE FILE(TITLE_PAGE); 
     CLOSE FILE(TITLE_PAGE); 
     RETURN; 
END; 

In this example, the READ statement specifies the SET option. The input record is read into a buffer, INREC, that is a based character-string variable. The assignment statement modifies the buffer, and the REWRITE statement rewrites the record. Because the REWRITE statement does not specify a FROM option, PL/I uses the contents of the buffer to rewrite the current record in the file (that is, the record that was just read).

9.3.5 Position Information for a Record File

When a record file is open, PL/I maintains the following position information:

When a file is opened the current record is undefined and the next record designates the first record in the file or, if the file is empty, the end-of-file.

After a sequential read operation, the current record designates the record just read. The next record indicates the following record or, if there are no more records, the end-of-file.

After a keyed I/O statement, that is, an I/O statement that specifies the KEY or KEYFROM option, the current record and next record are set as described in the following chart. (X is the record specified by key and X+1 is the next record or, if there are no more records, the end-of-file.)
Statement Current Record Next Record
READ X X+1
WRITE X X+1
REWRITE X X+1
DELETE undefined X+1


Chapter 10
Preprocessor

The PL/I preprocessor permits you to alter a source program at compile time. Preprocessor statements can be mixed with nonpreprocessor statements in the source program, but preprocessor statements are executed only at compile time. Any resulting source program changes are then used for further compilation.

The preprocessor is embedded in the compiler, and so is also called the embedded preprocessor.

During compilation, the preprocessor performs two types of preprocessing:

Preprocessor statements allow you to include text from alternative sources (INCLUDE libraries, directories, and the VAX Common Data Dictionary), control the course of compilation (%DO, %GOTO, %IF, and %PROCEDURE), issue user-generated diagnostic messages, and selectively control listings and formats. The preprocessor statements are summarized in Table 10-1.

This chapter describes the preprocessor statements and functions.

10.1 Preprocessor Compilation Control

At compile time, preprocessor variables, procedures, and variable expressions are evaluated in the order that they appear in the source text, and the new values are substituted in the source program in the same order. Thus, the course of compilation becomes conditional, and the resulting executable program can have a variety of features. Note that preprocessor variables must be declared and activated before replacement occurs.

For example:


 
EXAMPLE: PROCEDURE OPTIONS(MAIN); 
 
%DECLARE HOUR FIXED; 
%HOUR = SUBSTR(TIME(),1,2); 
 
%IF HOUR > 7 & HOUR < 18 
%THEN 
%FATAL 'Please compile this outside of prime time'; 
 
%DECLARE T CHARACTER; 
%ACTIVATE T NORESCAN; 
 
%T='''Compiled on '||DATE()||''''; 
 
DECLARE INIT_MESSAGE CHARACTER(60) VARYING INITIAL(T); 
 
%IF VARIANT() = '' | VARIANT() = 'NORMAL' 
%THEN 
  %INFORM 'NORMAL'; 
%ELSE %DO; 
  %IF VARIANT() = 'SPECIAL' 
    %THEN 
      %INFORM 'SPECIAL'; 
    %ELSE 
      %IF VARIANT() = 'NONE' 
      %THEN %; 
      %ELSE 
         %DO; 
         %T='''unknown variant '||variant()||''''; 
         %WARN t; 
         INIT_MESSAGE=INIT_MESSAGE||' with '||T; 
         %END; 
%END; 
 
PUT SKIP LIST (INIT_MESSAGE); 
 
END EXAMPLE; 
 

This example illustrates several aspects of the preprocessor. First, the programmer specified that this program must be compiled outside of prime time. Second, the VARIANT preprocessor built-in function is used to determine which variant was specified on the command line using the /VARIANT switch. Third, user-generated preprocessor messages remind the programmer which value was given to VARIANT.

Notice the number of apostrophes around the string constant assigned to T. Apostrophes are sufficient if the value of T is used only in a preprocessor user-generated diagnostic message; the value of T is concatenated with nonpreprocessor text and assigned to INIT_MESSAGE. During preprocessing, apostrophes are stripped off string constants. In order to ensure that the run-time program also has apostrophes around the string, additional apostrophes are needed.

10.2 Preprocessor Statements

All preprocessor statements are preceded by a percent sign (%) and terminated by a semicolon (;). All text that appears within these delimiters is considered part of the preprocessor statement and is executed at compile time. For example:


%DECLARE HOUR FIXED;   /* declaration of a preprocessor 
                                          single variable */ 
 
%DECLARE (A,B) CHARACTER; /* a factored preprocessor 
                                             declaration  */ 
 
%HOUR = SUBSTR(TIME(),1,2);  /* preprocessor assignment 
                               statement using two built-in 
                                               functions  */ 
 
%STATE: PROCEDURE (X) RETURNS (BIT); /* preprocessor 
                                                procedure */ 

Notice that a percent sign is required only at the beginning of the statement. The percent sign alerts the compiler that until the line is terminated with a semicolon, all subsequent text is preprocessor text. Therefore, no other percent signs are required on the line. However, when you include Common Data Dictionary record definitions, you may need to include the usual PL/I punctuation.

Labels (preceded by a percent sign) are permitted on preprocessor statements and required on preprocessor procedures. As with other labels, preprocessor labels are used as the target of program control statements.

A preprocessor label must be an unsubscripted label constant. The format for a preprocessor label is:

%label: preprocessor-statement; 

Table 10-1 summarizes the preprocessor statements. Each statement is then described in detail in an individual subsection.

Table 10-1 Summary of PL/I Preprocessor Statements
Statement Use
%Assignment Evaluates a preprocessor expression and gives its value to a preprocessor identifier
%; Null statement, specifies no preprocessor operation
%ACTIVATE Makes the value of declared preprocessor variables eligible for replacement
%DEACTIVATE Makes the value of declared preprocessor variables ineligible for replacement
%DECLARE Defines the preprocessor variable names and identifiers to be used in a PL/I program and specifies the data attributes associated with them
%DICTIONARY Specifies data definitions to be included from the VAX Common Data Dictionary (CDD)
%DO Denotes the beginning of a group of preprocessor statements to be executed as a unit
%END Denotes the end of a block or group of statements that started with a %PROCEDURE or a %DO statement
%ERROR Generates a user-defined error diagnostic message
%FATAL Generates a user-defined fatal diagnostic message
%GOTO Transfers control to a labeled preprocessor statement
%IF Tests a preprocessor expression and establishes action to be performed based on the results
%INCLUDE Copies the text of an external file into the source file at compile time
%INFORM Generates a user-defined informational diagnostic message
%[NO]LIST Same as %[NO]LIST_ALL
%[NO]LIST_ALL Does or does not include CDD records, INCLUDE files, machine code, and source statements in the listing from that point on
%[NO]LIST_DICTIONARY Does or does not include CDD records in the listing from that point on
%[NO]LIST_INCLUDE Does or does not include INCLUDE files in the listing from that point on
%[NO]LIST_MACHINE Does or does not include machine code in the listing from that point on
%[NO]LIST_SOURCE Does or does not include source code in the listing from that point on
%PAGE Provides listing pagination without form feeds in the source text
%PROCEDURE Begins a preprocessor procedure
%REPLACE Assigns a constant value to an identifier at compile time
%RETURN Returns a value from execution of a preprocessor procedure to the point of invocation
%SBTTL Allows specification of a listing subtitle line
%TITLE Allows specification of a listing title line
%WARN Generates a user-defined warning diagnostic message


Previous Next Contents Index