Kednos PL/I for UNIX

User's Manual for Digital UNIX

April 1996

This manual gives an overview of the PL/I language and an explanation
of PL/I program development. It describes the operation of the
Kednos PL/I for UNIX compiler and the features of the Digital UNIX
operating system environment that are important to the PL/I
programmer.

 

 

 

Operating System and Version: Digital UNIX Version 3.2 and
higher

Software Version: Kednos PL/I for UNIX
Version 1.3

 

Kednos Corporation
Pebble Beach, California
Second Printing (Update), April 1996

Kednos Systems, Inc., makes no representations that the use of its products in the manner described in this publication will not infringe on existing or future patent rights, nor do the descriptions contained in this publication imply the granting of licenses to make, use, or sell equipment or software in accordance with the description.

Possession, use, or copying of the software described in this publication is authorized only pursuant to a valid written license from Kednos or an authorized sublicensor.

No responsibility is assumed for the use or reliability of software on equipment that is not listed as supported in the Product Description.

Restricted Rights: Use, duplication or disclosure by the U.S. Government is subject to restrictions as set forth in subparagraph (c)(1)(ii) of the Rights in Technical Data and Computer Software clause at DFARS 252.227-7013.

© Kednos Corporation, 1995, 1996, All Rights Reserved.

Kednos Corporation, Kednos PL/I, and Kednos VPO are trademarks of Kednos Corporation.

Alpha AXP, AXP, CDD, DEC,DEC 4000, DECwindows, Digital, OpenVMS AXP, ULTRIX, VAX, OpenVMS, VT102, VT220, VT240, VT320, VT330, VT340, and the DIGITAL logo are trademarks of Digital Equipment Corporation.

SAA and IBM are trademarks of International Business Machine Inc.

Stratus is a trademark of Stratus Computer Inc.

Kednos PL/I for UNIX includes the GNU readline and assembler software. See See for the entire text of the Free Software Foundation's GNU Copyleft.

Portions Copyright 1984-1990 FairCom Corporation. All Rights Reserved.

Kednos requests your critical evaluation to assist in preparing future documentation. Please send any comments to comments@Kednos.com or by physical mail to:

Kednos Corporation
1051 Rodeo Road
Pebble Beach, CA  93953

Table of Contents

Preface ix

Intended Audience ix

Structure of This Manual ix

Where to Find More Information x

Conventions x

Chapter 1 --

Overview of Kednos PL/I for UNIX 1-1

Chapter 2 --

Developing a PL/I Program 2-1

Creating Source Files 2-1

Compiling and Linking a PL/I Program 2-1

The pl1 Command 2-1

Compilation with pl1 2-2

Compiling Multi-Language Programs 2-4

Driver Options 2-4

Linking Objects using the pl1 Command 2-8

Run-Time Libraries 2-8

Library Search Path 2-9

PL/I Preprocessor 2-10

Preprocessor Compilation Control 2-11

Preprocessor Procedures 2-12

Compiler Listing Files 2-14

Compiler Error Messages 2-18

Running a PL/I Program 2-20

Run-Time Errors 2-20

Passing Command Line Parameters to a PL/I Program 2-20

Accessing Command Line Parameters in PL/I Programs 2-20

Specifying Command Line Parameters 2-22

Chapter 3 --

Using the dbg Debugger 3-1

Overview 3-1

General Information 3-3

Terminology 3-3

Accessing Data 3-6

Accessible Data 3-6

Accessing Static Data 3-6

Accessing Automatic and Parameter Data 3-7

Accessing Based Data 3-7

Qualifying Structure References 3-7

Referring to Arrays and Structures 3-8

Preparing to Use the Debugger 3-8

Compiling for the dbg Debugger 3-8

Debugging Optimized Programs 3-9

Starting and Ending a Debugging Session 3-10

The dbg Command 3-10

Creating .dbginit Files 3-11

Ending the Debugging Session 3-11

Using the dbg Command Line Editing Features 3-11

Getting Started with Command Line Editing 3-12

The Initialization File, ~/.inputrc 3-13

The Sample Program 3-14

The Debugger Commands 3-16

Debugger Error Messages 3-18

ALIAS 3-19

AUDIT 3-21

BREAK 3-22

CLEAR BREAK 3-26

CONTINUE 3-28

DESCRIBE 3-29

DIRECTORY 3-31

DOWN 3-32

ENVIRONMENT 3-33

EXIT 3-35

HELP 3-36

INITIALIZE 3-37

LIST 3-39

PLAYBACK 3-42

PROMPT 3-43

RECORD 3-44

REGISTER 3-45

SET 3-46

SHELL 3-48

SHOW 3-49

SIGNAL 3-51

STEP 3-53

UP 3-55

WALKBACK 3-56

Chapter 4 --

The File System 4-1

File Control 4-1

Using the UNIX File System for I/O 4-2

PL/I Files and UNIX File Specifications 4-2

Using the TITLE Option 4-3

Using Environment Variables 4-4

Environment Variables in TITLE Values 4-4

Process Standard System File Names 4-5

Expanding File Specifications 4-6

Error Handling 4-7

Values Returned by PL/I Built-In Functions for Error Handling 4-8

Writing an Error Handler 4-8

Default Error Handling for the File System 4-9

Chapter 5 --

File Organizations and Input/Output 5-1

File Organizations 5-1

Access Modes for Record I/O 5-3

Sequential Access 5-3

Direct Access 5-4

Direct and Sequential Access 5-4

Access by Record Identification 5-4

Record Formats 5-5

Fixed-Length Records 5-5

IBM Dialect Fixed Length Environment Options 5-5

Variable-Length Records 5-6

IBM Dialect Variable Length Environment Options 5-6

Stream Files 5-6

Stream Files Organization 5-6

Creating a Stream File 5-7

Appending Records to an Existing File 5-8

Superseding an Existing File 5-8

Relative Files 5-8

Relative File Organization 5-8

Creating a Relative File 5-9

Using Relative Files 5-10

Populating a Relative File 5-11

Updating a Relative File 5-12

Reading a Relative File Sequentially 5-12

Error Handling 5-13

Chapter 6 --

Options of the ENVIRONMENT Attribute 6-1

Specifying and Using Environment Options 6-1

Arguments for Environment Options 6-1

Expressions 6-2

Variable References 6-3

Boolean Values 6-3

Interpretation of ENVIRONMENT Options for Existing Files 6-3

Conflicting and Invalid ENVIRONMENT Options 6-3

Summary of ENVIRONMENT Options 6-4

APPEND Option 6-11

BLKSIZE Option 6-11

CONSECUTIVE Option 6-12

DEFAULT_FILE_NAME Option 6-12

DELETE Option 6-13

F, FB, FS, or FSB Option 6-14

FILE_ID Option 6-14

FILE_ID_TO Option 6-15

FIXED_LENGTH_RECORDS Option 6-16

GROUP_PROTECTION Option 6-16

MAXIMUM_RECORD_SIZE Option 6-17

OWNER_PROTECTION Option 6-18

RECORD_ID_ACCESS Option 6-19

RECSIZE Option 6-19

SCALARVARYING Option 6-20

SHARED_READ Option 6-22

SUPERSEDE Option 6-22

TEMPORARY Option 6-23

V, VB, VS, or VSB Option 6-24

WORLD_PROTECTION Option 6-25

ENVIRONMENT Options for File Protection and File Sharing 6-26

File Protection 6-26

Defining File Protection 6-27

File Sharing 6-28

Chapter 7 --

Input/Output Statement Options 7-1

Option Format 7-1

Summary of Input/Output Statement Options 7-2

NO_ECHO Option 7-3

PROMPT Option 7-3

PURGE_TYPE_AHEAD Option 7-4

RECORD_ID Option 7-5

RECORD_ID_TO Option 7-6

Chapter 8 --

File-Handling Built-In Subroutines 8-1

FLUSH Built-In Subroutine (DEC Dialect Only) 8-1

REWIND Built-In Subroutine (DEC Dialect Only) 8-2

Chapter 9 --

General Information 9-1

How the Sort Program Interface Works 9-2

Determining Which Entry Point to Use 9-3

Calling the Sort Subroutines 9-4

General Format of the Sort Interface Call 9-4

Specifying the Sort Fields 9-5

Specifying Record Information 9-7

Specifying Storage 9-8

Using the Return Code 9-9

Specifying Input and Output Routines 9-10

Specifying a File Prefix 9-10

Specifying Message Level 9-10

Input and Output Routines 9-11

Using the PLIRETC Built-In Subroutine 9-11

Writing Input Routines 9-12

Writing Output Routines 9-14

Programming Examples 9-15

Calling the PLISRTA Entry Point 9-15

Calling the PLISRTD Entry Point 9-16

Chapter 10 --

Error Handling 10-1

RESIGNAL Built-In Subroutine 10-1

VAXCONDITION Condition 10-2

ON-Unit Actions 10-4

Handling the Condition 10-4

Resignaling the Condition 10-5

Executing a Nonlocal GOTO 10-6

Stopping the Program 10-8

Relationship of UNIX Signals to PL/I ON-Units 10-8

Accessing the Signal Values 10-10

Modifying the ONCODE Values 10-11

Search Path for ON-Units 10-13

Default Handling for Main Procedures 10-14

Default Handling for Non-Main Procedures 10-15

Multiple Conditions 10-17

Scope of ON-Units 10-20

ON-Unit Examples 10-20

Condition-Handling Built-In Functions 10-22

ONCODE Built-In Function 10-22

ONFILE Built-In Function 10-24

ONKEY Built-In Function 10-24

Chapter 11 --

Using PL/I in the Common Language Environment 11-1

The UNIX Procedure Calling and Condition Handling Standard 11-2

Parameter-Passing Mechanisms 11-2

Passing Parameters by Reference 11-3

Using the ANY Attribute 11-3

Dummy Arguments for Arguments Passed by Reference 11-4

Using Pointer Values for Arguments Passed by Reference 11-5

Passing Arrays to a FORTRAN Routine by Reference 11-5

Passing Parameters by Value 11-5

Dummy Arguments for Arguments Passed by Value 11-7

Special Parameter Attributes 11-7

OPTIONS(VARIABLE) Option 11-8

OPTIONAL Attribute 11-8

TRUNCATE Attribute 11-9

Calling Routines 11-9

Determining the Type of Call 11-10

Declaring an External Routine and Its Arguments 11-10

Calling the External Routine 11-10

Appendix A --

GNU Software Information A-1

GNU Copyleft A-1

Preamble A-1

TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION A-2

How to Apply These Terms to Your New Programs A-8

Figures

Figure 3-1. Specifying Environments 3-5

Figure 5-1. Relative File 5-9

Figure 10-1. Resignaling a Condition 10-6

Figure 10-2. Unwinding the Call Stack 10-7

Figure 10-3. Execution of an ON-Unit 10-14

Figure 10-4. Search for an ON-Unit 10-17

Figure 10-5. Effect of Multiple Conditions 10-18

Tables

Table P-1. Documentation Conventions Table xi

Table 2-1. Alphabetic List of PL/I Driver Options 2-4

Table 3-1. dbg Command Line Options 3-10

Table 3-2. Debugger Command Summary 3-17

Table 4-1. Default Process Stream Names 4-5

Table 4-2. System File Names for Get and Put Statements 4-5

Table 6-1. Description of Columns in Table 6-2 6-4

Table 6-2. Summary of DEC and ANSI Dialect ENVIRONMENT Options 6-5

Table 6-3. Summary of IBM Dialect ENVIRONMENT Options 6-6

Table 6-4. ENVIRONMENT Options That Are Ignored 6-7

Table 6-5. Default Record Sizes 6-18

Table 6-6. Default Record Sizes 6-20

Table 7-1. Summary of Input/Output Statement Options 7-2

Table 9-1. Entry Points for the Sort Program 9-3

Table 10-1. Corresponding Values 10-10

Table 10-2. ONCODE Values for PL/I ON Conditions 10-23

Table 11-1. Converted Data Types of Arguments Passed by Reference 11-4

Table 11-2. Assignment of Data Type to Dummy Arguments 11-7

Reader's Comments Card Back of Book
Figures

Figure 3-1. Specifying Environments 3-5

Figure 5-1. Relative File 5-9

Figure 10-1. Resignaling a Condition 10-6

Figure 10-2. Unwinding the Call Stack 10-7

Figure 10-3. Execution of an ON-Unit 10-14

Figure 10-4. Search for an ON-Unit 10-17

Figure 10-5. Effect of Multiple Conditions 10-18

Tables

Table P-1. Documentation Conventions Table xv

Table 2-1. Alphabetic List of PL/I Driver Options 2-4

Table 3-1. dbg Command Line Options 3-10

Table 3-2. Debugger Command Summary 3-17

Table 4-1. Default Process Stream Names 4-5

Table 4-2. System File Names for Get and Put Statements 4-5

Table 6-1. Description of Columns in Table 6-2 6-4

Table 6-2. Summary of DEC and ANSI Dialect ENVIRONMENT Options 6-5

Table 6-3. Summary of IBM Dialect ENVIRONMENT Options 6-6

Table 6-4. ENVIRONMENT Options That Are Ignored 6-7

Table 6-5. Default Record Sizes 6-18

Table 6-6. Default Record Sizes 6-20

Table 7-1. Summary of Input/Output Statement Options 7-2

Table 9-1. Entry Points for the Sort Program 9-3

Table 10-1. Corresponding Values 10-10

Table 10-2. ONCODE Values for PL/I ON Conditions 10-23

Table 11-1. Converted Data Types of Arguments Passed by Reference 11-4

Table 11-2. Assignment of Data Type to Dummy Arguments 11-7

Preface

This manual describes how to use theKednos PL/I for UNIX compiler on the Digital UNIX operating system, and contains detailed explanations of the extensions made to the standard PL/I language for this implementation. To aid in program development, it includes information on some UNIX commands and utilities. It also includes information to assist in writing PL/I programs that use features of the file system and the operating system.

Intended Audience

This manual is designed for programmers who have a working knowledge of PL/I and some familiarity with the Digital UNIX operating system and the C shell (csh).

Structure of This Manual

This manual is divided into the following sections:

  • See gives an overview of the Kednos PL/I for UNIX compiler.
  • See explains developing a PL/I program.
  • See explains debugging PL/I programs.
  • See describes the file system.
  • See explains record and stream input/output.
  • See summarizes ENVIRONMENT options.
  • See explains input/output statement options.
  • See explains file-handling built-in subroutines.
  • Chapter 9 describes the Sort program interface, valid for the ibm dialect.
  • See describes condition handling.
  • See explains using PL/I in the common language environment

See contains the Free Software Foundation's Copyleft.

Where to Find More Information

The Kednos PL/I for UNIX Reference Manual contains a complete definition of PL/I for RISC ULTRIX and the VAX PL/I languages, with detailed reference information on all standard PL/I language elements.

The Kednos PL/I for UNIX Installation Guide gives instructions on how to install the PL/I for RISC ULTRIX compiler.

The manpages contain information on PL/I built-in functions and pseudovariables. For an introduction to manpages, type the following:

man 3pl1 intro

 

The Digital UNIX documentation set gives complete information on the operating system.

Conventions

For the purposes of this manual, the term PL/I refers to Kednos PL/I for UNIX, which runs on the DEC OSF/1 and Digital UNIX systems.

All descriptions of the effects of executing statements and evaluating expressions assume that the initial procedure activation of the program is through an entry point with OPTIONS(MAIN).

It is further assumed that any non-PL/I procedures called by the program follow all conventions of the PL/I run-time environment.

 
. Documentation Conventions Table

Conventions

Meaning

 

This symbol represents a single stroke of the RETURN key on the keyboard.

 

This symbol represents a control key combination. The letter X can be bny keyboard character. To generate a control key combination, hold down the CTRL key while pressing the specified letter.

command

System text and code in examples and in text appears in the Courier typeface. Since the UNIX operating system differentiates between lowercase and uppercase characters, literal strings in examples and text must be entered exactly as shown.

bold

User input in interactive examples appears in the bold Courier typeface.

bold

Bold words in text indicate the first use of a new term.

italic

File and variable names appear in italics..

 

Vertical ellipses indicate that irrelevant parts of the program text or program output have been omitted..

quotation mark
apostrophe

The term quotation mark is used only to refer to the double quotation mark character ("). The term apostrophe is used to refer to the single quotation mark character (').

#

A # symbol is used in some contexts to indicate a single ASCII space character.)

pl1(1)

Specifies a manual page. For more information, type:
man section page

 

This margin icon indicates that the paragraph contains important information to which you should pay close attention.

SYNTAX

Syntax (format) diagrams appear in the Helvetica typeface.

. . .

Horizontal ellipses indicate that additional parameters, options, or values can optionally be entered. When a comma precedes an ellipsis, it indicates that successive items must be separated by commas. Used in syntax diagrams.

[ ]

Square brackets indicate that a syntactic element is optional and you need not specify it. Used in syntax diagrams

 

Brackets surrounding two or more stacked items indicate conflicting options, one of which can optionally be chosen. Used in syntax diagrams

 

Braces surrounding two or more stacked items indicate conflicting options, one of which must be chosen. Used in syntax diagrams

FILE (file-reference)

An uppercase word or phrase indicates a keyword that must be entered as shown; a lowercase word or phrase indicates an item for which a variable value must be supplied. This convention applies to syntax diagrams, not to code examples.

 

 

Overview of Kednos PL/I for UNIX

Kednos PL/I for UNIX is a comprehensive and powerful programming language useful for systems programming, scientific computation, and commercial data handling and data organization. It is a block-structured language that lends itself to the creation of efficient and maintainable structured programs. It has extensive string-handling capabilities.

Kednos PL/I for UNIX is Kednos's implementation, with extensions, of the American National Standard PL/I General-Purpose Subset, ANSI X3.74-1981. The General-Purpose Subset is a subset of full PL/I, ANSI X3.53-1976.

The General-Purpose Subset was designed for scientific, commercial, and systems programming on small and medium-size computer systems. The subset excludes features of PL/I that are prone to error, not often used, or that greatly increase the complexity of run-time support required by the compiler.

Over and above its conformity to the General-Purpose Subset,Kednos PL/I for UNIX offers many enhancements that extend the functionality of the subset. Some of these extensions are features of full PL/I, and some are features for compatibility with other PL/I implementations in the industry, especially VAX PL/I. Other extensions integrate Kednos PL/I for UNIX into the Digital UNIX common language environment and into a complete programming environment. Kednos PL/I for UNIX extensions are intended for programs that will execute exclusively under the control of the UNIX operating system.

The Kednos PL/I for UNIX extensions provide support for the UNIX Procedure Calling and Condition Handling Standard, allowing PL/I procedures to call procedures written in other languages. Another notable extension is the preprocessor, which allows for conditional compilation of programs and for compile-time source transformation; it enables users to write procedures that will be executed at compile time.

Kednos PL/I for UNIX can be used with a number of tools in a complete programming environment. For example, the compiler system provides a source level, interactive debugger called dbg. This enables you to debug programs as they execute. Use of the debugger is described in See of this manual.

TheKednos PL/I for UNIX language is fully described in the Kednos PL/I for UNIX Reference Manual. This reference manual contains further information on the General-Purpose Subset, the UNIX extensions, and the differences between Kednos PL/I for UNIX and other implementations of the PL/I language.

Kednos PL/I for UNIX is compatible with other versions of Kednos PL/I (Open VMS and RISC ULTRIX) with some exceptions. VMS specific options that are not compatible are emulated, flagged at compile-time, or ignored, depending on the VMS specific option. See the appendix on language differences in the Kednos PL/I for UNIX Reference Manual for more information.

 

Developing a PL/I Program

This chapter describes how to create, compile, link, and run a Kednos PL/I for UNIX program.

Creating Source Files

A PL/I source file is a UNIX file that contains PL/I code, as defined in the Kednos PL/I for UNIX Reference Manual.

To create a source file, use the text editor of your preference, such as the vi editor. You can also use any of the UNIX file management tools available on your system to generate source files. For example:

Compiling and Linking a PL/I Program

The following sections discuss the pl1 command and the command options.

The pl1 Command

A program called a driver invokes the major components of the compiler system. The components are:

The pl1 command runs the driver that compiles, optimizes, assembles, and link edits your programs. The command may be followed immediately by one or more options, by one or more filenames, or both.

Format
pl1 [option] ... filename.suffix [filename.suffix ...]
 
option

A driver option. Driver options specify instructions to all the processing phases. You can specify either the long or short version of the options, as shown in See . Alphabetic List of PL/I Driver Options .

filename.suffix

An input source file containing the program or module to be compiled. You must specify a file suffix. Valid suffixes are:

  • PL/I: .pli or .pl1
  • Object code: .o

You can include more than one file specification on the same command line by separating the file specifications with a space as follows:

pl1 file1.pl1 file2.pl1

 

Compilation with pl1

The driver command, pl1, invokes the following processing phases to compile and optionally link edit the source file:

  • PL/I compiler: The front-end processes the source file, producing an internal language called ucode. PL/I then converts the optimized ucode to assembly language.
  • Assembly: Converts the assembly-language code to an object file.
  • Link edit: Merges object files and libraries producing an executable binary.

By default, the pl1 command both compiles and link edits a source module. If you specify the -c driver option, processing stops after the assembler phase, producing a linkable object file. You can then use the pl1 or ld command to link edit the linkable object(s) into one executable binary. By default, the linkable object file has the same name as the source file, but with the suffix .o.

For example:

pl1 file.pli -c

 

This produces the linkable object file.o.

The default name of the executable binary is a.out. For example:

pl1 file.pl1

 

This command line produces the executable binary a.out.

You can specify a different name for the executable binary by using the driver option -o and supplying the desired file name. For example:

pl1 file.pl1 -o file

 

This command line compiles and link edits the source module file.pli and produces an executable binary, file.

If you have previously compiled the source module and used the -c option to produce the linkable object file.o, the following command line links edit the object module:

pl1 file.o -o file

 

This command link edits the object module file.o and produces the executable binary file. You can link edit several object modules together to produce a single executable binary, as follows:

pl1 file1.o file2.o -o file

 

This command link edits the object modules file1.o and file2.o and produces the executable binary file.

When specifying a name for your executable binary or object module, note that the full file name (file name and extension) must differ from the name of the source file(s). In other words, when compiling file.pli, do not supply file.pli as the full file name of your executable binary or object module.

Compiling Multi-Language Programs

When your application has two or more source programs written in different languages, including C, Pascal, and Fortran, compile each program module separately with the appropriate driver and then link them in a separate step. To create the linkable objects, use the pl1 command option -c. The following example compiles a PL/I program and a C program:

pl1 -c plifile.pli

cc -c cfile.c

 

When you compile the routines, the drivers produce the linkable object files plifile.o and cfile.o. Use the pl1 command to perform the link edit, which loads and initializes the appropriate run-time libraries for PL/I.

Driver Options

See . Alphabetic List of PL/I Driver Options lists the options for the pl1 command line. The UNIX manpage pl1(1) also describes the pl1 command options if the manual pages are installed on the system.

. Alphabetic List of PL/I Driver Options

Option

Long Option

Meaning

-a

--align

Specifies natural alignment. On Alpha processors, -a is equivalent to -a8

-an

--align=n

Aligns to the specified byte boundary. n must be a power of two. The default value is -a1, which causes the compiler to align so there are no pad bytes in structures.

Note: Some programs rely on structures not being padded for alignment.

-c

--compile_only

Suppresses the loading phase of the compilation. Produces an object file even when you compile only one program.

-D dialect

--dialect=dialect

Defines the dialect of the compiler, where dialect is one of the following: ibm, dec, ansi. The default dialect is ansi.

See the Kednos PL/I for UNIX Reference Manual for information on the differences in dialects.

-g

--debug

Produces debugger symbol table information. This option implies the -N option.

-Idir

--include_dir=dir

Defines an additional directory for the PL/I preprocessor to search when looking for %INCLUDE modules You can specify this option multiple times to define several directories.

-k

--check

Enables range and subscript checking. Turns on signalling of the STRINGRANGE and SUBSCRIPTRANGE conditions. Use this option to generate code to dynamically check the values of array, character, and bit string indexes.

See the Kednos PL/I for UNIX Reference Manual for more information on the STRINGRANGE and SUBSCRIPTRANGE conditions.

-lname

--library=name

When linking, search an object library named libname.a, where name is a string.

-L

--library_dir

Changes the algorithm of searching for libx.a or libx.b so the default directories are not searched. Use this option when you only want to search the directories specified by the ld(1) option -Ldir.

-Ldir

--library_dir=dir

Changes the algorithm of searching for libx.a or libx.b so that ld searches the specified directory before the default library directories.

-m lower 1

--case lower

Specifies that all identifiers are case insensitive and externals are converted to lower case. This is the default.

-m mix

--case mix

Specifies that all identifiers are case sensitive. Allows mixed case identifiers

-m upper

--case upper

Specifies that all identifiers are case insensitive and externals are converted to upper case.

-M lower

-M mix

-M upper

--include_case lower

--include_case mix

--include_case upper

Specifies the case of the include file names in a preprocessor %INCLUDE statement. The specified case is applied when the module name is built by the preprocessor. -M lower is the default, specifying that all file names are converted to lowercase. -M mix specifies case sensitivity, allowing mixed case file names. -M upper converts filenames to upper-case.

-N

--non_shared

Links the image without shared libraries. By default, images are linked with shared libraries. You must link without shared libraries to use the dbg debugger. Thus the -N option is implied by the -g option.

-o file

--output file

Generates an executable binary with the specified file name. If you do not use this option, the compiler names the executable binary a.out.

-O

--optimize

Performs all optimizations, including global register allocation.

Use this option to create ucode object files for all PL/I source files. The newly created ucode object files, ucode object files specified on the command line, the run-time start-up routine, and all the run-time libraries are ucode linked. The compiler optimizes the resulting ucode linked file, then links it as usual, producing an executable binary. The ucode linking does not produce an .o file.

 

Restrictions: The -c option cannot be specified with the -O option. The -O option must precede all source file arguments.

-p
or
-p1

--profile
or
--profile=1

Generate information for profiling.

Use this option to prepare for profiling by periodically sampling the program counter value. The option affects run-time loading. When loading occurs, the standard run-time start-up is replaced by the profiling run-time start-up routine. The level 1 profiling library libprof1.a is searched.

-p0

--profile=0

Do not generate information for profiling. This is the default.

-P
or
-P1

--preprocessor
or
--preprocessor=1

Turns on the preprocessor phase of compilation. This is the default for the -D dec dialect.

See the Kednos PL/I for UNIX Reference Manual for more information on the preprocessor.

-P0

--preprocessor=0

Turns off the preprocessor phase of compilation. This is the default for the -D ibm and -D ansi dialects.

-s

--list

Generates a compiler listing file with corresponding filename and a suffix of .l. The listing file includes source program lines with all the included files expanded, and a datamap of the program.

-T variant

--variant variant

Defines the compilation variant used by the VARIANT preprocessor built-in function. Ignored if you compile without using the preprocessor.

See the Kednos PL/I for UNIX Reference Manual for more information.

-u suffixname

--suffix suffixname

Defines the file suffix for include files. Supplied for compatibility with Digital and valid for the -D dec dialect only.

-v

--verbose

Displays the compiler passes, with their arguments, input, and output files, as they execute. Also displays resource usage in the C shell time format.

-w

--nowarn

Suppresses compiler warning messages.

-x

--xref

Includes cross reference information in the listing file. Implies -s; you need not use -s if you use -x.

Linking Objects using the pl1 Command

Use the pl1 command to link edit separate objects into one executable binary when the main program is written in PL/I. The driver recognizes the .o suffix as the name of a file containing object code suitable for link editing and immediately invokes the link editor. For example:

pl1 -o file mainfile1.o file2.o

 

Write the main program in PL/I and use the pl1 command to link edit the program to insure correct initialization of the PL/I run-time library. This statement produces the executable binary file.

The pl1 command implicitly calls the ld link editor (unless you specify the -c compile-only option). The link editor combines object modules to produce an executable binary. These object modules include:

A pl1 command where all the parameters are object files does only a link edit. For example, such a command might appear in a file for make(1) that specifies a build procedure. This file separates the compile operations from the link edit so that make can omit operations on source files that have not been modified.

If possible, use the pl1 command instead of ld to link edit PL/I object files. This automatically selects the correct run-time libraries and the correct version of ld. However, if you need to specify options to ld, you must invoke ld directly. Refer to the manpage on ld(1) for more information on specifying ld options, including specifying the run-time libraries.

Run-Time Libraries

The object code for the PL/I built-in routines is in an archive library. The distinctive suffix .a identifies a file as an archive library. The link editor gets your program code from your object file or files, and then gets the built-in routine code from object libraries called run-time libraries. It merges them and resolves references.

Kednos PL/I for UNIX includes the following run-time libraries:

  • libpli.a

The default run-time library for the pl1 command. It contains support for all PL/I language features except indexed file support (files declared or opened using the ENVIRONMENT(INDEXED) option). Programs using indexed files that are linked to this library generate fatal run-time errors.

  • libplit.a

Contains the same features as libpli.a with the addition of indexed file support (see libpli.a). Because the library increases the size of executable binaries, slows the link editing process, and requires additional memory during execution, use it only when indexed file support is required.

  • Indexed file support is an add-on option to Kednos PL/I for UNIX.
  • libpliisam.a

Contains additional support functions required by libplit.a.

To specify other libraries when invoking the link editor, use the -l option. Library names start with lib and have extensions .so (shared object), .a (archive) or .b (ucode). For example, if you have written a PL/I program that calls routines from the run-time library libx11.a, then specify:

pl1 . . . -lx11

 

Library Search Path

The link editor (ld) searches for any libraries you specify using the default search path listed in the manpage for ld. However, the system administrator or installer determines the actual location of the PL/I run-time libraries, so you might need to add directories to the default search path.

The -L option to the link editor, when followed by a directory name, adds the specified directory to the search path for run-time libraries. Do not type any separators between -L and the name of the directory. You can use this option several times; the link editor searches the directories in the order that you specify on the command line. Your definition of the search path must precede your specification of libraries (using the -l option described in See Run-Time Libraries ) on the command line.

The link editor searches the directories you specify with -L, in the order you specify them on the command line, before it searches the standard directories (which were specified during installation). This lets you specify files that supersede the usual run-time library.

If you use the -L option and do not follow it with a directory name, the link editor does not search its standard directories.

When you use the -L option, the link editor uses the following search path:

1st directory specified by -L
  1. 2nd directory specified by -L
  2. Last directory specified by -L
  3. The default search directories, as listed in the manpage for ld on your system, unless you specified the -L option without a path

PL/I Preprocessor

The PL/I preprocessor lets you change a source program at compile time. You can mix preprocessor statements with nonpreprocessor statements in the source program, but the preprocessor statements only execute at compile time. The resulting source program is then used for further compilation.

The preprocessor does two types of preprocessing:

Preprocessor statements let you include text from other sources (%INCLUDE statements), control the course of compilation (%DO, %GOTO, %VARIANT, %PROCEDURE, and %IF), issue user-generated diagnostic messages, and selectively control listings and formats. The preprocessor statements are described in full in the Kednos PL/I for UNIX Reference Manual.

Preprocessor Compilation Control

At compile time, preprocessor variables, procedures, and variable expressions are evaluated in the order in which 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 binary may exhibit a variety of unique features. Note that preprocessor variables and procedures must be declared and activated before replacement occurs.

For example:

%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);

