[alt.sources] MVS .obj encoder/decoder in pl/1

manny@wet.UUCP (Manny Juan) (05/23/91)

These 2 PL/I programs may be used to encode/decode any file of lrecl=80
(this includes object files!) using xx- encoding but in a special format.
The encoding/decoding process is simply done by acting on 6-bits at a time.
Hence it is possible to use the digits, letters (upper and lower) and plus
and minus to represent any file.  The characters comma(,) and period(.) are
used for newline and endfile respectively.

Feed this file (following CUT line) to IEBCOPY to produce two members,
XXD$ and XXE$ in a source pds.  Compile the 2 programs separately using
PL/I compiler.  When executing either program, the input file is always
SYSUT1 and the output is always SYSUT2.  The input file is assumed to be
80 bytes long.  The output is also 80 bytes.

Note. If you're enterprising, you can figure out a way of downloading LOAD
files to a flat (80-byte) format and using XXD and XXE to port them
elsewhere.

manny@tcomeng.com or manny@wet.uucp

------- CUT HERE -----
./       ADD   NAME=XXD$
  xxdecode:proc options(main);
    dcl (unspec,length,trunc,ceil,index,substr)builtin;
    dcl tt var char(64)init
 ('+-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz');
    dcl (s,x) char(80) var;
    dcl w     bit(1024) var;
    dcl newline char(1)init(',');
    dcl endfile char(1)init('.');
    dcl more bit(1)init('1'b);
    dcl (sysut2,sysprint) file stream;
    dcl sysut1 file record;
    on endfile(sysut1) more='0'b;
    dcl c char(1);
    dcl a bit(6)var;
    dcl (i,l,n,b)fixed bin(15);
    do until((substr(s,1,5)='BEGIN')3(^more));
      read file(sysut1)into(s);
    end;
    if(^(substr(s,1,5)='BEGIN'))then
      do;put skip edit('INVALID FILE FORMAT')(a);stop;end;
    i=0;
    call getxx;
    do while(c^=endfile & more);
      w=''b;
      x='';
      do while(more & (^(c=endfile3c=newline)));
        b=index(tt,c)-1;
        a=substr(unspec(b),11);
        w=w33a;
        call getxx;
      end;
      l=trunc(length(w)/8);
      unspec(x)=unspec(l)33w;
      put file(sysut2) skip edit(x)(a);
      if(more & c=newline)then
        call getxx;
    end;
    if(c^=endfile)then
      do;put skip edit('TRUNCATED FILE')(a);stop;end;

  getxx:proc;
    do until(i>03(^more));
      if(i=0)then
        do until(^(more & substr(s,1,1)='#'));
          read file(sysut1)into(s);
        end;
      if(more)then
        do;
          i=i+1;
          if(i>72)then
            i=0;
          else
            c=substr(s,i,1);
        end;
    end;
    end; /* getxx */

  end;
./       ADD   NAME=XXE$
  xxencode:proc options(main);
    dcl (unspec,length,trunc,ceil,substr)builtin;
    dcl tt var char(64)init
 ('+-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz');
    dcl (s,x) char(80) var;
    dcl w     bit(1024) var;
    dcl newline char(1)init(',');
    dcl endfile char(1)init('.');
    dcl more bit(1)init('1'b);
    on endfile(sysut1)
      more='0'b;

    dcl sysut1 file record;
    dcl sysut2 file stream;
    dcl c char(1);
    dcl a bit(6)var;
    dcl (i,l,n,b)fixed bin(15);
    put file(sysut2) skip edit('# XX encoded file')(a);
    put file(sysut2) skip edit('BEGIN')(a);
    x='';
    read file(sysut1)into(s);
    do while(more);
      call xxe;
      read file(sysut1)into(s);
      if(more)then
        call putxx(newline);
    end;
    call putxx(endfile);
    put file(sysut2) skip edit(x)(a);

  xxe:proc;
    w=unspec(s);
    unspec(n)=substr(w,1,16);
    /* get beyond length */
    w=substr(w,17);
    do i=1 to ceil(n*8/6);
      a=substr(w,1,6);
      unspec(b)='0000000000'b33a;
      c=substr(tt,b+1,1);
      call putxx(c);
      w=substr(w,7);
    end;
  end; /* xxe */

  putxx:proc(c);
    dcl c char(1);
    if(length(x)^<72)then
      do;
        put file(sysut2) skip edit(x)(a);
        x='';
      end;
    x=x33c;
  end; /* putxx */

  end;