Iron Spring PL/I Compiler

Programming Guide

Version 0.9.4


Introduction

PL/I is a powerful programming language suitable for a wide range of problems. PL/I has been used to write operating systems and compilers, simulations, real-time programs, mathematical software, spreadsheets, GUI programs, and for general computing.

PL/I is widely used on mainframes and midrange systems today, but since the demise of Digital Research, Inc. has not been easily available on personal computers. Iron Spring Software was founded in 2007 with the intention of bringing the flexibility, reliability, and portability, and security of PL/I to a wider market.

Iron Spring PL/I is the leading cross-platform PL/I compiler supporting both Linux and OS/2. Both native and cross-compilation are supported.

This version of Iron Spring PL/I is still missing some features of full PL/I. The section Restrictions lists many of the missing features.

Modifications to Guide for 0.9.4

Modifications to Guide for 0.9.3
Modifications to Guide for 0.9.2
Modifications to Guide for 0.9.1
Modifications to Guide for 0.9.0
Modifications to Guide for 0.8c
Modifications to Guide for 0.8b
Modifications to Guide for 0.8a
Modifications to Guide for 0.7b
Editorial changes only.

Modifications to Guide for 0.7a

Modifications to Guide for 0.6a

Trademarks
eComStation is a trademark of Serenity Systems International.
EMX is a trademark of Eberhard Mattes.
Gnu is a trademark of the Free Software Foundation.
IBM is a trademark of IBM, Inc.
Intel is a trademark of Intel Corporation.
Iron Spring is a trademark of Iron Spring Software.
Linux is a registered trademark of Linus Torvalds.
VAX is a trademark of Hewlett-Packard, Inc.
WATCOM is a trademark of Sybase, Inc. and its subsidiaries.


Restrictions

MAIN
For better integration with 'ld' on Linux, the external procedure name 'main' is reserved and should not be used.
Interlanguage
PL/I procedures can call functions coded in other languages as long as they use the "SYSTEM" calling convention. The "OPTLINK" and other calling conventions are not supported. Programs in other languages can call PL/I procedures with restrictions. The main program must be PL/I. See Program Linkage for more information.
Preprocessor
In the current version of the compiler the only preprocessor statements fully implemented are %INCLUDE and the listing control statements %PAGE, %SKIP[(n)], %PRINT, %NOPRINT, and %REPLACE. %PROCESS (*PROCESS) is implemented incompatibly from the IBM compilers.
All other preprocessor statements will generate a diagnostic.
See Preprocessor for more information.
CONTROLLED
The CONTROLLED storage class is not yet fully supported. See CONTROLLED Storage for description.
GENERIC attribute
The GENERIC attribute.
DEFAULT
The DEFAULT statement.
DISPLAY options
The REPLY and EVENT options of the DISPLAY statement are not currently supported.
Input/Output
The I/O statements DELETE and UNLOCK are not implemented due to differences in Input/Output of the PC vs. the mainframe. This is a permanent restriction.
The COPY option of the GET statement, the ONKEY and SAMEKEY builtin functions.
GET and PUT LIST or EDIT of a structure will generate incorrect results, GET or PUT DATA will function correctly.
FETCH and RELEASE
The FETCH and Release statements are not currently implemented.
Array Handling builtins
The following array handling builtin functions are not implemented in the current version of the compiler: ALL, ANY, POLY, PROD, and SUM.
Mathematical builtins
The following mathematical builtin functions are not implemented in the current version of the compiler:
ACOS ASIN ATAN
ATAND ATANH
Arithmetic builtins
The following arithmetic builtin functions are not implemented in the current version of the compiler:
CONJG ROUND TRUNC
Builtins PLICKPT, PLICANC, PLIREST, PLITEST
These builtins are not implemented. This is a permanent restriction.
PLISRTx
The sort builtin functions PLISRTA, PLISRTB, PLISRTC, and PLISRTD are not currently implemented. It is anticipated that versions of these functions that interface to one or more sort products will be added in the future.
Aggregate Results
AREA
The AREA attribute, AREA data, and the EMPTY builtin function are not currently supported.
GRAPHIC data
GRAPHIC data support will not be included in this compiler. This is a permanent restriction. A future version will include WIDECHAR data for UTF-16 support. The features not supported include:
REFER
The REFER option for string lengths and array bounds.
LIKE
The LIKE attribute is implemented with one restriction. If a structure is declared as DECLARE a LIKE b; and some elements of "b" have the INITIAL attribute, the initialization is not performed for "a". This will be fixed in a future version.
UNION
The UNION attribute may not be used in adjustable structures.
Procedure calls
A minor structure is not allowed as an argument in a procedure call.

Other features
The compiler error message 995 ("Unimplemented feature xxx") and the run-time condition "UNIMPLEMENTED" are used to flag unimplemented features. Except for "permanent restrictions" noted above, these should be removed in future releases. Some infrequently-used conversions may still be only partially implemented.

Compiler Limits
Maximum number of dimensions15
Maximum number of levels in a structure 15
Maximum level number in a structure255
Maximum number of picture characters in a picture
(after expanding all repetition factors)
511
Maximum length of a CHAR or BIT string
(after expanding all repetition factors)
~32000
Maximum nesting depth of %INCLUDE files4
Maximum precision of FIXED DECIMAL data18
Default precision of FIXED DECIMAL data5
Maximum precision of FIXED BINARY data31
Default precision of FIXED BINARY data15
Maximum precision of FLOAT DECIMAL data20
Default precision of FLOAT DECIMAL data6
Maximum precision of FLOAT BINARY data64
Default precision of FLOAT BINARY data52
Minimum/maximum scale factor-128 / 128
Maximum length of an internal or
external label
31


