Git conversion: Make reactos the root directory, move rosapps, rostests, wallpapers...
[reactos.git] / base / applications / cmdutils / comp / comp.c
index 15a0db4..5e6b4aa 100644 (file)
-/*\r
- *  ReactOS Win32 Applications\r
- *  Copyright (C) 2005 ReactOS Team\r
- *\r
- *  This program is free software; you can redistribute it and/or modify\r
- *  it under the terms of the GNU General Public License as published by\r
- *  the Free Software Foundation; either version 2 of the License, or\r
- *  (at your option) any later version.\r
- *\r
- *  This program is distributed in the hope that it will be useful,\r
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
- *  GNU General Public License for more details.\r
- *\r
- *  You should have received a copy of the GNU General Public License\r
- *  along with this program; if not, write to the Free Software\r
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\r
- */\r
-/*\r
- * COPYRIGHT:   See COPYING in the top level directory\r
- * PROJECT:     ReactOS comp utility\r
- * FILE:        comp.c\r
- * PURPOSE:     Compares the contents of two files\r
- * PROGRAMMERS: Ged Murphy (gedmurphy@gmail.com)\r
- * REVISIONS:\r
- *   GM 25/09/05 Created\r
- *\r
- */\r
-\r
-\r
-#include <windows.h>\r
-#include <tchar.h>\r
-#include <stdio.h>\r
-#include <stdlib.h>\r
-#include <string.h>\r
-\r
-#define STRBUF 1024\r
-\r
-/* getline:  read a line, return length */\r
-INT GetLine(char *line, FILE *in)\r
-{\r
-    if (fgets(line, STRBUF, in) == NULL)\r
-        return 0;\r
-    else\r
-        return strlen(line);\r
-}\r
-\r
-/* print program usage */\r
-VOID Usage(VOID)\r
-{\r
-    _tprintf(_T("\nCompares the contents of two files or sets of files.\n\n"\r
-                "COMP [data1] [data2]\n\n"\r
-                "  data1      Specifies location and name of first file to compare.\n"\r
-                "  data2      Specifies location and name of second file to compare.\n"));\r
-}\r
-\r
-\r
-int _tmain (int argc, TCHAR *argv[])\r
-{\r
-    INT i;\r
-    FILE *fp1, *fp2;           // file pointers\r
-    PTCHAR Line1 = (TCHAR *)malloc(STRBUF * sizeof(TCHAR));\r
-    PTCHAR Line2 = (TCHAR *)malloc(STRBUF * sizeof(TCHAR));\r
-    TCHAR File1[_MAX_PATH],    // file paths\r
-          File2[_MAX_PATH];\r
-    BOOL bMatch = TRUE,        // files match\r
-         bAscii = FALSE,       // /A switch\r
-         bLineNos = FALSE;     // /L switch\r
-\r
-    /* parse command line for options */\r
-    for (i = 1; i < argc; i++)\r
-    {\r
-        if (argv[i][0] == '/')\r
-        {\r
-            --argc;\r
-            switch (argv[i][1]) {\r
-               case 'A': bAscii = TRUE;\r
-                         _tprintf(_T("/a not Supported\n")); (void)bAscii;   /*FIXME: needs adding */\r
-                         break;\r
-               case 'L': bLineNos = TRUE;\r
-                         _tprintf(_T("/l not supported\n")); (void)bLineNos; /*FIXME: needs adding */\r
-                         break;\r
-               case '?': Usage();\r
-                         return EXIT_SUCCESS;\r
-               default:\r
-                   _tprintf(_T("Invalid switch - /%c\n"), argv[i][1]);\r
-                   Usage();\r
-                   return EXIT_FAILURE;\r
-            }\r
-        }\r
-    }\r
-\r
-    switch (argc)\r
-    {\r
-        case 1 :\r
-                 _tprintf(_T("Name of first file to compare: "));\r
-                 fgets(File1, _MAX_PATH, stdin);\r
-                 for (i=0; i<_MAX_PATH; i++)\r
-                 {\r
-                     if (File1[i] == '\n')\r
-                     {\r
-                         File1[i] = '\0';\r
-                         break;\r
-                     }\r
-                 }\r
-\r
-                 _tprintf(_T("Name of second file to compare: "));\r
-                 fgets(File2, _MAX_PATH, stdin);\r
-                 for (i=0; i<_MAX_PATH; i++)\r
-                 {\r
-                     if (File2[i] == '\n')\r
-                     {\r
-                         File2[i] = '\0';\r
-                         break;\r
-                     }\r
-                 }\r
-                 break;\r
-        case 2 :\r
-                 _tcsncpy(File1, argv[1], _MAX_PATH);\r
-                 _tprintf(_T("Name of second file to compare: "));\r
-                 fgets(File2, _MAX_PATH, stdin);\r
-                 for (i=0; i<_MAX_PATH; i++)\r
-                 {\r
-                     if (File2[i] == '\n')\r
-                     {\r
-                         File2[i] = '\0';\r
-                         break;\r
-                     }\r
-                 }\r
-                 break;\r
-        case 3 :\r
-                 _tcsncpy(File1, argv[1], _MAX_PATH);\r
-                 _tcsncpy(File2, argv[2], _MAX_PATH);\r
-                 break;\r
-        default :\r
-                  _tprintf(_T("Bad command line syntax\n"));\r
-                  return EXIT_FAILURE;\r
-                  break;\r
-    }\r
-\r
-\r
-\r
-    if ((fp1 = fopen(File1, "r")) == NULL)\r
-    {\r
-        _tprintf(_T("Can't find/open file: %s\n"), File1);\r
-        return EXIT_FAILURE;\r
-    }\r
-    if ((fp2 = fopen(File2, "r")) == NULL)\r
-    {\r
-        _tprintf(_T("Can't find/open file: %s\n"), File2);\r
-        fclose(fp1);\r
-        return EXIT_FAILURE;\r
-    }\r
-\r
-\r
-    _tprintf(_T("Comparing %s and %s...\n"), File1, File2);\r
-\r
-    while ((GetLine(Line1, fp1) != 0) &&\r
-           (GetLine(Line2, fp2) != 0))\r
-    {\r
-        // LineCount++;\r
-        while ((*Line1 != '\0') && (*Line2 != '\0'))\r
-        {\r
-            if (*Line1 != *Line2)\r
-            {\r
-                bMatch = FALSE;\r
-                break;\r
-            }\r
-            Line1++, Line2++;\r
-        }\r
-    }\r
-\r
-    bMatch ? _tprintf(_T("Files compare OK\n")) : _tprintf(_T("Files are different sizes.\n"));\r
-\r
-    fclose(fp1);\r
-    fclose(fp2);\r
-\r
-\r
-    return EXIT_SUCCESS;\r
-}\r
-/* EOF */\r
+/*
+ *  ReactOS Win32 Applications
+ *  Copyright (C) 2005 ReactOS Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ * PROJECT:     ReactOS Comp utility
+ * COPYRIGHT:   See COPYING in the top level directory
+ * FILE:        base/applications/cmdutils/comp/comp.c
+ * PURPOSE:     Compares the contents of two files
+ * PROGRAMMERS: Ged Murphy (gedmurphy@gmail.com)
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#define WIN32_NO_STATUS
+#include <windef.h>
+#include <winbase.h>
+
+#include <conutils.h>
+
+#include "resource.h"
+
+#define STRBUF 1024
+
+/* getline: read a line, return length */
+INT GetBuff(PBYTE buff, FILE* in)
+{
+    return fread(buff, sizeof(BYTE), STRBUF, in);
+}
+
+INT FileSize(FILE* fd)
+{
+    INT result = -1;
+    if (fseek(fd, 0, SEEK_END) == 0 && (result = ftell(fd)) != -1)
+    {
+        /* Restoring file pointer */
+        rewind(fd);
+    }
+    return result;
+}
+
+
+int wmain(int argc, WCHAR* argv[])
+{
+    INT i;
+
+    /* File pointers */
+    FILE *fp1 = NULL;
+    FILE *fp2 = NULL;
+
+    INT BufLen1, BufLen2;
+    PBYTE Buff1 = NULL;
+    PBYTE Buff2 = NULL;
+    WCHAR File1[_MAX_PATH + 1], // File paths
+          File2[_MAX_PATH + 1];
+    BOOL bAscii = FALSE,        // /A switch
+         bLineNos = FALSE;      // /L switch
+    UINT LineNumber;
+    UINT Offset;
+    INT  FileSizeFile1;
+    INT  FileSizeFile2;
+    INT  NumberOfOptions = 0;
+    INT  FilesOK = 1;
+    INT  Status = EXIT_SUCCESS;
+
+    /* Initialize the Console Standard Streams */
+    ConInitStdStreams();
+
+    /* Parse command line for options */
+    for (i = 1; i < argc; i++)
+    {
+        if (argv[i][0] == L'/')
+        {
+            switch (towlower(argv[i][1]))
+            {
+                case L'a':
+                    bAscii = TRUE;
+                    NumberOfOptions++;
+                    break;
+
+                case L'l':
+                    bLineNos = TRUE;
+                    NumberOfOptions++;
+                    break;
+
+                case L'?':
+                    ConResPuts(StdOut, IDS_HELP);
+                    return EXIT_SUCCESS;
+
+                default:
+                    ConResPrintf(StdErr, IDS_INVALIDSWITCH, argv[i][1]);
+                    ConResPuts(StdOut, IDS_HELP);
+                    return EXIT_FAILURE;
+            }
+        }
+    }
+
+    if (argc - NumberOfOptions == 3)
+    {
+        wcsncpy(File1, argv[1 + NumberOfOptions], _MAX_PATH);
+        wcsncpy(File2, argv[2 + NumberOfOptions], _MAX_PATH);
+    }
+    else
+    {
+        ConResPuts(StdErr, IDS_BADSYNTAX);
+        return EXIT_FAILURE;
+    }
+
+    Buff1 = (PBYTE)malloc(STRBUF);
+    if (Buff1 == NULL)
+    {
+        ConPuts(StdErr, L"Can't get free memory for Buff1\n");
+        Status = EXIT_FAILURE;
+        goto Cleanup;
+    }
+
+    Buff2 = (PBYTE)malloc(STRBUF);
+    if (Buff2 == NULL)
+    {
+        ConPuts(StdErr, L"Can't get free memory for Buff2\n");
+        Status = EXIT_FAILURE;
+        goto Cleanup;
+    }
+
+    if ((fp1 = _wfopen(File1, L"rb")) == NULL)
+    {
+        ConResPrintf(StdErr, IDS_FILEERROR, File1);
+        Status = EXIT_FAILURE;
+        goto Cleanup;
+    }
+    if ((fp2 = _wfopen(File2, L"rb")) == NULL)
+    {
+        ConResPrintf(StdErr, IDS_FILEERROR, File2);
+        Status = EXIT_FAILURE;
+        goto Cleanup;
+    }
+
+    ConResPrintf(StdOut, IDS_COMPARING, File1, File2);
+
+    FileSizeFile1 = FileSize(fp1);
+    if (FileSizeFile1 == -1)
+    {
+        ConResPrintf(StdErr, IDS_FILESIZEERROR, File1);
+        Status = EXIT_FAILURE;
+        goto Cleanup;
+    }
+
+    FileSizeFile2 = FileSize(fp2);
+    if (FileSizeFile2 == -1)
+    {
+        ConResPrintf(StdErr, IDS_FILESIZEERROR, File2);
+        Status = EXIT_FAILURE;
+        goto Cleanup;
+    }
+
+    if (FileSizeFile1 != FileSizeFile2)
+    {
+        ConResPuts(StdOut, IDS_SIZEDIFFERS);
+        Status = EXIT_FAILURE;
+        goto Cleanup;
+    }
+
+    LineNumber = 1;
+    Offset = 0;
+    while (1)
+    {
+        BufLen1 = GetBuff(Buff1, fp1);
+        BufLen2 = GetBuff(Buff2, fp2);
+
+        if (ferror(fp1) || ferror(fp2))
+        {
+            ConResPuts(StdErr, IDS_READERROR);
+            Status = EXIT_FAILURE;
+            goto Cleanup;
+        }
+
+        if (!BufLen1 && !BufLen2)
+            break;
+
+        assert(BufLen1 == BufLen2);
+        for (i = 0; i < BufLen1; i++)
+        {
+            if (Buff1[i] != Buff2[i])
+            {
+                FilesOK = 0;
+
+                /* Reporting here a mismatch */
+                if (bLineNos)
+                    ConResPrintf(StdOut, IDS_MISMATCHLINE, LineNumber);
+                else
+                    ConResPrintf(StdOut, IDS_MISMATCHOFFSET, Offset);
+
+                if (bAscii)
+                {
+                    ConResPrintf(StdOut, IDS_ASCIIDIFF, 1, Buff1[i]);
+                    ConResPrintf(StdOut, IDS_ASCIIDIFF, 2, Buff2[i]);
+                }
+                else
+                {
+                    ConResPrintf(StdOut, IDS_HEXADECIMALDIFF, 1, Buff1[i]);
+                    ConResPrintf(StdOut, IDS_HEXADECIMALDIFF, 2, Buff2[i]);
+                }
+            }
+
+            Offset++;
+
+            if (Buff1[i] == '\n')
+                LineNumber++;
+        }
+    }
+
+    if (FilesOK)
+        ConResPuts(StdOut, IDS_MATCH);
+
+Cleanup:
+    if (fp2)
+        fclose(fp2);
+    if (fp1)
+        fclose(fp1);
+
+    if (Buff2)
+        free(Buff2);
+    if (Buff1)
+        free(Buff1);
+
+    return Status;
+}
+
+/* EOF */