This example illustrates several aspects of the preprocessor. First, you must compile this program outside of prime time. Second, depending upon the value of VARIANT, the program is compiled with a different variant.

Notice the number of single quote marks around the string constant assigned to T. Single quotes are sufficient if you only use the value of T in a preprocessor user-generated diagnostic message. That is, the value of T is concatenated with nonpreprocessor text and assigned to INIT_MESSAGE because during preprocessing, single quotes are stripped off of string constants. To ensure that the run-time program also has quotes around the string, you must supply additional quotes, as shown.

Preprocessor Procedures

The %PROCEDURE statement defines the beginning of a preprocessor procedure block and specifies the parameters, if any, of the procedure. A preprocessor procedure executes only at compile time. Invocation is similar to a function reference and occurs in two ways:

  • Preprocessor statements can invoke preprocessor procedures. In addition, preprocessor statements from within preprocessor procedures can invoke other preprocessor procedures.
  • Statements from the source program can invoke preprocessor procedures.

A preprocessor procedure is invoked by the appearance of its entry name and list of arguments. If the reference occurs in a nonpreprocessor statement, the entry name must be active before the preprocessor procedure is invoked. If the entry name is activated with the RESCAN option, the value of the preprocessor procedure is rescanned for further possible preprocessor variable replacement and procedure invocation. Preprocessor procedures can be invoked recursively.

Since the preprocessor procedure is always invoked as a function, the %PROCEDURE statement must also specify (using the RETURNS option) the data type attributes of the value that is returned to the point of invocation.

The return value replaces the preprocessor procedure reference in the invoking source code. Preprocessor procedures cannot return values using their parameter list. The return value must be capable of being converted to one of the data types CHARACTER, FIXED, or BIT. The maximum precision of the value returned by the %RETURNS statement is BIT(31), CHARACTER(32500), and FIXED(10).

You can use either of the following two types of argument lists in preprocessor procedures:

  • Positional argument lists end with a right parenthesis. They use parameters sequentially, as in a parenthesized list. Positional argument lists can be used in any preprocessor procedure.
  • Keyword argument lists end with a semicolon. They use parameters in any order, as long as each keyword matches the name of a parameter. Therefore, the order in which you list them does not affect the correct matching of parameters and arguments. You can only use keyword argument lists when the preprocessor procedure contains the STATEMENT option and is invoked from a nonpreprocessor statement.

Since a keyword argument list ends with a semicolon rather than a right parenthesis, the STATEMENT option lets you use a preprocessor procedure that has a keyword argument list as if it were a statement. Consequently, preprocessor procedures using the STATEMENT option let you extend the PL/I language by simulating otherwise unavailable features.

Preprocessor Statements and Procedures

All preprocessor statements are preceded by a percent sign (%) and are 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 */

 

Notice that a percent sign (%) is required only at the beginning of the statement, and must be the first item, other than white space (spaces or tabs) on the line. Preprocessor built-in functions are contained within preprocessor statements and consequently do not require a percent sign.

You can label preprocessor statements. Like other PL/I labels, you can use labels on preprocessor statements as the targets of program control statements. A preprocessor label must be an unsubscripted label constant preceded by a percent sign. The format for a preprocessor label is:

%label: preprocessor-statement;

 

As with other preprocessor statements, the percent sign alerts the compiler that all text until the semicolon line terminator is preprocessor text. Therefore, you do not need to enter another percent sign on that line.

The compiler treats all statements within a preprocessor procedure as preprocessor statements. You must label preprocessor procedures to invoke them, and you must use a percent sign before the procedure label. However, statements within the procedure do not require leading percent signs.

For a table summarizing the preprocessor statements and for individual descriptions of the statements, see the Kednos PL/I for UNIX Reference Manual.

Preprocessor Built-In Functions

A number of PL/I preprocessor built-in functions are available for use at compile time. With few exceptions, they have the same effect as run-time PL/I built-in functions with the same name. For a table summarizing the preprocessor built-in functions and for individual descriptions of the functions, see the Kednos PL/I for UNIX Reference Manual.

Compiler Listing Files

If you specify either the -s or -x compiler option, the PL/I compiler produces a listing file. The listing file contains the following information:

The following example shows portions of a listing file:

source file: /lang/tmp/real_progAAAaagzEa.pl

compiled on: 950923 at: 17:24:54 by: ANSI/IBM PL/I, rev 1.04in: /local/home/louise/test

Listing File is in: /local/home/louise/test/

 

0-1 0 0 Test: procedure options (main); À

0-2 1 0

0-3 1 0 declare x character (8) initial ('foo'),

0-4 1 0 input_x character (8) initial ('');

0-5 1 0 declare y fixed bin (15) initial (42),

0-6 1 0 input_y fixed bin (15) initial (0);

0-7 1 0 declare valid bit(1) initial ('0'B);

0-8 1 0

0-9 1 0 put skip list ('What is the answer?: ');

0-10 1 0 get list (input_y);

0-11 1 0 put skip list ('Type the most common file name: ');

0-12 1 0 get list (input_x);

0-13 1 0

0-14 1 0 if (x = input_x) & (y = input_y)

0-15 1 0 then

0-16 1 0 valid=real_programmer();

0-17 1 0 else begin;

0-18 2 0 put skip list ('You''re not a real programmer!');

0-19 2 0 goto exit;

0-20 2 0 end;

0-21 1 0

0-22 1 0 real_programmer: procedure() returns(bit(1));

0-23 2 0

0-24 2 0 /* this exists to show another subroutine level */

0-25 * 2 0 /* in the listing file */

0-26 2 0

0-27 2 0 declare real_prog bit(1);

0-28 2 0

0-29 2 0 put skip list ('You''re a Real Programmer!!!');

0-30 2 0 real_prog = '1'B;

0-31 2 0

0-32 2 0 end; /* real_programmer */

0-33 1 0

0-34 1 0 exit:

0-35 1 0

0-36 1 0 end Test;

<FF>

 

***** EXTERNAL ENTRY POINTS ***** Ã

 

name class size loc attributes

 

TEST constant ENTRY EXTERNAL

 

procedure TEST on line 1

 

name class size loc attributes

EXIT constant LABEL

def ref set

34

19

 

INPUT_X automatic 8c 84 CHAR(8) UNALIGNED INITIAL

def ref set

4

12

14

 

INPUT_Y automatic 1 96 FIXED BIN(15,0) ALIGNED PRECISION INITIAL

def ref set

6

10

14

 

REAL_PROGRAMMER

constant ENTRY RETURNS INTERNAL

def ref set

22

16

 

SYSIN constant FILE EXTERNAL

def ref set

1

10

12

 

SYSPRINT constant FILE EXTERNAL

def ref set

1

9

11

18

29

 

VALID automatic 1b 112 BIT(1) UNALIGNED INITIAL

def ref set

7

16

X automatic 8c 92 CHAR(8) UNALIGNED INITIAL

def ref set

3

14

Y automatic 1 128 FIXED BIN(15,0) ALIGNED PRECISION INITIAL

def ref set

5

14

 

begin block on line 17

 

no declared names

 

procedure REAL_PROGRAMMER on line 22

 

name class size loc attributes

 

REAL_PROG automatic 1b 96 BIT(1) UNALIGNED

def ref set

27

30

 

***** ENTRY POINTS AND ARRAY OF LABELS *****

 

name class size loc attributes

 

TEST constant ENTRY EXTERNAL

REAL_PROGRAMMER

constant ENTRY RETURNS INTERNAL

def ref set

22

16

 

<FF>

 

*****ERROR 179 SEVERITY 1 on line 1 in file Õ /lang/tmp/real_progAAAaagzEa.pl.*****

The undeclared name "SYSIN" has been contextually declared

in this block. It will acquire default attributes.

 

*****ERROR 179 SEVERITY 1 on line 1 in file /lang/tmp/real_progAAAaagzEa.pl.*****

The undeclared name "SYSPRINT" has been contextually

declared in this block. It will acquire default attributes.

 

The following list describes the callouts in the preceding listing file example:

Header information -- contains information about the source file you compiled, such as when you compiled it, the compiler variant used (dec, ansi, ibm), and the directory specification of the listing file.

À The source program listing -- contains line numbers generated by the compiler, an optional asterisk (*) if the line is continued from a previous line, a level number, specifying the level of procedural nesting, a second level number, specifying the block level within a procedure, and the source text.

à Cross reference listing tables -- includes tables listing external entry points, then a block-by-block listing of each procedure or internal block in the program, describing each variable declared in the block.

Õ Compilation error messages -- the text of any error messages generated during compilation.

Compiler Error Messages

The PL/I compiler identifies syntax errors and violations of language rules in the source program. If the compiler locates any errors, it writes messages to standard output. If you enter the pl1 command interactively, the messages are displayed on your screen.

If the compiler creates a listing file it also writes these messages to the listing, as shown in the previous section.

When it appears on the screen, a message from the compiler has the following format:

*****ERROR nn SEVERITY s on line line-no in file filename.*****

message-text

 

The nn specifies the error number.

The s specifies the severity of the error. The following letters represent possible severities:

  • 4-- Fatal. The compiler stops executing, does not continue the compilation, and does not produce an object module. You must correct the error before you can compile the program.
  • 3-- Error. The compiler continues, but does not produce an object module. You must correct the error before you can successfully compile the program.
  • 2-- Warning. The compiler produces an object module. It attempts to correct the error in the statement, but you should verify that the compiler's action is acceptable. Otherwise, your program may produce unexpected results.

The compiler produces messages with warning severity if it encounters the following:

  • Syntax errors (such as a missing END statement) that the compiler attempts to fix.
  • Language elements (such as undeclared variables) that are not part of the PL/I General-Purpose subset but do belong to full PL/I.
  • Legal PL/I General-Purpose Subset usage (such as assignment of a bit-string value to a fixed-point binary variable) that nonetheless may represent a programming error or produce unexpected results.
  • 1 -- Informational. This message usually appears with other messages to inform you of specific actions taken by the compiler. Informational messages also indicate nonstandard constructs and items that are syntactically correct, but that may contain programming errors. No action is necessary on your part. You may, however, want to check that your code performs as expected, and possibly modify the specified line.

The filename indicates the file specification.

The line number n specifies the source file line number of the statement that caused the error. This is the line number assigned to a statement by the compiler. The error message also appears in the listing file (if listing is requested) with the listing line number.

The message-text is the message. In many cases, the message text consists of more than one line of output. The messages generally provide enough information for you to determine the cause of an error and correct it.

Running a PL/I Program

To run a PL/I program, enter the name of the executable binary produced by the pl1 command. If you did not use the -o option in the pl1 command, the default name of the executable binary is a.out. Enter a.out to run your PL/I program. If you used the -o option and specified a filename, enter the filename to run your program.

Run-Time Errors

If an error occurs at run-time, a message appears on the terminal. See See for a description of run-time error conditions and messages.

Passing Command Line Parameters to a PL/I Program

You can pass command line parameters to your PL/I program, and access the parameters in your program. The following sections show how to write your code to access command line parameters, and how to run a program and specify command line parameters.

Accessing Command Line Parameters in PL/I Programs

Kednos PL/I for UNIX provides two methods to access command line parameters:

Through procedure parameters in the main program.

In your main program, you can declare up to ten parameters to be passed from the command line when users run your program. You must declare these parameters CHARACTER VARYING, giving the actual length of the string as the maximum length.

For example:

PARAM: PROCEDURE (name,address,city,state,zip)

OPTIONS(MAIN);

DECLARE (name,address,city,state,zip) CHAR(100) VARYING;

 

Your program can access these parameters only if the parameters are actually passed upon program invocation. To check the number of specified parameters, reference the external variable ARGC (argument count), included in the global definitions file pl1std.in, as shown in the example below.

  1. Through array of pointers to parameters.

You can access the command line parameters using the global variable ARGV (argument pointer), a pointer to an array of pointers to the actual parameters passed to the program. Again you can reference only as many parameters as were actually passed on the command line.

Both ARGC and ARGV are included in the global declarations include file, plistd.in, supplied with Kednos PL/I for UNIX.

The following example shows both methods of accessing command line parameters:

%INCLUDE pl1std;

 

PARAM_TEST: PROCEDURE (name, address, city, state, zip)
OPTIONS(MAIN);

DECLARE (name, address, city, state, zip) CHARACTER(100)
VARYING;

DECLARE i FIXED BIN;

 

IF ARGC >= 1 THEN

PUT SKIP EDIT ('Name: ',Name) (a,a);

ELSE

PUT SKIP EDIT ('Name is missing') (a);

 

IF ARGC >= 2 THEN

PUT SKIP EDIT ('Address: ',Address) (a,a);

ELSE

PUT SKIP EDIT ('Address is missing') (a);

 

IF ARGC >= 3 THEN

PUT SKIP EDIT ('City: ',City) (a,a);

ELSE

PUT SKIP EDIT ('City is missing') (a);

 

IF ARGC >= 4 THEN

PUT SKIP EDIT ('State: ',State) (a,a);

ELSE

PUT SKIP EDIT ('State is missing') (a);

 

IF ARGC >= 5 THEN

PUT SKIP EDIT ('Zip: ',Zip) (a,a);

ELSE

PUT SKIP EDIT ('Zip is missing') (a);

 

DO I = 1 TO ARGC;

PUT SKIP EDIT ('Parameter ',i, 'is ',ARGS(i)->ARG_CV) (a,f(2),a,a);

END; /* of do loop */

 

END; /* of program */

 

Specifying Command Line Parameters

To specify command line parameters, type them after the command that runs your PL/I program. For example, if you compile the preceding example using the -o command line option, and call your program param_test, run it as follows:

% param_test "Jocelyn Wood" "92 Forest Path" "Groveland" "New Hampshire" "01110"

 

  • Command line format varies in different UNIX shells. If this format does not work, see the manual pages for your shell for the correct format.

 

Using the dbg Debugger

This chapter describes how to use the dbg debugger with Kednos PL/I for UNIX programs. This chapter provides the following information:

Overview

A debugger helps you locate the cause of run-time errors like incorrect output, an infinite loop, or premature termination of your program. The debugger lets you observe and manipulate program execution interactively so you can find the point where it stopped working correctly. Using a debugger helps you isolate errors in your code much more quickly than you otherwise could.

To use a debugger, you must compile and link your program successfully -- your program must not contain illegal constructs in the source code.

By issuing debugger commands at your terminal, you can do the following:

Once you have found the error in your program, you can edit your source code, fix the problem, and compile, link, and run the corrected version.

Dbg is a high level symbolic UNIX debugger. Using dbg, you can refer to program locations by the symbols (names) you used for those locations in your program -- the names of variables, routines, labels, and so on.

The dbg debugger is specific to Kednos PL/I for UNIX. If you wrote your program in more than one language, the debugger executes all of the code, letting you use dbg commands to debug the PL/I sections.

In addition to the program execution, code manipulation and display functionality, dbg includes the following features:

You can record the commands you issue during a debugging session and play the file back to execute the commands automatically.

You can use the audit command to write both your commands and their output to a file.

The help command displays brief information about dbg commands and related topics.

You can use the alias command to create personalized replacements for dbg commands.

General Information

The next sections contain information and definitions you should understand before using dbg.

Terminology

The following terminology is used throughout this chapter:

Dbg works within the scope of the particular procedure block that is currently executing. This scope is the working environment. When you refer to a symbol or locator (defined later in this section), dbg looks for it in the working environment, issuing an error message if it is not found.

The environment command, described later in this chapter, lets you change the working environment. This and other commands require an environment specifier as a parameter. The environment structure parallels the directory/file structure of UNIX systems, starting with a root environment, similar to the root directory.

You can specify an environment in either of the following two ways:

:[name[:name...]]

 

The first colon (:) stands for the imaginary block, the block generated by the compiler to contain all outermost symbols in your source compilation unit. The imaginary block is at lexical level 0.

Name stands for the name of a routine in your source code. The first named routine must exist at lexical level 1 and not be contained in any other block.

You can specify a list of routine names contained within the first named routine. Use a colon to separate names.

  • relative environment -- starts at the working environment and walks up or down the lexical structure. You can specify relative environments in several ways.

To refer to a procedure either immediately contained in your current environment or contained at a lower level (contained within a procedure that ultimately is contained by your current environment), use a name or list of names to navigate inward, as follows:

 

name[:name...]

 

To refer to a procedure immediately superior within the current module, use a caret (^). You can use multiple carets to navigate upward through your environment structure. Note that you cannot, at any time, navigate outward beyond the imaginary block for the compilation unit.

 

When you combine the caret symbol and block names in a relative environment specification, use a colon to separate names. Do not use the colon between a name and a caret.

See . Specifying Environments shows a typical program structure and the commands used to specify various environments in the program, starting at your current working environment.

 
. Specifying Environments
  • expression -- any of the following:
  • a user-defined symbol (variable or constant)
  • a numeric literal
  • a string constant
  • locator -- either a program label or a source file line number that identifies a statement
  • routine -- a PL/I procedure or function

Definitions for other terms appear in the text, with the term in bold type.

Many dbg commands contain data references. The following sections give general information on when you can access various types of data and how to qualify data references.

Accessing Data

Dbg can access most PL/I data. However, you must consider storage class when you try to access data. In addition to assuring the data has a storage class that dbg can access, you may need to change your environment so you are in the scope of the data -- the part of your program where the named data has meaning -- to access some classes of data.

The following sections list the kinds of data that dbg can access, and describe how to access data of various storage classes. See See ENVIRONMENT for information on changing your environment. See See BREAK , See CONTINUE , and See STEP for information on executing your program and stopping in a specific location.

Accessible Data

Dbg can access any valid PL/I data except implicitly based variables, data with dynamic sizes or extents (including arrays with dynamic bounds and strings with dynamic lengths), parameter data with * extents, controlled data, and defined data.

Accessing Static Data

PL/I allocates storage for static data when the program activates, and maintains the storage for the duration of the program.You can set and show static data any time during program execution, providing your environment is within the name scope of the data.

External static data has the largest and outermost name scope. You can access it from all environments contained in your program since its scope extends from definition to the end of the program.

Internal static data is recognized from the declaration to the end of the immediately enclosing block, including contained blocks. To set or show internal static data, make sure your environment is in the name scope of the data.

Note that names declared in a block supersede both previous declarations of that name in any containing blocks and any external definitions, for that block and any contained blocks.

Accessing Automatic and Parameter Data

Automatic and parameter data exists locally in a routine. PL/I allocates storage for automatic variables only when the block that declares it is activated. The storage is released upon block deactivation. Parameter data likewise is unavailable until you call the routine to which the data is passed.

Dbg can access automatic and parameter data if the following conditions are true:

  • You have executed the program to a point where the data is active.
  • Your current working environment is the routine where the automatic or parameter data exists or is a block contained by that routine. Unlike static data, you cannot simply set your environment from your current working environment to the environment containing the data item.
Accessing Based Data

Access to explicitly qualified based variables follows the same rules as automatic data, with the following addition:

  • You can only access based data after PL/I allocates storage or obtains a valid address for the data. This occurs during program execution, when PL/I obtains a valid pointer value.

See the Kednos PL/I for UNIX Reference Manual for more information on based variables.

Qualifying Structure References

To access a structure member, you must fully qualify it within the structure. For example, the following structure contains a customer name:

DECLARE 1 CUSTOMER_NAME,

2 FIRST_NAME CHARACTER(15),

2 MIDDLE_INIT CHARACTER(1),

2 LAST_NAME CHARACTER(15);

 

If you are in an environment where this structure is active, you can access members of the structure by qualifying them fully to dbg as, for example, CUSTOMER_NAME.MIDDLE_INIT. You cannot omit intermediate qualification names when specifying structures to dbg.

Referring to Arrays and Structures

When referring to arrays and structures in dbg, enclose the array bounds and structure numbers in square brackets rather than parentheses. Also, note that each member of the structure must be individually qualified. For example, the following structure contains an array of customer names:

DECLARE 1 CUSTOMER_NAME(50),

2 FIRST_NAME CHARACTER(15),

2 MIDDLE_INIT CHARACTER(1),

2 LAST_NAME CHARACTER(15);

 

Within dbg, use the following syntax to refer to the first FIRST_NAME in this array:

CUSTOMER_NAME[1].FIRST_NAME[1]

 

The following example shows invalid syntax. Do not use either of these:

CUSTOMER_NAME[1,1].FIRST_NAME

CUSTOMER_NAME.FIRST_NAME[1,1]

 

Preparing to Use the Debugger

The following sections contain information on steps you must complete before using the dbg debugger, and general information on using the debugger with certain types of programs.

Compiling for the dbg Debugger

Source-level debugging relates the run-time operation of your program to the source files. For this to happen, your executable program must contain information that relates the run-time actions to elements from the source file, such as variable identifiers.

When compiling and/or linking for the debugger, specify the -g flag, as shown in the following examples:

The following command compiles lottery.pli for the debugger:

% pl1 -g -c lottery.pli

 

This produces an object file, lottery.o, and a file containing the symbol table information used by the compiler during linking, lottery.st.o.

  1. The following command links lottery.o for the debugger:

% pl1 -g lottery.o -o lottery

 

This produces an executable file, lottery, and a file containing the symbol table information used by the debugger, lottery.st.

  1. The following command compiles and links lottery.pli for the debugger:

% pl1 -g lottery.pli -o lottery

 

This produces an executable file, lottery, and a file containing the symbol table information used by the debugger, lottery.st.

See See The pl1 Command and See Linking Objects using the pl1 Command for information on the commands used to compile and link PL/I code. See See Driver Options for more information on using options when generating an executable file.

Debugging Optimized Programs

You normally do not perform source-level debugging on optimized code. The optimizing phases discussed in See are intended only for debugged programs.

The optimizer often reorders portions of code to gain efficiency. When you run optimized code using the debugger and look at the values of various symbols, they might not be in the state you expect given your current breakpoint location.

Also, optimized code sometimes uses registers, instead of memory, to store values. Thus, the value you find in memory may not be current, and the debugger will not find the current value in the register.

If you must debug optimized code, use an assembly-level debugger such as dbx.

Starting and Ending a Debugging Session

This section describes what happens when you start and end a debugging session.

The dbg Command

The dbg command invokes the dbg debugger and does the following:

Dbg looks for .dbginit in your $home directory and, if found, plays back the dbg commands in it.
  1. Dbg looks for .dbginit in your current directory and, if found, plays back the dbg commands in it.
  2. Dbg displays a prompt.
Format

dbg [option [...]] [filename]

 
option

Command options specify instructions for processing. See . dbg Command Line Options lists the dbg command options.

. dbg Command Line Options

Option

Description

-s

Specifies the symbol table file. Defaults to <filename>.st.

-n

Disables execution of the initialization files

filename

Specifies the name of the executable file. If you do not specify a filename, dbg uses the default, a.out.

Examples
Debugging the default file, a.out, after compiling the sample program, lottery, without the -o option:

% dbg

DBG Rev 0.0 Copyright (C) Kednos Systems, Inc. 1995

a.out

 

(dbg)

  1. Debugging the program lottery, which was compiled using the -o lottery command line option:

% dbg lottery

DBG Rev 0.0 Copyright (C) Kednos Systems, Inc. 1995

:LOTTERY

(dbg)

 

Creating .dbginit Files

Dbg executes the dbg commands in your .dbginit file or files when you invoke the debugger. Using these files is optional; you do not need to create a .dbginit files.

Use the .dbginit file in your $home directory to automatically execute dbg commands that you use every time you enter the debugger. Use the .dbginit file in your current working directory (where your PL/I executable file resides) to automatically execute dbg commands specific to your program. For example, you can use the shell command in dbg to print your working directory or the audit command in dbg to open an audit file.

Use your preferred UNIX editor to create .dbginit files. You can also use the record dbg command, described later in this chapter, to create a file containing dbg commands, which you can then rename to .dbginit.

Note that the commands in the .dbginit files must be valid at the point when dbg runs the .dbginit file. See the command descriptions for information on when commands can be executed.

Ending the Debugging Session

Use the exit dbg command to end your debugging session. See for more information.

Using the dbg Command Line Editing Features

Dbg uses readline, a product of the Free Software Foundation, to read the dbg command lines. Readline lets you edit the command line as you enter it. By default, the line editing commands emulate an emacs-style interface.

The Kednos PL/I for UNIX kit includes the readline(3) manpage, containing full information on the readline commands. Once you have installed Kednos PL/I for UNIX, access the manpage as you would any other manpage, by typing man 3 readline.

Getting Started with Command Line Editing

You only need a few commands to get started using command line editing. The simplest are the left and right arrows, which let you move backward and forward by character. Readline maintains a history of the commands you entered, which you can access. Use your up and down arrow keys to move up and down through the history list.

Some of the most useful commands to start with are:

Once you become comfortable with these commands, you may want to learn how to use advanced commands, such as creating keyboard macros and transposing words. These commands are described in the readline(3) manpage.

The Initialization File, ~/.inputrc

You can customize readline by putting commands in an initialization file. Dbg uses the same initialization file as any other application that uses readline - the file specified by the INPUTRC variable, with a default of ~/ .inputrc. The following example shows a .inputrc file that contains a section for dbg that enables filename completion:

set horizontal-scroll-mode On

set mark-modified-lines On

set meta-flag On

# set output-meta On

$if Bash

 

$endif

$if Dbg

set expand-tilde On

$endif

 

Once you create a .inputrc file containing a section for dbg (beginning with the line $if Dbg), you can use the additional commands you have defined. In the preceding example, you can now invoke filename completion on your dbg command lines by typing a partial filename and then a tab, to complete the filename.

The Sample Program

The rest of this chapter describes each debugger command in detail, giving examples based on a PL/I program named lottery. The lottery program computes the number of possible combinations and permutations of n numbers that can be drawn from a field of m numbers.

The initial program listing is:

/*

/* Lottery is the example program for the dbg chapter

/* of the User Manual.

/* Compile lottery.pli using the -g compiler option.

*/

LOTTERY: PROCEDURE OPTIONS(MAIN);

 

DECLARE (M_VALUE, N_VALUE) FLOAT BIN(53);

DECLARE (C,P) FLOAT BIN(53);

 

ON CONVERSION BEGIN;

PUT LIST('INVALID NUMBER ENTERED, TRY AGAIN!') SKIP;

ONSOURCE() = '0000000000000';

END;

 

ON OVERFLOW BEGIN;

PUT SKIP LIST('Number is too big, sorry!');

STOP;

END;

 

FACTORIAL: PROCEDURE (N) RETURNS (FLOAT BIN (53));

DECLARE N FLOAT BIN (53);

 

IF (N < 0.01) THEN

RETURN (1);

RETURN (N * FACTORIAL(N-1));

 

END FACTORIAL;

 

PERMUTATIONS: PROCEDURE (M,N) RETURNS (FLOAT BIN (53));

 

DECLARE M FLOAT BIN (53);

DECLARE N FLOAT BIN (53);

DECLARE P FLOAT BIN (53);

 

P = FACTORIAL(M) / FACTORIAL(M-N);

RETURN (P);

 

END PERMUTATIONS;

 

COMBINATIONS: PROCEDURE (M,N) RETURNS (FLOAT BIN (53));

DECLARE M FLOAT BIN (53);

DECLARE N FLOAT BIN (53);

DECLARE P FLOAT BIN (53);

 

P = PERMUTATIONS(M,N) / FACTORIAL(N);

RETURN (P);

 

END COMBINATIONS;

 

/* Begin Main Program */

M_VALUE = 0.0;

N_VALUE = 0.0;

 

DO WHILE (M_VALUE <= 0.0);

PUT SKIP LIST ('Enter number of choices (>0): ');

GET EDIT (M_VALUE) (F(12));

M_VALUE = TRUNC(M_VALUE);

END;

DO WHILE(N_VALUE <= 0.0);

PUT SKIP LIST ('Enter number of selections (>0): ');

GET EDIT (N_VALUE) (F(12));

N_VALUE = TRUNC(N_VALUE);

END;

 

P = PERMUTATIONS(M_VALUE,N_VALUE);

C = COMBINATIONS(M_VALUE,N_VALUE);

 

OUTPUT: PUT EDIT ('If order counts, chance is 1 in ', P)

(A,E(12)) SKIP;

PUT EDIT ('Otherwise, chance is 1 in ', C)

(A,E(12)) SKIP;

END LOTTERY;

The Debugger Commands

You can issue debugger commands any time you see the debugger prompt (dbg). Type the command at the (dbg) prompt and press the RETURN key. To issue several commands on a line, separate the command strings with semicolons (;).

You can abbreviate debugger commands as long as the abbreviation specifies a unique command. You can type debugger commands and keywords in either upper- or lower-case. The commands clear, CLEAR, and Clear are equivalent, for example.

If you enter a carriage return at the dbg prompt, giving no other dbg command, dbg recalls your last dbg command line and reissues it.

A typical debugging session might consist of the following steps:

Invoking the debugger using the dbg command.
  1. Initializing the program.
  2. Setting breakpoints to stop program execution at various places in the code.
  3. Executing your PL/I program.
  4. Using various debugger commands to determine the location where the program fails.
  5. Exiting the debugger.

Additional commands let you record your entire session, record sequences of commands and play them back as a script, get help on the debugger commands, and access the Shell to execute Shell commands.

See . Debugger Command Summary shows all the debugger commands. The following sections give details on each of the dbg commands. Each section contains a short description of the command, references to related commands, restrictions if appropriate, a format diagram, descriptions of each element of the format, and examples. The commands are arranged alphabetically.

While in a dbg session, you can get brief help on the commands. See See HELP for more information.

. Debugger Command Summary

Command Name

Description

<cr> (blank line)

recalls and re-issues the last dbg command line you entered

alias

1. creates a replacement for a dbg command

2. displays a list of previously created aliases

audit

1. starts or stops recording the dbg session, including both user-input dbg commands and their output

2. displays whether or not the session is being recorded

break

sets and reports breakpoints

clear break

clears breakpoints

continue

starts or resumes program execution

describe

shows all attribute information (metadata) for the specified program symbol

directory

displays or adds search directories for the dbg list command

down

sets your dynamic frame down one or more levels

environment

sets the scope in which dbg evaluates break, clear, describe, list, set, and show commands

exit

ends the dbg debugger session

help

displays brief information about a dbg topic

initialize

initializes dbg

list

displays lines of source code

playback

executes recorded debugger commands from the specified playback file

prompt

changes the dbg prompt string

record

1. starts or stops recording interactive dbg commands to a playback file

2. displays whether or not commands are being recorded

register

shows all the registers

return

not implemented yet

set

assigns a value to a variable

shell

