Fix PR1318 by reacting appropriately to a mutating option list.
[oota-llvm.git] / lib / Support / FileUtilities.cpp
index a7f42ddebf8c165dec4232b61e38874ef623cbbc..1736b0d5c31e2b0d99f23bb7158d624a990ab9b9 100644 (file)
@@ -16,7 +16,6 @@
 #include "llvm/System/Path.h"
 #include "llvm/System/MappedFile.h"
 #include "llvm/ADT/StringExtras.h"
-#include <cmath>
 #include <cstring>
 #include <cctype>
 using namespace llvm;
@@ -85,7 +84,13 @@ static bool CompareNumbers(char *&F1P, char *&F2P, char *F1End, char *F2End,
   }
 
   if (F1NumEnd == F1P || F2NumEnd == F2P) {
-    if (ErrorMsg) *ErrorMsg = "Comparison failed, not a numeric difference.";
+    if (ErrorMsg) {
+      *ErrorMsg = "FP Comparison failed, not a numeric difference between '";
+      *ErrorMsg += F1P[0];
+      *ErrorMsg += "' and '";
+      *ErrorMsg += F2P[0];
+      *ErrorMsg += "'";
+    }
     return true;
   }
 
@@ -101,8 +106,9 @@ static bool CompareNumbers(char *&F1P, char *&F2P, char *F1End, char *F2End,
       Diff = 0;  // Both zero.
     if (Diff > RelTolerance) {
       if (ErrorMsg) {
-        *ErrorMsg = "Compared: " + ftostr(V1) + " and " + ftostr(V2) +
-                    ": diff = " + ftostr(Diff) + "\n";
+        *ErrorMsg = "Compared: " + ftostr(V1) + " and " + ftostr(V2) + "\n";
+        *ErrorMsg += "abs. diff = " + ftostr(std::abs(V1-V2)) + 
+                     " rel.diff = " + ftostr(Diff) + "\n";
         *ErrorMsg += "Out of tolerance: rel/abs: " + ftostr(RelTolerance) +
                      "/" + ftostr(AbsTolerance);
       }
@@ -142,107 +148,119 @@ static void PadFileIfNeeded(char *&FileStart, char *&FileEnd, char *&FP) {
 /// error occurs, allowing the caller to distinguish between a failed diff and a
 /// file system error.
 ///
-int llvm::DiffFilesWithTolerance(const sys::Path &FileA,
-                                 const sys::Path &FileB,
+int llvm::DiffFilesWithTolerance(const sys::PathWithStatus &FileA,
+                                 const sys::PathWithStatus &FileB,
                                  double AbsTol, double RelTol,
                                  std::string *Error) {
-  try {
-    // Check for zero length files because some systems croak when you try to
-    // mmap an empty file.
-    size_t A_size = FileA.getSize();
-    size_t B_size = FileB.getSize();
-
-    // If they are both zero sized then they're the same
-    if (A_size == 0 && B_size == 0)
+  const sys::FileStatus *FileAStat = FileA.getFileStatus(false, Error);
+  if (!FileAStat)
+    return 2;
+  const sys::FileStatus *FileBStat = FileB.getFileStatus(false, Error);
+  if (!FileBStat)
+    return 2;
+
+  // Check for zero length files because some systems croak when you try to
+  // mmap an empty file.
+  size_t A_size = FileAStat->getSize();
+  size_t B_size = FileBStat->getSize();
+
+  // If they are both zero sized then they're the same
+  if (A_size == 0 && B_size == 0)
+    return 0;
+
+  // If only one of them is zero sized then they can't be the same
+  if ((A_size == 0 || B_size == 0)) {
+    if (Error)
+      *Error = "Files differ: one is zero-sized, the other isn't";
+    return 1;
+  }
+
+  // Now its safe to mmap the files into memory becasue both files
+  // have a non-zero size.
+  sys::MappedFile F1;
+  if (F1.open(FileA, sys::MappedFile::READ_ACCESS, Error))
+    return 2;
+  sys::MappedFile F2;
+  if (F2.open(FileB, sys::MappedFile::READ_ACCESS, Error))
+    return 2;
+  if (!F1.map(Error))
+    return 2;
+  if (!F2.map(Error))
+    return 2;
+
+  // Okay, now that we opened the files, scan them for the first difference.
+  char *File1Start = F1.charBase();
+  char *File2Start = F2.charBase();
+  char *File1End = File1Start+A_size;
+  char *File2End = File2Start+B_size;
+  char *F1P = File1Start;
+  char *F2P = File2Start;
+
+  if (A_size == B_size) {
+    // Are the buffers identical?
+    if (std::memcmp(File1Start, File2Start, A_size) == 0)
       return 0;
-    // If only one of them is zero sized then they can't be the same
-    if ((A_size == 0 || B_size == 0))
-      return 1;
-
-    // Now its safe to mmap the files into memory becasue both files
-    // have a non-zero size.
-    sys::MappedFile F1(FileA);
-    sys::MappedFile F2(FileB);
-    F1.map();
-    F2.map();
-
-    // Okay, now that we opened the files, scan them for the first difference.
-    char *File1Start = F1.charBase();
-    char *File2Start = F2.charBase();
-    char *File1End = File1Start+A_size;
-    char *File2End = File2Start+B_size;
-    char *F1P = File1Start;
-    char *F2P = File2Start;
-
-    if (A_size == B_size) {
-      // Are the buffers identical?
-      if (std::memcmp(File1Start, File2Start, A_size) == 0)
-        return 0;
-
-      if (AbsTol == 0 && RelTol == 0)
-        return 1;   // Files different!
+
+    if (AbsTol == 0 && RelTol == 0) {
+      if (Error)
+        *Error = "Files differ without tolerance allowance";
+      return 1;   // Files different!
     }
+  }
 
-    char *OrigFile1Start = File1Start;
-    char *OrigFile2Start = File2Start;
+  char *OrigFile1Start = File1Start;
+  char *OrigFile2Start = File2Start;
 
-    // If the files need padding, do so now.
-    PadFileIfNeeded(File1Start, File1End, F1P);
-    PadFileIfNeeded(File2Start, File2End, F2P);
+  // If the files need padding, do so now.
+  PadFileIfNeeded(File1Start, File1End, F1P);
+  PadFileIfNeeded(File2Start, File2End, F2P);
 
-    bool CompareFailed = false;
-    while (1) {
-      // Scan for the end of file or next difference.
-      while (F1P < File1End && F2P < File2End && *F1P == *F2P)
-        ++F1P, ++F2P;
+  bool CompareFailed = false;
+  while (1) {
+    // Scan for the end of file or next difference.
+    while (F1P < File1End && F2P < File2End && *F1P == *F2P)
+      ++F1P, ++F2P;
 
-      if (F1P >= File1End || F2P >= File2End) break;
+    if (F1P >= File1End || F2P >= File2End) break;
 
-      // Okay, we must have found a difference.  Backup to the start of the
-      // current number each stream is at so that we can compare from the
-      // beginning.
-      F1P = BackupNumber(F1P, File1Start);
-      F2P = BackupNumber(F2P, File2Start);
+    // Okay, we must have found a difference.  Backup to the start of the
+    // current number each stream is at so that we can compare from the
+    // beginning.
+    F1P = BackupNumber(F1P, File1Start);
+    F2P = BackupNumber(F2P, File2Start);
 
-      // Now that we are at the start of the numbers, compare them, exiting if
-      // they don't match.
-      if (CompareNumbers(F1P, F2P, File1End, File2End, AbsTol, RelTol, Error)) {
-        CompareFailed = true;
-        break;
-      }
+    // Now that we are at the start of the numbers, compare them, exiting if
+    // they don't match.
+    if (CompareNumbers(F1P, F2P, File1End, File2End, AbsTol, RelTol, Error)) {
+      CompareFailed = true;
+      break;
     }
+  }
 
-    // Okay, we reached the end of file.  If both files are at the end, we
-    // succeeded.
-    bool F1AtEnd = F1P >= File1End;
-    bool F2AtEnd = F2P >= File2End;
-    if (!CompareFailed && (!F1AtEnd || !F2AtEnd)) {
-      // Else, we might have run off the end due to a number: backup and retry.
-      if (F1AtEnd && isNumberChar(F1P[-1])) --F1P;
-      if (F2AtEnd && isNumberChar(F2P[-1])) --F2P;
-      F1P = BackupNumber(F1P, File1Start);
-      F2P = BackupNumber(F2P, File2Start);
-
-      // Now that we are at the start of the numbers, compare them, exiting if
-      // they don't match.
-      if (CompareNumbers(F1P, F2P, File1End, File2End, AbsTol, RelTol, Error))
-        CompareFailed = true;
-
-      // If we found the end, we succeeded.
-      if (F1P < File1End || F2P < File2End)
-        CompareFailed = true;
-    }
+  // Okay, we reached the end of file.  If both files are at the end, we
+  // succeeded.
+  bool F1AtEnd = F1P >= File1End;
+  bool F2AtEnd = F2P >= File2End;
+  if (!CompareFailed && (!F1AtEnd || !F2AtEnd)) {
+    // Else, we might have run off the end due to a number: backup and retry.
+    if (F1AtEnd && isNumberChar(F1P[-1])) --F1P;
+    if (F2AtEnd && isNumberChar(F2P[-1])) --F2P;
+    F1P = BackupNumber(F1P, File1Start);
+    F2P = BackupNumber(F2P, File2Start);
 
-    if (OrigFile1Start != File1Start)
-      delete[] (File1Start-1);   // Back up past null byte
-    if (OrigFile2Start != File2Start)
-      delete[] (File2Start-1);   // Back up past null byte
-    return CompareFailed;
-  } catch (const std::string &Msg) {
-    if (Error) *Error = Msg;
-    return 2;
-  } catch (...) {
-    *Error = "Unknown Exception Occurred";
-    return 2;
+    // Now that we are at the start of the numbers, compare them, exiting if
+    // they don't match.
+    if (CompareNumbers(F1P, F2P, File1End, File2End, AbsTol, RelTol, Error))
+      CompareFailed = true;
+
+    // If we found the end, we succeeded.
+    if (F1P < File1End || F2P < File2End)
+      CompareFailed = true;
   }
+
+  if (OrigFile1Start != File1Start)
+    delete[] (File1Start-1);   // Back up past null byte
+  if (OrigFile2Start != File2Start)
+    delete[] (File2Start-1);   // Back up past null byte
+  return CompareFailed;
 }