In FileManager: use full paths to unique files and directories on Windows,

since inodes are bogus abstraction on that platform.

Patch by Argiris Kirtzidis!


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@47535 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Ted Kremenek 2008-02-24 03:15:25 +00:00
Родитель 10c5fa3b17
Коммит 6bb816a3b8
2 изменённых файлов: 118 добавлений и 16 удалений

Просмотреть файл

@ -22,6 +22,7 @@
#include "llvm/Bitcode/Serialize.h"
#include "llvm/Bitcode/Deserialize.h"
#include "llvm/Support/Streams.h"
#include "llvm/Config/config.h"
using namespace clang;
// FIXME: Enhance libsystem to support inode and other fields.
@ -35,6 +36,107 @@ using namespace clang;
/// represent a dir name that doesn't exist on the disk.
#define NON_EXISTENT_DIR reinterpret_cast<DirectoryEntry*>((intptr_t)-1)
#ifdef LLVM_ON_WIN32
#define IS_DIR_SEPARATOR_CHAR(x) ((x) == '/' || (x) == '\\')
namespace {
static std::string GetFullPath(const char *relPath)
{
char *absPathStrPtr = _fullpath(NULL, relPath, 0);
assert(absPathStrPtr && "_fullpath() returned NULL!");
std::string absPath(absPathStrPtr);
free(absPathStrPtr);
return absPath;
}
}
class FileManager::UniqueDirContainer {
/// UniqueDirs - Cache from full path to existing directories/files.
///
llvm::StringMap<DirectoryEntry> UniqueDirs;
public:
DirectoryEntry &getDirectory(const char *Name, struct stat &StatBuf) {
std::string FullPath(GetFullPath(Name));
return UniqueDirs.GetOrCreateValue(
FullPath.c_str(),
FullPath.c_str() + FullPath.size()
).getValue();
}
size_t size() { return UniqueDirs.size(); }
};
class FileManager::UniqueFileContainer {
/// UniqueFiles - Cache from full path to existing directories/files.
///
llvm::StringMap<FileEntry> UniqueFiles;
public:
FileEntry &getFile(const char *Name, struct stat &StatBuf) {
std::string FullPath(GetFullPath(Name));
return UniqueFiles.GetOrCreateValue(
FullPath.c_str(),
FullPath.c_str() + FullPath.size()
).getValue();
}
size_t size() { return UniqueFiles.size(); }
};
#else
#define IS_DIR_SEPARATOR_CHAR(x) ((x) == '/')
class FileManager::UniqueDirContainer {
/// UniqueDirs - Cache from ID's to existing directories/files.
///
std::map<std::pair<dev_t, ino_t>, DirectoryEntry> UniqueDirs;
public:
DirectoryEntry &getDirectory(const char *Name, struct stat &StatBuf) {
return UniqueDirs[std::make_pair(StatBuf.st_dev, StatBuf.st_ino)];
}
size_t size() { return UniqueDirs.size(); }
};
class FileManager::UniqueFileContainer {
/// UniqueFiles - Cache from ID's to existing directories/files.
///
std::set<FileEntry> UniqueFiles;
public:
FileEntry &getFile(const char *Name, struct stat &StatBuf) {
return
const_cast<FileEntry&>(
*UniqueFiles.insert(FileEntry(StatBuf.st_dev,
StatBuf.st_ino)).first);
}
size_t size() { return UniqueFiles.size(); }
};
#endif
FileManager::FileManager() : UniqueDirs(*new UniqueDirContainer),
UniqueFiles(*new UniqueFileContainer),
DirEntries(64), FileEntries(64), NextFileUID(0)
{
NumDirLookups = NumFileLookups = 0;
NumDirCacheMisses = NumFileCacheMisses = 0;
}
FileManager::~FileManager() {
delete &UniqueDirs;
delete &UniqueFiles;
}
/// getDirectory - Lookup, cache, and verify the specified directory. This
/// returns null if the directory doesn't exist.
///
@ -63,11 +165,10 @@ const DirectoryEntry *FileManager::getDirectory(const char *NameStart,
if (stat(InterndDirName, &StatBuf) || // Error stat'ing.
!S_ISDIR(StatBuf.st_mode)) // Not a directory?
return 0;
// It exists. See if we have already opened a directory with the same inode.
// This occurs when one dir is symlinked to another, for example.
DirectoryEntry &UDE =
UniqueDirs[std::make_pair(StatBuf.st_dev, StatBuf.st_ino)];
DirectoryEntry &UDE = UniqueDirs.getDirectory(InterndDirName, StatBuf);
NamedDirEnt.setValue(&UDE);
if (UDE.getName()) // Already have an entry with this inode, return it.
@ -108,7 +209,7 @@ const FileEntry *FileManager::getFile(const char *NameStart,
// strip off everything after it.
// FIXME: this logic should be in sys::Path.
const char *SlashPos = NameEnd-1;
while (SlashPos >= NameStart && SlashPos[0] != '/')
while (SlashPos >= NameStart && !IS_DIR_SEPARATOR_CHAR(SlashPos[0]))
--SlashPos;
const DirectoryEntry *DirInfo;
@ -144,10 +245,7 @@ const FileEntry *FileManager::getFile(const char *NameStart,
// It exists. See if we have already opened a file with the same inode.
// This occurs when one dir is symlinked to another, for example.
FileEntry &UFE =
const_cast<FileEntry&>(*UniqueFiles.insert(FileEntry(StatBuf.st_dev,
StatBuf.st_ino)).first);
FileEntry &UFE = UniqueFiles.getFile(InterndFileName, StatBuf);
NamedFileEnt.setValue(&UFE);
if (UFE.getName()) // Already have an entry with this inode, return it.

Просмотреть файл

@ -48,6 +48,8 @@ class FileEntry {
friend class FileManager;
public:
FileEntry(dev_t device, ino_t inode) : Name(0), Device(device), Inode(inode){}
// Add a default constructor for use with llvm::StringMap
FileEntry() : Name(0), Device(0), Inode(0) {}
const char *getName() const { return Name; }
off_t getSize() const { return Size; }
@ -72,11 +74,15 @@ public:
/// names (e.g. symlinked) will be treated as a single file.
///
class FileManager {
/// UniqueDirs/UniqueFiles - Cache from ID's to existing directories/files.
class UniqueDirContainer;
class UniqueFileContainer;
/// UniqueDirs/UniqueFiles - Cache for existing directories/files.
///
std::map<std::pair<dev_t, ino_t>, DirectoryEntry> UniqueDirs;
std::set<FileEntry> UniqueFiles;
UniqueDirContainer &UniqueDirs;
UniqueFileContainer &UniqueFiles;
/// DirEntries/FileEntries - This is a cache of directory/file entries we have
/// looked up. The actual Entry is owned by UniqueFiles/UniqueDirs above.
///
@ -91,10 +97,8 @@ class FileManager {
unsigned NumDirLookups, NumFileLookups;
unsigned NumDirCacheMisses, NumFileCacheMisses;
public:
FileManager() : DirEntries(64), FileEntries(64), NextFileUID(0) {
NumDirLookups = NumFileLookups = 0;
NumDirCacheMisses = NumFileCacheMisses = 0;
}
FileManager();
~FileManager();
/// getDirectory - Lookup, cache, and verify the specified directory. This
/// returns null if the directory doesn't exist.