executes the specified shell command and returns to dbg

show

displays the contents of a variable

signal

starts or stops trapping signals before sending them to the program

step

executes the number of source lines specified

up

sets your dynamic frame up one or more levels

walkback

displays the call stack

Debugger Error Messages

See the on-line files, pl1dbgerr.ps and pl1dbgerr.txt, located in /usr/opt/PLI100/doc for more information about dbg errors.

ALIAS

Creates or lists aliases. An alias is a replacement name associated with an equivalence string. An equivalence string is a one-word dbg command or a quoted string containing a dbg command.

If you specify an existing replacement name, the new equivalence string replaces the existing equivalence string.

Aliases can recurse up to a maximum depth of 20 levels. See the examples section for an example of recursive alias definition.

Format

Omit all parameters to display a message listing all currently defined aliases.

replacement_name

Specifies the name to be replaced by the equivalence string. You can enclose the replacement name in quotation marks. It must be one word.

equivalence_string

A dbg command. You can enclose the equivalence string in quotation marks. Quotation marks are required if the equivalence string contains embedded white space.

Examples
Valid command formats.

The following legal commands all create an alias called "stop" which does exactly what the break command does. Each alias definition overwrites the existing alias definition.

(dbg) alias stop = break

(dbg) alias "stop" = break

note: Overwriting old alias.

(dbg) alias stop = "break"

note: Overwriting old alias.

(dbg) alias "stop" = "break"

note: Overwriting old alias.

(dbg) alias

stop = break

(dbg)

  1. Alias recursion.

Aliases can recurse up to a maximum depth of 20 levels. In the following example, the "halt" command replaces the "quit" command, the "stop" command replaces the "halt" command, and finally the "exit" command replaces the "stop" command, and dbg executes the "exit" command.

(dbg) alias stop = exit

(dbg) alias halt = stop

(dbg) alias quit = halt

(dbg) quit

Program terminated. Termination signal = 5

 

  1. Circuit detection.

Every time an alias translation occurs, dbg checks to see if there is a match.

(dbg) alias stop = exit

(dbg) alias halt = stop

(dbg) alias exit = halt

(dbg) exit

error: Circular alias detected.

 

You can still exit the debugger as follows:

(dbg) ex

Program terminated. Termination signal = 5

 

  • Dbg allows you to specify an alias that replaces one dbg command with another, for example, alias break = init. You can still use any un-aliased command abbreviation for the command you have used as a replacement name. For example, you can still specify "brea" for the break command.

AUDIT

Creates an audit file containing both user-input dbg commands and their output.

The audit command does not record program output. To record all input and output, making a transcript of the entire session, use the UNIX script(1) command. See the script(1) manpage for more information.

Format

Omit all parameters to display a message showing audit status and listing the filename if auditing is on.

on filename

Turns auditing on and writes to the specified file. If you were already writing to an audit file, this command closes the previous audit file.

off

Turns auditing off, closing the previously opened file.

Examples

(dbg) audit

 OFF

(dbg) audit on lottery.au

 ON lottery.au

 

(dbg) audit off

 OFF

 

The audit file, lottery.au, now contains the following lines:

** Audit file for program started on Fri Aug 18 18:25:03 1995 ON lottery.au

(dbg) list 13

13 PUT LIST('Invalid number entered, try again!') SKIP;

(dbg) audit

 ON lottery.au

(dbg) audit off

BREAK

Use the break command to set or display breakpoints. Breakpoints are locations in your program where you want execution to stop so you can use dbg commands to step through the code line by line, show or set values of variables, and so on.

When the program stops at a breakpoint, dbg does the following:

Reports that the breakpoint was triggered and displays the line number and environment where execution stopped.
  1. If you specified an action, dbg evaluates the string and executes the commands.
  2. If you specified a count and dbg has not encountered the breakpoint the specified number of times, execution resumes.
  3. Displays the (dbg) prompt.

You can then enter dbg commands at the prompt.

You can set multiple breakpoints. Use the break command to set each breakpoint. Dbg allows a maximum of 50 breakpoints.

If a single statement extends over more than one line, you can set a breakpoint only at the first line of the statement.

See See CLEAR BREAK for information on clearing breakpoints, and See CONTINUE for information on resuming execution from breakpoints.

Restrictions

You must initialize the program before you use the break command. See INITIALIZE

Format

break [absolute_env] [locator] [count = number] [action = "string"]

 

If you specify the break command without arguments, dbg displays a list of all the set breakpoints in the following format, displaying the actual environment, if it is not the current environment, and the locator of each breakpoint:

break set at [:environment:]locator

 

absolute_env

An absolute environment expression, as defined in See Terminology .

If you specify an absolute environment and do not specify a locator, dbg sets the breakpoint on the first executable line of code it encounters in the routine. If the routine contains no executable code, dbg displays a "line not found" message. If a breakpoint already exists on the first executable line, dbg displays a "breakpoint set" message. Otherwise dbg sets a breakpoint and displays a message containing the actual line number on which the break was set.

locator

An expression that resolves to the line number or label of a statement. If the statement is not executable, dbg searches forward in your code for an executable line. If no executable lines exist after the line you specified, dbg displays a "line not found" message. If an executable line is found that has a breakpoint already set, dbg displays a "breakpoint set" message. Otherwise, dbg sets a breakpoint on the executable line and displays a message containing the actual line number on which the break was set

count = number

Use the count parameter to specify that execution should stop only after dbg encounters the breakpoint a certain number of times.The specified number must be an integer or an expression that resolves to an integer. The default is 1.

Note that every time dbg hits the breakpoint after it reaches the number specified by "count", execution will stop. In other words, if you specify count=25, execution stops the 25th time dbg encounters the breakpoint and every time thereafter. If you want to stop after another 25 iterations, reissue the break command to reset the count.

action = "string"

Specifies one or more dbg commands. Dbg executes the commands when program execution stops at the breakpoint.

You must use double quotation marks around the specified string if it is more than one word long.

Examples

The numbers in these examples are keyed to the descriptions following the examples.

(dbg) break 20

Breakpoint set at :LOTTERY 20

(dbg) break 74 À

Breakpoint set at LOTTERY 75

(dbg) break :lottery Ã

Breakpoint set at :LOTTERY 55

(dbg) break output Õ

Breakpoint set at LOTTERY 72

(dbg) break :lottery output

error: Breakpoint already set

(dbg) break :lottery 10

error: Breakpoint already set

(dbg) break 37 action="show n"

Breakpoint set at LOTTERY:PERMUTATIONS 37

(dbg) break -

:LOTTERY 20

:LOTTERY 72

:LOTTERY 75

:LOTTERY:PERMUTATIONS 37 action = "show n"

Current location is __start+0x0

(dbg) break 25 count=3 action=reg --

Breakpoint set at :LOTTERY:FACTORIAL 25 count = 3 action = "reg"

(dbg) continue "

 

Breakpoint encountered at :LOTTERY:FACTORIAL 25

$0 0x0 0 "

 

$f31 0

pc 0x1200a658 302032472

(dbg)

 

Set a breakpoint. DBG gives a success message showing the breakpoint, including the environment.

Attempt to set another breakpoint. Since the chosen line does not contain an executable statement, sets a breakpoint at the next line containing executable code.

Set a breakpoint at the absolute environment :lottery, which is the main routine of your program. Dbg sets the breakpoint at the first executable statement and informs you of the actual location.

Set a breakpoint at a label.

Shows the format used to set a breakpoint at a label using an absolute environment. In this case, the breakpoint was already set.

Shows the format used to set a breakpoint at a line using an absolute environment. In this case, the breakpoint was already set.

The break command with no parameters displays all currently set breakpoints.

Set another breakpoint, this time specifying a count and action.

Resume program execution.

The program stops at the first breakpoint it encounters, the one set in step eight. Execution stops at the breakpoint the third time it is encountered. DBG executes the specified action, the dbg register command to show all the registers and their contents, and then waits for a command.

CLEAR BREAK

Use the clear break command to clear breakpoints that you set using the break command. See See BREAK for information on setting breakpoints.

Restrictions

You must initialize the program before you use the clear break command. See INITIALIZE

Format
absolute_env

An absolute environment expression, as defined in See Terminology .

locator

An expression that resolves to the line number or label of an executable statement for which you previously set a breakpoint using the break dbg command.

If you attempt to clear a break on a non-executable line, dbg searches forward in the routine and clears the first breakpoint it encounters. If the routine contains no breakpoints, a "breakpoint not set" message. Otherwise dbg sets a breakpoint and displays a message containing the actual line number on which the break was cleared.

@all

Clears all breakpoints.

Dbg displays a success message, including the actual environment and locator, after clearing the specified breakpoint(s):

Examples

These examples assume you have set the breaks specified in See BREAK .

(dbg) clear break 20

Breakpoint cleared from :LOTTERY 20

(dbg) clear break :lottery:72

Breakpoint cleared from :LOTTERY 72

(dbg) clear break 35

error: Breakpoint not set at line 35

(dbg) clear break @all

Breakpoint cleared from :LOTTERY:PERMUTATIONS 37

Breakpoint cleared from :LOTTERY:FACTORIAL 25

 

(dbg)

CONTINUE

The continue command initiates program execution or continues execution of the program after it has stopped.

Restrictions

You must initialize the program before you use the continue command. See INITIALIZE

Format

continue [at locator]

 
at locator

An expression that resolves to the line number or label of an executable statement. The keyword at is required for this clause.

Examples

In the following example, the break command sets a breakpoint. The first continue command starts program execution. Execution stops at the breakpoint, and the user executes some dbg commands. The second continue command resumes execution until the next breakpoint.

(dbg) break 37 count=2

Breakpoint set at :LOTTERY 37

(dbg) continue

 

Breakpoint encountered at :LOTTERY 37

(dbg)show m

2.00000000000000E+00

 

(dbg)continue at 58

 

Enter number of choices (>0)  8

 

Enter number of selections (>0)  2

Breakpoint encountered at :LOTTERY 37

(dbg)

DESCRIBE

Use the describe command to show attribute information about a symbol. This information includes the attributes you specified in the declaration statement, plus all the PL/I defaults applied to the symbol.

Format

describe [environment:] symbol-name

 
environment:

Use this optional parameter to show information about a symbol in another environment.

symbol-name

The name of a user-defined program symbol. You can describe any type of symbol, including arrays and structures. You cannot describe a single array element or structure member.

Examples

The following examples use the describe command to show attribute information for various types of PL/I symbols.

describing a typical symbol

(dbg) describe m

M float binary(53,0) aligned parameter 8 bytes at 0x48 bytes

 

  1. describing a structure

(dbg) list 33,39

33: DECLARE 1 PAYROLL,

34: 2 NAME,

35: 3 LAST CHARACTER(80) VARYING,

36: 3 FIRST CHARACTER(80) VARYING,

37: 2 SALARY FIXED DECIMAL(7,2);

38:

39: PAYROLL.NAME.LAST = INPUT_BUFFER.NAME.LAST;

(dbg) describe payroll

1 PAYROLL automatic 180 bytes at 0x38 bytes

2 NAME member 164 bytes at 0x0 bytes

3 LAST character(80) varying unaligned member 82 bytes at 0x0 bytes

3 FIRST character(80) varying unaligned member 82 bytes at 0x52 bytes

2 SALARY fixed decimal(7,2) aligned member 16 bytes at 0xa4 bytes

 

  1. describing an array

(dbg) list 12,16

12: DECLARE MONTHS (12) CHARACTER (9) VARYING

13: INITIAL('January','February','March','April',

14: 'May','June','July','August',

15: 'September','October','November',

16: 'December');

(dbg) describe months

MONTHS (1:12) character(9) varying unaligned automatic

initialized 144 bytes at 0x70 bytes

(dbg)

 

  1. describing an explicitly based structure

Breakpoint encountered at :AGGREGATES:SUBR:60

(dbg) list 50,60

50: DECLARE 1 RES_DATA BASED (RPTR),

51: 2 DATE CHARACTER(8),

52: 2 HOTEL CHARACTER(3),

53: 2 PARTY_NAME,

54: 3 LAST CHARACTER(20),

55: 3 FST CHARACTER(10),

56: 2 STAY FIXED BIN(7);

57:

58: ALLOCATE RES_DATA SET(RPTR);

59: RES_DATA.DATE = '053095';

60: RES_DATA.HOTEL_CODE = 'XYZ';

(dbg) describe res_data

1 RES_DATA based() 44 bytes at 0xffffffffffffff50 bytes

2 DATE character(8) unaligned member 8 bytes at 0x0 bytes

2 HOTEL character(3) unaligned member 3 bytes at 0x8 bytes

2 PARTY_NAME member 30 bytes at 0xb bytes

3 LAST character(20) unaligned member 20 bytes at 0xb bytes

3 FST character(10) unaligned member 10 bytes at 0x1f bytes

2 STAY fixed binary(7,0) aligned member 2 bytes at 0x2a bytes

(dbg)

DIRECTORY

Use the directory command to display or add to the list of directories searched when dbg opens a source file for listing. (See See LIST for more information about listing source file lines.)

Format

directory [directory-name]

 
directory-name

Use this optional parameter to add the named directory to your list of search directories.

Omit this parameter to display the current list of search directories.

Examples

(dbg) directory

1:.

(dbg) dir home/louise/test/good

(dbg) dir

1:.

2:/home/louise/test/good

DOWN

Use the down command to navigate downward (toward the more recent frame) through your dynamic frames. (See for information on navigating upward through dynamic frames. Contrast with See ENVIRONMENT , which navigates through your lexical environment.)

Restrictions

You must initialize the program before you use the down command. See INITIALIZE

Format

down [number-of-frames]

 
number-of-frames

Use this optional parameter to specify how many frames dbg should move down through. The number must be an integer.

Omit this parameter to go down one frame.

Examples

(dbg) break 50

Breakpoint set at :LOTTERY:COMBINATIONS:50

(dbg) init

(dbg) continue

Breakpoint encountered at :LOTTERY:COMBINATIONS:50

50: RETURN (P);

(dbg) up

:LOTTERY

(dbg) up

:LOTTERY:COMBINATIONS

(dbg) down

:LOTTERY

(dbg) up

:LOTTERY:COMBINATIONS

(dbg) down 2

:LOTTERY:COMBINATIONS

(dbg) down

error: DOWN command invalid when at the breakpoint environment.

 

At this point, you have returned to your initial location.

ENVIRONMENT

Use the environment command to set your working environment. The environment command affects the scope in which dbg evaluates break, clear, describe, list, set, and show commands. Note that the environment command has no effect on the breakpoint or program execution. If you issue a continue or step command, execution resumes relative to the established breakpoint environment.

Format

environment [environment-specification]

 
environment-specification

One of the following:

@all

@break

environment-specifier

 

If you do not specify an environment specification, the environment command displays the current working environment.

@all

Use @all to list all the top level environments.

@break

Use @break to set your environment to the block where your program is currently stopped.

environment-specifier

Use either an absolute or relative environment specifier to identify the procedure block that you want to become your working environment. See the entry on environment in See Terminology for more information.

Examples

The following example is keyed to the list that follows it.

 

Breakpoint encountered at :LOTTERY:COMBINATIONS:49

(dbg) environment

:LOTTERY:COMBINATIONS

(dbg) environment :lottery À

:LOTTERY

(dbg) show N Ã

error: Symbol N not within current scope or not properly qualified.

(dbg) environment @all Õ

:LOTTERY

(dbg) environment permutations

:LOTTERY:PERMUTATIONS

(dbg) show N

8.00000000000000E+00

(dbg) environment @break -

:LOTTERY:PERMUTATIONS

(dbg)environment ^ --

:LOTTERY

(dbg)step "

Current location is :LOTTERY:FACTORIAL:26

 

Code execution has stopped at a breakpoint. The environment command, with no parameters, shows the current environment.

The environment command, followed by an absolute environment specifier, sets the scope to LOTTERY.

You try to show the symbol N within the PERMUTATIONS subroutine. Although your breakpoint is within that subroutine, your environment is currently LOTTERY and so you cannot show the symbol.

The environment command with the @all parameter shows all the top level environments that you can specify.

The environment command used with an absolute environment specifier sets the environment to the PERMUTATIONS subroutine.

You can now show the symbol N within the current environment.

The environment command with the @break parameter resets environment to the scope of the breakpoint at which execution stopped.

A relative environment specifier navigates out one level.

The step command steps one line from the breakpoint, even though the environment is different.

EXIT

The exit dbg command terminates the child debugger process containing your program, ends the debug session and exits the debugger. See See INITIALIZE for more information on the creation of the child debugger process.

Format

exit

 
Example

(dbg) exit

%

HELP

Displays information about dbg topics.

Format

help [topic]

 
topic

An entry listed in the help menu.

If you do not enter a topic, dbg displays a menu of topics. You can select a topic from this menu.

You can abbreviate topic names. If you enter a non-unique abbreviation, dbg displays the next higher level help topic.

Examples

(dbg) help

Top Help

Additional help available for:

commands

initialization

locator

primary-expression

string

(dbg) help commands

All commands and all keywords within all commands are....

 

STep

Up

Walkback

(dbg) help lo

A locator is used to specify a code address....

 

(dbg)

INITIALIZE

The initialize command creates a child debugger process containing your program, and establishes the child process as a debugee of the debugger. You must initialize the program before you use any of the following commands:

break

set

clear

show

continue

step

If you have an existing child process and execute the initialize command, dbg kills the existing child process and creates a new one. This establishes a start address at the beginning of the new child process.

Executing the initialize command does not affect established breakpoints. To remove breakpoints, use the clear break command. For more information, see See CLEAR BREAK .

Format

initialize [argument [,argument...]] [< filename] [> filename]

 
  • The arguments and the redirection parameters can occur in any order; you do not have to specify them in the order shown in the format diagram.
argument

One or more arguments passed to the user program.

< filename

The name of the file containing input to the user program.

> filename

The name of the file to contain output from the user program.

Examples
In the following example, the lottery program has no arguments and does not redirect input or output.

(dbg) initialize

note: Child process 18249 created

(dbg)

  1. If you rewrite the lottery program to accept the selection field size and number of selections as program arguments instead of prompting for them, and you want to redirect output to the file results, you can specify the arguments and redirection on the initialize command line.

(dbg) initialize 30 5 >results

note: Child process 19330 created

(dbg)

LIST

Use the list command to display a sequence of source program lines.

Format

If you specify the list command without arguments, dbg displays ten lines of source code to either side of the current line, or all lines to the beginning and/or end of the current scope, if there are fewer than ten lines.

Dbg lists twenty-one lines of source code at a time and then displays a prompt.

@all

Lists all source lines in the current program module.

locator

The line number or label of an executable statement.

To display the 21 lines containing one specific line, use the list command followed by the source line number.

To display specific lines, use the list command followed by the source line number of the first line to be listed, followed by a the source line number of the last source line you want to display. You can list up to 32767 lines of source code.

To display a single line, use the list command followed by the source line number, a comma, and the source line number again.

Examples
Default

By default, the display starts at the current source line, which dbg tracks internally. The default range of the listing is 10 lines above and below the current statement for a total of 21 lines. For example:

Breakpoint encountered at :LOTTERY:FACTORIAL:50

(dbg) list

60: 50: RETURN (P);

(dbg) list

40:

41:END PERMUTATIONS;

42:

43:COMBINATIONS: PROCEDURE (M,N) RETURNS (FLOAT BIN (53));

44:

45: DECLARE M FLOAT BIN (53);

46: DECLARE N FLOAT BIN (53);

47: DECLARE P FLOAT BIN (53);

48:

49: P = PERMUTATIONS(M,N) / FACTORIAL(N);

50: RETURN (P);

51:

52:END COMBINATIONS;

53:

54:/* Begin main program */

55: M_VALUE = 0.0;

56: N_VALUE = 0.0;

57:

58: DO WHILE (M_VALUE <= 0.0);

59: PUT SKIP LIST ('Enter number of choices (>0): ');

60: GET EDIT (M_VALUE) (F(12));

(dbg)

 

  1. Listing specific lines

To list specific lines, specify the starting and ending lines on the dbg command line. The following example lists five lines of the program starting at line 8:

(dbg) list 8,12

8: DECLARE (TRUNC,ONSOURCE) BUILTIN;

9: DECLARE (M_VALUE, N_VALUE) FLOAT BIN(53);

10: DECLARE (C,P) FLOAT BIN(53);

11:

12: ON CONVERSION BEGIN;

(dbg)

 

  1. Listing one line

To list one line, specify the same line number as the starting and ending lines, as follows:

(dbg) list 8,8

8: DECLARE (TRUNC,ONSOURCE) BUILTIN;

 

  1. To list the 21 lines centering on a specific line, specify the center line number, as follows:

(dbg) list 12

2: /* Lottery is the example program for the dbg chapter

3: /* of the User Manual.

 

19: PUT SKIP LIST ('Number is too big, sorry!');

20: STOP;

 

  1. Listing all lines

Use the list @all command to list your entire source program.

(dbg) initialize

Child

(dbg) list @all

1: /*

2: /* Lottery is the example program for the dbg chapter

3: /* of the User Manual.

4: /* Compile lottery.pli using the -g compiler option.

5: */

6: LOTTERY: PROCEDURE OPTIONS(MAIN);

 

71: PUT EDIT ('If order counts, chance is 1 in ', P)

72: (A,E(12)) SKIP;

73: PUT EDIT ('Otherwise, chance is 1 in ', C)

74: (A,E(12)) SKIP;

75: END LOTTERY;

PLAYBACK

Executes the commands in a playback file. You can create a playback file either by editing a file using your preferred editor or by using the dbg record command.

See See RECORD for information on recording debugger commands.

Format

playback filename

 
filename

The name of the file containing the debugger commands you want to execute.

Examples

The recorded file, lottery.py, contains the following lines:

break 20

break 37

break 48

 

The following example assumes you are debugging lottery and have issued the initialize command:

(dbg)playback lottery.py

(dbg) break 20

Breakpoint set at :LOTTERY:20

(dbg) break 37

Breakpoint set at :LOTTERY:PERMUTATIONS:37

(dbg) break 48

Breakpoint set at :LOTTERY:COMBINATIONS:48

 

PROMPT

Changes the command prompt to the specified string.

Format

prompt "string"

 
Examples

(dbg) prompt "dbg> "

dbg>

RECORD

Turns command recording on and off. Command recording writes commands given to the dbg debugger to the specified file.

See See PLAYBACK for information on playing back recorded commands, and See Creating .dbginit Files for information on using files containing recorded commands as initialization files.

Format

If you execute the record command with no parameters, dbg displays a status message telling you whether recording is currently on or off.

on filename

Turns command recording on and writes to the specified file.

off

Turns command recording off, closing the previously opened file.

Examples

(dbg) record

 OFF

(dbg) record on lottery.py

 ON lottery.py

(dbg) break 20

Breakpoint set at :LOTTERY:20

(dbg) break 37

Breakpoint set at :LOTTERY:PERMUTATIONS:37

(dbg) break 48

Breakpoint set at :LOTTERY:COMBINATIONS:48

(dbg) record off

OFF

 

The recorded file contains the following lines:

break 20

break 37

break 48

REGISTER

Displays the contents of all registers.

Format

register

 
Examples

(dbg) register

$0 0x0 0

$1 0xa22 2594

$2 0x14000950 335546704

$3 0x0 0

$4 0x0 0

$5 0xffffffffffffffff -1

 

$f27 0

$f28 0

$f29 0

$f30 0

$f31 0

pc 0x1200a3d8 302031832

(dbg)

 

SET

Use the set command to change the value of a variable. The set command works like a PL/I assignment statement.

Restrictions

You must initialize the program before you use the set command. See INITIALIZE

Format

set variable-name = value

 
variable-name

The fully-qualified name of the variable. You can set any variable that you can access. See See Accessing Data for more information.

value

A variable or constant that resolves to, or can be converted to, a value of the same data type as the variable being set. You can specify an element of an array by fully qualifying your specification, enclosing it in square brackets, providing the data type matches. Enclose strings in double quotation marks (for example, "string").

Examples

In the following examples, the set command assigns new values to different variables. The debugger validates that you have specified a value consistent with the data type and dimensional constraints of the variable.

Setting a variable to an integer value:

(dbg) set m = 10

Old value = 20

New value = 10

 

  1. Setting element 12 of an array of characters (you cannot deposit an entire array aggregate with a single assign command, only an element) to a value:

(dbg) set alph_array[12] = "K"

Old value = 'L'

New value = 'K'

 

  1. Setting a character variable to the value of element 12 of an array of characters:

(dbg) set middle_in = alph_array[12]

Old value = ' '

New value = 'K'

 

SHELL

Lets you access the shell defined by your SHELL environment variable (the default is /bin/sh, the Bourne shell) and execute shell commands.

Format

shell [shell-command]

 
shell-command

A string containing a valid command for your shell. The command executes and control returns to dbg.

If you do not specify a shell command, dbg pushes to your interactive shell. Use the shell termination sequence, such as exit, logout, or an end-of-file command, to return to dbg.

Examples

(dbg) shell

1%

 

5% exit

(dbg)

 

SHOW

The show command displays the value of a variable. You can show scalar variables, subscripted array elements, and structure members. Dbg formats the data according to the compiler-generated data type of the specified variable.

When you show a character string containing non-printable characters, special characters or control characters, dbg displays them in octal with the following exceptions:

Restrictions

You must initialize the program before you use the show command. See INITIALIZE

Format

show variable-name

 
variable-name

A string containing a valid reference to a variable in the current scope. You must properly qualify structure variable references, and include an explicit pointer reference to explicitly based variables.

Examples
Showing a simple variable:

(dbg) show n

2.000000000000000E+1

(dbg)

 

  1. Showing a member of an explicitly based structure:

(dbg) list 50,60

50: DECLARE 1 RES_DATA BASED (RPTR),

51: 2 DATE CHARACTER(8),

52: 2 HOTEL_CODE CHARACTER(3),

53: 2 PARTY_NAME,

54: 3 LAST CHARACTER(20),

55: 3 FIRST CHARACTER(10),

56: 2 STAY FIXED BIN(7);

57:

58: ALLOCATE RES_DATA SET(RPTR);

59: RES_DATA.DATE = '053095';

60: RES_DATA.HOTEL_CODE = 'XYZ';

61:

62: RETURN;

(dbg) break 62

Breakpoint set at :AGGREGATES:SUBR:62

(dbg) cont

Breakpoint encountered at :AGGREGATES:62

(dbg) show rptr->res_data.date

'053095   '

(dbg)

 

SIGNAL

The signal command displays the current signal values or lets you change the values. If you change a signal value it remains changed for the duration of your debugging session or until you change it again. Intervening initialize statements do not restore the default signal values.

When a program executes under debugger control, all signals pass to the debugger. The following steps occur:

The user-written program signals a condition.
  1. Control passes to the debugger.
  2. The debugger handles the signal as specified by the values of the STOP, IGNORE and REPORT options.
Format

If you issue the signal command with no parameters, dbg displays a table of all the signals by number and name and the currently set values for the STOP, IGNORE and REPORT options.

signal-identifier

One of the signals listed in the table. You can specify either the signal number or the signal name. If you specify a signal identifier, you must specify one or more of the options.

STOP

Toggles the STOP option. If STOP is true, the child process stops and the debugger reports the signal and displays the (dbg) prompt. If STOP is false, the child process continues.

IGNORE

Toggles the IGNORE option. If IGNORE is true, the debugger does not pass the signal to the child process. If IGNORE is false, the debugger gives the signal to the child process, which can then handle it.

REPORT

Toggles the REPORT option. If REPORT is true, the debugger reports the signal to you. If REPORT is false, the debugger does not report that the signal occurred.

You can specify any combination of values for the options. However, if STOP is true, the debugger always reports the signal to you before displaying the (dbg) prompt, even if REPORT is false.

Example

The following example displays the current signal values and resets the values for the SIGFPE condition so that it is not passed to the child process. When the SIGFPE signal occurs, the user program stops. The debugger displays the (dbg) prompt. The user can then look at data, modify a few values, and continue execution at a point before the signal occurred. The signal will not be passed to the child process.

(dbg) signal

Stop Ignore Report Event Name

1 T F T Hangup SIGHUP

2 T F T Interrupt SIGINT

3 T F T Quit SIGQUIT

4 T F T Illegal instruction SIGILL

5 T T T Trace/BPT trap SIGTRAP

6 T F T Abort process SIGABRT

7 T F T EMT trap SIGEMT

8 T F T Floating point exception SIGFPE

9 T F T Killed SIGKILL

10 T F T Bus error SIGBUS

11 T F T Segmentation fault SIGSEGV

 

31 T F T User defined signal 2 SIGUSR2

bearing) signal sigfpe ignore

Stop Ignore Report Event Name

8 T T T Floating point exception SIGFPE

(dbg) continue

program stopped: Floating point exception

Current location is P_LOUT+0x20

(dbg)

STEP

A step operation executes the program one source line at a time. After dbg executes the specified number of source lines, it displays the following message:

Program stepped to :env:m

 

where env is the current environment and m is the line number at the beginning of the statement where execution stopped. Use the continue or step command to resume program execution.

Step always steps to the next executable line of PL/I code. If the source line calls a routine, the step operation stops at the first executable line of the routine, if it is in PL/I. If the routine is in another language, the step operation stops at the first executable line of PL/I code after the routine.

Restrictions

You must initialize the program before you use the step command. See INITIALIZE

Format

step [n]

 
n

The number of source lines to step through. The default is 1.

Coding Hint

The step debugger command lets you execute a specified number of source program lines. When you type several statements on a single line, you cannot step through the statements individually. To step through statements individually, place them on separate source lines.

Examples

The following example continues the previous example, where the program is about to call the combinations routine:

(dbg) step

[combinations:40x4005dc] p = permutations(m,n) / factorial(n);

stopped at [combinations:42 ,0x4005dc] p = permutations(m,n) / factorial(n);

(dbg) w

37 combinations: procedure (m,n) returns (float bin (53));

38 declare m float bin (53);

39 declare n float bin (53);

40 declare p float bin (53);

41

>* 42 p = permutations(m,n) / factorial(n);

43 return (p);

44

45 end combinations;

46

(dbg)

 

If you specify an integer argument, dbg performs the specified number of step operations.

UP

Use the up command to navigate upward (toward the less recent frames) through your dynamic frames. (See See DOWN for information on navigating downward through dynamic frames. Contrast with See ENVIRONMENT , which navigates through your lexical environment.)

Restrictions

You must initialize the program before you use the up command. See INITIALIZE

Format

up [number-of-frames]

 
number-of-frames

Use this optional parameter to specify how many frames dbg should move up through. The number must be an integer.

Omit this parameter to go up one frame.

Examples

(dbg) break 50

Breakpoint set at :LOTTERY:COMBINATIONS:50

(dbg) init

(dbg) continue

Breakpoint encountered at :LOTTERY:COMBINATIONS:50

50: RETURN (P);

(dbg) up

:LOTTERY

(dbg) up

:LOTTERY:COMBINATIONS

(dbg) up

