TIP: Click on subject to list as thread! ANSI
echo: os2prog
to: Ivan Todoroski
from: David Noon
date: 1999-01-21 21:27:04
subject: Pl/I

In a message dated 01-19-99, Ivan Todoroski said to David Noon about "Pl/I"

Hi Ivan,

IT>  Lets see what can I make out of this...

 DN> =========================== XRANGE.PLI==============================
 DN>  /* Same as REXX's XRANGE() built-in function */
 DN>  XRANGE:
 DN>  PROC(lb,ub) RETURNS(CHAR(256) VAR) OPTIONS(REENTRANT REORDER);
IT>                                                 ^^^^^^^^^ Huh!?

 DN>      DCL  (lb,ub)             CHAR(1) BYVALUE;
IT>                                           ^^^^^^^!!!

 DN>      DCL  curr_byte           BIN FIXED(8,0) UNSIGNED,
IT>                                   ^^^^^^^^^^^^^^ What??!?

In PL/I you specify the precision you require for your computational
variables. In this case, a fixed point number stored in binary with a
minimum total width of 8 bits and 0 bits after the binary point. No sign bit
is to be added to it, either.

This ensures that the arithmetic limits of a variable are at least the
specified amount on any platform. Should the variable be too large for a
given platform the compiler flags it long before you execute the code. This
eliminates the possibility of a "long int" being not long enough on some
hardware.

IT>  OK, the PROC() declaration looks standard enough, except for those
IT>  OPTIONS() there... does that REENTRANT mean what I think it means?

Yes, it asks the compiler to ensure the code can be executed by 2 or more
threads concurrently.

IT>   Are you saying that you can actually tell the compiler which
IT>   functions are thread-safe and which aren't? If you don't specify
IT>   REENTRANT, will the compiler take special measures to ensure that no
IT>   two threads execute inside that function at the same time?

Yes. I believe it will also check that you do not modify anything declared
in the STATIC storage class, either. However, I normally use the NONASGN
attribute (non-assignable) with STATIC.

Under OS/2, you need the option LIBS(MULTI) so that the thread-safe RTL is
linked in.

IT>   What about that REORDER?

Allows the compiler to reorder the sequence of execution for optimal flow of
control. [Pipeline!!]

IT>   It's obvious that DCL (probably short for DECLARE?) is for defining
IT>   variables etc., much like VAR in Pascal. The first declares lb and ub
IT>   as CHAR's (or is that one-element arrays of CHAR?),

CHAR variables are true strings. In this case, they are of length 1.

IT>   and what caught
IT>   my attention was that BYVALUE keyword! Do you mean you can actually
IT>   specify the way the parameter is passed for each parameter?!

Yes. Each parameter can be either BYADDR or BYVALUE. You can also put one of
these into the OPTIONS() list as the default for the given PROC.

IT>   Now
IT>   that's what I call total control :) Most languages tend to abstract
IT>   the hardware away from your hands, but this one accepts the reality!

Well, the Watcom C/C++ compiler gives you even more control over calling
mechanisms with its #pragma aux, but that is highly non-portable.

IT>  And the more I grind thruogh this code, the stranger it gets! What's
IT>  that BIN FIXED(8,0) stuff? Are you defining a single byte integer
IT>  there? Does this mean that you can define 24-bit integers, or maybe
IT>  even 19-bit ones? This is insane... :)

Yes. The precision of an integer can be from 1 bit up to the implementation
limit. You can also choose between packed BCD and binary for computational
representation.

 DN>           result              CHAR(256) VAR INIT(''),

IT>            OK, this one is pretty much self-explanatory...

A varying length character string that can be between 0 and 256 bytes long,
initialised to a null string.

 DN>           (BYTE,RANK)         BUILTIN;

IT>           ... but this one isn't!

Those are built-in casting functions. RANK() casts from CHAR(1) to an
integer value and BYTE() casts an integer to CHAR(1).

 DN>      /* Loop through from lower byte to upper byte */
 DN>      DO curr_byte = RANK(lb) TO RANK(ub);
 DN>           result ||= BYTE(curr_byte);
 DN>      END;

 DN>      /* Job done */
 DN>      RETURN(result);
 DN>  END XRANGE;

IT>  The rest is pretty much clear, except those RANK() and BYTE()
IT>  functions you used there...

Well, they are simple casts that really produce no object code.

PL/I supplies conversions between character and computational values. These
follow the "common sense" approach to semantics. For example,

           DCL      i      BIN FIXED(31,0), /* signed DWORD integer */
                    s      CHAR(12);        /* string of length 12 */

           i = 125;   /* No problem */
           s = i;     /* s becomes '         125' */

So, the second assignment includes converting the number to a displayable
format, not taking the byte value. However, if it had been:

           s = BYTE(i);

the first byte of s would have been ASCII 125 (on a PC) and the remaining 11
bytes filled with blanks. As a result, the cast is necessary in order to
force the program to produce potentially unprintable characters.

IT>In my opinion, a language in which you can grasp the meaning of most of
IT>the statements without ever having seen it before must be a
IT>GoodThing(tm).

IT>Especially when those statements put such power in your hands...

IT> This is one of the reasons I like REXX so much, and don't like Perl at
IT> all...

As I have said in this echo before, I enjoy writing Perl for others. It's a
form of sadism, I suppose.

Regards

Dave

___
 * MR/2 2.25 #353 * What?!?  DOSSHELL *isn't* supposed to be a joke?

--- Maximus/2 3.01
* Origin: DoNoR/2,Woking UK (44-1483-717904) (2:440/4)
SEEN-BY: 396/1 632/0 371 633/260 262 267 270 371 635/444 506 728 639/252
SEEN-BY: 670/218
@PATH: 440/4 255/1 251/25 396/1 633/260 635/506 728 633/267

SOURCE: echomail via fidonet.ozzmosis.com

Email questions or comments to sysop@ipingthereforeiam.com
All parts of this website painstakingly hand-crafted in the U.S.A.!
IPTIA BBS/MUD/Terminal/Game Server List, © 2025 IPTIA Consulting™.