• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2#
3# american fuzzy lop++ - custom code formatter
4# --------------------------------------------
5#
6# Written and maintaned by Andrea Fioraldi <andreafioraldi@gmail.com>
7#
8# Copyright 2015, 2016, 2017 Google Inc. All rights reserved.
9# Copyright 2019-2022 AFLplusplus Project. All rights reserved.
10#
11# Licensed under the Apache License, Version 2.0 (the "License");
12# you may not use this file except in compliance with the License.
13# You may obtain a copy of the License at:
14#
15#   http://www.apache.org/licenses/LICENSE-2.0
16#
17
18import subprocess
19import sys
20import os
21import re
22
23# string_re = re.compile('(\\"(\\\\.|[^"\\\\])*\\")') # future use
24
25with open(".clang-format") as f:
26    fmt = f.read()
27
28CLANG_FORMAT_BIN = os.getenv("CLANG_FORMAT_BIN")
29if CLANG_FORMAT_BIN is None:
30    o = 0
31    try:
32        p = subprocess.Popen(["clang-format-11", "--version"], stdout=subprocess.PIPE)
33        o, _ = p.communicate()
34        o = str(o, "utf-8")
35        o = re.sub(r".*ersion ", "", o)
36        # o = o[len("clang-format version "):].strip()
37        o = o[: o.find(".")]
38        o = int(o)
39    except:
40        print("clang-format-11 is needed. Aborted.")
41        exit(1)
42    # if o < 7:
43    #    if subprocess.call(['which', 'clang-format-7'], stdout=subprocess.PIPE) == 0:
44    #        CLANG_FORMAT_BIN = 'clang-format-7'
45    #    elif subprocess.call(['which', 'clang-format-8'], stdout=subprocess.PIPE) == 0:
46    #        CLANG_FORMAT_BIN = 'clang-format-8'
47    #    elif subprocess.call(['which', 'clang-format-9'], stdout=subprocess.PIPE) == 0:
48    #        CLANG_FORMAT_BIN = 'clang-format-9'
49    #    elif subprocess.call(['which', 'clang-format-11'], stdout=subprocess.PIPE) == 0:
50    #        CLANG_FORMAT_BIN = 'clang-format-11'
51    #    else:
52    #        print ("clang-format 7 or above is needed. Aborted.")
53    #        exit(1)
54    else:
55        CLANG_FORMAT_BIN = "clang-format-11"
56
57COLUMN_LIMIT = 80
58for line in fmt.split("\n"):
59    line = line.split(":")
60    if line[0].strip() == "ColumnLimit":
61        COLUMN_LIMIT = int(line[1].strip())
62
63
64def custom_format(filename):
65    p = subprocess.Popen([CLANG_FORMAT_BIN, filename], stdout=subprocess.PIPE)
66    src, _ = p.communicate()
67    src = str(src, "utf-8")
68
69    in_define = False
70    last_line = None
71    out = ""
72
73    for line in src.split("\n"):
74        if line.lstrip().startswith("#"):
75            if line[line.find("#") + 1 :].lstrip().startswith("define"):
76                in_define = True
77
78        if (
79            "/*" in line
80            and not line.strip().startswith("/*")
81            and line.endswith("*/")
82            and len(line) < (COLUMN_LIMIT - 2)
83        ):
84            cmt_start = line.rfind("/*")
85            line = (
86                line[:cmt_start]
87                + " " * (COLUMN_LIMIT - 2 - len(line))
88                + line[cmt_start:]
89            )
90
91        define_padding = 0
92        if last_line is not None and in_define and last_line.endswith("\\"):
93            last_line = last_line[:-1]
94            define_padding = max(0, len(last_line[last_line.rfind("\n") + 1 :]))
95
96        if (
97            last_line is not None
98            and last_line.strip().endswith("{")
99            and line.strip() != ""
100        ):
101            line = (" " * define_padding + "\\" if in_define else "") + "\n" + line
102        elif (
103            last_line is not None
104            and last_line.strip().startswith("}")
105            and line.strip() != ""
106        ):
107            line = (" " * define_padding + "\\" if in_define else "") + "\n" + line
108        elif (
109            line.strip().startswith("}")
110            and last_line is not None
111            and last_line.strip() != ""
112        ):
113            line = (" " * define_padding + "\\" if in_define else "") + "\n" + line
114
115        if not line.endswith("\\"):
116            in_define = False
117
118        out += line + "\n"
119        last_line = line
120
121    return out
122
123
124args = sys.argv[1:]
125if len(args) == 0:
126    print("Usage: ./format.py [-i] <filename>")
127    print()
128    print(" The -i option, if specified, let the script to modify in-place")
129    print(" the source files. By default the results are written to stdout.")
130    print()
131    exit(1)
132
133in_place = False
134if args[0] == "-i":
135    in_place = True
136    args = args[1:]
137
138for filename in args:
139    code = custom_format(filename)
140    if in_place:
141        with open(filename, "w") as f:
142            f.write(code)
143    else:
144        print(code)
145