# Global Metrics

path: .metrics.nexits.sum
old: 12.0
new: 57.0
path: .metrics.nexits.average
old: 1.0
new: 2.0357142857142856
path: .metrics.cyclomatic.average
old: 1.0666666666666669
new: 3.6333333333333337
path: .metrics.cyclomatic.sum
old: 16.0
new: 109.0
path: .metrics.cognitive.sum
old: 1.0
new: 101.0
path: .metrics.cognitive.average
old: 0.08333333333333333
new: 3.607142857142857
path: .metrics.mi.mi_sei
old: 39.02046083841565
new: -43.414715661562255
path: .metrics.mi.mi_original
old: 55.37400774766395
new: -1.0070750520263942
path: .metrics.mi.mi_visual_studio
old: 32.382460671148515
new: 0.0
path: .metrics.nom.total
old: 12.0
new: 28.0
path: .metrics.nom.functions
old: 12.0
new: 28.0
path: .metrics.nargs.average
old: 0.0
new: 1.3928571428571428
path: .metrics.nargs.sum
old: 0.0
new: 39.0
path: .metrics.halstead.effort
old: 24296.07546156776
new: 901018.9424597644
path: .metrics.halstead.level
old: 0.07258064516129031
new: 0.014705882352941176
path: .metrics.halstead.n2
old: 72.0
new: 170.0
path: .metrics.halstead.vocabulary
old: 88.0
new: 204.0
path: .metrics.halstead.N2
old: 124.0
new: 680.0
path: .metrics.halstead.bugs
old: 0.27962081496386565
new: 3.1095773163343776
path: .metrics.halstead.length
old: 273.0
new: 1727.0
path: .metrics.halstead.volume
old: 1763.4248318879822
new: 13250.278565584773
path: .metrics.halstead.estimated_program_length
old: 508.2346001038465
new: 1432.5701957459207
path: .metrics.halstead.N1
old: 149.0
new: 1047.0
path: .metrics.halstead.time
old: 1349.7819700870978
new: 50056.60791443136
path: .metrics.halstead.n1
old: 16.0
new: 34.0
path: .metrics.halstead.difficulty
old: 13.77777777777778
new: 68.0
path: .metrics.halstead.purity_ratio
old: 1.8616652018455917
new: 0.8295137207561788
path: .metrics.loc.cloc
old: 20.0
new: 38.0
path: .metrics.loc.sloc
old: 91.0
new: 413.0
path: .metrics.loc.lloc
old: 12.0
new: 174.0
path: .metrics.loc.ploc
old: 55.0
new: 319.0
path: .metrics.loc.blank
old: 16.0
new: 56.0

# Spaces Data

## Minimal test - lines (206, 208)

path: .spaces[0].spaces[8].metrics.halstead.N1
old: 5.0
new: 11.0
path: .spaces[0].spaces[8].metrics.halstead.N2
old: 3.0
new: 7.0
path: .spaces[0].spaces[8].metrics.halstead.length
old: 8.0
new: 18.0
path: .spaces[0].spaces[8].metrics.halstead.n2
old: 3.0
new: 5.0
path: .spaces[0].spaces[8].metrics.halstead.level
old: 0.4
new: 0.2040816326530612
path: .spaces[0].spaces[8].metrics.halstead.vocabulary
old: 8.0
new: 12.0
path: .spaces[0].spaces[8].metrics.halstead.estimated_program_length
old: 16.36452797660028
new: 31.26112492884004
path: .spaces[0].spaces[8].metrics.halstead.effort
old: 60.0
new: 316.19369256360596
path: .spaces[0].spaces[8].metrics.halstead.time
old: 3.3333333333333335
new: 17.566316253533664
path: .spaces[0].spaces[8].metrics.halstead.volume
old: 24.0
new: 64.5293250129808
path: .spaces[0].spaces[8].metrics.halstead.bugs
old: 0.005108729549290353
new: 0.015470851358978374
path: .spaces[0].spaces[8].metrics.halstead.purity_ratio
old: 2.045565997075035
new: 1.7367291627133357
path: .spaces[0].spaces[8].metrics.halstead.difficulty
old: 2.5
new: 4.9
path: .spaces[0].spaces[8].metrics.halstead.n1
old: 5.0
new: 7.0
path: .spaces[0].spaces[8].metrics.mi.mi_original
old: 154.24412008219068
new: 131.30345810999222
path: .spaces[0].spaces[8].metrics.mi.mi_sei
old: 146.92819499625
new: 113.83181573424925
path: .spaces[0].spaces[8].metrics.mi.mi_visual_studio
old: 90.2012398141466
new: 76.78564801753932
path: .spaces[0].spaces[8].metrics.loc.sloc
old: 1.0
new: 3.0
path: .spaces[0].spaces[8].metrics.loc.ploc
old: 1.0
new: 3.0

### Code

    FILE* OpenFile(int Fd, const char* Mode) {
      return _fdopen(Fd, Mode);
    }

## Minimal test - lines (151, 200)

