![]() |
Iron Spring PL/I compilerProgramming GuideAlpha 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. |
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.
Compiled PL/I code has not yet been tested as part of a DLL.
major features not implemented
| ACOS | COS | LOG | SINH | EXP |
| ASIN | COSD | LOG2 | SQRT | |
| ATAN | COSH | LOG10 | TAN | |
| ATAND | ERF | SIN | TAND | |
| ATANH | ERFC | SIND | TANH |
| ADD | CONJG | DIVIDE | SUBTRACT | MULTIPLY |
| ROUND | TRUNC |
| Compiler Limits | |
|---|---|
| Maximum number of dimensions | 15 |
| Maximum number of levels in a structure | 15 |
| Maximum level number in a structure | 255 |
| 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 files | 4 |
| Maximum precision of FIXED DECIMAL data | 18 |
| Default precision of FIXED DECIMAL data | 5 |
| Maximum precision of FIXED BINARY data | 31 |
| Default precision of FIXED BINARY data | 15 |
| Maximum precision of FLOAT DECIMAL data | 20 |
| Default precision of FLOAT DECIMAL data | 6 |
| Maximum precision of FLOAT BINARY data | 64 |
| Default precision of FLOAT BINARY data | 52 |
| Minimum/maximum scale factor | -128 / 128 |
| Maximum length of an internal or external label | 31 |
See Restrictions for information on major language features that are not currently implemented.
| ALLOCATE | ALLOCATE(n) allocates n bytes of storage and returns a pointer to the first byte. |
| BYTE | BYTE returns a character string of length one. Byte(n) is equivalent to the
following: SUBSTR( COLLATE(), MOD(n,256)+1, 1 ) |
| COLLATE | COLLATE Returns a character string of length 256 containing all 256 possible character values. |
| COMPARE | COMPARE(x,y,z) compares "z" bytes from locations pointed to by "x" and "y". |
| COPY | COPY(x,y) returns a string consisting of "y" concatenated copies of string "x". |
| PLIFILL | PLIFILL moves requested number of copies of a single byte to a specified location with no conversion, padding, or truncation. |
| PLIFREE | PLIFREE frees storage allocated by ALLOCATE |
| PLIMOVE | PLIMOVE(x,y,z) moves "z" bytes to the location pointed to by "x" from the location pointed to by "y". |
| RANK | RANK 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 |
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);
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.
A B C
340
341 %include DSA;
342
D E F
341 (INF104)Processing include file DSA.
G
1 /********************************************************************/
2 /* */
The listing is paginated with imbedded formfeed characters 'G', currently every fifty-six lines.
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 '*'.
'K shows the address of the item in '<' '>'. The addresses are displayed as follows:
; 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.
MSGBLK segment dword common 'MSGBLK' _MSGBLK EQU $ org _MSGBLK+34h MSGBLK endsHere 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 endsThe 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.
| Internal Data Representations | |
|---|---|
| FIXED BIN, precision 7 or less | BYTE |
| FIXED BIN, precision 15 or less | WORD |
| FIXED BIN, precision 31 or less | DWORD |
| 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 less | REAL4 |
| FLOAT DEC, precision 14 or less | REAL8 |
| FLOAT DEC, precision>14 | REAL10 |
| CHARACTER(n) | n bytes |
| BIT(n) ALIGNED | (n+7)/8 bytes |
| BIT(n) UNALIGNED | n bits |
| PTR, OFFSET | NEAR 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.
Iron Spring PL/I can read and write:
>>-DECLARE-name-+------+-+--------+-+--------+-+----------------------------------+-+---------------+-><
| | | | | | | | | |
+-FILE-+ +-RECORD-+ +-INPUT -+ +-ENVIRONMENT(environment options)-+ +-other attributes-+
| | | |
+-STREAM-+ +-OUTPUT-+
| |
+-UPDATE-+
| SYSIN | ENV(V CRLF RECSIZE(120)) LINESIZE(120) |
| SYSPRINT | ENV(V CRLF RECSIZE(120)) LINESIZE(120) PAGESIZE(60) |
| If stdin and stdout are the current VIO window, these files default to ENV( BLKSIZE(0) ). | |
+----------------------- , -------------------------------------+
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-+
+----- , ---------+
v |
>>-CLOSE--.--FILE(file_ref)-+-- ; --><
>>-GET-FILE(file_ref)-+-----------------+-+----------------------+- ; --><
| | | |
+-SKIP----------+-+ +-|data_specification|-+
| |
+-(expr)-+
>>-PUT-FILE(file_ref)-+---------------------+-+----------------------+- ; --><
| | | |
+-PAGE-+------------+-+ +-|data_specification|-+
| | | |
| +-LINE(expr)-+ |
| |
+-SKIP-+--------+-----+
| | | |
| +-(expr)-+ |
| |
+-LINE(expr)----------+
|--+------+---( |data-list| )---------------------+----| | | | +-LIST-+ | | | +-DATA---+-----------------+-------------------+ | | | | | +-( |data-list| )-+ | | | | +-----------------------------------+ | | v | | +-EDIT---.-( |data-list| )-( |format-list| }-+-+
>>-READ-FILE(file_ref)-+-----------------------------------+----------- ; --><
| |
+-INTO(ref)-+-------------+---------+
| | | |
| +-KEY(expr)---+ |
| | | |
| +-KEYTO(ref)--+ |
| |
+-SET(pointer-ref)-+-------------+--+
| | | |
| +-KEY(expr)---+ |
| | | |
| +-KEYTO(ref)--+ |
| |
+-IGNORE(expr)----------------------+
>>-WRITE-FILE(file_ref)--FROM(ref)--+-------------------------+----------- ; --><
| |
+-KEYFROM(expr)-----------+
| |
+-KEYTO(ref)--------------+
>>-LOCATE--based-variable--FILE(file-ref)--+--------------------------------------+---- ; --><
| | | |
+-SET(pointer-ref)-+ +-KEYFROM(expr)--+
>>-REWRITE-FILE(file_ref)--+-----------+--+-----------+----------- ; --><
| | | |
+-FROM(ref)-+ +-KEY(expr)-+
DECLARE osdelete ENTRY( CHAR(*) VAR )
RETURNS( FIXED BIN(31) )
EXT( '_pli_OSDelete' );
DECLARE rc FIXED BIN(31);
RC = osdelete( filename );
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 );
'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.
The following steps are not required, but will simplify debugging.
| elseif _dbg@dbg$os == 12 && ?@main { | Following this |
| go/until/noflip @main | |
| } | |
| elseif ?@@_PLI_MAIN { | Insert these three lines |
| go/until/noflip @@_PLI_MAIN | |
| } |
The IBM "ASDT" debugger is also usable.
*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.