- add sources.
[platform/framework/web/crosswalk.git] / src / ppapi / generators / idl_c_proto.py
1 #!/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 prototypes and definitions """
7
8 import glob
9 import os
10 import sys
11
12 from idl_log import ErrOut, InfoOut, WarnOut
13 from idl_node import IDLNode
14 from idl_ast import IDLAst
15 from idl_option import GetOption, Option, ParseOptions
16 from idl_parser import ParseFiles
17
18 Option('cgen_debug', 'Debug generate.')
19
20 class CGenError(Exception):
21   def __init__(self, msg):
22     self.value = msg
23
24   def __str__(self):
25     return repr(self.value)
26
27
28 def CommentLines(lines, tabs=0):
29   # Generate a C style comment block by prepending the block with '<tab>/*'
30   # and adding a '<tab> *' per line.
31   tab = '  ' * tabs
32
33   out = '%s/*' % tab + ('\n%s *' % tab).join(lines)
34
35   # Add a terminating ' */' unless the last line is blank which would mean it
36   # already has ' *'
37   if not lines[-1]:
38     out += '/\n'
39   else:
40     out += ' */\n'
41   return out
42
43 def Comment(node, prefix=None, tabs=0):
44   # Generate a comment block from the provided Comment node.
45   comment = node.GetName()
46   lines = comment.split('\n')
47
48   # If an option prefix is provided, then prepend that to the comment
49   # for this node.
50   if prefix:
51     prefix_lines = prefix.split('\n')
52     # If both the prefix and comment start with a blank line ('*') remove
53     # the extra one.
54     if prefix_lines[0] == '*' and lines[0] == '*':
55       lines = prefix_lines + lines[1:]
56     else:
57       lines = prefix_lines + lines;
58   return CommentLines(lines, tabs)
59
60 def GetNodeComments(node, tabs=0):
61   # Generate a comment block joining all comment nodes which are children of
62   # the provided node.
63   comment_txt = ''
64   for doc in node.GetListOf('Comment'):
65     comment_txt += Comment(doc, tabs=tabs)
66   return comment_txt
67
68
69 class CGen(object):
70   # TypeMap
71   #
72   # TypeMap modifies how an object is stored or passed, for example pointers
73   # are passed as 'const' if they are 'in' parameters, and structures are
74   # preceeded by the keyword 'struct' as well as using a pointer.
75   #
76   TypeMap = {
77     'Array': {
78       'in': 'const %s',
79       'inout': '%s',
80       'out': '%s*',
81       'store': '%s',
82       'return': '%s',
83       'ref': '%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     'Interface': {
100       'in': 'const %s*',
101       'inout': '%s*',
102       'out': '%s**',
103       'return': '%s*',
104       'store': '%s*'
105     },
106     'Struct': {
107       'in': 'const %s*',
108       'inout': '%s*',
109       'out': '%s*',
110       'return': ' %s*',
111       'store': '%s',
112       'ref': '%s*'
113     },
114     'blob_t': {
115       'in': 'const %s',
116       'inout': '%s',
117       'out': '%s',
118       'return': '%s',
119       'store': '%s'
120     },
121     'mem_t': {
122       'in': 'const %s',
123       'inout': '%s',
124       'out': '%s',
125       'return': '%s',
126       'store': '%s'
127     },
128     'mem_ptr_t': {
129       'in': 'const %s',
130       'inout': '%s',
131       'out': '%s',
132       'return': '%s',
133       'store': '%s'
134     },
135     'str_t': {
136       'in': 'const %s',
137       'inout': '%s',
138       'out': '%s',
139       'return': 'const %s',
140       'store': '%s'
141     },
142     'cstr_t': {
143       'in': '%s',
144       'inout': '%s*',
145       'out': '%s*',
146       'return': '%s',
147       'store': '%s'
148     },
149     'TypeValue': {
150       'in': '%s',
151       'inout': '%s*',
152       'out': '%s*',
153       'return': '%s',
154       'store': '%s'
155     },
156   }
157
158
159   #
160   # RemapName
161   #
162   # A diction array of PPAPI types that are converted to language specific
163   # types before being returned by by the C generator
164   #
165   RemapName = {
166   'blob_t': 'void**',
167   'float_t': 'float',
168   'double_t': 'double',
169   'handle_t': 'int',
170   'mem_t': 'void*',
171   'mem_ptr_t': 'void**',
172   'str_t': 'char*',
173   'cstr_t': 'const char*',
174   'interface_t' : 'const void*'
175   }
176
177   def __init__(self):
178     self.dbg_depth = 0
179
180   #
181   # Debug Logging functions
182   #
183   def Log(self, txt):
184     if not GetOption('cgen_debug'): return
185     tabs = '  ' * self.dbg_depth
186     print '%s%s' % (tabs, txt)
187
188   def LogEnter(self, txt):
189     if txt: self.Log(txt)
190     self.dbg_depth += 1
191
192   def LogExit(self, txt):
193     self.dbg_depth -= 1
194     if txt: self.Log(txt)
195
196
197   def GetDefine(self, name, value):
198     out = '#define %s %s' % (name, value)
199     if len(out) > 80:
200       out = '#define %s \\\n    %s' % (name, value)
201     return '%s\n' % out
202
203   #
204   # Interface strings
205   #
206   def GetMacroHelper(self, node):
207     macro = node.GetProperty('macro')
208     if macro: return macro
209     name = node.GetName()
210     name = name.upper()
211     return "%s_INTERFACE" % name
212
213   def GetInterfaceMacro(self, node, version = None):
214     name = self.GetMacroHelper(node)
215     if version is None:
216       return name
217     return '%s_%s' % (name, str(version).replace('.', '_'))
218
219   def GetInterfaceString(self, node, version = None):
220     # If an interface name is specified, use that
221     name = node.GetProperty('iname')
222     if not name:
223       # Otherwise, the interface name is the object's name
224       # With '_Dev' replaced by '(Dev)' if it's a Dev interface.
225       name = node.GetName()
226       if name.endswith('_Dev'):
227         name = '%s(Dev)' % name[:-4]
228     if version is None:
229       return name
230     return "%s;%s" % (name, version)
231
232
233   #
234   # Return the array specification of the object.
235   #
236   def GetArraySpec(self, node):
237     assert(node.cls == 'Array')
238     fixed = node.GetProperty('FIXED')
239     if fixed:
240       return '[%s]' % fixed
241     else:
242       return '[]'
243
244   #
245   # GetTypeName
246   #
247   # For any valid 'typed' object such as Member or Typedef
248   # the typenode object contains the typename
249   #
250   # For a given node return the type name by passing mode.
251   #
252   def GetTypeName(self, node, release, prefix=''):
253     self.LogEnter('GetTypeName of %s rel=%s' % (node, release))
254
255     # For Members, Params, and Typedefs get the type it refers to otherwise
256     # the node in question is it's own type (struct, union etc...)
257     if node.IsA('Member', 'Param', 'Typedef'):
258       typeref = node.GetType(release)
259     else:
260       typeref = node
261
262     if typeref is None:
263       node.Error('No type at release %s.' % release)
264       raise CGenError('No type for %s' % node)
265
266     # If the type is a (BuiltIn) Type then return it's name
267     # remapping as needed
268     if typeref.IsA('Type'):
269       name = CGen.RemapName.get(typeref.GetName(), None)
270       if name is None: name = typeref.GetName()
271       name = '%s%s' % (prefix, name)
272
273     # For Interfaces, use the name + version
274     elif typeref.IsA('Interface'):
275       rel = typeref.first_release[release]
276       name = 'struct %s%s' % (prefix, self.GetStructName(typeref, rel, True))
277
278     # For structures, preceed with 'struct' or 'union' as appropriate
279     elif typeref.IsA('Struct'):
280       if typeref.GetProperty('union'):
281         name = 'union %s%s' % (prefix, typeref.GetName())
282       else:
283         name = 'struct %s%s' % (prefix, typeref.GetName())
284
285     # If it's an enum, or typedef then return the Enum's name
286     elif typeref.IsA('Enum', 'Typedef'):
287       if not typeref.LastRelease(release):
288         first = node.first_release[release]
289         ver = '_' + node.GetVersion(first).replace('.','_')
290       else:
291         ver = ''
292       # The enum may have skipped having a typedef, we need prefix with 'enum'.
293       if typeref.GetProperty('notypedef'):
294         name = 'enum %s%s%s' % (prefix, typeref.GetName(), ver)
295       else:
296         name = '%s%s%s' % (prefix, typeref.GetName(), ver)
297
298     else:
299       raise RuntimeError('Getting name of non-type %s.' % node)
300     self.LogExit('GetTypeName %s is %s' % (node, name))
301     return name
302
303
304   #
305   # GetRootType
306   #
307   # For a given node return basic type of that object.  This is
308   # either a 'Type', 'Callspec', or 'Array'
309   #
310   def GetRootTypeMode(self, node, release, mode):
311     self.LogEnter('GetRootType of %s' % node)
312     # If it has an array spec, then treat it as an array regardless of type
313     if node.GetOneOf('Array'):
314       rootType = 'Array'
315     # Or if it has a callspec, treat it as a function
316     elif node.GetOneOf('Callspec'):
317       rootType, mode = self.GetRootTypeMode(node.GetType(release), release,
318                                             'return')
319
320     # If it's a plain typedef, try that object's root type
321     elif node.IsA('Member', 'Param', 'Typedef'):
322       rootType, mode = self.GetRootTypeMode(node.GetType(release),
323                                             release, mode)
324
325     # If it's an Enum, then it's normal passing rules
326     elif node.IsA('Enum'):
327       rootType = node.cls
328
329     # If it's an Interface or Struct, we may be passing by value
330     elif node.IsA('Interface', 'Struct'):
331       if mode == 'return':
332         if node.GetProperty('returnByValue'):
333           rootType = 'TypeValue'
334         else:
335           rootType = node.cls
336       else:
337         if node.GetProperty('passByValue'):
338           rootType = 'TypeValue'
339         else:
340           rootType = node.cls
341
342     # If it's an Basic Type, check if it's a special type
343     elif node.IsA('Type'):
344       if node.GetName() in CGen.TypeMap:
345         rootType = node.GetName()
346       else:
347         rootType = 'TypeValue'
348     else:
349       raise RuntimeError('Getting root type of non-type %s.' % node)
350     self.LogExit('RootType is "%s"' % rootType)
351     return rootType, mode
352
353
354   def GetTypeByMode(self, node, release, mode):
355     self.LogEnter('GetTypeByMode of %s mode=%s release=%s' %
356                   (node, mode, release))
357     name = self.GetTypeName(node, release)
358     ntype, mode = self.GetRootTypeMode(node, release, mode)
359     out = CGen.TypeMap[ntype][mode] % name
360     self.LogExit('GetTypeByMode %s = %s' % (node, out))
361     return out
362
363
364   # Get the passing mode of the object (in, out, inout).
365   def GetParamMode(self, node):
366     self.Log('GetParamMode for %s' % node)
367     if node.GetProperty('in'): return 'in'
368     if node.GetProperty('out'): return 'out'
369     if node.GetProperty('inout'): return 'inout'
370     return 'return'
371
372   #
373   # GetComponents
374   #
375   # Returns the signature components of an object as a tuple of
376   # (rtype, name, arrays, callspec) where:
377   #   rtype - The store or return type of the object.
378   #   name - The name of the object.
379   #   arrays - A list of array dimensions as [] or [<fixed_num>].
380   #   args -  None if not a function, otherwise a list of parameters.
381   #
382   def GetComponents(self, node, release, mode):
383     self.LogEnter('GetComponents mode %s for %s %s' % (mode, node, release))
384
385     # Generate passing type by modifying root type
386     rtype = self.GetTypeByMode(node, release, mode)
387     if node.IsA('Enum', 'Interface', 'Struct'):
388       rname = node.GetName()
389     else:
390       rname = node.GetType(release).GetName()
391
392     if rname in CGen.RemapName:
393       rname = CGen.RemapName[rname]
394     if '%' in rtype:
395       rtype = rtype % rname
396     name = node.GetName()
397     arrayspec = [self.GetArraySpec(array) for array in node.GetListOf('Array')]
398     callnode = node.GetOneOf('Callspec')
399     if callnode:
400       callspec = []
401       for param in callnode.GetListOf('Param'):
402         if not param.IsRelease(release):
403           continue
404         mode = self.GetParamMode(param)
405         ptype, pname, parray, pspec = self.GetComponents(param, release, mode)
406         callspec.append((ptype, pname, parray, pspec))
407     else:
408       callspec = None
409
410     self.LogExit('GetComponents: %s, %s, %s, %s' %
411                  (rtype, name, arrayspec, callspec))
412     return (rtype, name, arrayspec, callspec)
413
414
415   def Compose(self, rtype, name, arrayspec, callspec, prefix, func_as_ptr,
416               include_name, unsized_as_ptr):
417     self.LogEnter('Compose: %s %s' % (rtype, name))
418     arrayspec = ''.join(arrayspec)
419
420     # Switch unsized array to a ptr. NOTE: Only last element can be unsized.
421     if unsized_as_ptr and arrayspec[-2:] == '[]':
422       prefix +=  '*'
423       arrayspec=arrayspec[:-2]
424
425     if not include_name:
426       name = prefix + arrayspec
427     else:
428       name = prefix + name + arrayspec
429     if callspec is None:
430       out = '%s %s' % (rtype, name)
431     else:
432       params = []
433       for ptype, pname, parray, pspec in callspec:
434         params.append(self.Compose(ptype, pname, parray, pspec, '', True,
435                                    include_name=True,
436                                    unsized_as_ptr=unsized_as_ptr))
437       if func_as_ptr:
438         name = '(*%s)' % name
439       if not params:
440         params = ['void']
441       out = '%s %s(%s)' % (rtype, name, ', '.join(params))
442     self.LogExit('Exit Compose: %s' % out)
443     return out
444
445   #
446   # GetSignature
447   #
448   # Returns the 'C' style signature of the object
449   #  prefix - A prefix for the object's name
450   #  func_as_ptr - Formats a function as a function pointer
451   #  include_name - If true, include member name in the signature.
452   #                 If false, leave it out. In any case, prefix is always
453   #                 included.
454   #  include_version - if True, include version in the member name
455   #
456   def GetSignature(self, node, release, mode, prefix='', func_as_ptr=True,
457                    include_name=True, include_version=False):
458     self.LogEnter('GetSignature %s %s as func=%s' %
459                   (node, mode, func_as_ptr))
460     rtype, name, arrayspec, callspec = self.GetComponents(node, release, mode)
461     if include_version:
462       name = self.GetStructName(node, release, True)
463
464     # If not a callspec (such as a struct) use a ptr instead of []
465     unsized_as_ptr = not callspec
466
467     out = self.Compose(rtype, name, arrayspec, callspec, prefix,
468                        func_as_ptr, include_name, unsized_as_ptr)
469
470     self.LogExit('Exit GetSignature: %s' % out)
471     return out
472
473   # Define a Typedef.
474   def DefineTypedef(self, node, releases, prefix='', comment=False):
475     __pychecker__ = 'unusednames=comment'
476     build_list = node.GetUniqueReleases(releases)
477
478     out = 'typedef %s;\n' % self.GetSignature(node, build_list[-1], 'return',
479                                               prefix, True,
480                                               include_version=False)
481     # Version mangle any other versions
482     for index, rel in enumerate(build_list[:-1]):
483       out += '\n'
484       out += 'typedef %s;\n' % self.GetSignature(node, rel, 'return',
485                                                  prefix, True,
486                                                  include_version=True)
487     self.Log('DefineTypedef: %s' % out)
488     return out
489
490   # Define an Enum.
491   def DefineEnum(self, node, releases, prefix='', comment=False):
492     __pychecker__ = 'unusednames=comment,releases'
493     self.LogEnter('DefineEnum %s' % node)
494     name = '%s%s' % (prefix, node.GetName())
495     notypedef = node.GetProperty('notypedef')
496     unnamed = node.GetProperty('unnamed')
497
498     if unnamed:
499       out = 'enum {'
500     elif notypedef:
501       out = 'enum %s {' % name
502     else:
503       out = 'typedef enum {'
504     enumlist = []
505     for child in node.GetListOf('EnumItem'):
506       value = child.GetProperty('VALUE')
507       comment_txt = GetNodeComments(child, tabs=1)
508       if value:
509         item_txt = '%s%s = %s' % (prefix, child.GetName(), value)
510       else:
511         item_txt = '%s%s' % (prefix, child.GetName())
512       enumlist.append('%s  %s' % (comment_txt, item_txt))
513     self.LogExit('Exit DefineEnum')
514
515     if unnamed or notypedef:
516       out = '%s\n%s\n};\n' % (out, ',\n'.join(enumlist))
517     else:
518       out = '%s\n%s\n} %s;\n' % (out, ',\n'.join(enumlist), name)
519     return out
520
521   def DefineMember(self, node, releases, prefix='', comment=False):
522     __pychecker__ = 'unusednames=prefix,comment'
523     release = releases[0]
524     self.LogEnter('DefineMember %s' % node)
525     if node.GetProperty('ref'):
526       out = '%s;' % self.GetSignature(node, release, 'ref', '', True)
527     else:
528       out = '%s;' % self.GetSignature(node, release, 'store', '', True)
529     self.LogExit('Exit DefineMember')
530     return out
531
532   def GetStructName(self, node, release, include_version=False):
533     suffix = ''
534     if include_version:
535       ver_num = node.GetVersion(release)
536       suffix = ('_%s' % ver_num).replace('.', '_')
537     return node.GetName() + suffix
538
539   def DefineStructInternals(self, node, release,
540                             include_version=False, comment=True):
541     out = ''
542     if node.GetProperty('union'):
543       out += 'union %s {\n' % (
544           self.GetStructName(node, release, include_version))
545     else:
546       out += 'struct %s {\n' % (
547           self.GetStructName(node, release, include_version))
548
549     # Generate Member Functions
550     members = []
551     for child in node.GetListOf('Member'):
552       member = self.Define(child, [release], tabs=1, comment=comment)
553       if not member:
554         continue
555       members.append(member)
556     out += '%s\n};\n' % '\n'.join(members)
557     return out
558
559
560   def DefineStruct(self, node, releases, prefix='', comment=False):
561     __pychecker__ = 'unusednames=comment,prefix'
562     self.LogEnter('DefineStruct %s' % node)
563     out = ''
564     build_list = node.GetUniqueReleases(releases)
565
566     # TODO(noelallen) : Bug 157017 finish multiversion support
567     if node.IsA('Struct'):
568       if len(build_list) != 1:
569         node.Error('Can not support multiple versions of node.')
570       assert len(build_list) == 1
571
572
573     if node.IsA('Interface'):
574       # Build the most recent one versioned, with comments
575       out = self.DefineStructInternals(node, build_list[-1],
576                                        include_version=True, comment=True)
577
578       # Define an unversioned typedef for the most recent version
579       out += '\ntypedef struct %s %s;\n' % (
580           self.GetStructName(node, build_list[-1], include_version=True),
581           self.GetStructName(node, build_list[-1], include_version=False))
582     else:
583       # Build the most recent one versioned, with comments
584       out = self.DefineStructInternals(node, build_list[-1],
585                                        include_version=False, comment=True)
586
587
588     # Build the rest without comments and with the version number appended
589     for rel in build_list[0:-1]:
590       out += '\n' + self.DefineStructInternals(node, rel,
591                                                include_version=True,
592                                                comment=False)
593
594     self.LogExit('Exit DefineStruct')
595     return out
596
597
598   #
599   # Copyright and Comment
600   #
601   # Generate a comment or copyright block
602   #
603   def Copyright(self, node, cpp_style=False):
604     lines = node.GetName().split('\n')
605     if cpp_style:
606       return '//' + '\n//'.join(filter(lambda f: f != '', lines)) + '\n'
607     return CommentLines(lines)
608
609
610   def Indent(self, data, tabs=0):
611     """Handles indentation and 80-column line wrapping."""
612     tab = '  ' * tabs
613     lines = []
614     for line in data.split('\n'):
615       # Add indentation
616       line = tab + line
617       space_break = line.rfind(' ', 0, 80)
618       if len(line) <= 80 or 'http' in line:
619         # Ignore normal line and URLs permitted by the style guide.
620         lines.append(line.rstrip())
621       elif not '(' in line and space_break >= 0:
622         # Break long typedefs on nearest space.
623         lines.append(line[0:space_break])
624         lines.append('    ' + line[space_break + 1:])
625       else:
626         left = line.rfind('(') + 1
627         args = line[left:].split(',')
628         orig_args = args
629         orig_left = left
630         # Try to split on '(arg1)' or '(arg1, arg2)', not '()'
631         while args[0][0] == ')':
632           left = line.rfind('(', 0, left - 1) + 1
633           if left == 0:  # No more parens, take the original option
634             args = orig_args
635             left = orig_left
636             break
637           args = line[left:].split(',')
638
639         line_max = 0
640         for arg in args:
641           if len(arg) > line_max: line_max = len(arg)
642
643         if left + line_max >= 80:
644           indent = '%s    ' % tab
645           args =  (',\n%s' % indent).join([arg.strip() for arg in args])
646           lines.append('%s\n%s%s' % (line[:left], indent, args))
647         else:
648           indent = ' ' * (left - 1)
649           args =  (',\n%s' % indent).join(args)
650           lines.append('%s%s' % (line[:left], args))
651     return '\n'.join(lines)
652
653
654   # Define a top level object.
655   def Define(self, node, releases, tabs=0, prefix='', comment=False):
656     # If this request does not match unique release, or if the release is not
657     # available (possibly deprecated) then skip.
658     unique = node.GetUniqueReleases(releases)
659     if not unique or not node.InReleases(releases):
660       return ''
661
662     self.LogEnter('Define %s tab=%d prefix="%s"' % (node,tabs,prefix))
663     declmap = dict({
664       'Enum': CGen.DefineEnum,
665       'Function': CGen.DefineMember,
666       'Interface': CGen.DefineStruct,
667       'Member': CGen.DefineMember,
668       'Struct': CGen.DefineStruct,
669       'Typedef': CGen.DefineTypedef
670     })
671
672     out = ''
673     func = declmap.get(node.cls, None)
674     if not func:
675       ErrOut.Log('Failed to define %s named %s' % (node.cls, node.GetName()))
676     define_txt = func(self, node, releases, prefix=prefix, comment=comment)
677
678     comment_txt = GetNodeComments(node, tabs=0)
679     if comment_txt and comment:
680       out += comment_txt
681     out += define_txt
682
683     indented_out = self.Indent(out, tabs)
684     self.LogExit('Exit Define')
685     return indented_out
686
687
688 # Clean a string representing an object definition and return then string
689 # as a single space delimited set of tokens.
690 def CleanString(instr):
691   instr = instr.strip()
692   instr = instr.split()
693   return ' '.join(instr)
694
695
696 # Test a file, by comparing all it's objects, with their comments.
697 def TestFile(filenode):
698   cgen = CGen()
699
700   errors = 0
701   for node in filenode.GetChildren()[2:]:
702     instr = node.GetOneOf('Comment')
703     if not instr: continue
704     instr.Dump()
705     instr = CleanString(instr.GetName())
706
707     outstr = cgen.Define(node, releases=['M14'])
708     if GetOption('verbose'):
709       print outstr + '\n'
710     outstr = CleanString(outstr)
711
712     if instr != outstr:
713       ErrOut.Log('Failed match of\n>>%s<<\nto:\n>>%s<<\nFor:\n' %
714                  (instr, outstr))
715       node.Dump(1, comments=True)
716       errors += 1
717   return errors
718
719
720 # Build and resolve the AST and compare each file individual.
721 def TestFiles(filenames):
722   if not filenames:
723     idldir = os.path.split(sys.argv[0])[0]
724     idldir = os.path.join(idldir, 'test_cgen', '*.idl')
725     filenames = glob.glob(idldir)
726
727   filenames = sorted(filenames)
728   ast = ParseFiles(filenames)
729
730   total_errs = 0
731   for filenode in ast.GetListOf('File'):
732     errs = TestFile(filenode)
733     if errs:
734       ErrOut.Log('%s test failed with %d error(s).' %
735                  (filenode.GetName(), errs))
736       total_errs += errs
737
738   if total_errs:
739     ErrOut.Log('Failed generator test.')
740   else:
741     InfoOut.Log('Passed generator test.')
742   return total_errs
743
744 def main(args):
745   filenames = ParseOptions(args)
746   if GetOption('test'):
747     return TestFiles(filenames)
748   ast = ParseFiles(filenames)
749   cgen = CGen()
750   for f in ast.GetListOf('File'):
751     if f.GetProperty('ERRORS') > 0:
752       print 'Skipping %s' % f.GetName()
753       continue
754     for node in f.GetChildren()[2:]:
755       print cgen.Define(node, comment=True, prefix='tst_')
756
757
758 if __name__ == '__main__':
759   sys.exit(main(sys.argv[1:]))
760