path: .spaces[0].spaces[6].metrics.cognitive.average
old: 0.0
new: 14.0
path: .spaces[0].spaces[6].metrics.cognitive.sum
old: 0.0
new: 14.0
path: .spaces[0].spaces[6].metrics.loc.ploc
old: 1.0
new: 40.0
path: .spaces[0].spaces[6].metrics.loc.lloc
old: 1.0
new: 21.0
path: .spaces[0].spaces[6].metrics.loc.blank
old: 0.0
new: 6.0
path: .spaces[0].spaces[6].metrics.loc.cloc
old: 0.0
new: 4.0
path: .spaces[0].spaces[6].metrics.loc.sloc
old: 1.0
new: 50.0
path: .spaces[0].spaces[6].metrics.mi.mi_visual_studio
old: 90.80912574437468
new: 39.3046583652914
path: .spaces[0].spaces[6].metrics.mi.mi_sei
old: 148.4278547652622
new: 43.59861067684025
path: .spaces[0].spaces[6].metrics.mi.mi_original
old: 155.2836050228807
new: 67.2109658046483
path: .spaces[0].spaces[6].metrics.nargs.average
old: 0.0
new: 4.0
path: .spaces[0].spaces[6].metrics.nargs.sum
old: 0.0
new: 4.0
path: .spaces[0].spaces[6].metrics.nexits.sum
old: 1.0
new: 2.0
path: .spaces[0].spaces[6].metrics.nexits.average
old: 1.0
new: 2.0
path: .spaces[0].spaces[6].metrics.cyclomatic.sum
old: 1.0
new: 11.0
path: .spaces[0].spaces[6].metrics.cyclomatic.average
old: 1.0
new: 11.0
path: .spaces[0].spaces[6].metrics.halstead.N1
old: 4.0
new: 152.0
path: .spaces[0].spaces[6].metrics.halstead.estimated_program_length
old: 12.754887502163468
new: 292.5692484333749
path: .spaces[0].spaces[6].metrics.halstead.purity_ratio
old: 1.8221267860233523
new: 1.179714711424899
path: .spaces[0].spaces[6].metrics.halstead.length
old: 7.0
new: 248.0
path: .spaces[0].spaces[6].metrics.halstead.level
old: 0.5
new: 0.040624999999999994
path: .spaces[0].spaces[6].metrics.halstead.N2
old: 3.0
new: 96.0
path: .spaces[0].spaces[6].metrics.halstead.effort
old: 39.302968908806456
new: 35911.27326133506
path: .spaces[0].spaces[6].metrics.halstead.time
old: 2.1834982727114696
new: 1995.0707367408368
path: .spaces[0].spaces[6].metrics.halstead.n2
old: 3.0
new: 39.0
path: .spaces[0].spaces[6].metrics.halstead.difficulty
old: 2.0
new: 24.615384615384617
path: .spaces[0].spaces[6].metrics.halstead.bugs
old: 0.0038532659414573967
new: 0.3628267352915559
path: .spaces[0].spaces[6].metrics.halstead.volume
old: 19.651484454403228
new: 1458.8954762417368
path: .spaces[0].spaces[6].metrics.halstead.vocabulary
old: 7.0
new: 59.0
path: .spaces[0].spaces[6].metrics.halstead.n1
old: 4.0
new: 20.0

### Code

    void IterateDirRecursive(const std::string &Dir,
                             void (*DirPreCallback)(const std::string &Dir),
                             void (*DirPostCallback)(const std::string &Dir),
                             void (*FileCallback)(const std::string &Dir)) {
      // TODO(metzman): Implement ListFilesInDirRecursive via this function.
      DirPreCallback(Dir);

      DWORD DirAttrs = GetFileAttributesA(Dir.c_str());
      if (!IsDir(DirAttrs)) return;

      std::string TargetDir(Dir);
      assert(!TargetDir.empty());
      if (TargetDir.back() != '\\') TargetDir.push_back('\\');
      TargetDir.push_back('*');

      WIN32_FIND_DATAA FindInfo;
      // Find the directory's first file.
      HANDLE FindHandle = FindFirstFileA(TargetDir.c_str(), &FindInfo);
      if (FindHandle == INVALID_HANDLE_VALUE) {
        DWORD LastError = GetLastError();
        if (LastError != ERROR_FILE_NOT_FOUND) {
          // If the directory isn't empty, then something abnormal is going on.
          Printf("FindFirstFileA failed for %s (Error code: %lu).\n", Dir.c_str(),
                 LastError);
        }
        return;
      }

      do {
        std::string Path = DirPlusFile(Dir, FindInfo.cFileName);
        DWORD PathAttrs = FindInfo.dwFileAttributes;
        if (IsDir(PathAttrs)) {
          // Is Path the current directory (".") or the parent ("..")?
          if (strcmp(FindInfo.cFileName, ".") == 0 ||
              strcmp(FindInfo.cFileName, "..") == 0)
            continue;
          IterateDirRecursive(Path, DirPreCallback, DirPostCallback, FileCallback);
        } else if (PathAttrs != INVALID_FILE_ATTRIBUTES) {
          FileCallback(Path);
        }
      } while (FindNextFileA(FindHandle, &FindInfo));

      DWORD LastError = GetLastError();
      if (LastError != ERROR_NO_MORE_FILES)
        Printf("FindNextFileA failed for %s (Error code: %lu).\n", Dir.c_str(),
               LastError);

      FindClose(FindHandle);
      DirPostCallback(Dir);
    }

## Minimal test - lines (79, 84)

path: .spaces[0].spaces[3].metrics.nargs.sum
old: 0.0
new: 1.0
path: .spaces[0].spaces[3].metrics.nargs.average
old: 0.0
new: 1.0
path: .spaces[0].spaces[3].metrics.cognitive.sum
old: 0.0
new: 1.0
path: .spaces[0].spaces[3].metrics.cognitive.average
old: 0.0
new: 1.0
path: .spaces[0].spaces[3].metrics.halstead.level
old: 0.4
new: 0.08906882591093118
path: .spaces[0].spaces[3].metrics.halstead.volume
old: 28.52932501298081
new: 210.90827503317317
path: .spaces[0].spaces[3].metrics.halstead.length
old: 9.0
new: 46.0
path: .spaces[0].spaces[3].metrics.halstead.bugs
old: 0.005732795045386515
new: 0.05921849147793715
path: .spaces[0].spaces[3].metrics.halstead.N1
old: 5.0
new: 27.0
path: .spaces[0].spaces[3].metrics.halstead.estimated_program_length
old: 19.60964047443681
new: 86.15946414084446
path: .spaces[0].spaces[3].metrics.halstead.effort
old: 71.32331253245202
new: 2367.92472423608
path: .spaces[0].spaces[3].metrics.halstead.purity_ratio
old: 2.1788489416040897
new: 1.8730318291487928
path: .spaces[0].spaces[3].metrics.halstead.time
old: 3.96240625180289
new: 131.55137356867112
path: .spaces[0].spaces[3].metrics.halstead.N2
old: 4.0
new: 19.0
path: .spaces[0].spaces[3].metrics.halstead.difficulty
old: 2.5
new: 11.227272727272728
path: .spaces[0].spaces[3].metrics.halstead.n2
old: 4.0
new: 11.0
path: .spaces[0].spaces[3].metrics.halstead.n1
old: 5.0
new: 13.0
path: .spaces[0].spaces[3].metrics.halstead.vocabulary
old: 9.0
new: 24.0
path: .spaces[0].spaces[3].metrics.mi.mi_original
old: 153.34515096830847
new: 113.68609531642348
path: .spaces[0].spaces[3].metrics.mi.mi_visual_studio
old: 89.67552688205174
new: 66.48309667627105
path: .spaces[0].spaces[3].metrics.mi.mi_sei
old: 145.63125671373976
new: 88.51715365783039
path: .spaces[0].spaces[3].metrics.cyclomatic.average
old: 1.0
new: 2.0
path: .spaces[0].spaces[3].metrics.cyclomatic.sum
old: 1.0
new: 2.0
path: .spaces[0].spaces[3].metrics.nexits.average
old: 1.0
new: 2.0
path: .spaces[0].spaces[3].metrics.nexits.sum
old: 1.0
new: 2.0
path: .spaces[0].spaces[3].metrics.loc.ploc
old: 1.0
new: 6.0
path: .spaces[0].spaces[3].metrics.loc.lloc
old: 1.0
new: 4.0
path: .spaces[0].spaces[3].metrics.loc.sloc
old: 1.0
new: 6.0

