X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FSupport%2FMemoryBuffer.cpp;h=4d26d38731a8078b65a3e763207a1fb0389125e3;hb=e6be34a53ecbe8c2ff9f0793b13d847e94c0de91;hp=c590f02d74c117b2d8dde49058a6b429c57ea1d4;hpb=333ffd4abfcc3be32a945dc73c81adeafde1ba6b;p=oota-llvm.git diff --git a/lib/Support/MemoryBuffer.cpp b/lib/Support/MemoryBuffer.cpp index c590f02d74c..4d26d38731a 100644 --- a/lib/Support/MemoryBuffer.cpp +++ b/lib/Support/MemoryBuffer.cpp @@ -2,8 +2,8 @@ // // 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. // //===----------------------------------------------------------------------===// // @@ -14,6 +14,8 @@ #include "llvm/Support/MemoryBuffer.h" #include "llvm/System/MappedFile.h" #include "llvm/System/Process.h" +#include "llvm/System/Program.h" +#include #include #include #include @@ -37,7 +39,7 @@ void MemoryBuffer::initCopyOf(const char *BufStart, const char *BufEnd) { BufferEnd = BufferStart+Size; memcpy(const_cast(BufferStart), BufStart, Size); *const_cast(BufferEnd) = 0; // Null terminate buffer. - MustDeleteBuffer = false; + MustDeleteBuffer = true; } /// init - Initialize this MemoryBuffer as a reference to externally allocated @@ -57,9 +59,13 @@ namespace { 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 { @@ -76,6 +82,15 @@ MemoryBuffer *MemoryBuffer::getMemBuffer(const char *StartPtr, 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 @@ -102,6 +117,24 @@ MemoryBuffer *MemoryBuffer::getNewMemBuffer(unsigned Size, } +/// 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, ""); +} + //===----------------------------------------------------------------------===// // MemoryBufferMMapFile implementation. //===----------------------------------------------------------------------===// @@ -110,7 +143,9 @@ namespace { 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(); @@ -120,14 +155,15 @@ public: }; } -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(); @@ -146,10 +182,12 @@ MemoryBufferMMapFile::MemoryBufferMMapFile(const sys::Path &Filename) { // No need to keep the file mapped any longer. File.unmap(); } + return false; } MemoryBufferMMapFile::~MemoryBufferMMapFile() { - File.unmap(); + if (File.isMapped()) + File.unmap(); } //===----------------------------------------------------------------------===// @@ -157,10 +195,16 @@ MemoryBufferMMapFile::~MemoryBufferMMapFile() { //===----------------------------------------------------------------------===// 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 - 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 @@ -176,8 +220,13 @@ MemoryBuffer *MemoryBuffer::getFile(const char *FilenameStart, unsigned FnSize, } // 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(SB->getBufferStart()); @@ -229,11 +278,15 @@ MemoryBuffer *MemoryBuffer::getSTDIN() { std::vector 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; }