blob: 584cfaa813871311e8502976b92ef7a58a5e5f21 [file] [log] [blame]
[email protected]38c0f7e2011-06-02 01:16:301#!/usr/bin/python
2#
3# Copyright (c) 2011 The Chromium Authors. All rights reserved.
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6
7""" Generator for C style prototypes and definitions """
8
9import glob
10import os
11import sys
12
13from idl_log import ErrOut, InfoOut, WarnOut
[email protected]5eef2882011-07-19 00:08:5414from idl_node import IDLNode
15from idl_ast import IDLAst
[email protected]38c0f7e2011-06-02 01:16:3016from idl_option import GetOption, Option, ParseOptions
[email protected]5eef2882011-07-19 00:08:5417from idl_parser import ParseFiles
18
19Option('cgen_debug', 'Debug generate.')
20
21class CGenError(Exception):
22 def __init__(self, msg):
[email protected]dbe50942011-11-09 23:19:1923 self.value = msg
[email protected]5eef2882011-07-19 00:08:5424
25 def __str__(self):
26 return repr(self.value)
[email protected]38c0f7e2011-06-02 01:16:3027
28
[email protected]f7314732011-08-24 23:03:0629def CommentLines(lines, tabs=0):
30 # Generate a C style comment block by prepending the block with '<tab>/*'
31 # and adding a '<tab> *' per line.
32 tab = ' ' * tabs
33
34 out = '%s/*' % tab + ('\n%s *' % tab).join(lines)
35
36 # Add a terminating ' */' unless the last line is blank which would mean it
37 # already has ' *'
38 if not lines[-1]:
39 out += '/\n'
40 else:
41 out += ' */\n'
42 return out
43
44def Comment(node, prefix=None, tabs=0):
45 # Generate a comment block from the provided Comment node.
46 comment = node.GetName()
47 lines = comment.split('\n')
48
49 # If an option prefix is provided, then prepend that to the comment
50 # for this node.
51 if prefix:
52 prefix_lines = prefix.split('\n')
53 # If both the prefix and comment start with a blank line ('*') remove
54 # the extra one.
55 if prefix_lines[0] == '*' and lines[0] == '*':
56 lines = prefix_lines + lines[1:]
57 else:
58 lines = prefix_lines + lines;
59 return CommentLines(lines, tabs)
60
[email protected]406793d2011-11-14 22:26:5461def GetNodeComments(node, tabs=0):
[email protected]f7314732011-08-24 23:03:0662 # Generate a comment block joining all comment nodes which are children of
63 # the provided node.
64 comment_txt = ''
65 for doc in node.GetListOf('Comment'):
66 comment_txt += Comment(doc, tabs=tabs)
67 return comment_txt
68
69
[email protected]5eef2882011-07-19 00:08:5470class CGen(object):
71 # TypeMap
72 #
73 # TypeMap modifies how an object is stored or passed, for example pointers
74 # are passed as 'const' if they are 'in' parameters, and structures are
75 # preceeded by the keyword 'struct' as well as using a pointer.
76 #
77 TypeMap = {
78 'Array': {
79 'in': 'const %s',
80 'inout': '%s*',
81 'out': '%s*',
82 'store': '%s',
83 'return': '%s'
84 },
85 'Callspec': {
86 'in': '%s',
87 'inout': '%s',
88 'out': '%s',
89 'store': '%s',
90 'return': '%s'
91 },
92 'Enum': {
93 'in': '%s',
94 'inout': '%s*',
95 'out': '%s*',
96 'store': '%s',
97 'return': '%s'
98 },
99 'Struct': {
100 'in': 'const %s*',
101 'inout': '%s*',
102 'out': '%s*',
103 'return': ' %s*',
104 'store': '%s'
105 },
[email protected]a7f58e82011-09-26 20:53:44106 'blob_t': {
107 'in': 'const %s',
108 'inout': '%s',
109 'out': '%s',
110 'return': '%s',
111 'store': '%s'
112 },
[email protected]5eef2882011-07-19 00:08:54113 'mem_t': {
114 'in': 'const %s',
115 'inout': '%s',
116 'out': '%s',
117 'return': '%s',
118 'store': '%s'
119 },
120 'str_t': {
121 'in': 'const %s',
122 'inout': '%s',
123 'out': '%s',
124 'return': 'const %s',
125 'store': '%s'
126 },
127 'TypeValue': {
128 'in': '%s',
129 'inout': '%s*',
130 'out': '%s*',
131 'return': '%s',
132 'store': '%s'
133 },
[email protected]38c0f7e2011-06-02 01:16:30134 }
135
[email protected]38c0f7e2011-06-02 01:16:30136
[email protected]5eef2882011-07-19 00:08:54137 #
138 # RemapName
139 #
140 # A diction array of PPAPI types that are converted to language specific
141 # types before being returned by by the C generator
142 #
143 RemapName = {
[email protected]a7f58e82011-09-26 20:53:44144 'blob_t': 'void**',
[email protected]5eef2882011-07-19 00:08:54145 'float_t': 'float',
146 'double_t': 'double',
147 'handle_t': 'int',
148 'mem_t': 'void*',
149 'str_t': 'char*',
150 'interface_t' : 'const void*'
151 }
[email protected]38c0f7e2011-06-02 01:16:30152
[email protected]5eef2882011-07-19 00:08:54153 def __init__(self):
154 self.dbg_depth = 0
[email protected]5eef2882011-07-19 00:08:54155
156 #
157 # Debug Logging functions
158 #
159 def Log(self, txt):
160 if not GetOption('cgen_debug'): return
[email protected]406793d2011-11-14 22:26:54161 tabs = ' ' * self.dbg_depth
[email protected]5eef2882011-07-19 00:08:54162 print '%s%s' % (tabs, txt)
163
164 def LogEnter(self, txt):
165 if txt: self.Log(txt)
166 self.dbg_depth += 1
167
168 def LogExit(self, txt):
169 self.dbg_depth -= 1
170 if txt: self.Log(txt)
171
[email protected]406793d2011-11-14 22:26:54172
173 def GetDefine(self, name, value):
174 out = '#define %s %s' % (name, value)
175 if len(out) > 80:
176 out = '#define %s \\\n %s' % (name, value)
177 return '%s\n' % out
178
179 #
180 # Interface strings
181 #
182 def GetMacroHelper(self, node):
183 macro = node.GetProperty('macro')
184 if macro: return macro
185 name = node.GetName()
186 name = name.upper()
187 return "%s_INTERFACE" % name
188
189 def GetInterfaceMacro(self, node, version = None):
190 name = self.GetMacroHelper(node)
191 if version is None:
192 return name
193 return '%s_%s' % (name, str(version).replace('.', '_'))
194
195 def GetInterfaceString(self, node, version = None):
196 # If an interface name is specified, use that
197 name = node.GetProperty('iname')
198 if not name:
199 # Otherwise, the interface name is the object's name
200 # With '_Dev' replaced by '(Dev)' if it's a Dev interface.
201 name = node.GetName()
202 if name.endswith('_Dev'):
203 name = '%s(Dev)' % name[:-4]
204 if version is None:
205 return name
206 return "%s;%s" % (name, version)
207
208
[email protected]5eef2882011-07-19 00:08:54209 #
210 # Return the array specification of the object.
211 #
212 def GetArraySpec(self, node):
213 assert(node.cls == 'Array')
[email protected]5eef2882011-07-19 00:08:54214 fixed = node.GetProperty('FIXED')
215 if fixed:
216 return '[%s]' % fixed
217 else:
218 return '[]'
219
220 #
221 # GetTypeName
222 #
223 # For any valid 'typed' object such as Member or Typedef
224 # the typenode object contains the typename
225 #
226 # For a given node return the type name by passing mode.
227 #
[email protected]f7314732011-08-24 23:03:06228 def GetTypeName(self, node, release, prefix=''):
229 self.LogEnter('GetTypeName of %s rel=%s' % (node, release))
[email protected]5eef2882011-07-19 00:08:54230
[email protected]f7314732011-08-24 23:03:06231 # For Members, Params, and Typedefs get the type it refers to otherwise
232 # the node in question is it's own type (struct, union etc...)
[email protected]5eef2882011-07-19 00:08:54233 if node.IsA('Member', 'Param', 'Typedef'):
[email protected]f7314732011-08-24 23:03:06234 typeref = node.GetType(release)
[email protected]5eef2882011-07-19 00:08:54235 else:
236 typeref = node
237
238 if typeref is None:
239 raise CGenError('No type for %s' % node)
240
241 # If the type is a (BuiltIn) Type then return it's name
242 # remapping as needed
243 if typeref.IsA('Type'):
244 name = CGen.RemapName.get(typeref.GetName(), None)
245 if name is None: name = typeref.GetName()
246 name = '%s%s' % (prefix, name)
247
248 # For structures, preceed with 'struct' or 'union' as appropriate
249 elif typeref.IsA('Interface', 'Struct'):
250 if typeref.GetProperty('union'):
251 name = 'union %s%s' % (prefix, typeref.GetName())
252 else:
253 name = 'struct %s%s' % (prefix, typeref.GetName())
254
255 # If it's an enum, or typedef then return the Enum's name
256 elif typeref.IsA('Enum', 'Typedef'):
[email protected]03f41ec2011-11-18 22:53:04257 # The enum may have skipped having a typedef, we need prefix with 'enum'.
258 if typeref.GetProperty('notypedef'):
259 name = 'enum %s%s' % (prefix, typeref.GetName())
260 else:
261 name = '%s%s' % (prefix, typeref.GetName())
[email protected]5eef2882011-07-19 00:08:54262
263 else:
264 raise RuntimeError('Getting name of non-type %s.' % node)
265 self.LogExit('GetTypeName %s is %s' % (node, name))
266 return name
267
268
269 #
270 # GetRootType
271 #
272 # For a given node return basic type of that object. This is
273 # either a 'Type', 'Callspec', or 'Array'
274 #
[email protected]f7314732011-08-24 23:03:06275 def GetRootTypeMode(self, node, release, mode):
[email protected]5eef2882011-07-19 00:08:54276 self.LogEnter('GetRootType of %s' % node)
277 # If it has an array spec, then treat it as an array regardless of type
278 if node.GetOneOf('Array'):
279 rootType = 'Array'
280 # Or if it has a callspec, treat it as a function
281 elif node.GetOneOf('Callspec'):
[email protected]f7314732011-08-24 23:03:06282 rootType, mode = self.GetRootTypeMode(node.GetType(release), release,
[email protected]5eef2882011-07-19 00:08:54283 'return')
284
285 # If it's a plain typedef, try that object's root type
286 elif node.IsA('Member', 'Param', 'Typedef'):
[email protected]f7314732011-08-24 23:03:06287 rootType, mode = self.GetRootTypeMode(node.GetType(release),
288 release, mode)
[email protected]5eef2882011-07-19 00:08:54289
290 # If it's an Enum, then it's normal passing rules
291 elif node.IsA('Enum'):
292 rootType = node.cls
293
294 # If it's an Interface or Struct, we may be passing by value
295 elif node.IsA('Interface', 'Struct'):
296 if mode == 'return':
297 if node.GetProperty('returnByValue'):
298 rootType = 'TypeValue'
299 else:
300 rootType = node.cls
301 else:
302 if node.GetProperty('passByValue'):
303 rootType = 'TypeValue'
304 else:
305 rootType = node.cls
306
307 # If it's an Basic Type, check if it's a special type
308 elif node.IsA('Type'):
309 if node.GetName() in CGen.TypeMap:
310 rootType = node.GetName()
311 else:
312 rootType = 'TypeValue'
313 else:
314 raise RuntimeError('Getting root type of non-type %s.' % node)
315 self.LogExit('RootType is "%s"' % rootType)
316 return rootType, mode
317
318
[email protected]f7314732011-08-24 23:03:06319 def GetTypeByMode(self, node, release, mode):
320 self.LogEnter('GetTypeByMode of %s mode=%s release=%s' %
321 (node, mode, release))
322 name = self.GetTypeName(node, release)
323 ntype, mode = self.GetRootTypeMode(node, release, mode)
[email protected]ec5af272011-07-19 01:21:53324 out = CGen.TypeMap[ntype][mode] % name
[email protected]5eef2882011-07-19 00:08:54325 self.LogExit('GetTypeByMode %s = %s' % (node, out))
326 return out
327
328
329 # Get the passing mode of the object (in, out, inout).
330 def GetParamMode(self, node):
331 self.Log('GetParamMode for %s' % node)
332 if node.GetProperty('in'): return 'in'
333 if node.GetProperty('out'): return 'out'
334 if node.GetProperty('inout'): return 'inout'
335 return 'return'
336
337 #
338 # GetComponents
339 #
340 # Returns the signature components of an object as a tuple of
341 # (rtype, name, arrays, callspec) where:
342 # rtype - The store or return type of the object.
343 # name - The name of the object.
344 # arrays - A list of array dimensions as [] or [<fixed_num>].
345 # args - None of not a function, otherwise a list of parameters.
346 #
[email protected]f7314732011-08-24 23:03:06347 def GetComponents(self, node, release, mode):
348 self.LogEnter('GetComponents mode %s for %s %s' % (mode, node, release))
[email protected]5eef2882011-07-19 00:08:54349
350 # Generate passing type by modifying root type
[email protected]f7314732011-08-24 23:03:06351 rtype = self.GetTypeByMode(node, release, mode)
[email protected]5eef2882011-07-19 00:08:54352 if node.IsA('Enum', 'Interface', 'Struct'):
353 rname = node.GetName()
354 else:
[email protected]f7314732011-08-24 23:03:06355 rname = node.GetType(release).GetName()
[email protected]5eef2882011-07-19 00:08:54356
357 if rname in CGen.RemapName:
358 rname = CGen.RemapName[rname]
359 if '%' in rtype:
360 rtype = rtype % rname
361 name = node.GetName()
362 arrayspec = [self.GetArraySpec(array) for array in node.GetListOf('Array')]
363 callnode = node.GetOneOf('Callspec')
364 if callnode:
365 callspec = []
366 for param in callnode.GetListOf('Param'):
367 mode = self.GetParamMode(param)
[email protected]f7314732011-08-24 23:03:06368 ptype, pname, parray, pspec = self.GetComponents(param, release, mode)
[email protected]5eef2882011-07-19 00:08:54369 callspec.append((ptype, pname, parray, pspec))
370 else:
371 callspec = None
372
373 self.LogExit('GetComponents: %s, %s, %s, %s' %
374 (rtype, name, arrayspec, callspec))
375 return (rtype, name, arrayspec, callspec)
376
377
378 def Compose(self, rtype, name, arrayspec, callspec, prefix, func_as_ptr):
379 self.LogEnter('Compose: %s %s' % (rtype, name))
380 arrayspec = ''.join(arrayspec)
381 name = '%s%s%s' % (prefix, name, arrayspec)
382 if callspec is None:
383 out = '%s %s' % (rtype, name)
384 else:
385 params = []
386 for ptype, pname, parray, pspec in callspec:
387 params.append(self.Compose(ptype, pname, parray, pspec, '', True))
388 if func_as_ptr: name = '(*%s)' % name
389 out = '%s %s(%s)' % (rtype, name, ', '.join(params))
390 self.LogExit('Exit Compose: %s' % out)
391 return out
392
393 #
394 # GetSignature
395 #
396 # Returns the 'C' style signature of the object
397 # prefix - A prefix for the object's name
398 # func_as_ptr - Formats a function as a function pointer
399 #
[email protected]f7314732011-08-24 23:03:06400 def GetSignature(self, node, release, mode, prefix='', func_as_ptr=True):
[email protected]5eef2882011-07-19 00:08:54401 self.LogEnter('GetSignature %s %s as func=%s' % (node, mode, func_as_ptr))
[email protected]f7314732011-08-24 23:03:06402 rtype, name, arrayspec, callspec = self.GetComponents(node, release, mode)
[email protected]5eef2882011-07-19 00:08:54403 out = self.Compose(rtype, name, arrayspec, callspec, prefix, func_as_ptr)
404 self.LogExit('Exit GetSignature: %s' % out)
405 return out
406
[email protected]f7314732011-08-24 23:03:06407 # Define a Typedef.
408 def DefineTypedef(self, node, releases, prefix='', comment=False):
[email protected]406793d2011-11-14 22:26:54409 __pychecker__ = 'unusednames=comment'
[email protected]f7314732011-08-24 23:03:06410 release = releases[0]
411 out = 'typedef %s;\n' % self.GetSignature(node, release, 'return',
412 prefix, True)
[email protected]5eef2882011-07-19 00:08:54413 self.Log('DefineTypedef: %s' % out)
414 return out
415
416 # Define an Enum.
[email protected]f7314732011-08-24 23:03:06417 def DefineEnum(self, node, releases, prefix='', comment=False):
[email protected]406793d2011-11-14 22:26:54418 __pychecker__ = 'unusednames=comment,releases'
[email protected]5eef2882011-07-19 00:08:54419 self.LogEnter('DefineEnum %s' % node)
[email protected]03f41ec2011-11-18 22:53:04420 name = '%s%s' % (prefix, node.GetName())
421 notypedef = node.GetProperty('notypedef')
422 unnamed = node.GetProperty('unnamed')
[email protected]5eef2882011-07-19 00:08:54423 if unnamed:
424 out = 'enum {'
[email protected]03f41ec2011-11-18 22:53:04425 elif notypedef:
426 out = 'enum %s {' % name
[email protected]5eef2882011-07-19 00:08:54427 else:
428 out = 'typedef enum {'
[email protected]5eef2882011-07-19 00:08:54429 enumlist = []
430 for child in node.GetListOf('EnumItem'):
431 value = child.GetProperty('VALUE')
[email protected]f7314732011-08-24 23:03:06432 comment_txt = GetNodeComments(child, tabs=1)
[email protected]5eef2882011-07-19 00:08:54433 if value:
434 item_txt = '%s%s = %s' % (prefix, child.GetName(), value)
435 else:
436 item_txt = '%s%s' % (prefix, child.GetName())
437 enumlist.append('%s %s' % (comment_txt, item_txt))
438 self.LogExit('Exit DefineEnum')
439
[email protected]03f41ec2011-11-18 22:53:04440 if unnamed or notypedef:
[email protected]5eef2882011-07-19 00:08:54441 out = '%s\n%s\n};\n' % (out, ',\n'.join(enumlist))
442 else:
443 out = '%s\n%s\n} %s;\n' % (out, ',\n'.join(enumlist), name)
444 return out
445
[email protected]f7314732011-08-24 23:03:06446 def DefineMember(self, node, releases, prefix='', comment=False):
[email protected]406793d2011-11-14 22:26:54447 __pychecker__ = 'unusednames=prefix,comment'
[email protected]f7314732011-08-24 23:03:06448 release = releases[0]
[email protected]5eef2882011-07-19 00:08:54449 self.LogEnter('DefineMember %s' % node)
[email protected]f7314732011-08-24 23:03:06450 out = '%s;' % self.GetSignature(node, release, 'store', '', True)
[email protected]5eef2882011-07-19 00:08:54451 self.LogExit('Exit DefineMember')
452 return out
453
[email protected]e8a83feb2011-08-25 21:04:26454 def DefineStructInternals(self, node, release, suffix='', comment=True):
[email protected]5eef2882011-07-19 00:08:54455 out = ''
[email protected]5eef2882011-07-19 00:08:54456 if node.GetProperty('union'):
[email protected]e8a83feb2011-08-25 21:04:26457 out += 'union %s%s {\n' % (node.GetName(), suffix)
[email protected]5eef2882011-07-19 00:08:54458 else:
[email protected]e8a83feb2011-08-25 21:04:26459 out += 'struct %s%s {\n' % (node.GetName(), suffix)
[email protected]5eef2882011-07-19 00:08:54460
461 # Generate Member Functions
462 members = []
463 for child in node.GetListOf('Member'):
[email protected]e8a83feb2011-08-25 21:04:26464 member = self.Define(child, [release], tabs=1, comment=comment)
[email protected]5eef2882011-07-19 00:08:54465 if not member:
466 continue
467 members.append(member)
468 out += '%s\n};\n' % '\n'.join(members)
[email protected]e8a83feb2011-08-25 21:04:26469 return out
470
471
472 def DefineStruct(self, node, releases, prefix='', comment=False):
[email protected]406793d2011-11-14 22:26:54473 __pychecker__ = 'unusednames=comment,prefix'
[email protected]e8a83feb2011-08-25 21:04:26474 self.LogEnter('DefineStruct %s' % node)
475 out = ''
476 build_list = node.GetUniqueReleases(releases)
477
478 # Build the most recent one with comments
479 out = self.DefineStructInternals(node, build_list[-1], comment=True)
480
481 # Build the rest without comments and with the version number appended
482 for rel in build_list[0:-1]:
483 ver_num = node.GetVersion(rel)
484 ver = ("_%s" % ver_num).replace('.', '_')
485 out += '\n' + self.DefineStructInternals(node, rel, suffix=ver,
486 comment=False)
487
[email protected]5eef2882011-07-19 00:08:54488 self.LogExit('Exit DefineStruct')
489 return out
490
[email protected]e8a83feb2011-08-25 21:04:26491
[email protected]5eef2882011-07-19 00:08:54492 #
493 # Copyright and Comment
494 #
495 # Generate a comment or copyright block
496 #
497 def Copyright(self, node, tabs=0):
498 lines = node.GetName().split('\n')
[email protected]f7314732011-08-24 23:03:06499 return CommentLines(lines, tabs)
[email protected]5eef2882011-07-19 00:08:54500
501
502 # Define a top level object.
[email protected]f7314732011-08-24 23:03:06503 def Define(self, node, releases, tabs=0, prefix='', comment=False):
504 if not node.InReleases(releases):
[email protected]5eef2882011-07-19 00:08:54505 return ''
[email protected]38c0f7e2011-06-02 01:16:30506
[email protected]f7314732011-08-24 23:03:06507 self.LogEnter('Define %s tab=%d prefix="%s"' % (node,tabs,prefix))
[email protected]406793d2011-11-14 22:26:54508 declmap = dict({
509 'Enum': CGen.DefineEnum,
510 'Function': CGen.DefineMember,
511 'Interface': CGen.DefineStruct,
512 'Member': CGen.DefineMember,
513 'Struct': CGen.DefineStruct,
514 'Typedef': CGen.DefineTypedef
515 })
[email protected]f7314732011-08-24 23:03:06516
517 out = ''
[email protected]406793d2011-11-14 22:26:54518 func = declmap.get(node.cls, None)
[email protected]f7314732011-08-24 23:03:06519 if not func:
520 ErrOut.Log('Failed to define %s named %s' % (node.cls, node.GetName()))
521 define_txt = func(self, node, releases, prefix=prefix, comment=comment)
522
523 comment_txt = GetNodeComments(node, tabs=0)
524 if comment_txt and comment:
525 out += comment_txt
526 out += define_txt
527
528 tab = ' ' * tabs
529 lines = []
530 for line in out.split('\n'):
531 # Add indentation
532 line = tab + line
533 if len(line) > 80:
534 left = line.rfind('(') + 1
535 args = line[left:].split(',')
536 line_max = 0
537 for arg in args:
538 if len(arg) > line_max: line_max = len(arg)
539
540 if left + line_max >= 80:
541 space = '%s ' % tab
542 args = (',\n%s' % space).join([arg.strip() for arg in args])
543 lines.append('%s\n%s%s' % (line[:left], space, args))
544 else:
545 space = ' ' * (left - 1)
546 args = (',\n%s' % space).join(args)
547 lines.append('%s%s' % (line[:left], args))
548 else:
549 lines.append(line.rstrip())
550 self.LogExit('Exit Define')
551 return '\n'.join(lines)
552
[email protected]38c0f7e2011-06-02 01:16:30553# Clean a string representing an object definition and return then string
554# as a single space delimited set of tokens.
555def CleanString(instr):
556 instr = instr.strip()
557 instr = instr.split()
558 return ' '.join(instr)
559
560
561# Test a file, by comparing all it's objects, with their comments.
562def TestFile(filenode):
[email protected]5eef2882011-07-19 00:08:54563 cgen = CGen()
564
[email protected]38c0f7e2011-06-02 01:16:30565 errors = 0
[email protected]5eef2882011-07-19 00:08:54566 for node in filenode.GetChildren()[2:]:
[email protected]38c0f7e2011-06-02 01:16:30567 instr = node.GetOneOf('Comment')
[email protected]5eef2882011-07-19 00:08:54568 if not instr: continue
569 instr.Dump()
570 instr = CleanString(instr.GetName())
[email protected]38c0f7e2011-06-02 01:16:30571
[email protected]f7314732011-08-24 23:03:06572 outstr = cgen.Define(node, releases=['M14'])
[email protected]5eef2882011-07-19 00:08:54573 if GetOption('verbose'):
574 print outstr + '\n'
[email protected]38c0f7e2011-06-02 01:16:30575 outstr = CleanString(outstr)
576
577 if instr != outstr:
578 ErrOut.Log('Failed match of\n>>%s<<\n>>%s<<\nto:' % (instr, outstr))
579 node.Dump(1, comments=True)
580 errors += 1
581 return errors
582
583
[email protected]38c0f7e2011-06-02 01:16:30584# Build and resolve the AST and compare each file individual.
585def TestFiles(filenames):
586 if not filenames:
587 idldir = os.path.split(sys.argv[0])[0]
588 idldir = os.path.join(idldir, 'test_cgen', '*.idl')
589 filenames = glob.glob(idldir)
590
591 filenames = sorted(filenames)
[email protected]5eef2882011-07-19 00:08:54592 ast = ParseFiles(filenames)
[email protected]38c0f7e2011-06-02 01:16:30593
594 total_errs = 0
[email protected]5eef2882011-07-19 00:08:54595 for filenode in ast.GetListOf('File'):
[email protected]38c0f7e2011-06-02 01:16:30596 errs = TestFile(filenode)
597 if errs:
[email protected]5eef2882011-07-19 00:08:54598 ErrOut.Log('%s test failed with %d error(s).' %
599 (filenode.GetName(), errs))
[email protected]38c0f7e2011-06-02 01:16:30600 total_errs += errs
601
602 if total_errs:
[email protected]f0dd202f2011-06-07 01:36:01603 ErrOut.Log('Failed generator test.')
[email protected]38c0f7e2011-06-02 01:16:30604 else:
[email protected]f0dd202f2011-06-07 01:36:01605 InfoOut.Log('Passed generator test.')
[email protected]38c0f7e2011-06-02 01:16:30606 return total_errs
607
[email protected]38c0f7e2011-06-02 01:16:30608def Main(args):
609 filenames = ParseOptions(args)
[email protected]5eef2882011-07-19 00:08:54610 if GetOption('test'):
611 return TestFiles(filenames)
612 ast = ParseFiles(filenames)
613 for f in ast.GetListOf('File'):
614 if f.GetProperty('ERRORS') > 0:
615 print 'Skipping %s' % f.GetName()
616 continue
617 print DefineDepends(node)
618 for node in f.GetChildren()[2:]:
619 print Define(node, comment=True, prefix='tst_')
620
[email protected]38c0f7e2011-06-02 01:16:30621
622if __name__ == '__main__':
623 sys.exit(Main(sys.argv[1:]))