### Code

    std::string Basename(const std::string &Path) {
      size_t Pos = Path.find_last_of("/\\");
      if (Pos == std::string::npos) return Path;
      assert(Pos < Path.size());
      return Path.substr(Pos + 1);
    }

## Minimal test - lines (62, 72)

path: .spaces[0].spaces[1].metrics.nexits.sum
old: 1.0
new: 2.0
path: .spaces[0].spaces[1].metrics.nexits.average
old: 1.0
new: 2.0
path: .spaces[0].spaces[1].metrics.nargs.average
old: 0.0
new: 1.0
path: .spaces[0].spaces[1].metrics.nargs.sum
old: 0.0
new: 1.0
path: .spaces[0].spaces[1].metrics.cyclomatic.average
old: 1.0
new: 2.0
path: .spaces[0].spaces[1].metrics.cyclomatic.sum
old: 1.0
new: 2.0
path: .spaces[0].spaces[1].metrics.loc.ploc
old: 1.0
new: 9.0
path: .spaces[0].spaces[1].metrics.loc.sloc
old: 1.0
new: 11.0
path: .spaces[0].spaces[1].metrics.loc.blank
old: 0.0
new: 2.0
path: .spaces[0].spaces[1].metrics.loc.lloc
old: 1.0
new: 4.0
path: .spaces[0].spaces[1].metrics.cognitive.sum
old: 0.0
new: 1.0
path: .spaces[0].spaces[1].metrics.cognitive.average
old: 0.0
new: 1.0
path: .spaces[0].spaces[1].metrics.mi.mi_visual_studio
old: 88.53493745197343
new: 60.78175598781615
path: .spaces[0].spaces[1].metrics.mi.mi_sei
old: 142.81741287200575
new: 74.45189760444485
path: .spaces[0].spaces[1].metrics.mi.mi_original
old: 151.39474304287458
new: 103.9368027391656
path: .spaces[0].spaces[1].metrics.halstead.N1
old: 7.0
new: 28.0
path: .spaces[0].spaces[1].metrics.halstead.time
old: 6.9188632372745955
new: 113.5002818065214
path: .spaces[0].spaces[1].metrics.halstead.N2
old: 5.0
new: 18.0
path: .spaces[0].spaces[1].metrics.halstead.bugs
old: 0.00831285578253799
new: 0.05366919014034088
path: .spaces[0].spaces[1].metrics.halstead.effort
old: 124.53953827094271
new: 2043.0050725173855
path: .spaces[0].spaces[1].metrics.halstead.difficulty
old: 3.0
new: 9.818181818181818
path: .spaces[0].spaces[1].metrics.halstead.level
old: 0.3333333333333333
new: 0.10185185185185185
path: .spaces[0].spaces[1].metrics.halstead.n2
old: 5.0
new: 11.0
path: .spaces[0].spaces[1].metrics.halstead.n1
old: 6.0
new: 12.0
path: .spaces[0].spaces[1].metrics.halstead.volume
old: 41.51317942364757
new: 208.0838499786226
path: .spaces[0].spaces[1].metrics.halstead.estimated_program_length
old: 27.11941547876375
new: 81.07329781366414
path: .spaces[0].spaces[1].metrics.halstead.purity_ratio
old: 2.259951289896979
new: 1.7624629959492204
path: .spaces[0].spaces[1].metrics.halstead.length
old: 12.0
new: 46.0
path: .spaces[0].spaces[1].metrics.halstead.vocabulary
old: 11.0
new: 23.0

### Code

    bool IsFile(const std::string &Path) {
      DWORD Att = GetFileAttributesA(Path.c_str());

      if (Att == INVALID_FILE_ATTRIBUTES) {
        Printf("GetFileAttributesA() failed for \"%s\" (Error code: %lu).\n",
            Path.c_str(), GetLastError());
        return false;
      }

      return IsFile(Path, Att);
    }

## Minimal test - lines (24, 411)

path: .spaces[0].metrics.mi.mi_original
old: 58.41380699801309
new: 0.2659463619974787
path: .spaces[0].metrics.mi.mi_sei
old: 40.7784340554111
new: -44.45121567986864
path: .spaces[0].metrics.mi.mi_visual_studio
old: 34.160121051469645
new: 0.1555241883026191
path: .spaces[0].metrics.nargs.sum
old: 0.0
new: 39.0
path: .spaces[0].metrics.nargs.average
old: 0.0
new: 1.3928571428571428
path: .spaces[0].metrics.cyclomatic.sum
old: 15.0
new: 108.0
path: .spaces[0].metrics.cyclomatic.average
old: 1.0714285714285714
new: 3.724137931034482
path: .spaces[0].metrics.nexits.sum
old: 12.0
new: 57.0
path: .spaces[0].metrics.nexits.average
old: 1.0
new: 2.0357142857142856
path: .spaces[0].metrics.cognitive.sum
old: 1.0
new: 101.0
path: .spaces[0].metrics.cognitive.average
old: 0.08333333333333333
new: 3.607142857142857
path: .spaces[0].metrics.halstead.difficulty
old: 13.82857142857143
new: 69.2289156626506
path: .spaces[0].metrics.halstead.volume
old: 1728.6652190148643
new: 13170.36421498185
path: .spaces[0].metrics.halstead.n2
old: 70.0
new: 166.0
path: .spaces[0].metrics.halstead.estimated_program_length
old: 493.0498111861476
new: 1397.230282206101
path: .spaces[0].metrics.halstead.length
old: 269.0
new: 1723.0
path: .spaces[0].metrics.halstead.effort
old: 23904.970457234125
new: 911770.03348537
path: .spaces[0].metrics.halstead.level
old: 0.07231404958677685
new: 0.014444831186912636
path: .spaces[0].metrics.halstead.purity_ratio
old: 1.832898926342556
new: 0.8109287766721422
path: .spaces[0].metrics.halstead.time
old: 1328.0539142907846
new: 50653.89074918722
path: .spaces[0].metrics.halstead.vocabulary
old: 86.0
new: 200.0
path: .spaces[0].metrics.halstead.N1
old: 148.0
new: 1047.0
path: .spaces[0].metrics.halstead.N2
old: 121.0
new: 676.0
path: .spaces[0].metrics.halstead.bugs
old: 0.2766119168062828
new: 3.134264340265713
path: .spaces[0].metrics.halstead.n1
old: 16.0
new: 34.0
path: .spaces[0].metrics.loc.sloc
old: 77.0
new: 388.0
path: .spaces[0].metrics.loc.cloc
old: 14.0
new: 27.0
path: .spaces[0].metrics.loc.blank
old: 12.0
new: 55.0
path: .spaces[0].metrics.loc.lloc
old: 12.0
new: 174.0
path: .spaces[0].metrics.loc.ploc
old: 51.0
new: 306.0
path: .spaces[0].metrics.nom.functions
old: 12.0
new: 28.0
path: .spaces[0].metrics.nom.total
old: 12.0
new: 28.0

