blob: d183e4b9224e407b94403aa745925b285409c3a5 [file] [log] [blame]
[email protected]8c311f02012-11-17 16:01:321#!/usr/bin/env python
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
4# found in the LICENSE file.
5
6""" Generator for C++ style thunks """
7
8import glob
9import os
10import re
11import sys
12
13from idl_log import ErrOut, InfoOut, WarnOut
14from idl_node import IDLAttribute, IDLNode
15from idl_ast import IDLAst
16from idl_option import GetOption, Option, ParseOptions
17from idl_outfile import IDLOutFile
18from idl_parser import ParseFiles
19from idl_c_proto import CGen, GetNodeComments, CommentLines, Comment
20from idl_generator import Generator, GeneratorByFile
21
22Option('thunkroot', 'Base directory of output',
23 default=os.path.join('..', 'thunk'))
24
25
26class TGenError(Exception):
27 def __init__(self, msg):
28 self.value = msg
29
30 def __str__(self):
31 return repr(self.value)
32
33
[email protected]cba2c4302012-11-20 18:18:1334class ThunkBodyMetadata(object):
35 """Metadata about thunk body. Used for selecting which headers to emit."""
36 def __init__(self):
37 self._apis = set()
[email protected]2a7e8c52013-03-30 00:13:2538 self._builtin_includes = set()
[email protected]8f2a08d52012-12-08 00:10:5039 self._includes = set()
[email protected]cba2c4302012-11-20 18:18:1340
41 def AddApi(self, api):
42 self._apis.add(api)
43
44 def Apis(self):
45 return self._apis
46
[email protected]8f2a08d52012-12-08 00:10:5047 def AddInclude(self, include):
48 self._includes.add(include)
49
50 def Includes(self):
51 return self._includes
52
[email protected]2a7e8c52013-03-30 00:13:2553 def AddBuiltinInclude(self, include):
54 self._builtin_includes.add(include)
55
56 def BuiltinIncludes(self):
57 return self._builtin_includes
58
[email protected]cba2c4302012-11-20 18:18:1359
[email protected]8c311f02012-11-17 16:01:3260def _GetBaseFileName(filenode):
61 """Returns the base name for output files, given the filenode.
62
63 Examples:
[email protected]a5b6ace2013-02-08 21:09:5264 'dev/ppb_find_dev.h' -> 'ppb_find_dev'
[email protected]8c311f02012-11-17 16:01:3265 'trusted/ppb_buffer_trusted.h' -> 'ppb_buffer_trusted'
66 """
67 path, name = os.path.split(filenode.GetProperty('NAME'))
68 name = os.path.splitext(name)[0]
[email protected]8c311f02012-11-17 16:01:3269 return name
70
71
72def _GetHeaderFileName(filenode):
73 """Returns the name for the header for this file."""
74 path, name = os.path.split(filenode.GetProperty('NAME'))
75 name = os.path.splitext(name)[0]
76 if path:
77 header = "ppapi/c/%s/%s.h" % (path, name)
78 else:
79 header = "ppapi/c/%s.h" % name
80 return header
81
82
83def _GetThunkFileName(filenode, relpath):
84 """Returns the thunk file name."""
85 path = os.path.split(filenode.GetProperty('NAME'))[0]
86 name = _GetBaseFileName(filenode)
87 # We don't reattach the path for thunk.
88 if relpath: name = os.path.join(relpath, name)
89 name = '%s%s' % (name, '_thunk.cc')
90 return name
91
92
[email protected]2a7e8c52013-03-30 00:13:2593def _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
[email protected]a3887962013-04-16 21:02:16104def _MakeEnterLine(filenode, interface, member, arg, handle_errors, callback,
105 meta):
[email protected]8c311f02012-11-17 16:01:32106 """Returns an EnterInstance/EnterResource string for a function."""
[email protected]2a7e8c52013-03-30 00:13:25107 api_name = interface.GetName()
108 if api_name.endswith('Trusted'):
109 api_name = api_name[:-len('Trusted')]
110 if api_name.endswith('_Dev'):
111 api_name = api_name[:-len('_Dev')]
112 api_name += '_API'
[email protected]a3887962013-04-16 21:02:16113 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
[email protected]2a7e8c52013-03-30 00:13:25119
[email protected]8c311f02012-11-17 16:01:32120 if arg[0] == 'PP_Instance':
121 if callback is None:
[email protected]2a7e8c52013-03-30 00:13:25122 arg_string = arg[1]
[email protected]8c311f02012-11-17 16:01:32123 else:
[email protected]2a7e8c52013-03-30 00:13:25124 arg_string = '%s, %s' % (arg[1], callback)
[email protected]a3887962013-04-16 21:02:16125 if interface.GetProperty('singleton') or member.GetProperty('singleton'):
126 if not manually_provided_api:
127 _AddApiHeader(filenode, meta)
[email protected]2a7e8c52013-03-30 00:13:25128 return 'EnterInstanceAPI<%s> enter(%s);' % (api_name, arg_string)
129 else:
130 return 'EnterInstance enter(%s);' % arg_string
[email protected]8c311f02012-11-17 16:01:32131 elif arg[0] == 'PP_Resource':
[email protected]8c311f02012-11-17 16:01:32132 enter_type = 'EnterResource<%s>' % api_name
[email protected]a3887962013-04-16 21:02:16133 if not manually_provided_api:
134 _AddApiHeader(filenode, meta)
[email protected]8c311f02012-11-17 16:01:32135 if callback is None:
136 return '%s enter(%s, %s);' % (enter_type, arg[1],
137 str(handle_errors).lower())
138 else:
139 return '%s enter(%s, %s, %s);' % (enter_type, arg[1],
140 callback,
141 str(handle_errors).lower())
142 else:
143 raise TGenError("Unknown type for _MakeEnterLine: %s" % arg[0])
144
145
146def _GetShortName(interface, filter_suffixes):
147 """Return a shorter interface name that matches Is* and Create* functions."""
148 parts = interface.GetName().split('_')[1:]
149 tail = parts[len(parts) - 1]
150 if tail in filter_suffixes:
151 parts = parts[:-1]
152 return ''.join(parts)
153
154
155def _IsTypeCheck(interface, node):
156 """Returns true if node represents a type-checking function."""
157 return node.GetName() == 'Is%s' % _GetShortName(interface, ['Dev', 'Private'])
158
159
160def _GetCreateFuncName(interface):
161 """Returns the creation function name for an interface."""
162 return 'Create%s' % _GetShortName(interface, ['Dev'])
163
164
165def _GetDefaultFailureValue(t):
166 """Returns the default failure value for a given type.
167
168 Returns None if no default failure value exists for the type.
169 """
170 values = {
171 'PP_Bool': 'PP_FALSE',
172 'PP_Resource': '0',
173 'struct PP_Var': 'PP_MakeUndefined()',
[email protected]12b6f612013-02-13 18:17:58174 'float': '0.0f',
[email protected]8c311f02012-11-17 16:01:32175 'int32_t': 'enter.retval()',
176 'uint16_t': '0',
177 'uint32_t': '0',
178 'uint64_t': '0',
179 }
180 if t in values:
181 return values[t]
182 return None
183
184
185def _MakeCreateMemberBody(interface, member, args):
186 """Returns the body of a Create() function.
187
188 Args:
189 interface - IDLNode for the interface
190 member - IDLNode for member function
191 args - List of arguments for the Create() function
192 """
193 if args[0][0] == 'PP_Resource':
[email protected]8917a672013-02-25 17:18:04194 body = 'Resource* object =\n'
195 body += ' PpapiGlobals::Get()->GetResourceTracker()->'
[email protected]8c311f02012-11-17 16:01:32196 body += 'GetResource(%s);\n' % args[0][1]
[email protected]8917a672013-02-25 17:18:04197 body += 'if (!object)\n'
198 body += ' return 0;\n'
199 body += 'EnterResourceCreation enter(object->pp_instance());\n'
[email protected]8c311f02012-11-17 16:01:32200 elif args[0][0] == 'PP_Instance':
[email protected]8917a672013-02-25 17:18:04201 body = 'EnterResourceCreation enter(%s);\n' % args[0][1]
[email protected]8c311f02012-11-17 16:01:32202 else:
203 raise TGenError('Unknown arg type for Create(): %s' % args[0][0])
204
[email protected]8917a672013-02-25 17:18:04205 body += 'if (enter.failed())\n'
206 body += ' return 0;\n'
[email protected]8c311f02012-11-17 16:01:32207 arg_list = ', '.join([a[1] for a in args])
208 if member.GetProperty('create_func'):
209 create_func = member.GetProperty('create_func')
210 else:
211 create_func = _GetCreateFuncName(interface)
[email protected]8917a672013-02-25 17:18:04212 body += 'return enter.functions()->%s(%s);' % (create_func,
213 arg_list)
[email protected]8c311f02012-11-17 16:01:32214 return body
215
216
[email protected]b082d582013-04-18 14:02:00217def _GetOutputParams(member, release):
218 """Returns output parameters (and their types) for a member function.
219
220 Args:
221 member - IDLNode for the member function
222 release - Release to get output parameters for
223 Returns:
224 A list of name strings for all output parameters of the member
225 function.
226 """
227 out_params = []
228 callnode = member.GetOneOf('Callspec')
229 if callnode:
230 cgen = CGen()
231 for param in callnode.GetListOf('Param'):
232 mode = cgen.GetParamMode(param)
233 if mode == 'out':
234 # We use the 'store' mode when getting the parameter type, since we
235 # need to call sizeof() for memset().
236 _, pname, _, _ = cgen.GetComponents(param, release, 'store')
237 out_params.append(pname)
238 return out_params
239
240
[email protected]8917a672013-02-25 17:18:04241def _MakeNormalMemberBody(filenode, release, node, member, rtype, args,
242 include_version, meta):
[email protected]8c311f02012-11-17 16:01:32243 """Returns the body of a typical function.
244
245 Args:
246 filenode - IDLNode for the file
[email protected]8917a672013-02-25 17:18:04247 release - release to generate body for
[email protected]8c311f02012-11-17 16:01:32248 node - IDLNode for the interface
249 member - IDLNode for the member function
250 rtype - Return type for the member function
251 args - List of 4-tuple arguments for the member function
[email protected]8917a672013-02-25 17:18:04252 include_version - whether to include the version in the invocation
[email protected]cba2c4302012-11-20 18:18:13253 meta - ThunkBodyMetadata for header hints
[email protected]8c311f02012-11-17 16:01:32254 """
255 is_callback_func = args[len(args) - 1][0] == 'struct PP_CompletionCallback'
256
257 if is_callback_func:
258 call_args = args[:-1] + [('', 'enter.callback()', '', '')]
[email protected]8f2a08d52012-12-08 00:10:50259 meta.AddInclude('ppapi/c/pp_completion_callback.h')
[email protected]8c311f02012-11-17 16:01:32260 else:
261 call_args = args
262
263 if args[0][0] == 'PP_Instance':
264 call_arglist = ', '.join(a[1] for a in call_args)
265 function_container = 'functions'
266 else:
267 call_arglist = ', '.join(a[1] for a in call_args[1:])
268 function_container = 'object'
269
[email protected]8917a672013-02-25 17:18:04270 function_name = member.GetName()
271 if include_version:
272 version = node.GetVersion(release).replace('.', '_')
273 function_name += version
274
[email protected]8c311f02012-11-17 16:01:32275 invocation = 'enter.%s()->%s(%s)' % (function_container,
[email protected]8917a672013-02-25 17:18:04276 function_name,
[email protected]8c311f02012-11-17 16:01:32277 call_arglist)
278
279 handle_errors = not (member.GetProperty('report_errors') == 'False')
[email protected]b082d582013-04-18 14:02:00280 out_params = _GetOutputParams(member, release)
[email protected]8c311f02012-11-17 16:01:32281 if is_callback_func:
[email protected]b082d582013-04-18 14:02:00282 # TODO(teravest): Reduce code duplication below.
[email protected]a3887962013-04-16 21:02:16283 body = '%s\n' % _MakeEnterLine(filenode, node, member, args[0],
284 handle_errors, args[len(args) - 1][1], meta)
[email protected]8c311f02012-11-17 16:01:32285 value = member.GetProperty('on_failure')
286 if value is None:
287 value = 'enter.retval()'
[email protected]b082d582013-04-18 14:02:00288 if member.GetProperty('always_set_output_parameters'):
289 body += 'if (enter.failed()) {\n'
290 for param in out_params:
291 body += ' memset(%s, 0, sizeof(*%s));\n' % (param, param)
292 body += ' return %s;\n' % value
293 body += '}\n'
294 body += 'return enter.SetResult(%s);' % invocation
295 meta.AddBuiltinInclude('string.h')
296 else:
297 body += 'if (enter.failed())\n'
298 body += ' return %s;\n' % value
299 body += 'return enter.SetResult(%s);' % invocation
[email protected]8c311f02012-11-17 16:01:32300 elif rtype == 'void':
[email protected]a3887962013-04-16 21:02:16301 body = '%s\n' % _MakeEnterLine(filenode, node, member, args[0],
302 handle_errors, None, meta)
[email protected]b082d582013-04-18 14:02:00303 if member.GetProperty('always_set_output_parameters'):
[email protected]2a7e8c52013-03-30 00:13:25304 body += 'if (enter.succeeded()) {\n'
305 body += ' %s;\n' % invocation
306 body += ' return;\n'
307 body += '}'
308 for param in out_params:
[email protected]b082d582013-04-18 14:02:00309 body += '\nmemset(%s, 0, sizeof(*%s));' % (param, param)
[email protected]2a7e8c52013-03-30 00:13:25310 meta.AddBuiltinInclude('string.h')
[email protected]b082d582013-04-18 14:02:00311 else:
312 body += 'if (enter.succeeded())\n'
313 body += ' %s;' % invocation
[email protected]2a7e8c52013-03-30 00:13:25314
[email protected]8c311f02012-11-17 16:01:32315 else:
316 value = member.GetProperty('on_failure')
317 if value is None:
318 value = _GetDefaultFailureValue(rtype)
319 if value is None:
320 raise TGenError('No default value for rtype %s' % rtype)
321
[email protected]a3887962013-04-16 21:02:16322 body = '%s\n' % _MakeEnterLine(filenode, node, member, args[0],
323 handle_errors, None, meta)
[email protected]b082d582013-04-18 14:02:00324 if member.GetProperty('always_set_output_parameters'):
325 body += 'if (enter.failed()) {\n'
326 for param in out_params:
327 body += ' memset(%s, 0, sizeof(*%s));\n' % (param, param)
328 body += ' return %s;\n' % value
329 body += '}\n'
330 body += 'return %s;' % invocation
331 meta.AddBuiltinInclude('string.h')
332 else:
333 body += 'if (enter.failed())\n'
334 body += ' return %s;\n' % value
335 body += 'return %s;' % invocation
[email protected]8c311f02012-11-17 16:01:32336 return body
337
338
[email protected]cba2c4302012-11-20 18:18:13339def DefineMember(filenode, node, member, release, include_version, meta):
[email protected]8c311f02012-11-17 16:01:32340 """Returns a definition for a member function of an interface.
341
342 Args:
343 filenode - IDLNode for the file
344 node - IDLNode for the interface
345 member - IDLNode for the member function
346 release - release to generate
347 include_version - include the version in emitted function name.
[email protected]cba2c4302012-11-20 18:18:13348 meta - ThunkMetadata for header hints
[email protected]8c311f02012-11-17 16:01:32349 Returns:
350 A string with the member definition.
351 """
352 cgen = CGen()
353 rtype, name, arrays, args = cgen.GetComponents(member, release, 'return')
[email protected]03f8b542013-04-02 17:57:50354 body = 'VLOG(4) << \"%s::%s()\";\n' % (node.GetName(), member.GetName())
[email protected]8c311f02012-11-17 16:01:32355
356 if _IsTypeCheck(node, member):
[email protected]a3887962013-04-16 21:02:16357 body += '%s\n' % _MakeEnterLine(filenode, node, member, args[0], False,
358 None, meta)
[email protected]8917a672013-02-25 17:18:04359 body += 'return PP_FromBool(enter.succeeded());'
[email protected]8c311f02012-11-17 16:01:32360 elif member.GetName() == 'Create':
[email protected]03f8b542013-04-02 17:57:50361 body += _MakeCreateMemberBody(node, member, args)
[email protected]8c311f02012-11-17 16:01:32362 else:
[email protected]03f8b542013-04-02 17:57:50363 body += _MakeNormalMemberBody(filenode, release, node, member, rtype, args,
364 include_version, meta)
[email protected]8c311f02012-11-17 16:01:32365
366 signature = cgen.GetSignature(member, release, 'return', func_as_ptr=False,
367 include_version=include_version)
[email protected]8917a672013-02-25 17:18:04368 return '%s\n%s\n}' % (cgen.Indent('%s {' % signature, tabs=0),
369 cgen.Indent(body, tabs=1))
370
371
372def _IsNewestMember(member, members, releases):
373 """Returns true if member is the newest node with its name in members.
374
375 Currently, every node in the AST only has one version. This means that we
376 will have two sibling nodes with the same name to represent different
377 versions.
378 See http://crbug.com/157017 .
379
380 Special handling is required for nodes which share their name with others,
381 but aren't the newest version in the IDL.
382
383 Args:
384 member - The member which is checked if it's newest
385 members - The list of members to inspect
386 releases - The set of releases to check for versions in.
387 """
388 build_list = member.GetUniqueReleases(releases)
[email protected]ba054c02013-02-26 23:27:18389 release = build_list[0] # Pick the oldest release.
[email protected]8917a672013-02-25 17:18:04390 same_name_siblings = filter(
391 lambda n: str(n) == str(member) and n != member, members)
392
393 for s in same_name_siblings:
394 sibling_build_list = s.GetUniqueReleases(releases)
[email protected]ba054c02013-02-26 23:27:18395 sibling_release = sibling_build_list[0]
[email protected]8917a672013-02-25 17:18:04396 if sibling_release > release:
397 return False
398 return True
[email protected]8c311f02012-11-17 16:01:32399
400
401class TGen(GeneratorByFile):
402 def __init__(self):
403 Generator.__init__(self, 'Thunk', 'tgen', 'Generate the C++ thunk.')
404
405 def GenerateFile(self, filenode, releases, options):
406 savename = _GetThunkFileName(filenode, GetOption('thunkroot'))
407 my_min, my_max = filenode.GetMinMax(releases)
408 if my_min > releases[-1] or my_max < releases[0]:
409 if os.path.isfile(savename):
410 print "Removing stale %s for this range." % filenode.GetName()
411 os.remove(os.path.realpath(savename))
412 return False
413 do_generate = filenode.GetProperty('generate_thunk')
414 if not do_generate:
415 return False
416
417 thunk_out = IDLOutFile(savename)
[email protected]cba2c4302012-11-20 18:18:13418 body, meta = self.GenerateBody(thunk_out, filenode, releases, options)
[email protected]a3887962013-04-16 21:02:16419 # TODO(teravest): How do we handle repeated values?
420 if filenode.GetProperty('thunk_include'):
421 meta.AddInclude(filenode.GetProperty('thunk_include'))
[email protected]cba2c4302012-11-20 18:18:13422 self.WriteHead(thunk_out, filenode, releases, options, meta)
423 thunk_out.Write('\n\n'.join(body))
424 self.WriteTail(thunk_out, filenode, releases, options)
[email protected]8c311f02012-11-17 16:01:32425 return thunk_out.Close()
426
[email protected]cba2c4302012-11-20 18:18:13427 def WriteHead(self, out, filenode, releases, options, meta):
[email protected]8c311f02012-11-17 16:01:32428 __pychecker__ = 'unusednames=options'
429 cgen = CGen()
430
431 cright_node = filenode.GetChildren()[0]
432 assert(cright_node.IsA('Copyright'))
433 out.Write('%s\n' % cgen.Copyright(cright_node, cpp_style=True))
434
435 # Wrap the From ... modified ... comment if it would be >80 characters.
436 from_text = 'From %s' % (
437 filenode.GetProperty('NAME').replace(os.sep,'/'))
438 modified_text = 'modified %s.' % (
439 filenode.GetProperty('DATETIME'))
440 if len(from_text) + len(modified_text) < 74:
441 out.Write('// %s %s\n\n' % (from_text, modified_text))
442 else:
443 out.Write('// %s,\n// %s\n\n' % (from_text, modified_text))
444
[email protected]2a7e8c52013-03-30 00:13:25445 if meta.BuiltinIncludes():
446 for include in sorted(meta.BuiltinIncludes()):
447 out.Write('#include <%s>\n' % include)
448 out.Write('\n')
[email protected]8c311f02012-11-17 16:01:32449
450 # TODO(teravest): Don't emit includes we don't need.
451 includes = ['ppapi/c/pp_errors.h',
452 'ppapi/shared_impl/tracked_callback.h',
453 'ppapi/thunk/enter.h',
454 'ppapi/thunk/ppb_instance_api.h',
455 'ppapi/thunk/resource_creation_api.h',
456 'ppapi/thunk/thunk.h']
457 includes.append(_GetHeaderFileName(filenode))
[email protected]cba2c4302012-11-20 18:18:13458 for api in meta.Apis():
459 includes.append('ppapi/thunk/%s.h' % api.lower())
[email protected]8f2a08d52012-12-08 00:10:50460 for i in meta.Includes():
461 includes.append(i)
[email protected]8c311f02012-11-17 16:01:32462 for include in sorted(includes):
463 out.Write('#include "%s"\n' % include)
464 out.Write('\n')
465 out.Write('namespace ppapi {\n')
466 out.Write('namespace thunk {\n')
467 out.Write('\n')
468 out.Write('namespace {\n')
469 out.Write('\n')
470
471 def GenerateBody(self, out, filenode, releases, options):
[email protected]cba2c4302012-11-20 18:18:13472 """Generates a member function lines to be written and metadata.
473
474 Returns a tuple of (body, meta) where:
475 body - a list of lines with member function bodies
476 meta - a ThunkMetadata instance for hinting which headers are needed.
477 """
[email protected]8c311f02012-11-17 16:01:32478 __pychecker__ = 'unusednames=options'
[email protected]8917a672013-02-25 17:18:04479 out_members = []
[email protected]cba2c4302012-11-20 18:18:13480 meta = ThunkBodyMetadata()
[email protected]8c311f02012-11-17 16:01:32481 for node in filenode.GetListOf('Interface'):
482 # Skip if this node is not in this release
483 if not node.InReleases(releases):
484 print "Skipping %s" % node
485 continue
486
487 # Generate Member functions
488 if node.IsA('Interface'):
[email protected]8917a672013-02-25 17:18:04489 members = node.GetListOf('Member')
490 for child in members:
[email protected]8c311f02012-11-17 16:01:32491 build_list = child.GetUniqueReleases(releases)
492 # We have to filter out releases this node isn't in.
493 build_list = filter(lambda r: child.InReleases([r]), build_list)
494 if len(build_list) == 0:
495 continue
[email protected]8917a672013-02-25 17:18:04496 assert(len(build_list) == 1)
497 release = build_list[-1]
498 include_version = not _IsNewestMember(child, members, releases)
499 member = DefineMember(filenode, node, child, release, include_version,
500 meta)
[email protected]8c311f02012-11-17 16:01:32501 if not member:
502 continue
[email protected]8917a672013-02-25 17:18:04503 out_members.append(member)
504 return (out_members, meta)
[email protected]8c311f02012-11-17 16:01:32505
[email protected]cba2c4302012-11-20 18:18:13506 def WriteTail(self, out, filenode, releases, options):
[email protected]8c311f02012-11-17 16:01:32507 __pychecker__ = 'unusednames=options'
508 cgen = CGen()
509
510 version_list = []
511 out.Write('\n\n')
512 for node in filenode.GetListOf('Interface'):
513 build_list = node.GetUniqueReleases(releases)
514 for build in build_list:
515 version = node.GetVersion(build).replace('.', '_')
516 thunk_name = 'g_' + node.GetName().lower() + '_thunk_' + \
517 version
518 thunk_type = '_'.join((node.GetName(), version))
519 version_list.append((thunk_type, thunk_name))
520
[email protected]8c71647a62013-02-26 19:32:50521 declare_line = 'const %s %s = {' % (thunk_type, thunk_name)
522 if len(declare_line) > 80:
523 declare_line = 'const %s\n %s = {' % (thunk_type, thunk_name)
524 out.Write('%s\n' % declare_line)
[email protected]cfc881d2013-01-03 19:07:46525 generated_functions = []
[email protected]8917a672013-02-25 17:18:04526 members = node.GetListOf('Member')
527 for child in members:
[email protected]8c311f02012-11-17 16:01:32528 rtype, name, arrays, args = cgen.GetComponents(
529 child, build, 'return')
[email protected]8917a672013-02-25 17:18:04530 if not _IsNewestMember(child, members, releases):
531 version = node.GetVersion(build).replace('.', '_')
532 name += '_' + version
[email protected]cfc881d2013-01-03 19:07:46533 if child.InReleases([build]):
534 generated_functions.append(name)
535 out.Write(',\n'.join([' &%s' % f for f in generated_functions]))
536 out.Write('\n};\n\n')
[email protected]8c311f02012-11-17 16:01:32537
538 out.Write('} // namespace\n')
539 out.Write('\n')
540 for thunk_type, thunk_name in version_list:
541 thunk_decl = 'const %s* Get%s_Thunk() {\n' % (thunk_type, thunk_type)
542 if len(thunk_decl) > 80:
543 thunk_decl = 'const %s*\n Get%s_Thunk() {\n' % (thunk_type,
544 thunk_type)
545 out.Write(thunk_decl)
546 out.Write(' return &%s;\n' % thunk_name)
547 out.Write('}\n')
548 out.Write('\n')
549 out.Write('} // namespace thunk\n')
550 out.Write('} // namespace ppapi\n')
551
552
553tgen = TGen()
554
555
556def Main(args):
557 # Default invocation will verify the golden files are unchanged.
558 failed = 0
559 if not args:
560 args = ['--wnone', '--diff', '--test', '--thunkroot=.']
561
562 ParseOptions(args)
563
564 idldir = os.path.split(sys.argv[0])[0]
565 idldir = os.path.join(idldir, 'test_thunk', '*.idl')
566 filenames = glob.glob(idldir)
567 ast = ParseFiles(filenames)
568 if tgen.GenerateRange(ast, ['M13', 'M14'], {}):
569 print "Golden file for M13-M14 failed."
570 failed = 1
571 else:
572 print "Golden file for M13-M14 passed."
573
574 return failed
575
576
577if __name__ == '__main__':
578 sys.exit(Main(sys.argv[1:]))