blob: 7159412e15077cd5b43e17e36f6e7746edd33bfd [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]a3887962013-04-16 21:02:16282 body = '%s\n' % _MakeEnterLine(filenode, node, member, args[0],
283 handle_errors, args[len(args) - 1][1], meta)
[email protected]135f5942013-04-19 14:25:18284 failure_value = member.GetProperty('on_failure')
285 if failure_value is None:
286 failure_value = 'enter.retval()'
287 failure_return = 'return %s;' % failure_value
288 success_return = 'return enter.SetResult(%s);' % invocation
[email protected]8c311f02012-11-17 16:01:32289 elif rtype == 'void':
[email protected]a3887962013-04-16 21:02:16290 body = '%s\n' % _MakeEnterLine(filenode, node, member, args[0],
291 handle_errors, None, meta)
[email protected]135f5942013-04-19 14:25:18292 failure_return = 'return;'
293 success_return = '%s;' % invocation # We don't return anything for void.
[email protected]8c311f02012-11-17 16:01:32294 else:
[email protected]a3887962013-04-16 21:02:16295 body = '%s\n' % _MakeEnterLine(filenode, node, member, args[0],
296 handle_errors, None, meta)
[email protected]135f5942013-04-19 14:25:18297 failure_value = member.GetProperty('on_failure')
298 if failure_value is None:
299 failure_value = _GetDefaultFailureValue(rtype)
300 if failure_value is None:
301 raise TGenError('There is no default value for rtype %s. '
302 'Maybe you should provide an on_failure attribute '
303 'in the IDL file.' % rtype)
304 failure_return = 'return %s;' % failure_value
305 success_return = 'return %s;' % invocation
306
307 if member.GetProperty('always_set_output_parameters'):
308 body += 'if (enter.failed()) {\n'
309 for param in out_params:
310 body += ' memset(%s, 0, sizeof(*%s));\n' % (param, param)
311 body += ' %s\n' % failure_return
312 body += '}\n'
313 body += '%s' % success_return
314 meta.AddBuiltinInclude('string.h')
315 else:
316 body += 'if (enter.failed())\n'
317 body += ' %s\n' % failure_return
318 body += '%s' % success_return
[email protected]8c311f02012-11-17 16:01:32319 return body
320
321
[email protected]cba2c4302012-11-20 18:18:13322def DefineMember(filenode, node, member, release, include_version, meta):
[email protected]8c311f02012-11-17 16:01:32323 """Returns a definition for a member function of an interface.
324
325 Args:
326 filenode - IDLNode for the file
327 node - IDLNode for the interface
328 member - IDLNode for the member function
329 release - release to generate
330 include_version - include the version in emitted function name.
[email protected]cba2c4302012-11-20 18:18:13331 meta - ThunkMetadata for header hints
[email protected]8c311f02012-11-17 16:01:32332 Returns:
333 A string with the member definition.
334 """
335 cgen = CGen()
336 rtype, name, arrays, args = cgen.GetComponents(member, release, 'return')
[email protected]03f8b542013-04-02 17:57:50337 body = 'VLOG(4) << \"%s::%s()\";\n' % (node.GetName(), member.GetName())
[email protected]8c311f02012-11-17 16:01:32338
339 if _IsTypeCheck(node, member):
[email protected]a3887962013-04-16 21:02:16340 body += '%s\n' % _MakeEnterLine(filenode, node, member, args[0], False,
341 None, meta)
[email protected]8917a672013-02-25 17:18:04342 body += 'return PP_FromBool(enter.succeeded());'
[email protected]8c311f02012-11-17 16:01:32343 elif member.GetName() == 'Create':
[email protected]03f8b542013-04-02 17:57:50344 body += _MakeCreateMemberBody(node, member, args)
[email protected]8c311f02012-11-17 16:01:32345 else:
[email protected]03f8b542013-04-02 17:57:50346 body += _MakeNormalMemberBody(filenode, release, node, member, rtype, args,
347 include_version, meta)
[email protected]8c311f02012-11-17 16:01:32348
349 signature = cgen.GetSignature(member, release, 'return', func_as_ptr=False,
350 include_version=include_version)
[email protected]8917a672013-02-25 17:18:04351 return '%s\n%s\n}' % (cgen.Indent('%s {' % signature, tabs=0),
352 cgen.Indent(body, tabs=1))
353
354
355def _IsNewestMember(member, members, releases):
356 """Returns true if member is the newest node with its name in members.
357
358 Currently, every node in the AST only has one version. This means that we
359 will have two sibling nodes with the same name to represent different
360 versions.
361 See http://crbug.com/157017 .
362
363 Special handling is required for nodes which share their name with others,
364 but aren't the newest version in the IDL.
365
366 Args:
367 member - The member which is checked if it's newest
368 members - The list of members to inspect
369 releases - The set of releases to check for versions in.
370 """
371 build_list = member.GetUniqueReleases(releases)
[email protected]ba054c02013-02-26 23:27:18372 release = build_list[0] # Pick the oldest release.
[email protected]8917a672013-02-25 17:18:04373 same_name_siblings = filter(
374 lambda n: str(n) == str(member) and n != member, members)
375
376 for s in same_name_siblings:
377 sibling_build_list = s.GetUniqueReleases(releases)
[email protected]ba054c02013-02-26 23:27:18378 sibling_release = sibling_build_list[0]
[email protected]8917a672013-02-25 17:18:04379 if sibling_release > release:
380 return False
381 return True
[email protected]8c311f02012-11-17 16:01:32382
383
384class TGen(GeneratorByFile):
385 def __init__(self):
386 Generator.__init__(self, 'Thunk', 'tgen', 'Generate the C++ thunk.')
387
388 def GenerateFile(self, filenode, releases, options):
389 savename = _GetThunkFileName(filenode, GetOption('thunkroot'))
390 my_min, my_max = filenode.GetMinMax(releases)
391 if my_min > releases[-1] or my_max < releases[0]:
392 if os.path.isfile(savename):
393 print "Removing stale %s for this range." % filenode.GetName()
394 os.remove(os.path.realpath(savename))
395 return False
396 do_generate = filenode.GetProperty('generate_thunk')
397 if not do_generate:
398 return False
399
400 thunk_out = IDLOutFile(savename)
[email protected]cba2c4302012-11-20 18:18:13401 body, meta = self.GenerateBody(thunk_out, filenode, releases, options)
[email protected]a3887962013-04-16 21:02:16402 # TODO(teravest): How do we handle repeated values?
403 if filenode.GetProperty('thunk_include'):
404 meta.AddInclude(filenode.GetProperty('thunk_include'))
[email protected]cba2c4302012-11-20 18:18:13405 self.WriteHead(thunk_out, filenode, releases, options, meta)
406 thunk_out.Write('\n\n'.join(body))
407 self.WriteTail(thunk_out, filenode, releases, options)
[email protected]8c311f02012-11-17 16:01:32408 return thunk_out.Close()
409
[email protected]cba2c4302012-11-20 18:18:13410 def WriteHead(self, out, filenode, releases, options, meta):
[email protected]8c311f02012-11-17 16:01:32411 __pychecker__ = 'unusednames=options'
412 cgen = CGen()
413
414 cright_node = filenode.GetChildren()[0]
415 assert(cright_node.IsA('Copyright'))
416 out.Write('%s\n' % cgen.Copyright(cright_node, cpp_style=True))
417
418 # Wrap the From ... modified ... comment if it would be >80 characters.
419 from_text = 'From %s' % (
420 filenode.GetProperty('NAME').replace(os.sep,'/'))
421 modified_text = 'modified %s.' % (
422 filenode.GetProperty('DATETIME'))
423 if len(from_text) + len(modified_text) < 74:
424 out.Write('// %s %s\n\n' % (from_text, modified_text))
425 else:
426 out.Write('// %s,\n// %s\n\n' % (from_text, modified_text))
427
[email protected]2a7e8c52013-03-30 00:13:25428 if meta.BuiltinIncludes():
429 for include in sorted(meta.BuiltinIncludes()):
430 out.Write('#include <%s>\n' % include)
431 out.Write('\n')
[email protected]8c311f02012-11-17 16:01:32432
433 # TODO(teravest): Don't emit includes we don't need.
434 includes = ['ppapi/c/pp_errors.h',
435 'ppapi/shared_impl/tracked_callback.h',
436 'ppapi/thunk/enter.h',
437 'ppapi/thunk/ppb_instance_api.h',
438 'ppapi/thunk/resource_creation_api.h',
439 'ppapi/thunk/thunk.h']
440 includes.append(_GetHeaderFileName(filenode))
[email protected]cba2c4302012-11-20 18:18:13441 for api in meta.Apis():
442 includes.append('ppapi/thunk/%s.h' % api.lower())
[email protected]8f2a08d52012-12-08 00:10:50443 for i in meta.Includes():
444 includes.append(i)
[email protected]8c311f02012-11-17 16:01:32445 for include in sorted(includes):
446 out.Write('#include "%s"\n' % include)
447 out.Write('\n')
448 out.Write('namespace ppapi {\n')
449 out.Write('namespace thunk {\n')
450 out.Write('\n')
451 out.Write('namespace {\n')
452 out.Write('\n')
453
454 def GenerateBody(self, out, filenode, releases, options):
[email protected]cba2c4302012-11-20 18:18:13455 """Generates a member function lines to be written and metadata.
456
457 Returns a tuple of (body, meta) where:
458 body - a list of lines with member function bodies
459 meta - a ThunkMetadata instance for hinting which headers are needed.
460 """
[email protected]8c311f02012-11-17 16:01:32461 __pychecker__ = 'unusednames=options'
[email protected]8917a672013-02-25 17:18:04462 out_members = []
[email protected]cba2c4302012-11-20 18:18:13463 meta = ThunkBodyMetadata()
[email protected]8c311f02012-11-17 16:01:32464 for node in filenode.GetListOf('Interface'):
465 # Skip if this node is not in this release
466 if not node.InReleases(releases):
467 print "Skipping %s" % node
468 continue
469
470 # Generate Member functions
471 if node.IsA('Interface'):
[email protected]8917a672013-02-25 17:18:04472 members = node.GetListOf('Member')
473 for child in members:
[email protected]8c311f02012-11-17 16:01:32474 build_list = child.GetUniqueReleases(releases)
475 # We have to filter out releases this node isn't in.
476 build_list = filter(lambda r: child.InReleases([r]), build_list)
477 if len(build_list) == 0:
478 continue
[email protected]8917a672013-02-25 17:18:04479 assert(len(build_list) == 1)
480 release = build_list[-1]
481 include_version = not _IsNewestMember(child, members, releases)
482 member = DefineMember(filenode, node, child, release, include_version,
483 meta)
[email protected]8c311f02012-11-17 16:01:32484 if not member:
485 continue
[email protected]8917a672013-02-25 17:18:04486 out_members.append(member)
487 return (out_members, meta)
[email protected]8c311f02012-11-17 16:01:32488
[email protected]cba2c4302012-11-20 18:18:13489 def WriteTail(self, out, filenode, releases, options):
[email protected]8c311f02012-11-17 16:01:32490 __pychecker__ = 'unusednames=options'
491 cgen = CGen()
492
493 version_list = []
494 out.Write('\n\n')
495 for node in filenode.GetListOf('Interface'):
496 build_list = node.GetUniqueReleases(releases)
497 for build in build_list:
498 version = node.GetVersion(build).replace('.', '_')
499 thunk_name = 'g_' + node.GetName().lower() + '_thunk_' + \
500 version
501 thunk_type = '_'.join((node.GetName(), version))
502 version_list.append((thunk_type, thunk_name))
503
[email protected]8c71647a62013-02-26 19:32:50504 declare_line = 'const %s %s = {' % (thunk_type, thunk_name)
505 if len(declare_line) > 80:
506 declare_line = 'const %s\n %s = {' % (thunk_type, thunk_name)
507 out.Write('%s\n' % declare_line)
[email protected]cfc881d2013-01-03 19:07:46508 generated_functions = []
[email protected]8917a672013-02-25 17:18:04509 members = node.GetListOf('Member')
510 for child in members:
[email protected]8c311f02012-11-17 16:01:32511 rtype, name, arrays, args = cgen.GetComponents(
512 child, build, 'return')
[email protected]8917a672013-02-25 17:18:04513 if not _IsNewestMember(child, members, releases):
514 version = node.GetVersion(build).replace('.', '_')
515 name += '_' + version
[email protected]cfc881d2013-01-03 19:07:46516 if child.InReleases([build]):
517 generated_functions.append(name)
518 out.Write(',\n'.join([' &%s' % f for f in generated_functions]))
519 out.Write('\n};\n\n')
[email protected]8c311f02012-11-17 16:01:32520
521 out.Write('} // namespace\n')
522 out.Write('\n')
523 for thunk_type, thunk_name in version_list:
524 thunk_decl = 'const %s* Get%s_Thunk() {\n' % (thunk_type, thunk_type)
525 if len(thunk_decl) > 80:
526 thunk_decl = 'const %s*\n Get%s_Thunk() {\n' % (thunk_type,
527 thunk_type)
528 out.Write(thunk_decl)
529 out.Write(' return &%s;\n' % thunk_name)
530 out.Write('}\n')
531 out.Write('\n')
532 out.Write('} // namespace thunk\n')
533 out.Write('} // namespace ppapi\n')
534
535
536tgen = TGen()
537
538
539def Main(args):
540 # Default invocation will verify the golden files are unchanged.
541 failed = 0
542 if not args:
543 args = ['--wnone', '--diff', '--test', '--thunkroot=.']
544
545 ParseOptions(args)
546
547 idldir = os.path.split(sys.argv[0])[0]
548 idldir = os.path.join(idldir, 'test_thunk', '*.idl')
549 filenames = glob.glob(idldir)
550 ast = ParseFiles(filenames)
551 if tgen.GenerateRange(ast, ['M13', 'M14'], {}):
552 print "Golden file for M13-M14 failed."
553 failed = 1
554 else:
555 print "Golden file for M13-M14 passed."
556
557 return failed
558
559
560if __name__ == '__main__':
561 sys.exit(Main(sys.argv[1:]))