home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / lib / tex / uuencode.shar / uudecode.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1988-04-18  |  5.2 KB  |  216 lines

  1. program uudecode;
  2.  
  3.   CONST defaultSuffix = '.uue';
  4.         offset = 32;
  5.  
  6.   TYPE string80 = string[80];
  7.  
  8.   VAR infile: text;
  9.       outfile: file of byte;
  10.       lineNum: integer;
  11.       line: string80;
  12.  
  13.   procedure Abort(message: string80);
  14.  
  15.     begin {abort}
  16.       writeln;
  17.       if lineNum > 0 then write('Line ', lineNum, ': ');
  18.       writeln(message);
  19.       halt
  20.     end; {Abort}
  21.  
  22.   procedure NextLine(var s: string80);
  23.  
  24.     begin {NextLine}
  25.       LineNum := succ(LineNum);
  26.       write('.');
  27.       readln(infile, s)
  28.     end; {NextLine}
  29.  
  30.   procedure Init;
  31.  
  32.     procedure GetInFile;
  33.  
  34.       VAR infilename: string80;
  35.  
  36.       begin {GetInFile}
  37.         if ParamCount = 0 then abort ('Usage: uudecode <filename>');
  38.         infilename := ParamStr(1);
  39.         if pos('.', infilename) = 0
  40.           then infilename := concat(infilename, defaultSuffix);
  41.         assign(infile, infilename);
  42.         {$i-}
  43.         reset(infile);
  44.         {$i+}
  45.         if IOresult > 0 then abort (concat('Can''t open ', infilename));
  46.         writeln ('Decoding ', infilename)
  47.       end; {GetInFile}
  48.  
  49.     procedure GetOutFile;
  50.  
  51.       var header, mode, outfilename: string80;
  52.           ch: char;
  53.  
  54.       procedure ParseHeader;
  55.  
  56.         VAR index: integer;
  57.  
  58.         Procedure NextWord(var word:string80; var index: integer);
  59.  
  60.           begin {nextword}
  61.             word := '';
  62.             while header[index] = ' ' do
  63.               begin
  64.                 index := succ(index);
  65.                 if index > length(header) then abort ('Incomplete header')
  66.               end;
  67.             while header[index] <> ' ' do
  68.               begin
  69.                 word := concat(word, header[index]);
  70.                 index := succ(index)
  71.               end
  72.           end; {NextWord}
  73.  
  74.         begin {ParseHeader}
  75.           header := concat(header, ' ');
  76.           index := 7;
  77.           NextWord(mode, index);
  78.           NextWord(outfilename, index)
  79.         end; {ParseHeader}
  80.  
  81.       begin {GetOutFile}
  82.         if eof(infile) then abort('Nothing to decode.');
  83.         NextLine (header);
  84.         while not ((copy(header, 1, 6) = 'begin ') or eof(infile)) do
  85.           NextLine(header);
  86.         writeln;
  87.         if eof(infile) then abort('Nothing to decode.');
  88.         ParseHeader;
  89.         assign(outfile, outfilename);
  90.         writeln ('Destination is ', outfilename);
  91.         {$i-}
  92.         reset(outfile);
  93.         {$i+}
  94.         if IOresult = 0 then
  95.           begin
  96.             write ('Overwrite current ', outfilename, '? [Y/N] ');
  97.             repeat
  98.               read (kbd, ch);
  99.               ch := UpCase(ch)
  100.             until ch in ['Y', 'N'];
  101.             writeln(ch);
  102.             if ch = 'N' then abort ('Overwrite cancelled.')
  103.           end;
  104.         rewrite (outfile);
  105.       end; {GetOutFile}
  106.  
  107.     begin {init}
  108.       lineNum := 0;
  109.       GetInFile;
  110.       GetOutFile;
  111.     end; { init}
  112.  
  113.   Function CheckLine: boolean;
  114.  
  115.     begin {CheckLine}
  116.       if line = '' then abort ('Blank line in file');
  117.       CheckLine := not (line[1] in [' ', '`'])
  118.     end; {CheckLine}
  119.  
  120.  
  121.   procedure DecodeLine;
  122.  
  123.     VAR lineIndex, byteNum, count, i: integer;
  124.         chars: array [0..3] of byte;
  125.         hunk: array [0..2] of byte;
  126.  
  127. {    procedure debug;
  128.  
  129.       var i: integer;
  130.  
  131.       procedure writebin(x: byte);
  132.  
  133.         var i: integer;
  134.  
  135.         begin
  136.           for i := 1 to 8 do
  137.             begin
  138.               write ((x and $80) shr 7);
  139.               x := x shl 1
  140.             end;
  141.           write (' ')
  142.         end;
  143.  
  144.       begin
  145.         writeln;
  146.         for i := 0 to 3 do writebin(chars[i]);
  147.         writeln;
  148.         for i := 0 to 2 do writebin(hunk[i]);
  149.         writeln
  150.       end;      }
  151.  
  152.     function nextch: char;
  153.  
  154.       begin {nextch}
  155.         lineIndex := succ(lineIndex);
  156.         if lineIndex > length(line) then abort('Line too short.');
  157.         if not (line[lineindex] in [' '..'`'])
  158.           then abort('Illegal character in line.');
  159. {        write(line[lineindex]:2);}
  160.         if line[lineindex] = '`' then nextch := ' '
  161.                                   else nextch := line[lineIndex]
  162.       end; {nextch}
  163.  
  164.     procedure DecodeByte;
  165.  
  166.       procedure GetNextHunk;
  167.  
  168.         VAR i: integer;
  169.  
  170.         begin {GetNextHunk}
  171.           for i := 0 to 3 do chars[i] := ord(nextch) - offset;
  172.           hunk[0] := (chars[0] shl 2) + (chars[1] shr 4);
  173.           hunk[1] := (chars[1] shl 4) + (chars[2] shr 2);
  174.           hunk[2] := (chars[2] shl 6) + chars[3];
  175.           byteNum := 0  {;
  176.           debug          }
  177.         end; {GetNextHunk}
  178.  
  179.       begin {DecodeByte}
  180.         if byteNum = 3 then GetNextHunk;
  181.         write (outfile, hunk[byteNum]);
  182.         {writeln(bytenum, ' ', hunk[byteNum]);}
  183.         byteNum := succ(byteNum)
  184.       end; {DecodeByte}
  185.  
  186.     begin {DecodeLine}
  187.       lineIndex := 0;
  188.       byteNum := 3;
  189.       count := (ord(nextch) - offset);
  190.       for i := 1 to count do DecodeByte
  191.     end; {DecodeLine}
  192.  
  193.   procedure terminate;
  194.  
  195.     var trailer: string80;
  196.  
  197.     begin {terminate}
  198.       if eof(infile) then abort ('Abnormal end.');
  199.       NextLine (trailer);
  200.       if length (trailer) < 3 then abort ('Abnormal end.');
  201.       if copy (trailer, 1, 3) <> 'end' then abort ('Abnormal end.');
  202.       close (infile);
  203.       close (outfile)
  204.     end;
  205.  
  206.   begin {uudecode}
  207.     init;
  208.     NextLine(line);
  209.     while CheckLine do
  210.       begin
  211.         DecodeLine;
  212.         NextLine(line)
  213.       end;
  214.     terminate
  215.   end.
  216.