mobile/android/base/jni-generator.py

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 # This Source Code Form is subject to the terms of the Mozilla Public
     2 # License, v. 2.0. If a copy of the MPL was not distributed with this
     3 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
     5 import argparse
     6 import re
     8 STUB_TEMPLATE = '''
     9 typedef %(returnType)s (*%(functionName)s_t)(%(paramTypes)s);
    10 static %(functionName)s_t f_%(functionName)s;
    11 extern "C" NS_EXPORT %(returnType)s JNICALL
    12 %(functionName)s(%(parameterList)s) {
    13     if (!f_%(functionName)s) {
    14         arg0->ThrowNew(arg0->FindClass("java/lang/UnsupportedOperationException"),
    15                        "JNI Function called before it was loaded");
    16         return %(returnValue)s;
    17     }
    18     %(returnKeyword)s f_%(functionName)s(%(arguments)s);
    19 }
    20 '''
    21 BINDING_TEMPLATE = '  xul_dlsym("%(functionName)s", &f_%(functionName)s);\n'
    24 class Generator:
    25     """
    26     Class to convert a javah-produced JNI stub file into stubs/bindings files
    27     for inclusion into mozglue.
    28     """
    29     def __init__(self, outputfile):
    30         self.outputfile = outputfile
    32     def write(self, guard, stuff):
    33         self.outputfile.write('#ifdef %s\n' % guard)
    34         self.outputfile.write(stuff)
    35         self.outputfile.write('#endif\n\n')
    37     def process(self, inputfile):
    38         self.outputfile.write('/* WARNING - This file is autogenerated by '
    39                               + 'mobile/android/base/jni-generator.py. '
    40                               + 'Do not edit manually! */\n')
    42         # this matches lines such as:
    43         # JNIEXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_onResume
    44         # and extracts the return type and the function name
    45         nameRegex = re.compile('''JNIEXPORT \s+
    46                                   (?P<returnType>\S+) \s+
    47                                   JNICALL \s+
    48                                   (?P<functionName>\S+)''', re.VERBOSE)
    50         # this matches lines such as:
    51         #   (JNIEnv *, jclass);
    52         # and extracts everything within the parens; this will be split
    53         # on commas to get the argument types.
    54         paramsRegex = re.compile('\((.*)\);')
    56         for line in inputfile:
    57             line = line.strip()
    59             match = re.match(nameRegex, line)
    60             if match:
    61                 returnType = match.group('returnType')
    62                 functionName = match.group('functionName')
    64             match = re.match(paramsRegex, line)
    65             if match:
    66                 paramTypes = re.split('\s*,\s*', match.group(1))
    67                 paramNames = ['arg%d' % i for i in range(0, len(paramTypes))]
    68                 if returnType == 'void':
    69                     returnValue = ''
    70                 elif returnType in ('jobject', 'jstring'):
    71                     returnValue = 'nullptr'
    72                 elif returnType in ('jint', 'jfloat', 'jdouble', 'jlong'):
    73                     returnValue = '0'
    74                 elif returnType == 'jboolean':
    75                     returnValue = 'false'
    76                 else:
    77                     raise Exception(('Unsupported JNI return type %s found; '
    78                                      + 'please update mobile/android/base/'
    79                                      + 'jni-generator.py to handle this case!')
    80                                     % returnType)
    82                 self.write('JNI_STUBS', STUB_TEMPLATE % {
    83                     'returnType': returnType,
    84                     'functionName': functionName,
    85                     'paramTypes': ', '.join(paramTypes),
    86                     'parameterList': ', '.join('%s %s' % param
    87                                      for param in zip(paramTypes, paramNames)),
    88                     'arguments': ', '.join(paramNames),
    89                     'returnValue': returnValue,
    90                     'returnKeyword': 'return' if returnType != 'void' else ''})
    91                 self.write('JNI_BINDINGS', BINDING_TEMPLATE % {
    92                     'functionName': functionName})
    95 def main():
    96     parser = argparse.ArgumentParser(
    97         description='Generate mozglue bindings for JNI functions.')
    98     parser.add_argument('inputfile', type=argparse.FileType('r'))
    99     parser.add_argument('outputfile', type=argparse.FileType('w'))
   100     args = parser.parse_args()
   101     gen = Generator(args.outputfile)
   102     try:
   103         gen.process(args.inputfile)
   104     finally:
   105         args.outputfile.close()
   106         args.inputfile.close()
   108 if __name__ == '__main__':
   109     main()

mercurial