diff options
Diffstat (limited to 'Lex/HeaderMap.cpp')
-rw-r--r-- | Lex/HeaderMap.cpp | 54 |
1 files changed, 52 insertions, 2 deletions
diff --git a/Lex/HeaderMap.cpp b/Lex/HeaderMap.cpp index 5b9c4b0d23..ebcbc17f80 100644 --- a/Lex/HeaderMap.cpp +++ b/Lex/HeaderMap.cpp @@ -12,10 +12,60 @@ //===----------------------------------------------------------------------===// #include "clang/Lex/HeaderMap.h" +#include "clang/Basic/FileManager.h" +#include "llvm/ADT/scoped_ptr.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/MemoryBuffer.h" using namespace clang; -const HeaderMap *HeaderMap::Create(const FileEntry *FE, std::string &ErrorInfo){ - // FIXME: woot! +enum { + HeaderMagicNumber = ('h' << 24) | ('m' << 16) | ('a' << 8) | 'p' +}; + +struct HMapHeader { + uint32_t Magic; // Magic word, also indicates byte order. + uint16_t Version; // Version number -- currently 1. + uint16_t Reserved; // Reserved for future use - zero for now. + uint32_t StringsOffset; // Offset to start of string pool. + uint32_t Count; // Number of entries in the string table. + uint32_t Capacity; // Number of buckets (always a power of 2). + uint32_t MaxValueLength; // Length of longest result path (excluding nul). + // Strings follow the buckets, at StringsOffset. +}; + + +/// HeaderMap::Create - This attempts to load the specified file as a header +/// map. If it doesn't look like a HeaderMap, it gives up and returns null. +/// If it looks like a HeaderMap but is obviously corrupted, it puts a reason +/// into the string error argument and returns null. +const HeaderMap *HeaderMap::Create(const FileEntry *FE) { + // If the file is too small to be a header map, ignore it. + unsigned FileSize = FE->getSize(); + if (FileSize <= sizeof(HMapHeader)) return 0; + + llvm::scoped_ptr<const llvm::MemoryBuffer> File( + llvm::MemoryBuffer::getFile(FE->getName(), strlen(FE->getName()), 0, + FE->getSize())); + if (File == 0) return 0; // Unreadable file? + const char *FileStart = File->getBufferStart(); + + // We know the file is at least as big as the header, check it now. + const HMapHeader *Header = reinterpret_cast<const HMapHeader*>(FileStart); + + // Sniff it to see if it's a headermap. + if (Header->Version != 1 || Header->Reserved != 0) + return 0; + + // Check the magic number. + bool NeedsByteSwap; + if (Header->Magic == HeaderMagicNumber) + NeedsByteSwap = false; + else if (Header->Magic == llvm::ByteSwap_32(HeaderMagicNumber)) + NeedsByteSwap = true; // Mixed endianness headermap. + else + return 0; // Not a header map. + return 0; } |