Rizin
unix-like reverse engineering framework and cli tools
clang-format.py
Go to the documentation of this file.
1 #!/usr/bin/env python3
2 #
3 # SPDX-FileCopyrightText: 2021 Anton Kochkov <anton.kochkov@gmail.com>
4 # SPDX-License-Identifier: LGPL-3.0-only
5 
6 import argparse
7 import glob
8 import itertools
9 import subprocess
10 import sys
11 
12 from git import Repo
13 
14 dirlist = [
15  "binrz",
16  "librz",
17  "subprojects/rzar",
18  "subprojects/rzbochs",
19  "subprojects/rzgdb",
20  "subprojects/ptrace-wrap",
21  "subprojects/rzqnx",
22  "subprojects/rzw32dbg_wrap",
23  "subprojects/rzwinkd",
24  "test/unit",
25 ]
26 
27 skiplist = [
28  "/gnu/",
29  "librz/asm/arch/vax/",
30  "librz/asm/arch/riscv/",
31  "librz/asm/arch/sh/gnu/",
32  "librz/asm/arch/i8080/",
33  "librz/asm/arch/z80/",
34  "librz/asm/arch/avr/",
35  "librz/asm/arch/arm/aarch64/",
36  "librz/hash/xxhash/",
37  "librz/bin/mangling/cxx/",
38  "librz/bin/d/jni.h",
39  "librz/util/bdiff.c",
40  "librz/asm/arch/tms320/c55x/table.h",
41  "librz/include/sflib/",
42 ]
43 
44 patterns = ["*.c", "*.cpp", "*.h", "*.hpp", "*.inc"]
45 
46 
47 def should_scan(filename):
48  return any(directory in filename for directory in dirlist) and any(
49  pattern[1:] in filename for pattern in patterns
50  )
51 
52 
53 def skip(filename):
54  return any(skipfile in filename for skipfile in skiplist)
55 
56 
58  for directory, pattern in itertools.product(dirlist, patterns):
59  for filename in glob.iglob(directory + "/**/" + pattern, recursive=True):
60  if not skip(filename):
61  yield filename
62 
63 
64 def get_edited_files(args):
65  repo = Repo()
66 
67  for diff in repo.index.diff(args.diff):
68  filename = diff.a_path
69  if should_scan(filename) and not skip(filename):
70  yield filename
71 
72 
73 def build_command(check, filenames, verbose):
74  cmd = ["clang-format", "--style=file"]
75  if verbose:
76  cmd += ["--verbose"]
77  if check:
78  cmd += ["--Werror", "--dry-run"]
79  else:
80  cmd += ["-i"]
81  return cmd + filenames
82 
83 
84 def format_files(args, files):
85  if len(files) == 0:
86  print("No C files to format.")
87  sys.exit(0)
88  cmd = build_command(args.check, files, args.verbose)
89  r = subprocess.run(cmd, check=False)
90  sys.exit(r.returncode)
91 
92 
93 def get_file(args):
94  filename = args.file
95  if should_scan(filename) and not skip(filename):
96  return [filename]
97 
98  return []
99 
100 
101 def get_files(args):
102  if args.diff:
103  return get_edited_files(args)
104 
105  if args.file:
106  return get_file(args)
107 
108  return get_matching_files()
109 
110 
111 def process(args):
112  files = get_files(args)
113  format_files(args, list(files))
114 
115 
116 def parse():
117  parser = argparse.ArgumentParser(description="Clang format the rizin project")
118  parser.add_argument(
119  "-c", "--check", action="store_true", help="enable the check mode"
120  )
121  parser.add_argument(
122  "-v", "--verbose", action="store_true", help="use verbose output"
123  )
124  parser.add_argument("-f", "--file", help="formats (or checks) only the given file")
125  parser.add_argument(
126  "-d",
127  "--diff",
128  type=str,
129  default=None,
130  help="format all modified file related to branch",
131  )
132  return parser.parse_args()
133 
134 
135 def main():
136  args = parse()
137  process(args)
138 
139 
140 if __name__ == "__main__":
141  main()
size_t len
Definition: 6502dis.c:15
static void list(RzEgg *egg)
Definition: rz-gg.c:52
def should_scan(filename)
Definition: clang-format.py:47
def get_edited_files(args)
Definition: clang-format.py:64
def build_command(check, filenames, verbose)
Definition: clang-format.py:73
def get_matching_files()
Definition: clang-format.py:57
def process(args)
def skip(filename)
Definition: clang-format.py:53
def format_files(args, files)
Definition: clang-format.py:84
def get_files(args)
def get_file(args)
Definition: clang-format.py:93
Definition: regcomp.c:57