Pli New 22012006
Pli New 22012006
Pli New 22012006
23/01/2006
PL/I
Page:- 1 / 119
PL/I
SECTION NO.
23/01/2006
CONTENTS
TOPIC
Page:- 2 / 119
PAGE
SECTION 1
SECTION 2
SECTION 3
12
SECTION 4
PROCEDURES, FUNCTIONS
21
SECTION 5
32
SECTION 6
CONTROL STATEMENTS
44
SECTION 7
47
SECTION 8
ARRAYS
60
SECTION 9
63
SECTION 10
STORAGE CONTROL
69
SECTION 11
82
SECTION 12
85
SECTION 13
RECORD I/O
93
SECTION 14
96
SECTION 15
102
PL/I
23/01/2006
SECTION 1
Page:- 3 / 119
back
PL/I
23/01/2006
:
&
|
>
<
_
?
Page:- 4 / 119
Colon
NOT symbol
AND symbol
OR symbol
Greater than symbol
Less than symbol
Break (underscore)
Question mark
PL/I
23/01/2006
PL/I CONSTANTS
Decimal Fixed Point
Page:- 5 / 119
0.1234E+2
X.XXXXXE+XX, X.XXXXXE-XX
Maximum Precision is 33
Character String
'ABCDE'
'ABCD''EF', (2)'ABCD'
Maximum length is 32767
'11011'B, (16)'0'B
Maximum length is 32767
1011B
0.11011011E+48B
Maximum Precision is 109
*/
*/
100 90 80 70 90
OR
90
70
80
90
100
OR
100,90,80,70,90
In List Directed I/O no record boundaries are considered. Items are either separated by a
blank or a comma
GET LIST (A,B) COPY; /* additionally copies the data to SYSPRINT */
Example of Input 12.90,.04E+3,'ABCD','1010'B
Example
DECLARE DATA1
CHAR(12);
GET LIST (DATA1);
OUTPUT
PUT LIST (50,'ABC',123,127);
PUT LIST (23,86,87);
1
50
86
25
ABC
87
49
123
73
127
97
23
121
PL/I
23/01/2006
Page:- 6 / 119
PROGRAM STRUCTURE
MNPROC: PROCEDURE OPTIONS(MAIN);
.
.
CALL SUBPROC_1;
CALL SUBPROC_2;
.
RETURN;
*PROCESS;
SUBPROC_1: PROCEDURE;
.
.
END SUBPROC_1;
*PROCESS;
SUBPROC_2: PROCEDURE;
.
.
END SUBPROC_2;
END MNPROC;
PL/I
23/01/2006
//PLI.SYSIN DD *
MYPROG: PROCEDURE OPTIONS(MAIN);
DCL FIELD1 FIXED DECIMAL(7,2);
DCL FIELD2 FIXED DECIMAL(7,2);
DCL SUM FIXED DECIMAL(7,2);
GET DATA (FIELD1,FIELD2);
CALL ADD;
PUT SKIP LIST(SUM);
PUT SKIP DATA;
/* Procedure ADD */
ADD:PROCEDURE;
SUM=A+B;
END ADD;
/* End of Procedure ADD */
END MYPROG;
/*
//GO.SYSIN DD *
FIELD2=1.23,FIELD1=3.45;
/*
//
Page:- 7 / 119
PL/I
23/01/2006
SECTION 2
Page:- 8 / 119
back
IEL1C
IEL1CL
IBMZC
IBMZCL
PL/I
23/01/2006
Page:- 9 / 119
PL/I
23/01/2006
Page:- 10 / 119
[NO]GONUMBER
controls whether the compiler produces code which will give line
number from the source program to be included in run time
messages
[NO]GOSTMT
[NO]OBJECT
[NO]OPTIONS
[NO]SOURCE
PL/I
23/01/2006
Page:- 11 / 119
[NO]MACRO
[NO]MAP
[NO]LIST
[NO]OFFSET
The compiler prints the offset of the object code for every line
relative to the entry point of the procedure. It is an alternative
way of identifying the failing line in your program from run time
error messages.
SYSTEM (MVS|CMS|TSO|CICS..)
Specifies the format in which parameters are passed to the main
PLI procedure (this is system dependent)
[NO]XREF(FULL|SHORT) Controls inclusion of cross reference table in the listing
These options can be set in the source by the
%PROCESS option,option,..;
or
*PROCESS option,option,.;
You can look at the PL/I programmers guide for explanation on all possible options.
PL/I
23/01/2006
SECTION 3
Page:- 12 / 119
back
Storage
4 bits / decimal
digit, sign
Basic Usage
Arithmetic
Operations
FIXED BINARY
Fixed Point
Halfword or
Fullword
Arithmetic
Operations
FLOAT DECIMAL
FLOAT BINARY
Floating Point
32 | 64 | 128 Bits
Arithmetic
Operations
PICTURE
Zoned Decimal
Numeric
Character
CHARACTER
Character
Alphabetic
Character
BIT
Bit
Logical
Data
/*
only base defined
/* scale and precision default to FLOAT (6)
*/
*/
DCL A BINARY
/*
only base defined
/*scale and precision default to FLOAT(21)
*/
*/
DCL A FIXED;
/*
only scale defined
*/
/* base and precision default to DECIMAL (5,0)*/
DCL A FLOAT /*
PL/I
23/01/2006
Page:- 13 / 119
CHAR(20) INIT('ABCDEFGH');
/* Left Justified and padded on right with blanks
*/
CHAR(20)
VARYING;
/* This is a two byte length field followed */
/* by a 20 byte field for data
*/
/* overlay on A
*/
/* overlay on A
*/
/* ERROR !, not allowed
*/
Character String
Bit String
Defined Item
coded arithmetic variable with same BASE, SCALE,
PRECISION
Character string or Bit String
Character string or Bit string
Position Attribute
DCL
CHAR_LIST
DCL
A
CHAR(20);
CHAR(10) DEFINED CHAR_LIST;
PL/I
23/01/2006
DCL
Page:- 14 / 119
Initial Attribute
Use this to initialise variables
DCL
A
FIXED DECIMAL (7,2) INITIAL(24.50);
DCL
B
CHAR(10) INIT((10)'A');
DCL
C
BIT(2) INIT('00'B);
DCL
D
FIXED BINARY(15) INIT (0);
same effect can also be achieved by an assignment statement at lower code efficiency.
PL/I Data Attributes
FIXED DECIMAL ( Also represented as FIXED, DECIMAL FIXED)
Data Format
Packed Decimal
Type of Data
Coded arithmetic
Default Precision
5 Decimal Digits
S99,999
Maximum Precision
15 Decimal digits
S999,999,999,999,999
Used for monetary calculations
Example:
DCL
A
FIXED DECIMAL (5,2) INIT (123.45);
FIXED BINARY
Data Format
Fixed point signed binary (Halfword or Fullword)
Type of Data
Coded arithmetic
Default Precision
15 Bits plus sign bit
(Decimal 32,767)
Maximum Precision
31 Bits plus sign bit
(Decimal 2,147,483,647)
Used for fast computations, usually for integers
Variables beginning I-N default to fixed Binary unless explicitly defined otherwise
Can be used for representing fractions, but fractions do not have exact representation
in Binary .
Example:
DCL
A
FIXED BINARY (31) INIT(2147483647);
FLOAT DECIMAL (Also represented as DECIMAL)
Data Format
Floating Point, 32bit, 64 bit or 128 bit representation
Type of data
Coded Arithmetic
Default precision
6 Decimal digits
Maximum precision
33 Decimal digits
Examples:
DCL
A
FLOAT DEC(6);
DCL
A
DEC (6);
/* Defaults to FLOAT */
DCL
A
FLOAT DEC(6) INIT(6.0E+12);
Note that in storage there is no difference between FLOAT BINARY and FLOAT
DECIMAL data representation. They are both represented as E, D and L format floating
point data, depending on the precision.
BIT
Data Format
bit (8 bits per byte)
Type of Data
Logical
Default length
None
Maximum Length
32767 bits
Examples
DCL
FLAGS BIT(8)
INIT('11100001'B);
DCL
FLAGS BIT(32)
INIT((32)'0'B);
Note that bit strings are (like character strings ) assigned left to right. If a smaller bit string
is assigned to a larger string, padding with binary zeroes takes place on the vacant right
PL/I
23/01/2006
Page:- 15 / 119
positions. If the assigned bit string is larger than the receiving field then truncation takes
place on the right.
CHARACTER
Data Format
Character
Type of data
Alphanumeric (anything goes)
Default length
None
Maximum Length
32767 characters
On assignment data is left aligned and vacant positions on right are padded with spaces.
If the receiving field is smaller, then truncation takes place on the right.
Example:
DCL
A
CHAR(20) INIT('ABCDEF');
DCL
A
CHAR(10) INIT((10)' ');
DATA DECLARATION
Explicit Declaration
The scope of an explicit declaration of a name is that block to which the declaration is
internal, including all contained blocks, except those blocks (and any blocks contained
within them) to which another explicit declaration of the same name is internal.
A block in PL/I can be a Procedure block or Begin block. Begin blocks are delimited by
BEGIN and END keywords.
P: PROC;
DCL A, B;
Q: PROC;
DCL B, C;
R: PROC
DCL C, D
*/
END R;
/* now c of proc q is visible
/* b of proc q is visible
/* a of proc p is visible
*/
*/
*/
*/
END Q;
*/
END P;
DECLARE Statement
The DECLARE statement specifies attributes of a name and its position determines the
scope of the declaration of the name.
DECLARE [level] name [attribute] , [level] name [attribute]
Factoring of Attributes
Attributes common to several names can be factored to eliminate repeated specification
of the same attribute.
DECLARE (A,B,C,D) BINARY FIXED (31);
PL/I
23/01/2006
Page:- 16 / 119
A name that appears in the BASED attribute, in a SET option, or on the left-hand side
of a locator qualification symbol is given the POINTER attribute. (You will get a
detailed explanation of BASED and POINTER attribute in the section on Storage
Management).
A name that appears in an IN option, or in the OFFSET attribute, is given the AREA
attribute. (You will get a detailed explanation of BASED and POINTER attribute in the
section on Storage Management).
Examples of contextual declaration are:
READ FILE (ABC) INTO (Q);
ALLOCATE X IN (S);
In these statements, ABC is given the FILE attribute, and S is given the AREA attribute.
PL/I
23/01/2006
Page:- 17 / 119
Scopes of Declarations
P
A: PROCEDURE;
DECLARE P, Q;
B: PROCEDURE;
DECLARE Q;
R = Q;
C: BEGIN;
DECLARE R;
DO I = 1 TO 10;
.
END;
END C;
END B;
D: PROCEDURE;
DECLARE S;
END D;
END A;
P is declared in the block A and known throughout A since it is not re-declared.
Q is declared in block A, and re-declared in block B. The scope of the first declaration
of Q is all of A except B; the scope of the second declaration of Q is block B only.
R is declared in block C, but a reference to R is also made in block B. The reference
to R in block B results in an implicit declaration of R in A, the external procedure.
Therefore, two separate names (R and R`) with different scopes exist. The scope of
the explicitly declared R is block C; the scope of the implicitly declared R is all of A
except block C.
I is referred to in block C. This results in an implicit declaration in the external
procedure A. As a result, this declaration applies to all of A, including the contained
procedures B, C, and D.
S is explicitly declared in procedure D an is known only within D.
INTERNAL and EXTERNAL Attributes
INTERNAL specifies that the name can be known only in the declaring block. Any other
explicit declaration of that name refers to a new object with a different, non overlapping
scope.
A name with the EXTERNAL attribute can be declared more than once, either in different
external procedures or within blocks contained in external procedures. All declarations of
the same name with the EXTERNAL attribute refer to the same data.
EXTERNAL is the default for controlled variables, file constants, entry constants,
Because external declarations for the same name all refer to the same data, they must all
result in the same set of attributes.
Language Specified Defaults
PL/I
23/01/2006
Page:- 18 / 119
When a problem-data name has not been declared with a data type or when the
RETURNS option is omitted from a function procedure, the default is coded arithmetic
problem data.
If mode, scale, and base are not specified by a DECLARE or DEFAULT statement, or by
a RETURNS option, variables with names beginning with any of the letters I through N
are given the attributes REAL FIXED BINARY (15,0), and those with names beginning
with any other alphabetic character are given the attributes REAL FLOAT DECIMAL (6).
If mode, scale, or base is specified by a DECLARE or DEFAULT statement, or by a
RETURNS option, the remaining attributes are completed from the following list of
defaults:
The default base is DECIMAL.
The default scale is FLOAT.
The default mode is REAL.
Default precision is then completed from the following list:
(5,0) for DECIMAL FIXED
(15,0) for BINARY FIXED
(6) for DECIMAL FLOAT
(21) for BINARY FLOAT
For example the statement:
DCL X BINARY (15)
/* no scale specified .gets the attributes REAL and FLOAT
*/
*/
DEFAULT Statement
The DEFAULT statement specifies data-attribute defaults (when attribute sets are not
complete). Any attributes not applied by the DEFAULT statement for any partially
complete explicit or contextual declarations, and for implicit declarations, are supplied by
language-specified defaults.
Abbreviation: DFT RANGE(letter)
Specifies that the defaults apply to names that begin with the name(s) specified. Letter
can be any letter in the English alphabet.
Example:
RANGE (ABC)
applies to these names:
ABC
ABCD
ABCDE
but not to:
ABD
ACB
AB
A
Hence a single letter in the range-specification applies to all names that start with that
letter.
PL/I
23/01/2006
Page:- 19 / 119
Conversion
A is converted
to FLOAT
Comments
scale is different
FIXED -> FLOAT
C is converted
to FIXED BIN
base is different
DEC -> BIN
E is converted
to FLOAT BIN
DCL K CHAR(13),
I CHAR(5),
J BIT(8);
K = I || J;
J is converted to
CHAR(8)
Assignment Statements
PL/I
23/01/2006
DCL
DCL
DCL
A
B
C
Page:- 20 / 119
C = A+B;
/* note that assignment is the = sign */
A,B,C = 0;
/* all three variables assigned value 0 */
C = A*3 ;
/* Right hand side is an expression */
Note that the assigned term can be a variable or an expression ( of constants /
constants and variables.
Arithmetic Operations
**
Exponentiation
*
Multiplication
/
Division
+
Addition
Subtraction
Rule 1: Order of resolution in an arithmetic expression is Exponentiation first going right
to left. Next moving from left to right multiplication or division, whichever appears
first. Then addition or subtraction , whichever appears first, moving from left to
right.
Rule 2: If parenthesis are used in an expression, the innermost expression within the
parenthesis is resolved first, in consonance with Rule 1, and the resolution
moves outwards. Example A * (B+C)
/* resolve B+C first and multiply the result by A
*/
Rule 3: Prefix operators are performed before infix operators
Example A = B**-A
/* Negate A first. Then raise B to the power of A
*/
Rule 4: Any expression or element may be raised to a power which can be a negative
value Example A**2, (A+5)**3, A**-B
Rule 5: If two or more operators with the highest priority appear in the same expression,
the order of priority is from right to left
Example -A**2 /* Exponentiation first, Negation next
*/
A**B**C /* Evaluate B**C first.Then raise A to the resultant power*/
Operator Precedence
Level
Operator
1
prefix +, prefix -, ** ,
2
*, /
3
infix +, infix 4
||
5
>=,>,=,<, =,..
6
&
7
|
PL/I
23/01/2006
SECTION 4
PROCEDURES, FUNCTIONS
Page:- 21 / 119
back
Built In Functions
Declaration required
DCL
function-name BUILTIN;
Example
DCL
DATE
BUILTIN;
The important built in functions are covered in detail in the next section. Only one
example of the SUBSTR built in function is explained below to introduce the concept of a
PSEUDO variable
Pseudo variables
SUBSTR(arg1,I,J)
Returns a sub-string from arg1 (character, Bit or Picture attribute)starting at position I and
J characters long. Arg1 can be a constant, variable name or an expression. It may also
be specified as a LIST item in a GET or PUT statement.
SUBSTR is a built in function that can appear on the LHS of an assignment statement (or
as a receiving field, for example in a GET statement).
Example:
DCL
DATE CHAR(6) INIT('980215');
SUBSTR(DATE,1,2)='99';
/* change YY to 99
*/
GET LIST (SUBSTR(DATE,3,4)); /* get MMDD from SYSIN
*/
PROGRAM ORGANISATION
Programs
A PL/I program consists of one or more external procedures. Each procedure can
contain other procedures, begin-blocks, or both.
Program Activation
A PL/I program becomes active when a calling program invokes the main procedure.
CONTRL: PROCEDURE OPTIONS(MAIN);
CALL A;
CALL B;
CALL C;
END CONTRL;
Blocks
A block is a delimited sequence of statements that determines the scope of the
names declared within it, limits the allocation of automatic variables, and
determines the scope of DEFAULT statements.
Two kinds of blocks: procedure blocks and begin-blocks.
Begin-blocks and procedures can contain declarations that are treated as local
definitions of names.
These declarations are not known outside their own block.
Automatic storage is allocated upon entry to the block where the storage is
declared. The storage is freed upon exit from the block.
PL/I
23/01/2006
Page:- 22 / 119
Block Activation
Except for the main procedure, external and internal procedures contained in a
program are activated only when they are invoked by a procedure reference.
Begin-blocks are activated through sequential flow or as ON-units.
During Block Activation:
Storage is allocated for automatic variables and initialisation, if specified.
Currently active blocks known to the procedure are identified, so that the correct
generations of automatic storage are accessible, and the correct ON-units can be
entered.
Storage is also allocated at this time for any dummy arguments that might be created
in this block.
Block Termination
A procedure is terminated when control passes back to the invoking block or to
some other active block, by means other than a procedure reference. Similarly, a
begin-block is terminated when control passes to another active block, by means
other than a procedure reference.
During block termination:
The ON-unit environment is re-established as it existed before the block was
activated.
PL/I
23/01/2006
Page:- 23 / 119
PROCEDURE;
.
.
.
END NAME;
The leftmost label of the PROCEDURE statement represents the primary entry point of
the procedure. Optionally, additional labels define secondary entry points. The ENTRY
statement also defines secondary entry points.
B: ENTRY;
PROCEDURE and ENTRY Statements
A procedure (subroutine or function) can have one or more entry points. The primary
entry point to a procedure is established by the leftmost label of the PROCEDURE
statement. Secondary entry points to a procedure are established by additional labels of
the PROCEDURE statement and by the ENTRY statement.
A: I: PROCEDURE (X);
is the same as:
PL/I
23/01/2006
Page:- 24 / 119
A: PROCEDURE (X);
I : ENTRY (X);
Declaring an External Entry Point
DCL Y EXTERNAL ENTRY;
When an EXTERNAL ENTRY is declared without a parameter descriptor list, matching
between parameters and arguments does not occur. Therefore, no diagnostic message is
issued for any incorrect (Number, Type or sequence)arguments that are specified in a
CALL to such an entry point.
Example:
DECLARE X ENTRY EXTERNAL;
CALL X(parameter);
/* No diagnostic message issued */
Format for PROCEDURE statement
entry-constant: PROCEDURE (parameter, parameter,)
RETURNS(attribute) OPTIONS (Options-list)
Format for ENTRY statement
entry-constant: ENTRY (parameter, parameter,)
RETURNS(attribute) OPTIONS (Options-list)
Important OPTIONS are
BYADDR or BYVALUE
Specify how all parameters defined for this procedure entry are passed. If you specify
BYADDR, parameters are received by address. If you specify BYVALUE, parameters are
received by value. Any change to a parameter that is being passed by value is not
reflected in the argument passed by the caller. BYADDR is the default
BYVALUE can be specified for EXTERNAL PROCEDURE statements, but it cannot be
specified for internal procedures or ENTRY statements. Additionally BYVALUE entry
points can only have scalar arguments and return values that are either POINTER or
REAL FIXED BINARY(31,0)
BYADDR is the default.
Example:
EXTR: PROCEDURE(A,B) OPTIONS (BYADDR);
DCL (A,B) FLOAT;
MAIN
The PL/I procedure is the initial procedure of a PL/I program. The operating
system control program invokes it as the first step in the execution of that
program.
PL/I
23/01/2006
Page:- 25 / 119
Any number of arguments can be passed in the CALL statement invoking the
entry, from zero up to the number specified by the entry declaration, but
intervening arguments cannot be omitted.
Parameter Attributes
Because a parameter has no associated storage within the invoked procedure, it cannot
be declared to have any of the storage attributes STATIC, AUTOMATIC, BASED, or
DEFINED. However, it can be declared to have the CONTROLLED attribute.
Procedure Activation
After the keyword CALL in a CALL statement.
After the keyword CALL in the CALL option of the INITIAL attribute
Example: SET_UP is the name of a procedure that can set the initial values of
elements in TABLE. X and Y are arguments passed to SET_UP.
DECLARE TABLE (20,20) INITIAL CALL SET_UP (X,Y);
As a function reference
Entry Points
A:
READIN:
PROCEDURE;
statement-1
statement-2
ERRT: ENTRY;
statement-3
statement-4
statement-5
NEXT: RETR: ENTRY;
statement-6
...
END READIN;
In the example, A is the primary entry point. A and READIN specify the same entry point,
as do NEXT and RETR. However note that depending on the entry point used to invoke
the procedure, the code executed can be different. The procedure can be activated by
any of the following statements:
CALL
CALL
CALL
CALL
CALL
A;
ERRT;
NEXT;
RETR;
READIN;
Entry Variables
DECLARE ENT1 ENTRY VARIABLE;
ENT1 = ERRT;
CALL ENT1; /* this call and the next call have the same effect
CALL ERRT; /* this call and the previous have the same effect
Procedure Termination
Normal procedure termination occurs when:
*/
*/
PL/I
23/01/2006
Page:- 26 / 119
PL/I
23/01/2006
Page:- 27 / 119
PL/I
23/01/2006
Page:- 28 / 119
PROCEDURE;
GET LIST (A, B, C, Y);
X = Y**3+SUBA(A,B,C);
.
.
END MAINP;
SUBA: PROCEDURE (U,V,W) RETURNS (BIN FLOAT (21));
DCL (U,V,W) . . . ;
IF U > V + W
THEN RETURN (0);
ELSE
RETURN ( U*V*W);
END SUBA;
Association of Arguments and Parameters
PL/I
23/01/2006
Page:- 29 / 119
When a function or subroutine is invoked, parameters in the parameter list are associated
, from left to right, with the arguments in the argument list. The number of parameters and
arguments must be the same.
Dummy Arguments
A reference to an argument, not its value, is generally passed to a subroutine or function.
This is known as passing arguments by reference.
However, this is not always possible, for example when constants are passed. Therefore,
the compiler allocates storage (in storage belonging to the invoking procedure) for some
arguments using attributes that agree with the parameter, converts, and assigns the
argument to the allocated storage, and then passes a reference to the allocated storage.
These storage locations are called dummy arguments. Any change to a parameter for
which a dummy argument has been created is reflected only in the value of the dummy
argument and not in the value of the original argument from which it was constructed.
A dummy argument is created when the original argument is any of the following:
A constant.
An expression with operators, parentheses, or function references.
A variable whose data attributes or alignment attributes are different from the
attributes declared for the parameter.
In the case of arguments and parameters with the PICTURE attribute, a dummy
argument is created unless the picture specifications match exactly, after any
repetition factors are applied.
A controlled string or area (because an ALLOCATE statement could change the length
or extent).
Passing an Argument to the MAIN Procedure
TOM: PROC (PARAM) OPTIONS (MAIN) ;
DCL PARAM CHAR(100) VARYING;
When NOEXECOPS is specified, the MAIN procedure can have a single parameter
that is a VARYING CHARACTER string. The parameter is passed as is, and a
descriptor is set up. (/, if contained in the string, is treated as part of the string).
Example:
MAIN: PROC(PARM) OPTIONS(MAIN NOEXECOPS);
DCL PARM CHAR(n) VARYING;
Note that the OPTION NOEXECOPS implies that the PARM string is not evaluated
by the run environment of MVS but passed unchanged to the user program.
Shows a MAIN procedure that can be invoked as follows:
//
PL/I
23/01/2006
Page:- 30 / 119
BEGIN;
statement-1
statement-2
.
.
.
statement-n
END B;
Unlike a procedure, a label is optional for a begin-block.
Begin-block Activation
Begin-blocks are activated through sequential flow or as a unit in an IF, ON, WHEN, or
OTHERWISE statement. Control can be transferred to a labelled BEGIN statement by
execution of a GO TO statement.
Begin-Block Termination
A begin-block is terminated when control passes to another active block by some means
other than a procedure reference; that is, when:
Control reaches the END statement for the block. When this occurs, control moves to
the statement physically following the END, except when the block is an ON-unit.
The execution of a GO TO statement within the begin-block (or any block activated
from within that begin-block) transfers control to a point not contained within the block.
A STOP or EXIT statement is executed (thereby terminating execution of the current
task and all its sub-tasks).
Control reaches a RETURN statement that transfers control out of the begin-block
(and out of its containing procedure as well).
Entry Data
Entry data can be an entry constant or the value of an entry variable. An entry constant is
a name written as a label prefix to a PROCEDURE or ENTRY statement, or a name
declared with the ENTRY attribute and not the VARIABLE attribute. An entry constant can
be assigned to an entry variable.
Example:
P:
PROCEDURE;
DECLARE EV ENTRY VARIABLE,
(E1,E2) ENTRY;
EV = E1;
CALL EV;
EV = E2;
CALL EV;
PL/I
23/01/2006
Page:- 31 / 119
BUILTIN Attribute
Specifies that the name is a built-in function name, PSEUDOVARIABLE name, or built-in
subroutine name
A:
PROCEDURE;
DECLARE SQRT FLOAT BINARY;
X = SQRT;
/* programmer declared SQRT is assigned */
B: BEGIN;
DECLARE SQRT BUILTIN;
Z = SQRT(P);
/* internal SQRT function is called*/
END B;
END
A;
RETURN Statement
The RETURN statement terminates execution of the procedure that contains the
RETURN statement.
RETURN (expression);
The RETURN statement with expression is used to terminate a procedure invoked by a
function reference.
PL/I
23/01/2006
Page:- 32 / 119
SECTION 5
PL/I
23/01/2006
Page:- 33 / 119
PL/I
23/01/2006
Page:- 34 / 119
P1:PROCEDURE;
DCL X CHAR(2);
DCL Y CHAR(2);
DCL Z CHAR(2);
DCL SUM FIXED DEC(7);
.
.
CALL P2;
.
.
P2:PROCEDURE;
DCL A CHAR(2);
DCL B CHAR(2);
DCL C CHAR(2);
DCL SUM CHAR(7);
/* this hides the SUM in P1
*/
X = 'AB';
/* Parameters in outer block can be accessed */
.
.
END P2;
END P1;
Note: X,Y and Z are known to P1.However A,B and C are not known to P1
A,B and C come into existence only when P2 is invoked
X,Y,Z,A,B and C are all known to P2.
Inner blocks can see out. Outer blocks cannot see inwards.
Any data item with the EXTERNAL attribute tells the compiler that this variable is known
outside this module and is to be allocated once in the Global data area. However all other
modules which refer to this variable must declare this variable with same name and
attributes including the EXTERNAL attribute.
Classification of Built In Functions
To aid in their description, built-in functions are listed in classes below. The first four
classes are computational built-in functions.
String-handling
Arithmetic
Mathematical
Array-handling
Condition-handling
Storage control
Event
Input / Output
Miscellaneous
String-Handling Built In Functions
The string-handling built-in functions simplify the processing of bit and character strings.
They are:
BIT
BOOL
CHAR
GRAPHIC
HIGH
INDEX
LENGTH
LOW
MPSTR
REPEAT
STRING
SUBSTR
TRANSLATE
UNSPEC
VERIFY
PL/I
23/01/2006
Page:- 35 / 119
DECIMAL
DIVIDE
FIXED
FLOAT
FLOOR
IMAG
MAX
MIN
MOD
MULTIPLY
PRECISION
REAL
ROUND
SIGN
TRUNC
ONFILE
ONKEY
ONLOC
ONSOURCE
Use of these functions is in context (returns a meaningful value) when within the scope of
an ON-unit entered for the condition specific to the built-in function, or within an ON-unit
for the ERROR or FINISH condition when raised as an implicit action. All other uses are
out of context.
Storage Control Built In Functions
The storage-control built in functions allow you to determine the storage requirements and
location of variables, to assign special values to area and locator variables, to perform
conversion between offset and pointer values, and to obtain the number of generations of
a controlled variable. They are:
ADDR
ALLOCATION
ENTRYADDR
NULL
POINTERADD
POINTERVALUE
PL/I
23/01/2006
BINARYVALUE
CURRENTSTORAGE
EMPTY
OFFSET
POINTER
Page:- 36 / 119
STORAGE
SYSNULL
PLISRTD
PLITEST
Pseudo-variables
Pseudo-variables represent receiving fields. Except when noted in the description, the
Pseudo-variables :
Can appear on the left of the assignment symbol in an assignment.
Can appear in a data list of a GET statement or in the STRING option of a PUT
statement.
Some of the commonly used Pseudo-variables are:
ONCHAR
ONSOURCE
STRING
SUBSTR
ADDR (Storage control)
ADDR returns the pointer value that identifies the generation of x. The syntax for ADDR
is:
ADDR (X) Reference to variable of any data type,
ALLOCATION (Storage Control)
ALLOCATION returns a FIXED BINARY (31,0) value specifying the number of
generations that can be accessed in the current task for X. The syntax for ALLOCATION
is:
ALLOCATION (X)
BINARYVALUE (Storage Control)
BINARYVALUE returns a REAL FIXED BIN (31,0) value that is the converted value of its
pointer expression, X. The syntax for BINARYVALUE is:
PL/I
23/01/2006
Page:- 37 / 119
BINARYVALUE (X)
COUNT (Input / Output)
COUNT returns a FIXED BINARY (15,0) value specifying the number of data items
transmitted during the last GET or PUT operation on X. The syntax for COUNT is:
COUNT (X)
X is a File-reference. The file must be open and have the STREAM attribute.
CURRENTSTORAGE (Storage Control)
CURRENTSTORAGE returns a FIXED BINARY (31,0) value giving the implementationdefined storage in bytes, required by X . The syntax for CURRENTSTORAGE is:
CURRENTSTORAGE (X)
DATAFIELD (Condition-Handling)
DATAFIELD is in context in a NAME condition ON-unit (or any of its dynamic
descendants), and returns a character string whose value is the contents of the field that
raised the condition.
DATAFIELD ( )
DATE (Miscellaneous)
DATE returns a character string, length 6, in the format YYMMDD. The syntax for DATE
is:
DATE ( )
The returned character string represents:
YY
last two digits of the current year
MM
Current month
DD
Current day
DATETIME (Miscellaneous)
DATATIME returns a character string, length 17, in the format of
YYYYMMDDHHMMSSTTT. The syntax for DATATIME is:
DATETIME ( )
The returned character string represents:
YYYY
MM
DD
HH
MM
SS
TTT
Current year
Current month
Current day
Current hour
Current minute
Current second
Current millisecond
DIM (Array-Handling)
DIM returns a FIXED BINARY (31,0) value specifying the current extent of the dimension
Y of X . The syntax for DIM is:
PL/I
23/01/2006
Page:- 38 / 119
DIM (X, Y)
X
Array expression. X must not have less than Y dimensions, and X must
not be an array of structures.
Y
Expression specifying a particular dimension of X. If necessary, Y is
converted to a FIXED BINARY (31,0) value. Y must be greater than or equal to 1
If the extent of an array dimension exceeds the allowable number for the implementation,
the DIM function returns an undefined value.
EMPTY (Storage Control)
EMPTY returns an area of zero extent. It can be used to free all allocations in an area.
The syntax for EMPTY is:
EMPTY ( )
Example
DECLARE A AREA,
I BASED (P);
J BASED (Q);
ALLOCATE I IN (A), J IN (A);
A = EMPTY( );
/*equivalent to: FREE I IN (A), J IN (A);*/
HBOUND (Array-Handling)
HBOUND returns a FIXED BINARY (31,0) value specifying the current upper bound of
dimension Y of X. The syntax for HBOUND is:
HBOUND (X, Y)
X Array expression. X must not have less than Y dimensions, and X must not be an
array of structures.
Y Expression specifying a particular dimension of X. If necessary Y is converted to a
FIXED BINARY (15,0) value. Y must be greater than or equal to 1
INDEX (String-Handling)
INDEX returns a FIXED BINARY (15,0) value indicating the starting position within X of a
sub-string identical to Y. The syntax for INDEX is:
INDEX (X, Y)
X
String-expression to be searched.
Y
String-expression to be searched for.
if Y does not occur in X, or if either X or Y have zero length, the value zero is returned
If occurs more than once in X, the starting position of the leftmost occurrence is returned.
LBOUND (Array-Handling )
LBOUND returns a FIXED BINARY (31,0) value specifying the current lower bound of
dimension Y of X. The syntax for LBOUND is:
LBOUND (X, Y)
PL/I
23/01/2006
Page:- 39 / 119
X
Array expression, X must not have less than Y dimensions, and X must
not be an array of structures.
Y
Expression specifying the particular dimension of X. If necessary Y is
converted to a FIXED BINARY (15,0) value . Y must be greater than or equal to 1
LENGTH (String-Handling)
LENGTH returns a FIXED BINARY (15,0) value specifying the current length of X. The
syntax for LENGTH is:
LENGTH (X)
X
String -expression. If X is binary it is converted to bit string; otherwise
any other conversion required is to character string.
LINENO ( Input / Output)
LINENO returns a FIXED BINARY (15,0) value specifying the current line number of X.
The syntax for LINENO is:
LINENO (X)
X
File-reference.
The file must be open and have the PRINT attribute.
NULL (Storage Control)
NULL returns the null pointer value . The null pointer value does not identify any
generation of a variable The null pointer value can be converted to OFFSET by
assignment of the built-in function value to an offset variable. The syntax for NULL is:
NULL ( )
OFFSET (Storage Control)
OFFSET returns an offset value derived from a pointer reference X and relative to an
area Y. If X is the null pointer value, the null offset value is returned. The syntax for
OFFSET is:
OFFSET (X, Y)
X
Pointer reference, which must identify a generation of a based variable
within the area Y, or be the null pointer value.
Y
Area reference.
ONCHAR (Condition-Handling)
ONCHAR returns a character string of length 1, containing the character that caused
the CONVERSION condition to be raised. It is in context in an ON-unit (or any of its
dynamic descendants) for the CONVERSION condition or for the ERROR or FINISH
condition raised as the implicit action for the CONVERSION condition. The syntax for
ONCHAR is:
ONCHAR ( )
ONCHAR ( Pseudo-variable )
The Pseudo-variable sets the current value of the ONCHAR built-in function. The
element value assigned to the pseudo-variable is converted to a character value of length
1. The new character is used when the conversion is re-attempted.
ONCHAR ( )
PL/I
23/01/2006
Page:- 40 / 119
ONCODE (Condition-Handling)
ONCODE returns FIXED BINARY (15,0) value that is the condition code. It is in context in
any ON-unit, or any dynamic descendant of an ON-unit.
ONCODE ( )
ONFILE (Condition-Handling)
ONFILE returns a character string whose value is the name of the file for which an
input/output or CONVERSION condition is raised.
ONFILE ( )
ONLOC (Condition-Handling)
ONLOC returns a character string whose value is the name of the entry-point used for the
current invocation of the procedure in which a condition was raised. It is in context in
any ON-unit, or in any of its dynamic descendants.
ONLOC ( )
ONSOURCE (Condition - Handling)
ONSOURCE returns a character string whose value is the contents of the field that was
being processed when the CONVERSION condition was raised. It is in context in an ONunit, or any of its dynamic descendants, for the CONVERSION condition or for the
ERROR or FINISH condition raised as the implicit action for the CONVERSION
CONDITION. The syntax for ONSOURCE is:
ONSOURCE ( )
ONSOURCE (Pseudo-variable)
The pseudo-variable sets the current value of the ONSOURCE built-in function. The
element value assigned to the pseudo-variable is converted to a character string and, if
necessary, is padded on the right with blanks or truncated to match the length of the field
that raised the CONVERSION condition. The new string is used when the conversion is
re-attempted.
ONSOURCE ( )
PLIRETC (Built-in Subroutine)
This built-in subroutine allows you to set a return code that can be examined by the
program or (sub) system that invoked this PL/I program or by another PL/I procedure via
the PLIRETV built-in function. The syntax for PLIRETC is:
PLIRETC (return-code)
Example: CALL PLIRETC(16); /* sets return code of 16 */
PLIRETV (Miscellaneous)
PLIRETV returns a FIXED BINARY (31,0) value that is the PL/I return code. The syntax
for PLIRETV is:
PL/I
23/01/2006
Page:- 41 / 119
PLIRETV ( )
The value of the PL/I return code is the most recent value specified by a CALL PLIRETC
statement in any task or the value returned by a COBOL or assembler routine (via
Register 15) whose entry point is declared with the option OPTIONS(RETCODE), or
zero.
POINTER (Storage Control)
POINTER returns a pointer value that identifies the generation specified by an offset
reference X, in an area specified by Y. If X is the null offset value, the null pointer value is
returned. The syntax for POINTER is:
POINTER (X, Y)
X
Y
Offset reference, which can be the null offset value; if it is not, it must
identify a generation of a based variable.
Area reference.
STORAGE ( X )
A variable of any data type, data organisation, alignment
STRING (String-Handling)
STRING returns an element bit or character string that is the concatenation of all the
elements of X. The syntax for STRING is:
STRING ( X )
X
SUBSTR (String-Handling)
SUBSTR returns a sub-string, specified by Y and Z, of X. The syntax for SUBSTR is:
SUBSTR ( X, Y, Z)
X
PL/I
23/01/2006
Z
Page:- 42 / 119
PL/I
23/01/2006
Page:- 43 / 119
PL/I
23/01/2006
SECTION 6
Logical Testing
Symbols
GE or >=
GT or >
NE or
=
LT or <
LE or <=
NL or
NG or
Page:- 44 / 119
CONTROL STATEMENTS
Operations
Greater than or equal to
Greater than
Not equal to
Equal to
Less than
Less than or equal to
Not less than
Not greater than
IF A=B THEN
IF A=C THEN
X=1;
ELSE
X=3;
back
PL/I
23/01/2006
Page:- 45 / 119
AND
OR
PL/I
23/01/2006
Page:- 46 / 119
.
.
END;
Example(s):
DO I=1 TO 100 BY 1;
*/
DO I=100 TO 1 BY -1;
DO I=1 BY 1;
*/
PL/I
23/01/2006
SECTION 7
Page:- 47 / 119
back
WHAT
system
ACTION ? action
no
book_name
ON units can be declared to handle specific conditions. Within an ON unit facilities are
provided to get more information on the condition that caused the ON unit to be activated.
Some of these are ONCODE( ), ONSOURCE( ), ONCHAR( ). A normal return from an
ON unit is said to take place when execution returns through END statement. An
abnormal termination is said to occur when we branch out of the ON unit through a
GOTO statement. You cannot code a RETURN statement in an ON unit.
ON condition
BEGIN;
.
.
END;
Example:
ON ENDFILE(SYSIN)
BEGIN
.
.
END;
Example:
ON ERROR SYSTEM; /* restores back system action for ERROR condition*/
ON ERROR
BEGIN;
ON ERROR SYSTEM;
PUT DATA;
/* output all variables and values
*/
PL/I
23/01/2006
Page:- 48 / 119
END;
Condition Handling
Condition Prefixes
You can specify whether or not some conditions are enabled or disabled. If a condition is
enabled, the raising of the condition executes an action. If a condition is disabled, the
raising of the conditions does not execute an action.
Enabling and disabling can be specified for the eligible conditions by a condition prefix.
Example:
(SIZE): L1 X=(I**N); /* enable SIZE condition for this statement only */
The conditions that are always enabled unless they are explicitly disabled by condition
prefixes are:
CONVERSION
FIXEDOVERFLOW
OVERFLOW
UNDERFLOW
ZERODIVIDE
Each of the preceding conditions can be disabled by condition prefix specifying the
condition name preceded by NO with intervening blanks as below.
NOCOVERSION
NOFIXEDOVERFLOW
NOOVERFLOW
NOUNDERFLOW
NOZERODIVIDE
The conditions that are always disabled unless they are enabled by a condition prefix are:
SIZE
SUBSCRIPTRANGE
STRINGRANGE
STRINGSIZE
All other conditions are always enabled and cannot be disabled . These conditions are:
AREA
ATTENTION
CONDITION
ENDFILE
ENDPAGE
ERROR
FINISH
KEY
NAME
RECORD
TRANSMIT
UNDEFINEDFILE
PENDING
PL/I
23/01/2006
Page:- 49 / 119
The ON statement establishes the action to be executed for any subsequent raising of
an enabled condition in the scope of the established action.
ON condition [SNAP] [SYSTEM] | on-unit
SNAP
Specifies that when the enabled condition is raised, a list is printed of all the blocks and
ON-units active in the current task at the time the condition is raised. The action of the
SNAP option precedes the action of the ON-unit.
SYSTEM
Specifies that the implicit action is taken. The implicit action is not the same for every
condition, although for most conditions a message is printed and the ERROR condition is
raised.
on-unit
Specifies the action to executed when the condition is raised and is enabled. The action
is defined by the statement or statements in the ON-unit itself. The On-unit is not
executed at the time the ON statement is executed; it is executed only when the specified
enabled condition is raised.
null on-Unit
The effect of a null statement on-unit is to execute normal return from the condition. Use
of the null on-unit is not the same as disabling, for two reasons:
A null ON-unit can be specified for any condition, but not all conditions can be
disabled.
Disabling a condition, if possible, can save time by avoiding any checking for this
condition. (If a null ON-unit is specified, the system must still check for the raising of
the condition).
The execution of an ON statement establishes an action specification for a condition.
Once this action is established, it remains established throughout that block and
throughout all dynamically descendent blocks (blocks entered via CALL or a function
reference) until it is overridden by the execution of another ON statement or a REVERT
statement or until termination of the block in which the ON statement is executed.
Example for REVERT:PROC1: PROCEDURE;
ON CONVERSION BEGIN;
END;
B: PROC2;
ON CONVERSION BEGIN;
END;
.
.
REVERT CONVERSION;
END PROC2;
END PROC1;
PL/I
23/01/2006
Page:- 50 / 119
Note: Dynamic descendency refers to the fact that ON-units are inherited from the
calling procedure in all circumstances. Dynamic descendency is not known until run time,
since a procedure can be called from anywhere where it is visible.
SIGNAL Statement
You can raise a condition by means of the SIGNAL statement. This statement can be
used in program testing to verify the action of an ON-unit and to determine whether the
correct action is associated with the condition. The established action is taken unless the
condition is disabled.
If the specified condition is disabled, the SIGNAL statement becomes equivalent to a null
statement. The syntax for the SIGNAL statement is:
SIGNAL Condition;
Classification of Conditions
The conditions are classified as follows:
Computation conditions-those associated with data handling, expression evaluation,
and computation. The conditions are:
CONVERSION
SIZE
FIXEDOVERFLOW
UNDERFLOW
OVERFLOW
ZERODIVIDE
If a computational conditional (except UNDERFLOW) is raised and the condition is
disabled, the program is in error;
Input/output conditions-those conditions associated with input and output.
They are:
ENDFILE
KEY
UNDEFINEDFILE
ENDPAGE
TRANSMIT
NAME
RECORD
PL/I
23/01/2006
Page:- 51 / 119
PL/I
23/01/2006
Page:- 52 / 119
Implicit Action: A message is printed and execution continues with the statement
following SIGNAL.
Status: CONDITION is always enabled.
Normal Return: Execution continues with the statement following the SIGNAL statement.
CONVERSION Condition
The CONVERSION computational condition is raised whenever an invalid conversion is
attempted on character data.
A character other than 0 or 1 exists in character data being converted to bit data.
A character value being converted to a numeric character field, or to coded arithmetic,
contains characters which are not the representation of an optionally signed arithmetic
constant, or an expression to represent a complex constant .
A value being converted to a character pictured item contains characters not allowed
by the picture specification.
The syntax for CONVERSION is;
ON CONVERSION .
Implicit Action: A message is printed and the ERROR condition is raised.
Status: CONVERSION is enabled throughout the program, except within the scope of a
condition prefix specifying NOCONVERSION.
Normal Return: If the ONSOURCE or ONCHAR PSEUDOVARIABLE is used, the
program retries the conversion on return from the on-unit. If the error is not corrected, the
program loops. If these PSEUDOVARIABLES are not used the ERROR condition is
raised.
Example
DCL X BIT(4);
X = '10A1';
/* all chars must be 1 or 0
*/
ENDFILE Condition
The ENDFILE input \ output condition can be raised during a GET or READ operation by
an attempt to read past the end of the file specified in the GET or READ statement. It
applies only to SEQUENTIAL INPUT, SEQUENTIAL UPDATE, and STREAM INPUT files.
The syntax for ENDFILE is:
ON ENDFILE (file-reference) ..
In record-oriented data transmission, ENDFILE is raised whenever an end of file is
encountered during the execution of a READ statement.
In stream-oriented data transmission, ENDFILE is raised during the execution of a GET
statement if an end of file is encountered either before any items in the GET statement
data list have been transmitted or between transmission of two of the data items. If an
PL/I
23/01/2006
Page:- 53 / 119
PL/I
23/01/2006
Page:- 54 / 119
ON ERROR
Implicit Action: If the condition is raised in the major task, the FINISH condition is raised
and the task terminates. If the condition is raised in any other task, the program is
terminated.
Status: ERROR is always enabled
Normal Return : The implicit action is taken.
FINISH Condition
The FINISH condition is raised during execution of a statement that would terminate the
major task of the PL/I program, that is, by a STOP statement in any task, or an EXIT
statement in the major task, or a RETURN or END statement in the MAIN procedure of
the program.
Note: The STOP statement immediately terminates the program including all concurrent
tasks. Before termination the FINISH condition is raised in the task in which the STOP
executes. On normal return from the on-unit all tasks in the program terminate.
The EXIT statement immediately terminates the program or the task that contains the
statement and all tasks attached by this task. If executed in a major task, EXIT raises the
FINISH condition in that task. On normal return from the on-unit, the task executing the
statement and all of its descendant tasks are terminated. Thus EXIT in a major task is
equivalent to a STOP statement.
The condition is also raised by SIGNAL FINISH, and as part of the implicit action for the
ERROR condition. The condition is raised in the task in which the statement is executed,
and any ON-unit specified for the condition is executed as part of that task. An abnormal
return from the ON-unit avoids program termination and allows the program to continue.
The syntax for FINISH is:
ON FINISH
Implicit Action: No action is taken and processing continues from the point where the
condition was raised.
Status: FINISH is always enabled.
Normal Return: Execution of the statement is resumed.
FIXEDOVERFLOW Condition
The FIXEDOVERFLOW computational condition is raised when the length of the result of
a fixed-point arithmetic operation exceeds the maximum length allowed by the
implementation.
The FIXEDOVERFLOW condition differs from the SIZE condition in that SIZE is raised
when a result exceeds the declared size of a variable, while FIXEDOVERFLOW is raised
when a result exceeds the maximum allowed by the computer. The syntax for
FIXEDOVERFLOW IS
ON FIXEDOVERFLOW ..
PL/I
23/01/2006
Page:- 55 / 119
FIXED DEC(15);
FIXED DEC(15);
FIXED DEC(15);
/* fixed point overflow is raised
*/
OVERFLOW
Occurs when the magnitude of the result of a floating point operation exceeds 10**75
A=55E71;
B=23E11;
C=A*B;
/* OVERFLOW condition is raised
*/
Result: The value of such an invalid floating point number is undefined
Implicit Action: A message is printed and ERROR is raised.
Status: Enabled throughout the program except within the scope of NOOVERFLOW
Normal Return: Control returns to the point after the instruction which caused this
condition.
SIZE Condition
The SIZE computational condition is raised only when high-order (that is, leftmost)
significant binary or decimal digits are lost in an attempted assignment to a variable or an
intermediate result or in an input/output operation. This loss can result from a conversion
involving different data types, different bases, different scales, or different precision. The
size condition is not enabled unless it appears in a condition prefix. The syntax for SIZE
is:
ON SIZE ..
The SIZE condition differs from the FIXEDOVERFLOW condition in that, whereas
FIXEDOVERFLOW is raised when the size of a calculated fixed-point value exceeds the
maximum allowed by the implementation, SIZE is raised when the size of the value being
assigned to a data item exceeds the declared (or default) size of the data item in your
program. SIZE can be raised on assignment of a value regardless of whether or not
FIXEDOVERFLOW was raised in the calculation of the value.
The declared size is not necessarily the actual precision with which the item is held
storage, however, the limit for SIZE is the declared or default size, not the actual size
storage. For example, a fixed binary item of precision (20) occupies a FULLWORD
storage, but SIZE is raised if a value whose size exceeds FIXED BINARY (20)
assigned to it.
in
in
in
is
PL/I
23/01/2006
Page:- 56 / 119
Because this checking involves a substantial overhead in both storage space and run
time, it usually is used only in program testing. You should remove it for production
programs.
If the SIZE condition is raised and it is disabled, the program is in error.
Result: The result of the assignment is undefined.
Implicit Action: A message is printed and the ERROR condition is raised.
Status: SIZE is disabled within the scope of a NOSIZE condition prefix and elsewhere
throughout the program, except within the scope of a condition prefix specifying SIZE.
Example
DCL
X
DCL
Y
X = Y;
FIXED DEC(4);
FIXED DEC(5) INIT(12345);
/* size condition is raised
*/
STRINGRANGE Condition
The STRINGRANGE program-checkout condition is raised whenever the values of the
arguments to a SUBSTR reference fail to comply with the rules described for the
SUBSTR built-in function. It is raised for each such reference. The syntax for
STRINGRANGE is:
ON STRINGRANGE.
Implicit Action: A message is printed and processing continues as described for normal
return.
Status: STRINGRANGE is disabled by default and within the scope of a
NOSTRINGRANGE condition prefix. It is enabled only within the scope of a
STRINGRANGE condition prefix.
Normal Return: Depends on various factors. (See PL/I language reference)
Example
DCL
NAME CHAR(20);
DCL
FIRST CHAR(16);
FIRST=SUBSTR(NAME,5,20); /* raises the string range condition
*/
PL/I
23/01/2006
Page:- 57 / 119
Result: After the condition action, the truncated string is assigned to its target string. The
right-hand characters, bits or graphics of the source string are truncated so that the target
string can accommodate the source string.
Implicit Action; A message is printed and processing continues.
Status: STRINGSIZE is disabled by default and within the scope of a NOSTRINGSIZE
condition prefix. It is enabled only within the range of a STRINGSIZE condition prefix.
Example
DCL
NAME CHAR(20);
DCL
FIRST CHAR(16);
FIRST=NAME;
/* raises the stringsize condition
*/
/* To enable stringsize (which is off by default) for an assignment statement code */
/* below
*/
(STRINGSIZE):
RECEIVE = SUBSTR(FIELD_1,5,20);
SUBCRIPTRANGE Condition
The SUBSCRIPTRANGE program-checkout condition is raised whenever a subscript is
evaluated and found to lie outside its specified bounds.
ON SUBCRIPTRANGE .
Result: When SUBCRIPTRANGE has been raised, the value of the invalid subscript is
undefined, and, hence, the reference is also undefined.
Implicit Action: A message is printed and the ERROR condition is raised.
Status: SUBSCRIPTRANGE is disabled by default and within the scope of a
NOSUBSCRIPTRANGE condition prefix. It is enabled only within the scope of a
SUBCRIPTRANGE condition prefix.
Normal Return: Normal return from a SUBSCRIPTRANGE ON-unit raises the ERROR
condition .
UNDEFINEDFILE Condition
The UNDEFINEDFILE input/output condition is raised whenever a nonzero return code is
received from the OPEN SVC. If the attempt is made by means of an OPEN statement
that specifies more than one file, the condition is raised after attempts to open all files
specified. The syntax for UNDEFINEDFILE is:
ON UNDEFINEDFILE (file-reference) ..
Implicit Action: A message is printed and the ERROR condition is raised.
Status: UNDEFINDFILE is always enabled.
Normal Return: Upon the normal completion of the final ON-unit, control is given to the
statement immediately following the statement that raised the condition.
ZERODIVIDE Condition
PL/I
23/01/2006
Page:- 58 / 119
*/
PL/I
23/01/2006
Page:- 59 / 119
PL/I
23/01/2006
SECTION 8
Page:- 60 / 119
ARRAYS
back
Arrays
DCL STUD_AVG (365) FIXED DEC(4,2);
DCL TABLE(0:11) FIXED DEC(5);
DCL GRAPH(-3:3) FIXED DEC(5,2);
DCL LIST(-2:6) FIXED BIN(15,0) INIT(1,2,4,21,2,3,4,80,90);
DCL TABLE(3,2) FIXED DEC(5);
ROW 1
ROW 2
ROW 3
COLUMN 1
(1,1)
(2,1)
(3,1)
COLUMN 2
(1,2)
(2,2)
(3,2)
/* first element)
PL/I
23/01/2006
Page:- 61 / 119
A(10)
B(10)
FIXED DEC(6);
FIXED DEC(6);
DCL
A=-A;
/* A is now -1,-2,-3,-4,-5,-6
*/
A=A*2;
/* A is now -2,-4,-6,-8,-10,-12
*/
DCL
A=A+B;
*/
*/
PL/I
23/01/2006
Page:- 62 / 119
PUT DATA(ARRAY);
END MYPROG;
/*
//
Example to demonstrate ARRAYS
//USERAA1 JOB MSGCLASS=A,NOTIFY=USERAA
//MYSTEP EXEC PROC=IEL1CLG,REGION.PLI=1M
//PLI.SYSIN DD *
MYPROG: PROCEDURE OPTIONS(MAIN);
DCL FIELD_ARRAY(10) FIXED DECIMAL(7,2) INIT(1,2,3,(7)9);
DCL SUM FIXED DECIMAL(7,2);
CALL ADD(FIELD_ARRAY);
PUT SKIP LIST(SUM);
ADD:PROCEDURE (A);
DCL A(*) FIXED DECIMAL(7,2);
DCL (HBOUND,LBOUND) BUILTIN;
DCL INDEX FIXED BINARY(15);
DCL UPPER FIXED BINARY(15);
DCL LOWER FIXED BINARY(15);
SUM=0;
LOWER=LBOUND(A,1);
UPPER=HBOUND(A,1);
DO INDEX=LOWER TO UPPER BY 1;
SUM=SUM+A(INDEX);
END;
END ADD;
END MYPROG;
/*
//
PL/I
23/01/2006
SECTION 9
Page:- 63 / 119
back
Pictures
To treat character strings as Arithmetic data
To treat arithmetic quantities as character strings
To edit data ( Zero suppression, Dollar float, +,-,DB,CR and comma decimal
insertion in numeric data) for output to printer
PICTURE 'picture specification characters'
Picture specification characters are 9,V,$,Z,.,,,DB,CR
DCL
PIC '999V99'
DCL
*/
Bytes
5
5
5
5
5
5
5
5
5
5
6
6
6
6
6
6
Equivalent
Value assigned Int. value
DECIMAL FIXED(5)
12345
12345^
DECIMAL FIXED(5)
12345
12345^
DECIMAL FIXED(5,2) 123.45
123^45
DECIMAL FIXED(5,2) 12345
345^00
DECIMAL FIXED(5,5) 12345
^00000
DECIMAL FIXED(5)
123
00123^
DECIMAL FIXED(5,2) 123
123^00
DECIMAL FIXED(2,1) 123.45
3^4
DECIMAL FIXED(5,2) -123.45
123^45
DECIMAL FIXED(5,2) -123.45
-123^45
DECIMAL FIXED(5,2) -123.45
-123^45
DECIMAL FIXED(5,2) +123.45
123^45
DECIMAL FIXED(5,2) +123.45
+123^45
DECIMAL FIXED(5,2) -123.45
123^45DECIMAL FIXED(5,2) +123.45
+123^45
DECIMAL FIXED(5,2) -123.45
123^45
Note
PIC
99999
99999V
999V99
999V99
V99999
99999
999V99
9V9
999V99
S999V99
-999V99
-999V99
S999V99
999V99S
+999V99
+999V99
Note:
1:Truncation of most significant digits occurred
2:Truncation of significant digits occurred
3:Truncation on both sides of decimal points occurred
4:Sign is lost as picture clause did not have provision for sign S
Arithmetic Operations on Decimal Picture Data
DCL
SUM PIC'9999';
DCL
A
PIC'999';
DCL
B
PIC'999';
SUM = A + B;
The compiler generates code to
a)Convert A to Fixed Decimal
b)Convert B to Fixed Decimal format
c) Add A and B
d)Convert the result to character form (PIC of SUM)
e)Place the converted result in SUM.
1
2
3
4
PL/I
23/01/2006
Page:- 64 / 119
Note that arithmetic operations can be performed on PIC fields with editing
characters. However it results in inefficient code.
Z picture character Is used for suppression of leading Zeroes.
PIC
ZZZZ9
ZZZZ9
ZZZZZ
ZZZV99
ZZZVZZ
ZZZVZZ
ZZZV99
Z9999
ZZZVZ9
ZZ9ZZ
Value assigned
Internal Representation
100
bb100
0
bbbb0
0
bbbbb
123
12300
1234
23400
.01
bbbb1
0
bbb00
0
b0000
/* invalid. If one Z appears to right of decimal, then all edit
chars must b Z */
/* Invalid. All Z'S must be to the left of the 9
*/
Decimal Point
This is an insertion character
DCL
A
PIC'999V.99' INIT(12.34);
PUT LIST(A); /* outputs 012.34
*/
DCL
A
PIC'999V99' INIT(12.34);
PUT LIST(A); /* outputs 01234
*/
The alignment is caused by the V edit character. Decimal point is only output as
an insertion character. See example below to illustrate this:
DCL
A
PUT LIST(A);
PIC'999.99V' INIT(12.34);
/* outputs
000.12 */
Comma
This is an insertion character
DCL
A
PIC'9,999V.99' INIT(3512.34);
PUT LIST(A); /* outputs 3,512.34
*/
DCL
A
PUT LIST(A);
PIC'Z,ZZZV.99' INIT(3512.34);
/* outputs 3,512.34
*/
DCL
A
PUT LIST(A);
PIC'Z,ZZZV.99' INIT(512.34);
/* outputs
512.34
*/
Blank
Is another insertion character. Use this to generate blanks on the right hand side
of the picture string. If you need blanks on the left, use the Z edit character
DCL
DCL
DCL
A
PIC'999V99BBB';
/* three blanks on the right*/
B
PIC'Z,ZZZV.99(7)B';
/* seven blanks on the right*/
EDITED_DATE PIC'99B99B99'; /*insert blanks between
YY,MM, and DD*/
Slash
Is another insertion character
DCL
RUN_DATE
CHAR(6);
DCL
EDITED_RUN_DATE PIC'99/99/99';
EDITED_RUN_DATE=RUN_DATE;
PL/I
23/01/2006
Page:- 65 / 119
Dollar Sign
In the Floating form (where there is more than one $ sign) leading zeroes
are suppressed and last leading Zero is replaced with the $ sign. In static
form (only one $ sign) it appears wherever defined in the picture string.
DCL
B
PUT LIST(B);
PIC'$999V.99' INIT(12.34);
/* outputs $012.34
*/
DCL
B
PUT LIST(B);
PIC'$$$$V.99' INIT(12.34);
/* outputs b$12.34
*/
/*error!*/
Asterisk
Usually used as a floating character for protection against forgery
DCL
A
PIC'*****9V.99'
INIT(104.75);
PUT LIST(A); /*
outputs
***104.75
*/
DCL
A
PIC'*****V.**'
INIT(104.75);
PUT LIST(A); /*
outputs
**104.75
*/
DCL
A
PIC'*****V.**'
INIT(.75);
PUT LIST(A); /*
outputs
*****.75 */
CR and DR
DB or CR can be used to indicate negative values. CR or DB
to the right of all digit positions in the PIC clause.
DCL
A
PIC'99V.99CR'
INIT(-12.75);
PUT LIST(A); /*
outputs
12.75CR
DCL
A
PIC'99V.99DB'
INIT(-12.75);
PUT LIST(A); /*
outputs
12.75DB
DCL
A
PIC'99V.99CR'
INIT(12.75);
PUT LIST(A); /*
outputs 12.75bb
PL/I
23/01/2006
Page:- 66 / 119
The first 4 positions are numeric and the last two are alphabetic.
Code the data item which is to receive the above data as PIC'9999AA'
DCL
A
PIC'9999AA';
DCL
B
CHAR(6);
A = B; /* if the format of the assigned data does not conform to the
PIC of the receiving field, the CONVERSION condition
is raised
*/
The P specification is allowed in input and output GET and PUT statements
GET FILE(SYSIN) EDIT(A,B,C,D) (COL(1),P'ZZZ9',P'99V99',P'AA999',P'(5)9');
Input value
bb15
1234
AB123
AB123
Format
P'ZZZ9'
P'99V99'
P'AA999'
P'(5)9'
DCL
ASSETS
FIXED DECIMAL(11,2);
ASSETS = 45326985.76;
PUT EDIT(ASSETS) (P'$$$$,$$$,$$$V.99');
/* outputs b$45,326,985.76
*/
DCL
ASSETS
FIXED DECIMAL(11,2);
ASSETS = 2500.00;
PUT EDIT(ASSETS) (P'$ZZZ,ZZZ,ZZZV.99');
/* outputs $bbbbbb2,500.00 */
Structures
DCL
EMP_ADDRESS,
2
NAME CHAR(20),
2
STREET
CHAR(20),
2
CITY
CHAR(20),
2
STATE
CHAR(20);
READ FILE(INFILE) INTO (EMP_ADDRESS);
Notes:
Level 1 is the Major structure level which does not have attributes. However
other storage qualifiers like BASED(P) are to be specified here.
Any number > 1 can represent lower levels
Attributes and INIT are defined only at elementary levels
There is no equivalent to the COBOL FILLER
STRING(EMP_ADDRESS) concatenates all the elements into one character
string.
STRING(structure variable) can also be used as a pseudo variable (on the
LHS of an assignment statement.
Initial Attribute
Elementary data items in the structure can have the INIT attribute
Example:
DCL
1
SALARY_RECORD,
2
NAME,
3
LAST
CHAR(10)
INIT('JOHNSON'),
2
EMP_NO
FIXED DEC(5) INIT(12345),
2
HOURS,
3
REGULAR FIXED DEC(4) INIT(100),
PL/I
23/01/2006
2
3
WAGES,
REG_PAY FIXED DEC(4)
Page:- 67 / 119
INIT(2000);
INVENTORY_ITEM,
PART_NO
CHAR(8),
QTY_IN_HAND
PIC'9999',
SALES_HISTORY(12) PIC'99999';
INVENTORY_ITEM.SALES_HISTORY(1) = 1234;
Arrays of structures
DCL
1
2
WEATHER(20),
TEMP,
3
HIGH FIXED DEC(4,1),
3
LOW FIXED DEC(4,1),
2
VELOCITY,
3
HIGH FIXED DEC(4,1),
3
LOW FIXED DEC(4,1),
2
RAINFALL,
3
HIGH FIXED DEC(4,1),
3
LOW FIXED DEC(4,1);
Refer to structure as WEATHER(n)
Refer to VELOCITY as VELOCITY(n)
Refer to TEMP.HIGH as TEMP.HIGH(n) /* called subscripted qualified name
*/
Assignments
We can assign one structure to another so long as they have the same minor
structuring and same number of elementary items. If arrays are contained within,
the bounds must be the same. We can assign Major to minor structures or vice
versa provided the relative structuring, as defined above, is the same.
Note that even if the attributes of the data items are different, conversion takes
place as per rules.
DCL 1 A
PL/I
23/01/2006
2
2
2
2
2
Page:- 68 / 119
B FIXED DEC(5),
C FIXED BIN(31),
D CHAR(20),
E FIXED BIN(15),
F FLOAT DEC(5);
DCL 1 AA
2 BB FIXED BIN(15),
2 CC FIXED DEC(5),
2 DD CHAR(10),
2 EE FIXED DEC(4),
2 FF FIXED DEC(6);
A = AA;
*/
PL/I
23/01/2006
SECTION 10
Page:- 69 / 119
STORAGE CONTROL
back
Storage Classes
Unless declared otherwise variables will have the storage class AUTOMATIC
MAIN: PROCEDURE OPTIONS(MAIN);
DCL 1 STRUCTURE,
2 A FIXED DEC (6,2),
2 B CHAR(20);
.
.
P1:
PROC;
DCL TABLE(100) CHAR(10);
.
END P1;
P2:
PROC;
DCL LIST(500) FIXED;
.
END P2;
END MAIN;
MAIN
P1
P2
STRUCTURE
TABLE
AUTOMATIC Storage
AUTOMATIC Storage
PL/I
23/01/2006
Page:- 70 / 119
P2:
PROC;
DCL LIST(500) FIXED STATIC;
.
END P2;
END MAIN;
MAIN
P1
P2
LIST
TABLE
STRUCTURE
static storage
static storage
automatic storage
PL/I
23/01/2006
Q->AREA = PQRS;
Page:- 71 / 119
Implementing Overlays
DCL A(100) FIXED BIN(15);
DCL B(50) FIXED BIN(15) DEFINED A;
/* traditional definition of overlay
*/
DCL A(100) FIXED BIN(15);
DCL B(50) FIXED BIN(15) BASED(P);
P = ADDR(A);
/* alternate method
*/
/* note that storage size of B must not
exceed that of A
*/
It is possible to have two variables based on one POINTER.
DCL PTR POINTER;
DCL 1 A,
2 B PIC'9999',
2 C FIXED DEC (13,2),
2 D CHAR(21);
DCL 1 J
2
2
2
BASED(PTR),
X FIXED BIN(15),
Y FLOAT DEC(6),
Z BIT(7);
DCL 1 W BASED(PTR),
2 K FIXED BIN(15),
2 L FIXED BIN(15);
PTR = ADDR(A);
When overlay defining a CHAR varying field special considerations exist
DCL FIELD CHAR(100) VARYING;
DCL 1 STRUCTURE BASED(P),
2 LENGTH FIXED BIN(15,0),
2 DATA CHAR(100);
P = ADDR(FIELD);
Note that LENGTH overlays the Half word length field preceding the varying
character field.
Using POINTERS in I/O (Locate mode I/O)
DCL P POINTER;
DCL TAPE FILE INPUT RECORD ENVIRONMENT(F BLKSIZE (240)
RECSIZE(24));
DCL 1 ISSUES BASED(P),
2 CODE
CHAR(1),
2 QTY
PIC'(4)9',
2 JOB_#
PIC'(4)9',
2 PART_#
PIC'(7)9',
2 DEPT
PIC'99',
2 UNUSED
CHAR(6);
DCL 1 RECEIPTS BASED(P),
2 CODE
CHAR(1),
2 QTY
PIC'(4)9',
2 UNUSED
CHAR(6),
PL/I
23/01/2006
Page:- 72 / 119
2 PART_#
PIC'(7)9',
2 SUPPLIER CHAR'(6)9';
READ FILE (TAPE) SET(P);
SELECT (ISSUES.CODE);
WHEN ('1') CALL PROCESS_ISSUES;
WHEN ('2') CALL PROCESS_RECEIPTS;
END;
/* using locate mode output */
DCL DATA BASED(P);
NEXT: LOCATE DATA FILE(OUTFILE);
DATA = ...;
GO TO NEXT;
Controlled Storage
DCL A(100) FIXED DEC(5) CONTROLLED; /* A does not exist here */
ALLOCATE A; /* Storage for A is allocated here
*/
GET LIST(A);
. . . use A here
FREE A;
/* Storage for A is de-allocated here */
Note that controlled variables after allocation exist until they are explicitly freed. They
are not affected by block boundaries. For arrays the size specification may be deferred
until ALLOCATE
DCL A(*) FIXED DEC(5) CONTROLLED;
ALLOCATE A(100);
DCL TABLE(*,*) BIN(1) CONTROLLED;
ALLOCATE TABLE(100,100);
Note that a repeat allocation before a free results in a new generation of the variable. The
previous generation is pushed into a stack meant for storing multiple generations of
controlled variables. A free will then cause the previous generation to be popped out of
the stack. Example follows:
DCL BUFF CHAR(100) CONTROLLED;
ALLOCATE BUFF;
BUFF = 'THIS IS FIRST GENERATION OF BUFF';
PUT LIST(BUFF);
/* this is first generation of buff */
ALLOCATE BUFF;
BUFF = 'THIS IS SECOND GENERATION OF BUFF';
PUT LIST(BUFF);
/* this is second generation of buff*/
FREE BUFF;
PUT LIST(BUFF);
/* this is first generation of buff */
FREE BUFF;
/* No BUFF in existence
*/
The ALLOCATION(X) built in function returns a FIXED BINARY(31) value indicating the
number of generations of X that exist.
DCL 1 PRODUCT BASED(Q),
2 DESCRIPTION CHAR(20),
PL/I
23/01/2006
2
CODE
Page:- 73 / 119
FIXED DEC(4);
DCL P POINTER;
ALLOCATE PRODUCT SET(P); /* note that Q is not changed by this */
P->PRODUCT.DESCRIPTION = 'SCREW';
/* PRODUCT is referenced by a locator qualifier */
FREE P->PRODUCT;
DCL NULL BUILTIN;
Storage Control
AUTOMATIC specifies that storage is allocated upon each entry to the block that
contains the storage declaration. The storage is released when the block is exited.
STATIC specifies that storage is allocated when the program is loaded. The storage is
not freed until program execution is completed.
CONTROLLED specifies that you maintain full control over the allocation and freeing
of storage with the ALLOCATE and FREE statements. Multiple allocations of the same
controlled variable in the same task, without intervening freeing, stack generations of
the variable.
BASED, like CONTROLLED, specifies that you maintain full control over storage
allocation and freeing. Multiple allocations are not stacked but are available at any
time. Each allocation can be identified by the value of a locator variable.
The default storage class is AUTOMATIC
Automatic and based variables can have internal scope only.
Static and controlled variables can have internal or external scope.
Static Storage and Attribute
You use static storage when the variable is local to the procedure and the value it
contains must be saved between successive invocations. Variables declared with the
STATIC attribute are allocated prior to running a program. They remain allocated until the
program terminates
Example
A: PROC OPTIONS(MAIN);
.
.
.
B: PROC;
DECLARE X STATIC INTERNAL;
.
.
.
END B;
END A;
Although the variable X is allocated throughout the program, it can be referenced only
within procedure B or any block contained in B.
PL/I
23/01/2006
Page:- 74 / 119
PL/I
23/01/2006
Page:- 75 / 119
.
.
.
END B;
END A;
The variable X can be referred to within the procedure B and that part of the procedure A
that follows execution of the CALL statement.
ALLOCATE Statement for Controlled Variables
The ALLOCATE statement allocates storage for controlled variables, independent of
procedure block boundaries. The bounds of controlled arrays, the lengths of controlled
strings, and the size of controlled areas, as well as their initial values, can also be
specified at the time the ALLOCATE statement is executed.
If a bound, length, or size is explicitly specified in an ALLOCATE statement, it
overrides that given in the DECLARE statement.
If a bound, length, or size is specified by an asterisk in an ALLOCATE statement, the
bound, length, or size is taken from the current generation.
DCL X (20) FIXED BIN CTL;
ALLOCATE X; /* the upper bound is taken as 20 from the DCL statement */
DCL X(20) CHAR(5) CONTROLLED;
ALLOCATE X(25) CHAR(6);
/* DCL upper bound and length are overridden
*/
Initial values are assigned to a variable upon allocation, if it has an INITIAL attribute in
either the ALLOCATE statement or DECLARE statement. If an INITIAL attribute
appears in both DECLARE and ALLOCATE statements, the INITIAL attribute in the
ALLOCATE statement is used.
FREE Statement for Controlled Variables
The FREE statement frees the storage allocated for controlled variables. The storage can
then be used for other allocations. For controlled variables, the next most recent
allocation is made available, and subsequent references in the task refer to that
allocation.
Multiple Generations of Controlled Variables
An ALLOCATE statement for a variable for which storage was previously allocated and
not freed pushes down or stacks storage for the variable. This stacking creates a new
generation of data for the variable. The new generation becomes the current generation;
the previous generation cannot be directly accessed until the current generation has
been freed. When storage for this variable is freed, using the FREE statement, storage is
popped up from the stack.
Example
DCL X(10,20) CHAR(5) CTL;
ALLOCATE X;
ALLOCATE X(10,10);
ALLOCATE X(*,*);
The first generation of X has bounds (10,20); the second and third generations have
bounds (10,10). The elements of each generation of X are all character strings of length
5.
PL/I
23/01/2006
Page:- 76 / 119
The asterisk notation can also be used in a DECLARE statement, but has a different
meaning.
Example
DCL Y CHAR(*) CTL,
N FIXED BIN;
N=20;
ALLOCATE Y CHAR(N);
ALLOCATE Y;
The length of the character string Y is taken from the previous generation unless it is
specified in an ALLOCATE statement, in which case Y is given the specified length. This
allows you to defer the specification of the string length until the actual allocation of
storage.
Built-in Functions for Controlled Variables
The ALLOCATION built-in function returns a binary value of precision (31,0) indicating
the number of generations that you can access in the current task for a given controlled
variable. Array-handling functions DIM, which determines the extent of a specified
dimension of an array, and LBOUND and HBOUND, which determine the lower and
upper bound, respectively, of a specified dimension of
a given array. The
CURRENTSTORAGE built-in function return the amount of storage required by a
particular variable. STORAGE returns allocated storage for a variable. For strings, the
built-in function LENGTH returns the current length of the string.
Based Storage and Attribute
A declaration of a based variable is the amount of storage required and its attributes. A
locator value identifies the location of the generation. A based variable can be used to
describe existing data, to obtain storage by means of the ALLOCATE statement, or to
access data in a buffer by means of the LOCATE statement or READ (with SET option)
statement.
DCL X FIXED BIN BASED(P);
This declares that references to X, except when the reference is explicitly qualified, use
the variable P to locate the storage for X.
Locator Data
There are two types of locator data: pointer and offset.
The value of a pointer variable is effectively an address of a location in storage
relative to the start of the virtual address space ( X00000000).
The value of an offset variable specifies a location relative to the start of an AREA
variable and remains valid when the area is assigned to a different part of storage.
When an offset variable is used in a reference, its value is implicitly converted to a
pointer value.
Explicit conversion of an offset to a pointer value is accomplished using the POINTER
built-in function.
DCL P POINTER, O OFFSET(B), B AREA;
P = POINTER(O,B);
The OFFSET built-in function complements the POINTER built-in function and returns
an offset value derived from a given pointer and area.
PL/I
23/01/2006
Page:- 77 / 119
Locator Qualification
Locator qualification is the association of one or more locator references with a based
reference to identify a particular generation of a based variable. This is called a locatorqualified reference. The composite symbol -> represents qualified by or points to.
Example:
P -> X
X is a based variable and P is a locator variable.
Reference to a based variable can also be implicitly qualified. The locator reference used
to determine the generation of a based variable that is implicitly qualified is the one
declared with the based variable.
Example
DCL X FIXED BIN BASED(P);
ALLOCATE X;
X= X + 1;
References to X can also be explicitly locator-qualified as follows:
P->X = P->X + 1;
Q = P;
Q->X = Q->X + 1;
Levels of Locator Qualification
DECLARE X BASED (P),
P POINTER BASED (Q),
Q OFFSET (A);
ALLOCATE P; /* have to do this first to make instance of P */
ALLOCATE X; /* Now we can make an instance of X */
The references: X, P->X, and Q->P->X all represent three levels of locator
qualification and are equivalent ways of referencing X.
POINTER Variable and Attribute
A pointer variable is declared contextually if it appears in the declaration of a based
variable, as a locator qualifier, in a BASED attribute, or in the SET option of an
ALLOCATE, LOCATE, or READ statement.
Setting Pointer Variables
NULL ( ) returns null pointer value
SYSNULL ( ) returns null pointer value. Use for static pointer and offset variables
POINTERADD(X,Y) . X is a pointer, Y is a FIXED BIN(31)
POINTERVALUE(X). X is FIXED BIN(31)
POINTER(X,Y). X is an OFFSET , Y is an AREA, returns a POINTER.
A READ statement with the SET option.
An ALLOCATE statement.
By assignment of the value of another locator variable, or a locator value returned by
a user-defined function.
Note: BINARYVALUE(P) is the reverse of POINTERVALUE(X). P is a pointer and the
function returns a FIXED BINARY(31) VALUE.
Built-In Functions for Based Variables
PL/I
23/01/2006
Page:- 78 / 119
The ADDR built-in function returns a pointer value that identifies the first byte of a
variable.
In general, the value of the NULL built-in function is used whenever a pointer (or offset)
variable does not identify a location in storage. There are many ways a pointer can
acquire the null value:
1. By assignment of the NULL built-in function
2. Assignment of the value returned by the ADDR built-in function for an unallocated
controlled variable.
3. It can also acquire the system null value by the assignment of the SYSNULL built-in
function.
ALLOCATE Statement for Based Variables
The ALLOCATE statement allocates storage for based variables and sets a locator
variable that can be used to identify the location, independent of procedure block
boundaries.
ALLOCATE (based-variable [, based-variable,])
[IN ( area-reference)]
[SET (locator-reference)]
Storage is allocated in an area when the IN option is specified or the SET option specifies
an offset variable.
FREE Statement for based variables
The FREE statement frees the storage allocated for based and controlled variables.
FREE locator-qualifier->based-variable [IN (area-reference)]
Area Data and Attribute
Area Variables describe areas of storage that are reserved for the allocation of based
variables. This reserved storage can be allocated to, and freed from, based variables by
the ALLOCATE and FREE statements. Area variables can have any storage class and
must be aligned.
When a based variable is allocated and an area is not specified, the storage is obtained
from wherever it is available.
You might want to identify the locations of based variables within an area variable relative
to the start of the area variable. Offset variables are provided for this purpose.
A variable is given the AREA attribute contextually by its appearance in the OFFSET
attribute or an IN option, or by explicit declaration. The syntax for the AREA attribute is:
AREA [ ( * | expression ) ]
If expression, or *, is not specified, the default is 1000
Use * for AREA with controlled attribute to defer the area size until allocation.
Examples of AREA declarations are:
PL/I
23/01/2006
Page:- 79 / 119
BASED(O),
BASED(P),
AREA,
OFFSET(A);
ALLOCATE X;
ALLOCATE Y IN(A);
The storage class of area A and offset O is AUTOMATIC by default. The first ALLOCATE
statement is equivalent to:
ALLOCATE X IN(A) SET(O);
The second ALLOCATE statement is equivalent to;
ALLOCATE Y IN(A) SET(P);
Area Assignment
The value of an area reference can be assigned to one or more area variables by an
assignment statement. Area-to-area assignment has the effect of freeing all allocations in
the target area and then assigning the extent of the source area to the target area, so
that all offsets for the source area are valid for the target area.
Example
DCL X BASED (O(1)),
O(2) OFFSET (A),
(A,B) AREA;
ALLOC X IN (A);
X = 1;
ALLOC X IN (A) SET (O(2));
O(2)->X = 2;
B = A;
Using the POINTER built-in function, the references POINTER (O(2),B)->X and
PL/I
23/01/2006
Page:- 80 / 119
is equivalent to ('AA')
is equivalent to ('A','A')
is equivalent to ('A','A')
Note that first index is string repetition factor ( (3)'B' is 'BBB'). The outer index is the
iteration factor ( (2)(3)'B' is 'BBB','BBB').
Example of demonstration of POINTERS
//USERAA1 JOB MSGCLASS=A,NOTIFY=USERAA
//MYSTEP EXEC PROC=IEL1CLG,REGION.PLI=1M
//PLI.SYSIN DD *
%PROCESS ATTRIBUTES(FULL),NOT('~');
MYPROG: PROCEDURE OPTIONS(MAIN);
DCL 1 LINK BASED(P),
2 DATA CHAR(80),
2 NEXT POINTER;
DCL (HEAD,THIS) POINTER;
DCL COUNT FIXED DEC(3);
DCL BUFFER CHAR(80);
DCL NULL BUILTIN;
ALLOCATE LINK SET(HEAD);
COUNT=1;
PUT STRING(BUFFER) EDIT(COUNT,'ABCDEFGHIJKLMNOPQRS')(F(3),A);
HEAD->DATA=BUFFER;
THIS=HEAD;
DO I=1 TO 100 BY 1;
ALLOCATE LINK SET(THIS->NEXT);
COUNT=COUNT+1;
PUT STRING(BUFFER) EDIT(COUNT,'ABCDEFGHIJKLMNOPQRS')(F(3),A);
THIS=THIS->NEXT;
THIS->DATA=BUFFER;
END;
THIS->NEXT=NULL;
THIS=HEAD;
DO WHILE(THIS ~= NULL);
PUT SKIP EDIT(THIS->DATA)(A);
THIS=THIS->NEXT;
END;
PL/I
23/01/2006
Page:- 81 / 119
END MYPROG;
/*
//
Example of demonstration of CONTROLLED attribute
//USERAA1 JOB MSGCLASS=A,NOTIFY=USERAA
//MYSTEP EXEC PROC=IEL1CLG,REGION.PLI=1M
//PLI.SYSIN DD *
%PROCESS ATTRIBUTES(FULL),NOT('~');
MYPROG: PROCEDURE OPTIONS(MAIN);
DCL 1 LINK CONTROLLED,
2 DATA CHAR(80);
DCL COUNT FIXED BINARY(15);
DCL BUFFER CHAR(80);
DCL NULL BUILTIN;
DO I=1 TO 100 BY 1;
ALLOCATE LINK;
PUT STRING(BUFFER) EDIT(I,'ABCDEFGHIJKLMNOPQRS')(F(3),A);
LINK.DATA=BUFFER;
COUNT=COUNT+1;
END;
COUNT=ALLOCATION(LINK);
DO I=1 TO COUNT BY 1;
PUT SKIP EDIT(LINK.DATA)(A);
FREE LINK;
END;
END MYPROG;
/*
//
PL/I
23/01/2006
SECTION 11
Page:- 82 / 119
back
TYPES OF TRANSMISSION
Stream Data formatting facilities, less efficient, conversion to character form before
output or input. Stream implies that the data of the file is a continuos stream of
data items in character form assigned to variables or from expressions to the
stream
Record No data formatting facilities, more efficient, image of data in program buffer
written to media. Record mode implies that the file consists of physically separate
records each of which consist of one or more data items in any form
Record VS Stream I/O
STREAM I/O
(LIST / EDIT / DATA)
GET characters
Convert to
Coded arithmetic
form
RECORD
READ
Process coded
arithmetic form
Process Data in
Record form
Any
conversions
have to be
done by the
programmer
Convert coded
arithmetic form
to character form
Write
Put characters
PL/I
23/01/2006
Page:- 83 / 119
In record I/O data in any form (coded or character) may be stored. In stream form the
data has to be in character form only.
Record mode I/O may be used with any type of data set(QSAM, VSAM KSDS, VSAM
RRDS, VSAM ESDS). Stream I/O can be used only on sequential data sets.
TYPES OF DATA SETS SUPPORTED BY PL/I
Type of data set
PL/I organization
Sequential
CONSECUTIVE
Indexed sequential
INDEXED
Direct
REGIONAL
KSDS,ESDS,RRDS
VSAM
FILE INPUT / OUTPUT
Action
Define the File
Open the File
Process the File
Close the File
PL/I statement
DECLARE filename FILE
OPEN FILE(filename);
READ/WRITE/REWRITE/DELETE/LOCATE for access by
record
GET/PUT for stream access
CLOSE FILE(filename)
A file used within a PL/I program has a PL/I file name. If you have the following file
declaration in your program:
DCL STOCK FILE STREAM INPUT;
Create a DD statement with a data definition name (DDNAME)
//STOCK
DD
DSN=PARTS.INSTOCK, . . .
Ensure that the DDNAME of the DD statement that defines the data set is the same as
either the declared PL/I file name. If the file name is longer than 7 characters, the default
DDNAME is composed of a compiler generated truncated name (first 4 and last 3
characters).
FILE ATTRIBUTE OF A DATA ITEM
Main attributes are
GROUP
ALTERNATIVES
Usage
STREAM | RECORD
Function
INPUT | OUTPUT | UPDATE
Access
SEQUENTIAL | DIRECT
Scope
EXTERNAL | INTERNAL
Notes on Attributes
RECORD
STREAM
DEFAULT
STREAM
INPUT
SEQUENTIAL
EXTERNAL
INPUT
OUTPUT
UPDATE
Input only
Output only
Valid only for RECORD mode. Transmission in either
direction
SEQUENTIAL
PL/I
23/01/2006
DIRECT
Page:- 84 / 119
physical sequence
Valid in RECORD MODE only. Records accessed in any
order by KEY. Implies KEYED attribute.
ENVIRONMENT
VSAM | CONSECUTIVE
F | FB | V | VB, BLKSIZE(N), RECSIZE (N)
KEYED
FILE(file-reference).
FILE(file-reference).
/*both*/
/*use only one*/
/*UPDATE for record only*/
/*record only */
/*record only */
/*stream only*/
/*both */
/*stream output only*/
/*stream only with PRINT*/
/*Stream I/O*/
/*Stream I/O*/
READ FILE(file-reference)..
WRITE FILE(file-reference)
REWRITE FILE(file-reference).
DELETE FILE(file-reference)
/*Record I/O*/
/*Record I/O*/
/*Record I/O*/
/*Record I/O*/
CLOSE FILE(file-reference)
PL/I
23/01/2006
Page:- 85 / 119
SECTION 12
F | FB | FS | FBS | V |VB | U
RECSIZE (record-length)
BLKSIZE (block-size)
/*
DD
Use the GET and PUT verbs for the I/O within your program
Salient points of Stream I/O
The I/O is in a continuos stream and record boundaries are not reflected to the user
program, although they exist at the Physical level.
The I/O is in character mode. For example coded arithmetic data is converted to
character (display) mode both ways(From arithmetic mode to character mode on
output and from character mode to coded mode on input).
On input the data items must be in character mode and either BLANK or COMMA
must be used as a separator (LIST mode).
In PUT LIST for printer output the data is output in predetermined tab positions
spaced at 21 positions between tabs.
List Directed data Transmission
PL/I
23/01/2006
Page:- 86 / 119
/* SPRINTF of C */
Data Specifications
LIST (data-item, data-item,.)
DATA (data-item, data-item,.)
EDIT (data-item, data-item,) (format-item, format-item,)
Notes
COPY
SKIP
PAGE
LINE
Example
DCL INVEN FILE INPUT STREAM ENV(options);
ENV options are BLKSIZE, RECSIZE etc. Note that these are required for new files
and may be specified in the program or in the JCL. For existing files these can be
omitted as the system will fill up the DCB from the catalogue information for the
existing dataset.
Note that Filename is the DD name in the run JCL for this program.
INPUT or OUTPUT attribute can be deferred and specified with the OPEN statement
also. This can be useful when the same file is opened for write / closed / opened for
read.
Default is INPUT unless the file has the PRINT attribute in which case it defaults to
OUTPUT.
Example
DCL INVEN FILE STREAM INPUT ENV(F BLKSIZE(80));
Print Attribute
Use this for printer output.
This will enable options on PUT like PAGE, SKIP( ), LINE( ) etc.
PL/I
23/01/2006
Page:- 87 / 119
This attribute can be used only when STREAM and OUTPUT are other attributes.
This attribute causes first byte of each record of the data set to be reserved for
carriage control character
Note record size is size of print line plus one position for RECFM F. For RECFM V it is
print line size + 9.
DCL PRINTR FILE OUTPUT STREAM PRINT ENV(F BLKSIZE(133));
DCL PRINTBUF CHAR(132);
PUT FILE(PRINTR) LIST(PRINTBUF);
DCL I FIXED BINARY(15);
I=LINENO(PRINTR) /*returns value of the LINENO counter maintained by PL/I */
Stream Files are automatically opened with first GET or PUT.
PAGESIZE and LINESIZE for PRINT files should be specified only in OPEN statement.
OPEN FILE(PRINTR) PAGESIZE(50) LINESIZE(120);
Default output is to SYSPRINT with default line size of 120.Override this by
OPEN FILE(SYSPRINT) LINESIZE(133);
Default input is from SYSIN with a RECSIZE of 80
Note that FILE attributes can be specified in the JCL, DCL and OPEN statements. They
are merged at OPEN time.
The CLOSE FILE(DATAIN); statement is used to close the file. Program end also
automatically closes all files
Edit Directed I/O
Edit Directed I/O overcomes some of the limitations of LIST directed I/O like need for
spaces or commas to separate data (wastage of space) or printing at predetermined
tab positions for printer output.
Edit I/O is part of Stream I/O and therefore deals only in character data.
Consider the following Data which is intended to be read with LIST directed I/O
GET LIST(EMPNUM,EMPNAME);
EMPNUM EMPNAM
12345678,SRINIVASKAMATH
Note the comma separating the two data items
For EDIT directed I/O
GET FILE(filename) EDIT(datalist) (formatlist);
GET EDIT(EMPNUM,EMPNAME) (COLUMN(1),F(8),A(15));
EMPNUM EMPNAM
12345678SRINIVASKAMATH
Note the absence of blank or comma to separate the two data items
Format identifiers are
A(n)
n Alphameric characters
PL/I
23/01/2006
F(m,n)
X(n)
COLUMN(n)
Page:- 88 / 119
Note that in the event of insufficient format identifiers the set of identifiers provided are
used again starting with the first format identifier
GET EDIT(A,B,C) (F(4),F(5));
A
->
F(4)
B
->
F(5)
C
->
F(4)
Excess format identifiers are ignored.
The I/O continues across record boundaries until all the identifiers have been
read or written
A
B
1
70 71 80 1
30
DCL
A
CHAR(70);
DCL
B
CHAR(40);
GET EDIT (A,B) (A(70),A(40));
A
1
Record boundary
B
70
40
DCL
A
CHAR(70);
DCL
B
CHAR(40);
Record boundary
GET EDIT (A,B) (COLUMN(1),A(70),COLUMN(1),A(40));
Alternately,
DCL
A
CHAR(70);
DCL
B
CHAR(40);
GET EDIT (A,B) (A(70),X(10),A(40));
Example:
To read first forty positions of each record
DCL FIELD_1 CHAR(40);
DO I=1 to 10;
GET EDIT(FIELD_1) (COLUMN(1),A(40));
END;
Data items may be Data aggregates
Example:
DCL
TABLE(100)
FLOAT DEC(6);
GET EDIT(TABLE) (COLUMN(1),F(6,2));
/* note that 100 records will be read to satisfy this read
I/O can be to a string in memory rather than to a FILE
PUT STRING (FIELD_1) EDIT (A,B,C) (A(20),A(10),F(3));
GET STRING (FIELD_1) EDIT (A,B,C) (A(20),A(10),F(3));
*/
PL/I
23/01/2006
Page:- 89 / 119
This option can be used to effect CHAR to coded arithmetic or vice versa conversion.
Writing Headings
PUT EDIT('THIS IS A HEADING STARTING IN COLUMN 32')
(PAGE,COLUMN(32),A); /*the compiler calculates width of A*/
PUT EDIT(MM,'/',DD,'/',YY) (A,A,A,A,A);
Format Identifiers
A(w)
Character field of width w
A
B(w)
F(w)
F(w,d)
X(w)
COLUMN(n)
LINE(n)
Skip to line n
PAGE
SKIP
PL/I
23/01/2006
Page:- 90 / 119
GET DATA(A,B,C,D);
GET DATA(B,D,A,C);
*/
*/
The COUNT(filename) returns the data items input during last GET
Data Directed Output
DCL
A
FIXED DEC(5) INIT(0);
DCL
B
FIXED DEC(5) INIT(0);
DCL
C
FIXED DEC(5) INIT(175);
PUT DATA (A,B,C);
Outputs ->
A=0
B=0
C=175;
Note that A is in TAB position 1
B is in TAB position 25
C is in TAB position 49
On Units and relevant built in functions
UNDEFINEDFILE(file reference) condition is raised when the file referenced fails to open.
You can use
ENDFILE(file reference) is raised on sequential input, when a read is issued after the end
of file is reached.
The TRANSMIT(file reference) is raised whenever a block / record I/O failed. Usually due
to media problems, typically tape I/O.
ENDPAGE(file reference) is raised on end of a page
NAME(file reference) is raised when a GET DATA finds superfluous data in the input
stream. Use the DATAFIELD( ) built in function to find the field in error.
KEY(file reference) is raised for keyed files (VSAM KSDS for example) when a keywrror
occurs.
LINENO(file reference) built in function to find out the line number you are currently at on
a page in a print file.
COUNT(file reference) returns the number of items input or output on the last GET or
PUT operation.
ONFILE( ) returns the file referenced when a conversion condition is entered due to a
conversion condition on a GET or PUT operation.
ONKEY( ) returns the key in error.
PL/I
23/01/2006
Page:- 91 / 119
PL/I
23/01/2006
Page:- 92 / 119
PL/I
23/01/2006
SECTION 13
Page:- 93 / 119
RECORD I/O
back
FROM
SET
Specifies a pointer variable that is set to point to the location in the buffer
into which the record has been moved during the READ operation
PL/I
23/01/2006
Page:- 94 / 119
KEY
Specifies character key that identifies a record for a VSAM KSDS data
set. Can appear only if the FILE has DIRECT attribute or VSAM and
KEYED attribute. Can be used in a READ statement for INPUT or
UPDATE file or in a REWRITE for a DIRECT UPDATE file.
KEYFROM
Specifies a character key that identifies the record in the data set. Can
be used in a WRITE statement for SEQUENTIAL output, or WRITE
statement for DIRECT OUTPUT to a VSAM data set.
KEYTO
Write Sequences
Sequential or Direct keyed Write
WRITE FILE(LOANS) FROM (LOANREC) KEYFROM(LOANNO);
Sequential non-keyed Write
WRITE FILE(LOANS) FROM (LOANREC);
Locate mode sequential write
DCL BUFFER CHAR(80) BASED(P);
LOCATE BUFFER FILE(OUTFILE);
Locate mode keyed write
DCL BUFFER CHAR(80) BASED(P);
DCL KEYFLD CHAR(5);
LOCATE BUFFER FILE(OUTFILE) KEYFROM(KEYFLD);
Read Sequences
Sequential Read
DCL BUFFER CHAR(80);
READ FILE(INFILE) INTO(BUFFER);
Sequential Read Locate mode
DCL BUFFER CHAR(80) BASED(P);
READ FILE(INFILE) SET(P);
Direct Read
DCL BUFFER CHAR(80);
DCL KEYFLD CHAR(5);
READ FILE(INFILE) INTO(BUFFER) KEY(KEYFLD);
Direct Read Locate Mode
DCL BUFFER CHAR(80) BASED(P);
DCL KEYFLD CHAR(5);
READ FILE(INFILE) SET(P) KEY(KEYFLD);
Update Sequences
PL/I
23/01/2006
Page:- 95 / 119
PL/I
23/01/2006
Page:- 96 / 119
SECTION 14
DD
DSNAME=VSAMDS, DISP=SHR
PL/I
23/01/2006
Page:- 97 / 119
represent an unsigned integer. If not 8 characters truncate or pad with blanks (interpreted
as Zeros) on the left.
You define a direct VSAM data set by using a file declaration with the following attributes:
DCL filename FILE RECORD {INPUT | OUTPUT | UPDATE}
DIRECT KEYED
ENVIRONMENT (VSAM);
Loading a KSDS
Open the file for KEYED SEQUENTIAL OUTPUT and present the records in
ascending key order, use the KEYFROM option.
If the KSDS already contains some records, and you open the associated file with the
SEQUENTIAL and OUTPUT attributes, you can only add records at the end of the
data set.
KEYED SEQUENTIAL OUTPUT file is used with a WRITE with FROM and
KEYFROM keywords in the statement. The data must be presented in ascending key
order.
EXAMPLE OF DEFINING A KSDS USING IDCAMS
//USERIDB JOB CLASS=C,
//
MSGCLASS=X,MSGLEVEL=(1,1),NOTIFY=USERID
//STEP1 EXEC PGM=IDCAMS
//SYSPRINT DD SYSOUT=*
//SYSIN DD *
DELETE USERID.KSDS CLUSTER
DEFINE CLUSTER (NAME(USERID.KSDS) INDEXED KEYS(5,0) RECORDSIZE(80,80) TRACKS(2,2)) DATA(CONTROLINTERVALSIZE(1024))
//
Example of loading a VSAM KSDS sequentially
//USERID1 JOB NOTIFY=&SYSUID,CLASS=A,MSGLEVEL=(1,1)
//PLIPROC JCLLIB ORDER=(USERID.PLI.PROCLIB)
//DOPROC EXEC PROC=IBMZCB
//PLI.SYSIN DD DSN=USERID.PLI.SOURCE(VSAMLS),DISP=SHR
//BIND.SYSLMOD DD DSN=USERID.PLI.LOADLIB(VSAMLS),DISP=SHR
//*
//RUN EXEC PGM=VSAMLS
//STEPLIB DD DSN=USERID.PLI.LOADLIB,DISP=SHR
//VSAM
DD DSN=USERID.KSDS,DISP=SHR
//IN
DD DSN=USERID.PLI.LOAD.DATA,DISP=SHR
//SYSPRINT DD SYSOUT=*
//
Input data presented via USERID.PLI.LOAD.DATA (PS,FB,80/800)
0000100010SDSDSDSDSSDSDSD
0000200011SDSDSDSDSSDSDSD
0000400012SDSDSDSDSSDSDSD
0000600010SDSDSDSDSSDSDSD
0001800011SDSDSDSDSSDSDSD
0002000012SDSDSDSDSSDSDSD
0003200010SDSDSDSDSSDSDSD
0004400014SDSDSDSDSSDSDSD
0005600011SDSDSDSDSSDSDSD
PL/I
23/01/2006
Page:- 98 / 119
0006800010SDSDSDSDSSDSDSD
VSAMLS
*PROCESS NOT('~');
VSAMLS: PROC OPTIONS(MAIN);
DCL (ONFILE,ONCODE) BUILTIN;
DCL VSAM FILE RECORD SEQUENTIAL OUTPUT KEYED ENV(VSAM);
DCL IN FILE STREAM INPUT;
DCL BUFFER CHAR(80);
DCL KEYFLD CHAR(5) DEF (BUFFER);
DCL EOF BIT(1) INIT('0'B);
ON UNDEFINEDFILE(IN) BEGIN;
PUT SKIP LIST('OPEN ERROR ',ONFILE);
STOP;
END;
ON UNDEFINEDFILE(VSAM) BEGIN;
PUT SKIP LIST('OPEN ERROR ',ONFILE);
STOP;
END;
ON KEY(VSAM) BEGIN;
PUT SKIP EDIT('KEY ERROR ON FILE ',ONFILE,
' ONCODE ',ONCODE)(A);
END;
ON ENDFILE(IN) BEGIN;
EOF='1'B;
END;
OPEN FILE(IN);OPEN FILE(VSAM);
GET FILE(IN) EDIT(BUFFER)(A(80));
DO WHILE(~EOF);
WRITE FILE(VSAM) FROM(BUFFER) KEYFROM(KEYFLD);
GET FILE(IN) EDIT(BUFFER)(A(80));
END;
END VSAMLS;
VSAMRS
*PROCESS NOT('~');
VSAMRS: PROC OPTIONS(MAIN);
DCL (ONFILE,ONCODE) BUILTIN;
DCL VSAM FILE RECORD SEQUENTIAL INPUT KEYED ENV(VSAM);
DCL BUFFER CHAR(80);
DCL KEYFLD CHAR(5);
DCL EOF BIT(1) INIT('0'B);
ON UNDEFINEDFILE(VSAM) BEGIN;
PUT SKIP LIST('OPEN ERROR ',ONFILE);
STOP;
END;
ON ENDFILE(VSAM) BEGIN;
EOF='1'B;
END;
OPEN FILE(VSAM);
READ FILE(VSAM) INTO(BUFFER) KEYTO(KEYFLD);
DO WHILE(~EOF);
PUT SKIP EDIT(BUFFER,' ',KEYFLD)(A);
READ FILE(VSAM) INTO(BUFFER) KEYTO(KEYFLD);
END;
END VSAMRS;
PL/I
23/01/2006
Page:- 99 / 119
VSAPUPD
This program reads update information from userid.PLI.UPDT.DATA(PS,FB,81/810).
The format of the update data is
<op char(1)><key char(5)><data char(75) optional depending on code>
Code can be A for add a new record, C for change an existing record, D for deleting an
existing record and P for printing an existing record. If you code A or C the third field of
75 characters is required.
Here is sample update data
D10001
A1000110010SDSDSDSDSSDS
P10001
D10001
P10001
A1000110010SDSDSDSDSSDS
P10001
C1000110010SDSDSDSDSSDS*****updated*********
P10001
Here is the JCL
//USERID1 JOB NOTIFY=&SYSUID,CLASS=A,MSGLEVEL=(1,1)
//PLIPROC JCLLIB ORDER=(USERID.PLI.PROCLIB)
//DOPROC EXEC PROC=IBMZCB
//PLI.SYSIN DD DSN=USERID.PLI.SOURCE(VSAMUPD),DISP=SHR
//BIND.SYSLMOD DD DSN=USERID.PLI.LOADLIB(VSAMUPD),DISP=SHR
//*
//RUN EXEC PGM=VSAMUPD
//STEPLIB DD DSN=USERID.PLI.LOADLIB,DISP=SHR
//VSAM
DD DSN=USERID.KSDS,DISP=SHR
//UPDT
DD DSN=USERID.PLI.UPDT.DATA,DISP=SHR
//SYSPRINT DD SYSOUT=*
//
*PROCESS NOT('~');
VSAMUPD: PROC OPTIONS(MAIN);
DCL (ONFILE,ONCODE,ONKEY) BUILTIN;
DCL VSAM FILE RECORD DIRECT UPDATE KEYED ENV(VSAM);
DCL UPDT FILE RECORD SEQUENTIAL INPUT ENV(CONSECUTIVE);
/*
IO BUFFER DEFS
*/
DCL BUFFER CHAR(81);
DCL OP CHAR(1) DEF(BUFFER);
DCL KEYFLD CHAR(5) DEF(BUFFER) POS(2);
DCL DATA CHAR(80) DEF(BUFFER) POS(2);
/*
IO BUFFER DEFS END
*/
/*
ON UNITS DEFINITIONS START
*/
DCL EOF BIT(1) INIT('0'B);
DCL GOODKEY BIT(1);
ON ENDFILE(UPDT) EOF='1'B;
ON UNDEFINEDFILE(VSAM) BEGIN;
PUT SKIP LIST('OPEN ERROR ',ONFILE);
PL/I
23/01/2006
STOP;
END;
ON UNDEFINEDFILE(UPDT) BEGIN;
PUT SKIP LIST('OPEN ERROR ',ONFILE);
STOP;
END;
ON KEY(VSAM) BEGIN;
PUT SKIP EDIT
('KEY CONDITION ',ONFILE,ONKEY)(X(3),A,X(1),A,X(1),A);
GOODKEY='0'B;
END;
/*
ON UNIT DEFINITIONS END
*/
OPEN FILE(VSAM);OPEN FILE(UPDT);
READ FILE(UPDT) INTO(BUFFER); /* PRIMING READ */
DO WHILE(~EOF);
GOODKEY='1'B;
PUT SKIP EDIT('>>>',BUFFER)(A);
SELECT (OP);
WHEN ('A') WRITE FILE(VSAM) FROM(DATA) KEYFROM(KEYFLD);
WHEN ('D') DELETE FILE(VSAM) KEY(KEYFLD);
WHEN ('C') DO;
READ FILE(VSAM) INTO(OLDDATA) KEY(KEYFLD);
IF GOODKEY
THEN REWRITE FILE(VSAM) FROM(DATA) KEY(KEYFLD);
END;
WHEN ('P') DO;
READ FILE(VSAM) INTO(DATA) KEY(KEYFLD);
IF GOODKEY THEN PUT SKIP EDIT(DATA)(X(3),A);
END;
OTHERWISE PUT SKIP LIST('BAD OPERATION CODE');
END;
READ FILE(UPDT) INTO(BUFFER);
END;
END VSAMUPD;
Creating an Alternate Index
//USERIDB JOB CLASS=C,
//
MSGCLASS=X,MSGLEVEL=(1,1),NOTIFY=USERID
//STEP1 EXEC PGM=IDCAMS,REGION=512K
//SYSPRINT DD SYSOUT=*
//SYSIN
DD *
DELETE USERID.KSDS.ALTINDX ALTERNATEINDEX
DEFINE ALTERNATEINDEX (NAME(USERID.KSDS.ALTINDX)NONUNIQUEKEY KEYS(5 5) RECORDSIZE(80 512)TRACKS(1 1)RELATE(USERID.KSDS))
/*
//
Building the Index
//KAM0001B JOB (SCB-SCB-KAM0001-XXX-999),CLASS=C,
PL/I
23/01/2006
//
MSGCLASS=X,MSGLEVEL=(1,1),NOTIFY=KAM0001
//STEP1 EXEC PGM=IDCAMS,REGION=512K
//SYSPRINT DD SYSOUT=*
//DD1
DD DSN=KAM0001.KSDS,DISP=OLD
//DD2
DD DSN=KAM0001.KSDS.ALTINDX,DISP=OLD
//SYSIN
DD *
BLDINDEX INFILE(DD1) OUTFILE(DD2)
/*
//
Defining the path
//USERIDB JOB CLASS=C,
//
MSGCLASS=X,MSGLEVEL=(1,1),NOTIFY=USERID
//STEP1 EXEC PGM=IDCAMS,REGION=512K
//SYSPRINT DD SYSOUT=*
//SYSIN
DD *
DEFINE PATH(NAME(USERID.KSDS.PATH)PATHENTRY(USERID.KSDS.ALTINDX))
/*
//
You can use the VSAMRS program to read the KSDS file via the PATH
//USERID1 JOB NOTIFY=&SYSUID,CLASS=A,MSGLEVEL=(1,1)
//PLIPROC JCLLIB ORDER=(USERID.PLI.PROCLIB)
//DOPROC EXEC PROC=IBMZCB
//PLI.SYSIN DD DSN=USERID.PLI.SOURCE(VSAMRS),DISP=SHR
//BIND.SYSLMOD DD DSN=USERID.PLI.LOADLIB(VSAMRS),DISP=SHR
//*
//RUN EXEC PGM=VSAMRS
//STEPLIB DD DSN=USERID.PLI.LOADLIB,DISP=SHR
//VSAM
DD DSN=USERID.KSDS.PATH,DISP=SHR
//SYSPRINT DD SYSOUT=*
//
PL/I
SECTION 15
23/01/2006
back
SQLCA
You must include the SQLCA.
EXEC SQL
INCLUDE SQLCA;
Coding rules
1. Note how you code the embedded SQL statement as illustrated above.
2. The statement conforms to a PL/I source statement rules ( except that you must specify
EXEC
3. SQL on one line) and is terminated with a semi colon.
4. You can include PL/I comments in embedded SQL statements wherever you can use a blank,
except between the keywords EXEC and SQL
5. You can use any valid PL/I name for a host variable.
6. For the WHENEVER Statement, the target for the GOTO clause must be a label in the PL/I
source code and must be within the scope of any SQL statements that WHENEVER affects.
7. EXEC SQL WHENEVER SQLERROR GOTO :Host Label
8. You must explicitly declare all host variable before their first use in the SQL statements,
unless you specify the pre-compiler option TWOPASS.
9. A colon (:) must precede all host variables in an SQL statement.
10. Where the variable declaration is not complete, the pre-compiler uses the data attribute
defaults specified in the statement PL/I DEFAULT. If the declaration for a variable is not valid,
then any SQL statement that references the variable might result in the message
"UNDECLARED HOST VARIABLE".
11. The pre-compiler uses only the names and data attributes of the variables; it ignores the
alignment, scope, and storage attributes
12. You can use a PL/I host structure name so long as the subordinate levels name scalars.
13. Use a FIXED BINARY(15) variable as an indicator variable. The usage is as in other
languages:- :<variable name that can have NULL values >:<indicator variable name>
DB2 extensions, Result Set Locators
DCL ( variable-name, . . .) SQL TYPE IS RESULT_SET_LOCATOR
The pre-compiler defines these as FIXED BINARY(31) even though it will ultimately have a
pointer value. If you want to assign a pointer variable to this field you must use the built in
function BINARYVALUE to convert the pointer to a FIXED BINARY(31) value.
SQLDA
Under some circumstances, based on your application, you may have to include an SQL
descriptor area. Some instances where you may have to do this are indicated below:FETCH...USING DESCRIPTOR descriptor-name
PL/I
23/01/2006
Where instead of specifying host variables, you set up the SQLDA for receiving a row from the
result set
DESCRIBE statement-name INTO descriptor-name
Where a prepared statement is described (information about the result row in terms of columns is
set into the SQLDA)
DESCRIBE CURSOR INTO descriptor-name
The information returned in the SQLDA describes the columns in the result set associated with
the named cursor.
DESCRIBE PROCEDURE INTO descriptor-name
You use this when you dont know how many result sets are being returned by a stored
procedure.
CALL...USING DESCRIPTOR descriptor-name
Where the SQLDA that contains a valid description of host variables that are to be passed as
parameters to the procedure.
Mapping DB2 data types to PL/I data types. Note that an even SQLTYPE value , say 500 allows
nulls and 501 does not allow nulls. Note that float data types are also available, see the DB2
manuals.
PL/I Data Type
SQLTYPE of
Host Variable
SQLLEN of Host
Variable
500
SMALLINT
496
INTEGER
DEC FIXED(p,s)
0<=p<=15 and
0<=s<=p(1)
484
p in byte 1, s in
byte 2
DECIMAL(p,s)
CHAR(n)
452
CHAR(n)
CHAR(n) VARYING
1<=n<=254
448
VARCHAR(n)
456
VARCHAR(n)
SQL TYPE IS
RESULT_SET_LOCATOR
972
PL/I
23/01/2006
PL/I Equivalent
Notes
SMALLINT
BIN FIXED(n)
1<=n<=15
INTEGER
BIN FIXED(n)
16<=n<=31
DECIMAL(p,s) or
NUMERIC(p,s)
If p<16:
DEC FIXED(p) or
DEC FIXED(p,s)
p is precision;
s is scale.
1<=p<=31
and 0<=s<=p
REAL or
FLOAT(n)
BIN FLOAT(p) or
DEC FLOAT(m)
1<=n<=21,
1<=p<=21 and
1<=m<=6
DOUBLE PRECISION
DOUBLE, or
FLOAT(n)
BIN FLOAT(p) or
DEC FLOAT(m)
22<=n<=53,
22<=p<=53 and
7<=m<=16
CHAR(n)
CHAR(n)
1<=n<=254
VARCHAR(n) or
LONG VARCHAR
CHAR(n) VAR
DATE
CHAR(n)
n=>10
TIME
CHAR(n)
n=>8
TIMESTAMP
CHAR(n)
n=>19
Result set
locator
SQL TYPE IS
RESULT_SET_LOCATOR
PL/I
23/01/2006
The PL/I compiler is invoked to process only PL/I macros in the source. The compiler is invoked
with the options PARM='MACRO,NOSYNTAX,MDECK,NOINSOURCE'. The output source with
macros expanded is written to SYSPUNCH
DB/2 Pre compiler DSNHPC is invoked with PARM='HOST(PLI),SOURCE'. The DBRM is written
to the PDS member pointed to by DBRMLIB. The pre compiled source is written to SYSCIN.
The PL/I compiler is invoked and the Input source is presented via SYSIN (points to the same
data set that was created via SYSCIN in the previous step). The object code is written to
SYSLIN. DCLGEN and other copybooks must be input via SYSLIB.
LKED step. Primary Input via SYSLIN. Secondary input (Linkage editor control cards / or
subroutine object code) via SYSIN and SYSLIB respectively. The Load module is written to
SYSLMOD.
The stubs that need to be link edited depend on the environment in which the program is to run.
1. For the batch environment the stub DSNELI has to be link edited for resolving DB2 calls.
2. If you are creating a stored procedure link edit the DSNALI stub instead. If you are creating a
stored procedure SYSLMOD must point to a load library in the STEPLIB concatenation of the
<subsystem name>SPAS started procedure.
3. If you are creating a PL/I DB2 CICS program link edit the DSNCLI stub.
After preparing the program load module you have to bind the DBRM into a plan for a DB2
program that is not a stored procedure. For a stored procedure you must bind the DBRM into a
package.
Look at sample JCL set up on the system.
PLIDB2CL
for preparing a DB2 program that is not a stored procedure
PLIDB2SP
for preparing a DB2 program that is a stored procedure
DB2BNDPK
for binding a package for a stored procedure
DB2BNDPL
for binding a plan for a DB2 program that is not a stored procedure
DB2PLIR
Can be used for running the PL/I DB2 program (that may also invoke a
Stored Procedure)
Note that the only difference between PLIDB2CL and PLIDB2SP is the stub that gets link edited
with the program (DSNELI and DSNALI). Note also the PROC that is used is DSNHLI.
For a CICS DB2 program the JCL has the following steps:Invoke the PL/I compiler with PARM='MACRO,NOSYNTAX,MDECK,NOINSOURCE' to expand
PL/I macros if present.
Invoke the DB2 translator DSNHPC,PARM='HOST(PLI),SOURCE'
Invoke the CICS translator DFHECP1$ to translate EXEC CICS commands
Invoke the PL/I compiler for compiling the PL/I source
Link edit the program including the stub DSNCLI
Note:-If the program makes MQ calls also include the stub CSQCSTUB
Samples
General Notes on SPUFI:Set up SPUFI if you have not done so.
You need to allocate a data set for SPUFI output. The following JCL may be used:-
PL/I
23/01/2006
PL/I
23/01/2006
PTR=ADDR(DCLTESTPLI);
GET FILE(INFILE) EDIT (LINE)(A(80));
DO WHILE (EOF);
EXEC SQL
INSERT INTO TESTPLI (CUSTNO,CUSTDTLS) VALUES
(:CUSTNO,:CUSTDTLS);
PUT SKIP EDIT('SQLCODE:-',SQLCODE)(A,A);
IF SQLCODE =0 THEN DO;
CALL DSNTIAR ( SQLCA, ERROR_MESSAGE, DATA_LEN );
DO I=1 TO DATA_DIM;
PUT SKIP EDIT(ERROR_TEXT(I))(A);
END;
END;
GET FILE(INFILE) EDIT(LINE) (A(80));
END;
END PLIDB21;
Sample-2
This sample opens a cursor and reads all the rows in the TESTPLI table and prints them on
SYSPRINT.
PL/I
23/01/2006
EXEC SQL
CLOSE INCURSOR;
ERR_ROUTINE: PROC;
PUT SKIP EDIT('SQLCODE:-',SQLCODE)(A,A);
CALL DSNTIAR ( SQLCA, ERROR_MESSAGE, DATA_LEN );
DO I=1 TO DATA_DIM;
PUT SKIP EDIT(ERROR_TEXT(I))(A);
END;
END ERR_ROUTINE;
END PLIDB22;
Sample-3
This sample illustrates how we can update the table using a cursor.
PL/I
23/01/2006
IF SQLCODE =0 THEN
CALL ERR_ROUTINE;
ELSE
DO;
PUT SKIP EDIT('EXISTING DATA:- ',CUSTNO,CUSTDTLS)(A);
EXEC SQL
UPDATE TESTPLI SET
CUSTDTLS = :CUSTDTLSI
WHERE CURRENT OF INCURSOR;
IF (SQLCODE=0) THEN CALL ERR_ROUTINE;
ELSE PUT SKIP EDIT
('SUCCESSFUL UPDATE OF KEY:-',CUSTNOI)(A);
END;
EXEC SQL
CLOSE INCURSOR;
READ FILE(UPDTFILE) INTO(BUFFER);
END;
PUT SKIP EDIT('EOJ')(A);
ERR_ROUTINE: PROC;
DCL PLIRETV BUILTIN;
PUT SKIP EDIT('SQLCODE:-',SQLCODE)(A,A);
CALL DSNTIAR ( SQLCA, ERROR_MESSAGE, DATA_LEN );
PUT SKIP LIST(PLIRETV);
DO I=1 TO DATA_DIM;
PUT SKIP EDIT(ERROR_TEXT(I))(A);
END;
END ERR_ROUTINE;
END PLIDB23;
SQLDA
The SQLDA is an acronym for the SQL Descriptor area. As the name implies it is used by DB2 to
describe DB2 objects to an application. We start with the SQLDA structure itself in the context of
the PL/I host language to see what it contains:-
DECLARE
1 SQLDA BASED(SQLDAPTR),
2 SQLDAID CHAR(8),
2 SQLDABC FIXED(31) BINARY,
2 SQLN
FIXED(15) BINARY,
2 SQLD
FIXED(15) BINARY,
2 SQLVAR(SQLSIZE REFER(SQLN)),
3 SQLTYPE FIXED(15) BINARY,
3 SQLLEN
FIXED(15) BINARY,
3 SQLDATA POINTER,
3 SQLIND
POINTER,
3 SQLNAME CHAR(30) VAR;
Notes:The actual size of the structure is dependent on SQLN. This is because the number of elements
in the SQLVAR array is SQLN. (The concept is the same as in the COBOL clause OCCURS
DEPENDING ON .
PL/I
23/01/2006
If SQLN is set to 750 (the maximum DB2 may need) the size is 16+750*44, which is 33016. The
44 is arrived at based on the size of each SQLVAR element. We say that the maximum number of
elements DB2 may need is 750 because if the SQLDA is used to describe the number of columns
in a row that maximum is 750. In actual practice we set SQLN to a realistic value, say 40, or to
another specific value if we are sure of it.
The structure if inserted into your PL/I application is a based structure. This means we have to
allocate storage for this before it is used at run time. Say we use it in the statement
EXEC SQL
DESCRIBE TABLE :PARM INTO :SQLDA USING NAMES;
If we assume that no matter what table name the variable PARM holds at run time, the maximum
number of columns is 100, then the size of SQLDA would then be 4416. Here is how we would
allocate it:DCL SQLDA_STORAGE CHAR(4416) BASED(P);
ALLOCATE SQLDA_STORAGE SET(SQLDAPTR);
/* NOW SET SQLN */
SQLDA.SQLN=100;
/* SQLN=100 WOULD DO FINE IF WE HAD ONLY ONE SQLDA*/
For a DESCRIBE TABLE SQL statement the structure would have been populated like below:SQLDAID
is set to
SQLDA
SQLDABC
is set to
SQLN*44+16
SQLN
remains at
100
SQLD
is set to
number of SQLVAR entries populated(number of columns)
Each SQLVAR entry describes a column as below:SQLTYPE
is set to
The data type of the column and whether NULLS are
permitted. For example 496 is for long integer (FIXED BINARY
With NULLS not allowed and 497 is for a long integer with
NULLS allowed. 452/453 are for fixed length character strings.
Look at SQL reference for the complete list.
SQLLEN
is set to
The number of bytes of storage required for the column data.
SQLDATA
is set to
X'0000zzzz', where zzzz is the associated CCSID.
SQLIND
is not used
SQLNAME
is set to
The column name.
Note that the context in which the SQLDA is used determines what the SQLVAR entries and the
value of the SQLD data items mean.
Sample-4
This sample illustrates the use of the SQLDA to describe a TABLE. When you run this program be
sure to pass a table name via the PARM JCL field.
PL/I
23/01/2006
PL/I
23/01/2006
PL/I
23/01/2006
IF SQLCODE =0 THEN
CALL ERR_ROUTINE;
ELSE
CALL PRINT_ROW;
END;
ERR_ROUTINE: PROC;
PUT SKIP EDIT('SQLCODE:-',SQLCODE)(A,A);
CALL DSNTIAR ( SQLCA, ERROR_MESSAGE, DATA_LEN );
DO I=1 TO DATA_DIM;
PUT SKIP EDIT(ERROR_TEXT(I))(A);
END;
END ERR_ROUTINE;
/* PRINT EACH COLUMN */
PRINT_ROW: PROC;
DCL I FIXED BINARY(15);
DCL PDATA CHAR(1000) BASED(Q);
DCL VDATA CHAR(1000) VARYING;
DCL 01 VDATA_OVL BASED(P),
02 VARL FIXED BINARY(15),
02 VARD CHAR(1000);
P=ADDR(VDATA);
DO I=1 TO SQLD;
Q=SQLDATA(I);
VARD=SUBSTR(PDATA,1,SQLLEN(I));
VARL=SQLLEN(I);
PUT SKIP EDIT('COLNAME ',SQLNAME(I),' ',VDATA)(A(8),A(12),A,A);
END;
END PRINT_ROW;
/* END OF PRINT ROUTINE */
END PLIDB25;
Sample-6
PLIDB26 is a more refined version of this program and formats the output in a better way.
Look in the system for the source code for this program and understand it on your own.
Sample-7
PLIDB27:-This sample illustrates the use of dynamic SQL. We read the SQL statement from
SYSIN so we dont know until run time what SQL statement we are going to execute.
Here is the sequence of what we do in our program:-
PL/I
23/01/2006
PL/I
23/01/2006
Stored Procedures
A stored procedure is a compiled program, stored at a DB2 local or remote server, that can execute
SQL statements.
A client application program uses the SQL statement CALL to invoke the stored procedure.
Stored procedures can issue many SQL statements. The client program invokes the procedure using
a single SQL CALL statement to the DB2 Server. This reduces network traffic to a single send and
receive operation.
The client program needs authorization to execute the stored procedure. Authorizations to access the
server data directly is not needed. This eliminates the chances of fraudulent manipulation of server
data from the client system.
The client program is insulated from data base design changes as these have an impact only on the
stored procedure. So long as input and output parameters to the procedure dont change, the client
program does not need change.
Core business logic used by many clients can be implemented in a stored procedure.
An open systems client can access VSAM or IMS data through a stored procedure. The stored
procedure fetches VSAM or IMS data and populates a DB2 table. A cursor can be opened on the
table and the result set returned to the client. The client thus deals only with DB2 data. The stored
procedure can source this data from non DB2 sources.
For example to call procedure A on the local system:-
PL/I
23/01/2006
Before the CALL statement is processed, the user must set the following fields in the SQLDA:
1. SQLN to indicate the number of SQLVAR occurrences provided in the SQLDA. This number
must not be less than SQLD.
2. SQLDABC to indicate the number of bytes of storage allocated for the SQLDA. This number
must be not be less than SQLN*44+16.
3. SQLD to indicate the number of variables used in the SQLDA when processing the
statement. This number must be the same as the number of parameters of the procedure.
4. SQLVAR occurrences to indicate the attributes of the variables.
Only a single instance (scalar value) of a parameter can be passed. You cannot pass structures
or arrays.
If a stored procedure abnormally terminates:
1. The calling program receives an SQL error as notification that the stored procedure failed.
2. DB2 places the calling programs unit of work in a must-rollback state.
For the Application Programmer
1. Write the Stored Procedure using the appropriate Language.
2. Pre-compile, compile and Link edit the stored procedure into the user library in the STEPLIB
concatenation of the stored procedure Address space(s) started proc.
3. Define the procedure to DB2. If you are at DB2 version 5 or below you must make an entry in
the DB2 Catalog table SYSIBM.SYSPROCEDURES. For later versions of DB2 you define the
procedure using the CREATE PROCEDURE DDL.
4. Bind the DBRM created in the compilation step into a Package. The collection in which this
package is bound is made known to DB2 when you defined the procedure in the step above.
Note that the following sample has been tested elsewhere but to run on your target
system, the DB2 subsystem must have been set up properly. It is therefore provided only
for illustrative purposes.
For the sample stored procedure illustrated below, the following DDL was used to define the
procedures, except for some changes in input parameters:-
PL/I
23/01/2006
STAY RESIDENT NO
RUN OPTIONS 'MSGFILE(OUTFILE),RPTSTG(ON),RPTOPTS(ON)'
NO WLM ENVIRONMENT
PROGRAM TYPE MAIN
SECURITY DB2
DYNAMIC RESULT SETS 10
COMMIT ON RETURN NO;
Notes on the DDL above that creates the stored procedure definition in the DB2 catalog:1.
2.
The procedure name (load module) as known to MVS is back lighted in blue.
3.
The arguments passed are defined thus:(V1 CHAR(5) IN, V2 INTEGER OUT,V3 CHAR(80) OUT)
V1 is an input only argument CHAR(5)
V2 is an output only argument FIXED BINARY(31)
V3 is an output argument CHAR(80).
The stored procedure accesses the arguments like this:-
5.
The DBRM from compiling the source is bound into a collection KAMCOL1.
6.
You must in addition to bind (or packadm) authority have execute authority on this
collection.
7.
A limit for time execution has been set via the ASUTIME parameter.
8.
The parameter passing style is of type general.(look at DB2 programming guide for other,
more complex argument passing styles).
9.
The program is not to stay resident and will be loaded afresh from the LOADLIB every time
needed.
10.
11.
The stored procedure does not run in an WLM controlled address space and will run in
<sub system name>SPAS (like DSN1SPAS).
12.
The stored procedure will run as a main program and you must therefore code
OPTIONS(MAIN) in the PROCEDURE statement.
13.
14.
The commit point is taken in caller code, not when the stored procedure returns.
PL/I
23/01/2006
*PROCESS NOT('~');
KAM03SP: PROC(P1,P2,P3) OPTIONS(MAIN);
DCL P1 CHAR(5);
DCL P2 FIXED BINARY(31);
DCL P3 CHAR(80);
EXEC SQL
INCLUDE SQLCA;
EXEC SQL
INCLUDE TESTPLI;
EXEC SQL
DECLARE INCURSOR CURSOR WITH RETURN FOR
SELECT CUSTNO,CUSTDTLS FROM TESTPLI
WHERE CUSTNO > :CUSTNO;
CUSTNO=P1;
EXEC SQL
OPEN INCURSOR;
IF SQLCODE ~=0 THEN DO;
P3='OPEN FAILED';
P2=SQLCODE;
RETURN;
END;
Calling Program:-KAM03SPM
*PROCESS NOT('~');
KAM3SPM: PROC OPTIONS(MAIN);
DCL ADDR BUILTIN;
DCL A1 CHAR(5) INIT('00050');
DCL A2 FIXED BINARY(31);
DCL A3 CHAR(80);
DCL CUSTNO CHAR(5);
DCL CUSTDTLS CHAR(75);
EXEC SQL
INCLUDE SQLCA;
DCL LCV SQL TYPE IS RESULT_SET_LOCATOR VARYING;
EXEC SQL
CALL KAM03SP (:A1,:A2,:A3);
IF SQLCODE~=466 THEN DO;
PUT SKIP EDIT('CALL SQLCODE:-',SQLCODE)(A,A);
PUT SKIP EDIT('FETCH SQLCODE:-',A2)(A,A);
PUT SKIP EDIT('FETCH MESSAGE:-',A3)(A,A);
RETURN;
END;
EXEC SQL
ASSOCIATE LOCATORS(:LCV) WITH PROCEDURE KAM03SP ;
IF SQLCODE~=0 THEN DO;
PUT SKIP EDIT('ASSOCIATE FAILED',SQLCODE)(A,F(4));
PL/I
23/01/2006
RETURN;
END;
EXEC SQL
ALLOCATE CSR CURSOR FOR RESULT SET :LCV;
IF SQLCODE~=0 THEN DO;
PUT SKIP EDIT('ALLOCATE FAILED',SQLCODE)(A,F(4));
RETURN;
END;
SQLCODE=0;
DO WHILE (SQLCODE=0);
EXEC SQL
FETCH CSR INTO :CUSTNO, :CUSTDTLS;
PUT SKIP EDIT(CUSTNO,CUSTDTLS)(A);
END;
PUT SKIP EDIT('FETCH LAST SQLCODE',SQLCODE)(A,F(4));
END KAM3SPM;