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 |