home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / utilities / cli / bindiff11.lha / BinDiff.mod < prev    next >
Encoding:
Text File  |  1995-01-27  |  7.3 KB  |  344 lines

  1. (*************************************************************************
  2.   :Program.       BinDiff
  3.   :Version.       V1.1 (27.01.95)
  4.   :Contents.      see --background--
  5.  
  6.   :Author.        Jan Hense [juh]
  7.   :Address.       Lothringerstr. 9/Rgb., 81667 München, Germany
  8.   :Address.       Tel. +49-89-4807104, e-mail j.hense@amc.insider.sub.de
  9.   :Copyright.     freely distributable
  10.  
  11.   :Language.      Oberon (with Amiga Oberon extensions)
  12.   :Translator.    Amiga Oberon v3.00d
  13. **************************************************************************)
  14.  
  15. MODULE BinDiff;
  16.  
  17. IMPORT
  18.  
  19.   Break, Dos, Exec, Strings, SYSTEM;
  20.  
  21.  
  22. (*
  23. ******* BinDiff/--background-- *******************************************
  24. *
  25. *   NAME
  26. *
  27. *       BinDiff v1.1
  28. *
  29. *   DESCRIPTION
  30. *
  31. *       Compare two binary files in chunks of 8 bytes, dumping all
  32. *       differing chunks. Differing bytes are marked. Line format is:
  33. *
  34. *       offset:  file1-hex file1-chars  |  file2-hex file2-chars
  35. *
  36. *       If BinDiff finds any differences it sets WARN (5) as the DOS
  37. *       error code, else OK (0). BinDiff is pure of heart and can
  38. *       therefore be made resident.
  39. *
  40. *   SYNOPSIS
  41. *
  42. *       BinDiff FILE1/A,FILE2/A,HEX/S,ALL/S,QUIET/S
  43. *
  44. *   OPTIONS
  45. *
  46. *       FILE1, FILE2 - the two files to be compared
  47. *       HEX - offsets are printed in hex not decimal
  48. *       ALL - dump all, not only differing chunks
  49. *       QUIET - all output is omitted
  50. *
  51. *   COMPILING
  52. *
  53. *       This program was written in Oberon-2 with Amiga Oberon extensions.
  54. *       Compile and link it under Amiga Oberon v3.00 with
  55. *
  56. *         oberon -amd BinDiff
  57. *         olink -amd BinDiff
  58. *
  59. *       To extract this documentation use Autodoc 2.7 by hartmut Goebel:
  60. *
  61. *         autodoc -a -f BinDiff.mod > BinDiff.doc
  62. *
  63. *   AUTHOR
  64. *
  65. *       Jan Hense
  66. *       Lothringerstr. 9/Rgb.
  67. *       81667 München, Germany
  68. *       Tel. +49-89-4807104
  69. *       e-mail j.hense@amc.insider.sub.de
  70. *
  71. *   COPYRIGHT
  72. *
  73. *       Copyright reserved by the author. Freely distributable.
  74. *
  75. **************************************************************************
  76. *
  77. *)
  78.  
  79.  
  80. (*
  81. ******* BinDiff/--history-- **********************************************
  82. *
  83. *   v1.1 (27.01.95) [juh]
  84. *
  85. *       bug: forgot Dos.FreeArgs()
  86. *       slight changes in output format
  87. *       new option: QUIET/S
  88. *       added COMPILING in --background--
  89. *       now sets WARN as DOS error code if any diffs were found
  90. *
  91. *   v1.0 (07.01.95) [juh]
  92. *
  93. *       Created initial version.
  94. *
  95. **************************************************************************
  96. *
  97. *   TO DO
  98. *
  99. *)
  100.  
  101.  
  102. CONST
  103.  
  104.   template = "FILE1/A,FILE2/A,HEX/S,ALL/S,QUIET/S"
  105.     "\o$VER: BinDiff 1.1 (27.01.95) ©1995 j.hense@amc.insider.sub.de";
  106.  
  107.   missingArgs = "BinDiff: arguments incomplete\n";
  108.   noOpen = "BinDiff: couldn't open file '%s'\n";
  109.   readError = "BinDiff: read error #%ld in file '%s'\n";
  110.  
  111.   longerThan = "File '%s' is longer than '%s'\n";
  112.   diffsFound = "Differences found: %ld\n";
  113.   noDiffsFound = "No differences found\n";
  114.  
  115.   emphasizeCSI = "\[33m";
  116.   normalCSI = "\[0m";
  117.   unprintable = "\[1m·\[0m";
  118.   unprintableLen = 7+1;
  119.  
  120.   lineLength = 8;
  121.  
  122.  
  123. TYPE
  124.  
  125.   ArgsStruct = STRUCT (as: Dos.ArgsStruct)
  126.     file1: Exec.STRPTR;
  127.     file2: Exec.STRPTR;
  128.     hex: LONGINT;
  129.     all: LONGINT;
  130.     quiet: LONGINT;
  131.   END;
  132.  
  133.  
  134. VAR
  135.  
  136.   rda: Dos.RDArgsPtr;
  137.   args: ArgsStruct;
  138.   file1, file2: Dos.FileHandlePtr;
  139.   quiet: BOOLEAN;
  140.   totalDiffs: LONGINT;
  141.   line1, line2: ARRAY lineLength+1 OF CHAR;
  142.   len1, len2: LONGINT;
  143.   err: LONGINT;
  144.   offset: LONGINT;
  145.   void: LONGINT;
  146.  
  147.  
  148.  
  149.  
  150. PROCEDURE DumpDiffedLine(VAR line1, line2: ARRAY OF CHAR;
  151.                                       len: LONGINT);
  152.  
  153. VAR
  154.  
  155.   n: LONGINT;
  156.   c: CHAR;
  157.   char: ARRAY unprintableLen OF CHAR;
  158.  
  159. BEGIN
  160.  
  161.   FOR n := 0 TO len-1 DO
  162.     c := line1[n];
  163.     IF (c<" ") OR ((c>"~") & (c<"¡")) THEN
  164.       COPY(unprintable, char);
  165.     ELSE
  166.       char[0] := c; char[1] := 0X;
  167.     END;
  168.     IF c#line2[n] THEN
  169.       Dos.PrintF("%s%s%s",
  170.         SYSTEM.ADR(emphasizeCSI),
  171.         SYSTEM.ADR(char),
  172.         SYSTEM.ADR(normalCSI));
  173.     ELSE
  174.       Dos.PrintF("%s", SYSTEM.ADR(char));
  175.     END;
  176.     (* IF (n MOD 4)=3 THEN Dos.PrintF(" "); END; *)
  177.   END;
  178.  
  179.   (* fill up line *)
  180.   FOR n := n TO lineLength-1 DO
  181.     Dos.PrintF(" ");
  182.   END;
  183.  
  184. END DumpDiffedLine;
  185.  
  186.  
  187.  
  188. PROCEDURE DumpDiffedLineHex(VAR line1, line2: ARRAY OF CHAR;
  189.                                      len: LONGINT);
  190.  
  191. VAR
  192.  
  193.   n: LONGINT;
  194.  
  195. BEGIN
  196.  
  197.   FOR n := 0 TO len-1 DO
  198.     IF line1[n]#line2[n] THEN
  199.       Dos.PrintF("%s%02lx%s",
  200.         SYSTEM.ADR(emphasizeCSI),
  201.         ORD(line1[n]),
  202.         SYSTEM.ADR(normalCSI));
  203.     ELSE
  204.       Dos.PrintF("%02lx", ORD(line1[n]));
  205.     END;
  206.     IF (n MOD 4)=3 THEN Dos.PrintF(" "); END;
  207.   END;
  208.  
  209.   (* fill up line *)
  210.   FOR n := n TO lineLength-1 DO
  211.     Dos.PrintF("  ");
  212.     IF (n MOD 4)=3 THEN Dos.PrintF(" "); END;
  213.   END;
  214.  
  215. END DumpDiffedLineHex;
  216.  
  217.  
  218.  
  219. PROCEDURE CompareTwoLines(offset: LONGINT;
  220.                 VAR line1, line2: ARRAY OF CHAR;
  221.                      len1,  len2: LONGINT);
  222.  
  223. VAR
  224.  
  225.   len, n, d: LONGINT;
  226.  
  227. BEGIN
  228.  
  229.   IF len1<len2 THEN len := len1; ELSE len := len2; END;
  230.  
  231.   (* are there any diffs? *)
  232.   FOR n := 0 TO len-1 DO
  233.     IF line1[n]#line2[n] THEN INC(d); END;
  234.   END;
  235.   INC(totalDiffs, d);
  236.   IF quiet OR ((d=0) & (args.all=0)) (* only differing lines *) THEN
  237.     RETURN;
  238.   END;
  239.  
  240.   IF args.hex=0 THEN
  241.     Dos.PrintF("%08ld:  ", offset);
  242.   ELSE
  243.     Dos.PrintF("%08lx:  ", offset);
  244.   END;
  245.  
  246.   DumpDiffedLineHex(line1, line2, len);
  247.   Dos.PrintF("  ");
  248.   DumpDiffedLine(line1, line2, len);
  249.  
  250.   Dos.PrintF("  |  ");
  251.  
  252.   DumpDiffedLineHex(line2, line1, len);
  253.   Dos.PrintF("  ");
  254.   DumpDiffedLine(line2, line1, len);
  255.  
  256.   Dos.PrintF("\n");
  257.  
  258. END CompareTwoLines;
  259.  
  260.  
  261.  
  262. BEGIN
  263.  
  264.   rda := Dos.ReadArgs(template, args, NIL);
  265.   quiet := (args.quiet#0);
  266.   IF rda = NIL THEN
  267.     IF ~quiet THEN Dos.PrintF(missingArgs); END;
  268.     HALT(10);
  269.   END;
  270.  
  271.   file1 := Dos.Open(args.file1^, Dos.oldFile);
  272.   IF file1=NIL THEN
  273.     IF ~quiet THEN Dos.PrintF(noOpen, args.file1); END;
  274.     HALT(10);
  275.   END;
  276.  
  277.   file2 := Dos.Open(args.file2^, Dos.oldFile);
  278.   IF file2=NIL THEN
  279.     IF ~quiet THEN Dos.PrintF(noOpen, args.file2); END;
  280.     HALT(10);
  281.   END;
  282.  
  283.   totalDiffs := 0;
  284.   offset := 0;
  285.   void := Dos.SetIoErr(0);  (* FRead() doesn't clear IoErr *)
  286.   LOOP
  287.  
  288.     len1 := Dos.FRead(file1, line1, 1, lineLength);
  289.     err := Dos.SetIoErr(0);
  290.     IF err>0 THEN
  291.       IF ~quiet THEN Dos.PrintF(readError, err, args.file1); END;
  292.       HALT(10);
  293.     END;
  294.  
  295.     len2 := Dos.FRead(file2, line2, 1, lineLength);
  296.     err := Dos.SetIoErr(0);
  297.     IF err>0 THEN
  298.       IF ~quiet THEN Dos.PrintF(readError, err, args.file2); END;
  299.       HALT(10);
  300.     END;
  301.  
  302.     IF (len1=0) OR (len2=0) THEN  (* EOF *)
  303.       EXIT;
  304.     END;
  305.  
  306.     CompareTwoLines(offset, line1, line2, len1, len2);
  307.  
  308.     IF len1#len2 THEN  (* EOF in next read *)
  309.       EXIT;
  310.     END;
  311.  
  312.     INC(offset, len1);
  313.  
  314.   END;
  315.  
  316.   IF ~quiet THEN
  317.  
  318.     IF len1>len2 THEN
  319.       Dos.PrintF(longerThan, args.file1, args.file2);
  320.     ELSIF len2>len1 THEN
  321.       Dos.PrintF(longerThan, args.file2, args.file1);
  322.     END;
  323.  
  324.     IF totalDiffs>0 THEN
  325.       Dos.PrintF(diffsFound, totalDiffs);
  326.     ELSE
  327.       Dos.PrintF(noDiffsFound);
  328.     END;
  329.  
  330.   END;
  331.  
  332.   IF totalDiffs>0 THEN
  333.     HALT(5);  (* DOS return code = WARN *)
  334.   END; (* don't append code after this line! *)
  335.  
  336. CLOSE
  337.  
  338.   IF ~quiet THEN Dos.PrintF(normalCSI); (* in case of user break *) END;
  339.   IF file1#NIL THEN Dos.OldClose(file1); END;
  340.   IF file2#NIL THEN Dos.OldClose(file2); END;
  341.   Dos.FreeArgs(rda);
  342.  
  343. END BinDiff.
  344.