PL/I

PL/I

PL/I

 View Only
  • 1.  GUID: generate in a PL/I program on z/OS

    Posted Thu August 02, 2012 05:14 AM
    Hi there,  
    I need to generate a GUID in a PL/I program - but how can I do that? 
    The best would be a function call like "myGUID = GetGUID();" - or somthing like that.
    If it works in both BATCH and CICS it would be really nice.
    Can anyone help?
    PeterOL


  • 2.  Re: GUID: generate in a PL/I program on z/OS

    Posted Thu August 30, 2012 11:48 PM
     It is a 128 bit quantity, better to pass as argument.
     
    This example does not implement the clock sequence part per rfc4122,
    and  use cpu serial in place of MAC address.
     
     *PROCESS LIMITS(FIXEDBIN(63));
     guid: package;

     define structure
        1 guid
         ,3 time_low unsigned fixed bin(32)
         ,3 time_mid unsigned fixed bin(16)
         ,3 time_hi_and_version unsigned fixed bin(16)
         ,3 clock_seq_hi_and_reserved unsigned fixed bin(8)
         ,3 clock_seq_low unsigned fixed bin(8)
         ,3 node char(6)
     ;

     define structure
        1 _FEEDBACK
         ,3 tok_sev fixed bin(15)
         ,3 tok_msgno fixed bin(15)
         ,3 *
           ,5 tok_case bit(2) unaligned
           ,5 tok_sever bit(3) unaligned
           ,5 tok_ctrl bit(3) unaligned
         ,3 tok_facid(3) char
         ,3 tok_isi fixed bin(31)
     ;

     dcl CEEGMT entry(fixed bin(31) byaddr, real float decimal(16) byaddr,
         1 optional type _FEEDBACK byaddr) options(assembler);

     dcl getcpuid ext('__get_cpuid') entry(char(11) byaddr)
         returns(optional fixed bin(31))
     options( linkage(optlink) nodescriptor );

     guidfmt: proc(u,out);
         dcl u type guid byvalue;
         dcl out char(*) varz byaddr;
         out='';
         out=heximage(addr(u.time_low),4); out||='-';
         out||=heximage(addr(u.time_mid),2); out||='-';
         out||=heximage(addr(u.time_hi_and_version),2); out||='-';
         out||=heximage(addr(u.clock_seq_hi_and_reserved),2); out||='-';
         out||=heximage(addr(u.node),6);
     end guidfmt;

     genguid: proc(u);
        dcl u type guid;
        dcl lilgmt fixed bin(31);
        dcl secgmt real float decimal(16);
        dcl t unsigned fixed bin(64);
        dcl fb type _FEEDBACK;
        dcl buf char(11);
        dcl rc fixed bin(31);
        dcl pid fixed unsigned bin(32);
        call CEEGMT(lilgmt,secgmt,fb);
        if (fb.tok_sev = 0 & fb.tok_msgno = 0) then do;
        end;
        else stop;
        call getcpuid(buf);
        u.node=substr(buf,1,6);
        t=secgmt*10000000;
        u.time_low=iand(t,'00000000ffffffff'xn);
        u.time_mid=iand(isrl(t,32),'000000000000ffff'xn);
        u.time_hi_and_version=iand(isrl(t,48),'0000000000000fff'xn);
        u.time_hi_and_version=ior(isll(1,12),u.time_hi_and_version);
        u.clock_seq_low=0;
        u.clock_seq_hi_and_reserved = 0;
        u.clock_seq_hi_and_reserved =
          iand(u.clock_seq_hi_and_reserved,'3f'xn);
        u.clock_seq_hi_and_reserved =
          ior(u.clock_seq_hi_and_reserved,'80'xn);
     end genguid;

     test: proc options(main);
        dcl u type guid;
        dcl out char(100) varz;
        call genguid(u);
        call guidfmt(u,out);
        display("guid:"||out);
     end test;

     end guid;

    ccw


  • 3.  Re: GUID: generate in a PL/I program on z/OS

    Posted Fri August 31, 2012 05:35 AM
     Thank you "ccw" - this looks interesting.
    I have now tried to compile your code but I get a severe error on these lines:

    109.0 1 U.TIME_LOW=IAND(T,'00000000ffffffff'XN);

    110.0 1 U.TIME_MID=IAND(ISRL(T,32),'000000000000ffff'XN);

    111.0 1 U.TIME_HI_AND_VERSION=IAND(ISRL(T,48),'0000000000000fff'XN);

    5655-W67 IBM(R) Enterprise PL/I for z/OS 2012.08.31 11:24:18 Page 8

    Compiler Messages

    Message Line.File Message Description

    IBM1920I S 109.0 FIXED BINARY constant contains too many digits.

    IBM1920I S 110.0 FIXED BINARY constant contains too many digits.

    IBM1920I S 111.0 FIXED BINARY constant contains too many digits.

      
    PeterOL


  • 4.  Re: GUID: generate in a PL/I program on z/OS

    Posted Sat September 01, 2012 05:50 PM
    Ok, I got the same errors if I do not use the option LIMITS(FIXEDBIN(63))
    you need that line as the first line or specify that as a compile option.
     
     *PROCESS LIMITS(FIXEDBIN(63)); 
     
    Note the node portion of the GUID is suppose to contain the MAC address of one of
    the ethernet cards on the system. In theory no two ethernet cards on this planet should 
    have the same MAC. I don't know of any good way to obtain that on MVS  other than issuing 
    console or TSO command netstat arp all tcp tcpip. CPU serial is not a perfect substitution.
    You can hard code you MAC if you know the program only runs on one single system.
     
    ccw


  • 5.  Re: GUID: generate in a PL/I program on z/OS

    Posted Mon September 03, 2012 02:31 AM
    Hi again,
    I get the same error if the *PROCESS line is active or not.
    This is z/OS PL/I version 4.1 compiler.
    I do have a solution to the GUID but as it is at the moment it depends on getting a timestamp from DB2.
    Maybe I can get a timestamp directly from PL/I with all the digits as DB2 can deliver.
     
    The current problem for me are the DB2 issue. Some project want to include the code in a high-level place where DB2 code is not allowed. We have a rule on CICS that dialogs modules have to be withot DB2. Also in batch some project restricts DB2 to same datamodules and not in the main-loop or business modules.
     
    Well I just need to do whatever people ask for - more or less :-)
         
     
    PeterOL


  • 6.  Re: GUID: generate in a PL/I program on z/OS

    Posted Mon September 03, 2012 04:22 AM
     That line need to be the first line and starts at the first column and you should see
     
      Line.File Process Statements

         1.0    *PROCESS LIMITS(FIXEDBIN(63));

     
    In the compile listing, works on 4.1.
    If for whatever reason it does not work for you, you can replace the proc genuuid with this version which does not use 64 bit integers.
     ......
     genguid: proc(u);
        dcl u type guid;
        dcl lilgmt fixed bin(31);
        dcl secgmt real float decimal(16);
        dcl t1 unsigned fixed bin(32);
        dcl t2 unsigned fixed bin(32);
        dcl fb type _FEEDBACK;
        dcl buf char(11);
        dcl rc fixed bin(31);
        dcl pid fixed unsigned bin(32);
        call CEEGMT(lilgmt,secgmt,fb);
        if (fb.tok_sev = 0 & fb.tok_msgno = 0) then do;
        end;
        else stop;
        call getcpuid(buf);
        u.node=substr(buf,1,6);
        t1=(secgmt*10000000/4294967296);
        t2=secgmt*10000000;
        t2*=16;
        u.time_low=iand(t2,'ffffffff'xn);
        u.time_mid=iand(t1,'0000ffff'xn);
        u.time_hi_and_version=iand(isrl(t1,16),'00000fff'xn);
        u.time_hi_and_version=ior(isll(1,12),u.time_hi_and_version);
        u.clock_seq_low=0;
        u.clock_seq_hi_and_reserved = 0;
        u.clock_seq_hi_and_reserved =
          iand(u.clock_seq_hi_and_reserved,'3f'xn);
        u.clock_seq_hi_and_reserved =
          ior(u.clock_seq_hi_and_reserved,'80'xn);
     end genguid;
     ......
     
     
    ccw


  • 7.  Re: GUID: generate in a PL/I program on z/OS

    Posted Mon September 03, 2012 06:36 AM
     I do see that, the error was fagged first time I did a compile.
    I have now changed the code, but I get a link issue - I have send that to a responsible for our compile/link setup. Thanks for all your help and code. Regards Peter.
    PeterOL