In Thumb2, direct branches can be encoded as either a "short" conditional branch...
[oota-llvm.git] / utils / FileUpdate / FileUpdate.cpp
1 //===- FileUpdate.cpp - Conditionally update a file -----------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // FileUpdate is a utility for conditionally updating a file from its input
11 // based on whether the input differs from the output. It is used to avoid
12 // unnecessary modifications in a build system.
13 //
14 //===----------------------------------------------------------------------===//
15
16 #include "llvm/Support/CommandLine.h"
17 #include "llvm/Support/MemoryBuffer.h"
18 #include "llvm/Support/PrettyStackTrace.h"
19 #include "llvm/Support/ToolOutputFile.h"
20 #include "llvm/Support/Signals.h"
21 #include "llvm/Support/system_error.h"
22 using namespace llvm;
23
24 static cl::opt<bool>
25 Quiet("quiet", cl::desc("Don't print unnecessary status information"),
26       cl::init(false));
27
28 static cl::opt<std::string>
29 InputFilename("input-file", cl::desc("Input file (defaults to stdin)"),
30               cl::init("-"), cl::value_desc("filename"));
31
32 static cl::opt<std::string>
33 OutputFilename(cl::Positional, cl::desc("<output-file>"), cl::Required);
34
35 int main(int argc, char **argv) {
36   sys::PrintStackTraceOnErrorSignal();
37   PrettyStackTraceProgram X(argc, argv);
38   cl::ParseCommandLineOptions(argc, argv);
39
40   if (OutputFilename == "-") {
41     errs() << argv[0] << ": error: Can't update standard output\n";
42     return 1;
43   }
44
45   // Get the input data.
46   error_code ec;
47   MemoryBuffer *In =
48     MemoryBuffer::getFileOrSTDIN(InputFilename.c_str(), ec);
49   if (In == 0) {
50     errs() << argv[0] << ": error: Unable to get input '"
51            << InputFilename << "': " << ec.message() << '\n';
52     return 1;
53   }
54
55   // Get the output data.
56   MemoryBuffer *Out = MemoryBuffer::getFile(OutputFilename.c_str(), ec);
57
58   // If the output exists and the contents match, we are done.
59   if (Out && In->getBufferSize() == Out->getBufferSize() &&
60       memcmp(In->getBufferStart(), Out->getBufferStart(),
61              Out->getBufferSize()) == 0) {
62     if (!Quiet)
63       errs() << argv[0] << ": Not updating '" << OutputFilename
64              << "', contents match input.\n";
65     return 0;
66   }
67
68   delete Out;
69
70   // Otherwise, overwrite the output.
71   if (!Quiet)
72     errs() << argv[0] << ": Updating '" << OutputFilename
73            << "', contents changed.\n";
74   std::string ErrorStr;
75   tool_output_file OutStream(OutputFilename.c_str(), ErrorStr,
76                              raw_fd_ostream::F_Binary);
77   if (!ErrorStr.empty()) {
78     errs() << argv[0] << ": Unable to write output '"
79            << OutputFilename << "': " << ErrorStr << '\n';
80     return 1;
81   }
82
83   OutStream.os().write(In->getBufferStart(), In->getBufferSize());
84
85   // Declare success.
86   OutStream.keep();
87
88   return 0;
89 }