Add most of base/ build/ buildtools/ testing/ third_party/googletest/

Enough to make ./tools/gn/bootstrap/bootstrap.py work on Linux.

Change-Id: I94de95f1ce87dd3672d1a99c62254edee8be45bd
Reviewed-on: https://gn-review.googlesource.com/1100
Reviewed-by: Petr Hosek <phosek@google.com>
Commit-Queue: Scott Graham <scottmg@chromium.org>
diff --git a/buildtools/clang_format/OWNERS b/buildtools/clang_format/OWNERS
new file mode 100644
index 0000000..a14b04c
--- /dev/null
+++ b/buildtools/clang_format/OWNERS
@@ -0,0 +1,2 @@
+nick@chromium.org

+thakis@chromium.org

diff --git a/buildtools/clang_format/README.chromium b/buildtools/clang_format/README.chromium
new file mode 100644
index 0000000..514b77c
--- /dev/null
+++ b/buildtools/clang_format/README.chromium
@@ -0,0 +1,15 @@
+Name: clang-format
+Short Name: clang-format
+URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/clang-format/
+Version: 5.0.0
+Date: 14 Jun 2017
+Revision: See DEPS
+License: University of Illinois/NCSA Open Source License
+License File: NOT_SHIPPED
+Security Critical: No
+
+Description:
+A tool for formatting C++ code to style.
+
+Local Modifications:
+None
diff --git a/buildtools/clang_format/README.txt b/buildtools/clang_format/README.txt
new file mode 100644
index 0000000..29b446c
--- /dev/null
+++ b/buildtools/clang_format/README.txt
@@ -0,0 +1,33 @@
+This folder contains clang-format scripts. The binaries will be automatically
+downloaded from Google Storage by gclient runhooks for the current platform.
+
+For a walkthrough on how to maintain these binaries:
+  https://chromium.googlesource.com/chromium/src/+/master/docs/updating_clang_format_binaries.md
+
+To upload a file:
+  python ~/depot_tools/upload_to_google_storage.py -b chromium-clang-format <FILENAME>
+
+On Linux and Mac, check that clang-format has its +x bit set before you run this
+upload command. Don't upload Linux and Mac binaries from Windows, since
+upload_to_google_storage.py will not set the +x bit on google storage when it's
+run from Windows.
+
+To download a file given a .sha1 file:
+  python ~/depot_tools/download_from_google_storage.py -b chromium-clang-format -s <FILENAME>.sha1
+
+List the contents of GN's Google Storage bucket:
+  python ~/depot_tools/third_party/gsutil/gsutil ls gs://chromium-clang-format/
+
+To initialize gsutil's credentials:
+  python ~/depot_tools/third_party/gsutil/gsutil config
+
+  That will give a URL which you should log into with your web browser. The
+  username should be the one that is on the ACL for the "chromium-clang-format"
+  bucket (probably your @google.com address). Contact the build team for help
+  getting access if necessary.
+
+  Copy the code back to the command line util. Ignore the project ID (it's OK
+  to just leave blank when prompted).
+
+gsutil documentation:
+  https://developers.google.com/storage/docs/gsutil
diff --git a/buildtools/clang_format/script/CMakeLists.txt b/buildtools/clang_format/script/CMakeLists.txt
new file mode 100644
index 0000000..a13633e
--- /dev/null
+++ b/buildtools/clang_format/script/CMakeLists.txt
@@ -0,0 +1,39 @@
+set(LLVM_LINK_COMPONENTS support)
+
+add_clang_tool(clang-format
+  ClangFormat.cpp
+  )
+
+set(CLANG_FORMAT_LIB_DEPS
+  clangBasic
+  clangFormat
+  clangRewrite
+  clangToolingCore
+  )
+
+target_link_libraries(clang-format
+  ${CLANG_FORMAT_LIB_DEPS}
+  )
+
+if( LLVM_USE_SANITIZE_COVERAGE )
+  add_subdirectory(fuzzer)
+endif()
+
+install(PROGRAMS clang-format-bbedit.applescript
+  DESTINATION share/clang
+  COMPONENT clang-format)
+install(PROGRAMS clang-format-diff.py
+  DESTINATION share/clang
+  COMPONENT clang-format)
+install(PROGRAMS clang-format-sublime.py
+  DESTINATION share/clang
+  COMPONENT clang-format)
+install(PROGRAMS clang-format.el
+  DESTINATION share/clang
+  COMPONENT clang-format)
+install(PROGRAMS clang-format.py
+  DESTINATION share/clang
+  COMPONENT clang-format)
+install(PROGRAMS git-clang-format
+  DESTINATION bin
+  COMPONENT clang-format)
diff --git a/buildtools/clang_format/script/ClangFormat.cpp b/buildtools/clang_format/script/ClangFormat.cpp
new file mode 100644
index 0000000..14bff19
--- /dev/null
+++ b/buildtools/clang_format/script/ClangFormat.cpp
@@ -0,0 +1,388 @@
+//===-- clang-format/ClangFormat.cpp - Clang format tool ------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief This file implements a clang-format tool that automatically formats
+/// (fragments of) C++ code.
+///
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/DiagnosticOptions.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/Version.h"
+#include "clang/Format/Format.h"
+#include "clang/Rewrite/Core/Rewriter.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Signals.h"
+
+using namespace llvm;
+using clang::tooling::Replacements;
+
+static cl::opt<bool> Help("h", cl::desc("Alias for -help"), cl::Hidden);
+
+// Mark all our options with this category, everything else (except for -version
+// and -help) will be hidden.
+static cl::OptionCategory ClangFormatCategory("Clang-format options");
+
+static cl::list<unsigned>
+    Offsets("offset",
+            cl::desc("Format a range starting at this byte offset.\n"
+                     "Multiple ranges can be formatted by specifying\n"
+                     "several -offset and -length pairs.\n"
+                     "Can only be used with one input file."),
+            cl::cat(ClangFormatCategory));
+static cl::list<unsigned>
+    Lengths("length",
+            cl::desc("Format a range of this length (in bytes).\n"
+                     "Multiple ranges can be formatted by specifying\n"
+                     "several -offset and -length pairs.\n"
+                     "When only a single -offset is specified without\n"
+                     "-length, clang-format will format up to the end\n"
+                     "of the file.\n"
+                     "Can only be used with one input file."),
+            cl::cat(ClangFormatCategory));
+static cl::list<std::string>
+LineRanges("lines", cl::desc("<start line>:<end line> - format a range of\n"
+                             "lines (both 1-based).\n"
+                             "Multiple ranges can be formatted by specifying\n"
+                             "several -lines arguments.\n"
+                             "Can't be used with -offset and -length.\n"
+                             "Can only be used with one input file."),
+           cl::cat(ClangFormatCategory));
+static cl::opt<std::string>
+    Style("style",
+          cl::desc(clang::format::StyleOptionHelpDescription),
+          cl::init("file"), cl::cat(ClangFormatCategory));
+static cl::opt<std::string>
+FallbackStyle("fallback-style",
+              cl::desc("The name of the predefined style used as a\n"
+                       "fallback in case clang-format is invoked with\n"
+                       "-style=file, but can not find the .clang-format\n"
+                       "file to use.\n"
+                       "Use -fallback-style=none to skip formatting."),
+              cl::init("LLVM"), cl::cat(ClangFormatCategory));
+
+static cl::opt<std::string>
+AssumeFileName("assume-filename",
+               cl::desc("When reading from stdin, clang-format assumes this\n"
+                        "filename to look for a style config file (with\n"
+                        "-style=file) and to determine the language."),
+               cl::init("<stdin>"), cl::cat(ClangFormatCategory));
+
+static cl::opt<bool> Inplace("i",
+                             cl::desc("Inplace edit <file>s, if specified."),
+                             cl::cat(ClangFormatCategory));
+
+static cl::opt<bool> OutputXML("output-replacements-xml",
+                               cl::desc("Output replacements as XML."),
+                               cl::cat(ClangFormatCategory));
+static cl::opt<bool>
+    DumpConfig("dump-config",
+               cl::desc("Dump configuration options to stdout and exit.\n"
+                        "Can be used with -style option."),
+               cl::cat(ClangFormatCategory));
+static cl::opt<unsigned>
+    Cursor("cursor",
+           cl::desc("The position of the cursor when invoking\n"
+                    "clang-format from an editor integration"),
+           cl::init(0), cl::cat(ClangFormatCategory));
+
+static cl::opt<bool> SortIncludes(
+    "sort-includes",
+    cl::desc("If set, overrides the include sorting behavior determined by the "
+             "SortIncludes style flag"),
+    cl::cat(ClangFormatCategory));
+
+static cl::list<std::string> FileNames(cl::Positional, cl::desc("[<file> ...]"),
+                                       cl::cat(ClangFormatCategory));
+
+namespace clang {
+namespace format {
+
+static FileID createInMemoryFile(StringRef FileName, MemoryBuffer *Source,
+                                 SourceManager &Sources, FileManager &Files,
+                                 vfs::InMemoryFileSystem *MemFS) {
+  MemFS->addFileNoOwn(FileName, 0, Source);
+  return Sources.createFileID(Files.getFile(FileName), SourceLocation(),
+                              SrcMgr::C_User);
+}
+
+// Parses <start line>:<end line> input to a pair of line numbers.
+// Returns true on error.
+static bool parseLineRange(StringRef Input, unsigned &FromLine,
+                           unsigned &ToLine) {
+  std::pair<StringRef, StringRef> LineRange = Input.split(':');
+  return LineRange.first.getAsInteger(0, FromLine) ||
+         LineRange.second.getAsInteger(0, ToLine);
+}
+
+static bool fillRanges(MemoryBuffer *Code,
+                       std::vector<tooling::Range> &Ranges) {
+  IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem(
+      new vfs::InMemoryFileSystem);
+  FileManager Files(FileSystemOptions(), InMemoryFileSystem);
+  DiagnosticsEngine Diagnostics(
+      IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs),
+      new DiagnosticOptions);
+  SourceManager Sources(Diagnostics, Files);
+  FileID ID = createInMemoryFile("<irrelevant>", Code, Sources, Files,
+                                 InMemoryFileSystem.get());
+  if (!LineRanges.empty()) {
+    if (!Offsets.empty() || !Lengths.empty()) {
+      errs() << "error: cannot use -lines with -offset/-length\n";
+      return true;
+    }
+
+    for (unsigned i = 0, e = LineRanges.size(); i < e; ++i) {
+      unsigned FromLine, ToLine;
+      if (parseLineRange(LineRanges[i], FromLine, ToLine)) {
+        errs() << "error: invalid <start line>:<end line> pair\n";
+        return true;
+      }
+      if (FromLine > ToLine) {
+        errs() << "error: start line should be less than end line\n";
+        return true;
+      }
+      SourceLocation Start = Sources.translateLineCol(ID, FromLine, 1);
+      SourceLocation End = Sources.translateLineCol(ID, ToLine, UINT_MAX);
+      if (Start.isInvalid() || End.isInvalid())
+        return true;
+      unsigned Offset = Sources.getFileOffset(Start);
+      unsigned Length = Sources.getFileOffset(End) - Offset;
+      Ranges.push_back(tooling::Range(Offset, Length));
+    }
+    return false;
+  }
+
+  if (Offsets.empty())
+    Offsets.push_back(0);
+  if (Offsets.size() != Lengths.size() &&
+      !(Offsets.size() == 1 && Lengths.empty())) {
+    errs() << "error: number of -offset and -length arguments must match.\n";
+    return true;
+  }
+  for (unsigned i = 0, e = Offsets.size(); i != e; ++i) {
+    if (Offsets[i] >= Code->getBufferSize()) {
+      errs() << "error: offset " << Offsets[i] << " is outside the file\n";
+      return true;
+    }
+    SourceLocation Start =
+        Sources.getLocForStartOfFile(ID).getLocWithOffset(Offsets[i]);
+    SourceLocation End;
+    if (i < Lengths.size()) {
+      if (Offsets[i] + Lengths[i] > Code->getBufferSize()) {
+        errs() << "error: invalid length " << Lengths[i]
+               << ", offset + length (" << Offsets[i] + Lengths[i]
+               << ") is outside the file.\n";
+        return true;
+      }
+      End = Start.getLocWithOffset(Lengths[i]);
+    } else {
+      End = Sources.getLocForEndOfFile(ID);
+    }
+    unsigned Offset = Sources.getFileOffset(Start);
+    unsigned Length = Sources.getFileOffset(End) - Offset;
+    Ranges.push_back(tooling::Range(Offset, Length));
+  }
+  return false;
+}
+
+static void outputReplacementXML(StringRef Text) {
+  // FIXME: When we sort includes, we need to make sure the stream is correct
+  // utf-8.
+  size_t From = 0;
+  size_t Index;
+  while ((Index = Text.find_first_of("\n\r<&", From)) != StringRef::npos) {
+    outs() << Text.substr(From, Index - From);
+    switch (Text[Index]) {
+    case '\n':
+      outs() << "&#10;";
+      break;
+    case '\r':
+      outs() << "&#13;";
+      break;
+    case '<':
+      outs() << "&lt;";
+      break;
+    case '&':
+      outs() << "&amp;";
+      break;
+    default:
+      llvm_unreachable("Unexpected character encountered!");
+    }
+    From = Index + 1;
+  }
+  outs() << Text.substr(From);
+}
+
+static void outputReplacementsXML(const Replacements &Replaces) {
+  for (const auto &R : Replaces) {
+    outs() << "<replacement "
+           << "offset='" << R.getOffset() << "' "
+           << "length='" << R.getLength() << "'>";
+    outputReplacementXML(R.getReplacementText());
+    outs() << "</replacement>\n";
+  }
+}
+
+// Returns true on error.
+static bool format(StringRef FileName) {
+  if (!OutputXML && Inplace && FileName == "-") {
+    errs() << "error: cannot use -i when reading from stdin.\n";
+    return false;
+  }
+  // On Windows, overwriting a file with an open file mapping doesn't work,
+  // so read the whole file into memory when formatting in-place.
+  ErrorOr<std::unique_ptr<MemoryBuffer>> CodeOrErr =
+      !OutputXML && Inplace ? MemoryBuffer::getFileAsStream(FileName) :
+                              MemoryBuffer::getFileOrSTDIN(FileName);
+  if (std::error_code EC = CodeOrErr.getError()) {
+    errs() << EC.message() << "\n";
+    return true;
+  }
+  std::unique_ptr<llvm::MemoryBuffer> Code = std::move(CodeOrErr.get());
+  if (Code->getBufferSize() == 0)
+    return false; // Empty files are formatted correctly.
+  std::vector<tooling::Range> Ranges;
+  if (fillRanges(Code.get(), Ranges))
+    return true;
+  StringRef AssumedFileName = (FileName == "-") ? AssumeFileName : FileName;
+
+  llvm::Expected<FormatStyle> FormatStyle =
+      getStyle(Style, AssumedFileName, FallbackStyle, Code->getBuffer());
+  if (!FormatStyle) {
+    llvm::errs() << llvm::toString(FormatStyle.takeError()) << "\n";
+    return true;
+  }
+
+  if (SortIncludes.getNumOccurrences() != 0)
+    FormatStyle->SortIncludes = SortIncludes;
+  unsigned CursorPosition = Cursor;
+  Replacements Replaces = sortIncludes(*FormatStyle, Code->getBuffer(), Ranges,
+                                       AssumedFileName, &CursorPosition);
+  auto ChangedCode = tooling::applyAllReplacements(Code->getBuffer(), Replaces);
+  if (!ChangedCode) {
+    llvm::errs() << llvm::toString(ChangedCode.takeError()) << "\n";
+    return true;
+  }
+  // Get new affected ranges after sorting `#includes`.
+  Ranges = tooling::calculateRangesAfterReplacements(Replaces, Ranges);
+  FormattingAttemptStatus Status;
+  Replacements FormatChanges = reformat(*FormatStyle, *ChangedCode, Ranges,
+                                        AssumedFileName, &Status);
+  Replaces = Replaces.merge(FormatChanges);
+  if (OutputXML) {
+    outs() << "<?xml version='1.0'?>\n<replacements "
+              "xml:space='preserve' incomplete_format='"
+           << (Status.FormatComplete ? "false" : "true") << "'";
+    if (!Status.FormatComplete)
+      outs() << " line=" << Status.Line;
+    outs() << ">\n";
+    if (Cursor.getNumOccurrences() != 0)
+      outs() << "<cursor>"
+             << FormatChanges.getShiftedCodePosition(CursorPosition)
+             << "</cursor>\n";
+
+    outputReplacementsXML(Replaces);
+    outs() << "</replacements>\n";
+  } else {
+    IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem(
+        new vfs::InMemoryFileSystem);
+    FileManager Files(FileSystemOptions(), InMemoryFileSystem);
+    DiagnosticsEngine Diagnostics(
+        IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs),
+        new DiagnosticOptions);
+    SourceManager Sources(Diagnostics, Files);
+    FileID ID = createInMemoryFile(AssumedFileName, Code.get(), Sources, Files,
+                                   InMemoryFileSystem.get());
+    Rewriter Rewrite(Sources, LangOptions());
+    tooling::applyAllReplacements(Replaces, Rewrite);
+    if (Inplace) {
+      if (Rewrite.overwriteChangedFiles())
+        return true;
+    } else {
+      if (Cursor.getNumOccurrences() != 0) {
+        outs() << "{ \"Cursor\": "
+               << FormatChanges.getShiftedCodePosition(CursorPosition)
+               << ", \"IncompleteFormat\": "
+               << (Status.FormatComplete ? "false" : "true");
+        if (!Status.FormatComplete)
+          outs() << ", \"Line\": " << Status.Line;
+        outs() << " }\n";
+      }
+      Rewrite.getEditBuffer(ID).write(outs());
+    }
+  }
+  return false;
+}
+
+}  // namespace format
+}  // namespace clang
+
+static void PrintVersion() {
+  raw_ostream &OS = outs();
+  OS << clang::getClangToolFullVersion("clang-format") << '\n';
+}
+
+int main(int argc, const char **argv) {
+  llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
+
+  cl::HideUnrelatedOptions(ClangFormatCategory);
+
+  cl::SetVersionPrinter(PrintVersion);
+  cl::ParseCommandLineOptions(
+      argc, argv,
+      "A tool to format C/C++/Java/JavaScript/Objective-C/Protobuf code.\n\n"
+      "If no arguments are specified, it formats the code from standard input\n"
+      "and writes the result to the standard output.\n"
+      "If <file>s are given, it reformats the files. If -i is specified\n"
+      "together with <file>s, the files are edited in-place. Otherwise, the\n"
+      "result is written to the standard output.\n");
+
+  if (Help)
+    cl::PrintHelpMessage();
+
+  if (DumpConfig) {
+    llvm::Expected<clang::format::FormatStyle> FormatStyle =
+        clang::format::getStyle(
+            Style, FileNames.empty() ? AssumeFileName : FileNames[0],
+            FallbackStyle);
+    if (!FormatStyle) {
+      llvm::errs() << llvm::toString(FormatStyle.takeError()) << "\n";
+      return 1;
+    }
+    std::string Config = clang::format::configurationAsText(*FormatStyle);
+    outs() << Config << "\n";
+    return 0;
+  }
+
+  bool Error = false;
+  switch (FileNames.size()) {
+  case 0:
+    Error = clang::format::format("-");
+    break;
+  case 1:
+    Error = clang::format::format(FileNames[0]);
+    break;
+  default:
+    if (!Offsets.empty() || !Lengths.empty() || !LineRanges.empty()) {
+      errs() << "error: -offset, -length and -lines can only be used for "
+                "single file.\n";
+      return 1;
+    }
+    for (unsigned i = 0; i < FileNames.size(); ++i)
+      Error |= clang::format::format(FileNames[i]);
+    break;
+  }
+  return Error ? 1 : 0;
+}
+
diff --git a/buildtools/clang_format/script/clang-format-bbedit.applescript b/buildtools/clang_format/script/clang-format-bbedit.applescript
new file mode 100644
index 0000000..fa88fe9
--- /dev/null
+++ b/buildtools/clang_format/script/clang-format-bbedit.applescript
@@ -0,0 +1,27 @@
+-- In this file, change "/path/to/" to the path where you installed clang-format
+-- and save it to ~/Library/Application Support/BBEdit/Scripts. You can then
+-- select the script from the Script menu and clang-format will format the
+-- selection. Note that you can rename the menu item by renaming the script, and
+-- can assign the menu item a keyboard shortcut in the BBEdit preferences, under
+-- Menus & Shortcuts.
+on urlToPOSIXPath(theURL)
+	return do shell script "python -c \"import urllib, urlparse, sys; print urllib.unquote(urlparse.urlparse(sys.argv[1])[2])\" " & quoted form of theURL
+end urlToPOSIXPath
+
+tell application "BBEdit"
+	set selectionOffset to characterOffset of selection
+	set selectionLength to length of selection
+	set fileURL to URL of text document 1
+end tell
+
+set filePath to urlToPOSIXPath(fileURL)
+set newContents to do shell script "/path/to/clang-format -offset=" & selectionOffset & " -length=" & selectionLength & " " & quoted form of filePath
+
+tell application "BBEdit"
+	-- "set contents of text document 1 to newContents" scrolls to the bottom while
+	-- replacing a selection flashes a bit but doesn't affect the scroll position.
+	set currentLength to length of contents of text document 1
+	select characters 1 thru currentLength of text document 1
+	set text of selection to newContents
+	select characters selectionOffset thru (selectionOffset + selectionLength - 1) of text document 1
+end tell
diff --git a/buildtools/clang_format/script/clang-format-diff.py b/buildtools/clang_format/script/clang-format-diff.py
new file mode 100755
index 0000000..ffa30e7
--- /dev/null
+++ b/buildtools/clang_format/script/clang-format-diff.py
@@ -0,0 +1,121 @@
+#!/usr/bin/env python
+#
+#===- clang-format-diff.py - ClangFormat Diff Reformatter ----*- python -*--===#
+#
+#                     The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+#===------------------------------------------------------------------------===#
+
+r"""
+ClangFormat Diff Reformatter
+============================
+
+This script reads input from a unified diff and reformats all the changed
+lines. This is useful to reformat all the lines touched by a specific patch.
+Example usage for git/svn users:
+
+  git diff -U0 --no-color HEAD^ | clang-format-diff.py -p1 -i
+  svn diff --diff-cmd=diff -x-U0 | clang-format-diff.py -i
+
+"""
+
+import argparse
+import difflib
+import re
+import string
+import subprocess
+import StringIO
+import sys
+
+
+def main():
+  parser = argparse.ArgumentParser(description=
+                                   'Reformat changed lines in diff. Without -i '
+                                   'option just output the diff that would be '
+                                   'introduced.')
+  parser.add_argument('-i', action='store_true', default=False,
+                      help='apply edits to files instead of displaying a diff')
+  parser.add_argument('-p', metavar='NUM', default=0,
+                      help='strip the smallest prefix containing P slashes')
+  parser.add_argument('-regex', metavar='PATTERN', default=None,
+                      help='custom pattern selecting file paths to reformat '
+                      '(case sensitive, overrides -iregex)')
+  parser.add_argument('-iregex', metavar='PATTERN', default=
+                      r'.*\.(cpp|cc|c\+\+|cxx|c|cl|h|hpp|m|mm|inc|js|ts|proto'
+                      r'|protodevel|java)',
+                      help='custom pattern selecting file paths to reformat '
+                      '(case insensitive, overridden by -regex)')
+  parser.add_argument('-sort-includes', action='store_true', default=False,
+                      help='let clang-format sort include blocks')
+  parser.add_argument('-v', '--verbose', action='store_true',
+                      help='be more verbose, ineffective without -i')
+  parser.add_argument('-style',
+                      help='formatting style to apply (LLVM, Google, Chromium, '
+                      'Mozilla, WebKit)')
+  parser.add_argument('-binary', default='clang-format',
+                      help='location of binary to use for clang-format')
+  args = parser.parse_args()
+
+  # Extract changed lines for each file.
+  filename = None
+  lines_by_file = {}
+  for line in sys.stdin:
+    match = re.search('^\+\+\+\ (.*?/){%s}(\S*)' % args.p, line)
+    if match:
+      filename = match.group(2)
+    if filename == None:
+      continue
+
+    if args.regex is not None:
+      if not re.match('^%s$' % args.regex, filename):
+        continue
+    else:
+      if not re.match('^%s$' % args.iregex, filename, re.IGNORECASE):
+        continue
+
+    match = re.search('^@@.*\+(\d+)(,(\d+))?', line)
+    if match:
+      start_line = int(match.group(1))
+      line_count = 1
+      if match.group(3):
+        line_count = int(match.group(3))
+      if line_count == 0:
+        continue
+      end_line = start_line + line_count - 1;
+      lines_by_file.setdefault(filename, []).extend(
+          ['-lines', str(start_line) + ':' + str(end_line)])
+
+  # Reformat files containing changes in place.
+  for filename, lines in lines_by_file.iteritems():
+    if args.i and args.verbose:
+      print 'Formatting', filename
+    command = [args.binary, filename]
+    if args.i:
+      command.append('-i')
+    if args.sort_includes:
+      command.append('-sort-includes')
+    command.extend(lines)
+    if args.style:
+      command.extend(['-style', args.style])
+    p = subprocess.Popen(command, stdout=subprocess.PIPE,
+                         stderr=None, stdin=subprocess.PIPE)
+    stdout, stderr = p.communicate()
+    if p.returncode != 0:
+      sys.exit(p.returncode);
+
+    if not args.i:
+      with open(filename) as f:
+        code = f.readlines()
+      formatted_code = StringIO.StringIO(stdout).readlines()
+      diff = difflib.unified_diff(code, formatted_code,
+                                  filename, filename,
+                                  '(before formatting)', '(after formatting)')
+      diff_string = string.join(diff, '')
+      if len(diff_string) > 0:
+        sys.stdout.write(diff_string)
+
+if __name__ == '__main__':
+  main()
diff --git a/buildtools/clang_format/script/clang-format-sublime.py b/buildtools/clang_format/script/clang-format-sublime.py
new file mode 100644
index 0000000..16ff56e
--- /dev/null
+++ b/buildtools/clang_format/script/clang-format-sublime.py
@@ -0,0 +1,58 @@
+# This file is a minimal clang-format sublime-integration. To install:
+# - Change 'binary' if clang-format is not on the path (see below).
+# - Put this file into your sublime Packages directory, e.g. on Linux:
+#     ~/.config/sublime-text-2/Packages/User/clang-format-sublime.py
+# - Add a key binding:
+#     { "keys": ["ctrl+shift+c"], "command": "clang_format" },
+#
+# With this integration you can press the bound key and clang-format will
+# format the current lines and selections for all cursor positions. The lines
+# or regions are extended to the next bigger syntactic entities.
+#
+# It operates on the current, potentially unsaved buffer and does not create
+# or save any files. To revert a formatting, just undo.
+
+from __future__ import print_function
+import sublime
+import sublime_plugin
+import subprocess
+
+# Change this to the full path if clang-format is not on the path.
+binary = 'clang-format'
+
+# Change this to format according to other formatting styles. See the output of
+# 'clang-format --help' for a list of supported styles. The default looks for
+# a '.clang-format' or '_clang-format' file to indicate the style that should be
+# used.
+style = 'file'
+
+class ClangFormatCommand(sublime_plugin.TextCommand):
+  def run(self, edit):
+    encoding = self.view.encoding()
+    if encoding == 'Undefined':
+      encoding = 'utf-8'
+    regions = []
+    command = [binary, '-style', style]
+    for region in self.view.sel():
+      regions.append(region)
+      region_offset = min(region.a, region.b)
+      region_length = abs(region.b - region.a)
+      command.extend(['-offset', str(region_offset),
+                      '-length', str(region_length),
+                      '-assume-filename', str(self.view.file_name())])
+    old_viewport_position = self.view.viewport_position()
+    buf = self.view.substr(sublime.Region(0, self.view.size()))
+    p = subprocess.Popen(command, stdout=subprocess.PIPE,
+                         stderr=subprocess.PIPE, stdin=subprocess.PIPE)
+    output, error = p.communicate(buf.encode(encoding))
+    if error:
+      print(error)
+    self.view.replace(
+        edit, sublime.Region(0, self.view.size()),
+        output.decode(encoding))
+    self.view.sel().clear()
+    for region in regions:
+      self.view.sel().add(region)
+    # FIXME: Without the 10ms delay, the viewport sometimes jumps.
+    sublime.set_timeout(lambda: self.view.set_viewport_position(
+      old_viewport_position, False), 10)
diff --git a/buildtools/clang_format/script/clang-format-test.el b/buildtools/clang_format/script/clang-format-test.el
new file mode 100644
index 0000000..0e1f4dd
--- /dev/null
+++ b/buildtools/clang_format/script/clang-format-test.el
@@ -0,0 +1,126 @@
+;;; clang-format-test.el --- unit tests for clang-format.el  -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2017  Google Inc.
+
+;; Author: Philipp Stephani <phst@google.com>
+
+;; This file is distributed under the University of Illinois Open Source
+;; License.  See LICENSE.TXT for details.
+
+;;; Commentary:
+
+;; Unit tests for clang-format.el.
+
+;;; Code:
+
+(require 'clang-format)
+
+(require 'cl-lib)
+(require 'ert)
+(require 'pcase)
+
+(ert-deftest clang-format-buffer--buffer-encoding ()
+  "Tests that encoded text is handled properly."
+  (cl-letf* ((call-process-args nil)
+             ((symbol-function 'call-process-region)
+              (lambda (&rest args)
+                (push args call-process-args)
+                (pcase-exhaustive args
+                  (`(,_start ,_end ,_program ,_delete (,stdout ,_stderr)
+                             ,_display . ,_args)
+                   (with-current-buffer stdout
+                     (insert "<?xml version='1.0'?>
+<replacements xml:space='preserve' incomplete_format='false'>
+<replacement offset='4' length='0'> </replacement>
+<replacement offset='10' length='0'> </replacement>
+</replacements>
+"))
+                   0)))))
+    (with-temp-buffer
+      (let ((buffer-file-name "foo.cpp")
+            (buffer-file-coding-system 'utf-8-with-signature-dos)
+            (default-process-coding-system 'latin-1-unix))
+        (insert "ä =ö;\nü= ß;\n")
+        (goto-char (point-min))
+        (end-of-line)
+        (clang-format-buffer))
+      (should (equal (buffer-string) "ä = ö;\nü = ß;\n"))
+      (should (eolp))
+      (should (equal (buffer-substring (point) (point-max))
+                     "\nü = ß;\n")))
+    (should-not (cdr call-process-args))
+    (pcase-exhaustive call-process-args
+      (`((,start ,end ,_program ,delete (,_stdout ,_stderr) ,display . ,args))
+       (should-not start)
+       (should-not end)
+       (should-not delete)
+       (should-not display)
+       (should (equal args
+                      '("-output-replacements-xml" "-assume-filename" "foo.cpp"
+                        "-style" "file"
+                        ;; Beginning of buffer, no byte-order mark.
+                        "-offset" "0"
+                        ;; We have two lines with 2×2 bytes for the umlauts,
+                        ;; 1 byte for the line ending, and 3 bytes for the
+                        ;; other ASCII characters each.
+                        "-length" "16"
+                        ;; Length of a single line (without line ending).
+                        "-cursor" "7")))))))
+
+(ert-deftest clang-format-buffer--process-encoding ()
+  "Tests that text is sent to the clang-format process in the
+right encoding."
+  (cl-letf* ((hexdump (executable-find "hexdump"))
+             (original-call-process-region
+              (symbol-function 'call-process-region))
+             (call-process-inputs nil)
+             ;; We redirect the input to hexdump so that we have guaranteed
+             ;; ASCII output.
+             ((symbol-function 'call-process-region)
+              (lambda (&rest args)
+                (pcase-exhaustive args
+                  (`(,start ,end ,_program ,_delete (,stdout ,_stderr)
+                            ,_display . ,_args)
+                   (with-current-buffer stdout
+                     (insert "<?xml version='1.0'?>
+<replacements xml:space='preserve' incomplete_format='false'>
+</replacements>
+"))
+                   (let ((stdin (current-buffer)))
+                     (with-temp-buffer
+                       (prog1
+                           (let ((stdout (current-buffer)))
+                             (with-current-buffer stdin
+                               (funcall original-call-process-region
+                                        start end hexdump nil stdout nil
+                                        "-v" "-e" "/1 \"%02x \"")))
+                         (push (buffer-string) call-process-inputs)))))))))
+    (skip-unless hexdump)
+    (with-temp-buffer
+      (let ((buffer-file-name "foo.cpp")
+            (buffer-file-coding-system 'utf-8-with-signature-dos)
+            (default-process-coding-system 'latin-1-unix))
+        (insert "ä\n")
+        (clang-format-buffer))
+      (should (equal (buffer-string) "ä\n"))
+      (should (eobp)))
+    (should (equal call-process-inputs '("c3 a4 0a ")))))
+
+(ert-deftest clang-format-buffer--end-to-end ()
+  "End-to-end test for ‘clang-format-buffer’.
+Actually calls the clang-format binary."
+  (skip-unless (file-executable-p clang-format-executable))
+  (with-temp-buffer
+    (let ((buffer-file-name "foo.cpp")
+          (buffer-file-coding-system 'utf-8-with-signature-dos)
+          (default-process-coding-system 'latin-1-unix))
+      (insert "ä =ö;\nü= ß;\n")
+      (goto-char (point-min))
+      (end-of-line)
+      (clang-format-buffer))
+    (should (equal (buffer-string) "ä = ö;\nü = ß;\n"))
+    (should (eolp))
+    (should (equal (buffer-substring (point) (point-max))
+                   "\nü = ß;\n"))))
+
+;;; clang-format-test.el ends here
diff --git a/buildtools/clang_format/script/clang-format.el b/buildtools/clang_format/script/clang-format.el
new file mode 100644
index 0000000..aa9c3ff
--- /dev/null
+++ b/buildtools/clang_format/script/clang-format.el
@@ -0,0 +1,193 @@
+;;; clang-format.el --- Format code using clang-format  -*- lexical-binding: t; -*-
+
+;; Keywords: tools, c
+;; Package-Requires: ((cl-lib "0.3"))
+
+;;; Commentary:
+
+;; This package allows to filter code through clang-format to fix its formatting.
+;; clang-format is a tool that formats C/C++/Obj-C code according to a set of
+;; style options, see <http://clang.llvm.org/docs/ClangFormatStyleOptions.html>.
+;; Note that clang-format 3.4 or newer is required.
+
+;; clang-format.el is available via MELPA and can be installed via
+;;
+;;   M-x package-install clang-format
+;;
+;; when ("melpa" . "http://melpa.org/packages/") is included in
+;; `package-archives'.  Alternatively, ensure the directory of this
+;; file is in your `load-path' and add
+;;
+;;   (require 'clang-format)
+;;
+;; to your .emacs configuration.
+
+;; You may also want to bind `clang-format-region' to a key:
+;;
+;;   (global-set-key [C-M-tab] 'clang-format-region)
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'xml)
+
+(defgroup clang-format nil
+  "Format code using clang-format."
+  :group 'tools)
+
+(defcustom clang-format-executable
+  (or (executable-find "clang-format")
+      "clang-format")
+  "Location of the clang-format executable.
+
+A string containing the name or the full path of the executable."
+  :group 'clang-format
+  :type '(file :must-match t)
+  :risky t)
+
+(defcustom clang-format-style "file"
+  "Style argument to pass to clang-format.
+
+By default clang-format will load the style configuration from
+a file named .clang-format located in one of the parent directories
+of the buffer."
+  :group 'clang-format
+  :type 'string
+  :safe #'stringp)
+(make-variable-buffer-local 'clang-format-style)
+
+(defun clang-format--extract (xml-node)
+  "Extract replacements and cursor information from XML-NODE."
+  (unless (and (listp xml-node) (eq (xml-node-name xml-node) 'replacements))
+    (error "Expected <replacements> node"))
+  (let ((nodes (xml-node-children xml-node))
+        (incomplete-format (xml-get-attribute xml-node 'incomplete_format))
+        replacements
+        cursor)
+    (dolist (node nodes)
+      (when (listp node)
+        (let* ((children (xml-node-children node))
+               (text (car children)))
+          (cl-case (xml-node-name node)
+            ('replacement
+             (let* ((offset (xml-get-attribute-or-nil node 'offset))
+                    (length (xml-get-attribute-or-nil node 'length)))
+               (when (or (null offset) (null length))
+                 (error "<replacement> node does not have offset and length attributes"))
+               (when (cdr children)
+                 (error "More than one child node in <replacement> node"))
+
+               (setq offset (string-to-number offset))
+               (setq length (string-to-number length))
+               (push (list offset length text) replacements)))
+            ('cursor
+             (setq cursor (string-to-number text)))))))
+
+    ;; Sort by decreasing offset, length.
+    (setq replacements (sort (delq nil replacements)
+                             (lambda (a b)
+                               (or (> (car a) (car b))
+                                   (and (= (car a) (car b))
+                                        (> (cadr a) (cadr b)))))))
+
+    (list replacements cursor (string= incomplete-format "true"))))
+
+(defun clang-format--replace (offset length &optional text)
+  "Replace the region defined by OFFSET and LENGTH with TEXT.
+OFFSET and LENGTH are measured in bytes, not characters.  OFFSET
+is a zero-based file offset, assuming ‘utf-8-unix’ coding."
+  (let ((start (clang-format--filepos-to-bufferpos offset 'exact 'utf-8-unix))
+        (end (clang-format--filepos-to-bufferpos (+ offset length) 'exact
+                                                 'utf-8-unix)))
+    (goto-char start)
+    (delete-region start end)
+    (when text
+      (insert text))))
+
+;; ‘bufferpos-to-filepos’ and ‘filepos-to-bufferpos’ are new in Emacs 25.1.
+;; Provide fallbacks for older versions.
+(defalias 'clang-format--bufferpos-to-filepos
+  (if (fboundp 'bufferpos-to-filepos)
+      'bufferpos-to-filepos
+    (lambda (position &optional _quality _coding-system)
+      (1- (position-bytes position)))))
+
+(defalias 'clang-format--filepos-to-bufferpos
+  (if (fboundp 'filepos-to-bufferpos)
+      'filepos-to-bufferpos
+    (lambda (byte &optional _quality _coding-system)
+      (byte-to-position (1+ byte)))))
+
+;;;###autoload
+(defun clang-format-region (start end &optional style)
+  "Use clang-format to format the code between START and END according to STYLE.
+If called interactively uses the region or the current statement if there
+is no active region.  If no style is given uses `clang-format-style'."
+  (interactive
+   (if (use-region-p)
+       (list (region-beginning) (region-end))
+     (list (point) (point))))
+
+  (unless style
+    (setq style clang-format-style))
+
+  (let ((file-start (clang-format--bufferpos-to-filepos start 'approximate
+                                                        'utf-8-unix))
+        (file-end (clang-format--bufferpos-to-filepos end 'approximate
+                                                      'utf-8-unix))
+        (cursor (clang-format--bufferpos-to-filepos (point) 'exact 'utf-8-unix))
+        (temp-buffer (generate-new-buffer " *clang-format-temp*"))
+        (temp-file (make-temp-file "clang-format"))
+        ;; Output is XML, which is always UTF-8.  Input encoding should match
+        ;; the encoding used to convert between buffer and file positions,
+        ;; otherwise the offsets calculated above are off.  For simplicity, we
+        ;; always use ‘utf-8-unix’ and ignore the buffer coding system.
+        (default-process-coding-system '(utf-8-unix . utf-8-unix)))
+    (unwind-protect
+        (let ((status (call-process-region
+                       nil nil clang-format-executable
+                       nil `(,temp-buffer ,temp-file) nil
+
+                       "-output-replacements-xml"
+                       "-assume-filename" (or (buffer-file-name) "")
+                       "-style" style
+                       "-offset" (number-to-string file-start)
+                       "-length" (number-to-string (- file-end file-start))
+                       "-cursor" (number-to-string cursor)))
+              (stderr (with-temp-buffer
+                        (unless (zerop (cadr (insert-file-contents temp-file)))
+                          (insert ": "))
+                        (buffer-substring-no-properties
+                         (point-min) (line-end-position)))))
+          (cond
+           ((stringp status)
+            (error "(clang-format killed by signal %s%s)" status stderr))
+           ((not (zerop status))
+            (error "(clang-format failed with code %d%s)" status stderr)))
+
+          (cl-destructuring-bind (replacements cursor incomplete-format)
+              (with-current-buffer temp-buffer
+                (clang-format--extract (car (xml-parse-region))))
+            (save-excursion
+              (dolist (rpl replacements)
+                (apply #'clang-format--replace rpl)))
+            (when cursor
+              (goto-char (clang-format--filepos-to-bufferpos cursor 'exact
+                                                             'utf-8-unix)))
+            (if incomplete-format
+                (message "(clang-format: incomplete (syntax errors)%s)" stderr)
+              (message "(clang-format: success%s)" stderr))))
+      (delete-file temp-file)
+      (when (buffer-name temp-buffer) (kill-buffer temp-buffer)))))
+
+;;;###autoload
+(defun clang-format-buffer (&optional style)
+  "Use clang-format to format the current buffer according to STYLE."
+  (interactive)
+  (clang-format-region (point-min) (point-max) style))
+
+;;;###autoload
+(defalias 'clang-format 'clang-format-region)
+
+(provide 'clang-format)
+;;; clang-format.el ends here
diff --git a/buildtools/clang_format/script/clang-format.py b/buildtools/clang_format/script/clang-format.py
new file mode 100644
index 0000000..ae8a6eb
--- /dev/null
+++ b/buildtools/clang_format/script/clang-format.py
@@ -0,0 +1,116 @@
+# This file is a minimal clang-format vim-integration. To install:
+# - Change 'binary' if clang-format is not on the path (see below).
+# - Add to your .vimrc:
+#
+#   map <C-I> :pyf <path-to-this-file>/clang-format.py<cr>
+#   imap <C-I> <c-o>:pyf <path-to-this-file>/clang-format.py<cr>
+#
+# The first line enables clang-format for NORMAL and VISUAL mode, the second
+# line adds support for INSERT mode. Change "C-I" to another binding if you
+# need clang-format on a different key (C-I stands for Ctrl+i).
+#
+# With this integration you can press the bound key and clang-format will
+# format the current line in NORMAL and INSERT mode or the selected region in
+# VISUAL mode. The line or region is extended to the next bigger syntactic
+# entity.
+#
+# You can also pass in the variable "l:lines" to choose the range for
+# formatting. This variable can either contain "<start line>:<end line>" or
+# "all" to format the full file. So, to format the full file, write a function
+# like:
+# :function FormatFile()
+# :  let l:lines="all"
+# :  pyf <path-to-this-file>/clang-format.py
+# :endfunction
+#
+# It operates on the current, potentially unsaved buffer and does not create
+# or save any files. To revert a formatting, just undo.
+from __future__ import print_function
+
+import difflib
+import json
+import platform
+import subprocess
+import sys
+import vim
+
+# set g:clang_format_path to the path to clang-format if it is not on the path
+# Change this to the full path if clang-format is not on the path.
+binary = 'clang-format'
+if vim.eval('exists("g:clang_format_path")') == "1":
+  binary = vim.eval('g:clang_format_path')
+
+# Change this to format according to other formatting styles. See the output of
+# 'clang-format --help' for a list of supported styles. The default looks for
+# a '.clang-format' or '_clang-format' file to indicate the style that should be
+# used.
+style = 'file'
+fallback_style = None
+if vim.eval('exists("g:clang_format_fallback_style")') == "1":
+  fallback_style = vim.eval('g:clang_format_fallback_style')
+
+def get_buffer(encoding):
+  if platform.python_version_tuple()[0] == '3':
+    return vim.current.buffer
+  return [ line.decode(encoding) for line in vim.current.buffer ]
+
+def main():
+  # Get the current text.
+  encoding = vim.eval("&encoding")
+  buf = get_buffer(encoding)
+  text = '\n'.join(buf)
+
+  # Determine range to format.
+  if vim.eval('exists("l:lines")') == '1':
+    lines = vim.eval('l:lines')
+  else:
+    lines = '%s:%s' % (vim.current.range.start + 1, vim.current.range.end + 1)
+
+  # Determine the cursor position.
+  cursor = int(vim.eval('line2byte(line("."))+col(".")')) - 2
+  if cursor < 0:
+    print('Couldn\'t determine cursor position. Is your file empty?')
+    return
+
+  # Avoid flashing an ugly, ugly cmd prompt on Windows when invoking clang-format.
+  startupinfo = None
+  if sys.platform.startswith('win32'):
+    startupinfo = subprocess.STARTUPINFO()
+    startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
+    startupinfo.wShowWindow = subprocess.SW_HIDE
+
+  # Call formatter.
+  command = [binary, '-style', style, '-cursor', str(cursor)]
+  if lines != 'all':
+    command.extend(['-lines', lines])
+  if fallback_style:
+    command.extend(['-fallback-style', fallback_style])
+  if vim.current.buffer.name:
+    command.extend(['-assume-filename', vim.current.buffer.name])
+  p = subprocess.Popen(command,
+                       stdout=subprocess.PIPE, stderr=subprocess.PIPE,
+                       stdin=subprocess.PIPE, startupinfo=startupinfo)
+  stdout, stderr = p.communicate(input=text.encode(encoding))
+
+  # If successful, replace buffer contents.
+  if stderr:
+    print(stderr)
+
+  if not stdout:
+    print(
+        'No output from clang-format (crashed?).\n'
+        'Please report to bugs.llvm.org.'
+    )
+  else:
+    lines = stdout.decode(encoding).split('\n')
+    output = json.loads(lines[0])
+    lines = lines[1:]
+    sequence = difflib.SequenceMatcher(None, buf, lines)
+    for op in reversed(sequence.get_opcodes()):
+      if op[0] is not 'equal':
+        vim.current.buffer[op[1]:op[2]] = lines[op[3]:op[4]]
+    if output.get('IncompleteFormat'):
+      print('clang-format: incomplete (syntax errors)')
+    vim.command('goto %d' % (output['Cursor'] + 1))
+
+main()
diff --git a/buildtools/clang_format/script/fuzzer/CMakeLists.txt b/buildtools/clang_format/script/fuzzer/CMakeLists.txt
new file mode 100644
index 0000000..c7772fc
--- /dev/null
+++ b/buildtools/clang_format/script/fuzzer/CMakeLists.txt
@@ -0,0 +1,11 @@
+set(LLVM_LINK_COMPONENTS support)
+
+add_clang_executable(clang-format-fuzzer
+  EXCLUDE_FROM_ALL
+  ClangFormatFuzzer.cpp
+  )
+
+target_link_libraries(clang-format-fuzzer
+  ${CLANG_FORMAT_LIB_DEPS}
+  LLVMFuzzer
+  )
diff --git a/buildtools/clang_format/script/fuzzer/ClangFormatFuzzer.cpp b/buildtools/clang_format/script/fuzzer/ClangFormatFuzzer.cpp
new file mode 100644
index 0000000..5334ce8
--- /dev/null
+++ b/buildtools/clang_format/script/fuzzer/ClangFormatFuzzer.cpp
@@ -0,0 +1,26 @@
+//===-- ClangFormatFuzzer.cpp - Fuzz the Clang format tool ----------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief This file implements a function that runs Clang format on a single
+///  input. This function is then linked into the Fuzzer library.
+///
+//===----------------------------------------------------------------------===//
+
+#include "clang/Format/Format.h"
+
+extern "C" int LLVMFuzzerTestOneInput(uint8_t *data, size_t size) {
+  // FIXME: fuzz more things: different styles, different style features.
+  std::string s((const char *)data, size);
+  auto Style = getGoogleStyle(clang::format::FormatStyle::LK_Cpp);
+  Style.ColumnLimit = 60;
+  applyAllReplacements(s, clang::format::reformat(
+                              Style, s, {clang::tooling::Range(0, s.size())}));
+  return 0;
+}
diff --git a/buildtools/clang_format/script/git-clang-format b/buildtools/clang_format/script/git-clang-format
new file mode 100755
index 0000000..3d1ba8a
--- /dev/null
+++ b/buildtools/clang_format/script/git-clang-format
@@ -0,0 +1,551 @@
+#!/usr/bin/env python
+#
+#===- git-clang-format - ClangFormat Git Integration ---------*- python -*--===#
+#
+#                     The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+#===------------------------------------------------------------------------===#
+
+r"""                                                                             
+clang-format git integration                                                     
+============================                                                     
+                                                                                 
+This file provides a clang-format integration for git. Put it somewhere in your  
+path and ensure that it is executable. Then, "git clang-format" will invoke      
+clang-format on the changes in current files or a specific commit.               
+                                                                                 
+For further details, run:                                                        
+git clang-format -h                                                              
+                                                                                 
+Requires Python 2.7                                                              
+"""               
+
+from __future__ import print_function
+import argparse
+import collections
+import contextlib
+import errno
+import os
+import re
+import subprocess
+import sys
+
+usage = 'git clang-format [OPTIONS] [<commit>] [<commit>] [--] [<file>...]'
+
+desc = '''
+If zero or one commits are given, run clang-format on all lines that differ
+between the working directory and <commit>, which defaults to HEAD.  Changes are
+only applied to the working directory.
+
+If two commits are given (requires --diff), run clang-format on all lines in the
+second <commit> that differ from the first <commit>.
+
+The following git-config settings set the default of the corresponding option:
+  clangFormat.binary
+  clangFormat.commit
+  clangFormat.extension
+  clangFormat.style
+'''
+
+# Name of the temporary index file in which save the output of clang-format.
+# This file is created within the .git directory.
+temp_index_basename = 'clang-format-index'
+
+
+Range = collections.namedtuple('Range', 'start, count')
+
+
+def main():
+  config = load_git_config()
+
+  # In order to keep '--' yet allow options after positionals, we need to
+  # check for '--' ourselves.  (Setting nargs='*' throws away the '--', while
+  # nargs=argparse.REMAINDER disallows options after positionals.)
+  argv = sys.argv[1:]
+  try:
+    idx = argv.index('--')
+  except ValueError:
+    dash_dash = []
+  else:
+    dash_dash = argv[idx:]
+    argv = argv[:idx]
+
+  default_extensions = ','.join([
+      # From clang/lib/Frontend/FrontendOptions.cpp, all lower case
+      'c', 'h',  # C
+      'm',  # ObjC
+      'mm',  # ObjC++
+      'cc', 'cp', 'cpp', 'c++', 'cxx', 'hpp',  # C++
+      # Other languages that clang-format supports
+      'proto', 'protodevel',  # Protocol Buffers
+      'java',  # Java
+      'js',  # JavaScript
+      'ts',  # TypeScript
+      ])
+
+  p = argparse.ArgumentParser(
+    usage=usage, formatter_class=argparse.RawDescriptionHelpFormatter,
+    description=desc)
+  p.add_argument('--binary',
+                 default=config.get('clangformat.binary', 'clang-format'),
+                 help='path to clang-format'),
+  p.add_argument('--commit',
+                 default=config.get('clangformat.commit', 'HEAD'),
+                 help='default commit to use if none is specified'),
+  p.add_argument('--diff', action='store_true',
+                 help='print a diff instead of applying the changes')
+  p.add_argument('--extensions',
+                 default=config.get('clangformat.extensions',
+                                    default_extensions),
+                 help=('comma-separated list of file extensions to format, '
+                       'excluding the period and case-insensitive')),
+  p.add_argument('-f', '--force', action='store_true',
+                 help='allow changes to unstaged files')
+  p.add_argument('-p', '--patch', action='store_true',
+                 help='select hunks interactively')
+  p.add_argument('-q', '--quiet', action='count', default=0,
+                 help='print less information')
+  p.add_argument('--style',
+                 default=config.get('clangformat.style', None),
+                 help='passed to clang-format'),
+  p.add_argument('-v', '--verbose', action='count', default=0,
+                 help='print extra information')
+  # We gather all the remaining positional arguments into 'args' since we need
+  # to use some heuristics to determine whether or not <commit> was present.
+  # However, to print pretty messages, we make use of metavar and help.
+  p.add_argument('args', nargs='*', metavar='<commit>',
+                 help='revision from which to compute the diff')
+  p.add_argument('ignored', nargs='*', metavar='<file>...',
+                 help='if specified, only consider differences in these files')
+  opts = p.parse_args(argv)
+
+  opts.verbose -= opts.quiet
+  del opts.quiet
+
+  commits, files = interpret_args(opts.args, dash_dash, opts.commit)
+  if len(commits) > 1:
+    if not opts.diff:
+      die('--diff is required when two commits are given')
+  else:
+    if len(commits) > 2:
+      die('at most two commits allowed; %d given' % len(commits))
+  changed_lines = compute_diff_and_extract_lines(commits, files)
+  if opts.verbose >= 1:
+    ignored_files = set(changed_lines)
+  filter_by_extension(changed_lines, opts.extensions.lower().split(','))
+  if opts.verbose >= 1:
+    ignored_files.difference_update(changed_lines)
+    if ignored_files:
+      print('Ignoring changes in the following files (wrong extension):')
+      for filename in ignored_files:
+        print('    %s' % filename)
+    if changed_lines:
+      print('Running clang-format on the following files:')
+      for filename in changed_lines:
+        print('    %s' % filename)
+  if not changed_lines:
+    print('no modified files to format')
+    return
+  # The computed diff outputs absolute paths, so we must cd before accessing
+  # those files.
+  cd_to_toplevel()
+  if len(commits) > 1:
+    old_tree = commits[1]
+    new_tree = run_clang_format_and_save_to_tree(changed_lines,
+                                                 revision=commits[1],
+                                                 binary=opts.binary,
+                                                 style=opts.style)
+  else:
+    old_tree = create_tree_from_workdir(changed_lines)
+    new_tree = run_clang_format_and_save_to_tree(changed_lines,
+                                                 binary=opts.binary,
+                                                 style=opts.style)
+  if opts.verbose >= 1:
+    print('old tree: %s' % old_tree)
+    print('new tree: %s' % new_tree)
+  if old_tree == new_tree:
+    if opts.verbose >= 0:
+      print('clang-format did not modify any files')
+  elif opts.diff:
+    print_diff(old_tree, new_tree)
+  else:
+    changed_files = apply_changes(old_tree, new_tree, force=opts.force,
+                                  patch_mode=opts.patch)
+    if (opts.verbose >= 0 and not opts.patch) or opts.verbose >= 1:
+      print('changed files:')
+      for filename in changed_files:
+        print('    %s' % filename)
+
+
+def load_git_config(non_string_options=None):
+  """Return the git configuration as a dictionary.
+
+  All options are assumed to be strings unless in `non_string_options`, in which
+  is a dictionary mapping option name (in lower case) to either "--bool" or
+  "--int"."""
+  if non_string_options is None:
+    non_string_options = {}
+  out = {}
+  for entry in run('git', 'config', '--list', '--null').split('\0'):
+    if entry:
+      name, value = entry.split('\n', 1)
+      if name in non_string_options:
+        value = run('git', 'config', non_string_options[name], name)
+      out[name] = value
+  return out
+
+
+def interpret_args(args, dash_dash, default_commit):
+  """Interpret `args` as "[commits] [--] [files]" and return (commits, files).
+
+  It is assumed that "--" and everything that follows has been removed from
+  args and placed in `dash_dash`.
+
+  If "--" is present (i.e., `dash_dash` is non-empty), the arguments to its
+  left (if present) are taken as commits.  Otherwise, the arguments are checked
+  from left to right if they are commits or files.  If commits are not given,
+  a list with `default_commit` is used."""
+  if dash_dash:
+    if len(args) == 0:
+      commits = [default_commit]
+    else:
+      commits = args
+    for commit in commits:
+      object_type = get_object_type(commit)
+      if object_type not in ('commit', 'tag'):
+        if object_type is None:
+          die("'%s' is not a commit" % commit)
+        else:
+          die("'%s' is a %s, but a commit was expected" % (commit, object_type))
+    files = dash_dash[1:]
+  elif args:
+    commits = []
+    while args:
+      if not disambiguate_revision(args[0]):
+        break
+      commits.append(args.pop(0))
+    if not commits:
+      commits = [default_commit]
+    files = args
+  else:
+    commits = [default_commit]
+    files = []
+  return commits, files
+
+
+def disambiguate_revision(value):
+  """Returns True if `value` is a revision, False if it is a file, or dies."""
+  # If `value` is ambiguous (neither a commit nor a file), the following
+  # command will die with an appropriate error message.
+  run('git', 'rev-parse', value, verbose=False)
+  object_type = get_object_type(value)
+  if object_type is None:
+    return False
+  if object_type in ('commit', 'tag'):
+    return True
+  die('`%s` is a %s, but a commit or filename was expected' %
+      (value, object_type))
+
+
+def get_object_type(value):
+  """Returns a string description of an object's type, or None if it is not
+  a valid git object."""
+  cmd = ['git', 'cat-file', '-t', value]
+  p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+  stdout, stderr = p.communicate()
+  if p.returncode != 0:
+    return None
+  return stdout.strip()
+
+
+def compute_diff_and_extract_lines(commits, files):
+  """Calls compute_diff() followed by extract_lines()."""
+  diff_process = compute_diff(commits, files)
+  changed_lines = extract_lines(diff_process.stdout)
+  diff_process.stdout.close()
+  diff_process.wait()
+  if diff_process.returncode != 0:
+    # Assume error was already printed to stderr.
+    sys.exit(2)
+  return changed_lines
+
+
+def compute_diff(commits, files):
+  """Return a subprocess object producing the diff from `commits`.
+
+  The return value's `stdin` file object will produce a patch with the
+  differences between the working directory and the first commit if a single
+  one was specified, or the difference between both specified commits, filtered
+  on `files` (if non-empty).  Zero context lines are used in the patch."""
+  git_tool = 'diff-index'
+  if len(commits) > 1:
+    git_tool = 'diff-tree'
+  cmd = ['git', git_tool, '-p', '-U0'] + commits + ['--']
+  cmd.extend(files)
+  p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
+  p.stdin.close()
+  return p
+
+
+def extract_lines(patch_file):
+  """Extract the changed lines in `patch_file`.
+
+  The return value is a dictionary mapping filename to a list of (start_line,
+  line_count) pairs.
+
+  The input must have been produced with ``-U0``, meaning unidiff format with
+  zero lines of context.  The return value is a dict mapping filename to a
+  list of line `Range`s."""
+  matches = {}
+  for line in patch_file:
+    match = re.search(r'^\+\+\+\ [^/]+/(.*)', line)
+    if match:
+      filename = match.group(1).rstrip('\r\n')
+    match = re.search(r'^@@ -[0-9,]+ \+(\d+)(,(\d+))?', line)
+    if match:
+      start_line = int(match.group(1))
+      line_count = 1
+      if match.group(3):
+        line_count = int(match.group(3))
+      if line_count > 0:
+        matches.setdefault(filename, []).append(Range(start_line, line_count))
+  return matches
+
+
+def filter_by_extension(dictionary, allowed_extensions):
+  """Delete every key in `dictionary` that doesn't have an allowed extension.
+
+  `allowed_extensions` must be a collection of lowercase file extensions,
+  excluding the period."""
+  allowed_extensions = frozenset(allowed_extensions)
+  for filename in list(dictionary.keys()):
+    base_ext = filename.rsplit('.', 1)
+    if len(base_ext) == 1 or base_ext[1].lower() not in allowed_extensions:
+      del dictionary[filename]
+
+
+def cd_to_toplevel():
+  """Change to the top level of the git repository."""
+  toplevel = run('git', 'rev-parse', '--show-toplevel')
+  os.chdir(toplevel)
+
+
+def create_tree_from_workdir(filenames):
+  """Create a new git tree with the given files from the working directory.
+
+  Returns the object ID (SHA-1) of the created tree."""
+  return create_tree(filenames, '--stdin')
+
+
+def run_clang_format_and_save_to_tree(changed_lines, revision=None,
+                                      binary='clang-format', style=None):
+  """Run clang-format on each file and save the result to a git tree.
+
+  Returns the object ID (SHA-1) of the created tree."""
+  def iteritems(container):
+      try:
+          return container.iteritems() # Python 2
+      except AttributeError:
+          return container.items() # Python 3
+  def index_info_generator():
+    for filename, line_ranges in iteritems(changed_lines):
+      if revision:
+        git_metadata_cmd = ['git', 'ls-tree',
+                            '%s:%s' % (revision, os.path.dirname(filename)),
+                            os.path.basename(filename)]
+        git_metadata = subprocess.Popen(git_metadata_cmd, stdin=subprocess.PIPE,
+                                        stdout=subprocess.PIPE)
+        stdout = git_metadata.communicate()[0]
+        mode = oct(int(stdout.split()[0], 8))
+      else:
+        mode = oct(os.stat(filename).st_mode)
+      # Adjust python3 octal format so that it matches what git expects
+      if mode.startswith('0o'):
+          mode = '0' + mode[2:]
+      blob_id = clang_format_to_blob(filename, line_ranges,
+                                     revision=revision,
+                                     binary=binary,
+                                     style=style)
+      yield '%s %s\t%s' % (mode, blob_id, filename)
+  return create_tree(index_info_generator(), '--index-info')
+
+
+def create_tree(input_lines, mode):
+  """Create a tree object from the given input.
+
+  If mode is '--stdin', it must be a list of filenames.  If mode is
+  '--index-info' is must be a list of values suitable for "git update-index
+  --index-info", such as "<mode> <SP> <sha1> <TAB> <filename>".  Any other mode
+  is invalid."""
+  assert mode in ('--stdin', '--index-info')
+  cmd = ['git', 'update-index', '--add', '-z', mode]
+  with temporary_index_file():
+    p = subprocess.Popen(cmd, stdin=subprocess.PIPE)
+    for line in input_lines:
+      p.stdin.write('%s\0' % line)
+    p.stdin.close()
+    if p.wait() != 0:
+      die('`%s` failed' % ' '.join(cmd))
+    tree_id = run('git', 'write-tree')
+    return tree_id
+
+
+def clang_format_to_blob(filename, line_ranges, revision=None,
+                         binary='clang-format', style=None):
+  """Run clang-format on the given file and save the result to a git blob.
+
+  Runs on the file in `revision` if not None, or on the file in the working
+  directory if `revision` is None.
+
+  Returns the object ID (SHA-1) of the created blob."""
+  clang_format_cmd = [binary]
+  if style:
+    clang_format_cmd.extend(['-style='+style])
+  clang_format_cmd.extend([
+      '-lines=%s:%s' % (start_line, start_line+line_count-1)
+      for start_line, line_count in line_ranges])
+  if revision:
+    clang_format_cmd.extend(['-assume-filename='+filename])
+    git_show_cmd = ['git', 'cat-file', 'blob', '%s:%s' % (revision, filename)]
+    git_show = subprocess.Popen(git_show_cmd, stdin=subprocess.PIPE,
+                                stdout=subprocess.PIPE)
+    git_show.stdin.close()
+    clang_format_stdin = git_show.stdout
+  else:
+    clang_format_cmd.extend([filename])
+    git_show = None
+    clang_format_stdin = subprocess.PIPE
+  try:
+    clang_format = subprocess.Popen(clang_format_cmd, stdin=clang_format_stdin,
+                                    stdout=subprocess.PIPE)
+    if clang_format_stdin == subprocess.PIPE:
+      clang_format_stdin = clang_format.stdin
+  except OSError as e:
+    if e.errno == errno.ENOENT:
+      die('cannot find executable "%s"' % binary)
+    else:
+      raise
+  clang_format_stdin.close()
+  hash_object_cmd = ['git', 'hash-object', '-w', '--path='+filename, '--stdin']
+  hash_object = subprocess.Popen(hash_object_cmd, stdin=clang_format.stdout,
+                                 stdout=subprocess.PIPE)
+  clang_format.stdout.close()
+  stdout = hash_object.communicate()[0]
+  if hash_object.returncode != 0:
+    die('`%s` failed' % ' '.join(hash_object_cmd))
+  if clang_format.wait() != 0:
+    die('`%s` failed' % ' '.join(clang_format_cmd))
+  if git_show and git_show.wait() != 0:
+    die('`%s` failed' % ' '.join(git_show_cmd))
+  return stdout.rstrip('\r\n')
+
+
+@contextlib.contextmanager
+def temporary_index_file(tree=None):
+  """Context manager for setting GIT_INDEX_FILE to a temporary file and deleting
+  the file afterward."""
+  index_path = create_temporary_index(tree)
+  old_index_path = os.environ.get('GIT_INDEX_FILE')
+  os.environ['GIT_INDEX_FILE'] = index_path
+  try:
+    yield
+  finally:
+    if old_index_path is None:
+      del os.environ['GIT_INDEX_FILE']
+    else:
+      os.environ['GIT_INDEX_FILE'] = old_index_path
+    os.remove(index_path)
+
+
+def create_temporary_index(tree=None):
+  """Create a temporary index file and return the created file's path.
+
+  If `tree` is not None, use that as the tree to read in.  Otherwise, an
+  empty index is created."""
+  gitdir = run('git', 'rev-parse', '--git-dir')
+  path = os.path.join(gitdir, temp_index_basename)
+  if tree is None:
+    tree = '--empty'
+  run('git', 'read-tree', '--index-output='+path, tree)
+  return path
+
+
+def print_diff(old_tree, new_tree):
+  """Print the diff between the two trees to stdout."""
+  # We use the porcelain 'diff' and not plumbing 'diff-tree' because the output
+  # is expected to be viewed by the user, and only the former does nice things
+  # like color and pagination.
+  #
+  # We also only print modified files since `new_tree` only contains the files
+  # that were modified, so unmodified files would show as deleted without the
+  # filter.
+  subprocess.check_call(['git', 'diff', '--diff-filter=M', old_tree, new_tree,
+                         '--'])
+
+
+def apply_changes(old_tree, new_tree, force=False, patch_mode=False):
+  """Apply the changes in `new_tree` to the working directory.
+
+  Bails if there are local changes in those files and not `force`.  If
+  `patch_mode`, runs `git checkout --patch` to select hunks interactively."""
+  changed_files = run('git', 'diff-tree', '--diff-filter=M', '-r', '-z',
+                      '--name-only', old_tree,
+                      new_tree).rstrip('\0').split('\0')
+  if not force:
+    unstaged_files = run('git', 'diff-files', '--name-status', *changed_files)
+    if unstaged_files:
+      print('The following files would be modified but '
+                'have unstaged changes:', file=sys.stderr)
+      print(unstaged_files, file=sys.stderr)
+      print('Please commit, stage, or stash them first.', file=sys.stderr)
+      sys.exit(2)
+  if patch_mode:
+    # In patch mode, we could just as well create an index from the new tree
+    # and checkout from that, but then the user will be presented with a
+    # message saying "Discard ... from worktree".  Instead, we use the old
+    # tree as the index and checkout from new_tree, which gives the slightly
+    # better message, "Apply ... to index and worktree".  This is not quite
+    # right, since it won't be applied to the user's index, but oh well.
+    with temporary_index_file(old_tree):
+      subprocess.check_call(['git', 'checkout', '--patch', new_tree])
+    index_tree = old_tree
+  else:
+    with temporary_index_file(new_tree):
+      run('git', 'checkout-index', '-a', '-f')
+  return changed_files
+
+
+def run(*args, **kwargs):
+  stdin = kwargs.pop('stdin', '')
+  verbose = kwargs.pop('verbose', True)
+  strip = kwargs.pop('strip', True)
+  for name in kwargs:
+    raise TypeError("run() got an unexpected keyword argument '%s'" % name)
+  p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
+                       stdin=subprocess.PIPE)
+  stdout, stderr = p.communicate(input=stdin)
+  if p.returncode == 0:
+    if stderr:
+      if verbose:
+        print('`%s` printed to stderr:' % ' '.join(args), file=sys.stderr)
+      print(stderr.rstrip(), file=sys.stderr)
+    if strip:
+      stdout = stdout.rstrip('\r\n')
+    return stdout
+  if verbose:
+    print('`%s` returned %s' % (' '.join(args), p.returncode), file=sys.stderr)
+  if stderr:
+    print(stderr.rstrip(), file=sys.stderr)
+  sys.exit(2)
+
+
+def die(message):
+  print('error:', message, file=sys.stderr)
+  sys.exit(2)
+
+
+if __name__ == '__main__':
+  main()