Re: Class Notes for a PL/I Course.

"Giuseppe Vitillaro giuseppe-yuD/ahkh7LvrZ44/[email protected] [H390-MVS]" <[email protected]> Thu, 3 Oct 2019 19:46:07 +0200 (CEST)
Newsgroups gmane.comp.emulators.hercules390.mvs
Message-ID <[email protected]>
On Thu, 3 Oct 2019, Bernd Oppolzer berndoppolzer-/[email protected] [H390-MVS] wrote:

> Am 03.10.2019 um 12:42 schrieb Giuseppe Vitillaro giuseppe-yuD/ahkh7LvrZ44/[email protected] 
> [H390-MVS]:
>>
>>  On Thu, 3 Oct 2019, Bernd Oppolzer berndoppolzer-/[email protected] [H390-MVS]
>>  wrote:
>> > 
>> >  Kind regards
>> > 
>>
>>  I guess declaring this way a variable in the main program:
>>
>>  DECLARE ZAZA CHARACTER(10) STATIC EXTERNAL INITIAL ( 'GIGIO' );
>>
>>  and using it in an external procedure in this way:
>>
>>  ZZ: PROCEDURE;
>>  DECLARE ZAZA CHARACTER(10) EXTERNAL;
>>  PUT FILE(SYSPRINT) SKIP EDIT ('ZAZA=', ZAZA ) (2(A));
>>  RETURN;
>>  END ZZ;
>>
>>  it is the best which can be done in PL/I(F) to get something
>>  which looks like a global C variable?
>> 
>
> The short answer is: yes, this is the best.
>
> The long answer is: this does not really help you, if you want to
> do some sort of dynamic linking, because you need the linker to
> resolve those external references.
>
> BTW: STATIC in the main program is not needed or even forbidded,
> because EXTERNAL variables are STATIC by default.
>
>
>>
>>  Another thing I'm looking for is something like
>>  the C typedef syntax.
>>
>>  The "LIKE" syntax looks to do something similar,
>>  but for an already "allocated" variable, if
>>  the variable is not actually a pointer.
>>
>>  Anything better can be done with PL/I (F)?
>>
>>  Peppe.
>> 
>> 
>
> This is somehow related to the question above.
>
> If you want parameters to be passed between external functions,
> they may be structures - in the general case.
>
> The C way to do this would be
>
> - have a typedef of the struct in an include file
> - then use this include file on both sides
> - pass pointers of this struct between caller and called function
>
> This way the called function can read and write values from and
> to the parameter structure.
>
> In traditional PL/1, there is no typedef. There is simply no concept
> of type. See the funny assignment of structures (called aggregates),
> where it is only needed that the layout of the structures are
> congruent in a certain way, but the types of the components may differ.
>
> Or the second variant: BY NAME.
>
> This is all very different from what other languages do.
>
> So what is done "in real word" is often the following:
>
> we use %INCLUDE files, too. This works in PL/1, even if you don't
> use the preprocessor (which is another very interesting topic;
> the PL/1 preprocessor is much more powerful than the C macro processor,
> for example).
>
> in these %INCLUDE files, we define PL/1 structures (or aggregates)
> without the structure header, that is, without the DCL and the level 1
> definition. Only level 3 or 5 ...
>
> these structure bodies are used at both sides (caller and callee).
>
> But the caller declares:
>
> DCL 1 PARM_STRUCT AUTO,
> %INCLUDE (PARMINC);;
>
> and the callee declares:
>
> DCL 1 PARM_STRUCT BASED (PARM_PTR),
> %INCLUDE (PARMINC);;
>
> and the call looks like this:
>
> CALL CALLEE (ADDR (PARM_STRUCT));
>
> that is, only parameters are passed.
>
> It is possible to pass structures, but then you will get real trouble
> with structure aggregates.
>
> Passing pointers to structures will work well, when calling other
> languages, too. There will be some issues with component alignment
> (the PL/1 methods differ from that of other languages), but that
> can be solved.
>
> This is not typedef, but it works a little bit like typedef :-)
> == COBOL copybooks :-)
>
> HTH,
> kind regards
>
> Bernd
>
>
>
>

Got it, Benrd, thanks again.

Yep, this looks like near what we do in C
with a typedef to a structure and using a
pointer is a nice trick ;-)

In the meanwhile I did some progress with
my VS2FB/FB2VS exercise.

The ability of PL/I(F) to manage at the
same time a FILE STREAM and a FILE RECORD
is a wonderful feature, which makes
storing a VS dataset into an FB(80)
dataset as simple as, I guess, it can
be under MVS.

What I've now, basically, are two I/O loops,
one for storing a VS FILE RECORD into an
FB FILE STREAM:

DECLARE OUTF FILE STREAM OUTPUT;
DECLARE INPF FILE RECORD INPUT ENV(VS);
....
LP = ADDR(L);
DO WHILE(TRUE);
   READ FILE(INPF) INTO(BUF);
   L = LENGTH(BUF);
   PUT FILE(OUTF) EDIT(SP,BUF) (A(2),A);
END;

and the other one for restoring the FB
FILE STREAM back into a VS FILE RECORD:

DECLARE INPF FILE STREAM INPUT;
DECLARE OUTF FILE RECORD OUTPUT ENV(VS);
,,,
LP = ADDR(L);
DO WHILE(TRUE);
   GET FILE(INPF) EDIT ( SP ) ( A(2) );
   IF ( L = 0 ) THEN GOTO EOF;
   GET FILE(INPF) EDIT ( BUF ) ( A(L) );
   WRITE FILE(OUTF) FROM ( BUF );
END;

where the last FB record has a plain
zero length marking the logical EOF
of the VS dataset.

The PL/I(F) limitation to a "CHAR(32767) VARYING"
should not be a problem here, I hope, because the max
VS LRECL I may expect is actually 32760, isn't it?

The only "glitch" in this code I can foresee, which
actually works over an IEBCOPY output
VS dataset, is in the conversion between
the "FIXED BIN(15)" variable L and its
corresponding "CHARACTER(2)" SP binary
representation.

What I'm doing now, which I guess is
really my C habit, is using the LP pointer
in this way:

DECLARE L FIXED BIN(15);
DECLARE LP POINTER;
DECLARE SP CHARACTER(2) BASED(LP);

which makes SP overloading the same memory
area of the L record lenght variable once
LP is initialized to the ADDRess of L.

Is there any "clean way" to make such
a conversion with PL/I (F), at runtime?

Beside that, now, I can easily store
my IEBCOPY datasets into FB datasets, possibly members
of a PDS FB(80), and trasfer them to my Linux filesystems,
a simple way to store backups of my PDS
under MVS and Linux, without using XFER370
and its bad habits, which I really hate ;-)

By the way, it is fast as an hell, with a large
enough FB(80) BLKSIZE, almost as XFER370.

Any way to make it faster with PL/I(F)?

Just for reference, if anyone would even wish
to a have a look to my poor PL/I coding the
JCL test streams are stored at these URLs:

http://www.vitillaro.org/curr/VS2FB
http://www.vitillaro.org/curr/FB2VS

Peppe.