IBM Mainframe Forum Index
 
Log In
 
IBM Mainframe Forum Index Mainframe: Search IBM Mainframe Forum: FAQ Register
 

PLI - printing from multiple programs


IBM Mainframe Forums -> PL/I & Assembler
Post new topic   Reply to topic
View previous topic :: View next topic  
Author Message
Pedro

Global Moderator


Joined: 01 Sep 2006
Posts: 2547
Location: Silicon Valley

PostPosted: Fri Sep 08, 2017 6:36 am
Reply with quote

I have several large programs that print to the same file.

Each program has:
Code:
Dcl mymsgs FILE Stream Output Print;


I was originally doing this:
Code:
PUT FILE(mymsgs) LIST('text1');
call prog2

Put FILE(mymsgs) LIST('text3');

where external prog2 did:
PUT FILE(mymsgs) LIST('text2');

but the result was out of order:
text2
text1
text3

So I added FLUSH statements:
Code:
PUT FILE(mymsgs) LIST('text1');
FLUSH FILE(mymsgs) ;
call prog2

FLUSH FILE(mymsgs) ;
Put FILE(mymsgs)  LIST('text3');

where external prog2 did:
PUT FILE(mymsgs) LIST('text2');

Great! now I get the text in the correct order.

But I did all of my testing to:
Code:
//MYMSGS  DD SYSOUT=*


Now, when I use a data set instead of SYSOUT=*, I am only seeing some of the text from prog2.

Code:
//MYMSGS DD  DISP=(NEW,CATLG),DSN=MY.OUTPUT,
//           SPACE=(CYL,(2,1))


Does anybody have any insight as to why I do not get all of the output?
Back to top
View user's profile Send private message
steve-myers

Active Member


Joined: 30 Nov 2013
Posts: 917
Location: The Universe

PostPosted: Fri Sep 08, 2017 7:02 am
Reply with quote

Yes.

When you send a message to a JES2 data set, the message is added to any messages already in the data set.

In your arrangement, the first program opened, then closed the data set, and then the second program did the same. When you have a real data set (as opposed to a JES data set, which is a little different) the second use of the data set restarts output to the data set. In other words, the data already in the data set is trashed, as you observed.

One possible fix, provided MY.OUTPUT does not actually exist, is to specify DISP=(MOD.CATLG) rather than DISP=(NEW,CATLG)

For what it's worth, I suspect JES2 would tell you it's working as designed. Whether the design is appropriate is another question, and probably goes back to the design history of HASP and was forwarded to JES2. When HASP developed the idea of data sets, when the JCL specified SYSOUT=X, the DD statement was allocated to a pseudo printer, and OPEN/CLOSE boundaries were effectively ignored and HASP treated the device like a real printer. Come JES2, they decided it should behave the same way.
Back to top
View user's profile Send private message
prino

Senior Member


Joined: 07 Feb 2009
Posts: 1306
Location: Vilnius, Lithuania

PostPosted: Fri Sep 08, 2017 12:59 pm
Reply with quote

Don't have time to test this now, in a few minute we're off to the Netherlands for a birthday, but I find it very strange that printing to a file would not gave the same results as printing to sysout. and in the 32+ years I've used PL/I, I've never had to resort to using FLUSH, even for programs with dozens of external subroutines.

What you might try is opening myfile explicitly in your main program. Files are by default external, so if the definitions in each module are the same, there should be no problems.
Back to top
View user's profile Send private message
steve-myers

Active Member


Joined: 30 Nov 2013
Posts: 917
Location: The Universe

PostPosted: Fri Sep 08, 2017 5:42 pm
Reply with quote

Enterprise PL/I Language Reference wrote:
The FLUSH statement flushes the buffers associated with an open output file (or with all open output files if * is specified). This normally happens when the file is closed or the program ends, but the FLUSH statement ensures the buffers are flushed before any other processing occurs.