main+0x204

(dbg) up

_ftext+0xe4

(dbg) up

error: ../updown/up_cmd.c:Can not move 1 frames to get to new state.

 

At this point, dbg has detected the beginning of the call stack.

WALKBACK

Use the walkback command to display the frames on the call stack.

Restrictions

You must initialize the program before you use the walkback command. See INITIALIZE

Format

walkback [number-of-frames]

 
number-of-levels

Use this optional parameter to specify how many frames of the call stack to display, going from the most current frame back. The number must be an integer.

Omit this parameter to display the entire call stack.

Examples

(dbg) break 50

Breakpoint set at :LOTTERY:COMBINATIONS:50

(dbg) init

(dbg) continue

Breakpoint encountered at :LOTTERY:COMBINATIONS:50

50: RETURN (P);

(dbg) walkback

Current location :LOTTERY:COMBINATIONS:50

Called from :LOTTERY:70+14

Called from :LOTTERY:COMBINATIONS:52+3c

Called from main+0x204

Called from _ftext+0xe4

(dbg)

 

 

The File System

This chapter discusses the use of files for input and output (I/O) in PL/I and describes the aspects of the Digital UNIX operating system that relate to PL/I I/O. The chapter includes the following topics:

See , See , See , and See give additional information on the file system, such as stream and record I/O, options (ENVIRONMENT and I/O statement options), and built-in subroutines for file handling.

File Control

File constants and variables provide your program with access to files. Your program first declares a file constant or variable, and then associates the constant or variable with a file when it opens the file.

A file declaration specifies an identifier and the FILE attribute, and optionally specifies one or more file description attributes that describe the type of I/O operation that will be used to process the file. Subsequent I/O statements denote the file by a FILE option.

The OPEN statement explicitly opens a PL/I file with a specified set of attributes that describe the file and the method for accessing it. A file can also be opened implicitly by a READ, WRITE, REWRITE, DELETE, PUT, or GET statement issued for a file that is not open, or by a built-in subroutine that refers to a file that is not open.

When PL/I opens a file, the initial positioning depends on the type of file (record or stream), the access mode, and certain ENVIRONMENT options. File positioning for stream files and record files is described in See , " See File Organizations and Input/Output ".

The CLOSE statement dissociates a PL/I file from the physical file with which it was associated when it was opened. Some ENVIRONMENT options are valid on the CLOSE statement; the ENVIRONMENT options are summarized in See .

Declaring, opening, and closing files are discussed in more detail in the Kednos PL/I for UNIX Reference Manual.

Using the UNIX File System for I/O

When a PL/I program contains an I/O statement, for example, OPEN or READ, the compiler translates the request into a call to the appropriate PL/I run-time library routine. These routines in turn make calls to the appropriate Digital UNIX system services.

Note that, although you can call Digital UNIX system services directly from a PL/I program, it is not normally necessary to do so. A PL/I program executed on the Digital UNIX operating system has full access to I/O capabilities through the following language elements:

PL/I Files and UNIX File Specifications

In a PL/I program, all I/O operations are performed on a file, using the name of a file constant or file variable. When the file is opened, PL/I associates the name of the file constant with a specific device or file on the computer system.

By default, when a file variable is specified in an OPEN statement or in an I/O statement, the name used is that of the file constant with which the variable is currently associated. For example:

DECLARE F FILE,

G FILE VARIABLE;

G = F;

OPEN FILE(G);

 

In this example, F is a file constant and G is a file variable assigned the value of F. In the OPEN statement, PL/I uses the name F to associate the PL/I file with a UNIX file. The default file would be F. To change the name, use the title option of the DEFAULT_FILE_NAME environment option. Refer to See DEFAULT_FILE_NAME Option for more information.

The following sections describe in more detail how PL/I associates a file constant with a device or file.

Using the TITLE Option

When you specify the TITLE option on an OPEN statement, you can include all or part of a Digital UNIX file specification to indicate the file or device to be associated with the PL/I file. The following examples illustrate the use of the TITLE option.

This file specification completely defines a file on the local Digital UNIX system. When accessing the file OUTFILE, the program will be written to the file /usr/payroll/january.

OPEN FILE (OUTFILE)

TITLE ('/usr/payroll/january');

 

The following is an example of using a variable to specify the title:

NAME = 'TEST'||COUNT;

OPEN FILE(NEWFILE) OUTPUT TITLE(NAME);

 

The specification of this file is determined by the value of COUNT. For example, if COUNT is 5 when this OPEN statement executes, the file created is TEST5.

When no TITLE option is specified, PL/I supplies a default value for the file's title. The default title is the name of the file constant associated with the PL/I file.

If the value of the specified title begins with a dollar sign ($) the value is interpreted as an environment variable and substituted accordingly. If the substituted value contains a dollar sign ($) it is also interpreted as an environment variable. This process terminates when no further substitutions can be made or there are no more dollar signs.

Upon completion of the translation phase, if the DEFAULT_FILE_NAME option of the ENVIRONMENT attribute is used, the name associated with the file is merged with the DEFAULT_FILE_NAME option.

If the file specification that is finally achieved is invalid or represents an illegal device or file (for example, an input file cannot be found), the UNDEFINEDFILE condition is signaled. Note that the final file specification cannot exceed the value of MAXPATHLEN as defined in <sys/param.h>.

Using Environment Variables

Before executing a program at the shell level, you can create an environment variable to assign a UNIX file specification to the identifier of a PL/I file constant or to a value specified in a TITLE option. For example, suppose your PL/I program declares and opens a file as follows:

DECLARE INFILE FILE;

OPEN FILE (INFILE) RECORD OUTPUT;

 

The local file specification created on the Digital UNIX system is INFILE.

Environment Variables in TITLE Values

The value specified in a TITLE option can represent a environment variable when it starts with a dollar sign ($) For example:

OPEN FILE(INFILE) TITLE ('$NEWFILE');

 

If, before running the program, you define an environment variable called $NEWFILE, the OPEN statement would use the value of NEWFILE as the title. For example:

% setenv NEWFILE /usr/users/you/databases/phonebook

 

(This command may differ on your shell.) The file opened would be:

/usr/users/you/databases/phonebook

 

Process Standard System File Names

The system provides every process with a default set of standard name assignments, as listed in See . Default Process Stream Names . Because the files associated with these assignments exist for the life of the process, and because they are permanently open, they are called process permanent files.

. Default Process Stream Names

Stream Name

Default Equivalence Name

stdin

Standard input. For an interactive user, this is the terminal or, if redirected, the input command file.

stdout

Standard output. For an interactive user, this is the terminal or, if redirected, the output file name specified.

The default files associated with the GET and PUT statements, SYSIN and SYSPRINT, are defined by PL/I as follows:

. System File Names for Get and Put Statements

Statement

Default PL/I
File

Default Title

GET

SYSIN

stdin

PUT

SYSPRINT

stdout

Thus, when your program executes a GET statement that does not specify the FILE option, and if SYSIN was not explicitly opened with a title, the run-time system reads from standard input.

A similar set of associations occurs when a program executes a PUT statement without the FILE option: the resulting output is written to standard output, stdout.

In the dec and ansi dialects, the process permanent file SYSOUT is also mapped to stdout.

The file symbols "SYSPRINT", "SYSIN", and "SYSOUT" are always case insensitive regardless of the specified compiler -m or --case option. In other words, whether you specify "sysprint", "Sysprint", or "SYSPRINT", you will always refer to the pre-declared PL/I files.

The file symbols "SYS$PRINT", "SYS$INPUT", and "SYS$OUTPUT" are not predeclared. However, if you declare any of these, they map to the same files as the predeclared process permanent files, "SYSPRINT", "SYSIN", and "SYSOUT".

Expanding File Specifications

The following examples enumerate the steps in completing a file specification. All examples assume that the following environment variable assignments are in effect:

STATE_NAME = NEBRASKA

STATES = /usr/BACKUP

They also assume the following current default device and directory:

/usr/users/malcolm

 

Example 1:

DECLARE STATES FILE RECORD OUTPUT;

OPEN FILE(STATES) TITLE ('/usr/STATE.DATA/NEVADA');

 

Steps:

Obtain the value in the TITLE option. This value represents the complete file specification.

Final Specification: /usr/STATE.DATA/NEVADA

Example 2:

DECLARE STATES FILE RECORD OUTPUT;

OPEN FILE(STATES) TITLE ('$STATE_NAME');

 

Steps:

Obtain the value from the TITLE option, $STATE_NAME.
  1. Translate the environment variable STATE_NAME to obtain the equivalence, NEBRASKA.

Final Specification: /usr/users/malcolm/NEBRASKA

Example 3:

DCL $STATES FILE RECORD OUTPUT;

OPEN FILE ($STATES);

 

Steps:

Apply the default title, STATES.
  1. Translate the environment variable STATES to obtain the equivalence name, /usr/BACKUP.

Final Specification: /usr/BACKUP

Error Handling

Kednos PL/I for UNIX uses the standard PL/I ON condition names to signal run-time errors that occur for file operations. The ON conditions and the circumstances under which they are signaled are as follows:

  • The UNDEFINEDFILE condition is signaled whenever a file cannot be opened.
  • The ENDFILE condition is signaled when the end-of-file is reached during an input operation.
  • The ENDPAGE condition is signaled for a file with the PRINT attribute when the current line number exceeds the page size specified for the file.
  • The KEY condition is signaled for a file with the KEYED attribute when any error involving the interpretation, writing, or specification of a key occurs.
  • The ERROR condition is signaled for all other file-related errors.

In the IBM dialect only, the following ON conditions are also used:

  • The NAME condition handles errors involving data-directed GET statements with the FILE option.
  • The RECORD condition handles size errors involving records during READ, WRITE, or REWRITE operations.
  • The TRANSMIT condition handles errors involving uncorrectable transmission errors during record I/O.

See the Kednos PL/I for UNIX Reference Manual for more information on these conditions.

To handle any of these conditions in a PL/I procedure, you can establish an ON-unit to receive control if the specified condition is signaled. For example:

ON UNDEFINEDFILE (INFILE) OPEN FILE (INFILE)

TITLE ('input');

 

The ON statement provides a default title for the file INFILE.

Values Returned by PL/I Built-In Functions for Error Handling

An ON-unit can be a generalized error-handling routine, written so that it responds to specific errors or prints an error message. Following are the PL/I built-in functions that provide meaningful information in an ON-unit to handle a file system error:

Whenever an error is signaled, the built-in function ONCODE makes available the condition value associated with the specific error. When a PL/I program is executing under control of the Digital UNIX operating system, the value returned by the ONCODE built-in function is a unique 32-bit condition value that indicates the reason for the error. This value is from the file system or from the PL/I run-time system. Note that Digital UNIX file system errors are mapped to RMS (VAX Record Management Services) errors by the PL/I run-time library for compatibility with VAX PL/I.

The built-in function ONFILE returns a character string giving the name of the file constant on which the error occurred.

If the file was being accessed by key, the ONKEY built-in function returns the key value that caused the error to be signaled.

Writing an Error Handler

You can write an ON-unit to detect and correct errors that occur during file operations. The following example shows an ON-unit that detects whether a record with a given key value was not found or whether an attempt was made to write a record whose key duplicates the value of an existing key.

ON KEY(STATE_FILE) BEGIN;

%INCLUDE $RMSDEF;

/* Check for a record not found */

IF ONCODE() = RMS$_RNF /* if record not found */

THEN DO;

PUT SKIP EDIT(STATENAME,'Not found.')

(A,X,A);

STOP;

END;

/* Check for duplicate key */

ELSE

IF ONCODE = RMS$_DUP

THEN DO;

PUT SKIP EDIT('Record already exists for', STATENAME)

(A,X,A);

STOP;

END;

END;

 

In this example, the ON-unit declares symbolic names for two specific status values returned by ONCODE:

In an ON-unit for the KEY condition, ONCODE may also return the value associated with the status code RMS$_KEY. This code indicates that a key value is invalid; for example, it is an incorrect data type.

The symbolic names for RMS status codes are declared as %REPLACE constants in the system include file $RMSDEF (/usr/lib/cmplrs/pli100/usr/include/rmsdef.in).

Default Error Handling for the File System

If a file system error occurs during the execution of a PL/I statement, the PL/I run-time system signals either the specific PL/I condition name or the ERROR condition. If no user-specified ON-units exist to handle either the specific PL/I condition or the ERROR condition, PL/I performs its default condition handling.

If any active procedure specified OPTIONS (MAIN), a default PL/I condition handler is present and executed. It prints a PL/I run-time error message. If there is no default PL/I handler, the error signal is passed to the default condition handler established by the UNIX system, which prints the message associated with the RMS error. If the error was a fatal error, the handler terminates the program; otherwise, the program continues.

The following example illustrates the type of message that the PL/I run-time system displays when an error occurs during an I/O operation:

PL/I unhandled exception at 0x00401380:

PL/I ERROR condition.

PL/I UNDEFINEDFILE condition on file 'INFILE'.

FILENAME: '/usr/users/tim/databases/myfile.dat'.

FILENAME, FNF, File not found.

 

In this example, the error occurred because an OPEN statement could not find the specified file. This fatal error terminates the program.

 

 

File Organizations and Input/Output

Record I/O is performed by the READ, WRITE, DELETE, and REWRITE statements; each statement processes an entire record. In stream I/O, more than one line or record can be processed by a single statement. In addition, some forms of record I/O allow you to access records in the file by record number or by a key field contained in the record.

This chapter includes the following topics:

For position information and descriptions of the READ, WRITE, DELETE, and REWRITE statements, see the Kednos PL/I for UNIX Reference Manual.

File Organizations

The UNIX file system supports only stream files; however, the PL/I run-time system simulates the behavior of relative files by imposing restrictions on the access of files having these organizations.

One of the consequences of this is that (unlike VAX PL/I) the Kednos PL/I for UNIX run-time system relies on the file organization and access method specified in the DECLARE, OPEN, and READ statements of your PL/I program to determine the file organization. Thus it is up to the programmer to ensure that the correct file organization is specified in the input/output statements of the PL/I program; otherwise, results are unpredictable. To avoid problems when specifying the file, always open a file with the same file attributes.

Restrictions

Kednos PL/I for UNIX does not support some file organizations or combinations of file organizations and access methods due to limitations of the file system. These are:

  • Stream access of relative file with fixed or variable length records
  • Sequential access of stream file with variable length records (supported by VAX PL/I)
  • Direct access of stream file with variable length records (supported by VAX PL/I)

The following file organizations are supported by PL/I:

  • Stream
  • Relative
Stream Files

In a stream file, characters are ordered one after the other, in the order in which they are written. New characters can be added only at the end of an existing file. Stream files are discussed in more detail in See Stream Files .

Relative Files

A relative file contains a specified number of fixed-length cells, numbered from 1 to n, where n is a user-specified maximum. Any record written to the file is written to a specific numbered cell; the cell number is also the relative record number of the record in the file.

Normally, the records in a relative file have an implied numeric data field, for example, an account number or employee number, which corresponds to the cell in which the record will be placed. When you read or write a record in a relatively organized file, you specify the record by its relative record number. Relative files are discussed in more detail in See Relative Files .

Access Modes for Record I/O

In standard PL/I, you can specify one of the following sets of attributes to define the way a program is going to access the records in a file:

In PL/I, there is an additional way to access a file. Specify the ENVIRONMENT option RECORD_ID_ACCESS to indicate that records can be read or written randomly with the file address of the record.

Although you cannot change the organization of the records in a file after you have created the file, you can select a different type of access mode for reading or processing the file. You can also access a file using more than one access mode; for example, you can read a record in an indexed file by specifying a key, and then read records sequentially beginning at that position in the file.

Sequential Access

You can use sequential access with any type of file organization except stream access to a variable length record file. When you access a file sequentially, each read or write operation reads or writes the next record in the file. As you process a file sequentially, PL/I keeps track of the current record (that is, the record just read or written) and the next record (the record that follows the record just read or written).

When you access a relative file sequentially, the records are read or written in order by relative record number. In a file in which not all cells contain records, sequential input operations involve only cells that contain data records.

Direct Access

When you access a file randomly by key, each I/O request must contain the KEY or KEYFROM option.For a relative file, the key is the relative record number of the record to be accessed.

By default, a READ statement accesses a record based on an exact match of the key specified. In PL/I, you have the option of requesting that the READ statement match any record with an equal or greater key value, or any record with a greater key value.

Direct and Sequential Access

When you access a file for random and sequential access, you can read records sequentially or randomly. For example, you can use a keyed READ statement to position the file at a specified record and then read or process records sequentially from that position.

Access by Record Identification

You can use a record identification to access records in any type of disk file (except stream files with variable length records) that is opened for any type of access. To access records by record identification:

Specify the RECORD_ID_ACCESS option in the ENVIRONMENT attribute for the file.
  1. Supply a 2-element array variable to save the record identification of records you want to access by record identification.
  2. Specify the array variable in the RECORD_ID_TO option on a READ, REWRITE, or WRITE statement that accesses a record in the file, and save the value that is returned.
  3. Specify the array variable that contains a valid record identification in a RECORD_ID option on a READ, REWRITE, or DELETE statement.

For example:

DECLARE LIBFILE FILE ENVIRONMENT(RECORD_ID_ACCESS),

SAVED_ID(2) FIXED BINARY(31);

OPEN FILE(LIBFILE) DIRECT;

READ FILE(LIBFILE) KEY(MODULE_NAME) INTO(INREC)

OPTIONS(RECORD_ID_TO(SAVED_ID));

 

The READ statement in this example returns the value of the record identification associated with the record whose key is indicated by the variable MODULE_NAME. The value of SAVED_ID may subsequently be used in a REWRITE or DELETE statement to modify the record.

Record Formats

The following types of record formats are allowed for all file organizations:

  • Fixed length
  • Variable length

You must specify the format when you create a file and each time you open the file. This is necessary because PL/I cannot determine the format of the records in the file.

Fixed-Length Records

In a file containing fixed-length records, all records have the same length. Thus, when you create a file with fixed-length records, you must specify the length of each record in the file; this size cannot be changed after the file is created.

To create a file with fixed-length records in a PL/I program, use the FIXED_LENGTH_RECORDS option of the ENVIRONMENT attribute. The MAXIMUM_RECORD_SIZE option specifies the size of each record. For example:

DECLARE FIXED_FILE FILE RECORD KEYED OUTPUT

ENVIRONMENT(FIXED_LENGTH_RECORDS,

MAXIMUM_RECORD_SIZE(80));

 

When the file FIXED_FILE is opened, its record format is established as having fixed-length 80-character records.

When a file that has fixed-length records is processed by READ and WRITE statements, the file system checks the length of the variable specified in the INTO or FROM option to see if it is the same as the length of the records in the file. If not, the ERROR condition is signaled.

IBM Dialect Fixed Length Environment Options

The following environment options are available in the IBM dialect only:

  • F, FB, FS, or FBS -- all equivalent to FIXED_LENGTH_RECORDS
  • RECSIZE -- equivalent to MAXIMUM_RECORD_SIZE

Variable-Length Records

PL/I supports only record I/O on variable-length record files with relative file organizations. In a file containing variable-length records, each record can have a different size. PL/I places a count field at the beginning of each record to indicate its size; however, this count field is not considered a part of the data record, nor is the length of the count field included in the size of the record.

Variable length is the default record format for PL/I files. Use the MAXIMUM_RECORD_SIZE option to specify the maximum length that any record can have. For example:

DECLARE VAR_FILE FILE RECORD OUTPUT

ENVIRONMENT(MAXIMUM_RECORD_SIZE(80));

 

This declaration indicates that the file VAR_FILE has variable-length records, each with a maximum length of 80 characters.

When a file that has variable-length records is processed by READ statements, the file system checks the length of the variable specified in the INTO option to see if it is large enough to hold the record being read. If not, the ERROR condition is signaled.

IBM Dialect Variable Length Environment Options

The following environment options are available in the IBM dialect only:

  • V, VB, VS, or VBS -- all equivalent to the variable length record fomat
  • RECSIZE -- equivalent to MAXIMUM_RECORD_SIZE
Stream Files

Record I/O on stream files is limited to those with fixed-length records. This section shows examples of some typical sequential file I/O operations on stream disk files.

Stream Files Organization

Stream input and output are performed by the statements GET and PUT, respectively. Both statements can perform either list-directed or edit-directed operations.

A file has the STREAM attribute if it meets any of the following conditions:

Files declared with the STREAM attribute have the following characteristics:

Stream files contain only ASCII data. The ASCII format used to represent program data in a stream output file differs depending on the attributes given to the file. For example, the representation of character strings differs depending on the presence or absence of the PRINT attribute in the file declaration.

Unlike VAX VMS, an existing stream file cannot be reopened and accessed by the READ and WRITE statements. Stream files are true byte streams on UNIX. If READ and WRITE open a file implicitly, the attributes RECORD INPUT SEQUENTIAL and RECORD OUTPUT SEQUENTIAL are implied, respectively. These attributes are not compatible with an existing disk file created with the STREAM and OUTPUT attributes, and these operations will produce unpredictable results.

Creating a Stream File

Whenever a PL/I program opens a file with the SEQUENTIAL OUTPUT attributes, PL/I creates a new stream file. By default, records are 510-byte, variable-length records. If record I/O is done on this file, you must specify the FIXED_LENGTH_RECORDS attribute (or the IBM dialect equivalent attribute). 2

Appending Records to an Existing File

In PL/I, you can open a file with the APPEND option of ENVIRONMENT to add new records to the end of an existing sequential file. This overrides the default action of PL/I, which is to overwrite an existing file when the existing file is opened for output. For example:

OPEN FILE (BIRD_FILE) OUTPUT SEQUENTIAL

TITLE ('BIRDS.DAT')

ENVIRONMENT (APPEND, FIXED_LENGTH_RECORDS);

WRITE FILE (BIRD_FILE) FROM (NEWDATA);

 

This OPEN statement opens the file BIRD_FILE and positions it at its current end-of-file. The WRITE statement adds a new record at the end of the file.

Superseding an Existing File

The ENVIRONMENT option SUPERSEDE lets you create a new version of a file each time you open it, simultaneously deleting an existing version. This is the default behavior for output files in PL/I. For example, the following OPEN statement opens the file CONTROL.DAT, deleting any pre-existing versions of the file.

OPEN FILE(CONTROL) OUTPUT RECORD TITLE('CONTROL.DAT')

ENVIRONMENT(SUPERSEDE);

 

Relative Files

This section describes the organization of a relative file, suggests considerations for creating and using relative files, and shows examples of some typical relative file I/O operations.

Relative File Organization

The relative file organization is suitable for files with data that can be arranged serially and be uniquely identified by an integer value, for example, a part number or an employee identification number. Within the file, records are written into cells that are numbered; there is a one-to-one correspondence between the cell number and the integer value associated with the data in the record. This number, called the relative record number, is the key by which records are accessed.

See . Relative File illustrates a relative file in which not all cells contain records. The first record written to the file was relative record number 1 (which may have been data for a part numbered 1 or an employee whose number is 1, for example). The second record written was relative record number 2. The third record written was relative record number 4; thus cell number 3 does not contain a record.

 

 

. Relative File

Although the cells in a relative file have the same length, the records need not be fixed-length records. However, when a record is smaller than the length of a cell, the unused space is wasted.

Creating a Relative File

In PL/I, relative file organization is the default organization for files that are opened with the KEYED attribute. Thus, when a WRITE statement is directed to a file with the KEYED and OUTPUT attributes, PL/I creates a relative file.

When you initially create a relative file in a PL/I program, consider using the ENVIRONMENT option MAXIMUM_RECORD_SIZE (or the IBM dialect RECSIZE option) to maximize the efficiency of I/O operations on the file.

Maximum Record Size

When you specify the length of the records in a file, the value you specify is used in the MAXIMUM_RECORD_SIZE option (or the IBM dialect RECSIZE option) to calculate a cell size. It uses the following formulas to calculate the size:

  • For all records -- cell size = 2 + MAXIUM_RECORD_SIZE (two bytes are required for overhead; they contain the deletion indicator)
  • For variable-length records -- cell size = 3 + maximum record size (three bytes are required for overhead: two bytes for the individual record size, and one byte for a deletion indicator)

When you select a record size for a relative file, try to specify a size that is no greater than the largest record that will be written. Otherwise, any unused space in each cell will be wasted. If you do not specify a maximum record size for either fixed- or variable-length records, PL/I uses the default length of 480 bytes.

Using Relative Files

You can create a relative file from any existing file that is suitable for relative file organization. See . Creating a Relative File illustrates copying a sequential file with fixed-length records into a relative file.

. Creating a Relative File

COPY_TO_RELATIVE: PROCEDURE OPTIONS(MAIN);

 

%INCLUDE PARTLIST; /* Declaration of PARTLIST */

DECLARE OLDFILE FILE INPUT RECORD SEQUENTIAL ENVIRONMENT(

FIXED_LENGTH_RECORDS,

MAXIMUM_RECORD_SIZE(36));

DECLARE RECORD_NUMBER FIXED BINARY(15);

DECLARE

PARTS FILE OUTPUT KEYED RECORD ENVIRONMENT(

FIXED_LENGTH_RECORDS, À

MAXIMUM_RECORD_SIZE(36));

 

ON ENDFILE(OLDFILE) BEGIN; Ã

CLOSE FILE(OLDFILE), FILE(PARTS);

STOP;

END;

 

OPEN FILE(OLDFILE), FILE(PARTS);

 

DO WHILE('1'B);

READ FILE(OLDFILE) INTO(PARTLIST); Õ

RECORD_NUMBER = PARTLIST.NUMBER;

WRITE FILE(PARTS) FROM(PARTLIST)
KEYFROM(RECORD_NUMBER);

END;

END COPY_TO_RELATIVE;

 

The following notes are keyed to See . Creating a Relative File :

The structure PARTLIST describes the layout of the records in the file. The records will be ordered in the relative file according to the field PARTLIST.NUMBER.

The relative file PARTS is declared with fixed-length, 36-byte records.

The file OLDFILE is the sequential file containing the records to be copied to a relative file. When the end-of-file is reached, the file is closed and the STOP statement terminates the program.

As each record is read into the structure PARTLIST, the value of NUMBER is copied to the fixed binary integer RECORD_NUMBER. The part number is maintained in each record in its character-string form.

Each WRITE statement copies the record to the output file, specifying the value of the part number as a relative record number.

Records in this file can subsequently be accessed either sequentially or by part number. To access a record by part number, you specify the number as a key. For example:

GET LIST(INPUT_NUMBER) OPTIONS(PROMPT('Part? '));

READ FILE(PARTS) INTO(PARTLIST) KEY(INPUT_NUMBER);

 

Here, the value entered in response to the GET statement is used as a key value to access a record in the file.

Populating a Relative File

In See . Creating a Relative File , the file PARTS is opened with the KEYED and OUTPUT attributes. When this program is executed, the amount of space allocated for the file PARTS depends on the relative record numbers of the records that are written to the file. For example, if the largest record number specified for a record is 200, only enough space for 200 records is allocated.

Updating a Relative File

To add or modify records in a relative file, open the file with the DIRECT and UPDATE attributes. For example, a procedure that updates the file PARTS when new stock is ordered might contain the following:

ORDER_PARTS: PROCEDURE(ORDERED_AMOUNT,PART_NUMBER);

%INCLUDE PARTLIST; /* Declaration of PART.LIST */

DECLARE (ORDERED_AMOUNT,PART_NUMBER) FIXED BIN(15);

DECLARE PARTS FILE RECORD DIRECT UPDATE;

 

OPEN FILE(PARTS);

READ FILE(PARTS) INTO(PARTLIST)

KEY(PART_NUMBER);

PARTLIST.ON_ORDER = PARTLIST.ON_ORDER +

ORDERED_AMOUNT;

REWRITE FILE(PARTS) FROM(PARTLIST);

CLOSE FILE(PARTS);

END;

 

In this example, the procedure ORDER_PARTS receives as its parameters the order quantity and the part number. It reads the record associated with the part number from the file, adds the order quantity to the existing quantity, and rewrites the record.

Reading a Relative File Sequentially

You can access a relative file sequentially as well as by key. When you access the file sequentially, each READ statement returns the record in the next cell that contains a record, skipping empty cells. The following example illustrates reading a relative file sequentially:

PRINT_PART: PROCEDURE OPTIONS(MAIN);

%INCLUDE PARTLIST; /* Declaration of PARTLIST */

 

DECLARE PARTS FILE,

CHECK_NUM FIXED;

 

DECLARE EOF BIT(1) ALIGNED INIT('0'B);

 

OPEN FILE(PARTS) INPUT SEQUENTIAL RECORD KEYED;

ON ENDFILE(PARTS) EOF = '1'B;

READ FILE(PARTS) INTO(PARTLIST) KEYTO(CHECK_NUM);

DO WHILE(^EOF);

PUT SKIP EDIT(PARTLIST.NAME, /* Output data */

UNIT_PRICE,

IN_STOCK,

ON_ORDER)

(A,X,A,X,A,X,A);

PUT SKIP EDIT('Relative record number',CHECK_NUM,

'Part number:',PARTLIST.NUMBER)

(X(10),A,X,F(5),A,X,A); /* Output

verification */

READ FILE(PARTS) INTO(PARTLIST) KEYTO(CHECK_NUM);

END;

 

This procedure outputs the contents of the file PARTS, listing each field in the data records described by PARTLIST. The READ statement specifies the KEYTO option; the procedure outputs the value returned to the variable CHECK_NUM.

Error Handling

PL/I signals the KEY condition when errors occur during the processing of record numbers for relative files. For example, it signals the KEY condition when the number of a record that already exists is specified in a KEYFROM option in a WRITE statement.

The following sample ON-unit shows how to detect whether a record already exists in a relative file.

ON KEY(PARTS) BEGIN;

%INCLUDE $RMSDEF;

/* Check for duplicate records */

IF ONCODE() = RMS$_REX /* If duplicate */

THEN DO;

PUT SKIP EDIT('Part number',

PARTLIST.NUMBER,'exists. Reenter')

(A,X,A,X,A);

GET LIST(PARTLIST.NUMBER); /* Get new value */

GOTO GET_DATA; /* Go get other data */

END;

END;

GET_DATA:

 

In this example, the ON-unit gets symbolic names for a specific status value returned by ONCODE, from RMSDEF, a system include file provided for compatibility with VAX PL/I. The value RMS$_REX indicates that a record already exists.

In an ON-unit for the KEY condition for a relative file, ONCODE can also return the values associated with the following status codes:

The symbolic names for these status codes are included from the system include file rmsdef.in, from /usr/lib/pl1/include.

 

Options of the ENVIRONMENT Attribute

The options of the ENVIRONMENT attribute provided by Kednos PL/I for UNIX let you do the following:

This chapter presents an overview of the environment options and information on how to specify them, and gives a description of each option. The descriptions of the environment options are arranged in alphabetic order. The chapter concludes with a discussion of the environment options designed for file protection, file sharing, and I/O optimization.

Specifying and Using Environment Options

