| Index: third_party/chrome/ppapi/generators/idl_c_proto.py
|
| diff --git a/third_party/chrome/ppapi/generators/idl_c_proto.py b/third_party/chrome/ppapi/generators/idl_c_proto.py
|
| new file mode 100755
|
| index 0000000000000000000000000000000000000000..7965630863fe0e24b73d393372df5d423e1576e7
|
| --- /dev/null
|
| +++ b/third_party/chrome/ppapi/generators/idl_c_proto.py
|
| @@ -0,0 +1,738 @@
|
| +#!/usr/bin/env python
|
| +# Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
| +# Use of this source code is governed by a BSD-style license that can be
|
| +# found in the LICENSE file.
|
| +
|
| +""" Generator for C style prototypes and definitions """
|
| +
|
| +import glob
|
| +import os
|
| +import sys
|
| +
|
| +from idl_log import ErrOut, InfoOut, WarnOut
|
| +from idl_node import IDLNode
|
| +from idl_ast import IDLAst
|
| +from idl_option import GetOption, Option, ParseOptions
|
| +from idl_parser import ParseFiles
|
| +
|
| +Option('cgen_debug', 'Debug generate.')
|
| +
|
| +class CGenError(Exception):
|
| + def __init__(self, msg):
|
| + self.value = msg
|
| +
|
| + def __str__(self):
|
| + return repr(self.value)
|
| +
|
| +
|
| +def CommentLines(lines, tabs=0):
|
| + # Generate a C style comment block by prepending the block with '<tab>/*'
|
| + # and adding a '<tab> *' per line.
|
| + tab = ' ' * tabs
|
| +
|
| + out = '%s/*' % tab + ('\n%s *' % tab).join(lines)
|
| +
|
| + # Add a terminating ' */' unless the last line is blank which would mean it
|
| + # already has ' *'
|
| + if not lines[-1]:
|
| + out += '/\n'
|
| + else:
|
| + out += ' */\n'
|
| + return out
|
| +
|
| +def Comment(node, prefix=None, tabs=0):
|
| + # Generate a comment block from the provided Comment node.
|
| + comment = node.GetName()
|
| + lines = comment.split('\n')
|
| +
|
| + # If an option prefix is provided, then prepend that to the comment
|
| + # for this node.
|
| + if prefix:
|
| + prefix_lines = prefix.split('\n')
|
| + # If both the prefix and comment start with a blank line ('*') remove
|
| + # the extra one.
|
| + if prefix_lines[0] == '*' and lines[0] == '*':
|
| + lines = prefix_lines + lines[1:]
|
| + else:
|
| + lines = prefix_lines + lines;
|
| + return CommentLines(lines, tabs)
|
| +
|
| +def GetNodeComments(node, tabs=0):
|
| + # Generate a comment block joining all comment nodes which are children of
|
| + # the provided node.
|
| + comment_txt = ''
|
| + for doc in node.GetListOf('Comment'):
|
| + comment_txt += Comment(doc, tabs=tabs)
|
| + return comment_txt
|
| +
|
| +
|
| +class CGen(object):
|
| + # TypeMap
|
| + #
|
| + # TypeMap modifies how an object is stored or passed, for example pointers
|
| + # are passed as 'const' if they are 'in' parameters, and structures are
|
| + # preceeded by the keyword 'struct' as well as using a pointer.
|
| + #
|
| + TypeMap = {
|
| + 'Array': {
|
| + 'in': 'const %s',
|
| + 'inout': '%s',
|
| + 'out': '%s*',
|
| + 'store': '%s',
|
| + 'return': '%s',
|
| + 'ref': '%s*'
|
| + },
|
| + 'Callspec': {
|
| + 'in': '%s',
|
| + 'inout': '%s',
|
| + 'out': '%s',
|
| + 'store': '%s',
|
| + 'return': '%s'
|
| + },
|
| + 'Enum': {
|
| + 'in': '%s',
|
| + 'inout': '%s*',
|
| + 'out': '%s*',
|
| + 'store': '%s',
|
| + 'return': '%s'
|
| + },
|
| + 'Interface': {
|
| + 'in': 'const %s*',
|
| + 'inout': '%s*',
|
| + 'out': '%s**',
|
| + 'return': '%s*',
|
| + 'store': '%s*'
|
| + },
|
| + 'Struct': {
|
| + 'in': 'const %s*',
|
| + 'inout': '%s*',
|
| + 'out': '%s*',
|
| + 'return': ' %s*',
|
| + 'store': '%s',
|
| + 'ref': '%s*'
|
| + },
|
| + 'blob_t': {
|
| + 'in': 'const %s',
|
| + 'inout': '%s',
|
| + 'out': '%s',
|
| + 'return': '%s',
|
| + 'store': '%s'
|
| + },
|
| + 'mem_t': {
|
| + 'in': 'const %s',
|
| + 'inout': '%s',
|
| + 'out': '%s',
|
| + 'return': '%s',
|
| + 'store': '%s'
|
| + },
|
| + 'str_t': {
|
| + 'in': 'const %s',
|
| + 'inout': '%s',
|
| + 'out': '%s',
|
| + 'return': 'const %s',
|
| + 'store': '%s'
|
| + },
|
| + 'cstr_t': {
|
| + 'in': '%s',
|
| + 'inout': '%s*',
|
| + 'out': '%s*',
|
| + 'return': '%s',
|
| + 'store': '%s'
|
| + },
|
| + 'TypeValue': {
|
| + 'in': '%s',
|
| + 'inout': '%s*',
|
| + 'out': '%s*',
|
| + 'return': '%s',
|
| + 'store': '%s'
|
| + },
|
| + }
|
| +
|
| +
|
| + #
|
| + # RemapName
|
| + #
|
| + # A diction array of PPAPI types that are converted to language specific
|
| + # types before being returned by by the C generator
|
| + #
|
| + RemapName = {
|
| + 'blob_t': 'void**',
|
| + 'float_t': 'float',
|
| + 'double_t': 'double',
|
| + 'handle_t': 'int',
|
| + 'mem_t': 'void*',
|
| + 'str_t': 'char*',
|
| + 'cstr_t': 'const char*',
|
| + 'interface_t' : 'const void*'
|
| + }
|
| +
|
| + def __init__(self):
|
| + self.dbg_depth = 0
|
| +
|
| + #
|
| + # Debug Logging functions
|
| + #
|
| + def Log(self, txt):
|
| + if not GetOption('cgen_debug'): return
|
| + tabs = ' ' * self.dbg_depth
|
| + print '%s%s' % (tabs, txt)
|
| +
|
| + def LogEnter(self, txt):
|
| + if txt: self.Log(txt)
|
| + self.dbg_depth += 1
|
| +
|
| + def LogExit(self, txt):
|
| + self.dbg_depth -= 1
|
| + if txt: self.Log(txt)
|
| +
|
| +
|
| + def GetDefine(self, name, value):
|
| + out = '#define %s %s' % (name, value)
|
| + if len(out) > 80:
|
| + out = '#define %s \\\n %s' % (name, value)
|
| + return '%s\n' % out
|
| +
|
| + #
|
| + # Interface strings
|
| + #
|
| + def GetMacroHelper(self, node):
|
| + macro = node.GetProperty('macro')
|
| + if macro: return macro
|
| + name = node.GetName()
|
| + name = name.upper()
|
| + return "%s_INTERFACE" % name
|
| +
|
| + def GetInterfaceMacro(self, node, version = None):
|
| + name = self.GetMacroHelper(node)
|
| + if version is None:
|
| + return name
|
| + return '%s_%s' % (name, str(version).replace('.', '_'))
|
| +
|
| + def GetInterfaceString(self, node, version = None):
|
| + # If an interface name is specified, use that
|
| + name = node.GetProperty('iname')
|
| + if not name:
|
| + # Otherwise, the interface name is the object's name
|
| + # With '_Dev' replaced by '(Dev)' if it's a Dev interface.
|
| + name = node.GetName()
|
| + if name.endswith('_Dev'):
|
| + name = '%s(Dev)' % name[:-4]
|
| + if version is None:
|
| + return name
|
| + return "%s;%s" % (name, version)
|
| +
|
| +
|
| + #
|
| + # Return the array specification of the object.
|
| + #
|
| + def GetArraySpec(self, node):
|
| + assert(node.cls == 'Array')
|
| + fixed = node.GetProperty('FIXED')
|
| + if fixed:
|
| + return '[%s]' % fixed
|
| + else:
|
| + return '[]'
|
| +
|
| + #
|
| + # GetTypeName
|
| + #
|
| + # For any valid 'typed' object such as Member or Typedef
|
| + # the typenode object contains the typename
|
| + #
|
| + # For a given node return the type name by passing mode.
|
| + #
|
| + def GetTypeName(self, node, release, prefix=''):
|
| + self.LogEnter('GetTypeName of %s rel=%s' % (node, release))
|
| +
|
| + # For Members, Params, and Typedefs get the type it refers to otherwise
|
| + # the node in question is it's own type (struct, union etc...)
|
| + if node.IsA('Member', 'Param', 'Typedef'):
|
| + typeref = node.GetType(release)
|
| + else:
|
| + typeref = node
|
| +
|
| + if typeref is None:
|
| + node.Error('No type at release %s.' % release)
|
| + raise CGenError('No type for %s' % node)
|
| +
|
| + # If the type is a (BuiltIn) Type then return it's name
|
| + # remapping as needed
|
| + if typeref.IsA('Type'):
|
| + name = CGen.RemapName.get(typeref.GetName(), None)
|
| + if name is None: name = typeref.GetName()
|
| + name = '%s%s' % (prefix, name)
|
| +
|
| + # For Interfaces, use the name + version
|
| + elif typeref.IsA('Interface'):
|
| + rel = typeref.first_release[release]
|
| + name = 'struct %s%s' % (prefix, self.GetStructName(typeref, rel, True))
|
| +
|
| + # For structures, preceed with 'struct' or 'union' as appropriate
|
| + elif typeref.IsA('Struct'):
|
| + if typeref.GetProperty('union'):
|
| + name = 'union %s%s' % (prefix, typeref.GetName())
|
| + else:
|
| + name = 'struct %s%s' % (prefix, typeref.GetName())
|
| +
|
| + # If it's an enum, or typedef then return the Enum's name
|
| + elif typeref.IsA('Enum', 'Typedef'):
|
| + # The enum may have skipped having a typedef, we need prefix with 'enum'.
|
| + if typeref.GetProperty('notypedef'):
|
| + name = 'enum %s%s' % (prefix, typeref.GetName())
|
| + else:
|
| + name = '%s%s' % (prefix, typeref.GetName())
|
| +
|
| + else:
|
| + raise RuntimeError('Getting name of non-type %s.' % node)
|
| + self.LogExit('GetTypeName %s is %s' % (node, name))
|
| + return name
|
| +
|
| +
|
| + #
|
| + # GetRootType
|
| + #
|
| + # For a given node return basic type of that object. This is
|
| + # either a 'Type', 'Callspec', or 'Array'
|
| + #
|
| + def GetRootTypeMode(self, node, release, mode):
|
| + self.LogEnter('GetRootType of %s' % node)
|
| + # If it has an array spec, then treat it as an array regardless of type
|
| + if node.GetOneOf('Array'):
|
| + rootType = 'Array'
|
| + # Or if it has a callspec, treat it as a function
|
| + elif node.GetOneOf('Callspec'):
|
| + rootType, mode = self.GetRootTypeMode(node.GetType(release), release,
|
| + 'return')
|
| +
|
| + # If it's a plain typedef, try that object's root type
|
| + elif node.IsA('Member', 'Param', 'Typedef'):
|
| + rootType, mode = self.GetRootTypeMode(node.GetType(release),
|
| + release, mode)
|
| +
|
| + # If it's an Enum, then it's normal passing rules
|
| + elif node.IsA('Enum'):
|
| + rootType = node.cls
|
| +
|
| + # If it's an Interface or Struct, we may be passing by value
|
| + elif node.IsA('Interface', 'Struct'):
|
| + if mode == 'return':
|
| + if node.GetProperty('returnByValue'):
|
| + rootType = 'TypeValue'
|
| + else:
|
| + rootType = node.cls
|
| + else:
|
| + if node.GetProperty('passByValue'):
|
| + rootType = 'TypeValue'
|
| + else:
|
| + rootType = node.cls
|
| +
|
| + # If it's an Basic Type, check if it's a special type
|
| + elif node.IsA('Type'):
|
| + if node.GetName() in CGen.TypeMap:
|
| + rootType = node.GetName()
|
| + else:
|
| + rootType = 'TypeValue'
|
| + else:
|
| + raise RuntimeError('Getting root type of non-type %s.' % node)
|
| + self.LogExit('RootType is "%s"' % rootType)
|
| + return rootType, mode
|
| +
|
| +
|
| + def GetTypeByMode(self, node, release, mode):
|
| + self.LogEnter('GetTypeByMode of %s mode=%s release=%s' %
|
| + (node, mode, release))
|
| + name = self.GetTypeName(node, release)
|
| + ntype, mode = self.GetRootTypeMode(node, release, mode)
|
| + out = CGen.TypeMap[ntype][mode] % name
|
| + self.LogExit('GetTypeByMode %s = %s' % (node, out))
|
| + return out
|
| +
|
| +
|
| + # Get the passing mode of the object (in, out, inout).
|
| + def GetParamMode(self, node):
|
| + self.Log('GetParamMode for %s' % node)
|
| + if node.GetProperty('in'): return 'in'
|
| + if node.GetProperty('out'): return 'out'
|
| + if node.GetProperty('inout'): return 'inout'
|
| + return 'return'
|
| +
|
| + #
|
| + # GetComponents
|
| + #
|
| + # Returns the signature components of an object as a tuple of
|
| + # (rtype, name, arrays, callspec) where:
|
| + # rtype - The store or return type of the object.
|
| + # name - The name of the object.
|
| + # arrays - A list of array dimensions as [] or [<fixed_num>].
|
| + # args - None if not a function, otherwise a list of parameters.
|
| + #
|
| + def GetComponents(self, node, release, mode):
|
| + self.LogEnter('GetComponents mode %s for %s %s' % (mode, node, release))
|
| +
|
| + # Generate passing type by modifying root type
|
| + rtype = self.GetTypeByMode(node, release, mode)
|
| + if node.IsA('Enum', 'Interface', 'Struct'):
|
| + rname = node.GetName()
|
| + else:
|
| + rname = node.GetType(release).GetName()
|
| +
|
| + if rname in CGen.RemapName:
|
| + rname = CGen.RemapName[rname]
|
| + if '%' in rtype:
|
| + rtype = rtype % rname
|
| + name = node.GetName()
|
| + arrayspec = [self.GetArraySpec(array) for array in node.GetListOf('Array')]
|
| + callnode = node.GetOneOf('Callspec')
|
| + if callnode:
|
| + callspec = []
|
| + for param in callnode.GetListOf('Param'):
|
| + mode = self.GetParamMode(param)
|
| + ptype, pname, parray, pspec = self.GetComponents(param, release, mode)
|
| + callspec.append((ptype, pname, parray, pspec))
|
| + else:
|
| + callspec = None
|
| +
|
| + self.LogExit('GetComponents: %s, %s, %s, %s' %
|
| + (rtype, name, arrayspec, callspec))
|
| + return (rtype, name, arrayspec, callspec)
|
| +
|
| +
|
| + def Compose(self, rtype, name, arrayspec, callspec, prefix, func_as_ptr,
|
| + ptr_prefix, include_name, unsized_as_ptr):
|
| + self.LogEnter('Compose: %s %s' % (rtype, name))
|
| + arrayspec = ''.join(arrayspec)
|
| +
|
| + # Switch unsized array to a ptr. NOTE: Only last element can be unsized.
|
| + if unsized_as_ptr and arrayspec[-2:] == '[]':
|
| + prefix += '*'
|
| + arrayspec=arrayspec[:-2]
|
| +
|
| + if not include_name:
|
| + name = prefix + arrayspec
|
| + else:
|
| + name = prefix + name + arrayspec
|
| + if callspec is None:
|
| + out = '%s %s' % (rtype, name)
|
| + else:
|
| + params = []
|
| + for ptype, pname, parray, pspec in callspec:
|
| + params.append(self.Compose(ptype, pname, parray, pspec, '', True,
|
| + ptr_prefix='', include_name=True,
|
| + unsized_as_ptr=unsized_as_ptr))
|
| + if func_as_ptr:
|
| + name = '(%s*%s)' % (ptr_prefix, name)
|
| + if not params:
|
| + params = ['void']
|
| + out = '%s %s(%s)' % (rtype, name, ', '.join(params))
|
| + self.LogExit('Exit Compose: %s' % out)
|
| + return out
|
| +
|
| + #
|
| + # GetSignature
|
| + #
|
| + # Returns the 'C' style signature of the object
|
| + # prefix - A prefix for the object's name
|
| + # func_as_ptr - Formats a function as a function pointer
|
| + # ptr_prefix - A prefix that goes before the "*" for a function pointer
|
| + # include_name - If true, include member name in the signature.
|
| + # If false, leave it out. In any case, prefix and ptr_prefix
|
| + # are always included.
|
| + # include_version - if True, include version in the member name
|
| + #
|
| + def GetSignature(self, node, release, mode, prefix='', func_as_ptr=True,
|
| + ptr_prefix='', include_name=True, include_version=False):
|
| + self.LogEnter('GetSignature %s %s as func=%s' %
|
| + (node, mode, func_as_ptr))
|
| + rtype, name, arrayspec, callspec = self.GetComponents(node, release, mode)
|
| + if include_version:
|
| + name = self.GetStructName(node, release, True)
|
| +
|
| + # If not a callspec (such as a struct) use a ptr instead of []
|
| + unsized_as_ptr = not callspec
|
| +
|
| + out = self.Compose(rtype, name, arrayspec, callspec, prefix,
|
| + func_as_ptr, ptr_prefix, include_name, unsized_as_ptr)
|
| +
|
| + self.LogExit('Exit GetSignature: %s' % out)
|
| + return out
|
| +
|
| + # Define a Typedef.
|
| + def DefineTypedef(self, node, releases, prefix='', comment=False):
|
| + __pychecker__ = 'unusednames=comment'
|
| + build_list = node.GetUniqueReleases(releases)
|
| +
|
| + # TODO(noelallen) : Bug 157017 finish multiversion support
|
| + if len(build_list) != 1:
|
| + node.Error('Can not support multiple versions of node: %s' % build_list)
|
| + assert len(build_list) == 1
|
| +
|
| + out = 'typedef %s;\n' % self.GetSignature(node, build_list[0], 'return',
|
| + prefix, True)
|
| + self.Log('DefineTypedef: %s' % out)
|
| + return out
|
| +
|
| + # Define an Enum.
|
| + def DefineEnum(self, node, releases, prefix='', comment=False):
|
| + __pychecker__ = 'unusednames=comment,releases'
|
| + self.LogEnter('DefineEnum %s' % node)
|
| + name = '%s%s' % (prefix, node.GetName())
|
| + notypedef = node.GetProperty('notypedef')
|
| + unnamed = node.GetProperty('unnamed')
|
| +
|
| + if unnamed:
|
| + out = 'enum {'
|
| + elif notypedef:
|
| + out = 'enum %s {' % name
|
| + else:
|
| + out = 'typedef enum {'
|
| + enumlist = []
|
| + for child in node.GetListOf('EnumItem'):
|
| + value = child.GetProperty('VALUE')
|
| + comment_txt = GetNodeComments(child, tabs=1)
|
| + if value:
|
| + item_txt = '%s%s = %s' % (prefix, child.GetName(), value)
|
| + else:
|
| + item_txt = '%s%s' % (prefix, child.GetName())
|
| + enumlist.append('%s %s' % (comment_txt, item_txt))
|
| + self.LogExit('Exit DefineEnum')
|
| +
|
| + if unnamed or notypedef:
|
| + out = '%s\n%s\n};\n' % (out, ',\n'.join(enumlist))
|
| + else:
|
| + out = '%s\n%s\n} %s;\n' % (out, ',\n'.join(enumlist), name)
|
| + return out
|
| +
|
| + def DefineMember(self, node, releases, prefix='', comment=False):
|
| + __pychecker__ = 'unusednames=prefix,comment'
|
| + release = releases[0]
|
| + self.LogEnter('DefineMember %s' % node)
|
| + if node.GetProperty('ref'):
|
| + out = '%s;' % self.GetSignature(node, release, 'ref', '', True)
|
| + else:
|
| + out = '%s;' % self.GetSignature(node, release, 'store', '', True)
|
| + self.LogExit('Exit DefineMember')
|
| + return out
|
| +
|
| + def GetStructName(self, node, release, include_version=False):
|
| + suffix = ''
|
| + if include_version:
|
| + ver_num = node.GetVersion(release)
|
| + suffix = ('_%s' % ver_num).replace('.', '_')
|
| + return node.GetName() + suffix
|
| +
|
| + def DefineStructInternals(self, node, release,
|
| + include_version=False, comment=True):
|
| + out = ''
|
| + if node.GetProperty('union'):
|
| + out += 'union %s {\n' % (
|
| + self.GetStructName(node, release, include_version))
|
| + else:
|
| + out += 'struct %s {\n' % (
|
| + self.GetStructName(node, release, include_version))
|
| +
|
| + # Generate Member Functions
|
| + members = []
|
| + for child in node.GetListOf('Member'):
|
| + member = self.Define(child, [release], tabs=1, comment=comment)
|
| + if not member:
|
| + continue
|
| + members.append(member)
|
| + out += '%s\n};\n' % '\n'.join(members)
|
| + return out
|
| +
|
| +
|
| + def DefineStruct(self, node, releases, prefix='', comment=False):
|
| + __pychecker__ = 'unusednames=comment,prefix'
|
| + self.LogEnter('DefineStruct %s' % node)
|
| + out = ''
|
| + build_list = node.GetUniqueReleases(releases)
|
| +
|
| + # TODO(noelallen) : Bug 157017 finish multiversion support
|
| + if node.IsA('Struct'):
|
| + if len(build_list) != 1:
|
| + node.Error('Can not support multiple versions of node.')
|
| + assert len(build_list) == 1
|
| +
|
| +
|
| + if node.IsA('Interface'):
|
| + # Build the most recent one versioned, with comments
|
| + out = self.DefineStructInternals(node, build_list[-1],
|
| + include_version=True, comment=True)
|
| +
|
| + # Define an unversioned typedef for the most recent version
|
| + out += '\ntypedef struct %s %s;\n' % (
|
| + self.GetStructName(node, build_list[-1], include_version=True),
|
| + self.GetStructName(node, build_list[-1], include_version=False))
|
| + else:
|
| + # Build the most recent one versioned, with comments
|
| + out = self.DefineStructInternals(node, build_list[-1],
|
| + include_version=False, comment=True)
|
| +
|
| +
|
| + # Build the rest without comments and with the version number appended
|
| + for rel in build_list[0:-1]:
|
| + out += '\n' + self.DefineStructInternals(node, rel,
|
| + include_version=True,
|
| + comment=False)
|
| +
|
| + self.LogExit('Exit DefineStruct')
|
| + return out
|
| +
|
| +
|
| + #
|
| + # Copyright and Comment
|
| + #
|
| + # Generate a comment or copyright block
|
| + #
|
| + def Copyright(self, node, cpp_style=False):
|
| + lines = node.GetName().split('\n')
|
| + if cpp_style:
|
| + return '//' + '\n//'.join(filter(lambda f: f != '', lines)) + '\n'
|
| + return CommentLines(lines)
|
| +
|
| +
|
| + def Indent(self, data, tabs=0):
|
| + """Handles indentation and 80-column line wrapping."""
|
| + tab = ' ' * tabs
|
| + lines = []
|
| + for line in data.split('\n'):
|
| + # Add indentation
|
| + line = tab + line
|
| + if len(line) <= 80:
|
| + lines.append(line.rstrip())
|
| + else:
|
| + left = line.rfind('(') + 1
|
| + args = line[left:].split(',')
|
| + orig_args = args
|
| + orig_left = left
|
| + # Try to split on '(arg1)' or '(arg1, arg2)', not '()'
|
| + while args[0][0] == ')':
|
| + left = line.rfind('(', 0, left - 1) + 1
|
| + if left == 0: # No more parens, take the original option
|
| + args = orig_args
|
| + left = orig_left
|
| + break
|
| + args = line[left:].split(',')
|
| +
|
| + line_max = 0
|
| + for arg in args:
|
| + if len(arg) > line_max: line_max = len(arg)
|
| +
|
| + if left + line_max >= 80:
|
| + indent = '%s ' % tab
|
| + args = (',\n%s' % indent).join([arg.strip() for arg in args])
|
| + lines.append('%s\n%s%s' % (line[:left], indent, args))
|
| + else:
|
| + indent = ' ' * (left - 1)
|
| + args = (',\n%s' % indent).join(args)
|
| + lines.append('%s%s' % (line[:left], args))
|
| + return '\n'.join(lines)
|
| +
|
| +
|
| + # Define a top level object.
|
| + def Define(self, node, releases, tabs=0, prefix='', comment=False):
|
| + # If this request does not match unique release, or if the release is not
|
| + # available (possibly deprecated) then skip.
|
| + unique = node.GetUniqueReleases(releases)
|
| + if not unique or not node.InReleases(releases):
|
| + return ''
|
| +
|
| + self.LogEnter('Define %s tab=%d prefix="%s"' % (node,tabs,prefix))
|
| + declmap = dict({
|
| + 'Enum': CGen.DefineEnum,
|
| + 'Function': CGen.DefineMember,
|
| + 'Interface': CGen.DefineStruct,
|
| + 'Member': CGen.DefineMember,
|
| + 'Struct': CGen.DefineStruct,
|
| + 'Typedef': CGen.DefineTypedef
|
| + })
|
| +
|
| + out = ''
|
| + func = declmap.get(node.cls, None)
|
| + if not func:
|
| + ErrOut.Log('Failed to define %s named %s' % (node.cls, node.GetName()))
|
| + define_txt = func(self, node, releases, prefix=prefix, comment=comment)
|
| +
|
| + comment_txt = GetNodeComments(node, tabs=0)
|
| + if comment_txt and comment:
|
| + out += comment_txt
|
| + out += define_txt
|
| +
|
| + indented_out = self.Indent(out, tabs)
|
| + self.LogExit('Exit Define')
|
| + return indented_out
|
| +
|
| +
|
| +# Clean a string representing an object definition and return then string
|
| +# as a single space delimited set of tokens.
|
| +def CleanString(instr):
|
| + instr = instr.strip()
|
| + instr = instr.split()
|
| + return ' '.join(instr)
|
| +
|
| +
|
| +# Test a file, by comparing all it's objects, with their comments.
|
| +def TestFile(filenode):
|
| + cgen = CGen()
|
| +
|
| + errors = 0
|
| + for node in filenode.GetChildren()[2:]:
|
| + instr = node.GetOneOf('Comment')
|
| + if not instr: continue
|
| + instr.Dump()
|
| + instr = CleanString(instr.GetName())
|
| +
|
| + outstr = cgen.Define(node, releases=['M14'])
|
| + if GetOption('verbose'):
|
| + print outstr + '\n'
|
| + outstr = CleanString(outstr)
|
| +
|
| + if instr != outstr:
|
| + ErrOut.Log('Failed match of\n>>%s<<\nto:\n>>%s<<\nFor:\n' %
|
| + (instr, outstr))
|
| + node.Dump(1, comments=True)
|
| + errors += 1
|
| + return errors
|
| +
|
| +
|
| +# Build and resolve the AST and compare each file individual.
|
| +def TestFiles(filenames):
|
| + if not filenames:
|
| + idldir = os.path.split(sys.argv[0])[0]
|
| + idldir = os.path.join(idldir, 'test_cgen', '*.idl')
|
| + filenames = glob.glob(idldir)
|
| +
|
| + filenames = sorted(filenames)
|
| + ast = ParseFiles(filenames)
|
| +
|
| + total_errs = 0
|
| + for filenode in ast.GetListOf('File'):
|
| + errs = TestFile(filenode)
|
| + if errs:
|
| + ErrOut.Log('%s test failed with %d error(s).' %
|
| + (filenode.GetName(), errs))
|
| + total_errs += errs
|
| +
|
| + if total_errs:
|
| + ErrOut.Log('Failed generator test.')
|
| + else:
|
| + InfoOut.Log('Passed generator test.')
|
| + return total_errs
|
| +
|
| +def main(args):
|
| + filenames = ParseOptions(args)
|
| + if GetOption('test'):
|
| + return TestFiles(filenames)
|
| + ast = ParseFiles(filenames)
|
| + cgen = CGen()
|
| + for f in ast.GetListOf('File'):
|
| + if f.GetProperty('ERRORS') > 0:
|
| + print 'Skipping %s' % f.GetName()
|
| + continue
|
| + for node in f.GetChildren()[2:]:
|
| + print cgen.Define(node, comment=True, prefix='tst_')
|
| +
|
| +
|
| +if __name__ == '__main__':
|
| + sys.exit(main(sys.argv[1:]))
|
| +
|
|
|