The manual seems to me to be saying the FLUSH statement accomplishes this task by immediately closing a PL/I file.

Now I mostly work in Assembler, and I've noticed when using QSAM "locate mode" PUT macros that a line in progress does not actually get written until the related DCB is closed or the next PUT macro is issued. This makes sense: "locate mode" PUT returns the address of an I/O area to fill and the only way to be certain this is complete is to issue a new PUT or to close the DCB. "Move mode" PUTs usually seem to be more immediate. Even so, if it's filling an I/O buffer the buffer won't get written until it's filled or the related DCB is closed.
Back to top
View user's profile Send private message
Pedro

Global Moderator


Joined: 01 Sep 2006
Posts: 2547
Location: Silicon Valley

PostPosted: Fri Sep 08, 2017 11:31 pm
Reply with quote

More investigation is needed. The default for OPEN FILE is BUFFERED (vs. UNBUFFERED). I will try using the UNBUFFERED.

Also, in the declare, I used STREAM instead of RECORD. Is there a recommendation?
Back to top
View user's profile Send private message
prino

Senior Member


Joined: 07 Feb 2009
Posts: 1306
Location: Vilnius, Lithuania

PostPosted: Mon Sep 11, 2017 12:53 am
Reply with quote

I've done a quick check, and all is well:

Code:
//PRINOCOM JOB (PRINO),
//             'RAHP COMP/LINK',
//             CLASS=A,
//             MSGCLASS=H,
//             MSGLEVEL=(1,1),
//             NOTIFY=&SYSUID
//*********************************************************************
//IEFBR14 EXEC PGM=IEFBR14
//SYSLIN    DD DSN=&&OBJECT,
//             DISP=(,PASS),
//             UNIT=SYSDA,
//             SPACE=(CYL,(2,2,1)),
//             DCB=(RECFM=FB,LRECL=80,BLKSIZE=27920)
//*********************************************************************
//IBMZPLI EXEC PGM=IBMZPLI,
//             REGION=0M,
//             PARM=('+DD:PLISTD +DD:PLIUSER')
//*
//STEPLIB   DD DSN=PLI.V4R5M0.SIBMZCMP,
//             DISP=SHR
//*
//SYSUEXIT  DD DSN=NULLFILE,
//             DISP=SHR
//*
//SYSPRINT  DD SYSOUT=*
//*
//SYSUT1    DD UNIT=SYSDA,
//             SPACE=(CYL,(5,5))
//*
//PLISTD    DD DSN=&SYSUID..RAHP.DATA(PXEP45Z),
//             DISP=SHR
//*
//PLIUSER   DD *
nolist
  test(all,sym,separate,sepname) sysparm('TEST') opt(0)
notest sysparm('') opt(3)
//*
//SYSIN     DD *
 /* Roberts Q&D PL/I test program                              */
 test: proc(parm) options(main) reorder;
 dcl parm char     (100) var;
 dcl plixopt char (100) var ext
     init ('ISASIZE(64K) HEAP(128K,64K)');

 dcl sysprint file;
 on error snap
   begin;
     on error snap system;
     call plidump('HB');
   end;

 dcl test2 entry(*);

 dcl orecord  file record output env(fb recsize(80) total);
 dcl ostream  file stream print;

 dcl orec char (80) init ('test 1');

 put skip list(orec);
 put skip file(ostream) list(orec);
 write file(orecord) from(orec);
 call test2('plork');

 orec = 'test 3';
 put skip list(orec);
 put skip file(ostream) list(orec);
 write file(orecord) from(orec);
 end test;