All environment options can be specified in the declaration of a file constant or, in sthe dec and ansi dialects, in an OPEN statement . Certain options can also be specified in a CLOSE statement.

If you declare a file constant or file variable explicitly or implicitly as EXTERNAL, you must use identical attributes, including ENVIRONMENT options, in all blocks that declare the file.

Arguments for Environment Options

Environment options fall into the following categories, based on whether they require an argument and, if so, what type of argument is required:

All arguments must be specified in parentheses following the name of the environment option. For example:

ENVIRONMENT (

MAXIMUM_RECORD_SIZE(1024),

FILE_ID_TO(WORKFILE_ID),

FIXED_LENGTH_RECORDS('1'B) )

 

Considerations for specifying each type of argument are given in the following sections.

Expressions

You can use integer expressions and character expressions in expression arguments for environment options. The ways you can specify these arguments differ for DECLARE statements and for OPEN and CLOSE statements.

In a DECLARE statement, you must specify a constant expression. Integer expressions can consist of integer constants, constant identifiers defined by %REPLACE statements, and the operators +, -, *, and /. You must specify character expressions using character-string constants.

In an OPEN or a CLOSE statement, you can specify the argument using constant expressions or variable references, or expressions or variable references of the required type.

If a single variable is specified for an expression, its data type must be convertible to the data type of the option. All integer constants and expressions are converted to FIXED BINARY(31).

You can specify all character-string expressions using varying or nonvarying strings. The description of the option specifies the maximum length of a string argument.

For any of these options, PL/I applies a default value if no option is specified for the file when it is opened.

Variable References

Options that are specified by variable references cannot be specified in a DECLARE statement. The data type of the variable must match the data type described in the option description.

Boolean Values

For an option that can be enabled or disabled, you can specify a Boolean constant, that is, '1'B (to enable) or '0'B (to disable) the option in a DECLARE statement. In an OPEN or CLOSE statement, you can specify a Boolean constant, variable, or expression.

An option that is specified without a value is interpreted as enabled. For example, the following are equivalent:

ENVIRONMENT(FIXED_LENGTH_RECORDS)

ENVIRONMENT(FIXED_LENGTH_RECORDS('1'B))

 

For arguments of this type, PL/I converts any non-Boolean value to BIT(1) ALIGNED.

Interpretation of ENVIRONMENT Options for Existing Files

Many ENVIRONMENT options specify values that can be set only when a file is created. For example, the length of records in a file with fixed-length records is set when the file is created and cannot be changed thereafter. When these options are specified, they determine the option for the file if the OPEN option creates the file. Because the options are not stored with the file, they must be given for each opening of a file. The results are unpredictable if the options given do not match with those existing for the file.

Conflicting and Invalid ENVIRONMENT Options

Conflicting or invalid options or values for options can be detected during compilation or at run time. At compile time, the compiler issues a diagnostic message to indicate the error.

At run time, the UNDEFINEDFILE condition is signaled if conflicting options are in effect or if conflicting values are specified for the same option. For example, if the MAXIMUM_RECORD_SIZE option is specified in the DECLARE and OPEN statements for a given file and if the options specify different values, UNDEFINEDFILE is signaled.

For run-time errors, an ON-unit can reference the ONCODE built-in function to determine the specific error, if desired. If no ON-unit exists for the UNDEFINEDFILE condition, the PL/I run-time system displays an error message describing the error that occurred.

Summary of ENVIRONMENT Options

The options to the PL/I ENVIRONMENT attribute for the DEC and ANSI dialects are summarized in alphabetic order in See . Summary of DEC and ANSI Dialect ENVIRONMENT Options .The ENVIRONMENT options for the IBM dialect are summarized in See . Description of Columns in Table 6-2 describes the columns in See . Summary of DEC and ANSI Dialect ENVIRONMENT Options .

The sections following these tables describe the Kednos PL/I for UNIX environment options in detail.

. Description of Columns in See . Summary of DEC and ANSI Dialect ENVIRONMENT Options

Option

Gives the name of the ENVIRONMENT option and its argument, if any. An option that does not show an argument can be specified with a Boolean argument.

Usage

Briefly describes the option.

Specify At

Indicates when the option is meaningful. The possible items in this column are:
Create -- the option can be specified on a DECLARE or OPEN. It is meaningful when a file is created.
Open -- the option can be specified on a DECLARE or OPEN. It is meaningful when an existing file is opened.
Close -- the option can be specified on a DECLARE, OPEN, or CLOSE. It takes effect when the file is closed.
Update -- the option is meaningful when an existing file is opened with the UPDATE attribute or with the ENVIRONMENT option APPEND

Valid I/O Types

Indicates whether the option is valid for stream or record files.

Default Value

Indicates the default value, if any, when the option is not specified for a file.

Data Type

Specifies the required data type of the argument.

 
. Summary of DEC and ANSI Dialect ENVIRONMENT Options

Option

Usage

Specify At

Valid I/O Types

Default Value

Data Type

APPEND

Places output for a file at the end of a file.

Create Open

Record Stream

Disabled

BIT(1)

DEFAULT_
FILE_NAME (expression)

Defines a default specification for a file.

Create Open

Record Stream

None

CHAR(128)
VARYING

DELETE

Specifies that the file be deleted when it is closed.

Create Open Close

Record Stream

Disabled

BIT(1)

FILE_ID (variable)

Identifies a file by its internal file identification.

Open

Record Stream

Not applicable

(6)FIXED BINARY(31)

FILE_ID_TO (variable)

Identifies a file by its internal file identification.

Create Open

Record Stream

Not applicable

(6)FIXED BINARY(31)

FIXED_
LENGTH_
RECORDS

Specifies a file with fixed-length records of a maximum record size.

Create

Record

Disabled

BIT(1)

GROUP_
PROTECTION (expression)

Defines the type of file access allowed to members of the owner's group.

Create

Record Stream

Current process default 3

CHAR(4)

MAXIMUM_
RECORD_SIZE (expression)

Specifies the maximum size valid for records in the file.

Create

Record

Varies 4

FIXED BINARY(31)

OWNER_
PROTECTION (expression)

Specifies the type of file access allowed the owner of the file.

Create

Record Stream

Current process default See See umask(1)

CHAR(4)
VARYING

RECORD_ID_
ACCESS

Indicates that records will be accessed by internal file system identification.

Create Open

Record

Disabled

BIT(1)

SHARED_READ

Lets other users read records in the file.

Create Open

Record

Enabled 5

BIT(1)

TEMPORARY

Specifies a temporary file which is deleted when the process terminates.

Create

Record Stream

Disabled

BIT(1)

WORLD_
PROTECTION (expression)

Specifies the type of file access allowed to general system users.

Create

Record Stream

Current process default See See umask(1)

CHAR(4) VARYING

 
. Summary of IBM Dialect ENVIRONMENT Options

Option

Usage

Specify At

Valid I/O Types

Default Value

Data Type

BLKSIZE (expression)

Specifies the size of a block when writing to a buffered file.

Create

Record

Current record size

FIXED BINARY(31)

CONSECUTIVE

Specifies that records in the file are placed in physical sequence.

Create

Record Stream

Enabled

BIT(1)

F|FB|FS|FBS

Specifies a file with fixed-length records of a maximum record size. These are all equivalent to F; the B and S portions are ignored.

Create

Record

Disabled

BIT(1)

RECSIZE

Specifies the maximum size valid for records in the file.

Create

Record Stream

Varies 6

FIXED BINARY(31)

SCALARVARYING

Specifies that varying character strings are read/written using the entire storage of the variable.

Create

Record

Disabled

BIT(1)

V|VB|VS|VBS

Specifies a file with variable-length records with a maximum record size. These are all equivalent to V; the B and S portions are ignored.

Create

Record

Enabled

BIT(1)

Some environment options are accepted but ignored by the Kednos PL/I for UNIX compiler, for compatibility with other implementations of PL/I. See . ENVIRONMENT Options That Are Ignored lists these options:

. ENVIRONMENT Options That Are Ignored

Option

Usage

Specify At

Valid I/O Types

Default Value

Data Type

BACKUP_
DATE
(variable)

Overrides the default backup date of the file.

Create Open

Record Stream

Date and time file was last backed up

BIT(64) ALIGNED

BLOCK_
BOUNDARY_
FORMAT

Indicates that records must not cross block boundaries.

Create

Record Stream

Disabled

BIT(1)

BLOCK_SIZE
(expression)

Specifies the size of a block for the creation of a magnetic tape file.

Create

Record Stream

Mount
BLOCKSIZE Value

FIXED BINARY(31)

BUCKET_SIZE
(expression)

Defines the number of 512-byte blocks in a bucket for an indexed sequential or a relative file.

Create

Record

Maximum record size

FIXED BINARY(31)

CARRIAGE_
RETURN_
FORMAT

Indicates that records in the file will be printed with default carriage control.

Create

Record

Enabled

BIT(1)

CONTIGUOUS

Specifies that an output file must be placed in a physically contiguous extent on disk.

Create

Record Stream

Disabled

BIT(1)

CONTIGUOUS_
BEST_TRY

Requests that if possible an output file be placed in a physically contiguous extent on disk.

Create

Record Stream

Disabled

BIT(1)

CREATION_
DATE (variable)

Overrides default creation date of the file.

Create

Record Stream

Current date and time

BIT(64) ALIGNED

DEFERRED_
WRITE

Requests file system optimization of output.

Create Open

Record

Disabled

BIT(1))

EXPIRATION_
DATE(variable)

Defines the expiration date for a magnetic tape file.

Create

Record Stream

Creation date

BIT(64) ALIGNED

EXTENSION_
SIZE(expression)

Specifies a default extension size for a disk file.

Create Open

Record Stream

System default

FIXED BINARY(31)

FILE_SIZE
(expression)

Defines the initial number of blocks to be allocated for a file.

Create

Record Stream

Not applicable

FIXED BINARY(31)

INDEX_NUMBER (expression)

Specifies the initial index to use in accessing records in an indexed sequential file.

CreateOpen

Record

Disabled

FIXED BINARY(31)

INDEXED

Defines an indexed sequential file.

Open

Record

Disabled

BIT(1)

INITIAL_FILL

Specifies that the initial fill value specified when the file was created is to be used.

Open

Record

Enabled

BIT(1)

MAXIMUM_
RECORD_
NUMBER (expression)

Specifies the largest record number that will be valid for records in a relative file.

Create

Record

0

FIXED BINARY(31)

MULTIBLOCK_
COUNT
(expression)

Specifies the number of blocks to be allocated for file system buffering.

Create Open

Record

Current process default

FIXED BINARY(31)

MULTIBUFFER_
COUNT (expression)

Specifies the number of buffers to be allocated for file system buffering.

Create Open

Record

Current process default

FIXED BINARY(31)

NO_SHARE

Prohibits all types of shared access to the file.

Open

Record

ISAM only

Enabled

BIT(1)

READ_AHEAD

Requests file system optimization on read operations.

Open

Record Stream

Disabled

BIT(1)

READ_CHECK

Requests verification of read operations.

Create Open

Record Stream

Disabled

BIT(1)

RETRIEVAL_
POINTERS
(expression)

Specifies the number of file system extent pointers to be maintained for file access.

Create Open

Record Stream

Current system default

FIXED BINARY(31)

REVISION_DATE (variable)

Overrides the default revision date of the file.

Close

Record Stream

Date and time file is closed

BIT(64) ALIGNED

SHARED_WRITE

ALLOWS OTHER USERS TO READ AND WRITE RECORDS IN THE FILE.

create open

Record

ISAM only

Disabled

BIT(1)

SUPERSEDE

Replaces an existing file with the same file name, file type, and version number.

Create

Record Stream

Enabled

BIT(1)

SYSTEM_
PROTECTION (expression)

Defines the type of file access allowed to users with system user identification codes (UICs).

Create

Record Stream

Current process default

CHAR(4)

TRUNCATE

Specifies that any unused space allocated for a file be deallocated when the file is closed

Create Open Close

Record

Enabled

Bit(1)

WRITE_BEHIND

Requests file system optimization on output operations.

Create Update

Record Stream

Disabled

BIT(1)

WRITE_CHECK

Requests verification of output operations.

Create Update

Record Stream

Disabled

BIT(1)

APPEND Option
Valid Dialects: ansi, dec

The APPEND option opens an existing file for output so that new records are added following the current end-of-file. The format of this option is as follows:

APPEND [ (boolean-expression) ]

 
Rules
  • The APPEND option is meaningful only when an existing file is opened with the OUTPUT attribute. It overrides the default action for opening an output file, which is to create a new file or overwrite an existing file.
  • If the APPEND option is specified when a file is created, the option is ignored; that is, if the file does not exist, a new file is created.
Usage

Use the APPEND option to open a file and position it at the end-of-file. For example, to add records at the end of a file, you can open the file as follows:

DECLARE LISTFILE FILE SEQUENTIAL OUTPUT;

 

OPEN FILE(LISTFILE) ENVIRONMENT(APPEND);

 

This OPEN statement opens the file LISTFILE. The file is positioned at its current end-of-file.

BLKSIZE Option
Valid Dialects: ibm

The BLKSIZE option sets the size of a buffer in BUFFERED file. This option is valid only with BUFFERED files and is ignored otherwise. The format of this option is:

BLKSIZE(size)

 

size

A positive integer or a fixed binary(31) static variable specifying the maximum block size for the file. Valid values range from the current record size to 32767 bytes. Note that the actual length of a variable-length record includes the four control bytes containing length information.

Although PL/I provides a default of the current record size, this default will not give you any of the advantages of buffered I/O. To improve performance when using buffers to write to a file, specify a block-size that is a multiple of the record size plus any control bytes.

CONSECUTIVE Option
Valid Dialects: ibm

The CONSECUTIVE option specifies that records in a file are placed in physical sequence. Once the location of one record is determined, the next record location can be determined by its physical position in the file.

CONSECUTIVE [ (boolean-expression) ]

 
Rules
  • The CONSECUTIVE option is valid when a file is created.
Usage

The CONSECUTIVE option is enabled by default; you need not specify it explicitly.

DEFAULT_FILE_NAME Option
Valid Dialects: ansi, dec

The DEFAULT_FILE_NAME option specifies default file name for a file. Its format is:

DEFAULT_FILE_NAME [ (character-expression) ]

 
character-expression

Is a character-string expression.

Rules
  • The DEFAULT_FILE_NAME option is meaningful when a file is created or opened.
  • The character-expression may optionally containing an asterisk (*). If there is no asterisk in the character expression, an asterisk is assumed to be at the rightmost end. The maximum length of the string is 128 characters.
  • The value of the TITLE option is inserted in the position of the (assumed) asterisk.

The next example shows how to open the file /usr/users/tim/employee.dat:

OPEN FILE (INFILE) INPUT TITLE('employee')

ENVIRONMENT(DEFAULT_FILE_NAME('/usr/users/tim/*.dat'));

 

The following example shows how to open the file /tmp/workfile:

OPEN FILE (INFILE) INPUT TITLE('workfile')

ENVIRONMENT(DEFAULT_FILE_NAME('/tmp/'));

DELETE Option
Valid Dialects: ansi, dec

The DELETE option specifies that the file is to be deleted when it is closed. The format of this option is:

DELETE [ (boolean-expression) ]

 
Rules
  • The DELETE option can be specified when a file is created, opened, or closed.
  • Once the DELETE option has been enabled for a file on a particular open, it cannot be disabled.
  • The DELETE option can not be used on an indexed sequential file.
Usage

Use this option to delete an existing file. For example:

DECLARE INFILE FILE;

OPEN FILE (INFILE) ENVIRONMENT (DELETE);

CLOSE FILE(INFILE);

 

When this CLOSE statement is executed, the file associated with the PL/I file constant INFILE is deleted.

F, FB, FS, or FSB Option
Valid Dialects: ibm

The F, FB, FS, and FSB options all equate to the dec/ansi dialect FIXED_LENGTH_RECORDS option. Blocking and spanning are unsupported. The format of this option is:

F [ (boolean-expression) ]

 

See See FIXED_LENGTH_RECORDS Option for more information.

FILE_ID Option
Valid Dialects: ansi, dec

When the FILE_ID option is specified in the opening of an existing file, PL/I uses the value specified in the FILE_ID option to locate the file. The format of the option is:

FILE_ID(variable-reference)

 
variable-reference

Specifies the name of the 6-element array variable containing the file identification. See See FILE_ID_TO Option for information on obtaining the file identification when you create a file.

The variable must be declared as (6) FIXED BINARY(31) and must be connected.

Rules
  • The FILE_ID option is valid only when an existing file is opened.
  • This option conflicts with the TITLE, DEFAULT_FILE_NAME, and FILE_ID_TO options.
  • If there is no file with the indicated file identification, the UNDEFINEDFILE condition is signaled.
  • This option is provided only for use with the TEMPORARY option. You must specify the FILE_ID option to reopen a file that was created with the TEMPORARY option.
FILE_ID_TO Option
Valid Dialects: ansi, dec

Use the FILE_ID_TO option to obtain the file identification when you create a file. Its format is:

FILE_ID_TO(variable-reference)

 
variable-reference

Specifies the name of the 6-element array variable. PL/I returns the file identification of the created file to this variable.

You must declare the variable as (6) FIXED BINARY(31), and it must be connected.

Rules
  • The FILE_ID_TO option is meaningful when a file is created or opened.
  • FILE_ID_TO option conflicts with the FILE_ID option.
  • This option can only be used with temporary files.
Usage

This option allows you to save the internal file identification of a file created with the TEMPORARY option so that you can access the file later and eventually delete it.

For an example of the FILE_ID_TO and FILE_ID options used for temporary files, see the following description of the TEMPORARY option.

FIXED_LENGTH_RECORDS Option
Valid Dialects: ansi, dec

The FIXED_LENGTH_RECORDS option specifies that all records in the file are to be of the same length. If you do not specify this option when you create a file, the records in the file will be variable length by default. The format of this option is:

FIXED_LENGTH_RECORDS [ (boolean-expression) ]

 
Rules
  • The FIXED_LENGTH_RECORDS option must be specified at both creation and open time.
  • The FIXED_LENGTH_RECORDS option conflicts with the combination of the STREAM and OUTPUT file description attributes.
Usage

When the FIXED_LENGTH_RECORDS option is specified for the creation of a file, the size of each record can be specified with the MAXIMUM_RECORD_SIZE option. If MAXIMUM_RECORD_SIZE is not specified, PL/I provides a default length of 512 bytes for stream files and a default length of 480 bytes for relative files. There is no default for indexed files.

GROUP_PROTECTION Option
Valid Dialects: ansi, dec

The GROUP_PROTECTION option defines the type of access to be permitted to the file by other users in the owner's group (also see id(1)). The format of this option is:

GROUP_PROTECTION (character-expression)

 
character-expression

Is a 1- to 4-character string expression indicating the access privileges to be granted to users in the owner's group. The expression can contain any of the following letters to indicate the access allowed:

r -- Read access is allowed.

w -- Write/delete access is allowed.

x -- Execute access is allowed.

Letters can be repeated, but the maximum length of the string is 4 characters. The character-expression string is case insensitive; "W" and "w" are equivalent.

For compatibility with OpenVMS implementations of PL/I, you can use "d" as a synonym for "w", and "e" as a synonym for "x". All other characters are invalid. If any other character is present in the string, the UNDEFINEDFILE condition is signaled.

Rules
  • The GROUP_PROTECTION option is meaningful only when a file is created.
  • If no protection options are specified, PL/I applies the current system or process default protection (see umask(1)). If any protection options are specified, the protection for unspecified user categories defaults to no access.
MAXIMUM_RECORD_SIZE Option
Valid Dialects: ansi, dec

The MAXIMUM_RECORD_SIZE option specifies the largest size that records in a file can have. The actual meaning of this option varies according to the type of file:

  • For a file with fixed-length records, the maximum record size indicates the size of each record in bytes.
  • For a file with variable-length records, the maximum record size is the size in bytes of the largest record that can be written to the file.

The format of this option is:

MAXIMUM_RECORD_SIZE(integer-expression)

 
integer-expression

Is a numeric expression with values in the range 1 to 32,767. A value of 0 indicates that there is no user-defined limit to the size of records.

If the value is out of range, the UNDEFINEDFILE condition is signaled.

Rules

The MAXIMUM_RECORD_SIZE option is meaningful when a file is created and when it is opened. If the specified opened size does not match the specified created size, the results are undefined. If not specified, PL/I provides a default length based on the file organization and record format as follows:

. Default Record Sizes

File Organization

Record Format

Default

Sequential

Fixed length

512

Sequential

Variable length

510

Relative

Fixed or variable length

480

OWNER_PROTECTION Option
Valid Dialects: ansi, dec

The OWNER_PROTECTION option defines the type of access to be permitted to the file by the file's owner and by other users with the same user identification (UID). Refer to id(2) for more information. The format of this option is:

OWNER_PROTECTION (character-expression)

 
character-expression

Is a 1- to 4-character string expression indicating the access privileges to be granted to the file's owner. The character-string expression can contain any of the following letters to indicate the access allowed:

r -- Read access is allowed.

w -- Write/delete access is allowed.

x -- Execute access is allowed.

Letters can be repeated, but the maximum length of the string is 4 characters. The character-expression string is case insensitive; "W" and "w" are equivalent.

For compatibility with OpenVMS implementations of PL/I, you can use "d" as a synonym for "w", and "e" as a synonym for "x". All other characters are invalid. If any other character is present in the string, the UNDEFINEDFILE condition is signaled.

Rules
  • The OWNER_PROTECTION option is meaningful only when a file is created.
  • If no protection options are specified, PL/I applies the current system or process default protection (see umask(1)). If any protection options are specified, the protection for unspecified user categories defaults to no access.
RECORD_ID_ACCESS Option
Valid Dialects: ansi, dec

The RECORD_ID_ACCESS option indicates that the records in a file will be accessed randomly, using the internal identification of the records. The format of this option is:

RECORD_ID_ACCESS [ (boolean-expression) ]

 
Rules
  • The RECORD_ID_ACCESS option is meaningful when a file is created or opened.
Usage

You must open a file with this option to use the RECORD_ID_TO and RECORD_ID options of the record I/O statements. See See , See Input/Output Statement Options for more information.

When a file is opened with the RECORD_ID_ACCESS option, access by record identification can be mixed with sequential access or access by key during this opening. However, a statement cannot specify a record both by key and by record identification.

RECSIZE Option
Valid Dialect: ibm

The RECSIZE option specifies the largest size that records in a file can have. The actual meaning of this option varies according to the type of file:

  • For a file with fixed-length records, the maximum record size indicates the size of each record in bytes.
  • For a file with variable-length records, the maximum record size is the size in bytes of the largest record that can be written to the file.
  • For a stream file, the RECSIZE option is the same as specifying a LINESIZE on the OPEN statement. Note that specification of LINESIZE on the OPEN statement overrides a prior specification of RECSIZE on the declaration.

The format of this option is:

RECSIZE(integer-expression)

 
integer-expression

Is a numeric expression with values in the range 1 to 32,767. A value of 0 indicates that there is no user-defined limit to the size of records.

If the value is out of range, the UNDEFINEDFILE condition is signaled.

Rules

If RECSIZE is not specified, PL/I provides a default length based on the file organization and record format as follows:

. Default Record Sizes

File Organization

Record Format

Default

Sequential

Fixed length

512

Sequential

Variable length

510

Relative

Fixed or variable length

480

SCALARVARYING Option
Valid Dialects: ansi, dec, ibm

The SCALARVARYING option specifies that character strings with the VARYING attribute be read and written in strict accordance with the PL/I ANSI standard. Its format is as follows:

SCALARVARYING [ (boolean-expression) ]

 
Rules
  • The SCALARVARYING option is meaningful when a file is created or opened.
  • SCALARVARYING conflicts with the STREAM file description attribute.
Usage

The SCALARVARYING option has the following effect on I/O operations involving VARYING character-string variables:

  • When a record is written from a varying-length character string, the entire storage of the string is written, including the word containing the string's current length.
  • When a record is read into a varying-length character-string variable, the first word of the record is read into the variable's current length field.

Thus, records to be read into or from variables with the VARYING attribute should be images of a varying character string -- including the 2-byte count field at the beginning of the string.

When SCALARVARYING is not specified, character-string variables with the VARYING attribute are handled so as to facilitate reading and writing files with variable-length records. The rules are as follows:

  • On an input operation, the entire record read into the variable is treated as a character string and assigned to the variable. Thus, the current length of the variable is always set to the record length of the record read, unless truncation occurs.
  • On an output operation, only the characters of the string's current value are written.

For strings with the VARYING attribute that are embedded in arrays or structures, the entire storage is always read or written.

When a file is to be read with SCALARVARYING in effect, the target variable must be declared CHARACTER VARYING, and the length of the target variable must match the record length of each record in the file, minus two bytes. If the length does not match, the ERROR condition is signaled.

The following example illustrates reading a file with the SCALARVARYING option (presumably the file was created with the SCALARVARYING option in effect):

DECLARE EOF BIT(1) ALIGNED INITIAL('0'B);

DECLARE STRING CHARACTER(80) VARYING,

INFILE FILE RECORD INPUT;

OPEN FILE(INFILE) ENVIRONMENT(SCALARVARYING);

ON ENDFILE(INFILE) EOF = '1'B;

READ FILE(INFILE) INTO(STRING);

DO WHILE (^EOF);

PUT SKIP LIST(LENGTH(STRING),STRING);

READ FILE(INFILE) INTO(STRING);

END;

 

The file defined as INFILE must have 82-byte records: the first two bytes of each record must contain the length of the data within the record. This READ statement reads 82 bytes, and uses the first two as the length and contents of each string.

SHARED_READ Option
Valid Dialects: ansi, dec

The SHARED_READ option specifies that other users who have concurrent access to the file can read records in it. The format of this option is:

SHARED_READ [ (boolean-expression) ]

 
Rules
  • The SHARED_READ option is meaningful when a file is created or opened.
  • The SHARED_READ option conflicts with the NO_SHARE option.
Usage

By default, the SHARED_READ option is disabled when a file is opened for output or update; that is, sharing is not allowed by default if anyone is writing to the file. SHARED_READ is enabled when a file is opened for input, that is, sharing is allowed if no one is writing to the file.

SUPERSEDE Option
Valid Dialects: ansi, dec

The SUPERSEDE option specifies that if a file already exists with the same name and type, it will be deleted and a new file created in its place. This is the default. The format of this option is:

SUPERSEDE [ (boolean-expression) ]

Rules
  • The SUPERSEDE option is meaningful only when a file is created.
  • The SUPERSEDE option conflicts with the APPEND option.
Compatibility Note
  • On VAX VMS, the default is not to supersede.
Usage

By default, the file system creates a new file whenever a file is opened for output.

TEMPORARY Option
Valid Dialects: ansi, dec

The TEMPORARY option creates a temporary file name using tempnam(3s). The format of this option is:

TEMPORARY [ (boolean-expression) ]

 
Rules
  • The TEMPORARY option is meaningful only when a file is created.
  • The TEMPORARY option conflicts with the TITLE and the DEFAULT_FILE_NAME options.
Usage

When you create a file with the TEMPORARY option, the file system calls tempnam(3s) to create a uniquely named temporary file. A file thus created can be used during the execution of the program and deleted on completion, without cluttering up the current working directory.

The file can be deleted when it is closed or, if needed later, can be deleted after it has been reused. You specify deletion by using the DELETE option when you open, reopen, or close the file.

However, because the name of the temporary file is not available to a PL/I application, the file can be reaccessed only by its internal file identification. You can obtain this identification by specifying the FILE_ID_TO option when the file is created. For example:

DECLARE WORKFILE FILE OUTPUT SEQUENTIAL,

WORKFILE_ID (6) FIXED BINARY(31);

OPEN FILE(WORKFILE) ENVIRONMENT (

TEMPORARY,

FILE_ID_TO(WORKFILE_ID));

 

CLOSE FILE(WORKFILE);

 

OPEN FILE (WORKFILE) ENVIRONMENT (

FILE_ID(WORKFILE_ID),

DELETE);

 

These statements declare the file WORKFILE, open it with the FILE_ID_TO option, close it, and later reopen it, using the FILE_ID option and specifying the file identification obtained when the file was first opened. The second OPEN statement also specifies the DELETE option of ENVIRONMENT, so that the file is deleted when it is subsequently closed.

V, VB, VS, or VSB Option
Valid Dialects: ibm

The V, VB, VS, and VSB options all equate to the variable length record format, which is the default record format for all dialects. Blocking and spanning are unsupported.

V [ (boolean-expression) ]

 
Rules
  • The V option is valid when a file is created.
Usage

The variable record format is enabled by default; you need not specify it explicitly.

WORLD_PROTECTION Option
Valid Dialects: ansi, dec

The WORLD_PROTECTION option defines the type of access to be permitted to the file by users who are not in the owner's group and who are not the superuser. Refer to id(1). The format of this option is:

WORLD_PROTECTION(character-expression)

 
character-expression

Is a 1- to 4-character string expression indicating the access privileges to be granted to users in the world category. The character-string expression can contain any of the following letters to indicate the access allowed:

r -- Read access is allowed.

w -- Write/delete access is allowed.

x -- Execute access is allowed.

Letters can be repeated, but the maximum length of the string is 4 characters. The character-expression string is case insensitive; "W" and "w" are equivalent.

For compatibility with OpenVMS implementations of PL/I, you can use "d" as a synonym for "w", and "e" as a synonym for "x". All other characters are invalid. If any other character is present in the string, the UNDEFINEDFILE condition is signaled.

Rules
  • The WORLD_PROTECTION option is meaningful only when a file is created.
  • If no protection options are specified, PL/I applies the current system or process default protection (see umask(1)). If any protection options are specified, the protection for unspecified user categories defaults to no access.
ENVIRONMENT Options for File Protection and File Sharing

This section discusses the ENVIRONMENT options that take advantage of special processing options for file protection and file sharing.

File Protection

Each user who is authorized to use the system is assigned a user identification (UID) and a group id (GID) by the system manager. When a PL/I program creates a file, the current UID associated with the process executing the program defines the file's ownership.

Based on this UID, called the owner UID, the file system defines the file protection in terms of which users on the system can access the file and what operations they can perform on the file. These users are defined as follows:

The types of permissions defined for a file are:

The types of permissions defined for a directory are:

The difference between read access and execute access is that you are allowed to perform wildcard operations on a directory you have read access to, but you must know the exact pathname of a file in a directory to which you have only execute access.

You can explicitly control the protection applied to a file by specifying the type of access allowed each category of user.

In a PL/I program, you can specify file protection when you create the file.

Defining File Protection

When you specify ENVIRONMENT options for a file you are creating in a PL/I program, you can specify the following options to define the access permitted to various users:

OWNER_PROTECTION

GROUP_PROTECTION

WORLD_PROTECTION

These options specify the types of access permitted by the specification of the following codes:

r -- gives the right to read the file.

w (or d) -- gives the right to modify or delete the file.

