Re: Class Notes for a PL/I Course.
"Bernd Oppolzer berndoppolzer-/[email protected] [H390-MVS]" <[email protected]> Fri, 4 Oct 2019 00:23:30 +0200
| Newsgroups | gmane.comp.emulators.hercules390.mvs |
|---|---|
| Message-ID | <[email protected]> |
Am 03.10.2019 um 19:46 schrieb Giuseppe Vitillaro giuseppe-yuD/ahkh7LvrZ44/[email protected] [H390-MVS]: > > > 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? > No, no clean way IMO. You are reading a CHAR(2) field using stream I/O, which is in fact a BIN FIXED (15) length field, and you need to use it as a BIN FIXED (15) field. This is not really a conversion; the overlay that you are using is IMO the right thing to do. Using newer PL/1 compilers, I would write something like DECLARE L FIXED BIN(15); DECLARE SP CHARACTER(2) BASED(ADDR(L)); but PL/1 (F) does not support this. > 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)? > No, I don't think so. It took me some time to understand that you are using stream I/O and the GET/EDIT and PUT/EDIT instructions to write buffers to the FB 80 dataset that are far larger than 80 bytes, and that the GET and PUT statement will in fact do the folding and unfolding of the large buffers to the 80 byte records for you. This is great ... this solution would not have come to my mind. In most companies that I worked, stream I/O was always forbidden for production programs; it was only allowed for test output. Even listings had to be produced using record output in most companies (using RECFM FBM and machine control characters). So I would come up with a solution using record I/O for the FB 80 file and probably doing the splitting of the larger buffer into 80 byte pieces (and joining at the other side) using handwritten PL/1 logic. Don't know, if this would make a difference in performance. Maybe. It would be interesting to see, where the length fields are in your FB 80 dataset. I guess, they can appear at any column, depending on the length of the original VS records. If I did the splitting myself, I would probably use a file format, where the length fields are always at position 1 and 2 of the FB80 records. This of course means - that the VS buffer must be split in pieces of 78 bytes length - that you can use the length fields of the records after the first one for some additional control (e.g. repeating the total length of the VS record, or the remaining length, or marking the end of the total record) - that you have some unused space at the end of the record in the general case In this case, you don't need no special EOF record using a zero length field. > > 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. > > > Very nics, congrats :-) I am coding in PL/1 almost every day (for money) ... :-) there are only two minor remarks, both are a matter of personal style: a) DECLARE is abbreviated DCL most of the time b) ENDFILE processing is normally done using a BIT switch, avoiding the GOTO. Example: DCL SW_EOF BIT(1) INIT ('0'B); ON ENDFILE(INPF)? SW_EOF = '1'B; .... DO WHILE (^ SW_EOF); ?? READ FILE(INPF) INTO (BUF); ?? ... END; /* processing continues here at EOF */ HTH, kind regards Bernd Stuttgart (Germany)