Documentation

Complete HTML documentation for Iron Spring PL/I will be available as part of a future release. In the meantime, documentation for the IBM "PL/I for MVS and VM Compiler 1.1" is available
online.

Compiler Differences

The reference implementation for this compiler is IBM PL/I for MVS and VM 1.1. Most of the differences are in the area of Input/Output. See the section
Input and Output for a description of the input/output facilities.

See Restrictions for information on major language features that are not currently implemented.

Character representation
Multiple alternate characters can be used to represent OR and NOT. Either the single or double quote can be used as a string delimiter.
DECIMAL FLOAT
DECIMAL FLOAT data is simulated using BINARY FLOAT. This is similar to S/370 PL/I implementations that simulate both DECIMAL FLOAT and BINARY FLOAT using the hardware Hexadecimal floating point formats.
FIXED BINARY
FIXED BINARY data with precision 7 or less is stored in a single byte.
E Format
E Format output will print four digits for exponent instead of two. Output field widths may need to be adjusted.
STRING
The STRING builtin function and pseudovariable restrict the range of data allowed as arguments. This should not affect most normal use of STRING. See the section Builtin Functions and Pseudovariables for the definition of STRING.
ONCODE
The ONCODE builtin function returns only the base value of the error code. For example, IBM PL/I can return codes 600 to 639 for CONVERSION. This compiler will return 600 in all cases. This is a permanent restriction. See list of oncodes.
Additional builtins
The following additional builtin functions are supported:
ALLOCATE, BYTE, COLLATE, COMPARE, COPY, CS, HEXIMAGE, MAXLENGTH, PLIFILL, PLIFREE, PLIMOVE, RANK.
See the section Builtin Functions and Pseudovariables for the definitions.
ATTENTION
The ATTENTION condition is enabled by default. It is raised by pressing ^C while running a text-mode application or otherwise sending XCPT_SIGNAL_INTR/SIGINT to the PL/I process. If no ON-Unit is established for ATTENTION, the implicit action is the same as for ERROR: print an error message and raise the FINISH condition. On normal return from an established ON-Unit, execution continues unaffected. Note that ATTENTION will be raised only in the initial task/thread
RETURNS keyword
Procedure and Entry statements (not ENTRY declarations) may specify "RETURNS( CHARACTER(*) [VARYING] )", or "RETURNS( BIT(*) [VARYING] )". The length of the returned string is determined by the entry declaration in the calling program, e.g.:
DECLARE a ENTRY RETURNS( CHARACTER(20) );.
IBM compilers require an explicit length and will not allow '*'.
EXTERNAL Attribute and Program Linkage
The EXTERNAL attribute has been enhanced to allow the provision of a non-PL/I name visible to procedures outside the PL/I program. The syntax is:
DECLARE x EXTERNAL( 'environment_name' )
See Program Linkage. for more details.


Running the Compiler

The "PLIC" command is used to invoke the compiler.

