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 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
94 """Adds an API header for the given file to the ThunkBodyMetadata.""" | 94 """Adds an API header for the given file to the ThunkBodyMetadata.""" |
95 # The API header matches the file name, not the interface name. | 95 # The API header matches the file name, not the interface name. |
96 api_basename = _GetBaseFileName(filenode) | 96 api_basename = _GetBaseFileName(filenode) |
97 if api_basename.endswith('_dev'): | 97 if api_basename.endswith('_dev'): |
98 api_basename = api_basename[:-len('_dev')] | 98 api_basename = api_basename[:-len('_dev')] |
99 if api_basename.endswith('_trusted'): | 99 if api_basename.endswith('_trusted'): |
100 api_basename = api_basename[:-len('_trusted')] | 100 api_basename = api_basename[:-len('_trusted')] |
101 meta.AddApi(api_basename + '_api') | 101 meta.AddApi(api_basename + '_api') |
102 | 102 |
103 | 103 |
104 def _MakeEnterLine(filenode, interface, arg, handle_errors, callback, meta): | 104 def _MakeEnterLine(filenode, interface, member, arg, handle_errors, callback, |
| 105 meta): |
105 """Returns an EnterInstance/EnterResource string for a function.""" | 106 """Returns an EnterInstance/EnterResource string for a function.""" |
106 api_name = interface.GetName() | 107 api_name = interface.GetName() |
107 if api_name.endswith('Trusted'): | 108 if api_name.endswith('Trusted'): |
108 api_name = api_name[:-len('Trusted')] | 109 api_name = api_name[:-len('Trusted')] |
109 if api_name.endswith('_Dev'): | 110 if api_name.endswith('_Dev'): |
110 api_name = api_name[:-len('_Dev')] | 111 api_name = api_name[:-len('_Dev')] |
111 api_name += '_API' | 112 api_name += '_API' |
| 113 if member.GetProperty('api'): # Override API name. |
| 114 manually_provided_api = True |
| 115 # TODO(teravest): Automatically guess the API header file. |
| 116 api_name = member.GetProperty('api') |
| 117 else: |
| 118 manually_provided_api = False |
112 | 119 |
113 if arg[0] == 'PP_Instance': | 120 if arg[0] == 'PP_Instance': |
114 if callback is None: | 121 if callback is None: |
115 arg_string = arg[1] | 122 arg_string = arg[1] |
116 else: | 123 else: |
117 arg_string = '%s, %s' % (arg[1], callback) | 124 arg_string = '%s, %s' % (arg[1], callback) |
118 if interface.GetProperty('singleton_resource'): | 125 if interface.GetProperty('singleton') or member.GetProperty('singleton'): |
119 _AddApiHeader(filenode, meta) | 126 if not manually_provided_api: |
| 127 _AddApiHeader(filenode, meta) |
120 return 'EnterInstanceAPI<%s> enter(%s);' % (api_name, arg_string) | 128 return 'EnterInstanceAPI<%s> enter(%s);' % (api_name, arg_string) |
121 else: | 129 else: |
122 return 'EnterInstance enter(%s);' % arg_string | 130 return 'EnterInstance enter(%s);' % arg_string |
123 elif arg[0] == 'PP_Resource': | 131 elif arg[0] == 'PP_Resource': |
124 enter_type = 'EnterResource<%s>' % api_name | 132 enter_type = 'EnterResource<%s>' % api_name |
125 _AddApiHeader(filenode, meta) | 133 if not manually_provided_api: |
| 134 _AddApiHeader(filenode, meta) |
126 if callback is None: | 135 if callback is None: |
127 return '%s enter(%s, %s);' % (enter_type, arg[1], | 136 return '%s enter(%s, %s);' % (enter_type, arg[1], |
128 str(handle_errors).lower()) | 137 str(handle_errors).lower()) |
129 else: | 138 else: |
130 return '%s enter(%s, %s, %s);' % (enter_type, arg[1], | 139 return '%s enter(%s, %s, %s);' % (enter_type, arg[1], |
131 callback, | 140 callback, |
132 str(handle_errors).lower()) | 141 str(handle_errors).lower()) |
133 else: | 142 else: |
134 raise TGenError("Unknown type for _MakeEnterLine: %s" % arg[0]) | 143 raise TGenError("Unknown type for _MakeEnterLine: %s" % arg[0]) |
135 | 144 |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
238 if include_version: | 247 if include_version: |
239 version = node.GetVersion(release).replace('.', '_') | 248 version = node.GetVersion(release).replace('.', '_') |
240 function_name += version | 249 function_name += version |
241 | 250 |
242 invocation = 'enter.%s()->%s(%s)' % (function_container, | 251 invocation = 'enter.%s()->%s(%s)' % (function_container, |
243 function_name, | 252 function_name, |
244 call_arglist) | 253 call_arglist) |
245 | 254 |
246 handle_errors = not (member.GetProperty('report_errors') == 'False') | 255 handle_errors = not (member.GetProperty('report_errors') == 'False') |
247 if is_callback_func: | 256 if is_callback_func: |
248 body = '%s\n' % _MakeEnterLine(filenode, node, args[0], handle_errors, | 257 body = '%s\n' % _MakeEnterLine(filenode, node, member, args[0], |
249 args[len(args) - 1][1], meta) | 258 handle_errors, args[len(args) - 1][1], meta) |
250 body += 'if (enter.failed())\n' | 259 body += 'if (enter.failed())\n' |
251 value = member.GetProperty('on_failure') | 260 value = member.GetProperty('on_failure') |
252 if value is None: | 261 if value is None: |
253 value = 'enter.retval()' | 262 value = 'enter.retval()' |
254 body += ' return %s;\n' % value | 263 body += ' return %s;\n' % value |
255 body += 'return enter.SetResult(%s);' % invocation | 264 body += 'return enter.SetResult(%s);' % invocation |
256 elif rtype == 'void': | 265 elif rtype == 'void': |
257 # On failure, zero out all output parameters. | 266 # On failure, zero out all output parameters. |
258 out_params = [] | 267 out_params = [] |
259 callnode = member.GetOneOf('Callspec') | 268 callnode = member.GetOneOf('Callspec') |
260 if callnode: | 269 if callnode: |
261 cgen = CGen() | 270 cgen = CGen() |
262 for param in callnode.GetListOf('Param'): | 271 for param in callnode.GetListOf('Param'): |
263 mode = cgen.GetParamMode(param) | 272 mode = cgen.GetParamMode(param) |
264 if mode == 'out': | 273 if mode == 'out': |
265 # We use the 'store' mode when getting the parameter type, since we | 274 # We use the 'store' mode when getting the parameter type, since we |
266 # need to call sizeof() for memset(). | 275 # need to call sizeof() for memset(). |
267 ptype, pname, _, _ = cgen.GetComponents(param, release, 'store') | 276 ptype, pname, _, _ = cgen.GetComponents(param, release, 'store') |
268 out_params.append((pname, ptype)) | 277 out_params.append((pname, ptype)) |
269 | 278 |
270 body = '%s\n' % _MakeEnterLine(filenode, node, args[0], handle_errors, | 279 body = '%s\n' % _MakeEnterLine(filenode, node, member, args[0], |
271 None, meta) | 280 handle_errors, None, meta) |
272 if not out_params: | 281 if not out_params: |
273 body += 'if (enter.succeeded())\n' | 282 body += 'if (enter.succeeded())\n' |
274 body += ' %s;' % invocation | 283 body += ' %s;' % invocation |
275 else: | 284 else: |
276 body += 'if (enter.succeeded()) {\n' | 285 body += 'if (enter.succeeded()) {\n' |
277 body += ' %s;\n' % invocation | 286 body += ' %s;\n' % invocation |
278 body += ' return;\n' | 287 body += ' return;\n' |
279 body += '}' | 288 body += '}' |
280 for param in out_params: | 289 for param in out_params: |
281 body += '\nmemset(%s, 0, sizeof(%s));' % param | 290 body += '\nmemset(%s, 0, sizeof(%s));' % param |
282 meta.AddBuiltinInclude('string.h') | 291 meta.AddBuiltinInclude('string.h') |
283 | 292 |
284 else: | 293 else: |
285 value = member.GetProperty('on_failure') | 294 value = member.GetProperty('on_failure') |
286 if value is None: | 295 if value is None: |
287 value = _GetDefaultFailureValue(rtype) | 296 value = _GetDefaultFailureValue(rtype) |
288 if value is None: | 297 if value is None: |
289 raise TGenError('No default value for rtype %s' % rtype) | 298 raise TGenError('No default value for rtype %s' % rtype) |
290 | 299 |
291 body = '%s\n' % _MakeEnterLine(filenode, node, args[0], handle_errors, | 300 body = '%s\n' % _MakeEnterLine(filenode, node, member, args[0], |
292 None, meta) | 301 handle_errors, None, meta) |
293 body += 'if (enter.failed())\n' | 302 body += 'if (enter.failed())\n' |
294 body += ' return %s;\n' % value | 303 body += ' return %s;\n' % value |
295 body += 'return %s;' % invocation | 304 body += 'return %s;' % invocation |
296 return body | 305 return body |
297 | 306 |
298 | 307 |
299 def DefineMember(filenode, node, member, release, include_version, meta): | 308 def DefineMember(filenode, node, member, release, include_version, meta): |
300 """Returns a definition for a member function of an interface. | 309 """Returns a definition for a member function of an interface. |
301 | 310 |
302 Args: | 311 Args: |
303 filenode - IDLNode for the file | 312 filenode - IDLNode for the file |
304 node - IDLNode for the interface | 313 node - IDLNode for the interface |
305 member - IDLNode for the member function | 314 member - IDLNode for the member function |
306 release - release to generate | 315 release - release to generate |
307 include_version - include the version in emitted function name. | 316 include_version - include the version in emitted function name. |
308 meta - ThunkMetadata for header hints | 317 meta - ThunkMetadata for header hints |
309 Returns: | 318 Returns: |
310 A string with the member definition. | 319 A string with the member definition. |
311 """ | 320 """ |
312 cgen = CGen() | 321 cgen = CGen() |
313 rtype, name, arrays, args = cgen.GetComponents(member, release, 'return') | 322 rtype, name, arrays, args = cgen.GetComponents(member, release, 'return') |
314 body = 'VLOG(4) << \"%s::%s()\";\n' % (node.GetName(), member.GetName()) | 323 body = 'VLOG(4) << \"%s::%s()\";\n' % (node.GetName(), member.GetName()) |
315 | 324 |
316 if _IsTypeCheck(node, member): | 325 if _IsTypeCheck(node, member): |
317 body += '%s\n' % _MakeEnterLine(filenode, node, args[0], False, None, meta) | 326 body += '%s\n' % _MakeEnterLine(filenode, node, member, args[0], False, |
| 327 None, meta) |
318 body += 'return PP_FromBool(enter.succeeded());' | 328 body += 'return PP_FromBool(enter.succeeded());' |
319 elif member.GetName() == 'Create': | 329 elif member.GetName() == 'Create': |
320 body += _MakeCreateMemberBody(node, member, args) | 330 body += _MakeCreateMemberBody(node, member, args) |
321 else: | 331 else: |
322 body += _MakeNormalMemberBody(filenode, release, node, member, rtype, args, | 332 body += _MakeNormalMemberBody(filenode, release, node, member, rtype, args, |
323 include_version, meta) | 333 include_version, meta) |
324 | 334 |
325 signature = cgen.GetSignature(member, release, 'return', func_as_ptr=False, | 335 signature = cgen.GetSignature(member, release, 'return', func_as_ptr=False, |
326 include_version=include_version) | 336 include_version=include_version) |
327 return '%s\n%s\n}' % (cgen.Indent('%s {' % signature, tabs=0), | 337 return '%s\n%s\n}' % (cgen.Indent('%s {' % signature, tabs=0), |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
368 if os.path.isfile(savename): | 378 if os.path.isfile(savename): |
369 print "Removing stale %s for this range." % filenode.GetName() | 379 print "Removing stale %s for this range." % filenode.GetName() |
370 os.remove(os.path.realpath(savename)) | 380 os.remove(os.path.realpath(savename)) |
371 return False | 381 return False |
372 do_generate = filenode.GetProperty('generate_thunk') | 382 do_generate = filenode.GetProperty('generate_thunk') |
373 if not do_generate: | 383 if not do_generate: |
374 return False | 384 return False |
375 | 385 |
376 thunk_out = IDLOutFile(savename) | 386 thunk_out = IDLOutFile(savename) |
377 body, meta = self.GenerateBody(thunk_out, filenode, releases, options) | 387 body, meta = self.GenerateBody(thunk_out, filenode, releases, options) |
| 388 # TODO(teravest): How do we handle repeated values? |
| 389 if filenode.GetProperty('thunk_include'): |
| 390 meta.AddInclude(filenode.GetProperty('thunk_include')) |
378 self.WriteHead(thunk_out, filenode, releases, options, meta) | 391 self.WriteHead(thunk_out, filenode, releases, options, meta) |
379 thunk_out.Write('\n\n'.join(body)) | 392 thunk_out.Write('\n\n'.join(body)) |
380 self.WriteTail(thunk_out, filenode, releases, options) | 393 self.WriteTail(thunk_out, filenode, releases, options) |
381 return thunk_out.Close() | 394 return thunk_out.Close() |
382 | 395 |
383 def WriteHead(self, out, filenode, releases, options, meta): | 396 def WriteHead(self, out, filenode, releases, options, meta): |
384 __pychecker__ = 'unusednames=options' | 397 __pychecker__ = 'unusednames=options' |
385 cgen = CGen() | 398 cgen = CGen() |
386 | 399 |
387 cright_node = filenode.GetChildren()[0] | 400 cright_node = filenode.GetChildren()[0] |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
525 print "Golden file for M13-M14 failed." | 538 print "Golden file for M13-M14 failed." |
526 failed = 1 | 539 failed = 1 |
527 else: | 540 else: |
528 print "Golden file for M13-M14 passed." | 541 print "Golden file for M13-M14 passed." |
529 | 542 |
530 return failed | 543 return failed |
531 | 544 |
532 | 545 |
533 if __name__ == '__main__': | 546 if __name__ == '__main__': |
534 sys.exit(Main(sys.argv[1:])) | 547 sys.exit(Main(sys.argv[1:])) |
OLD | NEW |