home *** CD-ROM | disk | FTP | other *** search
/ C!T ROM 2 / ctrom_ii_b.zip / ctrom_ii_b / PROGRAM / PASCAL / DSUTIL11 / FMERGE / FMERGE.PAS < prev   
Pascal/Delphi Source File  |  1993-09-20  |  18KB  |  559 lines

  1. {-----------------------------------------------------------------------}
  2. { PROJECT        NON-PROFIT HIGH QUALITY PROFESSIONAL SOFTWARE,  }
  3. {            AVAILABLE FOR ALL WORLD                }
  4. { LIBRARY        SYSTEM UTILITIES                                }
  5. { MODULE        FILE_MERGE                                    }
  6. { FILE NAME        FMERGE.PAS                    }
  7. { PURPOSE               MERGE BINARY FILES SPLITTED TO SOME PARTS    } 
  8. { VERSION        1.30                        }
  9. { DATE            20-Sep-93                    }
  10. { DESIGN        Dmitry Stefankov                }
  11. { IMPLEMENTATION    Dmitry Stefankov                 }
  12. { COMPANY        Freelance Software Engineer            }
  13. { ADDRESS        Isakowskogo str, 4-2-30                }
  14. {            Moscow, 123181                    }
  15. {            USSR                        }
  16. {            Tel. 007 (095) 944-6304                }
  17. { COPYRIGHT NOTICE    Copyright (C) 1987-1993, Dmitry Stefankov    }
  18. { RESTRICTED RIGHTS    AVAILABLE ONLY FOR FREE DISTRIBUTION,           }
  19. {            NOT FOR COMMERCIAL PURPOSE            }
  20. { COMPUTER        IBM PC or compatible                }
  21. { OPERATING SYSTEM    MS/PC-DOS Version 3.30 or higher        }
  22. { COMPILER        Turbo Pascal Version 6.0            }
  23. {                       (Borland International Inc.) or compatible      }
  24. { ASSEMBLY LANGUAGE    Microsoft MASM 5.10 or compatible               }
  25. { LINKER        Turbo Pascal internal                           }
  26. { ARGUMENTS             <evenfile>  -   input filename ('even' bytes)   }
  27. {            <oddfile>   -   input filename ('odd' bytes)    }
  28. {            <outfile>   -   resulting file            }
  29. {                       <evencount> -   # of bytes to put early         }
  30. {                       <oddcount>  -   # of bytes to put later         }
  31. { RETURN        See error return codes definitions        }
  32. { REQUIRES        Source Code Files                               }
  33. {                       NONE                                            }
  34. {                       External Object Files                           }
  35. {                       NONE                                            }
  36. {            Maintence Project Files                }
  37. {            NONE                        }
  38. { NATURAL LANGUAGE      English Language                                }
  39. { SPECIAL        None                        }
  40. { DESCRIPTION        1.Read   input  stream (first early, then later)}
  41. {                       2.Format output stream (do entity from # bytes) }
  42. {                       3.Write  output stream (entity)            }
  43. { REVISION HISTORY    Dima Stefankov (DS)                }
  44. {               1.00  11-Aug-92  DS  initilal release        }
  45. {            1.01  06-Mar-93  DS  added more fast block read    }
  46. {                         and writing from/to file   }
  47. {            1.02  23-Mar-93  DS  some style changes        }
  48. {            1.03  30-Mar-93  DS  updated message output    }
  49. {                       1.10  19-May-93  DS  some style updates         }
  50. {                       1.20  15-Aug-93  DS  full overwritten of rd/wr, }
  51. {                                            added parameters to vary of}
  52. {                                            # of bytes transferred from}
  53. {                                            input stream files         }
  54. {            1.30  20-Sep-93  DS  some style updates        }
  55. {-----------------------------------------------------------------------}
  56.  
  57.  
  58. {*======================= PROGRAM HEADER PART ==========================*}
  59.  
  60. PROGRAM MergeBinaryFiles;
  61.  
  62.  
  63. {*** other modules ***}
  64. {*USES;*}
  65.  
  66.  
  67. {** switches for compilation **}
  68. {$S-}        {*  stack checking   *}
  69. {$R-}           {*  range checking   *}
  70.  
  71.  
  72. {* generate version for debugging version *}
  73. {***$DEFINE  DebugVersion}
  74.  
  75.  
  76. {*========================== CONSTANTS PART ============================*}
  77.  
  78. CONST
  79.      asPurpose                  =       'FILE MERGE UTILITY';
  80.      asVersion                  =       '1.30';
  81.      asAuthor                   =       'Dima Stefankov';
  82.      asCopyright                =       'Copyright (c) 1987, 1993';
  83.      asProgram                  =       'FMerge';
  84.      asProgramU                 =       'FMERGE';
  85.      asProgramPrompt            =       asProgram+': ';
  86.  
  87.      { exit codes }
  88.        errTerminateOK           =     0;
  89.        errOnLineHelp        =     1;
  90.        errSourceEvenNotFound    =     2;
  91.        errSourceOddNotFound     =     3;
  92.        errDestDontWrite         =     4;
  93.        errBadEvenCount          =     5;
  94.        errBadOddCount           =     6;
  95.  
  96.  
  97.      { miscellaneous equates }
  98.        achNULL               =        #0;
  99.        achYes                =        'Y';
  100.        achHexPrefix          =        '$';
  101.        aHexRadix             =        16;
  102.  
  103.      { defaults to byte count }
  104.        aEvenCountDef         =        1;
  105.        aOddCountDef          =        1;
  106.        aEvenCountMax         =        4096;
  107.        aOddCountMax          =        4096;
  108.  
  109.      { allocating memory heaps sizes }
  110.        aMaxInBufSize         =       aEvenCountMax;
  111.        aMaxOutBufSize        =       aMaxInBufSize * 2;
  112.  
  113.  
  114. {*====================== TYPED CONSTANTS PART ==========================*}
  115.  
  116. CONST
  117.  
  118.   setHexChars  :    SET OF System.Char  =  ['0'..'9','A'..'F','a'..'f'];
  119.  
  120.   gdwOutBufOfs          :       System.Word          =       0;
  121.   gdwEvenByteCount      :       System.Word          =       aEvenCountDef;
  122.   gdwOddByteCount       :       System.Word          =       aOddCountDef;
  123.   gdwEvenIndex          :       System.Word          =       aEvenCountDef;
  124.   gdwOddIndex           :       System.Word          =       0;
  125.   gdwEvenActualCount    :       System.Word          =       0;
  126.   gdwOddActualCount     :       System.Word          =       0;
  127.   gdwEvenBufTotalCount  :       System.Word          =       0;
  128.   gdwOddBufTotalCount   :       System.Word          =       0;
  129.   agbReadEvenPart       :       System.Boolean       =       System.True;
  130.  
  131.  
  132. {*=========================== VARIABLES PART ===========================*}
  133.  
  134. VAR
  135.   gfInStreamEven, gfInStreamOdd, gfOutStream :  FILE;
  136.   gsInNameEven,   gsInNameOdd,   gsOutName   :  STRING;
  137.  
  138.   glpOutBuf,
  139.   glpInEvenBuf,
  140.   glpInOddBuf                                :  System.Pointer;
  141.   gliEvenInBytesCount,
  142.   gliOddInBytesCount,
  143.   gliInBytesCount                 :  System.Longint;
  144.   gdwCmdCount                                :  System.Word;
  145.   giErrorCode                                :  System.Integer;
  146.   gsTempInput                                :  STRING;
  147.  
  148.  
  149. {*=========================== FORWARD REFERENCES =======================*}
  150.  
  151. PROCEDURE    _ProgramOutputMessage(sMessage : STRING); FORWARD;
  152.  
  153.  
  154. {*=========================== FUNCTIONAL PART ==========================*}
  155.  
  156. FUNCTION  _fnbFileExist(VAR fStruc : FILE; sFileName : STRING) : System.Boolean;
  157. {* Check that file exits. *}
  158. VAR
  159.   bResult  :  System.Boolean;
  160.  
  161. BEGIN
  162.   {** try to open the file **}
  163.   System.Assign(fStruc,sFileName);
  164.   {$I-}
  165.   System.Reset(fStruc);
  166.   {$I+}
  167.  
  168.   {** copy the result of last I/O operation **}
  169.   bResult := (System.IOResult = 0);
  170.  
  171.   IF (bResult)
  172.     THEN  System.Close(fStruc);
  173.   {if-then}
  174.  
  175.   _fnbFileExist := bResult;
  176. END; { _fnbFileExist }
  177.  
  178.  
  179. FUNCTION   _fnchGetFirstChar(sInput : STRING) : System.Char;
  180. {* Returns a first char from string. *}
  181. VAR
  182.   chTemp  :  System.Char;
  183.  
  184. BEGIN
  185.    IF (System.Length(sInput) <> 0)
  186.      THEN  chTemp := sInput[1]
  187.      ELSE  chTemp := achNULL;
  188.    {if-then-else}
  189.   _fnchGetFirstChar := chTemp;
  190. END;
  191. { _fnchGetFirstChar }
  192.  
  193.  
  194. FUNCTION  _fndbHexCharToBin(chIn: System.Char) : System.Byte; assembler;
  195. {* Converts the hexadecimal char to binary number. *}
  196. asm
  197.         mov   al,chIn        { AL = chIn }
  198.         sub   al,'0'         { AL <- AL - '0' }
  199.  
  200.         cmp   al,9           { test for digit 0-9 }
  201.         jbe   @Done
  202.  
  203.         and   al,11011111b   { make uppercase }
  204.         sub   al,'A'-'9'-1   { AL = 'A'..'F' }
  205.  
  206.       @Done:
  207.                              { AL = function result }
  208. END;
  209.     {asm-end}
  210. { _fndbHexCharToBin }
  211.  
  212.  
  213. FUNCTION  _fnliHexStrToBin(sHexInput : STRING; VAR iErrCode : System.Integer) : System.Longint;
  214. {* Converts hexadecimal string to decimal number. *}
  215. VAR
  216.   ddNumber               :       System.Longint;
  217.   dbStrIndex, dbStrLen   :       System.Byte;
  218.  
  219. BEGIN
  220.   iErrCode   := 0;
  221.   ddNumber   := 0;
  222.   dbStrIndex := 1;
  223.   dbStrLen := System.Length(sHexInput);
  224.  
  225.   WHILE (iErrCode = 0) and (dbStrLen > 0) DO
  226.   BEGIN
  227.     IF  (sHexInput[dbStrIndex] IN setHexChars)
  228.     THEN  BEGIN
  229.                ddNumber := ddNumber * aHexRadix +
  230.                            _fndbHexCharToBin(sHexInput[dbStrIndex]);
  231.                System.Inc(dbStrIndex);
  232.                System.Dec(dbStrLen);
  233.           END
  234.     ELSE
  235.         iErrCode  := -1;
  236.     {if-then-else}
  237.   END;
  238.   {while-do}
  239.  
  240.   _fnliHexStrToBin := ddNumber;
  241. END;  { _fnliHexStrToBin }
  242.  
  243.  
  244. FUNCTION  _fnddGetNum(sInput : STRING;VAR iErrorCode : System.Integer)  :  System.Longint;
  245. {* Reads a numeric string. *}
  246. VAR
  247.   ddTemp      :   System.Longint;
  248.  
  249. BEGIN
  250.   IF  (sInput[1] <> achHexPrefix)
  251.      THEN  System.Val(sInput,ddTemp,iErrorCode)
  252.      ELSE  ddTemp := _fnliHexStrToBin(Copy(sInput,2,System.Length(sInput)-1),iErrorCode);
  253.   {if-then-else}
  254.   _fnddGetNum := ddTemp;
  255. END;
  256. { _fnddGetNum }
  257.  
  258.  
  259. FUNCTION  _fndbReadEvenInFile : System.Byte;
  260. {* Buffered reading from even input stream. *}
  261. BEGIN
  262. {$IFDEF  DebugVersion}
  263.   _fndbReadEvenInFile := $0;
  264. {$ELSE}
  265.   IF (gdwEvenActualCount = 0)
  266.     THEN  BEGIN
  267.     _ProgramOutputMessage('Read Even.');
  268.     {$I-}
  269.     System.BlockRead(gfInStreamEven,
  270.                      System.Mem[System.Seg(glpInEvenBuf^):System.Ofs(glpInEvenBuf^)],
  271.                      aMaxInBufSize,gdwEvenBufTotalCount);
  272.     gdwEvenActualCount := gdwEvenBufTotalCount;
  273.     {$I+}
  274.           END;
  275.   {if-then}
  276.    System.Dec(gdwEvenActualCount);
  277.   _fndbReadEvenInFile := System.Mem[System.Seg(glpInEvenBuf^):
  278.                                     (System.Ofs(glpInEvenBuf^)+(gdwEvenBufTotalCount-(1+gdwEvenActualCount)))];
  279. {$ENDIF  DebugVersion}
  280. END;
  281. { _fndbReadEvenInFile }
  282.  
  283.  
  284. FUNCTION  _fndbReadOddInFile : System.Byte;
  285. {* Buffered reading from odd input stream. *}
  286. BEGIN
  287. {$IFDEF  DebugVersion}
  288.   _fndbReadOddInFile := $FF;
  289. {$ELSE}
  290.   IF (gdwOddActualCount = 0)
  291.     THEN  BEGIN
  292.     _ProgramOutputMessage('Read Odd.');
  293.     {$I-}
  294.     System.BlockRead(gfInStreamOdd,
  295.                      System.Mem[System.Seg(glpInOddBuf^):System.Ofs(glpInOddBuf^)],
  296.                      aMaxInBufSize,gdwOddBufTotalCount);
  297.     gdwOddActualCount := gdwOddBufTotalCount;
  298.     {$I+}
  299.           END;
  300.   {if-then}
  301.    System.Dec(gdwOddActualCount);
  302.   _fndbReadOddInFile := System.Mem[System.Seg(glpInOddBuf^):
  303.                                     (System.Ofs(glpInOddBuf^)+(gdwOddBufTotalCount-(1+gdwOddActualCount)))];
  304. {$ENDIF  DebugVersion}
  305. END;
  306. { _fndbReadOddInFile }
  307.  
  308.  
  309.  
  310. {*=========================== PROCEDURAL PART ==========================*}
  311.  
  312. PROCEDURE  _PutByteToOutFile(dbNextChar : System.Byte);
  313. {* Buffered writing to output stream. *}
  314. BEGIN
  315.   IF  (gdwOutBufOfs >= aMaxOutBufSize)
  316.     THEN  BEGIN
  317.          System.BlockWrite(gfOutStream,
  318.                            System.Mem[System.Seg(glpOutBuf^):System.Ofs(glpOutBuf^)],
  319.                            aMaxOutBufSize);
  320.          gdwOutBufOfs := 0;
  321.           END;
  322.   {if-then}
  323.   System.Mem[System.Seg(glpOutBuf^):(System.Ofs(glpOutBuf^)+gdwOutBufOfs)] := dbNextChar;
  324.   System.Inc(gdwOutBufOfs);
  325. END;
  326. {  _PutByteToOutFile }
  327.  
  328.  
  329. PROCEDURE    _ProgramOutputMessage(sMessage : STRING);
  330. {* Output a message with a program name as prefix. *}
  331. BEGIN
  332.   System.WriteLn(asProgramPrompt+sMessage);
  333. END;
  334. { _ProgramOutputMessage }
  335.  
  336.  
  337. PROCEDURE    _CopyrightDisplay;
  338. {* Outputs the copyright notice. *}
  339. BEGIN
  340.      System.WriteLn(asPurpose+
  341.             '  Version '+
  342.             asVersion+
  343.                     ',  '+
  344.             asCopyright
  345.             +'  '+
  346.             asAuthor);
  347. END;  { _CopyrightDisplay }
  348.  
  349.  
  350.  
  351. {*============================== MAIN PART =============================*}
  352.  
  353. BEGIN
  354.  
  355.   _CopyrightDisplay;
  356.  
  357.  
  358.  {* find # of user parameters *}
  359.    gdwCmdCount := System.ParamCount;
  360.  
  361.   IF (gdwCmdCount < 3)
  362.     THEN BEGIN
  363.       _ProgramOutputMessage('on-line help');
  364.       System.WriteLn(' Usage: '+asProgramU+' evenfile oddfile outfile [evencount [oddcount]]');
  365.       System.WriteLn('  evenfile   -  source file (1st part)');
  366.       System.WriteLn('  oddfile    -  source file (2nd part)');
  367.       System.WriteLn('  outfile    -  destination file');
  368.       System.WriteLn('  evencount  -  # of xfr bytes at each pass from 1st part (def=',
  369.                      aEvenCountDef,',max=',aEvenCountMax,')');
  370.       System.WriteLn('  oddcount   -  # of xfr bytes at each pass from 2nd part (def=',
  371.                      aOddCountDef,',max=',aOddCountMax,')');
  372.       System.WriteLn('  Numbers may be decimals, or hexadecimals (first symbol is ''$'' for hex.).');
  373.       System.Halt(errOnLineHelp);
  374.          END
  375.     ELSE BEGIN
  376.       gsInNameEven := System.ParamStr(1);
  377.       gsInNameOdd  := System.ParamStr(2);
  378.       gsOutName    := System.ParamStr(3);
  379.          END;
  380.   {if-then-else}
  381.  
  382.  
  383.   {** source files exists? **}
  384.   IF  NOT(_fnbFileExist(gfInStreamEven,gsInNameEven)) THEN
  385.   BEGIN
  386.     System.WriteLn(asProgramPrompt+'Unable to open file '+gsInNameEven);
  387.     System.Halt(errSourceEvenNotFound);
  388.   END;
  389.   {if-then}
  390.  
  391.   IF  NOT(_fnbFileExist(gfInStreamOdd,gsInNameOdd)) THEN
  392.   BEGIN
  393.     System.WriteLn(asProgramPrompt+'Unable to open file '+gsInNameOdd);
  394.     System.Halt(errSourceOddNotFound);
  395.   END;
  396.   {if-then}
  397.  
  398.  
  399.   {** destination file present? **}
  400.   IF (_fnbFileExist(gfOutStream,gsOutName)) THEN
  401.   BEGIN
  402.     System.Write(asProgramPrompt+'Output file '+gsOutName+
  403.                  ' already exists. Overwrite? (n/y): ');
  404.     System.ReadLn(gsTempInput);
  405.     IF (System.UpCase(_fnchGetFirstChar(gsTempInput)) <> achYes)
  406.       THEN  System.Halt(errDestDontWrite);
  407.     {if-then}
  408.   END;
  409.   {if-then}
  410.  
  411.  
  412.   {** read the following parameter = even bytes count **}
  413.   IF (gdwCmdCount >  3)
  414.     THEN  BEGIN
  415.      gsTempInput := System.ParamStr(4);
  416.      gdwEvenByteCount := _fnddGetNum(gsTempInput,giErrorCode);
  417.  
  418.      IF ((giErrorCode <> 0) OR
  419.          (aEvenCountDef > gdwEvenByteCount) OR
  420.          (gdwEvenByteCount > aEvenCountMax))
  421.       THEN
  422.          BEGIN
  423.            System.WriteLn(asProgramPrompt+' Bad even count found.');
  424.            System.Halt(errBadEvenCount);
  425.          END;
  426.       {if-then}
  427.           END;
  428.   {if-then}
  429.  
  430.  
  431.   {** read the following parameter = odd bytes count **}
  432.   IF (gdwCmdCount >  4)
  433.     THEN  BEGIN
  434.      gsTempInput := System.ParamStr(5);
  435.      gdwOddByteCount := _fnddGetNum(gsTempInput,giErrorCode);
  436.  
  437.      IF ((giErrorCode <> 0) OR
  438.          (aOddCountDef > gdwOddByteCount) OR
  439.          (gdwOddByteCount > aOddCountMax))
  440.       THEN
  441.          BEGIN
  442.            System.WriteLn(asProgramPrompt+' Bad odd count found.');
  443.            System.Halt(errBadOddCount);
  444.          END;
  445.       {if-then}
  446.           END;
  447.   {if-then}
  448.  
  449.  
  450.  {* do in/out streams *}
  451.   System.Assign(gfInStreamEven,gsInNameEven);
  452.   System.Reset(gfInStreamEven,1);
  453.  
  454.   System.Assign(gfInStreamOdd,gsInNameOdd);
  455.   System.Reset(gfInStreamOdd,1);
  456.  
  457.   System.Assign(gfOutStream,gsOutName);
  458.   System.Rewrite(gfOutStream,1);
  459.  
  460.  
  461.  {* find a minimal file size from input streams *}
  462.   IF (System.FileSize(gfInStreamEven) <= (System.FileSize(gfInStreamOdd)))
  463.     THEN  gliInBytesCount := System.FileSize(gfInStreamEven)
  464.     ELSE  gliInBytesCount := System.FileSize(gfInStreamOdd);
  465.   {if-then-else}
  466.  
  467.  
  468.  {* allocate a memory *}
  469.   System.GetMem(glpInEvenBuf,aMaxInBufSize);
  470.   System.GetMem(glpInOddBuf,aMaxInBufSize);
  471.   System.GetMem(glpOutBuf,aMaxOutBufSize);
  472.  
  473.  
  474.  {* initialize the internal variables *}
  475.     gliEvenInBytesCount := System.FileSize(gfInStreamEven);
  476.     gliOddInBytesCount := System.FileSize(gfInStreamOdd);
  477.     gdwEvenIndex := gdwEvenByteCount;
  478.  
  479.  {* main loop *}
  480.     WHILE  (gliEvenInBytesCount <> 0) OR (gliOddInBytesCount <> 0)  DO
  481.     BEGIN
  482.        IF  (agbReadEvenPart)
  483.           THEN  BEGIN
  484.             IF  (gliOddInBytesCount <> 0)
  485.               THEN  BEGIN
  486.                  WHILE (gliEvenInBytesCount <> 0) AND (gdwEvenIndex <> 0) DO
  487.                  BEGIN
  488.                    _PutByteToOutFile(_fndbReadEvenInFile);
  489.                     System.Dec(gdwEvenIndex);
  490.                     IF (gdwEvenIndex = 0)
  491.                       THEN  gdwOddIndex := gdwOddByteCount;
  492.                     {if-then}
  493.                    System.Dec(gliEvenInBytesCount);
  494.                  END;
  495.                  {while-do}
  496.                  agbReadEvenPart := System.False;
  497.                     END
  498.               ELSE  BEGIN
  499.                 WHILE  (gliEvenInBytesCount <> 0)  DO
  500.                 BEGIN
  501.                    _PutByteToOutFile(_fndbReadEvenInFile);
  502.                    System.Dec(gliEvenInBytesCount);
  503.                 END;
  504.                 {while-do}
  505.                     END;
  506.             {if-then-else}
  507.                 END
  508.           ELSE  BEGIN
  509.             IF  (gliEvenInBytesCount <> 0)
  510.               THEN  BEGIN
  511.                  WHILE (gliOddInBytesCount <> 0) AND (gdwOddIndex <> 0) DO
  512.                  BEGIN
  513.                    _PutByteToOutFile(_fndbReadOddInFile);
  514.                     System.Dec(gdwOddIndex);
  515.                     IF (gdwOddIndex = 0)
  516.                       THEN  gdwEvenIndex := gdwEvenByteCount;
  517.                     {if-then}
  518.                    System.Dec(gliOddInBytesCount);
  519.                  END;
  520.                  {while-do}
  521.                  agbReadEvenPart := System.True;
  522.                     END
  523.               ELSE  BEGIN
  524.                 WHILE  (gliOddInBytesCount <> 0)  DO
  525.                 BEGIN
  526.                    _PutByteToOutFile(_fndbReadOddInFile);
  527.                    System.Dec(gliOddInBytesCount);
  528.                 END;
  529.                 {while-do}
  530.                     END;
  531.             {if-then-else}
  532.                 END;
  533.        {if-then-else}
  534.     END;
  535.     {while-do}
  536.  
  537.  
  538.  {* check what is present in output buffer? *}
  539.   IF (gdwOutBufOfs <> 0)
  540.     THEN  BEGIN
  541.        _ProgramOutputMessage('Write last output buffer.');
  542.        System.BlockWrite(gfOutStream,
  543.                          System.Mem[System.Seg(glpOutBuf^):System.Ofs(glpOutBuf^)],
  544.                          gdwOutBufOfs);
  545.           END;
  546.   {if-then}
  547.  
  548.   _ProgramOutputMessage('Done.');
  549.  
  550.   System.FreeMem(glpInEvenBuf,aMaxInBufSize);
  551.   System.FreeMem(glpInOddBuf,aMaxInBufSize);
  552.   System.FreeMem(glpOutBuf,aMaxOutBufSize);
  553.  
  554.   System.Close(gfInStreamEven);
  555.   System.Close(gfInStreamOdd);
  556.   System.Close(gfOutStream);
  557.  
  558.   {* System.Halt(errTerminateOk); *}
  559. END.