home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / CPM / STARTKIT / UUENCODE.PAS < prev    next >
Pascal/Delphi Source File  |  2000-06-30  |  7KB  |  290 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.       listsave : integer  = 0;
  73.  
  74. var list,temp,temp2 : bufptr;
  75.  
  76. begin
  77.   if notopen then
  78.     begin
  79.       notopen := FALSE;
  80.       assign(inf,infilename);
  81.       {$i-}
  82.       reset(inf);
  83.       {$i+}
  84.       if ioresult <> 0 then
  85.         begin
  86.           writeln('File ',infilename,' not found.  Aborting');
  87.           halt
  88.         end;
  89.       infsize := filesize(inf);
  90.       new(list);
  91.       list^.next := NIL;
  92.       listsave := ord(list);
  93.       sectsread := 0
  94.     end;
  95.   list := ptr(listsave);
  96.   if bytptr > 128 then
  97.     begin
  98.       if list^.next <> NIL then
  99.         begin
  100.           temp := list^.next;
  101.           dispose(list);
  102.           list := temp;
  103.           bytptr := 1
  104.         end
  105.         else begin
  106.           dispose(list);
  107.           list := NIL;
  108.           j := 0;
  109.           while (sectsread<infsize) and (j<sectstobuf) do
  110.             begin
  111.               new(temp2);
  112.               temp2^.next := NIL;
  113.               if list=NIL then
  114.                 begin
  115.                   list := temp2;
  116.                   temp := list
  117.                 end
  118.                 else begin
  119.                   temp^.next := temp2;
  120.                   temp := temp2
  121.                 end;
  122.               blockread(inf,temp^.buffer,1);
  123.               j := succ(j);
  124.               sectsread := succ(sectsread)
  125.             end;
  126.           bytptr := 1
  127.         end
  128.     end;
  129.     listsave := ord(list);
  130.     if list <> NIL then
  131.       begin
  132.         b := list^.buffer[bytptr];
  133.         bytptr := succ(bytptr);
  134.         getbyte := TRUE
  135.       end
  136.       else begin
  137.         b := 0;
  138.         getbyte := FALSE
  139.       end
  140. end;
  141.  
  142.   procedure Abort (message: string80);
  143.  
  144.     begin {abort}
  145.       writeln(message);
  146.       close(inf);
  147.       close(outfile);
  148.       halt
  149.     end; {abort}
  150.  
  151.   procedure Init;
  152.  
  153.     procedure GetFiles;
  154.  
  155.       VAR i: integer;
  156.           temp: string80;
  157.           ch: char;
  158.  
  159.       begin {GetFiles}
  160.         if ParamCount < 1 then abort ('No input file specified.');
  161.         infilename := ParamStr(1);
  162.         {$I-}
  163.         assign (inf, infilename);
  164.         reset (inf);
  165.         {$i+}
  166.         if IOResult > 0 then abort (concat ('Can''t open file ', infilename));
  167.  
  168.         write('Uuencoding file ', infilename);
  169.  
  170.         i := pos('.', infilename);
  171.         if i = 0
  172.           then outfilename := infilename
  173.           else outfilename := copy (infilename, 1, pred(i));
  174.         mode := defaultMode;
  175.         if ParamCount > 1 then
  176.           for i := 2 to ParamCount do
  177.             begin
  178.               temp := Paramstr(i);
  179.               if temp[1] in ['0'..'9']
  180.                 then mode := temp
  181.                 else outfilename := temp
  182.             end;
  183.         if pos ('.', outfilename) = 0
  184.           then outfilename := concat(outfilename, defaultExtension);
  185.         assign (outfile, outfilename);
  186.         writeln (' to file ', outfilename, '.');
  187.  
  188.         {$i-}
  189.         reset(outfile);
  190.         {$i+}
  191.         if IOresult = 0 then
  192.           begin
  193.             Write ('Overwrite current ', outfilename, '? [Y/N] ');
  194.             repeat
  195.               read (kbd, ch);
  196.               ch := Upcase(ch)
  197.             until ch in ['Y', 'N'];
  198.             writeln (ch);
  199.             if ch = 'N' then abort(concat (outfilename, ' not overwritten.'))
  200.           end;
  201.         close(outfile);
  202.  
  203.         {$i-}
  204.         rewrite(outfile);
  205.         {$i+}
  206.         if ioresult > 0 then abort(concat('Can''t open ', outfilename));
  207.       end; {getfiles}
  208.  
  209.     begin {Init}
  210.       GetFiles;
  211.       bytesInLine := 0;
  212.       lineLength := 0;
  213.       numbytes := 0;
  214.       writeln (outfile, header, ' ', mode, ' ', infilename);
  215.     end; {init}
  216.  
  217.   procedure FlushLine;
  218.  
  219.     VAR i: integer;
  220.  
  221.     procedure writeout(ch: char);
  222.  
  223.       begin {writeout}
  224.         if ch = ' ' then write(outfile, '`')
  225.                     else write(outfile, ch)
  226.       end; {writeout}
  227.  
  228.     begin {FlushLine}
  229.       write ('.');
  230.       writeout(chr(bytesInLine + offset));
  231.       for i := 0 to pred(lineLength) do
  232.         writeout(line[i]);
  233.       writeln (outfile);
  234.       lineLength := 0;
  235.       bytesInLine := 0
  236.     end; {FlushLine}
  237.  
  238.   procedure FlushHunk;
  239.  
  240.     VAR i: integer;
  241.  
  242.     begin {FlushHunk}
  243.       if lineLength = charsPerLine then FlushLine;
  244.       chars[0] := hunk[0] shr 2;
  245.       chars[1] := (hunk[0] shl 4) + (hunk[1] shr 4);
  246.       chars[2] := (hunk[1] shl 2) + (hunk[2] shr 6);
  247.       chars[3] := hunk[2] and sixBitMask;
  248.       {debug;}
  249.       for i := 0 to 3 do
  250.         begin
  251.           line[lineLength] := chr((chars[i] and sixBitMask) + offset);
  252.           {write(line[linelength]:2);}
  253.           lineLength := succ(lineLength)
  254.         end;
  255.       {writeln;}
  256.       bytesInLine := bytesInLine + numbytes;
  257.       numbytes := 0
  258.     end; {FlushHunk}
  259.  
  260.   procedure encode1;
  261.  
  262.     begin {encode1};
  263.       if numbytes = bytesperhunk then flushhunk;
  264.       endofinfile := not (getbyte(hunk[numbytes]));
  265.       if not endofinfile then numbytes := succ(numbytes)  {No succ at EOF -BE}
  266.     end; {encode1}
  267.  
  268.   procedure terminate;
  269.  
  270.     begin {terminate}
  271.       if numbytes > 0 then flushhunk;
  272.       if lineLength > 0
  273.         then
  274.           begin
  275.             flushLine;
  276.             flushLine;
  277.           end
  278.         else flushline;
  279.       writeln (outfile, trailer);
  280.       close (outfile);
  281.       close (inf);
  282.     end; {terminate}
  283.  
  284.  
  285.   begin {uuencode}
  286.     init;
  287.     while not endofinfile do encode1;
  288.     terminate
  289.   end. {uuencode}
  290.