blob: d63ea03cfc40b879c1ceb3c176cb60b9dfffca92 [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
Christopher Ferris15d3fef2017-02-24 12:26:48 -080082def cleanupFile(dst_file, src_file, 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"""
Christopher Ferris15d3fef2017-02-24 12:26:48 -080086 # Check the header path
87 if not os.path.exists(src_file):
88 print_error(no_update, "'%s' does not exist\n" % src_file)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080089 return None, None
90
Christopher Ferris15d3fef2017-02-24 12:26:48 -080091 if not os.path.isfile(src_file):
92 print_error(no_update, "'%s' is not a file\n" % src_file)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080093 return None, None
94
Christopher Ferris15d3fef2017-02-24 12:26:48 -080095 # Extract the architecture if found.
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080096 arch = None
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080097 statics = kernel_known_generic_statics
Christopher Ferris15d3fef2017-02-24 12:26:48 -080098 m = re.search(r"(^|/)asm-([\w\d_\+\.\-]+)/.*", rel_path)
99 if m and m.group(2) != 'generic':
100 arch = m.group(2)
101 statics = statics.union(kernel_known_statics.get(arch, set()))
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800102
Christopher Ferris15d3fef2017-02-24 12:26:48 -0800103 # Now, let's parse the file.
Tao Baod7db5942015-01-28 10:07:51 -0800104 parser = cpp.BlockParser()
Christopher Ferris15d3fef2017-02-24 12:26:48 -0800105 blocks = parser.parseFile(src_file)
Tao Baod7db5942015-01-28 10:07:51 -0800106 if not parser.parsed:
Christopher Ferris15d3fef2017-02-24 12:26:48 -0800107 print_error(no_update, "Can't parse '%s'" % src_file)
108 return None
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800109
Andrew Hsieh126601d2012-03-23 23:07:36 +0800110 macros = kernel_known_macros.copy()
111 if arch and arch in kernel_default_arch_macros:
112 macros.update(kernel_default_arch_macros[arch])
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800113
Raghu Gandhama864c2c2013-01-16 16:42:47 -0800114 if arch and arch in kernel_arch_token_replacements:
Christopher Ferrisd12c3322015-09-15 14:13:17 -0700115 blocks.replaceTokens(kernel_arch_token_replacements[arch])
Raghu Gandhama864c2c2013-01-16 16:42:47 -0800116
Christopher Ferrisd12c3322015-09-15 14:13:17 -0700117 blocks.optimizeMacros(macros)
David 'Digit' Turnerfc269312010-10-11 22:11:06 +0200118 blocks.optimizeIf01()
Christopher Ferrisd12c3322015-09-15 14:13:17 -0700119 blocks.removeVarsAndFuncs(statics)
120 blocks.replaceTokens(kernel_token_replacements)
121 blocks.removeMacroDefines(kernel_ignored_macros)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800122
123 out = StringOutput()
Christopher Ferrisd12c3322015-09-15 14:13:17 -0700124 out.write(kernel_disclaimer)
Elliott Hughes96c1db72017-05-25 13:48:01 -0700125 blocks.write(out)
Christopher Ferris15d3fef2017-02-24 12:26:48 -0800126 return out.get()
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800127
128
129if __name__ == "__main__":
130
131 def usage():
132 print """\
133 usage: %s [options] <header_path>
134
135 options:
136 -v enable verbose mode
137
138 -u enabled update mode
139 this will try to update the corresponding 'clean header'
140 if the content has changed. with this, you can pass more
141 than one file on the command-line
142
David 'Digit' Turnerfc269312010-10-11 22:11:06 +0200143 -k<path> specify path of original kernel headers
144 -d<path> specify path of cleaned kernel headers
145
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800146 <header_path> must be in a subdirectory of 'original'
147 """ % os.path.basename(sys.argv[0])
148 sys.exit(1)
149
150 try:
Christopher Ferrisd12c3322015-09-15 14:13:17 -0700151 optlist, args = getopt.getopt(sys.argv[1:], 'uvk:d:')
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800152 except:
153 # unrecognized option
Christopher Ferrisd12c3322015-09-15 14:13:17 -0700154 sys.stderr.write("error: unrecognized option\n")
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800155 usage()
156
Christopher Ferrisd12c3322015-09-15 14:13:17 -0700157 no_update = True
158 dst_dir = get_kernel_dir()
159 src_dir = get_kernel_headers_original_dir()
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800160 for opt, arg in optlist:
161 if opt == '-u':
Christopher Ferrisd12c3322015-09-15 14:13:17 -0700162 no_update = False
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800163 elif opt == '-v':
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700164 logging.basicConfig(level=logging.DEBUG)
Dima Zavin4c4a9632009-08-05 17:55:30 -0700165 elif opt == '-k':
Christopher Ferrisd12c3322015-09-15 14:13:17 -0700166 src_dir = arg
David 'Digit' Turnerfc269312010-10-11 22:11:06 +0200167 elif opt == '-d':
Christopher Ferrisd12c3322015-09-15 14:13:17 -0700168 dst_dir = arg
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800169
170 if len(args) == 0:
171 usage()
172
Christopher Ferrisd12c3322015-09-15 14:13:17 -0700173 if no_update:
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800174 for path in args:
Christopher Ferris15d3fef2017-02-24 12:26:48 -0800175 dst_file = os.path.join(dst_dir, path)
176 src_file = os.path.join(src_dir, path)
177 new_data = cleanupFile(dst_file, src_file, path)
178 print new_data
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800179
180 sys.exit(0)
181
Christopher Ferris15d3fef2017-02-24 12:26:48 -0800182 # Now let's update our files.
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800183
184 b = BatchFileUpdater()
185
186 for path in args:
Christopher Ferris15d3fef2017-02-24 12:26:48 -0800187 dst_file = os.path.join(dst_dir, path)
188 src_file = os.path.join(src_dir, path)
189 new_data = cleanupFile(dst_file, src_file, path, no_update)
190 if not new_data:
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800191 continue
192
Christopher Ferris15d3fef2017-02-24 12:26:48 -0800193 b.readFile(path)
194 r = b.editFile(path, new_data)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800195 if r == 0:
196 r = "unchanged"
197 elif r == 1:
198 r = "edited"
199 else:
200 r = "added"
201
Christopher Ferris15d3fef2017-02-24 12:26:48 -0800202 print "cleaning: %-*s -> %-*s (%s)" % (35, path, 35, path, r)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800203
204
David 'Digit' Turnerfc269312010-10-11 22:11:06 +0200205 b.updateGitFiles()
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800206
207 sys.exit(0)