Kednos PL/I for UNIX

Reference Manual

April 1996

This manual defines Kednos PL/I for UNIX. It includes the keywords
and the semantic and syntax rules of PL/I programming language
statements, attributes, built-in functions, and other language elements.

 

 

 

Operating System and Version: Digital UNIX Version 3.2 or
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, Kednos PL/I, and Kednos VPO are trademarks of Kednos Corporation.

Alpha 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 the Kednos PL/I for UNIX User's Manual 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

Preface xxiii

Intended Audience xxiii

Associated Documents xxiii

Conventions xxiv

Technical Assumptions xxv

Terminological Conventions xxv

Chapter 1 --

Program Structure and Content 1-1

Lexical Elements 1-1

Keywords 1-2

Punctuation 1-2

Identifiers 1-5

Comments 1-5

Statements 1-6

Statement Formats 1-7

Condition Prefixes (IBM Dialect Only) 1-7

Statement Labels 1-8

Simple Statements 1-8

Compound Statements 1-9

Preprocessor Statements 1-9

Summary of Statements by Function 1-9

Program Format 1-12

Blocks 1-13

Begin Blocks 1-15

Procedure Blocks 1-16

Containment 1-16

Block Activation 1-17

Relationship of Block Activations 1-17

Block Termination 1-20

Data and Variables 1-20

Preprocessor 1-21

Chapter 2 --

Declarations 2-1

DECLARE Statement 2-2

Simple Declarations 2-2

Declarations Outside Procedures 2-3

Multiple Simple Declarations 2-4

Factored Simple Declarations 2-4

Array Declarations 2-5

Structure Declarations 2-6

Attributes 2-7

ALIGNED Attribute 2-15

ANY Attribute 2-15

AREA Attribute 2-16

AUTOMATIC Attribute 2-17

BASED Attribute 2-17

BINARY Attribute 2-18

BIT Attribute 2-19

BUFFERED and UNBUFFERED Attributes (IBM Dialect Only) 2-20

BUILTIN Attribute 2-21

CHARACTER Attribute 2-22

CONDITION Attribute 2-23

CONTROLLED Attribute 2-23

DECIMAL Attribute 2-24

DEFINED Attribute 2-25

DIMENSION Attribute 2-26

DIRECT Attribute 2-27

ENTRY Attribute 2-28

ENVIRONMENT Attribute 2-30

EXTERNAL Attribute 2-33

FILE Attribute 2-34

FIXED Attribute 2-34

FLOAT Attribute 2-36

GLOBALDEF Attribute 2-36

GLOBALREF Attribute 2-37

INITIAL Attribute 2-37

INPUT Attribute 2-41

INTERNAL Attribute 2-42

KEYED Attribute 2-42

LABEL Attribute 2-43

LIKE Attribute 2-43

MEMBER Attribute 2-44

NONVARYING Attribute 2-44

OFFSET Attribute 2-44

OPTIONAL Attribute (Dec and Ansi Dialects Only) 2-45

OUTPUT Attribute 2-45

PARAMETER Attribute 2-46

PICTURE Attribute 2-46

POINTER Attribute 2-47

POSITION Attribute 2-47

PRECISION Attribute 2-48

PRINT Attribute 2-49

READONLY Attribute 2-49

RECORD Attribute 2-50

REFER Attribute 2-50

REFERENCE Attribute 2-50

RETURNS Attribute 2-51

SEQUENTIAL Attribute 2-52

STATIC Attribute 2-53

STREAM Attribute 2-53

STRUCTURE Attribute 2-54

TYPE Attribute 2-54

TRUNCATE Attribute 2-56

UNALIGNED Attribute 2-57

UNBUFFERED Attribute (IBM Dialect Only) 2-57

UNION Attribute 2-57

UPDATE Attribute 2-58

VALUE Attribute 2-59

VARIABLE Attribute 2-60

VARYING Attribute 2-60

Chapter 3 --

Data Types 3-1

Summary of Data Types 3-1

Declarations 3-2

Default Attributes 3-3

Attributes of Constants 3-4

Arithmetic Operands 3-5

Compatible Data Types 3-6

Arithmetic Data 3-8

Precision and Scale of Arithmetic Data Types 3-8

Fixed-Point Binary Data 3-9

Internal Representation of Fixed-Point Binary Data 3-10

Fixed-Point Decimal Data 3-11

Fixed-Point Decimal Constants 3-11

Fixed-Point Decimal Variables 3-12

Use in Expressions 3-12

Internal Representation of Fixed-Point Decimal Data 3-13

Floating-Point Data 3-13

Floating-Point Constants 3-14

Floating-Point Variables 3-14

Using Floating-Point Data in Expressions 3-15

Floating-Point Data Formats 3-15

IEEE S_floating Format 3-16

IEEE T_floating Format 3-17

Character Pictured Data 3-17

Character Picture Characters 3-18

Examples of Character Picture Variable Definitions 3-18

Numeric Pictured Data 3-19

Picture Characters 3-20

Picture Syntax 3-28

Examples 3-31

Assigning Values to Pictured Variables 3-32

Extracting Values from Pictured Data 3-33

Editing by Picture 3-34

The Internal Representation of Pictured Variables 3-34

Character String Data 3-36

Character String Constants 3-36

Replication of String Constants 3-37

Character-String Variables 3-37

Fixed-Length Character String Variables 3-38

Internal Representation of Fixed-Length Character Data 3-39

Varying-Length Character String Variables 3-39

Internal Representation of Varying Character Data 3-40

Alignment of Character Strings 3-40

Bit-String Data 3-40

Bit-String Constants 3-41

Replication Factor for Bit-String Constants 3-42

Bit-String Variables 3-43

Alignment of Bit-String Data 3-44

Internal Representation of Bit Data 3-45

Bit Strings and Integers 3-48

Pointer Data 3-49

Pointer Variables in Expressions 3-50

Internal Representation of Pointer Data 3-50

Offset Data 3-50

Label Data 3-51

Label Array Constants 3-52

Label Values 3-54

Label Variables 3-55

Internal Representation of Label Variables 3-56

Entry Data 3-57

Entry Constants 3-57

Entry Values 3-58

Entry Variables 3-58

Internal Representation of Entry Variables 3-59

File Data 3-60

File Constants 3-60

File Values 3-61

File Variables 3-61

Area Data 3-62

Area Variables in Expressions 3-63

Reading and Writing Areas 3-63

Internal Representation of Area Data 3-63

Condition Data 3-64

Chapter 4 --

Aggregates 4-1

Arrays 4-1

Array Declarations 4-1

References to Individual Elements 4-5

Initializing Arrays 4-6

Assigning Values to Array Variables 4-10

Order of Assignment and Output for Multidimensional Arrays 4-11

Using GET and PUT Statements with Array Variables 4-12

Passing Arrays as Arguments 4-12

Built-In Functions Providing Array Dimension Information 4-13

Structures 4-14

Structure Declarations and Attributes 4-14

Using The UNION Attribute On Structure Declarations 4-16

Initializing Structures 4-17

Using Structure Variables in Expressions 4-17

Passing Structure Variables as Arguments 4-18

Member Attributes 4-18

Using the TYPE Attribute 4-18

Using the LIKE Attribute 4-21

Using the REFER Option 4-23

Structure-Qualified References 4-27

Arrays of Structures 4-28

Arrays of Structures that Contain Arrays 4-29

Connected and Unconnected Arrays 4-30

Internal Representation of Aggregate Data 4-32

Chapter 5 --

Storage Classes 5-1

Automatic Variables 5-2

Static Variables 5-2

Internal Variables 5-3

External Variables 5-3

Based Variables 5-5

Data Types Used with Based Variables 5-6

Allocation in Areas 5-6

Referring to Based Variables 5-8

Based Variables and Dynamic Storage Allocation 5-10

Using the ADDR Built-in Function 5-13

Data-Type Matching for Based Variables 5-14

Matching by Overlay Defining 5-14

Matching by Left-to-Right Equivalence 5-15

Nonmatching Based Variable References 5-16

Examples of Based Variables 5-16

Controlled Variables 5-19

Using the ALLOCATION Built-In Function 5-20

Using the ADDR Built-In Function 5-21

Dynamically Allocated Variables 5-22

ALLOCATE Statement 5-22

FREE Statement 5-23

Other Mechanisms for Dynamic Storage Allocation 5-25

Defined Variables 5-25

String Overlay Defining 5-26

Rules for Overlay Defining 5-28

Storage Sharing 5-28

Chapter 6 --

Expressions and Data Type Conversions 6-1

Assignment Statement 6-1

Operators and Operands 6-4

Arithmetic Operators 6-5

Logical Operators 6-6

NOT 6-8

AND 6-8

OR 6-9

EXCLUSIVE OR 6-10

AND THEN 6-10

OR ELSE 6-11

Relational Operators 6-12

Arithmetic Comparisons 6-12

Bit-String Comparisons 6-13

Character-String Comparisons 6-13

Comparing Noncomputational Data 6-13

Concatenation Operator 6-14

Precedence of Operators and Expression Evaluation 6-15

Data Type Conversion of Operands and Expressions 6-17

Contexts in which PL/I Converts Data 6-18

Derived Data Types for Arithmetic Operations 6-21

Conversion of Operands in Nonarithmetic Operations 6-22

Built-In Conversion Functions 6-23

Implicit Conversion During Assignment 6-24

Assignment to Arithmetic Variables 6-25

Arithmetic to Arithmetic Conversions 6-25

Pictured to Arithmetic Conversions 6-27

Bit-String to Arithmetic Conversions 6-27

Character-String to Arithmetic Conversions 6-29

Assignments to Bit-String Variables 6-30

Arithmetic to Bit-String Assignments 6-30

Pictured to Bit-String Conversions 6-32

Character-String to Bit-String Conversions 6-33

Assignments to Character-String Variables 6-33

Arithmetic to Character-String Conversions 6-34

Pictured to Character-String Conversion 6-37

Bit-String to Character-String Conversion 6-37

Assignments to Pictured Variables 6-37

Conversions Between Offsets and Pointers 6-38

Chapter 7 --

Procedures 7-1

PROCEDURE Statement 7-2

Functions and Function References 7-4

ENTRY Statement 7-5

Specifying Entry Points 7-7

Multiple Entry Points 7-8

CALL Statement 7-9

Parameters and Arguments 7-10

Rules for Specifying Parameters 7-13

Argument Passing 7-15

Calling External and Internal Procedures 7-18

Terminating Procedures 7-20

Passing Arguments to Non-PL/I Procedures 7-22

Passing Arguments by Immediate Value 7-22

Passing Arguments by Reference 7-23

Chapter 8 --

Program Control 8-1

DO Groups and Statements 8-1

Simple DO 8-2

DO WHILE 8-3

DO UNTIL 8-4

DO REPEAT 8-6

Controlled DO 8-9

BEGIN Statement 8-13

END Statement 8-15

IF Statement 8-16

Nested IF Statements 8-17

SELECT Statement 8-18

The Two Forms of the SELECT Statement 8-19

OTHERWISE Clause 8-21

Nested SELECT Statements 8-21

GOTO Statement 8-22

LEAVE Statement 8-26

STOP Statement 8-28

Null Statement 8-29

Condition Handling 8-30

ON Statement 8-30

SIGNAL Statement 8-31

REVERT Statement 8-32

Summary of ON Conditions 8-34

ANYCONDITION Condition 8-37

AREA Condition 8-37

ATTENTION Condition (IBM Dialect Only) 8-37

CHECK Condition (IBM Dialect Only) 8-38

CONDITION Condition 8-39

CONVERSION Condition 8-39

ENDFILE Condition 8-42

ENDPAGE Condition 8-43

ERROR Condition 8-45

FINISH Condition 8-45

FIXEDOVERFLOW Condition 8-46

KEY Condition 8-47

NAME Condition (IBM Dialect Only) 8-49

OVERFLOW Condition 8-50

RECORD Condition (IBM Dialect Only) 8-50

SIZE Condition (IBM Dialect Only) 8-51

STRINGRANGE Condition 8-53

STRINGSIZE Condition (IBM Dialect Only) 8-55

SUBSCRIPTRANGE Condition 8-55

STORAGE Condition 8-56

TRANSMIT Condition (IBM Dialect Only) 8-56

UNDEFINEDFILE Condition 8-57

UNDERFLOW Condition 8-59

VAXCONDITION Condition 8-60

ZERODIVIDE Condition 8-60

Default PL/I ON-Unit 8-60

Using Condition Prefixes (IBM Dialect Only) 8-61

Scope of Condition Prefixes 8-61

Default Status of Conditions 8-62

Establishing ON-Units 8-63

Contents of an ON-Unit 8-64

Search Path for ON-Units 8-65

Completion of ON-Units 8-65

Chapter 9 --

Input and Output 9-1

Opening and Closing Files 9-1

File Declarations 9-2

File Variables 9-2

Opening a File 9-3

OPEN Statement Options 9-5

Effects of Opening a File 9-6

Establishing the File's Attributes 9-7

Determining the File Specification 9-8

Accessing an Existing File 9-9

Creating a File 9-9

File Positioning 9-10

File Description Attributes and Options 9-10

Closing a File 9-11

Stream I/O 9-12

Processing and Positioning of Stream Files 9-14

Input by the GET Statement 9-16

Syntax Summary of the GET Statement 9-16

GET EDIT 9-19

GET LIST 9-20

GET SKIP 9-23

Execution of the GET Statement 9-23

Output by the PUT Statement 9-26

Syntax Summary of the PUT Statement 9-26

PUT EDIT 9-29

PUT LINE 9-30

PUT LIST 9-31

PUT PAGE 9-32

PUT SKIP 9-32

Execution of the PUT Statement 9-33

Format Items 9-34

A Format Item 9-35

B Format Items 9-37

COLUMN Format item 9-41

E Format Item 9-42

F Format Item 9-46

LINE Format Item 9-49

P Format Item 9-50

PAGE Format Item 9-52

R Format Item 9-52

SKIP Format Item 9-55

TAB Format Item 9-55

X Format Item 9-57

Format Specifications 9-59

Processing and Positioning of Character Strings 9-67

Terminal I/O 9-68

Simple Input from a Terminal 9-68

Simple Output to a Terminal 9-69

Print File 9-70

Record I/O 9-73

READ Statement 9-75

File Positioning Following a READ Statement 9-77

WRITE Statement 9-79

File Positioning Following a WRITE Statement 9-80

DELETE Statement 9-83

File Positioning Following a DELETE Statement 9-84

REWRITE Statement 9-84

File Positioning Following a REWRITE Statement 9-85

LOCATE Statement (IBM Dialect Only) 9-87

File Positioning Following a LOCATE Statement 9-89

Position Information for a Record File 9-89

Chapter 10 --

Preprocessor 10-1

Preprocessor Compilation Control 10-2

Preprocessor Statements 10-3

%Assignment Statement 10-5

% (Null) 10-6

%ACTIVATE 10-6

%DEACTIVATE 10-8

%DECLARE 10-9

%DO 10-10

%END 10-11

%ERROR 10-11

%FATAL 10-12

%GOTO 10-12

%IF 10-14

%INCLUDE 10-14

%INFORM 10-17

%PROCEDURE 10-17

%REPLACE Statement 10-25

%RETURN Statement 10-26

%WARN 10-26

User-Generated Diagnostic Messages 10-27

Preprocessor Built-In Functions 10-29

Chapter 11 --

Built-In Functions, Subroutines, and Pseudovariables 11-1

Built-In Function Arguments 11-1

Conditions Signaled 11-2

Summary of Built-In Functions 11-2

Descriptions of Built-In Functions 11-9

ABS 11-9

ACOS 11-10

ADD 11-10

ADDR 11-11

ALL 11-11

ALLOCATION 11-12

ANY 11-13

ASIN 11-13

ATAN 11-13

ATAND 11-14

ATANH 11-14

BINARY 11-15

BIT 11-16

BOOL 11-16

BYTE 11-18

BYTESIZE 11-18

CEIL 11-18

CHARACTER 11-19

COLLATE 11-20

COPY 11-20

COS 11-21

COSD 11-21

COSH 11-21

CURRENTSTORAGE 11-21

DATE 11-22

DATETIME 11-23

DECIMAL 11-23

DECODE 11-24

DIMENSION 11-25

DIVIDE 11-26

EMPTY 11-26

ENCODE 11-27

ERF 11-27

ERFC 11-28

ERROR 11-28

EVERY 11-28

EXP 11-29

FIXED 11-29

FLOAT 11-30

FLOOR 11-30

HBOUND 11-31

HIGH 11-31

INDEX 11-32

INFORM 11-33

INT 11-33

LBOUND 11-35

LENGTH 11-36

LINE 11-36

LINENO 11-36

LOG 11-36

LOG10 11-37

LOG2 11-37

LOW 11-37

MAX 11-38

MAXLENGTH 11-38

MIN 11-39

MOD 11-40

MULTIPLY 11-42

NULL 11-43

OFFSET 11-44

ONCHAR 11-44

ONCODE 11-45

ONFILE 11-45

ONKEY 11-46

ONLOC 11-46

ONSOURCE 11-47

PLIRETV 11-47

POINTER 11-47

POSINT 11-48

PRECISION 11-50

PROD 11-50

RANK 11-51

REPEAT 11-51

REVERSE 11-52

ROUND 11-53

SEARCH 11-55

SIGN 11-56

SIN 11-57

SIND 11-57

SINH 11-57

SIZE 11-57

SOME 11-61

SQRT 11-61

STORAGE 11-61

STRING 11-62

SUBSTR 11-63

SUBTRACT 11-64

SUM 11-65

TAN 11-66

TAND 11-66

TANH 11-66

TIME 11-66

TRANSLATE 11-67

TRIM 11-69

TRUNC 11-71

UNSPEC 11-71

VARIANT 11-72

VERIFY 11-73

WARN 11-74

Built-In Subroutines 11-75

Pseudovariables 11-76

INT Pseudovariable 11-77

ONCHAR Pseudovariable 11-79

ONSOURCE Pseudovariable 11-80

PAGENO Pseudovariable 11-80

POSINT Pseudovariable 11-80

STRING Pseudovariable 11-82

SUBSTR Pseudovariable 11-83

UNSPEC Pseudovariable 11-84

Appendix A --

Alphabetic Summary of Keywords A-1

Appendix B --

Dialect Differences B-1

Data Declarations B-1

Data Types B-1

Condition Handling B-1

Condition Prefixes B-2

ON Conditions B-2

Return Values for Condition Signals B-2

Sort Support B-2

Record and Stream I/O B-2

Built-in Functions B-3

Built-in Subroutines B-3

Appendix C --

Compatibility with PL/I Standards B-1

Relation to the 1981 PL/I General-Purpose Subset B-1

Program Structure B-2

Program Control B-2

Storage Control B-2

Input/Output B-2

Attributes and Pictures B-3

Built-In Functions and Pseudovariables B-3

Expressions B-3

198x PL/I General-Purpose Subset Features Supported B-4

Lexical Constructs B-4

Program Control B-4

Storage Control B-4

Input/Output B-5

Attributes and Pictures B-5

Built-In Functions and Pseudovariables B-5

Expressions B-6

Full PL/I Features Supported B-6

Program Structure B-6

Program Control B-6

Storage Control B-6

Attributes and Pictures B-6

Built-In Functions and Pseudovariables B-7

Expressions B-7

Nonstandard Features from Other Implementations B-7

Preprocessor B-7

Program Control B-8

IBM Dialect I/O Features and Other IBM Dialect Features B-8

Built-In Functions B-8

LIKE Extension B-8

Declarations B-8

PL/I-Specific Extensions for the Digital Unix Platform B-8

Procedure-Calling and Condition-Handling Extensions B-8

Miscellaneous Extensions B-9

Implementation-Defined Values and Features B-10

Appendix D --

Migration Notes C-1

Keywords Not Supported C-1

Differences Between Kednos PL/I for UNIX Digital's PL/I and Other Digital-Compatible Versions of PL/I C-7

Statements C-7

Data Type Attributes C-7

Default Values for Data Type Attributes C-7

Floating Point Data Types C-8

Scale Factors C-8

Procedures and Entries Specified with the Returns Option C-8

Passing Arguments to Non-PL/I Procedures C-8

GOTO Statement C-9

Condition Handling C-9

File Handling C-9

Preprocessor C-9

Built-in Functions and Subroutines C-10

Appendix E --

Language Summary D-1

Statements D-1

Attributes D-9

Statement Format D-11

Expressions and Data Conversions D-12

Pseudovariables D-15

Built-In Subroutines D-16

Figure 1-1. Relationship of Block Activations 1-18

Figure 3-1. Internal Representation of Fixed-Point Binary Data 3-11

Figure 3-2. Fixed-Point Decimal Data Representation 3-13

Figure 3-3. IEEE S_floating Data Representation 3-16

Figure 3-4. IEEE T_floating Data Representation 3-17

Figure 3-5. Internal Representation of a Pictured Variable 3-35

Figure 3-6. Internal Representation of a Pictured Variable 3-35

Figure 3-7. Unaligned Bit String Storage 3-46

Figure 3-8. Sample Unaligned Bit String Storage 3-46

Figure 3-9. Aligned Bit String Storage 3-47

Figure 3-10. Sample Aligned Bit String Storage 3-47

Figure 3-11. Variable Label Data Representation 3-56

Figure 3-12. Entry Variable Data Representation 3-59

Figure 4-1. Specifying Elements of an Array 4-8

Figure 4-2. Storage of Structure with REFER Option 4-25

Figure 4-3. Remapped Storage of Structure with REFER Option 4-26

Figure 4-4. Connected and Unconnected Arrays 4-31

Figure 5-1. External Variables 5-4

Figure 5-2. Using the ALLOCATE Statement 5-11

Figure 5-3. Using the READ Statement with a Based Variable 5-13

Figure 5-4. Using the ADDR Built-In Function 5-14

Figure 5-5. An Overlay Defined Variable 5-27

Figure 11-1. Example of the BOOL Built-In Function 11-17

Table Pref-1. Documentation Conventions Table xxiv

Table 1-1. Punctuation Marks Recognized by PL/I 1-3

Table 1-2. Summary of PL/I Statements 1-10

Table 2-1. Alphabetic Summary of PL/I Attributes   2-10

Table 2-2. Default Values for BINARY Attribute 2-19

Table 2-3. Default Values for the DECIMAL Attribute. 2-25

Table 2-4. Default Values for Unspecified FIXED Attributes 2-35

Table 2-5. Default Values for Unspecified FLOAT Attributes 2-36

Table 3-1. Implied Attributes for Computational Data 3-3

Table 3-2. Default Values for Precision 3-9

Table 3-3. Ranges of Floating-Point Formats 3-15

Table 3-4. Ranges of Precision for Floating-Point Types 3-16

Table 3-5. Floating-Point Types Used by PL/I 3-16

Table 3-6. Picture Characters 3-20

Table 3-7. ASCII Representation of Encoded-Sign Characters 3-24

Table 4-1. Specifying Array Dimensions 4-3

Table 4-2. Natural Alignment for Structure Members 4-33

Table 6-1. Data Types for Assignment Statement 6-2

Table 6-2. Infix Arithmetic Operators 6-5

Table 6-3. Logical Operators 6-6

Table 6-4. Precedence of Operators 6-15

Table 6-5. Contexts in Which PL/I Converts Data 6-20

Table 6-6. Derived Data Types 6-21

Table 6-7. Converted Precision as a Function of Target and Source Attributes 6-22

Table 6-8. Built-In Functions for Conversions Between Arithmetic and Nonarithmetic Types 6-23

Table 6-9. Conversion from Fixed Binary 6-26

Table 8-1. Summary of ON Conditions 8-36

Table 8-2. Values of ONCODE Raised by RECORD 8-51

Table 8-3. Values of ONCODE Raised by SIZE 8-52

Table 8-4. Values of ONCODE Raised by STRINGRANGE 8-53

Table 8-5. Values of ONCODE Raised by STRINGSIZE 8-55

Table 8-6. Values of ONCODE Raised by TRANSMIT 8-57

Table 8-7. Conditions Enabled by Default 8-62

Table 8-8. Conditions Disabled by Default 8-62

Table 8-9. Conditions That Cannot be Disabled 8-62

Table 9-1. File Description Attributes Implied when a File is Opened 9-7

Table 9-2. Summary of File Description Attributes 9-10

Table 9-3. Attributes and Access Modes for Stream Files 9-12

Table 9-4. Input String Formatting 9-36

Table 9-5. Output String Formatting 9-37

Table 9-6. Input with the B Format Item 9-40

Table 9-7. Output with the B Format Item 9-40

Table 9-8. Representation of Floating-Point Values 9-43

Table 9-9. Input with the E Format Item 9-45

Table 9-10. Output with the E Format Item 9-45

Table 9-11. Input with the F Format Item 9-48

Table 9-12. Output with the F Format Item 9-48

Table 9-13. Input with the P Format Item 9-51

Table 9-14. Output with the P Format Item 9-52

Table 9-15. Attributes and Access Modes for Record Files 9-73

Table 9-16. Position Information for a Record File 9-89

Table 10-1. Summary of PL/I Preprocessor Statements 10-4

Table 10-2. Implied Attributes for Variables 10-9

Table 10-3. Summary of PL/I Preprocessor Built-In Functions 10-29

Table 11-1. Summary of PL/I Built-In Functions 11-3

Table 11-2. Summary of PL/I Built-In Subroutines 11-75

Table 11-3. Pseudovariables by Dialect 11-77

Table A-1. PL/I Keywords A-1

Table D-1. PL/I Keywords Not Supported C-1

Table D-2. Summary of Unsupported IBM I/O Features C-5

Table D-3. Digital Default Values for Data Type Attribute C-7

Table E-1. Operators D-12

Table E-2. Precedence of Operators D-13

Table E-3. Contexts in Which PL/I Converts Data D-14

Table 11-4. Summary of PL/I Built-In Subroutines D-16

Preface

Kednos PL/I for UNIX is a strict superset of the ANSI X3.74-1981 PL/I General Purpose Subset and provides most of the features of the new ANSI X3.74-1987 PL/I General Purpose Subset and many of the features of the ANSI X3.53-1976 (full) PL/I language standard.

Intended Audience

This manual is intended for programmers using PL/I to design or implement applications on UNIX systems. A prerequisite for attaining optimal benefit from the manual is that its users understand the concepts of programming in PL/I and are familiar with the keywords and topics that will be searched for information.

This manual is not suitable for use as a tutorial document.

Associated Documents

The Kednos PL/I for UNIX User's Manual provides information on program development with the system-specific command language, the extensive I/O capabilities provided in PL/I, and programming techniques available to PL/I programs executing under the exclusive control of the operating system.

For information on installing PL/I, see the Kednos PL/I for UNIX Installation Guide.

Conventions

. 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 any 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.

Technical Assumptions

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 PL/I calling conventions and all conventions of the PL/I run-time environment. Except as explicitly noted, descriptions of I/O statements do not cover the effects of system-specific options.

For details on mixed-language programming and system-specific options, see the Kednos PL/I for UNIX User's Manual.

Terminological Conventions

Information in this manual applies to the use of Kednos PL/I for UNIX on the Digital UNIX Operating System unless otherwise indicated.

The term PL/I refers to Kednos PL/I for UNIX.

The terms "full PL/I" and "standard PL/I" refer to the ANSI standard PL/I, X3.53--1976.

 

Program Structure and Content

This chapter introduces the following elements of a PL/I program:

Future chapters discuss these topics in more detail.

Lexical Elements

This section describes the following topics:

Keywords

A keyword is a name that has a special meaning to PL/I when used in a specific context. In context, keywords identify statements, attributes, options, and other program elements. PL/I keywords are not reserved words, so it is possible to use them in a program in other than their keyword context.

PL/I has numerous keywords. See , See Alphabetic Summary of Keywords describes the PL/I keywords, including brief identifications of their uses and valid abbreviations for the keywords that can be abbreviated.

Punctuation

PL/I recognizes punctuation marks in statements. The punctuation marks serve the following two functions:

  • They specify arithmetic or other operations to be performed on expressions.
  • They delimit and separate identifiers, keywords, constants, and statements.

For example:

A = B + C;

 

In this statement, the equal sign (=), the addition operator (+), and the semicolon (;) delimit the identifiers A, B, and C, as well as define the operation to be performed. ( See , See Expressions and Data Type Conversions describes the effect of the various operators in expressions.)

Whenever you use a punctuation mark in a PL/I statement, you can precede or follow the character with any number of spaces (except in the case of an operator consisting of two characters, like >= or **, which you must enter without a space between the two characters). For example, the following two statements are equivalent:

DECLARE ( A, B ) FIXED DECIMAL ( 7, 0 ) ;

DECLARE(A,B)FIXED DECIMAL(7,0);

 

In the second statement, all nonessential spaces are omitted; the parentheses and commas are sufficient to distinguish elements in the statement. The only space required in this statement is the space that separates the two keywords FIXED and DECIMAL.

See . Punctuation Marks Recognized by PL/I lists all the punctuation marks recognized by PL/I.

 

. Punctuation Marks Recognized by PL/I

Category

Symbol

Meaning

Arithmetic operators

+

Addition or unary plus

-

Subtraction or unary minus

/

Division

*

Multiplication

**

Exponentiation

Relational (or comparison) operators

>

Greater than

<

Less than

=

Equal to

^>

Not greater than

^<

Not less than

^=

Not equal to

>=

Greater than or equal to

<=

Less than or equal to

Logical operators

^

Logical NOT (unary) and

EXCLUSIVE OR (binary)

&

Logical AND

&:

Logical AND THEN

| or !

Logical OR

|: or !:

Logical OR ELSE

Concatenation operator

|| or !!

String concatenation

Separators

,

Delimits elements in a list

;

Terminates a PL/I statement

.

Separates identifiers in a structure name; specifies a decimal point

:

Terminates a procedure name or a statement label

()

Encloses lists and extents; defines the order of evaluation of expressions; separates statement and option names from specific keywords; specifies a parameter list

'

Delimits character strings and bit strings

Locator qualifier

->

Pointer resolution

The tilde (~) is equivalent to the circumflex (^), and the exclamation point (!) is equivalent to the vertical bar (|).

Spaces, Tabs, and Line-End Characters

In addition to punctuation marks, PL/I accepts spaces, tabs, and line-end characters between identifiers, constants, and keywords.

The rules for entering spaces are:

  • Between any identifiers, keywords, or constants
  • Preceding or following punctuation marks that normally serve as delimiters, for example, tabs or commas

The line-end character is a valid punctuation mark between items in a PL/I statement except when it is embedded in a string constant. In a string constant, the line-end character is ignored. For example:

A = 'THIS IS A VERY LONG STRING THAT MUST BE CONTI

NUED ON MORE THAN ONE LINE IN THE SOURCE FILE';

 

This assignment statement gives the variable A the value of the specified character-string constant. (The line-end character in the constant is ignored.) Note that any tabs or spaces preceding NUED in the previous example will be included in the string.

Identifiers

An identifier is a user-supplied name for a procedure, a statement label, or a variable that represents a data item. The rules for forming identifiers are:

  • An identifier can have from 1 to 31 characters.
  • An identifier can consist of any of the following characters:
  • The alphabetic letters A through Z and a through z. PL/I converts all lowercase letters to uppercase when it compiles a source program. The identifiers abc, ABC, Abc, and so on, all refer to the same object.
  • The numeric digits 0 through 9.
  • The underscore character (_).
  • The dollar sign character ($).
  • The pound sign character (#).
  • The at sign character (@).
  • An identifier cannot contain any blanks, spaces, or hyphens.
  • An identifier must begin with an alphabetic letter, a dollar sign ($), or an underscore (_). It cannot begin with a numeral.

Examples of valid identifiers are:

STATE

total

FICA_PAID_YEAR_TO_DATE

ROUND1

PAYMENTS_IN_$S

 

Comments

A comment is an informational tool for documenting a PL/I program. To insert a comment in a program, enclose it within the character pairs /* and */. For example:

/* This is a comment ... */

 

Wherever the starting characters (/*) appear in a program, the compiler ignores all text until it encounters the ending characters (*/). A comment can span several lines.

The rules for entering comments are:

  • A comment can appear anywhere that a space can appear.
  • A comment can contain any character except the pair */; comments cannot be nested.

The following are examples of comments:

A = B + C ; /* Add B and C */

 

/* ********* START OF SECOND PHASE ********* */

 

DECLARE/*COUNTER*/A FIXED BINARY (7);

 

/* This module performs the following steps:

1. Initializes all arrays and data structures.

2. Establishes default condition handlers.

*/

 

Although complete comments cannot be nested, you can comment out a statement such as the following:

DECLARE EOF BIT(1); /* end-of-file */

 

To do this, precede the DECLARE statement with another /* pair, as follows:

/* DECLARE EOF BIT(1); /* end-of-file */

 

The compiler will then ignore all text, including the DECLARE statement and the second /*, until it reaches the */.

Statements

A statement is the basic element of a PL/I procedure. Statements are used to do the following:

See . Summary of PL/I Statements and See . Summary of PL/I Preprocessor Statements provide summaries of PL/I statements. Detailed descriptions of these statements appear throughout this manual.

Statement Formats

The general format of a PL/I statement consists of an optional condition prefix, an optional statement label, the body of the statement, and the required semicolon terminator. The format of a statement is:

[ ( condition-prefix [ ,condition-prefix ] ... ) : ] [ label: ] statement-body;

 

The body of the statement consists of user-specified identifiers, literal constants, or PL/I keywords. Each element must be properly separated, either by special characters that punctuate the statement or by spaces or comments.

Condition Prefixes (IBM Dialect Only)

The optional condition prefix specifies a PL/I condition to enable or disable for the statement. If you disable a condition, no program interrupt results if the condition occurs during execution of the statement.

The condition prefix precedes the statement label, if you specify a label, and the statement body. It consists of any valid condition or list of conditions, or the negated version of the condition or conditions, enclosed in parentheses, terminated by a colon. For example:

(ERROR,NOENDFILE): NEWREC: READ FILE (INFILE) INTO (INREC);

 

Any statement except precompiler statements (statements beginning with the % character), and the DECLARE, DEFAULT, or ENTRY statements can have condition prefixes.

If you use a condition prefix on a FORMAT statement, it must be the same prefix used on the referring GET or PUT statement.

Statement Labels

The optional statement label identifies a statement so that it can be referred to elsewhere in the program, for example, as the target of a GOTO statement. A label precedes a statement; it consists of any valid identifier terminated by a colon. For example:

TARGET: A = A + B;

READ_LOOP: READ FILE (TEXT) INTO (TEMP);

A statement cannot have more than one label. See See Identifiers for more information on identifier format.

Simple Statements

A simple statement contains only one action to be performed. There are three types of simple statements:

  • Keyword statements
  • Assignment statements
  • Null statements
Keyword Statements

Keyword statements are identified by the PL/I keyword that requests a specific action. Examples of keyword statements are:

READ FILE (A) INTO (B);

GOTO LOOP;

DECLARE COUNTER FIXED BINARY (7);

 

In these examples, READ, GOTO, and DECLARE are keywords that identify these statements to PL/I.

Assignment Statements

PL/I identifies an assignment statement by syntax: an assignment statement consists of an identifier followed by an equal sign (=) , followed by an identifier or expression. For example:

A = B;

TOTAL = TOTAL + PRICE;

COUNTER = 0;

 

Null Statements

A null statement consists of only a semicolon (;). It indicates that PL/I is to perform no operation. For example:

IF A < B THEN GOTO COMPUTE;

ELSE;

 

This IF statement shows a common use of the null statement: as the target of an ELSE clause.

Compound Statements

A compound statement contains more than one PL/I statement within the statement body. It is terminated by the semicolon that terminates the final statement. The IF and ON statements are examples of compound statements.

Preprocessor Statements

Preprocessor statements start with a percent sign (%). They can be simple or compound, as described in the preceding sections. For a full description of preprocessor statements, see See , See Preprocessor .

Summary of Statements by Function

You can group PL/I statements by function into the following categories.

Data Definition and Assignment Statements

The DECLARE statement defines variable names:

DECLARE identifier [attribute ...];

 

The assignment statement gives a value to a variable:

reference = expression;

 
Input/Output Statements

These statements identify files and data formats and perform input and output operations:

CLOSE

GET

READ

DELETE

OPEN

REWRITE

FORMAT

PUT

WRITE

Program Structure Statements

These statements define the organization of the program into procedures, blocks, and groups:

BEGIN

END

PROCEDURE

DO

ENTRY

null

Flow Control Statements

These statements change or interrupt the normal sequential flow of execution in a PL/I program:

CALL

ON

SIGNAL

GOTO

RETURN

STOP

IF

REVERT

 

LEAVE

SELECT

 

Storage Allocation Statements

These statements acquire and control the use of storage in a PL/I program:

ALLOCATE

FREE

 

See . Summary of PL/I Statements gives a summary of the PL/I statements and their uses.

. Summary of PL/I Statements

Statement

Use

Assignment

Evaluates an expression and gives its value to an identifier

Null

Specifies no operation

ALLOCATE

Allocates storage for a based or controlled variable

BEGIN

Denotes the beginning of a block of statements to be executed as a unit

CALL

Transfers control to a subroutine or external procedure

CLOSE

Terminates association of a file control block with an input or output file

DECLARE

Defines the variable names and identifiers to be used in a PL/I program and specifies the data attributes associated with them

DELETE

Removes an existing record from a file

DO

Denotes the beginning of a group of statements to be executed as a unit

END

Denotes the end of a block or group of statements begun with a BEGIN, DO, or PROCEDURE statement

ENTRY

Specifies an alternative point at which a procedure can be invoked

FORMAT

Specifies the format of data that is being read or written with GET EDIT and PUT EDIT statements and defines the conversion, if any, to be performed

FREE

Releases storage of a based or controlled variable

GET

Obtains data from an external stream file or from a character-string expression

GOTO

Transfers control to a labeled statement

IF

Tests an expression and establishes actions to be performed based on the result of the test

LEAVE

Transfers control out of a DO group

LOCATE

Allocates storage in an output buffer. Used with the BUFFERED environment option. (ibm dialect only)

ON

Establishes the action to be performed when a specified condition is signaled

OPEN

Establishes the association between a file control block and an external file

PROCEDURE

Specifies the point of invocation for a program, subroutine, or user-defined function

PUT

Transfers data to an external stream file or to a character-string variable

READ

Obtains a record from a file

RETURN

Gives back control to the procedure from which the current procedure was invoked

REVERT

Cancels the effect of the most recently established ON unit

REWRITE

Replaces a record in an existing file

SELECT

Tests a series of expressions and establishes the action to be performed based on the result of the test

SIGNAL

Causes a specific condition to be signaled

STOP

Halts the execution of the current program

WRITE

Copies data from the program to an external record file

Program Format

A PL/I program consists of a series of statements, which perform the following tasks:

A statement comprises user-specified identifiers, constants, and PL/I keywords, separated by blanks, comments, and punctuation marks. You can organize statements into structural sequences of groups or blocks. See . Structure of a PL/I Program shows the structure of a PL/I program.

. Structure of a PL/I Program

SAMPLE: PROCEDURE OPTIONS (MAIN);

 

DECLARE (X,Y,Z) FIXED, À

MESSAGE CHARACTER(80) INITIAL ('HELLO'),

CALC ENTRY (FLOAT) RETURNS (FLOAT),

TOTAL FLOAT;

 

X = 0; Ã

PUT SKIP LIST(MESSAGE);

 

FINISH: PROCEDURE; Õ

DECLARE TEXT (5) CHARACTER (20);

END FINISH;

 

END SAMPLE;

 

Key to See . Structure of a PL/I Program :

A PROCEDURE is the basic executable program unit.

À The declarations of variables in a procedure are usually, but not necessarily, placed at the beginning of the procedure.

à Executable statements are placed following variable declarations.

Õ Internal procedures may be placed anywhere.

All procedures must terminate with END statements.

The source text of a PL/I program is freeform. As long as you terminate every statement with a semicolon (;), individual statements can begin in any column, be on additional lines, or be written with more than one statement to a line.

Individual keywords or identifiers of a statement, however, must be confined to one line. Only a character-string constant (which must be enclosed in apostrophes) can be on more than one line.

PL/I programs are easier to read and comprehend if you follow a standard pattern in formatting. For example:

  • Write source statements with no more than one statement per line.
  • Use indention to show the nesting level of blocks and DO-groups.

Blocks

PL/I is a block-structured language with each block composed of a sequence of PL/I statements. There are two types of blocks:

Scope of Names

The scope of a declaration of a name is that region of the program in which the name has meaning. A name has meaning in the following locations:

  • The block in which it is declared
  • Any blocks contained within the declaring block, as long as the name is not redeclared in the contained block
  • Any procedure contained in the program, if the name is declared outside a procedure

Two or more declarations of the same name are not allowed in a single block unless one or more of the declarations are of structure members.

Two declarations of the same name in different blocks denote distinct objects unless both specify the EXTERNAL attribute. All EXTERNAL declarations of a particular name denote the same variable or constant, and all must agree as to the properties of the variable or constant, otherwise unpredictable results will occur. Note that EXTERNAL is the default for declarations of ENTRY and FILE constants. It must be specified explicitly for variables.

The following example shows the scope of internal names:

 

NAME

SCOPE

DECLARE Q STATIC FIXED;

Q

MAINP, ALPHA, BETA, and CALC

MAINP: PROCEDURE OPTIONS (MAIN);

MAINP

MAINP, ALPHA, BETA, and CALC

DECLARE (X, Y, Z) FIXED;

X, Y

MAINP, ALPHA, BETA, and CALC

 

Z in MAINP

MAINP, ALPHA, and CALC

 

 

 

ALPHA: PROCEDURE;

ALPHA

MAINP, ALPHA, BETA, and CALC

BETA: BEGIN;

BETA

ALPHA, BETA

DECLARE Z FLOAT;

Z in BETA

BETA

GOTO ERROR;

 

 

END BETA;

 

 

ERROR:

ERROR

ALPHA, BETA

END ALPHA;

 

 

 

 

 

CALC: PROCEDURE;

CALC

MAINP, ALPHA, and CALC

DECLARE (SUM, TOTAL) FLOAT;

SUM, TOTAL

CALC

END CALC;

 

 

END MAINP;

 

 

Declarations can appear outside procedures and, if contained within the same block, have meaning throughout all procedures contained in the block. However, if there are multiple blocks, declarations outside procedures must have the EXTERNAL attribute if they are to be recognized by all blocks and procedures in the program. For example:

File A.PLI

DECLARE X FIXED EXTERNAL STATIC;

A: PROCEDURE OPTIONS(MAIN);

DECLARE B ENTRY;

END A;

 

File B.PLI

B: PROCEDURE;

END B;

 

In this example, the variable X has meaning in both procedures, which are part of the same program. Because the two procedures are in two different files, X must be declared with the EXTERNAL attribute. If X is declared with the INTERNAL attribute, X is recognized only in the first procedure.

Begin Blocks

A begin block is a sequence of statements headed by a BEGIN statement (see See BEGIN Statement ) and terminated by an END statement (see See END Statement ). In general, you can use a begin block wherever a single PL/I statement would be valid. In some contexts, such as an ON-unit, a begin block is the only way to perform several statements instead of one. A primary use of begin blocks is to localize variables. Because execution of a begin block causes a block activation, automatic variables declared within the begin block are local to it, and their storage disappears when the block completes execution.

Another way to allow your program to perform several statements in place of one is to use a DO group (see See DO Groups and Statements ). You should choose it when possible because it does not incur the overhead associated with block activation. Use a begin block when there are declarations present or when you require multiple statements in an ON unit.

Procedure Blocks

A procedure is a sequence of statements (possibly including begin blocks and other procedures) headed by a PROCEDURE statement and terminated by an END statement. Unlike a begin block, which executes when control reaches it, a procedure executes only when it is specifically invoked. Invocation occurs in the following ways:

  • Enter the name of the program to invoke the main procedure of a PL/I program. This is the procedure that has OPTIONS(MAIN) on its PROCEDURE statement.
  • Statements within a procedure can invoke other procedures. The CALL statement invokes a procedure as a subroutine. A function reference invokes a function, which is a procedure that returns a value for use in the evaluation of an expression.

A PL/I program must have at least one procedure, the main procedure. Any procedure, including the main procedure, can contain others; these are called internal procedures. A procedure that is not contained within any other is called an external procedure. The main procedure is always an external procedure.

Except for the main procedure, no procedure executes unless it is invoked by a CALL statement or a function reference. See , See Procedures discusses procedures in more detail.

Containment

As an example, block B is said to be contained in another block A if all of B's source text, from label (if any) to END statement inclusive, is between A's BEGIN or PROCEDURE statement and A's END statement. If block B is not contained in any other block within block A, then B is said to be immediately contained in A. For example:

A: PROCEDURE OPTIONS(MAIN);

B: PROCEDURE;

END B;

BEGIN;

CALL B;

END; /* of begin block */

END A;

 

The procedures B and the begin block all are immediately contained in A.

If block B is contained in block A, then B is said to be nested in A. The maximum nesting level is 64.

Block Activation

A block is activated when program execution flows into it. The following events happen when a block is activated:

  • All automatic variables declared in the block become active
  • All parameters passed to the block become active

When control leaves the block, the automatic variables become undefined and inaccessible.

You can only enter a procedure block with a CALL statement (see See CALL Statement ) or a function reference. If an internal procedure is declared within a source program, control flows around the internal procedure during the normal sequence of execution.

A begin block is entered when it is encountered during the normal flow of execution or when a GOTO statement transfers control to a labelled BEGIN statement.

Relationship of Block Activations

During the execution of a program, many blocks can be simultaneously active. Two different relationships can be defined among block activations; they are the immediate dynamic descendance and the immediate parent activation.

For example:

B: PROCEDURE OPTIONS(MAIN);

A: PROCEDURE;

CALL Q;

END A;

Q: PROCEDURE;

END Q;

BEGIN;

CALL A;

END; /* of begin block */

END B;

 

See . Relationship of Block Activations shows these relationships.

 

. Relationship of Block Activations

In the immediate dynamic descendance relationship, a block activation is the immediate dynamic descendant of the block that invoked it. At a given time, the chain of immediate dynamic descendants includes all existing block activations, starting with the activation of the main procedure and terminating in the current block activation. For example, in See . Relationship of Block Activations , the begin block is the immediate dynamic descendant of procedure B; the complete chain is B, begin block, A, Q. This chain is used for finding the applicable ON-unit when a condition is signaled.

The other relationship shown in See . Relationship of Block Activations applies to activations of nested blocks. An activation of a block X that is a begin block or internal procedure has an immediate parent activation, which is an activation of the block that immediately contains X. The chain of immediate parent activations extends back to an activation of the external procedure containing X. In See . Relationship of Block Activations , the parent chain for the begin block, procedure A, and procedure Q leads directly back to the activation of B, because each of these blocks is immediately contained in B. This chain is used in interpreting references.

When a block is activated, its immediate parent activation is determined as follows:

  • If the block is an external procedure, it has no parent activation.
  • If the block is a begin block, its immediate parent activation is the activation that invoked it. Therefore, the begin block is the immediate dynamic descendant of its immediate parent.
  • If the block is an internal procedure invoked in block activation B by a reference to an entry constant (such as A in See . Relationship of Block Activations ) declared in block B, then the immediate parent of the new block activation of A is the activation of A in the parent chain starting at B.
  • If the block is an internal procedure invoked by an entry variable, the parent activation is taken from the entry value. It was originally set when the complete entry value was generated by the assignment of an entry constant to an entry variable ( See Entry Data discusses entry data).

Block Termination

When a block terminates normally, that is, when an END statement or a RETURN statement is executed, the following events occur:

  • the current block is released and control goes to the preceding block activation.
  • If a nonlocal GOTO statement is executed that transfers control out of the current block, the current block and any blocks between it and the block containing the label that is the target of the GOTO statement are released.
  • The on-unit environment is reset to its former state.
  • Storage allocated for automatic variables local to the block is released.
  • Any tasks attached to the block terminate.

Data and Variables

The statements in a PL/I program process data, generally in the form of variables that take on different values as the result of program execution. In PL/I, you must declare variables in a DECLARE statement in the scope where you reference them. The compiler assigns the default attributes to any undeclared variables (see See Default Attributes for more information).

Declaring a variable, or using an undeclared variable, associates an identifier with a set of attributes and with a region of storage. Thus, when you declare a variable you must usually specify one or more data type attributes to be associated with it. (The concept of an attribute is more basic to PL/I than the concept of a data type.) Furthermore, you can specify how the variable is to be allocated by supplying a storage-class attribute in the declaration.

A few examples of PL/I attributes are BIT, CHARACTER, BINARY, DECIMAL, FILE, FLOAT, PRINT, UPDATE, and VALUE. For a complete alphabetic list of the PL/I attributes with their uses, see See Attributes .

An identifier can refer to a single variable (called a scalar variable) or to a collection of related variables. Such a collection is called an aggregate. There are two kinds of aggregates:

The following chapters provide information on these topics:

Preprocessor

PL/I supports an embedded lexical preprocessor, which recognizes a specific set of statements that are executed at compile time. These statements cause the PL/I compiler to include additional text in the source program or to change the values of constant identifiers at compile time.

Preprocessor statements are identified by a leading unquoted percent sign (%) and are terminated by an unquoted semicolon (;), except for %THEN and %IF statements. You can freely intermix preprocessor statements with the rest of the source program statements.

For additional information on the PL/I preprocessor and preprocessor statements, see See , See Preprocessor .

 

Declarations

The declaration of a name in a PL/I program consists of a user-specified identifier and the attributes of the name. The attributes describe the following:

A name is declared either explicitly in a DECLARE statement or implicitly by its appearance in a particular context. For example:

CALC: PROCEDURE;

 

This statement is an implicit declaration of the name CALC as an entry constant.

This chapter describes the DECLARE statement and data attributes.

DECLARE Statement

The DECLARE statement specifies the attributes associated with names. The format of the DECLARE statement is:

level

Levels are integral values that specify the relationship of members of structures. Specify the level first, before the rest of the declaration.

declaration

Declarations consist of identifiers and attributes. A declaration has the following format:

The format of the DECLARE statement varies according to the number and nature of the items being declared. You can declare a single identifier, optionally specifying a level, bound-pair list, and other attributes for that identifier. Or you can include, in parentheses, a list of declarations to which the level and all subsequent attributes apply. In this case you can specify simple identifiers or you can include attributes for individual identifiers.

Use bound pairs to specify the dimensions of arrays. Bound pairs must be in parentheses and must immediately follow the identifier or the list of declarations.

The following sections describe various formats of the DECLARE statement.

Simple Declarations

A simple declaration defines a single name and describes its attributes. The format of a simple declaration is:

DECLARE identifier [attribute ...] ;

 
identifier

A 1- to 31-character user-supplied name. The name must be unique within the current block.

An identifier can consist of any of the alphanumeric characters A through Z, a through z, 0 through 9, dollar signs ($), underscores (_), pound sign (#) and at sign (@), but must begin with an alphabetic letter, dollar sign, underscore, pound sign or at sign.

attribute

One or more attributes of the name. Attribute keywords must be separated by spaces. They can appear in any order.

See Attributes for a list of the valid attribute keywords and their meanings.

The following are examples of simple declarations:

DECLARE COUNTER FIXED BINARY (7);

DECLARE TEXT_STRING CHARACTER (80) VARYING;

DECLARE INFILE FILE;

 

If you do not give a name specific attributes in a DECLARE statement or you reference an undeclared name, the name has the default attributes FIXED BINARY (31) AUTOMATIC. Note that the compiler issues a warning message whenever it gives default attributes to a name.

Declarations Outside Procedures

You can declare a variable outside any procedure. Any variable so declared is visible to all procedures contained by the module. The format for declarations outside procedures is the same as for other declarations, however the storage-class attribute cannot be AUTOMATIC. If you do not specify a storage-class or you specify it as AUTOMATIC, the compiler issues a warning and supplies the STATIC attribute. The following example shows the use of this type of declaration:

DECLARE A STATIC FIXED BINARY(31);

FIRST: PROCEDURE;

DECLARE B FIXED BINARY(31);

END FIRST;

 

SECOND: PROCEDURE;

DECLARE C FIXED BINARY(31);

END SECOND;

 

In this example, variable A is visible in both the FIRST and SECOND procedures, but variables B and C are visible only in their containing procedures.

Multiple Simple Declarations

Multiple simple declarations define two or more names and their individual attributes. This format of the DECLARE statement is:

DECLARE identifier [attribute ... ] [,identifier [attribute ... ]] ...;

 

When you specify more than one set of names and their attributes, separate each name and attribute set from the preceding set with a comma. A semicolon must follow the last name.

The following example shows multiple declarations:

DECLARE COUNTER FIXED BINARY (7),

TEXT_STRING CHARACTER (80) VARYING,

Y FILE;

 

This DECLARE statement defines the variables COUNTER, TEXT_STRING, and Y. The attributes for each variable follow the name of the variable.

Factored Simple Declarations

When two or more names have common attributes, you can combine the declarations into a single, factored declaration. This format of the DECLARE statement is:

DECLARE (identifier[,identifier ...]) [attribute ...];

 

When you use this format, place names that share common attributes in parentheses and separate them with commas. The attributes that follow the parenthetical list of names are applied to all the named identifiers.

The following examples show factored declarations:

DECLARE (COUNTER, RATE, INDEX) FIXED BINARY (7) INITIAL (0);

DECLARE (INPUT_MESSAGE, OUTPUT_MESSAGE, PROMPT)

CHARACTER (80) VARYING;

 

In these declarations, the variables COUNTER, RATE, and INDEX share the attributes FIXED BINARY (7) and are given the initial value of zero. The variables INPUT_MESSAGE, OUTPUT_MESSAGE, and PROMPT share the attributes CHARACTER (80) VARYING.

You can also specify attributes, within the parentheses, attributes that are unique to specific variable names within the parenthetical list. Use the following format:

DECLARE (declaration-item, declaration-item [,declaration-item]) attribute ...

 

For example:

DECLARE (INFILE INPUT RECORD,

OUTFILE OUTPUT STREAM) FILE;

 

The DECLARE statement declares INFILE as a RECORD INPUT file and OUTFILE as a STREAM OUTPUT file.

You can nest parentheses, as shown in the following example:

DECLARE ( (INFILE INPUT, OUTFILE OUTPUT) RECORD,

SYSFILE STREAM ) FILE;

 

The DECLARE statement declares INFILE as a RECORD INPUT file, OUTFILE as a RECORD OUTPUT file, and SYSFILE as a STREAM file.

Array Declarations

The declaration of an array specifies the dimensions of the array and the bounds of each dimension. This format of a DECLARE statement is:

DECLARE declaration (bound-pair, ...) [attribute ...];

 

where each bound pair has the following format:

Specify one bound pair for each dimension of the array. The number of elements per dimension is defined by the bound pair. The extent of an array is the product of the numbers of elements in its dimensions. If you omit the lower bound, the lower bound for that dimension is 1 by default.

For example:

DECLARE SALARIES(100) FIXED DECIMAL(7,2);

 

This statement declares a 100-element array with the identifier SALARIES. Each element is a fixed-point decimal number with a total of seven digits, two of which are fractional. The identifier in the statement can be replaced with a list of declarations, to declare several objects with the same attributes. For instance:

DECLARE (SALARIES,PAYMENTS) (100) FIXED DECIMAL(7,2);

 

This declares SALARIES and another array, PAYMENTS, with the same dimensions and other attributes.

You can use an asterisk (*) as the bound pair when you declare arrays as parameters of a procedure. The asterisk indicates that the parameter can accept array arguments with any number of elements. If you specify one array dimension with an asterisk, you must specify all dimensions of that array with asterisks. See See Rules for Specifying Parameters for more information and examples.

For further details on how to specify the bounds of an array, and for examples of array declarations, see See Array Declarations .

Structure Declarations

The declaration of a structure defines the organization of the structure and the names of members at each level in the structure. This format of a DECLARE statement is:

Each declaration specifies a member of the structure and must be preceded by a level number. As shown in the following example, a single variable can be declared at a particular level; or the level can contain one or more complete declarations, including declarations of arrays or other structures. The major structure name is declared as structure level 1; minor members must be declared with level numbers greater than 1.

DECLARE 1 PAYROLL,

2 NAME,

3 LAST CHARACTER(80) VARYING,

3 FIRST CHARACTER(80) VARYING,

2 SALARY FIXED DECIMAL(7,2);

 

This statement declares a structure named PAYROLL.

Alternatively, because the last and first names have the same attributes, the same structure can be declared as follows:

DECLARE 1 PAYROLL,

2 NAME,

3 (LAST,FIRST) CHARACTER(80) VARYING,

2 SALARY FIXED DECIMAL(7,2);

 

For details and examples of structure declarations, see See Structure Declarations and Attributes .

Attributes

Attributes define and describe the characteristics of names used in a PL/I program. Each name in a PL/I program has a set of attributes associated with it. You can specify attributes in any of the following contexts:

DECLARE SIGNAL CHARACTER (20);

 

In this declaration, the keyword attribute CHARACTER is associated with the identifier SIGNAL. The syntax length attribute of the variable is specified in parentheses following the CHARACTER keyword. In this manual, keyword attributes are shown in format lines in uppercase letters. Attributes given by syntax are shown in lowercase letters.

Attributes can also be implied by the presence of other attributes. For example, if the RETURNS attribute is specified for an identifier, the compiler supplies the ENTRY attribute by default.

The entry for each attribute in this chapter gives its syntax and abbreviation (if any) and describes related and conflicting attributes. See See . Alphabetic Summary of PL/I Attributes for a concise alphabetic summary of PL/I attributes.

Computational Data Type Attributes

The attributes that define arithmetic and string data are:

You can specify these attributes for all elements of an array and for individual members of a structure.

Noncomputational Data Type Attributes

The following attributes apply to program data that is not used for computation:

AREA

CONDITION

ENTRY [VARIABLE]

FILE [VARIABLE]

LABEL

OFFSET

POINTER

 

Storage-Class and Scope Attributes

The following attributes control the allocation and use of storage for a computational variable and define the scope of the variable:

AUTOMATIC [INITIAL(initial-element,...)]

BASED [(pointer-reference)] [INITIAL(initial-element,...)]

CONTROLLED [INITIAL(initial-element,...)]

DEFINED(variable-reference) [POSITION(expression)]

STATIC [READONLY] [INITIAL(initial-element,...)]

PARAMETER

INTERNAL

Member Attributes

You can apply the following attributes to the major or minor members of a structure:

LIKE

MEMBER

REFER

STRUCTURE

TYPE

UNION

 
File Description Attributes

You can apply the following attributes to file constants and used in OPEN statements:

Entry Name Attributes

You can apply the following attributes to identifiers of entry points:

Nondata Type Attributes

You can apply the following attributes to data declarations:

ALIGNED

DIMENSION

UNALIGNED

 

See . Alphabetic Summary of PL/I Attributes lists the PL/I attributes. The sections following this table describe each attribute in detail.

. Alphabetic Summary of PL/I Attributes  

Attribute

Use

ALIGNED

Requests alignment of bit-string variables in storage

ANY

Indicates that a parameter (of an external procedure not written in PL/I) can have any data type

AREA [(extent)]

Defines an area of storage for the allocation of based variables

 

Requests dynamic allocation of storage for a variable

BASED [(pointer-reference)]

Indicates that a variable's storage is located by a pointer

 

Defines a binary base for arithmetic data

BIT [(length)]

Defines bit-string data

 

Specifies whether records of a record file should or should not pass through intermediate storage buffers. (ibm dialect only)

BUILTIN

Defines a built-in function name

 

Defines character-string data

 

Defines an identifier as a condition name

 

Defines a variable whose storage is allocated and freed in successive and fixed-sequence generations

 

Defines a decimal base for arithmetic data

 

Indicates that a variable will share the storage allocated for another variable

 

Indicates that a variable is an array, and defines the number and extent of its dimensions

DIRECT

Specifies that a file will be only accessed randomly

ENTRY (descriptor, ...)

Describes an external procedure and its parameters

 

Specifies system-dependent information about a file

 

Identifies the name of a variable whose storage is referenced or defined in other procedures

FILE

Identifies a PL/I file constant or file variable

FIXED [(precision[,scale-factor])]

Defines a fixed-point arithmetic variable

FLOAT [(precision)]

Defines a floating-point arithmetic variable

GLOBALDEF [(psect-name)]

Defines an external variable and optionally specifies the program section in which the variable will reside

GLOBALREF

Declares an external variable which is defined in an external procedure

 

Provides initial values for variables

INPUT

Specifies that a file will be used for input

 

Limits the scope of a variable to the block in which it is defined

KEYED

Specifies that a file can be accessed randomly by key

LABEL

Defines a label variable

LIKE structure-reference

Copies the declaration of a structure to another structure variable

MEMBER

Specifies that an item is a member of a structure

 

Specifies that the length of a string is nonvarying

OFFSET [(area-reference)]

Defines an offset variable

OPTIONAL

Indicates that a parameter need not be specified in a call.

OUTPUT

Specifies that a file will be used for output

 

Indicates that a variable will be assigned a value when it is used as an argument to a procedure

 

Specifies the format of numeric data stored in character form

 

Defines a pointer variable

 

Specifies the position within a variable at which a defined variable begins

 

Specifies the number of digits in an arithmetic variable and, with fixed-point data, the number of fractional digits

PRINT

Specifies that a file is to be formatted for printing

READONLY

Specifies that a static variable's value does not change during program execution

RECORD

Specifies that a file will be accessed by record I/O statements

REFER

Defines dynamically self-defining structures

RETURNS (returns-descriptor)

Specifies that an external entry is a function and describes the value returned by it

 

Specifies that a file can be accessed sequentially

STATIC

Requests static allocation of storage

STREAM

Specifies that a file will be accessed by stream I/O statements

STRUCTURE

Specifies that a variable is a structure variable

TRUNCATE

Specifies, in a declaration of a formal parameter, that the actual parameter list can be truncated at the point where this argument should occur

TYPE

Copies declarations of structures, scalars, and arrays to another variable

 

Specifies nonalignment for bit-string variables in storage

UNION

Indicates that a variable will share the storage allocated for another variable

UPDATE

Specifies that records in a file can be rewritten or deleted

 

Requests either that a global symbol be accessed by value rather than by reference, or that an argument be passed to a procedure by immediate value

VARIABLE

Defines variable entry and file data

 

Defines a varying-length character or bit string

ALIGNED Attribute

The ALIGNED attribute controls the storage boundary of bit-string data in storage. The format of the ALIGNED attribute is:

ALIGNED

 

You can specify the ALIGNED attribute in conjunction with the BIT attribute in a DECLARE statement to request alignment of a bit-string variable on a byte boundary. If you specify ALIGNED for an array of bit-string variables, each element of the array is aligned.

You can specify ALIGNED in the declaration of a nonvarying character-string variable. Specifying ALIGNED is not recommended with character strings, as all character strings are byte-aligned.

Restriction

The ALIGNED attribute conflicts with the VARYING attribute and is invalid with all data-type attributes other than BIT and CHARACTER. You must specify either BIT or CHARACTER with the ALIGNED attribute.

ANY Attribute

The ANY attribute specifies that an entry's corresponding argument can be of any data type. This attribute is applicable only to the declaration of entry names denoting non-PL/I procedures. The format of the ANY attribute is:

Restrictions

If you specify ANY for a parameter, you cannot specify any data-type attributes for that parameter except CHARACTER(*). If ANY is used by itself, the parameter is passed by reference. If ANY is used with VALUE, the parameter is passed by immediate value. If ANY is used with CHARACTER(*), the parameter is passed by character descriptor.

Example

DECLARE EXT_ROUTINE ENTRY (ANY VALUE);

 

This statement identifies the procedure EXT_ROUTINE and indicates that the procedure accepts a single argument, of any data type, passed by value.

AREA Attribute

The AREA attribute defines an area variable. The format of the AREA attribute is:

AREA [(extent)]

 
extent

The size of the area in bytes. The extent must be a nonnegative integer. The maximum size is 500 million bytes.

The rules for specifying the extent are:

  • If AREA is specified for a static variable declaration, extent must be a restricted integer expression. A restricted integer expression is one that yields only integral results and has only integral operands. Such an expression can use only the addition (+), subtraction (-), and multiplication (*) operators.
  • If AREA is specified in the declaration of a parameter or in a parameter descriptor, you can specify extent as an integer constant or as an asterisk (*).
  • If AREA is specified for an automatic or based variable, you can specify extent as an integer constant or as an expression. For automatic variables, the extent expression must not contain any variables or functions declared in the same block, except for parameters.
  • If no extent is specified for the area, a default of 1024 bytes is provided. Kednos recommends explicitly specifying a size, because the default varies considerably between PL/I implementations.
Restrictions

The AREA attribute is not allowed in a returns descriptor. The AREA attribute conflicts with all other data-type attributes.

AUTOMATIC Attribute

The AUTOMATIC attribute specifies, for one or more variables, that PL/I is to allocate storage only for the duration of a block. An automatic variable is not allocated storage until the block that declares it is activated. The storage is released when the block is deactivated. The format of the AUTOMATIC attribute is:

AUTOMATIC explicitly defines the storage-class of a variable, array, or major structure in a DECLARE statement. Because AUTOMATIC is the default for internal variables, you need not specify it.

Restriction

The AUTOMATIC attribute conflicts with the following attributes (the specification of which implies that storage allocation is not to be automatic):

BASED

GLOBALREF

CONTROLLED

PARAMETER

DEFINED

READONLY

EXTERNAL

STATIC

GLOBALDEF

 

The AUTOMATIC attribute cannot be applied to minor structures, members of structures, parameters, or descriptions in an ENTRY or RETURNS attribute.

For a discussion of PL/I storage allocation, see See , See Storage Classes .

BASED Attribute

The BASED attribute defines a based variable, that is, a variable whose actual storage will be denoted by a pointer or offset reference. The format of the BASED attribute is:

BASED [ (reference) ]

 
reference

A reference to a pointer or offset variable or pointer-valued function. If the reference is to an offset variable, that variable must be declared with a base area. Each time a reference is made to a based variable without an explicit pointer or offset qualifier, the reference is evaluated to obtain the pointer or offset value.

Restriction

The following attributes conflict with the BASED attribute:

AUTOMATIC

GLOBALDEF

READONLY

CONTROLLED

GLOBALDEF

STATIC

DEFINED

PARAMETER

VALUE

EXTERNAL

 

 

The BASED attribute cannot be applied to minor structures, members of structures, parameters, or descriptions in an ENTRY or RETURNS attribute. See See Based Variables for more information.

BINARY Attribute

The BINARY attribute specifies that an arithmetic variable has a binary base. The format of the BINARY attribute is:

When you specify the BINARY attribute for an identifier, you can also specify one of the following attributes to define the scale and precision of the data:

FIXED [(precision)]

FLOAT [(precision)]

 

FIXED indicates a fixed-point binary value and FLOAT indicates a floating-point binary value.

For a fixed-point binary value, the precision specifies the number of bits representing an integer and must be in the range 1 through 31.

For a floating-point value, the precision specifies the number of bits representing the mantissa of a floating-point number and must be in the range 1 through 53

The maximum floating-point binary precision is always 53. The default values applied to the BINARY attribute are listed in See . Default Values for BINARY Attribute :

. Default Values for BINARY Attribute

Attributes Specified

dec Dialect

ibm Dialect

ansi Dialect

BINARY

FIXED (31)

FIXED (15)

FIXED (15)

BINARY FIXED

(31)

(15)

(15)

BINARY FLOAT

(24)

(21)

(24)

Restrictions

The BINARY attribute directly conflicts with any other data-type attribute.

BIT Attribute

The BIT attribute identifies a variable as a bit-string variable. The format of the BIT attribute is:

BIT[(length)]

 
length

The number of bits in the variable. If you do not specify a length, the default length is 1 bit. The length must be in the range 0 through 32,767.

The rules for specifying the length are:

  • If the attribute is specified for a static variable declaration or in a returns descriptor, length must be a restricted integer expression. A restricted integer expression is one that yields only integral results and has only integral operands. Such an expression can use only the addition (+), subtraction (-), and multiplication (*) operators.
  • If the attribute is specified in the declaration of a parameter or in a parameter descriptor, you can specify length as a restricted integer expression or as an asterisk (*).
  • If the attribute is specified for an automatic, based, controlled, or defined variable, you can specify length as an expression. In the case of automatic or defined variables, the expression must not contain any variables or functions that are declared in the same block except for parameters.

If specified, the length in parentheses must follow the keyword BIT.

If you give a variable the BIT attribute, you can also specify the ALIGNED attribute to request alignment of the variable on a byte boundary in storage.

Restriction

The BIT attribute directly conflicts with any other data-type attribute.

BUFFERED and UNBUFFERED Attributes (IBM Dialect Only)

The BUFFERED and UNBUFFERED file description attributes specify whether or not each record of a RECORD file must pass through intermediate storage buffers during transmission to auxiliary storage. The format of the BUFFERED attribute is:

The format of the UNBUFFERED attribute is:

If you specify BUFFERED, data transmission is usually overlapped with processing. You must specify BUFFERED in a file description to use the LOCATE statement on that file.

If you specify UNBUFFERED, records in the file do not need to pass through a buffer. They may be transmitted directly to and from the main storage associated with the variable. However, buffers may still be used if the records in the file are variable-length. When you specify UNBUFFERED, data transmission is not overlapped with processing.

You can specify the BUFFERED or UNBUFFERED attribute in a DECLARE statement for a file constant.

Restriction

The BUFFERED attribute conflicts with the UNBUFFERED attribute. Buffering only applies to RECORD files.

BUILTIN Attribute

The BUILTIN attribute indicates that the name declared is the name of a PL/I built-in function. Within the block in which the name is declared, all references to the name will be interpreted as references to the built-in function or pseudovariable of that name. The format of the BUILTIN attribute is:

BUILTIN

Use the BUILTIN attribute when you want to refer to a built-in function within a scope where you used the function's name as a variable name.

You can also use the BUILTIN attribute to invoke a built-in function that takes no arguments (such as the DATE function) without including a null argument list.

Restriction

When you specify the BUILTIN attribute, you cannot specify any other attributes.

Examples

OUTER: PROCEDURE;

DECLARE MAX FIXED BINARY STATIC INITIAL (10);

INNER: PROCEDURE;

DECLARE MAX BUILTIN, /* supersedes the variable */

(A,B,TEST) FIXED BIN(15);

A = 10;

B = 20;

TEST = MAX(A,B);

END INNER;

END OUTER;

 

The keyword MAX is used here as a variable name. In the internal procedure INNER, the MAX built-in function is invoked. Because the scope of the name MAX includes the internal procedure, the function must be redeclared with BUILTIN.

You can also use the BUILTIN attribute to declare PL/I built-in functions that have no arguments, if you want to invoke them without the empty argument list. For example:

DECLARE DATE BUILTIN;

PUT LIST(DATE);

 

Without the declaration, the PUT LIST statement would have to include an empty argument list for DATE:

PUT LIST(DATE());

 

CHARACTER Attribute

The CHARACTER attribute identifies a variable as a character-string variable. The format of the CHARACTER attribute is:

length

The number of characters in a fixed-length string or the maximum length of a varying- length string. If not specified, a length of 1 is assumed. The length must be in the range 0 through 32,767 characters.

The rules for specifying the length are:

  • If the attribute is specified for a static variable declaration or in a returns descriptor, length must be a restricted integer expression.
  • If the attribute is specified in the declaration of a parameter or in a parameter descriptor, you can specify length as a restricted integer expression or as an asterisk (*).
  • If the attribute is specified for an automatic, based, or defined variable, you can specify length as an expression. In the case of automatic or defined variables, the expression must not contain any variables or functions that are declared in the same block except for parameters.

If specified, the length must immediately follow the keyword CHARACTER, and it must be enclosed in parentheses.

If you give a variable the CHARACTER attribute, you can also specify the attribute VARYING, NONVARYING, ALIGNED, or UNALIGNED.

Restriction

The CHARACTER attribute directly conflicts with any other data-type attribute.

CONDITION Attribute

You can optionally use the CONDITION attribute in a declaration to specify that the variable name is a condition name. You can specify INTERNAL or EXTERNAL scope attributes with the CONDITION attribute. The default scope is external. The format of the CONDITION attribute is:

condition-name

Name used for ON units to handle programmer-defined conditions.

CONTROLLED Attribute

The CONTROLLED attribute causes a variable's actual storage to be allocated and freed dynamically in generations, only the most recent of which is accessible to the program. The format of the CONTROLLED attribute is:

Restrictions

The following attributes conflict with the CONTROLLED attribute:

AUTOMATIC

BASED

DEFINED

GLOBALDEF

GLOBALREF

READONLY

STATIC

VALUE

PARAMETER

 

The CONTROLLED attribute cannot be applied to minor structures, members of structures, parameters, or descriptions in an ENTRY or RETURNS attribute.

See See Controlled Variables for more information.

DECIMAL Attribute

The DECIMAL attribute specifies that an arithmetic variable has a decimal base. The format of the DECIMAL attribute is:

When you specify the DECIMAL attribute for a variable, you can also specify the following attributes to define the scale factor and precision of the data:

FIXED (precision[,scale-factor])

FLOAT (precision)

 

FIXED indicates a fixed-point value, and FLOAT indicates a floating-point decimal value.

(precision[,scale-factor])

The precision of a fixed-point decimal value is the total number of integral and fractional digits. The precision of a floating-point decimal value is the total number of digits in the mantissa.

The precision for a fixed-point decimal value must be in the range 1 through 31; the scale factor, if specified, must be greater than or equal to 0 and less than or equal to the specified precision.

The precision for a floating-point decimal value must be in the range 1 through 15.

The default values applied to the DECIMAL attribute are listed in See . Default Values for the DECIMAL Attribute. .

. Default Values for the DECIMAL Attribute.

Attributes Specified

dec Dialect

ibm Dialect

ansi Dialect

DECIMAL

FIXED (10,0)

FIXED (5,0)

FIXED (10,0)

DECIMAL FIXED

(10,0)

(5,0)

(10,0)

DECIMAL FIXED (n)

(n,0)

(n,0)

(n,0)

DECIMAL FLOAT

(7)

(6)

(7)

Restrictions

The DECIMAL attribute conflicts with any other data-type attribute.

DEFINED Attribute

The DEFINED attribute indicates that PL/I is not to allocate storage for the variable, but is to map the description of the variable onto the storage of another base variable. The DEFINED attribute provides a way to access the same data using different names. The format of the DEFINED attribute is:

variable-reference

A reference to a variable that has storage associated with it. The variable must not have the BASED, CONTROLLED, or DEFINED attribute. The variable and the declared variable must satisfy the rules given in See Defined Variables .

The DEFINED attribute can optionally specify a position within the referenced variable at which the definition begins. For example:

DECLARE ZIP CHARACTER(20),

ZONE CHARACTER(10)

DEFINED(ZIP) POSITION(4);

 

Restrictions

The following attributes conflict with the DEFINED attribute:

AUTOMATIC

BASED

CONTROLLED

EXTERNAL

GLOBALDEF

GLOBALREF

INITIAL

PARAMETER

READONLY

STATIC

UNION

VALUE

The DEFINED attribute cannot be applied to minor structures, members of structures, parameters, or descriptions in an ENTRY or RETURNS attribute.

See See Defined Variables for more information.

DIMENSION Attribute

The DIMENSION attribute defines a variable as an array. It specifies the number of dimensions of the array and the bounds of each dimension. The format of the DIMENSION attribute is:

bound-pair

One or two expressions that indicate the number of elements in a single dimension of the array. You must specify the list of bound pairs immediately following the name of the identifier in the array declaration if the optional keyword DIMENSION or DIM is omitted; otherwise, you must specify the list of bound pairs immediately following the keyword DIMENSION or DIM. See the following examples.

The maximum number of dimensions allowed is eight.

A bound pair can be specified:

  • [lowerbound:]upperbound

This format of a bound pair specifies the minimum and maximum subscripts that can be used for the dimension. The number of elements is:

(upperbound- lowerbound) + 1

If the lower bound is omitted, it defaults to 1.

This format of a bound pair, when used to define a parameter for a procedure or function, indicates that the bounds are to be determined from the associated argument. If one bound pair is specified as an asterisk, all bound pairs must be specified as asterisks.

The following two declarations are exactly equivalent:

DECLARE A(10) FIXED BIN;

DECLARE A FIXED BIN DIMENSION(10);

 

The following two declarations are also equivalent:

DECLARE B(1:5,1:5) FLOAT DEC;

DECLARE B DIM(1:5,1:5) FLOAT DEC;

 

DIRECT Attribute

The DIRECT file description attribute indicates that a file will be accessed only in a nonsequential manner, that is, by key or by relative record number.

The format of the DIRECT attribute is:

DIRECT

 

The DIRECT attribute implies the RECORD and KEYED attributes.

Specify the DIRECT attribute on a DECLARE statement for a file constant or on an OPEN statement to access the file. A file declared with the DIRECT attribute must be one of the following:

  • A relative file
  • An indexed sequential file
  • A sequential disk file with fixed-length records
  • A sequential file opened with ENVIRONMENT(BLOCK_ID)

To to access a file both randomly and sequentially, use the SEQUENTIAL attribute instead of DIRECT.

Restriction

The DIRECT attribute conflicts with the SEQUENTIAL, STREAM, and PRINT attributes.

For a description of the attributes that are applied to files, see See Establishing the File's Attributes .

ENTRY Attribute

The ENTRY attribute declares a constant or variable whose value is an entry point and describes the attributes of the parameters (if any) that are declared for the entry point. The format of the ENTRY attribute is:

parameter-descriptor

A set of attributes describing a parameter of the entry. Attributes describing a single parameter must be separated by spaces; sets of attributes (each set describing a different parameter) must be separated by commas. Parameter descriptors are not allowed if the ENTRY attribute is within a RETURNS descriptor.

The following rules apply to the specification of a parameter descriptor for an array or structure:

  • If the parameter is a structure, the level number must precede the attributes for each member.
  • You must specify extents for a parameter using only integer constants, restricted integer expressions, or asterisks (*).
  • You cannot specify storage-class attributes.
OPTIONS (VARIABLE) (dec and ansi dialects only)

Indicates that you can invoke the specified external procedure with a variable number of arguments. At least one parameter descriptor must be specified following the ENTRY keyword if OPTIONS(VARIABLE) is specified.

OPTIONS(VARIABLE) conflicts with OPTIONS(C).

This option is provided for use in calling non-PL/I procedures. For complete details on using OPTIONS (VARIABLE), see the Kednos PL/I for UNIX User's Manual.

OPTIONS (C)

Indicates that the called routine is written in C and should be called using the C language calling and return conventions. OPTIONS(C) conflicts with OPTIONS(VARIABLE).

RETURNS (returns-descriptor)

For an entry that is invoked as a function reference, an option giving the data type attributes of the function value returned. For entry points that are invoked by function references, the RETURNS attribute is required; for procedures that are invoked by CALL statements, the RETURNS attribute is invalid.

The ENTRY attribute without the VARIABLE attribute implies the EXTERNAL attribute (and implies that the declared item is a constant), unless the ENTRY attribute is used to declare a parameter.

You must declare all external entry constants with the ENTRY attribute.

Restrictions

You cannot declare internal entry constants with the ENTRY attribute in the procedure to which they are internal. Internal entry constants are declared implicitly by the labels on the PROCEDURE or ENTRY statements of an internal procedure.

The ENTRY attribute conflicts with all other data-type attributes.

Example

DECLARE COPYSTRING ENTRY (CHARACTER (40) VARYING,

FIXED BINARY(7))

RETURNS (CHARACTER(*));

 

This declaration describes the external entry COPYSTRING. This entry has two parameters: a varying-length character string with a maximum length of 40 and a fixed-point binary value. The RETURNS attribute indicates that COPYSTRING is invoked as a function and that it returns a character string of any length.

ENVIRONMENT Attribute

The ENVIRONMENT file description attribute is used in DECLARE, OPEN, and CLOSE statements to specify options that define file characteristics specific to the Digital UNIX file system and options that request special processing not available in the standard PL/I language. The format of the ENVIRONMENT attribute is:

option, ...

One or more keyword options separated by commas.

Summary of Options

The following items with asterisks (*) are options you can specify in a CLOSE statement.

APPEND

BACKUP_DATE(variable-reference)

BATCH*

BLOCK_BOUNDARY_FORMAT

BLOCK_IO

BLOCK_SIZE(expression)

BUCKET_SIZE(expression)

CARRIAGE_RETURN_FORMAT

CONTIGUOUS

CONTIGUOUS_BEST_TRY

CREATION_DATE(variable-reference)

CURRENT_POSITION

DEFAULT_FILE_NAME(character-expression)

DEFERRED_WRITE

DELETE*

EXPIRATION_DATE(variable-reference)

EXTENSION_SIZE(expression)

FILE_ID(variable-reference)

FILE_ID_TO(variable-reference)

FILE_SIZE(expression)

FIXED_CONTROL_SIZE(expression)

FIXED_CONTROL_SIZE_TO(variable-reference)

FIXED_LENGTH_RECORDS

F, FB, FS, or FBS (IBM Dialect Only)

GROUP_PROTECTION(character-expression)

IGNORE_LINE_MARKS

INDEX_NUMBER

INITIAL_FILL

MAXIMUM_RECORD_NUMBER(expression)

MAXIMUM_RECORD_SIZE(expression)

MULTIBLOCK_COUNT(expression)

MULTIBUFFER_COUNT(expression)

NO_SHARE

OWNER_GROUP(expression)

OWNER_ID(expression)

OWNER_MEMBER(expression)

OWNER_PROTECTION(character-expression)

PRINTER_FORMAT

READ_AHEAD

READ_CHECK

RECORD_ID_ACCESS

RETRIEVAL_POINTERS(expression)

REVISION_DATE(variable-reference)*

REWIND_ON_CLOSE*

REWIND_ON_OPEN

SCALARVARYING

SHARED_READ

SHARED_WRITE

SPOOL*

SUPERSEDE

SYSTEM_PROTECTION(character-expression)

TEMPORARY

TRUNCATE

USER_OPEN(entry-name)

V, VB, VS, or VBS (IBM Dialect Only)

WORLD_PROTECTION(character-expression)

WRITE_BEHIND

WRITE_CHECK

The previous list of options to the ENVIRONMENT attribute are described in detail in the Kednos PL/I for UNIX User's Manual.

You can specify all ENVIRONMENT options in OPEN statements. You can also specify all ENVIRONMENT options except those that require variable references in DECLARE statements. Certain disposition options (noted in the list) can be specified in CLOSE statements.

Note that IBM's implementation of PL/I lets you specify the ENVIRONMENT option only in a DECLARE statement. Keep this in mind when using ENVIRONMENT options if you require compatibility with IBM's implementation of PL/I.

Some ENVIRONMENT options require you to specify a value. In a DECLARE statement, you must use a literal constant to supply the value required. In OPEN and CLOSE statements, however, you can use expressions (including but not limited to literal constants) to supply the values.

Any option that does not require a value can optionally be specified with a Boolean expression that indicates whether the option is to be enabled (if true) or disabled (if false). For example:

DECLARE IFDELETE BIT(1);

OPEN FILE (XYZ) ENVIRONMENT(DELETE(IFDELETE));

 

This DELETE option specifies a Boolean variable whose value can be true or false at run time. Boolean values must be specified as constants in DECLARE statements. You can specify Boolean values as expressions (including constants) in OPEN statements and CLOSE statements.

For a description of the attributes that are applied to files, see See Establishing the File's Attributes .

EXTERNAL Attribute

The EXTERNAL attribute declares an external name, that is, a name whose value is known to blocks outside the block where it is declared. The format of the EXTERNAL attribute is:

The EXTERNAL attribute is implied by the FILE, GLOBALDEF, and GLOBALREF attributes. EXTERNAL is also implied by declarations of entry constants (declarations that contain the ENTRY attribute but not the VARIABLE attribute). For variables, the EXTERNAL attribute implies the STATIC attribute.

(`name')

The exact, case-sensitive, name of the external variable.

Unless you specify -m upper or --case=upper as an option to the pl1 command, do not declare a procedure or any other external symbol that will map to " main" (in lowercase). This will conflict with the library function "main" supplied in the Kednos PL/I for UNIX run-time library.

Restrictions

The EXTERNAL attribute directly conflicts with the AUTOMATIC, BASED, and DEFINED attributes.

The EXTERNAL attribute cannot be applied to minor structures, members of structures, parameters, or descriptions in an ENTRY or RETURNS attribute.

The EXTERNAL attribute is invalid for variables that are the parameters of a procedure.

If a variable is declared as EXTERNAL STATIC INITIAL, all blocks that declare the variable must initialize the variable with the same value.

FILE Attribute

The FILE attribute declares a file constant or file variable. The format of the FILE attribute is:

FILE

 

The FILE attribute is implied by any of the following file description attributes:

DIRECT

OUTPUT

SEQUENTIAL

ENVIRONMENT

PRINT

STREAM

INPUT

RECORD

UPDATE

KEYED

 

 

See See . Summary of File Description Attributes for definitions of these file description attributes.

If the VARIABLE attribute is not specified, the FILE attribute declares a file constant. If the INTERNAL attribute is not specified, the file has the EXTERNAL attribute by default. All external declarations of a file constant are associated with the same file.

For a description of the attributes that are applied to files, see See Establishing the File's Attributes .

Restrictions

The FILE attribute conflicts with all other data-type attributes. If the FILE attribute is used to declare a variable or parameter, no file description attributes may be specified. If the VARIABLE attribute is not specified, no storage-class attributes are allowed.

FIXED Attribute

The FIXED attribute indicates that the variable so declared is arithmetic with a fixed number of fractional digits. Such variables are called fixed-point (as opposed to floating- point) variables because the decimal point and binary point are fixed relative to the representation of the value. The format of the FIXED attribute is:

FIXED [(precision[,scale-factor])]

 
precision

The precision is the number of decimal or binary digits used to represent values of the variable.

scale-factor

Scale factor indicates how much of the precision is to be used for fractional digits.

When you specify the FIXED attribute in a DECLARE statement, you can specify either the BINARY or the DECIMAL attribute to indicate a binary or decimal fixed-point variable. For example, the attributes FIXED BINARY(31) define a variable that takes fixed-point binary integer values of up to a maximum of 31 bits. The attributes FIXED DECIMAL(10,2) define a variable that takes fixed-point decimal values of up to 10 decimal digits, 2 of which are fractional. PL/I supplies default attributes for attributes that you do not specify (as shown in the following table).

You use fixed-point binary data to represent integers. The precision of a fixed-point binary variable must be in the range 1 through 31.

You can also use fixed-point decimal data, which can represent larger absolute values. You use fixed-point data whenever arithmetic values must be precise to a specified number of fractional digits. For a fixed-point decimal value, the precision must be in the range 1 through 31 (decimal digits). The scale factor, if specified, must be greater than or equal to zero and less than or equal to the specified precision. If the scale factor is omitted, zero is used (that is, an integer variable is declared).

The default values given for unspecified related attributes are listed in See . Default Values for Unspecified FIXED Attributes .

. Default Values for Unspecified FIXED Attributes

Attributes Specified

dec Dialect

ibm Dialect

ansi Dialect

FIXED

BINARY (31)

DECIMAL (5,0)

BINARY(15)

FIXED BINARY

(31)

(15)

(15)

FIXED DECIMAL

(10,0)

(5,0)

(10,0)

Restriction

The FIXED attribute directly conflicts with all data-type attributes except BINARY and DECIMAL.

FLOAT Attribute

The FLOAT attribute indicates that a variable is a floating-point arithmetic item. The format of the FLOAT attribute is:

FLOAT [(precision)]

 

precision

The range for a floating-point binary variable is 1 through 53. The range for a floating-point decimal variable is 1 through 15.

When you specify the FLOAT attribute in a DECLARE statement, you can specify either the BINARY or the DECIMAL attribute. The default values given for unspecified related attributes are listed in See . Default Values for Unspecified FLOAT Attributes .

 
. Default Values for Unspecified FLOAT Attributes

Attributes Specified

dec Dialect

ibm Dialect

ansi Dialect

FLOAT

BINARY (24)

DECIMAL(6)

BINARY(24)

FLOAT BINARY

(24)

(21)

(24)

FLOAT DECIMAL

(7)

(6)

(7)

Restriction

The FLOAT attribute directly conflicts with all data-type attributes except BINARY and DECIMAL.

GLOBALDEF Attribute

The GLOBALDEF attribute declares an external variable or an external file constant. It can optionally control the program section in which the data is allocated. The format of the GLOBALDEF attribute is:

GLOBALDEF [ (psect-name) ]

 
psect-name

The name of a program section. A program section name can have up to 31 characters, which can consist of the alphanumeric characters, dollar signs ($), pound signs (#), at signs (@), and underscores (_). The first character cannot be numeric (0 through 9).

If you do not specify a program section name, PL/I places the definition for the name in the default program section associated with the variable.

The GLOBALDEF attribute implies the EXTERNAL attribute. The GLOBALDEF attribute also implies STATIC except when used for file constants.

Restrictions

The GLOBALDEF attribute conflicts with the GLOBALREF and INTERNAL attributes. GLOBALDEF cannot be used with ENTRY constants.

Only one procedure in a program can declare a particular external variable with the GLOBALDEF attribute.

For complete details on using the GLOBALDEF attribute to declare global external symbols, see See External Variables .

GLOBALREF Attribute

The GLOBALREF attribute indicates that the declared name is a global symbol defined in an external procedure. The format of the GLOBALREF attribute is:

GLOBALREF

 

The GLOBALREF attribute implies the EXTERNAL attribute. The corresponding name must be declared in another procedure with the GLOBALDEF attribute or, if the external procedure is written in another programming language, with its equivalent in that language.

Restriction

The GLOBALREF attribute conflicts with the INITIAL, GLOBALDEF, and INTERNAL attributes. If GLOBALREF is specified with the FILE attribute, you cannot specify any other file description attributes.

See See External Variables for information about using this attribute.

INITIAL Attribute

The INITIAL attribute provides an initial value for a declared variable. The format of the INITIAL attribute is:

initial-element

A construct that supplies a value for the initialized variable. The value must be valid for assignment to the initialized variable. If the initialized variable is an array, a list of initial elements separated by commas is used to initialize individual elements. The number of initial elements must be 1 for a scalar variable and must not exceed the number of elements of an array variable. Each initial element must have one of the following forms:

  • string-constant
  • (replication-factor) string-constant
  • (iteration-factor) (string-constant)
  • (iteration-factor) (replication-factor) (string-constant)
  • [(iteration-factor)] arithmetic-constant
  • [(iteration-factor)] scalar-reference
  • [(iteration-factor)] (scalar-expression)
  • [(iteration-factor)] *

The iteration factors are nonnegative integer-valued expressions that specify the number of successive array elements to be initialized with the following value.

An asterisk (*) following the iteration factor specifies that the corresponding array elements are to be skipped during the initialization.

You can use a replication factor in combination with an iteration factor in initializing a string constant. For example, the following two statements are equivalent:

INITIAL ((10)('ABCABC'))

INITIAL ((10)((2)'ABC'))

 

The first statement uses an iteration factor exclusively; the second statement combines an iteration factor of 10 with a replication factor of 2.

A string constant must be parenthesized if it is used with an iteration factor, because this set of parentheses prevents the iteration factor from being interpreted as a string replication factor.

The following initial value is interpreted as a string replication factor, not an iteration factor, and cannot be used to initialize a whole array:

INITIAL ((10)'ABC')

 

(*) valid-expression

A construct that initializes all elements of an array to the same value by means of the asterisk iteration factor. The expression must evaluate to a value that is valid for assignment to the initialized array. If the expression is a string constant, it must be parenthesized so that the asterisk iteration factor is not interpreted as a string replication factor. The possible expressions are:

  • (string-constant)
  • ((replication-factor) string-constant)
  • arithmetic-constant
  • scalar-reference
  • (scalar-expression)
  • (aggregate-expression)
  • *

An asterisk following the asterisk iteration factor results in no initializations being performed.

Examples

The following are examples of declarations that include the INITIAL attribute:

DECLARE RATE FIXED DECIMAL (2,2) STATIC INITIAL (.04);

 

DECLARE SWITCH BINARY STATIC INITIAL ('1'B);

 

DECLARE BELL_CHAR BINARY STATIC INITIAL ('07'B4);

 

DECLARE OUTPUT_MESSAGE CHARACTER(20) STATIC

INITIAL ('GOOD MORNING');

 

DECLARE (A INITIAL ('A'), B INITIAL ('B'),

C INITIAL ('C')) STATIC CHARACTER;

DECLARE QUEUE_END POINTER STATIC INITIAL(NULL());

 

DECLARE X(10,5) FIXED BIN(31) INITIAL ((*) -2);

/* Initializes all 50 elements to -2 */

 

DECLARE 1 A(10),

2 B(10),

3 C(10) FIXED BIN(31) INITIAL ((*) 4);

/* Initializes all 1000 elements to 4 */

 

DECLARE A(10) FIXED INIT ((5) 1,(5) 2);

/* Initializes the first 5 elements to 1

and the second 5 elements to 2 */

 

The following declaration is not valid, because the asterisk iteration factor cannot be used to initialize part of an array; it can only be used to initialize all elements of the array to the same value:

DECLARE A(10) FIXED INIT ((5) 1,(*)2);

/* Invalid use of asterisk iteration

factor */

 

Restrictions

You can specify the INITIAL attribute for an automatic structure variable only if you initialize the structure through an aggregate valued function. For example:

DECLARE 1 TEST_STRUC,

2 FIRST_MEMBER CHARACTER (8),

2 SEC_MEMBER FIXED BINARY(15);

 

DECLARE INIT_FUNCTION ENTRY(FIXED,FIXED)

RETURNS(1 LIKE TEST_STRUC);

 

DECLARE INPUT_STRUC LIKE TEST_STRUC

INITIAL (INIT_FUNCTION(X,Y));

 

In this example, INIT_FUNCTION is an external function that returns a structure matching TEST_STRUC.

To initialize a structure without using an aggregate valued function, you must individually initialize the members of the structure.

You cannot specify the INITIAL attribute for a variable or member of a structure that has any of the following attributes:

DEFINED

ENTRY

FILE

LABEL

PARAMETER

UNION

If the initialized variable is STATIC, only constants, restricted expressions, and references to the NULL or EMPTY built-in functions are allowed. You can use these initial values with a constant iteration factor.

Variables and functions (except for parameters) occurring in an initial element (for automatic variables) must not be declared in the same block as the variable being initialized.

INPUT Attribute

The INPUT file description attribute indicates that the associated file is to be an input file. The format of the INPUT attribute is:

INPUT

 

Specify the INPUT attribute on a DECLARE statement for a file constant or on an OPEN statement to access the file for reading.

You can specify the INPUT attribute with either the STREAM or the RECORD attribute. For a stream file, INPUT indicates that the file will be accessed with GET statements. For a record file, INPUT indicates that the file will be accessed only with READ statements.

For example:

DECLARE INFILE RECORD INPUT;

 

OPEN FILE(INFILE);

READ FILE(INFILE) INTO(RECORD_BUFFER);

 

These statements declare, open, and access the first record in the input file INFILE.

For a description of the attributes that can be applied to files, see See . Summary of File Description Attributes .

The INPUT attribute can be supplied by default for a file, depending on the context of its opening. See See Establishing the File's Attributes for more information.

Restriction

The INPUT attribute conflicts with the OUTPUT, UPDATE, and PRINT attributes and with any data-type attribute other than FILE.

INTERNAL Attribute

The INTERNAL attribute limits the scope of an identifier to the block in which the identifier is declared and its dynamic descendents.

The format of the INTERNAL attribute is:

You only need to use the INTERNAL attribute to explicitly declare the scope of a file constant as internal. File constants, by default, have the EXTERNAL attribute.

Restriction

The INTERNAL attribute directly conflicts with the EXTERNAL, GLOBALDEF, and GLOBALREF attributes.

KEYED Attribute

The KEYED file description attribute indicates that you can randomly access records in the specified file. The KEYED attribute implies the RECORD attribute.

Specify KEYED in a DECLARE statement to identify a file or in an OPEN statement to open the file. For a description of the attributes that can be applied to files, see See . Summary of File Description Attributes .

Restriction

The KEYED attribute conflicts with the STREAM attribute and with any data-type attributes other than FILE.

LABEL Attribute

The LABEL attribute declares a label variable; it indicates that values given to the variable will be statement labels. The format of the LABEL attribute is:

LABEL

 
Restriction

You cannot specify the LABEL attribute with any other data-type attribute, the INITIAL attribute, or any file description attributes.

LIKE Attribute

The LIKE attribute copies the member declarations contained within a major or minor structure declaration into the structure variable to which it is applied. The format of the LIKE attribute is:

level-number identifier [attributes] LIKE reference

 
level-number

The level number to which the declarations in the reference are copied.

identifier

The variable to which the declarations in the reference are to be copied. The identifier must be preceded by a level number.

attributes

Storage class or dimensions appropriate for the level number. You can specify a storage class and dimensions with a major structure, or you can specify dimensions with a minor structure.

reference

The name of a major or minor structure that is known in the current block.

The LIKE attribute causes the structuring and member declarations of its reference to be copied, but not the name, storage class, or dimensioning (if any) of the reference. The exception to this rule is that the UNION attribute is propagated in a LIKE declaration. While logical structuring is copied, the level numbers themselves are not copied.

You can use the LIKE attribute on a structure already containing the LIKE attribute.

MEMBER Attribute

You can optionally specify the MEMBER attribute in the declaration of a structure member (minor structure). A structure member has the MEMBER attribute implicitly. The format of the MEMBER attribute is:

MEMBER

 
Restriction

The MEMBER attribute cannot be used with a major structure (that is, a structure variable with level 1).

NONVARYING Attribute

The NONVARYING attribute keyword explicitly states that a bit-string or character-string variable has a fixed length, not a varying length. Because NONVARYING is the default for bit and character strings, it need not be specified. The format of the NONVARYING attribute is:

OFFSET Attribute

The OFFSET attribute declares a variable that will be used to reference a based variable within an area. The format of the OFFSET attribute is:

OFFSET [(area-reference)]

 
area-reference

The name of a variable with the AREA attribute. The value of the offset variable will be interpreted as an offset within the specified area.

Examples

DECLARE MAP_SPACE AREA (40960),

MAP_START OFFSET (MAP_SPACE),

MAP_LIST(100) CHARACTER(80) BASED (MAP_START);

 

These declarations define an area named MAP_SPACE, an offset variable that will contain offset values within that area, and a based variable whose storage is located by the value of the offset variable MAP_START.

Restriction

The area reference must be omitted if the OFFSET attribute is specified within a returns descriptor, parameter declaration, or a parameter descriptor. The OFFSET attribute conflicts with all other data-type attributes.

OPTIONAL Attribute (Dec and Ansi Dialects Only)

The OPTIONAL attribute indicates that an actual parameter need not be specified in a call. If the actual parameter is not specified, you must specify a placeholder for it. PL/I passes a longword zero as the actual parameter in that position. The format of the OPTIONAL attribute is:

OPTIONAL

 
Example

DCL E ENTRY (FIXED,FIXED OPTIONAL);

CALL E(1,2);

CALL E(1,);

 

OUTPUT Attribute

The OUTPUT file description attribute indicates that data is to be written to, and not read from, the associated external device or file. The format of the OUTPUT attribute is:

OUTPUT

 

Specify the OUTPUT attribute on a DECLARE statement for a file constant or on an OPEN statement to access the file for writing. You can specify the OUTPUT attribute with either the STREAM or the RECORD attribute. For a stream file, OUTPUT indicates that the file will be accessed with PUT statements. For a record file, OUTPUT indicates that the file will be accessed with only WRITE statements.

Examples

DECLARE OUTFILE RECORD OUTPUT;

 

OPEN FILE(OUTFILE);

WRITE FILE(OUTFILE) FROM(RECORD_BUFFER);

 

These statements declare, open, and write a record to the output file OUTFILE.

For a description of the attributes that you can apply to files and the effects of combinations of these attributes, see See , See Input and Output .

Restriction

The OUTPUT attribute conflicts with the INPUT and UPDATE attributes and with any data-type attributes other than FILE. The OUTPUT attribute also conflicts with ENVIRONMENT(INDEXED).

PARAMETER Attribute

A variable occurring in the parameter list of a PROCEDURE or ENTRY statement has the PARAMETER attribute implicitly. You can optionally use the PARAMETER keyword in the declaration of a variable name to state explicitly that it is a parameter. The format of the PARAMETER attribute is:

Example

The following example uses the PARAMETER keyword:

TEST: PROC( A, B );

DCL A CHAR(*) PARAMETER;

DCL B FIXED BIN PARM;

 

Refer to See Parameters and Arguments for a more information.

PICTURE Attribute

The PICTURE attribute is used to declare a pictured variable. Pictured variables have fixed-point decimal attributes, but values of the variable are stored internally as character strings. The character string contains decimal digits representing the numeric value of the variable, plus special editing symbols described in the picture. The format of the PICTURE attribute is:

picture

A string of picture characters that define the representation of the variable.

See See Picture Characters for detailed information about picture characters, syntax, and examples.

Restriction

The PICTURE attribute conflicts with all other data-type attributes.

POINTER Attribute

The POINTER attribute indicates that the associated variable will be used to identify locations of data. The format of the POINTER attribute is:

Restriction

The POINTER attribute conflicts with all other data-type attributes.

POSITION Attribute

The POSITION attribute specifies the character or bit position in a defined variable's base at which the defined variable begins. The format of the POSITION attribute is:

expression

An integer expression that specifies a position in the base. A value of 1 indicates the first character or bit.

Restriction

You can specify the POSITION attribute only in connection with DEFINED and only when the defined variable satisfies the rules for string overlay defining (see See Rules for Overlay Defining ).

PRECISION Attribute

The PRECISION attribute specifies the maximum number of decimal or binary digits in a number. You can specify the precision of an arithmetic variable in any of the following formats, depending on the numeric base of the data item. The formats of the PRECISION attribute are:

BINARY [ FIXED ] [ [PRECISION] (precision[,scale-factor]) ]

[BINARY] FLOAT [ [PRECISION] (precision) ]

DECIMAL [ FIXED ] [ [PRECISION] (precision[,scale-factor]) ]

DECIMAL FLOAT [ [PRECISION] (precision) ]

 
precision

You can abbreviate the keyword PRECISION to PREC, or you can omit it entirely. If you use the keyword, the precision (and scale factor, if used) must immediately follow the keyword, which can be placed before or after any other attributes in the declaration. If you omit the keyword, the precision (and scale factor, if used) must follow the other attributes.

For example, the following declarations are equivalent:

DCL A FIXED BIN(31); DCL A FIXED BIN PRECISION(31);

 

DCL B FLOAT BIN(53); DCL B PREC(53) FLOAT BIN;

 

DCL C FIXED DEC(5,2); DCL C FIXED DEC PREC(5,2);

 

The precision of a floating-point data item is the number of decimal or binary digits in the mantissa of the floating-point representation.

scale-factor

The scale factor is the number of digits to the right of the decimal or binary point in fixed-point decimal or binary data. If no scale factor is specified with fixed-point data, the default is zero.

The ranges of values you can specify for the precision of each arithmetic data-type, and the defaults applied if you do not specify a precision, are summarized See Precision and Scale of Arithmetic Data Types .

PRINT Attribute

The PRINT attribute is used to declare a print file. The file SYSPRINT, used as the default output by PUT statements, is a print file. The format of the PRINT attribute is:

PRINT

 

Print files are stream output files with special formatting characteristics. The PRINT attribute implies the OUTPUT and STREAM attributes.

For a description of the attributes that are applied to files, see See Establishing the File's Attributes .

Restriction

The PRINT attribute conflicts with the INPUT, RECORD, UPDATE, KEYED, SEQUENTIAL, and DIRECT attributes.

READONLY Attribute

You can apply the READONLY attribute to any static computational variable whose value does not change during program execution. The format for the READONLY attribute is:

READONLY

 

When you specify READONLY in conjunction with the declaration of a static variable, the PL/I compiler allocates storage for the variable based on the fact that its value does not change. A static variable with the READONLY attribute is given an initial value with the INITIAL attribute.

Restrictions

You can apply the READONLY attribute only to static computational variables. You must declare the variables with the EXTERNAL, STATIC, GLOBALREF, or GLOBALDEF attribute.

The value of a variable with the READONLY attribute cannot be modified. An attempt to modify a variable declared with the READONLY attribute will result in a run-time error.

The READONLY attribute conflicts with the ENTRY, FILE, LABEL, POINTER, and VALUE attributes.

RECORD Attribute

The RECORD file description attribute indicates that data in an input or output file consists of separate records and that the file will be processed by record I/O statements. The format of the RECORD attribute is:

RECORD

 

The RECORD attribute is implied by the DIRECT, SEQUENTIAL, KEYED, and UPDATE attributes.

You can specify this attribute in a DECLARE statement for a file constant or in the OPEN statement that accesses the file.

For a description of the attributes that are applied to files, see See Establishing the File's Attributes .

Restriction

The RECORD attribute conflicts with the STREAM and PRINT attributes.

REFER Attribute

The REFER attribute defines dynamically self-defining structures. The format of the REFER attribute is:

refer-element REFER (refer-object-reference)

 

See See Using the REFER Option for more information.

REFERENCE Attribute

The REFERENCE attribute is accepted by Kednos PL/I for UNIX, for compatibility with other implementations of PL/I, but is ignored. By default, asterisk (*) extent parameters are passed by descriptor, in compliance with the PL/I language standard, and cannot be passed by reference. All other parameters are passed by reference in Kednos PL/I for UNIX unless the VALUE attribute is specified. The format of the REFERENCE attribute is:

Restriction

Note that you can only use the REFERENCE attribute in parameter descriptors.

RETURNS Attribute

The RETURNS attribute must be specified on the PROCEDURE or ENTRY statement if the corresponding entry point is invoked as a function. The RETURNS attribute is specified with the ENTRY attribute to give the data-type of a value returned by an external function. The format of the RETURNS option and attribute is:

RETURNS (returns-descriptor ... )

 
returns-descriptor

One or more attributes that describe the value returned by the function to its point of invocation. The returned value becomes the value of the function reference in the invoking procedure. The attributes must be separated by spaces, except for attributes (the precision, for example) that are enclosed in parentheses.

Restrictions

The data types you can specify for a returns descriptor are restricted to scalar elements of either computational or noncomputational types. Areas are not allowed.

You can specify the extent of a character-string value as an asterisk (*) to indicate that the string can have any length. Otherwise, extents must be specified with restricted expressions.

You cannot use the RETURNS option or the RETURNS attribute for procedures that are invoked by the CALL statement.

The attributes specified in a returns descriptor in a RETURNS attribute must correspond to those specified in the RETURNS option of the PROCEDURE statement or ENTRY statements in the corresponding procedure. For example:

CALLER: PROCEDURE OPTIONS (MAIN);

DECLARE COMPUTER ENTRY (FIXED BINARY)

RETURNS (FIXED BINARY); /* RETURNS attribute */

DECLARE TOTAL FIXED BINARY;

TOTAL = COMPUTER (A+B);

 

The first DECLARE statement declares an entry constant named COMPUTER. COMPUTER will be used in a function reference to invoke an external procedure, and the function reference must supply a fixed-point binary argument. The invoked function returns a fixed-point binary value, which then becomes the value of the function reference.

The function COMPUTER contains the following:

COMPUTER: PROCEDURE (X) RETURNS (FIXED BINARY); /* RETURNS option */

DECLARE (X, VALUE) FIXED BINARY;

RETURN (VALUE); /* RETURN statement */

 

In the PROCEDURE statement, COMPUTER is declared as an external entry constant, and the RETURNS option specifies that the procedure return a fixed-point binary value to the point of invocation. The RETURN statement specifies that the value of the variable VALUE be returned by COMPUTER. If the data-type of the returned value does not match the data-type specified in the RETURNS option, PL/I converts the value to the correct data-type according to the rules given under See Data Type Conversion of Operands and Expressions .

SEQUENTIAL Attribute

The SEQUENTIAL file description attribute indicates that records in the file will be accessed in a sequential manner. The format of the SEQUENTIAL attribute is:

If you specify SEQUENTIAL, the RECORD attribute is implied.

Specify the SEQUENTIAL attribute in a DECLARE statement for a file constant or in the OPEN statement that accesses the file.

You can apply the SEQUENTIAL attribute to files with sequential, relative, or indexed sequential file organizations.

For a description of the attributes that are applied to files, see See Establishing the File's Attributes .

Restriction

The SEQUENTIAL attribute conflicts with the DIRECT, STREAM, and PRINT attributes.

STATIC Attribute

The STATIC attribute specifies the way that PL/I is to allocate storage for a variable. The format of the STATIC attribute is:

STATIC

 

The STATIC attribute is implied by the EXTERNAL attribute. For more information on STATIC and on other storage-class attributes, see See , See Storage Classes .

Restriction

The STATIC attribute directly conflicts with the BASED, CONTROLLED, DEFINED, and parameter attributes. The STATIC attribute cannot be applied to members of structures, parameters, or descriptions in an ENTRY or RETURNS attribute.

STREAM Attribute

The STREAM file description attribute indicates that the file consists of ASCII characters and that it will be processed using GET and PUT statements. The format of the STREAM attribute is:

STREAM

 

The STREAM attribute is implied by the PRINT attribute. It is also supplied by default for a file that is implicitly opened with a GET or PUT statement.

Specify the STREAM attribute in a DECLARE statement for a file identifier or in the OPEN statement that opens the file.

For a description of the attributes that are applied to files, see See Establishing the File's Attributes .

Restriction

The STREAM attribute directly conflicts with the RECORD, KEYED, DIRECT, SEQUENTIAL, and UPDATE attributes.

STRUCTURE Attribute

You can optionally specify the STRUCTURE attribute in the declaration of a structure. The format of the STRUCTURE attribute is:

STRUCTURE

 

TYPE Attribute

The TYPE attribute copies the declarations contained within the type declaration to the variable to which it is applied. The format of the TYPE attribute is:

level-number identifier [attributes] TYPE reference

or

level-number identifier [attributes] TYPE (reference)

 

 
level-number

The level number to which the declarations in the reference are copied.

identifier

The variable to which the declarations in the reference are to be copied. The identifier must be preceded by a level number.

attributes

Storage class or dimensions appropriate for the level number. You can specify a storage class and dimensions with a major structure, or you can specify dimensions with a minor structure.

reference

The name of a type declaration that is known in the current block. You can optionally enclose this name in parentheses.

The TYPE attribute causes the declaration of its reference to be copied, but not the name, storage class, or dimensioning (if any) of the reference. The exception to this rule is that the UNION attribute is propagated in a TYPE declaration. While logical structuring is copied, the level numbers themselves are not copied.

You can use the TYPE attribute on a declaration already containing the TYPE attribute.

Restrictions

A TYPE definition cannot be:

  • A pointer-qualified variable
  • A subscripted variable
  • An entry variable
  • A variable declaration that leads to direct or indirect circular declarations

The following examples show circular declarations. Do not use these types of declarations.

DECLARE 1 S11,

2 F1 CHARACTER(10),

2 F2 TYPE(S11); /* Direct circular */

 

DECLARE V1 TYPE(V2); /* Indirect circular */

DECLARE V2 TYPE(V3);

DECLARE V3 TYPE(V1);

 

DECLARE A1(10) TYPE(A2); /* Indirect circular */

DECLARE A2(10) TYPE(A3);

DECLARE A3(10) TYPE(A1);

 

DECLARE 1 S31,

2 F1 CHARACTER(10),

2 F2 TYPE(S32); /* Indirect circular */

DECLARE 1 S32,

2 F1 CHARACTER(10),

2 F2 TYPE(S33);

DECLARE 1 S33,

2 F1 CHARACTER(10),

2 F2 TYPE(S31);

 

  • A structure variable with the BASED attribute and declarations with the REFER option if the TYPE variable does not have a BASED attribute.

For example:

DECLARE N FIXED BINARY;

DECLARE 1 VARIABLE_X BASED,

2 SIZE FIXED BINARY(15),

2 ITEMS (N REFER (VARIABLE_X.SIZE)) CHARACTER(80);

 

DECLARE VARIABLE_Y TYPE (VARIABLE_X); /* Error */

/* VARIABLE_Y not BASED */

 

TRUNCATE Attribute

The TRUNCATE attribute is used in the declaration of a formal parameter to indicate that the actual parameter list can be truncated at the point where this argument should occur. The format of the TRUNCATE attribute is:

TRUNCATE

 

When the actual call is made, the actual parameter list can stop at the parameter before the one declared with the TRUNCATE attribute. It is possible to pass an actual parameter in a position with the TRUNCATE attribute. Note that in this case, all remaining parameters must also be specified unless they have the TRUNCATE attribute.

Example

DCL E ENTRY (FIXED,FIXED TRUNCATE,FIXED);

CALL E(1);

CALL E(1,2,3);

 

The following call, however, will be invalid:

CALL E(1,2);

 

This call is invalid because the second parameter has the TRUNCATE attribute, so the third parameter must be specified.

UNALIGNED Attribute

The UNALIGNED attribute is used in conjunction with the BIT attribute to specify that a bit-string variable should not be aligned on a byte boundary. Because UNALIGNED is the default for bit strings, it need not be specified. The format of the UNALIGNED attribute is:

You can use the UNALIGNED attribute in the declaration of character strings. All character strings are aligned on byte boundaries; therefore, the UNALIGNED attribute has no effect on the actual storage of a character string.

Restriction

The UNALIGNED attribute conflicts with all data-type attributes other than BIT and CHARACTER.

UNBUFFERED Attribute (IBM Dialect Only)

See the description under the BUFFERED attribute.

UNION Attribute

The UNION attribute, which can be used only in conjunction with a level number in a structure declaration, signifies that all immediate members of the major or minor structure so designated occupy the same storage. Immediate members are those members having a level number 1 higher than the major or minor structure with the UNION attribute. For example, if the UNION attribute were associated with level n, then all members or minor structures at level n+1 up to the next member at level n would be immediate members and would occupy the same storage. The format for the UNION attribute is:

level-number

The level number of the variable with which the declarations in the reference share storage.

identifier

Names the variable with which the declarations in the reference share storage. A variable declared with the UNION attribute must be a major or minor structure.

*

You can specify an asterisk (*) in place of the identifier name.

storage-class

The storage class specified for the structure. You can specify the storage class only on level 1.

Example

The following example uses the UNION attribute to acquire a date from the DATE built-in function and display it as three separate variables containing the year, month, and day. The major structure uses an asterisk (*) in place of the identifier name.

MAIN PROCEDURE OPTIONS(MAIN);

DECLARE 1 * UNION STATIC,

2 MC_DATE CHARACTER(6),

2 S_PARTS,

3 YEAR CHARACTER(2),

3 MONTH CHARACTER(2),

3 DAY CHARACTER(2);

 

MC_DATE = DATE();

PUT SKIP LIST (YEAR, MONTH, DAY);

END MAIN;

 

UPDATE Attribute

The UPDATE attribute is a file description attribute indicating that the associated file is to be used for both input and output. You can apply the UPDATE attribute to relative files, indexed files, and sequential disk files with fixed-length records. The format of the UPDATE attribute is:

UPDATE

 

Specify the UPDATE attribute on a DECLARE statement for a file constant or on an OPEN statement to access the file for update. The UPDATE attribute implies the RECORD attribute.

For a description of the attributes that are applied to files, see See Establishing the File's Attributes .

Restriction

The UPDATE attribute directly conflicts with the INPUT, OUTPUT, STREAM, and PRINT attributes and with any data-type attribute other than FILE.

VALUE Attribute

The VALUE attribute is provided for passing parameters by value rather than by reference, or it can be used to specify a global constant value. The format of the VALUE attribute is:

The VALUE attribute serves two purposes:

In a parameter descriptor in an ENTRY declaration, it specifies that the corresponding argument is to be passed using the hardware-specific convention for passing arguments by value. For this usage, VALUE must be specified in conjunction with one of the following attributes:

ANY

FIXED BINARY(m) where m is less than or equal to 31

FLOAT BINARY(n) where n is less than or equal to 53

BIT(o) ALIGNED where o is less than or equal to 32

ENTRY

OFFSET

POINTER

  • In conjunction with the GLOBALREF or GLOBALDEF attributes, it specifies that a global external variable has a constant value for which no storage is allocated. The compiler can use this value as an immediate value in generating instructions. With the global external variables, the format is:

The VALUE attribute, when specified with the BIT attribute, implies the ALIGNED attribute.

VARIABLE Attribute

The VARIABLE attribute indicates that the associated identifier is a variable. VARIABLE is implied by all computational data-type attributes and by all noncomputational attributes except FILE and ENTRY. The format of the VARIABLE attribute is:

VARIABLE

 

If you specify the FILE or ENTRY attribute in a DECLARE statement without the VARIABLE attribute, the defined object is assumed to be a file or entry constant.

The VARIABLE attribute is implied by the LABEL attribute. You can declare label constants only by using the label identifier in the program; you cannot define a label constant in a DECLARE statement.

Restriction

The VARIABLE attribute is not valid in a returns descriptor or in a parameter descriptor.

VARYING Attribute

The VARYING attribute indicates that a bit-string, character-string, or graphic variable does not have a fixed length, but that its length changes according to its current value. The format of the VARYING attribute is:

You must specify a length attribute in conjunction with VARYING by giving the maximum length allowed for the variable. The current length is stored with the value and can be determined at any time with the LENGTH built-in function. If you need to determine the maximum declared length of a varying- length character string, use the MAXLENGTH built-in function.

The value of an uninitialized VARYING variable is undefined.

Special rules apply to reading and writing record files into and from variables that have the VARYING attribute. See the Kednos PL/I for UNIX User's Manual for more information.

Restriction

The VARYING attribute directly conflicts with any data-type attribute other than CHARACTER.

Examples

DECLARE STRING CHARACTER(80) VARYING;

 

A variable named STRING is declared as a varying-length character string with a maximum length of 80 characters.

S: PROCEDURE OPTIONS(MAIN);

DECLARE STRING CHARACTER(80) VARYING;

STRING = 'PIE';

 

PUT LIST (LENGTH(STRING));

PUT LIST (MAXLENGTH(STRING));

PUT LIST (SIZE(STRING));

END;

 

The value returned by the built-in function LENGTH is 3, the length of the current value of the string. The value returned by the built-in function MAXLENGTH is 80, the maximum declared length. The value returned by the built-in function SIZE is 82, the maximum declared length plus two (for the two bytes that hold the value of the current length).

 

Data Types

All programs process data items. Data items can be constants or variables. A constant data item has a value that does not change during program execution; a variable data item can represent different values.

A data item has an associated type that you can specify as an attribute or collection of attributes in a declaration. Unlike other languages that often have a distinction between data types and data attributes, a PL/I data type is entirely defined by the data attributes given to a data item identifier. The data type that you select determines the operations that you can perform on data items and how they are stored.

The rest of this chapter describes data types in more detail.

Summary of Data Types

PL/I supports the following computational data types:

Fixed point (binary integers and decimal integers and fractions)

Floating point (binary and decimal)

Pictured (fixed point data stored in character form)

PL/I also supports the following noncomputational data types and attributes:

You can place each of these data types in aggregate structures or arrays to form new data types. See See , See Aggregates for more information.

Declarations

To establish an identifier as a name in PL/I, you can declare it either implicitly or explicitly. Implicit declarations occur when you use an identifier as a name without explicitly declaring it. PL/I recognizes the identifier by context, giving it default attributes. Some common examples of implicit declaration are using an identifier as an entry-point name, statement label, or built-in function name, or using the default file constants SYSIN and SYSPRINT.

To explicitly declare an identifier, use a DECLARE statement. For example:

DECLARE AVERAGE FIXED DECIMAL;

DECLARE NAME CHARACTER (20);

 

The keywords DECIMAL, FIXED, and CHARACTER describe characteristics, or attributes, of the variables AVERAGE and NAME.

By explicitly declaring identifiers you can give them the specific attributes you require, instead of the default attributes, which may not be appropriate for your needs.

Default Attributes

It is not always necessary to define all the characteristics, or attributes, of a variable; the PL/I compiler makes assumptions about attributes that are not explicitly defined. For example:

DECLARE NUMBER FIXED;

 

If you are using the Digital variant of Kednos PL/I for UNIX, the default FIXED attribute implies the attributes BINARY(31). Thus, the variable NUMBER has the attributes FIXED BINARY(31). If you are using the IBM variant, the default FIXED attribute implies the attributes BINARY(15), and NUMBER has the attributes FIXED BINARY (15).

See . Implied Attributes for Computational Data shows the default attributes implied by each computational data attribute for the Digital variant (-D dec compiler option) and for the IBM variant (-D ibm compiler option).

. Implied Attributes for Computational Data

Specified

Digital Variant

IBM Variant

implicit declaration 1

FIXED BINARY(31)

If name begins with the letters I through N:

FIXED BINARY(15)

 

Otherwise::

FLOAT DECIMAL(6)

FIXED

BINARY(31)

BINARY(15)

BINARY

FIXED(31)

FIXED(15)

FIXED BINARY

(31)

(15)

FLOAT

BINARY(24)

BINARY(21)

FLOAT BINARY

(24)

(21)

DECIMAL

FIXED(10,0)

FIXED(5,0)

FIXED DECIMAL

(10,0)

(5,0)

FIXED DECIMAL(p)

(p,0)

(p,0)

FLOAT DECIMAL

(7)

(6)

BIT [ALIGNED]

(1)

(1)

CHARACTER [VARYING]

(1)

(1)

Attributes of Constants

Constants have attributes implied by the characters used to specify them. The following list describes the expression of constants and their attributes:

  • A series of characters enclosed in apostrophes is assumed to be a string constant:
  • If the letter B, which can be lowercase, is appended after the closing apostrophe, the constant is a bit-string constant, for example, '00010101'B. If the integer 2, 3, or 4 is appended to the letter B, the constant is a bit-string constant with the base 4, 8, or 16, respectively. Each digit occupies 2, 3, or 4 bits. For example, '17777'B3 is an octal constant that is represented internally as a string of 15 bits.
  • If the constant does not have the letter B appended, it is a character-string constant even when it contains only the characters 0 and 1. (However, a character string of 0s and 1s can be converted by a simple assignment to a bit string.)
  • If the constant is an integer, it has the attributes FIXED DECIMAL(n,0), where n is the number of digits in the integer. For example, the constant 1777 is a constant of type FIXED DECIMAL(4,0).
  • Constants with an appended or embedded decimal point, but with no following exponent, are of type FIXED DECIMAL(p,q), where p is the total number of digits and q is the number of digits to the right of the decimal point.
  • Consider this example where a fixed-point decimal constant has the following appended characters:

E digit ...

 

It is of type FLOAT DECIMAL(p), where p is the total number of digits in the fixed-point constant (that is, the total number to the left of the letter E).

Note that PL/I has no constants with the attributes FIXED BINARY, FLOAT BINARY. However, this presents no problems in programming because you can assign constants of any computational type to variables of any computational type and they are converted automatically to the target type.

You usually give values to binary variables by assigning decimal constants to them. For example:

I = 1;

 

This converts the decimal integer 1 and assigns the converted value to a fixed-point binary variable I. Consider the following example:

F = 1.333E-12;

 

This converts the floating-point decimal constant 1.333E-12 and assigns the converted value to a floating-point binary variable F.

Picture variables are usually given values by assigning fixed-point decimal constants. For example:

PAY_PIC = 123.44;

 

This assigns the fixed-point decimal value 123.44 to a picture variable PAY_PIC. The value of PAY_PIC is a pictured value, which is stored internally as a character string containing the characters 1, 2, 3, 4, and 4, along with any special formatting symbols defined for PAY_PIC.

Arithmetic Operands

The implied data types of constants are important primarily because of PL/I's rules for converting operands in an arithmetic operation. (Bit-string and character-string operations must have bit- and character-string operands, respectively.) All operations, including arithmetic operations, must be performed in a single data type, and automatic conversions are performed on arithmetic operands to make this possible. For example:

DECLARE X FLOAT DECIMAL (6);

X = X + 1.3;

 

In this example, the fixed-point decimal constant 1.3 is converted to floating-point decimal before the addition is performed. The rules for operand conversion are discussed in detail in See Derived Data Types for Arithmetic Operations .

For information about arithmetic operators, operands, and data conversions, see See , See Expressions and Data Type Conversions .

Compatible Data Types

In PL/I, the notion of compatible data types is used in the rules for passing arguments by reference and for based, controlled, defined, or external variables. For two nonstructure variables to have compatible data types, the following attributes must agree. That is, if one variable has the attribute, the other variable must also have it after the application of default rules:

ALIGNED

ENTRY

picture

AREA

FILE

PICTURE

array bounds

FIXED

POINTER

BINARY

FLOAT

precision

BIT

LABEL

PRECISION

CHARACTER

length

VARYING

DECIMAL

OFFSET

 

DIMENSION

 

 

Two pictured variables must have identical pictures after the expansion of iteration factors.

In addition, the following values must be equal:

  • Precisions and scale factors for arithmetic data
  • String lengths and area sizes
  • Number of dimensions for arrays and bounds in each dimension

Two structure variables have compatible data types if they have the same number of immediate members, and if corresponding members have compatible data types.

In general, you can specify string lengths, area sizes, and array bounds with expressions or with asterisks. The values used to determine whether two variables have compatible data types are obtained as follows:

  • For static variables, the values must be constants.
  • For automatic and defined variables, the expressions are evaluated when the block containing such a variable's declaration is activated. The resulting values are used for all references to the variable within that block activation.
  • For parameters, the declaration specifies any extents either with constants or with asterisks. In the case of asterisks, the extent in a particular procedure invocation is determined by the extent of the argument passed to the parameter. The extent remains the same throughout the procedure invocation.
  • For based or controlled variables, extent expressions are evaluated each time the variable is referenced.

Consider the following example:

/* Example of extent determination */

DATAT: PROCEDURE (PTR1);

 

DECLARE N FIXED, S CHARACTER(N) BASED(PTR1);

DECLARE PTR1 POINTER;

 

N = 10;

 

CALL P(S);

 

P: PROCEDURE(A);

 

DECLARE A CHARACTER(*), B CHARACTER(N);

N = 20;

PUT LIST(LENGTH(A),LENGTH(B),LENGTH(S));

END P;

 

END DATAT;

 

The PUT statement writes out:

10 10 20

 

The assignment to N inside the procedure P affects the extent of S, but not the extents of A or B, which were frozen when P was invoked.

Arithmetic Data

Arithmetic data types are used for variables on which arithmetic calculations are to be performed. The arithmetic data types supported by PL/I are as follows:

When you declare an arithmetic variable, you do not always have to define all its characteristics, or attributes.

See . Implied Attributes for Computational Data shows the implied attributes for computational data.

Precision and Scale of Arithmetic Data Types

The PRECISION attribute applies to decimal and binary data as follows:

  • The precision of a fixed-point data item is the total number of decimal or binary digits used to represent a value.
  • The precision of a floating-point data item is the number of decimal or binary digits in the mantissa of the floating-point representation.

Scale factors are supported for fixed-point decimal data. The scale of fixed-point data is the number of digits to the right of the decimal point. Fixed-point binary and floating-point data do not have a scale factor.

In this manual, the letter p is used to indicate precision, and the letter q is used to indicate the scale factor.

You can specify both precision and scale in a declaration. For example:

DECLARE x FIXED DECIMAL(10,3) INITIAL(1.234);

 

This example indicates that the value of x has 10 decimal digits and that 3 of those are fractional. When a value is assigned to the variable, its internal representation does not include the decimal point; the previous value for x is stored as 1234, and the decimal point is inserted when the number is output. The scale factor has the effect of multiplying the internal representation of the decimal number by a factor of 10 -q (where q is the absolute value of the specified scale).

See . Default Values for Precision summarizes the ranges of values you can specify for precision for each arithmetic data type and the defaults applied if you do not specify a precision.

. Default Values for Precision

Data Type
Attributes

Precision

Scale
Factor

Default Precision

BINARY FIXED

1 <= p <= 31

-

31

BINARY FLOAT
(Digital Variant)

1 <= p <= 113

-

24

BINARY FLOAT
(IBM Variant)

1 <= p <= 109

-

21

DECIMAL FIXED
(Digital Variant)

1 <= p <= 31

p >= q >= 0

10

DECIMAL FIXED
(IBM Variant)

1 <= p <= 15

p >= q >= 0

5

DECIMAL FLOAT
(Digital Variant)

1 <= p <= 34

-

7

DECIMAL FLOAT
(IBM Variant)

1 <= p <= 33

-

6

If no scale factor is specified for fixed-point decimal data, the default is 0.

Fixed-Point Binary Data

You can use the attributes FIXED and BINARY to declare integer variables and fractional variables in which the number of fractional digits is fixed (that is, nonfloating-point numbers). The FIXED attribute implies BINARY.

For example, you can declare a fixed-point binary variable as:

DECLARE X FIXED BINARY(31);

 

The compiler gives variable X the attributes FIXED, BINARY, and (31) in this declaration. The precision is 31.

PL/I has no representation in PL/I for a fixed-point binary constant. Instead, integer constants are represented as fixed decimal. However, fixed decimal integer constants (and variables) are converted to fixed binary when combined with fixed binary variables in expressions. For example:

I = I+3;

 

In this example, if I is a fixed binary variable, the integer 3 is represented as fixed decimal; however, PL/I converts it to fixed binary when evaluating the expression.

Fixed binary variables have a maximum precision of 31, so fixed binary integers can have values only in the range -2,147,483,648 through 2,147,483,647. An attempt to calculate a binary integer outside this range, in a context that requires an integer value, signals the FIXEDOVERFLOW condition.

The attributes FIXED BINARY are used to declare binary data in PL/I. The BINARY attribute is implied by FIXED. The format of a declaration of a single, fixed-point, binary variable is:

DECLARE identifier FIXED [BINARY] [(precision)];

 

There is no form for a fixed-point binary constant, although constants of other computational types are convertible to fixed-point binary. A fixed-point binary variable usually receives given values by being assigned to an expression of another computational type or another fixed-point binary variable.

Internal Representation of Fixed-Point Binary Data

See . Internal Representation of Fixed-Point Binary Data shows the internal representation of fixed-point binary data. Storage for fixed-point binary variables is always allocated in a byte, word, or longword. For any fixed-point binary value:

  • If p is in the range 1 through 7, a byte is allocated.
  • If p is in the range 8 through 15, a word is allocated.
  • If p is in the range 16 through 31, a longword is allocated.

The binary digits of the stored value go from right to left in order of increasing significance; for example, bit 6 of a FIXED BINARY (7) value is the most significant bit, and bit 0 is the least significant.

In all cases, the high-order bit (7, 15, or 31) represents the sign.

. Internal Representation of Fixed-Point Binary Data

Fixed-Point Decimal Data

Fixed-point decimal data is used in calculations where exact decimal values must be maintained, for example, in financial applications. You can also use fixed-point decimal data with a scale factor of 0 whenever integer data is required.

The following sections describe fixed-point constants and variables and their use in expressions.

This discussion is divided into the following parts:

  • Constants
  • Variables
  • Use in expressions
  • Internal representation
Fixed-Point Decimal Constants

A fixed-point decimal constant can have between 1 and 31 of the decimal digits 0 through 9 with an optional decimal point or sign, or both. If there is no decimal point, PL/I assumes it to be immediately to the right of the rightmost digit.

Some examples of fixed-point decimal constants are:

12

4.56

12345.54

-2

01.

 

The precision of a fixed-point decimal value is the total number of digits in the value. The scale factor is the number of digits to the right of the decimal point, if any. The scale factor cannot be greater than the precision.

Fixed-Point Decimal Variables

The attributes FIXED and DECIMAL are used to declare fixed-point decimal variables. The FIXED attribute is implied by DECIMAL.

If you do not specify the precision and the scale factor, the default values are 10 and 0, respectively.

The format of a declaration of a single fixed-point decimal variable is:

DECLARE identifier [FIXED] DECIMAL [(p[,q])];

 

Some examples of fixed-point decimal declarations are:

DECLARE PERCENTAGE FIXED DECIMAL (5,2);

DECLARE TONNAGE FIXED DECIMAL (9);

 

Use in Expressions

You cannot use fixed-point decimal data with a nonzero scale factor in calculations with binary integer variables. If you must use the two types of data together, use the DECIMAL built-in function to convert the binary value to a scaled decimal value before attempting an arithmetic operation. For example:

DECLARE I FIXED BINARY,

SUM FIXED DECIMAL (10,2);

SUM = SUM + DECIMAL (I);

 

Internal Representation of Fixed-Point Decimal Data

Fixed-point decimal data is stored in packed decimal format. Each digit is stored in a half-byte, as shown in See . Fixed-Point Decimal Data Representation . Bits 0 through 3 of the last half-byte contain a value indicating the sign. Normally, the hexadecimal value C indicates a positive value and the hexadecimal value D indicates a negative value. (PL/I also supports using the hexadecimal values A, E, and F for positive values and the hexadecimal value B for negative values.)

. Fixed-Point Decimal Data Representation

Floating-Point Data

The floating-point data types provide a way to express very large and very small numbers such as in scientific calculations. All floating-point calculations are performed on values in one of the binary floating-point formats. In general, the precision of the result is determined by the maximum precision of any operands in the operation. The numerical result of an operation is rounded to the result precision.

The following sections describe floating-point constants and variables and their use in expressions.

This discussion of floating-point data is divided into the following parts:

  • Constants
  • Variables
  • Use in expressions
  • Floating-point data formats
  • Internal representation of floating-point data
Floating-Point Constants

A floating-point constant can have one or more of the decimal digits 0 through 9 (with an optional decimal point), followed by the letter E and from one to five decimal digits representing a power of 10. The floating-point value and the integer exponent can both be signed. The first portion of the value, to the left of the letter E, is called the mantissa. The value to the right of the letter E is called the exponent.

Some examples of floating-point constants are:

2E10

-3E8

32E-8

.45632E16

 

The decimal precision of each of these values is the number of digits in the mantissa.

If you write a constant without the E and the exponent, it is considered to be fixed-point decimal. However, you can use such constants anywhere in expressions involving floating- point data.

All floating-point constants are decimal.

Floating-Point Variables

The keyword FLOAT identifies a floating-point variable in a declaration.

A floating-point value can be either binary or decimal. Because the internal representation of floating-point variables is binary, it is recommended that you use FLOAT BINARY (which is the default) to declare variables, unless you need the properties of FLOAT DECIMAL. (The difference between FLOAT BINARY and FLOAT DECIMAL appears only when a conversion to another type, such as character, for doing I/O is necessary.) You should declare all floating-point variables using the same base.

To declare a single floating-point binary variable, specify a DECLARE statement as follows:

DECLARE identifier FLOAT [BINARY] [(p)];

 

You can optionally specify the precision for a floating-point variable in the declaration. For example:

DECLARE X FLOAT BINARY(53);

 

The keyword FLOAT identifies a floating-point variable.

To declare a decimal floating-point variable, use the following format:

DECLARE identifier FLOAT DECIMAL [(p)];

 

For example:

DECLARE X FLOAT DECIMAL (10);

 

Using Floating-Point Data in Expressions

You can use both integer and scaled decimal constants in floating-point expressions. An arithmetic constant is always converted to the appropriate internal representation for use in a floating-point operation. The target type for the conversion depends on the context. For example:

DECLARE X FLOAT BINARY (53);

X = X + 1.3;

 

Here, the constant 1.3 is converted to floating point when the expression is evaluated.

Such a conversion is normally done during compilation, but in some cases the constant is maintained in decimal until run time.

Floating-Point Data Formats

PL/I supports the IEEE standards of floating point formats -- the S (single precision) and T (double precision) types. See . Ranges of Floating-Point Formats summarizes the approximate ranges of the floating-point formats.

. Ranges of Floating-Point Formats

Format

Range

S

0.29 * 10 -38 to 1.7 * 10 38

T

0.56*10 -308 to 0.9 * 10 308

See . Ranges of Precision for Floating-Point Types summarizes the ranges of precision (sign bits, exponent bits, and fractional bits of accuracy) for each type. See IEEE S_floating Format and See IEEE T_floating Format describe the internal representation of floating-point data.

. Ranges of Precision for Floating-Point Types

Floating-Point Type

Sign Bits

Exponent Bits

Fractional Bits

S (single precision)

1

8

24

T (double precision)

1

11

53

The PL/I compiler selects the appropriate floating-point type based on the precision you specify. The types are selected as shown in See . Floating-Point Types Used by PL/I , where p indicates precision.

. Floating-Point Types Used by PL/I

Precision (DECIMAL)

Precision (BINARY)

Digital UNIX

1 <= p <= 7

1 <= p <= 24

S

8 <= p <= 15

25 <= p <= 53

T

IEEE S_floating Format

The following PL/I types are represented using S_floating data, which occupies four contiguous bytes:

  • FLOAT BINARY (P) where P 24
  • FLOAT DECIMAL (P) where P 7

Bits are labeled from the right, 0 through 31, as shown in See . IEEE S_floating Data Representation .

. IEEE S_floating Data Representation

The form of S_floating data is sign magnitude, with bit 31 the sign bit (0 for positive numbers, 1 for negative numbers), bits 30:23 an exponent, and bits 22:0 a normalized 24-bit fraction including the redundant most significant fraction bit not represented. The value of data is in the range 1.17549435E-38 (normalized) to 3.40282347E38. The precision is approximately one part in 2**23; that is, typically seven decimal digits.

When loaded into a 64-bit register, the S_floating value resides in bits 29-63.

IEEE T_floating Format

The following PL/I types are represented using T_floating data, which occupies eight contiguous bytes:

  • FLOAT BINARY (P) where 24 < P 53
  • FLOAT DECIMAL (P) where 7 < P 15

Bits are labeled from the right, 0 through 63, as shown in See . IEEE T_floating Data Representation

. IEEE T_floating Data Representation

The form of T_floating data is sign magnitude, with bit 63 the sign bit (0 for positive numbers, 1 for negative numbers), bits 62:52 an exponent, and bits 51:0 a normalized 53-bit fraction including the redundant most significant fraction bit not represented. The value of data is in the approximate range 2.225073859D-308 (normalized) to 1.797693135D308. The precision is approximately one part in 2**52; that is, typically fifteen decimal digits.

Character Pictured Data

Use character pictured data to define fixed-length character strings and also specify that certain positions in the character string must contain specific types of characters.

A character picture specification must contain one or more A or X picture specification characters, and can also contain one or more 9 picture specification characters. A character picture specification might look like this in a DECLARE statement:

DECLARE EMPLOYEE_NUMBER PICTURE 'AAA999999X';

 

This statement declares the variable EMPLOYEE_NUMBER as a character pictured variable. The characters within the apostrophes describe its format.

The formatting possible with character pictured data is useful in applications where you have a specific defined format for a character string, such as an employee id or part number, but do not use the numeric portion of the string for calculations.

Character Picture Characters

lists the PL/I character picture characters and describes their meaning in a character pictured data item:

X

Any character in the DEC Multinational Character set.

A

Any alphabetic character, blank, $, #, or @

9

Any numeric digit or blank. Note that blanks are allowed, although they are not allowed when you use a '9' in a numeric picture character specification.

Examples of Character Picture Variable Definitions

The following examples show valid and invalid pictures given the following declaration for EMPLOYEE_NUMBER:

DECLARE EMPLOYEE_NUMBER PICTURE 'AAA999999X';

 

Valid pictures

'MFG123456A'

'prs52      x' (prs52 followed by four blanks and an x)

'$ab123456+'

 

Invalid pictures

'MF9123456A' (9 is invalid given the A format item for that position)

'prsA#3456x' (A and # are invalid given the 9 format item for those positions)

 

Numeric Pictured Data

Use numeric pictured data when you want to manipulate a quantity arithmetically and accept or display its value using a special format.

A numeric picture specification (or picture) describes both the numeric attributes of a pictured variable and its input/output (I/O) format. A simple picture might look like this in a DECLARE statement:

DECLARE CREDIT PICTURE '$99999V.99DB';

 

This statement declares the variable CREDIT as a pictured variable. The characters within the apostrophes describe its format.

The formatting possible with pictured data is useful in many applications, but pictured data is much less efficient than fixed-point decimal data for strictly computational use.

This section discusses the following topics:

  • The picture characters that make up a specification in the PICTURE attribute and in the P format item. It also describes picture syntax.
  • The process by which a value is assigned to a pictured variable or written out with the P format item.
  • The process by which a pictured value is assigned to other variables or acquired with the P format item.
  • Editing by picture.
  • The internal representation of pictured variables.

The formatting possible with pictured data is useful in many applications, but pictured data is less efficient than fixed-point decimal data in computations. Therefore, do not use pictured data unless you need the formatting.

Picture Characters

See . Picture Characters summarizes the PL/I picture characters, their meaning, and whether they effect numeric interpretation and internal representation. The paragraphs following the table describe the picture characters and syntax. All picture characters are shown here in uppercase, but their lowercase equivalents can be used.

. Picture Characters

Character

Meaning

Numeric
Interpretation

Internal
Representation

V

Position of assumed decimal point

yes

no

9

Decimal digit, including leading zeros

yes

yes

Z

Decimal digit with leading-zero suppression

yes

yes

*

Decimal digit with asterisk for leading zero

yes

yes

Y

Decimal digit with space for any zero

yes

yes

(n)

Iteration factor for subsequent character

yes

yes

T

Position of digit and encoded plus sign or minus sign

yes

yes

I

Position of digit and encoded plus sign if number >= 0

yes

yes

R

Position of digit and encoded minus sign if number < 0

yes

yes

$

Position(s) of (drifting)
dollar sign

yes

yes

+

Position(s) of (drifting) plus sign if number >= 0

yes

yes

-

Position(s) of (drifting) minus sign if number < 0

yes

yes

S

Position(s) of (drifting) plus sign or minus sign

yes

yes

,

Position at which comma is inserted

no

yes

.

Position at which decimal point is inserted

no

yes

/

Position at which slash is inserted

no

yes

B

Position at which space is inserted

no

yes

CR

Positions at which 'CR' is inserted if number < 0

no

yes

DB

Positions at which 'DB' is inserted if number < 0

no

yes

F ( [] n )

Scaling factor for fixed decimal numbers

yes

yes

K

Positions the exponent field

yes

yes

E

Positions the letter E, indicating the start of the exponent field

yes

yes

Decimal Place Character (V)

The V character shows the position of the assumed decimal point, or the scale factor for the fixed-point decimal value. The V character has no effect on the internal representation of the pictured value and does not cause a decimal point to appear in the internal representation or in the output (use the period insertion character for this purpose). The following rules apply to the V character:

  • Only one V character can appear in a picture.
  • If a picture does not contain the V character, the V is assumed to be at the right end of the picture. That is, the pictured value has a scale factor of 0.
  • When a fixed-point value is assigned to a pictured variable, the integral portion of the assigned value is described by the picture characters to the left of the V; the fractional portion of the assigned value is described by the picture characters to the right of the V. Values with too many or too few digits are handled as follows:

If the assigned value has fewer integral digits than are indicated by the picture characters to the left, then the integral value of the pictured variable is extended on the left with zeros. If the assigned value has too many integral digits, the value of the pictured variable is undefined and the FIXEDOVERFLOW condition is signaled.

If the assigned value has fewer fractional digits than are indicated in the picture, then the fractional value of the pictured variable is extended on the right with zeros. If the assigned value has too many fractional digits, then the excess fractional digits are truncated on the right; no condition is signaled. Thus, if the V character is the last character in the picture or is omitted, assigned fixed-point values are truncated to integers.

The following example shows the effect of the V character:

DECLARE PRICE PICTURE '$$9V.99',

BAD_PRICE PICTURE '$$9.99';

PRICE = .98; /* Output as $0.98 */

BAD_PRICE = .98; /* Output as $0.00 */

PRICE = 98; /* Output as $98.00 */

BAD_PRICE = 98; /* Output as $0.98 */

 

In this example, note that the variable PRICE, which contains the V character, represents the value properly. The variable BAD_PRICE, which contains only the period insertion character, has an assumed V character at the end of the picture, which causes the variable to misrepresent the value.

Digit Characters (9, Z, *, Y)

The characters 9, Z, and Y, and the asterisk character (*) mark the positions occupied by decimal digits. The number of these characters present in a picture specifies the number of digits, or precision, of the fixed-point decimal value of the pictured variable. The following rules apply to these characters:

  • The position occupied by 9 always contains a decimal digit, whether or not the digit is significant in the numeric interpretation of the pictured value. Leading zeros at positions occupied by a 9 are output.
  • The position occupied by Z contains a decimal digit only if the digit is significant in the integral portion of the numeric interpretation; if the digit is a leading 0, it is replaced by a space. Several additional rules apply to the Z character:

The Z character must not appear in the same picture with the asterisk character (*). It must not appear to the right of the characters 9, T, I, or R nor to the right of a drifting string.

If the Z character appears to the right of the V character, then all digits to the right of the V must be indicated by Z characters. Fractional zeros are then suppressed only if all fractional digits are 0 and all of the integral digits are suppressed; in that case, the internal representation contains only spaces in the digit positions.

  • The position occupied by the asterisk character (*) functions identically with the Z character, except that leading zeros are replaced by asterisks instead of spaces.
  • The position occupied by the Y character contains a decimal digit only if the digit is not 0. All zeros in the indicated positions, whether significant or not, are replaced by spaces.
Iteration Factor (n)

You can precede any picture character that can appear more than once in a picture by an iteration factor, which must be a positive integer constant enclosed in parentheses. For example:

'(4)9'

 

This picture is the same as the following one:

'9999'

 

Encoded-Sign Characters (T, I, R)

You can use the characters T, I, and R, which are encoded-sign characters, wherever 9 is valid. Each represents a digit that has the sign of the pictured value encoded in the same position. You can use only one encoded-sign character in a picture.

An encoded-sign character cannot be used in a picture that contains one of the following characters: S, +,-, CR, or DB (described in the following text).

The meanings of the characters are:

  • The T character indicates that the position contains an encoded minus sign if the numeric value is less than 0 and an encoded plus sign if the numeric value is greater than or equal to 0.
  • The I character indicates an encoded plus sign if the numeric value is greater than or equal to 0. Otherwise, the position contains an ordinary digit.
  • The R character indicates an encoded minus sign if the numeric value is less than 0. Otherwise, the position contains an ordinary digit.

See . ASCII Representation of Encoded-Sign Characters lists the encoded-sign characters and their ASCII equivalents.

. ASCII Representation of Encoded-Sign Characters

Digit

ASCII Character

Digit

ASCII Character

+0

{

-0

}

+1

A

-1

J

+2

B

-2

K

+3

C

-3

L

+4

D

-4

M

+5

E

-5

N

+6

F

-6

O

+7

G

-7

P

+8

H

-8

Q

+9

I

-9

R

Drifting Characters ($, +, -, S)

The dollar sign ($), plus sign (+), minus sign (-), and S character are drifting characters. You can use the drifting characters to indicate digits or to indicate a symbol to be inserted when, for example, a pictured value is written out by PUT LIST. The meanings of the characters are:

  • The dollar sign ($) causes a dollar sign to be inserted.
  • The plus sign (+) causes a plus sign to be inserted if the numeric value is greater than or equal to 0.
  • The minus sign (-) causes a minus sign to be inserted if the numeric value is less than 0.
  • The S character causes a plus sign to be inserted if the numeric value is greater than or equal to 0, and a minus sign if the value is less than 0.

If one of these characters is used alone in the picture, it marks the position at which a special symbol or space is always inserted, and it has no effect on the value's numeric interpretation. In this case, the character must appear either before or after all characters that specify digit positions.

However, if a series of n of these characters appears, then the rightmost n-1 of the characters in the series also specify digit positions. If the digit is a leading 0, the leading 0 is suppressed, and the leftmost character drifts to the right; the character appears either in the position of the last drifting character in the series or immediately to the left of the first significant digit, whichever comes first.

Used this way, the n-1 drifting characters also define part of the numeric precision of the pictured variable, because they describe at least some of the positions occupied by decimal digits. For an example of this behavior by a drifting character (the dollar sign), refer to the V decimal place character description.

The following additional rules apply to drifting characters:

  • A drifting string is a series of more than one of the same type of drifting character. Only one drifting string can appear in the picture; any other drifting characters can be used only singly and therefore designate insertion characters, not digits.
  • The Z and asterisk (*) cannot appear to the right of a drifting string.
  • A digit position cannot be specified (for instance, with a 9) to the left of a drifting string.
  • A drifting string can contain the V character and one of the insertion characters, which are defined as follows:

If the drifting string contains an insertion character, it is inserted in the internal representation only if a significant digit appears to its left. In the position of the insertion character, a space appears if the leftmost significant digit is more than one position to the right; the drifting symbol appears if the next position to the right contains the leftmost significant digit.

If the drifting string contains a V character, all digit positions to the right of the V (the fractional digits) must also be part of the drifting string. In this case, insignificant fractional digits are suppressed only when all integral and fractional digits are zeros: they are replaced by spaces in the internal representation. If any digit is not 0, all fractional digits appear as actual digits.

Any insertion characters immediately to the right of a drifting string are considered part of it.

Insertion Characters (, . / B)

The insertion characters indicate that characters are inserted between digits in the pictured value. The insertion characters are the comma (,), period (.), slash (/), and the space(B). The B character indicates that a space is always inserted at the indicated position.

The drifting characters ($, +, -, S) also function as insertion characters when used singly (that is, not as part of a drifting string).

The period (.) does not imply a decimal place character V (see the example in the description of the V character, described earlier).

The following rules describe insertion by the comma, period, and slash insertion characters.

  • In general, the insertion character itself is inserted in the internal representation of the pictured value. In particular, this is true if the insertion character is the first character in the picture, or if all the picture characters to its left are characters that do not specify decimal digits.
  • If 0 suppression occurs, the insertion character is inserted only in these cases:

If a significant digit appears immediately to its left

If the V character appears immediately to its left, and the fractional part of the numeric value contains significant digits

  • If the position preceding the insertion character is occupied by an asterisk or drifting string and the preceding position is taken by a leading 0, then the preceding character also indicates the character to be inserted in the position of the insertion character. If, however, the preceding position is taken by a leading 0 and does not have an asterisk or drifting string, then the insertion character's position is a space in the internal representation of the pictured value.
  • To guarantee that the decimal point is in the same position in both the numeric and character interpretations, the V and period characters must be adjacent. However, if the period precedes the V, then it is suppressed if there are no significant integral digits, even though all the fractional digits are significant. This property can make fractions appear to be integers when the internal (character) value is displayed. Consequently, the period should immediately follow the V character; it will then be in the correct location and will appear whenever any fractional digit is significant. The following example shows the correct and incorrect placement of the period:

DECLARE NUM PICTURE 'ZZZV.ZZ',

BAD_NUM PICTURE 'ZZZ.VZZ';

NUM=0.02; /* Output as .02 */

BAD_NUM=0.02; /* Output as 02 */

 

  • You can use other insertion characters, such as the comma, to separate the integral and fractional portions of a number. Do not use the comma with GET LIST input, because in that context it separates different data items in the input stream.
Credit (CR) and Debit (DB) Characters

These picture characters are always specified as the character pairs CR and DB. If either pair is included, it appears if the numeric value is less than zero. In each case, the associated positions contain two spaces if the numeric value is greater than or equal to 0.

The characters are inserted with the same case as used in the picture. If the lowercase form cr is used in the picture, lowercase letters are inserted in the pictured value; if the combination Cr is used, then Cr is inserted.

The credit and debit characters cannot be combined in one picture, nor can they be used in the same picture as any other character that specifies the sign of the value (S, plus sign (+), and minus sign (-) characters). In addition, they must appear to the right of all picture characters specifying digits.

Scaling Factor Character (F([+ or -] n))

The F character specifies the scale factor for a fixed-point decimal value. You can specify it once, at the right end of the picture specification.

Format

F ( [] n )

F

Indicates that the following number is a scaling factor.

(+ or -)

Indicates whether the decimal point should be moved to the right (if positive) or left (if negative).

n

The number of places to move the decimal place. You must specify n such that the number of digits following the V picture character minus the number specified with the F picture character is between -128 and 127.

Exponent Characters (K and E)

Use the K and E characters in numeric pictures to describe picture equivalents for floating-point decimal numbers. These characters delimit the exponent field.

K

Shows the position where the exponent field begins. This character does not appear in the data item.

E

Shows the position where the letter E, followed by the exponent field, appears in the data item.

Only one K or E can appear in a picture.

For example:

DECLARE RESULT PICTURE 'SZ999V.99ES99'

 

Picture Syntax

After all its iterations are expanded and all its insertion characters are removed, a picture must satisfy the following syntax rules (the notation character, or ellipsis (...), indicate a series of the same character, with no embedded characters).

Picture:

'[left-part]center-part[right-part]'

 

Left-part:

Right-part:

Center-part:

  • The character Y, T, I, or R can appear wherever 9 is valid with the following restrictions. Only one character T, I, or R can appear in a picture. A picture cannot contain T, I, or R if it also contains S, +, -, CR, or DB.
Examples
Valid Pictures

'S99V.99'

 

The picture specifies a signed fixed-point number with a precision of 4 (p=4) and a scale factor of 2 (q=2). The sign of the number is always included in its representation, in the first position. A period is inserted at the position of the assumed decimal point.

'****99'

 

The picture specifies a 6-digit integer, with the first four leading zeros replaced by asterisks.

'****V.**'

 

The picture specifies a fixed-point number with p=6, q=2. The first four leading zeros are replaced by asterisks in the integral portion. Both fractional digits always appear unless all six digits are 0. A period is inserted at the position of the assumed decimal point.

'ZZ99V.99'

 

The picture specifies a fixed-point number with p=6, q=2. The first two digits in the integral portion are replaced with spaces if they are zeros. Two digits always appear on either side of the decimal point.

'(4)SV.99'

 

The picture specifies a fixed-point number with p=5, q=2. (The iteration factor 4 specifies a string of four S characters, one of which specifies a sign and three of which specify digits.) A plus (+) or minus (-) symbol is inserted to the immediate left of the first significant digit, or to the left of the decimal point if no integral digit is significant. Any insignificant integral digits are replaced with spaces or with the sign symbol.

'ZZZ,ZZZV.99'

 

The picture specifies a fixed-point number with p=8, q=2. If the integral portion has four or more significant digits, a comma is inserted between the third and fourth digit; otherwise, both the leading zeros and the comma are suppressed. The decimal point always appears followed by two fractional digits.

'ZZZ.ZZZV,99'

 

The picture specifies a fixed-point number with p=8, q=2. If the integral portion has four or more significant digits, a period is inserted between the third and fourth; otherwise, both the leading zeros and the period are suppressed. The decimal point (indicated by a comma) always appears followed by two fractional digits.

'ZZZ/ZZZ/ZZZ'

 

The picture specifies a fixed-point number with p=9, q=0. A slash is inserted between the 3-digit groups unless the digit preceding the slash is a suppressed 0.

Invalid Pictures

'999ZZZZV.99'

 

The picture is invalid because a 9 occurs to the left of Z.

'$$$--99v.99'

 

The picture is invalid because it contains two drifting strings ('$$$'and '--').

'(4)-V.ZZZ'

 

The picture is invalid because fractional digits in this case must be pictured either with a drifting minus sign or with 9s.

Assigning Values to Pictured Variables

Assignment of a computational value to a pictured variable is performed in the following two steps:

  1. The value is converted to fixed decimal, with precision and scale as specified by the picture.
  2. The resulting fixed decimal value is edited into the pictured variable.

If PL/I cannot perform one of these steps in a meaningful fashion, an error occurs. The following examples show two programming errors that are common in assignments to pictured variables.

CREDIT = '$12443.00';

 

This example signals the CONVERSION condition, because the character string contains a dollar sign and cannot be converted to fixed-point decimal. The value assigned to CREDIT should be either '12443.00' or 12443.00, both of which result in the same value assigned to CREDIT.

If a negative value is assigned to a pictured variable, the picture must include one of the sign picture characters (such as DB). For example:

CREDIT = -12443.00;

 

If the picture of CREDIT did not contain the DB characters, this assignment would signal the FIXEDOVERFLOW condition, because the sign would be lost. In some circumstances (for example, with the READ statement), it is possible to assign a value to a pictured variable that is not valid with respect to the variable's picture specification. In such cases, you can use the VALID built-in function to validate the contents of the variable.

Extracting Values from Pictured Data

When you use a pictured value in an arithmetic context (such as an assignment to an arithmetic variable), the picture is used to extract the fixed-point decimal number from the character string that internally represents the pictured value. Extraction also occurs when you input a pictured value with the GET EDIT statement and the P format item. If the contents of the pictured variable or input item do not conform to the picture, an error occurs.

For example:

DECLARE CREDIT PICTURE '$99999V.99DB';

 

In the picture for CREDIT, the 9 character specifies the position of a decimal digit; because the picture contains seven of these, the fixed-point decimal precision of CREDIT is 7. The V character separates the integral and fractional digits; because there are two 9 characters to the right of the V, the scale factor of CREDIT is 2. Because the V character specifies only a numeric property, a period picture character (.) to ensure that the output value has a decimal point in the correct place.

The period and dollar sign are always inserted in the internal representation and the output value regardless of CREDIT's numeric value.

The picture character DB appears only when the value of CREDIT is less than 0; otherwise, two spaces appear in the indicated positions. The DB character also indicates that CREDIT's value is numerically negative, so that if CREDIT is later assigned to an arithmetic variable the variable will be given a negative value.

Editing by Picture

Any computational value or expression can be assigned to a pictured variable, as long as it meets these two qualifications:

  • The value either is a fixed-point decimal value or can be converted to a fixed-point decimal value.
  • The fixed-point decimal value can be represented with the precision and scale factor of the picture specified for the target pictured variable.

When a value is assigned to a pictured variable, the value is edited to construct a character string that meets the picture specification. Editing also occurs when a value is output with the PUT EDIT statement and the P format item. Editing was performed in the previous examples in which fixed-point decimal values were assigned to the pictured variable CREDIT.

Because a picture specifies a fixed-point decimal value, the FIXEDOVERFLOW condition is signaled in the same circumstances as for assignment of an expression to a FIXED DECIMAL variable.

The Internal Representation of Pictured Variables

A pictured variable has the attributes of a fixed-point decimal variable, but values assigned to it are stored internally as character strings. Such a character string contains digits describing the variable's numeric value as well as special symbols. An individual picture character and its position in the picture indicate the interpretation of an associated position in the pictured value.

The picture characters fall into three categories:

  • Characters that do not affect internal representation. The decimal place character (V) is the only one in this category.
  • Characters that affect both the numeric interpretation and internal representation of the value. These characters indicate how the digits of the numeric value should be placed in the string and where to place a sign as follows:

The digit characters (9, Z, *, Y)

The encoded-sign characters (T, I, R)

The drifting characters ($, +,-, S)

  • Characters that affect only the internal representation of the value. These characters appear in the internal characters string as follows:

The insertion characters (comma, period, slash, space)

The credit (CR) and debit (DB) characters

See Picture Characters describes each picture character in more detail. The assignment CREDIT = 12443.00; stores data internally, as shown in See . Internal Representation of a Pictured Variable , as a character string where delta () represents a space.

. Internal Representation of a Pictured Variable

The assignment CREDIT = -12443.00; stores data internally as shown in See . Internal Representation of a Pictured Variable .

. Internal Representation of a Pictured Variable

In situations that call for a character representation of a pictured data item (such as output with PUT LIST), this internal representation is used, including the nonnumeric characters. On output, the values assigned to CREDIT would look like this:

$12443.00 /* a positive value (credit) */

$12443.00DB /* a negative value (debit) */

 

Character String Data

A character string is a sequence of zero or more characters. The value of a character-string variable can consist of any DEC Multinational Character to a maximum length of 32,767 characters. The first 128 characters of the DEC Multinational Character Set are the ASCII characters.

Every character-string variable has a length attribute that specifies either the length of all values of the variable (fixed-length strings) or the maximum length of a value of the variable (varying-length strings).

This discussion of character-string data is divided into the following parts:

Character String Constants

A character string constant can consist of any characters in the DEC Multinational Character Set.

When you use character-string constants in a program, you must enclose the strings in apostrophes or quotation marks, as shown in the following examples:

'Total is:'

"Enter your first name: "

 

To specify a character string containing a literal apostrophe, use two apostrophes within the string. For example:

'Life isn''t fair'

 

When you specify a character string with embedded apostrophes as shown, the final result contains only a single apostrophe.

Replication of String Constants

You can use a replication factor to replicate character-string and bit-string constants in any context of the program. A replication factor is an unsigned integer constant that specifies the number of times a simple string constant is replicated to produce a resulting string constant. For example:

(4)'season '

 

In this example, the string is repeated four times. The character constant resulting from this specification is equivalent to:

'season season season season '

 

You can use a replication factor in combination with the iteration factor in INITIAL. For example, the following two statements are equivalent:

INITIAL ((10)('ABCABC'))

INITIAL ((10)((2)'ABC'))

 

The first example uses an iteration factor exclusively, but the second example combines an iteration factor of 10 with a replication factor of 2. Note that an extra set of parentheses is required to separate the iteration factor from the replication factor and the character string.

Character-String Variables

The CHARACTER keyword identifies a variable as a character-string variable in a declaration. The format is:

The addition of the VARYING attribute indicates a varying-length character-string variable.

An optional number in parentheses specifies the length of the variable, that is, the number of bytes needed to contain its value (maximum is 32,767). This length attribute specifies either the length of all values of the variable (fixed-length strings) or the maximum length of a value of the variable (varying-length strings). If the length is not specified, PL/I uses the default length of one character, or byte. The rules for specifying the length are:

  • For a static variable declaration, the length must be an integer constant.
  • In the declaration of a parameter or returns descriptor, you can specify the length as an integer constant or as an asterisk (*). The resulting string is fixed length unless VARYING is also specified.
  • For an automatic, based, or defined variable, you can specify the length as an integer constant or as an expression. In the case of automatic or defined variables, the expression must not contain any variables or functions that are declared in the same block, except for parameters.
  • The maximum length in any string declaration is 32,767.

If specified, n must immediately follow the keyword CHARACTER, and must be enclosed in parentheses.

Fixed-Length Character String Variables

A fixed-length character string is one that does not have the VARYING attribute. For a particular allocation of a fixed-length character string variable, all its values have the same length. When a program assigns a value to a fixed-length character-string variable, however, the value does not need to have the same length defined for the variable. Depending on the size of the value, PL/I adjusts the assignment length according to the following rules:

  • If the value is smaller than the length of the character string, PL/I pads the character string with spaces on the right. For example:

DECLARE STRING CHARACTER (10);

STRING = 'ABCDEF';

 

The final value of the variable STRING is 'ABCDEF    ', that is, the characters ABCDEF followed by four space characters.

  • If the value is larger than the length of the variable, PL/I truncates the character string on the right. For example:

DECLARE STRING CHARACTER (4);

STRING = 'ABCDEF';

 

Here, the final value of STRING is 'ABCD', that is, the first four characters of the value 'ABCDEF'.

Internal Representation of Fixed-Length Character Data

PL/I stores fixed-length character string data in a contiguous sequence of bytes with the leftmost character occupying the lowest memory address.

Varying-Length Character String Variables

When you define a character string variable, you can also specify the VARYING attribute. In a varying character-string variable, the length is not fixed. The length specified in the declaration of the variable defines the maximum length of any value that can be assigned to the variable. Each time a value is assigned, the current length changes. For example:

DECLARE NAME CHARACTER (20) VARYING;

NAME = 'COOPER';

NAME = 'RANDOM FACTOR';

 

The declaration of the variable NAME indicates that the maximum length of any character- string value it can have is 20. The current length becomes 6 when NAME is assigned the value 'COOPER'; the length becomes 13 when NAME is assigned the value 'RANDOM FACTOR'; and so on.

When a varying character string is assigned a value with a length greater than the maximum defined, the value is truncated on the right.

The initial length of an automatic varying-length character string variable is undefined unless the variable is initialized.

You can use the LENGTH built-in function to determine the current length of any string, and the MAXLENGTH built-in function to determine the maximum length.

Internal Representation of Varying Character Data

A varying-length character string consists of a fixed binary (15) value (stored as a word) specifying the string's current length, followed by a sequence of bytes in sequentially higher memory addresses.

Alignment of Character Strings

The PL/I language makes a distinction between aligned and unaligned varying character strings. (No such distinction is made for fixed length character strings or for character string constants.) A varying character string is aligned if it is declared with the ALIGNED attribute.

This distinction affects only argument passing. If a procedure declares a parameter as ALIGNED CHARACTER, and if the corresponding argument is an unaligned character-string variable or vice versa, the actual argument will be a dummy variable. For example:

DECLARE GETSTRING ENTRY (CHARACTER (*) ALIGNED);

DECLARE STRING CHARACTER (8);

CALL GETSTRING (STRING);

 

PL/I constructs a dummy variable here to pass the unaligned string variable STRING to the called procedure GETSTRING, rather than passing the actual argument by reference.

All character strings on the Digital Alpha hardware are aligned on byte boundaries. You should not use the ALIGNED attribute to declare character string variables.

Bit-String Data

A bit string consists of a sequence of binary digits, or bits. It can be used as a Boolean value, which has one of two states: true (if any bit is non-zero) or false (if all bits are 0).

Like a fixed-length character string, a bit string has a fixed length defined in the declaration or specified by the number of bits in a bit-string constant. The maximum length of any bit string is 32,767 bits. However, bit-string variables cannot be declared with the VARYING attribute.

The rest of this section discusses bit-string constants and variables, alignment of bit-string data, and the use of bit strings to represent integers.

This discussion of bit-string data is divided into the following parts:

Bit-String Constants

To specify a bit-string constant, enclose the string in apostrophes and follow the closing apostrophe with the letter B. For example:

'0101'B

'10101010'B

'1'B

 

The length of a bit-string constant is always the number of binary digits specified; the B does not count in the length of the string. You can specify a bit-string constant with a maximum of 1000 characters between the apostrophes.

You can also specify a bit-string constant using the following syntax:

'character-string'Bn
 
n

Is the number of bits to be represented by each digit in the string. n can have the value 1 through 4, and if not specified defaults to 1.

This format allows you to specify bit-string constants with bases other than 2. You can use base 4, 8, and 16, where n equals 2, 3, and 4 respectively. For example:

'EF8'B4

'117'B3

'223'B2

 

These constants specify the hexadecimal value EF8, the octal value 117, and the base 4 value 223. All such constants are stored internally as bit strings, not as integer representations of the value.

The valid characters for each type of bit-string constant are as follows:

  • For B or B1, only the characters 0 and 1 are valid
  • For B2, only the characters 0, 1, 2, and 3 are valid
  • For B3, only the characters 0, 1, 2, 3, 4, 5, 6, and 7 are valid
  • For B4, the characters 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, and F are valid (the letters A through F can be either upper- or lowercase)

Using the B format items, you can also acquire or output (with the GET EDIT and PUT EDIT statements) bit-string data in binary, base 4, octal, or hexadecimal format. See See B Format Items for more information on the B format item.

Replication Factor for Bit-String Constants

A replication factor is an unsigned integer constant that specifies the number of times a simple bit-string constant is replicated. A replication factor permits repetition of bit strings in any context where a simple string constant is permissible, including format items and assignment, string, and arithmetic operations. The format of a replication factor is as follows:

(r)'string'Bn

 
r

An unsigned integer that represents the number of times that the string is to be replicated.

string

A simple bit string constant to be replicated. The bit string is enclosed in apostrophes.

An example of replication is:

DECLARE (A) BIT (800);

A = (400) '2'B2;

PUT SKIP LIST ((A));

 

In this example, A will be replicated to its maximum specified length of 800 characters.

The resulting character constant looks like this:

'10101010101010101010101010101010

10101010101010101010101010'B

 

You can use the replication factor in combination with the iteration factor in INITIAL. For example, the following two statements are equivalent:

INITIAL ((10)('ABCABC'B4))

INITIAL ((10)((2)'ABC'B4))

 

The first statement uses an iteration factor exclusively; the second statement combines an iteration factor of 10 with a replication factor of 2. An extra set of parentheses is required to separate the iteration factor from the replication factor and the bit string.

Bit-String Variables

Use the BIT attribute to declare a bit-string variable. The format is:

DECLARE variable-name BIT [(length)];

 

You can optionally specify the length of the variable in parentheses. The length can be from 0 to 32,767; the default length is one bit. The rules for specifying the length are as follows:

  • If BIT is specified for a static variable declaration or in a returns descriptor, the length must be an integer constant.
  • If BIT is specified in the declaration of a parameter or in a parameter descriptor, you can specify the length as an integer constant or as an asterisk (*).
  • If BIT is specified for an automatic, based, or defined variable, you can specify the length as an integer constant or as an expression. In the case of automatic or defined variables, the expression must not contain any variables or functions that are declared in the same block, except for parameters.

A program can assign to a bit-string variable a value larger or smaller than the variable's defined length. In such cases, PL/I does the following:

  • If the assigned string is shorter than the defined length, PL/I pads the bit-string value with zeros in the direction of least significance. The less significant bits are on the right as the string is represented by PUT LIST.
  • If the assigned string is longer, PL/I truncates the least significant bits from the bit-string value.

You can convert bit-string variables to other data types; however, there are some precautions you must observe if you do so. See Data Type Conversion of Operands and Expressions describes how to convert bit-string variables.

Alignment of Bit-String Data

PL/I distinguishes between aligned and unaligned bit-string variables. (Bit-string constants are always unaligned.) A bit-string variable is aligned only if it is declared with the ALIGNED attribute, as shown in the following example:

DECLARE FLAGS BIT (8) ALIGNED;

 

PL/I allocates storage for an aligned bit-string variable on a byte boundary and reserves an integral number of bytes to contain the variable. Unaligned bit-string variables always occupy only as many bits as are needed to contain them. They need not be on byte boundaries. You can optionally specify the UNALIGNED attribute in a declaration; UNALIGNED is the default for bit strings.

In general, operations involving unaligned bit-string variables are less efficient than those involving aligned bit-string variables. Unaligned bit-string variables are also invalid as the targets of the FROM and INTO options of record I/O statements, and as the argument of the ADDR built-in function. Moreover, most non-PL/I programs that accept bit-string arguments require the strings to be aligned.

In most cases, you should declare bit-string variables with the ALIGNED attribute. Use unaligned bit-string variables when bit strings must be packed as tightly as possible, for example, in arrays and in structures. See See ALIGNED Attribute for more information.

Internal Representation of Bit Data

In this discussion, the term most significant bit means the leftmost bit in an external representation of a string, as, for example, when the string is output by the PUT LIST statement. The least significant bit is the rightmost bit in the external representation.

The notion of significance has no meaning for bit strings unless they are used to store integers. PL/I permits the use of bit strings for this purpose, and has defined rules for conversions between bit strings and other data types.

  • The use of PL/I bit-string data to store integers is not recommended, for two reasons:

    1. In assignments involving two bit strings of different lengths, the source string is padded or truncated as required to make a string of the length of the target.

    2. As shown in the following discussions, the significance of bits results in bit strings being stored in the reverse order from actual numeric data. Consequently, conversion of bit strings to arithmetic data is expensive in terms of execution speed, except in the special case of a 1-bit string.

    3. Internal representation is implementation specific. Do not rely on internal representation in your program, especially if you are writing transportable code.

Use the UNSPEC built-in function and UNSPEC pseudovariable when you must store integers in a compact form. Otherwise, use the data types FIXED BINARY and FIXED DECIMAL for integer arithmetic .

In Kednos PL/I for UNIX, bit strings are stored in memory with the leftmost bit (as represented by PUT LIST) in the lowest memory location, and bits following the leftmost in successively higher memory locations. This representation of a bit string is reversed by PUT with respect to a conventional picture of memory locations, in which the lowest location appears on the right and higher locations on the left. If you are accustomed to using PL/I on computers other than VAX or Alpha AXP machines and if you do not change your data to correct for this difference, the result is likely to be in error.

Unaligned Bit Strings

An unaligned bit string is stored beginning at an arbitrary bit location in storage; this location is the location of the most significant bit. The subsequent, less significant, bits are stored in progressively higher locations in memory, as shown in See . Unaligned Bit String Storage .

. Unaligned Bit String Storage

The following programming sequence shows how a value for an unaligned bit-string variable is stored:

DECLARE ABIT BIT (10);

ABIT = '1011'B;

 

After the assignment, the variable appears in storage as shown in See . Sample Unaligned Bit String Storage .

. Sample Unaligned Bit String Storage
Aligned Bit Strings

PL/I allocates storage for an aligned bit-string variable on a byte boundary and allocates an integral number of bytes. The number of bytes to be allocated is calculated as:

ceil(n/8)

Here, n is the length specified for the bit string.

Beginning at bit 0 (the lowest memory location) of the lowest allocated byte, the bit string is stored like unaligned bit-string data; that is, the beginning bit is used to hold the most significant bit in the string. Less significant bits are stored in progressively higher memory locations. Unused bits are set to 0 each time the bit-string variable is assigned a value.

The representation is shown in See . Aligned Bit String Storage .

. Aligned Bit String Storage

The following programming sequence shows how values are stored for aligned bit strings:

DECLARE ABIT BIT (10) ALIGNED;

ABIT = '10011'B;

 

In this example, the variable ABIT is aligned. When it is assigned the value 10011, the value is stored as shown in See . Sample Aligned Bit String Storage .

. Sample Aligned Bit String Storage

Bit Strings and Integers

PL/I defines conversions between bit-string data and other data types, and the compiler carries out these conversions. However, the conversions defined by PL/I are not always straightforward or intuitive; the padding and truncation that take place during assignment of bit strings of different lengths result in implicit multiplication or division of the bit string's integer value. For example:

DECLARE BITSTR BIT (10);

BITSTR = 1;

PUT LIST (BITSTR);

 

The output is:

'0001000000'B

 

The result may seem incorrect, but it conforms to PL/I's rules for conversion to bit strings. In this case, the fixed-decimal constant 1 is converted to a FIXED BINARY(4) value, which is in turn converted to an intermediate bit string of length 4:

'0001'B

 

Next, this intermediate bit string is assigned to the variable BITSTR. Because BITSTR is of length 10, the intermediate bit string is padded on the right with zeros, producing the result as output by PUT LIST. If you now attempt to interpret the value of BITSTR as an integer (for example, by using BITSTR as the argument of the BINARY built-in function), the result would be 64, not 1.

Extra execution time is required to reverse the order of bits when the integer's value is computed. Using arithmetic variables to represent integers is more efficient.

Because of the unexpected results and longer execution time, avoid using bit strings to represent integers or other data types.

Pointer Data

A pointer is a variable whose value represents the address in memory of another variable or data item.

Pointers are used to qualify references to based variables, that is, variables for which storage is explicitly allocated at run time by the ALLOCATE statement. For example:

DECLARE LIST_POINTER POINTER;

DECLARE 1 LIST_STRUCTURE BASED,

2 FORWARD_PTR POINTER,

2 MEMBER_NAME CHAR(20) VAR;

 

ALLOCATE LIST_STRUCTURE SET (LIST_POINTER);

LIST_POINTER -> LIST_STRUCTURE.MEMBER_NAME = 'newname';

 

When these statements are executed, the ALLOCATE statement allocates storage for a variable LIST_STRUCTURE and sets the pointer LIST_POINTER to the address in memory of the allocated storage. This dynamically created variable is called an allocation of the variable LIST_STRUCTURE.

In the assignment statement, the locator qualifier ->) and the identifier LIST_POINTER distinguish this allocation of LIST_STRUCTURE from allocations created by other ALLOCATE statements, if any. Pointers may also be used directly in declarations of based variables. For example:

DECLARE X POINTER,

BUFFER CHARACTER(80) BASED (X);

 

The variable X is given the POINTER attribute. Then it is used as the target pointer in another declaration, which defines a buffer to be based on X.

This section discusses the following:

Pointer Variables in Expressions

Expressions containing pointer variables are restricted to the relational operators equal (=) and not equal (^=), and the assignment operator.

For example, to test whether a pointer is currently pointing to valid storage, you can write the following statement:

IF LIST_POINTER ^= NULL() THEN

DO;

 

The NULL built-in function always returns a null pointer value.

You can use pointer variables in simple assignment statements that assign a pointer value to a pointer variable. For example:

LIST_POINTER_1 = LIST_POINTER_2;

LIST_END = NULL();

 

You can also use a pointer variable as the source or target in an assignment statement involving an offset variable or offset value.

Internal Representation of Pointer Data

A pointer occupies a longword (32 bits) of storage and represents a virtual memory address.

Offset Data

You declare an offset variable with the OFFSET attribute, optionally followed by an area variable reference. The value of the offset variable will be interpreted as an offset within the specified area, unless the POINTER function is used to explicitly specify another area. You must omit the area reference if the OFFSET attribute is specified within a returns descriptor, parameter declaration, or parameter descriptor. For example:

DECLARE MAP_SPACE AREA (40960),

MAP_START OFFSET (MAP_SPACE),

MAP_LIST(100) CHARACTER(80) BASED (MAP_START);

 

These declarations define an area named MAP_SPACE; an offset variable, MAP_START, that will contain offset values within that area; and a based variable whose storage is located by the value of MAP_START.

Offset variables are given values by assignment from existing offset values or from conversion of pointer values. PL/I also automatically converts a pointer value to an offset value, or an offset value to a pointer value, in an assignment statement. The following assignments are valid:

  1. pointer-variable = pointer-value;
  2. pointer-variable = pointer-value fixed-binary-number;
  3. offset-variable = offset-value;
  4. pointer-variable = offset-variable;
  5. offset-variable = pointer-value;

In assignment 3, any area references are ignored in the assignment; therefore, the offset value and variable can refer to different areas. In assignments 4 and 5, the offset variable must have been declared with an area reference.

Expressions containing offset variables are restricted to the relational operators = and ^=, for testing the equality or inequality of two values.

Label Data

A label identifies a statement so that it can be referred to elsewhere in the program, for example, as the target of a GOTO statement. A label precedes a statement and consists of any valid identifier terminated by a colon. Some examples are:

TARGET: A = A + B;

READ_LOOP: READ FILE (TEXT) INTO (TEMP);

 

These statements contain the implicit declarations of the names TARGET and READ_LOOP as label constants.

No statement can have more than one label. A statement can, however, be preceded by any number of labeled null statements. For example:

A: ;

B: DO I = 1 TO 5;

 

Other statements in the program can refer to the DO statement in this example by specifying either label A or label B.

A name occurring as a statement label is implicitly declared as a label constant. It has the attributes LABEL and constant. You cannot explicitly declare label constants.

This section discusses the following:

Label Array Constants

Any label constant except the label of a PROCEDURE or FORMAT statement can have a subscript. Subscripts must be specified with integer constants and can be either a simple constant or, using the IBM dialect, an array of up to seven dimensions. A subscript must appear in parentheses following the label name as shown in the following example:

PART(1):

PART(2):

PART(*):

 

The following example shows labels with two dimensions (valid in the IBM dialect only):

PART(1,1):

PART(1,2):

PART(*,*):

 

When labels are written this way, the unsubscripted label name represents the implicit declaration of a label array constant. In this example, the array is named PART and is treated as if it were declared within the block containing the subscripted labels. A default label can be created by using the asterisk (*) in place of a label constant. If a default label is used, it must be the last label in the list. If the variable subscript is out of range and the default label is present, the default label will be executed.

Elements of the array can be referenced in GOTO statements that specify a subscript. For example:

GOTO PART(I);

 

I is a variable whose value represents the subscript of the element of PART that is the label to be given control.

Make sure all the labels referenced by teh GOTO statement occur after the statement. See See GOTO Statement for more information.

Within a single block, you cannot use the same subscript value in two different subscripted references with the same name. For example:

PART(1):

 

This label array constant can be used only once in a block. However, the subscript values are not constrained to be in any particular order or to be consecutive. For example, you can use the array constants PART(1) and PART(3) without using PART(2).

If a name is used as a label array constant in two or more different blocks, each declaration of the name is treated as an internal declaration. For example:

LIST(2): RETURN;

BEGIN;

GOTO LIST (ELEMENT);

LIST(1):;

LIST(3):

END;

 

In this example, the value of ELEMENT cannot cause control to pass to the RETURN statement labeled LIST(2) in the containing block. The subscripted LIST labels in the begin block restrict the scope of the name to that block.

Label Values

Whenever a reference to a label constant is interpreted, the result is a label value. A label value has two components:

  • The first component designates the statement identified by the label constant.
  • The second component designates an activation of the block in which the label was declared (that is, to which the labeled statement belongs). If the label belongs to the current block, this block activation is the current block activation. If the label belongs to a containing block, the activation is found on the chain of parent block activations ending with the current block.

The GOTO statement with a label reference transfers control to the designated statement in the designated block activation. If the target block activation is different from the block activation in which the GOTO statement is executed, then the GOTO is nonlocal. For example:

DECLARE LV LABEL; /* LABEL variable */

 

LV = L; /* assigns a bound label value to LV */

BEGIN;

 

GOTO LV; /* nonlocal GOTO */

END;

L: RETURN;

 

Operations on label values are restricted to the operators = and ^= for testing the equality or inequality of two values. Two values are equal if they refer to the same statement in the same block activation.

Any reference to a label value after its block activation ceases to exist is an error with unpredictable results.

Label Variables

When an identifier is explicitly declared with the LABEL attribute, it acquires the VARIABLE attribute by default. You can use such a variable to denote different label values during the execution of the program.

For example:

DECLARE PROCESS LABEL;

 

IF CODE THEN

PROCESS = BILLING;

ELSE

PROCESS = CHARGE;

 

GOTO PROCESS;

 

When the GOTO statement evaluates the reference to the label PROCESS, the result is the current value of the variable. The GOTO statement transfers control to either of the labels BILLING or CHARGE, depending on the current value of the Boolean variable CODE.

You can also give values to label variables by passing label values as arguments or by returning a label value as the value of a function (although the latter method can lead to programming errors that are difficult to diagnose). For example:

CALL COMPUTER(ERROR_EXIT, YVAL, XVAL);

 

ERROR_EXIT:

 

In this example, the actual argument that is passed for ERROR_EXIT is a dummy argument whose value consists of the following:

  • The location in memory of the statement labeled ERROR_EXIT
  • A pointer to the stack frame for the block in which the CALL statement is executed

You can also declare arrays of label variables with up to seven dimensions. For example:

DECLARE LAB_ARRAY(10,20) LABEL;

GOTO LAB_ARRAY(I,J);

LAB_ARRAY(1,1):

LAB_ARRAY(1,2):

 

Restrictions

Any statement in a PL/I program can be labeled except a statement beginning an ON-unit or THEN, ELSE, WHEN, or OTHERWISE clauses

Labels on PROCEDURE, ENTRY, and FORMAT statements are not considered statement labels and cannot be used as the targets of GOTO statements.

An identifier occurring as a label in a block cannot be declared in that block (except as a structure member), and cannot occur in a parameter list of that block.

Internal Representation of Label Variables

See . Variable Label Data Representation shows the internal representation of variable label data.

. Variable Label Data Representation

Entry Data

Entry constants and variables are used to invoke procedures through specified entry points. An entry value specifies an entry point and a block activation of a procedure.

This section discusses the following:

Entry Constants

To declare entry constants, use labels on PROCEDURE or ENTRY statements.

To declare internal entry constants, use labels on PROCEDURE or ENTRY statements whose procedure blocks are nested in another block. You can use an internal entry constant anywhere within its scope to invoke its procedure block.

To declare external entry constants, either use labels on PROCEDURE or ENTRY statements that belong to external procedures, or explicitly declare the constant names with the ENTRY attribute. You can use an external entry constant to invoke its procedure block from any program location that is within its scope. Its scope is either the scope of its declaration (as a label) or the scope of a DECLARE statement for the constant.

You can declare external entry constants in DECLARE statements by using the ENTRY attribute. The declaration must agree with the actual entry point. That is, the declaration of the external entry constant must contain parameter descriptors for any parameters specified at the entry point, and, if the entry constant is to be used in a function reference, the declaration must have a returns descriptor describing the returned value.

Entry Values

Whenever a reference to an entry constant is interpreted, the result is an entry value. An entry value is the entry point of a procedure, and it serves to activate the block in which the entry point is declared (that is, the block in which the entry point's name appears as the label of a PROCEDURE or ENTRY statement). This block activation is the current block activation if the entry point belongs to the current block. If the entry point belongs to a containing block, the activation is on the chain of parent activations that ends at the current block activation.

No conversions are defined between entry data and other data types. You can assign an entry variable only the value of an entry constant or the value of another entry variable. The only operations that are valid for entry data are comparisons for equality (=) and inequality (^=). Two entry values are equal if they refer to the same entry point in the same block activation.

PL/I supports the passing of external procedures, but not internal procedures, as entry value parameters. To pass an internal procedure, use an entry parameter.

Entry Variables

Entry variables are variables (including parameters) that take entry values. If the VARIABLE attribute is specified with the ENTRY attribute in a DECLARE statement, the declared identifier is an entry variable. You can assign to an entry variable either another entry variable or an entry constant.

When an entry variable is used to invoke a procedure, its declaration must agree with the definition of the entry point. If the value you assign to an entry variable specifies an entry point with parameters, the parameters must be described with parameter descriptors in the declaration of the variable. If the assigned value specifies an entry point that is invoked as a function, then the declaration of the entry variable must have a RETURNS attribute that describes the data type of the returned value.

The scope of an entry variable name can be either internal or external. If neither the EXTERNAL nor the INTERNAL attribute is specified with the entry variable, the default is INTERNAL.

You can use the entry variable to represent different entry points during the execution of the PL/I program. For example:

DECLARE E ENTRY VARIABLE,

(A,B) ENTRY;

E = A;

CALL E;

 

The entry constant A is assigned to the entry variable E. The CALL statement results in the invocation of the external entry point A.

You can also declare arrays of entry variables. The following example shows an array of external functions:

DECLARE EXTRACT(10) ENTRY (FIXED,FIXED) VARIABLE RETURNS (FLOAT),

GETVAL FLOAT;

GETVAL = EXTRACT(3)(1,3);

 

This assignment statement references the third element of the array EXTRACT. When the statement is executed, this array element must contain a valid entry value.

  • Be careful when using static entry variables. The value of a static entry variable is valid only as long as the block in which that value was declared is active.

Internal Representation of Entry Variables

See . Entry Variable Data Representation shows the internal representation of entry variables.

. Entry Variable Data Representation

File Data

A PL/I file, or file constant, is represented by a file control block. A file control block is an internal data structure maintained by PL/I.

No conversions are defined between file data and other data types. You can assign a file variable only the value of a file constant or the value of another file variable. The only operations that are valid for file data are comparisons for equality (=) and inequality (^=).

This section discusses the following:

File Constants

To declare file constants, use the FILE attribute without the VARIABLE attribute. All file constants are external by default. To define an internal file constant, you must specify the INTERNAL attribute. For example:

DECLARE INFILE FILE;

 

This declaration declares a file constant named INFILE whose attributes include EXTERNAL by default.

DECLARE INFILE FILE INTERNAL;

 

This declaration specifies that the file constant named INFILE is internal to the block in which it is declared.

If you declare a file constant as EXTERNAL, you must use identical attributes, including ENVIRONMENT attributes, in all blocks that declare the constant. Otherwise, PL/I uses the last set of attributes encountered during compilation and ignores the others.

File Values

Whenever a reference to a file constant is interpreted, the result is a file value. A file value is a pointer to the file control block for the file with which the constant is associated. PL/I supports passing both external files and internal files as file value parameters.

File Variables

File variables are variables (including parameters) that take file values. If you specify the VARIABLE attribute with the FILE attribute in a DECLARE statement, the declared identifier is a file variable. You can assign either another file variable or a file constant to a file variable.

A file variable is represented internally as a longword that contains a pointer to a file control block. The value of the file variable, when evaluated, is the address of the file control block for the file with which the variable is currently associated.

The scope of a file variable name can be either internal or external. If neither the EXTERNAL nor the INTERNAL attribute is specified with the file variable, the default is external.

If you declare a file variable implicitly or explicitly as EXTERNAL, you must use identical attributes, including ENVIRONMENT attributes, in all blocks that declare the variable. Otherwise, PL/I uses the last set of attributes encountered during compilation and ignores the others.

You can use the file variable to represent different files during the execution of the PL/I program. For example:

DECLARE F FILE VARIABLE,

(A,B) FILE;

E = A;

CALL READFILE(E);

 

The file constant A is assigned to the file variable E. The CALL statement results in the invocation of the entry point READFILE with file A as its parameter.

You can also declare arrays of file variables. The following example shows an array of external file variables:

DECLARE FILELIST(10) FILE VARIABLE,

MYFILE FILE VARIABLE;

MYFILE = FILELIST(3);

This assignment statement references the third element of the array FILELIST. When the statement is executed, this array element must contain a valid file value.

Area Data

An area is a region of storage in which based variables can be allocated and freed. You define an area by declaring a variable with the AREA attribute. An area variable can belong to any storage class. Areas provide the following programming capabilities:

All areas must be declared with the AREA attribute before they can be referenced in a BASED attribute or an ALLOCATE statement with the IN option. For example:

DECLARE MYAREA AREA;

DECLARE PTR OFFSET(MYAREA);

DECLARE MYDATA FIXED BIN(31) BASED(PTR);

 

The variable MYAREA is given the AREA attribute. Then it is used as the target in another declaration, which defines a pointer offset based on MYAREA. To allocate storage for MYDATA in area MYAREA, use the IN option of the ALLOCATE statement as follows:

ALLOCATE MYDATA IN(MYAREA) SET (PTR);

 

When these statements are executed, the ALLOCATE statement allocates storage for a variable MYDATA in the area MYAREA and sets PTR to the offset in the area of the allocated storage.

This section discusses the following:

Area Variables in Expressions

Expressions containing area variables are restricted to the relational operators equal (=) and not equal (^=) and to comparison to the empty () built-in function.

For example, to test whether an area is empty, that is, to determine whether it currently has storage allocated in it, you can write the following statement:

IF MYAREA = EMPTY() THEN

DO;

 

The EMPTY() built-in function always returns an empty area value.

You can use area variables in simple assignment statements that assign one area variable to another. For example:

AREA_1 = AREA_2;

AREA_2 = EMPTY();

 

Reading and Writing Areas

An area can be the source or target of data transmission in READ and WRITE record I/O statements. If the area is written by itself (not as a member of a structure), only the current allocated portion is transmitted unless the SCALARVARYING option of the ENVIRONMENT attribute was specified when the file was opened.

Internal Representation of Area Data

An area occupies the number of bytes, specified in the extent, of storage. Since this storage includes overhead used by PL/I for bookkeeping, slightly less than the full amount (specified in the extent) is available for program allocations. See See AREA Attribute for information on specifying the extent of an area.

Condition Data

PL/I provides a CONDITION attribute for declaring programmer-defined conditions. These conditions may only be signaled by the SIGNAL statement.

Condition data occupies a longword (32 bits) of storage.

No conversions are defined between condition data and other data types. The only operations that are valid for condition data are comparisons for equality (=) and inequality (^=).

You can use the CONDITION data type as either a constant or a variables. For example, the following are valid declarations:

DECLARE (C1, C2, C3) CONDITION;

DECLARE C CONDITION VARIABLE;

 

Aggregates

An aggregate is a data structure, either an array or structure composed of items as follows:

Arrays

Arrays provide an orderly way to manipulate related variables of the same data type. An array variable is defined in terms of the number of elements that the array contains and the organization of those elements. These attributes of an array are called its dimensions.

Array Declarations

To declare an array, specify its dimensions in a DECLARE statement using one of the following syntaxes:

DECLARE identifier [DIMENSION] (bound-pair, ...) [attribute ...];

 

DECLARE (identifier [DIMENSION] (bound-pair, ...)) [attribute ...];

 

To declare two or more array variables that have the same dimensions, bounds, and attributes, use the following syntax:

DECLARE (identifier, ...) [DIMENSION] (bound-pair, ...) [attribute ...];

identifier

A valid PL/I identifier to be used as the name of the array.

bound-pair

A specification of the number of elements in each dimension of the array. A bound pair can consist of one of the following:

  • Two expressions separated by a colon giving the lower and upper bounds for that dimension
  • A single expression giving the upper bound only (the lower bound is then 1 by default)
  • An asterisk (*), used in the declaration of array parameters, indicating that the parameter can be matched to array arguments with varying numbers of elements in that dimension

Bound pairs in series must be separated by commas, and the list of bound pairs must be enclosed in parentheses. The list of bound pairs must immediately follow the identifier or the optional keyword DIMENSION or the list of declarations. The following rules apply to specifying the dimensions of an array and the bounds of a dimension:

  • An array can have up to eight dimensions.
  • The values you can specify for bounds are restricted as follows:

If the array has the STATIC attribute, you must specify all bounds as restricted integer expressions. A restricted integer expression is one that yields only integral results and has only integral operands, which can be evaluated at translation time. Such an expression can use only the addition (+), subtraction (-), and multiplication (*) operators.

If the array has the AUTOMATIC, BASED, CONTROLLED, or DEFINED attribute, you can specify the bounds as optionally signed integer constants or as expressions that yield integer values at run time. If the array has AUTOMATIC or DEFINED, the expressions must not contain any variables or functions that are declared in the same block, except for parameters.

  • The value of the lower bound you specify must be less than the value of the upper bound.

See . Specifying Array Dimensions shows several forms of bound pairs as used in declarations. Note that all the examples in See . Specifying Array Dimensions would be identical in effect if the optional keyword DIMENSION were added.

attribute

One or more data type attributes of the elements of the array. All attributes you specify apply to each of the elements in the array.

Elements of an array can have any data type. If the array has the FILE or ENTRY attribute, it must also have the VARIABLE attribute.

. Specifying Array Dimensions

Bound Pairs

Examples

ARRAY_NAME (bound)

 

A single value specifies:

 

  • That the array has a single dimension.
  • That the number of elements in the dimension is the bound (that is, 6).
  • That the value specified is the high bound, which is the largest numbered element. By default, the low bound is 1.

DECLARE VERBS (6) CHARACTER (12);

ARRAY_NAME (low-bound:high-bound)

A single range of values specifies:

 

  • That the array has a single dimension.
  • That the number of elements in the dimension is (high-bound) - (low-bound) + 1.
  • That the first value specified is the low bound and the second value specified is the high bound.

DECLARE TEMPERATURES (-60:120);

ARRAY_NAME (bound1,bound2,...)

A list of values specifies:

 

  • That the array is multidimensional. Each bound value represents a dimension in the array.
  • The extent of each dimension. Each bound defines the number of elements in a dimension.
  • The high-bound value of each dimension. The low-bound value of each dimension defaults to 1.

DECLARE TABLE (10,10) FIXED BINARY; DECLARE SETS (5,5,5,5) CHARACTER (80);

ARRAY_NAME (low-bound1:high-bound1,low-bound2,high- bound2,...)

A list of ranges specifies:

 

  • That the array is multidimensional. Each range of values represents a dimension of the array (ranges can be intermixed with single-bound specifications).
  • The extent of each dimension.
  • The low-bound and high-bound values of each dimension.

DECLARE WINDOWS (1:10,-2:32) FIXED; DECLARE HISTORIES (10,30:102,50);

ARRAY_NAME (*,...)

 

Asterisk extents specify:

 

  • The number of dimensions in the array. Each asterisk indicates a dimension.
  • That the extent of each dimension will be defined by the actual argument passed to the procedure when it is invoked.

ADDIT: PROCEDURE (ARR);
DECLARE ARR(*,*) FIXED;

The declaration of an array specifies its dimensions, the bounds of each dimension, and the attributes of the elements.

One bound pair is specified for each dimension of the array to define the number of elements in that dimension. The total number of elements in the array, called its extent, is the product of the number of elements in all the dimensions of the array. If omitted, the lower bound is 1 by default. You can use an asterisk (*) as the bound pair when you declare arrays as parameters of a procedure; the asterisk indicates that the parameter can accept array arguments with any number of elements. (If one dimension is specified with an asterisk, all must be specified with asterisks.) For example:

DECLARE SALARIES (100) FIXED DECIMAL (7,2);

 

This statement declares a 100-element array with the identifier SALARIES. Each element is a fixed-point decimal number with a total of seven digits, two of which are fractional.

The following statement declares a two-dimensional array of 64 integers:

DECLARE GAME_BOARD (8,8) FIXED BINARY (7);

 

The following statement declares a one-dimensional array of 12 character strings, each having a length of 2:

DECLARE PM_HOURS(13:24) CHARACTER(2);

 

The elements of the previous array is numbered 13 through 24 instead of 1 through 12.

You can replace the identifier in a statement with a list of declarations, which declares several arrays with the same attributes. For example:

DECLARE (SALARIES,PAYMENTS)(100) FIXED DECIMAL(7,2);

 

This statement declares SALARIES and another array, PAYMENTS, with the same dimensions and other attributes.

References to Individual Elements

You refer to an individual element in the array with subscripts. Because an array's attributes are common to all of its elements, a subscripted reference has the same properties as a reference to a scalar variable with those attributes.

You must enclose subscripts in parentheses in a reference to an array element. For example, in a one-dimensional array named ARRAY declared with the bounds (1:10), the elements are numbered 1 through 10 and are referred to as ARRAY(1), ARRAY(2), ARRAY(3), and so on.

The lower and upper bounds that you declare for a dimension determine the range of subscripts that you can specify for that dimension. The number of elements in any dimension of any array is:

(upper bound) - (lower bound) + 1

For multidimensional arrays, the subscript values represent an element's position with respect to each dimension in the array. See . Specifying Elements of an Array shows subscripts for elements of one-, two-, and three-dimensional arrays. In subscripted references for multidimensional arrays, the number of subscripts must match the number of dimensions of the array and must be separated by commas.

You can specify the subscript of an array element using any variables or expressions having integer values, that is, values that can be expressed as fixed binary or fixed decimal with a zero scale factor. For example:

DECLARE DAYS_IN_MONTH(12) FIXED BINARY;

DECLARE (COUNT, TOTAL) FIXED BINARY;

TOTAL = 0;

DO COUNT = 1 TO 12;

TOTAL = TOTAL + DAYS_IN_MONTH(COUNT);

END;

 

Here, the variable COUNT is used as a control variable in a DO loop. As the value of COUNT is incremented from 1 to 12, the value of the corresponding element of the array DAYS_IN_MONTH is added to the value of the variable TOTAL.

Initializing Arrays

Specify the INITIAL attribute for an array to initialize its values in the declaration. For example:

DECLARE MONTHS (12) CHARACTER (9) VARYING

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

'May', 'June', 'July', 'August',

'September', 'October', 'November', 'December');

 

Each element of the array MONTHS is assigned a value according to the order of the character-string constants in the initial list: MONTH(1) is assigned the value `January'; MONTH(2) is assigned the value `February'; and so on.

If the array being initialized is multidimensional, the initial values are assigned in row- major order.

To assign identical initial values to some or all elements of an array, you can use an iteration factor with the INITIAL attribute. For example:

DECLARE TEST_AVGS (30,4) FIXED DECIMAL (5,2)

STATIC INITIAL ((120) 50);

 

This statement declares the array TEST_AVGS with 120 elements, each of which is given an initial value of 50.

You can also use the asterisk (*)iteration factor to initialize all the elements of an array to the same value. For example:

DECLARE TEST_AVGS (30,4) FIXED DECIMAL (5,2)

STATIC INITIAL ((*) 50);

 

This statement also declares the array TEST_AVGS with 120 elements, each of which is given an initial value of 50.

Although PL/I supports the initialization of automatic arrays with the INITIAL attribute, for the following reasons this is not always the most efficient way (in terms of program compilation and execution) to initialize array elements:

  • When you initialize elements in an array that has the AUTOMATIC, BASED, or CONTROLLED attribute, the compiler does not check that all elements are initialized until run time. Thus, you do not receive any compile-time checking of initialization, even if you used constants to specify the array bounds and iteration factors.
  • Your programs will run more efficiently if you initialize automatic arrays with assignment statements rather than the INITIAL attribute.

If the array is not modified by your program, you can increase program efficiency by declaring the array with the STATIC and READONLY attributes and using the INITIAL attribute to initialize its elements. In this case, the compiler checks that you have initialized all the elements and that they are valid.

 

. Specifying Elements of an Array
Iteration Factors

When more than one successive element of an array is to be assigned the same value with the INITIAL attribute, you can specify an iteration factor. An iteration factor indicates the number of times that a specified value is to be used in the assignment of values to elements of an array. You can specify an iteration factor in one of the following formats:

(iteration-factor) arithmetic-constant

(iteration-factor) scalar-reference

(iteration-factor) (scalar-expression)

(iteration-factor) *

 
iteration-factor

An unsigned decimal constant indicating the number of times the specified value is to be used in the assignment of an array element. The iteration factor can be zero.

arithmetic-constant

Any arithmetic constant whose data type is valid for conversion to the data type of the array.

scalar-reference

A reference to any scalar variable or to the NULL built-in function.

scalar-expression

Any arithmetic or string expression or string constant. The expression or constant must be enclosed in parentheses.

*

Symbol used to indicate that the corresponding array element is not to be assigned an initial value.

You can use any of these forms for arrays that have the AUTOMATIC attribute. For arrays with the STATIC attribute, you can use only constants and the NULL built-in function.

For example, the following declaration of the array SCORES initializes all elements of the array to 1:

DECLARE SCORES (100) FIXED STATIC INITIAL ((100)1);

 

The next declaration initializes the first 50 elements to 1 and the last 50 elements to -1:

DECLARE SCORES (100) FIXED STATIC INITIAL ((50)1,(50)-1);

 

The following declaration initializes the first 49 elements to 1; the next 2 elements are not initialized; and the next 49 elements are initialized to -1:

DECLARE SCORES (100) FIXED STATIC INITIAL ((49)1,(2)*,(49)-1);

 

The declaration in the next example initializes all 10 elements of an array of character strings to the 26-character value in apostrophes. The string constant is enclosed in parentheses; this is required to differentiate between iteration factors and replication factors.

DECLARE ALPHABETS (10) CHARACTER(26) STATIC

INITIAL((10)('ABCDEFGHIJKLMNOPQRSTUVWXYZ'));

 

Assigning Values to Array Variables

You can specify an array variable as the target of an assignment statement in the following cases:

array-variable = expression;

 

This is valid where the expression yields a scalar value. Every element of the array is assigned the resulting value. The array variable must be a connected array whose elements are scalar.You can use the asterisk in an assignment:

array-variable (*,...) = expression;

 

You can use a single asterisk regardless of how many dimensions an array has, or you can use an asterisk for each dimension.

Note that the arithmetic operators, such as the plus sign (+) and the minus sign (-), can have arrays as operands, if all the arrays in the assignment have the same dimensions and bounds. For example, if ARRAYA, ARRAYB and ARRAYC have the same dimensions and bounds, the following assignment is valid:

ARRAYC = ARRAYA + ARRAYB;

 

The assignment is invalid if any of the three arrays differs in dimensions or bounds.

The following assignment is valid where the specified array variables have identical data-type attributes and dimensions:

array-variable-1 = array-variable-2;

 

Each element in array-variable-1 is assigned the value of the corresponding element in array-variable-2. In this type of assignment, both arrays must be connected. The actual storage they occupy must not overlap, unless the arrays are identical.

All other specifications of an array variable as the target of an assignment statement are invalid.

Order of Assignment and Output for Multidimensional Arrays

When a multidimensional array is initialized, or when it is assigned values without references to specific elements, PL/I assigns the values in row-major order. In row-major order, the rightmost subscript varies the most rapidly. For example, an array can be declared as follows:

DECLARE TESTS (2,2,3);

 

If TESTS is specified in a GET statement or in a declaration with the INITIAL attribute, values are assigned to the elements in the following order:

TESTS (1,1,1)

TESTS (1,1,2)

TESTS (1,1,3)

TESTS (1,2,1)

TESTS (1,2,2)

TESTS (1,2,3)

TESTS (2,1,1)

TESTS (2,1,2)

TESTS (2,1,3)

TESTS (2,2,1)

TESTS (2,2,2)

TESTS (2,2,3)

When an array is output with a PUT statement, PL/I uses the same order to output the array elements. For example:

PUT LIST (TESTS);

 

This PUT statement outputs the contents of TESTS in the order previously shown.

Using GET and PUT Statements with Array Variables

When you specify an array variable name in the input-target list of a GET LIST or GET EDIT statement, elements of the array are assigned values from the data items in the input stream. For example:

DECLARE VERBS (6) CHARACTER (15) VARYING;

GET LIST (VERBS);

 

When this GET LIST statement executes, it accepts data from the default input stream. Each input field delimited by blanks, tabs, or commas is considered a separate string. The values of these strings are assigned to elements of the array VERBS in the order VERBS(1), VERBS(2), ... VERBS(6). If a multidimensional array appears in an input-target list, input data items are assigned to the array elements in row-major order.

An array can also appear, with similar effects, in the output-source list of a PUT statement.

Passing Arrays as Arguments

You can pass an array variable as an argument to another procedure. Within the invoked procedure, the corresponding parameter must be declared with the same number of dimensions. The rules for specifying the bounds in a parameter descriptor for an array parameter are as follows:

  • If you specify the bounds with integer constants, they must match exactly the bounds of the corresponding argument.
  • You can specify all bounds as asterisks (*). Then, the bounds of the array are determined from the bounds of the corresponding argument when the procedure is actually invoked. If any bound is specified as an asterisk, all bounds must be specified as asterisks.

For example:

DECLARE SCAN ENTRY ((5,5,5) FIXED,(*) FIXED),

MATRIX (5,5,5) FIXED,

OUTPUT (20) FIXED;

CALL SCAN (MATRIX,OUTPUT);

 

The procedure SCAN receives two arrays as arguments. The first is a three-dimensional array whose bounds are known. The second is a one-dimensional array whose bounds are not known. The procedure SCAN can declare these parameters as follows:

SCAN: PROCEDURE (IN,OUT);

DECLARE IN (5,5,5) FIXED,

OUT (*) FIXED;

 

An array whose storage is unconnected cannot be passed as an argument. Arrays are always passed by reference.

Built-In Functions Providing Array Dimension Information

PL/I provides the following built-in functions that return information about the dimensions of an array:

  • DIMENSION returns the number of elements in a given dimension.
  • HBOUND returns the value of the upper bound of the array in a given dimension.
  • LBOUND returns the value of the lower bound of the array in a given dimension.

For the first dimension of an array X, the relationship of these functions can be expressed as follows:

DIMENSION (X,1) = HBOUND (X,1) - LBOUND (X,1) + 1

The procedure that follows uses the HBOUND and LBOUND built-in functions:

ADDIT: PROCEDURE (X);

DECLARE X (*) FIXED BINARY,

(COUNT,I) FIXED BINARY;

 

COUNT = 0;

DO I = LBOUND (X,1) TO HBOUND(X,1);

COUNT = COUNT + 1;

X(I) = COUNT;

END;

RETURN;

END;

 

This procedure receives a one-dimensional array as a parameter and initializes the elements of the array with integral values beginning with 1.

Structures

A structure is a data aggregate consisting of one or more members. The members can be scalar data items or aggregrates. Different members can have different data types. Structures are useful when you want to group related data items having different data types.

Structure Declarations and Attributes

The declaration of a structure defines its organization and the names of members at each level in the structure. The major structure name is declared as structure level 1; minor members must be declared with level numbers greater than 1. For example:

DECLARE 1 PAYROLL,

2 NAME,

3 LAST CHARACTER(80) VARYING,

3 FIRST CHARACTER(80) VARYING,

2 SALARY FIXED DECIMAL(7,2);

 

This statement declares a structure named PAYROLL. You can access the last name with a qualified reference:

PAYROLL.NAME.LAST = 'ROOSEVELT';

 

Alternatively, because the last and first names have the same attributes, you can declare the same structure as follows:

DECLARE 1 PAYROLL,

2 NAME,

3 (LAST,FIRST) CHARACTER(80) VARYING,

2 SALARY FIXED DECIMAL(7,2);

The following additional rules apply to the specification of level numbers:

  • Level numbers must be specified with decimal integer constants.
  • A level number must be separated from its associated variable name by at least one space or tab character.
  • Level numbers after level 1 can have any integer value, as long as each level number is equal to or greater than the level number of the preceding level. (There can be only one level 1 in each structure.)
  • Each identifier in the structure must be separated from the declaration of the previous identifier by a comma.
  • Substructures at the same logical level of nesting do not have to have the same level number.
  • The deepest possible logical level is 16.
  • The largest possible level number constant is 32767.
Attributes for Structure Variables

Within a structure, you can only declare members at the lowest level of each substructure with data-type attributes. Additional rules for specifying attributes for the various components of a structure are as follows:

  • Only the following attributes are valid for the major structure:
  • AUTOMATIC

    GLOBALDEF

    STATIC

    BASED

    GLOBALREF

    STRUCTURE

    CONTROLLED

    INTERNAL

    TYPE

    DEFINED

    LIKE

    UNION

    EXTERNAL

    READONLY

     

  • You can dimension the major structure, a minor structure, or any member of the structure: that is, there can be arrays of structures and structures whose members are arrays.
  • Member names cannot have any of the attributes a major structure can have except for INTERNAL and UNION attributes. You can use the UNION attribute on any member with a level number.
  • If a structure has the STATIC attribute, the extents of all members (lengths for character- and bit-string variables, dimensions for array variables, and area extents) must be specified with optionally signed decimal integer constants.

Using The UNION Attribute On Structure Declarations

A union is a variation of a structure in which all immediate members occupy the same storage. The UNION attribute (which must be associated with a level number in a structure declaration) declares a union. All immediate members of the union -- that is, all members having a logical level number one higher -- occupy the same storage. A reference to one member of a union refers to storage occupied by all members of the union. Therefore, a union provides a convenient way to look at a large entity (such as a character string or a bit mask) as a series of smaller entities (such as component character strings or individual flag bits).

A variable declared with the UNION attribute must be a major or minor structure. All members of a union must have a constant size (see See for format and details).

The UNION attribute is not part of the PL/I General-Purpose Subset; it is provided inKednos PL/I for UNIX to give users convenient access to data as it is internally represented. Potential applications of unions might depend on the internal representation of data, and would therefore not be transportable between this and other UNIX systems. The following example shows unions:

DECLARE 1 CUSTOMER_INFO,

2 PHONE_DATA UNION,

3 PHONE_NUMBER CHARACTER (13),

3 COMPONENTS,

4 LEFT_PAREN CHARACTER (1),

4 AREA_CODE CHARACTER (3),

4 RIGHT_PAREN CHARACTER (1),

4 EXCHANGE CHARACTER (3),

4 HYPHEN CHARACTER (1),

4 SPECIFIC_NUMBER CHARACTER (4),

2 ADDRESS_DATA,

 

The UNION attribute associated with the declaration of PHONE_DATA signifies that PHONE_DATA's immediate members (PHONE_NUMBER and COMPONENTS) occupy the same storage. Any modification of PHONE_NUMBER also modifies one or more members of COMPONENTS; conversely, modification of a member of COMPONENTS also modifies PHONE_NUMBER. Note, however, that the UNION attribute does not apply to the members of COMPONENTS because they are not immediate members of PHONE_DATA. The members of COMPONENTS occupy separate storage in the normal fashion for structure members.

The DEFINED attribute is a more portable method of mapping one variable onto the storage of another variable (see See Defined Variables for more information).

Initializing Structures

You can initialize a structure by giving the INITIAL attribute to its members. Not all members need be initialized. For example:

DECLARE 1 COUNTS,

2 FIRST FIXED BIN(15) INITIAL(0),

2 SECOND FIXED BIN(15),

2 THIRD (5) FIXED BIN(15) INITIAL (5(1));

 

The first and third members of the structure COUNTS are initialized.

The INITIAL attribute cannot be applied, however, to a major or a minor structure name.

In a union, the same data can only be initialized once.

Using Structure Variables in Expressions

You can specify the name of a major or minor structure in an assignment statement only if the source expression and the target variable are identical in size and structure, and all corresponding members have the same data types.

Passing Structure Variables as Arguments

You can pass a structure variable as an argument to another procedure. The relative structuring of the structure variable specified as the argument and the corresponding parameter must be the same. The level numbers do not have to be identical. The following example shows the parameter descriptor for a structure variable:

DECLARE SEND_REC ENTRY (1,

2 FIXED BINARY(31),

2 CHARACTER(40),

2 FIXED DECIMAL (5,2));

 

The written argument in the invocation of the external procedure SEND_REC must have the same structure, and its corresponding members must have the same data types.

When structures are passed as arguments, they must match the corresponding parameters. They cannot be passed by dummy argument.

Member Attributes

PL/I supports three member attributes, so named because they apply specifically to the declaration of structure members rather than to the structure as a whole. The member attributes are as follows:

  • The TYPE attribute
  • The LIKE attribute
  • The REFER option

The TYPE and LIKE attributes can be applied to structures, but are most often applied to structure members. Each is discussed in detail in the following sections.

Using the TYPE Attribute

The TYPE attribute copies a scalar, array, or member declaration in a major or minor structure into another scalar, array, or structure variable respectively. The TYPE attribute copies the attributes to the target variable. For structures, the TYPE attribute also copies the logical structuring and member declarations from the major or minor structure to the target variable.

TYPE does not copy any storage class or INITIAL attributes or dimensioning (except for dimensioning that is applied to arrays and members) from scalars, arrays, or structures.

Note that the TYPE attribute is a superset of the LIKE attribute. The TYPE attribute is identical to the LIKE attribute when it is used to copy a member declaration in a major or minor structure declaration into another structure variable.

An identifier names the variable to which the declarations for the reference are copied. The reference is the name of a scalar, an array, or a major or minor structure known to the current block. For structures, the identifier must be preceded by a level number. Any attributes that can be used with a structure variable at that level can be used with the identifier. For example, a major structure can specify a storage class and dimensions, and a minor structure can specify dimensions. The following example shows the TYPE attribute:

DECLARE NO_OF_SINGLE_ROOMS FIXED BINARY(31);

DECLARE NO_OF_DOUBLE_ROOMS TYPE (NO_OF_SINGLE_ROOMS);

 

In the previous example, the declaration of NO_OF_DOUBLE_ROOMS uses the TYPE attribute to create a declaration that duplicates the attributes of NO_OF_SINGLE_ROOMS. The parentheses around NO_OF_SINGLE_ROOMS are optional.

The declaration of NO_OF_DOUBLE_ROOMS is equivalent to the following:

DECLARE NO_OF_DOUBLE_ROOMS FIXED BINARY(31);

 

In the next example, the declaration uses the TYPE attribute to create the declaration that duplicates the attributes of BED_SERIAL_NOS:

DECLARE BED_SERIAL_NOS((NO_OF_SINGLE_ROOMS +

NO_OF_DOUBLE_ROOMS),2)

CHARACTER(12);

DECLARE TABLE_SERIAL_NOS TYPE(BED_SERIAL_NOS);

 

The declaration of TABLE_SERIAL_NOS in the previous example is equivalent to the following:

DECLARE TABLE_SERIAL_NOS((NO_OF_SINGLE_ROOMS +

NO_OF_DOUBLE_ROOMS),2)

CHARACTER(12);

In the following example, the declaration of NEW_RESER uses the TYPE attribute to create a set of member declarations that duplicate those in RES_DATA:

DECLARE 1 RES_DATA BASED (RPTR),

2 DATE CHARACTER(8),

2 HOTEL_CODE CHARACTER(3),

2 PARTY_NAME,

3 LAST CHARACTER(20),

3 FIRST CHARACTER(10),

2 STAY FIXED BIN(7),

1 NEW_RESER TYPE(RES_DATA);

 

ALLOCATE RES_DATA SET (RPTR);

GET LIST (NEW_RESER.DATE,NEW_RESER.HOTEL_CODE);

RES_DATA = NEW_RESER;

 

The declaration of NEW_RESER in the previous example is equivalent to the following:

DECLARE 1 NEW_RESER,

2 DATE CHARACTER(8),

2 HOTEL_CODE CHARACTER(3),

2 PARTY_NAME,

3 LAST CHARACTER(20),

3 FIRST CHARACTER(10),

2 STAY FIXED BINARY(7);

 

In the previous example, the members of NEW_RESER are assigned data after that data is validated; the entire contents of NEW_RESER are assigned to RES_DATA. This assignment is possible because the two structures are identical as a result of using the TYPE attribute.

You can use the TYPE attribute to copy a minor structure to a major structure and vice versa. You need not match either the level numbers or the logical levels. For example:

DECLARE 1 PARTY_NAME,

2 LAST CHAR(20),

2 FIRST CHAR(10);

 

Given the preceding declaration, the following declarations are the same:

DECLARE 1 SPOUSE_NAME TYPE(PARTY_NAME);

DECLARE 1 SPOUSE_NAME,

2 LAST CHAR(20),

2 FIRST CHAR(10);

 

You can also apply dimensions or, for a major structure, storage-class attributes to a structure variable declared with the TYPE attribute, as follows:

DECLARE 1 KID_NAMES (10) TYPE(PARTY_NAME);

 

Or, you can use:

DECLARE 1 DAILY_DATA,

2 DATE CHAR(8),

2 TODAYS_RESERS (NO_OF_RES) TYPE(RES_DATA);

Using the LIKE Attribute

The LIKE attribute copies the member declarations in a major or minor structure declaration into another structure variable. It copies the logical structuring and member declarations from the major or minor structure to the target variable, but does not copy any storage-class attributes or dimensioning (except for dimensioning that is applied to members).

An identifier names the variable to which the declarations in the reference are copied. The reference is the name of a major or minor structure known to the current block. The identifier must be preceded by a level number. Any attributes that can be used with a structure variable at that level can be used with the identifier; for example, a major structure can specify a storage class and dimensions, and a minor structure can specify dimensions.

The following example shows the LIKE attribute:

DECLARE 1 RES_DATA BASED (RPTR),

2 DATE CHARACTER(8),

2 HOTEL_CODE CHARACTER(3),

2 PARTY_NAME,

3 LAST CHARACTER(20),

3 FIRST CHARACTER(10),

2 STAY FIXED BIN(7),

1 NEW_RESER LIKE RES_DATA,

GET LIST (NEW_RESER.DATE,NEW_RESER.HOTEL_CODE);

RES_DATA = NEW_RESER;

 

In the previous example, the declaration of NEW_RESER uses the LIKE attribute to create a set of member declarations that duplicate those in RES_DATA. The declaration of NEW_RESER is equivalent to the following:

DECLARE 1 NEW_RESER,

2 DATE CHARACTER(8),

2 HOTEL_CODE CHARACTER(3),

2 PARTY_NAME,

3 LAST CHARACTER(20),

3 FIRST CHARACTER(10),

2 STAY FIXED BINARY(7);

 

In the previous example, the members of NEW_RESER are assigned data after that data is validated, the entire contents of NEW_RESER are assigned to RES_DATA. This assignment is possible because the two structures are identical as a result of using of the LIKE attribute.

You can use the LIKE attribute to copy a minor structure to a major structure and vice versa; neither the level numbers nor the logical levels must match. For example:

DECLARE 1 SPOUSE_NAME LIKE PARTY_NAME;

 

Given the declarations in the preceding example, this declaration is equivalent to the following:

DECLARE 1 SPOUSE_NAME,

2 LAST CHAR(20),

2 FIRST CHAR(10);

 

You can also apply dimensions or, for a major structure, storage-class attributes to a structure variable declared with the LIKE attribute:

DECLARE 1 KID_NAMES (10) LIKE PARTY_NAME;

or:

DECLARE 1 DAILY_DATA,

2 DATE CHAR(8),

2 TODAYS_RESERS (NO_OF_RES) LIKE RES_DATA;

You can also place the parentheses as follows:

DECLARE 1 KID_NAMES (10 LIKE PARTY_NAME);

 

Using the REFER Option

Use the REFER option to create self-defining based structures. In a based structure, the value of one member is used to determine the size of the storage space allocated for another member of the same structure. You can use the REFER option in a DECLARE statement to specify array bounds, the length of a BIT or CHARACTER string, or the size of an area.

The format of the REFER option is as follows:

refer-element REFER (refer-object-reference)

 
refer-element

An expression that represents the value assigned to the refer object when the structure is allocated. The refer element must satisfy the following conditions:

  • It must be an expression that produces a FIXED BINARY(31) value or a value that can be converted to FIXED BINARY (31).
  • It cannot reference storage in the structure containing the refer element.
refer-object-reference

A reference to a scalar variable. The refer object reference must satisfy the following conditions:

  • It cannot be a subscripted variable reference.
  • It cannot be locator qualified.
  • It must reference a refer object that is a previous member of the structure containing the REFER option.

The refer object is a scalar variable contained by the structure. The refer object must satisfy the following conditions:

  • It must be a previous member of the structure containing the REFER option, which references the refer object.
  • It must be scalar; it cannot be dimensioned or a dimensioned array.
  • It must have a computational data type.

An example of a structure declaration containing the REFER option is as follows:

DECLARE 1 STRUCTURE_S BASED(P),

2 I FIXED BINARY(31),

2 A CHARACTER(20 REFER(I));

 

For the compiler to allocate storage for a based structure, the structure must have a known size. In the example, the initial length for A is taken from the refer element, 20. However, the REFER option permits the size of the structure to change at run time as the value of the refer object (I) After allocation, the length of A is determined by I.

You can have multiple REFER options within a structure.

The following example and figures show storage mapping with the REFER option.

DECLARE 1 S BASED (POINTER),

2 I FIXED BINARY(15),

2 J FIXED BINARY(15),

2 A CHARACTER ((X*2+2) REFER(I)),

2 B(2) CHARACTER (Y REFER(J));

 

X = 5;

Y = 10;

 

ALLOCATE S;

 

S.A = 'ABCDEFGHIJKL';

S.B(1) = '0123456789';

S.B(2) = 'NOW IS THE';

END;

When this structure is allocated, the refer elements (X*2+2) and Y are evaluated and used to determine the length of the associated string. The evaluated refer element value (X*2+2) is assigned to the refer object I and Y is assigned to J. Thereafter, the sizes of strings A and B are determined by the value of the refer objects I and J.

Storage for the previous structure is shown in See . Storage of Structure with REFER Option .

. Storage of Structure with REFER Option

If the refer object I is assigned the value 6 and the refer object J is assigned the value 4, the resulting storage is remapped as shown in See . Remapped Storage of Structure with REFER Option .

. Remapped Storage of Structure with REFER Option
  • PL/I does not restrict the use of the REFER option within structure declarations: therefore, exercise caution in its use.

If you change a value that causes the size of one or more structure members to decrease, then some storage at the end of the allocated storage will become inaccessible for future reference.

If the scalar variable (the refer object) does not satisfy the following criteria, the results are undefined:

  • It must not be assigned a value that is less than 0 or greater than the refer element value used for structure allocation.
  • It must have the value used for allocation, if the structure is freed.

The following rules apply to structures containing the REFER option:

  • A structure containing the REFER option cannot be the target of a LIKE reference.
  • When a based structure is allocated, the order in which the refer elements are selected for evaluation is undefined.
  • When a based structure is allocated, the order in which the refer objects are selected for initialization is undefined.

Structure-Qualified References

To refer to a structure in a program, you use the major structure name, minor structure names, and individual member names. Member names need not be unique even within the same structure. To refer to the name of a member or minor structure, you must ensure only that the reference uniquely identifies it. You can qualify the variable name by preceding it with the name or names of higher-level (lower-numbered) variables in the structure; names in this format, called a qualified reference, must be separated by periods (.).

The following sample structure definition shows the rules for identifying names of variables within structures:

DECLARE 1 STATE,

2 NAME CHARACTER (20),

2 POPULATION FIXED BINARY (10),

2 CAPITAL,

3 NAME CHARACTER (30),

3 POPULATION FIXED BINARY (10),

2 SYMBOLS,

3 FLOWER CHARACTER (20),

3 BIRD CHARACTER (20);

 

The rules for selecting and specifying variable names for structures are as follows:

  • The name of the major structure is subject to the rules for the scope of variables in a program.
  • You can qualify the name of any minor structure or member in a structure by the names of higher-level members in the structure. You must specify the variable names from left to right in order of increasing level numbers and separated by periods. The members of the previous sample, completely qualified, are as follows:

STATE.NAME

STATE.POPULATION

STATE.CAPITAL.NAME

STATE.CAPITAL.POPULATION

STATE.SYMBOLS.FLOWER

STATE.SYMBOLS.BIRD

  • Names of minor structures or members within structures do not have to be qualified if they are unique within the scope of the name. The following names in the sample structure can be referred to without qualification (so long as there are no other variables with these names):

CAPITAL

SYMBOLS

FLOWER

BIRD

  • You can omit intermediate qualification names if the reference remains unambiguous. The following references to members in the sample structure are valid:

STATE.FLOWER

STATE.BIRD

If a name is ambiguous, the compiler cannot resolve the reference and issues a message. In the example, the names POPULATION and NAME are ambiguous.

You can specify the name of a major or minor structure in an assignment statement only if the source expression and the target variable are identical in size and structure, and all corresponding members have the same data types.

Arrays of Structures

An array of structures is an array whose elements are structures. Each structure has identical logical levels, minor structure names, and member names and attributes. For example, a structure STATE can be declared an array:

DECLARE 1 STATE (50),

2 NAME CHARACTER (20) VARYING,

2 POPULATION FIXED BINARY (31),

2 CAPITAL,

3 NAME CHARACTER (30) VARYING,

3 POPULATION FIXED BINARY (31),

2 SYMBOLS,

3 FLOWER CHARACTER (20),

3 BIRD CHARACTER (20);

 

A member of a structure that is an array inherits the dimensions of the structure. For example, the member CAPITAL.NAME of the structure STATE inherits the dimension 50. You must use a subscript whenever you refer to the variable CAPITAL.NAME, as in the following example:

PUT LIST (CAPITAL.NAME(I)) ;

 

A subscript for a member of a structure that is an array element can appear following any name within a qualified reference. For example, all of these references are equivalent:

STATE(10).CAPITAL.NAME

STATE.CAPITAL(10).NAME

STATE.CAPITAL.NAME(10)

 

Arrays of Structures that Contain Arrays

A structure that is defined with a dimension can have members that are arrays. For example:

DECLARE 1 STATE (50),

2 AVERAGE_TEMPS(12) FIXED DECIMAL (5,2),

 

In this example, the elements of the array STATE are structures. At the second level of the hierarchy of each structure, AVERAGE_TEMPS is an array of 12 elements. Because AVERAGE_TEMPS inherits the dimension of STATE, any of AVERAGE_TEMPS's elements must be referred to by two subscripts:

  • The first subscript references an element in STATE
  • The second subscript references an element in AVERAGE_TEMPS

These subscripts can appear following any name in the qualified reference. For example:

STATE(3).AVERAGE_TEMPS(4)

STATE.AVERAGE_TEMPS(3,4)

 

These references are equivalent.

Note the following rules for specifying subscripts for members of structures containing arrays:

  • The number of subscripts specified for any member must include any dimensions inherited from a major or minor structure declaration, as well as those specified for the member itself.
  • The subscripts that refer to a member of a structure in an array do not have to follow immediately the name to which they apply. However, the order of subscripts must be preserved.
  • The total number of dimensions, including the inherited dimensions, must not exceed eight.

Connected and Unconnected Arrays

A connected array is one whose elements occupy consecutive locations in storage. For example:

DECLARE NEWSPAPERS (10) CHARACTER (30);

 

In storage, the 10 elements of the array NEWSPAPERS occupy 10 consecutive 30-byte units. Thus, NEWSPAPERS is a connected array.

A connected array is valid as the target of an assignment statement, as long as the source expression is a similarly dimensioned array or a single scalar value. The top diagram in See . Connected and Unconnected Arrays shows the storage of a connected array.

In an unconnected array, the elements do not occupy consecutive storage locations. The bottom diagram in See . Connected and Unconnected Arrays shows the storage of an unconnected array. An unconnected array is not valid in an assignment statement or as the source or target of a record I/O statement. A structure with the dimension attribute always results in unconnected arrays. When a structure is dimensioned, each member of the structure inherits the dimensions of the structure and becomes, in effect, an array. For example:

DECLARE 1 STATE (50),

2 NAME CHARACTER (20) VARYING,

2 POPULATION FIXED BINARY (31);

 

In this example, the members NAME and POPULATION of the major structure STATE inherit the dimension 50 from the major structure. When PL/I allocates storage for a structure or a dimensioned structure, each member is allocated consecutive storage locations; thus, the elements of the arrays NAME and POPULATION are not connected.

 

. Connected and Unconnected Arrays

Internal Representation of Aggregate Data

Structures can be unaligned or naturally aligned. When a structure is unaligned, each of its members (except for unaligned bit string members) is aligned on a byte boundary. Unaligned bit-string members are bit aligned. In an array of unaligned structures (which contain members other than unaligned bit strings), each structure is aligned on a byte boundary. In an array of unaligned structures that contain only unaligned bit strings, the array elements are bit aligned.

When a structure is naturally aligned, each of its members is aligned as described in See . Natural Alignment for Structure Members . In an array of naturally aligned structures, each structure is aligned on the boundary that is the maximum alignment of its members.

The alignment you select is determined by the compile-time /NOALIGN or /ALIGN switch. The /NOALIGN switch (the default) produces unaligned structures. The /ALIGN switch produces aligned structures as described in See . Natural Alignment for Structure Members .

 

. Natural Alignment for Structure Members

Data Type

Precision

Alignment

FIXED BINARY(p)

p <= 7

byte

FIXED BINARY(p)

7 < p <= 15

word

FIXED BINARY(p)

p > 15

longword

FIXED DECIMAL(p,q)

 

word

FLOAT BINARY(p)

p <= 24

longword

FLOAT BINARY(p)

24 < p <= 53

quadword

FLOAT BINARY(p)

p > 53

octaword

FLOAT DECIMAL(p)

p <= 7

longword

FLOAT DECIMAL(p)

7 < p <= 15

quadword

FLOAT DECIMAL(p)

p > 15

octaword

CHAR (UNALIGNED)

 

byte

CHAR ALIGNED BYTE

 

byte

CHAR VARYING

 

word

BIT (UNALIGNED)

 

bit

BIT ALIGNED

 

longword

POINTER

 

longword

LABEL

 

quadword

ENTRY

 

quadword

FILE

 

longword

STRUCTURE

 

maximum of members

PICTURE

 

byte

OFFSET

 

longword

 

 

Storage Classes

The storage class to which a variable belongs determines whether PL/I allocates its storage at compile time or dynamically at run time. This chapter describes the following classes of variables:

See Dynamically Allocated Variables describes the mechanisms for dynamically allocating storage. See Storage Sharing describes how variables can share physical storage locations.

Automatic Variables

The default storage-class attribute for PL/I variables is AUTOMATIC. PL/I does not allocate storage for an automatic variable until the block that declares it is activated. When the block is deactivated the storage is released. For example:

CALC: BEGIN;

DECLARE TEMP FIXED BINARY (31);

END;

 

Each time the block labeled CALC is activated, storage is allocated for the variable TEMP. When the END statement is executed, the block is deactivated, and all storage for TEMP and all other automatic variables is released. The value of TEMP becomes undefined.

The storage requirements of an automatic variable are evaluated each time the block is activated. Thus, you can specify the length of an automatic character-string variable as follows:

DECLARE STRING_LENGTH FIXED;

COPY: BEGIN;

DECLARE TEXT CHARACTER(STRING_LENGTH);

END;

 

When this begin block is activated, the length of TEXT is evaluated. The variable is allocated storage depending on the value of STRING_LENGTH, which must have a valid value.

Static Variables

A static variable is allocated storage when the program is activated and exists for the duration of the program. A variable has the static attribute if you declare it with any of the attributes STATIC, EXTERNAL, GLOBALDEF, or GLOBALREF. In declaring static arrays and strings, you must use restricted expressions. (Note that the EXTERNAL scope attribute implies static storage for variables.)

If a block that declares a static variable is entered more than once during the execution of the program, the value of the static variable remains valid. For example:

UNIQUE_ID: PROCEDURE RETURNS (FIXED BINARY(31));

DECLARE ID STATIC INTERNAL FIXED INITIAL (0);

ID = ID + 1; /* Increment ID */

RETURN (ID);

END;

 

The function UNIQUE_ID declares the variable ID with the STATIC attribute and specifies an initial value of 0 for it. The variable is initialized to this value when the program is activated. The storage for the variable is preserved, and the function returns a different integer value each time it is referenced.

A variable with the STATIC attribute can also have external scope; that is, its definition and value can be accessed by any other procedure that declares it with the STATIC and EXTERNAL attributes.

Internal Variables

An internal variable is known only within the block in which it is defined and within all contained blocks. By default, PL/I gives all variables the INTERNAL attribute with the exception of data with the FILE and CONDITION attributes.

External Variables

An external variable provides a way for external procedures to share common data. All declarations that refer to an external variable must also declare it with the EXTERNAL attribute (or with an attribute that implies EXTERNAL) and with identical data type attributes. You can abbreviate the EXTERNAL keyword to EXT. The following example and See . External Variables show how procedures can use external variables:

 

APPLIC: PROCEDURE OPTIONS (MAIN);

DECLARE FLAGS BIT (64) ALIGNED EXTERNAL;

CALL READY;

READY: PROCEDURE;

DECLARE FLAGS BIT (64) ALIGNED EXTERNAL;

 

. External Variables

Further control is provided by the VALUE attribute, which can be used in conjunction with GLOBALDEF and GLOBALREF. A variable declared in this way is a constant whose value is used immediately in instructions generated by the compiler.

The EXTERNAL attribute is implied by the FILE, GLOBALDEF, GLOBALREF, and CONDITION attributes, and also by declarations of entry constants (that is, declarations that contain the ENTRY attribute but not the VARIABLE attribute). For variables, the EXTERNAL attribute implies the STATIC attribute.

The following rules apply to the use of external names:

  • The EXTERNAL attribute directly conflicts with the AUTOMATIC, BASED, DEFINED, and INTERNAL attributes.
  • You cannot apply the EXTERNAL attribute to minor structures, members of structures, parameters, or descriptions in an ENTRY or RETURNS attribute.
  • The EXTERNAL attribute is invalid for variables that are the parameters of a procedure.
  • If you declare a variable as EXTERNAL STATIC INITIAL, you must initialize the variable with the same value in all blocks that declare the variable.
  • If you declare a file constant or file variable explicitly or implicitly as EXTERNAL, you must use identical attributes, including ENVIRONMENT attributes, in all blocks that declare the file.

Based Variables

A based variable is a variable that describes a data type associated with storage that will be accessed through a pointer or offset value. PL/I does not allocate any storage for a based variable. Instead, you must explicitly allocate storage.

When you declare a based variable, you provide PL/I with a description of the data to be accessed by the variable. The actual data must be referenced by a pointer that contains the address of the data storage location. (See See BASED Attribute for more information.) For example:

DECLARE BUFFER CHARACTER(80) BASED (BUF_PTR),

LINE CHARACTER(80),

BUF_PTR POINTER;

BUF_PTR = ADDR(LINE);

 

The declaration of BUFFER does not allocate any storage. PL/I associates the declaration of the variable with the pointer variable BUF_PTR. During program execution, BUF_PTR is set to the location (address) in storage of the variable LINE by means of the ADDR built-in function. This effectively associates the description of BUFFER with the actual data value of LINE.

You can associate a based variable with a storage location by using the ADDR built-in function, as in the preceding example; by using the ALLOCATE statement; by using a locator-qualified reference to the based variable; by using the SET option of the READ statement; or by explicit allocation within an area.

The following sections cover these topics:

Data Types Used with Based Variables

The data types most commonly associated with based variables are pointers, areas, and offsets.

A pointer is a variable whose value represents the location in memory of another variable or data item. Pointers are used to access based variables and buffers allocated by the system as a result of the SET option of the READ and ALLOCATE statements.

Areas are regions of storage in which based variables can be allocated and freed. The use of areas can simplify and speed operations involving large or numerous based variables.

An offset is a value indicating the location of a based variable relative to the beginning of an area.

Allocation in Areas

PL/I supports storage management in areas (see See Area Data for more information). If you use the ALLOCATE statement with an area (either implied or explicitly specified), you can cause the allocation of storage to be performed in that area, instead of in the general memory pool for based and controlled storage.

Storage management in areas has a number of uses, including the following:

  • To allow an area to be moved to different addresses without invalidating its data.
  • To allocate storage that can be freed all at once with low overhead, by allocating variables in an area and then emptying the areas with the EMPTY built-in function rather than freeing the generations one at a time.
  • To allocate storage that can be rolled back, by allocating variables in an area and making periodic assignment of the area to a backup area.

If it is found that some operations need to be rolled back, the backup area can then be copied back into the current area (or they can be swapped). Note that when areas are assigned to each other, all offsets into the old area are valid for the new area as well.

To allocate storage in areas, use the IN and SET options on the ALLOCATE statement, the AREA and OFFSET data attributes, and the EMPTY built-in function.

The IN option on the ALLOCATE statement takes a reference to an area. If the IN option is not specified, the area is implied from the SET option if the SET option specifies an offset variable with a base area. The SET option itself can be implied from the base variable. Whether an area is specified explicitly or implied, the allocation is performed in that area instead of in the available memory pool for based and controlled storage. If an error is detected in the process, the AREA condition is raised.

Kednos PL/I for UNIX provides full support for allocation in areas as specified in the ANSI full PL/I language standard. In addition, it provides extensions to full PL/I, which enhance the usefulness of areas or provide for improved compatibility with other implementations of PL/I. These extensions are as follows:

  • Area control information is stored in the form of offsets so that an area can be moved to different addresses and still be correct (see See Offset Data for more information). As a result, you can assign areas as members of structures as long as their extents are identical. Note, however, that if such an assignment is performed, the entire area will be copied rather than just the extent. The position independence of the area control information also allows an area to be written to secondary storage and retrieved by another program at a different address. You must ensure that any data allocated in the area is position independent, by restricting locator values stored in the area to offsets specifying that area as a base.
  • You can assign areas of differing sizes to each other directly (that is, not as members of structures). The AREA condition will be raised if the target area is not large enough to hold the extent of the source area.
  • If you transmit an area by itself (as opposed to a member of an aggregate) with a WRITE or REWRITE statement, only the current extent of the area is transmitted (as in the case of varying-length character strings). You can transmit the entire area by using the SCALARVARYING ENVIRONMENT option.
  • The base area in an ALLOCATE statement need not match the base area of the offset. However, if they do match, then one area must contain the other.
  • A normal return from an AREA condition due to a full area during an allocation attempt will result in another allocation attempt. An infinite loop will occur if the problem is not corrected, because the area reference is not reevaluated before the retry is attempted after a normal return. The ON-unit must correct the condition by deallocating storage in the area, or by using the EMPTY built-in function.
  • The control information for an area is stored inside the area. The control information occupies at least 24 to 31 bytes for header information, plus space for linking unused portions of the area. The number of links needed to link unused portions of the area depends on how fragmented the area is. As a result, there are slightly fewer bytes available for the allocation of user variables in an area than the number of bytes the area is declared with.
  • Area variables are not initially empty. They must be explicitly initialized. For example:

A = EMPTY();

 

The initialization can be in an INITIAL clause of the declaration; for example:

DECLARE A AREA(100) STATIC INITIAL(EMPTY());

 

In both examples, the EMPTY built-in function returns an empty area value.

Note that the last three items in this list are features that differ in some other implementations of PL/I.

For examples showing allocation in areas, see See Examples of Based Variables .

Referring to Based Variables

A reference to a based variable (except in an ALLOCATE statement) must specify a pointer or offset reference designating the storage to be accessed. This qualifying pointer or offset reference can be implicit, if it is specified with the BASED attribute, or explicit, if the based variable reference is prefixed with a locator qualifier. A complete based variable reference (with the locator qualifier) has the following form:

qualifying-reference -> based-reference

 

Whether explicit or implicit, the qualifying reference must be to a pointer variable, a pointer-valued function, or an offset variable declared with a base area. The qualifying reference is evaluated each time the complete reference is evaluated and must yield a valid pointer value. If the qualifying reference is to an offset variable, the offset value is converted to a pointer using the base area specified in the offset variable's declaration.

You can use both implicit and explicit qualifications with the same based variable; the explicit qualifier overrides the implicit one. For example:

DECLARE X FIXED BIN BASED(P),

P POINTER,

(A,B) FIXED BIN;

P = ADDR(A);

X = ADDR(B)->X;

 

In the second assignment statement, the reference to X on the left-hand side of the assignment has the implicit qualifier P, which is the address of the variable A. The reference to X on the right-hand side is explicitly qualified with the address of another variable, B. This assigns the value of B to the variable A.

In PL/I, you can obtain a valid pointer value in any of the following ways:

  • Through the SET option of the ALLOCATE statement
  • From a user-provided storage allocation routine
  • Through the SET option of the READ statement
  • From applying the ADDR built-in function to an addressable variable
  • By converting an offset value to a pointer value

A pointer value is valid only as long as the storage to which it applies remains allocated. Moreover, a pointer obtained by the application of ADDR to a parameter or an automatic variable is valid only as long as the parameter's procedure invocation exists, even though the storage pointed to may exist longer.

The NULL built-in function returns a null pointer value that can be assigned to pointer and offset variables, but that is not valid for qualifying a based variable reference.

Based Variables and Dynamic Storage Allocation

These subsections discuss the dynamic allocation of storage by the ALLOCATE statement and the READ SET statement.

Using the ALLOCATE Statement

Each time it is executed, the ALLOCATE statement allocates storage for a based variable and, optionally, sets a pointer or offset variable to the location of the storage in memory. The storage allocated can also be assigned values if the variable is declared with the INITIAL attribute. For example:

DECLARE LIST (10) FIXED BINARY BASED,

(LIST_PTR_A, LIST_PTR_B) POINTER;

 

ALLOCATE LIST SET (LIST_PTR_A); À

ALLOCATE LIST SET (LIST_PTR_B); Ã

 

LIST_PTR_A -> LIST(1) = 10; Õ

LIST_PTR_B -> LIST(1) = 15;

 

As you can see in this example and See . Using the ALLOCATE Statement , the array LIST is declared with the BASED attribute; however, the declaration does not reserve storage for this variable. Instead, the ALLOCATE statements allocate storage for the variable and set the pointers LIST_PTR_A and LIST_PTR_B to the storage locations. LIST_PTR_A and LIST_PTR_B must both be declared with the POINTER attribute.

In references, the different allocations of LIST can then be distinguished (unless the pointers are assigned new values) by locator qualifiers that identify the specific allocation of LIST.

The phrase LIST_PTR_A-> is a locator qualifier; it specifies the pointer that locates an allocation of storage for the variable. In this example, the first element of the storage pointed to by LIST_PTR_A is assigned the value 10. The first element of the storage pointed to by LIST_PTR_B is assigned the value 15.

Any extent expressions in the based variable declaration are evaluated each time the variable is allocated or referenced. Therefore, based variables can be used for data aggregates whose size depends on input data.

 
. Using the ALLOCATE Statement

Here is an example of dynamically allocating a matrix that will be accessed by several external procedures:

DECLARE 1 MATRIX_CONTROL_BLOCK STATIC EXTERNAL,

2 MATRIX_POINTER POINTER,

2 (ROW_SIZE,COL_SIZE) FIXED BINARY(15);

 

DECLARE 1 MATRIX(ROW_SIZE,COL_SIZE) FIXED BINARY(15)

BASED(MATRIX_POINTER);

 

GET LIST(ROW_SIZE,COL_SIZE);

ALLOCATE MATRIX;

 

The SET Option of the READ Statement

When you use the READ statement with a based variable, you do not have to define storage areas within your program to buffer records for I/O operations. If you specify the SET option on the READ statement, the READ statement places an input record in a system buffer and sets a pointer variable to the location of this buffer. For example:

DECLARE REC_PTR POINTER,

NEW_BALANCE FIXED DECIMAL (6,2),

INFILE FILE RECORD INPUT SEQUENTIAL;

DECLARE 1 RECORD_LAYOUT BASED (REC_PTR),

2 NAME CHARACTER (15),

2 BALANCE FIXED DECIMAL (6,2);

 

READ FILE (INFILE) SET (REC_PTR) ;

 

REC_PTR->BALANCE = NEW_BALANCE;

REWRITE FILE (INFILE);

 

In this example, the structure defined to describe the records in a file is declared with the BASED attribute; the declaration does not reserve storage for this structure. When the READ statement is executed, the record is read into a system buffer and the pointer REC_PTR is set to its location.

When you use the SET option with the READ statement, a subsequent REWRITE statement need not specify the record to be rewritten. PL/I rewrites the record indicated by the pointer variable specified in the READ statement.

See . Using the READ Statement with a Based Variable shows this example.

. Using the READ Statement with a Based Variable

Using the ADDR Built-in Function

The ADDR built-in function returns the storage location of a variable. You can use it to associate the storage occupied by a variable with the description of a based variable. For example:

DECLARE A FIXED BINARY BASED (X),

B FIXED BINARY,

X POINTER;

X = ADDR (B);

A = 15;

 

In this example, the variable A is declared as a based variable, with X designated as its pointer. The variable B is an automatic variable; PL/I allocates storage for B when the block is activated. When the ADDR built-in function is referenced, it returns the location in storage of the variable B, and the assignment statement gives this value to the pointer X. This assignment associates the variable A with the storage occupied by B. Because A is based on X and X points to B, an assignment statement that gives a value to A actually modifies the storage occupied by the variable B. See . Using the ADDR Built-In Function shows this example.

 
. Using the ADDR Built-In Function

Data-Type Matching for Based Variables

In most applications, the data type of a based variable reference is identical to the data type under which the accessed storage is allocated. However, it is not required that the data types be identical. The following sections discuss type-matching criteria in more detail.

Matching by Overlay Defining

Matching by overlay defining is in effect if the based variable reference and the variable for which the storage was originally allocated are both suitable for character-string or bit- string overlay defining. The only further restriction is that the size n (in characters or bits) of the based variable reference must be less than or equal to the size in characters or bits of the original variable. The based variable reference accesses the first n characters or bits of the storage.

The first program in See Examples of Based Variables shows this type of matching. The structure members JOB_RECORD.DEPT_CODE (a character string of length 3) plus JOB_RECORD.JOB_CODE (a character string of length 6) and HEALTH_RECORD.EXAM DATE (a character string of length 9) are not identical. However, since they occupy the same total storage and are all stored as character strings, they meet the criteria for string overlay defining and for data-type matching.

Matching by Left-to-Right Equivalence

Matching by left-to-right equivalence applies to structured variables that are identical up to a certain point. To see if this applies, examine the declaration of the based variable, and consider only the portion on the left that includes the referenced member and all of the level-2 substructure containing the referenced member (if the member is not itself at level 2). If the original variable's declaration has a similar left part with identical data type, then the based variable reference and the original reference match. For example:

DECLARE 1 S1 BASED (P),

2 X,

3 (A,B) FIXED BIN,

2 Y,

3 C CHAR(10),

3 D(5) FLOAT;

 

DECLARE 1 S2 BASED(P),

2 X,

3 (A,B) FIXED BIN,

2 Y,

3 C CHAR(10),

3 E BIT(32);

 

ALLOCATE S1;

 

S2.A = 3; /* valid l-to-r match */

S2.C = 'X'; /* INVALID */

 

In the first assignment, S2.A is a valid reference because S1 and S2 match through the level-2 structure X. In the second assignment, S2.C is invalid in standard PL/I because the level-2 structures S2.Y and S1.Y do not match. However, the reference to S2.C does work.

This sort of matching is useful in connection with data structures and files, where the first part of a record contains a value indicating the precise structure of the remainder of the record.

Note that the UNION attribute allows this type of declaration to be written more easily.

Nonmatching Based Variable References

In PL/I, a based variable reference need not match the variable for which the storage was originally allocated. The only requirement is that the size of the based variable in bits be less than or equal to the size of the original variable in bits. For example:

DECLARE LINE_IMAGE CHAR(83) BASED(ADDR(LINE));

DECLARE 1 LINE,

2 NAME CHAR(17),

2 CLASS CHAR(12),

2 SIZE CHAR(7),

2 LOC CHAR(11),

2 ATT_LIST CHAR(36);

 

Examples of Based Variables

The program DEFINED uses based variables and the READ SET statement to process a file of personnel data (PERSONNEL.DAT). The file has two types of valid records, a job record and a health record, which are identified by a 1-character code in the first position. The two record types are declared as based structures (JOB_RECORD and HEALTH_RECORD), one of which is selected based on the record type character (`J' for job, `E' for health). Any record that does not begin with one of these characters is invalid and is written out as a reference to the based character variable INVALID_RECORD.

DEFINED: PROCEDURE OPTIONS(MAIN);

 

DECLARE P POINTER; /* pointer to structures */

 

DECLARE 1 JOB_RECORD BASED(P),

2 RECORD_TYPE CHARACTER(1),

2 NAME CHARACTER(20),

/* the two structures differ in this member: */

2 DEPT_CODE CHARACTER(3),

2 JOB_CODE CHARACTER(6);

 

DECLARE 1 HEALTH_RECORD BASED(P),

2 RECORD_TYPE CHARACTER(1),

2 NAME CHARACTER(20),

2 EXAM_DATE CHARACTER(9);

 

DECLARE INVALID_RECORD CHARACTER(30) BASED(P);

 

DECLARE PERSONNEL RECORD FILE;

DECLARE PERSOUT STREAM OUTPUT PRINT FILE;

 

/* used to control DO group: */

%REPLACE NOTENDFILE BY '1'B;

ON ENDFILE(PERSONNEL) BEGIN;

PUT FILE(PERSOUT) SKIP LIST

('All processing complete.');

STOP; /* program stops here */

END;

OPEN FILE(PERSONNEL) INPUT TITLE('PERSONNEL.DAT');

 

DO WHILE(NOTENDFILE);

/* terminated by ENDFILE ON-unit */

READ FILE(PERSONNEL) SET(P);

/* P is the location of the record we just READ */

IF P->JOB_RECORD.RECORD_TYPE = 'J' THEN

PUT FILE(PERSOUT) SKIP LIST

('Name = ',P->JOB_RECORD.NAME,

'Dept = ',P->DEPT_CODE,

' Job = ' ,P->JOB_CODE);

ELSE /* either a health record or an invalid record */

DO;

IF P->HEALTH_RECORD.RECORD_TYPE = 'E' THEN

PUT FILE(PERSOUT) SKIP LIST

('Name = ',P->HEALTH_RECORD.NAME,

'Exam date: ',P->EXAM_DATE);

ELSE /* invalid record type */

PUT FILE(PERSOUT) SKIP LIST

('Invalid record: ',P->INVALID_RECORD);

END;

END; /* repeat DO group until ENDFILE is signaled */

END DEFINED;

 

For example, assume that the file PERSONNEL.DAT contains these records:

JMary A. Ford        ACCINTAKE

EMary A. Ford        22July 80

t12345678901234567890pppppp.pp

The output file (PERSOUT.DAT) will contain the following output:

Name = Mary A. Ford        Dept = ACC Job = INTAKE

Name = Mary A. Ford        Exam date: 22July 80

Invalid record: t12345678901234567890pppppp.pp

All processing complete.

 

Notice these other features of the program:

  • The references to based variables have a locator qualifier (P->) for clarity. However, because all are declared with P as their pointer reference, the locator qualifier can be omitted.
  • References to the structure members RECORD_TYPE and NAME must be fully qualified with the name of their containing structures (JOB_RECORD and HEALTH_RECORD) because both structures have members with these names. In contrast, DEPT_CODE, JOB_CODE, and EXAM_DATE are unique to their structures and need not be fully qualified.

The UNION attribute can be used to declare a single record with a variant portion in place of JOB_RECORD and HEALTH_RECORD. For example:

DECLARE 1 RECORD BASED(P),

2 RECORD_TYPE CHARACTER(1),

2 NAME CHARACTER(20),

2 VARIANTS UNION,

3 JOB_INFO,

4 DEPT_CODE CHARACTER(3),

4 JOB_CODE CHARACTER(6),

3 EXAM_DATE CHARACTER(9);

 

Note that the UNION attribute is not available in many other PL/I implementations. Use this attribute carefully if you are writing transportable code.

Controlled Variables

A controlled variable is a variable whose actual storage is allocated and freed dynamically in generations, of which only the most recent is accessible to the program. Controlled variables are declared with the CONTROLLED attribute. A controlled variable can be a scalar, array, area, or major structure variable possessing any of the attributes that do not conflict with the CONTROLLED attribute. (See See CONTROLLED Attribute for more information.)

The CONTROLLED attribute cannot be applied to minor structures, members of structures, parameters, or descriptions in an ENTRY or RETURNS attribute.

A controlled variable has no storage assigned to it until an ALLOCATE statement allocates storage for it. Each storage assignment is a generation of the variable. Subsequent ALLOCATE statements allocate subsequent generations. At any time in the program's execution, a reference to a controlled variable is a reference to the most recent generation of that variable, that is, the generation created by the most recent ALLOCATE statement.

The FREE statement frees the most recent generation of a controlled variable. If an attempt is made to free a controlled variable for which no generation exists (or to refer to such a variable), PL/I signals the ERROR condition. The following example shows the use of controlled variables:

CONT: PROCEDURE OPTIONS (MAIN);

 

DECLARE STR CHARACTER (10) CONTROLLED;

 

ALLOCATE STR;

STR = 'First';

ALLOCATE STR;

STR = 'Second';

ALLOCATE STR;

STR = 'Third';

PUT SKIP LIST (STR);

FREE STR;

PUT SKIP LIST (STR);

FREE STR;

PUT SKIP LIST (STR);

FREE STR;

 

END;

The output of this program is as follows:

Third

Second

First

 

Using the ALLOCATION Built-In Function

Because only the most recent generation of a controlled variable is available to a program, controlled variables provide an easy way to implement a stack. The ALLOCATE statement is equivalent to a push operation, and the FREE statement is equivalent to a pop operation. The ALLOCATION built-in function returns the number of generations of a variable, so you can use it to find out if the stack is empty.

For example:

DECLARE NEXT_MOVE CHARACTER(5) CONTROLLED,

DIRECTIONS(4) CHARACTER(5) INITIAL(

'North','East','South','West'),

D FIXED BINARY (7);

ALLOCATE NEXT_MOVE; /* Part of a loop that reports */

NEXT_MOVE = DIRECTIONS(D);/* moves in reverse order */

DO WHILE /* Print moves in correct order */

(ALLOCATION(NEXT_MOVE) ^= 0);

PUT SKIP LIST ('Go ', NEXT_MOVE);

FREE NEXT_MOVE;

END;

 

See See ALLOCATION for more information about the ALLOCATION built-in function.

Using the ADDR Built-In Function

You can use a controlled variable as the argument of the ADDR built-in function. If a generation exists, ADDR returns a pointer to it. If no generation of the variable exists, ADDR returns the null pointer. Thus, you can use ADDR to preserve a pointer to a generation of a controlled variable that later becomes hidden under further generations, as in the following example:

DECLARE STOPS CHARACTER (20) VARYING CONTROLLED,

MIDPOINT CHARACTER (20) VARYING BASED (P),

P POINTER;

/* part of a loop */

ALLOCATE STOPS;

STOPS = CURRENT_LOC;

IF I = 5 THEN P = ADDR(STOPS);

PUT SKIP LIST (

'End reached! Halfway point was', MIDPOINT);

 

At a certain point during the execution of this program, the ADDR built-in function captures the address of the current generation of STOPS and assigns it to P. After more generations of STOPS have been allocated, MIDPOINT (which is based on P) has the value of that same intermediate generation of STOPS.

Note that the value of P (and therefore of MIDPOINT) is valid only so long as the intermediate generation of STOPS to which P points is allocated. As soon as that generation is freed, the value of P becomes invalid, and it must not be used in a pointer-qualified reference until it is reassigned.

A controlled variable cannot be used in a pointer-qualified reference. In the previous example, a reference like the following would be illegal:

P->STOPS

 

Dynamically Allocated Variables

This section describes the mechanisms for dynamically allocating storage.

ALLOCATE Statement

The ALLOCATE statement obtains storage for a based or controlled variable and sets (with based variables) a locator variable equal to the address of the allocated storage. The format of the ALLOCATE statement is as follows:

allocate-item

The syntax of the allocate item is:

variable-reference [SET(locator-reference)] [IN(area-reference)]

 
variable-reference

A based or controlled variable for which storage is to be allocated. The variable can be any scalar value, array, area, or major structure variable; it must be declared with the BASED or CONTROLLED attribute.

SET(locator-reference)

The specification of a pointer or offset variable (for based variables) that is assigned the value of the location of the allocated storage. If the SET option is omitted, the based variable must be declared with BASED(locator-reference) ; the variable designated by that locator reference is assigned the location of the allocated storage.

You cannot use the SET option to allocate controlled variables.

IN(area-reference)

The specification of an area reference (for based variables) in which the storage is to be allocated. If the IN option is omitted, the SET option (or implied SET option if the locator variable is an offset) must be an offset declared with OFFSET(area-reference).

You cannot use the IN option to allocate controlled variables.

Examples

DECLARE STATE CHARACTER(100) BASED (STATE_POINTER),

STATE_POINTER POINTER;

ALLOCATE STATE;

 

This ALLOCATE statement allocates storage for the variable STATE and sets the pointer STATE_POINTER to the location of the allocated storage.

The ALLOCATE statement obtains the amount of storage needed to accommodate the current extent of the specified variable. If, for example, a character-string variable is declared with an expression for its length, the ALLOCATE statement evaluates the current value of the expression to determine the amount of storage to be allocated. For example:

DECLARE BUFFER CHARACTER (BUFLEN) BASED,

BUF_PTR POINTER;

 

BUFLEN = 80;

ALLOCATE BUFFER SET (BUF_PTR);

 

Here, the value of BUFLEN is evaluated when the ALLOCATE statement is executed. The ALLOCATE statement allocates 80 bytes of storage for the variable BUFFER and sets the pointer variable BUF_PTR to its location.

The ALLOCATE statement is also used to allocate storage for controlled variables. A controlled variable is one whose actual storage is allocated and freed dynamically in generations, only the most recent of which is accessible to the program. Unlike based variables, a controlled variable cannot be used in a pointer-qualified reference.

If the variable being allocated has been declared with initial values, these values are assigned to the variable after allocation.

FREE Statement

The FREE statement releases the storage that was allocated for a based or controlled variable. The format of the FREE statement is as follows:

FREE free-item[,free-item ...];

 
free-item

The syntax of the free-item is:

variable-reference [IN(area-reference)]

 
variable-reference

A reference to the based or controlled variable whose storage is to be released.

If you do not explicitly free the storage acquired by the variable, the storage is not freed until the program terminates.

If you free a variable that is explicitly associated with a pointer, the pointer variable becomes invalid and must not be used to reference storage. You can only free a variable once for each allocation.

IN(area-reference)

The specification of an area reference (for based variables) in which the storage is to be freed. If the IN option is omitted, the variable reference must be either implicitly or explicitly based on an offset variable with a base area.

You cannot use the IN option in conjunction with controlled variables.

Examples

FREE LIST;

FREE P->INREC;

 

These statements release the storage acquired for the based variable LIST and for the allocation of INREC pointed to by the pointer P.

ALLOCATE STATE SET (STATE_POINTER);

 

FREE STATE;

 

This FREE statement releases the storage for the based variable STATE and makes the value of STATE_POINTER undefined.

Other Mechanisms for Dynamic Storage Allocation

PL/I has a variety of dynamic storage management mechanisms available besides those for based and controlled variables. You can also use explicitly specified calls to the malloc, calloc, and realloc memory allocation packages. For more information on these packages, see the manual pages on your system.

These storage control mechanisms are generally similar in the amount of overhead that they require both in execution time and in storage space, although certain mechanisms have characteristics that make them useful in specific circumstances.

In general, the standard PL/I language manipulation of dynamic memory provides reasonable performance with some built-in checking.

Defined Variables

The DEFINED attribute indicates that PL/I is not to allocate storage for the variable, but is to map the description of the variable onto the storage of another variable called the base variable. The DEFINED attribute provides a way to access the same data using different names (see See DEFINED Attribute for more information).

In a declaration of a defined variable, the DEFINED keyword, which you can abbreviate to DEF, is followed by a variable reference (which must not have the BASED or DEFINED attribute), and optionally by the position in the variable at which the defined variable begins. If you specify the position, you use the POSITION attribute followed by an expression in parentheses. The expression is an integer expression that specifies a position in the base; a value of 1 indicates the first character or bit. You can use the POSITION attribute only when the defined variable satisfies the rules for string overlay defining, which is described later in this section.

When you use the DEFINED attribute in the declaration of a variable, PL/I associates the description of the variable in the declaration with the storage allocated for the variable on which the declaration is defined. For example:

DECLARE NAMES(10) CHARACTER(5) DEFINED (LIST),

LIST(10) CHARACTER(5);

 

In this example, the variable NAMES is a defined variable; its data description is mapped to the storage occupied by the variable LIST. Any reference to NAMES or to LIST is resolved to the same location in memory.

With defined variables that meet the criteria for string overlay defining, you can use the POSITION attribute to specify the position in the base variable at which the definition begins. For example:

DECLARE ZIP CHARACTER(20),

ZONE CHARACTER(10) DEFINED(ZIP) POSITION(4);

 

This statement declares the variable ZONE and maps it to characters 4 through 13 of the variable ZIP.

The extent of a defined variable is determined at the time of block activation, but the base reference (and the position, if the POSITION attribute is also specified) is interpreted each time the defined variable is referenced. For example:

DECLARE I FIXED,

A(10) FIXED,

B FIXED DEFINED(A(I));

DO I = 1 TO 10;

B = I;

END;

 

The DO group assigns I to A(I) for I = 1,2, ... 10.

The base reference of a defined variable cannot be a reference to a based variable or to another defined variable. A defined variable and its base reference must satisfy one of the following criteria:

String Overlay Defining

If the defined variable is specified with the POSITION attribute, then both the defined variable and the base reference must be suitable for bit- or character-string overlay defining.

In brief, a variable is suitable for overlay defining if it consists entirely of characters or bits, and those characters or bits are packed into adjacent storage without gaps. Such a variable can be treated as a string or interpreted as different types of aggregates. For example:

DECLARE A (10) CHARACTER (5);

DECLARE B (5) CHARACTER (10) DEFINED (A);

A (1) = 'AAAAA';

A (2) = 'BBBBB';

PUT LIST (B(1));

 

See . An Overlay Defined Variable shows a 50-byte region of storage treated either as a 10-element array (A) of 5-character strings or as a 5-element array (B) of 10-character strings.

. An Overlay Defined Variable

If the defined variable and its base reference have identical data types, a reference to the defined variable is equivalent to the base reference. In the case of overlay defining, the defined variable maps onto part of the base reference's storage as follows:

  1. If the POSITION attribute was specified, let position be its value at the moment of reference; otherwise, let position equal 1.
  2. Let m be the total number of characters (or bits) specified by the data type of the defined variable. (Note that for pictured data, m is the total number of characters in the picture specification, exclusive of the V, K, and Fn characters.)
  3. A reference to the defined variable accesses m characters (or bits) of the base reference, beginning with the character or bit specified by position. The reference must lie entirely within the base reference; that is, position and m must satisfy the following formula: 1 <= position <= position + m <= n + 1

n is the total number of characters or bits in the base reference.

Rules for Overlay Defining

A variable V is suitable for character-string overlay defining if V is not an unconnected array and if one of the following criteria is satisfied:

  • V has the CHARACTER attribute, but not ALIGNED or VARYING.
  • V has the PICTURE attribute.
  • V is a structure, and each of V's members and submembers that is not a structure satisfies one of the first two criteria.

A variable V is suitable for bit-string overlay defining if V is not an unconnected array and if one of the following criteria is satisfied:

  • V has the BIT attribute but not ALIGNED.
  • V is a structure, and each of V's members or submembers that is not a structure satisfies the first criterion.

Storage Sharing

Variables that have any of the attributes BASED, DEFINED, UNION, or PARAMETER can share physical storage locations with one or more other variables.

A based variable is not allocated any storage when it is declared. Instead, storage is either located by a locator-qualified reference to the variable or allocated by the ALLOCATE statement. The BASED attribute then lets you describe the characteristics of a variable, which you can then locate by a reference that qualifies the variable name with any valid pointer value. Based variables are useful when the program must control the allocation of storage for several variables with identical attributes. The creation and processing of a queued or linked list is a common case. For full details on based variables and valid pointer values, see See Based Variables .

A defined variable uses the storage of a previously declared variable, which is referenced in the DEFINED attribute. The referenced variable is called the base of the defined variable. The base can be a character- or bit-string variable, suitable for a technique called string overlay defining. When the base is a string variable, the POSITION attribute can also be specified for the defined variable, giving the position within the base variable's storage at which the overlay defining begins. Defined variables are useful when the program must refer to the same storage by different names. For more information, see See Dynamically Allocated Variables .

Unions provide capabilities similar to those of defined variables, but the rules governing unions are less restrictive. A union is a variation of a structure in which all immediate members occupy the same storage.

You must use the UNION attribute with a level number in a structure declaration. UNION signifies that all immediate members of the major or minor designated structure occupy the same storage. Immediate members are members that have a level number one higher than the major or minor structure with the union attribute. For more information, see See Using The UNION Attribute On Structure Declarations .

Parameters of a procedure share storage with their associated arguments. The associated argument is either a variable written in the argument list or a dummy variable allocated by the compiler. When the written argument is a variable, the sharing of storage by the parameter and argument allows a procedure to return values to the invoking procedure by changing the value of the parameter. For instance, a function can return values in this manner in addition to returning the value specified in its RETURN statement. For more information, see See Parameters and Arguments .

 

Expressions and Data Type Conversions

An expression is a representation of a value or of the computation of a value, and an assignment gives the value contained in an expression to a variable. Together, expressions and assignments form the mechanism for performing computation.

This chapter covers the following topics:

Assignment Statement

The assignment statement gives a value to a specified variable. The format of the assignment statement is:

target, ... = expression;

 
target

A reference to a variable to be assigned the value of the expression. If there are two or more targets, they are separated by commas. A target can be:

  • A reference to a scalar variable or scalar array element
  • A reference to a pseudovariable (for example, SUBSTR)
  • A reference to a major or minor structure name or any member of a structure
  • A reference to an array variable
expression

Any valid expression.

PL/I evaluates the targets and the expression in any order. Thus, a program should not depend on the evaluation of the targets before the expression.

PL/I performs the following steps for assignment. Note that the only certain things about the order of steps performed are that step 1 precedes step 3 and that step 4 is performed last.

  1. The expression is evaluated, producing a value to be assigned to the target. An expression can consist of many subexpressions and operations, each of which must be evaluated.
  2. Each target is evaluated. If a target contains a pseudovariable, any expressions in the argument list are evaluated.
  3. If the data type of the result does not match the data type of a target variable, the resulting value is converted to the data type of the target, if possible. The compiler issues a WARNING message to alert you to the implicit conversion.
  4. The value of the expression is assigned to the targets.

Some general rules regarding the types of data you can specify in assignment statements are listed in See . Data Types for Assignment Statement . For the complete rules for data conversion in assignments, see See Data Type Conversion of Operands and Expressions .

. Data Types for Assignment Statement

Data Type

Rules

Area

Only the current extent of an area is moved from the source area to a target. If the target area is not large enough to hold the extent, the AREA condition is raised. Note that the assignment is performed in such a way that all offsets in the source area are valid in the target area after the assignment. Areas cannot be assigned as members of structures.

Arithmetic

PL/I converts an arithmetic expression to the type of its target if their types are different. If the target is a character- or bit-string variable, PL/I converts the arithmetic expression to its character- or bit-string equivalent.

A character-string expression can be converted to the data type of an arithmetic target only if the string consists solely of characters that have numeric equivalents.

Arrays

You can specify an array variable as the target of an assignment statement in only the following ways:

 

  • array-variable = expression;

where expression yields a scalar value. Every element of the array is assigned the resulting value.

  • array-variable-1 = array-variable-2;

where the specified array variables have identical data type attributes and dimensions. Each element in array-variable-1 is assigned the value of the corresponding element in array-variable-2.

The storage occupied by the two arrays must not overlap.

Any array variable specified in an assignment statement must occupy connected storage. All other specifications of an array variable as a target of an assignment statement are invalid.

Bit

When a target of an assignment is a bit-string variable, the resulting expression is truncated or padded with trailing zeros to match the length of the target.

Character

When a target of an assignment is a fixed-length character string, the resulting expression is truncated on the right or padded with trailing spaces to match the length of the target. If a target is a varying-length character string, the resulting expression is truncated on the right if it exceeds the maximum length of the target.

When one character-string variable is assigned to another, the storage occupied by the two variables cannot overlap.

Entry

If the specified expression is an entry constant, an entry variable, or a function reference that returns an entry value, the target variable must be an entry variable.

Label

If the specified expression is a label constant, a label variable, or a function reference that returns a label value, the target variable must be a label variable.

Pointer and Offset

If the specified expression is a pointer or offset, or a function reference that returns a pointer or offset, the target variable must be a pointer or offset variable.

Structures

You can specify the name of a major or minor structure as a target of an assignment statement only if the source expression is an identical structure with members in the same hierarchy and with identical sizes and data type attributes. The storage occupied by the two structures must not overlap.

Any structure variable specified in an assignment statement must occupy connected storage.

The following examples show types of assignment statements:

A = 1;

A = B + A;

SUM = A + 3;

STRING = 'word';

A,B = 5;

Operators and Operands

An operator is a symbol that requests a unique operation. Operands are the expressions on which operations are performed. Built-in functions can also be considered operators, as well as their arguments considered operands.

Operators

A prefix operator precedes a single operand. The prefix operators are the unary plus (+), the unary minus (-), and the logical NOT (^)

  • The plus sign can prefix an arithmetic value or variable. However, it does not change the sign of the operand.
  • A minus sign reverses the sign of an arithmetic operand.
  • The logical NOT (^) prefix operator performs a logical NOT operation on a bit-string operand; the bit value is complemented.

The following examples show expressions containing prefix operators:

A = +55;

B = -88;

BITC = ^BITB;

 

An infix operator appears between two operands, and indicates the operation to be performed on them. PL/I has infix operators for arithmetic, logical, and relational (comparison) operations, and for string concatenations. Following are some examples of expressions containing infix operators:

RESULT = A / B;

IF NAME = FIRST_NAME || LAST_NAME THEN GOTO NAMEOK;

 

An expression can contain both prefix and infix operators. For example:

A = -55 * +88;

You can apply prefix and infix operators to expressions by using parentheses for grouping. For a table giving the categories of operators and the operator symbols, see See .

Operands

Because all operators must yield scalar values, operands cannot be arrays or structures. The data type that you can use for an operand in a specific operation depends on the operator:

  • Arithmetic operators must have arithmetic operands; if the operands are of different arithmetic types, they are converted before the operation to a single type, called the derived data type. See Derived Data Types for Arithmetic Operations describes this process.
  • Logical operators must have bit-string operands.
  • Relational operators must have two operands of the same type. (Note, however, that comparisons are allowed between offsets and pointers.)
  • The operators greater than (>), less than (<), not greater than (^>), not less than (^<), greater than or equal to (>=), and less than or equal to (<=) are valid only with computational operands.
  • The concatenation operator must have two bit-string operands or two character-string operands.

Arithmetic Operators

The arithmetic operators perform calculations. Programs that accept numeric input and produce numeric output use arithmetic operators to construct expressions that perform the required calculations. The infix arithmetic operators are listed in See . Infix Arithmetic Operators .

. Infix Arithmetic Operators

Operator

Operation

+

Addition

-

Subtraction

*

Multiplication

/

Division

**

Exponentiation

In addition, there are two prefix operators: unary plus (+) and unary minus (-). The unary plus is valid on any arithmetic operand, but it performs no actual operation. The unary minus reverses the sign of any arithmetic operand.

For any arithmetic operator, operands must be arithmetic; that is, they must be constants, variables, or other expressions with the data type attribute BINARY, DECIMAL, or PICTURE. Operands of different arithmetic types are converted to a common type before the operation is performed.

Arithmetic operators have a predefined precedence that governs the order in which operations are performed. All expressions can be enclosed in parentheses to override the rules of precedence. See . Precedence of Operators lists the precedence of operators.

Logical Operators

The logical operators perform logical operations on one or two operands. The operands of the logical operators must be bit-string expressions, except that the operand of the NOT operator can be a bit-string expression or a single relational operator. All relational expressions result in bit-string values of length 1, and they can therefore be used as operands in logical operations.

Except when the NOT operator is used as the prefix of a relational operator, the result of a logical operation is always a bit string.

Except for AND THEN and OR ELSE, logical operations are performed on their operands bit by bit. If bit-string operands are not the same length, PL/I extends the smaller of the operands on the right (that is, in the direction of the least significance) with zeros to match the length of the larger operand. This length is always the length of the result.

See . Logical Operators describes the prefix and infix operators.

. Logical Operators

Prefix Operator

Operation

^ (circumflex)

Logical NOT. In a logical NOT operation, the value of the operand is complemented; that is, a 1 bit becomes a 0 and a 0 bit becomes a 1. The value of a relational expression is also complemented; that is ^(A <B) is equivalent to (A >= B).

Infix Operator

Operation

& (ampersand)

Logical AND. In a logical AND operation, two operands are compared. If corresponding bits are 1, the result is 1; otherwise, the result is 0.

| (vertical bar) or ! (exclamation point)

Logical OR. In a logical OR operation, two operands are compared. If either or both of two corresponding bits are 1, the result is 1; otherwise the result is 0. (The | and the ! characters can be used interchangeably.)

&: (ampersand and colon)

Logical AND THEN. The operation is like AND except that the second operand is evaluated only if the first operand is true, and except that AND THEN does not do bit-by-bit operations on bit-string operands.

^ (circumflex)

Logical EXCLUSIVE OR. Two operands are compared, and the result is 1 if one of the corresponding bits is 1 and the other is 0.

|: (vertical bar and colon) or !: (exclamation point and colon)

Logical OR ELSE. The operation is like OR except that the second operand is evaluated only if the first operand is false, and except that OR ELSE does not do a bit-by-bit operation on bit-string operands.

You can define additional operations on bit strings with the BOOL built-in function.

Logical expressions will not be completely evaluated in some cases. If the result of the total expression can be determined from the value of one or more individual operands, the evaluation can be terminated. For example:

A & B & C & D & E

 

In this expression, evaluation will stop when any operand or the result of any operation is a bit string containing all zeros.

Examples

DECLARE (BITA,BITB,BITC) BIT(4);

BITA = '0001'B;

BITB = '1001'B;

BITC = ^BITA; /* BITC equals '1110'B */

BITC = BITA | BITB; /* BITC equals '1001'B */

BITC = BITA & BITB; /* BITC equals '0001'B */

BITC = ^(BITA & BITB); /* BITC equals '1110'B */

BITC = ^(BITA > BITB); /* BITC equals '1000'B (true) */

In the last assignment statement, the logical NOT expression yields '1'B; when this value is assigned to BITC, a BIT(4) variable, the value is padded with zeros and becomes '1000'B.

NOT

The logical NOT operator in PL/I is the circumflex character (^) used as a prefix operator. In a logical NOT operation, the value of a bit is reversed. If a bit is 1, the result is 0; if a bit is 0, the result is 1.

The NOT operator can be used on expressions that yield bit-string values (bit-string, relational, and logical expressions). It can also be used to negate the meanings of the relational operators (<, >, =). For example:

IF A ^> B THEN

/* equivalent to IF A <= B ... */

 

The result of a logical NOT operation on a bit-string expression is a bit-string value. For example:

DECLARE (BITA, BITB) BIT (4);

BITA = '0011'B;

BITB = ^BITA;

 

The resulting value of BITB is 1100.

The NOT operator can test the falsity of an expression in an IF statement. For example:

IF ^(MORE_DATA) THEN ...

 

AND

The ampersand (&) character is the logical AND operator in PL/I. In a logical AND operation, two bit-string operands are compared bit by bit. If two corresponding bits are 1, the corresponding bit in the result is 1; otherwise, the resulting bit is 0.

The result of a logical AND operation is a bit-string value. All relational expressions result in bit strings of length 1; they can therefore be used as operands in an AND operation. If the two operands have different lengths, the shorter operand is converted to the length of the longer operand, and the greater length is the length of the result.

Examples

DECLARE (BITA, BITB, BITC) BIT (4);

BITA = '0011'B;

BITB = '1111'B;

BITC = BITA & BITB;

 

The resulting value of BITC is '0011'B.

The AND operator can test whether two or more expressions are both true in an IF statement. For example:

IF (LINENO(PRINT_FILE) < 60) &

(MORE_DATA = 'YES') THEN ...

 

OR

The vertical bar character (|) represents the logical OR operation in PL/I. In a logical OR operation, two bit-string operands are compared bit by bit. If the two operands are of different lengths, the shorter operand is converted to the length of the longer operand, and this is the length of the result. If either of two corresponding bits is 1, the resulting bit is 1; otherwise, the resulting bit is 0.

All relational expressions result in bit strings of length 1, and they can therefore be used as operands in an OR operation.

The result of the OR operation is a bit-string value. For example:

DECLARE (BITA, BITB, BITC) BIT (4);

BITA = '0011'B;

BITB = '1111'B;

BITC = BITA | BITB ;

 

The resulting value of BITC is '1111'B.

The OR operator can test whether one of the expressions in an IF statement is true. For example:

IF (LINENO(PRINT_FILE) < 60) |

(MORE_DATA = YES) THEN ...

 

You can use the exclamation point (!) vertical bar, for compatibility with other PL/I implementations.

EXCLUSIVE OR

The EXCLUSIVE OR operator (infix or dyadic ^) causes a bit-by-bit comparison of two bit-string operands. If the two operands are not of equal length, the shorter is padded with 0s until it is the same length as the other, and this length is also the length of the result. If either of two corresponding bits is 1 and the other is 0, the result is 1. If both are 1, or if both are 0, the result is 0.

All relational expressions result in bit strings of length 1, and they can therefore be used as operands in an EXCLUSIVE OR operation.

The result of the EXCLUSIVE OR operation is a bit-string value. For example:

DECLARE (BITA, BITB, BITC) BIT (4);

BITA = '0011'B;

BITB = '1011'B;

BITC = BITA ^ BITB;

 

The resulting value of BITC is '1000'B.

The EXCLUSIVE OR operator can be used to test whether one and only one of the expressions in an IF statement is true. For example:

IF (A > 0) ^ (B > 0) THEN ...

 

AND THEN

The ampersand-colon token (&:) is the AND THEN operator in PL/I. The AND THEN operator causes the first operand to be evaluated; if it is false, the result returned is '0'B. The second operand will never be evaluated if the first operand is false. If and only if the first operand is true, the second operand is evaluated. If both are true, the result returned is true ('1'B); otherwise, the result is false ('0'B).

The AND THEN operator performs a Boolean truth evaluation, not a bit-by-bit operation, even when the two operands are bit strings. For example, '00001'B &: '10000'B yields '1'B (not '00000'B, which would be the result of an AND operation on these two bit strings). The reason is that each operand is a non-zero bit value, and therefore each evaluates to '1'B.

The AND THEN operator yields the same result as the AND operator (&) when expressions are tested in an IF statement (as in the last example in See AND ). The difference is that the AND operator can have its operands evaluated in either order.

The AND THEN operator is useful in compound test expressions in which the second test should occur only if the first test was successful. For example:

IF (P ^= NULL()) &: (P->X ^= 4) THEN ...

 

This statement causes P->X to be evaluated only if P is not a null pointer. If the AND operator were used instead of AND THEN, this expression could cause an access violation (invalid pointer reference).

OR ELSE

The vertical bar and colon characters (|:) together are the OR ELSE operator in PL/I. The OR ELSE operator causes the first operand to be evaluated. If it is true, the result returned is '1'B. If and only if the first operand is false, the second operand is evaluated. If either or both operands are true, the result returned is '1'B; otherwise, the result is '0'B.

The OR ELSE operator performs a Boolean truth evaluation, not a bit-by-bit operation, even when the two operands are bit strings. For example:

'00001'B |: '10000'B

 

This yields:

'1'B

 

It does not yield'10001'B, which would be the result of an OR operation on these two bit strings. The reason is that each operand is a nonzero bit value, and therefore each evaluates to '1'B.

The OR ELSE operator yields the same result as the OR operator (|) when expressions are tested in an IF statement (as in the last example in the "OR Operator" entry). The difference is that the OR operator can have its operands evaluated in any order.

The OR ELSE operator is useful in compound test expressions in which the second test should occur only if the first test failed. For example:

IF (A=0) |: (B/A > 1) THEN ...

 

This results in the second expression (B/A > 1) being evaluated only if the first expression is false. Thus, the OR ELSE operator prevents an attempt to divide by zero.

Relational Operators

The relational, or comparison, operators test the relationship of two operands; the result is always a Boolean value (that is, a bit string of length 1). If the comparison is true, the resulting value is '1'B; if the comparison is false, the resulting value is '0'B. The relational operators are all infix operators. The following table describes all the relational operators:

Operator

Operation

<

Less than

^<

Not less than

<=

Less than or equal to

=

Equal to

^=

Not equal to

>=

Greater than or equal to

>

Greater than

^>

Not greater than

Note that PL/I recognizes the tilde symbol (~)as synonymous with the circumflex (^).

Relational operators compare any of the following data types: arithmetic (decimal or binary); bit-string; character-string; and entry, pointer, label, or file data. Specific results of operations on each type of data are elaborated below. The following general rules apply:

  • All operands must be scalar.
  • Both operands must be arithmetic, or they must have the same data type.
Arithmetic Comparisons

Arithmetic and picture operands are compared algebraically. If the operands have a different base, scale, or precision, PL/I converts them according to the rules for arithmetic operand conversion.

Bit-String Comparisons

When two bit strings are compared, they are compared bit by bit from the most significant bit to the least significant bit (as represented by PUT LIST). If the operands have different lengths, PL/I extends the smaller operand with zeros in the direction of the least significance. Null bit strings are equal.

Character-String Comparisons

When two character strings are compared, they are compared character by character in a left-to-right order. The comparison is based on the ASCII collating sequence. The ASCII characters are the first 128 characters of the DEC Multinational Character Set.

Note the following characteristics of the collating sequence:

  • Uppercase letters are less than any lowercase letters.
  • Numeric characters are less than any letters.

If the operands do not have the same length, PL/I extends the smaller operand on the right with blanks for the comparison. Either or both of the strings can have the attribute VARYING; PL/I uses the current length of a varying character string when it makes the comparison. Null character strings are equal.

Comparing Noncomputational Data

Only the following operators are valid, or meaningful, for comparisons of any of the noncomputational data types except areas (condition, entry, file, label, offset, and pointer):

Operator

Operation

=

Equal

^=

Not equal

The results of the comparisons provide the information indicated below for each data type.

Condition Data

Two condition values are equal if they identify the same condition values.

Entry Data

Two entry values are equal if they identify the same entry point in the same block activation of a procedure.

File Data

Two values defined with the FILE attribute are equal if they identify the same file constant.

Label Data

Two label values are equal if they identify the same statement in the same block activation. A label that identifies a null statement is not equal to the label of any other statement.

Offset Data

Two offset values are equal if they identify the same storage location or if they are both null.

Pointer Data

Two pointer values are equal if they identify the same storage location or if they are both null.

Concatenation Operator

The concatenation operator produces a single string from two strings specified as operands. The concatenation operator is two vertical bars (| |).

The operands must both be character strings or both be bit strings. (If not, the appropriate conversion is performed, and you get a warning message about the conversion. The result of the operation is a string of the same type as the operands.

Examples

CONCAT: PROCEDURE OPTIONS(MAIN);

DECLARE OUTFILE STREAM OUTPUT PRINT FILE;

 

PUT FILE(OUTFILE) SKIP LIST('ABC' || 'DEF');

PUT FILE(OUTFILE) SKIP LIST('001'B || '110'B);

PUT FILE(OUTFILE) SKIP LIST((3)'001'B !! '07'B3);

 

END CONCAT;

 

The program CONCAT writes the following output to the file OUTFILE.DAT:

ABCDEF

'001110'B

'001001001000111'B

 

Note that the exclamation point can be used in place of the vertical bar, for compatibility with other PL/I implementations.

Precedence of Operators and Expression Evaluation

The precedence, or priority, of operators defines the order in which expressions are evaluated when they contain more than one operator. See . Precedence of Operators gives the priority of PL/I operators. Low numbers indicate high priority. For example, the exponentiation operator (**) has the highest priority (1), so it is performed first, and the OR ELSE operator (| :) has the lowest priority, so it is performed last.

. Precedence of Operators

Operator

Priority

Left/Right
Associative

Order of Evaluation

()

0

N/A

deepest first

**

1

right

left to right

+ (prefix)

1

N/A

N/A

- (prefix)

1

N/A

N/A

^ (prefix)

1

N/A

N/A

*

2

left

left to right

/

2

left

left to right

+ (infix)

3

left

left to right

- (infix)

3

left

left to right

| |

4

left

left to right

>

5

left

left to right

<

5

left

left to right

^>

5

left

left to right

^<

5

left

left to right

=

5

left

left to right

^=

5

left

left to right

<=

5

left

left to right

>=

5

left

left to right

&

6

left

left to right

|

7

left

left to right

^ (infix)

7

left

left to right

&:

8

left

left to right across entire expression

|:

9

left

left to right across entire expression

Expressions are evaluated from left to right, with the following qualifications:

Consider the expression:

A |: B &: C

 

It should be parenthesized according to the rules of associativity as:

(A |: (B &: C))

 

However, the semantics of the OR ELSE (|:) and AND THEN (&:) operators dictate that the operands be evaluated in the order A, B, C as necessary. This means that the B &: C will be evaluated before A which might not be the intent of the programmer and might not conform to the semantic rules of the OR ELSE (|:) operator.

When PL/I determines which to evaluate first, (1) the deeply nested B &: C (consistent with the order of evaluation for parentheses), or (2) the A |: (consistent with the order of evaluation of |:), (1) the deeply nested B &: C is chosen.

Whenever an expression that contains any combination of two or more &: or |: operators, the order of operand evaluation will be performed in the order dictated by the associativity of the operators. This may or may not be the desired behavior. To work around this, you will have to construct similar program sequences using IF THEN constructs in conjunction with either the AND (&) operators to achieve the desired behavior.

A & USER_FUNCTION(ALPHA,BETA)

 

Evaluation of this expression can be terminated without the USER_FUNCTION reference being evaluated if the evaluation of A results in a false Boolean value. However, the evaluation of A might not occur first, because the order of evaluations is not guaranteed in AND operations. To ensure that the first operand is evaluated first, use &:, which is the AND THEN operator, instead of &.

A + B + FUNC(I) + C

 

The subexpression A+B might not be evaluated and the result stored before FUNC(I) is evaluated. Therefore, if FUNC(I) alters A, B, or C, results may not be as expected.

Data Type Conversion of Operands and Expressions

Conversion is the changing of a data item from one data type to another. Data conversion in PL/I takes place in many contexts, not all of them obvious ones. Program results that seem improper may in fact be caused by data conversion at some point during program execution. This section discusses the following topics:

Contexts in which PL/I Converts Data

PL/I can perform data conversions in the following contexts:

  • Assignment statements
  • Arguments passed to a procedure
  • Values specified in a RETURN statement
  • An argument converted by the built-in function FIXED, FLOAT, BINARY, DECIMAL, BIT, or CHARACTER
  • Conversions to and from character strings performed by the PUT and GET statements, respectively

If an attempt is made to assign a value to a target for which there is no defined conversion, the compiler generates a diagnostic message. For example:

F = '133.45';

 

If F is a variable with the attributes FIXED DECIMAL (5,2), then the statement assigns the numeric value 133.45 to F, as expected, although the compiler issues a WARNING message about the implicit conversion, stating that the constant '133.45' has been converted to a FIXED DECIMAL target. The warning does not prevent you from linking and running the program. However, note the following example:

F = 'ABC';

 

This statement results not only in a compiler WARNING message but, if you go on to link and run the program, you also receive a CONVERSION condition. This is normally fatal unless it is handled with an ON CONVERSION ON-unit.

See . Contexts in Which PL/I Converts Data describes the contexts in which PL/I converts data. The table also lists the built-in conversion functions, such as BINARY and CHARACTER, which you can use when you want to explicitly indicate a conversion and to specify such characteristics as the precision or string length of the converted result.

 
. Contexts in Which PL/I Converts Data

Context

Conversion Performed

target = expression;

In an assignment statement, the given expression is converted to the data type of the target.

entry-name

RETURNS (attribute ...);

 

RETURN (value);

In a RETURN statement, the specified value is converted to the data type specified by the RETURNS option on the PROCEDURE or ENTRY statement.

x + y

x - y

x * y

x / y

x**y

x | | y

x & y

x | y

x&:y

x | :y

x ^ y

x > y

x < y

x = y

x^=y

In any expression, if operands do not have the required data type, they are converted to a common data type before the operation. For most operators, the data types of all operands must be identical. A warning message is issued in the case of a concatenation conversion.

BINARY (expression)

BIT (expression) CHARACTER (expression)

DECIMAL (expression)

DECODE (expression)

ENCODE (expression)

FIXED (expression)

FLOAT (expression)

OFFSET (variable)

POINTER (variable)

PL/I provides built-in functions that perform specific conversions.

PUT LIST (item, ...);

Items in a PUT LIST statement are converted to character- string data.

GET LIST (item, ...);

Character-string input data is converted to the data type of the target item.

PAGESIZE (expression)

LINESIZE (expression)

SKIP (expression)

LINE (expression)

COLUMN (expression)

format items A, B, E, F, and X

TAB (expression)

Values specified for various options to PL/I statements must be converted to integer values.

DO control-variable ...

Values are converted to the attributes of the control variable.

parameter

Actual parameters are converted to the type of the formal parameter, if necessary.

INITIAL attribute

Initial values are converted to the type of the variable being initialized.

Derived Data Types for Arithmetic Operations

Even though arithmetic operands can be of different arithmetic types, all operations will be performed on objects of the same type. Any set of operands of different arithmetic types has an associated derived type, as follows:

  • If any operand has the attribute BINARY, the derived type is BINARY. Otherwise, the derived type is DECIMAL.
  • If any operand has the attribute FLOAT, the derived type is FLOAT. Otherwise, the derived type is FIXED.

See . Derived Data Types gives the derived data type for two arithmetic operands of different types. (Note that the types derived from FIXED DECIMAL in See . Derived Data Types are also derived when one operand is pictured.)

. Derived Data Types

Type of Operand 1

Type of Operand 2

Derived Type

FIXED BINARY

FLOAT BINARY

FLOAT BINARY

FIXED BINARY

FLOAT DECIMAL

FLOAT BINARY

FIXED DECIMAL

FLOAT DECIMAL

FLOAT DECIMAL

FIXED DECIMAL

FLOAT BINARY

FLOAT BINARY

FIXED BINARY

FIXED DECIMAL

FIXED BINARY

See . Converted Precision as a Function of Target and Source Attributes gives the precision resulting from the conversion of an operand to its derived type. The values p and q are known as the converted precision of an operand and are based on the values p and q of the source operand.

. Converted Precision as a Function of Target and Source Attributes

Target Data Type

Binary Fixed Source 2

Decimal Fixed Source See The constant 3.32 is an approximation of log2(10), the number of bits required to represent a decimal digit.

Binary Float Source See The constant 3.32 is an approximation of log2(10), the number of bits required to represent a decimal digit.

Decimal Float Source See The constant 3.32 is an approximation of log2(10), the number of bits required to represent a decimal digit.

Binary Fixed

p
q

min(ceil(p*3.32)+1,31)
min(ceil(q*3.32),31)

N/A
N/A

N/A
N/A

Decimal Fixed

min(ceil(p/3.32)+1,31) max(0,min(ceil(q*3.32),31))

p
q

N/A
N/A

N/A
N/A

Binary Float

min(p,53)

min(ceil(p*3.32),53)

p

min(ceil(p*3.32),
53)

Decimal Float

min(ceil(p/3.32),15)

min(p,15)

min(ceil(p/3.32),15)

p

All arithmetic operations except exponentiation are performed in the derived type of the two operands. Exponential operations are performed in a data type that is based on the derived type of the operands. All operations, including exponentiation, have results of the same type as that in which they are performed.

The result of an arithmetic operation can be assigned to a target variable of any computational type. The result is converted to the target type, following the rules in See Implicit Conversion During Assignment .

Conversion of Operands in Nonarithmetic Operations

As operations must be performed on operands of the same type, the following conversions are performed when operands do not match in nonarithmetic operations:

  • PICTURE is converted to CHARACTER.
  • DECIMAL is converted to CHARACTER.
  • FIXED BINARY is converted to BIT.
  • If either operand is CHARACTER, after other conversions have been performed, the noncharacter operand is converted to CHARACTER.

PL/I issues a warning message about a conversion in a concatenation expression, except when converting from picture to character.

Built-In Conversion Functions

The built-in conversion functions can take arguments that are either arithmetic or string expressions. They are often used to convert an operand to the type required in a certain context -- for instance, to convert a bit string to an arithmetic value for use as an arithmetic operand.

For the purpose of these functions, and in a few other contexts, derived arithmetic attributes are also defined for bit- and character-string expressions:

  • The derived type of a bit string is fixed-point binary. Its converted precision is 31, with a scale factor of 0.
  • The derived type of a character string is fixed-point decimal. Its converted precision is 31, with a scale factor of 0.

PL/I uses these derived attributes to determine the precision of values returned by the conversion functions if no precision is specified in the functions' argument lists. Note that the value of a string argument must also be convertible to the result type; for instance, '1.333' is convertible to arithmetic, but 'XYZ' is not.

See . Built-In Functions for Conversions Between Arithmetic and Nonarithmetic Types indicates which built-in functions you should use for each conversion between an arithmetic and a nonarithmetic type. In addition, you can use the BINARY, DECIMAL, FIXED, and FLOAT built-in conversion functions to control conversions between two arithmetic types.

. Built-In Functions for Conversions Between Arithmetic and Nonarithmetic Types

Conversion

Function

Arithmetic to bit

BIT

Arithmetic to character

CHARACTER

Arithmetic or character to fixed-point arithmetic

FIXED

Bit to arithmetic

BINARY

Bit to character

CHARACTER

Character to bit

BIT

Character to decimal

DECIMAL

Character to float

FLOAT

Arithmetic or character to binary

BINARY

Character to fixed binary

DECODE

Decimal integer to character

ENCODE

Integer (non-negative) to character

BYTE

Implicit Conversion During Assignment

During assignment, PL/I automatically converts the derived data type of an expression to the data type of a target, if necessary. In assignments, conversions are defined between the noncomputational types POINTER and OFFSET, and between any two computational types. However, a conversion during assignment results in an error if PL/I cannot perform it in a meaningful way. For example, you can assign the string '123.4' to a fixed decimal variable; you cannot, however, assign the string 'ABCD' to the same variable. Similarly, an assignment of an arithmetic type to a fixed variable results in the FIXEDOVERFLOW condition if integral digits are lost.

Although PL/I performs conversions in assignment statements, such conversions may represent programming errors and are in violation of the PL/I G subset standard. Therefore, the compiler issues a warning message that an implicit conversion is taking place. These messages do not terminate the compilation and may not indicate errors; they simply alert you to the fact that your program converts one data type to another in a way that may cause a problem when the program is run. You can prevent such warning messages in two ways:

  • Use the built-in conversion functions to convert data types explicitly. This method is recommended. See Built-In Conversion Functions summarizes the functions.
  • Use the -w or --nowarn option on the PLI command to suppress diagnostic warning messages. (The compiler will continue to print messages of greater severity.) However, you run the risk of missing important diagnostic information.

For example:

DECLARE (A,B) FIXED DECIMAL (5,2);

A = '123.45'; /* Warning message */

B = FIXED('123.45',5,2); /* No warning */

 

Both assignment statements assign the same value to their targets; however, the first statement causes a warning message from the compiler, while the second statement does not.

Assignment to Arithmetic Variables

Expressions of any computational type can be assigned to arithmetic variables. The conversion rules for each source type are described in the following sections.

Arithmetic to Arithmetic Conversions

A source expression of any arithmetic type can be assigned to a target variable of any arithmetic type. Note the following qualifications:

  • If the target is a variable of type FIXED BINARY or FIXED DECIMAL, then the FIXEDOVERFLOW condition is signaled when the source value has a larger number of integral digits than are specified in the precision of the target. If the target is a fixed- point binary variable, FIXEDOVERFLOW is signaled if the source value exceeds the storage allocated for the target, which can be larger than the declared precision of the target.
  • If the target is a variable of type FIXED DECIMAL(p,q) or FIXED BINARY(p,q) and the source value has more than q fractional digits, then the excess fractional digits of the source are truncated, and no condition is signaled. If the source has fewer than q fractional digits, the source value is padded on the right with zeros.
  • If the target value is floating point and the absolute source value is too large to be represented by a floating-point type, then the OVERFLOW condition is signaled, and the value of the target is undefined.
Conversions to Fixed Point

In the following examples, the specified source values are converted to FIXED DECIMAL(4,1):

Source Value

Converted Value

25.505

25.5

-2.562

-2.5

101

101.0

5365

FIXEDOVERFLOW - value undefined

Conversions to Floating Point

Let p be the precision of the floating-point target. If the source value is an integer that can be represented exactly in p digits, then the source value is converted to floating-point binary with no loss of accuracy.

Otherwise, the source value is converted to floating-point binary with rounding to precision p. For example, the constant 479 will be converted to FLOAT BINARY(24) without loss of accuracy, while the constant 16777217, which cannot be represented exactly in 24 bits, will be rounded during conversion.

Conversions from FIXED BINARY to Other Data Types

Conversions from FIXED BINARY to other data types follow the rules outlined below. Notice that these rules assume both precision and scale.

Precisions of the source and target are (p,q) and (p1,q1), respectively. The precision of the result is (p2,q2).

. Conversion from Fixed Binary

Target

Result

FIXED DECIMAL(p1,q1)

p2=1+CEIL(p1/3.32) and q2=CEIL(q1/3.32).

FIXED BINARY(p1,q1)

Precision and scale of the source are maintained during conversion; therefore, padding or truncation can occur. If nonzero bits are lost on the left, the result is undefined.

FLOAT DECIMAL(p1)

p2=CEIL(p1/3.32). The exponent indicates any fractional value.

FLOAT BINARY(p1)

p2=p1. The mantissa indicates any fractional value.

PICTURE

The target implies FIXED DECIMAL and is converted accordingly.

CHARACTER

The binary precision (p,q) is converted to a FIXED DECIMAL with precision (p1,q1), where p1=1+CEIL(p/3.32) and q1=CEIL(q/3.32). Then the rules for conversion from FIXED DECIMAL to CHARACTER are in effect.

BIT

The binary precision (p,q) is converted to an intermediate bit string where the size or precision is MIN(31,p-q). Then the intermediate bit string is converted to BIT(n). If (p-q) is negative or zero, the result is a null bit string.

If the scale factor is negative, substitute the FLOOR value for CEIL in the above calculations which contain q's.

Pictured to Arithmetic Conversions

In PL/I all pictured values have the associated attributes FIXED DECIMAL(p,q), where p is the total number of characters in the picture specification that specify decimal digits, and q is the total number of these digits that occur to the right of the V character. If the picture specification does not include a V character, then q is zero. This value is assigned to the target, following the PL/I rules for arithmetic to arithmetic conversion.

Bit-String to Arithmetic Conversions

When a bit-string value is assigned to an arithmetic variable, PL/I treats the bit string as a fixed-point binary value. A string of type BIT(n) is converted to FIXED BINARY(m,0), where m = min(n,31).

If the converted value is greater than or equal to 2 31 then FIXEDOVERFLOW is signaled. The leftmost bit in the bit string (as output by PUT LIST) is the most significant bit in the fixed-point binary value, not its sign. If the bit string is null, the fixed- point binary value is zero.

The intermediate fixed-point binary value is then converted to the target arithmetic type.

Note that bit strings are stored internally with the leftmost bit in the lowest address. The conversion to an arithmetic type must reverse the bits from this representation; therefore, you should avoid this conversion when performance is a consideration.

Examples

CONVTB: PROCEDURE OPTIONS(MAIN);

 

DECLARE STATUS FIXED BINARY(8);

DECLARE STATUS_D FIXED DECIMAL(10);

DECLARE OUT PRINT FILE;

 

OPEN FILE(OUT) TITLE('CONVTB.OUT');

ON FIXEDOVERFLOW PUT SKIP FILE(OUT)

LIST('Fixedoverflow:');

 

STATUS = '1001101'B;

PUT SKIP FILE(OUT) LIST(STATUS);

 

STATUS_D = '001101'B;

PUT SKIP FILE(OUT) LIST(STATUS_D);

 

STATUS = '1232'B2;

PUT SKIP FILE(OUT) LIST(STATUS);

 

STATUS = 'FF'B4;

PUT SKIP FILE(OUT) LIST(STATUS);

 

STATUS_D = '10111111111111111111111111111111'B;

END CONVTB;

 

Note that because the program CONVTB performs implicit conversions, the compiler issues WARNING messages. (Linking and running are accomplished successfully because the conversions are valid.)

The program CONVTB produces the following output:

77

13

110

255

 

Fixedoverflow:

 

The leftmost bit of all the bit-string constants is treated as the most significant numeric bit, not as a sign. For instance, the hexadecimal constant 'FF'B4 is converted to 255 instead of -127. The last assignment to STATUS_D signals the FIXEDOVERFLOW condition because the bit-string constant, when represented as a binary integer, is greater than 2 31 . The resulting value of STATUS_D is undefined.

Character-String to Arithmetic Conversions

When a character string is assigned to an arithmetic value, PL/I creates an intermediate numeric value based on the characters in the string. The type of this intermediate value is the same as that of an ordinary arithmetic constant comprising the same characters; for example, 342.122E-12 and '342.122E-12' are both floating-point decimal.

The character string can contain any series of characters that describes a valid arithmetic constant. That is, the character string can contain any of the numeric digits 0 through 9, a plus (+) or minus (-) sign, a decimal point (.), and the letter E. If the character string contains any invalid characters, the CONVERSION condition is signaled. See the following examples.

If the implied data type of the character string does not match the data type of the arithmetic target, PL/I converts the intermediate value to the data type of the target, following the PL/I rules for arithmetic to arithmetic conversions. In conversions to fixed point, FIXEDOVERFLOW is signaled if the character string specifies too many integral digits. Excess fractional digits are truncated without signaling a condition.

If the source character string is null or contains all spaces, the resulting arithmetic value is zero.

Examples

DECLARE SPEED FIXED DECIMAL (9,4);

SPEED = '23344.3882';

/* string converted to 23344.3882 */

 

SPEED = '32423.23SD';

/* CONVERSION condition */

 

SPEED = '4324324.3933';

/* FIXEDOVERFLOW condition */

 

SPEED = '1.33336';

/* string converted to 1.3333 */

 

Assignments to Bit-String Variables

In the conversion of any data type to a bit string, PL/I first converts the source data item to an intermediate bit-string value. Then, based on the length of the target string, it does the following:

  • If the length of the target bit-string value is greater than the length of the intermediate string, the target bit string (as represented by PUT LIST) is padded with zeros on the right.
  • If the length of the target bit-string value is less than the length of the intermediate string, the intermediate bit string (as represented by PUT LIST) is truncated on the right.

The next sections describe how PL/I arrives at the intermediate bit-string value for each data type.

Arithmetic to Bit-String Assignments

In converting an arithmetic value sv to a bit-string value, PL/I performs the following steps:

  1. Let v = abs(sv) .
  2. Determine a precision p as follows:
  3. Source

    Precision p

    FIXED BINARY(r,s)

    min(31,r-s)

    FLOAT BINARY(r)

    min(31,r)

    FIXED DECIMAL(r,s)

    min(31,ceil((r-s)*3.32))

    FLOAT DECIMAL(r)

    min(31,ceil(r*3.32))

  4. If p=0 (for example, when r=s), the intermediate string is a null bit string. Otherwise, the value v is converted to an integer n of type FIXED BINARY(p,0). If n>=2 p , the FIXEDOVERFLOW condition is signaled; otherwise, the intermediate bit string is of length p, and each of its bits represents a binary digit of n.

Bit strings are stored internally with the leftmost bit in the lowest address. The conversion must reverse the bits from this representation and should therefore be avoided when performance is a consideration. Note also that during the conversion, the sign of the arithmetic value and any fractional digits are lost.

Examples

CONVB: PROCEDURE OPTIONS(MAIN);

 

DECLARE NEW_STRING BIT(10);

DECLARE LONGSTRING BIT(16);

DECLARE OUT PRINT FILE;

 

OPEN FILE(OUT) TITLE('CONVB1.OUT');

 

NEW_STRING = 35;

PUT FILE(OUT) SKIP

LIST('35 converted to BIT(10):',NEW_STRING);

 

NEW_STRING = -35;

PUT FILE(OUT) SKIP

LIST('-35 converted to BIT(10):',NEW_STRING);

 

NEW_STRING = 23.12;

PUT FILE(OUT) SKIP

LIST('23.12 converted to BIT(10):',NEW_STRING);

NEW_STRING = .2312;

PUT FILE(OUT) SKIP

LIST('.2312 converted to BIT(10):',NEW_STRING);

 

NEW_STRING = 8001;

PUT FILE(OUT) SKIP

LIST('8001 converted to BIT(10):',NEW_STRING);

 

LONGSTRING = 8001;

PUT FILE(OUT) SKIP

LIST('8001 converted to BIT(16):',LONGSTRING);

END CONVB;

 

Note that because the program CONVB performs implicit conversions, the compiler issues WARNING messages. (Linking and running are accomplished successfully because the conversions are valid.)

The program CONVB produces the following output:

35 converted to BIT(10): '0100011000'B

-35 converted to BIT(10): '0100011000'B

23.12 converted to BIT(10): '0010111000'B

.2312 converted to BIT(10): '0000000000'B

8001 converted to BIT(10): '0111110100'B

8001 converted to BIT(16): '0111110100000100'B

 

The values 35 and -35 produce the same bit string because the sign is lost in the conversion. In the first assignment, 35, which is FIXED DECIMAL(2,0), is converted to FIXED BINARY(7,0) and then to a 7-bit string ('0100011'B). Three additional bits are appended to this intermediate bit string when it is assigned to NEW_STRING. Notice that the low-order bit of 8001 is lost when the constant is assigned to a BIT(10) variable.

Pictured to Bit-String Conversions

If the source value is pictured, its associated fixed-point decimal value is extracted. The fixed-point decimal value is then converted to a bit string, following the previous rules for arithmetic to bit-string conversion.

Character-String to Bit-String Conversions

PL/I can convert a character string of 0s and 1s to a bit string. Any character in the character string other than 0 or 1, including spaces, will signal the CONVERSION condition.

PL/I converts each 0 or 1 character in the character string to a 0 or a 1 bit in the corresponding position (as represented by PUT LIST) in the intermediate bit string.

If the source is a null character string, the intermediate string is a null bit string.

Examples

DECLARE NEW_STRING BIT(4);

 

NEW_STRING = '0010';

/* NEW_STRING = '0010'B */

 

NEW_STRING = '11';

/* NEW_STRING = '1100'B */

 

NEW_STRING = 'AS110';

/* CONVERSION condition */

 

Assignments to Character-String Variables

In the conversion of any data type to a character string, PL/I first converts the source value to an intermediate character-string value. Then it does one of the following:

  • If the length of the intermediate string is zero, a null string is assigned to the target.
  • If the target is a parameter or return value with an asterisk extent (as in RETURNS CHAR(*)), the intermediate string is assigned to the target.
  • If the target is of type CHARACTER, and the intermediate string is shorter than the maximum length of the target, the target is assigned the value of the intermediate string without trailing spaces if the target has the VARYING attribute. If the target does not have the VARYING attribute, the string is padded with trailing spaces.
  • If the maximum length of the target character string is less than the length of the intermediate string, the intermediate string is truncated.

The rules for how PL/I arrives at the intermediate string for conversion of each data type are described below. Examples illustrate the intermediate value as well as the resulting value.

Arithmetic to Character-String Conversions

The manner in which PL/I converts an arithmetic data item depends on the data type of the item, as described below.

Conversion from Fixed-Point Binary or Fixed-Point Decimal

If the data item source value is of type FIXED BINARY(p1,q1), PL/I first converts it to type FIXED DECIMAL(p2,q2), where:

p2 = min(ceil(p1/3.32)+1,31)

q2 = max(0,min(ceil(q1/3.32),31))

PL/I converts a value with attributes FIXED DECIMAL(p,q) to an intermediate string of length p+3. The numeric value is right-justified in the string. If the value is negative, a minus sign immediately precedes the value. If q is greater than zero, the value contains a decimal point followed by q digits. When p equals q, a 0 character precedes the decimal point. When q equals zero, a value of zero is represented by the 0 character.

Alternatively, the format of the intermediate string can be described by picture specifications, as follows:

  1. If q=0, the intermediate string is the string created by the following picture specification:

'BB(p)-9'

 

That is, the first two characters of the string are spaces. The last p characters in the string are the digit characters representing the integer; leading zeros are replaced by spaces except in the last position. If the integer is negative, a minus sign immediately precedes the first digit; if the number is not negative, this position contains a space. At least one digit always appears in the last position in the string.

  1. If p=q, the intermediate string is the string created by the following picture specification:

'-9V.(q)9'

 

That is, the first three characters are (in order) an optional minus sign if the fraction is negative, the digit 0, and a decimal point. If the number is not negative, the first character is a space. The last q characters in the string are the fractional digits of the number.

  1. If p > q, the intermediate string is the string created by the following picture specification:

'B(p-q)-9V.(q)9'

 

That is, the first character is always a space; the last q characters are the fractional digits of the number and are preceded by a decimal point; the decimal point is always preceded by at least one digit, which can be zero; all integral digits appear before the decimal point, and leading zeros are replaced by spaces; a minus sign precedes the first integral digit if the number is negative; if the number is not negative, then the minus sign is replaced by a space.

Examples

DECLARE STRING_1 CHARACTER (8),

STRING_2 CHARACTER (4);

 

STRING_1 = 283472.;

/* intermediate string = ' 283472',

STRING_1 = ' 28347' */

 

STRING_2 = 283472.;

/* intermediate string = ' 283472',

STRING_2 = ' 2' */

 

STRING_2 = -283472.;

/* intermediate string = ' -283472',

STRING_2 = ' -2' */

 

STRING_2 = -.003344;

/* intermediate string = '-0.003344',

STRING_2 = '-0.0' */

 

STRING_2 = -283.472;

/* intermediate string = ' -283.472',

STRING_2 = ' -28' */

 

STRING_2 = 283.472;

/* intermediate string = ' 283.472',

STRING_2 = ' 28' */

 

Conversion from Floating-Point Binary or Floating-Point Decimal

If the data item source value is of type FLOAT BINARY(p1), it is converted to FLOAT DECIMAL(p2), where:

p2 = min(ceil(p1/3.32),15)

For a value of type FLOAT DECIMAL(p), where p is less than or equal to 15, the intermediate string is of length p+6; this allows extra characters for the sign of the number, the decimal point, the letter E, the sign of the exponent, and the 2-digit exponent.

If the number is negative, the first character is a minus sign; otherwise, the first character is a space. The subsequent characters are a single digit (which can be 0), a decimal point, p-1 fractional digits, the letter E, the sign of the exponent (always + or -), and the exponent digits. The exponent field is of fixed length, and the zero exponent is shown as all zeros in the exponent field.

Examples

CONCH: PROCEDURE OPTIONS(MAIN);

 

DECLARE OUT PRINT FILE;

OPEN FILE(OUT) TITLE('CONCH.OUT');

 

PUT SKIP FILE(OUT) EDIT('''',25E25,'''') (A);

PUT SKIP FILE(OUT) EDIT('''',-25E25,'''') (A);

PUT SKIP FILE(OUT) EDIT('''',1.233325E-5,'''') (A);

PUT SKIP FILE(OUT) EDIT('''',-1.233325E-5,'''') (A);

 

END CONCH;

 

The program CONCH produces the following output:

'2.5E+26'

'-2.5E+26'

' 1.233325E-05'

'-1.233325E-05'

 

The PUT statement converts its output sources to character strings, following the rules described in this section. (The output strings are surrounded with apostrophes to make the spaces distinguishable.) In each case, the width of the quoted output field (that is, the length of the converted character string) is the precision of the floating-point constant plus 6.

Pictured to Character-String Conversion

If the source value is pictured, its internal, character-string representation is used without conversion as the intermediate character string.

Bit-String to Character-String Conversion

When PL/I converts a bit string to a character string, it converts each bit in the bit string (as represented by PUT LIST) to a 0 or 1 character in the corresponding position of the intermediate character string.

If the bit string is a null string, the intermediate character string is also a null string.

Examples

DECLARE STRING_1 CHARACTER (4),

STRING_2 CHARACTER (8);

 

STRING_1 = '1010'B;

/* STRING_1 = '1010' */

 

STRING_2 = '1010'B;

/* STRING_2 = '1010 ' */

 

STRING_1 = '010011'B;

/* STRING_1 = '0100' */

 

Assignments to Pictured Variables

A source expression of any computational type can be assigned to a pictured variable. The target pictured variable has a precision (p), which is defined as the number of characters in the picture specification that specify decimal digits. The target also has a scale factor (q) which is defined as the number of picture characters that specify digits and occur to the right of the V character in the picture specification. If the picture specification contains no V character, or if all digit-specification characters are to the left of V, then q is zero.

The source expression is converted to a fixed-point decimal value v of precision (p,q), following the PL/I rules for the source data type. This value is then edited to a character string s, as specified by the picture specification, and the value s is assigned to the pictured target.

When the value v is being edited to the string s, the CONVERSION condition is signaled if the value of v is less than zero and the picture specification does not contain one of the characters S, +, -, T, I, R, CR, or DB. The value of s is then undefined. FIXEDOVERFLOW is signaled if the value v has more integral digits than are specified by the picture specification of the target.

Conversions Between Offsets and Pointers

Offset variables are given values by assignment from existing offset values or from conversion of pointer values. Pointer variables are given values by assignment from existing pointer values or from conversion of offset values.

The OFFSET built-in function converts a pointer value to an offset value. The POINTER built-in function converts an offset value to a pointer.

PL/I also automatically converts a pointer value to an offset value, and vice versa, in an assignment statement. The following assignments are valid:

pointer-variable = pointer-value;

offset-variable = offset-value;

pointer-variable = offset-variable;

offset-variable = pointer-value;

 

In the third and fourth assignments above, the offset variable must have been declared with an area reference.

 

Procedures

A procedure is the basic executable program unit in PL/I. It consists of a sequence of statements, headed by a PROCEDURE statement and terminated by an END statement, that define an executable set of program instructions. There are three kinds of procedures:

See the Kednos PL/I for UNIX User's Manual for information on passing command-line input data to a program through the main procedure.

Subroutines and function procedures can be passed data from the invoking procedure by means of an argument list.

This chapter discusses the following topics:

PROCEDURE Statement

The PROCEDURE statement defines the beginning of a procedure block and specifies the parameters, if any, of the procedure. If the procedure is invoked as a function, the PROCEDURE statement also specifies the data type attributes of the value that the function returns to its point of invocation. The PROCEDURE statement can denote the beginning of either an internal or an external subroutine or function.

The format of the PROCEDURE statement is as follows:

entry-name

A 1- to 31-character identifier denoting the entry label of the procedure. The label cannot be subscripted. The PROCEDURE statement declares the entry name as an entry constant. The scope of the name is INTERNAL if the procedure is contained in any other block, and EXTERNAL if the procedure is not contained in any other block.

Unless you specify -m upper or --case=upper as an option to the pl1 command, do not declare a procedure or any other 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.

parameter,...

One or more parameters (separated by commas) that the procedure expects when it is activated. Each parameter specifies the name of a variable declared in the procedure headed by this PROCEDURE statement. The parameters must correspond, one-to-one, with arguments specified for the procedure when it is invoked with a CALL statement or in a function reference.

OPTIONS (option,...)

An option that specifies one or more options, separated by commas:

C

An option specifying that you can only use a C function to invoke the PL/I procedure at this entry point. The procedure is called using C calling conventions.

IDENT(string)

An option specifying a character-string constant giving the module ident for the listing and the object files. Only the first 31 characters of the string are recognized.

Each module should contain only one procedure with the IDENT option. Should there be more than one, the last specified indent will be the one used.

MAIN

An option specifying that the named procedure is the initial procedure in a program. The identifier of the procedure is the primary entry point for the program. The MAIN option is not allowed on internal procedures, and only one procedure in a program can have the MAIN option.

A program must have one procedure with OPTIONS(MAIN) in order for condition handling to work properly.

UNDERFLOW

An option that requests that the run-time system signal underflow conditions when they occur. By default, the run-time system does not signal these conditions.

RECURSIVE or NONRECURSIVE

An option that indicates (for program documentation) that the procedure will or will not be invoked recursively. In standard PL/I, the RECURSIVE option must be specified for a procedure to be invoked recursively. However, any procedure can be invoked recursively, and the RECURSIVE and NONRECURSIVE options are ignored by the compiler.

RETURNS (returns-descriptor)

An option specifying that the procedure is invoked by a function reference, as well as specifying the attributes of the function value returned. One of the possible attributes is TYPE. The syntax of the TYPE attribute is:

[(TYPE (reference))];

or

[(TYPE reference)];

 

RETURNS must be specified for functions. It is invalid for procedures that are invoked by CALL statements.

For valid return descriptors, see the RETURN statement section of See Terminating Procedures .

Functions and Function References

A function is a procedure that returns a value and that receives control when its name is referenced in an expression. There are two types of functions:

A user-written function must have the following elements:

For example:

ADDER: PROCEDURE (X,Y) RETURNS (FLOAT BINARY(24));

DECLARE (X,Y) FLOAT BINARY(24);

RETURN (X+Y);

END;

 

The function ADDER has two parameters, X and Y. They are floating-point binary variables declared within the function. When the function is invoked by a function reference, it must be passed two arguments to correspond to these parameters. It returns a floating-point binary value representing the sum of the arguments. The function ADDER can be referenced as follows:

TOTAL = ADDER(5,6);

 

The arguments in the reference to ADDER are converted to FLOAT.

If a function has no parameters, you must specify a null argument list; otherwise, the compiler treats the reference as a reference to an entry constant. Specify a null argument list as follows:

GETDATE = TIME_STAMP();

 

This assignment statement contains a reference to the function TIME_STAMP, which has no parameters.

This rule applies to PL/I built-in functions as well; however, if you declare a PL/I built-in function explicitly with the BUILTIN attribute, you need not specify the empty argument list. For example:

DECLARE P POINTER,

NULL BUILTIN;

P = NULL;

 

This example assigns a null pointer value to P. Without the declaration of NULL as a built-in function, the assignment statement would have been as follows:

P = NULL();

 

If you compile using the IBM dialect, you do not need to use empty parentheses to specify a null argument list. However, specifying them makes your code more transportable.

ENTRY Statement

The ENTRY statement defines an alternate entry point to a procedure. Its format is as follows:

entry-name

A 1- to 31-character label for the entry point. Specifying the entry name declares the name as an entry constant. The scope of the name is external if the ENTRY statement is contained in an external procedure, and is internal if it is contained in an internal procedure.

Unless you specify -m upper or --case=upper as an option to the pl1 command, do not declare a procedure or any other 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.

parameter, ...

One or more parameters that the procedure requires at this entry point. Each parameter specifies the name of a variable declared in the block to which this ENTRY statement belongs. The parameters must correspond, one to one, with arguments specified for the procedure when it is invoked via the ENTRY statement.

RECURSIVE or NONRECURSIVE

An option that indicates (for program documentation) that the procedure will or will not be invoked recursively. In standard PL/I, the RECURSIVE option must be specified for a procedure to be invoked recursively. However, any procedure can be invoked recursively, and the RECURSIVE and NONRECURSIVE options are ignored by the compiler.

RETURNS (returns-descriptor)

The RETURNS option gives the data type attributes of the function value returned for an entry that is invoked as a function reference.

One of the possible data type attributes is TYPE. The syntax of the TYPE attribute is:

[(TYPE (reference)];
 

or

[(TYPE reference];
 

For entry points that are invoked by function references, the RETURNS option is required; for procedures that are invoked by CALL statements, the RETURNS option is invalid.

Restrictions
  1. An ENTRY statement is not allowed in a begin block, in an ON-unit, or in a DO group except for a simple DO.
  2. You should avoid unnecessary use of ENTRY statements, because their effect is detrimental to the overall optimization of the program and they make debugging more complicated.

Specifying Entry Points

The entry points of a procedure are the points at which it can be invoked. The PROCEDURE statement specifies one entry point. You can specify additional entry points with ENTRY statements within the procedure block. ENTRY statements are allowed anywhere except as specified in the restrictions described in the above section.

The labels used on PROCEDURE and ENTRY statements declare those names as entry constants. The scope of the declarations is internal if the PROCEDURE and ENTRY statements appear in internal procedures, and external if they appear in external procedures.

You declare an entry name in the block containing the procedure to which the entry point belongs. For example:

P: PROCEDURE;

 

DECLARE E: ENTRY;

 

Q: PROCEDURE;

DECLARE E FIXED BINARY;

END Q;

 

END P;

 

The entry names E and Q are declared in procedure P. Within procedure Q, E is declared as a fixed-point binary variable. This does not conflict with the declaration of E as an entry in procedure P.

You can invoke an entry point by using the appropriate entry constant as the reference in a CALL statement or function reference. Invoking an entry point enters a procedure at the specified point and activates the procedure block that contains the entry point.

If the CALL statement or function reference invokes an entry point in an external procedure, the entry constant must be declared with the ENTRY attribute, as in See . Invoking an External Procedure . The declaration of an external constant must also describe the parameters for that entry point, if any. For example:

DECLARE PITCH ENTRY (CHARACTER(*), FIXED BINARY(15));

 

The identifier PITCH is declared as an entry constant. When the procedure containing this declaration is linked to other procedures, one of the external procedures must define an entry point named PITCH, either as the label of a PROCEDURE statement or as the label of an ENTRY statement.

The data type attributes in parentheses (called parameter descriptors) are the data types of the parameters that are defined elsewhere for the entry point PITCH. Arguments of these types must be supplied when PITCH is invoked.

If PITCH is to be used as a function, the DECLARE statement must also include a RETURNS attribute to describe the attributes of the returned value, as in the following example:

DECLARE PITCH ENTRY (CHARACTER(*), FIXED BINARY(15))

RETURNS(FIXED);

 

Within the scope of this DECLARE statement, the entry constant PITCH must be used in a function reference. The function reference will invoke the external entry point, and a returned fixed-point binary value will become the value of the function reference.

Multiple Entry Points

A procedure can be entered at more than one point. However, only one entry point can be specified by a PROCEDURE statement; additional entry points are declared with ENTRY statements.

The rules governing the declaration of multiple entry points follow:

  • A particular parameter need not be specified in all of a procedure's entry points (including the point defined by the PROCEDURE statement). However, a reference to the parameter is valid only if the procedure was invoked through one of the entries specifying the parameter.
  • In a procedure that has multiple entry points, a RETURN statement must be compatible with the entry point by which the procedure was invoked. If the entry point does not have a RETURNS option, the RETURN statement must not specify a return value. (In addition, it must be invoked as a "subroutine" -- that is, with the CALL statement.) If the entry point has a RETURNS option, the RETURN statement must specify a return value that is valid for conversion to the data type specified in the RETURNS option.
  • An ENTRY statement is not executable. If control reaches it sequentially, control immediately continues to the next statement.

The following example shows a procedure with two alternative entry points:

QUEUES: PROCEDURE(ELEMENT,QUEUE_HEAD);

 

ADD_ELEMENT: ENTRY(ELEMENT);

 

REMOVE_ELEMENT: ENTRY(ELEMENT);

 

This procedure can be entered by CALL statements that reference QUEUES, ADD_ELEMENT, or REMOVE_ELEMENT. If invoked at QUEUES, the procedure must be passed two parameters. If invoked at either of the alternative entries ADD_ELEMENT or REMOVE_ELEMENT, the procedure must be passed only one parameter.

When this procedure is entered at either alternative entry point, the entire block beginning at QUEUES is activated, but execution begins with the first executable statement following the entry point.

CALL Statement

The CALL statement transfers control to an entry point of a procedure and optionally passes arguments to the procedure. The format of the CALL statement is as follows:

CALL entry-name [(argument, ...)];

 
entry-name

The name of an external or internal procedure that does not have the RETURNS attribute. The entry name can also be an entry variable or a reference to a function that returns an entry value.

[(argument,...)]

The argument list to be passed to the called procedure. If specified, unless OPTIONS(VARIABLE) is specified in the declaration of an external entry name, the number of arguments must match the number of parameters in the parameter list of the invoked entry name. OPTIONS(VARIABLE) is valid only for use with non-PL/I procedures.

You must enclose arguments in parentheses. Multiple arguments must be separated by commas.

You can use the CALL statement to call an internal or external procedure. The following example illustrates a main procedure, CALLER, and a call to an internal procedure, PUT_OUTPUT. PUT_OUTPUT has two parameters, INSTRING and OUTFILE, that correspond to the arguments LINE and DEVICE specified in the CALL statement.

CALLER: PROCEDURE OPTIONS(MAIN);

CALL PUT_OUTPUT(LINE,DEVICE);

PUT_OUTPUT:PROCEDURE(INSTRING,OUTFILE);

END PUT_OUTPUT;

END CALLER;

Parameters and Arguments

A PL/I procedure can invoke other procedures, as well as pass values to and receive them from the invoked procedure. Values are passed to an invoked procedure by means of arguments written in the procedure invocation. Values are returned to the invoking procedure by means of parameters and also, in the case of functions, by specifying a value in the function's RETURN statement.

You can specify arguments for a subroutine (invoked by a CALL statement) or for a function (invoked by a function reference). Subroutines and functions return values by different means.

See . Parameters and Arguments illustrates the relationship between arguments (specified in a CALL statement) or function reference and parameters (specified in a PROCEDURE or ENTRY statement).

. Parameters and Arguments

CALLER:PROCEDURE;

DECLARE COMPUTER EXTERNAL ENTRY

(FIXED BINARY (7), CHARACTER (80) VARYING);

CALL COMPUTER (5,'ABC'); À

END CALLER;

COMPUTER:PROCEDURE (X,Y); Ã

DECLARE X FIXED BINARY (7); Õ

DECLARE Y CHARACTER (80) VARYING;

END COMPUTER;

 

The ENTRY attribute in a DECLARE statement provides a parameter descriptor for each parameter of the called procedure. A parameter descriptor is a set of data type attributes.

In a CALL statement or a function reference, arguments appear in parentheses following the name of the procedure. Arguments can be variables, expressions, aggregates, or (as in this example) constants.

The data type of each argument is matched with the corresponding parameter descriptor in the declaration of the entry.

The PROCEDURE statement for the called procedure specifies the parameters of the procedure. These parameters correspond, in the order specified, to the arguments specified in the CALL statement.

Each parameter specified in the PROCEDURE statement must be declared within the procedure.

A parameter is a variable that occurs in the parameter list of a PROCEDURE or ENTRY statement. When the procedure is invoked, each argument variable in the list is associated with a parameter. Within the called procedure, any reference to the parameter is equivalent to a reference to the associated argument variable.

If the invoked procedure is external to the invoking procedure, the attributes of the parameters must be described in parameter descriptors, which are part of the declaration of the external procedure.

An argument variable associated with a parameter is passed in a dummy argument if the argument is specified as a constant. References to that parameter in the invoked procedure do not modify any storage in the invoking procedure. For example:

TEST: PROCEDURE OPTIONS(MAIN);

 

DECLARE A FIXED BIN(31);

 

A = 100;

CALL SUBROUTINE(A,100);

PUT SKIP LIST (A,100);

END TEST;

 

SUBROUTINE: PROCEDURE(X,Y);

DECLARE (X,Y) FIXED BIN(31);

 

X = 101;

Y = 101;

 

END SUBROUTINE;

 

The result of this example is:

101 100

 

Rules for Specifying Parameters

The general rules listed below for specifying parameters are followed by specific rules that pertain only to certain data types.

  • You must declare a parameter explicitly in a DECLARE statement (to give it a data type) within the invoked procedure. This declaration must not be part of a structure.
  • You cannot declare a parameter with any of these attributes:
  • AUTOMATIC

    EXTERNAL

    READONLY

    BASED

    GLOBALDEF

    STATIC

    CONTROLLED

    GLOBALREF

     

    DEFINED

    INITIAL

     

  • You can specify up to 253 parameters for an entry point.
  • The parameters of an external entry must be explicitly specified by parameter descriptors in the declaration of the entry constant. The parameters of a procedure that is invoked through an entry variable must be specified by parameter descriptors in the ENTRY attribute of the variable's declaration. You cannot declare an internal entry (and its parameters) in the containing procedure.
  • Each parameter must have a corresponding argument at the time of the procedure's invocation. PL/I matches the data type of the parameter with the data type of the corresponding argument and creates a dummy argument if they do not match or if the parameter is a constant, expression, or is enclosed in parentheses.
Array Parameters

If the name of an array variable is passed as an argument, the corresponding parameter descriptor or parameter declaration must specify the same number of dimensions as the argument variable. You can declare the bounds of a dimension for an array parameter using asterisks (*) or optionally signed integer constants. If the bounds are specified with integer constants, they must match exactly the bounds of the corresponding argument.

An asterisk indicates that the bounds of a dimension are not known. (If one dimension contains an asterisk, all the dimensions must contain asterisks.) For example:

DECLARE SUMUP ENTRY ((*) FIXED BINARY);

 

This declaration indicates that SUMUP's argument is a one-dimensional array of fixed-point binary integers that can have any number of elements. Any one-dimensional array of fixed-point binary integers can be passed to this procedure.

All the data type attributes of the array argument and parameter must match.

Arrays are always passed by reference. They cannot be passed by dummy argument.

Structure Parameters

If the name of a structure variable is passed as an argument, the corresponding parameter descriptor or declaration must be identical, in terms of structure levels, members' sizes, and members' data types. The level numbers do not have to be identical, but the levels must be logically equivalent. You can specify array bounds and string lengths with asterisks or with optionally signed integer constants.

The following example shows the parameter descriptor for a structure variable:

DECLARE SEND_REC ENTRY (1,

2 FIXED BINARY(31),

2 CHARACTER(40) VARYING,

2 FIXED DECIMAL (8,2));

 

The written argument in the invocation of the external procedure SEND_REC must have the same structure, and its members must have the same data types.

You must pass structures by reference. They cannot be passed by dummy argument.

Character-String Parameters

If a character-string variable is passed as an argument, the corresponding parameter descriptor or parameter declaration can specify the length using an asterisk (*) or an optionally signed nonnegative integer constant. For example:

COPYSTRING: PROCEDURE (INSTRING,COUNT);

DECLARE INSTRING CHARACTER(*);

 

The asterisk in the declaration of this parameter indicates that the string can have any length. The string is fixed length unless VARYING is also included in the declaration.

Entry, File, and Labels Parameters

An entry, file, or label can be passed as an argument. The actual parameter is a variable.

Argument Passing

This section describes how PL/I passes an argument to procedures written in PL/I.

Number of Arguments

The number of arguments in the argument list must equal the number of parameters of the invoked entry point. The compiler checks that the count matches as follows:

  • For an internal procedure, the compiler checks the number of arguments in the argument list against the number of parameters on the PROCEDURE or ENTRY statement for the internal procedure.
  • For an external procedure, the compiler checks that the number of parameter descriptors in the ENTRY declaration list matches the number of arguments in the procedure invocation.

To specify arguments for a subroutine or function, enclose the arguments in parentheses following the procedure or entry-point name. For example, you can write a procedure call as follows:

CALL COMPUTER (A,B,C);

 

The variables A, B, and C in this example are arguments to be passed to the procedure COMPUTER. The procedure COMPUTER might have a parameter list like this:

COMPUTER: PROCEDURE (X, Y, Z);

DECLARE (X,Y,Z) FLOAT;

 

The parameters X, Y, and Z, specified in the PROCEDURE statement for the subroutine COMPUTER, are the parameters of the subroutine. PL/I establishes the equivalence of the arguments A, B, and C to the parameters X, Y, and Z.

Actual Arguments

When a PL/I procedure is invoked, each of its parameters is associated with a variable determined by the corresponding written argument of the procedure call. This variable is the actual argument for this procedure invocation. It can be one of the following:

  • A reference to the written argument
  • A dummy argument

The data type of the actual argument is the same as that of the corresponding parameter. When a written argument is a variable reference, PL/I matches the variable against the corresponding parameter's data type according to the rules described under See Argument Matching . If they match, the actual argument is the variable denoted by the written argument. That is, the parameter denotes the same storage as the written variable reference. If they do not match, the compiler creates a dummy argument and assigns to it the value of the written argument.

Dummy Arguments

A dummy argument is a unique temporary variable allocated by the compiler, which exists only for the duration of the procedure invocation.

When the written argument is a constant or an expression, the actual argument is always a dummy argument. The value of the written argument is assigned to the dummy argument following the rules of data type conversion before the call (this is described later). The data type of the written argument must be valid for assignment to the data type of the dummy argument.

Aggregate Arguments

An array, structure, or area argument must be a variable reference that matches the corresponding parameter. It cannot be a reference to an unconnected array. A dummy argument is never created for an array, structure, or area.

Argument Matching

A written argument that is a variable reference is passed by reference only if the argument and the corresponding parameter have identical data types:

  • For an internal procedure, the attributes of the argument must match those specified in the declaration of the parameter.
  • For an external procedure or a procedure invoked through an ENTRY variable, the attributes specified in the ENTRY attribute parameter descriptor must match those of the arguments.

When the compiler detects that a scalar variable argument does not match the data type of the corresponding parameter, it issues a warning message, creates a dummy argument, and associates the address of the dummy argument with the corresponding parameter. You can suppress the warning message and force the creation of a dummy argument if you enclose the argument in parentheses. For example, if a parameter requires a character varying string and an argument is a character nonvarying variable, you would enclose the variable in parentheses.

For string lengths and array bounds, an asterisk (*) in the parameter matches any expression. An integer constant matches only an integer constant with the same value.

Conversion of Arguments

When the data type of a written argument is suitable for conversion to the data type of the corresponding parameter descriptor, PL/I performs the conversion of the argument to a dummy argument using the rules described in See Data Type Conversion of Operands and Expressions .

Calling External and Internal Procedures

An external procedure is one whose text is not contained in any other block. The source text of an external procedure can be compiled separately from that of a calling procedure. The differences between internal and external procedures are as follows:

You cannot explicitly declare internal procedures. The procedure name is implicitly declared by its occurrence in the PROCEDURE or ENTRY statement.

An internal procedure, on the other hand, can reference internal variables declared in any procedure in which it is contained.

An internal procedure can be called only by the procedure that contains it or by other procedures at the same level of nesting within the containing procedure. The only exception is invocation through an entry variable.

The following example illustrates the use of an internal procedure:

. Invoking an Internal Procedure

MAINP: PROCEDURE OPTIONS (MAIN);

COMPUTE: PROCEDURE;

ADD_NUMBERS: PROCEDURE;

END ADD_NUMBERS;

END COMPUTE;

PRINT_REPORT: PROCEDURE;

END PRINT_REPORT;

END MAINP;

 

In See . Invoking an Internal Procedure , the procedures COMPUTE and PRINT_REPORT are internal to the procedure MAINP, and the procedure ADD_NUMBERS is internal to the procedure COMPUTE. MAINP can invoke the procedures COMPUTE and PRINT_REPORT, but not ADD_NUMBERS. COMPUTE and PRINT_REPORT can invoke one another. ADD_NUMBERS can call COMPUTE and PRINT_REPORT.

The following example illustrates the use of an external procedure:

. Invoking an External Procedure

WINDUP: PROCEDURE;

DECLARE PITCH EXTERNAL ENTRY (CHARACTER(15) VARYING,

FIXED BINARY(7) );

CALL PITCH (PLAYER_NAME,NUMBER_OF_OUTS);

 

The procedure WINDUP declares the procedure PITCH with the EXTERNAL and ENTRY attributes. The text of PITCH is in another source program that is separately compiled. When the object module that contains WINDUP is linked, the linker must be able to locate the object module that contains PITCH. You can accomplish this by including both object modules on the linker command line, or by placing PITCH in an object module library and including the library on the linker command line.

When a CALL statement or function reference invokes an entry point in an external procedure, the entry constant must be declared with the ENTRY attribute, as in the example above. Such a declaration must also describe the parameters for that entry point, if any. For example:

DECLARE PITCH ENTRY (CHARACTER(*), FIXED BINARY(15));

 

The identifier PITCH is declared as an entry constant. When the procedure containing this declaration is linked to other procedures, one of them must define an entry point named PITCH as the label either of a PROCEDURE statement or an ENTRY statement. If the linker cannot locate an external entry point, it issues a warning message.

The parameter descriptors define the data types of the parameters for the entry point PITCH. Arguments of these types must be supplied when PITCH is invoked.

If PITCH is to invoke a function, the DECLARE statement must also include a RETURNS attribute describing the attributes of the returned value, as follows:

DECLARE PITCH ENTRY (CHARACTER(*), FIXED BINARY(15))

RETURNS(FIXED);

 

Within the scope of this DECLARE statement, the entry constant PITCH must be used in a function reference. The function reference will invoke the external entry point, and a returned fixed-point binary value will become the value of the function reference.

A PL/I program can invoke an external procedure that is not written in PL/I. A common instance is the use of a system service by a PL/I program to obtain some system function not available directly through PL/I. Or, a PL/I program can invoke an external procedure written in another language that provides an application- specific function. Such instances are possible because Kednos PL/I for UNIX follows common language calling standards, as defined by the target platform.

Terminating Procedures

The execution of subroutines and functions can be terminated with the following statements:

If an END statement closes the procedure block of a subroutine before a RETURN or STOP statement is executed, the END statement has the same effect as RETURN. A function cannot be terminated without a RETURN statement. See See END Statement for more information.

A GOTO statement that transfers control to a label that is outside the current block terminates a subroutine or a function. The label specified on the GOTO statement must be known within the block that contains the GOTO statement, and the block containing the specified label must be active when the GOTO is executed. See See GOTO Statement for more information.

A STOP statement ends the entire program execution. It does not pass a return value. See See STOP Statement for more information.

A RETURN statement provides a normal termination for a subroutine or function. For a function, a RETURN statement must specify a return value. The rest of this section describes the RETURN statement.

RETURN Statement

The RETURN statement terminates execution of the current procedure. The format of the RETURN statement is as follows:

RETURN [ (return-value) ];

 
return-value

The value to be returned to the invoking procedure. If the current procedure was invoked by a function reference, a return value must be specified. If the current procedure was invoked by a CALL statement, a return value is invalid.

A return value can be any scalar arithmetic, bit-string, or character-string expression; it can also be an entry, pointer, or label expression or other noncomputational expression. The return value must be valid for conversion to the data type specified in the RETURNS option of the function.

The action taken by the RETURN statement depends on the context of the procedure activation, as follows:

  • If the current procedure is the main or only active procedure, the RETURN statement terminates the program.
  • If the current procedure was activated by a CALL statement, the next executable statement in the calling procedure is executed.
  • If the current procedure was activated by a function reference, control returns to continue the evaluation of the statement that contained the function reference.
  • If the RETURN statement is executed in a begin block, control returns from the containing procedure to the calling procedure.
Restrictions

The RETURN statement must not be immediately contained in an ON-unit or in a begin block that is immediately contained in an ON-unit.

Passing Arguments to Non-PL/I Procedures

There are two ways that a PL/I procedure can pass an argument to a non-PL/I procedure:

The following sections describe the requirements for each of these argument-passing mechanisms.

For more information on passing arguments to C programs, see the DEC OSF/1 Calling Standard For Axp Systems manual, available from Digital Equipment Corporation.

Passing Arguments by Immediate Value

To pass an argument by immediate value, 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 immediate value.

DECLARE VHF ENTRY (FIXED BINARY(31) VALUE);

 

You can also define PL/I procedures that receive arguments by immediate value. To do this, you must specify the VALUE attribute in the declaration of the parameter. For example, the corresponding definition of the procedure VHF would be as follows:

VHF: PROCEDURE (LENGTH);

 

DECLARE LENGTH FIXED BINARY(31) VALUE;

 

 

Arguments that can be passed by immediate value are limited to the following data types:

  • FIXED BINARY(m), where m <= 31
  • FLOAT BINARY(n), where n <= 53
  • BIT(o) ALIGNED, where o <= 32
  • ENTRY
  • OFFSET
  • POINTER

PL/I supports the passing of external procedures, but not internal procedures, as value parameters. To pass an internal procedure, use an entry parameter.

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 SETEF can appear as follows:

DECLARE SETEF ENTRY (ANY VALUE);

 

At the time of the procedure's invocation, PL/I converts the written argument as needed to create a longword dummy argument.

Passing Arguments by Reference

By default, PL/I passes all arguments by reference except character strings and arrays with nonconstant extents. The parameter descriptor for an argument to be passed by reference need specify only the data type of the parameter.

For example, you need to call a program that requires its first argument to be passed by immediate value and its second by reference. You could declare this procedure as follows:

DECLARE READEF ENTRY (FIXED BINARY(31) VALUE,

BIT (32) ALIGNED);

 

When the procedure is invoked, the second argument must be a variable declared as BIT(32) ALIGNED. PL/I passes the argument by reference.

An argument of any data type can be passed by reference. Bit-string variables, however, must have the ALIGNED attribute.

The data types in the parameter descriptors of all output arguments must match the data types of the written arguments. For convenience, you can specify ANY in the parameter descriptor. To describe an argument to be passed by reference, you can specify the ANY attribute without the VALUE attribute. 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 immediate 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. However, note that when you use the ANY attribute you cannot take advantage of the semantic type checking normally done by PL/I.

When an argument is passed by reference, PL/I passes the address of the actual argument. This address can be interpreted as a pointer value; you can explicitly specify a pointer value as an argument for data to be passed by reference; for example:

DECLARE GETHOSTNAME ENTRY (POINTER VALUE, ANY VALUE);

DECLARE HOSTNAME CHARACTER (6);

 

CALL GETHOSTNAME(ADDR(HOSTNAME), 6);

 

At this procedure invocation, PL/I places the pointer value returned by the ADDR built-in function directly in the argument list.

 

Program Control

The statements described in this chapter direct the run-time flow of execution from statement to statement. They are the DO, BEGIN, END, IF, SELECT, GOTO, LEAVE, STOP, null, ON, SIGNAL, and REVERT statements.

The remainder of the chapter describes how to handle conditions that arise during the execution of your program.

DO Groups and Statements

A DO-group is a sequence of PL/I statements delimited by a DO statement and its corresponding END statement. The DO statement begins a sequence of statements to be executed in a group; the group ends with the nonexecutable END statement; the group contains one or more statements between the DO and END statements.

For example:

IF BIRTH_YEAR > CURRENT_YEAR
THEN DO;

PUT SKIP LIST ('Birth year cannot be in the future.');

GOTO GET_BIRTH_YEAR;

END;

 

The statements in a DO-group are executed as the result of an unconditional DO statement or as the result of the successful test of a conditional DO. When the executable statements in this conditional DO-group are complete, execution continues with the next executable statement following the END statement.

You can nest DO-groups inside each other to a maximum level of 64.

Normally, all the statements contextually nested one level below the DO in the group are executed. However, control can be transferred out of a DO-group in the following ways:

DO-groups have several formats. These formats are described individually under the following subheadings:

Simple DO

A simple DO statement is a noniterative DO. The statements nested directly between the DO statement and its corresponding END statement are executed once. PL/I treats these nested statements as if they are one statement. After all statements in the group are executed, control passes to the next executable statement in the program.

The format of a simple DO statement is:

DO;

 

END;

 
Examples

IF A < B THEN DO;

PUT LIST ('more data needed');

GET LIST (VALUE);

A = A + VALUE;

END;

 

The simple DO statement is commonly used as the action of the THEN clause of an IF statement, as shown above, or of an ELSE option.

DO WHILE

A DO WHILE statement causes a group of statements to be repeatedly executed as long as a particular condition is satisfied. When the condition is not true, the group is not executed.

The format of the DO WHILE statement is:

DO WHILE (test-expression);

 

END;

 
test-expression

Any expression that yields a scalar value. If any bit of the value is a 1, then the test expression is true; otherwise, the test expression is false. The test expression must be enclosed in parentheses. (Comparison operations yield a value with the type BIT(1).)

This expression is evaluated before each execution of the DO-group. It must have a true value in order for the DO-group to be executed. Otherwise, control passes over the DO-group to the next executable statement following the END statement that terminates the group.

Examples

DO WHILE (A < B);

 

END;

 

This DO-group is executed as long as the value of the variable A is less than the value of the variable B.

DO WHILE (LIST->NEXT ^= NULL());

 

END;

 

This DO-group is executed until a forward pointer in a linked list has a null value.

DECLARE EOF BIT(1) INITIAL('0'B);

 

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

READ FILE(INFILE) INTO(INREC);

DO WHILE (^EOF);

 

READ FILE(INFILE) INTO(INREC);

END;

 

This DO-group reads records from the file INFILE until the end of the file is reached. At the beginning of each iteration of the DO-group, the expression ^EOF is evaluated; the expression is '1'B until the ENDFILE ON-unit sets the value of EOF to '1'B.

DO UNTIL

A DO UNTIL statement causes a group of statements to be repeatedly executed until a particular condition is satisfied. That is, while the condition is false, the group is repeated.

The format of the DO UNTIL statement is:

DO UNTIL (test-expression);

 

END;

 
test-expression

Any expression that yields a scalar value. If any bit of the value is 1, then the test expression is true; otherwise the test expression is false. The test expression must be enclosed in parentheses. (Comparison operations yield a value having the type BIT(1).)

This expression is evaluated after each execution of the DO-group. It must have a false value for the DO-group to be repeated. Otherwise, control passes to the next executable statement following the END statement that terminates the DO-group. The test expression must be enclosed in parentheses.

  • Both the WHILE and UNTIL options check the status of test expressions, but they differ in that the WHILE option tests the value of the test expression at the beginning of the DO- group, and UNTIL tests the value of the test expression at the end of the DO-group. Therefore, a DO-group with the UNTIL option and no WHILE option will always be executed at least once, but a DO-group with the WHILE option may never be executed.
Examples

DO UNTIL (A=0);

 

END;

 

This DO-group is executed at least once and continues as long as the value of A is not equal to zero.

DO UNTIL (K < ALPHA);

 

END;

 

This DO-group is executed at least once and continues as long as the value of the variable K is greater than or equal to the value of the variable ALPHA.

DO REPEAT

The DO REPEAT statement executes a DO-group repetitively for different values of a control variable. The control variable is assigned a start value that is used on the first iteration of the group. The REPEAT expression is evaluated before each subsequent iteration, and its result is assigned to the control variable. A WHILE clause can also be included. If it is included, the WHILE expression is evaluated before each iteration (including the first), but after the control variable has been assigned. The format of the DO REPEAT statement is:

DO variable = start-value REPEAT expression

[WHILE (test-expression)] [UNTIL (test-expression)];

 

END;

 
variable

A reference to a control variable. The control variable can be any scalar variable.

start-value

An expression specifying the initial value to be given to the control variable. The evaluation of this expression must yield a value that is valid for assignment to the control variable.

expression

An expression giving the value to be assigned to the control variable on reiterations of the DO REPEAT group. The expression is evaluated before each iteration after the first. Evaluation of this expression must yield a result that is valid for assignment to the control variable.

WHILE (test-expression)

An option specifying a condition that controls the termination of the DO REPEAT group. The DO REPEAT group continues while the condition is true. The specified test expression must yield a scalar value. If any bit of the value is 1, then the test expression is true; otherwise, the test expression is false. The test expression must be enclosed in parentheses.

This expression is evaluated each time control reaches the DO statement; the test expression must have a true value in order for the DO-group to be executed. Otherwise, control passes to the next executable statement following the END statement that terminates the DO-group.

See See Controlled DO for a discussion of this option when used with the controlled DO statement.

UNTIL (test-expression)

An option specifying a condition that further controls the termination of the DO REPEAT group. The DO REPEAT group continues until the condition is true. The specified test expression must yield a scalar value. If any bit in the value is 1, then the test expression is true; otherwise, the test expression is false. The test expression must be enclosed in parentheses.

This expression is evaluated after the first execution of the DO-group; the test expression must have a true value in order for the DO-group to be executed a second time. Otherwise, control passes to the next executable statement following the END statement that terminates the DO-group.

  • If the WHILE and UNTIL options are omitted, the DO REPEAT statement specifies no means for terminating the group; the execution of the group must be terminated by a statement or condition occurring within the group.

A DO REPEAT group is executed by the following steps:

  1. The following measures are taken to prevent the allocation of a new control variable during the execution of the DO-group:
  2. If the control variable is based, its pointer qualifier is evaluated and a temporary reference of the control variable type is created. The temporary reference is used as the control variable in subsequent steps.
  3. If the control variable is subscripted, its subscripts are evaluated and a temporary reference of the control variable type is created. The temporary reference is used as the control variable in subsequent steps.
  4. If the control variable is neither based nor subscripted, its reference is used in subsequent steps.
  5. The start value expression is evaluated and assigned to the control variable.
  6. If a WHILE option is present, its test expression is evaluated. If it does not produce a true value, the execution of the DO-group terminates. If the test expression is not present, execution continues.
  7. The body of the DO-group is executed. The execution of the DO-group may be terminated during this step by the execution of a STOP or RETURN statement or by the execution of a GOTO or LEAVE statement that transfers control outside the DO-group. Statements in the group can also modify the values of the control variable, REPEAT expression, and test expression.
  8. If an UNTIL option is present, its test expression is evaluated. If it produces a true value, the execution of the DO-group terminates. If the test expression is not present, execution continues.
  9. The REPEAT expression is evaluated and its value is assigned to the control variable.
  10. Execution continues at step 3.
Examples

DO LETTER='A' REPEAT (BYTE(I));

 

The preceding example will repeat the group with an initial LETTER value of 'A' and with subsequent values assigned by the built-in function BYTE(I). The control variable I can be assigned new values within the group. The group will iterate endlessly unless terminated by a statement or condition within the group.

DO I = 1 REPEAT (I + 2) WHILE ( I <= 100 );

 

The preceding example has the same effect as the following controlled DO statement:

DO I = 1 TO 100 BY 2;

 

The most common use of the DO REPEAT statement is in the manipulation of lists. For example:

DO P = LIST_HEAD REPEAT (P->LIST.NEXT)

WHILE ( P ^= NULL() );

 

In the preceding example, the pointer P is initialized with the value of the pointer control variable LIST_HEAD. The DO-group is then executed with this value of P. The REPEAT option specifies that each time control reaches the DO statement after the first execution of the DO-group, P is to be set to the value of LIST.NEXT in the structure currently pointed to by P.

Controlled DO

A controlled DO statement identifies a variable whose value controls the execution of the DO-group and defines the conditions under which the control variable is to be modified and repeatedly tested.

The format of the controlled DO statement is:

control-variable

A reference to a variable whose current value, as compared to the end value specified in the TO option, determines whether the DO-group is executed. If none of the options are specified, the DO-group is executed a single time regardless of the value of the control variable. The control variable must be of an arithmetic data type.

start-value

An expression specifying the initial value to be given to the control variable. Evaluation of this expression must yield an arithmetic value.

end-value

An expression giving the value to be compared with the control variable during successive iterations. Evaluation of this expression must yield an arithmetic value. This expression is evaluated exactly once when the statement is executed for the first time. Thus if the end value changes as the loop progresses, only this initial value is used.

If you specify the BY option and do not specify the TO option, execution repeats until terminated by the WHILE or UNTIL option or until a statement in the do-group transfers control out of the do-group.

modify-value

An expression giving a value by which the control value is to be modified. Evaluation of this expression must yield an arithmetic value. This expression is evaluated exactly once when the statement is executed for the first time. Thus if the modify value changes as the loop progresses, only this initial value is used. If you do not specify the BY option, the modify value defaults to 1.

REPEAT repeat-expression

An option that executes a DO-group repetitively for different values of a control variable. The repeat-expression gives the value that is assigned to the control variable on reiterations of the DO REPEAT group. The expression is evaluated before each iteration after the first iteration. Evaluation of this expression must yield a result that is valid for assignment to the control variable. See See DO REPEAT for more information.

WHILE (test-expression)

An option specifying a condition that further controls the execution of the DO-group. The condition must be true at the beginning of each DO-group iteration for the DO-group to be executed. The specified test expression must yield a scalar value. If any bit in the value is a 1, then the test expression is true; otherwise, the test expression is false. The test expression must be enclosed in parentheses.

UNTIL (test-expression)

An option specifying a condition that further controls the execution of the DO-group. This expression is evaluated at the end of each iteration of the DO-group, before the BY clause is applied to the control variable. The condition must be false at the end of a DO-group execution for the next DO-group iteration to be executed. The specified test expression must yield a scalar value. If any bit in the value is a 1, then the test expression is true; otherwise, the test expression is false. The test expression must be enclosed in parentheses.

  • If you omit the TO, WHILE, and UNTIL options, the controlled DO statement specifies no means for terminating the group. In this case, you must include a statement or condition in the do-group to terminate execution of the group.
Example

This DO-group prompts the user for integer input values and adds each input value to the current sum. When the sum exceeds 100, the DO-group exits.

DECLARE (NEXT_VALUE,SUM) FIXED BIN;

 

SUM = 0;

DO UNTIL ( SUM > 100 );

GET LIST (NEXT_VALUE) OPTIONS

PROMPT ('Next value to add? '));

SUM = SUM + NEXT_VALUE;

END;

 

PUT SKIP LIST ('The total sum is ',SUM);

 

The controlled DO-group is executed by the following steps:

  1. The following measures are taken to prevent the allocation of a new control variable during the execution of the DO-group:
  2. If the control variable is based, its pointer qualifier is evaluated and a temporary reference of the control variable type is created. The temporary reference is used as the control variable in subsequent steps.
  3. If the control variable is subscripted, its subscripts are evaluated and a temporary reference of the control variable type is created. The temporary reference is used as the control variable in subsequent steps.
  4. If the control variable is neither based nor subscripted, its reference is used in subsequent steps.
  5. The start value expression is evaluated and assigned to the control variable. The expressions specified in the TO and BY options (if specified) are evaluated, and their values are stored. These expressions can contain references to the object referenced by the control variable. If they do, the original reference, not the temporary reference, is used in evaluation of the expressions.
  6. If the TO option is present, the value of the control variable is compared with the end value specified in the TO option. Otherwise, this step is skipped. Execution of the DO-group terminates if either of the following is true:
  7. The modify value is greater than zero and the control variable is greater than the end-value.
  8. The modify value is less than zero and the control variable is less than the end value.

If this step terminates the DO-group on the first iteration, the control variable has a final value assigned by the start value. If the group is terminated on a subsequent iteration, the control variable has a final value assigned by step 6.

  1. If a WHILE option is present, its test expression is evaluated. If it does not produce a true value, the execution of the DO-group terminates.
  2. The body of the DO-group is executed. The execution of the DO-group can be terminated during this step by the execution of a STOP or RETURN statement or by the execution of a GOTO or LEAVE statement that transfers control out of the DO-group.

The body of the DO-group can also contain statements that change the values of the control variable, modify value, end value, or test expression. Changing the modify value or the end value in the body of the loop will not affect the number of times the loop is iterated. However, changing the value of the control variable or the test expression can affect the number of iterations if the control variable was not made into a temporary by step 1.

  1. If an UNTIL option is present, its test expression is evaluated. If it produces a true value, the execution of the DO-group terminates.
  2. Unless none of the options are specified, the value of the control variable is modified as follows:

control variable = control variable + modify value;

 

  1. Execution continues at step 3 unless none of the options are specified, in which case control passes to the next executable statement in the program.
Examples

DO I = 2 TO 100 BY 2;

 

This DO-group is executed 50 times, with values for I of 2, 4, 6, and so on.

DO I = LBOUND(ARRAY,1) TO HBOUND(ARRAY,1);

 

This DO-group is executed as many times as there are elements in the array variable ARRAY, using the subscript values of the array's elements for the values of I.

DO I = 1 BY 1 WHILE (X < Y);

 

This DO-group continues to be executed with successively higher values for I while the value of X is less than the value of Y.

DO I = 1 BY 1 WHILE (X < Y) UNTIL (X = 12);

 

This DO-group resembles the DO-group in the preceding example, except that the DO-group continues to be executed while the value of X is less than the value of Y or until the value of X is equal to 12.

A controlled DO statement that does not specify a TO or BY option results in a single iteration of the following DO-group. For example:

DO X = 1 WHILE (A);

 

Even if A is true, this DO-group executes a single time only. If A is false, it is not executed at all. Because there is no expression to change the value of X, the DO-group will not be executed again.

DO X = 1;

 

This DO-group executes a single time only, regardless of the value of X.

BEGIN Statement

The BEGIN statement denotes the start of a begin block.

The format of the BEGIN statement is:

BEGIN;

 

A begin block is a sequence of statements headed by a BEGIN statement and terminated by an END statement. A begin block can be used wherever a single executable statement is valid, for instance, in an ON-unit. The statements in a begin block can be any PL/I statements, and begin blocks can contain DO-groups, DECLARE statements, procedures, and other (nested) begin blocks.

A begin block provides a convenient way to localize variables. Variables declared as internal within a begin block are not allocated storage until the block is activated. When the block terminates, storage for internal automatic variables is released. A begin block terminates in the following situations:

  • When its corresponding END statement is encountered. Control continues with the next executable statement in the program.
  • When it executes a nonlocal GOTO to transfer control to a previous block.
  • When it executes a RETURN statement.

A begin block differs from a DO-group chiefly in its ability to localize variables. Variables declared within DO-groups are not localized to the group (unless the group contains a begin block or procedure that declares internal variables). Begin blocks are preferable when you want to restrict the scope of variables. Furthermore, there are some cases (such as ON-units) in which DO-groups cannot be used. Otherwise, DO-groups are often more efficient, because they do not have the overhead associated with block activation. In general, you should use a DO-group instead of a begin block unless there are declarations present or you require multiple statements in an ON-unit.

A begin block can designate a series of statements to be executed depending on the success or failure of a test in an IF statement. For example:

IF A = B THEN BEGIN ;

END;

 

A begin block also provides the only way to denote a series of statements to be executed when an ON condition is signaled. For example:

ON ERROR BEGIN;

[statement ... ]

END;

 

See See Blocks for more information.

END Statement

The END statement marks the end of the block or group headed by the most recent BEGIN, DO, SELECT, or PROCEDURE statement.

The format of the END statement is:

END [label-reference];

 
label-reference

A reference to the unsubscripted label on the PROCEDURE, BEGIN, SELECT, or DO statement for which the specified END statement is the termination. A label is not required. If specified, the label reference must match only one label, which is the label of the most recent BEGIN, DO, SELECT, or PROCEDURE statement that is not already matched with an END statement. If the label reference is omitted, the most recent textual, non-terminated PROC, BEGIN, SELECT, or DO statement is matched by default.

Note that a procedure declared with the RETURNS option must execute a RETURN statement before it encounters the END statement marking the end of the procedure.

When the END statement is encountered, one of the following actions is performed, depending on the type of block or group that it terminates:

  • When an END statement denotes the end of a procedure, the procedure is terminated. The storage allocated for the block is released, and all automatic variables are made inaccessible. If the current procedure is the main or only procedure, the program terminates. Otherwise, control returns to the statement following the CALL statement or function invocation that invoked the procedure.
  • When an END statement denotes the end of a begin block, the block is terminated. Storage allocated for the block is released, and all automatic variables are made inaccessible. Control passes to the next executable statement.
  • When an END statement denotes the end of a DO-group, control returns either to the DO statement that heads the group or to the next executable statement following the END statement. If the DO-group is headed by a simple DO, that is, one that causes the DO-group to be executed only once, control passes to the next executable statement. Otherwise, control returns to the head of the DO-group.
  • When an END statement denotes the end of a SELECT-group, the SELECT-group is terminated and control passes to the next executable statement following the end statement.

IF Statement

The IF statement tests an expression and performs a specified action if the result of the test is true.

The format of the IF statement is:

IF test-expression THEN action [ELSE action];

 
test-expression

Any valid expression that yields a scalar bit-string value. If any bit of the value is 1, then the test expression is true; otherwise, the test expression is false.

action

Any of the following:

  • Any unlabeled statement except the nonexecutable statements: DECLARE, END, ENTRY, FORMAT, or PROCEDURE
  • An unlabeled DO-group or begin block

The IF statement evaluates the test expression. If the expression is true, the action specified following the keyword THEN is executed. Otherwise, the action, if any, specified following the ELSE keyword is executed.

Examples

IF A < B THEN BEGIN;

 

The begin block following this statement is executed if the value of the variable A is less than the value of the variable B.

IF ^SUCCESS

THEN

CALL PRINT_ERROR;

ELSE

CALL PRINT_SUCCESS;

 

The IF statement defines the action to be taken if the variable SUCCESS has a false value (the THEN clause) and the action to be taken otherwise (the ELSE clause).

Nested IF Statements

The action specified in a THEN or an ELSE clause can be another IF statement.

An ELSE clause is matched with the nearest preceding IF/THEN that is not itself matched with a preceding ELSE. For example:

IF ABC

THEN

IF XYZ

THEN

GOTO GBH;

ELSE

GOTO THESTORE;

ELSE

GOTO HOME;

 

In this example, the first ELSE clause is executed if ABC is true and XYZ is false. The second ELSE clause is executed if ABC is false.

In some cases, proper matching of IF and ELSE can require a null statement (a semicolon) as the target of an ELSE. For example:

IF ABC

THEN

IF XYZ

THEN

GOTO HOME;

ELSE;

ELSE

GOTO THESTORE;

 

In this example, the ELSE GOTO THESTORE statement is executed if ABC is false.

SELECT Statement

The SELECT statement tests a series of expressions and performs a specified action depending on the result of the test. The statement has two forms: in the first form, the expressions in a WHEN clause are tested for truth; in the second form, the expressions in a WHEN clause are compared to see if any have the same value as another specified expression called the select expression. Any of the expressions can be, but need not be, constants. An optional OTHERWISE clause is available to name an action to be performed if none of the preceding expressions have satisfied the condition specified.

The two forms of the SELECT statement and the OTHERWISE clause are described in more detail below.

The general form of the SELECT statement is:

SELECT [(select-expression)];

[WHEN [ANY | ALL] (case-expression, ...) [action] ; ] ...

[(OTHERWISE | OTHER) [action] ; ]

END;

 
select-expression

An expression that can be evaluated to any type of value.

case-expression, ...

One or more expressions to be tested, evaluating to bit-string values, or, if a select expression is used, with values that will be compared to the select expression's value.

action

Any statement (including a null statement, another SELECT statement, a DO-group, or a BEGIN-END block) except a DECLARE, END, ENTRY, FORMAT, or PROCEDURE statement.

The Two Forms of the SELECT Statement

Depending on whether you use a select expression or not, SELECT has two different forms, which are explained in detail below.

SELECT Without a Select Expression

The first form of the SELECT statement omits the select expression. In this form, the expressions in a WHEN clause are evaluated, and a specified action is performed if the result of any test is true (or, if ALL is specified, the results of all tests are true); an expression is true if it evaluates to a bit string containing any bit with the value of '1'B. In the usual case, the test for truth results in a bit string containing one bit: '1'B for true or '0'B for false.

When the keyword ANY (the default) appears in the WHEN clause, then if any one of the expressions evaluates to true the corresponding action is performed. No further expressions in that WHEN clause or in subsequent WHEN clauses are evaluated (and thus the expressions need not have unique values), and no subsequent actions are performed.

The WHEN clauses are checked in the order listed. However, the expressions within one WHEN clause might be evaluated in any order, and not all these expressions are necessarily evaluated. As soon as any expression is found true, subsequent expressions are not evaluated.

If the keyword ALL appears in the WHEN clause, the action is performed only if all expressions in that WHEN clause evaluate to true. Once one action is performed, no subsequent WHEN clauses are evaluated and no subsequent actions are performed. If any expression in the WHEN clause does not result in a true value, no further expressions in that clause are evaluated and the action is not performed.

Following is an example of the first form of SELECT:

SELECT;

WHEN ANY (A=10,A=20,A=30) B=B+1;

WHEN (A=50) B=B+2;

WHEN (A=60) B=B+3;

WHEN (A=70) B=B+4;

WHEN (A=80) B=B+5;

WHEN (A=90) B=B+6;

WHEN ALL (A>90,A<500) B=B+10;

OTHERWISE B=B+C;

END;

The SELECT statement defines the action to be taken if the variable A has any of the values specified in the WHEN clauses (or, in the case of the WHEN ALL clause, if A is both greater than 90 and less than 500). If none of the WHEN clauses is true, the action specified in the OTHERWISE clause (B=B+C) is performed.

SELECT With a Select Expression

The second form of the SELECT statement has a select expression after the keyword SELECT. This form of the SELECT statement evaluates expressions in the WHEN clauses and then compares their values to the value of the select expression (instead of testing the expressions for truth or falsity, as in the first form of SELECT). It performs a specified action if any expression has the same value as the select expression (or, if ALL is used, all expressions have the same value as the select expression). In this form of the SELECT statement, as in the previous form, the expressions in a WHEN clause might be evaluated in any order, and not all the expressions are necessarily evaluated.

Following is an example of the second form of SELECT:

SELECT(A);

WHEN (50) C=C+1;

WHEN ANY (60,61,62,B+C) C=C+2;

WHEN ALL (70,D) C=C+3;

OTHERWISE C=C+D;

END;

 

The SELECT statement defines the action to be taken if the select expression (A in the example) evaluates to any or all of the values of the expressions following a WHEN clause. The first action (the assignment statement C=C+1) will be performed if A has a current value of 50. In that case, none of the subsequent WHEN clauses will be evaluated. The second WHEN clause includes the ANY keyword, and so the second action will be performed if A evaluates to or equals 60 or 61 or 62 or the sum of B and C. If neither the first nor the second action is performed, the third WHEN clause's expressions are tested. The third WHEN clause includes the ALL keyword, so the third action will be performed only if A equals both 70 and D. If none of the WHEN clauses causes an action to be performed, then the action in the OTHERWISE clause (the assignment statement C=C+D) will be performed.

OTHERWISE Clause

If none of the WHEN clauses causes the corresponding action to be performed, the action specified in the optional OTHERWISE clause is performed; but if the OTHERWISE clause is omitted, an ERROR condition is signalled. OTHERWISE can be followed by a semicolon (a null statement) to cause execution to continue and avoid an ERROR condition when you do not want to specify an action after OTHERWISE. For example:

OTHERWISE;

 

After an action is performed following a WHEN or OTHERWISE clause, control passes to the next executable statement following the END statement that terminates the SELECT statement, unless normal flow is altered within the action.

Nested SELECT Statements

Note that the action specified in a WHEN or OTHERWISE clause can be another SELECT statement, resulting in nested SELECT statements with the format shown in the following example:

SELECT;

WHEN (condition A)

SELECT;

WHEN (condition A1) statement 1;

WHEN (condition A2) statement 2;

END;

WHEN (condition B)

SELECT;

WHEN (condition B1) statement 3;

WHEN (condition B2) statement 4;

OTHERWISE statement 5;

END;

OTHERWISE statement 6;

END;

 

In this example, statement 1 is executed when both condition A and condition A1 are true. Statement 2 is executed when both condition A and condition A2 are true and A1 is false. If A is true but neither A1 nor A2 is true, an ERROR condition is reported because no OTHERWISE clause exists within this SELECT statement.

If condition A is false, condition B is checked. If B is true but B1 and B2 are both false, statement 5 (in the corresponding OTHERWISE clause) is executed. If conditions A and B are both false, statement 6 (in the outermost OTHERWISE clause) is executed.

If you want to avoid the possibility that execution could be stopped by an ERROR condition, which occurs in this example if condition A is true and A1 and A2 are false, you can put in an OTHERWISE clause with a null statement (a semicolon) as its action, which would cause control to pass to the first executable statement following the end of the outermost SELECT statement.

An END statement must terminate each SELECT statement.

GOTO Statement

The GOTO statement causes control to be transferred to a labeled statement in the current or any outer procedure.

The format of the GOTO statement is:

label-reference

A label constant or an expression that, when evaluated, yields a label value. A label value denotes a statement in the program.

The specified label cannot be the label of an ENTRY, FORMAT, or PROCEDURE statement. The label reference specified in a GOTO statement can be any of the following:

  • An unsubscripted label constant. For example:

GOTO ALPHA;

ALPHA:

 

  • A subscripted label constant, for which the subscript is specified with an integer constant or a variable expression. For example:

GOTO PROCESS(1);

PROCESS(1):

 

  • A label variable that, when evaluated, yields a label value. For example:

DECLARE PROCESS LABEL VARIABLE;

PROCESS = BILLING;

GOTO PROCESS;

 

  • A subscripted label variable that, when evaluated, yields a label value. For example:

DECLARE X(5) LABEL;

X(1) = NEXT;

 

GOTO X(1);

 

In the case of a label variable, the resulting label value must designate an existing block activation. (Similarly, a label constant must designate an existing block activation.) If the designated block activation is the current block activation, the GOTO statement causes a local GOTO. No special processing occurs.

OTHERWISE

This option can be used only when the label-reference is a subscripted label with a variable subscript. If present in any other case, it will be reported as an error.

Make sure all the labels referenced by the GOTO statement occur after the statement. If you use potential label references for a specific GOTO statement prior to the GOTO statement, you will cause compiler errors. The following example shows a program with this illegal construct:

PROGRAM: PROCEDURE OPTIONS (MAIN);

DECLARE I FIXED BINARY (31,0);

 

PART(1):

I=2;

GOTO PART(I) OTHERWISE;

 

END PROGRAM;

 

If the variable subscript is out of range and the OTHERWISE option is present, the statement following the GOTO will be executed next. If the OTHERWISE option is not specified and the subscript of the last label is not an asterisk (*), the subscript is reported out of range at run-time and the process will be terminated.

Nonlocal GOTO

If the specified label value is not in the current block, the GOTO statement is considered a nonlocal GOTO. The following can occur:

  • The current block, and any blocks intervening between it and the block containing the label value, are released. This rule applies both to procedure blocks and to begin blocks.
  • If a GOTO statement transfers control out of a procedure that is invoked in a function reference, the statement containing the function reference is not evaluated further.
  • A special case of a nonlocal GOTO occurs if a GOTO is executed in an ON-unit. The condition handling mechanism signals a system exception handler (SS$_UNWIND) to unwind the procedure call frames to the proper point before control transfers to the label. This allows programs to clean up intervening blocks before preceding.
Restriction

You can use either the OTHERWISE option or an asterisk (*) for the last label, but not both.

Examples

The following example shows the use of the GOTO statement:

RESTART:;

BEGIN;

ON ERROR GOTO RESTART;

END;

 

The GOTO statement provides a transfer address for the current procedure when the ERROR condition is signaled.

DECLARE PROCESS(5) LABEL;

GOTO PROCESS(2);

 

The GOTO statement evaluates the label reference and transfers control to the label constant corresponding to the second element of the array PROCESS. PROCESS consists of label variables.

The following restrictions apply to the use of labels and label data:

  • No statement can have more than one label. However, an executable statement can be preceded by any number of labeled null statements, which have the same effect as would multiple labels.
  • Operations on label values are restricted to the operators = and ^=, for testing equality or inequality. Two values are equal if they refer to the same statement in the same block activation.
  • Any statement in a PL/I program can be labeled except the following:
  • A DECLARE statement
  • A statement beginning an ON-unit, THEN clause, ELSE clause, WHEN clause, or OTHERWISE clause
  • Labels on PROCEDURE, ENTRY, and FORMAT statements are not considered statement labels and cannot be used as the targets of GOTO statements.
  • An identifier occurring as a label in a block cannot be declared in that block (except as a structure member) or occur in the block's parameter list.
  • Any reference to a label value after its block activation terminates is an error with unpredictable results.

For more information on labels, see See Label Data .

LEAVE Statement

The LEAVE statement causes control to be transferred out of the immediately containing DO-group or out of the containing DO-group whose label is specified with the statement.

The format of the LEAVE statement is:

LEAVE [label-reference];

 
label-reference

A reference to a label on a DO statement that heads a containing DO-group. The label reference can be a label constant or a subscripted label constant for which the subscript is specified with an integer constant. The label reference cannot be a label variable, nor can it be a subscripted label constant for which the subscript is specified with a variable.

On execution, a LEAVE statement with no label reference causes control to be transferred to the first statement following the END statement that terminates the immediately containing DO-group. If the LEAVE statement has a label, control is passed to the first executable statement following the END statement for the corresponding label indicated in the LEAVE statement. Thus, the LEAVE statement provides an alternative means of terminating execution of a DO-group. In the case of a LEAVE statement with a label reference, several nested DO-groups can be terminated as control transfers outside the referenced DO-group.

Restrictions

The following restrictions apply to the use of the LEAVE statement:

  • A LEAVE statement must be contained within a DO-group.
  • A LEAVE statement must be in the same block as the DO statement to which it refers.
  • If a LEAVE statement has a label reference, it must refer to a label on a DO statement that heads a DO-group that contains the LEAVE statement. The LEAVE statement must be in the same block as the labeled DO statement.
  • The label reference specified with a LEAVE statement must be a label constant or a subscripted label constant with an integer constant subscript.
Examples

The following example shows a LEAVE statement without a label reference:

DO I = 1 TO 100;

IF COMMAND = 'QUIT' THEN LEAVE;

END;

PUT LIST ('Job finished');

 

In this example, the LEAVE statement transfers control directly to the PUT statement if the condition in the IF statement is satisfied.

The next example shows a LEAVE statement with a label reference:

LOOP1: DO WHILE (MORE);

LOOP2: DO I = 1 TO 12;

IF QUAN(I) > 150 THEN LEAVE LOOP1;

END; /* Loop 2 */

END; /* Loop 1 */

 

In this example, the LEAVE statement transfers control to the first statement beyond the END statement that terminates LOOP1.

The following examples show some invalid uses of the LEAVE statement:

LEAVE; /* LEAVE statement must be in */

/* DO-group */

DO;

BEGIN;

LEAVE; /* LEAVE statement must be in */

END; /* same block as DO statement */

END;

ON ENDFILE(SYSIN) LEAVE; /* ON-unit is separate block */

DECLARE LABVAR LABEL VARIABLE;

LABVAR = LOOP;

LOOP: DO I = 1 TO 10;

LEAVE LABVAR; /* Label reference cannot be a variable */

END;

LAB(1): DO;

LAB(2): DO;

I = 1;

LEAVE LAB(I); /* Subscript must be a constant */

END;

END;

STOP Statement

The STOP statement terminates execution of a program, regardless of the current block activation.

The format of the STOP statement is:

STOP;

 

The STOP statement signals the FINISH condition, and closes all open files. If the main procedure has the RETURNS attribute, no return value is obtainable.

Null Statement

The null statement performs no action. Its format is:

;

 

The null statement usually serves as the target statement of a THEN or ELSE clause in an IF statement, as the target of a WHEN or OTHERWISE clause in a SELECT statement, or as an action in an ON-unit. The following examples illustrate these uses.

IF A < B THEN GOTO COMPUTE;

ELSE ;

 

In this example, no action takes place if A is greater than or equal to B; execution continues at the statement following ELSE ;. A construction of this type may be necessary when IF statements are nested (see See Nested IF Statements ).

SELECT;

WHEN (condition A,B,C) GOTO FILE_READ;

WHEN (condition D,E) GOTO UPDATE;

OTHERWISE;

END;

 

In this example, control is passed to the next executable statement after END if conditions A, B, C, D, and E are not true.

ON ENDPAGE(SYSPRINT);

 

In this example, no action takes place upon execution of the ON-unit; the I/O operation that caused the ENDPAGE condition continues.

The null statement can also be used to declare two labels for the same executable statement, as in the following example:

LABEL1: ;

LABEL2: statement ...

Condition Handling

A PL/I condition is any occurrence that causes the interruption of a program and a signal. When a condition is signaled, PL/I initiates a search for a user-written program unit called an ON-unit to handle the condition.

An ON condition is any one of several named conditions whose occurrence during the execution of a program interrupts the program. When a condition occurs or is signaled, a statement or sequence of statements, called an ON-unit, is executed. The SYSTEM option can be specified in the ON statement, causing the default system condition handling to be executed.

The following condition handling topics are discussed in subsequent sections:

ON Statement

The ON statement defines the action to be taken when a specific condition or conditions are signaled during the execution of a program. The ON statement is an executable statement. It must be executed before the statement that signals the specified condition.

The format of the ON statement is:

condition-name, ...

The name or names of the specific conditions for which an ON-unit or the SYSTEM option is specified. There is a keyword name associated with each condition. Successive keyword names must be separated by commas. The conditions are summarized in See . Summary of ON Conditions ; each condition is described in an individual entry in this manual.

on-unit

The action to be taken when the specified condition or conditions are signaled. An ON-unit can be:

  • Any single, unlabeled statement except DECLARE, DO, END, ENTRY, FORMAT, IF, ON, PROCEDURE, RETURN, or SELECT.
  • An unlabeled begin block.
  • A null statement (a semicolon alone), which causes program execution to continue as if the condition had been handled.

Only the most recent ON-unit established for a given condition can be active. If two successive ON statements are executed for the same condition, the second ON statement nullifies the first.

If no ON-unit is established for a particular condition, the condition ERROR is signaled. If no ON-unit is established for ERROR condition, the default system ON-unit is executed. See See Default PL/I ON-Unit .

SYSTEM

This option invokes the default system condition handling for the specified condition, overriding any existing ON-unit for the condition. See See Establishing ON-Units .

SIGNAL Statement

The SIGNAL statement causes a specified condition to be signaled, which causes the system to search for and execute an ON-unit to handle the condition. See See Search Path for ON-Units for more information.

The format of the SIGNAL statement is:

SIGNAL condition-name;

 
condition-name

The name of the condition to be signaled. It must be one of the keywords listed in See . Summary of ON Conditions . Each of these conditions is described in its own section.

Most conditions occur as a result of a hardware trap or fault, or as a result of signaling by PL/I run-time procedures. You can use the SIGNAL statement within a program as a general-purpose communication technique. In particular, the VAXCONDITION and CONDITION conditions let you signal unique user-defined condition values.

REVERT Statement

The REVERT statement cancels an ON-unit established for a specified condition or conditions in the current block only.

The format of the REVERT statement is as follows:

REVERT condition-name, ...;

 
condition-name, ...

The keyword name or names associated with the condition or conditions for which the ON-unit is to be reverted. Successive names must be separated by commas. The valid condition names are the same as for the ON statement.

If no ON-unit is established for a specified condition for the current block, the REVERT statement has no effect.

The REVERT statement does not cancel all ON-units that may be active at the same time it is executed (see See Search Path for ON-Units ), only a handler in the current block.

An ON-unit can be re-established after execution of a REVERT statement by subsequently executing an ON statement.

The REVERT statement has no effect on an ON-unit established for the ANYCONDITION condition unless the statement explicitly references the ANYCONDITION condition. For example:

REVERT ANYCONDITION;

 

Therefore, a statement such as the following has no effect on an ON-unit established for the ANYCONDITION condition:

REVERT ZERODIVIDE;

 

The next example shows this more clearly:

PROGRAM: PROCEDURE OPTIONS(MAIN);

DECLARE A FIXED;

DECLARE B FIXED INITIAL (5);

DECLARE C FIXED INITIAL (0);

 

ON ANYCONDITION BEGIN;

PUT SKIP LIST ('Handled condition = ',ONCODE());

END;

 

REVERT ZERODIVIDE;

 

A = B / C; /* Signal divzero */

 

ON ZERODIVIDE BEGIN;

PUT SKIP LIST ('Handled ZERODIVIDE');

END;

 

A = B / C; /* Signal divzero */

 

REVERT ZERODIVIDE;

 

A = B / C; /* Signal divzero */

 

ON ZERODIVIDE BEGIN;

PUT SKIP LIST ('Handled ZERODIVIDE');

END;

 

REVERT ANYCONDITION;

 

A = B / C; /* Signal divzero */

 

REVERT ZERODIVIDE;

 

A = B / C; /* Signal divzero */

 

END PROGRAM;

 

When you run the program, the following conditions result:

Handled condition = 1156

Handled ZERODIVIDE

Handled condition = 1156

Handled ZERODIVIDE

PL/I ERROR condition.

 

Summary of ON Conditions

Most, but not all, ON conditions are associated with errors. The types of conditions for which you can establish ON-units are grouped in the following categories:

  • Conditions that occur during I/O operations:
  • ENDFILE, to take action when the end-of-file occurs while a file is being read.
  • ENDPAGE, to take action when the last line on a page is printed.
  • KEY, to take action when an error occurs when a record is accessed by key.
  • NAME (IBM dialect only), to take action when an error occurs during a data-directed GET statement with the FILE option.
  • RECORD (IBM dialect only), to take action when an error involving record length occurs during a READ, WRITE, or REWRITE operation.
  • TRANSMIT (IBM dialect only), to take action when a transmission error occurs during any I/O operation.
  • UNDEFINEDFILE, to respond to any file-specific errors that can occur during the opening of a file.
  • Conditions that indicate arithmetic conditions related to hardware violations:
  • FIXEDOVERFLOW, to respond when integer or fixed-point values become too large to be expressed.
  • OVERFLOW, to respond when floating-point values become too large to be expressed.
  • UNDERFLOW, to respond when floating-point values become too small to be expressed.
  • ZERODIVIDE, to respond when the divisor in a division operation has a value of zero.
  • Other conditions:
  • AREA, to respond when an error has been detected during an operation on an area (various subconditions can be determined through use of the ONCODE built-in function).
  • CHECK (IBM dialect only), valid only in a condition prefix. Used to display some or all of the names and values of data items within the scope of the prefix, when they are accessed.
  • CONDITION, to respond to programmer-defined conditions.
  • CONVERSION, to respond to data conversion errors from CHARACTER to any arithmetic data type or bit string.
  • SIZE (IBM dialect only), to respond to errors occurring during assignment or I/O operations involving loss of high-order bits.
  • STORAGE, to respond when an error has been detected during allocation of a controlled variable or a based variable other than in an area.
  • STRINGRANGE, to respond to substring references that are beyond the length of the string.
  • STRINGSIZE (IBM dialect only), to respond to errors generated when strings are assigned to targets that are not long enough.
  • SUBSCRIPTRANGE, to respond to array references with out-of-bound subscripts.
  • General classes of exception conditions:
  • ANYCONDITION, to respond to all conditions for which no specific ON-unit is established in the current block.
  • ATTENTION (IBM dialect only), to respond to user-generated attention signals.
  • ERROR, to respond to language-specific and run-time- specific errors.
  • FINISH, to respond when a STOP statement is executed.
  • VAXCONDITION, to respond to condition values that are specific to the operating system or to be used as user-defined conditions created by SIGNAL VAXCONDITION(n).

See . Summary of ON Conditions summarizes ON conditions. Each condition is described individually in the sections that follow.

. Summary of ON Conditions

Condition Name

Function

ANYCONDITION

Handles any condition not specifically handled by another ON-unit

AREA

Handles a condition that occurs during an operation on an area

ATTENTION

(IBM dialect only) Handles user terminal-generated attention signal

CHECK

(IBM dialect only) Displays names and values of specified data items

CONDITION

Handles programmer-defined conditions

CONVERSION

Handles data conversion errors

ENDFILE

Handles end-of-file for a specified file

ENDPAGE

Handles end-of-page for a specified file with PRINT attribute

ERROR

Handles miscellaneous error conditions and conditions for which no specific ON- unit exists

FINISH

Handles program exit when the main procedure executes a RETURN statement, when any block executes a STOP statement, or when the program exits due to an error that is not handled by an ON-unit

FIXEDOVERFLOW

Handles fixed-point decimal and integer overflow exception conditions

KEY

Handles any error involving the key during keyed access to a specified file

NAME

(IBM dialect only) Handles errors involving data-directed GET statements with the FILE option

OVERFLOW

Handles floating-point overflow exception conditions

RECORD

(IBM dialect only) Handles size errors involving records during READ, WRITE, or REWRITE operations

SIZE

(IBM dialect only) Handles loss of high-order bits during assignment or I/O

STORAGE

Handles a condition that occurs during allocation of a controlled variable or a based variable other than in an area

STRINGRANGE

Handles out-of-bound substring references

STRINGSIZE

(IBM dialect only) Handles errors involving assigning a string to a target that is too short

SUBSCRIPTRANGE

Handles out-of-bound array references

TRANSMIT

(IBM dialect only) Handles errors involving uncorrectable transmission errors during record I/O

UNDEFINEDFILE

Handles any errors in opening a specified file

VAXCONDITION

Handles operating system or programmer-specified condition values

ZERODIVIDE

Handles divide-by-zero exception conditions

ANYCONDITION Condition

The ANYCONDITION keyword can be specified in an ON, REVERT, or SIGNAL statement. It designates an ON-unit established for all signaled conditions that are not handled by specific ON-units.

The ANYCONDITION keyword is not defined in the PL/I language. It is provided specifically for compatibility with the OpenVMS versions of PL/I.

AREA Condition

The AREA condition is raised when various operations fail in relation to areas. For example, it is raised if the extent of an area is not large enough to contain the variable or variables allocated to it, or if the area is incorrectly formatted.

For more information see the Kednos PL/I for UNIX User's Manual.

ATTENTION Condition (IBM Dialect Only)

The ATTENTION condition is raised during interactive processing when a user signals attention at the terminal or, during batch processing, by a SIGNAL ATTENTION statement.

When the ATTENTION condition is raised, an ATTENTION ON-unit is entered. PL/I ignores this condition if there is no ATTENTION ON-unit. On return from an ATTENTION ON-unit, execution resumes at a point in the program just following the point where the condition was raised.

CHECK Condition (IBM Dialect Only)

The CHECK condition is used to display names and values of data items within the scope of a condition prefix. The format of the CHECK condition is:

CHECK [ (name [,name]...) ]

 

name

A name of a data item, qualified or unqualified, which is one of the following:

  • An unsubscripted variable, either a data item or an aggregate
  • An entry or label constant

For example, within a condition prefix you can specify the following:

(CHECK(VAR1,VAR2,VAR3)):DO I = 1 TO 5;

 

You can enable the CHECK condition separately for any name in the scope of the condition prefix. If you do not specify any names, CHECK is enabled for all variables, label constants, and entry constants within the scope of the condition prefix.

The CHECK condition can be raised under the following conditions:

  • Statement labels -- before executing the statement prefixed by the named label. Ignored if the statement is a FORMAT statement.
  • Entry constants -- before invoking the entry point named by the entry constant.
  • Variables -- whenever any statement in the scope of the condition prefix changes the variable or any part of the variable.

The CHECK condition does not affect the statement being executed or the flow of execution.

CONDITION Condition

The CONDITION condition name is used for ON-units to handle programmer-defined conditions. The value returned by the ONCODE built-in function is PLI$_CONDITION. There is no way to distinguish between multiple programmer-defined conditions if they are specified in the same ON statement.

The format of the CONDITION condition name is:

CONDITION (cond-name)

 
cond-name

A name declared with the CONDITION attribute.

CONVERSION Condition

The CONVERSION condition name can be specified in an ON, SIGNAL, or REVERT statement to designate a CONVERSION condition or ON-unit.

PL/I signals the CONVERSION condition when the source character data in a conversion to bit-string or arithmetic data contains characters that are not valid in the specified context. In particular, the CONVERSION condition is raised when a character string is being converted and one of the following conditions is true:

  • The target of the conversion is an arithmetic type, and the source string does not contain a valid, optionally signed arithmetic constant.
  • The target of the conversion is a picture, and the source string does not conform to the picture specification.
  • The target of the conversion is a bit string, and a character other than 0 or 1 appears in the source string.

The CONVERSION condition can be raised either by a non-I/O conversion, such as an explicit conversion using a built-in function or an implicit conversion generated by the compiler, or by an I/O conversion in a GET statement. For example, A = BIT('1014') would cause the CONVERSION condition to be raised, because 4 is not a valid binary digit. Likewise, a GET statement with an arithmetic target would also cause the CONVERSION condition to be raised if the characters '12K45' appeared in the input field, because 'K' is not a valid numeric character.

You can use the ONSOURCE and ONCHAR built-in functions and pseudovariables inside an ON CONVERSION ON-unit. The ONSOURCE built-in function returns the source string that caused the CONVERSION condition to be raised. The ONCHAR built-in function returns the specific character that caused the conversion to fail. You can use the ONSOURCE pseudovariable to change the value of the conversion. Likewise, you can use the ONCHAR pseudovariable to modify only the single character in error.

If the CONVERSION condition was raised during a conversion required by the GET statement, the ONFILE built-in function returns the name of the file constant inside the CONVERSION ON-unit. If the CONVERSION condition was not raised during a conversion required by the GET statement, the ONFILE built-in function returns a null string.

ON-Unit Completion

A normal return from a CONVERSION condition will cause PL/I to attempt the conversion again if the ONSOURCE or ONCHAR pseudovariables have had values assigned to them. If the ONSOURCE value has not been modified, PL/I raises the ERROR condition instead.

For example:

/*

* Sample program that displays a 'quick-fix' CONVERSION

* ON-unit. At the end of this program, TARGET1 contains

* the value 14015, and TARGET2 contains the value '11100'B.

* Note that SOURCE1 and SOURCE2 are not modified.

*/

MAIN: PROCEDURE OPTIONS(MAIN);

 

DCL SOURCE1 CHARACTER(5) VARYING INITIAL('14$15');

DCL SOURCE2 CHARACTER(5) VARYING INITIAL('11q00');

DCL TARGET1 FIXED BINARY(31);

DCL TARGET2 BIT(5) ALIGNED;

/*

* Sample 'quick-fix' CONVERSION ON-unit that replaces

* erroneous lowercase q's with 1's, and all other

* erroneous characters with 0's.

*/

ON CONVERSION BEGIN;

PUT SKIP EDIT('"',ONSOURCE(),'" "',ONCHAR(),'"')((5)A);

IF ONCHAR() = 'q'

THEN

ONCHAR() = '1';

ELSE

ONCHAR() = '0';

END; /* ON */

/*

* Note that the CONVERSION condition is raised for all

* 3 of the following statements.

*/

TARGET1 = SOURCE1;

TARGET2 = SOURCE1;

TARGET2 = SOURCE2;

 

PUT SKIP(2) EDIT(SOURCE1,SOURCE2)(A,X(1),A);

PUT SKIP EDIT(TARGET1,TARGET2)(F(8),X(1),B(5));

END MAIN;

 

The output from this program is:

"14$15" "$"

"14$15" "4"

"14$15" "$"

"14$15" "5"

"11q00" "q"

 

14$15 11q00

14015 11100

 

The target of the conversion is undefined when the CONVERSION condition is raised.

The retry attempted on a normal return is for the single field that was in error. Attempts to assign a string containing, for example, a comma list of values will not be used for successive data items in a GET statement.

The actual value modified by the ONSOURCE and ONCHAR pseudovariables is a temporary value that is discarded once the conversion is complete, or the control flow cannot return to the point of the error. This means that invalid data stored in a character string variable will cause the CONVERSION condition to be raised each time the value is converted, not just the first time the conversion is attempted, regardless of modifications to the ONSOURCE and ONCHAR pseudovariables inside the CONVERSION ON-unit.

ENDFILE Condition

The ENDFILE condition name can be specified in an ON, SIGNAL, or REVERT statement to designate an end-of-file condition or ON-unit for a specific file.

PL/I signals the ENDFILE condition when a GET or READ statement attempts an input operation on a file or device after the last data item has been input.

The format of the ENDFILE condition name is:

ENDFILE (file-reference)

 
file-reference

The name of a file constant or file variable for which the ENDFILE ON-unit is established. If the name of a file variable is specified, the variable must be resolved to the name of a file constant when the on-unit is established, as well as when the condition is signaled.

An ENDFILE ON-unit can be established for any input file. For any particular file, the meaning of the end-of-file condition depends on the type of device. For example, end-of-file is signaled for a terminal device when an End of File character is read.

For a stream file, an end-of-file condition is signaled whenever a GET statement attempts to access an empty file or attempts to access a file whose last input field has been read.

For a record file, an end-of-file condition is signaled when a READ statement is executed with the file at the end-of-file position or when a read is attempted beyond the last record in the file. For example:

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

EOF = '0'B;

OPEN FILE (RECEIPTS) RECORD SEQUENTIAL;

READ FILE (RECEIPTS) INTO (RECORD);

DO WHILE (^EOF);

READ FILE (RECEIPTS) INTO (RECORD);

END;

 

In this example, the ON statement establishes the default action to be taken when the last record in the input file has been processed: the flag EOF is set to '1'B.

An ON-unit established to handle end-of-file conditions can reference the ONFILE built-in function to determine the name of the file constant for which the condition was signaled.

ON-Unit Completion

If the ON-unit for the ENDFILE condition does not transfer control elsewhere in the program, control returns to the statement following the GET or READ statement that caused the condition to be signaled.

When the ENDFILE condition is signaled, it remains in effect until the file is closed. Subsequent GET or READ statements for the file cause the ENDFILE condition to be signaled repeatedly.

ENDPAGE Condition

The ENDPAGE condition name can be specified in an ON, SIGNAL, or REVERT statement to designate an end-of- page condition or ON-unit for a specific print file.

The format of the ENDPAGE condition name is:

ENDPAGE (file-reference)

 
file-reference

The name of the file constant or file variable for which the ENDPAGE ON-unit is to be established. If the name of a file variable is specified, the variable must be resolved to the name of a file constant when the on-unit is established, as well as when the condition is signaled. The file must have the PRINT attribute.

The maximum number of lines that can be output on a single page is set by the PAGESIZE option of the OPEN statement. The maximum number of lines allowed on a single page is 32767. If not specified, PL/I uses the default page size, 60 lines.

PL/I signals the ENDPAGE condition when a PUT statement attempts to output a line beyond the last line specified for an output page. When the ENDPAGE condition is signaled, the current line number associated with the file is the page size plus 1. An ENDPAGE ON-unit allows you to provide special processing before output continues on a new page.

For example:

ON ENDPAGE (PRINTFILE) BEGIN;

PUT FILE (PRINTFILE) PAGE;

PUT FILE (PRINTFILE) LIST(HEADER_LINE);

PUT FILE (PRINTFILE) SKIP(2);

END;

 

The ON-unit for the ENDPAGE condition for the file PRINTFILE outputs a page eject and a header line for the new output page.

To cause PL/I to ignore the ENDPAGE condition when a large amount of output is written to a terminal, you can use the following ON-unit, that contains only the null statement:

ON ENDPAGE(SYSPRINT);

 

This is optional because PL/I ignores the ENDPAGE condition on SYSPRINT by default. You cannot catch the ENDPAGE(SYSPRINT) condition.

An ON-unit established to handle end-of-page conditions can reference the ONFILE built- in function to determine the name of the file constant for which the condition was signaled.

ON-Unit Completion

If the ON-unit does not transfer control elsewhere in the program, the line number is set to 1 and the program continues execution of the PUT statement. If the ENDPAGE condition was signaled during data transmission, the data is written on the new current line. If the ENDPAGE condition was caused by a LINE or a SKIP option on the PUT statement, then the action specified by these options is ignored on return.

An ENDPAGE condition can occur only once per page of output. If the ON-unit specified does not specify a new page, then execution and output continue. The current line number can increase indefinitely; PL/I does not signal the ENDPAGE condition again. However, if a LINE option on a PUT statement specifies a line number that is less than that of the current line, a new page is output and the current line is set to 1.

Default PL/I Action

If the ENDPAGE condition is signaled during file processing, PL/I starts output on a new page and continues processing. An exception is made for SYSPRINT which is to take no action. If the ENDPAGE condition is signaled as a result of a SIGNAL statement, the statement following the SIGNAL statement is executed and no page is output by default.

ERROR Condition

The ERROR condition name can be specified in an ON, SIGNAL, or REVERT statement to designate an error condition or ON-unit.

PL/I signals the ERROR condition in the following contexts:

  • When a condition occurs for which the default PL/I action is to signal ERROR
  • When the SIGNAL ERROR statement signals the condition
  • When there is a default PL/I ON-unit and a condition is signaled for which there is no corresponding ON-unit

PL/I signals the ERROR condition when any condition (except ENDPAGE, see preceding section) is raised and no ON-unit exists for the condition.

When any ON-unit is executed, the ON-unit can reference the built-in function ONCODE. This function returns the numeric condition value associated with the specific error that signaled the condition.

ON-Unit Completion

If an ERROR ON-unit does not handle the condition, the program is terminated.

FINISH Condition

The FINISH condition name can be specified in an ON, SIGNAL, or REVERT statement to designate a FINISH condition or a FINISH ON-unit.

PL/I signals the FINISH condition in the following contexts:

  • When any procedure in the program executes the STOP statement
  • When a procedure that specifies OPTIONS(MAIN) executes a RETURN statement, or, if the procedure does not execute a RETURN statement, when its corresponding END statement is executed
  • When the SIGNAL FINISH statement signals the condition
ON-Unit Completion

If a FINISH ON-unit that executes as a result of a SIGNAL FINISH statement does not execute a nonlocal GOTO statement, control returns to the statement following SIGNAL FINISH. If the FINISH ON-unit executes as a result of any of the other three causes listed above, the program terminates.

FIXEDOVERFLOW Condition

The FIXEDOVERFLOW condition name can be specified in an ON, SIGNAL, or REVERT statement to designate a fixed overflow condition or ON-unit.

PL/I signals the FIXEDOVERFLOW condition in the following circumstances:

  • When the result of an arithmetic operation on a fixed-point decimal or binary integer value exceeds the maximum precision of the hardware. The maximum precision allowed for a fixed-point decimal or binary value is 31.
  • When the source value of a fixed-point expression exceeds the precision of the target variable. For example, PL/I signals FIXEDOVERFLOW when a value that is not in the range -128 through 127 is assigned to a fixed-point binary variable with a precision of 7 bits and scale equal to zero. Similarly, the condition is signaled if a value assigned to a picture variable has more integral digits than are specified by the picture specification.

The value resulting from an operation that causes this condition is undefined.

Value of ONCODE

Two hardware exceptions exist that result in the FIXEDOVERFLOW condition. These are SS$_DECOVF (for a fixed-point decimal overflow) and SS$_INTOVF (for a fixed-point binary integer overflow). An ON-unit that receives control when FIXEDOVERFLOW is signaled can reference the ONCODE built-in function to determine which condition is actually signaled.

To define an ON-unit to respond specifically to either of these errors, use the VAXCONDITION condition name.

Example

To respond to a FIXEDOVERFLOW condition caused by either decimal or integer overflow, write an ON-unit as follows:

ON FIXEDOVERFLOW BEGIN;

IF ONCODE() = SS$_DECOVF THEN DO;

/* Decimal overflow handling */

END;

IF ONCODE() - SS$_INTOVF THEN DO;

/* Fixed binary overflow handling */

END;

END; /* ON */

 

To respond to a decimal overflow only, write an ON-unit like the following:

ON VAXCONDITION (SS$_DECOVF) BEGIN;

/* Decimal overflow handling */

END; /* ON */

 

ON-Unit Completion

If the ON-unit does not transfer control elsewhere in the program, control returns to the point at which the condition was signaled.

KEY Condition

The KEY condition name can be specified in an ON, SIGNAL, or REVERT statement to designate a key error condition or ON-unit for a specific file.

The format of the KEY condition name is:

KEY (file-reference)

 
file-reference

A reference to the file constant or file variable for which the ON-unit is to be established. If the name of a file variable is specified, the variable must be resolved to the name of a file constant when the on-unit is established, as well as when the condition is signaled.

PL/I signals the KEY condition during an operation on a keyed file when an error occurs in processing a key. Some examples of errors for which PL/I signals the KEY condition are:

  • The record indicated by the specified key cannot be found.
  • The key specification requires conversion from one data type to another and the conversion is not valid.
  • The key is not correctly specified.
  • The key of a relative file exceeds the maximum record number specified when the file was created. This error is shown in the Example section.

An ON-unit established to handle the KEY condition can obtain information about the condition by invoking the following built-in functions:

  • The ONFILE built-in function returns the name of the file being processed when the condition was signaled.
  • The ONCODE built-in function returns the specific RMS condition value associated with the error.
  • The ONKEY built-in function returns the key value that caused the condition to be signaled.
Example

The following example shows the key of a relative file exceeding the maximum record number specified.

%INCLUDE $RMSDEF;

 

KEYTEST: PROCEDURE OPTIONS(MAIN);

 

DECLARE

RECBUF CHAR(80),

MYFILE FILE;

 

ON KEY(MYFILE) BEGIN;

PUT SKIP LIST('Key condition raised');

IF ONCODE()=RMS$_MRN THEN

PUT SKIP LIST('You have exceeded the maximum record.');

 

STOP;

 

END;

 

OPEN FILE(MYFILE) TITLE('MYFILE.DAT') OUTPUT KEYED

ENVIRONMENT(FIXED_LENGTH_RECORDS,

MAXIMUM_RECORD_SIZE(80),

MAXIMUM_RECORD_NUMBER(20));

 

RECBUF = 'This record will not ever make it into the file';

 

WRITE FILE(MYFILE) FROM(RECBUF) KEYFROM(100);

 

END;

 

ON-Unit Completion

If the ON-unit does not execute a nonlocal GOTO, control returns to the statement immediately following the statement that caused the KEY condition.

NAME Condition (IBM Dialect Only)

You can specify the NAME condition name in an ON, SIGNAL, or REVERT statement to handle errors that happen during execution of GET statements with the FILE option. By default, when a NAME condition is raised PL/I ignores the invalid data field, displays a message, and continues.

The format of the NAME condition name is:

NAME (file-reference)

 
file-reference

A reference to the file constant or file variable for which the ON-unit is to be established. If the name of a file variable is specified, the variable must be resolved to the name of a file constant when the on-unit is established, as well as when the condition is signaled.

Some examples of errors for which PL/I signals the NAME condition are:

  • The syntax of the returned data is invalid.
  • The name of the data item is invalid or missing. It may not be found in the data list, not be qualified, not be known in the block, be too long, or for any other reason be invalid.
  • A subscript may be missing or invalid in format, or may be out of range.

Use the DATAFIELD built-in function to retrieve the incorrect data field.

ON-Unit Completion

If the ON-unit does not execute a nonlocal GOTO, control returns to the statement immediately following the statement that caused the NAME condition.

OVERFLOW Condition

The OVERFLOW condition name can be specified in an ON, REVERT, or SIGNAL statement or, if you compile using the IBM dialect, in a condition prefix, to designate an ON condition or ON-unit for floating-point overflow conditions.

The exponent of a floating-point value is adjusted, if possible, to represent the value with the specified precision. That is, the precision is maximized and the exponent is minimized. The maximum precisions allowed are:

  • binary floating-point value -- 53
  • decimal floating-point value -- 15

PL/I signals the OVERFLOW condition when the result of an arithmetic operation on a floating-point value exceeds the maximum exponent size allowed by the hardware.

The value resulting from an operation that causes this condition is undefined.

ON-Unit Completion

Control returns to the point of the interruption.

RECORD Condition (IBM Dialect Only)

You can specify the RECORD condition name in an ON, SIGNAL, or REVERT statement to handle errors that happen during execution of READ, WRITE, or REWRITE statements. By default, when a RECORD condition is raised, PL/I displays a message, and raises an ERROR condition.

The format of the RECORD condition name is:

RECORD (file-reference)

 
file-reference

A reference to the file constant or file variable for which the ON-unit is to be established. If the name of a file variable is specified, the variable must be resolved to the name of a file constant when the on-unit is established, as well as when the condition is signaled.

The ONCODE built-in function returns the specific condition codes associated with the error. See . Values of ONCODE Raised by RECORD lists the RECORD condition codes and their meanings.

. Values of ONCODE Raised by RECORD

ONCODE value

Raised by

20

A SIGNAL RECORD statement was executed.

21

Record variable is too small.
1. In a READ statement -- the record variable is smaller than the record being read; the excess portion of the record will be lost.
2. In a WRITE or REWRITE statement to a file with fixed length records-- The record variable is smaller than the record length; the excess portion of the record will be undefined.

22

Record variable is too large.
1. In a READ statement from a file with fixed-length records --the excess portion of the record variable will be undefined.
2. In a WRITE or REWRITE statement -- Either the record is too large and the excess portion will be lost, or the record is of zero length and the write or rewrite will not be done.

23

Record variable is too small to contain the key.

24

The record that was just read is zero length.

ON-Unit Completion

If the ON-unit does not execute a nonlocal GOTO, control returns to the statement immediately following the statement that caused the RECORD condition.

SIZE Condition (IBM Dialect Only)

You can specify the SIZE condition name in an ON, SIGNAL, or REVERT statement to handle errors that happen high-order (left-most) digits are lost in an assignment statement, intermediate result, or I/O operation. By default, when a SIZE condition is raised, PL/I displays a message and raises an ERROR condition.

The SIZE condition is disabled by default. To enable the SIZE condition, specify it in a condition prefix. If you signal the SIZE condition in a SIGNAL statement and SIZE is not enabled, PL/I displays an error.

The format of the SIZE condition name is:

SIZE

 

PL/I signals the SIZE condition when the following occurs:

  • The SIZE condition is enabled.
  • PL/I attempts to assign a value to a data item and the value exceeds the default or declared size of the target. This may occur during assignment or conversion.

Note that the size of the target is the default or declared size, not the actual amount of storage occupied by the data item. If you declare a variable as FIXED BINARY(17) and enable the SIZE condition, PL/I raises the condition if a value larger than FIXED BINARY(17) is assigned to the variable directly, by conversion, or as an intermediate value in a calculation.

The SIZE condition is not equivalent to the FIXEDOVERFLOW condition, which is raised when a fixed-point value exceeds the implementation's maximum value.

Checking for size errors incurs overhead both in storage space and execution time. Therefore, it is best to use this condition prefix during program testing but not in production programs.

The ONCODE built-in function returns the specific condition codes associated with the error. See . Values of ONCODE Raised by SIZE lists the SIZE condition codes and their meanings.

. Values of ONCODE Raised by SIZE

ONCODE value

Raised by

340

1. A SIGNAL SIZE statement was executed, or
2. SIZE was raised during assignment to a variable because high-order nonzero digits were lost, or
3. SIZE was raised during an I/O operation because significant digits were lost.

341

SIZE was raised during an I/O operation because high-order nonzero digits were lost.

ON-Unit Completion

If the ON-unit does not execute a nonlocal GOTO, control returns to the statement immediately following the statement that caused the SIZE condition.

STRINGRANGE Condition

The STRINGRANGE condition is raised when a substring reference is beyond the length of the string. The error is detected either by compiled code or by a run-time library routine.

  • By default, Kednos PL/I for UNIX does not signal the STRINGRANGE condition. Use the -k compiler option to enable STRINGRANGE condition signalling.

STRINGRANGE can be abbreviated STRG.

Any one of several subconditions can cause the STRINGRANGE condition to be raised. You can use the ONCODE built-in function to determine which one. See . Values of ONCODE Raised by STRINGRANGE shows the possible values of the ONCODE built-in function for the STRINGRANGE condition.

. Values of ONCODE Raised by STRINGRANGE

ONCODE value

Raised by

PLI$_STRRANGE

SIGNAL STRINGRANGE

PLI$_SUBSTR2

Out-of-range SUBSTR 2nd argument

PLI$_SUBSTR3

Out-of-range SUBSTR 3rd argument

PLI$_BIFSTAPOS

Out-of-range starting position for an INDEX, SEARCH, or VERIFY built-in function

Note that STRINGRANGE is always enabled in RTL code (which is currently used for more complex cases of INDEX, SEARCH, and VERIFY), but in-line checking is only performed if the -k or --check compiler option is used to compile the code in which the condition would be raised.

An example of the use of the STRINGRANGE condition and the ONCODE built-in function follows.

%INCLUDE $PLIDEF;

ON STRINGRANGE BEGIN;

/*

* The THEN clause below will be executed for all

* SUBSTR starting-position range errors. All other

* STRINGRANGE errors will be resignaled. Note that

* SUBSTR is processed in-line, so the code must be

* compiled with /CHECK=BOUNDS for this ON-unit to

* be effective.

*/

IF ONCODE() = PLI$_SUBSTR2

THEN

ELSE

CALL RESIGNAL();

END;

 

STRINGSIZE Condition (IBM Dialect Only)

The STRINGSIZE condition is raised when you try to assign a bit or character string to a target variable that is not long enough to hold the string. STRINGSIZE is disabled by default and must be enabled using a condition prefix.

If the STRINGSIZE condition is raised and not handled, the string is truncated from the right-hand end so that it will fit in the target variable. A message is displayed and processing continues.

The ONCODE built-in function returns the specific condition codes associated with the error. See . Values of ONCODE Raised by SIZE lists the STRINGSIZE condition codes and their meanings.

. Values of ONCODE Raised by STRINGSIZE

ONCODE value

Raised by

150

SIGNAL STRINGRANGE or assignment error in a bit or character string.

151

Assignment error in a mixed string.

ON-Unit Completion

If the ON-unit does not execute a nonlocal GOTO, control returns to the statement immediately following the statement that caused the STRINGSIZE condition.

SUBSCRIPTRANGE Condition

The SUBSCRIPTRANGE condition is raised in response to out-of-bounds subscripts in references to arrays. The value returned by the ONCODE built-in function for the SUBSCRIPTRANGE condition is PLI$_SUBRANGE or PLI$_SUBRANGEn, where n is the number of the subscript, in the range 1 through 8.

  • By default, Kednos PL/I for UNIX does not signal the SUBSCRIPTRANGE condition. Use the -k compiler option to enable SUBSCRIPTRANGE condition signalling.
STORAGE Condition

The STORAGE condition is raised when an error has been detected during allocation of a controlled variable or a based variable other than to an area. The most common cause is the exhaustion of virtual memory; another cause might be an erroneous attempt to allocate a negative amount of storage.

TRANSMIT Condition (IBM Dialect Only)

You can specify the TRANSMIT condition name in an ON, SIGNAL, or REVERT statement to handle errors that happen during execution of any I/O statement. By default, when a TRANSMIT condition is raised, PL/I displays a message, and raises an ERROR condition. This condition is always enabled.

The format of the TRANSMIT condition name is:

TRANSMIT (file-reference)

 
file-reference

A reference to the file constant or file variable for which the ON-unit is to be established. If the name of a file variable is specified, the variable must be resolved to the name of a file constant when the on-unit is established, as well as when the condition is signaled.

The TRANSMIT condition is raised at different points in execution of the I/O statement depending on the type of statement.

  • Input -- after transmission of the incorrect record and, when records are blocked, after transmission of each subsequent record in the block.
  • Output -- after transmission and, if records are blocked, after the block is complete.
  • Spanned record update -- on the last segment of a record and not for any subsequent records in the block.
  • For I/O using the EVENT option -- when the WAIT statement for that event is encountered.

The ONCODE built-in function returns the specific condition codes associated with the error. See . Values of ONCODE Raised by RECORD lists the TRANSMIT condition codes and their meanings.

. Values of ONCODE Raised by TRANSMIT

ONCODE value

Raised by

40

A SIGNAL TRANSMIT statement was executed.

41

Uncorrectable output transmission error.

42

Uncorrectable input transmission error.

43

Uncorrectable output transmission error in index.

44

Uncorrectable input transmission error.in index.

45

Uncorrectable output to sequence transmission error.

46

Uncorrectable input from sequence transmission error.

ON-Unit Completion

If the ON-unit does not execute a nonlocal GOTO, processing continues as though no error had occurred. Any other errors in the statement execution, such as RECORD, will be raised.

To avoid unexpected results, if you close the file in the ON-unit, exit from the ON-unit using a nonlocal GOTO so statement execution will not continue.

UNDEFINEDFILE Condition

The UNDEFINEDFILE condition name can be specified in an ON, SIGNAL, or REVERT statement to designate an undefined file condition or ON-unit for a specific file.

The format of the UNDEFINEDFILE condition name is:

file-reference

A reference to a file constant or file variable for which the ON-unit is established.

If the name of a file variable is specified, the variable must be resolved to the name of a file constant when the on-unit is established, as well as when the condition is signaled.

PL/I signals the UNDEFINEDFILE condition when a file cannot be opened. Following are some examples of errors that cause the UNDEFINEDFILE condition:

  • The value specified by the TITLE option is an invalid file specification.
  • The file is opened for input or update and the specified file does not exist.
  • An existing file is accessed with PL/I file description attributes that are inconsistent with the file's actual organization.
  • Any system-detected file error prevents the file from being accessed.

The UNDEFINEDFILE condition lets you establish an ON-unit to provide processing when a file cannot be opened, for example, to provide a default file if no file is specified at run time.

X: PROCEDURE (FILENAME);

DECLARE FILENAME CHARACTER (128) VARYING;

DECLARE INPUT_FILE FILE INPUT;

ON UNDEFINEDFILE (INPUT_FILE)

OPEN FILE (INPUT_FILE)

TITLE ('GENERIC_INPUT');

OPEN FILE (INPUT_FILE) TITLE (FILENAME);

 

In this example, the procedure X expects a file specification string to be passed as an argument. If no argument is passed, or if the argument is not a valid file specification, the OPEN statement fails. The UNDEFINEDFILE ON-unit provides a default OPEN statement with the file specification GENERIC_INPUT.

An ON-unit established to handle the UNDEFINEDFILE condition can obtain information about the condition by invoking the following built-in functions:

  • The ONFILE built-in function returns the name of the variable defined as FILE that was being processed when the condition was signaled.
  • The ONCODE built-in function returns the specific status value associated with the error.
ON-Unit Completion

The action taken on a normal return from the UNDEFINEDFILE condition depends on whether the file was opened explicitly or implicitly.

If the UNDEFINEDFILE condition was signaled following an explicit OPEN statement for a file, then the normal action following the ON-unit execution is for the program to continue. If the ON-unit does not transfer control elsewhere in the program, control returns to the statement following the OPEN statement that caused the condition to be signaled.

If the UNDEFINEDFILE condition was signaled during an implicit open attempt, the run- time system tests the state of the file. If the file is not open, the ERROR condition is signaled. If the file was opened by the ON-unit, execution of the I/O statement continues.

If an ON-unit receives control when an explicit OPEN results in the UNDEFINEDFILE condition, and the ON-unit does not handle the condition by opening the file or by transferring control elsewhere in the program, control returns to the statement following the OPEN. Then, if an attempt is made to access the file with an I/O statement, the UNDEFINEDFILE condition is signaled again when PL/I attempts the implicit open of the file. This time, PL/I signals the ERROR condition on completion of the ON-unit.

UNDERFLOW Condition

You can specify the UNDERFLOW condition name (which can be abbreviated UFL) in an ON, REVERT, or SIGNAL statement to designate a floating-point underflow condition or ON-unit.

PL/I signals the UNDERFLOW condition when the absolute value of the result of an arithmetic operation on a floating-point value is smaller than the minimum value that can be represented by the hardware.

ON-Unit Completion

On completion of the ON-unit, control is returned to the point of the interrupt. Continued execution is unpredictable.

This condition is signaled by PL/I only in procedures in which the UNDERFLOW option is enabled. The option is enabled when you specify UNDERFLOW in the procedure options.

The value resulting from an operation that causes the UNDERFLOW condition is undefined. (The value would be set to zero only if UNDERFLOW were not specified in the procedure options.)

VAXCONDITION Condition

The VAXCONDITION condition name can be specified in an ON, RESIGNAL, REVERT, or SIGNAL statement. The VAXCONDITION condition name provides a way to signal and handle operating-system or programmer-specified condition values. The format of the VAXCONDITION condition name is:

VAXCONDITION (expression)

 
expression

An expression yielding a fixed binary value. The expression is evaluated when the ON statement is executed, as well as when the condition is signaled.

The VAXCONDITION condition name is provided specifically for PL/I procedures that interact with operating system routines. For details on using the VAXCONDITION condition name and the meanings of system- and user-defined values that you can specify, see the Kednos PL/I for UNIX User's Manual.

ZERODIVIDE Condition

The ZERODIVIDE condition name can be specified in an ON, REVERT, or SIGNAL statement to designate a divide-by-zero condition or ON-unit.

PL/I signals the ZERODIVIDE condition when the divisor in a division operation has a value of zero. The value resulting from such an operation is undefined.

Default PL/I ON-Unit

PL/I defines a default ON-unit for the procedure that is designated as the main procedure. This is why there must be exactly one procedure with OPTIONS(MAIN) specified in any executable image. This default ON-unit performs the following actions depending on the condition signaled. Note that the severity of the signal is determined by the low three bits of the condition code.

  • 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. Note that ENDPAGE is ignored by default for SYSPRINT (see See ENDPAGE Condition for more information).
  • 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, it is given a chance to execute. If it executes a nonlocal GOTO or if it 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 condition handler. This handler prints a message, displays a traceback, and terminates the program.
  • If the signal is any condition other than ENDPAGE or ERROR with a fatal severity, 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 resignal results in return of control to the system, the default condition handler prints a message and a traceback. If the error is a fatal error, the default handler terminates the program; if the error is nonfatal, the program continues.

Using Condition Prefixes (IBM Dialect Only)

Condition prefixes let you enable or disable one or more PL/I conditions for the duration of a single statement. You can attach a condition prefix to any statement except the following: DECLARE, DEFAULT, ENTRY, or a preprocessor statement (any statement beginning with a % sign). For example:

DECLARE SOURCE CHARACTER(5) VARYING,

TARGET FIXED BINARY(31);

 

(OVERFLOW,NOCONVERSION): TARGET = SOURCE;

 

Since you disabled the CONVERSION condition, PL/I does not signal it. However, if floating-point overflow occurs, PL/I signals the OVERFLOW condition.

As shown in the example, you can enable a condition by using the condition name, or disable it by using the negated condition name (for example, NOCONVERSION).

Scope of Condition Prefixes

A condition prefix affects only the statement or block to which it is attached. It does not affect procedures or ON-units invoked during execution of the statement or block.

Condition prefixes attached to DO or SELECT statements apply only to the DO or SELECT statement, not to the entire DO or SELECT group.

Condition prefixes attached to compound statements apply only to the statement to which they are attached, not to the statements contained in the compound statement.

Condition prefixes attached to PROCEDURE or BEGIN statements apply to all statements in the block, including the END statement and any other PROCEDURE or BEGIN statements nested inside the block. You can enable or disable a condition for an entire block and all the contained blocks by attaching a condition prefix to the PROCEDURE or BEGIN statement of the outermost block that you want to affect.

Default Status of Conditions

By default, some conditions are enabled unless explicitly disabled, others are disabled unless explicitly enabled, and some cannot be disabled. See . Conditions Enabled by Default , See . Conditions Disabled by Default , and See . Conditions That Cannot be Disabled list the conditions in each of these three categories..

. Conditions Enabled by Default

CONVERSION

FIXEDOVERFLOW

OVERFLOW

UNDERFLOW

ZERODIVIDE

 

. Conditions Disabled by Default

CHECK

SIZE

STRINGRANGE

STRINGSIZE

SUBSCRIPTRANGE

 

. Conditions That Cannot be Disabled

AREA

ATTENTION

CONDITION

ENDFILE

ENDPAGE

ERROR

FINISH

KEY

NAME

PENDING

RECORD

TRANSMIT

UNDEFINEDFILE

 

 

Note that the optimizer detects and diagnoses some conditions, whether or not you enable or disable them. If the optimizer detects a condition and diagnoses it, the condition is not raised when you execute the program.

Establishing ON-Units

An ON-unit is established for a specific ON condition or conditions following the execution of an ON statement that specifies the condition name(s). For example:

ON ENDFILE (ACCOUNTS) GOTO CLOSE_FILES;

 

This ON statement defines an ON-unit for an ENDFILE (end-of-file) condition in the file specified by the name ACCOUNTS. The ON-unit consists of a single statement, a GOTO statement.

After an ON-unit is established by an ON statement for a condition, it remains in effect for the activation of the current block and all its dynamically descendant blocks, unless one of the following occurs:

  • Another ON statement is specified for the same condition in a dynamically descendant block. The ON-unit established within the descendant block remains in effect as long as the descendant 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. (See See REVERT Statement ).
  • 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 reverted.
  • An ON-unit is established inside the ON-unit:

ON OVERFLOW BEGIN

ON OVERFLOW BEGIN

END;

END;

 

Contents of an ON-Unit

An ON-unit can consist of a single simple statement, a group of statements in a begin block, or a null statement.

Simple Statements in ON-Units

The following ON statement specifies a single simple statement in the ON-unit:

ON ERROR GOTO WRITE_ERROR_MESSAGE;

 

This ON statement specifies a GOTO statement that transfers control to the label WRITE_ERROR_MESSAGE in the event of the ERROR condition.

The specified statement must not be labeled and must not be any of the following:

DECLARE

FORMAT

RETURN

DO

IF

SELECT

END

ON

 

ENTRY

PROCEDURE

 

Begin Blocks in ON-Units

An ON-unit can also consist of a sequence of statements in a begin block. For example:

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.

If a BEGIN statement is specified for the ON-unit, the BEGIN statement must not be labeled. The begin block can contain any statement except a RETURN statement.

Null Statements in ON-Units

A null statement specified for an ON-unit indicates that no processing is to occur when the condition occurs. Program execution continues as if the condition had been handled. For example:

ON ENDPAGE(SYSPRINT);

 

This ON-unit causes PL/I to continue output on a terminal regardless of the number of lines that have been output.

Search Path for ON-Units

When a condition is signaled during the execution of a PL/I procedure, PL/I searches for an ON-unit to respond to the condition. PL/I first searches the current block, that is, the block in which the condition occurred. If no ON-unit exists in this block for the specific condition, it searches the block that activated the current block (its parent), and then the block that activated that block, and so on.

PL/I executes the first ON-unit it finds, if any, that can handle the specified condition. If no ON-unit for the specific condition is found, default PL/I condition handling is performed.

Completion of ON-Units

The ON-unit can complete its execution in any of the following ways:

  • If the ON-unit executes a nonlocal GOTO statement, or if it invokes a subroutine or function that executes a nonlocal GOTO, program control is transferred to that statement and continues sequentially at that point in the program.
  • If the ON-unit executes a STOP statement, then the FINISH condition is signaled. If no FINISH ON-unit exists, the program is terminated.
  • An ON-unit can use the RESIGNAL built-in subroutine to request that PL/I continue to search for an ON-unit to handle a specific condition.
  • When any ON-unit (except for ERROR or FINISH) completes normally, control returns either to the statement that caused the condition or to the statement immediately following the statement that caused the condition.

Descriptions of each ON condition in this manual indicate the action that PL/I takes on completion of an ON-unit associated with the condition.

 

Input and Output

PL/I provides two distinct types of I/O processing, each of which handles input and output data in a different manner, and each of which has a unique set of I/O statements. These types of I/O are:

When a file is read or written with stream I/O, the data is treated as if it formed a continuous stream. Individual fields of data within the stream are delimited by commas, spaces, and record boundaries. A stream I/O statement specifies one or more fields to be processed in a single operation.

When a file is read or written with record I/O, however, a single record is processed upon the execution of an I/O statement.

This chapter describes I/O concepts that apply to both stream and record I/O.

Opening and Closing Files

This section discusses the following:

File Declarations

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

A file is denoted in an I/O statement by the FILE option as follows:

FILE(file-reference)

 
file-reference

The name specified in the file declaration. For example:

DECLARE INFILE FILE SEQUENTIAL INPUT;

OPEN FILE(INFILE);

 

Here, INFILE is the name of a file constant. A file constant is an identifier declared with the FILE attribute and without the VARIABLE attribute. Except for the default file constants SYSIN and SYSPRINT, all files must be declared before they can be opened and used.

By default, all file constants have the EXTERNAL attribute. Any external procedure that declares the identifier with the FILE attribute and without the INTERNAL attribute can access the same file constant and, therefore, the same physical file.

File Variables

In PL/I, you can also refer to files using file variables and file-valued functions. For example:

DECLARE ANYFILE FILE VARIABLE;

 

ANYFILE = INFILE;

OPEN FILE(ANYFILE);

 

If INFILE is declared as in the previous example, the OPEN statement opens the file INFILE.

A file variable can also be given a value by receiving a file constant or variable passed as an argument, or by receiving a file constant or variable as the value of a function. For example:

GETFILE: PROCEDURE (PRINTFILE);

DECLARE PRINTFILE FILE VARIABLE;

 

This file variable is given a value when the procedure GETFILE is invoked.

Opening a File

A file is opened explicitly by an OPEN statement or implicitly by a READ, WRITE, REWRITE, DELETE, PUT, or GET statement issued for a file that is not open.

The OPEN statement explicitly opens one or more PL/I files with a specified set of attributes that describe the file and the method for accessing it. The format of the OPEN statement is as follows:

OPEN FILE(file-reference) [file-attributes-and-options ...]

[,(file-reference) [file-attributes-and-options ...]] ...;

 
FILE(file-reference)

A reference to the file to be opened. If the file is already open, the OPEN statement has no effect. Therefore, if you want to change any attributes of an open file, you should first close it, and then reopen it with the new attributes.

file-attributes-and-options

The attributes and options of the file. The attributes specified are merged with the permanent attributes of the file specified in its declaration, if any. Then, default rules are applied to the union of these sets of attributes to complete the set of attributes in effect while the file is open.

The attributes you can specify with the OPEN statement are as follows:

BUFFERED (ibm dialect only)

PRINT

DIRECT

RECORD

ENVIRONMENT(option,...) (dec and ansi dialects only)

SEQUENTIAL

INPUT

STREAM

KEYED

UNBUFFERED (ibm dialect only)

OUTPUT

UPDATE

The file attributes are described in See , See Declarations .

The OPEN options are described in See OPEN Statement Options .

Examples

DECLARE INFILE FILE,

STATE_FILE FILE KEYED;

 

OPEN FILE (INFILE),

FILE (STATE_FILE) UPDATE;

CLOSE FILE (STATE_FILE);

OPEN FILE (STATE_FILE) INPUT SEQUENTIAL;

 

The DECLARE and OPEN statements for INFILE do not specify any file description attributes; PL/I applies the default attributes STREAM and INPUT. If any statement other than GET is used to process this file, the ERROR condition is signaled.

The file STATE_FILE is declared with the KEYED attribute. With the first OPEN statement that specifies this file, it is given the UPDATE attribute and opened for updating; that is, READ, WRITE, REWRITE, and DELETE statements can be used to operate on records in the file. The KEYED attribute implies the SEQUENTIAL attribute; thus, records in the file can be accessed sequentially or by key.

The second OPEN statement specifies the INPUT and SEQUENTIAL attributes. During this opening, the file can be accessed by sequential and keyed READ statements, but REWRITE, DELETE, and WRITE statements cannot be used.

DECLARE COPYFILE FILE OUTPUT;

OPEN FILE(COPYFILE) TITLE('COPYFILE.DAT');

 

The file specified by the file constant COPYFILE is opened for output. Each time this program is run, it creates a new version of the file COPYFILE.DAT.

OPEN Statement Options

The options that you can use in the OPEN statement are:

LINESIZE Option

The LINESIZE option specifies the maximum number of characters that can be output on a single line when the PUT statement writes data to a file with the STREAM and OUTPUT attributes. The format of the LINESIZE option is:

LINESIZE(expression)

 
expression

A fixed-point binary expression in the range 1 to 32767, giving the number of characters per line. If the expression is outside this range, a run-time error occurs.

The value specified in the LINESIZE option is used as the output line length for all subsequent output operations on the stream file, and it overrides the system default line size.

In the ibm dialect, if RECSIZE was specified in the declaration of a stream file, it is used as the output line length. However, if LINESIZE is specified in the OPEN statement, it overrides the previous RECSIZE specification.

The default line size is as follows:

  • If the output is to a physical record-oriented device, such as a line printer or terminal, the default line size is determined by the device.
  • If the output is to the default file, SYSPRINT, the default line size is 80.
  • If the output is to a print file, the default line size is 132.
  • If the output is to a nonrecord device (magnetic tape), the default line size is 510.

The line size is used by output operations to determine whether output will be placed on the current line or on the next line.

PAGESIZE Option

The PAGESIZE option is used in the OPEN statement to specify the maximum number of lines that can be written to a print file without signaling the ENDPAGE condition. The format of the PAGESIZE option is:

PAGESIZE(expression)

expression

A fixed-point binary expression in the range 1 through 32767, giving the number of lines per page. If the expression is outside this range, a run-time error occurs.

The value specified in the PAGESIZE option is used as the output page length for all subsequent output operations on the print file, and overrides the system default page size. The default page size is the following:

  • If the environment variable SYS$LP_LINES is defined, the default page size is the numeric value of SYS$LP_LINES minus 6.
  • If SYS$LP_LINES is not defined, or if its value is less than 30 or greater than 99, or if its value is not numeric, the default page size is 60.

During output operations, the ENDPAGE condition is signaled the first time that the specified page size is exceeded.

The PAGESIZE option is valid only for print files.

TITLE Option

The TITLE option is specified in an OPEN statement to designate the external file specification of the file to be associated with the PL/I file. The TITLE option is specified only on the OPEN statement for a file. Its format is as follows:

TITLE(expression)

 
expression

A character-string expression which represents an external file specification for the file.

For details on how the file specification is determined see the See Determining the File Specification .

Effects of Opening a File

Opening a file in PL/I has the following effects:

  • Any permanent attributes specified in a DECLARE statement of a file constant are merged with the attributes specified in the OPEN statement, if any, or with the attributes implied by the context of the opening. (For example, if no attributes are specified for a file in its declaration, and the first reference to the file is a GET statement, PL/I opens the file with the INPUT and STREAM attributes.) The rules that PL/I follows in applying default attributes are described in the next section.
  • The merged attributes apply to the file for the duration of this opening only. When the file is closed, only its permanent attributes remain in effect.
  • The file specification of the file is determined. This process is described in See Determining the File Specification .
  • If the file already exists, it is located and its attributes are checked for compatibility with the attributes specified or implied by the OPEN statement.
  • If the file does not exist, and if the attempted access does not require that the file exist, PL/I creates a new file using the attributes specified or implied to determine the file's organization.
  • If the file is opened successfully, the file is positioned.

Each of these steps is described in more detail below. If an error occurs during the opening of a file, the UNDEFINEDFILE condition is signaled (see the Kednos PL/I for UNIX User's Manual for more information on handling conditions).

Establishing the File's Attributes

The description attributes specified when a file is opened are merged with the file's permanent attributes. Duplicate specification of an attribute is allowed only for an attribute that does not specify a value.

An incomplete set of attributes is augmented with implied attributes. See . File Description Attributes Implied when a File is Opened summarizes the attributes that can be added to an incomplete set.

. File Description Attributes Implied when a File is Opened

Attribute

Implied Attributes

DIRECT

RECORD KEYED

KEYED

RECORD

PRINT

STREAM OUTPUT

SEQUENTIAL

RECORD

UPDATE

RECORD

If the set of attributes is still not complete, PL/I uses the following steps to complete the set:

  1. If neither STREAM nor RECORD is present or implied, STREAM is supplied.
  2. If neither INPUT, nor OUTPUT, nor UPDATE is present, INPUT is supplied.
  3. If RECORD is specified, but neither SEQUENTIAL nor DIRECT is present or implied, SEQUENTIAL is supplied.
  4. If the file is associated with the external file constant SYSPRINT, and the attributes STREAM and OUTPUT are present but the attribute PRINT is not, PRINT is supplied.
  5. If the set contains the LINESIZE option, it must contain STREAM and OUTPUT. If it contains these attributes and does not contain LINESIZE, the default system line size value is supplied.
  6. If the set contains the PAGESIZE option, it must contain PRINT. If PRINT is present but PAGESIZE is not, the default system page size is supplied.

The completed set of attributes applies only for the current opening of the file. The OPEN command does not change the permanent file attributes, specified in the file declaration.

Determining the File Specification

PL/I uses the value of the TITLE option to determine the file specification, that is, the actual name of the file or device on which the I/O is to be performed. The determination of the file specification depends on the following system-specific functions:

  1. The value of the TITLE option can be an environment variable, or a portion of it can contain an environment variable. In either case, the environment variable is translated. If the resulting name is an environment variable, that name is also translated, to a maximum of 10 translations.
  2. After translation, PL/I applies any default values specified in the DEFAULT_FILE_NAME option of the ENVIRONMENT attribute list.
  3. If the file specification is still not complete, system defaults are applied to the incomplete portions of the file specification.

If a file name is not specified, PL/I uses the default name, which is the name of the file constant which declared the file.

The maximum length of the expanded file specification is 128.

The rules for environment variable translation and for the application of system defaults are described in the Kednos PL/I for UNIX User's Manual.

Accessing an Existing File

A file opening accesses an existing file if the file specified by the TITLE option actually exists and if the following attributes are present:

  • The file is opened for INPUT or UPDATE.
  • The file is opened with the OUTPUT attribute and with the ENVIRONMENT(APPEND) option.

Whenever PL/I accesses an existing file, the file's organization is checked for compatibility with the PL/I attributes specified. If any incompatibilities exist, the UNDEFINEDFILE condition is signaled.

Creating a File

A file opening creates a new file if the following are all true:

  • The OUTPUT attribute is specified.
  • The TITLE option, after name translation and the application of system defaults, specifies a mass-storage device (such as a disk or a tape).
  • The ENVIRONMENT(APPEND) option is not specified.

You can specify the organization and record format of a new file with ENVIRONMENT options. If no ENVIRONMENT options are given, the new file's organization is determined as follows:

  • If the KEYED attribute is present, PL/I creates a relative file with a maximum record size of 480 bytes and a maximum record number of -2147883647.
  • If the PRINT attribute is present, PL/I creates a sequential file with variable-length records, maximum record length of 508, and a 2 byte fixed-control field used to store carriage-control information.
  • If neither KEYED nor PRINT is specified, PL/I creates a sequential file with variable-length records and a maximum record size of 510 bytes.

When a file is opened with the RECORD and OUTPUT attributes, only WRITE statements can be used to access the file. If the file has the KEYED attribute as well, the WRITE statements must include the KEYFROM option.

File Positioning

When PL/I opens a file, the initial positioning of the file depends on the type of file (record or stream), the access mode, and certain ENVIRONMENT options.

For a definition of the file-positioning information for record files, see See Position Information for a Record File . For a definition of file-positioning information for stream files, see See Processing and Positioning of Stream Files .

File Description Attributes and Options

The file description attributes are summarized in See . Summary of File Description Attributes . These attributes can be specified on DECLARE and OPEN statements.

. Summary of File Description Attributes

Attribute

Description

BUFFERED

Records must pass through intermediate storage buffers. (ibm dialect only)

DIRECT

Records in the file will be accessed randomly.

INPUT

The file is an input file and will only be read.

KEYED

Records in the file will be accessed by key.

OUTPUT

The file is an output file and will only be written.

PRINT

The file will be output on a printer or terminal.

RECORD

The file will be accessed with record I/O statements.

SEQUENTIAL

Records in the file will be accessed sequentially.

STREAM

The file will be accessed with stream I/O statements.

UNBUFFERED

Records need not pass through intermediate storage buffers.(ibm dialect only)

UPDATE

The file will be accessed for both reading and writing, and records can be rewritten and deleted.

For detailed descriptions of these attributes, see See , See Declarations .

Closing a File

The CLOSE statement dissociates PL/I files from the physical files with which they were associated when opened. The format of the CLOSE statement is as follows:

CLOSE FILE (file-reference) [ENVIRONMENT(DELETE)]

[,FILE(file-reference) [ENVIRONMENT(DELETE)]] ...;

 
FILE(file-reference)

A file to be closed. If the file is already closed, the CLOSE statement has no effect.

ENVIRONMENT(DELETE)

The DELETE ENVIRONMENT option is valid for the CLOSE statement in the dec and ansi dialects of Kednos PL/I for UNIX. The DELETE environment option specifies that the file is to be deleted when it is closed. For more information see the Kednos PL/I for UNIX User's Manual.

Examples

This CLOSE statement closes the file constant INFILE:

CLOSE FILE(INFILE);

 

Another example of a CLOSE statement is:

DECLARE STATE_FILE FILE KEYED;

 

OPEN FILE(STATE_FILE) DIRECT UPDATE;

CLOSE FILE(STATE_FILE);

OPEN FILE(STATE_FILE) INPUT SEQUENTIAL;

 

The file STATE_FILE is declared with the KEYED attribute. The first OPEN statement that specifies this file is given the DIRECT and UPDATE attributes and opened for updating; the file can be accessed only by key.

The CLOSE statement closes the file. The second OPEN statement specifies the INPUT and SEQUENTIAL attributes; the file can now be accessed sequentially.

Stream I/O

Stream I/O is one of the two general kinds of I/O performed by PL/I. Stream input and output is performed by the statements GET and PUT, respectively. Both statements can perform either list- directed or edit-directed operations.

In stream I/O, more than one record or line can be processed by a single statement, and, conversely, multiple statements can process a single line or record. In contrast, record I/O only processes one record of a file in each READ or WRITE statement.

See . Attributes and Access Modes for Stream Files summarizes the file description attributes and access modes for stream files.

. Attributes and Access Modes for Stream Files

Attributes Specified

Attributes Implied

Valid Devices and File Organizations

Usage

PRINT

STREAM OUTPUT

Any output device and any file

Individual data values are written with PUT statements that convert the values to character strings and automatically format the strings into lines, or records. A PUT statement can fill part or all of one or more lines. Data conversion and alignment within lines can use the default processing provided by the PUT LIST form of the PUT statement or can be explicitly controlled by format specifications in the PUT EDIT form of the PUT statement. The output fields can be aligned to specific tab positions.

The PAGESIZE and LINESIZE options can be specified to control the formatting of lines on pages. The ENDPAGE condition is signaled when the end- of-page is reached.

STREAM INPUT

 

Any input device and any file

Individual data items are read by GET statements. A single GET statement can process all or part of one or more lines or records. The format of an input field can be determined by the default processing provided by the GET LIST form of the GET statement or can be explicitly controlled by format specifications in the GET EDIT form of the GET statement.

STREAM OUTPUT

 

Any output device and any file

This form of stream output is similar to that provided when PRINT is specified, except that tab positioning and page formatting are not provided. Moreover, when string values are written with the PUT LIST form of the PUT statement, they are enclosed in apostrophes. Files that are created with these attributes can be read back in with GET LIST statements when the file is opened with the STREAM and INPUT attributes.

Successive GET statements acquire their input from the same line or record until all the characters in the line have been read, unless the program explicitly skips to the next line. When necessary, a single GET statement will read multiple lines to satisfy its input-target list. A single input data item cannot cross a line unless it is a character string enclosed in apostrophes or unless the ENVIRONMENT option IGNORE_LINE_MARKS is in effect for the input file. This option produces stream input operations that match exactly with standard PL/I. However, the option is usually not necessary; most programs produce the expected results without it. (For more information on ENVIRONMENT, see the Kednos PL/I for UNIX User's Manual.

Successive PUT statements write their output to the same line or record until the line size is reached or until the program explicitly skips to a new line. A single PUT statement will write as many records as necessary to satisfy its output-source list. Any single data item that will not fit on the current line is split across lines.

The next sections describe the following aspects of stream I/O:

Processing and Positioning of Stream Files

A stream file is a file of ASCII text, divided into lines. For every stream file used in a program, PL/I maintains the following information:

  • The locations of the beginning and end of the file. On input operations, the ENDFILE condition is signaled on the first attempt to read past the end of the file.
  • For output files, the maximum number of ASCII characters in a line, or the line size. The line size is either a default value or the specific value you have established for the file (see See Opening and Closing Files for LINESIZE option). The line size is used to determine when to skip to the next line. On input, a single data item cannot cross a line unless it is a character string enclosed in apostrophes or unless the file was opened with ENVIRONMENT (IGNORE_LINE_MARKS). On output, data items are continued on the next line.
  • The current position in the file. Essentially, this is the point in the file at which the last input or output operation stopped. It is the exact character position at which the next output item is written or from which the next input item is read.

Input operations can begin at any position from the current position onward. The default is the current position. To acquire data from a different position, do the following:

  • Use the SKIP option of the GET statement to advance by a specified number of lines before reading data.
  • Use control format items to move to a specified position before reading data. The GET statement restricts control format items to SKIP (the same operation as the SKIP option), COLUMN (advance to a specified character position), and X (advance by a specified number of character positions from the current position). Note that the control format items, unlike the SKIP option, are executed during, not before, the input of data. The control format items can signal the ENDFILE and ERROR conditions if the end-of-file is encountered.
  • Close and then reopen the file, which sets the current position to the first character in the file.

Because stream files are sequential files, output operations always place data at the end of the file. Do the following additional formatting of output with any stream output file:

  • Use the SKIP option of the PUT statement to skip lines following the current position. If the current position is the beginning of a line, the SKIP option inserts null lines in the file between the current position and the position of the next output.
  • Use the control format items to advance to a specified line or character position. The control format items are COLUMN (move to a specified character position), SKIP (the same effect as the SKIP option), and X (skip a specified number of characters following the current position). As with the input case, control format items execute only during the output of data; if only part of the format list is used, the excess control format items are ignored.

If the output file is a print file (that is, has the attributes STREAM, OUTPUT, and PRINT, or is the default file SYSPRINT), the following additional information is maintained for the file:

  • The current page number. The first output to a print file is written to page 1. The current page number is incremented by the PAGE option, the PAGE format item, and, in some circumstances, by the LINE option and LINE format item. You can evaluate the current page number for a specified print file with the PAGENO built-in function. You can also set it to a new value by assigning a value to the PAGENO pseudovariable.
  • The page size. This is an integer that specifies the number of lines on a page. The page size is either the default value or the specific number that you have established for the print file (see See Opening and Closing Files ). When the last line on a page is filled, the first attempt to write (or position the file) beyond that position signals the ENDPAGE condition. The ENDPAGE condition is signaled only on the first such attempt; if no ON-unit is established for the condition, a PUT PAGE is executed. For example, the ON-unit for the ENDPAGE condition can write a trailer at the bottom of the current page, or a header at the top of the next page, before printing a new page of data.
  • The current line number. This is an integer specifying the line currently being used for output, relative to the top of the page. The first line on the page is line 1. The LINENO built-in function can evaluate the current line of a specified print file. The LINE option of the PUT statement, and the LINE format item, can reposition the file to a specified line.
  • Position of tab stops. Tab stops always occur at 8-column increments on every line of a print file, beginning with column 1. The TAB format item can reposition a print file to a specified tab stop relative to the current position.

Terminals should always be declared as print files when used for output (see See Terminal I/O .)

Input by the GET Statement

The GET statement acquires data from an input stream, which is either a stream file or a character-string expression. The input file can be a file declared with the STREAM attribute or the default file SYSIN, usually associated with the user's default input device. See See Terminal I/O for more information.

This section describes the syntax, options, and execution of GET statements.

Syntax Summary of the GET Statement

The GET statement has several forms, as follows:

GET EDIT (input-target*, ...) (format-specification, ...)

GET LIST (input-target*, ...)

 

GET [FILE(file-reference)]* SKIP [(expression)] ;

 

Options* (dec and ansi dialects only)

NO_ECHO

NO_FILTER

PROMPT(expression)

PURGE_TYPE_AHEAD

 

*Syntax elements common to two or more forms

input-target

The names of one or more variables to be assigned values from the input stream. Multiple input targets must be separated by commas.

An input target has one of the following forms:

reference

 

The reference is to a scalar or aggregate variable of any computational type. If the reference is to an array, data is assigned to array elements in row- major order. If the reference is to a structure, data is assigned to structure members in the order of their declaration.

(input-target, ... DO reference=expression [TO expression]

[BY expression] [WHILE(expression)] [UNTIL(expression)])

 

Another form is:

(input-target, ... DO reference=expression

[REPEAT expression] [WHILE(expression)] [UNTIL(expression)])

 

The input target can be any of these forms, and the references and expressions are as for the DO statement. Notice that the parentheses surrounding the input target are in addition to the parentheses surrounding the entire input list.

For a discussion of the matching of format items to input targets and of the use of DO specifications, see See Format Specifications .

format-specification

A list of format items to control the conversion of data items in the input list. You can use data format items, control format items, or remote format items. For each variable name in the input-target list, there is a corresponding data format item in the format-specification list that specifies the width of the field and controls the data conversion. See See Format Items for more information.

FILE (file-reference)

An option specifying that the input stream is a file; the reference is to a declared file variable or constant. If neither the FILE option nor the STRING option is specified, PL/I assumes the file SYSIN. This file is associated with the default system input file SYS$INPUT.

If a file is specified and is not currently open, PL/I opens it with the attributes STREAM and INPUT. The UNDEFINEDFILE condition is signaled if the file cannot be opened.

SKIP [(expression)]

An option that advances the input file a specified number of lines before processing the input list. This option can be used only with the implied or explicit FILE option. If the expression is specified, it indicates the number of lines to be advanced; if it is omitted, the default is to skip to the next line. The SKIP option is always executed first, before any other input or positioning of the input file, regardless of its position in the statement.

OPTIONS (option, ...) (dec and ansi dialect only)

An option that specifies one or more of the following options. This option can be used only with the default or explicit FILE option; it cannot be used with the STRING option. Multiple options must be separated by commas.

CANCEL_CONTROL_O

NO_ECHO

NO_FILTER

PROMPT (string-expression)

PURGE_TYPE_AHEAD

The options are described fully in the Kednos PL/I for UNIX User's Manual.

STRING(expression)

An option specifying that the input stream is a character-string expression. The STRING option cannot be used with the FILE, OPTIONS, or SKIP option.

The GET STRING statement acquires a string from a character-string variable and assigns it to one or more input targets. If more than one input target is listed, the characters in the string should include any punctuation (comma or space separators or apostrophes) that would be required if the character string were in an external file.

GET EDIT

The GET EDIT statement acquires fields of character-string data from an input stream, which can be a stream file or a character-string expression. The stream file can be a declared file or the default file SYSIN. GET EDIT converts the character strings under control of a format specification and assigns the resulting values to a specified list of input targets (variables). It also allows input of characters from selected positions in the input stream.

The form of the GET EDIT statement is as follows:

GET EDIT (input-target, ...) (format-specification, ...)

The syntax is described in more detail in See Syntax Summary of the GET Statement .

Examples

GET EDIT (FIRST,MID_INITIAL,LAST) (A(12),A(1),A(20));

 

This statement reads the next 12 characters from the default stream input file (SYSIN) and assigns the string to FIRST. It then reads the next character into MID_INITIAL, and then the next 20 characters into LAST.

GET EDIT (SOCIAL_SECURITY) (A(12))

FILE (SOCIAL) SKIP (12);

 

This statement opens the stream file SOCIAL if the file was closed, advances 12 lines, reads the first 12 characters of the line, and assigns the characters to the variable SOCIAL_SECURITY.

GET EDIT (N, (A(I) DO I=1 TO N))

(F(4),SKIP,100 F(10,5));

 

where the dimension of A is less than or equal to 100. This reads the value of N from the input stream using the format item F(4). The process then skips to the next line (record). It reads N elements into the array A, using the format item F(10,5) for each element.

GET EDIT (NAME.FIRST,NAME.LAST)

(A(10),X(3),A(20))

STRING('Philip    A. Rothberg            ');

 

This statement assigns `Philip ' to the structure member NAME.FIRST, skips the middle initial, period, and space, and assigns `Rothberg             ' to NAME.LAST.

GET LIST

The GET LIST statement acquires character-string data from an input stream, which can be a stream file or a character-string expression. The stream file can be a declared file or the default file SYSIN. The acquired character strings are assigned to input targets named in the GET LIST statement, after being converted automatically to the target data types.

Use the GET LIST statement to read unformatted data from a stream file or character string. Because GET LIST does not require that data be aligned in specific columns, it is useful for acquiring input from a terminal.

The form of the GET LIST statement is as follows:

GET LIST (input-target, ...)

The syntax is described in more detail in See Syntax Summary of the GET Statement .

Specifying Input Data

The items to be read into the input targets are separated by a space or a single comma. Multiple spaces are treated as a single space, and a comma can be surrounded by spaces. The following rules apply:

  • No items can be split across lines unless the split occurs inside a quoted string.
  • Character strings do not have to be enclosed in apostrophes unless they contain a space or comma or are written on more than one line. When a character string is enclosed in apostrophes, n apostrophes within the string are written as n * 2 apostrophes; for instance, the word isn't would be specified as either:

isn't or 'isn''t'

 

  • When a line begins with a comma or when two commas appear in the line without intervening nonspace characters, the item in the input-target list corresponding to that item is not updated. The target retains whatever value it contained before GET LIST was executed.
  • Every input field, including the last input field in a line, must be terminated by a space, a comma, or a carriage return.
  • Input fields are also terminated by the end-of-file (FILE option) or end-of-string (STRING option), unless the end is encountered inside a quoted string.
  • If an input request from GET LIST encounters a null record, the null character string ('') is assigned, with appropriate conversion, to the corresponding input target. A null input record means a null record in a file or, if the input is from a terminal, a carriage return with no other input. See See Terminal I/O for examples. ENVIRONMENT (IGNORE_LINE_MARKS) is used for the input file, record terminators such as the carriage return are ignored, and the GET LIST statement waits until the input request is satisfied.
  • The CONVERSION condition is signaled whenever a data item in the stream cannot be converted to the data type of the corresponding item in the input-target list.
  • The ENDFILE condition is signaled if the end of the file is encountered during file input. The ERROR condition is signaled if the expression in the STRING option does not contain enough characters to complete processing of the input-target list.
Examples

GETS: PROCEDURE OPTIONS(MAIN);

 

DECLARE NAME CHARACTER(80) VARYING;

DECLARE AGE FIXED;

DECLARE (WEIGHT,HEIGHT) FIXED DECIMAL(5,2);

DECLARE SALARY PICTURE '$$$$$$V.$$';

DECLARE DOSAGE FLOAT;

 

DECLARE INFILE STREAM INPUT FILE;

DECLARE OUTFILE PRINT FILE;

 

GET FILE(INFILE)

LIST(NAME,AGE,WEIGHT,HEIGHT,SALARY,DOSAGE);

PUT FILE(OUTFILE)

LIST(NAME,AGE,WEIGHT,HEIGHT,SALARY,DOSAGE);

END GETS;

 

If the file INFILE.DAT contains the following data:

'Thomas R. Dooley',33,150.60,5.87,15000.50,4E-6,

 

then the program GETS writes the following output to OUTFILE.DAT:

Thomas R. Dooley 33 150.60 5.87 $15000.50 4.0000000E-06

 

In the input file (INFILE.DAT), the string `Thomas R. Dooley' is surrounded by apostrophes so PL/I will not interpret the spaces between words as field separators.

GSTR: PROCEDURE OPTIONS(MAIN);

 

DECLARE STREXP CHARACTER(80) VARYING;

DECLARE (A,B,C,D,E) FIXED;

DECLARE OUTFILE STREAM OUTPUT FILE;

 

OPEN FILE(OUTFILE) TITLE('GSTR.OUT');

STREXP = '1,2,3,4,5';

GET STRING(STREXP) LIST(A,B,C,D,E);

PUT FILE(OUTFILE) LIST(A,B,C,D,E);

END GSTR;

The program GSTR writes the following output to GSTR.OUT:

1 2 3 4 5

For other examples, see See Terminal I/O .

GET SKIP

The GET SKIP statement positions the input file at the start of a new line. The format of this GET statement is as follows:

GET [FILE(file-reference)] SKIP [(expression)] ;

 

The syntax is described in more detail in See Syntax Summary of the GET Statement .

Execution of the GET Statement

When a GET statement is executed, the first action is to evaluate the FILE option, if there is one. For example:

GET FILE(INFILE) LIST(A);

 

If INFILE references an open file, PL/I checks that the file has the INPUT and STREAM attributes.

If INFILE has not been opened, PL/I implicitly opens the file with the attributes INPUT and STREAM.

If the associated file does not exist, or if for any reason the associated file cannot be opened, the UNDEFINEDFILE condition is signaled.

If the statement has a STRING option instead of a FILE option, the reference in the STRING option is evaluated.

If the statement has neither a FILE option nor a STRING option, it is taken to refer to the default file constant SYSIN. SYSIN is declared by default with the STREAM INPUT attributes, and it is normally used for input from a terminal (see See Terminal I/O ).

If the input stream is a file, the next action is to execute the SKIP option, if there is one. The SKIP option cannot be used with the STRING option. Note that a GET statement can perform a SKIP operation even if it performs no data input. For example:

GET FILE(INFILE) SKIP(2);

 

This statement repositions the file referenced by INFILE to the second line following the current line in the file.

A GET statement that has the EDIT or LIST option performs input from the stream to a list of input targets, which must be variables of computational data types. If the input target is an aggregate variable, then input is assigned to each element of the aggregate; input values are assigned to array elements in row- major order and to structure members in the order of their declaration. An input target can also contain a DO construct that further controls the assignment. Because a stream consists only of ASCII characters, and the input targets are not necessarily character-string variables, an input field must be selected from the input stream for each target and must be converted, if necessary, to the type of the target.

In edit-directed (GET EDIT) statements, the selection and assignment of the input field are controlled by a format item that corresponds to the input target. In the default case, which applies to terminal input and to input from most stream files, a data format item assumes that the end of the input field has occurred if it encounters the end of a record in an input file or the end of a line when the input is from a terminal.

For example, a common technique for reading lines of varying length from a terminal is to deliberately use a format item that specifies a field wider than the column width of the terminal. If the user types a carriage return in response to an input request for GET EDIT, or if the end of a record is immediately encountered, the requested field width is filled with spaces and assigned to the input target under the control of the corresponding format item. (Note that all spaces will cause an error for B format items.) However, if the input stream is a character-string expression (GET STRING), the ERROR condition is signaled if the format item causes the end of the input string to be reached in the middle of an input field. If the input stream is a file declared or opened with ENVIRONMENT(IGNORE_LINE_MARKS), the search for characters to complete the input field continues at the next record.

In list-directed (GET LIST) statements, an input field is acquired by examining the input stream for the next character that is not a space character.

The following actions are taken depending on the character found:

  • If the next nonspace character is an apostrophe, the input field is assumed to contain a bit- or character-string constant, in the same format as that used to write a string constant in a program. The constant is acquired and can span the end of a record or line. However, the ERROR condition is signaled if the end of the file is reached before the terminating apostrophe is found; if the input stream is a character-string expression rather than a file, the ERROR condition is signaled if the end of the string is reached. The apostrophes and B suffix are removed from the constant, and any double apostrophe within a character-string constant is changed to a single apostrophe. (If the field contains a bit-string constant in base 4, octal, or hexadecimal radix, its binary equivalent is found.) The resulting character bit-string value is then assigned to the corresponding input target. If the input target is not of the same data type, the input value is converted according to the PL/I conversion rules (see See Data Type Conversion of Operands and Expressions ).
  • If the next nonspace character is a comma, and the previous operation on the input file was by GET LIST, and the previous input field was terminated by a space, carriage return, or end-of-record, the scan continues. If the next nonspace character is a comma, and the previous nonspace character was also a comma, the corresponding input target is skipped; the input target retains whatever value it had before the GET LIST statement.
  • If the input line or record is empty (that is, a carriage return or end-of-record is encountered immediately after the beginning of a line). The null character string ('') is assigned to the input target with appropriate type conversion. If the input file was opened with ENVIRONMENT(IGNORE_LINE_MARKS), the carriage return or end-of-record is ignored.
  • If the next nonspace character is neither a comma nor an apostrophe, the input field is then assumed to begin with this character and to be terminated by the next space, comma, carriage return, end-of-record (if ENVIRONMENT(IGNORE_LINE_MARKS) was not used), end-of-file (if the input stream is a file), or end-of-string (if the input stream is a character string). All the characters in the field are acquired and assigned, with appropriate type conversion, to the input target.

If the GET LIST statement attempts to read a file after its last input field has been read, or if it attempts to read an empty file, the ENDFILE condition is signaled. If the GET LIST statement attempts to read a character string after its last field has been read, or if it attempts to read a null string, the ERROR condition is signaled.

Output by the PUT Statement

The PUT statement transfers data from the program to the output stream. The output stream can be either a stream file or a character-string variable. The output file can be a declared file or the default file SYSPRINT.

This entry describes the syntax, options, and execution of PUT statements.

Syntax Summary of the PUT Statement

The PUT statement has several forms, as follows:

PUT EDIT (output-source*, ...) (format-specification, ...)

PUT [FILE (file-reference)*] LINE (expression);

 

PUT LIST (output-source,)*

PUT [FILE (file-reference)*] PAGE;

 

PUT [FILE (file-reference)*] SKIP [(expression)] ;

 

*Syntax elements common to two or more forms

output-source

A construct that specifies one or more expressions to be placed in the output stream. Multiple output sources must be separated by commas.

An output source has the following forms:

expression

 

The expression is of any computational type, including a reference to a scalar or aggregate variable. If the reference is to an array, data is output from array elements in row-major order. If the reference is to a structure, data is output from structure members in the order of their declaration.

(output-source, ...DO reference=expression

[TO expression][BY expression] [WHILE(expression)] [UNTIL(expression)])

 

Another form is:

(output-source, ...DO reference=expression

[REPEAT expression][WHILE (expression)][UNTIL(expression)])

 

The output source can be any of these forms, and the references and expressions are as for the DO statement. Notice that the parentheses surrounding this form of output source are in addition to the parentheses surrounding the entire output- source list.

For a discussion of the matching of format items to output sources and of the use of DO specifications, see See Format Specifications .

format-specification

A list of format items to control the conversion of data items in the output list. Format items can be data format items, control format items, or remote format items. For each variable name in the output-source list, there is a corresponding data format item in the format-specification list that specifies the width of the output field and controls the data conversion (see See Format Specifications and See Format Items ).

FILE(file-reference)

An option that specifies that the output stream be a stream file; the reference is to a declared file variable or constant. If neither the FILE option nor the STRING option is specified, PL/I uses the default file SYSPRINT. SYSPRINT is associated with the default system output file SYS$OUTPUT, which in turn is generally associated with the user's terminal.

If a file is specified, and it is not currently open, PL/I opens the file with the attributes STREAM and OUTPUT.

PAGE

An option that advances the output file to a new page before any data is transmitted. The PAGE option can be used only with implied or explicit print files. The file is positioned at the beginning of the next page, and the current page number is incremented by 1. The PAGE, LINE, and SKIP options are always executed, in that order, before any other output or file-positioning operations. The page size is either the default value or the specific value that you have established for the file (See See Opening a File ). The PAGESIZE option can be used only with print files.

LINE (expression)

An option that advances the output file to a specified line. You can use the LINE option only with implied or explicit print files. The expression must yield an integer i. Blank lines are inserted in the output file such that the next output data appears on the ith line of a page.

If the file is currently positioned at the beginning of line i, no operation is performed by the LINE option.

If the file is currently positioned before line i, and i is less than or equal to the page size, then blank lines are inserted following the current line until line i is reached.

If the file is currently positioned at or beyond line i, and the file is not at the beginning of line i, then the remainder of the page (the portion between the current line and the current page size) is filled with blank lines. The ENDPAGE condition is signaled.

When the LINE option is used within an ENDPAGE ON-unit, it causes a skip to the next page.

SKIP [(expression)]

An option that advances a specified number of lines from the current line. You can use the SKIP option only with the implied or explicit FILE option. The expression must yield an integer i, which must not be negative and must be greater than zero except for print files. If the expression is omitted, i equals 1.

If the file is not a print file, i-1 blank lines are inserted following the current line, and subsequent output of data begins at the beginning of (current line)+i.

If the file is a print file, i=0 causes a return to the beginning of the current line. If i is greater than zero, and either the current line exceeds the page size or the page size is greater than or equal to the current line plus i, then i-1 blank lines are inserted. Otherwise, the remainder of the current page is filled with blank lines, and the ENDPAGE condition is signaled.

On output devices with the space-suppression feature, SKIP(0) can be used to cause overprinting, underscoring, and so forth. For further information on pages in stream files, see See Terminal I/O .

OPTIONS (CANCEL_CONTROL_O)

A statement option that can be included only with the implied or explicit FILE option. The option is described fully in the Kednos PL/I for UNIX User's Manual.

STRING(reference)

An option that specifies that the output stream be the referenced character-string variable. The STRING option cannot be used in the same statement with FILE, OPTIONS, PAGE, LINE, or SKIP.

PUT EDIT

The PUT EDIT statement takes output sources (variables and expressions) from the program, converts the results to characters under control of a format specification, and places the resulting character strings in the output stream. The output stream is either a stream file or a character-string variable.

With PUT EDIT, the format of the output data is controlled by the program.

The form of the PUT EDIT statement is as follows:

PUT EDIT (output-source, ...) (format- specification, ...)

The syntax is described in more detail in See Syntax Summary of the PUT Statement .

Examples

PUT_ED: PROCEDURE OPTIONS(MAIN);

 

DECLARE SOURCE FIXED DECIMAL(7,2);

DECLARE OUTFILE PRINT FILE;

 

OPEN FILE(OUTFILE) TITLE('PUT_ED.OUT');

 

SOURCE = 12345.67;

 

PUT SKIP FILE(OUTFILE) EDIT(SOURCE) (F(8,2));

PUT SKIP FILE(OUTFILE) EDIT(SOURCE) (E(13));

PUT SKIP FILE(OUTFILE) EDIT(SOURCE) (A);

PUT SKIP FILE(OUTFILE) EDIT('American: ',SOURCE)

(A,P'ZZ,ZZZV.ZZ');

PUT SKIP FILE(OUTFILE) EDIT('European: ',SOURCE)

(A,P'ZZ.ZZZV,ZZ');

 

END PUT_ED;

 

The program PUT_ED writes the following output to PUT_ED.OUT:

12345.67

1.234567E+04

12345.67

American: 12,345.67

European: 12.345,67

 

PUT LINE

The PUT LINE statement advances a print file to a specified line. Its format is as follows:

PUT [FILE (file-reference)] LINE (expression);

 
file-reference

A reference to the file to which the statement applies. The file must be a print file.

The syntax is described in more detail in See Syntax Summary of the PUT Statement .

PUT LIST

The PUT LIST statement specifies a list of output sources (variables and expressions) whose results are converted to character strings and transmitted to the output stream. If the output file is a print file, the output character strings are placed at the start of the next tab stop, where a tab stop is in column 1, 9, 17, and so on. Otherwise, the strings are separated by spaces.

With PUT LIST, the conversion of the output sources and formatting of the output data are automatic and follow the PL/I rules for conversion to character strings.

The format of the PUT LIST statement is as follows:

PUT LIST (output-source, ...)

The syntax is described in more detail in See Syntax Summary of the PUT Statement .

Examples

PUTL: PROCEDURE OPTIONS(MAIN);

 

DECLARE I FIXED BINARY,

F FLOAT,

P PICTURE '99V.99',

S CHAR(10);

 

DECLARE INFILE STREAM INPUT FILE;

DECLARE OUTFILE PRINT FILE;

 

OPEN FILE(INFILE) TITLE('PUTL.IN');

OPEN FILE(OUTFILE) TITLE('PUTL.OUT');

 

GET FILE(INFILE) LIST (I,F,P,S);

PUT FILE(OUTFILE) SKIP LIST (I,F,P,S);

 

END PUTL;

Assume that the file PUTL.IN contains the following data:

2,3.54,22.33,'A string'

 

Then the program PUTL writes the following output to PUTL.OUT:

2 3.5400000E+00 22.33 A string

 

For print files, each output item is written at the next tab position. Floating-point values are represented in floating-point notation. Character values are not enclosed in apostrophes.

PUT PAGE

The PUT PAGE statement positions the output file at the start of a new page. This statement is valid only for print files, that is, files that have been opened with the PRINT attribute.

The form of the PUT PAGE statement is:

PUT [FILE(file-reference)] PAGE;

 

The syntax is described in more detail in See Syntax Summary of the PUT Statement .

Example

PUT FILE(REPORT) PAGE SKIP LINE(2);

 

The PUT statement advances the file REPORT to the beginning of the next page, advances to line 2, and skips to the beginning of the next line (3).

PUT SKIP

The PUT SKIP statement positions the output file at the start of a new line.

The form of the PUT SKIP statement is:

PUT [FILE(file-reference)] SKIP [(expression)];

 

The syntax is described in more detail in See Syntax Summary of the PUT Statement .

Execution of the PUT Statement

When a PUT statement is executed, the first action is to evaluate the FILE or STRING option, if there is one. If the statement has a FILE option and is not already open, the referenced file is either opened or created with the STREAM and OUTPUT attributes. The file is opened if it has the APPEND attribute; otherwise, it is created.

If neither the FILE option nor the STRING option is present, the output stream is assumed to be the default file SYSPRINT.

If the output stream is a file, the next action is to execute any of the options PAGE, LINE, and SKIP that occur in the statement, in that order. The output stream must be a file if any of these options are included, and it must be a print file if LINE or PAGE is included. Note that a PUT statement can contain one or more of these options even if it performs no data output. For example:

PUT FILE(OUT) PAGE LINE(20);

 

This statement skips to a new page in the file referenced by OUT (which must be a print file), moves to line 20 of the file, and then terminates.

However, if the statement also has a LIST or EDIT option, it then writes out a list of output sources, which must be variables, constants, or other expressions of computational data types. Because a stream consists only of ASCII characters, each output source is converted to a character string before being written out, as follows:

  • If the PUT statement is list directed, the output source is converted according to the PL/I rules for converting a computational value to a character string (see See Data Type Conversion of Operands and Expressions ).
  • If the PUT statement is edit directed, the output source is converted as specified by a corresponding format item. For details, see See Format Items .
  • If the output stream is a character-string variable or file with the attributes STREAM and OUTPUT (but not PRINT), the statement is list directed, and the output source is of type CHARACTER, the output source value is surrounded by apostrophes, and any apostrophe within the value is replaced by a double apostrophe.
  • If the output source is of type BIT, and the statement is list directed, the converted output source is surrounded by apostrophes, and the letter `B' is appended.

The converted output source is then written to the output stream, as follows:

  • If the statement is list directed and the output stream is a file with the attributes STREAM and OUTPUT (but not PRINT), then the converted output source is written beginning at the end of the file and followed by a single space. If the output stream is a print file, the converted output source is written out beginning at the end of the file, after enough spaces have been written out to move to the next tab stop. In either case, if the converted output source does not fit on the remainder of the current line, as much as possible is written on the current line, and the rest is written on the next line. The ENDPAGE condition can be signaled if the output stream is a print file. For more information on print files, see See Terminal I/O .
  • If the statement is edit directed, the exact number of characters specified by the format item is written out, and no space follows. As much output as possible is written on the remainder of the current line, and it is continued, if necessary, on the next line. Any additional positioning, such as on tab stops in a print file, is performed by control format items.
  • If the output stream is a character-string variable, the output process is identical to that for a STREAM OUTPUT file except that the first output source written out by a PUT statement is placed at the beginning of the variable's storage, and any previous value in the variable is erased. Note that the X format item, which can be used with PUT STRING, performs positioning by writing out spaces, not by skipping characters in the previous value of the variable. Note also that list-directed output to a character variable, followed by list-directed output of the variable itself, can result in a proliferation of apostrophes in the value finally written to a file.

Format Items

In PL/I, formatted input and output data is transferred with the GET EDIT and PUT EDIT statements, which include a format specification made up of format items.

PL/I format items are categorized as follows:

  • Data format items: A, B, E, F, and P
  • Remote format item: R
  • Control format items: COLUMN, LINE, PAGE, SKIP, TAB, and X

The data format items refer to a field of characters in the stream. Each data format item specifies the field width in characters and either the manner in which the field is used to represent a value (output) or the manner in which the characters in the field are to be interpreted (input). Because the representation or interpretation is under control of the format items, certain symbols used in the stream with GET LIST and PUT LIST are not used with GET EDIT or PUT EDIT:

  • Strings input by the GET EDIT statement should not be enclosed in apostrophes unless the apostrophes are intended to be part of the string. Strings output by PUT EDIT are not enclosed in apostrophes.
  • Bit strings input by the GET EDIT statement should not be enclosed in apostrophes, nor should they be followed by the radix factor B, B1, B2, B3, or B4. These factors are not added by the PUT EDIT statement on output.
  • The comma and space characters are not interpreted as data separators on input. On output, values are not automatically separated by spaces.

The following guidelines apply to errors and mismatches that occur between the actual data values and the fields specified by data format items:

  • On input, the CONVERSION condition is signaled if the field of characters cannot be interpreted as required by the format item.
  • On output, strings are left-justified in the specified field, and numeric data is right-justified. Truncation occurs if the field is too narrow to contain the necessary characters; strings are truncated on the right and numeric data on the left.

The rest of this section describes each format item in detail. The following subsections describe format-specification lists and the FORMAT statement.

A Format Item

The A format item (both uppercase and lowercase) describes the representation of a character string in the input or output stream. The form of the A format item is as follows:

A [(w)]

 
w

A nonnegative integer or an integer expression that specifies the width in characters of the field in the stream. If it is not included (PUT EDIT only), the field width equals the length of the converted output source.

Input with GET EDIT

The value w must be included when the A format item is used with GET EDIT. If w has a positive value, a character-string value comprising the next w characters in the input stream is acquired and assigned to the input variable.

The acquired character string is converted, if necessary, to the data type of the input target, following the PL/I data conversion rules. Apostrophes should enclose the stream data only if the apostrophes are intended to be acquired as part of the data.

Output with PUT EDIT

The output source associated with an A format item is converted, if necessary, to a string of characters. The result is assigned to a string of w characters, which are placed in the output stream. If w is omitted, the length of the output string equals the length of the converted output source. If w is zero, the A format item and the associated output source are skipped.

Output strings are not surrounded automatically by apostrophes. The converted output source is truncated or appended with trailing spaces, according to the value of w. The conversion of a computational data item to a character string is performed following the PL/I data conversion rules (see See Data Type Conversion of Operands and Expressions ).

See . Input String Formatting and See . Output String Formatting show the relationship between the internal and external representations of characters that are read or written with the A format item.

Input Examples

In See . Input String Formatting , the input stream is a field of characters beginning at the current position in the stream and continuing to the right. The # character signifies a space. The target type is the type of the variable to which the input value is assigned.

. Input String Formatting

Format Item

Input Stream

Target Type

Target Value

A(10)

##SHRUBBERY# ...

CHAR(10)

##SHRUBBER

A(6)

##SHRUBBERY# ...

CHAR(10)

##SHRU####

A(6)

##SHRUBBERY# ..

CHAR(10) VAR

##SHRU

A(10)

##1.2345#### ...

DECIMAL(4,1)

001.2

A(5)

##1.2345#### ...

DECIMAL(4,2)

01.20

A(6)

##1.2345#### ...

DECIMAL(4,2)

01.23

Output Examples

In See . Output String Formatting , the output source value is either a constant or the value of a variable that is written with the associated format item.

. Output String Formatting

Output Source Value

Format Item

Output Value

`STRING'

A(10)

STRING####

`STRING'

A

STRING

1.2345

A(2)

##

1.2345

A

##1.2345

-1.2345

A4)

#-1.

-1.2345

A

#-1.2345

''

A(10)

##########

''

A

[no output]

0

A(3)

###

0

A

###0

-12345

A(6)

##-123

-12345

A

##-12345

B Format Items

The B format items B, B1, B2, B3, and B4 describe representations of bit strings in an input or output stream. Note that the B can be typed lowercase. The form of the B format items is as follows:

B[m] (w)

 
m

The integer 1, 2, 3, or 4, specifying the radix factor, that is, 2m. B and B1 have the same meaning. When the radix factor is omitted or is 1, the bit string is represented by the characters 0 and 1 (binary) in the stream. When the radix factor is 2, the bit string is represented by the characters 0, 1, 2, and 3 (base 4). When the radix factor is 3, the bit string is represented by the characters 0, 1, 2, 3, 4, 5, 6, and 7 (octal). When the radix factor is 4, the bit string is represented by the characters 0 through 9 and A through F (hexadecimal).

w

A nonnegative integer or integer expression that specifies the width in characters of the field in the stream.

The interpretation of the B format items on input and output is described below.

Input with GET EDIT

The value w must be included when the B format items are used with GET EDIT. The number of characters specified by w is acquired. The input characters are converted to an intermediate bit string of length w*m. If the input target is not a bit-string variable, then this intermediate bit string is converted to the type of the input target, following the PL/I conversion rules (for details, see See Data Type Conversion of Operands and Expressions ).

The string of characters in the stream can be preceded or followed by spaces, which are ignored. All characters in the input field (except any leading and trailing spaces) must be those implied by the radix factor; otherwise, a CONVERSION condition is signaled. Consequently, input strings should not be enclosed in apostrophes and should not include the suffix Bm.

Output with PUT EDIT

The output source is converted, if necessary, to a bit string, following the PL/I rules for converting data to bit strings (see See Data Type Conversion of Operands and Expressions ). If the length of the resulting bit string is not a multiple of the radix factor (m), the bit string is padded with zeros on the right to make its length the next higher multiple.

The bit string is then converted to a character representation appropriate to the radix factor and placed in the output stream. The character representation is left- justified in the field specified by w and truncated or padded with spaces on the right if necessary. If w is unspecified, the output string length is equal to the converted output source. If w is zero, the B format item and its associated output source are skipped.

Examples

BFORMAT_XM: PROCEDURE OPTIONS(MAIN);

/* This program prints incorrect values for an integer */

DECLARE I FIXED BINARY(31);

DECLARE BFORM STREAM OUTPUT PRINT FILE;

I = 5;

OPEN FILE(BFORM) TITLE('BFORMXM.OUT');

PUT SKIP FILE(BFORM) EDIT ('Decimal:',I) (A,X,F(2));

PUT SKIP FILE(BFORM) EDIT ('Binary:',I) (A,X,B);

PUT SKIP FILE(BFORM) EDIT ('Base 4:',I) (A,X,B2);

PUT SKIP FILE(BFORM) EDIT ('Octal:',I) (A,X,B3);

PUT SKIP FILE(BFORM) EDIT ('Hexadecimal:',I) (A,X,B4);

END BFORMAT_XM;

 

This program produces the following output:

Decimal: 5

Binary: 0000000000000000000000000000101

Base 4: 0000000000000022

Octal: 00000000024

Hexadecimal: 0000000A

 

The base 4, octal, and hexadecimal representations of I are incorrect because the precision of I (31) is not a multiple of 2, 3, or 4. For the B2 and B4 format items, an extra zero bit was appended to the intermediate bit string, in effect multiplying the value of the string by 2. For B3, two extra bits were appended to make the string 33 bits long and thus divisible into an exact number of 3-bit segments. To avoid this problem, the precision of the output source must be a number that is evenly divisible by any radix factor with which it is to be written out, as in the following example:

BFORMAT_XM: PROCEDURE OPTIONS(MAIN);

 

/* This program prints correct values for an integer */

DECLARE I FIXED BINARY(24);

/* 24 is a multiple of 2*3*4 */

DECLARE BFORM STREAM OUTPUT PRINT FILE;

 

I = 5;

OPEN FILE(BFORM) TITLE('BFORMXM5.OUT');

 

PUT SKIP FILE(BFORM) EDIT ('Decimal:',I) (A,X,F(2));

PUT SKIP FILE(BFORM) EDIT ('Binary:',I) (A,X,B);

PUT SKIP FILE(BFORM) EDIT ('Base 4:',I) (A,X,B2);

PUT SKIP FILE(BFORM) EDIT ('Octal:',I) (A,X,B3);

PUT SKIP FILE(BFORM) EDIT ('Hexadecimal:',I) (A,X,B4);

 

END BFORMAT_XM;

 

This version of the program produces the following output:

Decimal: 5

Binary: 000000000000000000000101

Base 4: 000000000011

Octal: 00000005

Hexadecimal: 000005

 

The output values are correct representations of I because the precision (24) is evenly divisible by 2, 3, or 4.

The tables below show the relationship between the internal and external representations of characters that are read or written with the B format item.

Input Examples

In See . Input with the B Format Item , the input stream is a field of characters beginning at the current position in the stream and continuing to the right. The # characters signify spaces. The target type is the type of the variable to which the input value is assigned.

. Input with the B Format Item

Format Item

Input Stream

Target Type

Target Value

B(12)

111000111110...

BIT(12)

'111000111110'B

B(12)

######110011...

BIT(12)

'110011000000'B

B2(6)

123123...

BIT(12)

'011011011011'B

B3(4)

1775...

BIT(12)

'001111111101'B

B4(3)

1FA...

BIT(12)

'000111111010'B

Output Examples

In See . Output with the B Format Item , the output source is either a constant or the value of a variable written out with the associated format item.

. Output with the B Format Item

Output Source Value

Format Item

Output Value

4095

B

111111111111

4095

B(11)

11111111111

4095

B2

333333

4095

B3

7777

4095

B4

FFF

COLUMN Format item

The COLUMN format item sets a stream file to a specific character position within a line. In other words, COLUMN determines the position at which the next data will be output or from which the next data will be input. The COLUMN format item refers to an absolute character position in a line; for information on how to refer to a relative position, see See X Format Item .

The form of the COLUMN format item is:

w

A nonnegative integer or expression that identifies the wth position from the beginning of the current line. The value of the converted expression must be zero or positive. If the value of the converted expression is zero, a value of 1 is assumed.

If the file is already at the specified position, no operation is performed. If the file is already beyond the specified position, the format item is applied to the next line.

The interpretation of the COLUMN format item on input and output is given below.

Input with GET EDIT

The file is positioned at the column specified by w. Characters between the beginning of the line and this column are ignored. If the file is already positioned beyond the specified column, the remainder of the line is skipped and the format item is applied to the next line.

Output with PUT EDIT

The file is positioned at the column specified by w. Within the current line, positions between the wth column and the position of the last output data are filled with spaces.

If the file is already positioned beyond the specified column, the format item is applied to the next line. If w exceeds the line size, a value of 1 is assumed. See See Opening and Closing Files .

Examples

COL: PROCEDURE OPTIONS(MAIN);

 

DECLARE IN STREAM INPUT FILE;

DECLARE OUT STREAM OUTPUT FILE;

DECLARE LETTER CHARACTER(1);

 

PUT FILE(OUT) SKIP

EDIT('123456789012345678901234567890') (A);

PUT FILE(OUT) SKIP

EDIT('COL1','COL28') (A,COL(28),A);

 

GET FILE(IN) EDIT (LETTER) (A(1));

PUT FILE(OUT) SKIP(2)

LIST('Letter in column 1:',LETTER);

 

GET FILE(IN)

EDIT (LETTER) (COL(25),A(1));

PUT FILE(OUT) SKIP

LIST ('Letter in column 25:',LETTER);

 

END COL;

 

If the stream input file IN.DAT contains the following text:

ABCDEFGHIJKLMNOPQRSTUVWXYZ

 

then the program COL writes the following output to the stream output file OUT.DAT:

123456789012345678901234567890

COL1                       COL28

'Letter in column 1:' 'A'

'Letter in column 25:' 'Y'

 

E Format Item

The E format item describes the representation of a fixed- or floating-point value as a decimal floating-point number in a stream.

The form of the item is:

E(w[,d])

 
w

A nonnegative integer or expression that specifies the total width in characters of the field in the stream.

d

An optional nonnegative integer or expression that specifies the number of fractional digits in the stream representation and whose value is interpreted depending on GET EDIT and PUT EDIT statements as described below.

Input with GET EDIT

Used with GET EDIT, the E format item acquires a character-string value representing a floating-point decimal value and assigns it, with necessary conversions, to an input target of any computational type. If w is zero, no operation is performed on the input stream, and a null character string is converted and assigned to the input target.

For input, floating-point values can be represented in the stream in the forms listed in See . Representation of Floating-Point Values .

. Representation of Floating-Point Values

Form

Example

mantissa

124333

sign mantissa

-123.333

sign mantissa sign exponent

-123.333-12

sign mantissa E exponent

-123.333E12

sign mantissa E sign exponent

-123.343E-12

The mantissa is a fixed-point decimal constant, the sign is a plus (+) or minus (-) symbol, and the exponent is a decimal integer. A zero exponent is assumed if both the letter E and the exponent are omitted.

If, on input, the mantissa includes a decimal point, it overrides the specification of d. If no decimal point is included, then d specifies the number of fractional digits.

The value of w should be large enough to include the mantissa, the optional decimal point in the mantissa, the signs on the exponent and mantissa, the optional letter E, and the exponent. If the field width is too narrow, the stream representation is truncated on the right; if the field width is too wide, excess characters are acquired on the right and may contain invalid input.

Spaces can precede or follow the value in the stream and are ignored. If the entire field contains spaces, zero is assigned to the input target. If the stream representation is not one of the acceptable forms, an ERROR condition is signaled.

Output with PUT EDIT

Used in a PUT EDIT statement, the E format item converts an output source of any computational type to the following form for representation in the stream:

[-] digit . [fractional-digits] E sign exponent

 

Typical representations are as follows:

1.E+07

3.33E-10

-2.7186E+00

 

If d is omitted from the format item, then d = s -1, where s is the precision of the output source expressed in decimal. The decimal value is rounded before being written out.

The exponent is ordinarily a 2-digit decimal integer (for S_floating data) or a 3-digit decimal integer (for T_floating data) and is always signed. The exponent is adjusted so that the first digit of the mantissa is not zero, except that the value 0 is represented as:

0.0000 ... E+00

 

with a number of zeros to the right of the decimal point equal to the specified number of fractional digits.

To account for negative values with fractional digits, the specified width integer should be 7 greater than the number of digits to be represented in the mantissa: one character for the preceding minus sign, one for the decimal point in the mantissa, one for the letter E, one for the sign of the exponent, and two (or three) for the exponent itself.

If the number's representation is shorter than the specified field, the representation is right-justified in the field and the number is extended on the left with spaces.

If the field specified by w is too narrow, an ERROR condition is signaled.

Examples

The next tables show the relationship between the internal and external representations of numbers that are read or written with the E format item.

Input Examples

See . Input with the E Format Item shows an input stream that is a field of characters beginning at the current position in the stream and continuing to the right. The target type is the type of the variable to which the input value is assigned.

. Input with the E Format Item

Format Item

Input Stream

Target Type

Target Value

E(6,0)

124333...

DECIMAL(10,2)

124333.00

E(6,0)

-123333...

DECIMAL(10,2)

-12333.00

E(8)

-123.333...

DECIMAL(8,5)

-123.33300

E(11)

-123.333-12...

FLOAT DEC(7)

-1.233330E-10

E(11,3)

-123343E-12...

FLOAT DEC(15)

-1.23343000000000E-10

Output Examples

The output source value shown in See . Output with the E Format Item is either a constant or the value of a variable that is written out with the associated format item. The # character is used to signify a space.

. Output with the E Format Item

Output Source Value

Format Item

Output Value

-12234

E(11)

-1.2234E+04

-12234

E(11,2)

##-1.22E+04

12234

E(11)

#1.2234E+04

12234

E(11,2)

###1.22E+04

-12.234

E(11,1)

###-1.2E+01

-1.23456E3

E(12)

-1.23456E+03

-1.23456E3

E(12,2)

###-1.23E+03

F Format Item

The F format item describes the representation of a fixed- or floating-point value as a decimal fixed-point number in a stream.

The form of the item is:

F(w[,d])

 
w

A nonnegative integer or expression that specifies the total width in characters of the field in the stream.

d

An optional nonnegative integer or expression that specifies the number of fractional digits in the stream representation and whose value is interpreted depending on GET EDIT and PUT EDIT statements as described below.

Input with GET EDIT

Used with GET EDIT, the F format item acquires a fixed-point decimal value from the next w characters in the stream and converts it to an input target of any computational type. Fixed-point decimal values can be represented in the stream in the following forms:

number

sign number

 

The number is a fixed-point decimal constant, and the sign is a plus (+) or minus (-) symbol.

The following are valid representations:

124333

-123333

-123.

A CONVERSION condition is signaled if the field is not blank and does not contain a valid representation; otherwise, the fixed-point decimal number is extracted from the field and is assigned to the input target, with any necessary conversions. A decimal point included in the number overrides the specification of d. If no decimal point is included, d specifies the number of fractional digits. If d is omitted, it is assumed to be zero.

The value w should be only large enough to include the number, the optional decimal point in the number, and the optional sign. If w is too small, the stream representation is truncated on the right. If w is too large, extra characters, which might include invalid syntax, are acquired.

If w is zero, a null character string is converted and assigned to the input target, and no operation is performed on the stream.

Spaces can precede or follow the number in the stream and are ignored. If the entire string contains spaces or is a null string, the fixed-point decimal constant 0 is converted and assigned to the input target.

Output with PUT EDIT

Used in a PUT EDIT statement, the F format item converts an output source of any computational type to one of the following forms for representation in the stream:

integer

integer.fractional-digits

-integer.fractional-digits

 

Typical representations are:

3234

0.23432

3.33

-3234.33

 

The decimal value is rounded before being written out. If d is omitted from the format item, the decimal point is not shown, and only the integral part of the number is shown.

If d is larger than the number of fractional digits to be output, trailing zeros are appended to the output number. All leading zeros to the left of the decimal point are suppressed unless the integral part of the number is zero, in which case one zero appears to the left of the decimal point.

To account for negative values with fractional digits, the specified width integer should be 2 greater than the number of digits to be represented: one character for the preceding minus sign and one for the decimal point in the number.

If the number's representation is shorter than the specified field, the representation is right-justified in the field, and the number is extended on the left with spaces.

If the field is too narrow to represent the integral portion of the output number, an ERROR condition is signaled.

Examples

The tables below show the relationship between the internal and external representations of numbers that are read or written with the F format item.

Input Examples

See . Input with the F Format Item shows an input stream that is a field of characters beginning at the current position in the stream and continuing to the right. The target type is the type of the variable to which the input value is assigned.

. Input with the F Format Item

Format Item

Input Stream

Target Type

Target Value

F(10,2)

-123456.78...

DECIMAL(10,2)

-123456.78

F(10,4)

-1234.56789...

DECIMAL(10,2)

-1234.56

F(8,5)

-.123456789...

DECIMAL(5,5)

-0.12345

F(10)

1234.56789...

FLOAT DEC(7)

1.234568E+03

Output Examples

The output source value shown in See . Output with the F Format Item is either a constant or the value of a variable that is written out with the associated format item. The # character is used to specify a space.

. Output with the F Format Item

Output Source Value

Format Item

Output Value

-12.234

F(3,0)

-12

-12.234

F(6,2)

-12.23

-12.234

F(7,3)

-12.234

-1.23456E3

F(8)

###-1235

-1.23456E3

F(8,2)

-1234.56

'1000'B3

F(4)

#512

'1000000000000000'B

F(5)

32768

'100000'B3

F(5)

32768

'ABCEDF'B4

F(10)

##11259615

LINE Format Item

The LINE format item sets a print file to a specific line. It can be used only with print files and the PUT EDIT statement. If necessary, blank lines are inserted between the current file position and the specified line, and subsequent output begins on the specified line.

The LINE format item identifies an absolute line position on the current output page; to specify a line position relative to the current line, see SKIP format item.

The form of the LINE format item is:

LINE(w)

 
w

An integer, or an expression, that specifies a line on the current page, where line 1 is the first line. The maximum value for a print file's line number is 32767. If a program generates a value in excess of 32767, a run-time error occurs.

When the LINE format item is executed, the current line is determined. The current line is 1 if the file is at the beginning of a new page. Otherwise, the current line is n+1, where n is the number of complete lines already on the page. The position in the file is then changed as follows:

  • If line w is the current line, and the file is either at the beginning of a new line or at the beginning of a new page, then no operation is performed.
  • If line w is beyond the current line and is less than or equal to the current page size, then the file is positioned at line w, and the lines between the current line and line w are filled with blank lines. (See See Opening and Closing Files )
  • If line w is at or before the current line, the current line is not beyond the current page size, and the file is not at the beginning of a line or page, then the remainder of the page (the portion between the current line and the current page size) is filled with blank lines, and the ENDPAGE condition is signaled. The same actions occur when the current line is less than or equal to the page size and w is greater than the page size.
  • Otherwise, the file is positioned at the beginning of a new page, and the page number is incremented by 1 (for instance, when w is zero).
P Format Item

The picture format item (P) describes a field of characters in the input or output stream. The field can be an input field acquired with GET EDIT or an output field transmitted by PUT EDIT. With GET EDIT, the P format item acquires a pictured value from the input stream. With PUT EDIT, the P format item edits an output source to a specified picture format.

The form of the P format item is:

P 'picture'

 
'picture'

A picture of the same syntax as for the PICTURE data attribute. The syntax is summarized in PICTURE attribute (see See PICTURE Attribute ). The field width is the total number of characters, exclusive of V, in the picture.

The interpretation of the P format item, for input and output, is given below.

Input with GET EDIT

Used with the GET EDIT statement, the P format item acquires a pictured value (a field of characters) from the stream file, extracts its fixed-point decimal value, and assigns the value to an input target of any computational type. The picture describes a field of w characters, where w is the total number of picture characters in the picture, exclusive of the V character.

A string of w characters is acquired from the input stream and validated against the picture specified in the format item. The string is valid if it corresponds to an internal representation that would be created by the specified picture if the picture were used to declare a variable of type PICTURE. If the string is valid, its fixed- point decimal value is extracted and assigned to the input target. If necessary, the value is converted to the type of the input target, following the usual rules (see See Data Type Conversion of Operands and Expressions ). If the string is not valid, the CONVERSION condition is signaled.

When no decimal point appears in the input stream item, the scale factor of the item is assumed to be the number of digit positions specified to the right of the V character in the picture. If no V character appears, the scale factor is zero.

Output with PUT EDIT

Used with the PUT EDIT statement, the P format item outputs a source of any computational type in the specified format. If necessary, the output source is first converted to a fixed-point decimal value, following the PL/I conversion rules. The fixed-point decimal value is then edited by the picture specified in the format item. The P format item therefore describes an output field of w characters, where w is the total number of characters in the picture, exclusive of the V character. If the output source is a pictured value, then its extracted fixed-point decimal value must be capable of being edited by the picture specified in the P format item. Otherwise, the ERROR condition is signaled.

Examples

The following tables show the relationship between the internal and external representations of numbers that are read or written with the P format item.

Input Examples

The input stream shown in this table is a field of characters beginning at the current position in the stream and continuing to the right. The # character is used to specify a space. The target type is the type of the variable to which the input value is assigned.

. Input with the P Format Item

Format Item

Input Stream

Target Type

Target Value

P'$$$,$$$,$$9V.99DB'

$10,987,654.00DB...

DECIMAL(10,2)

-10987654.00

P'$$$,$$$,$$9V.99DB'

########$10.99##...

DECIMAL(10,2)

10.99

P'SSSSV.SSSSS'

##-1.12345...

DECIMAL(8,5)

-1.12345

P'SSSSV.SSSSS'

+100.12345...

DECIMAL(8,5)

100.12345

P'SSSSV.SSSSS'

#100.12345...

DECIMAL(8,5)

[CONVERSION]

P'SSSSV.SSSSS'

+1001.2345...

DECIMAL(8,5)

[CONVERSION]

The last two cases signal the CONVERSION condition. In the first case, the input field has a space instead of a plus symbol or minus symbol in the first position. In the second case, the input field has four digits to the left of the period, and the P format item specifies a maximum of three. The P format item in both cases uses drifting strings of S characters, and, if used to declare a picture variable, the specification could create several different character representations. However, the specification could not have created the last two input fields shown, and they are therefore invalid values.

Note that in the second line in the table, the characters "$10.99" must be surrounded with the number of spaces shown. The drifting dollar signs and the comma insertion characters always specify either digits, the characters themselves, or spaces. Similarly, the characters "DB" in the picture specification specify either these characters or the same number of spaces. If the pictured input value did not contain these spaces, it would be invalid.

Output Examples

The output source value shown in this table is either a constant or the value of a variable that is written out with the associated format item.

. Output with the P Format Item

Output Source Value

Format Item

Output Value

-12234

P'$$$$$$DB'

$12234DB

-12234

P 'SSSSSSV.SS'

-12234.00

-12.234

P 'T9V.999'

J2.234

-1.23456E3

P '-9999V.99'

-1234.56

-1.23456E3

P '+ZZZ9V.99'

#1234.56

PAGE Format Item

The PAGE format item is used with print files to begin a new page. See See Terminal I/O for more information on print files.

The form of the PAGE format item is:

PAGE

 

Subsequent output begins on line 1 of the next page, and the current page number for the print file is incremented by 1.

R Format Item

The R (remote) format item specifies the label of a FORMAT statement from which some or all of a format specification is obtained by a GET EDIT or PUT EDIT statement.

The form of the R format item is:

R (label)

 
label

The label of a FORMAT statement within the same block as the GET EDIT or PUT EDIT statement. If the item occurs in a recursive procedure, the R item and FORMAT statement must occur in the same recursion.

FORMAT Statement

The FORMAT statement describes a remote format-specification list to be used by GET EDIT or PUT EDIT statements. The FORMAT statement and remote (R) format item are useful when the same format specification is used by a large number of GET EDIT or PUT EDIT statements, or both. In this case, a change to the format specification can be made in the single FORMAT statement, rather than in each GET or PUT statement.

The form of the FORMAT statement is:

[(condition-prefix[,condition-prefix]... ):] label: FORMAT
(format-specification,...);

 
label

A valid PL/I label. A label is required and is specified in the GET EDIT or PUT EDIT statement that contains an R format item in its format-specification list.

condition-prefix (IBM Dialect Only)

A valid PL/I condition prefix. If you use a condition prefix on a FORMAT statement, it must be the same prefix used on the referring GET or PUT statement.

format-specification

A list of one or more format items that match corresponding input targets in a GET EDIT statement, or output sources in a PUT EDIT statement.

Although the FORMAT statement can contain another R format item, the following restrictions apply:

  • The FORMAT statement cannot designate its own label with an R format item.
  • The FORMAT statement cannot begin a chain of remote format items that leads back to the original FORMAT statement.
  • If you use a condition prefix on a remote format statement, it must be the same prefix used on the referring GET or PUT statement and the intervening format statement(s).
Examples

RFRM: PROCEDURE OPTIONS(MAIN);

 

DECLARE SYSIN STREAM INPUT FILE;

DECLARE SYSPRINT PRINT FILE;

DECLARE SALARY PICTURE '$$$$$$$$9V.99';

DECLARE (FIRST,MID,LAST) CHARACTER(80) VARYING;

DECLARE 1 HIRING,

2 DATE CHARACTER(20) VARYING,

2 EXPERIENCE FIXED,

2 SALARY PICTURE '$$$$$$$$9V.99';

OPEN FILE(SYSIN) TITLE('RFRM.IN');

OPEN FILE(SYSPRINT) TITLE('RFRM.OUT');

 

GET EDIT (SALARY, FIRST, MID, LAST, DATE, EXPERIENCE,

HIRING.SALARY)

(F(8,2),R(PERSONNEL_FORMAT));

 

PUT SKIP LIST(TRIM(LAST)||', '||TRIM(FIRST)||

' '||TRIM(MID)||':  Hired '||TRIM(DATE)||' at '||HIRING.SALARY);

PUT SKIP LIST(EXPERIENCE,' years prior experience');

PUT SKIP LIST('Present salary: '||SALARY);

 

PERSONNEL_FORMAT: FORMAT (R(NAME), A(20), SKIP, F(2), X,

F(8,2));

NAME: FORMAT(3(SKIP,A(80)));

 

END RFRM;

 

Assume the file RFRM.IN contains the following data:

 25005.50

Thomasina

A.

Delacroix

6 July 1976

 2 15003.65

 

The following output, with spacing as shown, will be written to the print file RFRM.OUT:

Delacroix, Thomasina A.:    Hired 6 July 1976 at   $15003.65

             2   years prior experience

Present salary:    $25005.50

 

SKIP Format Item

The SKIP format item sets a stream file to a new position relative to the current line. It is used with input and output files.

The form of the SKIP format item is:

SKIP [(w)]

 
w

An integer, or an expression, giving the number of lines to be skipped; the expression must not convert to a negative integer and must be greater than zero, except for print files. If w is omitted, a value of 1 is assumed.

If w is 1 or is omitted, the file is positioned at the beginning of the next line. If w is greater than 1, w-1 lines are skipped on input, but the ENDFILE condition is signaled if the end of the file is encountered first. On output, w-1 blank lines are inserted. In both cases, the new position is the beginning of (current line)+w.

Use with Print Files

If w is zero, the file is repositioned at the beginning of the current line, allowing overprinting of the line. If w is greater than zero, and either the current line exceeds the page size or the page size is greater than or equal to the current line plus w, then w-1 blank lines are inserted. Otherwise, the remainder of the page (the portion between the current line and the page size) is filled with blank lines, and the ENDPAGE condition is signaled.

TAB Format Item

The TAB format item sets a print file to a specified tab stop. It is used only for output to print files. Within a line, tab stops always occur every eight columns, starting at column 1. The form of the TAB format item is:

TAB [(w)]

 
w

An integer, or an expression, that identifies the wth tab stop from the current position; w must not be negative. If w equals zero, no operation is performed. If w is omitted, a value of 1 is assumed.

When the TAB format item is executed, the current column (cc) is determined. If the current position is the beginning of a line, page, or file, then cc is one. Otherwise, cc is the column in the current line at which the next output character would appear.

For example, if seven characters have already been written on a line, then the cc is column 8; this is where the next output would occur. The file is then repositioned in one of the following ways:

  • If there are at least w tab stops between (cc+1) and the end of the line, then the file is moved to the wth tab stop from the current column, and the intervening positions are filled with spaces. The end of the line is at one column after the current line size, which is either the default value or the specific value that you have established for the file. See See Opening and Closing Files for LINESIZE option.
  • If there are fewer than w tab stops on the remainder of the current line, the file is skipped to the beginning of the next line and positioned at the first tab stop (column 1). If, before the skip operation, the current line was the last line on the page, the ENDPAGE condition is signaled, and the current line becomes (page size)+1. The page size is either the default value or the specific value that you have established for the file. See See Opening and Closing Files for PAGESIZE option.
Examples

TAB: PROCEDURE OPTIONS(MAIN);

 

DECLARE OUT STREAM OUTPUT PRINT FILE;

 

OPEN FILE(OUT) LINESIZE(60);

PUT FILE(OUT) SKIP

EDIT('123456789012345678901234567890') (A);

 

PUT FILE(OUT) SKIP EDIT('COL1','?') (A,TAB(2),A);

PUT FILE(OUT) EDIT('!') (TAB(20),A);

PUT FILE(OUT) SKIP EDIT('*') (TAB(1),A);

PUT FILE(OUT) EDIT('abcdefg') (A); /* cc now = 17 */

PUT FILE(OUT) EDIT('&') (TAB(6),A);

END TAB;

 

The program TAB writes the following output to the print file OUT.DAT:

123456789012345678901234567890

COL1            ?

!

        *abcdefg

&

The question mark appears in column 17, which is the second tab stop following the string `COL1'. The exclamation point appears in column 1 of the next line because there are fewer than 20 tab stops on the remainder of the line. In the third PUT EDIT statement, the SKIP option first resets the current column to zero. When the TAB format item is executed, it must position the file to the first tab stop that is between column 1 (cc+1) and the end of the line; therefore, the file is positioned, and the asterisk appears, in column 9. Similarly, the fourth statement writes out the string `abcdefg', after which the current column is 17, a tab stop. Because the line size has been established as 60, there are only five tab stops between cc+1 and the end of the line: 25, 33, 41, 49, and 57. Therefore, the format item TAB(6) in the last PUT EDIT statement causes a skip to the next line, and the ampersand appears in column 1.

X Format Item

The X format item sets a stream file or character-string expression to a column relative to the current position. It is the only control format item that can be used with either the FILE or STRING option of GET EDIT and PUT EDIT. The form of the X format item is:

X [(w)]

 
w

An integer, or an expression, that specifies a number of consecutive character positions in the stream; w must not yield a negative integer value. If w yields zero, no operation is performed. If the w is omitted, its value is assumed to be 1.

Input with GET EDIT

On input, the next w columns after the current column are skipped.

Output with PUT EDIT

On output, w spaces are inserted following the current column.

When the output stream is a file, and the end of the current line is reached, the output of spaces continues on the next line until w spaces have been output. The size of the current line is either the default value or the specific value you have established for the file (see See Opening and Closing Files for LINESIZE option). If the file is a print file, the ENDPAGE condition is signaled if the page size is reached; on normal return from the ENDPAGE ON-unit, output of spaces continues at the top of the next page until w spaces have been output.

If the output stream is a character-string variable, w spaces are written to the variable. The ERROR condition is signaled if the maximum length of the string is exceeded.

Examples

XFOR: PROCEDURE OPTIONS(MAIN);

 

DECLARE INLINE CHARACTER(80) VARYING;

DECLARE FIRSTWORD CHARACTER(80) VARYING;

DECLARE OUTFILE PRINT FILE;

DECLARE SPACE1 FIXED;

 

GET EDIT(INLINE) (A(80)) OPTIONS(PROMPT('Line>'));

 

SPACE1 = INDEX(INLINE,' '); /*position of first wordbreak*/

FIRSTWORD = SUBSTR(INLINE,1,SPACE1-1);

 

PUT STRING(FIRSTWORD) EDIT(FIRSTWORD,'-FIRST WORD TYPED')

(A,X(2),A);

PUT SKIP FILE(OUTFILE) LIST(FIRSTWORD);

 

END XFOR;

 

The GET EDIT statement in the program XFOR inputs a complete line from a user's terminal, after issuing and receiving an answer to the prompt `Line >'. Assume that the interaction is as follows:

Line> beautiful losers

 

The following output will be written to OUTFILE.DAT:

beautiful -FIRST WORD TYPED

 

The X format item has correctly inserted two spaces between `beautiful' and `-FIRST WORD TYPED'.

XFOR2: PROCEDURE OPTIONS(MAIN);

 

DECLARE INLINE CHARACTER(80) VARYING;

DECLARE OUTFILE2 PRINT FILE;

 

GET EDIT(INLINE) (X(10),A(1000))

OPTIONS(PROMPT('Line>'));

 

PUT SKIP FILE(OUTFILE2) LIST(INLINE);

 

END XFOR2;

 

In the program XFOR2, the GET EDIT statement skips the first 10 characters typed after the prompt and then inputs the remainder of the line. Assume that the interaction is:

Line> ABCDEFGHIJKLMNOPQRSTUVWXYZ

 

The following output will be written to OUTFILE2.DAT:

KLMNOPQRSTUVWXYZ

 

The first 10 letters (A to J) have been ignored on input.

Format Specifications

In the GET EDIT, PUT EDIT, and FORMAT statements, format items are used singly or in combination to create format specifications. The syntax of a format specification is as follows:

The iteration factor is an integer or an integer expression that repeats the following format item or the following list of format specifications. Expressions must be enclosed in parentheses. If an integer iteration factor precedes a single format item that is not in parentheses, the iteration factor and the format item must be separated by a space. For example:

PUT EDIT (A) (F(5,2));

 

The preceding statement specifies a 5-character field containing decimal digits, two of which are fractional. Used by itself as a format specification, this item specifies one such field. To specify two such fields, precede the item with the iteration factor 2:

PUT EDIT (A,B) (2F(5,2));

 

Or:

PUT EDIT (A,B) (2 (F(5,2)));

 

An iteration factor can also repeat an entire list of format specifications:

PUT EDIT ( (A(I) DO I = 1 TO 10) ) /* 10 array elements */

( 2( F(5,2),2(F(7,2),E(8)) ) ); /* 10 format items */

 

Expanded into individual format items, this specification looks like this:

F(5,2),F(7,2),E(8),F(7,2),E(8),F(5,2),F(7,2),E(8),F(7,2),E(8)

 

If an expression is used as the iteration factor, it must be enclosed in parentheses, but does not require spaces. For example:

PUT EDIT (A) ((Z*4)F(5,2));

 

In general, data listed in the GET EDIT or PUT EDIT statement is matched to the expanded list of data format items, from left to right, until the end of the input-target or output-source list is reached. Matching occurs only between I/O data and data format items; control format items are executed only if they are encountered while the matching is in progress.

Format-Specification List

Format-specification lists are used in GET EDIT, PUT EDIT, and FORMAT statements to control the conversion of data between the program and the input or output stream and to precisely control positioning within the input or output stream. This entry describes the syntax of format-specification lists and the manner in which a format list is processed to acquire or transmit data.

Rules for Use

This section briefly describes rules and constraints for format-specification lists.

  • A GET EDIT or PUT EDIT statement must include one and only one format- specification list and also one and only one list of input targets or output sources. The input-target or output-source list must immediately follow the keyword EDIT and must be immediately followed by the format-specification list.
  • The same set of data format items is used for input and output. The F and E format items are used for I/O in fixed-point and floating-point formats, respectively. The A and B format items are used for I/O in character-string and bit-string formats, respectively. The P format item is used for both input and output of data, with the format specified by a picture contained in the format item.
  • Of the control format items, only X can be used when the input or output stream is a character string.
  • Unlike the statement options PAGE, LINE, and SKIP, the format items PAGE, LINE, and SKIP are executed in the order in which they occur.
How Edit-Directed Operations Are Performed

This section describes the manner in which format items are matched to input targets or output sources.

All edit-directed input statements include the following syntax:

EDIT (input-target, ...) (format-specification, ...)

 

All edit-directed output statements include the following syntax:

EDIT (output-source, ...) (format-specification, ...)

 
format-specification

One of the following:

  • A single control or data format item.
  • A construct containing an iteration factor followed by one or more format items.
  • An R format item, which specifies the label of a FORMAT statement. In effect, the entire format-specification list in the FORMAT statement is acquired and inserted at the position of the R format item.

Except for picture (P) and remote (R) format items, arguments to format items can be integer expressions.

input-target

One of the following:

  • A variable reference, which can be to a scalar or aggregate variable of any computational data type
  • A construct with the following syntax:

(input-target, ...DO reference=expression [TO expression]

[BY expression] [WHILE(expression)] [UNTIL(expression)] )

 
  • A construct with the following syntax:

(input-target, ... DO reference=expression [REPEAT expression]

[WHILE (expression)] [UNTIL(expression)] )

 
output-source

One of the following:

  • Any expression with a computational value, including references to scalar or aggregate variables of any computational type
  • A construct containing a DO specification, as shown for input targets

When PL/I performs an edit-directed operation, it examines the list of input targets or output sources, beginning with the first in the list. If the target or source is an array or structure or contains a DO specification, it is expanded to form a list of individual data items; an array is expanded in row-major order, a structure is expanded in the order of its declaration, and items preceding a DO specification are expanded according to the DO specification.

Within a single target or source, items at the innermost level of parentheses are processed first.

Given a list of one or more data items contained in the first target or source, PL/I processes the data items from left to right. Beginning with the leftmost data item, and for each subsequent item, PL/I executes format items until the data item has been either assigned a value from the input stream, or converted to a character representation and placed in the output stream. Control format items are therefore executed in the order in which they occur in the format-specification list. With the first target or source, the execution of format items begins with the leftmost format item in the format-specification list. If the end of the format-specification list is reached, PL/I returns to the leftmost format item and continues.

When all items contained in the first target or source have been processed, PL/I operates on the next target or source. The target or source is evaluated, and PL/I then examines the format-specification list, beginning where the previous operation stopped.

This processing continues until all data items in the input-target or output-source list have been processed, at which point the edit-directed statement terminates. If this occurs while PL/I is in the middle of the list of format items, the format items to the right are not executed.

Examples

The following examples show typical edit-directed operations. All cases shown are for input (GET EDIT), but the operations for PUT EDIT are similar. The simple cases, shown first, are with input targets that are scalar variable references. The next cases shown are with aggregate (array and structure) references. The last cases shown are with DO specifications.

Scalar Variables

The following examples have input targets that are scalar variables:

GET EDIT (A,B,C,D) (A(12),F(5,2),F(6,2),A(14));

 

The preceding statement acquires four values from the input stream: a 12-character string, a 5-digit fixed-point decimal number, a 6-digit fixed-point decimal number, and a 14-character string, and assigns these values, with any necessary conversions, to the target variables A, B, C, and D, respectively.

GET EDIT (A,B,C,D) (A(12));

 

The preceding statement acquires four 12-character strings and assigns them (with conversions, if necessary) to the targets A, B, C, and D.

GET EDIT (A,B,C,D) (A(12), 2 F(5,2), A(14));

 

The preceding statement acquires a 12-character string, two fixed-point decimal numbers, and a 14-character string, in that order, and assigns them to A, B, C, and D. (You can use embedded spaces in format lists, as elsewhere, for clarity; the space between 2 and F(5,2) is required.)

GET EDIT (A,B,C,D,E) ( 2( A(12),A(14) ), A(20) );

 

The preceding statement acquires, in order, a 12-character string, a 14-character string, another 12-character string, another 14-character string, and a 20-character string, and assigns the strings, in that order, to A, B, C, D, and E.

GET EDIT (A,B,C,D,E) ( 2( A(12),A(14) ), SKIP, A(20) );

 

The preceding statement performs the same operation as in the previous example, but acquires the 20-character string from the next line.

Aggregates

The following examples have input targets that are references to array and structure variables:

GET EDIT (A) ( 2( A(12),A(14) ), A(20) );

 

A is an array of five elements or a structure with five scalar members. This statement expands A to a list of individual data items. Then it acquires, in order, a 12-character string, a 14-character string, another 12-character string, another 14-character string, and a 20-character string, and assigns the strings, in that order, to the elements A(1) through A(5) (if an array) or to the five members of structure A in the order in which the members are declared.

GET EDIT (A,B) ( 2( A(12),A(14) ), A(20) );

 

Both A and B are aggregates with five elements or members. For A, this statement performs the same operation as in the previous example, and then repeats the operation for B, using the same format list each time. Because there are five format items specified, and the aggregates both have five elements or members, strings of the same length are acquired for corresponding elements of A and B.

GET EDIT (NAME) (SKIP,A(20),SKIP,A(80));

 

NAME is a structure declared as:

DECLARE 1 NAME,

2 FIRST CHARACTER(20) VARYING,

2 LAST CHARACTER(80) VARYING;

 

The following statement skips to the next line and acquires a 20-character string. It assigns the string to NAME.FIRST. This statement skips to the next line and acquires an 80-character string. This statement assigns that string to NAME.LAST.

GET EDIT (A,B) ( 2( A(12),A(14) ), SKIP, A(20) );

 

Both A and B are 4-element arrays. From the current line, this statement executes A(12), A(14), A(12), and A(14), in that order, and assigns the results to A(1) through A(4). This statement then skips to the next line and executes A(20), A(12), A(14), and A(12), in that order, and assigns the results to B(1) through B(4); the list of data items is now exhausted, so this statement does not execute SKIP a second time.

DO Specifications

The following examples have input targets that include DO specifications. The DO specifications control the assignment of input values to variables that are arrays and based structures.

Example 1:

GET EDIT ( (B(I) DO I=10 TO 4 BY -2) , B(1) )

( 2( A(12),A(14) ), A(20) );

 

B is a 10-element array. Notice that the parentheses surrounding the first input target are in addition to the parentheses surrounding the entire input-target list. The preceding statement executes the format items A(12), A(14), A(12), and A(14), in that order, and assigns the resulting strings to elements B(10), B(8), B(6), and B(4), respectively. It then executes A(20) and assigns the result to B(1).

Example 2:

GET EDIT ( ( (A(I,J) DO J=1 TO 10) DO I=1 TO 20) )

(F(5),F(6));

 

In the preceding statement, A is a two-dimensional array of 20 rows and 10 columns. Two hundred decimal integers are acquired and assigned to the array elements in the order A(1,1), A(1,2), ... ,A(20,10). Elements with odd-numbered columns receive 5-digit integers, and those with even-numbered columns, 6-digit integers. Because the DO specifications specify row-major order, the same operation is performed by the next example.

GET EDIT (A) (F(5),F(6));

 

Because row-major order is the default, nested DO specifications are used to change the order in which values are assigned.

The example has the same effect as the following DO-group:

DO I = 1 TO 20;

DO J = 1 TO 10;

GET EDIT(A(I,J)) (F(5),F(6));

END;

END;

 

Compared to a DO construct in an input-target list, however, nested DO groups are much less efficient in execution speed. In addition, some stream I/O statements may have different effects when specified in nested DO-groups as opposed to being specified with the DO construct in the input-target list. For example:

GET SKIP EDIT(input-target, ...) (format-specification, ...);

 

If you use this syntax in a pair of nested DO groups, as shown previously, the SKIP option is executed on each iteration of the innermost DO group. If you specify the DO construct in the input-target list, the SKIP option is executed only once, before any other input processing is performed.

Example 3:

GET EDIT ( ( CURRENT->PERSON.NAME

DO CURRENT = FIRST

REPEAT CURRENT->PERSON.NEXT

WHILE (CURRENT ^= NULL) ) )

(A(80));

CURRENT and FIRST are pointers, and PERSON is a based structure declared as:

DECLARE /* Based structure for list elements: */

1 PERSON BASED,

2 NEXT POINTER, /* Pointer to next element: */

2 NAME CHARACTER(80) VARYING;

DECLARE /* NULL function and pointers to first and

current list elements: */

NULL BUILTIN,

(FIRST,CURRENT) POINTER;

 

The GET EDIT statement reads 80-character strings from the input stream and assigns each to a list member PERSON.NAME. On the first input operation, the string is assigned to FIRST->PERSON.NAME. On subsequent iterations of the DO specification, the pointer to the next element, PERSON.NEXT, is assigned to CURRENT before the input operation. Before each input operation, including the first, the WHILE clause tests to determine whether the end of the queued list has been reached (indicated by the null pointer).

The DO REPEAT construct is often used in this type of application. You should use a WHILE or UNTIL clause in this or any DO REPEAT construct to be sure that the operation has a defined termination. However, the WHILE or UNTIL clause is not required.

Processing and Positioning of Character Strings

If the input or output stream is a character string, the processing is similar to the processing of files, but the positioning options are more limited:

  • Input can begin either at the beginning of the string or at a specified character position. The ERROR condition is signaled if the end of the string is encountered. Only the X format item is used for positioning.
  • The first output by a PUT statement always occurs at the beginning of the string, and subsequent output by the same statement follows the previous output. The ERROR condition is signaled if the maximum length of the string is exceeded. Only the X format item is used for positioning.

Terminal I/O

In most applications, the terminal is treated as a stream file. You can explicitly declare a stream file to be associated with a user's terminal. The stream input and output statements, GET and PUT, use the default PL/I files SYSIN (the terminal) and SYSPRINT, respectively, when no file reference is included in the statement.

This file is associated with the default system input file SYS$INPUT, which in turn is usually assigned to the user's terminal. The PL/I print file SYSPRINT is associated with the default system file SYS$OUTPUT, which, in interactive mode, is also assigned to the user's terminal.

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.

The file symbol "SYSOUT" is supported in the dec and ansi dialects; the file symbols "SYSPRINT" and "SYSIN" are supported in dec, ansi, and ibm dialects.

For further information, see the Kednos PL/I for UNIX User's Manual.

Simple Input from a Terminal

Simple input from a terminal is accomplished with the GET LIST statement, which in its simple form has the following format:

GET LIST (input-target, ...);

 

Because this statement has no reference to a specific file, the default file SYSIN (the terminal) is assumed. When this GET LIST statement is executed in a program, the program pauses until enough values are typed by the user to satisfy the input-target list.

The user must separate the values with the Return key, spaces, or commas. The user must press the Return key to send the typed line to the program.

In the context of simple terminal input, the input targets are usually simple variable references. For example:

GET LIST (SALARY,CONTRIBUTION(42),PAYROLL.DEDUCTION);

 

The preceding statement gets three character strings from the terminal. The strings are converted automatically to the target data types and assigned to the scalar variable SALARY, element 42 of the array CONTRIBUTION, and member DEDUCTION of the structure PAYROLL. There are several sequences with which the user can type the needed values, including the following:

15500,500,1200

15500

500

1200

15500 500

1200

 

If you press Return in response to an input request from GET LIST, the null character string, '', is assigned to the input target. If you press Return in response to an input request from GET EDIT, the requested field width is filled with spaces and assigned to the input target under control of the corresponding format item. (Note that an all-space field causes an error for B formats.)

For full details on input targets, see the GET LIST statement ( See Input by the GET Statement ).

Simple Output to a Terminal

You can send data to a terminal with the PUT LIST statement. A simple form of PUT LIST is as:

PUT LIST (output-source, ...);

 

The output sources in simple cases are expressions, including variable references. The PUT LIST statement converts the results of the expressions to the appropriate character representations and sends the character strings to the terminal. For instance:

PUT LIST (A,B,C);

 

This statement converts the values of the variables A, B, and C to character strings and sends the results to the terminal. In this simple case, the displayed strings are separated by tabs.

The file SYSPRINT, used as the default output stream by PUT LIST, is a print file, and the terminal has the characteristics of print files.

Print File

A print file is a stream output file that is intended for output on a terminal, line printer, or other output device. You can declare any stream output file to be a print file by using the PRINT attribute. The default stream output file, SYSPRINT, is a print file.

The following list describes the special features of print files, as opposed to ordinary stream output files:

  • Character strings are not enclosed in apostrophes on list-directed output.
  • List-directed output data items are separated by tabs instead of spaces. Tab stops occur at 8-column increments beginning with column 1. With the PUT EDIT statement and the TAB format item, you can begin output at a specified tab stop.
  • An internal record is kept of the current line in a print file. The LINENO built-in function returns the current line number for a specified file. This function allows you to keep track of the number of lines being written to a file and to decide where page advances should occur.
  • Print files are divided into both lines and pages. An internal record is kept of the number of lines per page. You can specify a page size when the print file is created (see See Opening and Closing Files for PAGESIZE option).
  • During output of data to a print file, the ENDPAGE condition is signaled when the output exceeds the page size.
  • New pages are started by the PUT PAGE statement, the PAGE format item, and certain other format items. Each of these operations increments the current page number by 1. The PAGENO built-in function returns the current page number from a print file. This function allows you to keep track of the number of pages being written to a file. You can set the current page number to a specific value by assigning the value to the PAGENO pseudovariable.
  • If the print file is a terminal, the output is written to the terminal at the conclusion of each PUT statement.
  • A print file is created with PRN-format carriage control. PRN format is efficient for both terminals and line printers because blank lines do not require individual records. (PRN format is discussed in the OpenVMS Record Management Services Reference Manual.)
  • Print files usually cannot be read properly with GET LIST or GET EDIT.
Examples

SIMPLE_INPUT: PROCEDURE OPTIONS (MAIN);

/* Simple input from user's terminal */

DECLARE BADGE_NUMBER FIXED DECIMAL (5),

SOCIAL_SECURITY_NUMBER CHARACTER(11);

 

GET LIST (BADGE_NUMBER,SOCIAL_SECURITY_NUMBER);

PUT LIST (BADGE_NUMBER,SOCIAL_SECURITY_NUMBER);

 

END SIMPLE_INPUT;

 

PL/I does not display a prompt character on the terminal when a program executes a GET or READ statement. Consequently, it is difficult to tell that a program is trying to read data unless the program executes an output statement containing a prompting message. The program SIMPLE_INPUT would be easier to use if the following statement appeared immediately before GET LIST:

PUT SKIP LIST('Enter badge number, social security number:');

 

The cursor remains on the same line after the prompt is displayed, so the input can be entered on the same line. The completed line might be:

Enter badge number, social security number: 7,116-40-0482

 

The GET statement also has a PROMPT statement option that displays a prompt on the user's terminal. See the Kednos PL/I for UNIX User's Manual.

TIN: PROCEDURE OPTIONS(MAIN);

 

DECLARE STRING CHAR(10) VARYING,

I FIXED BINARY STATIC INITIAL(0),

A FLOAT BINARY;

DECLARE EOF BIT STATIC INITIAL('0'B);

 

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

PUT SKIP LIST('Enter string, integer, float>');

GET LIST(STRING,I,A);

DO WHILE(^EOF); /* stop when CTRL/D is typed */

PUT SKIP LIST(STRING,I,A);

PUT SKIP LIST('Enter string, integer, float>');

GET LIST(STRING,I,A);

END;

 

END TIN;

 

Here, the user is prompted to enter three values from the default file SYSIN. The three values are immediately written out to the default file SYSPRINT. This sequence continues until the user answers the prompt with a Ctrl/D, which signals the ENDFILE condition for SYSIN; the program then terminates. The following is a sample dialog with the program:

$ RUN TIN

Enter string, integer, float> JONES,27,3.75

JONES 27 3.7500000E+00

Enter string, integer, float> JONES 27 3.75

JONES 27 3.7500000E+00

Enter string, integer, float> JONES

27KEY(Return)

3.75;KEY(Return)

JONES 27 3.7500000E+00

Enter string, integer, float> DOOLEY

KEY(Return)

4E-6;KEY(Return)

DOOLEY 0 4.0000000E-06

Enter string, integer, float>

$

 

Notice that input fields are separated by commas, spaces, or the RETURN key. Notice also that entering a blank line after `DOOLEY' causes the program to set the value of I to zero.

Other Topics

The following topics are of interest in terminal I/O applications:

Record I/O

Record I/O is performed by the READ, WRITE, DELETE, and REWRITE statements. In addition, the LOCATE statement is accepted in the IBM dialect.

In record I/O, each I/O statement processes an entire record. (In stream I/O, more than one line or record can be processed by a single statement.) See . Attributes and Access Modes for Record Files summarizes the file description attributes that apply to record I/O.

. Attributes and Access Modes for Record Files

Attributes
Specified

Attributes
Implied

Valid Devices
and File
Organizations

Usage

SEQUENTIAL OUTPUT

RECORD

Any output device or file

Records can be added to the end of the file with WRITE statements. Each WRITE statement adds a single record to the file.

SEQUENTIAL OUTPUT BUFFERED

RECORD

Any output device or file

Similar to SEQUENTIAL OUTPUT. In addition, the LOCATE statement can be used. (ibm dialect only)

SEQUENTIAL INPUT

RECORD

Any input device or file

Records in the file are read with READ statements. Each statement reads a single record.

SEQUENTIAL UPDATE

RECORD

Relative, stream

READ statements read a file's records in order. PL/I maintains the current record, which is the record just read. This record can be replaced in a REWRITE statement. In a relative file, the current record can also be deleted with a DELETE statement. Each statement processes a single record.

DIRECT OUTPUT

KEYED RECORD

Relative, stream

WRITE statements insert records into the file at positions specified by keys. Each statement inserts a single record.

DIRECT INPUT

KEYED RECORD

Relative, stream

READ statements specify records to be read randomly by key. Each statement reads a single record.

DIRECT UPDATE

KEYED RECORD

Relative, stream

READ, WRITE, and REWRITE statements specify records randomly by key. In a relative file, records can also be deleted by key.

KEYED SEQUENTIAL OUTPUT

RECORD

Relative, stream

WRITE statements insert records into the file at positions specified by keys. Each statement inserts a single record. This mode is identical to DIRECT OUTPUT.

KEYED SEQUENTIAL INPUT

RECORD

Relative, stream

READ statements access records in the file randomly by key or sequentially.

KEYED SEQUENTIAL UPDATE

RECORD

Relative, stream

Any record I/O operation is allowed except a WRITE statement that does not specify a key or a DELETE statement for a sequential disk file with fixed- length records.

READ Statement

The READ statement reads a record from a file, either the next record or a record specified by the KEY option. The file must have either the INPUT or the UPDATE attribute.

The format of the READ statement is:

READ FILE (file-reference)

FILE(file-reference)

The file from which the record is to be read. If the file is not currently open, PL/I opens the file with the implied attributes RECORD and INPUT. The implied attributes are merged with the attributes specified in the file's declaration.

INTO (variable-reference)

An option that specifies that the contents of the record are to be assigned to the specified variable. The variable must be an addressable variable. The INTO and SET options are mutually exclusive.

  • If the variable has the VARYING attribute and the file does not have the attribute ENVIRONMENT(SCALARVARYING), the entire record is treated as a string value and assigned to the variable. If the record is larger than the variable, it is truncated and the ERROR condition is signaled.
  • If the variable has the AREA attribute and the file does not have the attribute ENVIRONMENT(SCALARVARYING), the entire record is treated as an area value and assigned to the variable. If the extent of the area in the record is larger than the variable, the AREA condition is signaled and the target area is unmodified.
  • For any other type of variable, the record is copied into the variable's storage. If the record is not exactly the same size as the target variable, as much of the record as will fit is copied into the variable and the ERROR condition is signaled.
SET (pointer-variable)

An option that specifies that the record should be read into a buffer allocated by PL/I and that the specified pointer variable should be assigned the value of the location of the buffer in storage. The SET and INTO options are mutually exclusive.

This buffer remains allocated until the next operation on the file but no longer. Therefore, do not use either the pointer value or the buffer after the next operation on the file. The only valid use of the buffer during a subsequent I/O operation is in a REWRITE statement. In this case, you can rewrite the record from the buffer before the buffer is deallocated.

KEY (expression)

An option that specifies that the record to be read is to be located using the key specified by the expression. The file must have the KEYED attribute. The KEY and KEYTO options are mutually exclusive.

For a relative file or a sequential disk file with fixed-length records, the key is a fixed binary value indicating the relative record number of the record to be read.

The value of the specified expression is converted to the data type of the key. If no record with the specified key exists in the file, or if the value specified is not valid for conversion to the data type of the key, the KEY condition is signaled.

KEYTO (variable-reference)

An option that specifies that the key of the record being read is to be assigned to the designated variable. The value of the key is converted from the data type implied by the file's organization to the data type of the variable. The variable must have a computational data type but cannot be an unaligned bit string or an aggregate consisting entirely of unaligned bit strings. The KEYTO and KEY options are mutually exclusive.

KEYTO is specified only for a file that has both the KEYED and SEQUENTIAL attributes.

OPTIONS (option, ...) (dec and ansi dialects only)

An option that specifies one or more of the following READ statement options, separated by commas:

RECORD_ID (variable-reference)

RECORD_ID_TO (variable-reference)

All these options except remain in effect for the current statement only. These options are described fully in the Kednos PL/I for UNIX User's Manual.

IGNORE (expression) (IBM Dialect Only)

An option that specifies the number of records to skip on the next READ of a SEQUENTIAL INPUT or SEQUENTIAL UPDATE file. The expression must evaluate to an integer value n. If the expression evaluates to one (1) or more, the next READ statement for the file will retrieve (n+1)th record. If the expression is less than one (1), this READ statement has no effect. For example, the following expression specifies that the next five records in the PERSONNEL file should be ignored:

READ FILE (PERSONNEL) IGNORE(5);

 

File Positioning Following a READ Statement

If the file is accessed sequentially, the READ statement reads the next record in the file. If the next-record position is at the end-of-file, the ENDFILE condition is signaled.

After a successful read operation, the current record position in the file denotes the record that was just read. The next-record position denotes the following record or, if there is no following record, the end-of-file.

If any error other than an incorrect record size occurs, the current record becomes undefined and the next record is the same as it was before the read operation was attempted.

Examples

COPY: PROCEDURE;

DECLARE INREC CHARACTER(80) VARYING,

ENDED BIT(1) STATIC INIT('0'B),

(INFILE,OUTFILE) FILE;

 

OPEN FILE (INFILE) RECORD INPUT

TITLE('RECFILE.DAT');

OPEN FILE (OUTFILE) RECORD OUTPUT

TITLE('COPYFILE.DAT');

ON ENDFILE(INFILE) ENDED = '1'B;

 

READ FILE(INFILE) INTO (INREC);

DO WHILE (^ENDED);

WRITE FILE (OUTFILE) FROM (INREC);

READ FILE (INFILE) INTO (INREC);

END;

CLOSE FILE(INFILE);

CLOSE FILE(OUTFILE);

RETURN;

END;

 

The program COPY reads a file with variable-length records into a character string with the VARYING attribute and writes the records to a new output file.

It uses a DO-group to read the records in the file sequentially until the end-of-file is reached. It uses the ON statement to establish the action to be taken when the end-of-file occurs: it sets the bit ENDED to '1'B so that the DO-group will not be executed again.

The VARYING character-string variable INREC has a maximum length of 80 characters. If any record in the file is more than 80 characters, the ERROR condition is signaled. If no ERROR ON-unit exists, the program exits.

PRINT_DATA: PROCEDURE OPTIONS(MAIN);

DECLARE 1 EMPLOYEE BASED (EP),

2 NAME,

3 LAST CHAR(30),

3 FIRST CHAR(20),

3 MIDDLE_INIT CHAR(1),

2 DEPARTMENT CHAR(4),

2 SALARY FIXED DECIMAL (6,2),

EP POINTER,

EMP_FILE FILE;

 

DECLARE EOF BIT(1) STATIC INIT('0'B),

NUMBER FIXED BIN(31);

 

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

OPEN FILE(EMP_FILE) INPUT SEQUENTIAL KEYED;

READ FILE(EMP_FILE) SET(EP) KEYTO(NUMBER);

DO WHILE (^EOF);

PUT SKIP LIST('EMPLOYEE',NUMBER,

EMPLOYEE.NAME.FIRST,EMPLOYEE.NAME.LAST,

EMPLOYEE.NAME.MIDDLE_INIT);

READ FILE(EMP_FILE) SET(EP) KEYTO(NUMBER);

END;

CLOSE FILE(EMP_FILE);

 

END;

 

The PRINT_DATA program accesses a relative file sequentially with READ statements and obtains the key value of each record, that is, the relative record number. The records in the file EMP_FILE are arranged according to employee numbers. Each employee number corresponds to a relative record number in the file. The READ statements read records into the based structure EMPLOYEE and set the pointer EP to the location of the allocated buffer. The READ statements specify the KEYTO option to obtain the record number of each record. The procedure prints the employee numbers and names. When the last record has been read, the program closes the input file and exits.

WRITE Statement

The WRITE statement adds a record to a file, either at the end of a file that has the SEQUENTIAL and OUTPUT attributes, or in a specified key position in a file that has the KEYED and OUTPUT attributes or the KEYED and UPDATE attributes. The format of the WRITE statement is:

WRITE FILE(file-reference) FROM (variable-reference)

[ KEYFROM (expression) ]

[ OPTIONS (option, ...) ];

 
FILE (file-reference)

A reference to the file to which the record is to be written. If the file is not currently open, the WRITE statement opens the file with the implied attributes RECORD, OUTPUT, and SEQUENTIAL; these attributes are merged with the attributes specified in the file's declaration.

FROM (variable-reference)

A reference to the variable containing data for the output record. The variable must be addressable.

If the variable has the VARYING or the AREA attribute and the file does not have the attribute ENVIRONMENT(SCALARVARYING), the WRITE statement writes only the current value of the varying string or the area into the specified record. In all other cases, the WRITE statement writes the entire storage of the variable. If the contents of the variable do not fit the specified record size, the WRITE statement outputs as much of the variable as will fit, and the ERROR condition is signaled.

KEYFROM (expression)

An option specifying that the record to be written is to be positioned in the file according to the key specified by the expression. The file must have the KEYED attribute.

In a relative file or a sequential disk file with fixed-length records, the key value is a fixed binary value indicating the relative record number of the record to be written.

The value of the specified expression is converted to the data type of the key. If the specified key value cannot be converted to the data type of the key, the KEY condition is signaled.

OPTIONS (option) (dec and ansi dialect only)

An option specifying the WRITE statement option RECORD_ID_TO. The format of this option is:

RECORD_ID_TO (variable-reference)

This option is described fully in the Kednos PL/I for UNIX User's Manual.

File Positioning Following a WRITE Statement

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

Examples

TRUNC: PROCEDURE;

DECLARE INREC CHARACTER(80) VARYING,

OUTREC CHARACTER(80),

ENDED BIT(1) STATIC INIT('0'B),

(INFILE,OUTFILE) FILE;

 

OPEN FILE (INFILE) RECORD INPUT

TITLE('RECFILE.DAT');

OPEN FILE (OUTFILE) RECORD OUTPUT

TITLE('TRUNCFILE.DAT')

ENVIRONMENT(FIXED_LENGTH_RECORDS,

MAXIMUM_RECORD_SIZE(80));

 

ON ENDFILE(INFILE) ENDED = '1'B;

READ FILE(INFILE) INTO (INREC);

DO WHILE (^ENDED);

OUTREC = INREC;

WRITE FILE (OUTFILE) FROM (OUTREC);

READ FILE (INFILE) INTO (INREC);

END;

 

CLOSE FILE(INFILE);

CLOSE FILE(OUTFILE);

RETURN;

END;

 

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

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

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

The TRUNC procedure creates a new version of the file TRUNCFILE.DAT every time it executes.

ADD_EMPLOYEE: PROCEDURE;

 

DECLARE 1 EMPLOYEE,

2 NAME,

3 LAST CHAR(30),

3 FIRST CHAR(20),

3 MIDDLE_INIT CHAR(1),

2 DEPARTMENT CHAR(4),

2 SALARY FIXED DECIMAL (6,2),

EMP_FILE FILE;

 

DECLARE MORE_INPUT BIT(1) STATIC INIT('1'B),

NUMBER FIXED DECIMAL (5,0);

 

OPEN FILE(EMP_FILE) DIRECT UPDATE;

 

DO WHILE (MORE_INPUT);

PUT SKIP LIST('Employee Number');

GET LIST (NUMBER);

PUT SKIP LIST ('Name (Last, First, Middle Initial)');

GET LIST (EMPLOYEE.NAME.LAST,EMPLOYEE.NAME.FIRST,

EMPLOYEE.NAME.MIDDLE_INIT);

 

PUT SKIP LIST('Department');

GET LIST (EMPLOYEE.DEPARTMENT);

 

PUT SKIP LIST('Starting salary');

GET LIST(EMPLOYEE.SALARY);

 

WRITE FILE (EMP_FILE)

FROM (EMPLOYEE) KEYFROM(NUMBER);

 

PUT SKIP LIST('More?');

GET LIST(MORE_INPUT);

END;

CLOSE FILE(EMP_FILE);

RETURN;

END;

 

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

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

DELETE Statement

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

The format of the DELETE statement is:

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

 
FILE(file-reference)

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

KEY (expression)

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

In a relative file, the key is a fixed binary value indicating the relative record number of the record to be deleted.

The value of the specified expression is converted to the data type of the key. If no record with the specified key exists in the file, or if the value specified is not valid for conversion to the data type of the key, the KEY condition is signaled.

OPTIONS(option, ...) (dec and ansi dialects only)

An option giving one or more of the following DELETE statement options:

FAST_DELETE

RECORD_ID (reference)

Multiple options must be separated by commas.

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

These options are described fully in the Kednos PL/I for UNIX User's Manual.

File Positioning Following a DELETE Statement

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

REWRITE Statement

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

REWRITE FILE (file-reference)

[ FROM (variable-reference) [ KEY (expression) ]]

[ OPTIONS (option, ...) ];

 
FILE(file-reference)

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

FROM (variable-reference)

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

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

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

KEY (expression)

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

In a relative file or a sequential disk file with fixed-length records, the key is a fixed binary value indicating the relative record number of the record to be rewritten.

The value of the specified expression is converted to the data type of the key. If no record with the specified key exists, or if the value specified is not valid for conversion to the data type of the key, the KEY condition is signaled.

OPTIONS (option, ...)

An option giving one or more of the following REWRITE statement options. Multiple options must be separated by commas.

FIXED_CONTROL_FROM (variable-reference)

INDEX_NUMBER (expression)

MATCH_GREATER

MATCH_GREATER_EQUAL

MATCH_NEXT

MATCH_NEXT_EQUAL

RECORD_ID (expression)

RECORD_ID_TO (variable-reference)

All these options except INDEX_NUMBER remain in effect for the current statement only. These options are described fully in the Kednos PL/I for UNIX User's Manual.

File Positioning Following a REWRITE Statement

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

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

Examples

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

NEW_SALARY: PROCEDURE (EMPLOYEE_NUMBER,PAY);

 

DECLARE EMPLOYEE_NUMBER FIXED DECIMAL(5,0),

PAY FIXED DECIMAL (6,2);

 

 

 

DECLARE 1 EMPLOYEE,

2 NAME,

3 LAST CHAR(30),

3 FIRST CHAR(20),

3 MIDDLE_INIT CHAR(1),

2 DEPARTMENT CHAR(4),

2 SALARY FIXED DECIMAL (6,2),

EMP_FILE FILE;

 

OPEN FILE(EMP_FILE) DIRECT UPDATE;

READ FILE(EMP_FILE) INTO(EMPLOYEE)

KEY (EMPLOYEE_NUMBER);

EMPLOYEE.SALARY = PAY;

REWRITE FILE(EMP_FILE) FROM(EMPLOYEE)

KEY(EMPLOYEE_NUMBER);

CLOSE FILE(EMP_FILE);

RETURN;

END;

 

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

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

CHANGE_HEADER: PROCEDURE OPTIONS(MAIN);

 

DECLARE TITLE_PAGE FILE SEQUENTIAL UPDATE,

INREC CHARACTER(80) BASED(P),

P POINTER;

 

OPEN FILE(TITLE_PAGE);

READ FILE(TITLE_PAGE) SET(P);

 

INREC = 'Summary of Courses for Fall 1980';

REWRITE FILE(TITLE_PAGE);

CLOSE FILE(TITLE_PAGE);

RETURN;

END;

 

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

LOCATE Statement (IBM Dialect Only)

Use the LOCATE statement for output to a sequential file from a buffer. The LOCATE statement allocates storage in an output buffer for a based variable. It sets a pointer to the storage location in the buffer.

After executing the LOCATE statement, you can assign values directly to the output buffer by referencing based variables. Use the pointer variable set by the LOCATE statement to qualify by the based variables.

The next LOCATE, WRITE, or CLOSE statement for the referenced file transmits the data in the output buffer to the file.

The LOCATE statement can result in faster execution if the file contains large records and each record is referenced once or very few times. Although the indirect addressing technique incurs a small amount of overhead, there is less data movement, and less storage may be required.

To further optimize performance when writing large records, build the record in local variables in your program. Then assign the entire record to the output buffer using the pointer variable set by the LOCATE statement.

The format of the LOCATE statement is:

LOCATE based-variable FILE (file-reference)

[ SET (pointer-reference) ]

[ KEYFROM (expression) ];

 
based-variable

An unsubscripted level-1 based variable.

FILE(file-reference)

The output file to which buffers will be written. If the file is not open, it is opened with the implied attributes RECORD and OUTPUT; these attributes are merged with the attributes specified in the file declaration.

SET (pointer-variable)

Specifies a pointer variable to contain the value of the location of the record in the allocated storage buffer. If you do not specify the SET option, the LOCATE sets the pointer declared with the record variable.

If the record contains an element that is a varying-length string variable, you must specify the ENVIRONMENT(SCALARVARYING) option for the file.

The buffer remains allocated until the next LOCATE, WRITE or CLOSE operation on the file but no longer. Therefore, do not use either the pointer value or the buffer after the next LOCATE, WRITE or CLOSE operation on the file. The only valid use of the buffer during a subsequent I/O operation is in a REWRITE statement. In this case, you can rewrite the record from the buffer before the buffer is deallocated.

KEYFROM (expression)

Specifies that, when the record in the storage buffer is written to the file, it will be positioned in the file according to the key specified by the expression. The file must have the KEYED attribute.

In a sequential file with fixed-length records, the key value is a fixed binary value indicating the relative record number of the record to be located.

The value of the specified expression is converted to the data type of the key. If the specified key value cannot be converted to the data type of the key, the KEY condition is signaled.

File Positioning Following a LOCATE Statement

The next record position is set to the end-of-file. The current record is set to designate the record just written.

Position Information for a Record File

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

  • The next record, for files with the SEQUENTIAL INPUT or SEQUENTIAL UPDATE attributes. The next record designates the record that will be accessed by a READ statement that does not specify the KEY option. The next record may contain the end-of-file.
  • The current record, for a file with the UPDATE attribute. The current record designates either of the following:
  • The record that will be modified by a REWRITE statement that does not specify the KEY option
  • The record that will be deleted by a DELETE statement that does not specify the KEY option

The value of the current record may be undefined.

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

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

After a keyed I/O statement, that is, an I/O statement that specifies the KEY or KEYFROM option, the current record and next record are set as described in See . Position Information for a Record File . (X is the record specified by key and X+1 is the next record or, if there are no more records, the end-of-file.)

. Position Information for a Record File

Statement

Current Record

Next Record

READ

X

X+1

WRITE

X

X+1

REWRITE

X

X+1

DELETE

undefined

X+1

 

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 preprocessor statements are executed only at compile time. Any resulting source program changes are then used for further compilation.

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

During compilation, the preprocessor performs two types of preprocessing:

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

This chapter describes the preprocessor statements and functions.

Preprocessor Compilation Control

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

For example:

EXAMPLE: PROCEDURE OPTIONS(MAIN);

 

%DECLARE HOUR FIXED;

%HOUR = SUBSTR(TIME(),1,2);

 

%IF HOUR > 7 & HOUR < 18

%THEN

%FATAL 'Please compile this outside of prime time';

 

%DECLARE T CHARACTER;

%ACTIVATE T NORESCAN;

 

%T='''Compiled on '||DATE()||'''';

 

DECLARE INIT_MESSAGE CHARACTER(60) VARYING INITIAL(T);

 

%IF VARIANT() = '' | VARIANT() = 'NORMAL'

%THEN

%INFORM 'NORMAL';

%ELSE %DO;

%IF VARIANT() = 'SPECIAL'

%THEN

%INFORM 'SPECIAL';

%ELSE

%IF VARIANT() = 'NONE'

%THEN %;

%ELSE

%DO;

%T='''unknown variant '||variant()||''''

%WARN t;

INIT_MESSAGE=INIT_MESSAGE||' with '||T;

%END;

 

%END;

 

PUT SKIP LIST (INIT_MESSAGE);

 

END EXAMPLE;

 

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

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

Preprocessor Statements

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

%DECLARE HOUR FIXED; /* declaration of a preprocessor

single variable */

%DECLARE (A,B) CHARACTER; /* a factored preprocessor

declaration */

%HOUR = SUBSTR(TIME(),1,2); /* preprocessor assignment

statement using two built-in

functions */

%STATE: PROCEDURE (X) RETURNS (BIT); /* preprocessor

procedure */

 

Notice that a percent sign is required only at the beginning of the statement and must be the first text on the line (white space is ignored). Each preprocessor statement must be on a new line. The percent sign alerts the compiler that until the line is terminated with a semicolon, all subsequent text is preprocessor text. Therefore, no other percent signs are required on the line.

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

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

%label: preprocessor-statement;

 

You can specify multiple labels on a preprocessor statement (note that this is not true of non-preprocessor statements).

See . Summary of PL/I Preprocessor Statements summarizes the preprocessor statements. Each statement is then described in detail in an individual subsection.

. Summary of PL/I Preprocessor Statements

Statement

Use

%Assignment

Evaluates a preprocessor expression and gives its value to a preprocessor identifier

%;

Null statement, specifies no preprocessor operation

%ACTIVATE

Makes the value of declared preprocessor variables eligible for replacement

%DEACTIVATE

Makes the value of declared preprocessor variables ineligible for replacement

%DECLARE

Defines the preprocessor variable names and identifiers to be used in a PL/I program and specifies the data attributes associated with them

%DO

Denotes the beginning of a group of preprocessor statements to be executed as a unit

%END

Denotes the end of a block or group of statements that started with a %PROCEDURE or a %DO statement

%ERROR

Generates a user-defined error diagnostic message

%FATAL

Generates a user-defined fatal diagnostic message

%GOTO

Transfers control to a labeled preprocessor statement

%IF

Tests a preprocessor expression and establishes action to be performed based on the results

%INCLUDE

Copies the text of an external file into the source file at compile time

%INFORM

Generates a user-defined informational diagnostic message

%[NO]LIST 3

Same as %[NO]LIST_ALL

%[NO]LIST_ALL See Ignored by the Kednos PL/I for UNIX compiler. Included for compatibility with the Kednos OpenVMS PL/I compiler.

Does or does not include INCLUDE files, machine code, and source statements in the listing from that point on

%[NO]LIST_INCLUDE See Ignored by the Kednos PL/I for UNIX compiler. Included for compatibility with the Kednos OpenVMS PL/I compiler.

Does or does not include INCLUDE files in the listing from that point on

%[NO]LIST_MACHINE See Ignored by the Kednos PL/I for UNIX compiler. Included for compatibility with the Kednos OpenVMS PL/I compiler.

Does or does not include machine code in the listing from that point on

%[NO]LIST_SOURCE See Ignored by the Kednos PL/I for UNIX compiler. Included for compatibility with the Kednos OpenVMS PL/I compiler.

Does or does not include source code in the listing from that point on

%PAGE

Provides listing pagination without form feeds in the source text

%PROCEDURE

Begins a preprocessor procedure

%REPLACE

Assigns a constant value to an identifier at compile time

%RETURN

Returns a value from execution of a preprocessor procedure to the point of invocation

%SBTTL See Ignored by the Kednos PL/I for UNIX compiler. Included for compatibility with the Kednos OpenVMS PL/I compiler.

Allows specification of a listing subtitle line

%TITLE See Ignored by the Kednos PL/I for UNIX compiler. Included for compatibility with the Kednos OpenVMS PL/I compiler.

Allows specification of a listing title line

%WARN

Generates a user-defined warning diagnostic message

%Assignment Statement

The preprocessor assignment statement gives a value to a specified preprocessor variable.

The format of the assignment statement is:

%target = expression;

 
target

The name of the preprocessor variable to be assigned a value. It must be an unsubscripted reference to a preprocessor variable.

expression

Any valid preprocessor expression.

For arithmetic operations, only decimal integer arithmetic of precision (10,0) is performed. Each operand and all results are converted, if necessary, to a fixed decimal value of precision (10,0). Fractional digits are truncated.

% (Null)

The % (null) statement performs no action.

The format of the % (null) statement is:

%;

 

The most common use for the % (null) statement is as the target statement of a %THEN or %ELSE clause in an %IF statement. For example:

%IF

ERROR() > 0;

%THEN

%GOTO FIXIT;

%ELSE

%;

 

%ACTIVATE

The %ACTIVATE statement makes preprocessor variable and procedure identifiers eligible for replacement. If the compiler encounters the named identifier after executing a %ACTIVATE statement, it initiates variable replacement.

The format of the %ACTIVATE statement is:

element

The name of a previously declared preprocessor identifier and/or a list of identifiers, where the identifiers are separated by commas and the list is enclosed in parentheses.

RESCAN or NORESCAN

Specifies that the preprocessor is to continue or discontinue checking the text for secondary value replacement.

The RESCAN option specifies that preprocessor scanning continue until all possible identifier replacements are completed. RESCAN is the default option.

The NORESCAN option specifies that replacement be done only once; the resulting text is not rescanned for possible further replacement.

An identifier is activated by either a %ACTIVATE statement or a %DECLARE statement. When an activated identifier is encountered by the compiler, in unquoted nonpreprocessor statements, the variable name or procedure reference is replaced by its value. Replacement continues throughout the rest of the source program unless replacement is stopped with the %DEACTIVATE statement.

You can activate several variables with a single statement. For example:

%DECLARE (A,B,C) FIXED;

%ACTIVATE (A,B), C NORESCAN;

 

Because RESCAN is the default action, this statement activates A and B with the RESCAN option. C is activated, but is not rescanned.

If an identifier that is not a preprocessor variable or procedure is the target of a %ACTIVATE statement, a warning message is issued and the identifier is implicitly declared as a preprocessor variable with the FIXED attribute. Thereafter, the identifier variable is eligible for replacement when activated.

For example:

DECLARE (A,B,C) FIXED;

%DECLARE (A,B) FIXED;

%ACTIVATE (A,B);

 

%A = 1;

%B = (A + A);

C = A + B;

PUT SKIP LIST (C); /* C = 3 */

In the preceding example, the activated preprocessor variables A and B are assigned values by the preprocessor. Notice that variables A and B are also declared as nonpreprocessor variables; this establishes them as variables within the nonpreprocessor program.

In the following example, the variable B is deactivated by the %DEACTIVATE statement.

%DEACTIVATE B;

B = 900;

C = A + B;

PUT SKIP LIST (C); /* C = 901 */

END;

 

Because the preprocessor variable B is deactivated, the preprocessor assignment statement %B = (A + A) is not in effect and the value of B is taken from the run-time assignment of B = 900. However, the value of A remains 1.

%DEACTIVATE

The %DEACTIVATE statement makes preprocessor variable and procedure identifiers ineligible for replacement. After a variable or procedure has been deactivated, it will not be replaced during preprocessing. Replacement of a deactivated variable or procedure occurs again only after it is reactivated with the %ACTIVATE statement.

The format of the %DEACTIVATE statement is:

element

The name of a preprocessor identifier, or a list of identifiers that is enclosed in parentheses. Deactivated elements must have been previously declared preprocessor variables.

For example:

TESTF:PROCEDURE OPTIONS (MAIN);

DECLARE Y FIXED DECIMAL;

Y = 10; /* initial value: Y = 10 */

%DECLARE Y FIXED;

%Y = 3; /* replacement value: Y = 3 */

PUT SKIP LIST(Y); /* output: Y = 3 */

%DEACTIVATE Y;

PUT SKIP LIST(Y); /* output: Y = 10 */

END;

 

In this example, %Y, when activated, replaces all the occurrences of the variable Y by the value assigned to %Y, until %Y is deactivated by the %DEACTIVATE statement. The identifier %Y is implicitly activated when it is declared as a preprocessor identifier.

It is possible to deactivate several variables with a single statement. For example:

%DEACTIVATE (A,B,C,D,E,F);

 

%DECLARE

The %DECLARE statement establishes an identifier as a preprocessor variable, specifies the data type of the variable, and activates the identifier for replacement. %DECLARE can occur anywhere in a PL/I source program.

The format of the %DECLARE statement is:

element

The name of a preprocessor identifier or a list of identifiers, which are separated by commas and enclosed in parentheses. You can give elements the attribute BIT, FIXED, or CHARACTER, but you cannot specify precision or length. The compiler supplies the variables with the implied attributes shown in See . Implied Attributes for Variables .

. Implied Attributes for Variables

Specified Attribute

Implied Attributes

BIT

(31) INITIAL ((31)'0'B)

FIXED

DECIMAL (10,0) INITIAL (0)

CHARACTER

VARYING (32500) INITIAL (' ')

If no data type is specified, FIXED is assumed.

When a variable is declared in a preprocessor statement, it is activated for replacement and rescanning. The scope of a preprocessor variable is all of the text following the declaration of the variable, unless the variable is declared inside a preprocessor procedure. Using %DECLARE inside of a preprocessor procedure has the effect of declaring a local variable. For example:

%DECLARE HOUR FIXED;

 

In this example, HOUR is declared as a preprocessor variable identifier with the FIXED attribute. The compiler supplies the default values that make this declaration the equivalent of the following:

DECLARE HOUR FIXED DECIMAL (10,0) INITIAL (0);

  • In preprocessor declarations, the attribute FIXED implies FIXED DECIMAL. In nonpreprocessor declarations, FIXED implies FIXED BINARY.

Factored declarations are permitted and follow the same usage rules as nonpreprocessor declarations. For example:

%DECLARE (A,B) CHARACTER, C BIT;

 

Both A and B are declared with the CHARACTER attribute. The compiler supplies default values that make this declaration the equivalent of the following:

%DECLARE (A,B) CHARACTER VARYING(32500) INITIAL(''),

C BIT(31)INITIAL((31)'0'B);

 

%DO

The %DO statement begins a preprocessor DO-group, a sequence of statements terminating with the %END statement. The preprocessor DO-group must be a non-iterative simple DO-group, but it can be usefully combined with an %IF statement.

The format of the %DO statement is:

DO;

 

%END;

You can include both preprocessor and nonpreprocessor text in a preprocessor DO-group. For example:

%DECLARE T CHARACTER; /* declare T */

%ACTIVATE T NORESCAN; /* activate T for replacement */

%IF VARIANT() = 'NONE';

%THEN

%DO;

/* assign string to T */

%T = '''unknown variant''';

/* output unknown variant warning at compile time */

%WARN T;

/* assign value of T to nonpreprocessor variable */

INIT_MESSAGE = INIT_MESSAGE||' with '||T;

%END;

 

This preprocessor DO-group performs several steps. First, a string constant is assigned to T. Then the value of T is used in a preprocessor user-generated diagnostic message. This message is issued at compile time to warn the programmer that the program is compiled with an unknown variant. Finally, the value of T is concatenated with a nonpreprocessor string constant. INIT_MESSAGE, including the value of T, is part of the run-time image.

%END

The %END statement terminates a preprocessor procedure or DO-group.

The format of the %END statement is:

%END;

 

Preprocessing then continues with the next executable preprocessor statement.

%ERROR

The %ERROR statement provides a diagnostic error message during program compilation.

The format of the %ERROR statement is:

%ERROR preprocessor-expression;

preprocessor-expression

A maximum of 64 characters giving the text of the error message to be displayed. Messages of more than 64 characters are truncated.

Returned Message

The message displayed by %ERROR is:

%PLICOM-E-USERDIAG, preprocessor-expression

 

Compilation errors that result in the display of the %ERROR statement increment the informational diagnostic count displayed in the compilation summary, and inhibit production of an object file.

%FATAL

The %FATAL statement provides a diagnostic fatal message during program compilation.

The format of the %FATAL statement is:

%FATAL preprocessor-expression;

 
preprocessor-expression

The text of the fatal message you want displayed. The text is a character string with a maximum length of 64 characters. It is truncated if necessary.

Returned Message

The message displayed by %FATAL is:

%PLICOM-F-USERDIAG, preprocessor-expression

 

Compilation errors that result in a fatal error terminate compilation after the message is displayed.

%GOTO

The %GOTO statement causes the preprocessor to interrupt its sequential processing of source text and continue processing at the point specified in the %GOTO statement. A %GOTO is useful for avoiding large segments of text in the source program.

The format of the %GOTO statement is:

%GOTO label-reference;

label-reference

A label of a preprocessor statement. The label reference determines the point to which the compiler processing will be transferred.

Nonlocal %GOTOs are not permitted. In other words, if a %GOTO is used within a preprocessor procedure, control must not be passed out of the containing procedure. Also, a %GOTO must not transfer control into a preprocessor procedure.

The following example illustrates transfers (forward and backward) and the use of %GOTO:

%TEXT:PROCEDURE RETURNS(CHARACTER);

%CHANGE_TEXT: DO;

%IF WARN() = 5

%THEN

%GOTO CHANGE_TEXT;

%ELSE

%GOTO INSERT_TEXT;

%INSERT_TEXT: DO;

%END;

 

Depending on the status of the %IF statement in this example, program compilation takes one of two courses. Control is transferred either forward to the statement labeled INSERT_TEXT or backward to the statement labeled CHANGE_TEXT. The compiled program will then include one of the two blocks, but not both. Notice also in this example that the preprocessor built-in function WARN is used to determine preprocessor action, which makes the program self-diagnostic.

If program text is not compiled because the %GOTO statement transferred control over it, the compiler still checks the basic syntax of all statements. Therefore, comment delimiters and parentheses must balance, apostrophes must be paired correctly, and all statements must end with a semicolon.

%IF

The %IF statement controls the flow of program compilation according to the scalar bit value of a preprocessor expression. The %IF statement tests the preprocessor expression and performs the specified action if the result of the test is true.

The format of the %IF statement is:

%IF test-expression %THEN action [%ELSE action];

 
test-expression

Any valid preprocessor expression that yields a scalar bit value. If any bit of the value is 1, then the expression is true; otherwise, the expression is false.

action

A single, unlabeled preprocessor statement, %DO-group, %GOTO statement, or a preprocessor null statement. The specified action must not be an %END statement.

The %IF statement evaluates the preprocessor test expression. If the expression is true, the action specified following the keyword %THEN is compiled. Otherwise, the action, if any, following the %ELSE keyword is compiled. In either case, compilation resumes at the first executable statement following the termination of the %IF statement, unless a %GOTO in one of the action clauses causes compilation to resume elsewhere.

If an action is not compiled because the alternative action was compiled instead, the compiler still checks the basic syntax of all statements. Therefore, comment delimiters and parentheses must balance, apostrophes must be paired correctly, and all statements must end with a semicolon.

%INCLUDE

The %INCLUDE statement incorporates text from other files into the current source file during compilation. It can occur anywhere in a PL/I source file; it need not be part of a procedure.

The format of the %INCLUDE statement is:

file-spec

A file specification enclosed in apostrophes interpreted as the complete file specification or path. The filename is tried as specified with no environment variable translations and no applications of the -Idir or --suffix options. If the file is not found, an error will be generated.

module-name

The module-name is always converted to lower case. If the --suffix option is given, .suffix is appended, without conversion, to module-name. Next, each of the path names specified in the -Idir option is prepended to module-name to form a complete file name. If the file is not found in any of the given directories, the current directory (or `.') is tried.

directory-name

Specifies a path name which overrides the -Idir option. The value of the --fsuffix option is appended to module-name without conversion.

Notes

When you include a text file or a text module from a library, you can choose to include this INCLUDE file in the program's listing by using the -s or --list option on the pl1 command line.

This option provides compatibility with PL/I code previously compiled with VMS text libraries or IBM partition data set names. The directory-name is treated as a UNIX directory, and the module-name as the last qualifier in the path specification.

Included text files are listed in the data map in the listing file. The expanded include files are denoted by the file number (as listed in the data map) plus the line number within the include file. See the Kednos PL/I for UNIX User's Manual for more information.

The -M compiler option determines the case of include module names. When an include module name is built, PL/I first applies the case rule specified by the -M option, then appends the suffix, if one was specified by the -u compiler option.

When searching for a module, PL/I first checks in the current working directory, then each directory in the list specified by the -Idir compiler option, and last in the standard include directory, /usr/lib/pl1/include.

Examples

%INCLUDE '/usr/users/tim/project/header.in';

 

This statement includes the file /usr/users/tim/project/header.in without translation or regard for the -Idir or --suffix options. If this file does not exist, an error occurs.

%INCLUDE HEADER;

 

This statement looks for a module named HEADER with a suffix given by the --suffix option (if any) in the current directory then, if the module was not found, in the directory or directories specified by the --Idir option.

Consider the following command line:

pl1 --suffix .in -Idir /usr/users/tim/project

 

Given this command line, the preprocessor looks for the file /usr/users/tim/project/header.in.

%INCLUDE '/usr/users/tim/project(header)';

 

This statement looks in the directory /usr/users/tim/project for a file named header. If you specified the --suffix .in option, the complete file specification is /usr/users/tim/project/header.in.

Restrictions

%INCLUDE statements can be nested up to a maximum of four levels.

%INFORM

The %INFORM statement specifies a user-written diagnostic informational message to be displayed during program compilation.

The format of the %INFORM statement is:

%INFORM preprocessor-expression;

 
preprocessor-expression

The text of the informational message displayed. The text is a character string of up to 64 characters. The string is truncated if necessary.

Returned Message

The format of the message to be displayed by %INFORM is:

%PLICOM-I-USERDIAG, preprocessor-expression

 

The %INFORM statement increments the informational diagnostic count displayed in the compilation summary.

%PROCEDURE

A preprocessor procedure is a sequence of preprocessor statements headed by a %PROCEDURE statement and terminated by a %END statement. 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.

The format of the %PROCEDURE statement is:

label

An unsubscripted label constant. A preprocessor procedure is established by the appearance of the label name on the %PROCEDURE statement and terminated by the corresponding %END statement. The label name must be active if invoked from a nonpreprocessor statement.

Preprocessor label names can be activated and deactivated, but cannot be specified in a %DECLARE statement.

parameter-identifier

The name of a preprocessor identifier. Each identifier is a parameter of the procedure.

STATEMENT

A preprocessor procedure option. The STATEMENT option permits the use of a keyword argument list followed by an optional positional argument list in the preprocessor procedure invocation. The STATEMENT option returns strings that can be used as PL/I statements at run time.

RETURNS

A preprocessor procedure attribute. The RETURNS attribute defines the data type to be returned to the point of invocation in the source code. If you specify a data type that is inconsistent with the returned value, a conversion error may result.

preprocessor-expression

Value to be returned to the invoking source code. You must specify the preprocessor expression. The preprocessor expression is converted to the data type specified in the RETURNS option and is returned to the point of invocation. Therefore, the expression must be capable of being converted to CHARACTER(32500), FIXED(10), or BIT(31).

The %PROCEDURE statement defines the beginning of a preprocessor procedure block and specifies the parameters, if any, of the procedure. Because 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.

For example:

%A_VAR = A_PROC();

 

In this statement, the preprocessor procedure A_PROC is invoked and evaluated, and the result is returned and assigned to the preprocessor variable A_VAR.

As with other PL/I procedures, a parenthesized parameter list specifies the parameters that the preprocessor procedure expects when it is invoked. Each preprocessor parameter specifies the name of a variable declared in the preprocessor procedure. The preprocessor parameters must correspond one-to-one with arguments specified for the preprocessor procedure when it is invoked, except when the STATEMENT option is used.

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

Preprocessor procedures cannot be nested. The scope of a preprocessor procedure is the procedure itself; that is, variables, labels, and any %GOTO statements used inside of the procedure must be local.

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. You can invoke preprocessor procedures recursively.

When a preprocessor procedure (with or without the STATEMENT option) is invoked from a preprocessor statement, each argument is treated as an expression and the result of executing the preprocessor procedure is returned to the statement containing the invocation.

When a preprocessor procedure is invoked from nonpreprocessor source text, the arguments are interpreted as character strings and are delimited by the appearance of a comma or a right parenthesis occurring outside of balanced parentheses. For example, the positional argument list (Q(E,D), XYZ) has two arguments; the strings `Q(E,D)' and `XYZ'.

Examples

%A1: PROCEDURE RETURNS(FIXED);

DECLARE (A,B,C) FIXED;

A = 2;

B = 10;

C = A + B;

RETURN(C);

END;

 

This example declares the preprocessor procedure A1 and specifies that the procedure return a fixed decimal result after the preprocessor statements within the procedure have been executed.

The procedure returns the value 12 to the point of invocation. Note that the leading percent signs, normally associated with preprocessor statements, are not required within a preprocessor procedure.

PPFIB: PROCEDURE OPTIONS (MAIN);

DECLARE Y CHAR(14) INITIAL('Fibonacci Test');

%DECLARE Y FIXED; À

%F: PROCEDURE(X) RETURNS (FIXED); Ã

DECLARE X FIXED;

IF (X <= 1)

THEN RETURN(1);

ELSE RETURN(F(X-1)+F(X-2));

END; /* End preprocessor procedure */

%Y = F(10); Õ

PUT SKIP LIST(Y);

%Y = F(11);

PUT SKIP LIST(Y);

%Y = F(12);

PUT SKIP LIST(Y);

%DEACTIVATE Y; -

PUT SKIP LIST(Y); --

END; /* End run-time procedure */

 

This example uses a preprocessor procedure to return a Fibonacci number. The recursive preprocessor procedure labeled %F is invoked to return a single value, a Fibonacci number, to the point of invocation. The following notes correspond to the example:

The run-time variable Y is declared with the CHARACTER attribute and initialized to Fibonacci Test.

The preprocessor variable Y is declared with the FIXED attribute, which implies FIXED DECIMAL (10,0). This declaration automatically activates the preprocessor variable Y.

The preprocessor procedure F is defined. The percent sign for the END statement is optional in a preprocessor procedure.

Note that this procedure is recursive.

The preprocessor procedure is called, passed the value 10, and the 10th number in the Fibonacci series is calculated. The resulting value is assigned to the preprocessor variable Y.

Because the preprocessor variable Y is active by default, the compiler replaces the occurrence of Y in the PUT statement with the new preprocessor Y value.

Step 4 is repeated for the value 11.

Step 4 is repeated for the value 12.

The preprocessor variable Y is deactivated. No more scanning or replacement occurs. The preprocessor variable Y retains its final replacement value, 233.

The run-time value of Y (Fibonacci Test) is output.

The output from this program is:

89

144

233

Fibonacci Test

 

Using the STATEMENT Option

All preprocessor procedures (with or without the STATEMENT option) return a value to the invoking source code; that is, they are function procedures. Through the use of the STATEMENT option, the argument list to a preprocessor procedure can be a keyword argument list. Keyword argument lists are unique to preprocessor procedures and provide a powerful tool for manipulating PL/I.

A keyword argument list ends with a semicolon rather than the right parenthesis. In this way, the STATEMENT option permits you to use a preprocessor procedure as if it were a statement. Consequently, preprocessor procedures using the STATEMENT option let you extend the PL/I language by simulating features that may not otherwise be available.

Preprocessor procedures can have one of two distinctly different types of argument lists: positional or keyword. Positional argument lists (ending with a right parenthesis) use parameters sequentially, as in a parenthesized list. You can use positional argument lists in any preprocessor procedure. Keyword argument lists (ending with a semicolon) use parameters in any order, as long as each keyword matches the name of a parameter. This permits the option of specifying the order in which parameters are passed. You can use keyword argument lists only when the preprocessor procedure contains the STATEMENT option and is invoked from a nonpreprocessor statement.

When a preprocessor procedure is invoked from a nonpreprocessor statement, the STATEMENT option permits the use of a keyword argument list that follows the optional positional argument list in a preprocessor procedure invocation.

When you use keyword arguments in nonpreprocessor statements, the keywords can be used in any order. The following reference examples would produce a variety of results with positional arguments, because values would be used sequentially. Keyword arguments produce consistent results because keyword parameters are matched with keyword arguments.

%B: PROCEDURE (ALPHA, BETA, GAMMA) STATEMENT ...;

DECLARE (ALPHA, BETA, GAMMA) FIXED;

END;

 

B(1,2,3);

B ALPHA(1) GAMMA(3) BETA(2);

B(1) GAMMA(3) BETA(2);

B (,2,3) ALPHA(1);

 

The next example shows a more common use of the STATEMENT option; to generate PL/I source statements that define a unique run time feature. The preprocessor procedure APPEND returns a string, which is incorporated into the source program at compile time. At run time, the returned string is used as a PL/I function.

This preprocessor procedure permits a varying string to accumulate text up to its maximum size without danger of undetected truncation. Normally, strings that exceed their maximum size are truncated. The text returned by the preprocessor procedure provides the run-time program with a way to handle truncation. If the string would be truncated, a message is printed and the FINISH condition is signaled.

%APPEND: PROCEDURE (string,to) STATEMENT

RETURNS(CHARACTER);

 

%DECLARE (string,to) CHARACTER; À

%RETURN ( Ã

'IF LENGTH('||string||')+LENGTH('||to||') > SIZE('||to||')-2'||

' THEN DO;'||

'PUT SKIP LIST

(''Buffer overflowed appending to '||to||''');'||

'SIGNAL FINISH;'|| Õ

'END;'||

'ELSE '||to||' = '||to||'||'||string||';'||

'END;'

);

 

%END;

 

The following notes are keyed to this example:

The preprocessor procedure APPEND is defined with the parameters `string' and `to' and the STATEMENT option.

`String' and `to' are declared as parameters within the preprocessor procedure.

The %RETURN statement returns the value contained by the parentheses. This text then becomes part of the PL/I nonpreprocessor source program.

Notice the punctuation within the character string returned by %RETURN. At compile time, single quotes are stripped when the text is incorporated into the run-time PL/I program. In addition, the semicolon that delimits the invocation is not retained when the replacement takes place. All customary PL/I punctuation must be included in the character string.

If the current varying string and the additional string together are greater than the maximum length of the varying string, an informational message is printed and the FINISH condition is signaled.

The following invocations of the preprocessor procedure APPEND are all equivalent:

APPEND STRING('New String') TO (My_string);

APPEND TO(My_string) STRING('New String');

APPEND('New String') TO(My_string);

 

Notice that if you have a preprocessor procedure (A) with a label that is the same as the name of a keyword argument in another preprocessor procedure (B) with the STATEMENT option, then when B is invoked the keyword argument is treated as a call to procedure A, and not as a keyword parameter in B.

%REPLACE Statement

The preprocessor %REPLACE statement specifies that an identifier is a constant of a given value. It can be used anywhere within a procedure or anywhere in a PL/I source file.

Beginning at the point at which a %REPLACE statement is encountered, PL/I replaces all occurrences of the specified identifier with the specified constant value, until the end of compilation.

The format of the %REPLACE statement is:

%REPLACE identifier BY constant-value;

 
identifier

Any valid PL/I identifier. PL/I keywords are not valid identifiers in a %REPLACE statement. The identifier must not be the name of a declared preprocessor or program variable. PL/I permits multiple %REPLACE statements and %REPLACE statements that redefine the %REPLACE identifier.

constant-value

Any valid character-string, bit-string, or arithmetic constant.

Integer constants that are given values by %REPLACE statements are valid in constant expressions. For example:

%REPLACE PREFIX BY 8;

 

DECLARE BUFFER CHARACTER( 80 + PREFIX);

 

When the program containing these lines is compiled, the variable BUFFER is declared with a length of 88 characters.

%RETURN Statement

The %RETURN statement terminates execution of the current preprocessor procedure.

The format of the %RETURN statement is:

[%]RETURN (preprocessor-expression);

 
preprocessor-expression

Value to be returned to the invoking procedure. The preprocessor expression must be specified. The preprocessor expression is converted to the data type specified in the RETURNS option, and the value of the expression is returned to the point of invocation. Therefore, the expression must be capable of being converted to CHARACTER (32500) VARYING, FIXED (10), or BIT (31).

The value returned by a preprocessor procedure cannot contain preprocessor statements.

When the value of the evaluated preprocessor expression is passed back to the point of invocation, control returns to the evaluation of the statement that contained the reference to the preprocessor procedure.

Within a preprocessor procedure, the leading percent sign (%) is optional.

Multiple %RETURN statements are permitted in preprocessor procedures. See See %PROCEDURE for examples of %RETURN.

%WARN

The %WARN statement provides a diagnostic warning message during program compilation.

The format of the %WARN statement is:

%WARN preprocessor-expression;

 
preprocessor-expression

The text of the warning message to be displayed. The text is a character string with a maximum length of 60 characters. It is truncated if necessary.

Returned Message

The message displayed by %WARN is:

%PLICOM-W-USERDIAG, preprocessor-expression

 

The %WARN statement increments the warning diagnostic count displayed in the compilation summary.

User-Generated Diagnostic Messages

The PL/I embedded preprocessor provides four statements that permit user-generated diagnostic capability: %INFORM, %WARN, %ERROR, and %FATAL. Preprocessor diagnostic messages are compile-time messages, but you define the circumstances that invoke the message and the text displayed.

The action of each statement is to generate a diagnostic message of the appropriate severity level, with the preprocessor expression as the text of the message.

Examples

The first example shows how %INFORM can be used to return the value of VARIANT.

%IF VARIANT() = ''| VARIANT() = 'NORMAL'

%THEN

%INFORM 'NORMAL';

 

In this example, the %INFORM diagnostic message is used to let the programmer know that compilation is continuing according to a normal plan.

If the value of VARIANT is not specified at compile time or if the value is `NORMAL', then the following informational message is issued:

%PLICOM-I-USERDIAG, NORMAL

 

In the following example, an unknown variant is included at compile time. The %WARN statement issues a compile-time warning diagnostic message and saves the message so that when the program is run, the appropriate text is output by the program.

DECLARE INIT_MESSAGE CHAR(40) VARYING INITIAL (T);

%IF VARIANT() = 'NONE';

%THEN %;

%ELSE

%DO;

%T = '''unknown variant''';

%WARN T;

INIT_MESSAGE = 'Compiled with '||T;

%END;

 

PUT SKIP LIST (INIT_MESSAGE);

 

The preprocessor built-in functions INFORM, WARN, and ERROR return the number of user-generated diagnostics issued at any specified point during compilation. Therefore, you can use user-generated diagnostics to control the course of compilation. For example:

%IF WARN() > 5

%THEN

%GOTO change_text;

%ELSE;

 

This example specifies that compilation take a different course if there are more than five warning messages at that point in program compilation. If there are fewer than five warnings, then compilation proceeds along the current path.

%IF ERROR() >= 1

%THEN

%FATAL 'Ending Compilation';

 

This example stops compilation if there is an error that would inhibit the production of an object file.

User-generated diagnostic messages increment the count displayed in the diagnostic summary.

Preprocessor Built-In Functions

A number of PL/I built-in functions are available for use at compile time. Since preprocessor built-in functions work the same way as run-time PL/I built-in functions, refer to See , See Built-In Functions, Subroutines, and Pseudovariables for detailed descriptions of the functions.

The built-in functions are summarized in See . Summary of PL/I Preprocessor Built-In Functions according to the following functional categories:

 

Built-In Functions, Subroutines, and Pseudovariables

Kednos PL/I for UNIX provides a set of predefined functions, subroutines, and variables called built-in functions, built-in subroutines, and pseudovariables respectively.

This chapter describes the built-in functions, subroutines, and pseudovariables that you can use in your PL/I programs.

Built-In Function Arguments

Built-in functions are similar to operators, and their arguments are similar to operands. Built-in function arguments, if arithmetic, are converted to their derived type before the function reference is evaluated. All evaluations of built-in functions are performed in the result type. The arguments are converted again from the derived type to the result type if necessary. The precision of the result is the greater of the precisions of the two arguments.

For instance, all the mathematical functions return floating-point values; their arguments are converted to floating point (binary or decimal, depending on the base of the argument) before the operation is performed. For example:

DCL J FIXED BINARY(8); FT = ATAN(J,2);

 

Here the derived type of J and 2 is fixed-point binary. The converted precision of 2 is min(ceil(1/3.32)+1,31), or 2. The result type is FLOAT BINARY(8). Both arguments are then converted to FLOAT BINARY(8), and the ATAN operation is performed.

Note the following restrictions on built-in function arguments:

Conditions Signaled

Built-in functions, like other operations, can signal conditions. The mathematical functions, which are computed in floating point, can signal OVERFLOW and UNDERFLOW under the appropriate conditions. Functions that are computed in fixed point can signal FIXEDOVERFLOW. In general, string and other functions signal ERROR if a result cannot be computed. Refer to See Condition Handling for more information.

Summary of Built-In Functions

The built-in functions are summarized in See . Summary of PL/I Built-In Functions , according to the following categories:

See Descriptions of Built-In Functions provides detailed descriptions of the functions listed in See . Summary of PL/I Built-In Functions .

The abbreviations in the dialect column in See . Summary of PL/I Built-In Functions are a for ansi, d for dec, and i for ibm dialect.

. Summary of PL/I Built-In Functions

Category

Function Reference

Value Returned

Dialect

Arithmetic

ABS(x)

Absolute value of x

a,d,i

 

ADD(x,y,p[,q])

Value of x+y, with precision p and scale factor q

a,d,i

 

CEIL(x)

Smallest integer greater than or equal to x

a.d.i

 

DIVIDE(x,y,p[,q])

Value of x divided by y, with precision p and scale factor q

a,d,i

 

FLOOR(x)

Largest integer that is less than or equal to x

a,d,i

 

MAX(x,y)

Larger of the values x and y

a,d,i

 

MIN(x,y)

Smaller of the values x and y

a,d,i

 

MOD(x,y)

Value of x modulo y

a,d,i

 

MULTIPLY(x,y,p[,q])

Value of x*y, with precision p and scale factor q

a,d,i

 

PRECISION(x,p[,q])

Value of x, with precision p and optional scale factor q

i

 

ROUND(x,k)

Value of x rounded to k digits

a,d,i

 

SIGN(x)

-1, 0, or 1 to indicate the sign of x

a,d,i

 

SUBTRACT(x,y,p[,q])

Value of x-y, with precision p and scale factor q

a,d

 

TRUNC(x)

Integer portion of x

a,d,i

Mathematical

ACOS(x)

Arc cosine of x (angle, in radians, whose cosine is x)

a,d,i

 

ASIN(x)

Arc sine of x (angle, in radians, whose sine is x)

a,d,i

 

ATAN(x)

Arc tangent of x (the angle, in radians, whose tangent is x)

a,d,i

 

ATAN(x,y)

Arc tangent of x (the angle, in radians, whose sine is x and whose cosine is y)

a,d,i

 

ATAND(x)

Arc tangent of x (the angle, in degrees, whose tangent is x)

a,d,i

 

ATAND(x,y)

Arc tangent of x (the angle, in degrees, whose sine is x and whose cosine is y)

a,d,i

 

ATANH(x)

Hyperbolic arc tangent of x

a,d,i

 

COS(x)

Cosine of radian angle x

a,d,i

 

COSD(x)

Cosine of degree angle x

a,d,i

 

COSH(x)

Hyperbolic cosine of x

a,d,i

 

ERF(x)

Error function of x

i

 

ERFC(x)

Complement of the error function of x

i

 

EXP(x)

Base of the natural logarithm, e, to the power x

a,d,i

 

LOG(x)

Logarithm of x to the base e

a,d,i

 

LOG10(x)

Logarithm of x to the base 10

a,d,i

 

LOG2(x)

Logarithm of x to the base 2

a,d,i

 

SIN(x)

Sine of the radian angle x

a,d,i

 

SIND(x)

Sine of the degree angle x

a,d,i

 

SINH(x)

Hyperbolic sine of x

a,d,i

 

SQRT(x)

Square root of x

a,d,i

 

TAN(x)

Tangent of the radian angle x

a,d,i

 

TAND(x)

Tangent of the degree angle x

a,d,i

 

TANH(x)

Hyperbolic tangent of x

a,d,i

String-
Handling

BOOL(x,y,z)

Result of Boolean operation z performed on x and y

a,d,i

 

COLLATE()

ASCII character set

a,d,i

 

COPY(s,c)

c copies of specified string, s

a,d

 

EVERY(s)

Boolean value indicating whether every bit in bit string s is '1'B

a,d

 

HIGH(c)

String of length c of repeated occurrences of the highest character in the collating sequence

a,d,i

 

INDEX(s,c[,p])

Position of the character string c within the string s, starting at position p

a,d,i

 

LENGTH(s)

Number of characters or bits in the string s

a,d,i

 

LOW(c)

String of length c of repeated occurrences of the lowest character in the collating sequence

a,d,i

 

MAXLENGTH(s)

Maximum length of varying string s

a,d

 

REPEAT(x,y)

x concatenated to itself y times

i

 

REVERSE(s)

Reverse of the source character string or bit string

a,d

 

SEARCH(s,c[,p])

Position of the first character in s, starting at position p, that is found in c

a,d

 

SOME(s)

Boolean value indicating whether at least one bit in bit string s is '1'B

a,d

 

STRING(s)

Concatenation of values in array or structure s

a,d,i

 

SUBSTR(s,i[,j])

Part of string s beginning at i for j characters

a,d,i

 

TRANSLATE(s,c[,d])

String s with substitutions defined in c and d

a,d,i

 

TRIM(s[,e,f])

String s with all characters in e removed from the left, and all characters in f removed from the right. If you omit either e or f or both, blanks are removed from that side.

a,d

 

VERIFY(s,c[,p])

Position of the first character in s, starting at position p, which is not found in c

a,d,i

Conversion

BINARY(x[,p[,q]])

Binary value of x with precision p and scale factor q

a,d,i

 

BIT(s[,l])

Value of s converted to a bit string of length l

a,d,i

 

BYTE(x)

ASCII character represented by the integer x

a,d

 

CHARACTER(s[,l])

Value of s converted to a character string of length l

a,d,i

 

DECIMAL(x[,p[,q]])

Decimal value of x

a,d,i

 

DECODE(c,r)

Fixed binary value of the character string c converted to a base r number

a,d

 

ENCODE(i,r)

Character string representing the base r number that is equivalent to the fixed binary expression i

a,d

 

FIXED(x,p[,q])

Fixed arithmetic value of x

a,d,i

 

FLOAT(x,p)

Floating arithmetic value of x

a,d,i

 

INT(x[,p[,l]])

Signed integer value of variable x, located at position p with length l

a,d

 

POSINT(x[,p[,l]])

Unsigned integer value of variable x, located at position p with length l

a,d

 

RANK(c)

Integer representation of the ASCII character c

a,d

 

UNSPEC(x[,p[,l]])

Internal coded form of x, located at position p with length l

a,d,i

Condition-
Handling

ONCHAR()

Character that caused the CONVERSION condition to be raised

a,d,i

 

ONCODE()

Error code of the most recent run-time error

a,d,i

 

ONFILE()

Name of file constant for which the most recent ENDFILE, ENDPAGE, KEY, or UNDEFINEDFILE condition was signaled

a,d,i

 

ONKEY()

Value of key that caused KEY condition

a,d,i

 

ONLOC

Name of the entry point used for the invocation of the procedure where the condition was signaled

i

 

ONSOURCE()

Field containing the ONCHAR character when the CONVERSION condition was raised

a,d,i

Array-
Handling

ALL(x)

Boolean AND of all array elements

i

ANY(x)

Boolean OR of all array elements

i

DIMENSION(x[,n])

Extent of the nth dimension of x

a,d,i

HBOUND(x[,n])

Higher bound of the nth dimension of x

a,d,i

LBOUND(x[,n])

Lower bound of the nth dimension of x

a,d,i

PROD(x)

Arithmetic product of all the elements in x

a,d,i

SUM(x)

Arithmetic sum of all the elements in x

a,d,i

Storage

ADDR(x)

Pointer identifying the storage referenced by x

a,d,i

 

ALLOCATION(x)

Number of existing generations for controlled variable x

a,d,i

 

BYTESIZE(x)

Number of bytes allocated to variable x; same as SIZE function

a,d

 

CURRENTSTORAGE(x)

Number of bytes allocated to variable x, precision fixed bin(15)

i

 

EMPTY()

An empty area value

a,d,i

 

NULL()

A null pointer value

a,d,i

 

POINTER(o,a)

A pointer to the location at offset o within area a

a,d,i

 

SIZE(x)

Number of bytes allocated to variable x, precision fixed bin(31)

a,d

 

STORAGE(x)

Number of bytes allocated to variable x, precision fixed bin(31)

i

Timekeeping

DATE()

System date in the form YYMMDD

a,d,i

DATETIME()

System date and time in the form CCYYMMDDHHMMSSXX

a,d

TIME()

System time of day in the form HHMMSSXX

a,d,i

File Control

LINENO(x)

Line number of the print file identified by x

a,d,i

PAGENO(x)

Page number of the print file identified by x

a,d,i

Misc.

PLIRETV

PL/I return code, precision fixed bin(15)

i

Preprocessor

ABS(x)

Absolute value of x

a,d,i

 

BYTE(x)

ASCII character represented by integer x

a,d,i

 

COPY(s,c)

c copies of specified string s

a,d,i

 

DATE()

Compilation date in the form YYMMDD

a,d,i

 

DATETIME()

System date and time in the form CCYYMMDDHHMMSSXX

a,d,i

 

DECODE(c,r)

Fixed binary value of the character string c converted to a base r number

a,d,i

 

ENCODE(i,r)

Character string representing the base r number that is equivalent to the fixed binary expression i

a,d,i

 

ERROR()

Count of user-generated diagnostic error messages

a,d,i

 

INDEX(s,c[,p])

Position of the character string c within the string s, starting at position p

a,d,i

 

INFORM()

Count of user-generated diagnostic informational messages

a,d,i

 

LENGTH(s)

Number of characters or bits in the string s

a,d,i

 

LINE()

Line number in source program that contains the end of the specified preprocessor statement

a,d,i

 

MAX(x,y)

Larger of the values x and y

a,d,i

 

MIN(x,y)

Smaller of the values x and y

a,d,i

 

MOD(x,y)

Value of x modulo y

a,d,i

 

RANK(c)

Integer representation of the ASCII character c

a,d,i

 

REVERSE(s)

Reverse of the source character string or bit string

a,d,i

 

SEARCH(s,c[,p])

Position of the first character in s, starting at position p, that is found in c

a,d,i

 

SIGN(x)

-1,0, or 1 to indicate the sign of x

a,d,i

 

SUBSTR(s,i[,j])

Part of string s beginning at i for j characters

a,d,i

 

TIME()

Compilation time of the day in the form HHMMSSXX

a,d,i

 

TRANSLATE(s,c[,d])

String s with substitutions defined in c and d

a,d,i

 

TRIM(s[,e,f])

String s with all characters in e removed from the left and all characters in f removed from the right If you omit either e or f or both, blanks are removed from that side

a,d,i

 

VARIANT()

String result representing the value of -T variant command option

a,d,i

 

VERIFY(s,c[,p])

Position of the first character in s, starting at position p, which is not found in c

a,d,i

 

WARN()

Count of user-generated diagnostic warning messages

a,d,i

Descriptions of Built-In Functions

This section presents the built-in functions in alphabetical order.

ABS

Dialects - ansi, dec, ibm

The ABS built-in function returns the absolute value of an arithmetic expression x. Its format is:

ABS(x)

 
Examples

A = 3.567;

Y = ABS(A); /* Y = +3.567 */

A = -3.567;

Y = ABS(A); /* Y = +3.567 */

ROOT = SQRT (ABS(TEMP));

 

The last example shows a common use for the ABS built-in function: to ensure that an expression has a positive value before it is used as an argument to the square root (SQRT) built-in function.

ACOS

Dialects - ansi, dec, ibm

The ACOS built-in function returns a floating-point value that is the arc (inverse) cosine of an arithmetic expression x. The arc cosine is computed in floating point. The returned value is an angle w such that:

0 < = w <=p

The absolute value of x, after its conversion to floating point, must be less than or equal to 1. The format of the function is:

ACOS(x)

 

ADD

Dialects - ansi, dec, ibm

The ADD built-in function returns the sum of two arithmetic expressions x and y, with a specified precision p and an optionally specified scale factor q. The format of the function is:

ADD(x,y,p[,q])

 
p

An unsigned integer constant greater than zero and less than or equal to the maximum precision of the result type, which is 31for fixed-point data, 15 for floating-point decimal data, and 53 for floating-point binary data.

q

An integer constant less than or equal to the specified precision. The scale factor can be optionally signed when used in fixed-point binary addition. The scale factor for fixed-point binary must be in the range -31 to p. The scale factor for fixed-point decimal data must be in the range 0 to p. If you omit q, the default value is zero. Do not use a scale factor for floating-point arithmetic.

Expressions x and y are converted to their derived type before the addition is performed. For example:

ADDBIF: PROCEDURE OPTIONS (MAIN);

DECLARE X FIXED DECIMAL (8,3),

Y FIXED DECIMAL (8,3),

Z FIXED DECIMAL (9,3);

 

X=9500.374;

Y=2278.897;

Z = ADD (X,Y,9,3);

PUT SKIP LIST ('TOTAL =',Z);

END;

 

This program prints the following:

TOTAL = 11779.271

 

ADDR

Dialects - ansi, dec, ibm

The ADDR built-in function returns a pointer to storage denoted by a specified variable. The variable reference must be addressable. The format of the function is:

ADDR(reference)

 

If the reference is to a parameter (or any element or member of a parameter), the pointer value obtained must not be used after return from the parameter's procedure invocation. (This could occur, for example, if the pointer were saved in a static variable or returned as a function value.)

ALL

Dialects - ibm

The ALL built-in function takes an array as an argument and returns a bit string the length of the longest element of the referenced array. The returned string contains a one in every position where the equivalent positions in all the elements of the array exist and are ones. The format of the ALL built-in function is:

ALL(array-variable)

 

ALLOCATION

Dialects - ansi, dec, ibm

The ALLOCATION built-in function returns a fixed-point binary integer that is the number of existing generations of a specified controlled variable. If no generations of the specified variable exist, the function returns zero. The format of the function is:

reference

The name of a controlled variable.

Examples

DECLARE INPUT CHARACTER(10) CONTROLLED,

A CHARACTER(3) VARYING;

 

DO UNTIL (INPUT = 'QUIT');

ALLOCATE INPUT;

GET LIST(INPUT);

END;

A = ALLOCATION(INPUT);

PUT SKIP LIST('Generations = ';A);

 

This example uses the ALLOCATION built-in function to return the number of generations of the controlled variable INPUT. The example illustrates how input in an interactive program can be stored on a stack for future use.

ANY

Dialects - ibm

The ANY built-in function takes an array as an argument and returns a bit string the length of the longest element of the referenced array. The returned string contains a one in every position where the equivalent positions in any of the elements of the array exist and is a one. The format of the ANY built-in function is:

ANY(array-variable)

 

ASIN

Dialects - ansi, dec, ibm

The ASIN built-in function returns a floating-point value that is the arc (inverse) sine of an arithmetic expression x. The arc sine is computed in floating point. The returned value is an angle w such that:

-p/2 < = w<= p/2

The absolute value of x, after its conversion to floating point, must be less than or equal to 1. The format of the function is:

ASIN(x)

 

ATAN

Dialects - ansi, dec, ibm

The ATAN built-in function returns a floating-point value that is the arc tangent of an arithmetic expression y or an arc tangent computed from two arithmetic expressions y and x. The arc tangent is computed in floating point. If two arguments are supplied, they must both have nonzero values after they have been converted to floating point.

The format of the function is:

ATAN(y[,x])

 

Returned Values

The returned value represents an angle in radians.

If x is omitted, the returned value v equals arc tangent(s), such that:

-p/2 < v< p/2

Here, s is the value of expression y after its conversion to floating point.

If x is present, the returned value v equals arc tangent(s/r), such that if s >= 0 then 0 <= v <= p and if s < 0 then -p < v <  0, where s and r are, respectively, the values of expressions y and x after their conversion to floating point.

ATAND

Dialects - ansi, dec, ibm

The ATAND built-in function returns a floating-point value that is the arc tangent of a single arithmetic expression y or an arc tangent computed from two arithmetic expressions y and x. The arc tangent is computed in floating point. If two arguments are supplied, they must both have nonzero values after their conversion to floating point.

The format of the function is:

ATAND(y[,x])

 
Returned Value

The floating-point value returned (which represents an angle in degrees) equals:

ATAN(y,x)*180/p

ATANH

Dialects - ansi, dec, ibm

The ATANH built-in function returns a floating-point value that is the inverse hyperbolic tangent of an arithmetic expression x. After its conversion to floating point, the absolute value of the argument x must be less than 1.

The format of the function is:

ATANH(x)

 

BINARY

Dialects - ansi, dec, ibm

The BINARY built-in function converts an arithmetic or string expression x to its binary representation, with an optionally specified precision p and scale factor q. The returned value is either fixed- or floating-point binary, depending on whether x is a fixed- or floating-point expression.

The format of the function is:

p

The precision p, if specified, must be an integer constant greater than zero and less than or equal to the maximum precision of the result type -- 31if fixed-point binary and 53 if floating-point binary.

The precision p must be specified if x is a fixed-point value with fractional digits.

q

The scale factor q, if specified, must be an integer constant less than or equal to the specified precision and in the range -31 to 31.

Returned Value

The result type is fixed- or floating-point binary, depending on whether the argument x is a fixed- or floating-point expression. (If the argument is a bit- or character-string expression, the result type is fixed-point binary.)

The argument x is converted to the result type, giving a value v, following the PL/I rules for conversion.

The returned value is the value v, with precision p, and scale factor q. If p is omitted (integer and floating-point arguments only), the precision of the returned value is the converted precision of x. FIXEDOVERFLOW, OVERFLOW, or UNDERFLOW is signaled if appropriate.

BIT

Dialects - ansi, dec, ibm

The BIT built-in function converts an arithmetic or string expression x to a bit string of an optionally specified length. If x is a string expression, it must consist of 0s and 1s. If the length is specified, it must be a nonnegative integer. If the length is omitted, the returned value has a length determined by the PL/I rules for conversion to bit strings.

The format of the function is:

BIT(x[,length])

 

BOOL

Dialects - ansi, dec, ibm

The BOOL built-in function performs a Boolean operation on two bit-string arguments and returns the result as a bit string with the length of the longer argument.

The format of the function is:

BOOL(string-1,string-2,operation-string)

 
string-1

A bit-string expression of any length.

string-2

A bit-string expression of any length.

operation-string

A bit-string expression that is converted to length 4. Each bit in the operation string specifies the result of comparing two corresponding bits in string-1 and string-2. Specify bit positions in the operation string from left to right to define the operation, as in the following truth table:

String-1 Bit

String-2 Bit

Result of Boolean Operation

0

0

Bit 1 of operation string

0

1

Bit 2 of operation string

1

0

Bit 3 of operation string

1

1

Bit 4 of operation string

Thus, an AND operation, for instance, would be specified by the operation-string '0001'B.

If string-1 and string-2 are of different lengths, the shorter is extended on the right with zeros to the length of the longer.

Examples

X = '101010'B;

Y = '110011'B;

CHECK = BOOL (X,Y,'0110'B);

 

The operation string is '0110'B, which defines an EXCLUSIVE OR operation. The operation is performed as follows on the corresponding bits in the strings X and Y: The leftmost bit in X is 1 and the leftmost bit in Y is 1. The truth table above specifies that when the two corresponding bits in the two strings are both 1, then bit 4 of the operation string will be the result; in this case, bit 4 of the operation string '0110'B is 0. Thus, 0 is the first bit of the value to be returned. The second bit of X is 0 and of Y is 1. The truth table specifies that when the bit in the first string is 0 and in the second string is 1, the result will be bit 2 of the operation string. Here, bit 2 of the operation string '0110'B is 1, and so 1 is the second bit of the value to be returned. The operation continues in this manner with each two corresponding bits in the strings. The value returned is '011001'B.

See . Example of the BOOL Built-In Function illustrates this example.

. Example of the BOOL Built-In Function

BYTE

Dialects - ansi, dec

The BYTE built-in function returns the ASCII character whose ASCII code is the integer x; x must not be negative. The returned value is a character equivalent to BYTE(y), where y equals x modulo 256. The format of the function is:

BYTE(x)

 
Examples

DECLARE CHAR CHARACTER(1);

CHAR = BYTE(65); /* CHAR = 'A' */

CHAR = BYTE(32); /* CHAR = ' ' (space) */

 

BYTESIZE

Dialects - ansi, dec

This function is the same as the SIZE function. See See SIZE .

CEIL

Dialects - ansi, dec, ibm

The CEIL function returns the smallest integer that is greater than or equal to an arithmetic expression x. Its format is:

CEIL(x)

 
Returned Value

If x is a floating-point expression, a floating-point value is returned with the same precision as x. If x is a fixed-point expression, the returned value is a fixed-point value of the same base as x and with:

precision = min(31,p -q + 1)

scale factor = 0

Here, p and q are the precision and scale factor of x.

Examples

A = 4.3;

Y = CEIL(A); /* Y = 5 */

A = -4.3;

Y = CEIL(A); /* Y = -4 */

 

CHARACTER

Dialects - ansi, dec, ibm

The CHARACTER built-in function converts an arithmetic or string expression x to a character string of an optionally specified length. If the length is specified, it must be a nonnegative integer. If the length is omitted, the length of the returned value is determined by the PL/I rules for conversion to character strings. The format of the function is:

Examples

CHAR: PROCEDURE OPTIONS(MAIN);

 

DECLARE EXPRES FIXED DECIMAL(7,5);

DECLARE OUTPUT PRINT FILE;

 

EXPRES = 12.34567;

 

OPEN FILE(OUTPUT) TITLE('CHAR2.OUT');

 

PUT SKIP FILE(OUTPUT)

LIST('No length argument: ',CHARACTER(EXPRES));

PUT SKIP FILE(OUTPUT)

LIST('Length = 4: ',CHARACTER(EXPRES,4));

 

END CHAR;

 

The program CHAR produces the following output:

No length argument: 12.34567

Length = 4: 12

 

In the first PUT LIST statement, CHARACTER has only one argument, so the entire string is written out. The string '12.34567' is actually preceded by two spaces; this is the case with any nonnegative number converted to a character string. In the second PUT LIST statement, CHARACTER has a length argument of 4, so the first four characters of the converted string are written out as ' 12'.

COLLATE

Dialects - ansi, dec, ibm

The COLLATE built-in function returns a 256-character string consisting of the ASCII character set in ascending order. Its format is:

COLLATE()

 

COPY

Dialects - ansi, dec

The COPY built-in function copies a given string a specified number of times and concatenates the result into a single string. Its format is:

COPY(string,count)

 
string

Any bit- or character-string expression. If the expression is a bit string, the result is a bit string. Otherwise, the result is a character string.

count

Any expression that yields a nonnegative integer. The specified count controls the number of copies of the string that are concatenated, as follows:

Value of Count

String Returned

0

A null string

1

The string argument

n

Concatenated copies of the string argument

Examples

COPY('12',3)

 

This function reference returns the character-string value '121212'.

COS

Dialects - ansi, dec, ibm

The COS function returns a floating-point value that is the cosine of an arithmetic expression x, where x represents an angle in radians. The cosine is computed in floating point. The format of the function is:

COS(x)

 

COSD

Dialects - ansi, dec, ibm

The COSD built-in function returns a floating-point value that is the cosine of an arithmetic expression x, where x is an angle in degrees. The cosine is computed in floating point. The format of the function is:

COSD(x)

 

COSH

Dialects - ansi, dec, ibm

The COSH built-in function returns a floating-point value that is the hyperbolic cosine of an arithmetic expression x. The hyperbolic cosine is computed in floating point. The format of the function is:

COSH(x)

 

CURRENTSTORAGE

Dialects - ibm

The CURRENTSTORAGE built-in function returns a fixed binary (15) value that is the implementation-defined storage, in bytes, required by the specified variable. The format of the function is:

CURRENTSTORAGE(reference)

 

reference

The name of a variable known to this block except:

  • A variable that is not in connected storage.
  • An unaligned fixed-length BASED, DEFINED, subscripted, parameter, or structure element.
  • A minor structure with a first or last element that is an unaligned fixed-length bit string, unless that element is the first or last element of the containing major structure.
  • A major structure with the BASED, DEFINED, or parameter attribute with a first or last element that is an unaligned fixed-length bit string.
Returned Value

The returned value is a fixed bin(15) value containing the variable's actual storage size in bytes. This is the number of bytes that would be transmitted if you wrote the variable to a record file defined with the ENVIRONMENT(SCALARVARYING) option.

Some variables can have varying sizes. If the referenced variable is a varying-length string, the returned value includes the two bytes of storage allocated by PL/I to contain the current length of the string (the length-prefix) and the currently-used bytes. It does not include any unused bytes at the end of the string.

If the referenced variable is a scalar area, the returned value includes the storage used by the area control bytes and the current extent. It does not include any unused bytes at the end of the area.

However, if the referenced variable is an aggregate that contains areas or varying-length strings, the returned value includes the storage used by any control bytes and length prefixes plus the maximum lengths of the strings and the maximum sizes of the areas. This rule has one exception. If the referenced variable is a structure and the last element is a non-dimensioned area, the returned value contains only the current extent of that area, not the unused bytes at the end of the area.

DATE

Dialects - ansi, dec, ibm

The DATE built-in function returns a 6-character string in the form yymmdd, where:

yy

Is the current year (00-99)

mm

Is the current month (01-12)

dd

Is the current day of the month (01-31)

Its format is:

DATE()

 

The date returned is the run-time date. However, if DATE is used as a preprocessor built-in function, the date returned is the compile-time date.

DATETIME

Dialects - ansi, dec

The DATETIME built-in function returns a 16-character string in the form ccyymmddhhmmssxx, where:

cc

Is the current century (00-99)

yy

Is the current year (00-99)

mm

Is the current month (01-12)

dd

Is the current day of the month (01-31)

hh

Is the current hour (00-23)

mm

Is the minutes (00-59)

ss

Is the seconds (00-59)

xx

Is the hundredths of seconds (00-99)

The format of the function is:

DATETIME()

 

The date and time returned is the run-time date and time. However, if DATETIME is used as a preprocessor built-in function, the date and time returned is the compile-time date and time.

Note that the DATETIME function is identical to the century concatenated with DATE() and TIME().

DECIMAL

Dialects - ansi, dec, ibm

The DECIMAL built-in function converts an arithmetic or string expression x to a decimal value of an optionally specified precision p and scale factor q.

P and q, if specified, must be integer constants. P must be greater than zero and less than or equal to the maximum precision for the result type (31 for fixed-point, 34 for floating- point). If q is specified, x must be a fixed-point expression and p must also be specified; if q is omitted or has a negative value, the scale factor of the result is zero.

The format of the function is:

Returned Value

The result type is fixed-point or floating-point decimal, depending on whether x is a fixed- or floating-point expression. (If x is a bit- or character-string expression, the result type is fixed-point decimal.)

The expression x is converted to a value v of the result type, following the PL/I rules for conversion. The returned value is v with precision p and scale factor q. If p and q are omitted, they are the converted precision and scale factor of x. FIXEDOVERFLOW, UNDERFLOW, or OVERFLOW is signaled if appropriate.

DECODE

Dialects - ansi, dec

The DECODE built-in function converts a character string representing a number to a fixed binary number. It takes two arguments: a character string and an integer expression It converts the string to an unsigned, base r integer, where r is the specified radix. The function returns a FIXED BINARY(31,0) number representing the base ten equivalent of the string.

The format of the function is:

DECODE(character-expression,radix-expression)

 
character-expression

A character-string constant or variable whose component characters can be any of the digits from `0' through `9', from `a' through `f', and from `A' through `F'. The digits must be within the range of digits valid for the base specified in the radix-expression.

radix-expression

An expression evaluating to any integer from 2 through 16.

Examples

DECLARE (X,Y) FIXED BINARY;

X = DECODE('1010',2);

Y = DECODE('f0',16);

 

The fixed binary variables X and Y are given the values 10 and 240, respectively.

DIMENSION

Dialects - ansi, dec, ibm

The DIMENSION built-in function returns a fixed-point binary integer that is the number of elements in an array dimension. Its format is:

reference

A reference to an array variable.

dimension

An integer constant specifying the dimension of the array for which the extent is to be determined. If the dimension is not specified, the dimension parameter defaults to 1. Thus, DIMENSION(A) is equivalent to DIMENSION(A,1).

Examples

INIT: PROCEDURE (ARRAY);

DECLARE ARRAY(*) FIXED,

I FIXED;

 

DO I = 1 TO DIM(ARRAY);

ARRAY(I) = I;

END;

 

This procedure is passed a one-dimensional array of an unknown extent. The DIMENSION built-in function is used as the end value in a controlled DO statement. This DO-group assigns integral values to each element of the array ARRAY so that the first element has the value 1, the second element has the value 2, and so on to the last element of the array. (Because the array is one-dimensional, the optional second parameter is omitted and defaults to 1.)

DIVIDE

Dialects - ansi, dec, ibm

The DIVIDE built-in function divides an arithmetic expression x by an arithmetic expression y and returns the quotient with a specified precision p and an optionally specified scale factor q. The scale factor q must be an integer following these rules:

  • If either x or y is fixed binary, q must be in the range -31 through 31.
  • If both x and y are fixed decimal, q must not be negative.
  • If either x or y is floating point, q must be zero.
  • If q is omitted, it is assumed to be zero.

The expressions x and y are converted to their derived types before the division is performed. If y is zero after this conversion, the ZERODIVIDE condition is signaled. The quotient has the derived type of the two arguments.

The format of the function is:

DIVIDE(x,y,p[,q])

 

EMPTY

Dialects - ansi, dec, ibm

The EMPTY built-in function returns an empty area value for use in initializing areas. Its format is:

EMPTY()

 

The EMPTY built-in function is useful in initializing the contents of an area. Note that an area value must be assigned to an area before the area is used.

The following is an example of its use in a declaration:

DECLARE A AREA(1024) STATIC INITIAL(EMPTY());

 

ENCODE

Dialects - ansi, dec

The ENCODE built-in function converts a decimal integer to a character string. It converts the decimal integer (stored as a FIXED BINARY(31,0) number) to a base r number, where r is the radix you specify, and returns the resulting number as a character string. The function takes two arguments: a decimal integer and a radix; the radix is an integer in the range 2 through 16.

The format of the function is:

ENCODE(integer-expression,radix-expression)

 
integer-expression

An expression evaluating to a fixed binary number representing a decimal integer. Whether signed or not, this integer is treated by the function as unsigned.

radix-expression

An expression that evaluates to any integer from 2 through 16.

Examples

DECLARE (X,Y) CHARACTER(5) VARYING;

X = ENCODE(53,8);

Y = ENCODE(10,2);

 

The character-string variable X is assigned the value '65', which is the character equivalent of the octal number 65, which is the equivalent of the decimal number 53. The character-string variable Y is assigned the value '1010', which is the character equivalent of the binary number 1010, which is the equivalent of the decimal number 10.

ERF

Dialects - ibm

The ERF built-in function returns a floating-point value that is an approximation of the error function of x. The format of the function is:

ERF(real-expression)

 

The returned value has the base and precision of the real-expression, and the following value:

ERFC

Dialects - ibm

The ERFC built-in function returns a floating-point value that is an approximation of the complement of the error function of x. The format of the function is:

ERFC(real-expression)

 

The returned value has the base and precision of the real-expression, and the following value:

1 - ERF(real-expression)

 

ERROR

Dialects - ansi, dec

The ERROR preprocessor built-in function returns the number of preprocessor diagnostic error messages issued during compilation up to that particular point in the source program. The format for the ERROR built-in function is:

ERROR();

 

The function returns a fixed-point result representing the number of compile-time warning messages that were issued up until the point at which the built-in function was encountered.

EVERY

Dialects - ansi, dec

The EVERY built-in function determines whether every bit in a bit string is '1'B. In other words, it performs a logical AND operation on the elements of the bit string. The format of the function is:

EVERY(bit-string)

 

The function returns the value '1'B if all bits in the bit-string argument are '1'B. It returns '0'B if one or more bits in the argument are '0'B or if the argument is the null bit string.

EXP

Dialects - ansi, dec, ibm

The EXP built-in function returns a floating-point value that is the base e to the power of an arithmetic expression x. The computation is performed in floating point. The format of the function is:

EXP(x)

 

FIXED

Dialects - ansi, dec, ibm

The FIXED built-in function converts an arithmetic or string expression x to a fixed-point arithmetic value with a specified precision p and, optionally, a scale factor q.

The format of the function is:

FIXED(x,p[,q])

 
p

The number of bits used to represent the arithmetic value. The precision must be greater than zero and less than or equal to 31.

q

An integer in the range 0 through 31 for decimal data, and in the range -31 through 31 for binary data. If q is omitted, it is assumed to be zero. The scale factor q must be less than or equal to the specified precision.

Returned Value

The result type is fixed-point binary or decimal, depending on whether x is binary or decimal. (If x is a bit string, the result type is fixed-point binary; if x is a character string, the result type is fixed-point decimal.)

The expression x is converted to a value v of the result type, following the PL/I rules. The returned value is v with precision p and scale factor q. If q is omitted, the returned value has the converted precision of x and a scale factor of zero. FIXEDOVERFLOW is signaled if appropriate.

FLOAT

Dialects - ansi, dec, ibm

The FLOAT built-in function converts a string or arithmetic expression x to floating point, with a specified precision p. The precision p must be an integer constant that is greater than zero and less than or equal to the maximum precision of the result type, which is 15 for floating-point decimal data and 53 for floating-point binary data

If x is a character string, it can contain any series of characters that describes a valid arithmetic constant. That is, the character string can contain any of the numeric digits 0 through 9, a plus (+) or minus (-) sign, a decimal point (.), and the letter E. If the character string contains any invalid characters, the CONVERSION condition is signaled. The format of the FLOAT function is:

FLOAT(x,p)

Returned Value

The result type is floating-point binary or decimal, depending on whether x is a binary or decimal expression. (If x is a bit-string expression, the result type is floating-point binary; if x is a character-string expression, the result type is floating-point decimal.)

The expression x is converted to a value of the result type, following the PL/I conversion rules, and of the specified precision. UNDERFLOW or OVERFLOW is signaled if appropriate.

FLOOR

Dialects - ansi, dec, ibm

The FLOOR built-in function returns the largest integer that is less than or equal to an arithmetic expression x. The format is:

FLOOR(x)

 
Returned Value

If x is a floating-point expression, the returned value is a floating-point value. If x is a fixed-point expression, the returned value is a fixed-point value with the same base as x and with the following attributes:

precision = min(31,p - q + 1)

scale factor = 0

Here, p and q are the precision and scale factor of x.

For example:

FLOOR_DEMO: PROC OPTIONS(MAIN);

PUT LIST (FLOOR(3));

PUT LIST (FLOOR(-3.323));

PUT LIST (FLOOR(3.456E9));

END;

This program prints the following values:

3 -4 3.456E+09

 

HBOUND

Dialects - ansi, dec, ibm

The HBOUND built-in function returns a fixed-point binary integer that is the upper bound of an array dimension. The format is:

HBOUND(reference[,dimension])

 
reference

A reference to an array variable.

dimension

An integer constant indicating a dimension of the specified array. If the dimension is not specified, the dimension parameter defaults to 1. Thus, HBOUND(A) is equivalent to HBOUND(A,1).

HIGH

Dialects - ansi, dec, ibm

The HIGH built-in function returns a string of specified length that consists of repeated appearances of the highest character in the collating sequence. The format is:

HIGH(length)

 
length

The specified length of the returned string. The (maximum length of the returned string is 32767 characters.

Returned Value

The string returned is of the length specified. The rank of the highest character that can appear in the collating sequence for PL/I is ASCII DEL (value 255).

INDEX

Dialects - ansi, dec, ibm

The INDEX built-in function returns a fixed-point binary integer that indicates the position of the leftmost occurrence of a specified substring within a string. If the substring is not found, or if the length of either argument is zero, the INDEX function returns zero. This function is case-sensitive.

The format of the function is:

INDEX(string,substring[,starting-position])

 
string

The string to be searched for the given substring. It can be either a character-string or a bit-string expression.

substring

The substring to be located. It must have the same string data type as the string argument.

starting-position

A positive integer in the range 1 to n+1, where n is the length of the string. It specifies the leftmost position from which the search is to begin. (By default, the search begins at the left end of the string.)

Examples
  1. DECLARE RESULT FIXED BINARY(31);
    RESULT = INDEX ('ABCDEF','DEF');

RESULT is given the value 4 because the substring `DEF' begins at the fourth position in `ABCDEF'.

  1. RESULT = INDEX('SHARP FORTUNE','R');

RESULT is given the value 4 because the leftmost occurrence of `R' is at the fourth position in `SHARP FORTUNE'.

  1. RESULT = INDEX('SHARP FORTUNE','R',5);

The optional starting-position parameter specifies that the search begins at the fifth position of `SHARP FORTUNE'. Thus, RESULT is given the value 9: the first R is ignored, so the first recognized occurrence of `R' is found in the ninth position.

  1. RESULT = INDEX('0000101100001011','1011');

RESULT is given the value 5 because the leftmost occurrence of '1011' is at the fifth position in '0000101100001011'.

  1. NEW_STRING = '315-54-3159';
    IF INDEX(NEW_STRING,'-')=4 THEN
    PUT LIST('SOCIAL SECURITY NUMBER');

The INDEX function is used to determine whether or not a string is a Social Security number. The function finds the location of the first hyphen in the string.

INFORM

Dialects - ansi, dec

The INFORM preprocessor built-in function returns the number of diagnostic informational messages issued during compilation up to that point in the source program. The format for the INFORM built-in function is:

INFORM();

 

The function returns a FIXED result representing the number of compile-time warning messages that were issued up until the INFORM built-in function was encountered.

INT

Dialects - ansi, dec

The INT built-in function treats specified storage as a signed integer, and returns the value of the integer. The format is:

INT(expression[,position[,length]])

 
expression

A scalar expression or reference to connected storage. This reference cannot be an array, structure, or named constant. If position and length are not specified, the length of the referenced storage must not exceed 32 bits. If it exceeds 32 bits, a fatal run-time error results.

position

A positive integer value that denotes the position of the first bit in the field. If omitted, position defaults to 1, signifying the first bit of storage denoted by the expression. If specified, position must satisfy the following condition:

1 <= position <= size(expression)

Here, size(expression) is the length in bits of the storage denoted by expression. A position equal to size(expression) implies a zero-length field.

length

An integer value in the range 0 through 32 that specifies the length of the field. If omitted, length is the number of bits from the bit denoted by position through the end of the storage denoted by expression. If specified, length must satisfy the following condition:

0 <= length <= size(expression) - position

Here, size(expression) is the length in bits of the storage denoted by expression.

Returned Value

The value returned by INT is of the type FIXED BINARY (31). If the field has a length of zero, INT returns zero.

Examples

The following example shows the use of the INT built-in function to interpret the storage occupied by a bit string as an integer:

B16 = '0000000000001101'B; /* 16-bit string */

 

I = BIN(B16); /* I = 13 */

I = INT(B16); /* I = -20480 */

 

B64 = '5076ABCD00000000'B4; /* 64-bit string */

 

 

 

I = INT(B64,1,32); /* First 32 bits; I = -1277858294 */

I = INT(B64,33); /* Second 32 bits; I = 0 */

I = INT(B64); /* Field too large, run-time error */

 

Notice that, unlike the BIN built-in function, the INT built-in function performs no conversion. It simply treats the contents of the designated storage as a signed integer. Therefore, the value returned by INT depends on the data type (and therefore the internal representation) of the variable occupying the storage. For example:

INTEXM: PROCEDURE OPTIONS (MAIN);

 

DECLARE D FIXED DECIMAL (3,2),

C CHARACTER (4),

F FLOAT;

 

 

D = 2.54;

C = '2.54';

F = 2.54;

 

PUT SKIP LIST ( INT(D),

INT(C),

INT (F) );

 

END;

 

The output of this example is:

19493 875900466 -1889779422

 

LBOUND

Dialects - ansi, dec, ibm

The LBOUND built-in function returns a fixed-point binary integer that is the lower bound of an array dimension. The format is:

LBOUND(reference[,dimension])

 
reference

A reference to an array variable.

dimension

An integer constant indicating the dimension of the specified array. If the dimension is not specified, the dimension parameter defaults to 1. Thus, LBOUND(A) is equivalent to LBOUND(A,1).

LENGTH

Dialects - ansi, dec, ibm

The LENGTH built-in function returns a fixed-point binary integer that is the number of characters or the number of bits in a specified character- or bit-string expression. If the string is a varying-length character string, the function returns its current length. (To determine the maximum length of a varying-length character string, use the MAXLENGTH built-in function.)

The format of the function is:

LENGTH(string)

 

LINE

Dialects - ansi, dec, ibm

The LINE preprocessor built-in function returns the line number of the source program text containing the end of the preprocessor statement that calls the LINE built-in function.

The format of the function within a preprocessor expression is:

LINE()

 

LINENO

Dialects - ansi, dec, ibm

The LINENO built-in function returns a FIXED BINARY(15) integer that is the current line number of the referenced print file. The format is:

LINENO(reference)

 

If the referenced print file is closed, the returned value is the last value from the previous opening. If the file was never opened, the returned value is zero.

LOG

Dialects - ansi, dec, ibm

The LOG built-in function returns a floating-point value that is the base e (natural) logarithm of an arithmetic expression x. The computation is performed in floating point. The expression x must be greater than zero after its conversion to floating point.

The format of the function is:

LOG(x)

 

LOG10

Dialects - ansi, dec, ibm

The LOG10 built-in function returns a floating-point value that is the base 10 logarithm of arithmetic expression x. The computation is performed in floating point. The expression x must be greater than zero after its conversion to floating point.

The format of the function is:

LOG10(x)

 

LOG2

Dialects - ansi, dec, ibm

The LOG2 built-in function returns a floating-point value that is the base 2 logarithm of an arithmetic expression x. The computation is performed in floating point. The expression x must be greater than zero after its conversion to floating point.

The format of the function is:

LOG2(x)

 

LOW

Dialects - ansi, dec, ibm

The LOW built-in function returns a string of specified length that consists of repeated appearances of the lowest character in the collating sequence. The format is:

LOW(length)

 
length

The specified length of the returned string. The maximum length permitted is 32767 characters.

Returned String

The string returned is of the length specified. The rank of the lowest character that can appear in the collating sequence for PL/I is ASCII NUL (value 0).

MAX

Dialects - ansi, dec, ibm

The MAX built-in function returns the larger of two arithmetic expressions x and y. The format of the function is:

MAX(x,y)

 
Returned Value

The expressions x and y are converted to their derived type before the operation is performed (for a discussion of derived types see See Derived Data Types for Arithmetic Operations . If the derived type is floating point, the value returned is also floating point, with the larger precision of the two converted arguments. If the derived type is fixed point, the returned value is a fixed-point value with the base of the derived type. The value has the following attributes:

precision = min(31,max(px - qx,py - qy) + max(qx,qy))

scale factor = max(qx,qy)

Here, px,qx and py,qy are the converted precisions and scale factors of x and y, respectively.

The MAX built-in function is also a preprocessor built-in function; however, the preprocessor does not permit scale factors.

MAXLENGTH

Dialects - ansi, dec

The MAXLENGTH built-in function returns a fixed binary number representing the maximum possible length of a varying-length character string. The format is:

MAXLENGTH (string)

string

A reference to a character string or a bit string. If it is anything other than a varying-length character string, the MAXLENGTH function returns a result identical to the result that would be returned by the LENGTH built-in function.

For example:

MAXLENGTH_EXAMPLE: PROCEDURE OPTIONS(MAIN);

DCL CHAR_VAR CHARACTER(10) VARYING;

CHAR_VAR = 'String';

CALL SAMPLE(CHAR_VAR);

END MAXLENGTH_EXAMPLE;

SAMPLE: PROCEDURE(STRING);

DCL STRING CHAR(*) VARYING;

PUT LIST(LENGTH(STRING),MAXLENGTH(STRING));

END SAMPLE;

 

The program prints the following:

6 10

 

MIN

Dialects - ansi, dec, ibm

The MIN built-in function returns the smaller of two arithmetic expressions x and y. The format is:

MIN(x,y)

 
Returned Value

The expressions x and y are converted to their derived type before the operation is performed (for a discussion of derived types see See Derived Data Types for Arithmetic Operations . If the derived type is floating point, the value returned is also floating point, with the larger precision of the two converted arguments. If the derived type is fixed point, the returned value is a fixed-point value with the base of derived type. The value has the following attributes:

precision = min(31,max(px - qx,py - qy) + max(qx,qy))

scale factor = max(qx,qy)

Here, px,qx and py,qy are the converted precisions and scale factors of x and y.

The MIN built-in function is also a preprocessor built-in function; however, the preprocessor does not permit scale factors.

MOD

Dialects - ansi, dec, ibm

The MOD built-in function returns, for an arithmetic expression x and nonnegative arithmetic expression y, the value r that equals x modulo y. That is, r is the smallest positive value that must be subtracted from x to make the remainder of x divided by y exactly 0.

The format of the function is:

MOD(x,y)

 
Returned Value

The expressions x and y are converted to their derived type before the operation is performed.

If the derived type is unscaled fixed point, then the precision of the result is the precision of the second operand.

If the derived type is floating point, the returned value is an approximation in floating point, with the larger of the precisions of the two converted arguments.

The value returned is:

u - w * floor(u / w)

The arguments u and w become the arguments x and y, respectively, after conversion to their derived type. If w is zero, u is converted to the precision described below, which can signal FIXEDOVERFLOW.

If x and y are fixed-point expressions, a fixed-point value is returned. The value has the following attributes:

precision = min(31,pw - qw + max(qu,qw))

scale factor = max(qu,qw)

Here, qu is the scale factor of u, pw is the precision of w, and qw is the scale factor of w. The FIXEDOVERFLOW condition is signaled if the following is true:

pw - qw + max(qu,qw) > 31

The MOD built-in function is also a preprocessor built-in function; however, the preprocessor does not permit scale factors.

Examples

MODEX: PROCEDURE OPTIONS(MAIN);

 

DECLARE OUTMOD PRINT FILE;

 

ON FIXEDOVERFLOW PUT FILE(OUTMOD)

SKIP LIST('FIXEDOVERFLOW signaled');

 

PUT FILE(OUTMOD) SKIP LIST(MOD(28,128));

PUT FILE(OUTMOD) SKIP LIST(MOD(130,128));

PUT FILE(OUTMOD) SKIP LIST(MOD(-28,128));

PUT FILE(OUTMOD) SKIP LIST(MOD(4.5,.758));

PUT FILE(OUTMOD) SKIP LIST(MOD(-4.5,.758));

PUT FILE(OUTMOD) SKIP LIST(MOD(1.5E-3,-1.4E-3));

PUT FILE(OUTMOD) SKIP LIST(MOD(28,0));

 

END MODEX;

 

The program MODEX writes the following output to OUTMOD.DAT:

28

2

100

0.710

0.048

-1.3E-03

 

FIXEDOVERFLOW signaled

 

The last PUT statement attempts to take MOD(28,0). The constants 28 and 0 are both fixed-point decimal expressions, with precisions (2,0) and (1,0), respectively. Therefore, the attributes of the returned value are determined to be FIXED DECIMAL. The value has the following attributes:

precision = min(31,1 - 0 + max(0,0)) = 1

scale factor = max(0,0) = 0

Although 28 modulo 0 is 28, MOD(28,0) signals FIXEDOVERFLOW because 28 cannot be represented in the result precision. (The value of the function is therefore undefined.)

MULTIPLY

Dialects - ansi, dec, ibm

The MULTIPLY built-in function multiplies two arithmetic expressions x and y, and returns the product of the two values with a specified precision p and an optionally specified scale factor q.

The format of the function is:

MULTIPLY(x,y,p[,q])

 
p

An integer constant greater than zero and less than or equal to the maximum precision of the result type, which is 31 for fixed-point data, 15 for floating-point decimal data, and 53 for floating-point binary data.

q

An integer in the range -31 through p, when used with fixed-point binary multiplication. The scale factor for fixed-point decimal multiplication has a range 0 through p. A scale factor is not to be used with floating-point arithmetic. If no scale factor is designated, q defaults to zero.

Expressions x and y are converted to their derived type before the multiplication is performed.

For example:

MULT: PROCEDURE OPTIONS (MAIN);

 

DECLARE I_RATE FIXED DECIMAL(31,4),

PRINCIPAL FIXED DECIMAL(31,2),

OWED FIXED DECIMAL(31,6);

 

I_RATE = .1514;

 

PRINCIPAL = 27688.25;

 

OWED = MULTIPLY (I_RATE,PRINCIPAL,31,6);

 

PUT SKIP LIST ('INTEREST OWED =',OWED);

 

END;

 

Interest rates are calculated to six decimal places and the following string is printed:

INTEREST OWED = 4192.001050

 

NULL

Dialects - ansi, dec, ibm

The NULL built-in function returns a null pointer value. The format is:

NULL()

 
Examples

IF NEXT_POINTER = NULL() THEN CALL FINISH;

 

The IF statement checks whether the pointer variable NEXT_POINTER is null; if so, the CALL statement is executed.

The NULL built-in function can be used for offset variables as well as pointer variables, because the compiler automatically performs conversions between pointer and offset values.

OFFSET

Dialects - ansi, dec, ibm

The OFFSET built-in function converts a pointer to an offset relative to a designated area. If the pointer is null, the result is null. The format of the function is:

OFFSET(pointer,area)

 
pointer

A reference to a pointer variable whose current value either represents the location of a based variable within the specified area or is null.

area

A reference to a variable declared with the AREA attribute. If the specified pointer is not null, it must designate a storage location within this area.

Examples

DECLARE MAP_SPACE AREA (2048),

START OFFSET (MAP_SPACE),

QUEUE_HEAD POINTER;

START = OFFSET (QUEUE_HEAD,MAP_SPACE);

 

The offset variable START is associated with the area MAP_SPACE. The OFFSET built-in function converts the value of the pointer to an offset value.

ONCHAR

Dialects - ansi, dec, ibm

The ONCHAR built-in function returns the character that caused a CONVERSION condition to be raised. If there is no active CONVERSION condition, the return value is a single space.

The format of the function is:

ONCHAR()

 

The ONCHAR value is actually a single character substring of the ONSOURCE built-in function value, unless there is no active CONVERSION condition.

ONCODE

Dialects - ansi, dec, ibm

The ONCODE built-in function returns a fixed-point binary integer that is the status value of the most recent run-time error that signaled the current ON condition. You can use the function in any ON-unit to determine the specific error that caused the condition. If the function is used within any context outside an ON-unit, it returns a zero. The format is:

ONCODE()

 

ONFILE

Dialects - ansi, dec, ibm

The ONFILE built-in function returns the name of the file constant for which the current file-related condition was signaled. The format is:

ONFILE()

 

This built-in function can be used in an ON-unit established for any of the following conditions:

  • An ON-unit for the KEY, ENDFILE, ENDPAGE, and UNDEFINEDFILE conditions
  • A VAXCONDITION ON-unit established for I/O errors that can occur during file processing
  • An ERROR ON-unit that receives control as a result of the default PL/I action for file- related errors, which is to signal the ERROR condition
  • A CONVERSION ON-unit that was entered because of an error that occurred during conversion of data in a GET statement
Returned Value

The returned value is a varying-length character string. The ONFILE function returns a null string if referenced outside an ON-unit, within an ON-unit that is executed as a result of a SIGNAL statement, or within a CONVERSION ON-unit that was not entered because of a conversion in a GET statement.

ONKEY

Dialects - ansi, dec, ibm

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:

ONKEY()

 

This built-in function can be used in an ON-unit established for these conditions:

  • KEY, ENDFILE, or UNDEFINEDFILE
  • An ERROR ON-unit that receives control as a result of the default PL/I action for the KEY condition, which is to signal the ERROR condition
Returned Value

The returned key value is a varying-length character string. The ONKEY built-in function returns a null string if referenced outside an ON-unit or within an ON-unit executed as a result of the SIGNAL statement.

ONLOC

Dialects - ibm

The ONLOC built-in function returns the hexadecimal address of the entry point used for the current invocation of the procedure in which a condition was raised. Its format is:

ONLOC

 

This built-in function can be used in any ON-unit or any of the dynamic descendants of an ON-unit.

Returned Value

The returned key value is a varying-length character string. The ONKEY built-in function returns a null string if referenced outside an ON-unit or within an ON-unit executed as a result of the SIGNAL statement.

ONSOURCE

Dialects - ansi, dec, ibm

The ONSOURCE built-in function returns the source string that was being converted when the CONVERSION condition was raised. If no CONVERSION condition is active, the return value is a null string.

The format of the function is:

ONSOURCE()

 

PLIRETV

Dialects - ibm

The PLIRETV built-in function returns a fixed binary (15) value that is the PL/I return code. This is used in conjunction with the PLIRETC built-in subroutine. The returned value contains the most recent value returned by a call to PLIRETC. This built-in function is used with the Sort program, but also has other uses. (See the Kednos PL/I for UNIX User's Manual for more information on the Sort program and the PLIRETC built-in subroutine.)

The format of the function is:

PLIRETV

 

POINTER

Dialects - ansi, dec, ibm

The POINTER built-in function returns a pointer to the location identified by the referenced offset and area. The format is:

offset

A reference to an offset variable whose current value either represents the offset of a based variable within the specified area or is null.

area

A reference to a variable that is declared with the AREA attribute and with which the specified offset value is associated.

Returned Value

The returned value is of type POINTER. If the offset value is null, the result is null.

Examples

DECLARE MAP_SPACE AREA (2048),

START OFFSET (MAP_SPACE),

P POINTER;

P = POINTER (START,MAP_SPACE);

 

The POINTER built-in function converts the value of the offset variable START (in the area MAP_SPACE) to a pointer value.

POSINT

Dialects - ansi, dec

The POSINT built-in function treats specified storage as an unsigned integer, and returns the value of the integer. The format is:

POSINT(expression[,position[,length]])

 
expression

A scalar expression or reference to connected storage. This reference must not be an array, structure, or named constant. If position and length are not specified, the length of the referenced storage must not exceed 32 bits. (If it exceeds 32 bits, a FATAL run-time error results.)

position

A positive integer value that denotes the position of the first bit in the field. If omitted, position defaults to 1, signifying the first bit of the storage denoted by the expression. If specified, position must satisfy the following condition:

1 <= position <= size(expression)

Size(expression) is the length in bits of the storage denoted by expression. A position equal to size(expression) implies a zero-length field.

length

An integer value in the range 0 through 32 that specifies the length of the field. If omitted, length is the number of bits from the bit denoted by position through the end of the storage denoted by expression. If specified, length must satisfy the following condition:

0 <= length <= size(expression) - position

Size(expression) is the length in bits of the storage denoted by expression.

Returned Value

The value returned by POSINT is of the type FIXED BINARY (31). If the field has a length of zero, POSINT returns zero.

Because the POSINT built-in function treats storage as if it contained an unsigned integer, the value returned can be larger than the maximum positive value that can be contained in the signed integer that is stored in the same number of bits. For example, if the argument to POSINT is 32 bits long and has the high-order (sign) bit set, then the resulting value is too large for assignment to a FIXED BIN (31) variable. The result of such an operation is undefined.

Examples

The use of the POSINT built-in function is identical to the use of the INT built-in function, except that POSINT treats its argument as an unsigned integer. The following example illustrates this difference.

DECLARE (X15,Y15,I15,P15) FIXED BIN (15),

P31 FIXED BIN (31);

 

X15 = 585;

Y15 = -585;

I15 = INT(X15); /* I15 = 585 */

I15 = INT(Y15); /* I15 = -585 */

P15 = POSINT(X15); /* P15 = 585 */

P31 = POSINT(Y15); /* P31 = 64951 */

P15 = POSINT(Y15); /* ERROR signaled */

 

In this example, POSINT first assigns the storage referenced by X15 to P15. Because this storage is occupied by a positive integer and therefore has the sign bit clear, POSINT behaves exactly like INT. However, when POSINT is applied to storage occupied by a negative integer, it interprets the set sign bit as representing part of the integer. When the resulting value is assigned to a FIXED BIN (31) variable, it is seen to be larger than the FIXED BIN (15) variable results in PL/I signaling an ERROR condition.

PRECISION

Dialects - ibm

The PRECISION built-in function takes an input expression and returns the value converted to the specified precision. The format of the PRECISION built-in function is:

PRECISION(expression, digits [,scale]);

 
expression

Any valid arithmetic expression.

digits

An integer specifying the number of digits of precision to which the expression will be converted. It must not exceed the dialect-defined limit for the data type of the expression.

scale

An optional integer constant less than or equal to the specified precision. The scale factor can be optionally signed. It must not exceed the dialect-defined limit for the data type of the expression. The default scale factor is zero.

Do not use a scale factor with floating point expressions.

PROD

Dialects - ansi, dec, ibm

The PROD built-in function takes an array as an argument and returns the arithmetic product of all the elements in the array. The array must have the FIXED or the FLOAT attribute. The format of the PROD built-in function is:

PROD(array-variable);

 

If the array has the attributes FIXED(p,0), the result will have the attributes FIXED(p,0). If the array has the attributes FLOAT(p), the result will also have the attributes FLOAT(p). If the array has the attributes FIXED(p,q) with q not equal to 0, the result will have the attributes FLOAT(p).

The result will have the same base attribute as the array, either DECIMAL or BINARY.

Note that the PROD built-in function does not perform matrix multiplication of two arrays.

RANK

Dialects - ansi, dec

The RANK built-in function returns a fixed-point binary integer that is the ASCII code for the designated character. The precision of the returned value is 15. The format of the function is:

RANK(character)

 
character

Any expression yielding a 1-character value.

Examples

CODE = RANK('A'); /* CODE = 65 */

CODE = RANK('a'); /* CODE = 97 */

CODE = RANK('$'); /* CODE = 36 */

 

The ASCII characters are the first 128 characters of the DEC Multinational Character Set.

REPEAT

Dialects - ibm

The REPEAT built-in function copies a given string a specified number of times and concatenates the result into a single string. Its format is:

REPEAT(string,count)

 
string

Any bit- or character-string expression. If the expression is a bit string, the result is a bit string. Otherwise, the result is a character string.

count

Any expression that yields an integer. The specified count controls the number of repeats of the string that are concatenated to the original string, as follows:

Value of Count

String Returned

0 or negative

The string argument

1 to n

COUNT+1 concatenated copies of the string argument

Examples

The REPEAT built-in function is similar to the COPY built-in function, but not exactly the same. Compare the value returned by this example to the one returned by the example for the COPY built-in function:

REPEAT('12',3)

 

This function reference returns the character-string value '12121212'.

REVERSE

Dialects - ansi, dec

The REVERSE built-in function reverses the characters or bits in a string. It takes one argument, which is either a character string (fixed or varying) or a bit string. It returns a string of the same type and size as its argument, with all the characters (bytes) or bits reversed.

The format of the function is:

REVERSE(string-expression);

 
string-expression

An expression that evaluates to a character string or a bit string.

Examples

DECLARE X CHARACTER(4) VARYING,

Y BIT(8);

X = REVERSE('abc')

Y = REVERSE('00010101'B)

 

The character-string variable X is assigned the value `cba'. The bit-string variable Y is assigned the value '10101000'B.

ROUND

Dialects - ansi, dec, ibm

The ROUND built-in function rounds a fixed-point binary decimal expression to a specified number of binary or decimal places respectively. The format is:

ROUND(expression,position)

 
expression

An arithmetic expression that yields a fixed-point binary or decimal value; or a pictured value with fractional digits. A binary value can have a positive or negative non-zero scale factor, but a decimal value must have a positive non- zero scale factor.

position

A nonnegative integer constant specifying the number of binary or decimal places in the rounded result.

Returned Value

Where the arguments are an expression of type FIXED BINARY(p,q) or type FIXED DECIMAL(p,q) and position k, the returned value is the rounded value with the following attributes:

precision = max(1,min(p - q + k + 1,31))

scale factor = k

For a fixed binary number, the rounded value is:

ROUND(x,k) = sign(x)*(2 -k+1 )*floor(abs(x)*(2 k ) + 1)

For a fixed decimal number, the rounded value is:

ROUND(x,k) = sign(x)*(10 -k )*floor(abs(x)*10 k ) + 0.5)

Example 1

The following sample program shows rounding of scaled fixed binary numbers:

r: procedure options(main);

 

declare

fb1 fixed binary(31, 8),

fb2 fixed binary(31, 4),

fb3 fixed binary(31, 2),

fb4 fixed binary(31, 2),

fb5 fixed binary(31, 2);

 

fb1 = 16.8750; /* 7/8 */

fb2 = 15.4375; /* 7/16 */

fb3 = 128.25; /* 128 1/4 */

fb4 = 128.75; /* 128 3/4 */

fb5 = -128.75; /* -128 3/4 */

 

put skip edit ('round(16.8750, 2)=',round(fb1,2))

(a,col(20),f(15,5));

put skip edit ('round(16.8750, 3)=',round(fb1,3))

(a,col(20),f(15,5));

put skip edit ('round(15.4375, 1)=',round(fb2,1))

(a,col(20),f(15,5));

put skip edit ('round(128.25,0)=',round(fb3,0))

(a,col(20),f(15,5));

put skip edit ('round(128.75,0)=',round(fb4,0))

(a,col(20),f(15,5));

put skip edit ('round(-128.75,0)=',round(fb5,0))

(a,col(20),f(15,5));

end r;

 

This program produces the following output. Note that 16.87500 equals 16 7/8 in fractional notation and that 15.50000 equals 15 1/2 in fractional notation.

round(16.8750, 2)= 17.00000

round(16.8750, 3)= 16.87500

round(15.4375, 1)= 15.50000

round(128.25,0)= 128.00000

round(128.75,0)= 129.00000

round(-128.75,0)= -129.00000

 

Example 2

The following example shows rounding of scaled fixed decimal numbers:

A = 1234.567;

Y = ROUND(A,1); /* Y = 1234.6 */

 

Y = ROUND(A,0); /* Y = 1235 */

 

A = -1234.567;

Y = ROUND(A,2); /* Y = -1234.57 */

 

SEARCH

Dialects - ansi, dec

The SEARCH built-in function takes two character-string arguments and attempts to locate the first character in the first string that is also present in the second string. The search for a match is carried out from left to right. If one character is matched, the function returns the position of that character in the first string. This function is case sensitive.

The format is:

SEARCH(string-1,string-2[,starting-position])

 
string-1

A character-string expression. One character in the string is to be matched, if possible, in the second string.

string-2

A character-string expression to be compared, character by character, with each character in the first string, in order, until one matching character is found.

starting-position

A positive integer in the range 1 to n+1, where n is the length of the first string. It specifies the leftmost character in the first string from which the search is to begin. If starting-position is specified, any characters to the left of that position in the first string are ignored. (By default, the search begins with the leftmost character in the first string.)

Returned Value

The returned value is a positive integer representing the position in string-1 of the first character that is also found in string-2. If no match is found, the returned value is zero.

Examples

DECLARE STR1 CHARACTER(20) VARYING,

STR2 CHARACTER(10) INITIAL ('ABCDEFGHIJ'),

X FIXED DECIMAL(2);

STR1 = 'BARBARA';

X = SEARCH (STR1,STR2);

 

In this example, X is given the value 1 because the first character (`B') in STR1 (`BARBARA') is found in STR2 (`ABCDEFGHIJ').

STR1 = '12-GEORGE';

X = SEARCH (STR1,STR2);

 

Here, X is given the value 4. `G' is in the fourth position in `12-GEORGE' and is the first character in STR1 that is also present in STR2 (`ABCDEFGHIJ').

X = SEARCH (STR1,STR2,6);

 

X is given the value 8. The starting-position parameter, 6, causes the search to begin with the sixth character in `12-GEORGE', and thus the first matching character is the second `G', which is in the eighth position.

PUT LIST (SEARCH('ZZZBAD','ABCD'));

 

The function returns the value 4 because the position of `B' in `ZZZBAD' is 4, and `B' is the leftmost matching character. Here, constants are used instead of variables.

PUT LIST (SEARCH('ABCD','ZZZBAD'));

 

This statement is the same as the preceding one except that the parameters are reversed. Now the value returned is 1 instead of 4 because `A', the first character in `ABCD', is matched. Note that the order in which the parameters are given is crucial. Note also that duplicate characters in the second string never change the result.

PUT LIST (SEARCH (' TEST 123','0123456789'));

 

The function returns the value 9 because `1', which is in the ninth position, is the first character matched in the second string.

SIGN

Dialects - ansi, dec, ibm

The SIGN built-in function returns 1, -1, or 0, indicating whether an arithmetic expression is positive, negative, or zero, respectively. The returned value is a fixed-point binary integer.

The format of the function is:

SIGN(expression)

 

SIN

Dialects - ansi, dec, ibm

The SIN built-in function returns a floating-point value that is the sine of an arithmetic expression x, where x is an angle in radians. The sine is computed in floating point. The format of the function is:

SIN(x)

 

SIND

Dialects - ansi, dec, ibm

The SIND built-in function returns a floating-point value that is the sine of an arithmetic expression x, where x represents an angle in degrees. The sine is computed in floating point. The format of the function is:

SIND(x)

 

SINH

Dialects - ansi, dec, ibm

The SINH built-in function returns a floating-point value that is the hyperbolic sine of an arithmetic expression x. The hyperbolic sine is computed in floating point. The format of the function is:

SINH(x)

 

SIZE

Dialects - ansi, dec

The SIZE built-in function returns a fixed-point binary integer that is the number of bytes allocated to a referenced variable. The format is:

SIZE (reference)

 
reference

The name of a variable known to this block. The variable can be a scalar variable, an array or structure, or a structure member. The variable cannot be a constant or expression. Although references to individual array elements are allowed, the returned value in this instance is the size of the entire array, not the element.

Returned Value

The returned value is a fixed bin(31) value containing the variable's allocated size in bytes. For bit strings that do not exactly fill an integral number of bytes, the value is rounded up to the next byte.

For varying character-string variables, note that the returned value is two bytes greater than the declared length of the string. These extra two bytes are allocated by PL/I to contain the current length of the string. (If you want the value of the maximum length of a varying character string, use the MAXLENGTH built-in function. If you want the value of the current length of a varying character string, use the LENGTH built-in function.)

Examples

The following example illustrates the use of the SIZE built-in function on some scalar variables.

DECLARE S FIXED BINARY(31),

INT FIXED BINARY(15),

CHAR1 CHARACTER(5),

CHAR2 CHARACTER(5) VARYING,

BITSTRING BIT(10),

P POINTER;

 

S = SIZE(INT); /* S = 2 */

S = SIZE(CHAR1); /* S = 5 */

S = SIZE(CHAR2); /* S = 7 */

S = SIZE(BITSTRING); /* S = 2 */

S = SIZE(P); /* S = 4 */

 

Note the difference between the allocated size for the fixed-length and varying character strings. Note also that the returned value for the bit string is rounded up to 2 bytes, the integral number of bytes required to contain 10 bits.

DECLARE 1 STRUC,

2 CHARSTR CHARACTER(5),

2 BITSTR BIT(10),

ARRAY(5) FIXED BINARY(31),

S FIXED BINARY(31);

S = SIZE(STRUC); /* S = 7 */

S = SIZE(CHRSTR); /* S = 5 */

S = SIZE(ARRAY); /* S = 20 */

S = SIZE(ARRAY(2)); /* S = 20 */

 

In this example, the SIZE built-in function is applied to a structure, to one of its members, to an array, and to an element of the array. Note that a reference to an array element returns the same value as a reference to the entire array.

DECLARE 1 TARGET,

2 A BIT(9),

2 B BIT(10),

2 C BIT(1),

1 ALIGNED_TARGET,

2 A BIT(9) ALIGNED,

2 B BIT(10) ALIGNED,

2 C BIT(1) ALIGNED,

S FIXED BINARY(31);

 

S = SIZE(TARGET); /* S = 3 */

S = SIZE(ALIGNED_TARGET); /* S = 5 */

 

This example illustrates the difference in PL/I's storage of unaligned and aligned bit strings. The structure TARGET consists of three bit strings that are unaligned (the default storage mechanism). The three bit strings occupy 20 consecutive bits in memory. Therefore, only three bytes are required to hold the structure. The structure ALIGNED_TARGET consists of the same three strings, except each is declared with the ALIGNED attribute, forcing the structure to start on a byte boundary. In this structure, A and B each require two bytes while C requires one byte, for a total of five bytes. A similar situation exists with arrays of bit strings.

T: PROC OPTIONS(MAIN);

 

DCL P PTR;

DCL 1 S BASED(P),

2 I FIXED,

2 A(10 REFER(I)) FIXED;

 

ALLOCATE S;

PUT SKIP LIST(SIZE(S)); /* Returns 44 */

I = 5;

PUT SKIP LIST(SIZE(S)); /* Returns 24 */

END;

 

This example shows how the SIZE built-in function works on a structure containing the REFER option. SIZE returns the current size.

DECLARE STR CHARACTER(10) VARYING;

CALL SUB(STR);

SUB: PROCEDURE(X);

DECLARE X CHARACTER(*) VARYING;

 

PUT SKIP LIST (SIZE(X));

 

Here, the SIZE built-in function is used to determine the size of a parameter that is passed to a procedure. This PUT statement prints the value 12.

CALL MACRO_ROUTINE(

ADDR(OUTSTRING),SIZE(OUTSTRING) );

 

Here, the SIZE built-in function is used to supply an argument to a procedure (possibly one written in another language) that requires the size in bytes of a data structure.

SOME

Dialects - ansi, dec

The SOME built-in function allows you to determine whether at least one bit in a bit string is '1'B. In other words, it performs a logical OR operation on the elements of the bit string. The format of the SOME built-in function is:

SOME(bit-string)

 

The function returns the value '1'B if one or more bits in the bit-string argument are '1'B. It returns '0'B if every bit in the argument is '0'B or if the argument is the null bit string.

SQRT

Dialects - ansi, dec, ibm

The SQRT built-in function returns a floating-point value that is the square root of an arithmetic expression x. The square root is computed in floating point. After its conversion to floating point, x must be greater than or equal to zero.

The format of the function is:

SQRT(x)

 

STORAGE

Dialects - ibm

The STORAGE built-in function returns a fixed binary (31) value that is the implementation-defined storage, in bytes, required by the specified variable. The format of the function is:

STORAGE(reference)

 

reference

The name of a variable known to this block except:

  • A variable that is not in connected storage.
  • An unaligned fixed-length BASED, DEFINED, subscripted, parameter, or structure element.
  • A minor structure with a first or last element that is an unaligned fixed-length bit string, unless that element is the first or last element of the containing major structure.
  • A major structure with the BASED, DEFINED, or parameter attribute with a first or last element that is an unaligned fixed-length bit string.
Returned Value

The returned value is a fixed bin(31) value containing the variable's maximum storage size in bytes. This is the maximum number of bytes that could be transmitted if you wrote the variable to a record file defined with the ENVIRONMENT(SCALARVARYING) option.

Some variables can have varying sizes. If the referenced variable is a varying-length string, a scalar area, or an aggregate that contains areas or varying-length strings, the returned value includes the storage used by any control bytes and length prefixes plus the maximum lengths of the strings and the maximum sizes of the areas.

STRING

Dialects - ansi, dec, ibm

The STRING built-in function concatenates the elements of an array or structure and returns the result. Elements of a string array are concatenated in row-major order. Members of a structure are concatenated in the order in which they were declared.

The format of the STRING built-in function is:

STRING(reference)

 
reference

A reference to a variable that is suitable for bit-string or character-string overlay defining. Briefly, a variable is suitable if it consists entirely of characters or bits, and these characters or bits are packed into adjacent storage locations, without gaps.

Returned Value

The string returned is of type CHARACTER or BIT, depending on whether the reference is suitable for character- or bit-string overlay defining. The length of the string is the total number of characters or bits in the base reference.

Examples

STRING_BIF_EXAMPLE: PROCEDURE;

DECLARE NEW_NAME CHARACTER(40);

DECLARE 1 FULL_NAME,

2 FIRST_NAME CHARACTER(10),

2 MIDDLE_INITIAL CHARACTER(3),

2 LAST_NAME CHARACTER(27);

FIRST_NAME = 'MABEL';

MIDDLE_INITIAL = 'S.';

LAST_NAME = 'MERCER';

NEW_NAME = STRING(FULL_NAME);

/* NEW_NAME =

'MABEL S. MERCER '

where is a space */

END STRING_BIF_EXAMPLE;

 

SUBSTR

Dialects - ansi, dec, ibm

The SUBSTR built-in function returns a specified substring from a string. The format is:

SUBSTR(string,position[,length])

 
string

A bit- or character-string expression.

position

An integer expression that indicates the position of the first bit or character in the substring. The position must be greater than or equal to 1 and less than or equal to LENGTH(string) + 1.

length

An integer expression that indicates the length of the substring to be extracted. If not specified, length is:

LENGTH(string) - position + 1

In other words, if length is not specified, the substring is extracted beginning at the indicated position and ending at the end of the string.

The length must satisfy the following condition:

0 <= length <= LENGTH(string) - position + 1

Returned Value

The returned substring is of type BIT(length) or CHARACTER(length), depending on the type of the string argument. If the length argument is zero, the result is a null string.

Examples

DECLARE (NAME,LAST_NAME) CHARACTER(20),

START FIXED BINARY(31);

 

NAME = 'ISAK DINESEN';

/* NAME = 'ISAK#DINESEN ' */

 

START = INDEX(NAME,' ') + 1;

/* START = 6 */

 

LAST_NAME = SUBSTR(NAME,START);

/* default length = LENGTH(NAME) - START + 1 = 15 */

/* LAST_NAME = 'DINESEN ' */

 

SUBTRACT

Dialects - ansi, dec

The SUBTRACT built-in function returns the difference of two arithmetic expressions x and y, with a specified precision p and an optionally specified scale factor q. The format of the function is:

SUBTRACT(x,y,p[,q])

 
p

An unsigned integer constant greater than zero and less than or equal to the maximum precision of the result type, which is 31 for fixed-point data, 15 for floating-point decimal data, and 53 for floating-point binary data.

q

An integer constant less than or equal to the specified precision. The scale factor can be optionally signed when used in fixed-point binary subtraction. The scale factor for fixed-point binary must be in the range -31 through p. The scale factor for fixed-point decimal data must be in the range 0 through p. If you omit q, the default value is zero. Do not use a scale factor for floating-point arithmetic.

Expressions x and y are converted to their derived type before the subtraction is performed. For example:

SUBTRACTBIF: PROCEDURE OPTIONS (MAIN);

 

DECLARE X FIXED DECIMAL (8,3),

Y FIXED DECIMAL (8,3),

Z FIXED DECIMAL (9,3);

 

X=9500.374;

Y=2278.897;

Z = SUBTRACT (X,Y,9,3);

 

PUT SKIP LIST ('DIFFERENCE =',Z);

END;

 

This program prints:

DIFFERENCE = 7221.477

SUM

Dialects - ansi, dec, ibm

The SUM built-in function takes an array as an argument and returns the arithmetic sum of all the elements in the array. The array must have the FIXED or the FLOAT attribute. The format of the SUM built-in function is:

SUM(array-variable)

 

If the array has the attributes FIXED(p,q), the result will have the attributes FIXED(p,q). If the array has the attributes FLOAT(p), the result will also have the attributes FLOAT(p).

The result will have the same base attribute as the array, either DECIMAL or BINARY.

TAN

Dialects - ansi, dec, ibm

The TAN built-in function returns a floating-point value that is the tangent of an arithmetic expression x, where x represents an angle in radians. The tangent is computed in floating point. After its conversion to floating point, x must not be an odd multiple of /2

The format of the function is:

TAN(x)

 

TAND

Dialects - ansi, dec, ibm

The TAND built-in function returns a floating-point value that is the tangent of an arithmetic expression x, where x represents an angle in degrees. The tangent is computed in floating point. After its conversion to floating point, x must not be an odd multiple of 90.

The format of the function is:

TAND(x)

 

TANH

Dialects - ansi, dec, ibm

The TANH built-in function returns a floating-point value that is the hyperbolic tangent of an arithmetic expression x. The hyperbolic tangent is computed in floating point. The format of the function is:

TANH(x)

 

TIME

Dialects - ansi, dec, ibm

The TIME built-in function returns an 8-character string representing the current time of day in the following form:

hhmmssxx

 

The current hour (00-23)

The minutes (00-59)

The seconds (00-59)

Hundredths of seconds (00-99)

The format of the TIME built-in function is:

TIME()

 
Returned Value

If TIME is used as a preprocessor built-in function, the time returned is the time when the program was compiled; otherwise the function returns the time at run time.

TRANSLATE

Dialects - ansi, dec, ibm

Given a character-string argument, the TRANSLATE built-in function replaces occurrences of an old character with a corresponding translation character and returns the resulting string. The format is:

TRANSLATE(original,translation[,old-chars])

 
original

A character-string expression in which specific characters are to be translated.

translation

A character-string expression giving replacement characters for corresponding characters in old-chars.

old-chars

A character-string expression indicating which characters in the original are to be replaced. If old-chars is not specified, the default is COLLATE().

If the translation is shorter than old-chars, the translation is padded on the right with spaces to the length of old-chars before any translation occurs. If the translation is longer than old-chars, its excess characters (on the right) are ignored.

The following steps are performed for each character (beginning at the left) in the original:

  1. Let original(i) be the current character in the original string, and let result(i) be the corresponding character in the resulting string.
  2. Search old-chars for the leftmost occurrence of original(i).
  3. If old-chars does not contain original(i), then let result(i) equal original(i). Otherwise, let j equal the position of the leftmost occurrence of original(i) in old-chars, and let result(i) equal translation(j).
  4. Return to step 1.
Returned Value

The string returned is of type CHARACTER(length), where length is the length of the original string. If the original string is a null string, the returned value is a null string.

Examples

TRANSLATE_XM: PROCEDURE OPTIONS(MAIN);

 

DECLARE NEWSTRING CHARACTER(80) VARYING;

DECLARE TRANSLATION CHARACTER(128);

DECLARE I FIXED;

DECLARE COLLATE BUILTIN;

 

/* translate space to '0': */

NEWSTRING = TRANSLATE('1 2','0',' ');

PUT SKIP LIST(NEWSTRING);

 

/* translate letter 'F' to 'E': */

NEWSTRING = TRANSLATE('BFFLZFBUB','E','F');

PUT SKIP LIST(NEWSTRING);

 

/* change case of letters in sentence */

TRANSLATION = COLLATE;

DO I=RANK('A') TO RANK('Z'); /* replace upper with lower */

SUBSTR(TRANSLATION,I,1) = SUBSTR(COLLATE,I+32,1);

END;

 

DO I=RANK('a') TO RANK('z'); /* replace lower with upper */

SUBSTR(TRANSLATION,I,1) = SUBSTR(COLLATE,I-32,1);

END;

NEWSTRING =

TRANSLATE('THE QUICK BROWN fox JUMPS OVER THE LAZY dog',TRANSLATION);

PUT SKIP LIST(NEWSTRING);

 

END TRANSLATE_XM;

 

The first reference translates the string `1 2' to `102' The second reference translates `BFFLZFBUB' to `BEELZEBUB'. The third reference produces the following new sentence:

'the quick brown FOX jumps over the lazy DOG'

 

TRIM

Dialects - ansi, dec

The TRIM built-in function accepts a character string as an argument and returns a character string that consists of the input string with specified characters removed from the left and right. If you supply only one argument, TRIM removes blanks from the left and right of the argument. If you supply only the second argument, TRIM removes the specified characters from the left of the string and blanks from the right. If you supply both the second and third arguments, TRIM removes characters specified by those arguments from the left and right of the string, respectively.

The format of the TRIM built-in function is:

TRIM (input-string,[beginning-chars,end-chars])

 
input-string

A character-string variable or constant. This argument supplies the string from which characters are to be trimmed.

beginning-chars

A character-string variable or constant. This argument specifies characters to be trimmed from the left of the input string. If a character that is in the first position in the input string is also present anywhere in beginning-chars, that character is removed from the input string. This process is repeated until a character is encountered on the left of the input string that is not present in beginning-chars, or until the characters in the input string are exhausted.

end-chars

A character-string variable or constant. This argument specifies characters to be trimmed from the right of the input string. The process of removing characters from the right is identical to that of removing characters from the left, except that the character in the last position is examined.

The TRIM built-in function accepts either one or three arguments. Any of the arguments can consist of a null string; specifically, if beginning-chars or end-chars is null, no characters are removed from the corresponding end of the input string.

When only one argument is supplied, TRIM removes blanks from both ends of that argument. In other words, the following two expressions are equivalent:

TRIM(S)

TRIM(S,' ',' ')

 

Returned Value

The returned value is a character string with characters removed from the ends.

Examples

The following examples illustrate the use of the TRIM built-in function.

Text

Returned String

TRIM ('ABC')

'ABC'

TRIM(' ABC')

'ABC'

TRIM(' ABC ')

'ABC'

TRIM('ABC ')

'ABC'

TRIM(' ABCDEF','','E')

' ABCDEF'

TRIM(' ABCDEF','','FE')

' ABCD'

TRIM('ABCDEF','CADB','FE')

''

TRIM(' ABCDEF ','ABC ',' EDF')

''

TRIM('AAAABCCXCCDDDDEFFFF','AC','DF')

'BCCXCCDDDDE'

TRUNC

Dialects - ansi, dec, ibm

The TRUNC built-in function changes all fractional digits in an arithmetic expression x to zeros and returns the resulting integer value. Its format is:

TRUNC(x)

 
Returned Value

If x is a floating-point expression, the returned value is a floating-point value. If x is a fixed-point expression, the returned value is a fixed-point value with the same base as x. The value has the following attributes:

precision = min(31,p - q + 1)

scale factor = 0

Here, p and q are the precision and scale factor of x.

UNSPEC

Dialects - ansi, dec, ibm

The UNSPEC built-in function returns a bit string representing the internal coded value of the referenced variable, or a specified part of that variable. The variable can be an aggregate or a scalar variable of any type. The format of the function is:

UNSPEC(reference)

 
Returned Value

The returned value is a bit string whose length is the number of bits occupied by the referenced variable. The length of the bit string must be less than or equal to the maximum length for bit-string data. The returned bit string contains the contents of the storage of the referenced variable , the first bit in storage being the first bit in the returned value. The actual value may differ depending on the architecture of your platform. For example, the VAX and Alpha architecture store integers differently than the IBM architecture. Therefore, use the UNSPEC built-in function with caution when developing cross-platform software.

Note that if the referenced variable is a binary integer (FIXED BINARY), the first bit in the returned value is the lowest binary digit.

Examples

DECLARE X CHARACTER(2), Y BIT(16);

 

X = 'AB';

Y = UNSPEC(X);

DECLARE I FIXED BINARY(15);

I = 2;

PUT LIST(UNSPEC(I));

 

As a result of the first UNSPEC reference, Y contains the ASCII codes of 'A' and 'B'. The PUT LIST statement containing UNSPEC(I) prints the following string:

'0100000000000000'B

 

VARIANT

Dialects - ansi, dec

The VARIANT preprocessor built-in function returns a string representing the value of the variant qualifier in the command that invoked the compilation.

The format in a preprocessor expression is:

VARIANT()

 

The -T variant option permits specification of compilation variants. The value specified is available to the VARIANT preprocessor built-in function at compile time. The format of compilation variants is:

For example, if you want to compile a program with one of three different INCLUDE files, you can use the -T variant command qualifier to specify which file to include.

In the following example, the file SPECIAL.SRC is included in the program only if -T SPECIAL appears in the pl1 command line:

%IF VARIANT() = 'SPECIAL'

%THEN

%INCLUDE 'SPECIAL.SRC';

%IF VARIANT() = 'NONE'

%THEN;

 

No action is taken if -T NONE appears on the pli command line.

To specify a null variant, omit the -T option from the pli command line.

VERIFY

Dialects - ansi, dec, ibm

The VERIFY built-in function compares a string with a character-set string and verifies that all characters appearing in the string also appear in the character-set string. The function returns the value zero if they all appear. If not, the function returns a fixed-point binary integer that indicates the position of the first character in the string that is not present in the character-set string. The comparison is done character by character and left to right, and as soon as one nonmatching character is found in the first string, no more characters are compared. The function is case sensitive.

The format of the function is:

VERIFY(string,character-set-string[,starting-position])

 
string

A character-string expression representing the string to be checked.

character-set-string

A character-string expression containing the set of characters with which the characters in the first string are to be compared.

starting-position

A positive integer in the range 1 to n+1, where n is the length of the first string. It specifies the leftmost position in the first string to be compared with the character-set-string. (By default, the comparison starts at the left end of the first string.)

Examples
  1. STRING = 'HOW MUCH IS 1 PLUS 2';
    ALPHABET = 'abcdefghijklmnopqrstuvwxyz
    ABCDEFGHIJKLMNOPQRSTUVWXYZ ';
    A = VERIFY(STRING,ALPHABET);

The value of the variable ALPHABET is a string containing the 26 lowercase letters, the 26 uppercase letters, and the space character. The function returns a value of 13, indicating the position of the character `1', which is the first nonalphabetic and nonspace character in STRING.

  1. A = VERIFY(STRING,' ');

This example finds the first nonspace character in a string by using the space character as a test string. Note that constants can be used as the string parameters.

  1. NEWSTRING = 'ALL LETTERS';
    A = VERIFY(NEWSTRING,ALPHABET);

VERIFY returns a value of zero because all characters in the string NEWSTRING are present in the string ALPHABET.

  1. NEWSTRING = '9 LETTERS';
    A = VERIFY (NEWSTRING,ALPHABET,2);

The optional starting-position parameter specifies that the comparison begins at position 2 in NEWSTRING. VERIFY returns a value of zero because all characters beginning with the second character in the string NEWSTRING are present in the string ALPHABET. If the starting-position parameter had not been specified, VERIFY would have returned a value of 1, because the first character (`9') in NEWSTRING is not present in ALPHABET.

WARN

Dialects - ansi, dec

The WARN preprocessor built-in function returns the number of diagnostic warning messages issued during compilation up to that particular point in the source program. The format for the WARN built-in function is:

WARN();

 

The function returns a fixed result representing the number of compile-time warning messages that were issued up to the point at which the WARN built-in function was encountered.

Built-In Subroutines

Built-in subroutines are specific PL/I routines that provide various added capabilities. These routines can be used in a CALL statement. All arguments are evaluated as for normal subroutines.

The built-in subroutines are summarized in See . Summary of PL/I Built-In Subroutines , according to the following functional categories:

For more information on the PL/I subroutines in See . Summary of PL/I Built-In Subroutines , see the Kednos PL/I for UNIX User's Manual.

. Summary of PL/I Built-In Subroutines

Category

Routine Reference

Action

Dialect

Condition-handling

RESIGNAL()

Allows more processing of a signal.

dec,ansi

File-control

FLUSH(f)

Forces flushing of all buffers for file f.

dec,ansi

REWIND(f)

Resets file f to the beginning.

dec,ansi

Sorting

PLIRETC

Sets a return code. The Sort program examines this return code. You can also examine it in another PL/I program using the PLIRETV built-in function.

ibm

PLISRTA

An entry point of the Sort program.

ibm

PLISRTB

An entry point of the Sort program.

ibm

PLISRTC

An entry point of the Sort program.

ibm

PLISRTD

An entry point of the Sort program.

ibm

Pseudovariables

A pseudovariable can be used, in certain assignment contexts, in place of an ordinary variable reference. The following example assigns the character `A' to a one-character substring of S, beginning at the second character of S:

SUBSTR(S,2,1) = 'A';

 

A pseudovariable can be used wherever the following three conditions are true:

The principal contexts in which pseudovariables are used are:

Note that a pseudovariable cannot be used in preprocessor statements or in an argument list. In the following example, SUBSTR is not interpreted as a pseudovariable:

CALL P(SUBSTR(S,2,1));

 

Here, SUBSTR is interpreted as a built-in function reference, rather than as a pseudovariable. The actual argument passed to procedure P is a dummy argument containing the second character of string S.

See . Pseudovariables by Dialect lists the pseudovariables and the dialect in which they are valid:

. Pseudovariables by Dialect

Pseudovariable

Valid Dialect

INT

ansi, dec

ONSOURCE

ansi, dec, ibm

ONCHAR

ansi, dec, ibm

PAGENO

ansi, dec

POSINT

ansi, dec

STRING

ansi, dec, ibm

SUBSTR

ansi, dec, ibm

UNSPEC

ansi, dec, ibm

The next sections describe these pseudovariables in alphabetic order.

INT Pseudovariable

Dialects - ansi, dec

The INT pseudovariable assigns a signed integer value to specified storage. The format is:

INT(reference[,position[,length]]) = expression;

 
reference

A reference to connected storage. This reference must not be an array, structure, or named constant. If position and length are not specified, the length of the referenced storage must not exceed 32 bits. If it exceeds 32 bits, a fatal run-time error results.

position

A positive integer value that denotes the position of the first bit in the field. If omitted, position defaults to 1, signifying the first bit of the storage denoted by reference. If specified, position must satisfy the following condition:

1 <= position <= size(reference)

where size(reference) is the length in bits of the storage denoted by reference. A position equal to size(reference) implies a zero-length field.

length

An integer value in the range 0 through 32 that specifies the length of the field. If omitted, length is the number of bits from the bit denoted by position through the end of the storage denoted by reference. If specified, length must satisfy the following condition:

0<= position <= size(reference) - position

where size(reference) is the length in bits of the storage denoted by reference.

The INT pseudovariable is valid only in an assignment statement. You cannot use it as the target of an input statement or in other instances where pseudovariables are normally acceptable.

The expression to be assigned to the pseudovariable is first converted to the data type FIXED BINARY (31). Then, the internal representation of the resulting integer value is assigned to the storage specified by the arguments to INT. If the representation of the value is too large for assignment to the storage, the most significant bits of the integer are removed and no error is signaled.

Examples

DECLARE F FLOAT INITIAL (123.45);

INT(F,8,8) = 25; /* Alter the exponent */

PUT SKIP LIST (F); /* New value */

 

In this example, the INT pseudovariable is used to modify the exponent field of a floating-point variable. This example prints the following value:

9.5102418E-32

 

Proper interpretation of this result requires understanding of the internal representation of floating-point numbers. As such, this example is only valid on the Alpha hardware.

The next example demonstrates how the INT pseudovariable treats cases in which the value is too large for the specified storage:

INTOVER: PROCEDURE OPTIONS (MAIN);

 

DECLARE I15 FIXED BINARY (15),

I31 FIXED BINARY (31);

 

ON FIXEDOVERFLOW PUT SKIP LIST ('FIXEDOVERFLOW signaled');

I31 = -876543; /* Too big for I15 */

I15 = I31; /* Arithmetic assignment */

INT(I15) = I31; /* No error signaled */

PUT SKIP LIST (I15);

END;

 

This example produces the following output:

FIXEDOVERFLOW signaled

-24575

 

The arithmetic assignment to I15 signals FIXEDOVERFLOW because the value of I31 is outside the range of a FIXED BINARY (15) variable. However, the assignment using the INT pseudovariable does not signal an error; it just copies the low-order 16 bits of the value of I31 into the storage for I15.

ONCHAR Pseudovariable

Dialects - ansi, dec, ibm

The ONCHAR pseudovariable can be used to replace the single character in the ONSOURCE value that caused a CONVERSION condition to be raised. An attempt to assign a value to the ONCHAR pseudovariable when there is no active CONVERSION condition causes the ERROR condition to be raised.

The format of the pseudovariable is:

ONCHAR()

 

See See CONVERSION Condition for more information about CONVERSION condition name.

ONSOURCE Pseudovariable

Dialects - ansi, dec, ibm

The ONSOURCE pseudovariable can be used to replace the entire ONSOURCE value that caused a CONVERSION condition to be raised. An attempt to assign a value to the ONSOURCE pseudovariable when there is no active CONVERSION condition causes the ERROR condition to be raised.

The format of the pseudovariable is:

ONSOURCE()

The ONSOURCE value is a fixed-length string value. An assignment of a longer string is truncated, and an assignment of a shorter string is padded with blanks on the right to the necessary length.

See See CONVERSION Condition for more information about CONVERSION condition name.

PAGENO Pseudovariable

Dialects - ansi, dec

The PAGENO pseudovariable refers to the page number of the referenced print file. Assignment to the pseudovariable modifies the current page number. The format of the PAGENO pseudovariable in an assignment statement is:

PAGENO(reference) = expression;

 
reference

A reference to a file for which the page number is to be set. The file must be open and must be a print file.

PAGENO(reference) is a FIXED BINARY(15) variable; however, values assigned to it must not be negative.

POSINT Pseudovariable

Dialects - ansi, dec

The POSINT pseudovariable assigns an integer value to specified storage. The format is:

POSINT(expression1[,position[,length]]) = expression2;

 
expression1

A reference to connected storage. This reference must not be an array, structure, or named constant. If position and length are not specified, the length of the referenced storage must not exceed 32 bits. (If it exceeds 32 bits, a fatal run-time error results.)

position

A positive integer value that denotes the position of the first bit in the field. If omitted, position defaults to 1, signifying the first bit of the storage denoted by expression1. If specified, position must satisfy the following condition:

1 <= position <= size(expression1)

Size(expression1) is the length in bits of the storage denoted by expression1. A position equal to size(expression1) implies a zero-length field.

length

An integer value in the range 0 through 32 that specifies the length of the field. If omitted, length is the number of bits from the bit denoted by position through the end of the storage denoted by expression1. If specified, length must satisfy the following condition:

0<= position <= size(expression1) - position

Size(expression1) is the length in bits of the storage denoted by expression1.

expression2

Any expression that evaluates to an integer.

The POSINT pseudovariable is valid only in an assignment statement. It cannot be used as the target of an input statement or in other instances where pseudovariables are normally acceptable.

The expression to be assigned to the pseudovariable is first converted to the data type FIXED BINARY (31). Then, the internal representation of the resulting integer value is assigned to the storage specified by the arguments to POSINT. If the representation of the value is too large for assignment to the storage, the most significant bits of the integer are removed and no error is signaled.

The POSINT pseudovariable is identical in operation and use to the INT pseudovariable. For examples, see INT pseudovariable.

STRING Pseudovariable

Dialects - ansi, dec, ibm

The STRING pseudovariable interprets a suitable reference as a reference to a fixed-length string. By using it, you can modify an entire aggregate with a single string assignment or assign the aggregate to a pictured variable as if it were a character-string variable. The format of the pseudovariable (in an assignment statement) is:

STRING(reference) = expression;

reference

A reference to a variable that is suitable for character-string (or bit-string) overlay defining (see See Matching by Overlay Defining and See Rules for Overlay Defining ). The length of the pseudovariable is equal to the total number of characters (or bits) in the scalar or aggregate denoted by the reference. This length must be less than or equal to the maximum length for character-string (or bit-string) data.

Assignment to the STRING pseudovariable modifies the entire storage denoted by the reference.

Examples

STRING_PSD_EXAMPLE: PROCEDURE;

 

DECLARE 1 NAME,

2 FIRST CHARACTER(10),

2 MIDDLE_INITIAL CHARACTER(3)

2 LAST CHARACTER(10);

 

STRING(NAME)='FRANKLIN D. ROOSEVELT';

/* NAME.FIRST - 'FRANKLIN D';

NAME.MIDDLE_INITIAL = '. R';

NAME.LAST = 'OOSEVELT '; */

 

END STRING_PSD_EXAMPLE;

DECLARE 1 FLAGS,

2 (A,B,C) BIT(1);

STRING(FLAGS) = '0'B; /* sets all three flags false */

DECLARE P PICTURE /Z.ZZZV,ZZDB';

 

GET EDIT (STRING(P)) (A(10));

/* assigns 10 characters from SYSIN to P,

without conversion */

 

SUBSTR Pseudovariable

Dialects - ansi, dec, ibm

The SUBSTR pseudovariable refers to a substring of a specified string variable reference. Assignment to the pseudovariable modifies only the substring. The format of the pseudovariable (in an assignment statement) is:

SUBSTR(reference,position[,length]) = expression;

 
reference

A reference to a bit- or character-string variable. If the reference is to a varying-length character string, the substring defined by the position and length arguments must be within the current value of the string. Assignment to the SUBSTR pseudovariable does not change the length of a varying string.

position

An integer expression indicating the position of the first bit or character in the substring. The length must satisfy the following condition:

1 <= position <= LENGTH(reference) + 1

length

An integer expression that indicates the length of the substring. If unspecified, length is:

1 <= position <= LENGTH(reference) - position + 1

In other words, if length is not specified, the substring begins at the indicated position and ends at the end of the string. The length must satisfy the following condition:

length = LENGTH(reference) - position + 1

Note that the following two lines are equivalent:

SUBSTR(r,p,l) = v;

r = SUBSTR(r,1,p-1)||SUBSTR(v||SUBSTR(r,p+length(v)),1,l)

||SUBSTR(r,p+l);

 

Assignment to the SUBSTR pseudovariable does not change the length of reference.

Examples

DECLARE (NAME,NEW_NAME) CHARACTER(20) VARYING;

NAME = 'ISAK DINESEN';

NEW_NAME = NAME;

SUBSTR(NEW_NAME,4) = 'AC NEWTON';

/* NEW_NAME = 'ISAAC NEWTON' */

 

UNSPEC Pseudovariable

Dialects - ansi, dec, ibm

The UNSPEC pseudovariable interprets a reference to a scalar or aggregate element variable as a reference to a bit string. The format of the pseudovariable (in an assignment statement) is:

UNSPEC(reference) = expression;

 
reference

A reference to a scalar or aggregate variable. The length of its storage in bits must be less than or equal to the maximum length for bit-string data.

In an assignment of the form

UNSPEC(reference) = expression;

 

the value of the expression is converted to a bit string if necessary and copied into the storage of the reference. The value is truncated or zero-extended as necessary to match the length of the storage.

Examples

DECLARE X FIXED BINARY (15);

UNSPEC(X) = '110'B;

 

The use of the constant '110'b, which appears to be 6 in binary, actually assigns 3 to X. The two low-order bits of X (that is, X's first two bits of storage) are set; all other bits of X are cleared.

UNSPEC(X,1,3) = '101'B;

 

The optional parameters position and length are specified, causing the first three, low-order bits of the variable X to be assigned the value '101'B; the other bits are unaffected.

 

Alphabetic Summary of Keywords

See . PL/I Keywords summarizes all of the keywords. This alphabetic summary includes both the options for the ENVIRONMENT attribute and the options for I/O statements.

Some keywords are valid in one dialect but not others, or is used differently in different dialects. This is indicated, where appropriate, by the name of the dialect in parentheses after the explanation in the Use column.

. PL/I Keywords

Keyword

Abbreviation

Use

A

 

Format item

ABS

 

Preprocessor built-in function, Built-in function

ACOS

 

Built-in function

%ACTIVATE

 

Preprocessor statement

ADD

 

Built-in function

ADDR

 

Built-in function

ALIGNED

 

Attribute

ALL

 

Built-in function (ibm dialect only), Stream I/O option, accepted but ignored (ibm dialect only)

ALLOCATE

ALLOC

Statement

ALLOCATION

ALLOCN

Built-in function

ANY

 

Attribute, Built-in function (ibm dialect only)

ANYCONDITION

 

Condition name

APPEND

 

Environment option

AREA

 

Data attribute, Condition name

ASIN

 

Built-in function

ATAN

 

Built-in function

ATAND

 

Built-in function

ATANH

 

Built-in function

ATTENTION

ATTN

Condition

AUTOMATIC

AUTO

Attribute

B

 

Format item

B1

 

Format item

B2

 

Format item

B3

 

Format item

B4

 

Format item

BACKUP_DATE

 

Environment option

BASED

 

Attribute

BATCH

 

Environment option

BEGIN

 

Statement

BINARY

BIN

Data attribute, Built-in function

BIT

 

Data attribute, Built-in function

BLKSIZE

 

Environment option (ibm dialect only)

BLOCK_BOUNDARY_
FORMAT

 

Environment option

BLOCK_IO

 

Environment option

BLOCK_SIZE

 

Environment option

BOOL

 

Built-in function

BUFFERED

BUF

Attribute, Option of OPEN statement (ibm dialect only)

BUCKET_SIZE

 

Environment option

BUILTIN

 

Attribute

BY

 

DO option

BYTE

 

Preprocessor built-in function, Built-in function (dec and ansi dialects only)

BYTESIZE

 

Built-in function (dec and ansi dialects only)

C

 

Option to entry statement.

CALL

 

Statement

CANCEL_CONTROL_O

 

PUT OPTIONS option

CARRIAGE_RETURN_
FORMAT

 

Environment option

CEIL

 

Built-in function

CHARACTER

CHAR

Data attribute, Built-in function

CHECK

 

Statement, Condition prefix (ibm)

CLOSE

 

Statement

COLLATE

 

Built-in function

COLUMN

COL

Format item

CONDITION

COND

Attribute, Condition name

CONSECUTIVE

 

Environment option (ibm dialect only)

CONTIGUOUS

 

Environment option

CONTIGUOUS_BEST_TRY

 

Environment option

CONTROLLED

CTL

Attribute

CONVERSION

CONV

Condition name

COPY

 

Preprocessor built-in function, Built-in function (dec and ansi dialects only)

COS

 

Built-in function

COSD

 

Built-in function

COSH

 

Built-in function

CREATION_DATE

 

Environment option

CURRENT_POSITION

 

Environment option

CURRENTSTORAGE

CSTG

Built-in function (ibm dialect only)

DATE

 

Preprocessor built-in function, Built-in function

DATETIME

 

Preprocessor built-in function, Built-in function (dec and ansi dialects only)

%DEACTIVATE

 

Preprocessor statement

DECIMAL

DEC

Data attribute, Built-in function

%DECLARE

%DCL

Preprocessor statement

DECLARE

DCL

Statement

DECODE

 

Preprocessor built-in function, Built-in function (dec and ansi dialects only)

DEFAULT_FILE_NAME

 

Environment option

DEFERRED_WRITE

 

Environment option

DEFINED

DEF

Attribute

DELETE

 

Statement, Environment option

DIMENSION

DIM

Attribute, Built-in function

DIRECT

 

File attribute, OPEN option

DIVIDE

 

Built-in function

%DO

 

Preprocessor statement

DO

 

Statement, GET and PUT I/O specifier

E

 

Format item

EDIT

 

GET option, PUT option

%ELSE

 

Keyword of the %IF statement

ELSE

 

Keyword of the IF statement

EMPTY

 

Built-in function

ENCODE

 

Preprocessor built-in function, Built-in function (dec and ansi dialects only)

%END

 

Preprocessor statement

END

 

Statement

ENDFILE

 

Condition name

ENDPAGE

 

Condition name

ENTRY

 

Statement, Attribute

ENVIRONMENT

ENV

File attribute, OPEN option, CLOSE option

ERF

 

Built-in function (ibm dialect only)

ERFC

 

Built-in function (ibm dialect only)

%ERROR

 

Preprocessor statement

ERROR

 

Condition name, Preprocessor built-in function

EVERY

 

Built-in function (dec and ansi dialects only)

EXP

 

Built-in function

EXPIRATION_DATE

 

Environment option

EXTENSION_SIZE

 

Environment option

EXTERNAL

EXT

Attribute

FAST_DELETE

 

DELETE OPTIONS option

%FATAL

 

Preprocessor statement

FILE

 

Attribute, Option of the GET, PUT, READ, WRITE, DELETE, REWRITE, OPEN, and CLOSE statements

FILE_ID

 

Environment option

FILE_ID_TO

 

Environment option

FILE_SIZE

 

Environment option

FINISH

 

Condition name

FIXED

 

Data attribute, Built-in function

FIXEDOVERFLOW

FOFL

Condition name

FIXED_CONTROL_FROM

 

REWRITE OPTIONS option, WRITE OPTIONS option

FIXED_CONTROL_SIZE

 

Environment option

FIXED_CONTROL_SIZE_
TO

 

Environment option

FIXED_CONTROL_TO

 

READ OPTIONS option

FIXED_LENGTH_RECORDS

 

Environment option

FLOAT

 

Data attribute, Built-in function

FLOOR

 

Built-in function

FLOW

 

Stream I/O option, accepted but ignored (ibm dialect only)

FLUSH

 

Built-in subroutine (dec and ansi dialects only)

FORMAT

 

Statement

FREE

 

Statement

FROM

 

WRITE option, REWRITE option

GET

 

Statement

GLOBALDEF

 

Attribute

GLOBALREF

 

Attribute

%GOTO

 

Preprocessor statement

GOTO

GO TO

Statement

GROUP_PROTECTION

 

Environment option

HBOUND

 

Built-in function

HIGH

 

Built-in function

IDENT

 

PROCEDURE OPTIONS option

%IF

 

Preprocessor statement

IF

 

Statement

IGNORE

 

Option to the READ statement (ibm dialect only)

IGNORE_LINE_MARKS

 

Environment option

IN

 

ALLOCATE option, FREE option

%INCLUDE

 

Preprocessor statement

INDEX

 

Preprocessor built-in function, Built-in function

INDEXED

 

Environment option

INDEX_NUMBER

 

DELETE OPTIONS option, READ OPTIONS option, REWRITE OPTIONS option, Environment option

%INFORM

 

Preprocessor statement

INFORM

 

Preprocessor built-in function (dec and ansi dialects only)

INITIAL

INIT

Attribute

INITIAL_FILL

 

Environment option

INPUT

 

File attribute, OPEN option

INT

 

Built-in function (dec and ansi dialects only), Pseudovariable

INTERNAL

INT

Attribute

INTO

 

READ option

KEY

 

Condition name, READ option, DELETE option, REWRITE option

KEYED

 

File attribute, OPEN option

KEYFROM

 

WRITE option

KEYTO

 

READ option

LABEL

 

Attribute

LBOUND

 

Built-in function

LEAVE

 

Statement

LENGTH

 

Preprocessor built-in function, Built-in function

LIKE

 

Attribute

LINE

 

PUT option, Preprocessor built-in function, Format item

LINENO

 

Built-in function

LINESIZE

 

OPEN option

LIST

 

Attribute, GET option, PUT option

LOCATE

 

Statement (ibm dialect only)

LOCK_ON_READ

 

READ OPTIONS option

LOCK_ON_WRITE

 

READ OPTIONS option

LOG

 

Built-in function

LOG10

 

Built-in function

LOG2

 

Built-in function

LOW

 

Built-in function

LTRIM

 

Preprocessor built-in function, Built-in function

MAIN

 

PROCEDURE OPTIONS option

MANUAL_UNLOCKING

 

READ OPTIONS option

MATCH_GREATER

 

DELETE OPTIONS option, READ OPTIONS option, REWRITE OPTIONS option

MATCH_GREATER_EQUAL

 

DELETE OPTIONS option, READ OPTIONS option, REWRITE OPTIONS option

MATCH_NEXT

 

DELETE OPTIONS option, READ OPTIONS option, REWRITE OPTIONS option

MATCH_NEXT_EQUAL

 

DELETE OPTIONS option, READ OPTIONS option, REWRITE OPTIONS option

MAX

 

Preprocessor built-in function, Built-in function

MAXIMUM_RECORD_
NUMBER

 

Environment option

MAXIMUM_RECORD_
SIZE

 

Environment option

MAXLENGTH

 

Built-in function (dec and ansi dialects only)

MEMBER

 

Attribute

MIN

 

Preprocessor built-in function, Built-in function

MOD

 

Preprocessor built-in function, Built-in function

MULTIBLOCK_COUNT

 

Environment option

MULTIBUFFER_COUNT

 

Environment option

MULTIPLY

 

Built-in function

NAME

 

Condition (ibm dialect only), Condition prefix (ibm dialect only)

NOCHECK

 

Condition prefix (ibm dialect only)

NOCONVERSION

NOCONV

Condition prefix (ibm dialect only)

NOFIXEDOVERFLOW

NOFOFL

Condition prefix (ibm dialect only)

NOLOCK

 

READ OPTIONS option

NONEXISTENT_RECORD

 

READ OPTIONS option

NONRECURSIVE

 

PROCEDURE option, ENTRY option

NONVARYING

NONVAR

Attribute

NOOVERFLOW

 

Condition prefix (ibm dialect only)

NOSIZE

 

Condition prefix (ibm dialect only)

NOSTRINGRANGE

NOSTRG

Condition prefix (ibm dialect only)

NOSTRINGSIZE

NOSTRZ

Condition prefix (ibm dialect only)

NOSUBSCRIPTRANGE

NOSUBRG

Condition prefix (ibm dialect only)

NOZERODIVIDE

NOZDIV

Condition prefix (ibm dialect only)

NORESCAN

 

Option of the %ACTIVATE statement

NO_ECHO

 

GET OPTIONS option

NO_FILTER

 

GET OPTIONS option

NO_SHARE

 

Environment option

NULL

 

Built-in function

OFFSET

 

Data attribute

ON

 

Statement

ONCHAR

 

Built-in function, Pseudovariable

ONCODE

 

Built-in function

ONFILE

 

Built-in function

ONKEY

 

Built-in function

ONLOC

 

Built-in function (ibm dialect only)

ONSOURCE

 

Built-in function, Pseudovariable

OPEN

 

Statement

OPTIONS

 

File attribute, Option of the GET, PUT, READ, WRITE, DELETE, REWRITE, and PROCEDURE statements, and DECLARE variable name CHARACTER statement

OPTIONAL

 

Attribute (dec and ansi dialects only)

OUTPUT

 

File attribute, OPEN option

OVERFLOW

OFL

Condition name, Condition prefix (ibm)

OWNER_GROUP

 

Environment option

OWNER_ID

 

Environment option

OWNER_MEMBER

 

Environment option

OWNER_PROTECTION

 

Environment option

P

 

Format item

%PAGE

 

Preprocessor statement

PAGE

 

PUT option, Format item

PAGENO

 

Built-in function, Pseudovariable

PAGESIZE

 

OPEN option

PARAMETER

PARM

Attribute

PICTURE

PIC

Data attribute

PLIRETC

 

Built-in subroutine (ibm dialect only)

PLIRETV

 

Built-in function (ibm dialect only)

PLISRTA

 

Built-in subroutine (ibm dialect only)

PLISRTB

 

Built-in subroutine (ibm dialect only)

PLISRTC

 

Built-in subroutine (ibm dialect only)

PLISRTD

 

Built-in subroutine (ibm dialect only)

POINTER

PTR

Data attribute, Built-in function

POSINT

 

Built-in function, Pseudovariable

POSITION

POS

Attribute

PRECISION

PREC

Attribute, Built-in function (ibm dialect only)

PRINT

 

File attribute, OPEN option

PRINTER_FORMAT

 

Environment option

%PROCEDURE

%PROC

Preprocessor statement

PROCEDURE

PROC

Statement

*PROCESS

 

Statement (accepted but ignored)

PROD

 

Built-in function

PROMPT

 

GET OPTIONS option

PURGE_TYPE_AHEAD

 

GET OPTIONS option

PUT

 

Statement

R

 

Format item

RANK

 

Preprocessor built-in function, Built-in function (dec and ansi dialects only)

READ

 

Statement

READONLY

 

Attribute

READ_AHEAD

 

Environment option

READ_CHECK

 

Environment option

READ_REGARDLESS

 

READ OPTIONS option

RECORD

 

File attribute, OPEN option, Condition (ibm), Condition prefix (ibm dialect only)

RECORD_ID

 

DELETE OPTIONS option, READ OPTIONS option, REWRITE OPTIONS option

RECORD_ID_ACCESS

 

Environment option

RECORD_ID_TO

 

READ OPTIONS option, REWRITE OPTIONS option, WRITE OPTIONS option

RECSIZE

 

Environment option (ibm dialect only)

RECURSIVE

 

PROCEDURE option, ENTRY option

REFER

 

Attribute

REFERENCE

 

Attribute (accepted but ignored)

REGIONAL

 

Environment option (ibm dialect only) Accepted but ignored.

REPEAT

 

DO option, Built-in function (ibm dialect only)

%REPLACE

 

Preprocessor statement

RESCAN

 

Option of the %ACTIVATE statement

RESIGNAL

 

Built-in subroutine (dec and ansi dialects only)

RETRIEVAL_POINTERS

 

Environment option

%RETURN

 

Preprocessor statement

RETURN

 

Statement

RETURNS

 

Entry attribute, PROCEDURE option, ENTRY option

REVERSE

 

Preprocessor built-in function, Built-in function (dec and ansi dialects only)

REVERT

 

Statement

REVISION_DATE

 

Environment option

REWIND

 

Built-in subroutine (dec and ansi dialects only)

REWIND_ON_CLOSE

 

Environment option

REWIND_ON_OPEN

 

Environment option

REWRITE

 

Statement

ROUND

 

Built-in function

SCALARVARYING

 

Environment option

SEARCH

 

Preprocessor built-in function, Built-in function (dec and ansi dialects only)

SELECT

 

Statement

SEQUENTIAL

SEQL

File attribute, OPEN option

SET

 

READ option, ALLOCATE option

SHARED_READ

 

Environment option

SHARED_WRITE

 

Environment option

SIGN

 

Preprocessor built-in function, Built-in function

SIGNAL

 

Statement

SIN

 

Built-in function

SIND

 

Built-in function

SINH

 

Built-in function

SIZE

 

Built-in function (dec and ansi dialects only), Condition, Condition prefix (ibm dialect only)

SKIP

 

GET option, PUT option, Format item

SNAP

 

Option of PUT statement, accepted but ignored (ibm dialect only)

SOME

 

Built-in function (dec and ansi dialects only)

SPOOL

 

Environment option

SQRT

 

Built-in function

STATEMENT

 

Option of the %PROCEDURE statement

STATIC

 

Attribute

STOP

 

Statement

STORAGE

 

Condition name, Condition prefix (ibm dialect only), Built-in function (ibm dialect only)

STREAM

 

File attribute, OPEN option

STRING

 

GET option, PUT option, Built-in function, Pseudovariable

STRINGRANGE

STRG

Condition, Condition prefix (ibm dialect only)

STRINGSIZE

STRZ

Condition (ibm dialect only), Condition prefix (ibm dialect only)

STRUCTURE

 

Attribute

SUBSCRIPTRANGE

SUBRG

Condition name, Condition prefix (ibm dialect only)

SUBSTR

 

Preprocessor built-in function, Built-in function, Pseudovariable

SUBTRACT

 

Built-in function (dec and ansi dialects only)

SUM

 

Built-in function

SUPERSEDE

 

Environment option

SYSIN

 

Default input file

SYSPRINT

 

Default output file

SYSTEM

 

ON statement option

SYSTEM_PROTECTION

 

Environment option

TAB

 

Format item

TAN

 

Built-in function

TAND

 

Built-in function

TANH

 

Built-in function

TEMPORARY

 

Environment option

%THEN

 

Keyword of the %IF statement

THEN

 

Keyword of the IF statement

TIME

 

Built-in function

TIMEOUT_PERIOD

 

READ OPTIONS option

TITLE

 

OPEN option

TO

 

DO option

TRANSLATE

 

Preprocessor built-in function, Built-in function

TRANSMIT

 

Condition (ibm dialect only), Condition prefix (ibm dialect only)

TRIM

 

Preprocessor built-in function, Built-in function (dec and ansi dialects only)

TRUNC

 

Built-in function

TRUNCATE

 

Attribute, Environment option

UNALIGNED

UNAL

Attribute

UNBUFFERED

UNBUF

Attribute, Option of OPEN statement (IBM ONLY)

UNDEFINEDFILE

UNDF

Condition name, Condition prefix (ibm dialect only)

UNDERFLOW

 

Condition name, Condition prefix (ibm dialect only)

UNION

 

Attribute

UNLOCK

 

Statement, accepted but ignored (ibm dialect only)

UNSPEC

 

Built-in function, Pseudovariable

UNTIL

 

DO option

UPDATE

 

File attribute, OPEN option

USER_OPEN

 

Environment option

VALUE

VAL

Attribute

VARIABLE

 

Attribute, OPTIONS option

VARIANT

 

Preprocessor built-in function (dec and ansi dialects only)

VARYING

VAR

Attribute

VAXCONDITION

 

Condition name, Condition prefix (ibm dialect only)

VERIFY

 

Preprocessor built-in function, Built-in function

WAIT_FOR_RECORD

 

READ OPTIONS option

%WARN

 

Preprocessor statement

WARN

 

Preprocessor built-in function (dec and ansi dialects only)

WHEN

 

Keyword of the SELECT statement

WHILE

 

DO option

WORLD_PROTECTION

 

Environment option

WRITE

 

Statement

WRITE_BEHIND

 

Environment option

WRITE_CHECK

 

Environment option

X

 

Format item

ZERODIVIDE

ZDIV

Condition name, Condition prefix (ibm)

 

Dialect Differences

This appendix describes the differences between the various Kednos PL/I for UNIX dialects. The dialects are specified on the command line, using the -D dialect option. Legal dialects are dec (the default), ibm, and ansi. (For details on specifying command line options, see the Kednos PL/I for UNIX User's Manual.)

This manual and the Kednos PL/I for UNIX User's Manual contain detailed information on each of the dialect-specific features in the following summary. This appendix provides a concise listing of all the features, and provides references to the chapter or manual containing more information.

Data Declarations

When you declare data without specifying all the attributes, Kednos PL/I for UNIX applies default values. These values differ depending on the dialect you specify. Default values are listed in See , in the sections describing the specific attributes.

Data Types

Label data can have a subscript. If you specify the ibm dialect, this subscript can have multiple dimensions, up to a maximum of seven. See See for an example of multiply dimensioned label array constants.

Condition Handling

See and See contains details on format and usage of condition prefixes. See contains descriptions of the specific ON conditions.

Condition Prefixes

Condition prefixes are supported for the ibm dialect only.

ON Conditions

The following conditions are supported only in the ibm dialect of Kednos PL/I for UNIX:

ATTENTION, CHECK, NAME, RECORD, SIZE, STRINGSIZE, TRANSMIT

Return Values for Condition Signals

IBM and Digital implementations of PL/I return different values when certain conditions are signalled. Kednos PL/I for UNIX returns the values appropriate for the specified dialect. The ansi dialect returns the same values as the dec dialect.

Sort Support

The ibm dialect of Kednos PL/I for UNIX provides an interface to the separately licensed SyncSort application. The PLIRETC, PLISRTA, PLISRTB, PLISRTC and PLISRTD subroutines are used to implement sort support.

Record and Stream I/O

The ibm dialect of Kednos PL/I for UNIX supplies sevaral record I/O (file handling) features to enhance compatability. The following features are supported in the ibm dialect only:

See See and the Kednos PL/I for UNIX User's Manual for more information on these features.

Many other I/O keywords are either accepted but ignored or are recognized for purposes of giving an appropriate error message. These are listed in See .

The dec and ibm dialects support different ENVIRONMENT options and use them differently in statements; the ibm dialect allows them only in the file declaration. These differences are noted in See and the Kednos PL/I for UNIX User's Manual. The ansi dialect provides the same support as the dec dialect.

The file symbol "SYSOUT" is supported in the dec and ansi dialects; the file symbols "SYSPRINT" and "SYSIN" are supported in dec, ansi, and ibm dialects.

The OPTIONS keyword is supported on record and stream I/O statements in the ansi and dec dialects.

Built-in Functions

The following built-in functions are available in only the dec and ansi dialects:

BYTE, BYTESIZE, COPY, DATETIME, DECODE, ENCODE, ERROR, EVERY, INFORM, INT, MAXLENGTH, POSINT, RANK, REVERSE, SEARCH, SIZE, SOME, SUBTRACT, TRIM, VARIANT, WARN

The following built-in functions are available in the ibm dialect only:

ALL, ANY, COUNT, CURRENTSTORAGE, ERF, ERFC, ONLOC, PLIRETV, PRECISION, REPEAT, STORAGE

All other built-in functions are available in all dialects.

Built-in Subroutines

The FLUSH, RESIGNAL and REWIND subroutines are available in the dec and ansi dialects.

The PLIRETC, PLISRTA, PLISRTB, PLISRTC and PLISRTD subroutines are available in the ibm dialect.

 

Compatibility with PL/I Standards

This appendix describes the differences between Kednos PL/I for UNIX and the various PL/I language standards that are currently in force.

Kednos PL/I for UNIX is a strict superset of the ANSI X3.74-1981 PL/I General Purpose Subset and provides most of the features of the new ANSI X3.74-1987 PL/I General Purpose Subset and many of the features of the ANSI X3.53-1976 (full) PL/I language standard. Kednos PL/I for UNIX provides the SAA tm Common Programming Interface of IBM, compatibility with Digital (VAX PL/I, DEC PL/I) and other dialects of PL/I (such as LIANT and Stratus PL/I).

Relation to the 1981 PL/I General-Purpose Subset

The 1981 PL/I General-Purpose Subset (ANSI X3.74-1981) was designed to be useful in scientific, commercial, and systems programming, especially on small and medium-size computer systems. Among the primary goals of the design of the subset were the following:

The essential elements of the subset are described below. These descriptions are extracted from the ANSI X3.74-1981 standard.

Program Structure

The General-Purpose Subset includes a complete character set, with comments, identifiers, decimal arithmetic constants, and simple string constants.

Begin blocks and DO-groups are included in the subset. Each block or group in the program must be terminated with an END statement.

Program Control

The following program control statements are included in the subset: CALL, RETURN, IF, DO, GOTO, null, STOP, ON, REVERT, and SIGNAL.

The DO statement options supported are TO, BY, WHILE, and REPEAT.

An IF statement can contain unlabeled THEN and ELSE clauses.

An ON statement can specify a single condition. The condition names supported are ERROR, ENDFILE, ENDPAGE, FIXEDOVERFLOW, KEY, OVERFLOW, UNDEFINEDFILE, UNDERFLOW, and ZERODIVIDE.

Storage Control

The subset includes the assignment statement and the assignment of array and structure variables whose dimensions and data types match. The subset also permits aggregate promotion, that is, the assignment of a scalar expression to every element or member of an aggregate variable.

In the subset, only static variables can be initialized.

The ALLOCATE statement with the SET option and the FREE statement are included in the subset.

Input/Output

The I/O statements are:

  • OPEN and CLOSE
  • READ, WRITE, DELETE, and REWRITE for record I/O
  • GET and PUT, with FILE, STRING, EDIT, LIST, PAGE, SKIP, and LINE options for stream I/O

The file attributes, specified in DECLARE or OPEN, are DIRECT, ENVIRONMENT, INPUT, KEYED, OUTPUT, PRINT, RECORD, SEQUENTIAL, STREAM, and UPDATE.

The FORMAT statement is included. The format items are E, F, P, A, B, X, R, PAGE, SKIP, COLUMN, TAB, and LINE.

Attributes and Pictures

The DECLARE statement is included in the subset. All names must be declared, either by means of a DECLARE statement or by means of a label prefix.

The attributes supported are as follows: ALIGNED, AUTOMATIC, BASED, BINARY, BIT, BUILTIN, CHARACTER, DECIMAL, DEFINED, DIRECT, ENTRY, ENVIRONMENT, EXTERNAL, FILE, FIXED, FLOAT, INITIAL, INPUT, INTERNAL, KEYED, LABEL, OPTIONS, OUTPUT, PICTURE, POINTER, PRINT, RECORD, RETURNS, SEQUENTIAL, STATIC, STREAM, UPDATE, VARIABLE, and VARYING.

The picture characters included are CR, DB, S, V, Z, 9,-, +, $, and *. The picture insertion characters (. , / B) are also included.

Built-In Functions and Pseudovariables

The built-in functions in the subset are as follows: ABS, ACOS, ADDR, ASIN, ATAN, ATAND, ATANH, BINARY, BIT, BOOL, CEIL, CHARACTER, COLLATE, COPY, COS, COSD, COSH, DATE, DECIMAL, DIMENSION, DIVIDE, EXP, FIXED, FLOAT, FLOOR, HBOUND, INDEX, LBOUND, LENGTH, LINENO, LOG, LOG2, LOG10, MAX, MIN, MOD, NULL, ONCODE, ONFILE, ONKEY, PAGENO, ROUND, SIGN, SIN, SIND, SINH, SQRT, STRING, SUBSTR, TAN, TAND, TANH, TIME, TRANSLATE, TRUNC, UNSPEC, and VERIFY.

The pseudovariables are PAGENO, STRING, SUBSTR, and UNSPEC.

Expressions

The subset supports all infix and prefix operators, the locator qualifier, parenthesized expressions, subscripts, and function references. Implicit conversion from one data type to another is restricted to those contexts in which the conversion is likely to produce the desired results.

198x PL/I General-Purpose Subset Features Supported

The 198x PL/I General-Purpose Subset (ANSI X3.74-198x) was designed to extend the previous subset standard on the basis of experience with subset implementations and the desire for more capabilities in subset-conforming implementations.

The following sections describe features in this standard that have been implemented to date in Kednos PL/I for UNIX.

Lexical Constructs

The character pair /* is permitted within comments.

Both uppercase and lowercase characters are permitted in source programs.

No space is required after the P for picture constants.

Program Control

RETURNS(CHAR(*)) is supported.

The statements following THEN and ELSE can be labeled.

The NONRECURSIVE procedure option is supported.

The SELECT and LEAVE statements are supported.

The UNTIL clause for DO groups and clauses is supported.

The AREA, CONDITION, CONVERSION, FINISH, and STORAGE conditions are supported.

Multiple conditions can be specified for ON and REVERT.

The SYSTEM option of the ON statement is supported.

Storage Control

The IN option can be used for the ALLOCATE and FREE statements, and language controlled allocation in areas is supported.

The SET option is optional for ALLOCATE if the based variable being allocated was declared with a base pointer.

The ALLOCATE and FREE statements can specify a comma list of items.

String assignment can have the source and target overlapped.

Input/Output

Expressions can be used in GET and PUT FORMAT lists.

You can use, as the source or target of a file I/O statement, a function reference that performs I/O on the same file and then returns to the original statement.

The OPEN and CLOSE statements can contain a list of file specifications.

The FROM option of the REWRITE statement can be omitted.

Attributes and Pictures

The INITIAL attribute is allowed with AUTOMATIC storage. The initial items can contain asterisks to denote uninitialized values. The initial values can be expressions. The NULL built-in function can be used in both STATIC and AUTOMATIC INITIAL attributes. The initial iteration factor can be an asterisk.

Restricted expressions can be used for static extents, parameter extents, and returns descriptor extents.

The AREA and OFFSET data types are supported.

The REFER attribute can be used at the end of a structure.

The DIMENSION, PARAMETER, and NONVARYING keywords can be specified.

The UNALIGNED attribute can be specified, but only for BIT and CHARACTER variables.

SYSIN and SYSPRINT can be contextually declared as files.

The CONDITION attribute is supported.

The UNION attribute is supported.

Built-In Functions and Pseudovariables

The following built-in functions are supported: ADD, EMPTY, EVERY, HIGH, LOW, MULTIPLY, ONSOURCE, POINTER, REVERSE, SOME, and SUBTRACT.

The ONSOURCE pseudovariable is supported.

The INDEX and VERIFY built-in functions have an optional starting position parameter.

The UNSPEC built-in function and pseudovariable can be used on aggregates.

Expressions

The operators AND THEN (short-circuiting AND, specified as &:, and OR ELSE (short- circuiting OR, specified as |:, are supported.

EXCLUSIVE OR (infix or dyadic ^) is supported.

Full PL/I Features Supported

The items discussed in this section are features that are explicitly excluded from both the old subset standard (ANSI X3.74-1981) and the new subset standard (ANSI X3.74-198x) but that have been implemented in Kednos PL/I for UNIX. These features all exist in full PL/I.

Program Structure

The STRINGRANGE and SUBSCRIPTRANGE conditions are supported.

Replication factors for string constants are supported.

A comma list can be specified on the left-hand side of an assignment statement.

Program Control

The ENTRY statement is supported.

Storage Control

CONTROLLED storage is supported.

Attributes and Pictures

The CONTROLLED, LIKE, MEMBER, POSITION, PRECISION, REFER, and STRUCTURE attributes are supported. (The REFER attribute is restricted to BASED and CONTROLLED variables.)

The picture characters Y, T, I, R, F, K, and E are supported, and pictures can include iteration factors.

Built-In Functions and Pseudovariables

The POINTER built-in function is not restricted to ADDR.

The ALLOCATION and ONCHAR built-in functions are supported.

The ONCHAR pseudovariable is supported.

Expressions

The expression in a WHILE or UNTIL clause or in an IF statement can be a bit string of any length. When evaluated, the expression results in a true value if any bit of the string expression is a 1 and in a false value if all bits in the string expression are 0s.

The control variable and the expressions in the TO, BY, and REPEAT options of the DO statement are not restricted to integers and pointers.

Nonstandard Features from Other Implementations

The features discussed in this section are not described in any ANSI PL/I standard. They are, however, provided by some other implementations.

Preprocessor

Kednos PL/I for UNIX supports an embedded lexical preprocessor for compilation control. This feature is included for compatibility with PL/I for OpenVMS. Kednos suggests you use the preprocessor only if you require this compatibility. Therefore, it is turned on by default for the -D dec variant and off, by default, for the -D ansi and -D ibm variants.

The following preprocessor statements are included: %ACTIVATE, %DEACTIVATE, %DECLARE, %DO, %END, %ERROR, %FATAL, %GOTO, %INFORM, %IF, %LIST (ignored), %NOLIST (ignored), %PAGE, %PROCEDURE, %REPLACE, %RETURN, %SBTTL, %TITLE, and %WARN.

An %IF statement can contain unlabeled %THEN and %ELSE clauses.

The following preprocessor built-in functions are included: ABS, BYTE, COPY, DATE, DATETIME, DECODE, ENCODE, ERROR, INDEX, INFORM, LENGTH, LINE, MAX, MIN, MOD, RANK, REVERSE,SEARCH, SIGN, SUBSTR, TIME, TRANSLATE, TRIM, VARIANT, VERIFY, and WARN.

Program Control

Kednos PL/I for UNIX, IBM dialect, supports condition prefixes and the following conditions:

ATTENTION, CHECK, NAME, RECORD, SIZE, STRINGSIZE, TRANSMIT

IBM Dialect I/O Features and Other IBM Dialect Features

Kednos PL/I for UNIX, IBM dialect, supports several features to facilitate IBM file handling. See See for more information on these and other IBM dialect features.

Built-In Functions

The following nonstandard built-in functions are included: BYTE, BYTESIZE, DATETIME, DECODE, ENCODE, INT, MAXLENGTH, POSINT, RANK, SEARCH, SIZE, and TRIM.

LIKE Extension

Kednos PL/I for UNIX lets you use the LIKE attribute on a structure already containing LIKE.

Declarations

Variables can be declared outside procedures.

PL/I-Specific Extensions for the Digital Unix Platform

The extensions in the following sections are enhancements for PL/I programs executing on the Digital Unix platforms. These extensions are provided for procedure calling, condition handling, compilation control, and miscellaneous purposes.

Procedure-Calling and Condition-Handling Extensions

The following extensions to PL/I were made to allow procedures to call procedures written in any other programming language that also supports the OpenVMS calling standard.

  • The ANY, VALUE, and REFERENCE attributes describe how data is to be passed to a called procedure.
  • The OPTIONAL attribute indicates that a parameter need not be specified in a call; the TRUNCATE attribute indicates the point at which an actual parameter list can be truncated.
  • The LIST attribute can be used for the parameter descriptor in an external entry declaration to denote that a list of parameters may be specified.
  • The VARIABLE option for the ENTRY attribute permits a PL/I procedure to call a non-PL/I procedure with an argument list of variable length. It also permits a procedure to omit arguments in an argument list.

The following attributes provide storage classes for PL/I variables. These attributes permit PL/I programs interact with other procedures that use these storage classes.

  • The GLOBALDEF and GLOBALREF attributes let you define and access external global variables and optionally place all external global definitions in the same program section.
  • The READONLY attribute can be applied to a static computational variable whose value does not change.
  • The VALUE attribute defines a variable that is, in effect, a constant whose value is supplied by the linker. The value attribute can also be used to allow a procedure to receive constants passed by immediate value.

The following extensions to condition handling provide compatibility with condition handling in PL/I for OpenVMS product:

  • The ANYCONDITION condition name can be used in an ON-unit to handle any condition that is signaled that does not explicitly have an ON-unit of its own.
  • The VAXCONDITION condition name can be used in ON, SIGNAL, and REVERT statements to process conditions specific to OpenVMS systems.
  • The RESIGNAL built-in subroutine permits an ON-unit to keep a signal active.

Miscellaneous Extensions

The following built-in functions are supported: BYTE, DECODE, ENCODE, INT, POSINT, RANK, and SIZE.

Implementation-Defined Values and Features

The following values and features are implementation-defined:

 

Migration Notes

This appendix contains notes and comments about migration issues. It lists and describes keywords and functions of the PL/I language that are available in other implementations of PL/I but are not included in Kednos PL/I for UNIX. It also outlines the differences between Kednos PL/I for UNIX and Digital's implementations of PL/I.

The information in this appendix is not intended to represent either a complete or a formal description of migration issues. The information is presented informally and has not been subjected to extensive testing and verification.

Keywords Not Supported

The following two tables summarize keywords not supported in this version of Kednos PL/I for UNIX.

See . PL/I Keywords Not Supported lists keywords used in other implementations of PL/I but not in Kednos PL/I for UNIX. The table does not include ENVIRONMENT keywords or implementation-specific language extensions.Some keywords are supported in a specific implementation of PL/I. Those keywords are noted with the name of the implementation in parentheses.

See . Summary of Unsupported IBM I/O Features lists I/O keywords supported in the IBM implementation of PL/I but not in Kednos PL/I for UNIX.

. PL/I Keywords Not Supported

Keyword

Abbreviation

Use

ACTUALCOUNT

 

Built-in function

ADDREL

 

Built-in function

AFTER

 

Built-in function

ASMTDLI

 

Built-in subroutine (IBM )

BACKWARDS

 

Attribute, Option of OPEN statement (IBM)

BEFORE

 

Built-in function

BY NAME

 

Option of assignment statement

C

 

Format item

CALL

 

Option of INITIAL attribute

CASE

 

Option of DO statement

COMPLETION

CPLN

Built-in function(IBM ), Pseudovariable (IBM )

COMPLEX

CPLX

Attribute, Built-in function (IBM ), Pseudovariable (IBM )

CONJG

 

Built-in function (IBM )

CONNECTED

CONN

Attribute

CONSTANT

 

Attribute

CONVERSION

CONV

Condition prefix (IBM )

COPY

 

Option of GET statement (IBM )

COUNT

 

Built-in function (IBM )

D

 

Format item

DATA

 

Stream I/O transmission mode (IBM )

DATAFIELD

 

Built-in function (IBM )

DECAT

 

Built-in function

DEFAULT

DFT

Statement

DELAY

 

Statement (IBM )

DESCRIPTOR

DESC

Attribute, Built-in function

DESCRIPTORS

 

Option of DEFAULT statement

DISPLAY

 

Statement, Built-in subroutine

DOT

 

Built-in function

EVENT

 

Attribute, Option of several I/O statements (IBM )

EXCLUSIVE

EXCL

Attribute (IBM )

EXIT

 

Statement

EXTEND

 

Built-in subroutine

F

 

Format item

FETCH

 

Statement (IBM , accepted but ignored in Kednos PL/I for UNIX)

FORMAT

 

Attribute

FREE

 

Built-in subroutine

G

 

Format item

GENERIC

 

Attribute

GRAPHIC

 

Data type(IBM ), Build-in function (IBM )

H

 

Format item

HALT

 

Statement

IMAG

 

Built-in function(IBM ), pseudovariable (IBM )

IRREDUCIBLE

IRRED

Attribute

LIST

 

Option of OPEN statement

LOCAL

 

Attribute

LTRIM

 

Preprocessor built-in function, Built-in function

MPSTR

 

Built-in function(IBM )

NEXT_VOLUME

 

Built-in subroutine

NOCHECK

 

Statement

NOLOCK

 

Option of READ statement (IBM )

NONE

 

Option of DEFAULT statement

OFFSET

 

Built-in function

ONARGSLIST

 

Built-in function

ONCOUNT

 

Built-in function (IBM )

ONFIELD

 

Built-in function

ORDER

 

Option of BEGIN and PROCEDURE statements

OTHERWISE

OTHER

Keyword of the SELECT statement

PENDING

 

Condition

PLICANC

 

Built-in subroutine (IBM )

PLICKPT

 

Built-in subroutine (IBM )

PLIDTLI

 

Built-in subroutine (IBM )

PLIDUMP

 

Built-in subroutine (IBM )

PLIREST

 

Built-in subroutine (IBM )

PLITEST

 

Built-in subroutine (IBM )

POINTERADD

 

Built-in subroutine (IBM )

POINTERVALUE

 

Built-in subroutine (IBM )

POLY

 

Built-in function

PRESENT

 

Built-in function

PRIORITY

 

Option of CALL statement, Built-in function, Pseudovariable

RANGE

 

Option of DEFAULT statement

REAL

 

Attribute, Built-in function, Pseudovariable

REDUCIBLE

RED

Attribute

REENTRANT

 

Option of OPTIONS option

REFERENCE

 

Built-in function

RELEASE

 

Statement, Built-in Subroutine

REORDER

 

Option of BEGIN and PROCEDURE statements

REPLY

 

Option of DISPLAY statement

RTRIM

 

Preprocessor built-in function, Built-in function

SAMEKEY

 

Built-in function (IBM )

SNAP

 

ON statement option

SPACEBLOCK

 

Built-in subroutine

STATUS

 

Built-in function (IBM ), Pseudovariable (IBM )

SUB

 

Dummy variable of DEFINED attribute

SYSTEM

 

Option of DECLARE statement

TAB

 

Option of OPEN statement

TASK

 

Attribute, Option of OPTIONS option, Option of CALL statement

TRANSIENT

 

Attribute, option of OPEN statement(IBM)

UNDERFLOW

UFL

Condition name, PROCEDURE OPTIONS option

VALID

 

Built-in function

VALUE

 

Built-in function

WAIT

 

Statement

 

. Summary of Unsupported IBM I/O Features

Type of Keyword

Keyword

Action

File Attributes

BACKWARDS

Error

 

EXCLUSIVE

Error

 

TRANSIENT

Error

Environment Options

ADDBUFF

Accepted but ignored

 

ASCII

Error

 

BUFOFF

Error

 

BUFFERS

Accepted but ignored

 

COBOL

Error

 

CTLASA | CTL360

Error

 

D, DB record formats

Error

 

F, FB, FS, FBS record formats

All map to fixed length, no support for blocked

 

GENKEY

Error

 

GRAPHIC

Error

 

KEYLENGTH

Error

 

KEYLOCK

Error

 

INDEXAREA

Accepted but ignored

 

INDEXED

Error

 

LEAVE

Error

 

NCP

Error

 

NOWRITE

Accepted but ignored

 

REGIONAL

Error

 

REREAD

Error

 

TOTAL

Accepted but ignored

 

TP

Error

 

TRKOFL

Accepted but ignored

 

V, VB, VS, VBS record formats

All map to varying length, no support for blocked

 

VSAM and all VSAM-only options (BKWD, BUFND, BUFNI, BUFSP, PASSWORD, REUSE, SIS, SKIP)

Error 4

Statement Options

EVENT (option to READ, WRITE, REWRITE, and DELETE)

Error

Statements

UNLOCK

Accepted but ignored

Stream I/O Options

ALL

Accepted but ignored

 

COPY

Error

 

DATA

Error

 

FLOW

Accepted but ignored

 

SNAP

Accepted but ignored

 

Differences Between Kednos PL/I for UNIX Digital's PL/I and Other Digital-Compatible Versions of PL/I

The following sections describe differences between this version of PL/I and the other Digital versions of PL/I.

Statements

Kednos PL/I for UNIX accepts but ignores the unsupported *PROCESS statement, for compatibility with other versions of PL/I.

Data Type Attributes

Kednos PL/I for UNIX does not support the DESCRIPTOR data type attribute, which is in Digital's PL/I implementations.

See See , See Declarations for more information on supported data type attributes.

Default Values for Data Type Attributes

Kednos PL/I for UNIX supplies different default values for data type attributes depending on the variant specified as an option to the pl1 command. See See , See Data Types for more information on the Kednos PL/I for UNIX defaults. See . Digital Default Values for Data Type Attribute shows the default values for data type attributes supplied by Digital's PL/I.

. Digital Default Values for Data Type Attribute

Attributes Specified

Defaults in Digital' PL/I

BINARY

FIXED (31)

BINARY FIXED

(31)

BINARY FLOAT

(24)

DECIMAL

FIXED (10,0)

DECIMAL FIXED

(10,0)

DECIMAL FIXED (n)

(n,0)

DECIMAL FLOAT

(7)

Floating Point Data Types

OpenVMS versions of PL/I support F, D, G, and H floating point formats, in addition to the IEEE S and T floating point formats. Kednos PL/I for UNIX supports the standard IEEE formats only.

Scale Factors

Kednos PL/I for UNIX supports scale factors for fixed-point decimal data. Some other implementations support scale factors for fixed-point binary data. This is unsupported in Kednos PL/I for UNIX.

Procedures and Entries Specified with the Returns Option

If the PROCEDURE statement contains a RETURNS option, every ENTRY statement in the procedure must contain a matching RETURNS options. Likewise, if any entry point in the procedure returns a value, the PROCEDURE statement and all other entry points in the procedure must contain matching RETURNS options. This restriction did not apply in Kednos's PL/I for OpenVMS.

Passing Arguments to Non-PL/I Procedures

In Kednos's PL/I for OpenVMS, you can pass arguments to non-PL/I procedures by descriptor. You could use the DESCRIPTOR built-in function to force passing arguments by descriptor. PL/I would also do this automatically under certain conditions, as described in the reference manual for the OpenVMS PL/I language.

Kednos PL/I for UNIX does not support passing arguments by descriptor.

GOTO Statement

Kednos's PL/I for OpenVMS supports the OTHERWISE option on the GOTO statement. This option is not supported on either the RISC ULTRIX or Kednos PL/I for UNIX versions of PL/I.

Condition Handling

Kednos PL/I for UNIX does not support the ON statement SNAP option.

Kednos PL/I for UNIX, IBM variant, supports condition prefixes, which are not supported by the OpenVMS versions of PL/I.

Kednos PL/I for UNIX, IBM variant, supports the following conditions, which are not in the OpenVMS versions:

ATTENTION, CHECK, NAME, RECORD, SIZE, STRINGSIZE, TRANSMIT

The UNDERFLOW condition is supported in the Open VMS versions of PL/I but not in the Digital UNIX version.

File Handling

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:

Preprocessor

Since Digital UNIX does not support the VAX Common Data Dictionary (CDD), Kednos PL/I for UNIX does not support CDD features. These include the %DICTIONARY and %[NO]LIST_DICTIONARY statements.

Kednos PL/I for UNIX allows but ignores the following other list statements: [NO]LIST, [NO]LISTALL, [NO]LIST_INCLUDE, [NO]LIST_MACHINE, and [NO]LIST_SOURCE. These are functional in PL/I for Open VMS.

The VMS-based preprocessor built-in functions %LTRIM and %RTRIM are unsupported on Kednos PL/I for UNIX.

Kednos PL/I for UNIX requires each preprocessor statement to be on a new line, with nothing but white space preceding the % sign. OpenVMS and DEC PL/I do not have this requirement.

Built-in Functions and Subroutines

Due to differences in the operating systems, the built-in functions and subroutines supported by Kednos PL/I for UNIX differ from those supported by other versions of PL/I. The following lists show differences between OpenVMS and ULTRIX versions of PL/I and Kednos PL/I for UNIX.

The following built-in functions are supported in the OpenVMS versions of PL/I but not in Kednos PL/I for UNIX:

The following built-in subroutines are available in ULTRIX and OpenVMS PL/I but not Kednos PL/I for UNIX:

 

Language Summary

This appendix briefly describes Kednos PL/I for UNIX statements, attributes, statement format, expressions, data conversions, built-in functions, pseudovariables, and built-in subroutines.

Statements

%activate-statement
allocate-statement

allocate-item:

variable-reference [SET(locator-reference)] [IN(area-reference)]

 
%assignment-statement

%target = expression;

 
assignment-statement

target, ... = expression;

 
begin-statement

BEGIN;

 
call-statement

CALL entry-name [(argument, ...)];

 
close-statement

CLOSE FILE(file-reference) [ENVIRONMENT(option, ...)]

[,FILE(file-reference) [ENVIRONMENT(option, ...)]] ... ;

 
%deactivate-statement

element:

%declare-statement

element:

declare-statement

declaration:

delete-statement

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

 
%do-statement

%DO;

 

%END;

 
do-statement
%end-statement

%END;

 
end-statement

END [label-reference];

 
entry-statement
%error-statement

%ERROR preprocessor-expression;

 
%fatal-statement

%FATAL preprocessor-expression;

 
format-statement

label:

 

FORMAT (format-specification, ...);

 
free-statement

FREE variable-reference [IN area-reference], ...;

 
get-statement

GET EDIT (input-target, ...) (format-specification, ...)

GET LIST (input-target, ...)

GET [FILE(file-reference)]* SKIP [(expression)] ;

 
%goto-statement

%GOTO label-reference;

 
goto-statement
%if-statement

%IF test-expression %THEN action [%ELSE action];

if-statement

IF test-expression THEN action [ELSE action];

 
%include-statement
%inform-statement

%INFORM preprocessor-expression;

 
leave-statement

LEAVE [label-reference];

 
locate-statement (ibm dialect only)

LOCATE based-variable FILE (file-reference)

[ SET (pointer-reference) ]

[ KEYFROM (expression) ];

 
%null-statement

%;

 
null-statement

;

 
on-statement
open-statement

OPEN FILE(file-reference) [file-description-attribute ...]

(file-reference) [file-description- attribute ...]] ...;

 

%page-statement

%PAGE;

 
%procedure-statement
procedure-statement
put-statement

PUT EDIT (output-source, ...) (format-specification, ...)

PUT [FILE (file-reference)] LINE (expression);

 

PUT LIST (output-source,)

PUT [FILE (file-reference)] PAGE;

 

PUT [FILE (file-reference)] SKIP [(expression)] ;

 

read-statement

READ FILE (file-reference)

%replace-statement

%REPLACE identifier BY constant-value;

 
%return-statement

[%]RETURN (preprocessor-expression);

 
return-statement

RETURN [ (return-value) ];

 
revert-statement

REVERT condition-name, ...;

 
rewrite-statement

REWRITE FILE (file-reference)

[ FROM (variable-reference) [ KEY (expression) ]]

[ OPTIONS (option, ...) ];

 

%sbttl-statement

%SBTTL preprocessor-expression

 
select-statement

SELECT [(select-expression)];

[WHEN [ANY | ALL] (case-expression, ...) [action] ; ] ...

[(OTHERWISE | OTHER) [action] ; ]

END;

 
signal-statement

SIGNAL condition-name;

 
stop-statement

STOP;

 
%title-statement

%TITLE preprocessor-expression

 
%warn-statement

%WARN preprocessor-expression;

 
write-statement

WRITE FILE(file-reference) FROM (variable-reference)

[ KEYFROM (expression) ]

[ OPTIONS (option, ...) ];

Attributes

Computational Data Type Attributes

The following attributes define arithmetic and string data:

These attributes can be specified for all elements of an array and for individual members of a structure.

Noncomputational Data Type Attributes

The following attributes apply to program data that is not used for computation:

AREA

CONDITION

ENTRY [VARIABLE]

FILE [VARIABLE]

LABEL [VARIABLE]

OFFSET

POINTER

Storage Class and Scope Attributes

The following attributes control the allocation and use of storage for a data variable and define the scope of the variable:

AUTOMATIC [INITIAL(initial-element, ...)]

BASED [(pointer-reference)][INITIAL(initial-element, ...)]

CONTROLLED [INITIAL(initial-element, ...)]

DEFINED(variable-reference) [POSITION(expression)]

STATIC [READONLY] [INITIAL(initial-element, ...)]

PARAMETER

INTERNAL

Member Attributes

The following attributes can be applied to the major or minor members of a structure:

LIKE

MEMBER

REFER

STRUCTURE

TYPE

UNION

File Description Attributes

The following attributes can be applied to file constants and used in OPEN statements (ENVIRONMENT is valid on OPEN in the dec and ansi dialects only):

Entry Name Attributes

The following attributes can be applied to identifiers of entry points:

Non-Data Type Attributes

The following attributes can be applied to data declarations:

ALIGNED

DIMENSION

UNALIGNED

Statement Format

The general format of a PL/I statement consists of an optional condition prefix (ibmdialect only), an optional statement label, the body of the statement, and the required semicolon terminator. The format of a statement is:

[ ( condition-prefix [ ,condition-prefix ] ... ) : ] [ label: ] statement-body;

 

Expressions and Data Conversions

See . Operators lists the categories of operators, their symbols, and their meanings.

. Operators

Category

Symbol

Operation

Arithmetic operators

+
-
/
*
**

Addition or prefix plus
Subtraction or prefix minus
Division
Multiplication
Exponentiation

Relational (or comparison) operators

>
<
=
^>
^<
^=
>=
<=

Greater than
Less than
Equal to
Not greater than
Not less than
Not equal to
Greater than or equal to
Less than or equal to

Bit-string (or logical) operators

^ (prefix)
&
|
&:
|:
^ (infix)

Logical NOT
Logical AND
Logical OR
Logical AND THEN
Logical OR ELSE
Logical EXCLUSIVE OR

Concatenation operator

||

String concatenation

See . Precedence of Operators gives the priority of PL/I operators. Low numbers indicate high priority. For example, the exponentiation operator (**) has the highest priority (1), so PL/I performs it first, and the OR ELSE operator (|:) has the lowest priority (9), so PL/I performs it last.

. Precedence of Operators

Operator

Priority

Left/Right Associative

Order of Evaluation

()

0

N/A

deepest first

**

1

right

left to right

+ (prefix)

1

N/A

N/A

- (prefix)

1

N/A

N/A

^ (prefix)

1

N/A

N/A

*

2

left

left to right

/

2

left

left to right

+ (infix)

3

left

left to right

- (infix)

3

left

left to right

||

4

left

left to right

>

5

left

left to right

<

5

left

left to right

^>

5

left

left to right

^<

5

left

left to right

=

5

left

left to right

^=

5

left

left to right

<=

5

left

left to right

>=

5

left

left to right

&

6

left

left to right

|

7

left

left to right

^ (infix)

7

left

left to right

&:

8

left

left to right across entire expression

|:

9

left

left to right across entire expression

See . Contexts in Which PL/I Converts Data discusses the contexts in which PL/I performs data conversion.

. Contexts in Which PL/I Converts Data

Context

Conversion Performed

target = expression;

In an assignment statement, the given expression is converted to the data type of the target.

entry-name

RETURNS (attribute ...);

RETURN (value);

In a RETURN statement, the specified value is converted to the data type specified by the RETURNS option on the PROCEDURE or ENTRY statement.

x + y
x -y
x * y
x / y
x**y
x||y
x & y
x | y
x&:y
x|:y
x ^ y
x > y
x y<
x = y
x^=y

In any expression, if operands do not have the required data type, they are converted to a common data type before the operation. For most operators, the data types of all operands must be identical. A warning message is issued in the case of a concatenation conversion.

BINARY (expression)
BIT (expression)
CHARACTER (expression)
DECIMAL (expression)
FIXED (expression)
FLOAT (expression)
OFFSET (variable)
POINTER (variable)

PL/I provides built-in functions that perform specific conversions.

PUT LIST (item, ...);

Items in a PUT LIST statement are converted to character-string data.

GET LIST (item, ...);

Character-string input data is converted to the data type of the target item.

PAGESIZE (expression)
LINESIZE (expression)
SKIP (expression)
LINE (expression)
COLUMN (expression)
format items A, B, E, F, and X
TAB (expression)

Values specified for various options to PL/I statements must be converted to integer values.

DO control-variable ...

Values are converted to the attributes of the control variable.

parameter

Actual parameters are converted to the type of the formal parameter if necessary.

INITIAL attribute

Initial values are converted to the type of the variable being initialized.

Pseudovariables

PL/I has the following pseudovariables:

INT (dec and ansi dialects only)

ONSOURCE

ONCHAR

PAGENO (dec and ansi dialects only)

POSINT (dec and ansi dialects only)

STRING

SUBSTR

UNSPEC

Pseudovariables can be used, in certain assignment contexts, in place of an ordinary variable reference. For example:

SUBSTR(S,2,1) = 'A';

 

This assigns the character 'A' to a 1-character substring of S, beginning at the second character of S.

Pseudovariables can be used wherever the following three conditions are true:

Pseudovariables are used most often in the following locations:

Pseudovariables cannot be used in preprocessor statements or in an argument list. For example:

CALL P(SUBSTR(S,2,1));

 

Here, SUBSTR is interpreted as a built-in function reference, not as a pseudovariable. The actual argument passed to procedure P is a dummy argument containing the second character of string S.

Built-In Subroutines

See . Summary of PL/I Built-In Subroutines summarizes the built-in subroutines.

. Summary of PL/I Built-In Subroutines

Category

Routine Reference

Action

Dialect

Condition-handling

RESIGNAL()

Allows more processing of a signal.

dec,ansi

File-control

FLUSH(f)

Forces flushing of all buffers for file f.

dec,ansi

REWIND(f)

Resets file f to the beginning.

dec,ansi

Sorting

PLIRETC

Sets a return code. The Sort program examines this return code. You can also examine it in another PL/I program using the PLIRETV built-in function.

ibm

PLISRTA

An entry point of the Sort program.

ibm

PLISRTB

An entry point of the Sort program.

ibm

PLISRTC

An entry point of the Sort program.

ibm

PLISRTD

An entry point of the Sort program.

ibm

 

A

A format item 9-35

ABS built-in function 11-9

ACOS built-in function 11-10

%ACTIVATE statement 10-6, D-1

NORESCAN option 10-6

RESCAN option 10-6

Activation block 1-17

ADD built-in function 11-10

Addition 3-8

ADDR built-in function 11-11

passing pointer value 7-24

using 5-13, 5-21

Aggregates 4-1

arrays 4-1

internal representation 4-32

structures 4-14

ALIGNED attribute 2-15

Alignment

bit-string 2-15

character string 3-40

character-string 2-15

of bit strings 3-44

ALL built-in function 11-11

ALLOCATE statement 5-19, 5-22, D-1

using 5-10

ALLOCATION built-in function 11-12

using 5-20

AND operator 6-8

AND THEN operator 6-10

ANY attribute 2-15, 7-23 to 7-24

ANY built-in function 11-13

ANYCONDITION condition 8-37

Apostrophes, in character strings 3-37

Area 3-62, 5-6

reading and writing to 3-63

using the AREA attribute 2-16, 3-62

using the AREA condition 8-37

variables 3-63

Arguments 7-10

aggregate 7-17

array 7-13

character string 7-15

conversion 7-17

dummy 7-16

matching with parameters 7-17

null list 2-21, 7-5

of built-in functions 11-1

passing 7-15

arrays 4-12

by immediate value 7-22

by reference 2-50, 7-23

by value 2-59

structures 4-18, 7-14

to PL/I procedure 7-16

to subroutines or functions 7-15

relationship to parameters 7-11

specifying pointer values 7-24

Arithmetic

built-in functions

ABS 11-9

ADD 11-10

CEIL 11-18

DIVIDE 11-26

FLOOR 11-30

MAX 11-38

MIN 11-39

MOD 11-40

MULTIPLY 11-42

ROUND 11-53

SIGN 11-56

SUBTRACT 11-64

TRUNC 11-71

data 3-8

converting to bit-string 6-30

converting to character-string 6-34

relational expression 6-12

specifying precision 2-48, 3-8

operations

determining sign of a number 11-56

division 11-26

rounding to nearest digit 11-53

ZERODIVIDE signaled 8-60

operators 6-5, D-12

Arithmetic built-in functions

PRECISION 11-50

Array-handling built-in functions

ALL 11-11

ANY 11-13

DIMENSION 4-13, 11-25

HBOUND 4-13, 11-31

LBOUND 4-13, 11-35

PROD 11-50

SUM 11-65

Arrays 4-1

assigning values to 4-10, 4-12

bound pair 4-5

concatenating with STRING 11-62

connected 4-30

declaring 2-5, 4-1

as parameters 7-13

dimensions

determining extent 11-25

determining lower bound 11-35

determining upper bound 11-31

specifying 2-26, 4-2

extent of 4-5

initializing 4-6

of structures 4-28

referring to elements 4-29

unconnected arrays 4-30

order of assignment and output 4-11

passing as arguments 4-12, 7-13, 7-23

asterisk-extent 2-50

subscripts 4-5

unconnected 4-30

ASCII character set

obtaining integer value 11-51

obtaining string of 11-20

ASIN built-in function 11-13

%Assignment statement 10-5

Assignment statement 1-8, 6-1, D-1

and unconnected arrays 4-30

conversion during 6-24

arithmetic data 6-22

specifing structure 4-17

specifying array variables 4-10

structure 4-28

Asterisk (*)

as picture character 3-22

in array declaration 4-5

ATAN built-in function 11-13

ATAND built-in function 11-14

ATANH built-in function 11-14

Attention condition 8-37

Attributes 2-7, D-9

array variables 4-3

computational data type 2-8, D-9

default arithmetic 3-3

factors in declaration 2-4

file description 2-10, 9-3, 9-10, D-11

specifying on OPEN 9-3

for entry points 2-10, D-11

matching parameter and argument 7-17

member 2-9, 4-18, D-10

noncomputational data type 2-8, D-9

non-data type 2-10, D-11

scope 2-9, D-10

specifying in DECLARE statement 2-2

storage 2-9, D-10

structure variables 4-15

AUTOMATIC attribute 2-17

Automatic storage class 5-2

B

B format item 9-37

B picture character 3-26

BASED attribute 2-17, 5-5

Based variables 2-17, 5-5

associating with storage 5-5

data-type matching 5-14

left-to-right equivalence 5-15

overlay defining 5-14

example 5-16

freeing storage 5-23

nonmatching reference 5-16

obtaining storage 5-22

offset within area 3-50

REFER option 4-23

referring to 5-8

using READ statement 5-12

Begin blocks 1-13, 1-15, 8-13

effect of RETURN statement 7-21

in ON-unit 8-64

terminating 8-14 to 8-15

BEGIN statement 8-13, D-1

Binary

fixed-point data 3-9

floating-point data 3-13

BINARY attribute 2-18, 3-9

in floating-point declarations 3-14

BINARY built-in function 11-15

BIT attribute 2-19, 3-43

BIT built-in function 11-16

Bit strings 3-40

alignment 3-44

as integers 3-45

concatenation 6-14

constants 3-41

hexadecimal 3-41

maximum length 3-41

octal 3-41

specifying base 3-41

converting 3-48

from other types to 6-30

to arithmetic 6-23, 6-27

to character-string 6-23, 6-37

declaring variables 3-43

derived type and precision of 6-23

in relational expressions 6-13

internal representation 3-45

length

maximum 3-40

specifying 3-43

operator 6-6

overlay defining 5-28

passing as arguments

by reference 7-23

by value 7-22

storage in memory 3-45

unaligned 4-32

restrictions on use 3-44

variables 3-43

Block 1-13

activation 1-17

parent 1-19

procedure invocation 1-16, 7-7

relationships among 1-18

begin 1-13, 1-15, 8-13

containment 1-16

dynamic descendants 1-19

nesting 1-16

procedure 1-13, 1-16

terminating 1-20, 8-15

BLOCK_BOUNDARY_FORMAT ENVIRONMENT option 2-30

BLOCK_IO ENVIRONMENT option 2-30

BLOCK_SIZE ENVIRONMENT option 2-30

Boolean operations

defining with BOOL 11-16

testing 8-16

values 3-40

Bounds (of array) 4-2, 4-5

determining lower dimension 11-35

determining upper dimension 11-31

specifying dimensions 4-2

BUCKET_SIZE ENVIRONMENT option 2-30

BUFFERED attribute 2-20

BUILTIN attribute 2-21, 7-5

Built-in functions

arguments 11-1

conditions in 11-2

conversion 6-23

defining with BUILTIN attribute 2-21

evaluation of 11-1

preprocessor 10-29

summary (table) 11-3

Built-in subroutines 11-75

DISPLAY 11-75, D-16

EXTEND 11-75, D-16

FLUSH 11-75, D-16

RESIGNAL 8-65, 11-75, D-16

sorting 11-75

BY option of DO statement 8-10

BYTE built-in function 11-18

BYTESIZE built-in function 11-18

C

CALL statement 1-16, 7-9, D-2

calling non-PL/I procedures 2-15, 2-28, 7-22, B-8

CARRIAGE_RETURN_FORMAT ENVIRONMENT option 2-30

CEIL built-in function 11-18

CHARACTER attribute 2-22, 3-37

CHARACTER built-in function 11-19

Character set, ASCII 11-20

Character strings 3-36

alignment 3-40

comparing with VERIFY 11-73

concatenation 6-14

constants 3-36

very long 1-4

converting 6-33

from other types to 6-33

to arithmetic 6-23, 6-29

to bit 6-23

declaring 2-22

as parameters 7-15

derived type and precision of 6-23

determining length 11-36

fixed-length 3-38

internal representation 3-39

in relational expression 6-13

length attribute 3-38

overlay defining 5-28

passing as arguments 7-15

variables 3-37

varying length 3-38

varying-length 2-60, 3-39

internal representation 3-40

Characters

picture 3-20

substituting with TRANSLATE 11-67

used for punctuation in PL/I 1-2

CHECK condition 8-38

Circumflex (^) prefix operator 6-4

CLOSE statement 9-11, D-2

ENVIRONMENT attribute 9-11

COLLATE built-in function 11-20

COLUMN format item

definition 9-41

Comma (,) picture character 3-26

Comments 1-5

Comparison operator 1-2

Compatible data types 3-6

Compiler messages

%ERROR 10-11

%FATAL 10-12

%INFORM 10-17

%WARN 10-26

Compound statement 1-9

Computational data 2-8, D-9

Concatenation

COPY built-in function 11-20

operators 1-4, 6-14

REPEAT built-in function 11-51

required operands 6-5

CONDITION attribute 2-23

CONDITION condition 8-39

Condition data 3-64

in relational expressions 6-13

internal representation 3-64

Condition handling 8-30

built-in functions

ONCHAR 11-44

ONCODE 11-45

ONFILE 11-45

ONKEY 11-46

ONLOC 11-46

ONSOURCE 11-47

ON statement 8-30

Condition prefixes 1-7, 8-61

scope of 8-61

Conditions

ANYCONDITION 8-37

AREA 8-37

ATTENTION 8-37

CHECK 8-38

CONDITION 8-39

decimal overflow 8-46

default status 8-62

ENDFILE 8-42

ENDPAGE 8-43

ERROR 8-45

FINISH 8-45

FIXEDOVERFLOW 8-46

in built-in functions 11-2

integer overflow 8-46

KEY 8-47

NAME 8-49

OVERFLOW 8-50

RECORD 8-50

signalling 8-31

SIZE 8-51

STORAGE 8-56

STRINGRANGE 8-53

STRINGSIZE 8-55

SUBSCRIPTRANGE 8-55

TRANSMIT 8-56

UNDEFINEDFILE 8-57

UNDERFLOW 8-59

VAXCONDITION 8-60

ZERODIVIDE 8-60

Connected arrays 4-30

Constants

bit-string 3-41

character string 3-36

entry 3-57

file 3-60, 9-2

fixed-point decimal 3-11

floating-point 3-14

in argument list 7-16

integer 3-10

label 3-52

label array 3-52

Containment 1-13, 1-16

CONTIGUOUS ENVIRONMENT option 2-30

CONTIGUOUS_BEST_TRY ENVIRONMENT option 2-30

CONTROLLED attribute 2-23

Controlled DO statement 8-9

Controlled variables 2-23, 5-19

obtaining storage 5-22

Conversions 6-25

arithmetic to arithmetic 6-25

arithmetic to bit-string 6-30

arithmetic to character-string 6-34

ASCII to integer 11-51

bit-string to arithmetic 6-27

bit-string to character-string 6-37

built-in functions

BINARY 11-15

BIT 11-16

BYTE 11-18

CHARACTER 11-19

DECIMAL 11-23

DECODE 11-24

ENCODE 11-27

FIXED 11-29

FLOAT 11-30

INT 11-33

POSINT 11-48

RANK 11-51

UNSPEC 11-71

character-string to arithmetic 6-29

character-string to bit-string 6-33

integer to ASCII 11-18

of argument 7-17

of operands 6-21

offset to pointer 6-38

pictured to arithmetic 6-27

pictured to bit-string 6-32

pictured to character-string 6-33, 6-37

pointer to offset 6-38

to bit-string 6-30, 11-16

to character-string 6-33, 11-19

to decimal 11-23

to fixed point 11-29

to floating point 11-30

to picture 6-37

COPY built-in function 11-20

COS built-in function 11-21

COSD built-in function 11-21

COSH built-in function 11-21

CREATION_DATE ENVIRONMENT option 2-30

Credit (CR) picture character 3-27

Current record 9-89

CURRENT_POSITION ENVIRONMENT option 2-30

CURRENTSTORAGE built-in function 11-21

D

Data 1-20

default attributes 3-3

types 3-1

area 3-62

arguments

passed by immediate value 7-22

passed by reference 7-23

arithmetic 3-8

default precision 3-9

fixed-point binary 3-9

precision of 3-8

bit-string 3-40

character pictured 3-17

character-string 3-36

compatible 3-6

computational 3-1

condition 3-64

conversion between 6-17, 6-23

declaring 3-2

default attributes

for arithmetic operands 3-5

of constants 3-4

derived 6-21

entry 3-57

file 3-60, 9-1

fixed-point binary 3-9

fixed-point decimal 3-11

floating-point 3-13

label 3-51

noncomputational 3-2

in relational expression 6-13

numeric pictured 3-19

pointer 3-49

summary 3-1

Data conversions D-12

contexts 6-18

DATE built-in function 11-22

DATETIME built-in function 11-23

Day of month, current 11-22 to 11-23

%DEACTIVATE statement 10-8, D-2

Debit (DB) picture character 3-27

DECIMAL attribute 2-24

in floating-point declarations 3-14

DECIMAL built-in function 11-23

Decimal data

declaring 2-24

FIXEDOVERFLOW 8-46

fixed-point data 3-11

floating overflow 8-50

floating underflow 8-59

floating-point data 3-13

Decimal place, in picture 3-21

Declaration 2-1, 3-2

array 2-5, 4-1

file 9-2

multiple names 2-4

of variables with same attributes 2-4

simple 2-2

structure 2-6, 4-14

%DECLARE statement 10-9, D-2

DECLARE statement 2-2, D-2

DECODE built-in function 11-24

Default file attributes 9-7

DEFAULT_FILE_NAME ENVIRONMENT option 2-30

DEFERRED_WRITE ENVIRONMENT option 2-30

DEFINED attribute 2-25, 5-25

base position 2-47

DELETE ENVIRONMENT option 2-30

DELETE statement 9-1, 9-83, D-3

Derived type 6-21

of bit and character strings 6-23

Descendants of blocks 1-19, 8-63

D-floating format 3-16

Diagnostic messages

%ERROR 10-11

%FATAL 10-12

%INFORM 10-17

user-generated 10-27

%WARN 10-26

Digital variant, default attributes 3-3

DIMENSION attribute 2-26

DIMENSION built-in function 11-25

Dimensions, array 4-2, 4-30

DIRECT attribute 2-27, 9-10

DISPLAY built-in subroutine 11-75, D-16

DIVIDE built-in function 11-26

Division

controlling precision 11-26

ZERODIVIDE condition 8-60

%DO statement 10-10, D-3

DO statement 8-1, D-3

controlled DO 8-9, 8-11

DO REPEAT 8-6 to 8-7

DO UNTIL 8-4

DO WHILE 8-3

format 8-2

Documentation, program 1-5

DO-group 8-1

nesting 8-2

termination 8-15

Dollar ($) picture character 3-24

Double-precision floating point 3-16

Drifting picture character 3-24

Dummy argument 7-16

example 7-12

forcing creation of 7-17

Dynamic descendants

of blocks 1-19, 8-63

E

E format item 9-42

EDIT option

GET statement 9-19

PUT statement 9-29

Elements of arrays 2-6, 4-5

Empty argument list 7-5

EMPTY built-in function 5-6, 5-8, 11-26

ENCODE built-in function 11-27

Encoded-sign picture characters 3-23

%END statement 10-11, D-3

END statement 7-20, 8-15, D-3

ENDFILE condition 8-42

signaled 9-77

ENDPAGE condition 8-43

signaled 9-6, 9-70

Entry

`main' as name for 2-33, 7-6

constants 3-57

data 3-57

attributes 2-10, D-11

in relational expressions 6-13

internal representation 3-59

VARIABLE attribute 2-60

points

alternate 7-5

invoking 7-7

multiple 7-8

procedure 7-7

return value attributes 2-51

values 3-58

values, operations on 3-58

variables 3-58

ENTRY attribute 2-28

declaring non-PL/I procedures 7-22

ENTRY statement 7-5, D-3

ENVIRONMENT attribute 2-30

CLOSE options 9-11

ERF built-in function 11-27

ERFC built-in function 11-28

ERROR built-in function 11-28

ERROR condition 8-45

determining error status value 11-45

pictured variable assignment 3-33

signaled 9-76, 9-80

by default ON-unit 8-61

Error handling

of file-related error 11-45

ON condition 8-30

ONCHAR built-in function 11-44

ONCODE built-in function 11-45

%ERROR statement 10-11, 10-27, D-3

Errors

divide by zero 8-60

file opening 8-57

run-time conversion 6-24

VAX-specific conditions 8-60

Evaluation

of built-in functions 11-1

of expression 6-16

EVERY built-in function 11-28

EXCLUSIVE OR 11-17

EXCLUSIVE OR operator 6-10

EXP built-in function 11-29

EXPIRATION_DATE ENVIRONMENT option 2-30

Exponent (floating-point) 3-14

Exponent (K and E) picture characters 3-28

Expressions D-12

area variable in 3-63

bit-string data 6-13

character-string data 6-13

condition data 6-13

conversion of operands 6-21 to 6-22

converted precision 6-22

derived type 6-21

entry data 6-13

evaluation 6-16

file data 6-14

in argument list 7-16

label data 6-14

logical 6-6

noncomputational data 6-13

offset variable in 3-51, 6-14

pointer variable in 3-50, 6-14

precedence of operations 6-15, D-13

relational 6-12

restricted integer 4-2

using as subscripts 4-6

EXTEND built-in subroutine 11-75, D-16

EXTENSION_SIZE ENVIRONMENT option 2-30

Extensions to standard PL/I B-8

Extents

array 2-6, 4-5

determining 11-25

static variables 5-2

structure members 4-16

External

procedures 1-16, 2-33, 7-18

storage class 5-3

EXTERNAL attribute 2-33, 5-3

F

F format item 9-46

Fatal messages 10-12

%FATAL statement 10-12, 10-27, D-3

F-floating format 3-16

Fields 9-1

File 9-1

attributes 9-3, 9-10

BUFFERED 2-20

DIRECT 2-27

INPUT 2-41

KEYED 2-42

merged at open 9-7

OUTPUT 2-45

PRINT 2-49

RECORD 2-50

SEQUENTIAL 2-52

STREAM 2-53

UPDATE 2-58

VARIABLE 2-60

closing 9-11

comparing values 6-14

constant 3-60, 9-2

creating 9-9

declaration 9-2

default attributes on open 9-7

deleting records 9-83

description attributes 2-10, D-11

key error 8-47

OPEN statement 9-3

opening 9-3

error condition 8-57

existing 9-9

options 9-5

printing 9-70

read 9-75

record 9-73

sequential 2-52

source FOR %INCLUDE text 10-14

specifying line size 9-5

specifying page size 9-5

stream 9-68

updating 2-58, 9-84

values 3-61

variable 3-61, 9-2

writing 9-79

FILE attribute 2-34

File control built-in functions

LINENO 11-36

File specifications

determining 9-8

for error 11-45

specifying in OPEN 9-6

FILE_ID ENVIRONMENT option 2-30

FILE_ID_TO ENVIRONMENT option 2-30

FILE_SIZE ENVIRONMENT option 2-30

Files, unsupported IBM keywords C-5

FINISH condition 8-28, 8-45

FIXED attribute 2-34, 3-9

FIXED built-in function 11-29

FIXED_CONTROL option (READ) 9-77

FIXED_CONTROL_SIZE ENVIRONMENT option 2-30

FIXED_CONTROL_SIZE_TO ENVIRONMENT option 2-30

FIXED_LENGTH_RECORDS ENVIRONMENT option 2-30

Fixed-length character strings 3-37

FIXEDOVERFLOW condition 3-10, 3-22, 3-33, 8-46

Fixed-point data

binary 3-9

conversion 6-26

internal representation 3-10

decimal 3-11

constant 3-11

internal representation 3-13

precision 3-12

scale factor 3-12

use in expressions 3-12

variables 3-12

declaring 2-34

overflow condition 8-46

FLOAT attribute 2-36

FLOAT built-in function 11-30

Floating-point data 3-13

constant 3-14

declare 2-36

default precision 3-16

OVERFLOW condition 8-50

range of formats 3-15

range of precision 3-16

UNDERFLOW condition 8-59

using in expressions 3-15

FLOOR built-in function 11-30

FLUSH built-in subroutine 11-75, D-16

Format items 9-34, 9-59

A 9-35

B 9-37

COLUMN 9-41

E 9-42

F 9-46

iteration factor 9-60

LINE 9-49

list 9-53, 9-61

P 9-50

PAGE 9-52

R 9-52

repetition of 9-60

SKIP 9-55

TAB 9-55

X 9-57

FORMAT statement 9-53, D-4

label restriction 3-52

Format, program 1-12

FREE statement 5-19, 5-23, D-4

FROM option

REWRITE statement 9-84

WRITE statement 9-79

Functions 7-4

built-in 11-1

external 7-18

invoking procedure with 1-16

invoking with no arguments 7-5

references to 7-4

RETURN statement 7-21

return value attributes 2-51

terminating 7-20

user-written 7-4

G

GET statement 9-1, 9-16, D-4

assigning values to array elements 4-12

conversion of values 6-19

execution of 9-23

forms 9-16

GET EDIT 9-19

GET LIST 9-20, 9-68

GET SKIP 9-23

options 9-18

prompting 9-71

G-floating format 3-16

GLOBALDEF attribute 2-36

GLOBALREF attribute 2-37

%GOTO statement 10-12, D-4

GOTO statement 8-22, D-4

nonlocal GOTO 8-24

terminating subroutines or function 7-20

GROUP_PROTECTION ENVIRONMENT option 2-30

Groups, terminating 8-15

H

HBOUND built-in function 11-31

H-floating format 3-16

HIGH built-in function 11-31 to 11-32

I

I picture character 3-23

IBM variant, default attributes 3-3

IDENT option, PROCEDURE statement 7-3

Identifiers 1-5

associating with variables 1-20

rules for forming 1-5

%IF statement 10-14, D-4

IF statement 8-16, D-4

nesting 8-17

IGNORE option (READ) 9-77

IGNORE_LINE_MARKS ENVIRONMENT option 2-30

Immediate containment 1-16

Implementation-defined values B-10

IN option

ALLOCATE statement 5-6

%INCLUDE statement 10-14, D-5

rules for file specifications 10-15

INDEX_NUMBER ENVIRONMENT option 2-30

INDEX_NUMBER option (READ) 9-77

INDEXED ENVIRONMENT option 2-30

Infix operator 6-4

INFORM built-in function 11-33

%INFORM statement 10-17, 10-27, D-5

Informational messages 10-17

INITIAL attribute 2-37

with arrays 4-6

with structures 4-17

INITIAL_FILL ENVIRONMENT option 2-30

Input

record 9-73

READ statement 9-75

stream 9-23

GET statement 9-16

rules for specifing 9-20

INPUT attribute 2-41, 9-10

Input/Output

area 3-63

format lists 9-53

record files 9-73

statements

DELETE 9-83

GET 9-16

LOCATErecord 9-87

PUT 9-26

READ 9-75

REWRITE 9-84

WRITE 9-79

stream files 9-12

terminal 9-68

Insertion of picture character 3-26

INT built-in function 11-33

INT pseudovariable 11-77

Integer data overflow condition 8-46

Integer expression, restricted 2-16, 2-19

Integers

constant 3-10

fixed-point binary 3-9

fixed-point decimal 3-11

maximum values 3-10

Internal

procedures 1-16

value, obtaining 11-71

variables 5-3

INTERNAL attribute 2-42

Interrupts, handling 8-30

Iteration factor

INITIAL attribute 2-38, 4-7

initializing array 4-9

picture 3-23

with format item 9-60

K

KEY condition 8-47

determining key that caused 11-46

signaled 9-76, 9-80, 9-83, 9-85, 9-88

KEY option

DELETE statement 9-83

READ statement 9-76

REWRITE statement 9-85

KEYED attribute 2-42, 9-10

KEYFROM option (WRITE) 9-80, 9-88

KEYTO option (READ) 9-76

Keyword statements 1-8

Keywords 1-2, A-1

not supported C-1

recognition from context 1-2

L

LABEL attribute 2-43

Labels 3-51

array constant 3-52

constant 3-52

data

in relational expression 6-14

VARIABLE attribute 2-60

restrictions 3-55

subscripted 3-52

transferring control to 8-22

value 3-54

operations 3-54

variable 3-55

declaring 2-43

internal representation 3-56

LBOUND built-in function 11-35

LEAVE statement 8-26, D-5

Left-to-right equivalence 5-15

LENGTH built-in function 3-39, 11-36

Level numbers, specifying 4-15

Lexical elements

comments 1-5

identifiers 1-5

keywords 1-2, 1-4

punctuation 1-2

LIKE attribute 2-43, 4-18, 4-21

Line end character 1-4

LINE format item 9-49

Line numbers of files 11-36

LINE option, PUT statement 9-30

LINE preprocessor built-in function 11-36

Line size

default 9-5

specifying 9-5

LINENO built-in function 9-70, 11-36

LINESIZE option 9-5

LIST option

GET statement 9-20

PUT statement 9-31

Lists, in declarations 2-4

LOCATE statement 9-87, D-5

Locator qualifiers 5-9 to 5-10

LOG built-in function 11-37

LOG10 built-in function 11-37

LOG2 built-in function 11-37

Logarithm

computing base 10 11-37

computing base 2 11-37

computing natural 11-37

Logical expressions 6-6

evaluation 6-7

Logical operators 1-4, 6-6

AND 6-8

AND THEN 6-10

EXCLUSIVE OR 6-10

NOT 6-4, 6-8

OR 6-9

OR ELSE 6-11

LOW built-in function 11-37

M

MAIN option in PROCEDURE statement 7-3

Main procedure 1-16

Major structures

restriction on INITIAL 4-17

Mantissa 3-14

MATCH_NEXT option

READ statement 9-77

MATCH_NEXT_EQUAL option(READ) 9-77

Matching

based variable references 5-14

parameter and argument 7-17

Mathematical built-in functions

ACOS 11-10

ASIN 11-13

ATAN 11-13

ATAND 11-14

ATANH 11-14

COS 11-21

COSD 11-21

COSH 11-21

ERF 11-27

ERFC 11-28

evaluation of 11-1

EXP 11-29

LOG 11-37

LOG10 11-37

LOG2 11-37

SIN 11-57

SIND 11-57

SINH 11-57

SQRT 11-61

TAN 11-66

TAND 11-66

TANH 11-66

MAX built-in function 11-38

MAXIMUM_RECORD_NUMBER ENVIRONMENT option 2-30

MAXIMUM_RECORD_SIZE ENVIRONMENT option 2-30

MAXLENGTH built-in function 3-39, 11-38

MEMBER attribute 2-44

Member attributes 2-9, 4-18, D-10

LIKE 4-21

REFER 4-23

TYPE 4-18

UNION 4-16

Memory, locating variables in 11-11

Messages

compiler 6-24

diagnostic 10-11 to 10-12, 10-17, 10-26

MIN built-in function 11-39

Minor structure

restriction on INITIAL 4-17

Minus sign (-)

picture character 3-24

prefix operator 6-4

MOD built-in function 11-40

MOD preprocessor built-in function 11-40

Month, current 11-22 to 11-23

MULTIBLOCK_COUNT ENVIRONMENT option 2-30

MULTIBUFFER_COUNT ENVIRONMENT option 2-30

Multiple entry points 7-8

MULTIPLY built-in function 11-42

N

NAME condition 8-49

Names

declaring 2-2

rules for identifiers 1-5

scope 1-13

Nesting

DO-group 8-2

IF statement 8-17

%INCLUDE statement 10-16

of blocks 1-16

SELECT statements 8-21

Next record 9-89

Nine (9) picture character 3-22

NO_SHARE ENVIRONMENT option 2-30

Noncomputational data type attributes D-9

Nonlocal GOTO 7-20, 8-24

Nonmatching based variable reference 5-16

NONRECURSIVE option

ENTRY statement 7-6

PROCEDURE statement 7-3

NONVARYING attribute 2-44

NOT operator 6-4, 6-8

Null argument list 7-5

NULL built-in function 5-9, 11-43

%Null statement 10-6, D-5

Null statement 1-9, 8-29, D-5

in ON-unit 8-64

multiple labeled 8-25

O

OFFSET attribute 2-44, 3-50

OFFSET built-in function 11-44

Offset variables

converting to pointer 6-38, 11-47

declaring 3-50

in relational expressions 6-14

Offsets 5-6

ON conditions 8-30

ANYCONDITION 8-37

ENDFILE 8-42

FIXEDOVERFLOW 8-46

UNDEFINEDFILE 8-57

UNDERFLOW 8-59

VAXCONDITION 8-60

ZERODIVIDE 8-60

ON statement 8-30, D-5

ONCHAR built-in function 11-44

ONCHAR pseudovariable 11-79

ONCODE built-in function 8-48, 8-58, 11-45

ONFILE built-in function 8-43 to 8-44, 8-48, 8-58, 11-45

ONKEY built-in function 8-48, 11-46

ONLOC built-in function 11-46

ONSOURCE built-in function 11-47

ONSOURCE pseudovariable 11-80

ON-units

completion 8-65

default PL/I 8-60

invalid statements in 8-64

multiple statements in 8-14

restoring default handling 8-32

scope 8-63

to handle any condition 8-37

OPEN statement 9-3, D-5

LINESIZE option 9-5

PAGESIZE option 9-5

TITLE option 9-6

Opening a file 9-3

creating 9-9

effects 9-6

file positioning 9-10

implied attributes 9-7

Operands 6-5

conversion of 6-17

Operations

arithmetic 3-8

data type of result 6-22

required operands 6-5

bit-string 6-6

Boolean

defining 11-16

comparison

required operands 6-5

concatenation

required operands 6-5

logical

AND 6-8

AND THEN 6-10

EXCLUSIVE OR operator 6-10

NOT 6-8

OR 6-9

OR ELSE 6-11

required operands 6-5

nonarithmetic 6-22

relational operands 6-5

Operators 6-4

arithmetic 6-5

concatenation 6-14

infix 6-4

logical 6-6

precedence 6-15, D-13

prefix 6-4

relational 6-12

OPTIONAL attribute 2-45

OPTIONS option

DELETE statement 9-83

GET statement 9-18

PROCEDURE statement 7-3

PUT statement 9-29

READ statement 9-77

REWRITE statement 9-85

WRITE statement 9-80

OR

exclusive 11-17

operator 6-9

OR ELSE operator 6-11

OTHERWISE clause 8-18

Output

PUT statement 9-26

record 9-73

REWRITE statement 9-84

stream 9-33

to line printer 9-70

to terminal 9-70

WRITE statement 9-79

OUTPUT attribute 2-45, 9-10

Overflow

fixed-point data 8-46

floating-point data 8-50

OVERFLOW condition 8-50

Overlay defining 5-26

matching based variables by 5-14

POSITION attribute 2-47

rules for 5-28

OWNER_GROUP ENVIRONMENT option 2-30

OWNER_ID ENVIRONMENT option 2-30

OWNER_MEMBER ENVIRONMENT option 2-30

OWNER_PROTECTION ENVIRONMENT option 2-30

P

P format item 9-30, 9-50

Padding

bit-string 6-30

character-string 6-33

PAGE format item 9-52, 9-70

PAGE option of PUT statement 9-32

Page size

default 9-6

specifying 9-5

%PAGE statement D-5

PAGENO pseudovariable 11-80

Pages, end-of-page condition 8-43

PAGESIZE option 9-5

PARAMETER attribute 2-46

Parameter descriptors 7-12

VALUE attribute in 7-22

Parameters 7-10

arrays 7-13

character strings 7-15

declaring 7-13

matching with arguments 7-17

maximum number allowed 7-13

passing

structures 7-14

relationship to arguments 7-11

rules for specifying 7-13

specifying in PROCEDURE statement 7-2

structures 4-18

Parent activation 1-19

Period (.) picture character 3-26

PICTURE attribute 2-46

Picture characters 3-20

asterisk (*) 3-22

B 3-26

comma (,) 3-26

credit (CR) 3-27

debit (DB) 3-27

dollar ($) 3-24

encoded-sign 3-23

exponent(K and E) 3-28

I 3-23

minus(-) 3-24

nine (9) 3-22

period (.) 3-26

plus (+) 3-24

R 3-23

S 3-24

scaling factor (F) 3-27

slash (/) 3-26

T 3-23

V 3-21

Y 3-22

Z 3-22

Pictured variables 3-34

Pictures 9-30

character 3-20

character data 3-17

converting from other types 6-37

converting to arithmetic 6-27

converting to bit-string 6-32

converting to character-string 6-37

drifting characters 3-24

editing by 3-34

extracting value from 3-33

format item 9-50

iteration factor in 3-23

numeric data 3-19

specification 3-19

summary of characters 3-20

PL/I keywords not supported C-1

PLIRETV built-in function 11-47

Plus sign (+)

picture character 3-24

prefix operator 6-4

POINTER attribute 2-47

POINTER built-in function 11-47

Pointer data 3-49

Pointers 5-6

converting to offset 6-38, 11-44

data

in relational expression 6-14

internal representation 3-50

null value 11-43

obtaining values 5-9

passing as actual arguments 7-24

setting values

ADDR built-in function 11-11

ALLOCATE statement 5-22

SET option of READ 9-76, 9-88

valid value 5-9

POSINT built-in function 11-48

POSINT pseudovariable 11-80

POSITION attribute 2-47, 5-26

Position file

following DELETE 9-84

following LOCATE 9-89

following READ 9-77

following REWRITE 9-85

following WRITE 9-80

record files 9-89

stream I/O 9-14

Position string, stream I/O 9-67

Precedence of operations 6-15, D-13

Precision

arithmetic data types 3-8

default 3-9

fixed-point decimal 3-12

for floating-point data 3-16

pictured variables

defined by drifting characters 3-25

PRECISION attribute 2-48, 3-8

PRECISION built-in function 11-50

Prefix operator 6-4

Preprocessor built-in functions 10-29

Preprocessor statements 10-4

%ACTIVATE 10-6

assignment 10-5

conditions in 8-61

%DEACTIVATE 10-8

%DECLARE 10-9

%DO 10-10

%END 10-11

%ERROR 10-11

%FATAL 10-12

%GOTO 10-12

%IF 10-14

%INCLUDE 10-14

%INFORM 10-17

%Null 10-6

%PROCEDURE 10-17

%REPLACE 10-25

%RETURN 10-17, 10-26

%WARN 10-26

Preprocessor, about 1-21, 10-1

PRINT attribute 2-49, 9-10

Print file 9-70

declaring 2-49

PRINTER_FORMAT ENVIRONMENT option 2-30

Printers

end-of-page 8-43

output 9-70

Priority of operations 6-15, D-13

PRN-format carriage control 9-71

%PROCEDURE statement 10-17, D-6

STATEMENT option 10-22

PROCEDURE statement 7-2, D-6

label restriction 3-52

to define a procedure 1-16

Procedures 1-16, 7-1

`main' as name for 2-33, 7-2

blocks 1-13

declarations 7-2

outside procedures 2-3

entry points 3-58, 7-7

external 1-16, 7-18

declaring 2-33

IDENT option 7-3

internal 1-16

invoking 1-16

with CALL statement 7-9

with function reference 7-4

main procedure 1-16

parameters of 7-10

returning from 7-21

terminating 7-20

END statement 8-15

STOP statement 8-28

PROD built-in function 11-50

Programs

controlling execution 8-1

documenting 1-5

elements of 1-1

format of 1-12

structure of 1-12

terminating

with END statement 8-15

with STOP statement 8-28

PROMPT option 9-71

Pseudovariables 11-76, D-15

INT 11-77

ONCHAR 11-79

ONSOURCE 11-80

PAGENO 11-80

SUBSTR 11-83

UNSPEC 11-84

Punctuation marks 1-2

PUT statement 9-1, 9-26, D-6

conversion of values 6-19

execution of 9-33

forms 9-26

options 9-29

PUT EDIT 9-29

PUT LINE 9-30

PUT LIST 9-31, 9-69

PUT PAGE 9-32, 9-70

PUT SKIP 9-32

PUT STRING 9-58

Q

Qualifying reference, based variable 5-9

R

R format item 9-52

R picture character 3-23

RANK built-in function 11-51

RANK preprocessor built-in function 11-51

READ statement 9-1, 9-75, D-7

SET option 5-12

READ_AHEAD ENVIRONMENT option 2-30

READ_CHECK ENVIRONMENT option 2-30

READONLY attribute 2-49

RECORD attribute 2-50, 9-10

RECORD condition 8-50

Record files

access modes 9-73

attributes 9-73

Record I/O and unconnected arrays 4-30

RECORD_ID_ACCESS ENVIRONMENT option 2-30

RECORD_ID_FROM option(READ) 9-77

RECORD_ID_TO option

WRITE statement 9-80

RECORD_ID_TO option(READ) 9-77

Records

deleting from file 9-83

files 9-73

READ statement 9-75

READ with SET option 5-12

updating 9-84

writing records to 9-79

I/O 9-73

locating 9-87

reading 9-75

rewriting 9-84

writing 9-79

RECURSIVE option

ENTRY statement 7-6

PROCEDURE statement 7-3

REFER option 2-50, 4-18, 4-23

REFERENCE attribute 2-50

References

structure-qualified 4-27

to based variable 5-8

Relational operator 1-2, 6-12

REPEAT built-in function 11-51

REPEAT option, DO statement 8-6

Repetition of format item 9-60

%REPLACE statement 10-25, D-7

Replication factor 3-37, 3-42

RESIGNAL built-in subroutine 8-65, 11-75, D-16

Restricted integer expression 2-16, 2-19, 4-2

RETRIEVAL_POINTERS ENVIRONMENT option 2-32

%RETURN statement 10-17, 10-26, D-7

RETURN statement 7-21, D-7

conversion of values 6-18

terminating procedures 7-21

Returns

descriptor 2-51

value 7-21

RETURNS attribute 2-51

with ENTRY attribute 2-29

RETURNS option

ENTRY statement 7-6

PROCEDURE statement 7-3

REVERSE built-in function 11-52

REVERT statement 8-32, D-7

REVISION_DATE ENVIRONMENT option 2-32

REWIND_ON_CLOSE ENVIRONMENT option 2-32

REWIND_ON_OPEN ENVIRONMENT option 2-32

REWRITE statement 9-1, 9-84, D-8

SET option 5-13

RISC calling standard extensions B-8

ROUND built-in function 11-53

Row-major order 4-11

S

S picture character 3-24

%SBTTL statement D-8

SCALARVARYING ENVIRONMENT option 2-32, 9-75, 9-80, 9-84

Scale factor 3-12

binary 3-9

decimal 3-9

default 3-9

of pictured variable 3-21

Scaling Factor (F) picture character 3-27

Scope

attributes 2-9, D-10

INTERNAL attribute 2-42

of internal variables 5-3

of names 1-13

of ON-unit 8-65

of static variables 5-3

SEARCH built-in function 11-55

SELECT statement 8-18, D-8

Select-expression 8-18

Semicolon (;), as null statement 8-29

SEQUENTIAL attribute 2-52, 9-10

Sequential files 2-52

SET option

ALLOCATE statement 5-6, 5-22

example 5-10

READ statement 9-76, 9-88

example 5-12

S-floating format 3-16

Shared storage 5-28

SHARED_READ ENVIRONMENT option 2-32

SHARED_WRITE ENVIRONMENT option 2-32

SIGN built-in function 11-56

SIGNAL statement 8-31, D-8

Simple statement 1-8

SIN built-in function 11-57

SIND built-in function 11-57

Single-precision floating point 3-16

SINH built-in function 11-57

SIZE built-in function 11-57

SIZE condition 8-51

SKIP format item 9-55

SKIP option 9-28

GET statement 9-23

PUT statement 9-32

Slash (/) picture character 3-26

SOME built-in function 11-61

Source program format 1-12

Spaces 1-4

SPOOL ENVIRONMENT option 2-32

SQRT (Square root) built-in function 11-61

STATEMENT option(%PROCEDURE statement) 10-22

Statements 1-6

alphabetic summary 1-10

preprocessor 10-4

compound 1-9

condition prefix 1-7

format 1-7, D-11

functional summary 1-9

label 3-51

labels 1-8

simple 1-8

assignment 1-8

keyword 1-8

null 1-9

syntax of D-1 to D-8

STATIC attribute 2-53, 5-2

implied 2-33

implied by INTERNAL 5-4

Static variables, entry value 3-59

STOP statement 8-28, D-8

terminating subroutines or functions 7-20

Storage

allocating

for a based variable 5-22

for a controlled variable 5-22

for a static variable 2-53

for an automatic variable 2-17

within areas 3-62

attributes 2-9, D-10

automatic 5-2

based variables 5-5

based variables 2-17

bit string 3-45

built-in functions

ADDR 11-11

ALLOCATION 11-12

BYTESIZE 11-18

EMPTY 11-26

NULL 11-43

OFFSET 11-44

POINTER 11-47

SIZE 11-57

class 5-1

default 5-2

extensions to the standard B-9

defined 2-25, 5-25

example of allocation 5-10

freeing 5-23

internal variables 2-42

locating with ADDR 5-13

maximum size of data object 5-1

setting null pointer 11-43

sharing 5-28

specifying READONLY variable 2-49

static 5-2

Storage built-in functions

CURRENTSTORAGE 11-21

STORAGE 11-61

STORAGE condition 8-56

Storage sharing

with based variables 5-28

with defined variables 5-29

with parameters 5-29

with unions 5-29

STREAM attribute 2-53, 9-10

Stream files 2-53

access modes 9-12

associating with terminal 9-68

attributes 9-12

GET statement 9-16

I/O processing 9-12

PUT statement 9-26

Stream input 9-23

Stream output 9-33

STRING built-in function 11-62

String Handling

built-in functions

VERIFY 11-73

String handling

built-in functions

BOOL 11-16

COLLATE 11-20

COPY 11-20

EVERY 11-28

HIGH 11-31 to 11-32

LENGTH 11-36

LOW 11-37

MAXLENGTH 11-38

REPEAT 11-51

REVERSE 11-52

SEARCH 11-55

SOME 11-61

STRING 11-62

SUBSTR 11-63

TRANSLATE 11-67

TRIM 11-69

concatenation operator 6-14

replication factor 3-42

SUBSTR pseudovariable 11-83

STRING pseudovariable 11-82

STRINGRANGE condition 8-53

Strings

alignment 3-40

bit 3-40

constant 3-36

converting 6-23

defining overlays 5-28

fixed-length 3-38

replicating constants 3-37

varying-length 3-39

STRINGSIZE condition 8-55

STRUCTURE attribute 2-54

Structures 4-14

concatenating with STRING 11-62

declaration 2-6

declaring 4-14

as parameters 7-14

dimensioned 4-30

in an array 4-28

in assignment statements 4-28

level numbers 4-15

major 4-14, 4-17, 4-27

minor 4-14, 4-17, 4-27

naturally aligned 4-32

passing as arguments 4-18, 7-14

referring to members 4-27

structure-qualified reference 4-27

unaligned 4-32

union 4-16

Subroutines

CALL statement 7-9

external 7-18

file-handling D-16

summary 11-75, D-16

terminating 7-20

SUBSCRIPTRANGE condition 8-55

Subscripts 4-5

label 3-52

refering to array of structures 4-30

variable 4-6

SUBSTR built-in function 11-63

SUBSTR pseudovariable 11-83

Substrings

obtaining 11-63

overlay 11-83

SUBTRACT built-in function 11-64

SUM built-in function 11-65

Summary of PL/I language features D-1 to D-17

SUPERSEDE ENVIRONMENT option 2-32

Symbols, global 2-36 to 2-37

SYSIN default file 9-68

SYSOUT default file 9-68

SYSPRINT default file 9-68

SYSTEM_PROTECTION ENVIRONMENT option 2-32

T

T picture character 3-23

-T variant option 11-72

TAB format item

definition 9-55

Tabs 1-4

TAN built-in function 11-66

TAND built-in function 11-66

TANH built-in function 11-66

TEMPORARY ENVIRONMENT option 2-32

Terminal I/O 9-68, 9-70

Termination

END statement 8-15

of procedures 7-20

STOP statement 8-28

Text, including 10-14

T-floating format 3-16

TIME built-in function 11-66

Time of day 11-23

obtaining 11-66

Timekeeping

built-in functions

DATETIME 11-23

Timekeeping built-in functions

DATE 11-22

DATETIME 11-23

TIME 11-66

TITLE option 9-6, 9-8

in files 9-9

%TITLE statement D-8

to bit-string 6-33

Transfer control

GOTO statement 8-22

LEAVE statement 8-26

TRANSLATE built-in function 11-67

TRANSLATE preprocessor built-in function 11-67

TRANSMIT condition 8-56

TRIM built-in function 11-69

TRIM preprocessor built-in function 11-69

TRUNC built-in function 11-71

TRUNCATE attribute 2-56

TRUNCATE ENVIRONMENT option 2-32

Truncation

of bit-string 6-30

of character-string 6-33

of decimal value 11-71

TYPE attribute 2-54, 4-18

U

UNALIGNED attribute 2-57

UNBUFFERED attribute 2-20, 2-57

Unconnected arrays 4-30

UNDEFINEDFILE condition 8-57, 9-9

UNDERFLOW condition 8-59

UNDERFLOW option

PROCEDURE statement 7-3

UNION attribute 2-57, 4-16

UNSPEC built-in function 11-71

UNSPEC pseudovariable 11-84

UNTIL option 8-4

UPDATE attribute 2-58, 9-10

Updating file

rewriting record 9-84

Updating files

deleting records 9-83

USER_OPEN ENVIRONMENT option 2-32

User-generated diagnostic messages 10-27

%ERROR 10-11

%FATAL 10-12

%INFORM 10-17

%WARN 10-26

using with based variables 5-6

V

V picture character 3-21

VALID built-in function 3-33

VALUE attribute 2-59, 5-4

parameter descriptor 7-22

Values

implementation-defined standard B-10

passing by argument 2-59

VARIABLE attribute 2-60

VARIABLE option

ENTRY attribute 2-28

Variables 1-20

area 3-62

assigning value to 6-1

automatic 2-17, 5-2

based 2-17, 5-5

associating with storage 5-5

example 5-16

referring to 5-8

bit-string 3-43

character string 3-37

declaring 1-20, 2-2

defined 5-25

criteria for declaring 5-26

entry 3-58

external 5-3

file 3-61, 9-2

fixed-point decimal 3-12

in begin blocks 8-14

initializing 2-37

internal 5-3

label 3-55

internal representation 3-56

localizing 1-15, 8-14

offset

assigning values to 3-51

declaring 3-50

pictured 3-34

assigning values to 3-32

extracting values from 3-33

preprocessor 10-1

static 5-2

using as subscripts 4-6

VARIANT preprocessor built-in function 11-72

VARYING attribute 2-60

VAX calling standard extensions B-8

VAXCONDITION condition 8-60

VERIFY built-in function 11-73

W

-w (--nowarn) option 6-24

WARN preprocessor built-in function 11-74

%WARN statement 10-26 to 10-27, D-8

Warning messages 10-26

data conversion 6-24

WHEN clause 8-18

WHILE option, DO statement 8-3

WORLD_PROTECTION ENVIRONMENT option 2-32

WRITE statement 9-1, 9-79, D-8

WRITE_BEHIND ENVIRONMENT option 2-32

WRITE_CHECK ENVIRONMENT option 2-32

X

X format item 9-57

XOR operation 11-17

Y

Y picture character 3-22

Year, current 11-22 to 11-23

Z

Z picture character 3-22

ZERODIVIDE condition 8-60

Reader's Comments Kednos PL/I for UNIX Reference 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. The compiler issues a warning for each variable that you declare implicitly.

2. The constant 3.32 is an approximation of log2(10), the number of bits required to represent a decimal digit.

3. Ignored by the Kednos PL/I for UNIX compiler. Included for compatibility with the Kednos OpenVMS PL/I compiler.

4. Your program may work on Digital UNIX on supported non-VSAM media, without the VSAM options, as VSAM is a function of the media not the code.