The syntax of the PLIC command is shown. The case of the option switches is significant. Lower-case options have parameters, upper-case do not.


   PLIC [<options>] <input files> [-o <output file>]

        <options> = <output option>    [<include options>]         [<listing options>]
                    [<source margins>] [<character substitutions>] [<version info>]
                    [<error option>]   [<misc options>]

        Options may be entered in any order.
        The Linux shell requires that options containing () be enclosed in double quotes (").  

        <output option> = -S | -C | -L
                          -S = generate assembler (symbolic) output.
                          -C = generate compiled (object) output.
                          -L = generated linked (EXE or DLL) output.
                               (this option not currently implemented.}

        <include options> = -i<directory>
                            where <directory> is the absolute or relative path 
                            to a directory to be searched for %INCLUDE files.
                            This option may be used more than once on the command line,
                            and directories will be searched in the order listed.

        <listing options> =  -l[siaxgm]
                            one or more of [siaxgm] may be entered, in any order as -lsx
                            -ls = list source
                            -li = list insource
                            -la = list attributes
                            -lx = list cross-reference
                            -lg = list aggregates
                            -lm = list generated code in a format similar to an 
			    -lo = list procedure map (statement offset table)
                            Currently, the insource and aggregate listings are not available.

        <source margins> = -m(start[,end])
                           This option defines the first and last positions of each
                           input line that contain input for the compiler.  If this
                           option is omitted the source is assumed to be the entire line.
                           This option is included for compatibility with mainframe compilers
                           which would use, for example, -m(2,72).

        <character substitutions> = -cn(<list>) and/or
                                    -co(<list>)
                            This option defines up to four characters each to be used as
                            substitutions for the NOT(¬) [-cn()] and/or OR(|) [-co()]
                            operator IN ADDITION TO the defaults.  The caret (^) is
                            a metacharacter for the OS/2 command processor; if the
                            caret is to be used, code two consecutive carets,
                            for example -cn(^^).

        <version info> = -V
                         The compiler prints version and copyright information on stderr.

        <error option> = -e<option>
                         This option sets the errorlevel returned by the compiler for warning
                         and error messages.  Normally compiler returns 4 if only warnings were
                         issued, and 8 for any errors.
                         -ew tells the compiler to return 0 if only warning messages were issued.
                         -es tells the compiler to return 0 if any errors or warnings were issued.
                         This option is useful when the compiler is run from a script or makefile.

        <misc options> = -d<option>
                         <option> is a character string, with or without enclosing quotes.
                         -dLIB tells the compiler it is compiling a standard run-time library procedure.
                         -dELF causes the compiler to generate ELF object files.
                         -dOMF causes the compiler to generate OMF object files.
                         The default is to generate the standard object format for the host OS;
                         for OS/2 -dOMF is the default.

        <input files> and <output files> are absolute or relative path names.  Only one input and one
                         one output file are currently allowed.  If the output file is omitted the name
                         is generated.  For example, PLIC -S abc.pli will create a file named abc.asm.

Linking PL/I Programs

The "Release Notes" for your environment -
Linux or OS/2 contains a section on linking PL/I programs.


Compiler input

Compiler input is a standard text file [ENV(TEXT)]. Conventionally, the source program might have the extension ".pli" or ".pl1", but this is not required. Lines are delimited by Newline characters ('0A'x). There is no limitation on line length, although individual tokens such as character-strings are limited to approximately 32,000 characters. Other than newlines, characters lower in the collating-sequence than spaces ('20'x) are ignored. This means, therefore, that at the present time they should not be coded in character string constants. To compile a character string constant containing one or more of these characters concatenate the hexadecimal value, for example:

declare two_line_constant char(24) static initial( ('Line one' || '0D0A'x || 'Line two.') );
This type of expression is resolved at compile-time and does not generate any additional code.

The compiler chaaracter set is Codepage 850. The default representations for the OR character is '|', '7C'x in codepage 850, and for NOT '¬', 'AA'x in codepage 850. The corresponding unicode characters are U+007C [bar, vertical], and U+00AC [NOT SIGN]. The character As indicated above under Running the compiler, the options -cn and -co can be used to indicate additional encodings used to represent these characters.

String data can be delimited by either the single (') or double (") quote characters. The same character must be used to begin and end the string. The character not used as a delimiter may be part of the string. If portability is a concern, use only the single-quote to delimit strings. The character used as a delimiter can be included in the string by specifying it twice in succession, for example, 'Let''s dance' will be compiled as Let's dance, """Fine"", he said" as "Fine", he said.

Source lines are logically continued from the right margin of one line to the left margin of the next, with no whitespace assumed between the two character positions. (see the -m compiler option). Any characters outside the margins, as well as any characters lower than space in the collating sequence, are ignored. For example:


         Left Margin            Right Margin                  Line End
             |                       |                            |
             "This is a continued charsome stuff outside the margin
 extra stuff acter string"
will be compiled as This is a continued character string.

If a line ends with a word or a number with no trailing blank, and another word or number begins in the left margin of the next line the two will be considered a single token. A future release will cause words and numbers, but not strings, operators, etc., to break at the end of a line.

INCLUDE files are identical in format to the source file. Currently INCLUDE files must have either no extension or the extension ".inc" or ".cpy". The compiler option -i, which can be repeated multiple times, provides a list of directories to be searched, in the order written, to locate an INCLUDE file. The current working directory is always searched last if the file is not found sooner. INCLUDE files use the same list of alternate characters as the source, and must use the same margins, although a future release will allow these to be overridden for each individual file.


Compiler output

If any of the listing options (-lx) is specified, compiling a program xxx.pli will create a source listing file named xxx.lst.

Compiler output currently consists of the optional source, assembler, statement offset table, and symbol attribute, and cross-reference listings, and an optional object file or assembler file of the compiled program.

All pages of the listing have a heading similar to the following showing the date and time of compilation and the compiler version used. The title is taken from the first line of the source file. The subheading identifies the "Source Listing", the "Assembly Listing", and the "Symbol Table and Cross-Reference Listing."


Mar  5, 2010  10:28     /* _pli_Sig                                     */                          
0.8d                                                Source Listing           ...         Page 1     

Source listing:
If the compiler option "-ls" is specified a source listing will be generated.

Here are a few lines from a listing: The letters in blue are a key to the descriptions below, and are not part of the listing.


A   B  C
  340 
  341  %include DSA;
  342
  D     E   F 
341 (INF104)Processing include file DSA.
G

    1  /********************************************************************/
    2  /*                                                                  */

'B' is the line number. The source file and each %include file are numbered starting from line one. A future compiler version will also provide a file number for each include file to be used on error messages.

'C', the next 100 characters of the listing, show the input line. If the line is longer than 100 characters additional unnumbered lines will display the overflow.

The line following line 342 above shows the format of error, warning, and information messages. 'D' is the source line number. 'E' is the severity and message number (xxxyyy) 'xxx' is 'INF' for information-only messages as shown, 'WRN' for warnings, and 'ERR' for errors. 'yyy' is a unique message identifier for this error. 'F' is the message text.

Currently messages generated by the parser appear intermixed in the source listing, while code generator messages appear at the end of the source, or intermixed in the object code listing if one is produced. In a future version all messages will appear at the end. Due to parsing considerations the error message may appear one line before or after the line it references.

Assembly listing:
If the -lm option is specified, a listing of the generated code will appear after the source listing. This is similar in format to the listing generated by ALP. The major difference is that ALP displays immediate operands in big-endian order. This listing will always display immediate operands as they are stored in memory, i.e. little-endian.

Here is a small sample of the object code listing:


                                        ; Stmt 14, Line 17 (DO)
00000313 89 65 [CC]                      mov dword ptr -52[ebp],esp
00000316 8B 75 [D8]                      mov esi,dword ptr -40[ebp]
00000319 8B 3E                           mov edi,dword ptr 0[esi]
0000031B 83 FF 00                        cmp edi,00h
0000031E 90 90 90 90 90 90               db 90h,90h,90h,90h,90h,90h
00000324 8B 65 [CC]                      mov esp,dword ptr -52[ebp]
                                        ; Stmt 15, Line 18 (Assignment)
00000327 8B 75 [D8]                      mov esi,dword ptr -40[ebp]
0000032A 8B 3E                           mov edi,dword ptr 0[esi]
0000032C 89 7D [D4]                      mov dword ptr -44[ebp],edi
                                        ; Stmt 16, Line 19 (DO)
0000032F 89 65 [C8]                      mov dword ptr -56[ebp],esp
00000332 8B 75 [D4]                      mov esi,dword ptr -44[ebp]

The -lo option causes a procedure map to be printed listing the assembled offset of each statement, its starting line number, and the statement type. Here is the procedure map for the procedure containing the code shown above:


  Offset  Line Statement type             Offset  Line Statement type             Offset  Line Statement type           
      08     2 PROCEDURE                ENV
      23    10 Assignment                     35    11 PUT                            E4    12 PUT                      
    0180    13 Assignment                   0197    14 PUT                          0246    15 PUT                      
    02C3    16 PUT                          0313    17 DO                           0327    18 Assignment               
    032F    19 DO                           0343    20 PUT                          03BF    21 Assignment               
    03C8    22 END                          03D0    23 PUT                          0420    24 Assignment               
    0429    25 END                          042E    27 END                      

Symbol table and cross-reference listings:
If the compiler options "-la" or "-lx" are specified, the attribute list (symbol table) or cross-reference listing is printed as shown below. "-la" causes the variable attributes to be printed, "-lx" causes the cross-reference listing to be generated. The example below shows the results of specifying "-lax".


H                    I    J                                                     K
ADDR                 124  Builtin
BSW                  309  Entry Unaligned                                       < Code+'13C0'x >
                            265 
BYTE                 332* Builtin
                            737   738 
C                     77  Char(1) Unaligned                                     < DSA-'51'x(1) >
                            266   278   300   321   346   362   370   446   452   453 
                            478   507   510   512   514   516   531   553   557   566 
C4                   109  Char(4) Unaligned Based                               < +'00'x(4) >
                            297   298   533   615   679 
C4                   327  Char(4) Unaligned Parameter                           < Loc @DSA+'08'x(4) >
                            723   724   725   726   727 
CONDS                 97  (9) Char(6) Var Unaligned Static Init()               < Static+'12'x(8) >
                            407   635 
DSA_BELOW_EBP         27  Unaligned Structure In(PLI_DSA)                       < +'00'x(32) >
                            635   636   642   643   644   646   647 
DSA_CHC               33  Ptr Aligned In(PLI_DSA.DSA_BELOW_EBP)                 < +'08'x(4) >
                            643 
PLI_DSA              340  Unaligned Based Structure Level(1)                    < +'00'x(40) >
'H' is the name of the data element. If the name is longer than twenty characters it will appear on a line by itself, with the remaining data shown on the next line. 'I' is the line number of the declaration of this item. Undeclared data, like 'BYTE' above show the line number where this element is first used, followed by '*'.

Each generation of data will be listed separately. The two occurrences of 'C4' above represent two data elements with the name 'C4' in two different blocks. Usage of each is cross-referenced separately.

'J' lists the data attributes, which should be self-explanatory. This field may occupy more than one line.

'K' shows the address of the item in < >. The addresses are displayed as follows:

Code labels:
Code+'oooo'x. 'oooo' is the hexadecimal offset from the first code byte. See 'BSW' above.
STATIC data:
Static+'oooo'x(ll). 'oooo' is the offset from the first data byte. 'll' is the (decimal) length of the data element. The length of UNALIGNED BIT elements is shown as (x.y) where 'x' is the number of whole bytes, and 'y' is the number of additional bits. For an array, 'll' is the length of one member. See 'CONDS' above.
AUTOMATIC data:
DSA-oooo'x(ll). 'oooo' is the offset from the start of the DSA containing the data. Register EBP always points to the current DSA. Lexically containing DSAs (static scope) are chained from offset -8 in the contained DSA. All offsets are negative. See the file 'DSA.INC' distributed with the library. The variable 'C' above is an example of AUTOMATIC data.
BASED data:
+'oooo'x(ll). 'oooo' shows the offset from the beginning of the BASED variable or structure. See the first occurrence of 'C4' above.
Data addressed via locator:
Loc @DSA±'oooo'(ll). This is the address format for parameters, adjustable data, and CONTROLLED data. 'oooo' is the offset of the locator/descriptor which points to and describes the data. See the second 'C4' above.

If there were any errors or warnings, a message showing the number of them appears at the end of the listing.

Object output:
Compiling a program xxx.pli with the -C option will create an object file xxx.obj for OMF-format output, or xxx.o for ELF. The layout of the generated code is described under "Program Structure" below.

Assembler output:
Compiling a program xxx.pli with the -S option will create an assembler file xxx.asm in a format suitable for the IBM ALP assembler or the open-source JWASM assembler. Other assemblers will most likely not be able to assemble this file correctly.

The compiler generates assembler labels for level-1 EXTERNAL data and for each EXTERNAL ENTRY. Most assemblers have a list of reserved words which cannot be used for labels, typically including all register names (e.g. EAX), all instruction mnemonics (LEA), and most pseudo-ops (ORG). Using any of these as PL/I external labels will cause an assembly error.

A few lines of assembler output are shown:


; Stmt 2, Line 3 (PUT)
 .code
 sub esp,64 
 mov word ptr 0[esp],1 
 mov dword ptr 12[esp],ebp
The source statement and line number that generated each piece of code, along with the statement type is shown as indicated. The line number ties this code to the source listing.
Program Structure
The generated program consists of a single code segment(.text) identified by the label '_pli_code', a single static data segment(.data) identified by '_pli_data', an unnamed stack segment for OS/2, and zero or more external common segments. No BSS segment is currently generated. PL/I programs typically do not contain large amounts of uninitialized static data that would go into a BSS segment, although it is possible one will be added later.

External segments are generated for each variable or structure declared EXTERNAL, as well as for each EXTERNAL FILE. If the variable has the INITIAL attribute the data is always generated, otherwise the declared amount of storage is reserved. Here is the generated code for an uninitialized external structure named 'abc':


ABC segment dword common 'ABC'
_ABC equ $
 org _ABC+0Ch
ABC ends
Here is the code for the initialized external segment 'sysprint':

SYSPRINT segment dword common 'SYSPRINT'
_SYSPRINT equ $
 dd 0
 dd 0
 dd _SYSPRINT+12
 dw 8
 db 'SYSPRINT'
SYSPRINT ends
The linker combines identically-named external segments. The resulting length will be the length of the largest such segment. The data values will be taken from the first initialized segment encountered.

All declarations of EXTERNAL data should be identical in length, and, if one or more of the declarations contains the INITIAL attribute, the initial values should be the same. It is permissible to have only one declaration of EXTERNAL data have the INITIAL attribute, and all procedures declaring it will reference that data.

Internal Data Representations
FIXED BIN, precision 7 or lessBYTE
FIXED BIN, precision 15 or lessWORD
FIXED BIN, precision 31 or lessDWORD
FIXED DEC, any precision
Intel x87 BCD format
TBYTE
FLOAT BIN, precision 23 or less
Intel x87 short floating-point
REAL4
FLOAT BIN, precision 49 or less
Intel x87 long floating-point
REAL8
FLOAT BIN, precision>50
Intel x87 extended floating-point
REAL10
FLOAT DEC, precision 7 or lessREAL4
FLOAT DEC, precision 15 or lessREAL8
FLOAT DEC, precision>15REAL10
PTR, OFFSETNEAR PTR
CHARACTER(n)n bytes
BIT(n) ALIGNED(n+7)/8 bytes
BIT(n) UNALIGNEDn bits
VARYING strings will be preceded by a two-byte length prefix
which will force WORD alignment.
TASK24 bytes aligned on DWORD boundary
EVENT16 bytes aligned on DWORD boundary
EVENT data is always initialized.

Compiler Work File:
The compiler creates a temporary work file named PLI-xxxxxxxx-yyyyyyyy-zzzzzzzz.tmp, in the current working directory on OS/2, or the /tmp directory on Linux. Normally this file is deleted at the end of compilation. Errors in the beta version of the compiler causing certain traps may prevent automatic deletion of this file. If it not automatically removed it may be deleted manually.


Syntax Chart Format

In the syntax charts that follow, the characters '-', '.', '+', 'v', '^', '|', '<', and '>' are used only for drawing the chart, and are not part of the syntax. Other punctuation such as parentheses, semicolons, commas, etc. must be entered as shown.Words shown in CAPITALS are PL/I keywords. Words shown in lower-case represent names chosen by the programmer or variable information. (The actual case of the word in the program is not significant.) '>>' identifies the beginning of a diagram, and '><' represents the end. Entities appearing in '|' data '|' represent a syntax fragment that is expanded later. Elements on the main line of the diagram as '--- stuff ---' are required. Elements appearing above or below the main line represent choices. Elements shown all below the line are optional with no default. Where one element is shown above the line it represents the default if none of the choices is specified.

Input and Output Statements

In the following discussion, delimiter signifies either a linefeed character (ASCII '0A'x), or a carriage-return/linefeed combination (ASCII '0D0A'x).

Iron Spring PL/I can read and write:

  1. Standard text files, with lines of text terminated by delimiters.
  2. Files of fixed-length records with or without delimiters.
  3. Files of variable-length records where the length of each record is indicated by a two-byte binary prefix, with or without delimiters.
  4. Files containing arbitrary streams of binary data with no record boundaries.

File Declarations
The general form of a file declaration is shown below. As usual, keywords can be specified in any order. Many keywords may be specified either in the declaration or in the OPEN statement for the file. If they are specified in both, they must not conflict. For example, a file declared INPUT cannot be opened as OUTPUT or the UNDEFINEDFILE condition will raised when the file is opened.

>>-DECLARE-name-+------+-+--------+-+--------+-+----------------------------------+-+------------------+-><
                |      | |        | |        | |                                  | |                  |
                +-FILE-+ +-RECORD-+ +-INPUT -+ +-ENVIRONMENT(environment options)-+ +-other attributes-+
                         |        | |        |
                         +-STREAM-+ +-OUTPUT-+
                                    |        |
                                    +-UPDATE-+

RECORD and STREAM Files
  • STREAM indicates that the file is a continuous stream of data items in character form. STREAM files are read or written without regard to record boundaries. The PL/I statements GET and PUT are used to process STREAM files.
  • RECORD indicates that the file is logically divided into records which are composed of one or more data items in any form. A record is always read or written as a unit. The PL/I statements READ, WRITE, REWRITE, and LOCATE are used to process RECORD files.

INPUT, OUTPUT, and UPDATE
  • INPUT indicates that the file is to be read only. The file must exist or the UNDEFINEDFILE condition will be raised when the file is opened.
  • OUTPUT indicates that the file is to be written only. If the file does not exist, it will be created when opened. If it does exist, it will be deleted and a new file created, unless the ENVIRONMENT option APPEND is specified.
  • UPDATE indicates that the file is going to be both read and written.

ENVIRONMENT Options
The ENVIRONMENT attribute allows specification of implementation-dependent options for a file. Iron Spring PL/I allows coding of all ENVIRONMENT attributes allowed by IBM PL/I for MVS and VM. Only attributes actually used are described here.
  • Record format keywords: D, DB, F, FB, FS, FBS, V, VB, VS, VBS, U.
    One of these keywords is coded to indicate the type of records to be processed. Only the D, F, V, and U are significant, the others are provided for compatibility. F indicates that the file consists of records having all the same length. V or D indicate that the records in the file can have different lengths.

    The options TEXT, CRLF, LF, and VARLS provide additional information about the external representation of F, V, and D files.

    Record format U allows reading and writing files without regard to formatting or record boundaries. When reading INTO a character string, the amount of data available up to the maximum length of the string is returned. ENDFILE is raised only on the next read after the last byte has been returned. See the sample program 'readu.pli' for an example of using ENV(U) to read a file with no predetermined maximum record length. Writing FROM a character string writes n bytes of data from the string, where n is the current or constant length of the string.

  • BLKSIZE(n) specifies the size of the buffer used to transfer data to or from the file or device. If this keyword is not specified, a default value is used.
  • RECSIZE(n) specifies the uniform record length for F files, or the maximum record length for V or D files. If this keyword is not specified, the default is LINESIZE. The RECSIZE value describes only the data portion of the record, exclusive of delimiters, length prefixes, etc.
  • TEXT, CRLF or LF specifies the presence of record delimiters. If none of the three options is specified, no delimiters will be written on output or expected on input. TEXT indicates that the default record delimiter for the system will be used: CRLF for OS/2 or LF for Linux. The TEXT option should be used in preference to either CRLF or LF unless a specific delimiter is required, since code specifying TEXT is portable. LF indicates that a single newline character (ASCII '0A'x) delimits records in the file (Unix convention). CRLF indicates that a carriage-return/linefeed combination (ASCII '0D0A'x) is used as a delimiter (OS/2, DOS convention). The delimiters will be written as specified on output, but either is always acceptable for input.
  • VARLS specifies that records in the file will be written with a FIXED BINARY(15) prefix containing the length of the following data.
  • APPEND specifies that an INPUT or UPDATE file will have data appended to the end if it already exists. When the file is opened, the current file position will be set to the end of the file.

Other Attributes

STREAM files default to ENV(V TEXT) unless other attributes are specified. RECORD ENV(V) files default to ENV(V VARLS).

Standard Files
Unless overridden by ENVIRONMENT or OPEN, the standard files SYSIN and SYSPRINT default to stdin and stdout with the following attributes respectively.
SYSINENV(V TEXT RECSIZE(120)) LINESIZE(120)
SYSPRINTPRINT ENV(V TEXT RECSIZE(120)) LINESIZE(120) PAGESIZE(60)
If stdin and stdout are the current terminal(VIO) window, these files default to ENV( BLKSIZE(0) ).
Interactive options


DISPLAY statement

The DISPLAY statement writes text to stderr. The syntax is:

>>-DISPLAY (expression)--+-----------------+--+-------------------+----------- ; --><
                         |                 |  |                   |
                         +-REPLY(char-ref)-+  +-EVENT(event-ref)--+

"expression" is converted to a character string and written to stderr. If the "reply" option is not specified, this is followed by a newline. Otherwise the "reply" and "event" options are currently ignored.


CONTROLLED Storage

The current version of the compiler supports a restricted version of CONTROLLED storage. All lengths and bounds must be declared, although they can be variables. No length or bound information is allowed on the ALLOCATE statement. The following is not allowed:

  DCL a char(0) CTL;
  ALLOCATE a CHAR(5);
Instead use the following:

  DCL asize FIXED BINARY;
  DCL a char(asize) CTL;
  asize = 5;
  ALLOCATE a;

This will be extended to include full support for CONTROLLED variables in a future release.


Multitasking

The Compiler currently supports the "multitasking" API similar to IBM PL/I for MVS and VM. "Multithreading", as supported by IBM Enterprise PL/I, will be implemented in a future release. Iron Spring PL/I will then continue to support both feature sets.

The multitasking API adds a TASK data attribute, the TASK, EVENT, and PRIORITY options of the CALL statement, and the PRIORITY builtin function and pseudovariable. The EVENT attribute and the builtins/pseudovariables COMPLETION and STATUS, and the WAIT statement, which IBM does not consider part of the multitasking feature, are also documented here.

Tasks constitute a hierarchical structure with the initial task of the procedure, the "major task", at the root. If the major task "A" attaches tasks "B" and "C", these are then subtasks of "A". If subtask "B" attaches task "D", "D" is then a subtask of "B" and so on. When a task terminates, any subtasks which are not complete will be terminated. Otherwise a task will terminate when any of the following occurs: Execution of a STOP statement in any task will terminate the major task and all subtasks.

Multitasking considerations:


Additional Builtin Functions and Pseudovariables

This section lists only builtins in Iron Spring PL/I either not present in IBM PL/I for MVS and VM or implemented differently. The definitions are taken from IBM PL/I for OS/2 [OS2], IBM Enterprise PL/I [ENT], or VAX PL/I [VAX].

ALLOCATE(n) ALLOCATE allocates n bytes of storage and returns a pointer to the first byte. [OS2][ENT]
BYTE(n)BYTE returns a character string of length one equivalent to the following:
SUBSTR( COLLATE(), MOD(n,256)+1, 1 ) [ENT][VAX]
COLLATECOLLATE Returns a character string of length 256 containing all 256 possible character values. [OS2][ENT][VAX]
COMPARE(x,y,z)COMPARE compares "z" bytes at locations pointed to by "x" and "y". [OS2][ENT]
COPY(x,y)COPY returns a string consisting of "y" concatenated copies of string "x". [OS2][ENT][VAX]
CS(p,q,x)CS executes a hardware "CMPXCHG" instruction and returns a FIXED BINARY(31) value indicating whether or not the exchange was accomplished. q is a pointer expression which yields the address of a FIXED BINARY(31) variable q' to be set by the exchange, p is a pointer expression which yields the address of a FIXED BINARY(31) variable p' which is to be compared with q', and x is an expression which yields the new FIXED BINARY(31) value to be set. If p' and q' are equal x replaces q', and the CS builtin returns 0 (success). If they are unequal q' replaces p' [to set up for another call to CS] and the builtin returns 1 (failure). This provides an atomic "compare and swap" operation for thread or process synchronization. [ENT]
HEXIMAGE(x,y[,z])HEXIMAGE returns a character string that is the hexadecimal representation of 'y' bytes of storage at location 'x'. If 'z' is omitted, the length of the returned string is 2*y. If 'z' is present it must be CHARACTER(1) nonvarying, and the value of 'z' is inserted between every set of eight characters in the output string. In this case the length of the returned string is (2*y) + floor((y-1)/4). [OS2][ENT]
MAXLENGTH(x)MAXLENGTH returns the maximum length of the string value of "x". "x" must be computational; if it is not a string it is converted to a CHARACTER string before the length is calculated. This is different from the LENGTH builtin that converts BINARY arguments to BIT strings, but is consistent with IBM Enterprise PL/I. [OS2][ENT][VAX]
PLIFILL(x,y,z)PLIFILL moves "z" copies of a single byte "y" to a location "x" with no conversion, padding, or truncation. [OS2][ENT]
PLIFREE(p)PLIFREE frees storage at location "p" allocated by the ALLOCATE builtin. [OS2][ENT]
PLIMOVE(x,y,z)PLIMOVE moves "z" bytes to the location pointed to by "x" from the location pointed to by "y". [OS2][ENT]
RANK(c)RANK returns a FIXED BINARY(15) result. "c" is a character string of length one. RANK(c) is equivalent to the following:
INDEX( COLLATE(), c ) - 1 [ENT][VAX]
STRING(x)STRING concatenates the elements of array or structure "x" and returns the result. "x" is any reference that is suitable for string-overlay defining. Bit strings should have no gaps between elements caused by alignment. The string returned is a nonvarying character or bit string depending on the type of "x". The length of the string is the total number of characters or bits in "x". [ENT][VAX]
(definition change).


Program Linkage

PROCEDURE and ENTRY and PACKAGE statements
PROCEDURE statement.

PROCEDURE-+--------------------+-+-----------------+-+-----------------+-+-------------+-+------------------+-- ; ><
          |                    | |                 | |                 | |             | |                  |
          +-| ( parameters ) |-+ +-| returns-opt |-+ +-| options-opt |-+ +- RECURSIVE -+ +-| external-opt |-+
ENTRY statement.

ENTRY--+--------------------+-+-----------------+-+-----------------+-+-------------+-+------------------+- ; ><
       |                    | |                 | |                 | |             | |                  |
       +-| ( parameters ) |-+ +-| returns-opt |-+ +-| options-opt |-+ +- RECURSIVE -+ +-| external-opt |-+ 
Other keywords defined by The IBM PL/I for MVS and VM compiler 1.1 and various other compilers are accepted for source compatibility, but are otherwise ignored.


|parameters|

  +------- , ----------------+
  v                          |
|-.- parameter-description --+----|
Each parameter-description supplies the attributes for one parameter, therefore the entry expects as many arguments as there are items in the list. A parameter-description is a list of data attributes that describes that parameter. For example: FIXED BINARY(7), CHARACTER(8), POINTER, or ENTRY would all be valid parameter descriptions.


|returns-opt|

|-- RETURNS ( returns-description ) ---|
The returns-description describes the attributes of the data which will be returned by this entry if it is invoked as a function. If the returns-opt is omitted the attributes are determined by the first character name of the first or only name prefix — I thru N: FIXED BINARY(15), other: FLOAT DECIMAL(6).


|options-opt|

                +--- , --------+
                |              |
                +--------------+
                v              |
|---- OPTIONS ( . entry-option +  ) ---|
Each entry-option is one of the following:
FROMALIEN
Indicates that this entry may be called from a non-PL/I program. A FROMALIEN procedure should be considered to be non-nested — that is, it may not access any AUTOMATIC data in the containing procedures, if any. Also, any condition-handling established in a previously-called procedure will be ignored on entry to the FROMALIEN procedure.

LINKAGE( linkage-type )
'linkage-type' indicates the type of calling sequence with which this entry will be invoked. If LINKAGE is omitted, a standard PL/I convention will be used. (see Run-time Considerations). Currently the only valid linkage type is SYSTEM. This can be used to call functions written in C, including OS/2 API functions, but is also a valid convention among PL/I procedures, with some restrictions.
For source compatibility with IBM PL/I for OS/2, specify 'OPTIONS( BYVALUE LINKAGE(SYSTEM) )'. BYVALUE is assumed by this compiler and the keyword is ignored, but IBM PL/I defaults to BYADDR unless otherwise specified.

LINKAGE(OPTLINK) will be implemented in a future version to specify the "Optlink" calling convention that uses registers for some arguments.

MAIN
Indicates that this is the initial or 'main' procedure. Iron Spring PL/I allows only one OPTIONS(MAIN) procedure to be included in an executable program.

REENTRANT
This is included for compatibility only. All code compiled by Iron Spring PL/I is reentrant.

RECURSIVE is supported for compatibility only. It indicates that this entry may call itself, either directly or indirectly through a chain of calls. Iron Spring PL/I assumes all entries are potentially recursive.


|external-opt|

|-- EXTERNAL --+----------------------+---|
               |                      |
               +- ( external-name ) --+
The external-name is a character string, enclosed in quotes, representing the name by which this entry will be known to external callers. External 'external-name's beginning with the string "_pli" are reserved for use by the run-time library. If the 'external-name' is not specified, the default external name is an uppercase translation of the first label on the external procedure or entry statement. For example, x: y: PROCEDURE; will use "X" as the external name for the linker.

ENTRY Declarations
The following attributes can be used in the declaration of an external entry:

DECLARE-- decl-name --ENTRY-+--------------------+-+-----------------+-+-----------------+-+------------------+-- ; ><
                            |                    | |                 | |                 | |                  |
                            +-| ( parameters ) |-+ +-| returns-opt |-+ +-| options-opt |-+ +-| external-opt |-+
Parameters, returns-opt, and external-opt are described under "PROCEDURE and ENTRY Statements" above. An entry declared without a parameter list — DECLARE a ENTRY; will accept any number of arguments with no conversion. An entry declared with an empty parameter list — DECLARE a ENTRY(); does not allow any arguments.

|options-opt|

                +--- , --------+
                |              |
                +--------------+
                v              |
|---- OPTIONS ( . entry-option +  ) ---|
The following options are valid for entry declarations:
ASSEMBLER (abbreviated ASM)
Indicates that the entry is a non-PL/I procedure (assembler, C, etc.) The compiler generates code to save and restore the x87 Floating-point control word, since programs in different languages may change this unpredictably.
LINKAGE( linkage-type )
'linkage-type' is as described above under "PROCEDURE and ENTRY Statements".
PACKAGE statement.

PACKAGE-+-------------------------------------+----+-------------------------------------+--+-------------------+- ; ><
        |                                     ^    |                                     ^  |                   ^
        |               +----- , ------+      |    |                +---- , ------+      |  |                   |
        |               |              |      |    |                |             |      |  |                   |
        |               v              |      |    |                v             |      |  |                   |
        +- EXPORTS ( -+-+- procedure --+-+- )-+    +- RESERVES ( -+-+- variable --+-+- )-+  +- OPTIONS(options)-+
                      |                  ^                        |                 ^
                      |                  |                        |                 |
                      +------- * --------+                        +------- * -------+

A package is a block which can immediately contain only declarations, DEFAULT statements, and PROCEDURE blocks. The package forms a name scope that is shared by all declarations and procedures it contains. Some or all of the level-1 procedures can be exported and made known outside the package as external procedures.

EXPORTS
Specifies that all [EXPORTS(*)] or the named procedures are to be made known outside the package. Procedures not exported are known only within the package. If the EXPORTS keyword is not specified, EXPORTS(*) is assumed.
RESERVES
This keyword is not used by the Iron Spring compiler, and is treated as comments only due to differences in handling initialized and uninitialized EXTERNAL data.
OPTIONS
This keyword is not used by the Iron Spring compiler, and is treated as comments only for compatibility with other compilers.

All declarations with package scope (outside of procedures within the package) must have STATIC, BASED, CONTROLLED, or EXTERNAL storage class, AUTOMATIC data is not allowed outside of procedures.


Run-time considerations

Run-time messages
All run-time messages are written to stderr: