| Index: util/mach/mig.py
|
| diff --git a/util/mach/mig.py b/util/mach/mig.py
|
| new file mode 100755
|
| index 0000000000000000000000000000000000000000..2d248854d59ce5f171e6f69262bd4871631bc330
|
| --- /dev/null
|
| +++ b/util/mach/mig.py
|
| @@ -0,0 +1,123 @@
|
| +#!/usr/bin/env python
|
| +# coding: utf-8
|
| +
|
| +# Copyright 2014 The Crashpad Authors. All rights reserved.
|
| +#
|
| +# Licensed under the Apache License, Version 2.0 (the "License");
|
| +# you may not use this file except in compliance with the License.
|
| +# You may obtain a copy of the License at
|
| +#
|
| +# http://www.apache.org/licenses/LICENSE-2.0
|
| +#
|
| +# Unless required by applicable law or agreed to in writing, software
|
| +# distributed under the License is distributed on an "AS IS" BASIS,
|
| +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| +# See the License for the specific language governing permissions and
|
| +# limitations under the License.
|
| +
|
| +import re
|
| +import subprocess
|
| +import sys
|
| +
|
| +def FixUserImplementation(implementation):
|
| + """Rewrites a MIG-generated user implementation (.c) file.
|
| +
|
| + Rewrites the file at |implementation| by adding “__attribute__((unused))” to
|
| + the definition of any structure typedefed as “__Reply” by searching for the
|
| + pattern unique to those structure definitions. These structures are in fact
|
| + unused in the user implementation file, and this will trigger a
|
| + -Wunused-local-typedefs warning in gcc unless removed or marked with the
|
| + “unused” attribute.
|
| + """
|
| +
|
| + file = open(implementation, 'r+')
|
| + contents = file.read()
|
| +
|
| + pattern = re.compile('^(\t} __Reply);$', re.MULTILINE)
|
| + contents = pattern.sub(r'\1 __attribute__((unused));', contents)
|
| +
|
| + file.seek(0)
|
| + file.truncate()
|
| + file.write(contents)
|
| + file.close()
|
| +
|
| +def FixServerImplementation(implementation):
|
| + """Rewrites a MIG-generated server implementation (.c) file.
|
| +
|
| + Rewrites the file at |implementation| by replacing “mig_internal” with
|
| + “mig_external” on functions that begin with “__MIG_check__”. This makes these
|
| + functions available to other callers outside this file from a linkage
|
| + perspective. It then returns, as a list of lines, declarations that can be
|
| + added to a header file, so that other files that include that header file will
|
| + have access to these declarations from a compilation perspective.
|
| + """
|
| +
|
| + file = open(implementation, 'r+')
|
| + contents = file.read()
|
| +
|
| + # Find interesting declarations.
|
| + declaration_pattern = \
|
| + re.compile('^mig_internal (kern_return_t __MIG_check__.*)$',
|
| + re.MULTILINE)
|
| + declarations = declaration_pattern.findall(contents)
|
| +
|
| + # Remove “__attribute__((__unused__))” from the declarations, and call them
|
| + # “mig_external” or “extern” depending on whether “mig_external” is defined.
|
| + attribute_pattern = re.compile(r'__attribute__\(\(__unused__\)\) ')
|
| + declarations = ['#ifdef mig_external\nmig_external\n#else\nextern\n#endif\n' +
|
| + attribute_pattern.sub('', x) +
|
| + ';\n' for x in declarations]
|
| +
|
| + # Rewrite the declarations in this file as “mig_external”.
|
| + contents = declaration_pattern.sub(r'mig_external \1', contents);
|
| +
|
| + file.seek(0)
|
| + file.truncate()
|
| + file.write(contents)
|
| + file.close()
|
| + return declarations
|
| +
|
| +def FixHeader(header, declarations=[]):
|
| + """Rewrites a MIG-generated header (.h) file.
|
| +
|
| + Rewrites the file at |header| by placing it inside an “extern "C"” block, so
|
| + that it declares things properly when included by a C++ compilation unit.
|
| + |declarations| can be a list of additional declarations to place inside the
|
| + “extern "C"” block after the original contents of |header|.
|
| + """
|
| +
|
| + file = open(header, 'r+')
|
| + contents = file.read()
|
| + declarations_text = ''.join(declarations)
|
| + contents = '''\
|
| +#ifdef __cplusplus
|
| +extern "C" {
|
| +#endif
|
| +
|
| +%s
|
| +%s
|
| +#ifdef __cplusplus
|
| +}
|
| +#endif
|
| +''' % (contents, declarations_text)
|
| + file.seek(0)
|
| + file.truncate()
|
| + file.write(contents)
|
| + file.close()
|
| +
|
| +def main(args):
|
| + assert len(args) == 5
|
| + (defs_file, user_c, server_c, user_h, server_h) = args
|
| + subprocess.check_call(['mig',
|
| + '-user', user_c,
|
| + '-server', server_c,
|
| + '-header', user_h,
|
| + '-sheader', server_h,
|
| + defs_file])
|
| + FixUserImplementation(user_c)
|
| + server_declarations = FixServerImplementation(server_c)
|
| + FixHeader(user_h)
|
| + FixHeader(server_h, server_declarations)
|
| +
|
| +if __name__ == '__main__':
|
| + sys.exit(main(sys.argv[1:]))
|
|
|