### Code

    namespace fuzzer {

    static bool IsFile(const std::string &Path, const DWORD &FileAttributes) {

      if (FileAttributes & FILE_ATTRIBUTE_NORMAL)
        return true;

      if (FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
        return false;

      HANDLE FileHandle(
          CreateFileA(Path.c_str(), 0, FILE_SHARE_READ, NULL, OPEN_EXISTING,
                      FILE_FLAG_BACKUP_SEMANTICS, 0));

      if (FileHandle == INVALID_HANDLE_VALUE) {
        Printf("CreateFileA() failed for \"%s\" (Error code: %lu).\n", Path.c_str(),
            GetLastError());
        return false;
      }

      DWORD FileType = GetFileType(FileHandle);

      if (FileType == FILE_TYPE_UNKNOWN) {
        Printf("GetFileType() failed for \"%s\" (Error code: %lu).\n", Path.c_str(),
            GetLastError());
        CloseHandle(FileHandle);
        return false;
      }

      if (FileType != FILE_TYPE_DISK) {
        CloseHandle(FileHandle);
        return false;
      }

      CloseHandle(FileHandle);
      return true;
    }

    bool IsFile(const std::string &Path) {
      DWORD Att = GetFileAttributesA(Path.c_str());

      if (Att == INVALID_FILE_ATTRIBUTES) {
        Printf("GetFileAttributesA() failed for \"%s\" (Error code: %lu).\n",
            Path.c_str(), GetLastError());
        return false;
      }

      return IsFile(Path, Att);
    }

    static bool IsDir(DWORD FileAttrs) {
      if (FileAttrs == INVALID_FILE_ATTRIBUTES) return false;
      return FileAttrs & FILE_ATTRIBUTE_DIRECTORY;
    }

    std::string Basename(const std::string &Path) {
      size_t Pos = Path.find_last_of("/\\");
      if (Pos == std::string::npos) return Path;
      assert(Pos < Path.size());
      return Path.substr(Pos + 1);
    }

    size_t FileSize(const std::string &Path) {
      WIN32_FILE_ATTRIBUTE_DATA attr;
      if (!GetFileAttributesExA(Path.c_str(), GetFileExInfoStandard, &attr)) {
        DWORD LastError = GetLastError();
        if (LastError != ERROR_FILE_NOT_FOUND)
          Printf("GetFileAttributesExA() failed for \"%s\" (Error code: %lu).\n",
                 Path.c_str(), LastError);
        return 0;
      }
      ULARGE_INTEGER size;
      size.HighPart = attr.nFileSizeHigh;
      size.LowPart = attr.nFileSizeLow;
      return size.QuadPart;
    }

    void ListFilesInDirRecursive(const std::string &Dir, long *Epoch,
                                 Vector *V, bool TopDir) {
      auto E = GetEpoch(Dir);
      if (Epoch)
        if (E && *Epoch >= E) return;

      std::string Path(Dir);
      assert(!Path.empty());
      if (Path.back() != '\\')
          Path.push_back('\\');
      Path.push_back('*');

      // Get the first directory entry.
      WIN32_FIND_DATAA FindInfo;
      HANDLE FindHandle(FindFirstFileA(Path.c_str(), &FindInfo));
      if (FindHandle == INVALID_HANDLE_VALUE)
      {
        if (GetLastError() == ERROR_FILE_NOT_FOUND)
          return;
        Printf("No such file or directory: %s; exiting\n", Dir.c_str());
        exit(1);
      }

      do {
        std::string FileName = DirPlusFile(Dir, FindInfo.cFileName);

        if (FindInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
          size_t FilenameLen = strlen(FindInfo.cFileName);
          if ((FilenameLen == 1 && FindInfo.cFileName[0] == '.') ||
              (FilenameLen == 2 && FindInfo.cFileName[0] == '.' &&
                                   FindInfo.cFileName[1] == '.'))
            continue;

          ListFilesInDirRecursive(FileName, Epoch, V, false);
        }
        else if (IsFile(FileName, FindInfo.dwFileAttributes))
          V->push_back(FileName);
      } while (FindNextFileA(FindHandle, &FindInfo));

      DWORD LastError = GetLastError();
      if (LastError != ERROR_NO_MORE_FILES)
        Printf("FindNextFileA failed (Error code: %lu).\n", LastError);

      FindClose(FindHandle);

      if (Epoch && TopDir)
        *Epoch = E;
    }

    void IterateDirRecursive(const std::string &Dir,
                             void (*DirPreCallback)(const std::string &Dir),
                             void (*DirPostCallback)(const std::string &Dir),
                             void (*FileCallback)(const std::string &Dir)) {
      // TODO(metzman): Implement ListFilesInDirRecursive via this function.
      DirPreCallback(Dir);

      DWORD DirAttrs = GetFileAttributesA(Dir.c_str());
      if (!IsDir(DirAttrs)) return;

      std::string TargetDir(Dir);
      assert(!TargetDir.empty());
      if (TargetDir.back() != '\\') TargetDir.push_back('\\');
      TargetDir.push_back('*');

      WIN32_FIND_DATAA FindInfo;
      // Find the directory's first file.
      HANDLE FindHandle = FindFirstFileA(TargetDir.c_str(), &FindInfo);
      if (FindHandle == INVALID_HANDLE_VALUE) {
        DWORD LastError = GetLastError();
        if (LastError != ERROR_FILE_NOT_FOUND) {
          // If the directory isn't empty, then something abnormal is going on.
          Printf("FindFirstFileA failed for %s (Error code: %lu).\n", Dir.c_str(),
                 LastError);
        }
        return;
      }

      do {
        std::string Path = DirPlusFile(Dir, FindInfo.cFileName);
        DWORD PathAttrs = FindInfo.dwFileAttributes;
        if (IsDir(PathAttrs)) {
          // Is Path the current directory (".") or the parent ("..")?
          if (strcmp(FindInfo.cFileName, ".") == 0 ||
              strcmp(FindInfo.cFileName, "..") == 0)
            continue;
          IterateDirRecursive(Path, DirPreCallback, DirPostCallback, FileCallback);
        } else if (PathAttrs != INVALID_FILE_ATTRIBUTES) {
          FileCallback(Path);
        }
      } while (FindNextFileA(FindHandle, &FindInfo));

      DWORD LastError = GetLastError();
      if (LastError != ERROR_NO_MORE_FILES)
        Printf("FindNextFileA failed for %s (Error code: %lu).\n", Dir.c_str(),
               LastError);

      FindClose(FindHandle);
      DirPostCallback(Dir);
    }

    char GetSeparator() {
      return '\\';
    }

    FILE* OpenFile(int Fd, const char* Mode) {
      return _fdopen(Fd, Mode);
    }

    int CloseFile(int Fd) {
      return _close(Fd);
    }

    int DuplicateFile(int Fd) {
      return _dup(Fd);
    }

    void RemoveFile(const std::string &Path) {
      _unlink(Path.c_str());
    }

    void RenameFile(const std::string &OldPath, const std::string &NewPath) {
      rename(OldPath.c_str(), NewPath.c_str());
    }

    intptr_t GetHandleFromFd(int fd) {
      return _get_osfhandle(fd);
    }

    static bool IsSeparator(char C) {
      return C == '\\' || C == '/';
    }

    // Parse disk designators, like "C:\". If Relative == true, also accepts: "C:".
    // Returns number of characters considered if successful.
    static size_t ParseDrive(const std::string &FileName, const size_t Offset,
                             bool Relative = true) {
      if (Offset + 1 >= FileName.size() || FileName[Offset + 1] != ':')
        return 0;
      if (Offset + 2 >= FileName.size() || !IsSeparator(FileName[Offset + 2])) {
        if (!Relative) // Accept relative path?
          return 0;
        else
          return 2;
      }
      return 3;
    }

    // Parse a file name, like: SomeFile.txt
    // Returns number of characters considered if successful.
    static size_t ParseFileName(const std::string &FileName, const size_t Offset) {
      size_t Pos = Offset;
      const size_t End = FileName.size();
      for(; Pos < End && !IsSeparator(FileName[Pos]); ++Pos)
        ;
      return Pos - Offset;
    }

    // Parse a directory ending in separator, like: `SomeDir\`
    // Returns number of characters considered if successful.
    static size_t ParseDir(const std::string &FileName, const size_t Offset) {
      size_t Pos = Offset;
      const size_t End = FileName.size();
      if (Pos >= End || IsSeparator(FileName[Pos]))
        return 0;
      for(; Pos < End && !IsSeparator(FileName[Pos]); ++Pos)
        ;
      if (Pos >= End)
        return 0;
      ++Pos; // Include separator.
      return Pos - Offset;
    }

    // Parse a servername and share, like: `SomeServer\SomeShare\`
    // Returns number of characters considered if successful.
    static size_t ParseServerAndShare(const std::string &FileName,
                                      const size_t Offset) {
      size_t Pos = Offset, Res;
      if (!(Res = ParseDir(FileName, Pos)))
        return 0;
      Pos += Res;
      if (!(Res = ParseDir(FileName, Pos)))
        return 0;
      Pos += Res;
      return Pos - Offset;
    }

    // Parse the given Ref string from the position Offset, to exactly match the given
    // string Patt.
    // Returns number of characters considered if successful.
    static size_t ParseCustomString(const std::string &Ref, size_t Offset,
                                    const char *Patt) {
      size_t Len = strlen(Patt);
      if (Offset + Len > Ref.size())
        return 0;
      return Ref.compare(Offset, Len, Patt) == 0 ? Len : 0;
    }

    // Parse a location, like:
    // \\?\UNC\Server\Share\  \\?\C:\  \\Server\Share\  \  C:\  C:
    // Returns number of characters considered if successful.
    static size_t ParseLocation(const std::string &FileName) {
      size_t Pos = 0, Res;

      if ((Res = ParseCustomString(FileName, Pos, R"(\\?\)"))) {
        Pos += Res;
        if ((Res = ParseCustomString(FileName, Pos, R"(UNC\)"))) {
          Pos += Res;
          if ((Res = ParseServerAndShare(FileName, Pos)))
            return Pos + Res;
          return 0;
        }
        if ((Res = ParseDrive(FileName, Pos, false)))
          return Pos + Res;
        return 0;
      }

      if (Pos < FileName.size() && IsSeparator(FileName[Pos])) {
        ++Pos;
        if (Pos < FileName.size() && IsSeparator(FileName[Pos])) {
          ++Pos;
          if ((Res = ParseServerAndShare(FileName, Pos)))
            return Pos + Res;
          return 0;
        }
        return Pos;
      }

      if ((Res = ParseDrive(FileName, Pos)))
        return Pos + Res;

      return Pos;
    }

    std::string DirName(const std::string &FileName) {
      size_t LocationLen = ParseLocation(FileName);
      size_t DirLen = 0, Res;
      while ((Res = ParseDir(FileName, LocationLen + DirLen)))
        DirLen += Res;
      size_t FileLen = ParseFileName(FileName, LocationLen + DirLen);

      if (LocationLen + DirLen + FileLen != FileName.size()) {
        Printf("DirName() failed for \"%s\", invalid path.\n", FileName.c_str());
        exit(1);
      }

      if (DirLen) {
        --DirLen; // Remove trailing separator.
        if (!FileLen) { // Path ended in separator.
          assert(DirLen);
          // Remove file name from Dir.
          while (DirLen && !IsSeparator(FileName[LocationLen + DirLen - 1]))
            --DirLen;
          if (DirLen) // Remove trailing separator.
            --DirLen;
        }
      }

      if (!LocationLen) { // Relative path.
        if (!DirLen)
          return ".";
        return std::string(".\\").append(FileName, 0, DirLen);
      }

      return FileName.substr(0, LocationLen + DirLen);
    }

    std::string TmpDir() {
      std::string Tmp;
      Tmp.resize(MAX_PATH + 1);
      DWORD Size = GetTempPathA(Tmp.size(), &Tmp[0]);
      if (Size == 0) {
        Printf("Couldn't get Tmp path.\n");
        exit(1);
      }
      Tmp.resize(Size);
      return Tmp;
    }

    bool IsInterestingCoverageFile(const std::string &FileName) {
      if (FileName.find("Program Files") != std::string::npos)
        return false;
      if (FileName.find("compiler-rt\\lib\\") != std::string::npos)
        return false; // sanitizer internal.
      if (FileName == "")
        return false;
      return true;
    }

    void RawPrint(const char *Str) {
      _write(2, Str, strlen(Str));
    }

    void MkDir(const std::string &Path) {
      if (CreateDirectoryA(Path.c_str(), nullptr)) return;
      Printf("CreateDirectoryA failed for %s (Error code: %lu).\n", Path.c_str(),
             GetLastError());
    }

    void RmDir(const std::string &Path) {
      if (RemoveDirectoryA(Path.c_str())) return;
      Printf("RemoveDirectoryA failed for %s (Error code: %lu).\n", Path.c_str(),
             GetLastError());
    }

    const std::string &getDevNull() {
      static const std::string devNull = "NUL";
      return devNull;
    }

    }  // namespace fuzzer

## Minimal test - lines (26, 60)

path: .spaces[0].spaces[0].metrics.loc.sloc
old: 22.0
new: 35.0
path: .spaces[0].spaces[0].metrics.loc.cloc
old: 12.0
new: 0.0
path: .spaces[0].spaces[0].metrics.loc.lloc
old: 4.0
new: 16.0
path: .spaces[0].spaces[0].metrics.loc.blank
old: 0.0
new: 8.0
path: .spaces[0].spaces[0].metrics.loc.ploc
old: 10.0
new: 27.0
path: .spaces[0].spaces[0].metrics.mi.mi_original
old: 89.67353394498502
new: 78.34226940064421
path: .spaces[0].spaces[0].metrics.mi.mi_sei
old: 99.7996697498515
new: 37.93407072071062
path: .spaces[0].spaces[0].metrics.mi.mi_visual_studio
old: 52.44066312572224
new: 45.81419263195568
path: .spaces[0].spaces[0].metrics.cyclomatic.average
old: 1.2
new: 6.0
path: .spaces[0].spaces[0].metrics.cognitive.sum
old: 1.0
new: 5.0
path: .spaces[0].spaces[0].metrics.cognitive.average
old: 0.25
new: 5.0
path: .spaces[0].spaces[0].metrics.halstead.effort
old: 3046.6611818540064
new: 7963.779793270693
path: .spaces[0].spaces[0].metrics.halstead.N2
old: 26.0
new: 49.0
path: .spaces[0].spaces[0].metrics.halstead.estimated_program_length
old: 107.01955000865388
new: 170.3171490075026
path: .spaces[0].spaces[0].metrics.halstead.vocabulary
old: 28.0
new: 39.0
path: .spaces[0].spaces[0].metrics.halstead.time
old: 169.2589545474448
new: 442.4322107372607
path: .spaces[0].spaces[0].metrics.halstead.n1
old: 12.0
new: 13.0
path: .spaces[0].spaces[0].metrics.halstead.difficulty
old: 9.75
new: 12.25
path: .spaces[0].spaces[0].metrics.halstead.N1
old: 39.0
new: 74.0
path: .spaces[0].spaces[0].metrics.halstead.n2
old: 16.0
new: 26.0
path: .spaces[0].spaces[0].metrics.halstead.length
old: 65.0
new: 123.0
path: .spaces[0].spaces[0].metrics.halstead.purity_ratio
old: 1.646454615517752
new: 1.3846922683536795
path: .spaces[0].spaces[0].metrics.halstead.volume
old: 312.4780699337442
new: 650.1044729200565
path: .spaces[0].spaces[0].metrics.halstead.bugs
old: 0.07005323327136247
new: 0.132930582297863
path: .spaces[0].spaces[0].metrics.halstead.level
old: 0.10256410256410256
new: 0.08163265306122448
path: .spaces[0].spaces[0].metrics.nom.functions
old: 4.0
new: 1.0
path: .spaces[0].spaces[0].metrics.nom.total
old: 4.0
new: 1.0
path: .spaces[0].spaces[0].metrics.nargs.sum
old: 0.0
new: 2.0
path: .spaces[0].spaces[0].metrics.nargs.average
old: 0.0
new: 2.0
path: .spaces[0].spaces[0].metrics.nexits.average
old: 1.0
new: 6.0
path: .spaces[0].spaces[0].metrics.nexits.sum
old: 4.0
new: 6.0

### Code

    static bool IsFile(const std::string &Path, const DWORD &FileAttributes) {

      if (FileAttributes & FILE_ATTRIBUTE_NORMAL)
        return true;

      if (FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
        return false;

      HANDLE FileHandle(
          CreateFileA(Path.c_str(), 0, FILE_SHARE_READ, NULL, OPEN_EXISTING,
                      FILE_FLAG_BACKUP_SEMANTICS, 0));

      if (FileHandle == INVALID_HANDLE_VALUE) {
        Printf("CreateFileA() failed for \"%s\" (Error code: %lu).\n", Path.c_str(),
            GetLastError());
        return false;
      }

      DWORD FileType = GetFileType(FileHandle);

      if (FileType == FILE_TYPE_UNKNOWN) {
        Printf("GetFileType() failed for \"%s\" (Error code: %lu).\n", Path.c_str(),
            GetLastError());
        CloseHandle(FileHandle);
        return false;
      }

      if (FileType != FILE_TYPE_DISK) {
        CloseHandle(FileHandle);
        return false;
      }

      CloseHandle(FileHandle);
      return true;
    }

## Minimal test - lines (74, 77)

path: .spaces[0].spaces[2].metrics.nargs.sum
old: 0.0
new: 1.0
path: .spaces[0].spaces[2].metrics.nargs.average
old: 0.0
new: 1.0
path: .spaces[0].spaces[2].metrics.halstead.estimated_program_length
old: 12.754887502163468
new: 35.60964047443681
path: .spaces[0].spaces[2].metrics.halstead.purity_ratio
old: 1.8221267860233523
new: 1.8741916039177269
path: .spaces[0].spaces[2].metrics.halstead.n2
old: 3.0
new: 5.0
path: .spaces[0].spaces[2].metrics.halstead.N2
old: 3.0
new: 7.0
path: .spaces[0].spaces[2].metrics.halstead.difficulty
old: 2.0
new: 5.6
path: .spaces[0].spaces[2].metrics.halstead.volume
old: 19.651484454403228
new: 70.30835464468075
path: .spaces[0].spaces[2].metrics.halstead.level
old: 0.5
new: 0.17857142857142858
path: .spaces[0].spaces[2].metrics.halstead.n1
old: 4.0
new: 8.0
path: .spaces[0].spaces[2].metrics.halstead.vocabulary
old: 7.0
new: 13.0
path: .spaces[0].spaces[2].metrics.halstead.effort
old: 39.302968908806456
new: 393.72678601021215
path: .spaces[0].spaces[2].metrics.halstead.bugs
old: 0.0038532659414573967
new: 0.01790641806124263
path: .spaces[0].spaces[2].metrics.halstead.length
old: 7.0
new: 19.0
path: .spaces[0].spaces[2].metrics.halstead.time
old: 2.1834982727114696
new: 21.873710333900675
path: .spaces[0].spaces[2].metrics.halstead.N1
old: 4.0
new: 12.0
path: .spaces[0].spaces[2].metrics.loc.ploc
old: 1.0
new: 4.0
path: .spaces[0].spaces[2].metrics.loc.sloc
old: 1.0
new: 4.0
path: .spaces[0].spaces[2].metrics.loc.lloc
old: 1.0
new: 3.0
path: .spaces[0].spaces[2].metrics.mi.mi_sei
old: 148.4278547652622
new: 106.23475401527978
path: .spaces[0].spaces[2].metrics.mi.mi_original
old: 155.2836050228807
new: 125.96700005047744
path: .spaces[0].spaces[2].metrics.mi.mi_visual_studio
old: 90.80912574437468
new: 73.66491231022073
path: .spaces[0].spaces[2].metrics.cognitive.sum
old: 0.0
new: 1.0
path: .spaces[0].spaces[2].metrics.cognitive.average
old: 0.0
new: 1.0
path: .spaces[0].spaces[2].metrics.cyclomatic.average
old: 1.0
new: 2.0
path: .spaces[0].spaces[2].metrics.cyclomatic.sum
old: 1.0
new: 2.0
path: .spaces[0].spaces[2].metrics.nexits.average
old: 1.0
new: 2.0
path: .spaces[0].spaces[2].metrics.nexits.sum
old: 1.0
new: 2.0

### Code

    static bool IsDir(DWORD FileAttrs) {
      if (FileAttrs == INVALID_FILE_ATTRIBUTES) return false;
      return FileAttrs & FILE_ATTRIBUTE_DIRECTORY;
    }

## Minimal test - lines (202, 204)

path: .spaces[0].spaces[7].metrics.halstead.N1
old: 4.0
new: 5.0
path: .spaces[0].spaces[7].metrics.halstead.N2
old: 3.0
new: 1.0
path: .spaces[0].spaces[7].metrics.halstead.level
old: 0.5
new: 0.4
path: .spaces[0].spaces[7].metrics.halstead.estimated_program_length
old: 12.754887502163468
new: 11.60964047443681
path: .spaces[0].spaces[7].metrics.halstead.volume
old: 19.651484454403228
new: 15.509775004326936
path: .spaces[0].spaces[7].metrics.halstead.n2
old: 3.0
new: 1.0
path: .spaces[0].spaces[7].metrics.halstead.time
old: 2.1834982727114696
new: 2.1541354172676304
path: .spaces[0].spaces[7].metrics.halstead.vocabulary
old: 7.0
new: 6.0
path: .spaces[0].spaces[7].metrics.halstead.difficulty
old: 2.0
new: 2.5
path: .spaces[0].spaces[7].metrics.halstead.purity_ratio
old: 1.8221267860233523
new: 1.9349400790728015
path: .spaces[0].spaces[7].metrics.halstead.effort
old: 39.302968908806456
new: 38.77443751081734
path: .spaces[0].spaces[7].metrics.halstead.bugs
old: 0.0038532659414573967
new: 0.00381864321284214
path: .spaces[0].spaces[7].metrics.halstead.n1
old: 4.0
new: 5.0
path: .spaces[0].spaces[7].metrics.halstead.length
old: 7.0
new: 6.0
path: .spaces[0].spaces[7].metrics.mi.mi_sei
old: 148.4278547652622
new: 124.52705705444804
path: .spaces[0].spaces[7].metrics.mi.mi_original
old: 155.2836050228807
new: 138.71683447649625
path: .spaces[0].spaces[7].metrics.mi.mi_visual_studio
old: 90.80912574437468
new: 81.12095583420833
path: .spaces[0].spaces[7].metrics.loc.sloc
old: 1.0
new: 3.0
path: .spaces[0].spaces[7].metrics.loc.ploc
old: 1.0
new: 3.0

### Code

    char GetSeparator() {
      return '\\';
    }

## Minimal test - lines (86, 99)

path: .spaces[0].spaces[4].metrics.nexits.average
old: 1.0
new: 2.0
path: .spaces[0].spaces[4].metrics.nexits.sum
old: 1.0
new: 2.0
path: .spaces[0].spaces[4].metrics.cyclomatic.average
old: 1.0
new: 3.0
path: .spaces[0].spaces[4].metrics.cyclomatic.sum
old: 1.0
new: 3.0
path: .spaces[0].spaces[4].metrics.mi.mi_sei
old: 146.92819499625
new: 64.03687204171334
path: .spaces[0].spaces[4].metrics.mi.mi_visual_studio
old: 90.2012398141466
new: 56.51876081077621
path: .spaces[0].spaces[4].metrics.mi.mi_original
old: 154.24412008219068
new: 96.64708098642733
path: .spaces[0].spaces[4].metrics.loc.lloc
old: 1.0
new: 7.0
path: .spaces[0].spaces[4].metrics.loc.sloc
old: 1.0
new: 14.0
path: .spaces[0].spaces[4].metrics.loc.ploc
old: 1.0
new: 14.0
path: .spaces[0].spaces[4].metrics.nargs.sum
old: 0.0
new: 1.0
path: .spaces[0].spaces[4].metrics.nargs.average
old: 0.0
new: 1.0
path: .spaces[0].spaces[4].metrics.halstead.difficulty
old: 2.5
new: 9.904761904761903
path: .spaces[0].spaces[4].metrics.halstead.N2
old: 3.0
new: 32.0
path: .spaces[0].spaces[4].metrics.halstead.estimated_program_length
old: 16.36452797660028
new: 140.34438221418816
path: .spaces[0].spaces[4].metrics.halstead.vocabulary
old: 8.0
new: 34.0
path: .spaces[0].spaces[4].metrics.halstead.effort
old: 60.0
new: 3779.258110643109
path: .spaces[0].spaces[4].metrics.halstead.n1
old: 5.0
new: 13.0
path: .spaces[0].spaces[4].metrics.halstead.bugs
old: 0.005108729549290353
new: 0.08087540114591991
path: .spaces[0].spaces[4].metrics.halstead.length
old: 8.0
new: 75.0
path: .spaces[0].spaces[4].metrics.halstead.purity_ratio
old: 2.045565997075035
new: 1.8712584295225088
path: .spaces[0].spaces[4].metrics.halstead.volume
old: 24.0
new: 381.55971309377543
path: .spaces[0].spaces[4].metrics.halstead.N1
old: 5.0
new: 43.0
path: .spaces[0].spaces[4].metrics.halstead.n2
old: 3.0
new: 21.0
path: .spaces[0].spaces[4].metrics.halstead.level
old: 0.4
new: 0.10096153846153846
path: .spaces[0].spaces[4].metrics.halstead.time
old: 3.3333333333333335
new: 209.95878392461717
path: .spaces[0].spaces[4].metrics.cognitive.average
old: 0.0
new: 3.0
path: .spaces[0].spaces[4].metrics.cognitive.sum
old: 0.0
new: 3.0

### Code

    size_t FileSize(const std::string &Path) {
      WIN32_FILE_ATTRIBUTE_DATA attr;
      if (!GetFileAttributesExA(Path.c_str(), GetFileExInfoStandard, &attr)) {
        DWORD LastError = GetLastError();
        if (LastError != ERROR_FILE_NOT_FOUND)
          Printf("GetFileAttributesExA() failed for \"%s\" (Error code: %lu).\n",
                 Path.c_str(), LastError);
        return 0;
      }
      ULARGE_INTEGER size;
      size.HighPart = attr.nFileSizeHigh;
      size.LowPart = attr.nFileSizeLow;
      return size.QuadPart;
    }

## Minimal test - lines (101, 148)

path: .spaces[0].spaces[5].metrics.nexits.average
old: 1.0
new: 2.0
path: .spaces[0].spaces[5].metrics.nexits.sum
old: 1.0
new: 2.0
path: .spaces[0].spaces[5].metrics.halstead.bugs
old: 0.005108729549290353
new: 0.42436522748983424
path: .spaces[0].spaces[5].metrics.halstead.N2
old: 3.0
new: 98.0
path: .spaces[0].spaces[5].metrics.halstead.purity_ratio
old: 2.045565997075035
new: 1.4174340017413671
path: .spaces[0].spaces[5].metrics.halstead.difficulty
old: 2.5
new: 30.333333333333332
path: .spaces[0].spaces[5].metrics.halstead.n2
old: 3.0
new: 42.0
path: .spaces[0].spaces[5].metrics.halstead.length
old: 8.0
new: 246.0
path: .spaces[0].spaces[5].metrics.halstead.n1
old: 5.0
new: 26.0
path: .spaces[0].spaces[5].metrics.halstead.volume
old: 24.0
new: 1497.5158589475834
path: .spaces[0].spaces[5].metrics.halstead.vocabulary
old: 8.0
new: 68.0
path: .spaces[0].spaces[5].metrics.halstead.level
old: 0.4
new: 0.03296703296703297
path: .spaces[0].spaces[5].metrics.halstead.N1
old: 5.0
new: 148.0
path: .spaces[0].spaces[5].metrics.halstead.effort
old: 60.0
new: 45424.64772141003
path: .spaces[0].spaces[5].metrics.halstead.estimated_program_length
old: 16.36452797660028
new: 348.6887644283763
path: .spaces[0].spaces[5].metrics.halstead.time
old: 3.3333333333333335
new: 2523.591540078335
path: .spaces[0].spaces[5].metrics.cognitive.sum
old: 0.0
new: 20.0
path: .spaces[0].spaces[5].metrics.cognitive.average
old: 0.0
new: 20.0
path: .spaces[0].spaces[5].metrics.cyclomatic.sum
old: 1.0
new: 18.0
path: .spaces[0].spaces[5].metrics.cyclomatic.average
old: 1.0
new: 18.0
path: .spaces[0].spaces[5].metrics.loc.ploc
old: 1.0
new: 39.0
path: .spaces[0].spaces[5].metrics.loc.sloc
old: 1.0
new: 48.0
path: .spaces[0].spaces[5].metrics.loc.blank
old: 0.0
new: 8.0
path: .spaces[0].spaces[5].metrics.loc.cloc
old: 0.0
new: 1.0
path: .spaces[0].spaces[5].metrics.loc.lloc
old: 1.0
new: 23.0
path: .spaces[0].spaces[5].metrics.mi.mi_sei
old: 146.92819499625
new: 32.61956157946088
path: .spaces[0].spaces[5].metrics.mi.mi_visual_studio
old: 90.2012398141466
new: 38.67041896969032
path: .spaces[0].spaces[5].metrics.mi.mi_original
old: 154.24412008219068
new: 66.12641643817045
path: .spaces[0].spaces[5].metrics.nargs.average
old: 0.0
new: 4.0
path: .spaces[0].spaces[5].metrics.nargs.sum
old: 0.0
new: 4.0

### Code

    void ListFilesInDirRecursive(const std::string &Dir, long *Epoch,
                                 Vector *V, bool TopDir) {
      auto E = GetEpoch(Dir);
      if (Epoch)
        if (E && *Epoch >= E) return;

      std::string Path(Dir);
      assert(!Path.empty());
      if (Path.back() != '\\')
          Path.push_back('\\');
      Path.push_back('*');

      // Get the first directory entry.
      WIN32_FIND_DATAA FindInfo;
      HANDLE FindHandle(FindFirstFileA(Path.c_str(), &FindInfo));
      if (FindHandle == INVALID_HANDLE_VALUE)
      {
        if (GetLastError() == ERROR_FILE_NOT_FOUND)
          return;
        Printf("No such file or directory: %s; exiting\n", Dir.c_str());
        exit(1);
      }

      do {
        std::string FileName = DirPlusFile(Dir, FindInfo.cFileName);

        if (FindInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
          size_t FilenameLen = strlen(FindInfo.cFileName);
          if ((FilenameLen == 1 && FindInfo.cFileName[0] == '.') ||
              (FilenameLen == 2 && FindInfo.cFileName[0] == '.' &&
                                   FindInfo.cFileName[1] == '.'))
            continue;

          ListFilesInDirRecursive(FileName, Epoch, V, false);
        }
        else if (IsFile(FileName, FindInfo.dwFileAttributes))
          V->push_back(FileName);
      } while (FindNextFileA(FindHandle, &FindInfo));

      DWORD LastError = GetLastError();
      if (LastError != ERROR_NO_MORE_FILES)
        Printf("FindNextFileA failed (Error code: %lu).\n", LastError);

      FindClose(FindHandle);

      if (Epoch && TopDir)
        *Epoch = E;
    }