如何检测特定字符时关闭STDIN并获取llvm::MemoryBuffer内容?
Got it, let's tackle this problem. The issue here is that llvm::MemoryBuffer::getFileOrSTDIN("-") is designed to read all of stdin until it hits EOF (like when you press Ctrl+D on Unix or Ctrl+Z on Windows), but you want to stop reading as soon as a specific <END_CHAR> is encountered.
The fix is to handle the stdin case manually instead of relying on getFileOrSTDIN, since that function doesn't support custom termination characters. Here's how to do it properly within the LLVM ecosystem:
First, create a helper function that checks if we're reading from stdin, then reads characters until your end marker is found, and wraps the result in a MemoryBuffer:
#include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Error.h" llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>> getSourceBuffer(const std::string& File, char EndChar) { if (File == "-") { std::string inputContent; char currentChar; std::error_code readErr; // Read from stdin one character at a time until we hit EndChar or an error while ((readErr = llvm::sys::fs::readSTDIN(¤tChar, 1)) == 0 && currentChar != EndChar) { inputContent += currentChar; } // Handle any unexpected errors (ignore EOF if we didn't hit EndChar? Adjust as needed) if (readErr && readErr != llvm::errc::no_such_file_or_directory) { // EOF returns this code in LLVM's readSTDIN return llvm::make_error<llvm::StringError>(readErr.message(), readErr); } // Create a MemoryBuffer from our collected content; "<stdin>" is the buffer name for diagnostics return llvm::MemoryBuffer::getMemBufferCopy(inputContent, "<stdin>"); } else { // Use the original function for regular files return llvm::MemoryBuffer::getFileOrSTDIN(File); } }
Then replace your original getSource line with a call to this helper:
auto Source = getSourceBuffer(File, '<END_CHAR>'); // Replace '<END_CHAR>' with your actual termination character if (std::error_code err = Source.getError()) { llvm::errs() << err.message(); } else { someFunction(std::move(*Source), File, makeOutputWriter(Format, llvm::outs()), IdentifiersOnly, DumpAST); }
Why this works:
- We bypass
getFileOrSTDINfor stdin, since it's hardcoded to wait for EOF. - Using
llvm::sys::fs::readSTDINkeeps us within LLVM's I/O utilities (avoiding potential issues with C++ standard streams interacting with LLVM's own handling). - Once we hit your
<END_CHAR>, we stop reading immediately, package the collected content into aMemoryBuffer, and proceed tosomeFunctionwithout blocking.
You can adjust the error handling logic to match your needs—for example, if hitting EOF before <END_CHAR> should be considered an error, you can add a check for that and return an appropriate error message.
内容的提问来源于stack exchange,提问作者Mathieu Nls

