home *** CD-ROM | disk | FTP | other *** search
/ Garbo / Garbo.cdr / pc / doc_net / starter.2 < prev    next >
Encoding:
Text File  |  1990-05-31  |  5.6 KB  |  229 lines

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