home *** CD-ROM | disk | FTP | other *** search
/ Brotikasten / BROTCD01.iso / cpm / uucode.lbr / UUDECODE.PZS / UUDECODE.PAS
Pascal/Delphi Source File  |  1988-11-13  |  8KB  |  301 lines

  1. program uudecode;
  2.  
  3.   CONST defaultSuffix = '.uue';
  4.         offset = 32;
  5.  
  6.   TYPE string80 = string[80];
  7.  
  8.   VAR infile: text;
  9.       outf : file;
  10.       lineNum: integer;
  11.       line: string80;
  12.       outfilename : string80;
  13.  
  14. {Binary file read added by Ross Alford,  ...!mcnc!ecsvax!alford.  The original
  15.  MSDOS versions of uuencode/decode just use read/write on a FILE OF BYTE.
  16.  CP/M Turbo expects some file info to be stored in the first 4 bytes of files
  17.  of any type other than TEXT.  Putbyte (below) and Getbyte (in UUENCODE)
  18.  bypass this 'feature' by using blockread and blockwrite.  The only global
  19.  variables either use are  'infilename' and 'inf' or 'outfilename' and 'outf'}
  20.  
  21. procedure putbyte(b : byte; flush : boolean);
  22.  
  23. type bufptr = ^bufrec;
  24.      bufrec = record
  25.                 next : bufptr;
  26.                 buffer : array[1..128] of byte
  27.               end;
  28.  
  29. const sectstobuf = 8;                {max number of sectors to buffer}
  30.       sectswritten : integer = 1;    {constants are essentially statics}
  31.       bytptr : integer = 1;
  32.       notopen : boolean = TRUE;
  33.       infsize : integer = 0;
  34.       listsave : integer  = 0;
  35.       tempsave : integer = 0;
  36.  
  37. var list,temp,temp2 : bufptr;
  38.     i : integer;
  39.  
  40. begin
  41.   if flush then
  42.     begin
  43.       list := ptr(listsave);
  44.       temp := list;
  45.       for i := 1 to sectswritten do
  46.         begin
  47.           blockwrite(outf,temp^.buffer,1);
  48.           temp := temp^.next
  49.         end;
  50.       close(outf)
  51.     end
  52.     else begin
  53.       if notopen then
  54.         begin
  55.           notopen := FALSE;
  56.           assign(outf,outfilename);
  57.           {$i-}
  58.           reset(outf);
  59.           {$i+}
  60.           if ioresult = 0 then
  61.             begin
  62.               writeln('File ',outfilename,' exists.  Cannot overwrite.');
  63.               halt
  64.             end;
  65.           {$i-}
  66.           rewrite(outf);
  67.           {$i+}
  68.           if ioresult <> 0 then
  69.             begin
  70.               writeln('Cannot open file ',outfilename,' for output.');
  71.               halt
  72.             end;
  73.           new(list);
  74.           temp := list;
  75.           for i := 1 to sectstobuf - 1 do
  76.             begin
  77.               new(temp2);
  78.               temp2^.next := NIL;
  79.               temp^.next := temp2;
  80.               temp := temp2
  81.             end;
  82.           listsave := ord(list);
  83.           tempsave := listsave;
  84.         end;
  85.       temp := ptr(tempsave);
  86.       if bytptr > 128 then
  87.         begin
  88.           if temp^.next <> NIL then
  89.             begin
  90.               sectswritten := succ(sectswritten);
  91.               temp := temp^.next;
  92.               bytptr := 1
  93.             end
  94.             else begin
  95.               temp := ptr(listsave);
  96.               for i := 1 to sectstobuf do
  97.                 begin
  98.                   blockwrite(outf,temp^.buffer,1);
  99.                   temp := temp^.next
  100.                 end;
  101.               temp := ptr(listsave);
  102.               sectswritten := 1;
  103.               bytptr := 1
  104.             end
  105.         end;
  106.       temp^.buffer[bytptr] := b;
  107.       bytptr := succ(bytptr);
  108.       tempsave := ord(temp)
  109.     end
  110. end;
  111.  
  112.   procedure Abort(message: string80);
  113.  
  114.     begin {abort}
  115.       writeln;
  116.       if lineNum > 0 then write('Line ', lineNum, ': ');
  117.       writeln(message);
  118.       halt
  119.     end; {Abort}
  120.  
  121.   procedure NextLine(var s: string80);
  122.  
  123.     begin {NextLine}
  124.       LineNum := succ(LineNum);
  125.       write('.');
  126.       readln(infile, s)
  127.     end; {NextLine}
  128.  
  129.   procedure Init;
  130.  
  131.     procedure GetInFile;
  132.  
  133.       VAR infilename: string80;
  134.  
  135.       begin {GetInFile}
  136.         if ParamCount = 0 then abort ('Usage: uudecode <filename>');
  137.         infilename := ParamStr(1);
  138.         if pos('.', infilename) = 0
  139.           then infilename := concat(infilename, defaultSuffix);
  140.         assign(infile, infilename);
  141.         {$i-}
  142.         reset(infile);
  143.         {$i+}
  144.         if IOresult > 0 then abort (concat('Can''t open ', infilename));
  145.         writeln ('Decoding ', infilename)
  146.       end; {GetInFile}
  147.  
  148.     procedure GetOutFile;
  149.  
  150.       var header, mode : string80;
  151.           ch: char;
  152.  
  153.       procedure ParseHeader;
  154.  
  155.         VAR index: integer;
  156.  
  157.         Procedure NextWord(var word:string80; var index: integer);
  158.  
  159.           begin {nextword}
  160.             word := '';
  161.             while header[index] = ' ' do
  162.               begin
  163.                 index := succ(index);
  164.                 if index > length(header) then abort ('Incomplete header')
  165.               end;
  166.             while header[index] <> ' ' do
  167.               begin
  168.                 word := concat(word, header[index]);
  169.                 index := succ(index)
  170.               end
  171.           end; {NextWord}
  172.  
  173.         begin {ParseHeader}
  174.           header := concat(header, ' ');
  175.           index := 7;
  176.           NextWord(mode, index);
  177.           NextWord(outfilename, index)
  178.         end; {ParseHeader}
  179.  
  180.       begin {GetOutFile}
  181.         if eof(infile) then abort('Nothing to decode.');
  182.         NextLine (header);
  183.         while not ((copy(header, 1, 6) = 'begin ') or eof(infile)) do
  184.           NextLine(header);
  185.         writeln;
  186.         if eof(infile) then abort('Nothing to decode.');
  187.         ParseHeader;
  188.       end; {GetOutFile}
  189.  
  190.     begin {init}
  191.       lineNum := 0;
  192.       GetInFile;
  193.       GetOutFile;
  194.     end; { init}
  195.  
  196.   Function CheckLine: boolean;
  197.  
  198.     begin {CheckLine}
  199.       if line = '' then abort ('Blank line in file');
  200.       CheckLine := not (line[1] in [' ', '`'])
  201.     end; {CheckLine}
  202.  
  203.  
  204.   procedure DecodeLine;
  205.  
  206.     VAR lineIndex, byteNum, count, i: integer;
  207.         chars: array [0..3] of byte;
  208.         hunk: array [0..2] of byte;
  209.  
  210. {    procedure debug;
  211.  
  212.       var i: integer;
  213.  
  214.       procedure writebin(x: byte);
  215.  
  216.         var i: integer;
  217.  
  218.         begin
  219.           for i := 1 to 8 do
  220.             begin
  221.               write ((x and $80) shr 7);
  222.               x := x shl 1
  223.             end;
  224.           write (' ')
  225.         end;
  226.  
  227.       begin
  228.         writeln;
  229.         for i := 0 to 3 do writebin(chars[i]);
  230.         writeln;
  231.         for i := 0 to 2 do writebin(hunk[i]);
  232.         writeln
  233.       end;      }
  234.  
  235.     function nextch: char;
  236.  
  237.       begin {nextch}
  238.       {}  lineIndex := succ(lineIndex);
  239.         if lineIndex > length(line) then abort('Line too short.');
  240.         if not (line[lineindex] in [' '..'`'])
  241.           then abort('Illegal character in line.');
  242. {        write(line[lineindex]:2);}
  243.         if line[lineindex] = '`' then nextch := ' '
  244.                                   else nextch := line[lineIndex]
  245.       end; {nextch}
  246.  
  247.     procedure DecodeByte;
  248.  
  249.       procedure GetNextHunk;
  250.  
  251.         VAR i: integer;
  252.  
  253.         begin {GetNextHunk}
  254.           for i := 0 to 3 do chars[i] := ord(nextch) - offset;
  255.           hunk[0] := (chars[0] shl 2) + (chars[1] shr 4);
  256.           hunk[1] := (chars[1] shl 4) + (chars[2] shr 2);
  257.           hunk[2] := (chars[2] shl 6) + chars[3];
  258.           byteNum := 0  {;
  259.           debug          }
  260.         end; {GetNextHunk}
  261.  
  262.       begin {DecodeByte}
  263.         if byteNum = 3 then GetNextHunk;
  264.         putbyte(hunk[byteNum],FALSE);
  265.         {writeln(bytenum, ' ', hunk[byteNum]);}
  266.         byteNum := succ(byteNum)
  267.       end; {DecodeByte}
  268.  
  269.     begin {DecodeLine}
  270.       lineIndex := 0;
  271.       byteNum := 3;
  272.       count := (ord(nextch) - offset);
  273.       for i := 1 to count do DecodeByte
  274.     end; {DecodeLine}
  275.  
  276.   procedure terminate;
  277.  
  278.     var trailer: string80;
  279.  
  280.     begin {terminate}
  281.       if eof(infile) then abort ('Abnormal end.');
  282.       NextLine (trailer);
  283.       if length (trailer) < 3 then abort ('Abnormal end.');
  284.       if copy (trailer, 1, 3) <> 'end' then abort ('Abnormal end.');
  285.       close (infile);
  286.       putbyte(26,TRUE)
  287.     end;
  288.  
  289.   begin {uudecode}
  290.     init;
  291.     NextLine(line);
  292.     while CheckLine do
  293.       begin
  294.         DecodeLine;
  295.         NextLine(line)
  296.       end;
  297.     terminate
  298.   end.
  299.  
  300. --------------------CUT HERE------------for uudecode.uue-----------
  301.