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 |