//*
//SYSLIN    DD DSN=&&OBJECT(OBJ),
//             DISP=(OLD,PASS)
//*
//SYSPUNCH  DD DUMMY
//*********************************************************************
//IBMZPLI EXEC PGM=IBMZPLI,
//             REGION=0M,
//             PARM=('+DD:PLISTD +DD:PLIUSER')
//*
//STEPLIB   DD DSN=PLI.V4R5M0.SIBMZCMP,
//             DISP=SHR
//*
//SYSUEXIT  DD DSN=NULLFILE,
//             DISP=SHR
//*
//SYSPRINT  DD SYSOUT=*
//*
//SYSUT1    DD UNIT=SYSDA,
//             SPACE=(CYL,(5,5))
//*
//PLISTD    DD DSN=&SYSUID..RAHP.DATA(PXEP45Z),
//             DISP=SHR
//*
//PLIUSER   DD *
nolist
  test(all,sym,separate,sepname) sysparm('TEST') opt(0)
notest sysparm('') opt(3)
nooptions;
//*
//SYSIN     DD *
 /* Roberts Q&D PL/I test2 program                             */
 test2: proc(parm) reorder;
 dcl parm char     (100) var;

 dcl sysprint file;
 dcl orecord  file record output env(fb recsize(80) total);
 dcl ostream  file stream print;

 dcl orec char (80) init ('test 2');

 put skip list(orec);
 put skip file(ostream) list(orec);
 write file(orecord) from(orec);
 end test2;
//*
//SYSLIN    DD DSN=&&OBJECT(OBJ2),
//             DISP=(OLD,PASS)
//*
//SYSPUNCH  DD DUMMY
//*********************************************************************
//IEWL    EXEC PGM=IEWL,
//             PARM=('LET,LINECT=0,LIST,XREF',
//             'AMODE=31,RMODE=ANY')
//*
//SYSLIN    DD *
 INCLUDE OBJECT(OBJ)
 INCLUDE OBJECT(OBJ2)
 NAME TEST(R)
//*
//OBJECT    DD DSN=&&OBJECT,
//             DISP=(OLD,PASS)
//*
//SYSLIB    DD DSN=CEE.SCEELKED,
//             DISP=SHR
//*
//SYSUT1    DD UNIT=SYSDA,
//             SPACE=(CYL,(5,1))
//*
//SYSLMOD   DD DSN=&&LOAD,
//             DISP=(,PASS),
//             UNIT=SYSDA,
//             SPACE=(CYL,(2,2,1)),
//             DCB=(RECFM=U,LRECL=27988,BLKSIZE=0)
//*
//SYSPRINT  DD SYSOUT=*,
//             DCB=(RECFM=FBA,LRECL=121,BLKSIZE=27951)
//*********************************************************************
//GO      EXEC PGM=TEST
//STEPLIB   DD DSN=&&LOAD,
//             DISP=(OLD,PASS)
//*
//SYSPRINT  DD SYSOUT=*
//OSTREAM   DD SYSOUT=*
//ORECORD   DD SYSOUT=*


and the output:

Code:
SDSF JOB DATA SET DISPLAY - JOB PRINOCOM (JOB14398)    LINE 1-9 (9)                         
COMMAND INPUT ===>                                                                         
PREFIX=*  DEST=(ALL)  OWNER=PRINO  SYSNAME=                                                 
NP   DDNAME   StepName ProcStep DSID Owner    C Dest               Rec-Cnt Page-Cnt Byte-Cnt
     JESMSGLG JES2                 2 PRINO    H LOCAL                   16               888
     JESJCL   JES2                 3 PRINO    H LOCAL                  109             4,403
     JESYSMSG JES2                 4 PRINO    H LOCAL                  103             5,499
     SYSPRINT IBMZPLI            106 PRINO    H LOCAL                  414            13,830
     SYSPRINT IBMZPLI            107 PRINO    H LOCAL                  240             7,658
     SYSPRINT IEWL               108 PRINO    H LOCAL                  270            20,001
     SYSPRINT GO                 109 PRINO    H LOCAL                    3                48
     OSTREAM  GO                 110 PRINO    H LOCAL                    3                48
     ORECORD  GO                 111 PRINO    H LOCAL                    3                45


And the joblog from the end of the IEWL step:

