EGL Development User Group

EGL Development User Group

EGL Development User Group

The EGL Development User Group is dedicated to sharing news, knowledge, and insights regarding the EGL language and Business Developer product. Consisting of IBMers, HCL, and users, this community collaborates to advance the EGL ecosystem.

 View Only
  • 1.  Pass buffer by reference

    Posted 09/08/17 05:15 AM

    Hi,

    i'd like to create a z/OS batch application that will act like an http client. I did a similar application in PL/I using the z/OS http enabler toolkit ( using the http protocol enabler part ).

    I was able to link my egl basic program with the link stub of the toolkit after editing FDABCL:

    //X  IF &HASLKG..EQ.YES                                        //L2        EXEC PGM=IEWL,REGION=&RGN,                         //*        PARM='RENT,REUS,LIST,XREF,MAP,AMODE(31),RMODE(ANY)' //         PARM='RENT,REUS,LIST,XREF,MAP,AMODE(31)'            //SYSLIB   DD  DISP=SHR,DSN=&COBLIB                            //SELALMD  DD  DISP=SHR,DSN=&ELA..SELALMD                      //LINK01   DD  DISP=SHR,DSN=&LINKLIB                           //SYSLIN     DD  DSN=&CGHLQ..&SYSTEM..EZELKG(&MBR),DISP=SHR    //*SYSLIN    DD  CCUEXT=LKG,DISP=(NEW,DELETE),                 //*    UNIT=SYSDA,SPACE=(CYL,(999,999),RLSE),                  //*    DCB=(RECFM=FB,LRECL=80,BLKSIZE=3200)                    //OBJLIB   DD  DISP=SHR,DSN=&CGHLQ..&SYSTEM..OBJECT            //SYSLMOD  DD  DISP=SHR,DSN=&CGHLQ..&SYSTEM..LOAD              //SYSPRINT DD  CCUEXT=&CCUEXTL,DISP=(NEW,DELETE),              //    UNIT=VIO,SPACE=(CYL,(999,999),RLSE),                     //    DCB=(RECFM=FB,LRECL=121,BLKSIZE=1210)                    //SYSUT1   DD  SPACE=(1024,(&WSPC,&WSPC)),UNIT=VIO             //*PROVIDE ANY CUSTOM DD STATEMENTS HERE                       //X    ENDIF                                                   //*************************************************************

    I pass the link library as a symbolic given in the build descriptor( LINK01). Also, instead of relinking i did the whole linking in this section.

    After all, i can run the generated program and i can get correct return codes and messages (defined in the documentation) back from the services, so i can access them.

     

    My issue with making this work in EGL is that i am not sure how to pass data to the services. As soon as i need to pass parameters that are addresses of buffers i got into trouble and got error messages indicating that the parameter in question is invalid (inaccessible storage ) or empty, depending on what data type i try to use.

     

    HWTH-RETURN-CODE int;Conn-Handle hex(24); // 12 byteHWTH-DIAG-AREA char(136);HWTH_HANDLETYPE_CONNECTION  hex(8) = X"00000001";HWTH_HANDLETYPE_HTTPREQUEST hex(8) = X"00000002";HWTH_HANDLETYPE.VALUE = HWTH_HANDLETYPE_CONNECTION;call "HWTHINIT"(HWTH-RETURN-CODE, HWTH_HANDLETYPE.VALUE, Conn-Handle, HWTH-DIAG-AREA);Record HWTH_HANDLETYPE type basicRecord  01 VALUE hex(8);end

    This call is working just fine as the parameter list doesn't have any tricky element. However i cannot make the next one work:
     

    call "HWTHSET"(HWTH-RETURN-CODE, Conn-Handle, HWTH_OPT_URI, uri, length, HWTH-DIAG-AREA);

    Where uri is expected to be the address of a buffer holding some string.
    I tried several data type for uri but none of them worked, and the generated cobol code dosen't seem right either. Using string e.g. will map to some unintelligible structure (for me):
     

    CALL EZEPROGM USING HWTH-RETURN-COD-2 CONN-HANDLE-3  HWTH-OPT-URI-29 URI-36 LENGTH-43 HWTH-DIAG-AREA-7 

    where URI-36 is a pointer but i believe it doesn't point to what i need:

    04  URI-36 USAGE IS POINTER.

    And is filled like:

    * EGL *27* uri = "something";SET URI-36 TO EZESTR-40  ...SET EZESTR-40 TO ADDRESS OF EZETYPE-STRING0MOVE EZESTR-39 TO EZETYPE-DATA IN EZETYPE-STRING0     (1:EZETYPE-LENGTH IN EZETYPE-STRING0)  ...MOVE "something" TO EZESTR-39-1-----02  EZESTR-39-FILLER.                                                        03  EZESTR-39-1 PIC N(9) USAGE NATIONAL.                            02  EZESTR-39 REDEFINES EZESTR-39-FILLER PIC N(9) USAGE 

    Unfortunately EZETYPE-STRING0 is not a simple buffer-like thing but:

    01  EZETYPE-STRING0.                                                      02  EZETYPE-HEADER.                                                          03  EZETYPE-TYPEPTR USAGE IS POINTER.                                    03  EZETYPE-TOTAL-LENGTH PIC 9(9) COMP-4.                              03  EZETYPE-GARBCOLL-KEY PIC 9(9) COMP-4.                               03  EZETYPE-LENGTH PIC 9(9) COMP-4.                                    03  EZETYPE-PTR-ALIGNMENT PIC X(4).                               02  EZETYPE-DATA PIC N(32767) USAGE NATIONAL.

     

    Long story short: can you help me how to overcome this issue? What datatype should i use that is a simple array of bytes and i can pass the address of it?
     

    Daniel_Bekesi


  • 2.  Re: Pass buffer by reference

    Posted 10/18/17 02:18 PM

    In order to pass data to a service, the parameters must be flattened and possibly converted to a data type that can be understood. Passing a pointer to something doesn't fall into that category. EGL has written some "catcher" programs that interface between EGL's record/parms for the service and the service. This catcher does the preparatory work for passing data to and from the service.

    Is this service that you are trying to access, an external one (to EGL) or an EGL service? You should be able to write an EGL program that calls this service. 

    JeffDouglas


  • 3.  Re: Pass buffer by reference

    Posted 12/08/17 07:10 AM

    Hi Jeff,

    sorry for the late response i got some issues with logging in.

    Indeed, i ended up writing PL/I wrapper functions that are called from EGL and are calling the HTTP services.

    One tricky thing for me (i am not very familiar with PL/I ) was finding out how to pass the data back (response is handled by callback function written in PL/I ), but something like this ended up working:
     

    WRAPPOLL: PROCEDURE(bufferin);  DCL target_ptr ptr Initial(Addr(bufferin));  DCL chars char(32000) based(target_ptr);  chars = buffer; END WRAPPOLL;

    Where buffer holds the http response payload, and this function can be used in a polling manner.

    Similarly, the external services of this HTTP enablement kit are called from PL/I functions that are linked to the EGL:
     

    call "WRAPRQSR"(HWTH-RETURN-CODE, Conn-Handle, Req-Handle, HWTH-DIAG-AREA);

    Where WRAPRQSR is:

    WRAPRQSR: PROCEDURE(HWTH_RETURN_CODE,                     HWTH_HANDLE,                     HWTH_REQ_HANDLE,                     HWTH_DIAG_AREA                     ) OPTIONS(LINKAGE(SYSTEM)); DCL HWTH_RETURN_CODE TYPE HWTH_RETURNCODE_TYPE; DCL HWTH_HANDLE      TYPE HWTH_HANDLE_TYPE byValue; DCL HWTH_REQ_HANDLE  TYPE HWTH_HANDLE_TYPE byValue; DCL HWTH_DIAG_AREA   TYPE HWTH_DIAGAREA_TYPE;  CALL HWTHRQST(HWTH_RETURN_CODE,                HWTH_HANDLE,                HWTH_REQ_HANDLE,                HWTH_DIAG_AREA); END WRAPRQSR;
    Daniel_Bekesi