VIXL Release 1.13

Refer to the README.md and LICENCE files for details.

Change-Id: I922914f4e7da7cb939a8054cded11feb9ea51a86
diff --git a/tools/clang_format.py b/tools/clang_format.py
new file mode 100755
index 0000000..50dc0eb
--- /dev/null
+++ b/tools/clang_format.py
@@ -0,0 +1,193 @@
+#!/usr/bin/env python2.7
+
+# Copyright 2016, ARM Limited
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+#   * Redistributions of source code must retain the above copyright notice,
+#     this list of conditions and the following disclaimer.
+#   * Redistributions in binary form must reproduce the above copyright notice,
+#     this list of conditions and the following disclaimer in the documentation
+#     and/or other materials provided with the distribution.
+#   * Neither the name of ARM Limited nor the names of its contributors may be
+#     used to endorse or promote products derived from this software without
+#     specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import argparse
+import fnmatch
+import multiprocessing
+import os
+import signal
+import subprocess
+import sys
+import tempfile
+
+import config
+import git
+import printer
+import util
+
+
+is_output_redirected = not sys.stdout.isatty()
+
+# Catch SIGINT to gracefully exit when ctrl+C is pressed.
+def sigint_handler(signal, frame):
+  sys.exit(1)
+signal.signal(signal.SIGINT, sigint_handler)
+
+def BuildOptions():
+  parser = argparse.ArgumentParser(
+    description = '''This tool runs `clang-format` on C++ files.
+    If no files are provided on the command-line, all C++ source files in `src`,
+    `sample`, and `benchmarks` are processed.
+    When available, `colordiff` is automatically used to clour the output.''',
+    # Print default values.
+    formatter_class = argparse.ArgumentDefaultsHelpFormatter)
+  parser.add_argument('files', nargs = '*')
+  parser.add_argument('--in-place', '-i',
+                      action = 'store_true', default = False,
+                      help = 'Edit files in place.')
+  parser.add_argument('--jobs', '-j', metavar = 'N', type = int, nargs = '?',
+                      default = multiprocessing.cpu_count(),
+                      const = multiprocessing.cpu_count(),
+                      help = '''Runs the tests using N jobs. If the option is set
+                      but no value is provided, the script will use as many jobs
+                      as it thinks useful.''')
+  return parser.parse_args()
+
+
+# Returns 0 if the file is correctly formatted, or 1 otherwise.
+def ClangFormat(filename, in_place = False, progress_prefix = ''):
+  rc = 0
+  printer.PrintOverwritableLine('Processing %s' % filename,
+                                type = printer.LINE_TYPE_LINTER)
+
+  cmd_format = ['clang-format-3.6', filename]
+  temp_file, temp_file_name = tempfile.mkstemp(prefix = 'clang_format_')
+  cmd_format_string = '$ ' + ' '.join(cmd_format) + ' > %s' % temp_file_name
+  p_format = subprocess.Popen(cmd_format,
+                              stdout = temp_file, stderr = subprocess.STDOUT)
+
+  rc += p_format.wait()
+
+  cmd_diff = ['diff', '--unified', filename, temp_file_name]
+  cmd_diff_string = '$ ' + ' '.join(cmd_diff)
+  p_diff = subprocess.Popen(cmd_diff,
+                            stdout = subprocess.PIPE, stderr = subprocess.STDOUT)
+
+  if util.IsCommandAvailable('colordiff') and not is_output_redirected:
+    p_colordiff = subprocess.Popen(
+            ['colordiff', '--unified'],
+            stdin = p_diff.stdout,
+            stdout = subprocess.PIPE, stderr = subprocess.STDOUT)
+    out, unused = p_colordiff.communicate()
+  else:
+    out, unused = p_diff.communicate()
+
+  rc += p_diff.wait()
+
+  if in_place:
+      cmd_format = ['clang-format-3.6', '-i', filename]
+      p_format = subprocess.Popen(cmd_format,
+                                  stdout=temp_file, stderr=subprocess.STDOUT)
+
+  if rc != 0:
+    printer.Print('Incorrectly formatted file: ' + filename + '\n' + \
+                  cmd_format_string + '\n' + \
+                  cmd_diff_string + '\n' + \
+                  out)
+
+  return 0 if rc == 0 else 1
+
+
+# The multiprocessing map_async function does not allow passing multiple
+# arguments directly, so use a wrapper.
+def ClangFormatWrapper(args):
+  # Run under a try-catch  to avoid flooding the output when the script is
+  # interrupted from the keyboard with ctrl+C.
+  try:
+    return ClangFormat(*args)
+  except:
+    sys.exit(1)
+
+
+# Returns the total number of files incorrectly formatted.
+def ClangFormatFiles(files, in_place = False, jobs = 1, progress_prefix = ''):
+  if not util.IsCommandAvailable('clang-format-3.6'):
+    print(
+      printer.COLOUR_RED + \
+      ("`clang-format-3.6` not found. Please ensure it is installed "
+       "and in your PATH.") + \
+      printer.NO_COLOUR)
+    return -1
+
+  pool = multiprocessing.Pool(jobs)
+  # The '.get(9999999)' is workaround to allow killing the test script with
+  # ctrl+C from the shell. This bug is documented at
+  # http://bugs.python.org/issue8296.
+  tasks = [(f, in_place, progress_prefix) for f in files]
+  # Run under a try-catch  to avoid flooding the output when the script is
+  # interrupted from the keyboard with ctrl+C.
+  try:
+    results = pool.map_async(ClangFormatWrapper, tasks).get(9999999)
+    pool.close()
+    pool.join()
+  except KeyboardInterrupt:
+    pool.terminate()
+    sys.exit(1)
+  rc = sum(results)
+
+  printer.PrintOverwritableLine(
+      progress_prefix + '%d files are incorrectly formatted.' % rc,
+      type = printer.LINE_TYPE_LINTER)
+  printer.EnsureNewLine()
+  return rc
+
+
+def Find(path, filters = ['*']):
+  files_found = []
+
+  def NameMatchesAnyFilter(name, ff):
+    for f in ff:
+      if fnmatch.fnmatch(name, f):
+        return True
+    return False
+
+  for root, dirs, files in os.walk(path):
+    files_found += [os.path.relpath(os.path.join(root, fn))
+                    for fn in files if NameMatchesAnyFilter(fn, filters)]
+  return files_found
+
+
+def GetCppSourceFilesToFormat():
+  sources = []
+  source_dirs = [config.dir_benchmarks,
+                 config.dir_examples,
+                 config.dir_src_vixl ]
+  for directory in source_dirs:
+    sources += Find(directory, ['*.h', '*.cc'])
+  return sources
+
+
+if __name__ == '__main__':
+  # Parse the arguments.
+  args = BuildOptions()
+  files = args.files
+  if not files:
+    files = GetCppSourceFilesToFormat()
+
+  rc = ClangFormatFiles(files, in_place = args.in_place, jobs = args.jobs)
+  sys.exit(rc)