#include "llvm/Support/MemoryBuffer.h"
#include "llvm/System/MappedFile.h"
#include "llvm/System/Process.h"
+#include "llvm/System/Program.h"
#include <cassert>
#include <cstdio>
#include <cstring>
BufferEnd = BufferStart+Size;
memcpy(const_cast<char*>(BufferStart), BufStart, Size);
*const_cast<char*>(BufferEnd) = 0; // Null terminate buffer.
- MustDeleteBuffer = false;
+ MustDeleteBuffer = true;
}
/// init - Initialize this MemoryBuffer as a reference to externally allocated
class MemoryBufferMem : public MemoryBuffer {
std::string FileID;
public:
- MemoryBufferMem(const char *Start, const char *End, const char *FID)
+ MemoryBufferMem(const char *Start, const char *End, const char *FID,
+ bool Copy = false)
: FileID(FID) {
- init(Start, End);
+ if (!Copy)
+ init(Start, End);
+ else
+ initCopyOf(Start, End);
}
virtual const char *getBufferIdentifier() const {
return new MemoryBufferMem(StartPtr, EndPtr, BufferName);
}
+/// getMemBufferCopy - Open the specified memory range as a MemoryBuffer,
+/// copying the contents and taking ownership of it. This has no requirements
+/// on EndPtr[0].
+MemoryBuffer *MemoryBuffer::getMemBufferCopy(const char *StartPtr,
+ const char *EndPtr,
+ const char *BufferName) {
+ return new MemoryBufferMem(StartPtr, EndPtr, BufferName, true);
+}
+
/// getNewUninitMemBuffer - Allocate a new MemoryBuffer of the specified size
/// that is completely initialized to zeros. Note that the caller should
/// initialize the memory allocated by this method. The memory is owned by
class MemoryBufferMMapFile : public MemoryBuffer {
sys::MappedFile File;
public:
- MemoryBufferMMapFile(const sys::Path &Filename);
+ MemoryBufferMMapFile() {}
+
+ bool open(const sys::Path &Filename, std::string *ErrStr);
virtual const char *getBufferIdentifier() const {
return File.path().c_str();
};
}
-MemoryBufferMMapFile::MemoryBufferMMapFile(const sys::Path &Filename) {
+bool MemoryBufferMMapFile::open(const sys::Path &Filename,
+ std::string *ErrStr) {
// FIXME: This does an extra stat syscall to figure out the size, but we
// already know the size!
- bool Failure = File.open(Filename);
- Failure = Failure; // Silence warning in no-asserts mode.
- assert(!Failure && "Can't open file??");
+ bool Failure = File.open(Filename, sys::MappedFile::READ_ACCESS, ErrStr);
+ if (Failure) return true;
- File.map();
+ if (!File.map(ErrStr))
+ return true;
size_t Size = File.size();
// No need to keep the file mapped any longer.
File.unmap();
}
+ return false;
}
MemoryBufferMMapFile::~MemoryBufferMMapFile() {
- File.unmap();
+ if (File.isMapped())
+ File.unmap();
}
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
MemoryBuffer *MemoryBuffer::getFile(const char *FilenameStart, unsigned FnSize,
- int64_t FileSize) {
- sys::PathWithStatus P(std::string(FilenameStart, FnSize));
+ std::string *ErrStr, int64_t FileSize){
+ // FIXME: it would be nice if PathWithStatus didn't copy the filename into a
+ // temporary string. :(
+ sys::PathWithStatus P(FilenameStart, FnSize);
#if 1
- return new MemoryBufferMMapFile(P);
+ MemoryBufferMMapFile *M = new MemoryBufferMMapFile();
+ if (!M->open(P, ErrStr))
+ return M;
+ delete M;
+ return 0;
#else
// FIXME: We need an efficient and portable method to open a file and then use
// 'read' to copy the bits out. The unix implementation is below. This is
}
// If the file is larger than some threshold, use mmap, otherwise use 'read'.
- if (FileSize >= 4096*4)
- return new MemoryBufferMMapFile(P);
+ if (FileSize >= 4096*4) {
+ MemoryBufferMMapFile *M = new MemoryBufferMMapFile();
+ if (!M->open(P, ErrStr))
+ return M;
+ delete M;
+ return 0;
+ }
MemoryBuffer *SB = getNewUninitMemBuffer(FileSize, FilenameStart);
char *BufPtr = const_cast<char*>(SB->getBufferStart());
std::vector<char> FileData;
// Read in all of the data from stdin, we cannot mmap stdin.
- while (size_t ReadBytes = fread(Buffer, 1, 4096*4, stdin))
+ sys::Program::ChangeStdinToBinary();
+ while (size_t ReadBytes = fread(Buffer, sizeof(char), 4096*4, stdin))
FileData.insert(FileData.end(), Buffer, Buffer+ReadBytes);
-
+
+ FileData.push_back(0); // &FileData[Size] is invalid. So is &*FileData.end().
size_t Size = FileData.size();
+ if (Size <= 1)
+ return 0;
MemoryBuffer *B = new STDINBufferFile();
- B->initCopyOf(&FileData[0], &FileData[Size]);
+ B->initCopyOf(&FileData[0], &FileData[Size-1]);
return B;
}