blob: 0e0ed7658e8866bd746ef3e3b23e1179c38c7f48 [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
76noUpdate = 1
77
Elliott Hughesfddbafd2014-05-01 10:17:27 -070078def cleanupFile(path, original_path):
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080079 """reads an original header and perform the cleanup operation on it
80 this functions returns the destination path and the clean header
81 as a single string"""
82 # check the header path
David 'Digit' Turnerfc269312010-10-11 22:11:06 +020083 src_path = path
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080084
85 if not os.path.exists(src_path):
86 if noUpdate:
87 panic( "file does not exist: '%s'\n" % path )
88 sys.stderr.write( "warning: file does not exit: %s\n" % path )
89 return None, None
90
91 if not os.path.isfile(src_path):
92 if noUpdate:
93 panic( "path is not a file: '%s'\n" % path )
94 sys.stderr.write( "warning: not a file: %s\n" % path )
95 return None, None
96
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080097 if os.path.commonprefix( [ src_path, original_path ] ) != original_path:
98 if noUpdate:
99 panic( "file is not in 'original' directory: %s\n" % path );
100 sys.stderr.write( "warning: file not in 'original' ignored: %s\n" % path )
101 return None, None
102
103 src_path = src_path[len(original_path):]
104 if len(src_path) > 0 and src_path[0] == '/':
105 src_path = src_path[1:]
106
107 if len(src_path) == 0:
Glenn Kastenc61f9902011-12-19 11:27:50 -0800108 panic( "oops, internal error, can't extract correct relative path\n" )
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800109
110 # convert into destination path, extracting architecture if needed
111 # and the corresponding list of known static functions
112 #
113 arch = None
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800114 statics = kernel_known_generic_statics
Ben Cheng8bea2b62013-10-16 15:28:56 -0700115 m = re.match(r"asm-([\w\d_\+\.\-]+)(/.*)", src_path)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800116 if m and m.group(1) != 'generic':
117 dst_path = "arch-%s/asm/%s" % m.groups()
118 arch = m.group(1)
119 statics = statics.union( kernel_known_statics.get( arch, set() ) )
120 else:
Ben Cheng8bea2b62013-10-16 15:28:56 -0700121 # process headers under the uapi directory
122 # note the "asm" level has been explicitly added in the original
123 # kernel header tree for architectural-dependent uapi headers
124 m_uapi = re.match(r"(uapi)/([\w\d_\+\.\-]+)(/.*)", src_path)
125 if m_uapi:
126 dst_path = src_path
127 m_uapi_arch = re.match(r"asm-([\w\d_\+\.\-]+)", m_uapi.group(2))
128 if m_uapi_arch and m_uapi_arch.group(1) != 'generic':
129 arch = m_uapi_arch.group(1)
130 statics = statics.union( kernel_known_statics.get( arch, set() ) )
131 # common headers (ie non-asm and non-uapi)
132 else:
133 dst_path = "common/" + src_path
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800134
David 'Digit' Turnerfc269312010-10-11 22:11:06 +0200135 dst_path = os.path.normpath( kernel_cleaned_path + "/" + dst_path )
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800136
137 # now, let's parse the file
138 #
Tao Baod7db5942015-01-28 10:07:51 -0800139 parser = cpp.BlockParser()
140 blocks = parser.parseFile(path)
141 if not parser.parsed:
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800142 sys.stderr.write( "error: can't parse '%s'" % path )
143 sys.exit(1)
144
Andrew Hsieh126601d2012-03-23 23:07:36 +0800145 macros = kernel_known_macros.copy()
146 if arch and arch in kernel_default_arch_macros:
147 macros.update(kernel_default_arch_macros[arch])
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800148
Raghu Gandhama864c2c2013-01-16 16:42:47 -0800149 if arch and arch in kernel_arch_token_replacements:
150 blocks.replaceTokens( kernel_arch_token_replacements[arch] )
151
Andrew Hsieh126601d2012-03-23 23:07:36 +0800152 blocks.optimizeMacros( macros )
David 'Digit' Turnerfc269312010-10-11 22:11:06 +0200153 blocks.optimizeIf01()
154 blocks.removeVarsAndFuncs( statics )
155 blocks.replaceTokens( kernel_token_replacements )
David 'Digit' Turnerfc269312010-10-11 22:11:06 +0200156 blocks.removeMacroDefines( kernel_ignored_macros )
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800157
158 out = StringOutput()
David 'Digit' Turnerfc269312010-10-11 22:11:06 +0200159 out.write( kernel_disclaimer )
160 blocks.writeWithWarning(out, kernel_warning, 4)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800161 return dst_path, out.get()
162
163
164if __name__ == "__main__":
165
166 def usage():
167 print """\
168 usage: %s [options] <header_path>
169
170 options:
171 -v enable verbose mode
172
173 -u enabled update mode
174 this will try to update the corresponding 'clean header'
175 if the content has changed. with this, you can pass more
176 than one file on the command-line
177
David 'Digit' Turnerfc269312010-10-11 22:11:06 +0200178 -k<path> specify path of original kernel headers
179 -d<path> specify path of cleaned kernel headers
180
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800181 <header_path> must be in a subdirectory of 'original'
182 """ % os.path.basename(sys.argv[0])
183 sys.exit(1)
184
185 try:
David 'Digit' Turnerfc269312010-10-11 22:11:06 +0200186 optlist, args = getopt.getopt( sys.argv[1:], 'uvk:d:' )
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800187 except:
188 # unrecognized option
189 sys.stderr.write( "error: unrecognized option\n" )
190 usage()
191
192 for opt, arg in optlist:
193 if opt == '-u':
194 noUpdate = 0
195 elif opt == '-v':
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700196 logging.basicConfig(level=logging.DEBUG)
Dima Zavin4c4a9632009-08-05 17:55:30 -0700197 elif opt == '-k':
198 kernel_original_path = arg
David 'Digit' Turnerfc269312010-10-11 22:11:06 +0200199 elif opt == '-d':
200 kernel_cleaned_path = arg
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800201
202 if len(args) == 0:
203 usage()
204
205 if noUpdate:
206 for path in args:
Frank Maker7b6795d2011-05-25 11:07:04 -0700207 dst_path, newdata = cleanupFile(path,kernel_original_path)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800208 print newdata
209
210 sys.exit(0)
211
212 # now let's update our files.
213
214 b = BatchFileUpdater()
215
216 for path in args:
Frank Maker7b6795d2011-05-25 11:07:04 -0700217 dst_path, newdata = cleanupFile(path,kernel_original_path)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800218 if not dst_path:
219 continue
220
221 b.readFile( dst_path )
222 r = b.editFile( dst_path, newdata )
223 if r == 0:
224 r = "unchanged"
225 elif r == 1:
226 r = "edited"
227 else:
228 r = "added"
229
230 print "cleaning: %-*s -> %-*s (%s)" % ( 35, path, 35, dst_path, r )
231
232
David 'Digit' Turnerfc269312010-10-11 22:11:06 +0200233 b.updateGitFiles()
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800234
235 sys.exit(0)