Chromium Code Reviews| 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 # Clip off _dev suffix. | |
| 99 api_basename = api_basename[:-len('_dev')] | |
| 100 if api_basename.endswith('_trusted'): | |
| 101 # Clip off _dev suffix. | |
|
dmichael (off chromium)
2013/03/28 22:11:22
nit: _trusted (or just remove the comment)
| |
| 102 api_basename = api_basename[:-len('_trusted')] | |
| 103 meta.AddApi(api_basename + '_api') | |
| 104 | |
| 105 | |
| 86 def _MakeEnterLine(filenode, interface, arg, handle_errors, callback, meta): | 106 def _MakeEnterLine(filenode, interface, arg, handle_errors, callback, meta): |
| 87 """Returns an EnterInstance/EnterResource string for a function.""" | 107 """Returns an EnterInstance/EnterResource string for a function.""" |
| 108 api_name = interface.GetName() | |
| 109 if api_name.endswith('Trusted'): | |
| 110 api_name = api_name[:-len('Trusted')] | |
| 111 if api_name.endswith('_Dev'): | |
| 112 api_name = api_name[:-len('_Dev')] | |
| 113 api_name += '_API' | |
| 114 | |
| 88 if arg[0] == 'PP_Instance': | 115 if arg[0] == 'PP_Instance': |
| 89 if callback is None: | 116 if callback is None: |
| 90 return 'EnterInstance enter(%s);' % arg[1] | 117 arg_string = arg[1] |
| 91 else: | 118 else: |
| 92 return 'EnterInstance enter(%s, %s);' % (arg[1], callback) | 119 arg_string = '%s, %s' % (arg[1], callback) |
| 120 if interface.GetProperty('singleton_resource'): | |
| 121 _AddApiHeader(filenode, meta) | |
| 122 return 'EnterInstanceAPI<%s> enter(%s);' % (api_name, arg_string) | |
| 123 else: | |
| 124 return 'EnterInstance enter(%s);' % arg_string | |
| 93 elif arg[0] == 'PP_Resource': | 125 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 | 126 enter_type = 'EnterResource<%s>' % api_name |
| 102 # The API header matches the file name, not the interface name. | 127 _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: | 128 if callback is None: |
| 113 return '%s enter(%s, %s);' % (enter_type, arg[1], | 129 return '%s enter(%s, %s);' % (enter_type, arg[1], |
| 114 str(handle_errors).lower()) | 130 str(handle_errors).lower()) |
| 115 else: | 131 else: |
| 116 return '%s enter(%s, %s, %s);' % (enter_type, arg[1], | 132 return '%s enter(%s, %s, %s);' % (enter_type, arg[1], |
| 117 callback, | 133 callback, |
| 118 str(handle_errors).lower()) | 134 str(handle_errors).lower()) |
| 119 else: | 135 else: |
| 120 raise TGenError("Unknown type for _MakeEnterLine: %s" % arg[0]) | 136 raise TGenError("Unknown type for _MakeEnterLine: %s" % arg[0]) |
| 121 | 137 |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 233 if is_callback_func: | 249 if is_callback_func: |
| 234 body = '%s\n' % _MakeEnterLine(filenode, node, args[0], handle_errors, | 250 body = '%s\n' % _MakeEnterLine(filenode, node, args[0], handle_errors, |
| 235 args[len(args) - 1][1], meta) | 251 args[len(args) - 1][1], meta) |
| 236 body += 'if (enter.failed())\n' | 252 body += 'if (enter.failed())\n' |
| 237 value = member.GetProperty('on_failure') | 253 value = member.GetProperty('on_failure') |
| 238 if value is None: | 254 if value is None: |
| 239 value = 'enter.retval()' | 255 value = 'enter.retval()' |
| 240 body += ' return %s;\n' % value | 256 body += ' return %s;\n' % value |
| 241 body += 'return enter.SetResult(%s);' % invocation | 257 body += 'return enter.SetResult(%s);' % invocation |
| 242 elif rtype == 'void': | 258 elif rtype == 'void': |
| 259 # On failure, zero out all output parameters. | |
| 260 out_params = [] | |
| 261 callnode = member.GetOneOf('Callspec') | |
| 262 if callnode: | |
| 263 cgen = CGen() | |
| 264 for param in callnode.GetListOf('Param'): | |
| 265 mode = cgen.GetParamMode(param) | |
| 266 if mode == 'out': | |
| 267 # We use the 'store' mode when getting the parameter type, since we | |
| 268 # need to call sizeof() for memset(). | |
| 269 ptype, pname, _, _ = cgen.GetComponents(param, release, 'store') | |
| 270 out_params.append((pname, ptype)) | |
| 271 | |
| 243 body = '%s\n' % _MakeEnterLine(filenode, node, args[0], handle_errors, | 272 body = '%s\n' % _MakeEnterLine(filenode, node, args[0], handle_errors, |
| 244 None, meta) | 273 None, meta) |
| 245 body += 'if (enter.succeeded())\n' | 274 if not out_params: |
| 246 body += ' %s;' % invocation | 275 body += 'if (enter.succeeded())\n' |
| 276 body += ' %s;' % invocation | |
| 277 else: | |
| 278 body += 'if (enter.succeeded()) {\n' | |
| 279 body += ' %s;\n' % invocation | |
| 280 body += ' return;\n' | |
| 281 body += '}' | |
| 282 for param in out_params: | |
| 283 body += '\nmemset(%s, 0, sizeof(%s));' % param | |
| 284 meta.AddBuiltinInclude('string.h') | |
| 285 | |
| 247 else: | 286 else: |
| 248 value = member.GetProperty('on_failure') | 287 value = member.GetProperty('on_failure') |
| 249 if value is None: | 288 if value is None: |
| 250 value = _GetDefaultFailureValue(rtype) | 289 value = _GetDefaultFailureValue(rtype) |
| 251 if value is None: | 290 if value is None: |
| 252 raise TGenError('No default value for rtype %s' % rtype) | 291 raise TGenError('No default value for rtype %s' % rtype) |
| 253 | 292 |
| 254 body = '%s\n' % _MakeEnterLine(filenode, node, args[0], handle_errors, | 293 body = '%s\n' % _MakeEnterLine(filenode, node, args[0], handle_errors, |
| 255 None, meta) | 294 None, meta) |
| 256 body += 'if (enter.failed())\n' | 295 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. | 392 # Wrap the From ... modified ... comment if it would be >80 characters. |
| 354 from_text = 'From %s' % ( | 393 from_text = 'From %s' % ( |
| 355 filenode.GetProperty('NAME').replace(os.sep,'/')) | 394 filenode.GetProperty('NAME').replace(os.sep,'/')) |
| 356 modified_text = 'modified %s.' % ( | 395 modified_text = 'modified %s.' % ( |
| 357 filenode.GetProperty('DATETIME')) | 396 filenode.GetProperty('DATETIME')) |
| 358 if len(from_text) + len(modified_text) < 74: | 397 if len(from_text) + len(modified_text) < 74: |
| 359 out.Write('// %s %s\n\n' % (from_text, modified_text)) | 398 out.Write('// %s %s\n\n' % (from_text, modified_text)) |
| 360 else: | 399 else: |
| 361 out.Write('// %s,\n// %s\n\n' % (from_text, modified_text)) | 400 out.Write('// %s,\n// %s\n\n' % (from_text, modified_text)) |
| 362 | 401 |
| 402 if meta.BuiltinIncludes(): | |
| 403 for include in sorted(meta.BuiltinIncludes()): | |
| 404 out.Write('#include <%s>\n' % include) | |
| 405 out.Write('\n') | |
| 363 | 406 |
| 364 # TODO(teravest): Don't emit includes we don't need. | 407 # TODO(teravest): Don't emit includes we don't need. |
| 365 includes = ['ppapi/c/pp_errors.h', | 408 includes = ['ppapi/c/pp_errors.h', |
| 366 'ppapi/shared_impl/tracked_callback.h', | 409 'ppapi/shared_impl/tracked_callback.h', |
| 367 'ppapi/thunk/enter.h', | 410 'ppapi/thunk/enter.h', |
| 368 'ppapi/thunk/ppb_instance_api.h', | 411 'ppapi/thunk/ppb_instance_api.h', |
| 369 'ppapi/thunk/resource_creation_api.h', | 412 'ppapi/thunk/resource_creation_api.h', |
| 370 'ppapi/thunk/thunk.h'] | 413 'ppapi/thunk/thunk.h'] |
| 371 includes.append(_GetHeaderFileName(filenode)) | 414 includes.append(_GetHeaderFileName(filenode)) |
| 372 for api in meta.Apis(): | 415 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." | 526 print "Golden file for M13-M14 failed." |
| 484 failed = 1 | 527 failed = 1 |
| 485 else: | 528 else: |
| 486 print "Golden file for M13-M14 passed." | 529 print "Golden file for M13-M14 passed." |
| 487 | 530 |
| 488 return failed | 531 return failed |
| 489 | 532 |
| 490 | 533 |
| 491 if __name__ == '__main__': | 534 if __name__ == '__main__': |
| 492 sys.exit(Main(sys.argv[1:])) | 535 sys.exit(Main(sys.argv[1:])) |
| OLD | NEW |