2009-03-04 04:28:35 +01:00
|
|
|
#!/usr/bin/env python
|
2014-06-05 20:17:06 +02:00
|
|
|
|
|
|
|
#------------------------------------------------------------------------------
|
|
|
|
# Description of the header clean process
|
|
|
|
#------------------------------------------------------------------------------
|
|
|
|
# Here is the list of actions performed by this script to clean the original
|
|
|
|
# kernel headers.
|
|
|
|
#
|
|
|
|
# 1. Optimize well-known macros (e.g. __KERNEL__, __KERNEL_STRICT_NAMES)
|
|
|
|
#
|
|
|
|
# This pass gets rid of everything that is guarded by a well-known macro
|
|
|
|
# definition. This means that a block like:
|
|
|
|
#
|
|
|
|
# #ifdef __KERNEL__
|
|
|
|
# ....
|
|
|
|
# #endif
|
|
|
|
#
|
|
|
|
# Will be totally omitted from the output. The optimizer is smart enough to
|
|
|
|
# handle all complex C-preprocessor conditional expression appropriately.
|
|
|
|
# This means that, for example:
|
|
|
|
#
|
|
|
|
# #if defined(__KERNEL__) || defined(FOO)
|
|
|
|
# ...
|
|
|
|
# #endif
|
|
|
|
#
|
|
|
|
# Will be transformed into:
|
|
|
|
#
|
|
|
|
# #ifdef FOO
|
|
|
|
# ...
|
|
|
|
# #endif
|
|
|
|
#
|
|
|
|
# See tools/defaults.py for the list of well-known macros used in this pass,
|
|
|
|
# in case you need to update it in the future.
|
|
|
|
#
|
|
|
|
# Note that this also removes any reference to a kernel-specific
|
|
|
|
# configuration macro like CONFIG_FOO from the clean headers.
|
|
|
|
#
|
|
|
|
#
|
|
|
|
# 2. Remove variable and function declarations:
|
|
|
|
#
|
|
|
|
# This pass scans non-directive text and only keeps things that look like a
|
|
|
|
# typedef/struct/union/enum declaration. This allows us to get rid of any
|
|
|
|
# variables or function declarations that should only be used within the
|
|
|
|
# kernel anyway (and which normally *should* be guarded by an #ifdef
|
|
|
|
# __KERNEL__ ... #endif block, if the kernel writers were not so messy).
|
|
|
|
#
|
|
|
|
# There are, however, a few exceptions: it is seldom useful to keep the
|
|
|
|
# definition of some static inline functions performing very simple
|
|
|
|
# operations. A good example is the optimized 32-bit byte-swap function
|
|
|
|
# found in:
|
|
|
|
#
|
|
|
|
# arch-arm/asm/byteorder.h
|
|
|
|
#
|
|
|
|
# The list of exceptions is in tools/defaults.py in case you need to update
|
|
|
|
# it in the future.
|
|
|
|
#
|
|
|
|
# Note that we do *not* remove macro definitions, including these macro that
|
|
|
|
# perform a call to one of these kernel-header functions, or even define other
|
|
|
|
# functions. We consider it safe since userland applications have no business
|
|
|
|
# using them anyway.
|
|
|
|
#
|
|
|
|
#
|
2015-01-28 19:07:51 +01:00
|
|
|
# 3. Add a standard disclaimer:
|
2014-06-05 20:17:06 +02:00
|
|
|
#
|
|
|
|
# The message:
|
|
|
|
#
|
|
|
|
# /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
|
2009-03-04 04:28:35 +01:00
|
|
|
#
|
2014-06-05 20:17:06 +02:00
|
|
|
# Is prepended to each generated header.
|
|
|
|
#------------------------------------------------------------------------------
|
2009-03-04 04:28:35 +01:00
|
|
|
|
|
|
|
import sys, cpp, kernel, glob, os, re, getopt
|
|
|
|
from defaults import *
|
|
|
|
from utils import *
|
|
|
|
|
2015-09-15 23:13:17 +02:00
|
|
|
def print_error(no_update, msg):
|
|
|
|
if no_update:
|
|
|
|
panic(msg)
|
|
|
|
sys.stderr.write("warning: " + msg)
|
2009-03-04 04:28:35 +01:00
|
|
|
|
2015-09-15 23:13:17 +02:00
|
|
|
|
|
|
|
def cleanupFile(dst_dir, src_dir, rel_path, no_update = True):
|
2009-03-04 04:28:35 +01:00
|
|
|
"""reads an original header and perform the cleanup operation on it
|
|
|
|
this functions returns the destination path and the clean header
|
|
|
|
as a single string"""
|
|
|
|
# check the header path
|
2015-09-15 23:13:17 +02:00
|
|
|
full_path = os.path.join(src_dir, rel_path)
|
2009-03-04 04:28:35 +01:00
|
|
|
|
2015-09-15 23:13:17 +02:00
|
|
|
if not os.path.exists(full_path):
|
|
|
|
print_error(no_update, "file does not exist: '%s'\n" % full_path)
|
2009-03-04 04:28:35 +01:00
|
|
|
return None, None
|
|
|
|
|
2015-09-15 23:13:17 +02:00
|
|
|
if not os.path.isfile(full_path):
|
|
|
|
print_error(no_update, "path is not a file: '%s'\n" % full_path)
|
2009-03-04 04:28:35 +01:00
|
|
|
return None, None
|
|
|
|
|
|
|
|
# convert into destination path, extracting architecture if needed
|
|
|
|
# and the corresponding list of known static functions
|
|
|
|
#
|
|
|
|
arch = None
|
|
|
|
statics = kernel_known_generic_statics
|
2015-09-15 23:13:17 +02:00
|
|
|
m = re.match(r"asm-([\w\d_\+\.\-]+)(/.*)", rel_path)
|
2009-03-04 04:28:35 +01:00
|
|
|
if m and m.group(1) != 'generic':
|
|
|
|
dst_path = "arch-%s/asm/%s" % m.groups()
|
2015-09-15 23:13:17 +02:00
|
|
|
arch = m.group(1)
|
|
|
|
statics = statics.union(kernel_known_statics.get(arch, set()))
|
2009-03-04 04:28:35 +01:00
|
|
|
else:
|
2013-10-17 00:28:56 +02:00
|
|
|
# process headers under the uapi directory
|
|
|
|
# note the "asm" level has been explicitly added in the original
|
|
|
|
# kernel header tree for architectural-dependent uapi headers
|
2015-09-15 23:13:17 +02:00
|
|
|
m_uapi = re.match(r"(uapi)/([\w\d_\+\.\-]+)(/.*)", rel_path)
|
2013-10-17 00:28:56 +02:00
|
|
|
if m_uapi:
|
2015-09-15 23:13:17 +02:00
|
|
|
dst_path = rel_path
|
2013-10-17 00:28:56 +02:00
|
|
|
m_uapi_arch = re.match(r"asm-([\w\d_\+\.\-]+)", m_uapi.group(2))
|
|
|
|
if m_uapi_arch and m_uapi_arch.group(1) != 'generic':
|
2015-09-15 23:13:17 +02:00
|
|
|
arch = m_uapi_arch.group(1)
|
|
|
|
statics = statics.union(kernel_known_statics.get(arch, set()))
|
2013-10-17 00:28:56 +02:00
|
|
|
# common headers (ie non-asm and non-uapi)
|
|
|
|
else:
|
2015-09-15 23:13:17 +02:00
|
|
|
dst_path = os.path.join("common", rel_path)
|
2009-03-04 04:28:35 +01:00
|
|
|
|
2015-09-15 23:13:17 +02:00
|
|
|
dst_path = os.path.join(dst_dir, dst_path)
|
2009-03-04 04:28:35 +01:00
|
|
|
|
|
|
|
# now, let's parse the file
|
|
|
|
#
|
2015-01-28 19:07:51 +01:00
|
|
|
parser = cpp.BlockParser()
|
2015-09-15 23:13:17 +02:00
|
|
|
blocks = parser.parseFile(full_path)
|
2015-01-28 19:07:51 +01:00
|
|
|
if not parser.parsed:
|
2015-09-15 23:13:17 +02:00
|
|
|
print_error(no_update, "can't parse '%s'%" % full_path)
|
|
|
|
return None, None
|
2009-03-04 04:28:35 +01:00
|
|
|
|
2012-03-23 16:07:36 +01:00
|
|
|
macros = kernel_known_macros.copy()
|
|
|
|
if arch and arch in kernel_default_arch_macros:
|
|
|
|
macros.update(kernel_default_arch_macros[arch])
|
2009-03-04 04:28:35 +01:00
|
|
|
|
2013-01-17 01:42:47 +01:00
|
|
|
if arch and arch in kernel_arch_token_replacements:
|
2015-09-15 23:13:17 +02:00
|
|
|
blocks.replaceTokens(kernel_arch_token_replacements[arch])
|
2013-01-17 01:42:47 +01:00
|
|
|
|
2015-09-15 23:13:17 +02:00
|
|
|
blocks.optimizeMacros(macros)
|
2010-10-11 22:11:06 +02:00
|
|
|
blocks.optimizeIf01()
|
2015-09-15 23:13:17 +02:00
|
|
|
blocks.removeVarsAndFuncs(statics)
|
|
|
|
blocks.replaceTokens(kernel_token_replacements)
|
|
|
|
blocks.removeMacroDefines(kernel_ignored_macros)
|
2009-03-04 04:28:35 +01:00
|
|
|
|
|
|
|
out = StringOutput()
|
2015-09-15 23:13:17 +02:00
|
|
|
out.write(kernel_disclaimer)
|
2010-10-11 22:11:06 +02:00
|
|
|
blocks.writeWithWarning(out, kernel_warning, 4)
|
2009-03-04 04:28:35 +01:00
|
|
|
return dst_path, out.get()
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
|
|
|
|
def usage():
|
|
|
|
print """\
|
|
|
|
usage: %s [options] <header_path>
|
|
|
|
|
|
|
|
options:
|
|
|
|
-v enable verbose mode
|
|
|
|
|
|
|
|
-u enabled update mode
|
|
|
|
this will try to update the corresponding 'clean header'
|
|
|
|
if the content has changed. with this, you can pass more
|
|
|
|
than one file on the command-line
|
|
|
|
|
2010-10-11 22:11:06 +02:00
|
|
|
-k<path> specify path of original kernel headers
|
|
|
|
-d<path> specify path of cleaned kernel headers
|
|
|
|
|
2009-03-04 04:28:35 +01:00
|
|
|
<header_path> must be in a subdirectory of 'original'
|
|
|
|
""" % os.path.basename(sys.argv[0])
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
try:
|
2015-09-15 23:13:17 +02:00
|
|
|
optlist, args = getopt.getopt(sys.argv[1:], 'uvk:d:')
|
2009-03-04 04:28:35 +01:00
|
|
|
except:
|
|
|
|
# unrecognized option
|
2015-09-15 23:13:17 +02:00
|
|
|
sys.stderr.write("error: unrecognized option\n")
|
2009-03-04 04:28:35 +01:00
|
|
|
usage()
|
|
|
|
|
2015-09-15 23:13:17 +02:00
|
|
|
no_update = True
|
|
|
|
dst_dir = get_kernel_dir()
|
|
|
|
src_dir = get_kernel_headers_original_dir()
|
2009-03-04 04:28:35 +01:00
|
|
|
for opt, arg in optlist:
|
|
|
|
if opt == '-u':
|
2015-09-15 23:13:17 +02:00
|
|
|
no_update = False
|
2009-03-04 04:28:35 +01:00
|
|
|
elif opt == '-v':
|
2014-08-20 20:16:11 +02:00
|
|
|
logging.basicConfig(level=logging.DEBUG)
|
2009-08-06 02:55:30 +02:00
|
|
|
elif opt == '-k':
|
2015-09-15 23:13:17 +02:00
|
|
|
src_dir = arg
|
2010-10-11 22:11:06 +02:00
|
|
|
elif opt == '-d':
|
2015-09-15 23:13:17 +02:00
|
|
|
dst_dir = arg
|
2009-03-04 04:28:35 +01:00
|
|
|
|
|
|
|
if len(args) == 0:
|
|
|
|
usage()
|
|
|
|
|
2015-09-15 23:13:17 +02:00
|
|
|
if no_update:
|
2009-03-04 04:28:35 +01:00
|
|
|
for path in args:
|
2015-09-15 23:13:17 +02:00
|
|
|
dst_path, newdata = cleanupFile(dst_dir, src_dir, path)
|
2009-03-04 04:28:35 +01:00
|
|
|
print newdata
|
|
|
|
|
|
|
|
sys.exit(0)
|
|
|
|
|
|
|
|
# now let's update our files.
|
|
|
|
|
|
|
|
b = BatchFileUpdater()
|
|
|
|
|
|
|
|
for path in args:
|
2015-09-15 23:13:17 +02:00
|
|
|
dst_path, newdata = cleanupFile(dst_dir, src_dir, path, no_update)
|
2009-03-04 04:28:35 +01:00
|
|
|
if not dst_path:
|
|
|
|
continue
|
|
|
|
|
2015-09-15 23:13:17 +02:00
|
|
|
b.readFile(dst_path)
|
|
|
|
r = b.editFile(dst_path, newdata)
|
2009-03-04 04:28:35 +01:00
|
|
|
if r == 0:
|
|
|
|
r = "unchanged"
|
|
|
|
elif r == 1:
|
|
|
|
r = "edited"
|
|
|
|
else:
|
|
|
|
r = "added"
|
|
|
|
|
2015-09-15 23:13:17 +02:00
|
|
|
print "cleaning: %-*s -> %-*s (%s)" % (35, path, 35, dst_path, r)
|
2009-03-04 04:28:35 +01:00
|
|
|
|
|
|
|
|
2010-10-11 22:11:06 +02:00
|
|
|
b.updateGitFiles()
|
2009-03-04 04:28:35 +01:00
|
|
|
|
|
|
|
sys.exit(0)
|