Iron Spring PL/I compiler

Programming Guide

Alpha Version 0.5d

This is alpha software. The compiler is capable of compiling itself, but no guarantee of completeness or correctness should be inferred. Many PL/I features, or parts of features, that were not necessary for the compiler have been omitted from the initial version. A partial list is provided under restrictions below.


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.

This as an alpha version of Iron Spring PL/I. Version 0.5d is missing many features and parts of features of full PL/I. The section Restrictions lists many of the missing features.

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.
WATCOM is a trademark of Sybase, Inc. and its subsidiaries.


Restrictions

This is a list of major current restrictions of the compiler.

The compiler currently generates assembler output. Generation of .obj files is a priority goal for the near future.

The compiler doesn't yet support building Presentation Manager applications. Only text-mode applications are allowed. This is a priority goal.

PL/I procedures can call functions coded in other languages as long as they use the "system" calling convention. Programs coded in other languages can not yet call PL/I procedures. The "optlink" and other calling conventions are not supported.

Compiled PL/I code has not yet been tested as part of a DLL.

major features not implemented

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, and %NOPRINT. %PROCESS (*PROCESS) is implemented incompatibly from the IBM compilers. All other preprocessor statements will generate a diagnostic.
Special characters
The compiler currently uses the Unicode characters U+00AA for 'NOT' (¬), and U+007C for 'OR' (|). Other characters may be coded on the command-line to also represent these operators. (NOT is Alt-1-7-0 on the numeric keypad).
Tasking
TASK and EVENT data, the WAIT statement, and the tasking builtins PRIORITY, COMPLETION, and STATUS.
GENERIC attribute
The GENERIC attribute.
DEFAULT
The DEFAULT statement.
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.
Data-directed I/O is not currently supported.
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   COS LOG SINHEXP
ASIN COSD LOG2 SQRT
ATAN COSH LOG10TAN
ATAND   ERF SIN TAND
ATANH ERFC SIND TANH
Arithmetic builtins
The following arithmetic builtin functions are not implemented in the current version of the compiler:
ADD CONJG DIVIDE SUBTRACT MULTIPLY
ROUND TRUNC
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
Builtin functions will not return agregate results in the current version. This is similar to Subset G support for builtins.
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 16-bit Unicode character support. The features not supported include:
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.
DEFAULT
The DEFAULT statement is not implemented in the current version.
*PROCESS
The *PROCESS statement is used by this compiler to provide debug support. Parameters not recognized are ignored.

Other features
The compiler error message 995 ("Unimplemented feature xxx") and the run-time condition "UNIMPLEMENTED" are used to flag unimplemented features. Except for "premanent restrictions" noted above, these should be removed in future releases. Some less-used conversions may 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

Except as noted under Compiler Differences and Restrictions this compiler is compatible with The IBM "PL/I for MVS and VM Compiler 1.1". Complete HTML documentation will be available as part of a future release. In the meantime, documentation for the IBM compiler 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.

