| OLD | NEW |
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 """ Generator for C++ style thunks """ | 6 """ Generator for C++ style thunks """ |
| 7 | 7 |
| 8 import glob | 8 import glob |
| 9 import os | 9 import os |
| 10 import re | 10 import re |
| (...skipping 17 matching lines...) Expand all Loading... |
| 28 self.value = msg | 28 self.value = msg |
| 29 | 29 |
| 30 def __str__(self): | 30 def __str__(self): |
| 31 return repr(self.value) | 31 return repr(self.value) |
| 32 | 32 |
| 33 | 33 |
| 34 class ThunkBodyMetadata(object): | 34 class ThunkBodyMetadata(object): |
| 35 """Metadata about thunk body. Used for selecting which headers to emit.""" | 35 """Metadata about thunk body. Used for selecting which headers to emit.""" |
| 36 def __init__(self): | 36 def __init__(self): |
| 37 self._apis = set() | 37 self._apis = set() |
| 38 self._builtin_includes = set() |
| 38 self._includes = set() | 39 self._includes = set() |
| 39 | 40 |
| 40 def AddApi(self, api): | 41 def AddApi(self, api): |
| 41 self._apis.add(api) | 42 self._apis.add(api) |
| 42 | 43 |
| 43 def Apis(self): | 44 def Apis(self): |
| 44 return self._apis | 45 return self._apis |
| 45 | 46 |
| 46 def AddInclude(self, include): | 47 def AddInclude(self, include): |
| 47 self._includes.add(include) | 48 self._includes.add(include) |
| 48 | 49 |
| 49 def Includes(self): | 50 def Includes(self): |
| 50 return self._includes | 51 return self._includes |
| 51 | 52 |
| 53 def AddBuiltinInclude(self, include): |
| 54 self._builtin_includes.add(include) |
| 55 |
| 56 def BuiltinIncludes(self): |
| 57 return self._builtin_includes |
| 58 |
| 52 | 59 |
| 53 def _GetBaseFileName(filenode): | 60 def _GetBaseFileName(filenode): |
| 54 """Returns the base name for output files, given the filenode. | 61 """Returns the base name for output files, given the filenode. |
| 55 | 62 |
| 56 Examples: | 63 Examples: |
| 57 'dev/ppb_find_dev.h' -> 'ppb_find_dev' | 64 'dev/ppb_find_dev.h' -> 'ppb_find_dev' |
| 58 'trusted/ppb_buffer_trusted.h' -> 'ppb_buffer_trusted' | 65 'trusted/ppb_buffer_trusted.h' -> 'ppb_buffer_trusted' |
| 59 """ | 66 """ |
| 60 path, name = os.path.split(filenode.GetProperty('NAME')) | 67 path, name = os.path.split(filenode.GetProperty('NAME')) |
| 61 name = os.path.splitext(name)[0] | 68 name = os.path.splitext(name)[0] |
| (...skipping 14 matching lines...) Expand all Loading... |
| 76 def _GetThunkFileName(filenode, relpath): | 83 def _GetThunkFileName(filenode, relpath): |
| 77 """Returns the thunk file name.""" | 84 """Returns the thunk file name.""" |
| 78 path = os.path.split(filenode.GetProperty('NAME'))[0] | 85 path = os.path.split(filenode.GetProperty('NAME'))[0] |
| 79 name = _GetBaseFileName(filenode) | 86 name = _GetBaseFileName(filenode) |
| 80 # We don't reattach the path for thunk. | 87 # We don't reattach the path for thunk. |
| 81 if relpath: name = os.path.join(relpath, name) | 88 if relpath: name = os.path.join(relpath, name) |
| 82 name = '%s%s' % (name, '_thunk.cc') | 89 name = '%s%s' % (name, '_thunk.cc') |
| 83 return name | 90 return name |
| 84 | 91 |
| 85 | 92 |
| 93 def _AddApiHeader(filenode, meta): |
| 94 """Adds an API header for the given file to the ThunkBodyMetadata.""" |
| 95 # The API header matches the file name, not the interface name. |
| 96 api_basename = _GetBaseFileName(filenode) |
| 97 if api_basename.endswith('_dev'): |
| 98 api_basename = api_basename[:-len('_dev')] |
| 99 if api_basename.endswith('_trusted'): |
| 100 api_basename = api_basename[:-len('_trusted')] |
| 101 meta.AddApi(api_basename + '_api') |
| 102 |
| 103 |
| 86 def _MakeEnterLine(filenode, interface, arg, handle_errors, callback, meta): | 104 def _MakeEnterLine(filenode, interface, arg, handle_errors, callback, meta): |
| 87 """Returns an EnterInstance/EnterResource string for a function.""" | 105 """Returns an EnterInstance/EnterResource string for a function.""" |
| 106 api_name = interface.GetName() |
| 107 if api_name.endswith('Trusted'): |
| 108 api_name = api_name[:-len('Trusted')] |
| 109 if api_name.endswith('_Dev'): |
| 110 api_name = api_name[:-len('_Dev')] |
| 111 api_name += '_API' |
| 112 |
| 88 if arg[0] == 'PP_Instance': | 113 if arg[0] == 'PP_Instance': |
| 89 if callback is None: | 114 if callback is None: |
| 90 return 'EnterInstance enter(%s);' % arg[1] | 115 arg_string = arg[1] |
| 91 else: | 116 else: |
| 92 return 'EnterInstance enter(%s, %s);' % (arg[1], callback) | 117 arg_string = '%s, %s' % (arg[1], callback) |
| 118 if interface.GetProperty('singleton_resource'): |
| 119 _AddApiHeader(filenode, meta) |
| 120 return 'EnterInstanceAPI<%s> enter(%s);' % (api_name, arg_string) |
| 121 else: |
| 122 return 'EnterInstance enter(%s);' % arg_string |
| 93 elif arg[0] == 'PP_Resource': | 123 elif arg[0] == 'PP_Resource': |
| 94 api_name = interface.GetName() | |
| 95 if api_name.endswith('Trusted'): | |
| 96 api_name = api_name[:-len('Trusted')] | |
| 97 if api_name.endswith('_Dev'): | |
| 98 api_name = api_name[:-len('_Dev')] | |
| 99 api_name += '_API' | |
| 100 | |
| 101 enter_type = 'EnterResource<%s>' % api_name | 124 enter_type = 'EnterResource<%s>' % api_name |
| 102 # The API header matches the file name, not the interface name. | 125 _AddApiHeader(filenode, meta) |
| 103 api_basename = _GetBaseFileName(filenode) | |
| 104 if api_basename.endswith('_dev'): | |
| 105 # Clip off _dev suffix. | |
| 106 api_basename = api_basename[:-len('_dev')] | |
| 107 if api_basename.endswith('_trusted'): | |
| 108 # Clip off _trusted suffix. | |
| 109 api_basename = api_basename[:-len('_trusted')] | |
| 110 meta.AddApi(api_basename + '_api') | |
| 111 | |
| 112 if callback is None: | 126 if callback is None: |
| 113 return '%s enter(%s, %s);' % (enter_type, arg[1], | 127 return '%s enter(%s, %s);' % (enter_type, arg[1], |
| 114 str(handle_errors).lower()) | 128 str(handle_errors).lower()) |
| 115 else: | 129 else: |
| 116 return '%s enter(%s, %s, %s);' % (enter_type, arg[1], | 130 return '%s enter(%s, %s, %s);' % (enter_type, arg[1], |
| 117 callback, | 131 callback, |
| 118 str(handle_errors).lower()) | 132 str(handle_errors).lower()) |
| 119 else: | 133 else: |
| 120 raise TGenError("Unknown type for _MakeEnterLine: %s" % arg[0]) | 134 raise TGenError("Unknown type for _MakeEnterLine: %s" % arg[0]) |
| 121 | 135 |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 233 if is_callback_func: | 247 if is_callback_func: |
| 234 body = '%s\n' % _MakeEnterLine(filenode, node, args[0], handle_errors, | 248 body = '%s\n' % _MakeEnterLine(filenode, node, args[0], handle_errors, |
| 235 args[len(args) - 1][1], meta) | 249 args[len(args) - 1][1], meta) |
| 236 body += 'if (enter.failed())\n' | 250 body += 'if (enter.failed())\n' |
| 237 value = member.GetProperty('on_failure') | 251 value = member.GetProperty('on_failure') |
| 238 if value is None: | 252 if value is None: |
| 239 value = 'enter.retval()' | 253 value = 'enter.retval()' |
| 240 body += ' return %s;\n' % value | 254 body += ' return %s;\n' % value |
| 241 body += 'return enter.SetResult(%s);' % invocation | 255 body += 'return enter.SetResult(%s);' % invocation |
| 242 elif rtype == 'void': | 256 elif rtype == 'void': |
| 257 # On failure, zero out all output parameters. |
| 258 out_params = [] |
| 259 callnode = member.GetOneOf('Callspec') |
| 260 if callnode: |
| 261 cgen = CGen() |
| 262 for param in callnode.GetListOf('Param'): |
| 263 mode = cgen.GetParamMode(param) |
| 264 if mode == 'out': |
| 265 # We use the 'store' mode when getting the parameter type, since we |
| 266 # need to call sizeof() for memset(). |
| 267 ptype, pname, _, _ = cgen.GetComponents(param, release, 'store') |
| 268 out_params.append((pname, ptype)) |
| 269 |
| 243 body = '%s\n' % _MakeEnterLine(filenode, node, args[0], handle_errors, | 270 body = '%s\n' % _MakeEnterLine(filenode, node, args[0], handle_errors, |
| 244 None, meta) | 271 None, meta) |
| 245 body += 'if (enter.succeeded())\n' | 272 if not out_params: |
| 246 body += ' %s;' % invocation | 273 body += 'if (enter.succeeded())\n' |
| 274 body += ' %s;' % invocation |
| 275 else: |
| 276 body += 'if (enter.succeeded()) {\n' |
| 277 body += ' %s;\n' % invocation |
| 278 body += ' return;\n' |
| 279 body += '}' |
| 280 for param in out_params: |
| 281 body += '\nmemset(%s, 0, sizeof(%s));' % param |
| 282 meta.AddBuiltinInclude('string.h') |
| 283 |
| 247 else: | 284 else: |
| 248 value = member.GetProperty('on_failure') | 285 value = member.GetProperty('on_failure') |
| 249 if value is None: | 286 if value is None: |
| 250 value = _GetDefaultFailureValue(rtype) | 287 value = _GetDefaultFailureValue(rtype) |
| 251 if value is None: | 288 if value is None: |
| 252 raise TGenError('No default value for rtype %s' % rtype) | 289 raise TGenError('No default value for rtype %s' % rtype) |
| 253 | 290 |
| 254 body = '%s\n' % _MakeEnterLine(filenode, node, args[0], handle_errors, | 291 body = '%s\n' % _MakeEnterLine(filenode, node, args[0], handle_errors, |
| 255 None, meta) | 292 None, meta) |
| 256 body += 'if (enter.failed())\n' | 293 body += 'if (enter.failed())\n' |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 353 # Wrap the From ... modified ... comment if it would be >80 characters. | 390 # Wrap the From ... modified ... comment if it would be >80 characters. |
| 354 from_text = 'From %s' % ( | 391 from_text = 'From %s' % ( |
| 355 filenode.GetProperty('NAME').replace(os.sep,'/')) | 392 filenode.GetProperty('NAME').replace(os.sep,'/')) |
| 356 modified_text = 'modified %s.' % ( | 393 modified_text = 'modified %s.' % ( |
| 357 filenode.GetProperty('DATETIME')) | 394 filenode.GetProperty('DATETIME')) |
| 358 if len(from_text) + len(modified_text) < 74: | 395 if len(from_text) + len(modified_text) < 74: |
| 359 out.Write('// %s %s\n\n' % (from_text, modified_text)) | 396 out.Write('// %s %s\n\n' % (from_text, modified_text)) |
| 360 else: | 397 else: |
| 361 out.Write('// %s,\n// %s\n\n' % (from_text, modified_text)) | 398 out.Write('// %s,\n// %s\n\n' % (from_text, modified_text)) |
| 362 | 399 |
| 400 if meta.BuiltinIncludes(): |
| 401 for include in sorted(meta.BuiltinIncludes()): |
| 402 out.Write('#include <%s>\n' % include) |
| 403 out.Write('\n') |
| 363 | 404 |
| 364 # TODO(teravest): Don't emit includes we don't need. | 405 # TODO(teravest): Don't emit includes we don't need. |
| 365 includes = ['ppapi/c/pp_errors.h', | 406 includes = ['ppapi/c/pp_errors.h', |
| 366 'ppapi/shared_impl/tracked_callback.h', | 407 'ppapi/shared_impl/tracked_callback.h', |
| 367 'ppapi/thunk/enter.h', | 408 'ppapi/thunk/enter.h', |
| 368 'ppapi/thunk/ppb_instance_api.h', | 409 'ppapi/thunk/ppb_instance_api.h', |
| 369 'ppapi/thunk/resource_creation_api.h', | 410 'ppapi/thunk/resource_creation_api.h', |
| 370 'ppapi/thunk/thunk.h'] | 411 'ppapi/thunk/thunk.h'] |
| 371 includes.append(_GetHeaderFileName(filenode)) | 412 includes.append(_GetHeaderFileName(filenode)) |
| 372 for api in meta.Apis(): | 413 for api in meta.Apis(): |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 483 print "Golden file for M13-M14 failed." | 524 print "Golden file for M13-M14 failed." |
| 484 failed = 1 | 525 failed = 1 |
| 485 else: | 526 else: |
| 486 print "Golden file for M13-M14 passed." | 527 print "Golden file for M13-M14 passed." |
| 487 | 528 |
| 488 return failed | 529 return failed |
| 489 | 530 |
| 490 | 531 |
| 491 if __name__ == '__main__': | 532 if __name__ == '__main__': |
| 492 sys.exit(Main(sys.argv[1:])) | 533 sys.exit(Main(sys.argv[1:])) |
| OLD | NEW |