blob: 07766d3239c1b2e2d90be07ffc4c072453f553b9 [file] [log] [blame]
Elliott Hughes6b586e72021-04-15 13:39:08 -07001#!/usr/bin/env python3
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
Elliott Hughes180edef2023-11-02 00:08:05 +000072import sys, cpp, kernel, glob, os, re, getopt, textwrap
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080073from 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)
Daniel Mentz6d6b4ce2019-04-04 11:51:29 -070089 return None
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080090
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)
Daniel Mentz6d6b4ce2019-04-04 11:51:29 -070093 return None
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080094
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
Christopher Ferris15d3fef2017-02-24 12:26:48 -080097 m = re.search(r"(^|/)asm-([\w\d_\+\.\-]+)/.*", rel_path)
98 if m and m.group(2) != 'generic':
99 arch = m.group(2)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800100
Christopher Ferris15d3fef2017-02-24 12:26:48 -0800101 # Now, let's parse the file.
Tao Baod7db5942015-01-28 10:07:51 -0800102 parser = cpp.BlockParser()
Christopher Ferris15d3fef2017-02-24 12:26:48 -0800103 blocks = parser.parseFile(src_file)
Tao Baod7db5942015-01-28 10:07:51 -0800104 if not parser.parsed:
Christopher Ferris15d3fef2017-02-24 12:26:48 -0800105 print_error(no_update, "Can't parse '%s'" % src_file)
106 return None
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800107
Andrew Hsieh126601d2012-03-23 23:07:36 +0800108 macros = kernel_known_macros.copy()
109 if arch and arch in kernel_default_arch_macros:
110 macros.update(kernel_default_arch_macros[arch])
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800111
Christopher Ferrisbb9fcb42020-04-06 11:38:04 -0700112 blocks.removeStructs(kernel_structs_to_remove)
Christopher Ferrisd12c3322015-09-15 14:13:17 -0700113 blocks.optimizeMacros(macros)
David 'Digit' Turnerfc269312010-10-11 22:11:06 +0200114 blocks.optimizeIf01()
Elliott Hughes64f355f2017-08-30 16:10:24 -0700115 blocks.removeVarsAndFuncs(kernel_known_generic_statics)
Christopher Ferrisd12c3322015-09-15 14:13:17 -0700116 blocks.replaceTokens(kernel_token_replacements)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800117
118 out = StringOutput()
Elliott Hughes180edef2023-11-02 00:08:05 +0000119 out.write(textwrap.dedent("""\
120 /*
121 * This file is auto-generated. Modifications will be lost.
122 *
123 * See https://android.googlesource.com/platform/bionic/+/master/libc/kernel/
124 * for more information.
125 */
126 """))
Elliott Hughes96c1db72017-05-25 13:48:01 -0700127 blocks.write(out)
Christopher Ferris15d3fef2017-02-24 12:26:48 -0800128 return out.get()
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800129
130
131if __name__ == "__main__":
132
133 def usage():
Christopher Ferrisac7ec112021-04-19 13:50:16 -0700134 print("""\
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800135 usage: %s [options] <header_path>
136
137 options:
138 -v enable verbose mode
139
140 -u enabled update mode
141 this will try to update the corresponding 'clean header'
142 if the content has changed. with this, you can pass more
143 than one file on the command-line
144
David 'Digit' Turnerfc269312010-10-11 22:11:06 +0200145 -k<path> specify path of original kernel headers
146 -d<path> specify path of cleaned kernel headers
147
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800148 <header_path> must be in a subdirectory of 'original'
Christopher Ferrisac7ec112021-04-19 13:50:16 -0700149 """ % os.path.basename(sys.argv[0]))
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800150 sys.exit(1)
151
152 try:
Christopher Ferrisd12c3322015-09-15 14:13:17 -0700153 optlist, args = getopt.getopt(sys.argv[1:], 'uvk:d:')
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800154 except:
155 # unrecognized option
Christopher Ferrisd12c3322015-09-15 14:13:17 -0700156 sys.stderr.write("error: unrecognized option\n")
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800157 usage()
158
Christopher Ferrisd12c3322015-09-15 14:13:17 -0700159 no_update = True
Daniel Mentzd12d6f62019-04-15 15:19:31 -0700160 dst_dir = None
161 src_dir = None
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800162 for opt, arg in optlist:
163 if opt == '-u':
Christopher Ferrisd12c3322015-09-15 14:13:17 -0700164 no_update = False
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800165 elif opt == '-v':
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700166 logging.basicConfig(level=logging.DEBUG)
Dima Zavin4c4a9632009-08-05 17:55:30 -0700167 elif opt == '-k':
Christopher Ferrisd12c3322015-09-15 14:13:17 -0700168 src_dir = arg
David 'Digit' Turnerfc269312010-10-11 22:11:06 +0200169 elif opt == '-d':
Christopher Ferrisd12c3322015-09-15 14:13:17 -0700170 dst_dir = arg
Daniel Mentzd12d6f62019-04-15 15:19:31 -0700171 # get_kernel_dir() and get_kernel_headers_original_dir() require the current
172 # working directory to be a direct or indirect subdirectory of
173 # ANDROID_BUILD_TOP. Otherwise, these functions print an error message and
174 # exit. Let's allow the user to run this program from an unrelated
175 # directory, if they specify src_dir and dst_dir on the command line.
176 if dst_dir is None:
177 dst_dir = get_kernel_dir()
178 if src_dir is None:
179 src_dir = get_kernel_headers_original_dir()
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800180
181 if len(args) == 0:
182 usage()
183
Christopher Ferrisd12c3322015-09-15 14:13:17 -0700184 if no_update:
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800185 for path in args:
Christopher Ferris15d3fef2017-02-24 12:26:48 -0800186 dst_file = os.path.join(dst_dir, path)
187 src_file = os.path.join(src_dir, path)
188 new_data = cleanupFile(dst_file, src_file, path)
Daniel Mentzbb4cf7b2019-03-28 18:12:30 -0700189 # Use sys.stdout.write instead of a simple print statement to avoid
190 # sending an extra new line character to stdout. Running this
191 # program in non-update mode and redirecting stdout to a file should
192 # yield the same result as using update mode, where new_data is
193 # written directly to a file.
194 sys.stdout.write(new_data)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800195
196 sys.exit(0)
197
Christopher Ferris15d3fef2017-02-24 12:26:48 -0800198 # Now let's update our files.
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800199
200 b = BatchFileUpdater()
201
202 for path in args:
Christopher Ferris15d3fef2017-02-24 12:26:48 -0800203 dst_file = os.path.join(dst_dir, path)
204 src_file = os.path.join(src_dir, path)
205 new_data = cleanupFile(dst_file, src_file, path, no_update)
206 if not new_data:
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800207 continue
208
Daniel Mentz316f4a42019-03-28 18:32:29 -0700209 b.readFile(dst_file)
210 r = b.editFile(dst_file, new_data)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800211 if r == 0:
212 r = "unchanged"
213 elif r == 1:
214 r = "edited"
215 else:
216 r = "added"
217
Christopher Ferrisac7ec112021-04-19 13:50:16 -0700218 print("cleaning: %-*s -> %-*s (%s)" % (35, path, 35, path, r))
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800219
Christopher Ferrisac7ec112021-04-19 13:50:16 -0700220 b.updateFiles()
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800221
222 sys.exit(0)