Special characters
Alternate characters can be substituted for the NOT (ª) and OR (|) operators. See Running the compiler for the procedure for specifying additional characters. String data can be delimited by either the single (') or double (") quote characters. The same character must be used to begin and and 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.
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.
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.
Additional builtins
The following additional builtin functions are supported:
ALLOCATEALLOCATE(n) allocates n bytes of storage and returns a pointer to the first byte.
BYTEBYTE returns a character string of length one. Byte(n) is equivalent to the following:
SUBSTR( COLLATE(), MOD(n,256)+1, 1 )
COLLATECOLLATE Returns a character string of length 256 containing all 256 possible character values.
COMPARECOMPARE(x,y,z) compares "z" bytes from locations pointed to by "x" and "y".
COPYCOPY(x,y) returns a string consisting of "y" concatenated copies of string "x".
PLIFILLPLIFILL moves requested number of copies of a single byte to a specified location with no conversion, padding, or truncation.
PLIFREEPLIFREE frees storage allocated by ALLOCATE
PLIMOVEPLIMOVE(x,y,z) moves "z" bytes to the location pointed to by "x" from the location pointed to by "y".
RANKRANK returns a FIXED BINARY(15) result. The argument for RANK is a character string of length one. RANK(c) is equivalent to the following:
INDEX( COLLATE(), c ) - 1
ATTENTION
The ATTENTION condition is always enabled. It is raised by pressing ^C while running a VIO application or otherwise sending XCPT_SIGNAL_INTR 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 signal interrupts are sent only to thread 1 (the major task). Due to OS/2 restrictions, a backtrace printed as a result of 'ON ATTENTION SNAP ...' may be incomplete.

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 EXTERNAL( 'environment_name' ) , where the character string 'environment_name' can contain any characters acceptable to the OS/2 linker. The declaring PL/I code recognizes only the declared name. External "environment_name"s beginning with the string "_pli" are reserved for use by the run-time library. If the 'environment name' is not specified, the default external name is an uppercase translation of the first label on the external procedure, or of the declared entry name. For example, x: y: PROCEDURE; will use "X" as the external name for the linker. DECLARE abc ENTRY; will use "ABC".

EXTERNAL data (not EXTERNAL ENTRY) is not shared between executable and DLL code, nor among procedures in different DLLs. For example, data declared DECLARE a EXTERNAL POINTER; will identify different "a"s in procedures linked into in the executable, in DLL "1", and DLL "2". Within the executable or any one of the DLLs all occurrences of that declaration will identify the same "a".

The OPTIONS keyword on an ENTRY or PROCEDURE statement or an ENTRY declaration provides information regarding the linkage convention to be used.

OPTIONS( LINKAGE(SYSTEM) ) indicates that the entry uses a C-type linkage convention, where arguments are passed by value without descriptors. This can be used to call OS/2 functions which use this convention, 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.

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

OPTIONS( ASM ) indicates that the called entry point is a non-PL/I entry, and saves an instruction on the call.

If OPTIONS is not specified, a standard PL/I calling convention is used where arguments are passed by reference and descriptors are passed for arguments other than computational element-variables.

An example of an entry declaration using these features and the equivalent C-language definition is:

 DECLARE Create_MUTEX ENTRY( PTR, PTR, FIXED BIN(31), FIXED BIN(31) )
                      RETURNS( FIXED BIN(31) )
                      OPTIONS( ASM BYVALUE LINKAGE(SYSTEM) )
                      EXTERNAL( 'DosCreateMutexSem' );

 ULONG DosCreateMutexSem (PCSZ pszName, PHMTX phmtx, ULONG ulAttr, BOOL32 fState);

Running the Compiler

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

The syntax of the PLIC command is:


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

        <output option> = -S | -C | -L
                          -S = generate assembler (symbolic) output.
                               This is the only output option currently supported.
                          -C = generate compiled (object) output.
                          -L = generated linked (EXE or DLL) output.

        <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[siaxg]
                            one or more of [siaxg] may be entered, in any order.
                            -ls = list source
                            -li = list insource
                            -la = list attributes
                            -lx = list cross-reference
                            -lg = list aggregates
                            None of these options are currently implemented, the source
                            and attribute listings are always generated.

        <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 is included for compatibility with mainframe compilers
                           which would use, for example, -m(2,72).  
                           There is no restriction on the length of an input line.

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

        <error 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> where <option> is a character string, with or without enclosing quotes.
                         Currently the only miscellaneous option is -dLIB to tell the compiler it
                         is compiling a standard run-time library procedure.

        <input files> and <output files> are absolute or relative path names.  Ony 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.
                         The input file must be plain-text, with lines delimited by either a linefeed
                         [PL/I ENV(LF)] or carriage-return/linefeed [PL/I ENV(CRLF)].  There is no maximum
                         length for the input line, however each token is limited to approximately
                         32000 characters.

Compiler output

Compiler output currently consists of the source and attribute listing, and an assembler file of the compiled program.

Source and attribute listing:
Compiling a program xxx.pli will create a combined source listing/data attributes file named xxx.lst. Future compiler versions will add additional listing options and allow more flexibility in what is produced. Here are a few lines from a listing: The letters 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 excess.

The line following line 342 above shows the format of error, warning, and information messages. 'D' is the source line number. 'E' is the message number and severity (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. In a future version all messages will appear at the end.

The listing is paginated with imbedded formfeed characters 'G', currently every fifty-six lines.

Following the source listing the attribute list (symbol table) is printed as shown below. A future release will optionally combine a cross-reference listing. Variables are listed in alphabetic order.


H                    I    J                                                     K
ADDR                 124  Builtin
BSW                  309  Entry Unaligned                                       < Code+'13C0'x >
BYTE                 332* Builtin
C                     77  Char(1) Unaligned                                     < DSA-'51'x(1) >
C4                   109  Char(4) Unaligned Based                               < +'00'x(4) >
C4                   327  Char(4) Unaligned Parameter                           < Loc @DSA+'08'x(4) >
CONDS                 97  (9) Char(6) Var Unaligned Static Init()               < Static+'12'x(8) >
DSA_BELOW_EBP         27  Unaligned Structure In(PLI_DSA)                       < +'00'x(32) >
DSA_CHC               33  Ptr Aligned In(PLI_DSA.DSA_BELOW_EBP)                 < +'08'x(4) >
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 '*'.

'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 label '_pli_code'. See 'BSW' above.
STATIC data
Static+'oooo'x(ll). 'oooo' is the offset from the label '_pli_data. 'll' is the (decimal) length of the data element. If this was an UNALIGNED BIT element, the length would be 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. See the file 'DSA.INC' distributed with the library. '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±'0000'(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.

Assembler output:
Compiling a program xxx.pli will create an assembler file xxx.asm in a format suitable for the IBM ALP assembler. Other assemblers will most likely not be able to assemble this file. A future version of the compiler will produce .obj, .exe, and .dll files. A few lines of assembler output are shown:


; Stmt 31, Line 128 (Assignment)
 .code
 mov byte ptr -77[ebp],29h ; 00000023(4)
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. Each line of code and some lines of data contain a comment at the end indicating the hex offset and length of this assembler statement. Offsets for EXTERNAL data always start at zero.
Object Program Structure
The generated program consists of a single code segment '_pli_code', a single static data segment '_pli_data', an unnamed stack segment, and zero or more external data 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 segment named MSGBLK:


MSGBLK segment dword common 'MSGBLK'
_MSGBLK EQU $
 org _MSGBLK+34h
MSGBLK ends
Here is the code for the initialized external segment SYSIN:

SYSIN segment dword common 'SYSIN'
_SYSIN EQU $
 dd 0 ; FFFFFFFF(4)
 dd 0 ; 00000003(4)
 dd _SYSIN+12
 dw 5 ; 0000000B(2)
 db 'SYSIN'
SYSIN ends
The linker combines all 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 52 or less
Intel x87 long floating-point
REAL8
FLOAT BIN, precision>52
Intel x87 extended floating-point
REAL10
FLOAT DEC, precision 5 or lessREAL4
FLOAT DEC, precision 14 or lessREAL8
FLOAT DEC, precision>14REAL10
CHARACTER(n)n bytes
BIT(n) ALIGNED(n+7)/8 bytes
BIT(n) UNALIGNEDn bits
PTR, OFFSETNEAR PTR

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

Work file:
The compiler creates a temporary work file named PLI-xxxxxxxx-yyyyyyyy-zzzzzzzz.tmp in the current working directory. Normally this file is deleted at the end of compliation. Errors in the alpha version of the compiler causing certain traps may prevent deletion of this file. If it not automatically removed it may be deleted manually.


Input and Output

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 OS/2 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.

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

RECORD and STREAM Files

INPUT, OUTPUT, and UPDATE

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.

Other Attributes

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 CRLF RECSIZE(120)) LINESIZE(120)
SYSPRINTENV(V CRLF RECSIZE(120)) LINESIZE(120) PAGESIZE(60)
If stdin and stdout are the current VIO window, these files default to ENV( BLKSIZE(0) ).

STREAM files default to ENV(V CRLF) unless other attributes are specified. All other ENV(V) files default to ENV(V VARLS). Specifying PAGESIZE(0) on the OPEN statement will suppress page breaks for PRINT files.

Input/Output Statements
OPEN and CLOSE apply to both STREAM and RECORD files. The GET and PUT statements operate on STREAM files. The READ, WRITE, REWRITE, and LOCATE statements operate on RECORD files. The assumption is made that the reader is familiar with, or has access to a reference for, the I/O statements of IBM PL/I for MVS and VM. Only the syntax accepted by Iron Spring PL/I is shown here, no explanation is provided.

OPEN statement.

         +----------------------- , -------------------------------------+
         v                                                               |
>>-OPEN--.---FILE(file_ref)-+------------------+----+---------------+----+---- ; ----><
                            |                  |    |               |
                            +-|stream-options|-+    +-TITLE(string)-+  
                            |                  |
                            +-|record-options|-+


|stream-options| 

              +-INPUT ---------------------------+
              |                                  |   
|----STREAM---+----------------------------------+-+-------------+-----|
              |                                  | |             |                  
              +OUTPUT ---+-----------------------+ +-LINESIZE(m)-+                                   
                         |                       |                           
                         +-PRINT-+-------------+-+                           
                                 |             |                  
                                 +-PAGESIZE(n)-+                  

|record-options|

              +-INPUT -+
              |        |
|---RECORD----+--------+-+------------+-+-------+------| 
              |        | |            | |       |                    
              +-OUTPUT-+ +-BUFFERED---+ +-KEYED-+   
              |        | |            |                                      
              +-UPDATE-+ +-UNBUFFERED-+                                      
                

TITLE
The TITLE(string) option provides the OS/2 "filespec" of the file to be read or written. "String" is any valid character string expression. If the TITLE is omitted, the file name used by OS/2 will be the declared PL/I filename in uppercase, except for SYSIN and SYSPRINT which default to stdin and stdout. The TITLE may be a full filespec [TITLE('C:/test.dat')], an OS/2 device name [TITLE('LPT1:')], or a relative filespec. Unlike IBM OS/2 PL/I, file attributes may not be specified in the title string.

CLOSE statement.

          +----- , ---------+
          v                 |
>>-CLOSE--.--FILE(file_ref)-+-- ; --><

STREAM Input/Output

GET statement.

>>-GET-FILE(file_ref)-+-----------------+-+----------------------+- ; --><
                      |                 | |                      |
                      +-SKIP----------+-+ +-|data_specification|-+
                             |        |
                             +-(expr)-+ 
PUT statement.

>>-PUT-FILE(file_ref)-+---------------------+-+----------------------+- ; --><
                      |                     | |                      |
                      +-PAGE-+------------+-+ +-|data_specification|-+
                      |      |            | |
                      |      +-LINE(expr)-+ |
                      |                     |
                      +-SKIP-+--------+-----+
                      |      |        |     |
                      |      +-(expr)-+     |
                      |                     |
                      +-LINE(expr)----------+

Data Specification


|--+------+---( |data-list| )---------------------+----|
   |      |                                       |           
   +-LIST-+                                       |
   |                                              |
   +-DATA---+-----------------+-------------------+
   |        |                 |                   |
   |        +-( |data-list| )-+                   |
   |                                              |
   |        +-----------------------------------+ | 
   |        v                                   | |
   +-EDIT---.-( |data-list| )-( |format-list| }-+-+  

SKIP[(expr)]
The SKIP option causes a new line to be started in the data stream prior to transmitting any data from the current or subsequent GET or PUT statement. The (expr) is converted to an integer n. On output, n newlines (linefeed or carriage-return/linefeed) are inserted. On input the remainder of the current line and the n-1 following lines are skipped. If (expr) is omitted or not greater than zero, 1 is used for the value of n. For PRINT files, the ENDPAGE condition may be raised if PAGESIZE is exceeded.

PAGE
The PAGE option is valid only for PRINT files. It causes a page eject (ASCII '0C'x) to be inserted in the output stream prior to transmitting any data from the current or subsequent PUT statement. If both PAGE and LINE are present, the PAGE option is applied first.

LINE(expr)
The LINE option is valid only for PRINT files. It causes a new line to be started in the output stream prior to transmitting any data from the current or subsequent PUT statement. The (expr) is converted to an integer n. If n or more lines have been written on the current page, or if n exceeds PAGESIZE, a new page is started. newlines are inserted in the output strean to position the next data written at line n. If (expr) is less than or equal to zero, 1 is used for the value of n.


RECORD Input/Output

READ statement.

>>-READ-FILE(file_ref)-+-----------------------------------+----------- ; --><
                       |                                   |          
                       +-INTO(ref)-+-------------+---------+
                       |           |             |         |
                       |           +-KEY(expr)---+         |
                       |           |             |         |
                       |           +-KEYTO(ref)--+         |
                       |                                   | 
                       +-SET(pointer-ref)-+-------------+--+
                       |                  |             |  |
                       |                  +-KEY(expr)---+  |
                       |                  |             |  |
                       |                  +-KEYTO(ref)--+  | 
                       |                                   |
                       +-IGNORE(expr)----------------------+

WRITE statement.

>>-WRITE-FILE(file_ref)--FROM(ref)--+-------------------------+----------- ; --><
                                    |                         |
                                    +-KEYFROM(expr)-----------+
                                    |                         |
                                    +-KEYTO(ref)--------------+

LOCATE statement.

>>-LOCATE--based-variable--FILE(file-ref)--+--------------------------------------+---- ; --><
                                           |                  |  |                |
                                           +-SET(pointer-ref)-+  +-KEYFROM(expr)--+             

REWRITE statement.

>>-REWRITE-FILE(file_ref)--+-----------+--+-----------+----------- ; --><
                           |           |  |           |
                           +-FROM(ref)-+  +-KEY(expr)-+


User-callable PL/I Library Procedures

Most of the procedures in the PL/I runtime library (prf.lib) are for use by the compiler and are not user-callable. The following, however, may be useful: osdelete deletes a file by name.
DECLARE osdelete ENTRY( CHAR(*) VAR )
                          RETURNS( FIXED BIN(31) )
                          EXT( '_pli_OSDelete' );
DECLARE rc FIXED BIN(31);
RC = osdelete( filename );
filename
a character string variable or constant containing the name of the file to be deleted.
rc
a FIXED BIN(31) data element which will contain the OS/2 error code from DosDelete.
0 indicates no error.
2 indicates that the file was not found.
for other errors see the OS/2 Operating System Control Program Guide and Reference.

tempnam generates a unique name for a temporary file.

DECLARE tempnam ENTRY( CHAR(*) VAR, CHAR(*) VAR, CHAR(*) VAR )
                         RETURNS( CHAR(260) VARYING)
                         EXT( '_pli_Tempnam' );
DECLARE temp_filename CHAR(260) VARYING;
temp_filename = tempnam( sDir, sPfx, sSfx );
sDir
a VARYING CHARACTER string identifying the directory in which the file is to be located. If this is the null string the file will be located in the current working directory.
sPfx, sSfx
VARYING CHARACTER strings containing the prefix (sPfx) and the suffix (sSfx) to be attached to the generated name. Either or both may be the null string. The generated name will be:
   'sPfxpppppppp-tttttttt-uuuuuuuusSfx'
where 'pppppppp' is the hex value of the current process id (pid), 'tttttttt' is the hex value of the current thread id (tid), and 'uuuuuuuu' is a unique number within this process. If another file with this name already exists, the unique number is incremented until the generated name does not confilct with an existing file.
temp_filename
In the example this represents a VARYING CHARACTER string which will contain the generated unique name.


Debugging PL/I programs

The WATCOM® debugger may be used to debug PL/I programs.
Source-level debugging is not yet available, but since the compiler can generate assembly-language output, debugging at the assembly level is straightforward.

The following steps are not required, but will simplify debugging.

To get the debugger to stop at the beginning of the PL/I program, make the following modifications to "setup.dbg", normally found in the <WATCOM>\binw directory.
elseif _dbg@dbg$os == 12 && ?@main {Following this
go/until/noflip @main
}
elseif ?@@_PLI_MAIN { Insert these three lines
go/until/noflip @@_PLI_MAIN
}
After this, you will also need to link your program with a module definition file to export the symbol "_PLI_Main" so that it is visible to the debugger. The "samples" directory contains an example .def file and linker command to do this.

The IBM "ASDT" debugger is also usable.

Sometimes it may be desirable to compile-in a breakpoint to be activated when a specific location is reached or condition occurs. The following statement inserted in your source will activate a breakpoint when it is reached when running under control of a debugger:

 *PROCESS DBG(INT3); 
If the resulting executable is not run under a debugger, the interrupt will be ignored. Nevertheless, INT3 traps should not be left in a production program.

SNAP traceback The PL/I statement "ON CONDITION(xxx) SNAP..." will generate a traceback to stderr when the specified condition is raised. Beginning with the procedure generating the traceback (_pli_Trace) and working backwards, the trace lists the address of the active entry point of the procedure, the address of the statement in the calling procedure that called that entry, and the name of the entry point if available.

PLIDUMP output The PL/I statement "CALL PLIDUMP( "<options>", "<title>" ); will generate debugging output to stderr when executed. "title" is a character string used as the title of the dump. "options" provide one or more dump options, 'S' = terminate, 'C'=continue, 'T'=print traceback, 'B' = dump automatic storage. Options may be combined and may appear in any order, for example "TCB" means print trace, continue after snap, and dump all automatic storage. Storage is dumped in three sections: Temporaries (argument lists and storage used during expression evaluation), Data (non-temporary user data in the stack frame), and DSA (system data in stack frame). The layout of the DSA is given in lib\include\dsa.inc. This is subject to change in future releases.


version 0.5d, 30 Jan, 2008
http://www.iron-spring.com