PROGRAM uudecode; {v1.1 Toad Hall Tweak, 9 May 90 - Reformatted in case, style, indentation, etc. to my preferences. - Tweaked for Turbo Pascal v5.0 David Kirschbaum Toad Hall } Uses Dos,Crt; CONST DefaultSuffix = '.uue'; OFFSET = 32; TYPE Str80 = STRING[80]; VAR Infile: TEXT; Fi : FILE OF Byte; Outfile: FILE OF Byte; linenum: INTEGER; Line: Str80; size,remaining : longint; {v1.1 REAL;} PROCEDURE Abort(Msg: Str80); BEGIN WRITELN; IF linenum > 0 THEN WRITE('Line ', linenum, ': '); WRITELN(Msg); HALT END; {of Abort} PROCEDURE NextLine(VAR S: Str80); BEGIN Inc(linenum); {write('.');} READLN(Infile, S); Dec(remaining,LENGTH(S)-2); {-2 is for CR/LF} WRITE('bytes remaining: ',remaining:7,' (', remaining/size*100.0:3:0,'%)',CHR(13)); END; {of NextLine} PROCEDURE Init; PROCEDURE GetInFile; VAR Infilename: Str80; BEGIN IF ParamCount = 0 THEN Abort ('Usage: uudecode '); Infilename := ParamStr(1); IF POS('.', Infilename) = 0 THEN Infilename := CONCAT(Infilename, DefaultSuffix); ASSIGN(Infile, Infilename); {$I-} RESET(Infile); {$i+} IF IOResult > 0 THEN Abort (CONCAT('Can''t open ', Infilename)); WRITELN ('Decoding ', Infilename); ASSIGN(Fi,Infilename); RESET(Fi); size := FileSize(Fi); CLOSE(Fi); { IF size < 0 THEN size:=size+65536.0; } remaining := size; END; {of GetInFile} PROCEDURE GetOutFile; VAR Header, Mode, Outfilename: Str80; Ch: CHAR; PROCEDURE ParseHeader; VAR index: INTEGER; PROCEDURE NextWord(VAR Word:Str80; VAR index: INTEGER); BEGIN Word := ''; WHILE Header[index] = ' ' DO BEGIN Inc(index); IF index > LENGTH(Header) THEN Abort ('Incomplete header') END; WHILE Header[index] <> ' ' DO BEGIN Word := CONCAT(Word, Header[index]); Inc(index); END END; {of NextWord} BEGIN {ParseHeader} Header := CONCAT(Header, ' '); index := 7; NextWord(Mode, index); NextWord(Outfilename, index) END; {of ParseHeader} BEGIN {GetOutFile} IF EOF(Infile) THEN Abort('Nothing to decode.'); NextLine (Header); WHILE NOT ((COPY(Header, 1, 6) = 'begin ') OR EOF(Infile)) DO NextLine(Header); WRITELN; IF EOF(Infile) THEN Abort('Nothing to decode.'); ParseHeader; ASSIGN(Outfile, Outfilename); WRITELN ('Destination is ', Outfilename); {$I-} RESET(Outfile); {$I+} IF IOResult = 0 THEN BEGIN WRITE ('Overwrite current ', Outfilename, '? [Y/N] '); REPEAT Ch := Upcase(ReadKey); {v1.1} UNTIL Ch IN ['Y', 'N']; WRITELN(Ch); IF Ch = 'N' THEN Abort ('Overwrite cancelled.') END; REWRITE (Outfile); END; {of GetOutFile} BEGIN {Init} linenum := 0; GetInFile; GetOutFile; END; { init} FUNCTION Check_Line: BOOLEAN; BEGIN IF Line = '' THEN Abort ('Blank line in file'); Check_Line := NOT (Line[1] IN [' ', '`']) END; {of Check_Line} PROCEDURE DecodeLine; VAR lineIndex, byteNum, count, i: INTEGER; chars: ARRAY [0..3] OF Byte; hunk: ARRAY [0..2] OF Byte; { procedure debug; var i: integer; procedure writebin(x: byte); var i: integer; begin for i := 1 to 8 do begin write ((x and $80) shr 7); x := x shl 1 end; write (' ') end; begin writeln; for i := 0 to 3 do writebin(chars[i]); writeln; for i := 0 to 2 do writebin(hunk[i]); writeln end; } FUNCTION Next_Ch: CHAR; BEGIN Inc(lineIndex); IF lineIndex > LENGTH(Line) THEN Abort('Line too short.'); IF NOT (Line[lineindex] IN [' '..'`']) THEN Abort('Illegal character in line.'); { write(line[lineindex]:2);} IF Line[lineindex] = '`' THEN Next_Ch := ' ' ELSE Next_Ch := Line[lineIndex] END; {of Next_Ch} PROCEDURE DecodeByte; PROCEDURE GetNextHunk; VAR i: INTEGER; BEGIN FOR i := 0 TO 3 DO chars[i] := ORD(Next_Ch) - OFFSET; hunk[0] := (chars[0] ShL 2) + (chars[1] ShR 4); hunk[1] := (chars[1] ShL 4) + (chars[2] ShR 2); hunk[2] := (chars[2] ShL 6) + chars[3]; byteNum := 0 {; debug } END; {of GetNextHunk} BEGIN {DecodeByte} IF byteNum = 3 THEN GetNextHunk; WRITE (Outfile, hunk[byteNum]); {writeln(bytenum, ' ', hunk[byteNum]);} Inc(byteNum) END; {of DecodeByte} BEGIN {DecodeLine} lineIndex := 0; byteNum := 3; count := (ORD(Next_Ch) - OFFSET); FOR i := 1 TO count DO DecodeByte END; {of DecodeLine} PROCEDURE Terminate; VAR Trailer: Str80; BEGIN IF EOF(Infile) THEN Abort ('Abnormal end.'); NextLine (trailer); IF LENGTH (trailer) < 3 THEN Abort ('Abnormal end.'); IF COPY (trailer, 1, 3) <> 'end' THEN Abort ('Abnormal end.'); CLOSE (Infile); CLOSE (Outfile) END; {of Terminate} BEGIN {uudecode} Init; NextLine(Line); WHILE Check_Line DO BEGIN DecodeLine; NextLine(Line) END; Terminate END.