home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / cpm / cpm86 / uuencode.pas < prev    next >
Pascal/Delphi Source File  |  1986-09-29  |  7KB  |  293 lines

  1. Program uuencode;
  2. {Fixed 'off-by-one' error @ EOF in routine ENCODE1 - B.Eiben@MARKET - 16-Aug-86}
  3.  
  4.   CONST header = 'begin';
  5.         trailer = 'end';
  6.         defaultMode = '644';
  7.         defaultExtension = '.uue';
  8.         offset = 32;
  9.         charsPerLine = 60;
  10.         bytesPerHunk = 3;
  11.         sixBitMask = $3F;
  12.         endofinfile : boolean = FALSE;
  13.  
  14.   TYPE string80 = string[80];
  15.  
  16.   VAR inf : file;
  17.       outfile: text;
  18.       infilename, outfilename, mode: string80;
  19.       lineLength, numbytes, bytesInLine: integer;
  20.       line: array [0..59] of char;
  21.       hunk: array [0..2] of byte;
  22.       chars: array [0..3] of byte;
  23.  
  24.  
  25. {  procedure debug;
  26.  
  27.     var i: integer;
  28.  
  29.     procedure writebin(x: byte);
  30.  
  31.       var i: integer;
  32.  
  33.       begin
  34.         for i := 1 to 8 do
  35.           begin
  36.             write ((x and $80) shr 7);
  37.             x := x shl 1
  38.           end;
  39.         write (' ')
  40.       end;
  41.  
  42.     begin
  43.       for i := 0 to 2 do writebin(hunk[i]);
  44.       writeln;
  45.       for i := 0 to 3 do writebin(chars[i]);
  46.       writeln;
  47.       for i := 0 to 3 do writebin(chars[i] and sixBitMask);
  48.       writeln
  49.     end;  }
  50.  
  51. {Binary file read added by Ross Alford,  ...!mcnc!ecsvax!alford.  The original
  52.  MSDOS versions of uuencode/decode just use read/write on a FILE OF BYTE.
  53.  CP/M Turbo expects some file info to be stored in the first 4 bytes of files
  54.  of any type other than TEXT.  Getbyte (below) and Putbyte (in UUDECODE)
  55.  bypass this 'feature' by using blockread and blockwrite.  The only global
  56.  variables either use are 'infilename' and 'inf' or 'outfilename' and 'outf'}
  57.  
  58. function getbyte(var b : byte) : boolean;
  59.  
  60. type bufptr = ^bufrec;
  61.      bufrec = record
  62.                 next : bufptr;
  63.                 buffer : array[1..128] of byte
  64.               end;
  65.  
  66. const sectstobuf = 8;                {max number of sectors to buffer}
  67.       sectsread : integer = 0;       {constants are essentially statics}
  68.       bytptr : integer = 129;
  69.       notopen : boolean = TRUE;
  70.       j : integer = 0;
  71.       infsize : integer = 0;
  72.       listsaveofs : integer = 0;
  73.       listsaveseg : integer = 0;
  74.  
  75. var list,temp,temp2 : bufptr;
  76.  
  77. begin
  78.   if notopen then
  79.     begin
  80.       notopen := FALSE;
  81.       assign(inf,infilename);
  82.       {$i-}
  83.       reset(inf);
  84.       {$i+}
  85.       if ioresult <> 0 then
  86.         begin
  87.           writeln('File ',infilename,' not found.  Aborting');
  88.           halt
  89.         end;
  90.       infsize := filesize(inf);
  91.       new(list);
  92.       list^.next := NIL;
  93.       listsaveofs := ofs(list^);
  94.       listsaveseg := seg(list^);
  95.       sectsread := 0
  96.     end;
  97.   list := ptr(listsaveseg,listsaveofs);
  98.   if bytptr > 128 then
  99.     begin
  100.       if list^.next <> NIL then
  101.         begin
  102.           temp := list^.next;
  103.           dispose(list);
  104.           list := temp;
  105.           bytptr := 1
  106.         end
  107.         else begin
  108.           dispose(list);
  109.           list := NIL;
  110.           j := 0;
  111.           while (sectsread<infsize) and (j<sectstobuf) do
  112.             begin
  113.               new(temp2);
  114.               temp2^.next := NIL;
  115.               if list=NIL then
  116.                 begin
  117.                   list := temp2;
  118.                   temp := list
  119.                 end
  120.                 else begin
  121.                   temp^.next := temp2;
  122.                   temp := temp2
  123.                 end;
  124.               blockread(inf,temp^.buffer,1);
  125.               j := succ(j);
  126.               sectsread := succ(sectsread)
  127.             end;
  128.           bytptr := 1
  129.         end
  130.     end;
  131.     listsaveofs := ofs(list^);
  132.     listsaveseg := seg(list^);
  133.     if list <> NIL then
  134.       begin
  135.         b := list^.buffer[bytptr];
  136.         bytptr := succ(bytptr);
  137.         getbyte := TRUE
  138.       end
  139.       else begin
  140.         b := 0;
  141.         getbyte := FALSE
  142.       end
  143. end;
  144.  
  145.   procedure Abort (message: string80);
  146.  
  147.     begin {abort}
  148.       writeln(message);
  149.       close(inf);
  150.       close(outfile);
  151.       halt
  152.     end; {abort}
  153.  
  154.   procedure Init;
  155.  
  156.     procedure GetFiles;
  157.  
  158.       VAR i: integer;
  159.           temp: string80;
  160.           ch: char;
  161.  
  162.       begin {GetFiles}
  163.         if ParamCount < 1 then abort ('No input file specified.');
  164.         infilename := ParamStr(1);
  165.         {$I-}
  166.         assign (inf, infilename);
  167.         reset (inf);
  168.         {$i+}
  169.         if IOResult > 0 then abort (concat ('Can''t open file ', infilename));
  170.  
  171.         write('Uuencoding file ', infilename);
  172.  
  173.         i := pos('.', infilename);
  174.         if i = 0
  175.           then outfilename := infilename
  176.           else outfilename := copy (infilename, 1, pred(i));
  177.         mode := defaultMode;
  178.         if ParamCount > 1 then
  179.           for i := 2 to ParamCount do
  180.             begin
  181.               temp := Paramstr(i);
  182.               if temp[1] in ['0'..'9']
  183.                 then mode := temp
  184.                 else outfilename := temp
  185.             end;
  186.         if pos ('.', outfilename) = 0
  187.           then outfilename := concat(outfilename, defaultExtension);
  188.         assign (outfile, outfilename);
  189.         writeln (' to file ', outfilename, '.');
  190.  
  191.         {$i-}
  192.         reset(outfile);
  193.         {$i+}
  194.         if IOresult = 0 then
  195.           begin
  196.             Write ('Overwrite current ', outfilename, '? [Y/N] ');
  197.             repeat
  198.               read (kbd, ch);
  199.               ch := Upcase(ch)
  200.             until ch in ['Y', 'N'];
  201.             writeln (ch);
  202.             if ch = 'N' then abort(concat (outfilename, ' not overwritten.'))
  203.           end;
  204.         close(outfile);
  205.  
  206.         {$i-}
  207.         rewrite(outfile);
  208.         {$i+}
  209.         if ioresult > 0 then abort(concat('Can''t open ', outfilename));
  210.       end; {getfiles}
  211.  
  212.     begin {Init}
  213.       GetFiles;
  214.       bytesInLine := 0;
  215.       lineLength := 0;
  216.       numbytes := 0;
  217.       writeln (outfile, header, ' ', mode, ' ', infilename);
  218.     end; {init}
  219.  
  220.   procedure FlushLine;
  221.  
  222.     VAR i: integer;
  223.  
  224.     procedure writeout(ch: char);
  225.  
  226.       begin {writeout}
  227.         if ch = ' ' then write(outfile, '`')
  228.                     else write(outfile, ch)
  229.       end; {writeout}
  230.  
  231.     begin {FlushLine}
  232.       write ('.');
  233.       writeout(chr(bytesInLine + offset));
  234.       for i := 0 to pred(lineLength) do
  235.         writeout(line[i]);
  236.       writeln (outfile);
  237.       lineLength := 0;
  238.       bytesInLine := 0
  239.     end; {FlushLine}
  240.  
  241.   procedure FlushHunk;
  242.  
  243.     VAR i: integer;
  244.  
  245.     begin {FlushHunk}
  246.       if lineLength = charsPerLine then FlushLine;
  247.       chars[0] := hunk[0] shr 2;
  248.       chars[1] := (hunk[0] shl 4) + (hunk[1] shr 4);
  249.       chars[2] := (hunk[1] shl 2) + (hunk[2] shr 6);
  250.       chars[3] := hunk[2] and sixBitMask;
  251.       {debug;}
  252.       for i := 0 to 3 do
  253.         begin
  254.           line[lineLength] := chr((chars[i] and sixBitMask) + offset);
  255.           {write(line[linelength]:2);}
  256.           lineLength := succ(lineLength)
  257.         end;
  258.       {writeln;}
  259.       bytesInLine := bytesInLine + numbytes;
  260.       numbytes := 0
  261.     end; {FlushHunk}
  262.  
  263.   procedure encode1;
  264.  
  265.     begin {encode1};
  266.       if numbytes = bytesperhunk then flushhunk;
  267.       endofinfile := not (getbyte(hunk[numbytes]));
  268.       if not endofinfile then numbytes := succ(numbytes)  {No succ at EOF -BE}
  269.     end; {encode1}
  270.  
  271.   procedure terminate;
  272.  
  273.     begin {terminate}
  274.       if numbytes > 0 then flushhunk;
  275.       if lineLength > 0
  276.         then
  277.           begin
  278.             flushLine;
  279.             flushLine;
  280.           end
  281.         else flushline;
  282.       writeln (outfile, trailer);
  283.       close (outfile);
  284.       close (inf);
  285.     end; {terminate}
  286.  
  287.  
  288.   begin {uuencode}
  289.     init;
  290.     while not endofinfile do encode1;
  291.     terminate
  292.   end. {uuencode}
  293.