Code:
 IEW2008I 0F03 PROCESSING COMPLETED.  RETURN CODE =  0.



 ----------------------
 MESSAGE SUMMARY REPORT
 ----------------------
  TERMINAL MESSAGES      (SEVERITY = 16)
  NONE

  SEVERE MESSAGES        (SEVERITY = 12)
  NONE

  ERROR MESSAGES         (SEVERITY = 08)
  NONE

  WARNING MESSAGES       (SEVERITY = 04)
  NONE

  INFORMATIONAL MESSAGES (SEVERITY = 00)
  2008  2278  2322


  **** END OF MESSAGE SUMMARY REPORT ****

1test 1
 test 2
 test 3
1test 1
 test 2
 test 3
test 1
test 2
test 3

In other words, (and expecting nothing else), perfectly OK.

ORECORD (obviously) doesn't have the leading ASA character.

Changing //OSTREAM to a temporary dataset and following that with a SORT (SORT FIELDS=COPY) to SORTSOUT DD SYSOUT=* will add additional blank lines to the output, caused by the SKIP in the "put skip file(ostream) list(orec);" statements.
Back to top
View user's profile Send private message
Pedro

Global Moderator


Joined: 01 Sep 2006
Posts: 2547
Location: Silicon Valley

PostPosted: Mon Sep 11, 2017 8:35 am
Reply with quote

I probably have multiple problems... at least one problem is that when the second program is called, it receives an undefined file condition.

I issue a PUT statement right before calling the second program (I see it in the data set) and the first statement in the second program is a PUT, which I do not get.

fyi. I am adding a new function to existing PLI programs, several of which are 10K lines of code or more. I think something in the complexity of the setup is interfering with the PUT functions / file allocations.
Back to top
View user's profile Send private message
prino

Senior Member


Joined: 07 Feb 2009
Posts: 1306
Location: Vilnius, Lithuania

PostPosted: Mon Sep 11, 2017 3:44 pm
Reply with quote

Pedro wrote:
I probably have multiple problems... at least one problem is that when the second program is called, it receives an undefined file condition.

And the file is declared the same as in the main procedure?

Pedro wrote:
I issue a PUT statement right before calling the second program (I see it in the data set) and the first statement in the second program is a PUT, which I do not get.


You have an
Code:
on error
  begin;
    on error system
    "put whatever message"
    close file(sysprint);
  end;


Pedro wrote:
fyi. I am adding a new function to existing PLI programs, several of which are 10K lines of code or more. I think something in the complexity of the setup is interfering with the PUT functions / file allocations.

Highly unlikely, but you might try compiling "OPT(0)" and run the program again, although it's only once, using the old OS compiler, that this actually solved the problem. Enterprise PL/I can handle programs with 40k lines, we have someone on "that" system with a program that long, still using EPLI V3.3!
Back to top
View user's profile Send private message
Pedro

Global Moderator


Joined: 01 Sep 2006
Posts: 2547
Location: Silicon Valley

PostPosted: Mon Sep 11, 2017 9:51 pm
Reply with quote

I have separately linked programs, with several separate load modules.

There was some improvement after I closed the file before calling the second program, then opening it again later after the return. That was probably the origin of the problem. Now I have to figure out where else I need to do the same.
Back to top
View user's profile Send private message
View previous topic :: :: View next topic  
Post new topic   Reply to topic View Bookmarks
All times are GMT + 6 Hours
Forum Index -> PL/I & Assembler

 


Similar Topics
Topic Forum Replies
No new posts INCLUDE OMIT COND for Multiple values... DFSORT/ICETOOL 5
No new posts Replace Multiple Field values to Othe... DFSORT/ICETOOL 12
No new posts Multiple table unload using INZUTILB DB2 2
No new posts Grouping by multiple headers DFSORT/ICETOOL 7
No new posts How to append a PS file into multiple... JCL & VSAM 3
Search our Forums:

Back to Top