x (or e) -- gives the right to execute executable files.

These codes can be specified in any order for an option; if you specify an option and omit a code, that category of user is denied that type of access. If you specify one or more protection options, the protection for unspecified categories defaults to no access. If you do not specify any protection options, then PL/I uses the current default protection (umask) for all the categories.

For example:

ENVIRONMENT (

OWNER_PROTECTION ('rwx')

GROUP_PROTECTION('w'))

WORLD_PROTECTION ('r')

 

This specification defines protection to a file as follows:

Note that the UNIX command chmod lets the owner of a file change file permissions at any time. Additional commands and user privileges let users override or change file permissions. For details on these commands and privileges, see umask(1).

The file system applies the permissions you specify for a file when the file is accessed from a program or from the command level. It also applies the permissions when the file is shared.

File Sharing

PL/I lets multiple programs access records in the same file concurrently. All files are opened for SHARED_READ and access is controlled by the UNIX-level permissions on the file. Any number of programs can read records in a PL/I file providing they have access to the file.

 

 

Input/Output Statement Options

PL/I lets you specify the OPTIONS keyword on input/output statements and supports certain options for each statement. This chapter explains how to code options for I/O statements, summarizes the valid options for each I/O statement, and describes each option individually.

Option Format

Use the OPTIONS keyword and an options list in a statement to specify I/O statement options. Enclose the options list in parentheses and separate individual options by commas, as follows:

OPTIONS (option,...) ;

 

Following is an example of the I/O statement GET with three options, PROMPT, NO_ECHO, and PURGE_TYPE_AHEAD:

GET LIST (PASSWORD) OPTIONS (PROMPT('Enter password: '),

NO_ECHO, PURGE_TYPE_AHEAD);

 

Any option that does not require an argument can be followed by a Boolean expression in the following format:

option(Boolean-expression)

 

where Boolean-expression is a bit string of length 1, '1'B for true or '0'B for false. If you specify the option in the option list and do not specify a Boolean expression, the default value of `true' is supplied.

Summary of Input/Output Statement Options

See . Summary of Input/Output Statement Options lists the I/O options, their uses, the statements for which they are valid, and their data types.

. Summary of Input/Output Statement Options

Option

Usage

Valid Statements

Data Type

CANCEL_CONTROL_O 7

Disables effect of CTRL/O prior to terminal output.

PUT

BIT(1)

FAST_DELETE 8

Deletes a record without updating alternate indexes.

DELETE

BIT(1)

NO_ECHO

Suppresses display of input data on a terminal.

GET

BIT(1)

NO_FILTER

Sets UNIX raw mode
(see stty(1) for more information)

GET

BIT(1)

PROMPT (expression)

Writes a prompting message prior to an input operation.

GET

CHAR(*)

PURGE_TYPE_AHEAD

Clears the terminal type-ahead buffer before reading input data.

GET

BIT(1)

RECORD_ID (variable)

Accesses a record based on its internal identification.

DELETE READ REWRITE

(2) FIXED BINARY (31)

RECORD_ID_TO (variable)

Returns the value of a record's internal identification.

READ REWRITE WRITE

(2) FIXED BINARY (31)

NO_ECHO Option

The NO_ECHO option specifies, when the input device is a terminal, that the data entered at the terminal will not be displayed as it is entered.

Rules
  • The NO_ECHO option is valid only on a GET statement.
  • This option is ignored if the input device is not a terminal.
  • This option remains in effect only for the current statement; then it is reset to false.
Usage

Use the NO_ECHO option when you want to keep data entered at a terminal from being seen by users other than the one who entered the data. For example, if you request a password, the NO_ECHO option protects the password, as follows:

GET LIST (PASSWORD) OPTIONS (NO_ECHO,

PROMPT('Enter Password: '));

 

Data entered in response to this GET statement is not displayed on the terminal.

PROMPT Option

The PROMPT option specifies, when the input device is a terminal, a character-string prompt to be displayed before actual input. The format of this option is:

PROMPT (string-expression)

 
string-expression

Specifies a 1- to 254-character string expression.

Rules
  • The PROMPT option is valid only on a GET statement.
  • This option is meaningful only when the input device is a terminal.
Usage

Unlike a PUT statement followed by a GET statement, a GET statement with the PROMPT option is actually executed as a single statement. For example:

GET LIST (NUM) OPTIONS (PROMPT('Enter number: '));

 

When this statement is executed, the terminal display will be as:

Enter number: 44

 

The prompting string and the input data occur in the same statement.

The PROMPT option causes any data that was not processed by the last GET operation to be ignored. If the SKIP option is not specified, the prompt is output at the current cursor position. If you specify the SKIP option in conjunction with the PROMPT option, the SKIP operation is performed before the prompting message is displayed.

PURGE_TYPE_AHEAD Option

The PURGE_TYPE_AHEAD option specifies, when the input device is a terminal, that all data in the terminal's type-ahead buffer be deleted before the input operation is performed.

Rules
  • The PURGE_TYPE_AHEAD option is valid only on a GET statement.
  • This option is ignored if the input device is not a terminal.
Usage

When a command or program is being executed, the terminal keyboard accepts input data and stores it in a buffer called the type-ahead buffer. When the command or program is completed, the command interpreter reads its next command from the type-ahead buffer. When a GET statement is executed with this option in effect, any data in the type-ahead buffer is deleted, ensuring that the GET statement will not read any extraneous data.

RECORD_ID Option

The RECORD_ID option indicates that the record of interest is specified by its record identification. The format of this option is:

RECORD_ID (variable-reference)

 
variable-reference

Specifies the name of a 2-element array variable containing the record identification.

The variable must be declared as (2) be connected.

Rules
  • The RECORD_ID option is valid on a READ, REWRITE, or DELETE statement.
  • RECORD_ID conflicts with the KEY option on the READ, REWRITE, or DELETE statement.
  • The file on which the operation is being performed must have been opened with the ENVIRONMENT option RECORD_ID_ACCESS.
  • If the file is an indexed sequential file, the RECORD_ID option resets the value of the current index number to 0.
Usage

The following example illustrates a record whose record identification is saved for a later file access.

DECLARE

BOOKFILE FILE RECORD KEYED,

INBUF CHARACTER(180) VARYING,

SAVE_RECORD_ID(2) FIXED BINARY(31),

KEYVALUE CHARACTER(10);

OPEN FILE(BOOKFILE) ENV(RECORD_ID_ACCESS);

READ FILE(BOOKFILE) INTO(INBUF) KEY(KEYVALUE)

OPTIONS(RECORD_ID_TO(SAVE_RECORD_ID));

CLOSE FILE(BOOKFILE);

OPEN FILE(BOOKFILE) INPUT ENV(RECORD_ID_ACCESS);

READ FILE(BOOKFILE) INTO(INBUF)

OPTIONS(RECORD_ID(SAVE_RECORD_ID));

 

During the first opening of the file, the record identification of a specified record is obtained and saved. When the file is subsequently reopened, this value is used to access a record and to effectively position the file at that record.

RECORD_ID_TO Option

The RECORD_ID_TO option specifies the name of a variable to be assigned the value of the record identification of the record on which the current operation is being performed. The format of this option is:

RECORD_ID_TO (variable-reference)

 
variable-reference

Is a reference to a 2-element array variable that will receive the value of the record's identification.

The variable must be declared as (2) FIXED BINARY(31) and must be connected.

Rules
  • The RECORD_ID_TO option is valid on the READ, WRITE, and REWRITE statements.
  • The file on which the operation is being performed must have been opened with the RECORD_ID_ACCESS option of the ENVIRONMENT attribute.

 

 

File-Handling Built-In Subroutines

In addition to the PL/I input and output statements and the functions and features available through the options of the ENVIRONMENT attribute, there are also two built-in file-handling subroutines. They are called built-in subroutines because you do not need to declare them before using them in a PL/I program. The subroutines are:

Both of these subroutines are valid only in the dec dialect.

The following sections describe the FLUSH an dREWIND routines.

FLUSH Built-In Subroutine (DEC Dialect Only)

The FLUSH built-in subroutine writes all file buffers that have been modified and preserves all of the file attributes of the file. This subroutine provides the ability to checkpoint a file during its processing and ensure its integrity. Its calling sequence is:

CALL FLUSH (file-reference);

 
file-reference

Specifies the name of the file variable or file constant associated with the file whose buffers are to be flushed. If the file is not currently opened, the FLUSH subroutine performs no operation.

Use the FLUSH subroutine to explicitly request PLI to write all internal file buffers back to the file. This subroutine is called implicitly by the REWIND built-in subroutine.

REWIND Built-In Subroutine (DEC Dialect Only)

The REWIND built-in subroutine positions a file so that the next record to be read will be the first record in the file. Its calling sequence is as follows:

CALL REWIND (file-reference);

 
file-reference

Specifies the name of the file constant or file variable associated with the file to be rewound. If the file is not currently open, the REWIND subroutine implicitly opens the file with the attributes specified in the declaration of the file.

Use this subroutine to begin processing a file at its logical beginning. This subroutine is valid for disk files of all organizations. The position of the file following the call to the REWIND subroutine is:

  • A sequential file is positioned at its first record.
  • A relative record file is positioned at the first occupied cell.

You can also use the REWIND built-in subroutine to reposition a stream file after an end-of-file condition. Normally, if end-of-file (Ctrl/D on a terminal) is entered during an input operation on a stream input file, the PL/I program must close the input file and reopen it before any more data can be read. However, an ENDFILE ON-unit can be written as:

ON ENDFILE(STREAMFIL) CALL REWIND(STREAMFIL);

 

This ON-unit calls the REWIND built-in subroutine each time an end-of-file is encountered for the file constant STREAMFIL. The REWIND built-in subroutine repositions the stream file at its beginning so that the program can continue reading input.

 

Using Sort Subroutines (IBM Only)

The ibm dialect of Kednos PL/I for UNIX provides an interface to SyncSort, which must be separately licensed from Syncsort Incorporated.

To use the sort routines, insert code in your program to call one of the Sort program's entry points. The call passes information on the fields to be sorted. You must specify information about the data to be sorted, the type of sort to perform, the format and destination of the output, and so on.

The Sort program called by Kednos PL/I for UNIX provides a flexible interface with wide functionality. You define the sorting field in each record, the type of sort, and what types of error messages to display. You can also specify whether the data originates and/or is output to a file or a user-written routine.

The following sections describe how to use the sort routines.

General Information

Before writing the call to the Sort program, you must determine the following:

This section contains information on the PL/I sorting interface. Understanding the interface will help you decide which routine to use and what to pass to the routine. The sections following See Calling the Sort Subroutines give details on each portion of the call. They contain information on what specifying sort fields, the available sort types, how to determine storage needs, and so on.

How the Sort Program Interface Works

This section contains information on sorting using the PL/I sorting interface to call the Sort program, a separately licensed external product, SyncSort. Understanding the interface will help you decide which routine to use and what to pass to the routine. Kednos PL/I for UNIX contains a built-in interface to call SyncSort using the previously established IBM Sort program call syntax. This provides compatibility and portability between platforms.

The Kednos PL/I for UNIX Sort interface provides four entry points to the Sort program. Each entry point specifies a different combination of data source and destination, either from and to a file or from and to a subroutine, or a combination of the two. The entry points are described in See Determining Which Entry Point to Use .

The Sort program handles the complete sort operation. It communicates with the calling program, and any specified user-written input or output routines, by using return codes.

To use the Sort program, insert a CALL statement in your program. The CALL statements specifies one of the four Sort entry points. It must contain the correct arguments for the specified entry point. Once the Sort program is called, it does the following:

Gets records from a file or calls the specified user-written input subroutine to get records, using the selection criteria specified in the call.
  1. Sorts the records according to the sorting criteria specified in the call.
  2. Places the sorted records in a file or calls the specified user-written output routine to handle the records.
  3. Passes a return code, indicating success or failure, back to the calling program.

Note that user-written input or output routines become, for all purposes, part of the Sort program for the duration of the sort. The Sort program calls the routines at the appropriate point in processing. Return codes control the flow of control between the Sort program and the input or output routines, telling the Sort program whether it should call the routine again or continue to the next stage in processing.

Determining Which Entry Point to Use

When sorting in PL/I, the data can originate in a file and be output to another file, or it can originate and/or be output to a user-written PL/I subroutine. The simplest use of the Sort program is to sort a file and direct the results into another file. The input file must be in the default directory, and the output file will be placed in the default directory. By default, the input file is SORTIN and the output file is SORTOUT.

Using subroutines lets you manipulate the data before and/or after the sort. For example, you could read a file and sort only certain records, or you could print the resulting sorted data. Like files, input and output subroutines must exist in the default directory. The format of input and output routines is described more fully in See Input and Output Routines .

The Sort program interface provides four entry points. The following table lists the entry points to the Sort program and specifies the source and destination of data in each case:

. Entry Points for the Sort Program

Sort Subroutine Entry Point

Data Source

Data Destination

PLISRTA

File

File

PLISRTB

Subroutine

File

PLISRTC

File

Subroutine

PLISRTD

Subroutine

Subroutine

Calling the Sort Subroutines

Once you know your sort requirements and have decided on a sort routine, you can write the call to the PLISRTx routine. The following sections give the general syntax of the call and details on each required or optional argument.

General Format of the Sort Interface Call

The format of the call to any of the four sort entry points is:

CALL PLISRTx (sort-specification, record-specification, maximum-storage, return-code [,input-routine] [,output-routine] [,file-prefix,message-level] );

 
sort-specification

A character-string expression of the form:

'bSORTbFIELDS=(start1,length1,format1,order1
[,startn,lengthn,formatn,ordern] ) [,OPTION1[...,OPTIONn]]b'

 

This is a required argument.

record-specification

A character-string expression of the form:

'bRECORDbTYPE=RECTYPE[,LENGTH=(rec-length[,,min-length,
modal-length)]b'

 

This is a required argument.

maximum-storage

A fixed binary (31) expression giving the amount of storage to be used by the Sort program.

This is a required argument.

return-code

Fixed binary (31) user-supplied variable in which Sort returns a code indicating success or failure. This is a required argument.

input-routine

Name of the user-written PL/I routine that supplies records to the Sort program. Required for PLISRTB and PLISRTD; invalid otherwise.

output-routine

Name of the user-written PL/I routine that receives sorted records from the Sort program. Required for PLISRTC and PLISRTD; invalid otherwise.

file-prefix

Optional. Character string expression of four characters that replaces the default prefix `SORT' in the names of the input, output, and temporary files the Sort program uses.

message-level

Optional. Character string expression of two characters indicating how to handle the Sort diagnostic messages.

The following sections discuss each of these arguments in detail.

Specifying the Sort Fields

The sort-specification is the first argument to PLISRTx. It has the following syntax:

'bSORTbFIELDS=(start1,length1,format1,order1,
...startn,lengthn,formatn,ordern)[OPTION1[...,OPTIONn]]b'

 

b

One or more blank spaces. These blank spaces are mandatory; no other blank spaces are allowed.

start,length,format,order

The sorting information specifies the location of each sort field and how to sort by each field. You can specify multiple sets of sorting information but the total of all the lengths must be 256 bytes or less.

If you specify more than one sort field, the Sort program sorts on each field in order. In other words, it sorts on the first field, then sorts groups of records that have the same first field according to the second field, and so on.

Sort fields can overlap each other.

The following list gives details on each element of the sorting information.

start

Specifies the starting position in the record, in bytes. The first byte of data in a fixed-length string is byte 1. The first byte of data in a varying-length string is byte 5.

length

The length, in bytes, of the field. Maximum length is the maximum for the data type, as specified in the Kednos PL/I for UNIX Reference Manual.

format

The format of the data being sorted. All data passed between PL/I routines and the Sort program is in the form of character strings. The codes given below tell the Sort program what type of data is actually being sorted.

The sum of the lengths of all sort fields cannot exceed 65535 bytes.

order

The order in which records will be sorted. One of the following:

  • A -- Ascending. Example: a,b,c or 1,2,3
  • D -- Descending. Example: c,b,a or 3,2,1
OPTION1...,OPTIONn

Additional options to the Sort program. Use a comma separate any options from the preceding arguments and from each other. Do not put blank spaces between options.

The following list gives details on each additional option.

FILSZ=y

Gives the number of records in the sort. The Sort program uses this information for optimization. If y is an approximate number, precede it with the letter E.

SKIPREC=y

Specifies that the Sort program should skip y records at the beginning of the input file and sort the remaining records.

EQUALS|NOEQUALS

Specifies whether the order of records with equal sort criteria should be preserved according to the order in the input, or if it can be changed by the Sort program. You can improve sort performance by using NOEQUALS, which is the default.

Specifying Record Information

The record-specification is the second argument to PLISRTx. It has the following syntax:

'bRECORDbTYPE=RECTYPE[,LENGTH=(rec-length[,,min-length,
modal-length)]b'

 

b

One or more blank spaces. These blank spaces are mandatory; no other blank spaces are allowed.

RECTYPE

One of the following types of records:

F

fixed length

V

varying length EBCDIC

D

varying length ASCII

S

stream (newline)

LENGTH

For stream files only, LENGTH defaults to 512 bytes. The LENGTH argument is required for all other types of files. The length of a record can never exceed the value specified as rec-length. The maximum length you can specify is 32767 bytes.

rec-length

Length of the record to be sorted. For varying records, length is the maximum record length plus four bytes. This is compatible with the specification of sort record length on IBM systems. Required.

,,

two sort arguments not used in the PL/I interface. Required if you specify any of the following arguments.

min-length

The minimum length of the records being sorted, used for optimization. Used with varying length records only. Optional. Must be specified if modal-length is specified.

modal-length

The most common length of the records being sorted, used for optimization. Used with varying length records only. Optional.

Specifying Storage

You can specify storage either by declaring a fixed binary (31) variable and passing the variable to the Sort routine, or by passing a constant value. For example, either one of the following calls will invoke the Sort program PLISRTA to sort a 40-byte character record using 512,000 bytes of storage:

DECLARE RETURN_CODE FIXED BIN(31);

CALL PLISRTA(' SORT FIELDS=(1,40,CH,D) ', ' RECORD TYPE=F,LENGTH=(40) ', 512000, RETURN_CODE);

 

or:

DECLARE RETURN_CODE FIXED BIN(31);

DECLARE MAXSTORAGE FIXED BIN(31) INITIAL(512000);

CALL PLISRTA(' SORT FIELDS=(1,40,CH,D) ', ' RECORD TYPE=F,LENGTH=(40) ',MAXSTORAGE,RETURN_CODE);

 

You must specify a value for storage. Determining storage for a particular sorting operation can be complicated. One guideline is to provide enough storage so the storage can hold three sets of the records being sorted. However, this might be too much.

When using PLISRTB, PLISRTC, or PLISRTD, leave enough storage available on your system to open the files after the Sort programs use the specified amount.

In any case, do not specify an amount of storage greater than the available physical memory on your processor.

Kednos PL/I for UNIX passes the value specified for storage directly to the /MEMORY option of the SyncSort routines. For more information and guidelines on determining a value for storage, see the SyncSort Reference Guide.

Using the Return Code

The required return code argument is a variable to contain the fixed binary(31) value returned by the sort program. The sort program returns one of the following:

In your calling program, declare a fixed binary(31) variable to contain return code.

To determine success or failure of the sort, check the return code after the call to the Sort program.

For example, assume that the variable RETURN_CODE was declared for use with the Sort program. The following code calls PLISRTD to sort on a single 10-character field. Since the record is varying length, four bytes are added so the field starts at the fifth position in the record. The input and output routines are SORT_IN and SORT_OUT. After returning from the call, the code checks the success of the sort, and signals an error if necessary:

CALL PLISRTD (' SORT FIELDS=(5,10,CH,A),EQUALS ',

' RECORD TYPE=V,LENGTH=(84,,15,50) ',

256000,RETURN_CODE,SORT_IN,SORT_OUT);

IF RETURN_CODE ^= 0 THEN

DO;

PUT SKIP LIST ('Error! Return code = '||RETURN_CODE);

SIGNAL ERROR;

END;

 

Specifying Input and Output Routines

The input-routine argument is used with PLISRTB and PLISRTD. The output-routine argument is used with PLISRTC and PLISRTD. These arguments are required for the specified routines. They give the name of the user-written PL/I routine that supplies records to or accepts records from the Sort program. The specified routines must exist in the default directory. See See Input and Output Routines for more information on writing routines for use with the Sort program. See the preceding section for an example of calling PLISRTD, specifying the user-written input routine SORT_IN and the user-written output routine SORT_OUT.

Specifying a File Prefix

