| //===- FileUpdate.cpp - Conditionally update a file -----------------------===// | 
 | // | 
 | //                     The LLVM Compiler Infrastructure | 
 | // | 
 | // This file is distributed under the University of Illinois Open Source | 
 | // License. See LICENSE.TXT for details. | 
 | // | 
 | //===----------------------------------------------------------------------===// | 
 | // | 
 | // FileUpdate is a utility for conditionally updating a file from its input | 
 | // based on whether the input differs from the output. It is used to avoid | 
 | // unnecessary modifications in a build system. | 
 | // | 
 | //===----------------------------------------------------------------------===// | 
 |  | 
 | #include "llvm/Support/CommandLine.h" | 
 | #include "llvm/Support/MemoryBuffer.h" | 
 | #include "llvm/ADT/OwningPtr.h" | 
 | #include "llvm/Support/PrettyStackTrace.h" | 
 | #include "llvm/Support/ToolOutputFile.h" | 
 | #include "llvm/Support/Signals.h" | 
 | #include "llvm/Support/system_error.h" | 
 | using namespace llvm; | 
 |  | 
 | static cl::opt<bool> | 
 | Quiet("quiet", cl::desc("Don't print unnecessary status information"), | 
 |       cl::init(false)); | 
 |  | 
 | static cl::opt<std::string> | 
 | InputFilename("input-file", cl::desc("Input file (defaults to stdin)"), | 
 |               cl::init("-"), cl::value_desc("filename")); | 
 |  | 
 | static cl::opt<std::string> | 
 | OutputFilename(cl::Positional, cl::desc("<output-file>"), cl::Required); | 
 |  | 
 | int main(int argc, char **argv) { | 
 |   sys::PrintStackTraceOnErrorSignal(); | 
 |   PrettyStackTraceProgram X(argc, argv); | 
 |   cl::ParseCommandLineOptions(argc, argv); | 
 |  | 
 |   if (OutputFilename == "-") { | 
 |     errs() << argv[0] << ": error: Can't update standard output\n"; | 
 |     return 1; | 
 |   } | 
 |  | 
 |   // Get the input data. | 
 |   OwningPtr<MemoryBuffer> In; | 
 |   if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFilename.c_str(), In)) { | 
 |     errs() << argv[0] << ": error: Unable to get input '" | 
 |            << InputFilename << "': " << ec.message() << '\n'; | 
 |     return 1; | 
 |   } | 
 |  | 
 |   // Get the output data. | 
 |   OwningPtr<MemoryBuffer> Out; | 
 |   MemoryBuffer::getFile(OutputFilename.c_str(), Out); | 
 |  | 
 |   // If the output exists and the contents match, we are done. | 
 |   if (Out && In->getBufferSize() == Out->getBufferSize() && | 
 |       memcmp(In->getBufferStart(), Out->getBufferStart(), | 
 |              Out->getBufferSize()) == 0) { | 
 |     if (!Quiet) | 
 |       errs() << argv[0] << ": Not updating '" << OutputFilename | 
 |              << "', contents match input.\n"; | 
 |     return 0; | 
 |   } | 
 |  | 
 |   // Otherwise, overwrite the output. | 
 |   if (!Quiet) | 
 |     errs() << argv[0] << ": Updating '" << OutputFilename | 
 |            << "', contents changed.\n"; | 
 |   std::string ErrorStr; | 
 |   tool_output_file OutStream(OutputFilename.c_str(), ErrorStr, | 
 |                              raw_fd_ostream::F_Binary); | 
 |   if (!ErrorStr.empty()) { | 
 |     errs() << argv[0] << ": Unable to write output '" | 
 |            << OutputFilename << "': " << ErrorStr << '\n'; | 
 |     return 1; | 
 |   } | 
 |  | 
 |   OutStream.os().write(In->getBufferStart(), In->getBufferSize()); | 
 |  | 
 |   // Declare success. | 
 |   OutStream.keep(); | 
 |  | 
 |   return 0; | 
 | } |