//
// The LLVM Compiler Infrastructure
//
-// This file was developed by Chris Lattner and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
#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
}
+/// getFileOrSTDIN - Open the specified file as a MemoryBuffer, or open stdin
+/// if the Filename is "-". If an error occurs, this returns null and fills
+/// in *ErrStr with a reason. If stdin is empty, this API (unlike getSTDIN)
+/// returns an empty buffer.
+MemoryBuffer *MemoryBuffer::getFileOrSTDIN(const char *FilenameStart,
+ unsigned FnSize,
+ std::string *ErrStr,
+ int64_t FileSize) {
+ if (FnSize != 1 || FilenameStart[0] != '-')
+ return getFile(FilenameStart, FnSize, ErrStr, FileSize);
+ MemoryBuffer *M = getSTDIN();
+ if (M) return M;
+
+ // If stdin was empty, M is null. Cons up an empty memory buffer now.
+ const char *EmptyStr = "";
+ return MemoryBuffer::getMemBuffer(EmptyStr, EmptyStr, "<stdin>");
+}
+
//===----------------------------------------------------------------------===//
// MemoryBufferMMapFile implementation.
//===----------------------------------------------------------------------===//
public:
MemoryBufferMMapFile() {}
- bool open(const sys::Path &Filename);
+ bool open(const sys::Path &Filename, std::string *ErrStr);
virtual const char *getBufferIdentifier() const {
return File.path().c_str();
};
}
-bool MemoryBufferMMapFile::open(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);
+ 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();
//===----------------------------------------------------------------------===//
MemoryBuffer *MemoryBuffer::getFile(const char *FilenameStart, unsigned FnSize,
- int64_t FileSize) {
+ 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
MemoryBufferMMapFile *M = new MemoryBufferMMapFile();
- if (!M->open(P))
+ if (!M->open(P, ErrStr))
return M;
delete M;
return 0;
// If the file is larger than some threshold, use mmap, otherwise use 'read'.
if (FileSize >= 4096*4) {
MemoryBufferMMapFile *M = new MemoryBufferMMapFile();
- if (!M->open(P))
+ if (!M->open(P, ErrStr))
return M;
delete M;
return 0;
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;
}