The optional file prefix argument lets you replace the default prefix `SORT' in the names of the input, output, and temporary files the sort program uses. Using a file prefix lets you invoke the sort program multiple times and use different file prefixes so invocations do not interfere with each other. For example, you can specify 'TEMP' for the file prefix, as shown in the following example:

CALL PLISRTA(' SORT FIELDS=(1,40,CH,D) ', ' RECORD TYPE=F,LENGTH=(40) ',STOR,RETURN_CODE,'TEMP');

 

In this case, the sort program uses the files TEMPIN, TEMPOUT, TEMPWRK01 to TEMPWRKnn, TEMPCNTL, and TEMPCKPT.

The file prefix must be four characters starting with an alphabetic character. It can not be the reserved prefix LIST. Note that the names PEER, BALN, CRCX, OSCL, POLY, and DIAG are reserved file prefixes in other implementations of PL/I. Avoid using these for a file prefix if you are concerned about compatibility.

If you omit this argument but require the message-level argument, specify a null string ('') in place of the file prefix argument.

Specifying Message Level

The message-level argument indicates how the Sort program handles diagnostic messages. You can specify one of the following:

If you omit the file-prefix argument but require the message-level argument, specify a null string ('') in place of the file prefix argument. For example, the following call invokes PLISRTB to sort on the first 12 characters of a 30 character record in ascending order. Input is passed to the Sort program by a user-written routine called READ_DATA, the file prefix is defaulted to SORT, and no messages are passed back:

CALL PLISRTB(' SORT FIELDS=(1,12,CH,A) ', ' RECORD TYPE=F,LENGTH=(30) ',MAXSTORAGE,RETURN_CODE, READ_DATA,' ','NO');

Input and Output Routines

When sorting in PL/I, the data can originate in a file and be output to another file. This is done using PLISRTA, the simplest interface.

Input and output routines give you additional flexibility. When using routines PLISRTB, PLISRTC, and PLISRTD, your sort data can originate and/or be output to a user-written routine. These input and output routines are written in PL/I. They can be either internal or external procedures. If they are internal to the calling program (the program routine with the call to the Sort program), the input and output routines follow the usual scoping rules. Whether or not the routines are internal to the calling program, the input and output routine names must be known within the scope of the block containing the call.

The Sort program calls the input and output routines once for each record being sorted. Therefore, write each routine to handle one record at a time. Note that this means automatic variables will not retain their value between calls. If a variable, such as a counter, must retain its value between calls, either declare it STATIC or declare it in the containing block.

Using the PLIRETC Built-In Subroutine

The PLIRETC built-in subroutine lets you set a return code. Use PLIRETC in your input and output routines to return a value to the Sort program. This can also be used in conjunction with the PLIRETV built-in function for purposes other than sorting.

The format of the subroutine call is:

CALL PLIRETC(return-code)

 

return-code

A fixed binary(15) value.

Writing Input Routines

Use an input routine to manipulate the data in some way before sorting it. For example, you might want to print the data or generate or modify the sorting fields.

The input routine and the Sort program communicate using calls to PLIRETC. Sort allows three PLIRETC return codes when calling an input routine:

Calls made to PLISRTB or PLISRTD require an input routine. When using an input handling routine, the sort processing is as follows:

Your program calls PLISRTB or PLISRTD.
  1. The Sort program assumes control and calls the input routine.
  2. The input routine assumes control and does the following:
  3. The input routine checks to see if there are any more records to sort. If not, it calls PLIRETC with a return-code of 8.
  4. If there are records, the input routine does any processing required, then calls PLIRETC with a return-code of 12, and RETURNs, passing back a record in character-string format.
  5. The Sort program assumes control again and processes the record. It continues to call the input routine and receive records until it receives a return code of 8.
  6. The Sort program sorts all the records.
  7. The Sort program either writes the sorted records to the output file or calls the output routine, described in the next section.
  8. The Sort program sets up the return-code and returns to the statement after the CALL PLISRTx statement.

The input routine passes records back to the Sort program in the RETURN statement. Therefore you must specify the RETURNS attribute in the input routine PROCEDURE statement.

Returned records must be in character string format. They can be fixed or varying. Varying strings are padded differently depending on what you specify as the record format in the RECORD argument to the PLISRTx call. If you specify V, strings are not padded. If you specify F, strings are padded with blanks to the maximum length.

Example

SORT_INPUT_ROUTINE: PROCEDURE RETURNS(CHAR(80));

/* you must specify the returns attribute. For varying

   strings, the length must be the maximum length.

 

DECLARE CUST_RECORD CHARACTER(80);

DECLARE CUSTOMER_FILE FILE RECORD INPUT;

 

ON ENDFILE(CUSTOMER_FILE) BEGIN;

PUT SKIP(2) LIST('End of customer file input.');

CALL PLIRETC(8); /* signal end of input to Sort */

GOTO END_ROUTINE;

END;

 

/* Do any processing you require to get a record. */

/* For example, you could get the record from a file */

/* and then display the record. */

READ FILE (CUSTOMER_FILE) INTO (CUST_RECORD);

PUT SKIP LIST(CUST_RECORD);

/* signal Sort to include this record */

CALL PLIRETC(12);

RETURN(CUST_RECORD); /* return the record to Sort */

 

END_ROUTINE:

END SORT_INPUT_ROUTINE;

Writing Output Routines

Use an output routine to do an y post-sorting processing. For example, you might want to print the data or use the sorted data in a calculation.

The input routine and the Sort program communicate using calls to PLIRETC. Sort allows only one PLIRETC return codes when calling an input routine:

Calls made to PLISRTC or PLISRTD require an output routine. When using an output handling routine, the sort processing is as follows:

Your program calls PLISRTC or PLISRTD.
  1. The Sort program assumes control. When it requires a record, the Sort program gets it from the input file or the input routine, as described in the preceding section.
  2. The Sort program processes all of the records.
  3. The Sort program calls the output routine, passing it one record.
  4. The output routine assumes control and does the following:
  5. Processes the record as required.
  6. Calls PLIRETC with a return-code of 4.
  7. The Sort program assumes control and continues to pass records to the output routine until all the records have been processed.
  8. The Sort program sets up the return-code and returns to the statement after the CALL PLISRTx statement.

Note that the Sort program does not pass an end-of-data code to your output routine. Do any end-of-data processing after the Sort program returns to the calling program.

Example

SORT_OUTPUT_ROUTINE: PROCEDURE(CUST_RECORD);

 

DECLARE CUST_RECORD CHARACTER(80);

DECLARE NEWCUST_FILE FILE RECORD OUTPUT;

 

/* Do any processing you require. */

/* For example, you could display the record. */

PUT SKIP LIST(CUST_RECORD);

CALL PLIRETC(4); /* request the next record */

RETURN;

END SORT_OUTPUT_ROUTINE;

Programming Examples

This section contains an example of calling PLISRTA, which uses a file for both input and output, and PLISRTD, which uses input and output routines. PLISRTB and PLISRTC use a combination of files and routines. If you want to use either of those entry points, look at both of the following programs for examples.

Calling the PLISRTA Entry Point

SORT_EXAMPLE1: PROCEDURE OPTIONS(MAIN);

 

/* declare a variable to hold the code returned by the Sort

/* program

*/

DECLARE RETURN_CODE FIXED BIN(31);

 

/* call the PLISRTA entry point of the sort routine. */

 

CALL PLISRTA (' SORT FIELDS=(5,20,CH,A,25,20,CH,A,45,1,CH,A) ',

  ' RECORD TYPE=F,LENGTH=(120) ',

  4000000,

  RETURN_CODE,

  'CUST');

 

SELECT (RETURN_CODE);

WHEN(0) PUT SKIP LIST ('Sort completed successfully.');

WHEN(16) PUT SKIP LIST ('Sort failed.');

OTHERWISE

PUT SKIP LIST('Invalid Sort return code'||RETURN_CODE);

END; /*select*/

 

END SORT_EXAMPLE1;

 

The example above sorts a customer file by name. The arguments of the call to PLISRTA are:

Calling the PLISRTD Entry Point

SORT_EXAMPLE2: PROCEDURE OPTIONS(MAIN);

 

/* declare a variable to hold the code returned by the Sort

/* program

*/

DECLARE RETURN_CODE FIXED BIN(31);

 

 

/* call the PLISRTD entry point of the sort routine. */

 

CALL PLISRTD (' SORT FIELDS=(5,20,CH,A,25,20,CH,A,45,1,CH,A) ',

  ' RECORD TYPE=D,LENGTH=(124) ',

  4000000,

  RETURN_CODE,

  SORT_INPUT,

  SORT_OUTPUT,

  'CUST');

 

 

 

SELECT (RETURN_CODE);

WHEN(0) PUT SKIP LIST ('Sort completed successfully.');

WHEN(16) PUT SKIP LIST ('Sort failed.');

OTHERWISE

PUT SKIP LIST('Invalid Sort return code'||RETURN_CODE);

END; /*select*/

 

SORT_INPUT: PROCEDURE RETURNS(CHAR(120) VARYING);

/* you must specify the returns attribute. For varying

   strings, the length must be the maximum length. */

 

DECLARE CUST_RECORD CHARACTER(120) VARYING;

DECLARE CUSTOMER_FILE FILE RECORD INPUT;

 

ON ENDFILE(CUSTOMER_FILE) BEGIN;

PUT SKIP(2) LIST('End of customer file input.');

CALL PLIRETC(8); /* signal end of input to Sort */

GOTO END_ROUTINE;

END;

 

/* Do any processing you require to get a record. */

/* For example, you could get the record from a file */

/* and then display the record. */

READ FILE (CUSTOMER_FILE) INTO (CUST_RECORD);

PUT SKIP LIST(CUST_RECORD);

/* signal Sort to include this record */

CALL PLIRETC(12);

RETURN(CUST_RECORD); /* return the record to Sort */

 

END_ROUTINE:

END SORT_INPUT;

 

SORT_OUTPUT: PROCEDURE(CUST_RECORD);

 

DECLARE CUST_RECORD CHARACTER(*);

DECLARE NEWCUST_FILE FILE RECORD OUTPUT;

 

/* Do any processing you require. */

/* For example, you could display the record. */

PUT SKIP LIST(CUST_RECORD);

CALL PLIRETC(4); /* request the next record */

RETURN;

END SORT_OUTPUT;

 

END SORT_EXAMPLE2;

 

The example sorts a varying length record ASCII format customer file by customer name. The elements of the call to PLISRTD are similar to the ones in the call to PLISRTA. The differences are:

You must declare the input routine using the RETURNS(VARYING) attribute, and declare the CUST_RECORD as CHARACTER VARYING. The output routine must contain a CUST_RECORD declared as CHARACTER(*). The RECORD TYPE is D, since the file is in ASCII format with varying length records. The maximum record length is specified, including a 4 byte length prefix (compatible with the length prefix on IBM implementations of PL/I).

The two routines are internal to the main program.

 

Error Handling

In PL/I, errors are signaled through ON conditions and handled by groups of statements called ON-units. An ON condition is any one of several named conditions that interrupt program execution. When an ON condition occurs, or is signaled, the corresponding ON-unit is executed.

This chapter discusses the following topics:

Refer to the Kednos PL/I for UNIX Reference Manual for descriptions of the ON, REVERT, and SIGNAL statements and ON conditions.

RESIGNAL Built-In Subroutine

The RESIGNAL built-in subroutine is used in an ON-unit to pass a signaled condition, so that the run-time system will attempt to locate another ON-unit to handle the condition.

RESIGNAL works by setting up the internal mechanism for passing the signal. It does not by itself cause an exit from the ON-unit that calls it. Instead, it returns to the next statement in the ON-unit. Resignaling does not occur until execution of the ON-unit is completed.

The format of a statement calling the RESIGNAL built-in subroutine is:

CALL RESIGNAL();

 

When an ON-unit has determined that it cannot or should not respond to a condition, RESIGNAL permits the ON-unit to pass the signal along.

This subroutine is not part of the standard PL/I language. It is provided specifically for use in the UNIX operating system environment.

VAXCONDITION Condition

VAXCONDITION provides a general-purpose signaling mechanism for PL/I applications that execute under the control of the VMS operating system. This condition is carried to the PL/I compiler for compatibility reasons.

An ON-unit for a VAXCONDITION condition is established in the following format:

ON VAXCONDITION (expression) on-unit

 
expression

Any expression yielding a FIXED BINARY(31) value that can represent either a specific VMS condition value or status value, or an arbitrary user-specified value. The low-order three bits of the value are interpreted as the condition's severity by the default PL/I and system condition handlers. The expression is evaluated when the ON statement is executed, not when the condition is signaled.

A VAXCONDITION ON-unit can be used in conjunction with calls to system service, run-time library, or other system procedures that return status values. An error-handling routine can test the return status value from a system procedure and, if not successful, signal the error.

ON-units can exist for any number of specific values. For example:

VCND: PROCEDURE OPTIONS(MAIN);

 

%REPLACE COND1 BY 1234;

%REPLACE COND2 BY 5678;

ON VAXCONDITION(COND1), VAXCONDITION(COND2)

BEGIN;

PUT SKIP LIST ('Main handler for VAXCONDITIONs: ',

COND1,COND2);

PUT SKIP EDIT (' Caught ', oncode()) (A,F(5,0));

END;

 

P1: PROCEDURE;

 

ON VAXCONDITION(COND1)

BEGIN;

PUT SKIP EDIT ('p1: caught VAXCONDITION: ',COND1)

(A,F(5,0));

CALL RESIGNAL ();

END;

 

SIGNAL VAXCONDITION(COND1);

 

END P1;

 

P2: PROCEDURE;

 

ON VAXCONDITION(COND2)

BEGIN;

PUT SKIP EDIT ('p2: caught VAXCONDITION: ',COND2)

(A,F(5,0));

CALL RESIGNAL ();

END;

 

SIGNAL VAXCONDITION(COND2);

 

END P2;

 

CALL P1;

CALL P2;

CALL P1;

 

END VCND;

 

ON-Unit Actions

During its execution, an ON-unit can take any of the following courses of action:

These courses of action are described individually in the following subsections.

Handling the Condition

A condition is assumed to be handled in PL/I when the ON-unit established for the condition completes execution without performing one of the following actions:

When the condition is handled, PL/I continues execution of the program at the point of interruption. Normal completion of any ON-unit (except ERROR signaled as the default action) results in return of control either to the statement that caused the condition or to the statement immediately following the statement that caused the condition. However, the effects of normal return from ERROR, FIXEDOVERFLOW, OVERFLOW, UNDERFLOW, and ZERODIVIDE are generally unpredictable. Exceptions are cases of ERROR that are specifically documented to allow normal return, and ON-units that execute as a result of a SIGNAL statement. Normal return from a CONVERSION condition that modifies ONCHAR or ONSOURCE pseudovariables causes the conversion to be retried.

Resignaling the Condition

In PL/I, an ON-unit can choose not to handle a condition and can request that, rather than returning control to the point of interruption, PL/I continue to search for another ON-unit to handle the condition. It does this by calling the RESIGNAL built-in subroutine as follows:

CALL RESIGNAL();

 

The RESIGNAL built-in subroutine has no arguments.

When an ON-unit calls RESIGNAL, PL/I resumes its search of the call stack starting at the call frame beneath the frame in which it located the current ON-unit. The next example and See . Resignaling a Condition illustrate the effect of the RESIGNAL built-in subroutine. The reverse numbers indicate the order of execution. Procedure B establishes an ANYCONDITION ON-unit that handles specific VAXCONDITION values. When the ON-unit is executed as a result of a signal in either procedure B or C, it tests the current value of ONCODE to see whether it is a value of interest. If not, procedure B calls RESIGNAL.

A: PROCEDURE OPTIONS(MAIN);

ON FIXEDOVERFLOW BEGIN;

END;

CALL B;

B: PROCEDURE (X,Y); À

ON ANYCONDITION BEGIN;

IF (ONCODE() = SIGNAL_FOUND)!

(ONCODE() = SIGNAL_DONE) THEN

BEGIN;

END; /*Begin block for IF statement */

ELSE CALL RESIGNAL();

END; /* ON-unit */

CALL C;

C: PROCEDURE; Ã

/* FIXEDOVERFLOW signaled Õ

RETURN;

END;

 

See . Resignaling a Condition illustrates the preceding example.

 

. Resignaling a Condition

When the FIXEDOVERFLOW condition is signaled in procedure C, B calls RESIGNAL and PL/I continues its search of the call stack. It locates the ON-unit for handling the FIXEDOVERFLOW condition in procedure A and executes it.

Note that the default condition handling performed by PL/I uses the resignaling capability to continue signals that are not handled within the program. PL/I default condition handling is described in See Search Path for ON-Units .

Executing a Nonlocal GOTO

An ON-unit in a PL/I procedure can execute a nonlocal GOTO statement that transfers control to a previous block. In this case, PL/I releases call frames, beginning with the call frame created for the ON-unit, until it reaches the block containing the label specified in the GOTO statement.

This removal of call frames from the call stack is called an unwind. The next example and See . Unwinding the Call Stack illustrates a situation in which an unwind occurs. The reverse numbers indicate the order of execution. The ERROR ON-unit established in procedure A receives control when the ERROR condition is signaled in procedure C. This ON-unit executes the GOTO PRINT_MSG statement. The label PRINT_MSG is in procedure A. Thus, the call stack is unwound and the call frames for the ON-unit, procedure C, and procedure B, in that order, are removed from the stack, and execution continues at the label PRINT_MSG.

A: PROCEDURE OPTIONS(MAIN);

ON ERROR GOTO PRINT_MSG;

Õ

CALL B;

PRINT_MSG;

B: PROCEDURE; À

CALL C;

RETURN;

END;

C: PROCEDURE; Ã

RETURN; /* ERROR signaled */

END;

 

See . Unwinding the Call Stack illustrates the preceding example.

 

. Unwinding the Call Stack

When an unwind occurs in the UNIX environment, PL/I examines each call frame in the calling sequence to determine if a condition ON-unit exists for that frame. If so, PL/I calls the ON-unit with the condition value SS$_UNWIND, and the ON-unit has the chance to perform block- or procedure-specific cleanup operations.

Stopping the Program

You can use an ON-unit to terminate program execution. To do this, include a STOP statement in the ON-unit. For example:

ON UNDEFINEDFILE(INFILE) BEGIN;

 

PUT EDIT('File ',ONFILE(),' undefined. Error ',ONCODE())

(A,X,A,X,A,X,F(10));

STOP;

END;

 

The STOP statement performs the following actions:

Thus, when a FINISH ON-unit that has been executed as a result of a STOP statement handles the condition, control returns to the STOP statement, which then terminates the image.

If no FINISH or ANYCONDITION ON-unit exists, the program terminates.

If a FINISH or ANYCONDITION ON-unit executes a STOP statement, the program enters an infinite loop. Therefore, do not put STOP statements in FINISH or ANYCONDITION ON-units.

Relationship of UNIX Signals to PL/I ON-Units

In the UNIX environment, an exception is a hardware- or software-detected condition that synchronously or asynchronously interrupts the execution of an image. A condition handler is a procedure that exists specifically to respond to one or more such conditions; each procedure in the program can establish a condition handler. It is usually the responsibility of each handler to determine the specific condition that was signaled, and to decide whether or not to handle it.

Most high-level languages do not provide language constructs to handle exceptions; therefore, condition handlers are established by calling the UNIX Run-Time Library procedure signal(3). The PL/I language, however, uses the ON-unit condition handler to handle a specific condition. By using the keyword condition names defined by PL/I and the extensions provided by PL/I, you can write ON-units to handle any possible UNIX-specific condition. Each procedure can establish separate ON-units for each of several possible conditions that the procedure wishes to handle.

You should never use signal(3) to establish a condition handler in a PL/I call frame.

UNIX signals are mapped to PL/I signals and can be handled by on units in PL/I. The main program establishes default handlers for UNIX signals, thus this behavior is only in affect when the main program is in PL/I. PL/I runtime library establishes the default signal handler for all UNIX signals except SIGSTOP and SIGKILL which cannot be caught. For more information about UNIX signals see the signal(3) manpage.

The default handling of signals is as follows:

This signal is translated into an appropriate ONCODE. Refer to See . Corresponding Values for mapping from signal to oncode values.
  1. The normal condition handling mechanism is used to identify the appropriate PL/I condition handler to be invoked. That is, the stack is searched for an on unit that handles the condition. Floating point exceptions that are generated by hardware conditions are translated one of the following conditions:

OVERFLOW

UNDERFLOW

ZERODIVIDE

All other signals generated are handled either by a VAXCONDITION(signal) handler for the specific signal code or by the PL/I ANYCONDITION handler. As usual the specific code that caused the condition is available by calling ONCODE().

  1. If there is no ON-unit condition handler for the signal, the default action is the default action as defined by the operating system. This is described in signal(3).

Note that unlike other conditions, in the case of a UNIX signal not handled by a specific on condition handler, a PL/I ERROR condition is NOT generated. This allows UNIX signals to behave in the normal way if no condition handlers are used.

Accessing the Signal Values

Within a PL/I program the values for the UNIX signals are available in the following variables, each corresponding to one of the UNIX signals. For access to these variables, a program can GLOBALREF the variables. The standard include file, signaldef.in, contains the declarations for these variables. To include the signaldef.in file in your PL/I program, use the following statement:

%include $signaldef;

 

See . Corresponding Values identifies the correspondence between UNIX signal numbers and the corresponding ONCODE value.

. Corresponding Values

Signal

Variable

Initial Value

Decimal

Hexadecimal

SIGHUP

sig$_hup

140115980

0x85a000c

SIGINT

sig$_int

1617

0x651

SIGQUIT

sig$_quit

140115996

0x85a001c

SIGILL

sig$_ill

140116004

0x85a0024

SIGTRAP

sig$_trap

140116012

0x85a002c

SIGIOT

sig$_iot

140116020

0x85a0034

SIGEMT

sig$_emt

140116028

0x85a003c

SIGFPE

sig$_fpe

140116036

0x85a0044

SIGBUS

sig$_bus

140116052

0x85a0054

SIGSEGV

sig$_segv

12

0xc

SIGSYS

sig$_sys

140116068

0x85a0064

SIGPIPE

sig$_pipe

140116076

0x85a006c

SIGALRM

sig$_alrm

140116084

0x85a0074

SIGTERM

sig$_term

140116092

0x85a007c

SIGURG

sig$_urg

140116098

0x85a0082

SIGTSTP

sig$_tstp

140116114

0x85a0092

SIGCONT

sig$_cont

140116122

0x85a009a

SIGCHLD

sig$_chld

140116130

0x85a00a2

SIGTTIN

sig$_ttin

140116138

0x85a00aa

SIGTTOU

sig$_ttou

140116146

0x85a00b2

SIGIO

sig$_io

140116154

0x85a00ba

SIGXCPU

sig$_xcpu

140116164

0x85a00c4

SIGXFSZ

sig$_xfsz

140116172

0x85a00cc

SIGVTALRM

sig$_vtalrm

140116180

0x85a00d4

SIGPROF

sig$_prof

140116188

0x85a00dc

SIGWINCH

sig$_winch

140116194

0x85a00e2

SIGUSR1

sig$_usr1

140116212

0x85a00f4

SIGUSR2

sig$_usr2

140116220

0x85a00fc

SIGTRAP

ss$_intdiv

1156

0x484

SIGTRAP

ss$_intovf

1148

0x47c

SIGTRAP

ss$_subrng

1196

0x4ac

SIGFPE

ss$_fltovf

1164

0x48c

SIGFPE

ss$_decovf

1188

0x4a4

SIGFPE

ss$_fltdiv

1172

0x494

SIGFPE

ss$_fltund

1180

0x49c

Modifying the ONCODE Values

The numbers listed in See . Corresponding Values for the ONCODE values are under program control. The values listed are the initial value for each of the signals. These numbers may be modified, if desired, by assigning a new value to the variable. Take care not to duplicate these signal numbers or they cannot be distinguished. These values should not be modified within a condition handler.

You may want to use your own number for the ONCODE value, if the numbers are used to identify a related error message.

The following program shows an example of how UNIX signals can be handled, and how the ONCODE values can be modified:

UNIXSIG: PROC OPTIONS( MAIN );

 

dcl sig$_usr1 fixed bin(31) globalref;

dcl sig$_int fixed bin(31) globalref;

dcl sig$_quit fixed bin(31) globalref;

/* set specific value for sig$_int */

sig$_int = 999999;

 

call mainloop();

 

/* set up anycondition handler to test for

* sig$_usr1, sig$_int and sig$_quit */

mainloop: proc;

on anycondition begin;

if (oncode() = sig$_usr1) then

PUT LIST ( 'mainloop: caught sigusr1 ',oncode());

else if oncode() = sig$_int then

PUT LIST ( 'mainloop: caught sigint ',oncode());

else if oncode() = sig$_quit then

PUT LIST ( 'mainloop: caught sigquit ',oncode());

else call resignal();

put skip;

end;

 

/* set up specific handler for sig$_usr2 */

on vaxcondition(sig$_usr2) begin;

PUT LIST ( 'usr2: caught sigusr2 ',oncode());

put skip;

end;

 

/* main loop processing starts here */

 

END;

 

In this example, specific handlers are set up for the UNIX signals SIGUSR1, SIGINT, SIGQUIT, and SIGUSR2. The first three are caught in the ANYCONDITION handler and the ONCODE is compared to the current values in the global variables sig$_usr1, sig$_int and sig$_quit. The signal SIGUSR2 is caught in a specific VAXCONDITION on units testing for sig$_usr2.

Search Path for ON-Units

In PL/I, each call frame in the calling sequence for ON-units is searched in a specific sequence. If it reaches the call frame at which the program was entered without locating an ON-unit, it performs default condition handling. The default handling depends on whether or not the call frame at which the procedure was entered specified the MAIN option.

The next example and See . Execution of an ON-Unit illustrates the call frames established for the execution of a series of procedures. Procedure A establishes an ON-unit for the FIXEDOVERFLOW condition, and procedure B establishes an ON-unit for an UNDEFINEDFILE condition for the file PRINTFILE. When a FIXEDOVERFLOW condition is signaled in procedure C, PL/I locates the ON-unit established in procedure A and activates the corresponding ON-unit. When PL/I activates an ON-unit, it creates an activation record for the ON-unit and places the ON-unit on the call stack for execution, as if it were a unique block activation.

A: PROCEDURE OPTIONS(MAIN);

ON FIXEDOVERFLOW BEGIN;

END;

CALL B;

 

B: PROCEDURE;

ON UNDEFINEDFILE (PRINTFILE) OPEN

FILE (PRINTFILE) TITLE('SYS$OUTPUT');

CALL C;

 

C: PROCEDURE;

RETURN; /* Fixed overflow signaled */

END;

 

See . Execution of an ON-Unit illustrates the preceding example.

 

. Execution of an ON-Unit

Default Handling for Main Procedures

If PL/I entered a program at a procedure containing the MAIN option, PL/I searches for ON-units and performs default condition handling as follows:

PL/I searches for specific ON-units in the following order:
  1. A VAXCONDITION ON-unit established for the specific condition value that is being signaled
  2. A PL/I ON-unit established for a PL/I condition name, if PL/I defines a name for the condition
  3. An ANYCONDITION ON-unit

If one of these ON-units exists, it is executed and the search is ended. If the ON-unit completes execution by handling the condition, the program continues at the point at which the condition was signaled.

  1. If none of the above are found in any call frame, the default PL/I condition handler performs one of the following:
  2. If the signal is the ENDPAGE condition, the default PL/I handler executes a PUT PAGE for the file, and then continues the program at the point at which ENDPAGE was signaled. If the ENDPAGE condition is for SYSPRINT, no action is performed.
  3. If the signal is the ERROR condition and the severity is fatal, the default handler signals the FINISH condition. Then, one of the following occurs:

If a FINISH ON-unit is found, its execution is attempted. If it executes a nonlocal GOTO or signals another condition, program execution continues.

If no FINISH ON-unit is found, or if a FINISH ON-unit completes execution by handling the condition, then PL/I resignals the condition to the default UNIX condition handler. This handler prints a message and terminates the program.

  • If the signal is any condition other than ENDPAGE, ERROR with a fatal severity, or UNDERFLOW, the default PL/I handler signals the ERROR condition with the severity of the original condition. Then, one of the following occurs:

If an ERROR ON-unit is found, it is executed. If it completes execution by handling the condition, the program continues.

If an ERROR ON-unit is not found, the default PL/I handler resignals the condition. If this resignaling results in control returning to the system, the default UNIX condition handler prints a message. If the error is a fatal error, the default handler terminates the program; if the error is nonfatal, the program continues.

Default Handling for Non-Main Procedures

If the call frame at which the program was entered did not specify the MAIN option, the default condition handling is:

PL/I searches for specific ON-units in the following order:
  1. A VAXCONDITION ON-unit established for the specific condition value that is being signaled
  2. A PL/I ON-unit established for a PL/I condition name, if PL/I defines a name for the condition
  3. An ANYCONDITION ON-unit

If one of these ON-units exists, it is executed and the search is ended. If the ON-unit completes execution by handling the condition, the program continues at the point at which the condition was signaled.

  1. If no ON-units are found in any call frame, the condition is signaled to the caller which repeats steps one and two. If the resignal results in the return of control to the system, the default UNIX condition handler issues a message. If the error was a fatal error, the default UNIX handler terminates the program. Otherwise, the program continues.

The next example and See . Search for an ON-Unit illustrate a search for an ON-unit that will handle a decimal overflow condition. The reverse numbers indicate the sequence in which the search takes place.

A: PROCEDURE OPTIONS(MAIN);

ON ERROR BEGIN; Õ /* ERROR signaled */

- /* Execute ON-unit */

END;

CALL B; Ã

B: PROCEDURE; /* Look for ERROR */

CALL C;

RETURN; À

END;

 

C: PROCEDURE; /* Look for ERROR */

RETURN;

END;

 

Referring to the example above and See . Search for an ON-Unit , you can see that PL/I takes the following actions:

Searches the call frame (C) in which the condition was signaled for three specific ON-units: VAXCONDITION (SS$_DECOVF), FIXEDOVERFLOW, ANYCONDITION

Searches the previous call frame (B)

Reaches the main procedure (A) ON-units

Signals the ERROR condition

Searches the call frame (C) ERROR ON-unit

Searches the previous call frame (B)

Locates the ERROR ON-unit in the main procedure (A)

 

. Search for an ON-Unit

Multiple Conditions

If a second condition is signaled during the execution of an ON-unit, PL/I searches for an ON-unit that will handle the second condition, beginning in the call frame in which the second condition was signaled.

The next example and See . Effect of Multiple Conditions illustrate the search sequence followed when a second condition occurs during the execution of an ON-unit. The reverse numbers indicate the order of execution. The ERROR condition in procedure C is handled by the ON-unit established in procedure B. During the execution of this ON-unit, a FIXEDOVERFLOW condition is signaled. PL/I locates the ON-unit (shown in the See . Effect of Multiple Conditions as a box with dotted lines) established for FIXEDOVERFLOW conditions in procedure C and gives it control.

A: PROCEDURE OPTIONS(MAIN);

CALL B;

 

B: PROCEDURE; À

ON ERROR BEGIN;

END;

CALL C;

 

C: PROCEDURE; Ã /* Original ERROR signaled */ Õ

ON FIXEDOVERFLOW BEGIN;

END;

 

See . Effect of Multiple Conditions illustrates the preceding example.

 

. Effect of Multiple Conditions

Note that if the second condition is the same condition as the first, and the ON-unit does not establish another ON-unit, the same ON-unit will be executed repeatedly as the condition is signaled. A similar situation results when a STOP statement is executed within a FINISH or ANYCONDITION ON-unit; the program will enter an infinite loop when the STOP statement executes. The STOP statement signals FINISH, the current ON-unit is re-executed, the STOP statement is executed again, and so on.

In a PL/I program, an ANYCONDITION ON-unit or a VAXCONDITION ON-unit established specifically to handle the SS$_UNWIND condition is invoked during the unwind. The following example illustrates a VAXCONDITION ON-unit:

DECLARE SS$_UNWIND GLOBALREF VALUE FIXED BINARY(31);

ON VAXCONDITION(SS$_UNWIND) BEGIN;

CLOSE FILE(DATA_REC_TEMP) ENVIRONMENT(DELETE('0'B));

END;

 

Although it is not specifically resignaled, when an ON-unit that is handling the unwind condition completes execution, the unwind continues.

Note that when an ANYCONDITION ON-unit executes a nonlocal GOTO statement, the nonlocal GOTO causes an unwind, and the first ON-unit that is given control is the ANYCONDITION ON-unit itself. Thus, an infinite loop occurs. To avoid this situation, an ANYCONDITION ON-unit can contain the following lines:

ON ANYCONDITION BEGIN;

DECLARE SS$_UNWIND GLOBALREF VALUE FIXED;

IF ONCODE() = SS$_UNWIND THEN GOTO OKAY;

 

OKAY: END;

 

This check for the condition SS$_UNWIND ensures that if a nonlocal GOTO is executed in this ON-unit, it will not cause the ON-unit to be re-executed.

Scope of ON-Units

After an ON-unit is established, it remains in effect for the activation of the current block and all its dynamically descendent blocks, unless one of the following situations occurs:

  • Another ON statement is specified for the same condition in a descendent block. The ON-unit established within the descendent block remains in effect as long as the descendent block is active.
  • A REVERT statement is executed for the specified condition. A REVERT statement nullifies the most recent ON-unit for the specified condition.
  • Another ON statement is specified for the same condition within the current block. Within the same block, an ON statement for a specific condition cancels the previous ON-unit.
  • The block or procedure within which the ON-unit is established terminates. When a block exits, any ON-units it has established are canceled.
ON-Unit Examples

The following examples illustrate some typical ON-units. The first example establishes an ON-unit for the FINISH condition. The ON-unit ensures that two files are closed properly, and calls a routine that stops a timer in an orderly fashion.

ON FINISH BEGIN;

CLOSE FILE(INFILE);

CLOSE FILE(OUTFILE);

CALL TIMER_END;

END;

 

Normally, the FINISH ON-unit should be declared in the main procedure; however, it will be executed on image exit if it is established in any block that is active when that occurs.

The next example contains an ERROR ON-unit that will terminate a program in an orderly fashion, should some error occur that is not handled by a specific ON-unit.

DECLARE STATUS FIXED BINARY(31);

 

ON ERROR BEGIN;

CLOSE FILE (INFILE);

CLOSE FILE (OUTFILE);

STATUS = ONCODE();

GOTO FINIS;

END;

 

FINIS: RETURN (STATUS);

 

The ERROR ON-unit provides a cleanup procedure to ensure that the files identified as INFILE and OUTFILE are properly closed before the image exits. The ON-unit saves the value returned by ONCODE in the variable STATUS, and transfers control to a RETURN statement that returns the numeric value to the caller. If the procedure was invoked by a RUN command, this value is returned to the command interpreter, which in turn displays on the terminal the mnemonic code for the error and the error message.

The next example contains an ON-unit that changes the value of a bit variable when end-of-file is encountered.

DECLARE STATE_PTR POINTER,

STATE_FILE FILE,

EOF BIT(1) STATIC INIT('0'B);

 

ON ENDFILE(STATE_FILE) EOF = '1'B;

OPEN FILE(STATE_FILE) INPUT SEQUENTIAL;

READ FILE(STATE_FILE) SET(STATE_PTR);

DO WHILE (^EOF);

READ FILE(STATE_FILE) SET(STATE_PTR);

END;

 

The procedure reads the records in the file STATE_FILE until it encounters end-of-file. At that point, the ON-unit executes and changes the value of EOF from 0 to 1. This action causes the test in the DO WHILE statement to fail, terminating the loop that reads the records.

The following example shows an ON-unit that consists of a sequence of statements in a begin block:

ON ENDFILE (SYSIN) BEGIN;

CLOSE FILE (TEMP);

CALL PRINT_STATISTICS(TEMP);

END;

 

This ON-unit consists of CLOSE and CALL statements that request special processing when the end-of-file condition occurs during reading of the default system input file, SYSIN.

The following example shows a null statement specified for an ON-unit:

ON ENDPAGE(SYSPRINT);

 

This ON-unit causes PL/I to continue output on a terminal regardless of the number of lines already output. The null statement indicates that no processing is to occur when the condition occurs. Program execution continues as if the condition had been handled.

See , See File Organizations and Input/Output demonstrates an ON-unit that handles errors encountered during record I/O operations.

Condition-Handling Built-In Functions

The following sections discuss the two PL/I built-in functions that are useful for condition handling: ONCODE, and ONFILE.

ONCODE Built-In Function

All UNIX-defined conditions have symbolic names associated with them. When thePL/I ONCODE built-in function is invoked in an ON-unit, it returns the value of the associated global symbol. This 32-bit status value describes the condition that was signaled. The low-order three bits of the status value contain the severity of the condition (success, warning, error, or fatal). Severity is important when no ON-unit exists for a condition, and default condition handling is performed by PL/I (see See Search Path for ON-Units ). This number is program dependent.

All symbolic names associated with UNIX condition values are defined as system global symbols. Thus, you can declare the names for these values in a PL/I program using the GLOBALREF attribute, and refer to them symbolically. The linker will automatically locate the definitions of the symbols in the default system libraries when the procedure is linked. You can use the system global symbol names to refer to the values returned by the ONCODE built-in function in an condition-handling ON-unit.

See . ONCODE Values for PL/I ON Conditions lists the PL/I keyword condition names and the UNIX global symbol names associated with each condition name.            

. ONCODE Values for PL/I ON Conditions

PL/I Condition

UNIX Global Symbol Name 9

AREA 10

See the Kednos PL/I for UNIX Reference Manual for a discussion of allocation in areas.

CONDITION

PLI$_CONDITION

CONVERSION

PLI$_CONVERSION if a SIGNAL CONVERSION statement was executed, otherwise PLI$_ONCNVPOS (PLI$_ONCNVPOS could change in a future release of PL/I)

ENDFILE

PLI$_ENDFILE

ENDPAGE

PLI$_ENDPAGE

ERROR

A specific status value associated with the error that caused the condition to be signaled 11

FINISH

PLI$_FINISH

FIXEDOVERFLOW

SS$_DECOVF or SS$_INTOVF

KEY

PLI$_KEY

OVERFLOW

SS$_FLTOVF

STORAGE

PLI$_STORAGE

STRINGRANGE See Only signalled via SIGNAL statement. No hardware support on UNIX.

PLI$_STRRANGE

SUBSCRIPTRANGE See Only signalled via SIGNAL statement. No hardware support on UNIX.

PLI$_SUBRANGE

UNDEFINEDFILE

PLI$_UNDEFINEDFILE

UNDERFLOW

SS$_FLTUND

VAXCONDITION

Any user-defined condition or UNIX signal global symbol value that was signaled

ZERODIVIDE

SS$_FLTDIV or SS$_INTDIV

ONFILE Built-In Function

The ONFILE built-in function returns the name of the file constant for which the current file-related condition was signaled. Its format is given in the Kednos PL/I for UNIX Reference Manual.

The ONFILE built-in function can be used in the following ON-units:

The returned value is a varying-length character string. If referenced outside an ON-unit or within an ON-unit that is executed as a result of a SIGNAL statement, the ONFILE function returns a null string.

ONKEY Built-In Function

The ONKEY built-in function returns the key value that caused the KEY condition to be signaled during an I/O operation to a file that is being accessed by key. Its format is given in the Kednos PL/I for UNIX Reference Manual.

This built-in function can be used in an ON-unit established for these conditions:

The returned key value is a varying-length character string. If referenced outside an ON-unit, or within an ON-unit executed as a result of the SIGNAL statement, the ONKEY built-in function returns a null string.

 

Using PL/I in the Common Language Environment

The PL/I compiler is part of the UNIX Standards common language environment. This environment defines certain calling procedures and guidelines that allow you to call routines written in different languages or prewritten system routines from PL/I. You can call any of the following routine types from PL/I:

The terms routine, procedure, and function are used throughout this chapter.

The definitions of routine, procedure, and function used in this chapter differ somewhat from standard PL/I terminology. The following definitions, used for consistency with the UNIX system routines documentation, apply only to this chapter:

The UNIX Procedure Calling and Condition Handling Standard

The UNIX Procedure Calling and Condition Handling Standard describes the concepts used by all UNIX languages for invoking routines and passing data between them. This standard specifies the PL/I parameter handling mechanism as well as defining the calling sequence, argument data types and descriptor formats, condition handling, and stack unwinding.

The following sections discuss the parameter handling mechanism in more detail.

Parameter-Passing Mechanisms

To pass data between routines that are not written in the same UNIX language, you must specify how you want that data to be represented and interpreted. You do this by specifying a parameter-passing mechanism. The general parameter-passing mechanisms and their keywords and abbreviations in PL/I are as follows:

The parameter-passing mechanisms are intended for use only in calling non-PL/I routines. External routines written in PL/I should be called with the established mechanisms.

The following sections describe the arguments in terms of PL/I data types, dummy arguments created (if any), parameter-passing mechanism conventions, and attributes to define the manner in which parameters are to be passed. Remember that when PL/I creates a dummy argument, modifications, if any, that the called procedure makes to the dummy argument are not accessible to the caller.

Passing Parameters by Reference

When you pass a parameter by reference, the PL/I compiler passes the address at which the actual parameter value is stored. In other words, your routine has access to the parameter's storage address. Therefore, when you manipulate and change the value of this parameter, the changed value overwrites the previous value of the parameter. Thus, when you pass a parameter by reference, any changes that you make to the value of the parameter in your routine are reflected in the calling routine as well, provided a dummy argument was not created.

You can pass an argument of any data type by reference. PL/I uses this mechanism by default for all arguments except character strings or arrays with nonconstant extents, and unaligned bit strings. Note that bit-string variables must have the ALIGNED attribute to be passed by reference. In general, the parameter descriptor for an argument to be passed by reference only needs to specify the data type of the parameter.

For example, the MEMSET runtime library routine requires the first argument passed by reference, and the second and third argument passed by value. You can declare this procedure as follows:

DECLARE MEMSET ENTRY (ANY, CHAR(1) VALUE,

FIXED BIN(31) VALUE);

 

When this procedure is invoked, the first parameter can be any variable, the second parameter must be a character, and the third variable a numeric expression.

The data types in the parameter descriptors of all output arguments must match the data types of the written arguments.

Using the ANY Attribute

When you write a parameter descriptor for a non-PL/I procedure, you can specify the ANY attribute without the VALUE attribute to describe an argument being passed by reference. The argument can be of any addressable data type known to PL/I. For example:

DECLARE MEMSET ENTRY (ANY, CHAR(1) VALUE,

FIXED BIN(31) VALUE);

 

The first parameter descriptor in the ENTRY attribute specifies that the argument can have any data type and is being passed by reference. When you specify ANY for an argument to be passed by reference, you cannot specify data type attributes. Note that if you specify the VALUE attribute in conjunction with the ANY attribute, PL/I passes the argument by value.

The ANY attribute is especially useful when you must specify a data structure as an argument. You need not declare the structure within the parameter descriptor, only the ANY attribute.

Dummy Arguments for Arguments Passed by Reference

When PL/I passes an argument by reference, it puts either the address of the actual argument or the address of a dummy argument in the argument list of the called procedure. PL/I creates a dummy argument in the following cases:

  • When the written argument is a constant or an expression
  • When the written argument is enclosed in parentheses
  • When the data type of the written argument does not match the data type or precision specified in the parameter descriptor

In the last case of the previous list, PL/I issues an informational or warning message and, for scalar arguments, creates a dummy argument of the data type of the parameter. It places the address of this dummy argument in the argument list. If the argument is an aggregate, PL/I issues an error message and does not create a dummy argument for the array or structure.

In creating a dummy argument, PL/I does the conversions listed in See . Converted Data Types of Arguments Passed by Reference :

. Converted Data Types of Arguments Passed by Reference

Data Type of Written Argument

Data Type of Dummy Argument

BIT (unaligned)

BIT ALIGNED

FIXED BINARY (p,0) or
FIXED DECIMAL (p,0)

FIXED BINARY (31)

CHARACTER VARYING

CHARACTER NONVARYING

In all other cases, the data type of the dummy argument is the same as the data type of the written argument.

Using Pointer Values for Arguments Passed by Reference

When you pass an argument by reference, PL/I puts the address of the actual argument in the argument list. This address can be interpreted as a pointer value. In fact, you can explicitly specify a pointer value as an argument for data to be passed by reference. For example:

DECLARE MEMSET (POINTER VALUE, CHAR(1) VALUE,

FIXED BIN(31) VALUE);

 

When MEMSET is invoked with the following statement at the procedure invocation, PL/I places the pointer value returned by the ADDR built-in function directly in the argument list.

CALL MEMSET(ADDR(EMPLOYEE_RECORD), '', 100);

 

Passing Arrays to a FORTRAN Routine by Reference

In FORTRAN, you must always pass arrays by reference; the array extents are, by custom, passed as separate arguments. The REFERENCE attribute provides a convenient way to express an array parameter for FORTRAN. For example:

FTNARRAY: PROCEDURE(X);

DECLARE SUM ENTRY ((*) FLOAT REFERENCE, FIXED BINARY(31))

RETURNS (FLOAT);

 

DECLARE (S, X(*)) FLOAT;

 

S = SUM(X, DIM(X));

 

SUM is a FORTRAN routine that sums the elements of a one-dimensional array of floating-point numbers. Its second parameter is the number of elements in the array.

Passing Parameters by Value

When you pass a parameter by value, the PL/I compiler passes a copy of the parameter's value to the routine instead of passing its address. Because only a copy of the parameter's value is passed, the routine does not have access to the storage location of the parameter. Therefore, when you pass a parameter by value, any changes that you make to the parameter value in the called routine do not affect the value of that parameter in the calling routine.

For an argument to be passed by value, you must use the VALUE attribute in a parameter description. The following declaration of the external entry VHF illustrates a declaration for an external routine that receives its parameter by value.

DECLARE VHF ENTRY (FIXED BINARY(31) VALUE);

 

You can also define PL/I procedures that receive arguments by value. To do this, you must specify the VALUE attribute in the declaration of the parameter. For example, the corresponding definition of the routine VHF would be as follows:

VHF:PROCEDURE (LENGTH);

DECLARE LENGTH FIXED BINARY(31) VALUE;

 

Arguments that can be passed by value are limited to the following data types, which can be expressed in 32 bits:

No other data types can be passed by value. Note that when ENTRY VALUE is specified in a parameter descriptor, only the entry points of external routines may be passed by value. A complete entry value for an internal routine requires two longwords, one for the parent frame and one for the 32-bit entry-point address.

When you specify the VALUE attribute in a parameter descriptor, you can specify the ANY attribute instead of declaring any data type attributes. For example, the declaration of VHF can appear as follows:

DECLARE VHF ENTRY (ANY VALUE);

 

When the procedure is invoked, PL/I converts the written argument as needed to create a longword dummy argument.

Dummy Arguments for Arguments Passed by Value

For arguments to be passed by value, PL/I always creates a dummy argument directly in the argument list for the called procedure. If the parameter descriptor is specified with the ANY and VALUE attributes, PL/I creates dummy arguments the data types shown in See . Assignment of Data Type to Dummy Arguments :

. Assignment of Data Type to Dummy Arguments

Data Type of
Written Argument

Data Type of
Dummy Argument

FIXED BINARY, (p,0) or

FIXED DECIMAL (p,0)

FIXED BINARY (31)

BIT or BIT ALIGNED

BIT (32)

ENTRY

ENTRY

OFFSET

OFFSET

POINTER

POINTER

If a parameter descriptor is specified as VALUE with a particular data type (as opposed to being specified as ANY), a dummy argument of that data type is always created, and the written argument is assigned to the dummy. The written argument must be valid for conversion to the data type specified in the corresponding parameter descriptor.

Special Parameter Attributes

PL/I provides the OPTIONS(VARIABLE) option to the ENTRY declaration, and the OPTIONAL and TRUNCATE parameter attributes.

The option and parameter attributes are described in the following sections.

OPTIONS(VARIABLE) Option

This option is provided for use in calling non-PL/I procedures and can only be used for that purpose. If you declare an external entry with OPTIONS(VARIABLE), you can omit an optional argument and let the compiler pass a zero for the argument. The called procedure usually provides a default value. You must, however, enter the correct number of commas ton ensure that the argument list contains the correct number of longwords.

OPTIONAL Attribute

Some PL/I and non-PL/I routines with fixed-length argument lists accept optional arguments and provide a default action if no value is specified for the optional argument. When an optional argument is not specified, its corresponding argument list longword is filled with a value of zero passed by immediate value.

In PL/I, you can omit the specification of an optional argument in a written argument list as long as you enter the correct number of commas to ensure that the argument list will have the correct number of longwords. You can indicate that you are not specifying an optional argument in either of the following ways:

  • Omit the argument from the argument list.
  • If the argument is to be passed by immediate value, specify a zero for the written argument.

For example, an argument list that has three optional arguments can be written as follows:

(,,)

 

The called procedure must detect and interpret the optional parameters in the argument list. The following example illustrates optional arguments omitted from an argument list:

DECLARE ASCTIM ENTRY (

FIXED BINARY(15) OPTIONAL,

CHARACTER(*),

ANY OPTIONAL,

BIT(1) ALIGNED VALUE OPTIONAL),

TIME_STRING CHARACTER(24);

 

CALL ASCTIM(,TIME_STRING,,);

 

This call to the service ASCTIM specifies only the second argument; the argument list contains four arguments. When you specify a null argument, as in the previous example, PL/I always places a zero in the argument list passed to the called procedure.

TRUNCATE Attribute

Some routines may allow an argument list to be truncated in a specified location. For example:

DECLARE GET_INPUT ENTRY (ANY CHARACTER(*),

ANY CHARACTER(*) OPTIONAL TRUNCATE,

FIXED BINARY(15) OPTIONAL TRUNCATE);

 

This declaration routine (GET_INPUT) specifies that the argument list may vary in length. In fact, GET_INPUT has three parameters, but the last two parameters are optional.

When you invoke such a routine omitting trailing arguments, you do not have to account for all the arguments in the procedure invocation argument list. For example, the GET_INPUT routine can be invoked with trailing arguments omitted:

CALL GET_INPUT(GET_STRING);

 

The variable GET_STRING is specified for the first argument. The other two arguments are not specified.

Calling Routines

The basic steps for calling routines are the same whether you are calling a routine written in PL/I, a routine written in some other UNIX language, a system service, a utility routine, or a UNIX Run-Time Library routine. The following sections outline the procedures for calling non-PL/I routines.

Determining the Type of Call

Before you call an external routine, you must first determine whether the call should be a procedure call or a function call. You should call a routine as a procedure if it does not return a value. You should call a routine as a function if it returns any type of value.

Declaring an External Routine and Its Arguments

To call a routine written in another UNIX language, or to call a system routine, you need to declare the routine as an external procedure or function and to declare the data types and passing mechanisms of its arguments. Note that arguments can be either required or optional.

You should include the following information in an external routine declaration:

Calling the External Routine

Once you have declared a routine, you can call it. To call a procedure, you use the CALL statement. To call a function, you can use a function invocation either in an assignment statement or as an argument in another routine call. In either case, you must specify the name of the routine being called and all parameters required for that routine. Make sure the data types and passing mechanisms for the actual parameters you are passing coincide with those you declared earlier, and with those declared in the routine.

If you do not want to specify a value for a required parameter, you can pass a null argument by inserting a comma (,) placeholder in the argument list. If you use any passing mechanism other than the default, you must specify the passing mechanism in the CALL statement or the function call.

At this point, the routine being called receives control, executes, and then returns control to the calling routine at the next statement after the CALL statement or function call.

 

GNU Software Information

The following information pertains to the GNU readline and assembler software, used in the Kednos PL/I for UNIX software. The Free Software Foundation supplies the GNU Copyleft, which is provided verbatim in this appendix.

GNU Copyleft

Version 2, June 1991

Copyright (C) 1989, 1991 Free Software Foundation, Inc. 675 Mass Ave, Cambridge, MA 02139, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.

Preamble

The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too.

When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things.

To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it.

For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.

We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software.

Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations.

Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all.

The precise terms and conditions for copying, distribution and modification follow.

TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you".

Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does.

1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program.

You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.

2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:

a. You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change.

b. You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License.

c. If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.)

These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it.

Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program.

In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.

3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following:

a. Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,

b. Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,

c. Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.)

The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable.

If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code.

4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.

5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it.

6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License.

7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program.

If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances.

It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice.

This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.

8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License.

9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.

Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation.

10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally.

NO WARRANTY

11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

END OF TERMS AND CONDITIONS

How to Apply These Terms to Your New Programs

If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms.

To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found.

ONE LINE TO GIVE THE PROGRAM'S NAME AND AN IDEA OF WHAT IT DOES. Copyright (C) 19YY NAME OF AUTHOR This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

Also add information on how to contact you by electronic and paper mail.

If the program is interactive, make it output a short notice like this when it starts in an interactive mode:

Gnomovision version 69, Copyright (C) 19YY NAME OF AUTHOR Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details.

The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program.

You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names:

Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. SIGNATURE OF TY COON, 1 April 1989 Ty Coon, President of Vice

This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License.

Index

Symbols

$signaldef 10-10

A

Access modes 5-3

keyed 5-4

sequential 5-3

using record identification 5-4

Access privileges 6-26

Activation records of ON-units 10-13

ADDR built-in function 11-5

Aggregates, see Arrays and Structures

ANY attribute 11-3, 11-6

using with VALUE 11-7

ANY OPTIONAL 11-8

ANYCONDITION ON-unit

affect of nonlocal GOTO 10-19

calling during unwind 10-19

located in search for ON-units 10-14, 10-16

STOP statement in 10-19

APPEND ENVIRONMENT option 6-11

example 5-8

Archive libraries 2-8

AREA condition 10-23

Arguments

optional 11-8

passing

by reference 11-3

by value 11-5

specifying pointer values 11-5

truncating lists of 11-9

Arrays

passing as arguments 11-3

by reference 11-3

to FORTRAN 11-5

Ascending sort 9-6

Assembly language 2-2

Attributes for file access 5-3

audit debugger command 3-19, 3-21

Automatic data 3-7

B

Binary 2-2

Bit strings

passing by reference 11-3

passing by value 11-6

Boolean expressions

in ENVIRONMENT options 6-3

in I/O statement options 7-1

break debugger command 3-22

Breakpoints 3-22

Buffers, file 8-1

Built-in functions

ADDR 11-5

condition-handling 10-22

ONCODE 10-22

ONFILE 10-24

ONKEY 10-24

preprocessor 2-14

Built-in subroutines

file-handling 8-1

FLUSH 8-1

RESIGNAL 10-1, 10-5

REWIND 8-2

C

C 2-4

Call frame

for ON-unit 10-13

removing from call stack 10-6

Call stack

displaying 3-56

execution of ON-unit 10-13

searching for ON-units 10-13, 10-15 to 10-16

during unwind 10-8

effect of RESIGNAL 10-5

unwind 10-6, 10-8

CALL statement

external routines 11-10

FORTRAN example 11-5

non-PL/I routines 11-1

CANCEL_CONTROL_O option 7-2

Character strings

as arguments to ENVIRONMENT options 6-2

passing as arguments 11-3

reading and writing

fixed-length 5-5

varying-length 5-6

chmod command 6-28

Cleanup procedures 10-21

clear break debugger command 3-26

CLOSE statement 4-2

specifying ENVIRONMENT options 6-1

Compiler

causes of warnings 2-19

components of 2-1

debugging options 3-8

diagnostic message format 2-18

driver options 2-4

drivers for other languages 2-4

error severity 2-19

function of 2-1

processing phases 2-2

syntax error detection 2-19

CONDITION condition 10-23

Condition handlers 10-8

compared to ON-units 10-8

courses of action 10-4

default 10-14

defaults in routines 10-15

effects of using 10-4

multiple active 10-17

resignaling a condition 10-1, 10-5 to 10-6

search order 10-13

signal(3) 10-9

unwinding the call stack 10-6

using built-in functions 10-22

using STOP statement in 10-8

VAXCONDITION 10-2

Condition Handling Standard support 11-2

Condition values

file errors 4-8

user-defined 10-2

CONSECUTIVE ENVIRONMENT option 6-12

Constants, file 4-1

continue debugger command 3-28

D

dbg, see Debugger

Debugger 3-1

abbreviating commands 3-16

accessing data in 3-6

accessing types of data 3-7

assigning values to variables 3-46

audit command 3-19, 3-21

break command 3-22

clear break command 3-26

command summary (table) 3-16

compiling for 3-8

continue command 3-28

dbg command 3-10

describe command 3-29

directory command 3-31

down command 3-32

editing command lines 3-11

environment command 3-33

errors 3-18

help command 3-36

inputrc file 3-13

list command 3-39

logging a session 3-21

prompt 3-10, 3-16

prompt command 3-43

quit command 3-11, 3-35

record command 3-44

register command 3-45

set command 3-46

setting scope 3-33

shell command 3-48

show command 3-49

step command 3-53

up command 3-55

using on optimized code 3-9

walkback command 3-56

Default condition handling

main procedure 10-14

non-main procedure 10-15

DEFAULT_FILE_NAME ENVIRONMENT option 6-12

DELETE ENVIRONMENT option 6-13

Descending sort 9-6

describe debugger command 3-29

DIRECT file access 5-3

directory debugger command 3-31

down debugger command 3-32

Driver options 2-4

Dummy arguments

for by-value arguments 11-7

passing by reference 11-4

Duplicate keys, errors in 4-8

Dynamic frames, navigating through 3-32, 3-55

E

ENDFILE condition 4-7, 10-23 to 10-24

ENDPAGE condition 4-7, 10-23

action by default handler 10-15

ENTRY attribute, declaring non-PL/I routines 11-6

Entry name, as procedure argument 11-6

environment debugger command 3-33

ENVIRONMENT options 6-1

APPEND 6-11

CONSECUTIVE 6-12

DEFAULT_FILE_NAME 6-12

DELETE 6-13

F, FB, FS, and FSB 6-11, 6-14

FIXED_LENGTH_RECORDS 6-11, 6-14, 6-16, 6-24

GROUP_PROTECTION 6-16

MAXIMUM_RECORD_SIZE 6-17, 6-19

OWNER_PROTECTION 6-18

RECORD_ID_ACCESS 6-19

SCALARVARYING 6-20

SHARED_READ 6-22

specifying 6-1

specifying arguments 6-2 to 6-3

summary 6-4

SUPERSEDE 6-22

TEMPORARY 6-23

V, VB, VS, and VSB 6-24

WORLD_PROTECTION 6-25

Environment variables 4-4

Environment, access to data 3-6

EQUALS (sort option) 9-7

ERROR condition 10-23

action by default handler 10-15

default ON-unit action 10-4

for file errors 4-7

signaled

by default ON-unit 10-15

ERROR ON-unit 10-21

Errors

debugger 3-18

ENVIRONMENT options 6-3

file

default handling 4-9

error handler 4-8

handling 10-1

file 4-7

of file-related error 10-24

ON conditions 10-1

message format in compiler 2-18

relative file 5-13

run-time 2-20

severity 2-19

syntax 2-19

when passing arguments 11-4

Executable binary 2-2

Executing a PL/I program 2-20

External procedures as arguments 11-6

External routines

calling 11-9

non-PL/I 11-1

F

F, FB, FS, and FSB ENVIRONMENT options 6-11, 6-14

FAST_DELETE option 7-2

Fatal severity condition handling 10-15

FILE attribute 4-1

File constants 4-3

File specifications

completing 4-3

expanded 4-6

for error 10-24

invalid 4-4

TITLE option 4-3

Files 4-1

access modes and PL/I attributes 5-3

access privileges 6-26

accessing 4-1

built-in subroutines for 8-1

closing 4-2

creating 5-7

declaring 4-1

default version numbers 4-6

error conditions in 4-7

handling errors 4-8

keyed, error handler ex. 4-8

opening

ENVIRONMENT options 6-3

positioning 4-2

organization 5-1

ownership 6-26

prefix for sort files 9-10

process permanent 4-5

protection 6-26

specifying 6-27

reading and writing 5-11 to 5-12, 7-5

record 5-1

relative 5-8 to 5-13

signaling ONKEY built-in function 10-24

specifying to debugger 3-10

stream 5-7

see also Records, Relative files, Stream files

FILSZ (sort option) 9-7

FINISH condition

signaled

by default handler 10-15

by STOP statement 10-8

STOP statement in ON-unit 10-19

FIXED_LENGTH_RECORDS ENVIRONMENT option 5-5, 6-11, 6-14, 6-16, 6-24

Fixed-length records 5-5

FIXEDOVERFLOW condition 10-23

FLUSH built-in subroutine 8-1

Formats, record 5-5

Fortran 2-4

FORTRAN routines, passing arrays to 11-5

Functions, calling 11-10

G

-g compiler option 3-9

GET statement

default file title 4-5

NO_ECHO option 7-3

suppressing display of input 7-3

with PROMPT option 7-4

Global symbols

condition value 10-23

ONCODE values 10-23

reference in ON-unit

example 5-13

referencing in ON-unit 4-8, 10-23

GOTO statement, nonlocal 10-6

GROUP_PROTECTION ENVIRONMENT option 6-16, 6-27

H

Handling errors, see Condition handlers

help debugger command 3-36

I

I/O

overview of RISC ULTRIX features 4-1

statement options 7-3 to 7-6

I/O Statement options

format 7-1

I/O statement options 7-2 to 7-3

IBM dialect 4-7

File environment options 5-5 to 5-6

imaginary block 3-3

Include files

input parameter declarations 2-21

init debugger command 3-37

Input files, defining 4-3

Input/Output

file specifications 4-2

record file 5-1

stream file 5-6

to a file 4-2

inputrc file 3-13

K

KEY condition 4-7, 10-24

sample ON-unit 4-8, 5-13

KEY option, in relative file 5-11

KEYED attribute

creating a relative file with 5-9

example 5-10

file access 5-3

Keys

file access using 5-4

handling errors in 4-9, 5-14

L

Labels

preprocessor 2-14

symbols in debugger 3-2

Length of variable length records 5-6

Link edit 2-2

Linking objects 2-8

specifying run-time library 2-9

list debugger command 3-39

search directories 3-31

Local data 3-7

Logging a debugging session 3-21

M

Main procedure condition handling 10-14

MAXIMUM_RECORD_SIZE ENVIRONMENT option 5-5 to 5-6, 5-9, 6-17, 6-19

Message level (for sorting) 9-10

Messages, see Errors

Multiple active conditions 10-17

N

NAME condition 4-7

Name scope 3-6

NO_ECHO option 7-3

NOEQUALS (sort option) 9-7

Nonlocal GOTO 10-6

Non-PL/I routines 11-2

calling 11-1, 11-9

Null statements, in ON-units 10-22

O

Object file 2-2

Object libraries 2-8

ON conditions 4-7, 10-1

ONCODE built-in function 4-8, 10-23

return value global symbol names 10-23

STATUS variable 10-21

testing 10-6

values in KEY ON-unit 4-9, 5-14

ONFILE built-in function 4-8, 10-24

ONKEY built-in function 4-8, 10-24

ONCODE values 4-9, 5-14

ON-units

call frame created for 10-13

compared to condition handlers 10-8

courses of action 10-4

examples of 10-20

for KEY condition

in indexed file 4-8

in relative file 5-13

referencing global symbols 10-22

examples 4-8, 5-13

scope of 10-20

searching of call stack 10-13

OPEN statement 4-2

specifying TITLE option 4-3

Optimized code, debugging 3-9

OPTIONAL attribute 11-8

Options

ENVIRONMENT 6-1

summary 6-4

OPTIONS MAIN default condition handling 10-14

OPTIONS option 7-1

OPTIONS(VARIABLE) option 11-8

OUTPUT attribute

creating a new file 5-7

example 5-10

Output, record 5-1

OVERFLOW condition 10-23

OWNER_PROTECTION ENVIRONMENT option 6-18, 6-27

P

Parameter data 3-7

Parameters

attributes 11-7

passing to non-PL/I routines 11-2

VALUE attribute 11-6

Pascal 2-4

pl1 command 2-1 to 2-2

error messages 2-18

linking objects 2-8

pl1std.in 2-21

PLIRETC built-in subroutine 9-11

PLISRTA 9-3

example 9-8, 9-10, 9-15

PLISRTB 9-3

example 9-11

PLISRTC 9-3

PLISRTD 9-3

example 9-9, 9-15

Pointers, passing as arguments 11-5

Preprocessor 2-10

built-in functions 2-14

procedures 2-12, 2-14

statements 2-13

variables 2-11

Procedure Calling Standard support 11-2

%PROCEDURE statement 2-12

Procedures

calling 11-10

passing as arguments 11-6

preprocessor 2-12

Process permanent files 4-5

Program, executable 2-2

Prompt

debugger (dbg) 3-10

with GET statement 7-3

prompt debugger command 3-43

PROMPT option 7-3

Protection files 6-26 to 6-27

PURGE_TYPE_AHEAD option 7-4

PUT statement 4-5

Q

quit debugger command 3-11, 3-35

R

Random file access 5-4

Reading files 5-4, 5-11 to 5-12

RECORD condition 4-7

record debugger command 3-44

Record Management Services (RMS), condition values 4-9

RECORD_ID option 5-5, 7-5

RECORD_ID_ACCESS ENVIRONMENT option 5-4, 6-19

RECORD_ID_TO option 5-5, 7-6

Records

cell number 5-2

format 5-5

fixed-length 5-5

variable-length 5-6

identification, accessing records by 5-4

read into varying strings 5-6

record files 5-1

record I/O 5-1

specifying size 5-5, 5-9

Reference, passing by 11-3

ANY attribute 11-3

register debugger command 3-45

Relative files 5-8 to 5-9, 5-11 to 5-12

creating 5-9 to 5-10

examples 5-8

handling errors in 5-13

keys of 5-4

ONKEY built-in function 10-24

populating 5-11

updating 5-12

RESIGNAL built-in subroutine 10-1, 10-5 to 10-6

%RETURNS statement 2-12

REVERT statement 10-20

REWIND built-in subroutine 8-2

Routines

non-PL/I 11-2

symbols in debugger 3-2

Running a PL/I program 2-20

Run-time

errors 2-20

libraries 2-8

search path 2-9

search path with -L 2-10

S

SCALARVARYING ENVIRONMENT option 6-20

Scope 3-6

in debugger 3-33

in sort routines 9-11

Scripts, debugger 3-44

Search directories, debugger 3-31

Search order for ON-units 10-13, 10-15 to 10-16

Sequential file access 5-3

set debugger command 3-46

SET PROTECTION command 6-28

Severity

of compiler errors 2-19

of conditions 10-22

of resignaled condition 10-15

SHARED_READ ENVIRONMENT option 6-22

shell debugger command 3-48

show debugger command 3-49

Signal condition

user-defined values 10-2

values 10-22

Signal values 10-10

signal(3) 10-9

SKIPREC (sort option) 9-7

Sorting

calling the entry points 9-3

compatibility 9-2

data format 9-6

examples of calls 9-15

file prefix 9-10

file-prefix 9-5

format of call 9-4

input routines 9-11

input-routine 9-4

maximum-storage 9-4

message-level 9-5, 9-10

output routines 9-11

output-routine 9-5

PLIRETC built-in subroutine 9-11

record length 9-8

record type 9-7

record-specification 9-4

return-code 9-4, 9-9

scope of variables 9-11

sort field length 9-6

sort order 9-6

sort-specification 9-4 to 9-5

starting point 9-6

storage 9-8

SyncSort 9-1

Source file

compiler-generated line numbers 2-20

creating 2-1

displaying in debugger 3-39

Standard input 4-5

Standard output 4-5

Static data, debugger access to 3-6

stdin 4-5

stdout 4-5

step debugger command 3-53

STOP statement in ON-unit 10-8

Storage (for sorting) 9-8

STORAGE condition 10-23

Stream files 5-7

appending records to 5-7

appending to 5-8

creating 5-7

input/output processing 5-6

STRINGRANGE condition 10-23

Structures

specifying to debugger 3-7

using as file layout 5-11

Subroutines for file-handling 8-1

SUPERSEDE ENVIRONMENT option 5-8, 6-22

Symbols, showing in debugger 3-2, 3-29

SyncSort 9-1

SYSIN 10-22

defaults for 4-5

SYSPRINT

defaults for 4-5

System routines 11-1

T

TEMPORARY ENVIRONMENT option 6-23

Terminal input

displaying prompting message 7-3

suppressing display 7-3

TITLE option 4-3 to 4-4

Traceback, run-time file errors 4-10

TRANSMIT condition 4-7

TRUNCATE attribute 11-9

Type-ahead buffer, purging 7-4

U

ucode 2-2

UNDEFINEDFILE condition 4-4, 4-7, 10-23 to 10-24

ENVIRONMENT option conflicts 6-3

invalid file specifications 4-4

UNDERFLOW condition 10-23

Unwind 10-6, 10-8, 10-19

up debugger command 3-55

Updating relative files 5-12

User identification code, specifying 6-26

V

V, VB, VS, and VSB ENVIRONMENT options 6-24

VALUE attribute 11-6

parameter descriptor 11-6

using with ANY 11-7

Value, passing by 11-5

Variable-length records 5-6

Variables

environment 4-4

specifying file title with 4-4

examining using debugger 3-1

file 4-1 to 4-2

file, specifying title with 4-3

preprocessor 2-11

showing values in debugger 3-49

symbols in debugger 3-2

using in signals 10-10

Varying character strings 5-6

VAXCONDITION condition 10-2, 10-23

calling during unwind 10-19

located in search for ON-units 10-14 to 10-15

Version numbers, default 4-6

W

walkback debugger command 3-56

WORLD_PROTECTION ENVIRONMENT option 6-25, 6-27

Writing files 5-11 to 5-12

Z

ZERODIVIDE condition 10-23

Reader's Comments Kednos PL/I for UNIX User's Manual

Please use this form to comment on this manual. If you require a written reply to a software problem and are eligible to receive one under your support agreement, submit your comments as specified in your agreement.

  • Thank you for your assistance.
  • I rate this manual's: Excellent Good Fair Poor
  • Accuracy (software works as manual says)
  • Completeness (enough information)
  • Clarity (easy to understand)
  • Organization (structure of subject matter)
  • Figures (useful)
  • Examples (useful)
  • Index (ability to find topic)
  • Page layout (easy to find information)

 

I would like to see more/less

What I like best about this manual is

What I like least about this manual is

  •  
  • I found the following errors in this manual:
  • Page Description

____         

____         

____         

 

  • Additional comments or suggestions to improve this manual:

 

  • I am using Version _____ of the software this manual describes.
Name/Title Dept.

Company

Mailing Address

Phone

1. If you do not specify --case upper, do not declare an external symbol that will map to "main" (lowercase). This will conflict with the library function "main" supplied in the Kednos PL/I for UNIX run-time library.

In addition, the file symbols "SYSPRINT", "SYSIN", and "SYSOUT" are always case insensitive regardless of the specified compiler option. In other words, whether you specify "sysprint", "Sysprint", or "SYSPRINT", you will always refer to the pre-declared PL/I files.

2. The default is preserved for compatibility with VAX PL/I. Kednos PL/I for UNIX does not support SEQUENTIAL (record) access to variable length stream files.

3. See umask(1)

4. 512 bytes for sequential files with fixed-length records. For sequential files with variable-length records, the default is 510 bytes. For relative files, the default is 480 bytes.

5. Enabled if the file is opened for input, otherwise disabled.

6. 512 bytes for sequential files with fixed-length records. For sequential files with variable-length records, the default is 510 bytes. For relative files, the default is 480 bytes.

7. Ignored; UNIX does not recognize Ctrl/O.

8. Ignored; RMS performance option.

9. If a PL/I condition is explicitly specified in a SIGNAL statement, the ONCODE value corresponds to the condition message associated with the condition, for example, PLI$_UNDFILE, PLI$_KEY, and so on.

10. Only signalled via SIGNAL statement. No hardware support on UNIX.

11. These names correspond to the identification fields in the run-time messages.