Topic
  • 6 replies
  • Latest Post - ‏2012-09-03T10:36:14Z by PeterOL
PeterOL
PeterOL
9 Posts

Pinned topic GUID: generate in a PL/I program on z/OS

‏2012-08-02T09:13:37Z |
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?
Updated on 2012-09-03T10:36:14Z at 2012-09-03T10:36:14Z by PeterOL
  • ccw
    ccw
    7 Posts

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

    ‏2012-08-31T03:48:16Z  
     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;

  • PeterOL
    PeterOL
    9 Posts

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

    ‏2012-08-31T09:35:16Z  
    • ccw
    • ‏2012-08-31T03:48:16Z
     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;

     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.

      
  • ccw
    ccw
    7 Posts

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

    ‏2012-09-02T07:26:25Z  
    • PeterOL
    • ‏2012-08-31T09:35:16Z
     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.

      
    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.
     
    Updated on 2012-09-02T07:26:25Z at 2012-09-02T07:26:25Z by ccw
  • PeterOL
    PeterOL
    9 Posts

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

    ‏2012-09-03T06:30:41Z  
    • ccw
    • ‏2012-09-01T21:49:41Z
    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.
     
    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 :-)
         
     
  • ccw
    ccw
    7 Posts

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

    ‏2012-09-03T08:30:27Z  
    • PeterOL
    • ‏2012-09-03T06:30:41Z
    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 :-)
         
     
     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;
     ......
     
     
    Updated on 2012-09-03T08:30:27Z at 2012-09-03T08:30:27Z by ccw
  • PeterOL
    PeterOL
    9 Posts

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

    ‏2012-09-03T10:36:14Z  
    • ccw
    • ‏2012-09-03T08:22:16Z
     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;
     ......
     
     
     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.