home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / cpm / turbopas / decuf10.ark / DECUF.IF1 < prev    next >
Text File  |  1989-09-27  |  15KB  |  497 lines

  1. {* ----------------------------------------------------------------- *
  2.  *                                                                   *
  3.  *       U S E R   I N T E R F A C E    P R O C E D U R E S          *
  4.  *                                                                   *
  5.  * ----------------------------------------------------------------- *}
  6.  
  7. procedure DisplayHelpInfo ;
  8. {*
  9.  * DisplayHelpInfo - Display a short description of this program on
  10.  *                   the standard output file.
  11.  *}
  12. begin
  13.    WriteLn( 'DecUF (DECode_Uuencoded_File)  v 1.0' ) ;
  14.    Write  ( 'Usage  : DecUF <InputFile> [/o<OutputPath>]' ) ;
  15.    WriteLn( ' [/c{+,-}] [/s{+,-}] [/v{+,-}]' ) ;
  16.    WriteLn ;
  17.    WriteLn( 'Written by W. Nelis, Nelis@NLR.NL, 199106' ) ;
  18.    WriteLn ;
  19. end ;  { of DisplayHelpInfo }
  20.  
  21. procedure Panic( Severity : ErrorTypes ; ErrorMsg : Message ) ;  forward ;
  22.  
  23. procedure CrackParameters ;
  24. {*
  25.  * CrackParameters - Proces the parameters supplied to this program.
  26.  *}
  27. type
  28.    Parameters = ( InputFile  ,    { Drive/user/name of input file }
  29.                   OutputPath ,    { Drive/user for decoded files }
  30.                   FileCount  ,    { Input file contains one encoded file }
  31.                   CheckMode  ,    { Strict or relaxed checking }
  32.                   Verbose    ) ;  { Progress report enabled }
  33. var
  34.   Specified : set of Parameters ;  { Specified parameters }
  35.   NextParam :     KeywordString ;  { Next parameter from command line }
  36.   ColonPos  :           Integer ;  { Position of ':' in path name }
  37.   I         :           Integer ;  { Loop control variable }
  38.  
  39.  procedure ParameterError ;
  40.  {*
  41.   * ParameterError : Issue an error meesage about a parameter in error.
  42.   *                  The parameter in question is ignored.
  43.   *}
  44.  begin
  45.     Panic( Informative, 'Illegal Parameter "'+NextParam+'". It is ignored' ) ;
  46.  end;  { of ParameterError }
  47.  
  48.  procedure SetFlag( var Variable : Boolean ;  VarType : Parameters ) ;
  49.  {*
  50.   * SetFlag : Set the option Variable to TRUE if the third character in the
  51.   *           parameterstring is a '+' sign and set it to FALSE if it is a
  52.   *           '-' sign.  The presence of the option is saved in Specified.
  53.   *}
  54.  begin
  55.    if VarType in Specified then
  56.      ParameterError
  57.    else
  58.      if (Length(NextParam)=3) and (NextParam[3] in ['+','-']) then
  59.       begin
  60.        Specified:= Specified + [VarType] ;
  61.        Variable := NextParam[3]='+' ;
  62.       end
  63.      else
  64.        ParameterError ;
  65.  end ;  { of SetFlag }
  66.  
  67. begin
  68.    Specified:= [] ;  { Empty set of specified parameters }
  69.    for I:= 1 to ParamCount do
  70.     begin
  71.      NextParam:= ParamStr(I) ;
  72.      if (Length(NextParam)>1) and (NextParam[1]='/') then
  73. {*
  74.  * The parameter on the command line has the format /KV, in which 'K' is
  75.  * a one-character keyword and V the associated value.
  76.  *}
  77.       begin
  78.        case NextParam[2] of
  79. {*
  80.  * Specify the path, that is the drive and the user number, to the area
  81.  * to save the decoded file(s).
  82.  *}
  83.        'O' : begin
  84.                if Outputpath in Specified then
  85.                  ParameterError
  86.                else  { OutputPath is not yet specified }
  87.                 begin
  88.                  Specified     := Specified + [OutputPath] ;
  89.                  OutputFilePath:= Copy( NextParam, 3, 255 ) ;
  90.                  ColonPos      := Pos( ':', OutputFilePath ) ;
  91.                  if ColonPos=0 then
  92.                    OutputFilePath:= OutputFilePath + ':'
  93.                  else
  94.                    OutputFilePath:= Copy( OutputFilePath, 1, ColonPos ) ;
  95.                 end ;  { of else }
  96.              end ;  { of case O }
  97. {*
  98.  * Specify whether the input file contains one (S+) or more (S-) encoded
  99.  * files.
  100.  *}
  101.        'S' : SetFlag( OnlyOneFile   , FileCount ) ;
  102. {*
  103.  * Specify whether an error in the format is a fatal error (C+) or is to
  104.  * be ignored (C-).  In the latter case email headers are allowed within
  105.  * the input file.
  106.  *}
  107.        'C' : SetFlag( StrictChecking, CheckMode ) ;
  108. {*
  109.  * Specify whether a progres report, together with statistics, is to be
  110.  * generated (V+) or not (V-).
  111.  *}
  112.        'V' : SetFlag( VerboseMode   , Verbose   ) ;
  113.  
  114.        else  { the parameter is not supported }
  115.          ParameterError ;
  116.        end ;  { of cases }
  117.       end    { of if }
  118. {*
  119.  * The parameter on the command line is not of the format /KV, thus it must
  120.  * be the name of the input file.
  121.  *}
  122.      else
  123.       begin
  124.        if InputFile in Specified then
  125.          ParameterError
  126.        else
  127.         begin
  128.          Specified    := Specified + [InputFile] ;
  129.          InputFileName:= NextParam ;
  130.          if Pos( '.', InputFileName )=0 then
  131.            InputFileName:= InputFileName + DefaultExtension ;
  132.         end ;  { of else }
  133.       end ;  { of else }
  134.     end ;  { of for }
  135.  
  136. {*
  137.  * The inputfile must have been specified.
  138.  *}
  139.    if not (InputFile in Specified) then
  140.      Panic( Catastrophic, 'No input file specified' ) ;
  141. end ;  { of CrackParameters }
  142.  
  143. procedure DisplayStatistics ;
  144. {*
  145.  * DisplayStatistics - Display the statistics of this conversion run.
  146.  *}
  147. var
  148.    ByteCount : Real ;  { Actual number of bytes written }
  149. begin
  150.    ByteCount:= 128.0 * BytesWritten ;
  151.    Write  ( ^M ) ;  ClrEol ;
  152.    WriteLn ;
  153.    WriteLn( 'Number of lines read ....... ',         LinesRead:10 ) ;
  154.    WriteLn( 'Number of lines written .... ',      LinesWritten:10 ) ;
  155.    WriteLn( 'Number of characters read .. ',    CharactersRead:10 ) ;
  156.    WriteLn( 'Number of bytes written .... ',       ByteCount:10:0 ) ;
  157.    WriteLn( 'Number of heap flushes ..... ',       HeapFlushes:10 ) ;
  158.    WriteLn( 'Number of lines skipped .... ',      LinesSkipped:10 ) ;
  159.    WriteLn( 'Number of characters skipped ', CharactersSkipped:10 ) ;
  160. end ;  { of DisplayStatistics }
  161.  
  162. procedure PresetDecodeTable ;
  163. {*
  164.  * PresetDecodeTable - Preset the character-to-sextet conversion table
  165.  *                     to its default.
  166.  *}
  167. var
  168.    I : Char ;  { Loop control variable }
  169. begin
  170.    for I:= ' ' to '_' do
  171.      DecodeTable[I]:= Ord(I) - Ord(' ') ;
  172.    for I:= Succ('_') to Chr(255) do
  173.      DecodeTable[I]:= $FF ;
  174.  
  175.    DecodeTable['`']:= DecodeTable[' '] ;
  176. end ;  { of PresetDecodeTable }
  177.  
  178. {* ----------------------------------------------------------------- *
  179.  *                                                                   *
  180.  *        P R O L O G U E S   A N D   E P I L O G U E S              *
  181.  *                                                                   *
  182.  * ----------------------------------------------------------------- *}
  183. {*
  184.  * Both the execution of this program and the conversion of one file
  185.  * are encapsulated between a prologue and an epilogue.
  186.  *}
  187.  
  188. procedure CloseOutputFile ;  forward ;
  189.  
  190. procedure FilePrologue ;
  191. {*
  192.  * FilePrologue - Preset the global variables prior to the decoding of
  193.  *                the (next) file.
  194.  *}
  195. begin
  196.    OutputFileName   := OutputFilePath + 'NoName.XYZ' ;
  197.    OutputFileOpen   := False ;
  198.  
  199.    PresetDecodeTable ;
  200.    DecodeState      := Sextet0 ;
  201.    LineFormat       := Unknown ;
  202.  
  203.    BytesWritten     := 0 ;
  204.    CharactersRead   := 0 ;
  205.    CharactersSkipped:= 0 ;
  206.    HeapFlushes      := 0 ;
  207.    LinesRead        := 0 ;
  208.    LinesSkipped     := 0 ;
  209.    LinesWritten     := 0 ;
  210.  
  211.    AllocateChunk ;  { Reserve space for output data }
  212. end ;  { of FilePrologue }
  213.  
  214. procedure FileEpilogue ;
  215. {*
  216.  * FileEpilogue - Finish processing of the current output file.  The
  217.  *                global variables, except for the options, are set to
  218.  *                their default value.
  219.  *}
  220. begin
  221. {*
  222.  * Finish processing on the current result file.
  223.  *}
  224.    CloseOutputFile ;
  225.    if VerboseMode then
  226.      DisplayStatistics ;
  227. {*
  228.  * (P)reset global variables.
  229.  *}
  230.    ReleaseChunks ;  { Reset chunklist pointers, just to be sure }
  231. end ;  { of FileEpilogue }
  232.  
  233. procedure ProgramPrologue ;
  234. {*
  235.  * ProgramPrologue - Preset the global variables and interpret the command
  236.  *                   line options.
  237.  *}
  238. begin
  239. {*
  240.  * Preset the global variables.
  241.  *}
  242.    HeadChunkList:= Nil ;
  243.    TailChunkList:= Nil ;
  244.    NextLine     := ' ' ;
  245.    LineIndex    :=   1 ;
  246.    ErrorsInLine := [ ] ;
  247. {*
  248.  * Set defaults for all the options
  249.  *}
  250.    OutputFilePath:= Chr( Bdos($19) + Ord('A') )  + ':' ;
  251.    OnlyOneFile   := False ;
  252.    StrictChecking:= False ;
  253.    VerboseMode   := True  ;
  254. {*
  255.  * Now it is time to execute the file prologue: it resets the various
  256.  * global variables, which MUST have been (re)set in case the error
  257.  * processor is invoked!
  258.  *}
  259.    FilePrologue ;
  260.  
  261. {*
  262.  * Read the command line and extract the options.
  263.  *}
  264.    if ParamCount=0 then
  265.     begin
  266.      DisplayHelpInfo ;
  267.      UnInitFileNameUnit ;
  268.      Halt ;
  269.     end
  270.    else
  271.      CrackParameters ;
  272. end ;  { of ProgramPrologue }
  273.  
  274. procedure ProgramEpilogue ;
  275. {*
  276.  * ProgramEpilogue - Clean up before termination of the program.
  277.  *}
  278. begin
  279.    Close( InputFile ) ;
  280.    CloseOutputFile ;
  281. end ;  { of ProgramEpilogue }
  282.  
  283. procedure Panic ;
  284. {*
  285.  * Panic - Proces an error condition.
  286.  *}
  287. begin
  288. {*
  289.  * Exit from this routine, if the error is to be ignored.
  290.  *}
  291.    if (Severity=Warning) and (not StrictChecking) then
  292.      Exit ;
  293. {*
  294.  * Remove the progres report line from the screen.
  295.  *}
  296.    if VerboseMode then
  297.     begin
  298.      Write( ^M ) ;  { Goto left side of screen }
  299.      ClrEol      ;  { Remove progres report }
  300.     end ;  { of if }
  301. {*
  302.  * Display the errormessage, together with more detailed messages, if
  303.  * available.
  304.  *}
  305.    if LinesRead=0 then
  306.      Write( 'Error' )
  307.    else
  308.      Write( 'Error at line ', LinesRead ) ;
  309.    WriteLn( ' - ', ErrorMsg, '.' ) ;
  310.  
  311.    if IllegalCharacter in ErrorsInLine then
  312.      WriteLn( ' - Illegal character found.' ) ;
  313.    if Overflow         in ErrorsInLine then
  314.      WriteLn( ' - Internal line buffer too small.' ) ;
  315.    if IllegalFormat    in ErrorsInLine then
  316.      WriteLn( ' - Length field cannot be decoded.' ) ;
  317.    if WrongLength      in ErrorsInLine then
  318.      WriteLn( ' - Length field wrong.' ) ;
  319.    if WrongTerminator  in ErrorsInLine then
  320.      WriteLn( ' - Line terminator is not ''M''.' ) ;
  321. {*
  322.  * Take further actions, den pending on the type of error.
  323.  *}
  324.    if Severity=Catastrophic then
  325.     begin
  326.      WriteLn( 'Program premature terminated.' ) ;
  327.      ProgramEpilogue ;
  328.      UnInitFileNameUnit ;
  329.      Halt ;
  330.     end
  331.    else
  332.      if Severity<>Informative then
  333.       begin
  334.        if OutputFileOpen then
  335.         begin
  336.          WriteLn( 'File ', OutputFileName, ' is erased.' ) ;
  337.          ReleaseChunks ;       { Destroy any data gathered in chunks }
  338.          CloseOutputFile ;     { Close the result file and .. }
  339.          Erase( OutputFile ) ; { destroy the result file too }
  340.         end ;  { of if }
  341.        ProcessingState:= Completed ;  { Skip rest of file }
  342.       end ;  { of if/else }
  343. end ;  { of Panic }
  344.  
  345.  
  346. {*
  347.  * FILES : Opening and closing of both the input file and the result
  348.  * file.
  349.  *}
  350.  
  351. procedure OpenInputFile ;
  352. {*
  353.  * OpenInputFile - Open the input file.
  354.  *}
  355. begin
  356. {*
  357.  * Rebuild the input file name.
  358.  *}
  359.    SplitFileName( InputFileDesc, InputFileName ) ;
  360.    InputFileName:= ExpandFileName( InputFileDesc, DUNE_Format ) ;
  361.    RegisterFile( InputFileDesc, InputFile ) ;
  362.  
  363.    Assign( InputFile, ExpandFileName(InputFileDesc,DNE_Format) ) ;
  364.    {$I-}  Reset(InputFile) ;  {$I+}
  365.    if IOResult<>0 then  { the file doesn't exists }
  366.      Panic( Catastrophic, 'Can''t find file '+InputFileName )
  367.    else
  368.      if Eof(InputFile) then
  369.        Panic( Catastrophic, 'File '+InputFileName+' is empty' ) ;
  370. end ;  { of OpenInputFile }
  371.  
  372. procedure OpenOutputFile ;
  373. {*
  374.  * OpenOutputfile - Open the result file.
  375.  *}
  376. var
  377.    Answer : Char ;  { Answer from user }
  378. begin
  379. {*
  380.  * Rebuild output file name.
  381.  *}
  382.    SplitFileName( OutputFileDesc, OutputFileName ) ;
  383.    OutputFileName:= ExpandFileName( OutputFileDesc, DUNE_Format ) ;
  384.    RegisterFile( OutputFileDesc, OutputFile ) ;
  385.  
  386.    Assign( OutputFile, ExpandFileName(OutputFileDesc,DNE_Format) ) ;
  387.    {$I-} Reset( OutputFile ) ;  {$I+}
  388.    if IOResult=0 then  { the file exists already }
  389.     begin
  390.      Close( OutputFile ) ;
  391.      repeat
  392.        Write( ^G^M'Warning - file ', OutputFileName, ' exists. ' ) ;
  393.        Write( 'Overwrite (destroy) it (y/n)? ' ) ;  ClrEol ;
  394.        Read ( Kbd, Answer ) ;
  395.        Answer:= UpCase( Answer ) ;
  396.      until Answer in ['N','Y'] ;
  397.      WriteLn( Answer ) ;
  398.      if Answer='N' then
  399.       begin
  400.        ProcessingState:= Completed ;  { Skip this encoded file }
  401.        Exit ;
  402.       end ;  { of if }
  403.     end ;  { of if }
  404.  
  405. {$I-}  Rewrite( OutputFile ) ;  {$I+}
  406.    if IOResult=0 then
  407.      OutputFileOpen:= True
  408.    else
  409.      Panic( Catastrophic, 'Can''t write on file '+OutputFilename ) ;
  410. end ;  { of OpenOutputFile }
  411.  
  412. procedure CloseOutputFile ;
  413. {*
  414.  * CloseOutputFile - Write all buffered data to the result file and
  415.  *                   close it.
  416.  *}
  417. begin
  418.    if OutputFileOpen then
  419.     begin
  420.      FlushChunks ;
  421.      Close( OutputFile ) ;
  422.      OutputFileOpen:= False ;
  423.     end ;  { of if }
  424. end ;  { of CloseOutputFile }
  425.  
  426.  
  427. {*
  428.  * Handling of the input from the input file.
  429.  *}
  430.  
  431. procedure ReadNextLine ;
  432. {*
  433.  * ReadNextLine - Read the next line from the input file into NextLine.
  434.  *                Non-printable characters are removed from the line
  435.  *                image.
  436.  *}
  437. var
  438.    LineLength : Integer ;  { Current length of line read }
  439.    I          : Integer ;  { Loop control variable }
  440. begin
  441.    NextLine    :=    '' ;
  442.    ErrorsInLine:=    [] ;
  443.    if not Eof(InputFile) then
  444.     begin
  445.      ReadLn( InputFile, NextLine ) ;
  446.      CharactersRead:= CharactersRead + Length(NextLine) ;
  447. {*
  448.  * Remove the trailing blanks from string : uuencoded files
  449.  * are (should be) insensitive to trailing blank removal.
  450.  *}
  451.      LineLength:= Length(NextLine) ;
  452.      while (LineLength>0) and (NextLine[LineLength]=' ') do
  453.        Dec(LineLength) ;
  454.      if LineLength<Length(NextLine) then
  455.        NextLine:= Copy( NextLine, 1, LineLength ) ;
  456. {*
  457.  * See if there are any control-characters in the line read.  Optionally
  458.  * these characters could be removed.  However, the line probably will
  459.  * be rejected without interpretation.
  460.  *}
  461.      if LineLength>0 then
  462.        for I:= LineLength downto 1 do
  463.          if NextLine[I]<' ' then
  464.           begin
  465.            ErrorsInLine:= ErrorsInLine + [IllegalCharacter] ;
  466. (*         NextLine    := Copy( NextLine,   1,        I-1 ) +
  467.                           Copy( NextLine, I+1, LineLength ) ;  *)
  468.            Inc( CharactersSkipped ) ;
  469.           end ;  { of if/for/if }
  470.  
  471.     end ;  { of if Eof() }
  472.    Inc( LinesRead ) ;
  473. end ;  { of ReadNextLine }
  474.  
  475. function NextWord : KeyWordString ;
  476. {*
  477.  * NextWord - Extract the next word from NextLine starting at character
  478.  *            offset Index.
  479.  *}
  480. var
  481.    SomeWord : KeyWordString ;
  482. begin
  483.    SomeWord:= '' ;
  484.    while (LineIndex<=Length(NextLine)) and
  485.          (NextLine[LineIndex]=' ')    do
  486.      LineIndex:= Succ(LineIndex) ;
  487.  
  488.    while (LineIndex<=Length(NextLine)) and
  489.          (NextLine[LineIndex]<>' ')    do
  490.     begin
  491.      SomeWord:= SomeWord + NextLine[LineIndex] ;
  492.      LineIndex:= Succ(LineIndex) ;
  493.     end ;  { of while }
  494.    NextWord:= SomeWord ;
  495. end ;  { of NextWord }
  496.  
  497.