program DECode_Uuencoded_File ; {$A+} { Generate NON-recursive code (shorter and faster) } {$C+} { Do check for ^C and ^S during console output } {$R-} { Check all subrange variables to be within range } {$U-} { Do NOT check for ^C continuously } {$W2} { Allow up to 2 simultanous active WITH statements } {* ==================================================================== * * DecUF - Decode 'uuencoded' files. The input file may contain one * or more 'uuencoded' files. * * Version 1.0 , 199101: Original coding * Wim J.M. Nelis (Nelis@NLR.NL) * Rozenhof 4 * 8316 CX Marknesse * the Netherlands * Version 1.1 , 199105: Include extended file name unit. * Version 1.2 , 199106: Minor modifications in comment. This version * is included in the SimTel20 archives. * Version 1.3 , 199209: Introduce third kind of encoded files, namely * those with a checksum at the end of each line. *} const CurrentDrive = 0 ; { Indication for current drive in DOS calls } DefaultExtension = '.UUE' ; { Default extension of input file name } MaxChunkSize = 512 ; { Max size of one chunk of converted data } type KeyWordString = string[16] ; { A keyword, possibly a file name } Message = string[50] ; { (Error) message } ChunkPtr = ^Chunks ; ChunkSizes = 0..MaxChunkSize ; Chunks = record NextChunk : ChunkPtr ; { Pointer to next chunk } ChunkSize : ChunkSizes ; { Size of this chunk } Data : array[1..MaxChunkSize] of Byte ; end ; DecodingStates = ( Sextet0, { Decode 4 sextets into 3 octets } Sextet1, Sextet2, Sextet3 ) ; LineFormats = ( Unknown, { Format is not known yet } Basic , { Basic format, length + encoded data } Extended , { Either Trmntr or ChckSm } Trmntr , { Terminator at end of line } ChckSm ) ; { Checksum at end of line } ProcessingStates = ( Look_For_Start, { Look for either TABLE or BEGIN } Reading_Table , { Read the conversion table } Reading_Begin , { Proces BEGIN statement } Reading_Data , { Convert the next data line } Completed ) ; { END encountered } ErrorTypes = ( Catastrophic, { Error is fatal to program execution } Fatal , { Error is fatal to file conversion } Warning , { Error can optionally be ignored } Informative ) ; { Error is result of other error } LineErrors = ( IllegalCharacter, { Control character skipped } Overflow , { Line buffer too short } IllegalFormat , { Length field cannot be decoded } WrongLength , { Line length mismatch } WrongTerminator ) ; { Terminator is not 'M' } {$IEXTFN.UNT} var {* --- Input/Output files --- *} InputFile : Text ; { Input file } InputFileName : FullFileNames ; { Input file Name } InputFileDesc : FileDescriptors ; { Input file name, internal format } OutputFile : File ; { Result file, may be any type } OutputFilePath : FullFileNames ; { Path to directory to receive result file } OutputFileName : FullFileNames ; { Full name of result file } OutputFileDesc : FileDescriptors ; { Outputfile name, internal format } OutputFileOpen : Boolean ; { OutputFile is opened } {* --- Option flags --- *} OnlyOneFile : Boolean ; { Input file contains one encoded file } StrictChecking : Boolean ; { Check every line in encoded file } VerboseMode : Boolean ; { Give a progres report } DecodeTable : array[' '..#255] of Byte ; { Decoding table } DecodeState : DecodingStates ; HeadChunkList : ChunkPtr ; { Head of the list of chunks } TailChunkList : ChunkPtr ; { Tail of the list of chunks } ProcessingState : ProcessingStates ; { Current state } NextLine : string[80] ; { Current line } LineIndex : 1..80 ; { Index in NextLine } LineFormat : LineFormats ; { Format of encoded lines } CheckSum : Integer ; { Checksum of current line } Terminator : Char ; { Terminator of current line } ErrorsInLine : set of LineErrors ; { Errors detected in current line } {* --- Statistics per result file --- *} BytesWritten : Integer ; { Number of bytes written } CharactersRead : Integer ; { Number of characters read } CharactersSkipped : Integer ; { Number of characters skipped } HeapFlushes : Integer ; { Number of times the heap is flushed } LinesRead : Integer ; { Number of lines read } LinesSkipped : Integer ; { Number of lines NOT decoded } LinesWritten : Integer ; { Number of lines written } {* * The functions Dec and Inc are included to obtain a little bit of * compatibility with TP 5.0 and higher. *} procedure Dec( var SomeValue : Integer ) ; begin SomeValue:= Pred( SomeValue ) ; end ; { of Dec } procedure Inc( var SomeValue : Integer ) ; begin SomeValue:= Succ( SomeValue ) ; end ; { of Inc } {$IDECUF.IF0} {$IDECUF.IF1} {$IDECUF.IF2} {* * Start of main program. *} var Done : Boolean ; { Conversion of file completed } begin InitFileNameUnit ; ProgramPrologue ; OpenInputFile ; ProcessingState:= Look_For_Start ; Done := False ; while not (Eof(InputFile) or Done) do begin ReadNextLine ; case ProcessingState of Look_For_Start : CheckForStart ; Reading_Table : ReadConversionTable ; Reading_Begin : ProcesBegin ; Reading_Data : ProcesData ; Completed : if OnlyOneFile then Done:= True else CheckForStart ; else Panic( Fatal, 'Unexpected processing state' ) ; end ; { of case } end ; { of while } case ProcessingState of Look_For_Start : Panic( Informative, 'No valid encoded data found on '+InputFileName ) ; Reading_Table , Reading_Begin , Reading_Data : Panic( Informative, 'Unexpected end-of-file found on'+InputFileName ) ; end ; { of cases } ProgramEpilogue ; UnInitFileNameUnit ; end.