OSDN Git Service

Introduce a new tool_output_file class, which extends raw_ostream with
authorDan Gohman <gohman@apple.com>
Fri, 20 Aug 2010 00:48:10 +0000 (00:48 +0000)
committerDan Gohman <gohman@apple.com>
Fri, 20 Aug 2010 00:48:10 +0000 (00:48 +0000)
functionality that most command-line tools need: ensuring that the
output file gets deleted if the tool is interrupted or encounters an
error.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@111595 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Support/FormattedStream.h
include/llvm/Support/raw_ostream.h
lib/Support/FormattedStream.cpp
lib/Support/raw_ostream.cpp

index 58a1885..7bc6e47 100644 (file)
 
 namespace llvm 
 {
+  class formatted_tool_output_file;
+
   /// formatted_raw_ostream - Formatted raw_fd_ostream to handle
   /// asm-specific constructs.
   ///
   class formatted_raw_ostream : public raw_ostream {
+    friend class formatted_tool_output_file;
+
   public:
     /// DELETE_STREAM - Tell the destructor to delete the held stream.
     ///
@@ -136,6 +140,25 @@ namespace llvm
     }
   };
 
+  /// formatted_tool_output_file - This is a subclass of formatted_raw_ostream
+  /// for use when the underlying stream is a tool_output_file. It exposes
+  /// the keep() member function.
+  class formatted_tool_output_file : public formatted_raw_ostream {
+  public:
+    formatted_tool_output_file(tool_output_file &Stream, bool Delete = false) 
+      : formatted_raw_ostream(Stream, Delete) {}
+
+    formatted_tool_output_file() {}
+
+    ~formatted_tool_output_file();
+
+    void setStream(tool_output_file &Stream, bool Delete = false) {
+      return formatted_raw_ostream::setStream(Stream, Delete);
+    }
+
+    void keep() { return static_cast<tool_output_file *>(TheStream)->keep(); }
+  };
+
 /// fouts() - This returns a reference to a formatted_raw_ostream for
 /// standard output.  Use it like: fouts() << "foo" << "bar";
 formatted_raw_ostream &fouts();
index b7eae0f..5c16fcd 100644 (file)
@@ -370,10 +370,11 @@ public:
   ~raw_fd_ostream();
 
   /// close - Manually flush the stream and close the file.
+  /// Note that this does not call fsync.
   void close();
 
   /// seek - Flushes the stream and repositions the underlying file descriptor
-  ///  positition to the offset specified from the beginning of the file.
+  /// positition to the offset specified from the beginning of the file.
   uint64_t seek(uint64_t off);
 
   virtual raw_ostream &changeColor(enum Colors colors, bool bold=false,
@@ -484,6 +485,25 @@ public:
   ~raw_null_ostream();
 };
 
+/// tool_output_file - This class behaves like a raw_fd_ostream but adds a
+/// few extra features commonly needed for compiler-like tool output files:
+///   - The file is automatically deleted if the process is killed.
+///   - The file is automatically deleted when the tool_output_file
+///     object is destroyed unless the client calls keep().
+class tool_output_file : public raw_fd_ostream {
+  std::string Filename;
+  bool Keep;
+public:
+  tool_output_file(const char *filename, std::string &ErrorInfo,
+                   unsigned Flags = 0);
+
+  ~tool_output_file();
+
+  /// keep - Indicate that the tool's job wrt this output file has been
+  /// successful and the file should not be deleted.
+  void keep() { Keep = true; }
+};
+
 } // end llvm namespace
 
 #endif
index c72b5a1..77bdfab 100644 (file)
@@ -98,3 +98,6 @@ formatted_raw_ostream &llvm::fdbgs() {
   static formatted_raw_ostream S(dbgs());
   return S;
 }
+
+/// ~formatted_tool_output_file - Out-of-line destructor.
+formatted_tool_output_file::~formatted_tool_output_file() {}
index 71a2ac5..81ffe4a 100644 (file)
@@ -19,6 +19,7 @@
 #include "llvm/Config/config.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/ErrorHandling.h"
+#include "llvm/System/Signals.h"
 #include "llvm/ADT/STLExtras.h"
 #include <cctype>
 #include <cerrno>
@@ -669,3 +670,30 @@ void raw_null_ostream::write_impl(const char *Ptr, size_t Size) {
 uint64_t raw_null_ostream::current_pos() const {
   return 0;
 }
+
+//===----------------------------------------------------------------------===//
+//  tool_output_file
+//===----------------------------------------------------------------------===//
+
+/// SetupRemoveOnSignal - This is a helper for tool_output_file's constructor
+/// to allow the signal handlers to be installed before constructing the
+/// base class raw_fd_ostream.
+static const char *SetupRemoveOnSignal(const char *Filename) {
+  // Arrange for the file to be deleted if the process is killed.
+  if (strcmp(Filename, "-") != 0)
+    sys::RemoveFileOnSignal(sys::Path(Filename));
+  return Filename;
+}
+
+tool_output_file::tool_output_file(const char *filename, std::string &ErrorInfo, 
+                                   unsigned Flags)
+  : raw_fd_ostream(SetupRemoveOnSignal(filename), ErrorInfo, Flags),
+    Filename(filename),
+    Keep(!ErrorInfo.empty() /* If open fails, no cleanup is needed. */) {
+}
+
+tool_output_file::~tool_output_file() {
+  // Delete the file if the client hasn't told us not to.
+  if (!Keep && Filename != "-")
+    sys::Path(Filename).eraseFromDisk();
+}