blob: e84bcf959c334d5a14cde50e1bbd8a448d137fba [file] [log] [blame]
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001#!/usr/bin/env python
Christopher Ferris08b60742014-06-05 11:17:06 -07002
3#------------------------------------------------------------------------------
4# Description of the header clean process
5#------------------------------------------------------------------------------
6# Here is the list of actions performed by this script to clean the original
7# kernel headers.
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08008#
Christopher Ferris08b60742014-06-05 11:17:06 -07009# 1. Optimize well-known macros (e.g. __KERNEL__, __KERNEL_STRICT_NAMES)
10#
11# This pass gets rid of everything that is guarded by a well-known macro
12# definition. This means that a block like:
13#
14# #ifdef __KERNEL__
15# ....
16# #endif
17#
18# Will be totally omitted from the output. The optimizer is smart enough to
19# handle all complex C-preprocessor conditional expression appropriately.
20# This means that, for example:
21#
22# #if defined(__KERNEL__) || defined(FOO)
23# ...
24# #endif
25#
26# Will be transformed into:
27#
28# #ifdef FOO
29# ...
30# #endif
31#
32# See tools/defaults.py for the list of well-known macros used in this pass,
33# in case you need to update it in the future.
34#
35# Note that this also removes any reference to a kernel-specific
36# configuration macro like CONFIG_FOO from the clean headers.
37#
38#
39# 2. Remove variable and function declarations:
40#
41# This pass scans non-directive text and only keeps things that look like a
42# typedef/struct/union/enum declaration. This allows us to get rid of any
43# variables or function declarations that should only be used within the
44# kernel anyway (and which normally *should* be guarded by an #ifdef
45# __KERNEL__ ... #endif block, if the kernel writers were not so messy).
46#
47# There are, however, a few exceptions: it is seldom useful to keep the
48# definition of some static inline functions performing very simple
49# operations. A good example is the optimized 32-bit byte-swap function
50# found in:
51#
52# arch-arm/asm/byteorder.h
53#
54# The list of exceptions is in tools/defaults.py in case you need to update
55# it in the future.
56#
57# Note that we do *not* remove macro definitions, including these macro that
58# perform a call to one of these kernel-header functions, or even define other
59# functions. We consider it safe since userland applications have no business
60# using them anyway.
61#
62#
Tao Baod7db5942015-01-28 10:07:51 -080063# 3. Add a standard disclaimer:
Christopher Ferris08b60742014-06-05 11:17:06 -070064#
65# The message:
66#
67# /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
68#
69# Is prepended to each generated header.
70#------------------------------------------------------------------------------
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080071
72import sys, cpp, kernel, glob, os, re, getopt
73from defaults import *
74from utils import *
75
Christopher Ferrisd12c3322015-09-15 14:13:17 -070076def print_error(no_update, msg):
77 if no_update:
78 panic(msg)
79 sys.stderr.write("warning: " + msg)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080080
Christopher Ferrisd12c3322015-09-15 14:13:17 -070081
82def cleanupFile(dst_dir, src_dir, rel_path, no_update = True):
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080083 """reads an original header and perform the cleanup operation on it
84 this functions returns the destination path and the clean header
85 as a single string"""
86 # check the header path
Christopher Ferrisd12c3322015-09-15 14:13:17 -070087 full_path = os.path.join(src_dir, rel_path)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080088
Christopher Ferrisd12c3322015-09-15 14:13:17 -070089 if not os.path.exists(full_path):
90 print_error(no_update, "file does not exist: '%s'\n" % full_path)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080091 return None, None
92
Christopher Ferrisd12c3322015-09-15 14:13:17 -070093 if not os.path.isfile(full_path):
94 print_error(no_update, "path is not a file: '%s'\n" % full_path)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080095 return None, None
96
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080097 # convert into destination path, extracting architecture if needed
98 # and the corresponding list of known static functions
99 #
100 arch = None
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800101 statics = kernel_known_generic_statics
Christopher Ferrisd12c3322015-09-15 14:13:17 -0700102 m = re.match(r"asm-([\w\d_\+\.\-]+)(/.*)", rel_path)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800103 if m and m.group(1) != 'generic':
104 dst_path = "arch-%s/asm/%s" % m.groups()
Christopher Ferrisd12c3322015-09-15 14:13:17 -0700105 arch = m.group(1)
106 statics = statics.union(kernel_known_statics.get(arch, set()))
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800107 else:
Ben Cheng8bea2b62013-10-16 15:28:56 -0700108 # process headers under the uapi directory
109 # note the "asm" level has been explicitly added in the original
110 # kernel header tree for architectural-dependent uapi headers
Christopher Ferrisd12c3322015-09-15 14:13:17 -0700111 m_uapi = re.match(r"(uapi)/([\w\d_\+\.\-]+)(/.*)", rel_path)
Ben Cheng8bea2b62013-10-16 15:28:56 -0700112 if m_uapi:
Christopher Ferrisd12c3322015-09-15 14:13:17 -0700113 dst_path = rel_path
Ben Cheng8bea2b62013-10-16 15:28:56 -0700114 m_uapi_arch = re.match(r"asm-([\w\d_\+\.\-]+)", m_uapi.group(2))
115 if m_uapi_arch and m_uapi_arch.group(1) != 'generic':
Christopher Ferrisd12c3322015-09-15 14:13:17 -0700116 arch = m_uapi_arch.group(1)
117 statics = statics.union(kernel_known_statics.get(arch, set()))
Ben Cheng8bea2b62013-10-16 15:28:56 -0700118 # common headers (ie non-asm and non-uapi)
119 else:
Christopher Ferrisd12c3322015-09-15 14:13:17 -0700120 dst_path = os.path.join("common", rel_path)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800121
Christopher Ferrisd12c3322015-09-15 14:13:17 -0700122 dst_path = os.path.join(dst_dir, dst_path)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800123
124 # now, let's parse the file
125 #
Tao Baod7db5942015-01-28 10:07:51 -0800126 parser = cpp.BlockParser()
Christopher Ferrisd12c3322015-09-15 14:13:17 -0700127 blocks = parser.parseFile(full_path)
Tao Baod7db5942015-01-28 10:07:51 -0800128 if not parser.parsed:
Christopher Ferrisd12c3322015-09-15 14:13:17 -0700129 print_error(no_update, "can't parse '%s'%" % full_path)
130 return None, None
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800131
Andrew Hsieh126601d2012-03-23 23:07:36 +0800132 macros = kernel_known_macros.copy()
133 if arch and arch in kernel_default_arch_macros:
134 macros.update(kernel_default_arch_macros[arch])
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800135
Raghu Gandhama864c2c2013-01-16 16:42:47 -0800136 if arch and arch in kernel_arch_token_replacements:
Christopher Ferrisd12c3322015-09-15 14:13:17 -0700137 blocks.replaceTokens(kernel_arch_token_replacements[arch])
Raghu Gandhama864c2c2013-01-16 16:42:47 -0800138
Christopher Ferrisd12c3322015-09-15 14:13:17 -0700139 blocks.optimizeMacros(macros)
David 'Digit' Turnerfc269312010-10-11 22:11:06 +0200140 blocks.optimizeIf01()
Christopher Ferrisd12c3322015-09-15 14:13:17 -0700141 blocks.removeVarsAndFuncs(statics)
142 blocks.replaceTokens(kernel_token_replacements)
143 blocks.removeMacroDefines(kernel_ignored_macros)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800144
145 out = StringOutput()
Christopher Ferrisd12c3322015-09-15 14:13:17 -0700146 out.write(kernel_disclaimer)
David 'Digit' Turnerfc269312010-10-11 22:11:06 +0200147 blocks.writeWithWarning(out, kernel_warning, 4)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800148 return dst_path, out.get()
149
150
151if __name__ == "__main__":
152
153 def usage():
154 print """\
155 usage: %s [options] <header_path>
156
157 options:
158 -v enable verbose mode
159
160 -u enabled update mode
161 this will try to update the corresponding 'clean header'
162 if the content has changed. with this, you can pass more
163 than one file on the command-line
164
David 'Digit' Turnerfc269312010-10-11 22:11:06 +0200165 -k<path> specify path of original kernel headers
166 -d<path> specify path of cleaned kernel headers
167
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800168 <header_path> must be in a subdirectory of 'original'
169 """ % os.path.basename(sys.argv[0])
170 sys.exit(1)
171
172 try:
Christopher Ferrisd12c3322015-09-15 14:13:17 -0700173 optlist, args = getopt.getopt(sys.argv[1:], 'uvk:d:')
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800174 except:
175 # unrecognized option
Christopher Ferrisd12c3322015-09-15 14:13:17 -0700176 sys.stderr.write("error: unrecognized option\n")
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800177 usage()
178
Christopher Ferrisd12c3322015-09-15 14:13:17 -0700179 no_update = True
180 dst_dir = get_kernel_dir()
181 src_dir = get_kernel_headers_original_dir()
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800182 for opt, arg in optlist:
183 if opt == '-u':
Christopher Ferrisd12c3322015-09-15 14:13:17 -0700184 no_update = False
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800185 elif opt == '-v':
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700186 logging.basicConfig(level=logging.DEBUG)
Dima Zavin4c4a9632009-08-05 17:55:30 -0700187 elif opt == '-k':
Christopher Ferrisd12c3322015-09-15 14:13:17 -0700188 src_dir = arg
David 'Digit' Turnerfc269312010-10-11 22:11:06 +0200189 elif opt == '-d':
Christopher Ferrisd12c3322015-09-15 14:13:17 -0700190 dst_dir = arg
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800191
192 if len(args) == 0:
193 usage()
194
Christopher Ferrisd12c3322015-09-15 14:13:17 -0700195 if no_update:
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800196 for path in args:
Christopher Ferrisd12c3322015-09-15 14:13:17 -0700197 dst_path, newdata = cleanupFile(dst_dir, src_dir, path)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800198 print newdata
199
200 sys.exit(0)
201
202 # now let's update our files.
203
204 b = BatchFileUpdater()
205
206 for path in args:
Christopher Ferrisd12c3322015-09-15 14:13:17 -0700207 dst_path, newdata = cleanupFile(dst_dir, src_dir, path, no_update)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800208 if not dst_path:
209 continue
210
Christopher Ferrisd12c3322015-09-15 14:13:17 -0700211 b.readFile(dst_path)
212 r = b.editFile(dst_path, newdata)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800213 if r == 0:
214 r = "unchanged"
215 elif r == 1:
216 r = "edited"
217 else:
218 r = "added"
219
Christopher Ferrisd12c3322015-09-15 14:13:17 -0700220 print "cleaning: %-*s -> %-*s (%s)" % (35, path, 35, dst_path, r)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800221
222
David 'Digit' Turnerfc269312010-10-11 22:11:06 +0200223 b.updateGitFiles()
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800224
225 sys.exit(0)