summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ppapi/generators/idl_ast.py25
-rw-r--r--ppapi/generators/idl_c_header.py300
-rw-r--r--ppapi/generators/idl_c_proto.py314
-rw-r--r--ppapi/generators/idl_generator.py72
-rw-r--r--ppapi/generators/idl_namespace.py2
-rw-r--r--ppapi/generators/idl_node.py5
-rw-r--r--ppapi/generators/idl_outfile.py2
-rw-r--r--ppapi/generators/test_cgen/enum_typedef.idl4
-rw-r--r--ppapi/generators/test_cgen/interface.idl4
-rw-r--r--ppapi/generators/test_cgen/structs.idl4
-rw-r--r--ppapi/generators/test_cgen_range/versions.h42
-rw-r--r--ppapi/generators/test_cgen_range/versions.idl36
12 files changed, 460 insertions, 350 deletions
diff --git a/ppapi/generators/idl_ast.py b/ppapi/generators/idl_ast.py
index 57105b7..95eae32 100644
--- a/ppapi/generators/idl_ast.py
+++ b/ppapi/generators/idl_ast.py
@@ -78,7 +78,6 @@ class IDLFileTypeResolver(IDLVisitor):
if node.IsA('File'):
node.SetProperty('FILE', node)
-
# If this node has a TYPEREF, resolve it to a version list
typeref = node.property_node.GetPropertyLocal('TYPEREF')
if typeref:
@@ -90,6 +89,14 @@ class IDLFileTypeResolver(IDLVisitor):
return filenode
+class IDLReleaseResolver(IDLVisitor):
+ def VisitFilter(self, node, data):
+ return node.IsA('AST','File', 'Label')
+
+ def Depart(self, node, data, childdata):
+ if node.IsA('Label'):
+ return set([child.name for child in GetListOf('LabelItem')])
+ return childdata
class IDLVersionMapDefault(IDLVersionMap):
def GetRelease(self, version):
@@ -116,15 +123,6 @@ class IDLAst(IDLNode):
builtin = filenode
break
-# if not builtin:
-# builtin = IDLFile('pp_stdint.idl', [])
-# extranodes = [builtin]
-
-# for name in BuiltIn:
-# nameattr = IDLAttribute('NAME', name)
-# typenode = IDLNode('Type', 'BuiltIn', 1, 0, [nameattr])
-# builtin.AddChild(typenode)
-
IDLNode.__init__(self, 'AST', 'BuiltIn', 1, 0, extranodes + children)
self.SetProperty('LABEL', IDLVersionMapDefault())
self.Resolve()
@@ -135,6 +133,13 @@ class IDLAst(IDLNode):
IDLNamespaceLabelResolver().Visit(self, self.namespace)
IDLFileTypeResolver().Visit(self, None)
+ # Build an ordered list of all releases
+ self.releases = set()
+ for filenode in self.GetListOf('File'):
+ vmap = filenode.GetProperty('LABEL')
+ self.releases |= set(vmap.releases)
+ self.releases = sorted(self.releases)
+
def SetTypeInfo(self, name, properties):
node = self.namespace[name]
for prop in properties:
diff --git a/ppapi/generators/idl_c_header.py b/ppapi/generators/idl_c_header.py
index 46ca82a..edec95f 100644
--- a/ppapi/generators/idl_c_header.py
+++ b/ppapi/generators/idl_c_header.py
@@ -17,16 +17,14 @@ from idl_ast import IDLAst
from idl_option import GetOption, Option, ParseOptions
from idl_outfile import IDLOutFile
from idl_parser import ParseFiles
-from idl_c_proto import CGen
-from idl_generator import Generator
+from idl_c_proto import CGen, GetNodeComments, CommentLines, Comment
+from idl_generator import Generator, GeneratorByFile
Option('dstroot', 'Base directory of output', default='../c')
Option('guard', 'Include guard prefix', default='ppapi/c')
Option('out', 'List of output files', default='')
-cgen = CGen()
-
-def IDLToHeader(filenode, relpath=None, prefix=None):
+def GetOutFileName(filenode, relpath=None, prefix=None):
path, name = os.path.split(filenode.GetProperty('NAME'))
name = os.path.splitext(name)[0] + '.h'
if prefix: name = '%s%s' % (prefix, name)
@@ -34,168 +32,198 @@ def IDLToHeader(filenode, relpath=None, prefix=None):
if relpath: name = os.path.join(relpath, name)
return name
+def WriteGroupMarker(out, node, last_group):
+ # If we are part of a group comment marker...
+ if last_group and last_group != node.cls:
+ pre = CommentLines(['*',' @}', '']) + '\n'
+ else:
+ pre = '\n'
-def GenerateHeader(filenode, release, pref, inline=True):
- name = filenode.GetProperty('NAME')
-# if name == 'pp_stdint.idl': return
-
- # If we have an 'out' filter list, then check if we should output this file.
- outlist = GetOption('out')
- if outlist:
- outlist = outlist.split(',')
- if name not in outlist:
- return
+ if node.cls in ['Typedef', 'Interface', 'Struct', 'Enum']:
+ if last_group != node.cls:
+ pre += CommentLines(['*',' @addtogroup %ss' % node.cls, ' @{', ''])
+ last_group = node.cls
+ else:
+ last_group = None
+ out.Write(pre)
+ return last_group
- savename = IDLToHeader(filenode, relpath=GetOption('dstroot'), prefix=pref)
- out = IDLOutFile(savename)
+def GenerateHeader(out, filenode, releases):
gpath = GetOption('guard')
- def_guard = IDLToHeader(filenode, relpath=gpath, prefix=pref)
- def_guard = def_guard.replace('/','_').replace('.','_').upper() + '_'
- cright_node = filenode.GetChildren()[0]
- assert(cright_node.IsA('Copyright'))
-
- fileinfo = filenode.GetChildren()[1]
- assert(fileinfo.IsA('Comment'))
-
- out.Write('%s\n' % cgen.Copyright(cright_node))
- out.Write('/* From %s modified %s. */\n\n'% (
- filenode.GetProperty('NAME'), filenode.GetProperty('DATETIME')))
- out.Write('#ifndef %s\n#define %s\n\n' % (def_guard, def_guard))
-
- for label in filenode.GetListOf('Label'):
- if label.GetName() == GetOption('label'):
- cgen.SetVersionMap(label)
-
- deps = filenode.GetDeps(release)
- # Generate set of includes
- includes = set([])
- for dep in deps:
- depfile = dep.GetProperty('FILE')
- if depfile:
- includes.add(depfile)
- includes = [IDLToHeader(include, relpath=gpath) for include in includes]
- includes.append('ppapi/c/pp_macros.h')
-
- # Assume we need stdint if we "include" C or C++ code
- if filenode.GetListOf('Include'):
- includes.append('ppapi/c/pp_stdint.h')
-
- includes = sorted(set(includes))
- cur_include = IDLToHeader(filenode, relpath=gpath)
- for include in includes:
- if include == cur_include: continue
- out.Write('#include "%s"\n' % include)
-
- # Generate all interface defines
- out.Write('\n')
- for node in filenode.GetListOf('Interface'):
- out.Write( cgen.InterfaceDefs(node) )
-
- # Generate the @file comment
- out.Write('%s\n' % cgen.Comment(fileinfo, prefix='*\n @file'))
+ cgen = CGen()
+ pref = ''
+ do_comments = True
# Generate definitions.
last_group = None
- for node in filenode.GetChildren()[2:]:
- # If we are part of a group comment marker...
- if last_group and last_group != node.cls:
- pre = cgen.CommentLines(['*',' @}', '']) + '\n'
- else:
- pre = '\n'
-
- if node.cls in ['Typedef', 'Interface', 'Struct', 'Enum']:
- if last_group != node.cls:
- pre += cgen.CommentLines(['*',' @addtogroup %ss' % node.cls, ' @{', ''])
- last_group = node.cls
- else:
- last_group = None
-
- if node.IsA('Comment'):
- item = '%s\n\n' % cgen.Comment(node)
- elif node.IsA('Inline'):
- if not inline: continue
+ top_types = ['Typedef', 'Interface', 'Struct', 'Enum', 'Inline']
+ for node in filenode.GetListOf(*top_types):
+ # Skip if this node is not in this release
+ if not node.InReleases(releases):
+ print "Skiping %s" % node
+ continue
+
+ # End/Start group marker
+ if do_comments:
+ last_group = WriteGroupMarker(out, node, last_group)
+
+ if node.IsA('Inline'):
+ item = node.GetProperty('VALUE')
+ # If 'C++' use __cplusplus wrapper
if node.GetName() == 'cc':
- item = cgen.Define(node, prefix=pref, comment=True)
item = '#ifdef __cplusplus\n%s\n#endif // __cplusplus\n\n' % item
- elif node.GetName() == 'c':
- item = cgen.Define(node, prefix=pref, comment=True)
- else:
+ # If not C++ or C, then skip it
+ elif not node.GetName() == 'c':
continue
- if not item: continue
- else:
- #
- # Otherwise we are defining a file level object, so generate the
- # correct document notation.
- #
- item = cgen.Define(node, prefix=pref, comment=True)
- if not item: continue
- asize = node.GetProperty('assert_size()')
- if asize:
- name = '%s%s' % (pref, node.GetName())
- if node.IsA('Struct'):
- form = 'PP_COMPILE_ASSERT_STRUCT_SIZE_IN_BYTES(%s, %s);\n'
- else:
- form = 'PP_COMPILE_ASSERT_SIZE_IN_BYTES(%s, %s);\n'
- item += form % (name, asize[0])
-
- if item: out.Write('%s%s' % (pre, item))
+ if item: out.Write(item)
+ continue
+
+ #
+ # Otherwise we are defining a file level object, so generate the
+ # correct document notation.
+ #
+ item = cgen.Define(node, releases, prefix=pref, comment=True)
+ if not item: continue
+ asize = node.GetProperty('assert_size()')
+ if asize:
+ name = '%s%s' % (pref, node.GetName())
+ if node.IsA('Struct'):
+ form = 'PP_COMPILE_ASSERT_STRUCT_SIZE_IN_BYTES(%s, %s);\n'
+ else:
+ form = 'PP_COMPILE_ASSERT_SIZE_IN_BYTES(%s, %s);\n'
+ item += form % (name, asize[0])
+
+ if item: out.Write(item)
if last_group:
- out.Write(cgen.CommentLines(['*',' @}', '']) + '\n')
+ out.Write(CommentLines(['*',' @}', '']) + '\n')
- out.Write('#endif /* %s */\n\n' % def_guard)
- return out.Close()
-class HGen(Generator):
+class HGen(GeneratorByFile):
def __init__(self):
Generator.__init__(self, 'C Header', 'cgen', 'Generate the C headers.')
- def GenerateVersion(self, ast, release, options):
- outdir = GetOption('dstroot')
- skipList= []
- prefix = ''
- cfile = None
- cnt = 0
-
- for filenode in ast.GetListOf('File'):
- if GetOption('verbose'):
- print "Working on %s" % filenode
-
- # If this file has errors, skip it
- if filenode.GetProperty('ERRORS') > 0:
- skipList.append(filenode)
- continue
-
- if GenerateHeader(filenode, release, prefix):
- cnt = cnt + 1
-
- for filenode in skipList:
- errcnt = filenode.GetProperty('ERRORS')
- ErrOut.Log('%s : Skipped because of %d errors.' % (
- filenode.GetName(), errcnt))
-
- if skipList:
- return -len(skipList)
-
- if GetOption('diff'):
- return -cnt
- return cnt
+ def GetMacro(self, node):
+ name = node.GetName()
+ name = name.upper()
+ return "%s_INTERFACE" % name
+
+ 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
+
+
+ def GetOutFile(self, filenode, options):
+ savename = GetOutFileName(filenode, GetOption('dstroot'))
+ return IDLOutFile(savename)
+
+ def GenerateHead(self, out, filenode, releases, options):
+ cgen = CGen()
+ gpath = GetOption('guard')
+ release = releases[0]
+ def_guard = GetOutFileName(filenode, relpath=gpath)
+ def_guard = def_guard.replace('/','_').replace('.','_').upper() + '_'
+
+ cright_node = filenode.GetChildren()[0]
+ assert(cright_node.IsA('Copyright'))
+ fileinfo = filenode.GetChildren()[1]
+ assert(fileinfo.IsA('Comment'))
+
+ out.Write('%s\n' % cgen.Copyright(cright_node))
+ out.Write('/* From %s modified %s. */\n\n'% (
+ filenode.GetProperty('NAME'), filenode.GetProperty('DATETIME')))
+ out.Write('#ifndef %s\n#define %s\n\n' % (def_guard, def_guard))
+ # Generate set of includes
+
+ deps = set()
+ for release in releases:
+ deps |= filenode.GetDeps(release)
+
+ includes = set([])
+ for dep in deps:
+ depfile = dep.GetProperty('FILE')
+ if depfile:
+ includes.add(depfile)
+ includes = [GetOutFileName(include, relpath=gpath) for include in includes]
+ includes.append('ppapi/c/pp_macros.h')
+
+ # Assume we need stdint if we "include" C or C++ code
+ if filenode.GetListOf('Include'):
+ includes.append('ppapi/c/pp_stdint.h')
+
+ includes = sorted(set(includes))
+ cur_include = GetOutFileName(filenode, relpath=gpath)
+ for include in includes:
+ if include == cur_include: continue
+ out.Write('#include "%s"\n' % include)
+
+ # Generate all interface defines
+ out.Write('\n')
+ for node in filenode.GetListOf('Interface'):
+ idefs = ''
+ name = node.GetName()
+ macro = node.GetProperty('macro')
+ if not macro:
+ macro = self.GetMacro(node)
+ label = node.GetLabel()
+ if label:
+ for vers in label.versions:
+ strver = str(vers).replace('.', '_')
+ idefs += self.GetDefine('%s_%s' % (macro, strver),
+ '"%s;%s"' % (name, vers))
+ if label.GetRelease(vers) == releases[-1]:
+ idefs += self.GetDefine(macro, '%s_%s' % (macro, strver))
+ idefs += '\n'
+ out.Write(idefs)
+
+ # Generate the @file comment
+ out.Write('%s\n' % Comment(fileinfo, prefix='*\n @file'))
+
+ def GenerateBody(self, out, filenode, releases, options):
+ GenerateHeader(out, filenode, releases)
+
+ def GenerateTail(self, out, filenode, releases, options):
+ gpath = GetOption('guard')
+ def_guard = GetOutFileName(filenode, relpath=gpath)
+ def_guard = def_guard.replace('/','_').replace('.','_').upper() + '_'
+ out.Write('#endif /* %s */\n\n' % def_guard)
hgen = HGen()
def Main(args):
# Default invocation will verify the golden files are unchanged.
+ failed = 0
if not args:
args = ['--wnone', '--diff', '--test', '--dstroot=.']
ParseOptions(args)
+
idldir = os.path.split(sys.argv[0])[0]
idldir = os.path.join(idldir, 'test_cgen', '*.idl')
filenames = glob.glob(idldir)
+ ast = ParseFiles(filenames)
+ if hgen.GenerateRelease(ast, 'M14', {}):
+ print "Golden file for M14 failed."
+ failed = 1
+ else:
+ print "Golden file for M14 passed."
+
+
+ idldir = os.path.split(sys.argv[0])[0]
+ idldir = os.path.join(idldir, 'test_cgen_range', '*.idl')
+ filenames = glob.glob(idldir)
ast = ParseFiles(filenames)
- return hgen.GenerateVersion(ast, 'M14', {})
+ if hgen.GenerateRange(ast, ['M13', 'M14', 'M15'], {}):
+ print "Golden file for M13-M15 failed."
+ failed =1
+ else:
+ print "Golden file for M13-M15 passed."
+
+ return failed
if __name__ == '__main__':
retval = Main(sys.argv[1:])
diff --git a/ppapi/generators/idl_c_proto.py b/ppapi/generators/idl_c_proto.py
index a116e36..05937e4 100644
--- a/ppapi/generators/idl_c_proto.py
+++ b/ppapi/generators/idl_c_proto.py
@@ -26,6 +26,47 @@ class CGenError(Exception):
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, prefix=None, 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
#
@@ -103,17 +144,6 @@ class CGen(object):
def __init__(self):
self.dbg_depth = 0
- self.vmin = 0.0
- self.vmax = 1e100
- self.release = GetOption('release')
-
- def SetVersionMap(self, node):
- self.vmin = 0.0
- self.vmax = 1e100
- for version in node.GetListOf('LabelItem'):
- if version.GetName() == GetOption('release'):
- self.vmin = float(version.GetProperty('VALUE'))
- self.vmax = float(version.GetProperty('VALUE'))
#
# Debug Logging functions
@@ -152,12 +182,13 @@ class CGen(object):
#
# For a given node return the type name by passing mode.
#
- def GetTypeName(self, node, prefix=''):
- self.LogEnter('GetTypeName of %s' % node)
+ def GetTypeName(self, node, release, prefix=''):
+ self.LogEnter('GetTypeName of %s rel=%s' % (node, release))
- # For Members, Params, and Typedef's your want type it refers to
+ # 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(self.release)
+ typeref = node.GetType(release)
else:
typeref = node
@@ -194,19 +225,20 @@ class CGen(object):
# For a given node return basic type of that object. This is
# either a 'Type', 'Callspec', or 'Array'
#
- def GetRootTypeMode(self, node, mode):
+ 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(self.release),
+ 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(self.release), mode)
+ rootType, mode = self.GetRootTypeMode(node.GetType(release),
+ release, mode)
# If it's an Enum, then it's normal passing rules
elif node.IsA('Enum'):
@@ -237,10 +269,11 @@ class CGen(object):
return rootType, mode
- def GetTypeByMode(self, node, mode):
- self.LogEnter('GetTypeByMode of %s mode=%s' % (node, mode))
- name = self.GetTypeName(node)
- ntype, mode = self.GetRootTypeMode(node, 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
@@ -264,15 +297,15 @@ class CGen(object):
# arrays - A list of array dimensions as [] or [<fixed_num>].
# args - None of not a function, otherwise a list of parameters.
#
- def GetComponents(self, node, mode):
- self.LogEnter('GetComponents mode %s for %s' % (mode, node))
+ 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, mode)
+ rtype = self.GetTypeByMode(node, release, mode)
if node.IsA('Enum', 'Interface', 'Struct'):
rname = node.GetName()
else:
- rname = node.GetType(self.release).GetName()
+ rname = node.GetType(release).GetName()
if rname in CGen.RemapName:
rname = CGen.RemapName[rname]
@@ -285,7 +318,7 @@ class CGen(object):
callspec = []
for param in callnode.GetListOf('Param'):
mode = self.GetParamMode(param)
- ptype, pname, parray, pspec = self.GetComponents(param, mode)
+ ptype, pname, parray, pspec = self.GetComponents(param, release, mode)
callspec.append((ptype, pname, parray, pspec))
else:
callspec = None
@@ -317,32 +350,23 @@ class CGen(object):
# prefix - A prefix for the object's name
# func_as_ptr - Formats a function as a function pointer
#
- def GetSignature(self, node, mode, prefix='', func_as_ptr=True):
+ def GetSignature(self, node, release, mode, prefix='', func_as_ptr=True):
self.LogEnter('GetSignature %s %s as func=%s' % (node, mode, func_as_ptr))
- rtype, name, arrayspec, callspec = self.GetComponents(node, mode)
+ rtype, name, arrayspec, callspec = self.GetComponents(node, release, mode)
out = self.Compose(rtype, name, arrayspec, callspec, prefix, func_as_ptr)
self.LogExit('Exit GetSignature: %s' % out)
return out
- def GetMacro(self, node):
- name = node.GetName()
- name = name.upper()
- return "%s_INTERFACE" % name
-
- 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
-
- # Define an Typedef.
- def DefineTypedef(self, node, prefix='', comment=False):
- out = 'typedef %s;\n' % self.GetSignature(node, 'return', prefix, True)
+ # Define a Typedef.
+ def DefineTypedef(self, node, releases, prefix='', comment=False):
+ release = releases[0]
+ out = 'typedef %s;\n' % self.GetSignature(node, release, 'return',
+ prefix, True)
self.Log('DefineTypedef: %s' % out)
return out
# Define an Enum.
- def DefineEnum(self, node, prefix='', comment=False):
+ def DefineEnum(self, node, releases, prefix='', comment=False):
self.LogEnter('DefineEnum %s' % node)
unnamed = node.GetProperty('unnamed')
if unnamed:
@@ -353,12 +377,7 @@ class CGen(object):
enumlist = []
for child in node.GetListOf('EnumItem'):
value = child.GetProperty('VALUE')
- comment_txt = ''
- if comment:
- for comment_node in child.GetListOf('Comment'):
- comment_txt += self.Comment(comment_node, tabs=1)
- if comment_txt:
- comment_txt = '%s' % comment_txt
+ comment_txt = GetNodeComments(child, tabs=1)
if value:
item_txt = '%s%s = %s' % (prefix, child.GetName(), value)
else:
@@ -372,36 +391,15 @@ class CGen(object):
out = '%s\n%s\n} %s;\n' % (out, ',\n'.join(enumlist), name)
return out
- def DefineMember(self, node, prefix='', comment=False):
+ def DefineMember(self, node, releases, prefix='', comment=False):
+ release = releases[0]
self.LogEnter('DefineMember %s' % node)
-
-# out = ''
-# if comment:
-# for doc in node.GetListOf('Comment'):
-# out += self.Comment(doc)
- out = '%s;' % self.GetSignature(node, 'store', '', True)
+ out = '%s;' % self.GetSignature(node, release, 'store', '', True)
self.LogExit('Exit DefineMember')
return out
- def InterfaceDefs(self, node):
- out = ''
- name = node.GetName()
- macro = node.GetProperty('macro')
- if not macro:
- macro = self.GetMacro(node)
- label = node.GetLabel()
- if label:
- for vers in label.versions:
- strver = str(vers).replace('.', '_')
- out += self.GetDefine('%s_%s' % (macro, strver),
- '"%s;%s"' % (name, vers))
- if label.GetRelease(vers) == self.release:
- out += self.GetDefine(macro, '%s_%s' % (macro, strver))
- out += '\n'
- return out
-
# Define a Struct.
- def DefineStruct(self, node, prefix='', comment=False):
+ def DefineStruct(self, node, releases, prefix='', comment=False):
out = ''
self.LogEnter('DefineStruct %s' % node)
@@ -413,7 +411,7 @@ class CGen(object):
# Generate Member Functions
members = []
for child in node.GetListOf('Member'):
- member = self.Define(child, tabs=1, comment=comment)
+ member = self.Define(child, releases, tabs=1, comment=comment)
if not member:
continue
members.append(member)
@@ -421,9 +419,6 @@ class CGen(object):
self.LogExit('Exit DefineStruct')
return out
- def DefineType(self, node, prefix='', comment=False):
- return ''
-
#
# Copyright and Comment
#
@@ -431,124 +426,59 @@ class CGen(object):
#
def Copyright(self, node, tabs=0):
lines = node.GetName().split('\n')
- return self.CommentLines(lines, tabs)
-
- def Comment(self, node, prefix=None, tabs=0):
- comment = node.GetName()
-
- # Ignore comments that do not have a '*' marker
-# if comment[0] != '*' and not prefix: return ''
-
- lines = comment.split('\n')
- if prefix:
- prefix = prefix.split('\n')
- if prefix[0] == '*' and lines[0] == '*':
- lines = prefix + lines[1:]
- else:
- lines = prefix + lines;
- return self.CommentLines(lines, tabs)
-
- def CommentLines(self, lines, tabs=0):
- tab = ''.join([' ' for i in range(tabs)])
- if lines[-1] == '':
- return '%s/*' % tab + ('\n%s *' % tab).join(lines) + '/\n'
- else:
- return '%s/*' % tab + ('\n%s *' % tab).join(lines) + ' */\n'
+ return CommentLines(lines, tabs)
# Define a top level object.
- def Define(self, node, tabs=0, prefix='', comment=False):
- if True:
-# try:
- self.LogEnter('Define %s tab=%d prefix="%s"' % (node,tabs,prefix))
-
- node_nim = node.GetProperty('version')
- node_max = node.GetProperty('deprecate')
+ def Define(self, node, releases, tabs=0, prefix='', comment=False):
+ if not node.InReleases(releases):
+ return ''
- if node_nim is not None:
- node_nim = float(node_nim)
- else:
- node_nim = 0.0
+ self.LogEnter('Define %s tab=%d prefix="%s"' % (node,tabs,prefix))
+ declmap = {
+ 'Enum' : CGen.DefineEnum,
+ 'Function' : CGen.DefineMember,
+ 'Interface' : CGen.DefineStruct,
+ 'Member' : CGen.DefineMember,
+ 'Struct' : CGen.DefineStruct,
+ 'Typedef' : CGen.DefineTypedef,
+ }
- if node_max is not None:
- node_max = float(node_max)
- else:
- node_max = 1.0e100
-
- label = node.GetLabel()
- if label:
- lver = label.GetVersion(self.release)
-
- # Verify that we are in a valid version.
- if node_max <= lver: return ''
- if node_nim > lver: return ''
-
- declmap = {
- 'Describe' : CGen.DefineType,
- 'Enum' : CGen.DefineEnum,
- 'Function' : CGen.DefineMember,
- 'Interface' : CGen.DefineStruct,
- 'Member' : CGen.DefineMember,
- 'Struct' : CGen.DefineStruct,
- 'Type' : CGen.DefineType,
- 'Typedef' : CGen.DefineTypedef,
- }
-
- if node.cls == 'Inline':
- return node.GetProperty('VALUE')
-
- if node.cls == 'Label':
- return ''
-
- out = ''
- comment_txt = ''
- if comment:
- for doc in node.GetListOf('Comment'):
- comment_txt += self.Comment(doc)
-
- func = declmap.get(node.cls)
- if not func:
- ErrOut.Log('Failed to define %s named %s' % (node.cls, node.GetName()))
-
- define_txt = func(self, node, prefix=prefix, comment=comment)
- if comment_txt:
- out += '%s%s' % (comment_txt, define_txt)
- else:
- out += define_txt
-
- tab = ''
- for i in range(tabs):
- tab += ' '
-
- lines = []
- for line in out.split('\n'):
- # Add indentation
- line = '%s%s' % (tab, line)
- if len(line) > 80:
- left = line.rfind('(') + 1
- 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:
- space = '%s ' % tab
- args = (',\n%s' % space).join([arg.strip() for arg in args])
- lines.append('%s\n%s%s' % (line[:left], space, args))
- else:
- space = ' '.join(['' for i in range(left)])
- args = (',\n%s' % space).join(args)
- lines.append('%s%s' % (line[:left], args))
+ out = ''
+ func = declmap.get(node.cls)
+ 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
+
+ tab = ' ' * tabs
+ lines = []
+ for line in out.split('\n'):
+ # Add indentation
+ line = tab + line
+ if len(line) > 80:
+ left = line.rfind('(') + 1
+ 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:
+ space = '%s ' % tab
+ args = (',\n%s' % space).join([arg.strip() for arg in args])
+ lines.append('%s\n%s%s' % (line[:left], space, args))
else:
- lines.append(line.rstrip())
-
- # out = tab + ('\n%s' % tab).join(out.split('\n')) + '\n'
- self.LogExit('Exit Define')
- return '\n'.join(lines)
-# except:
- if False:
- node.Error('Failed to resolve.')
- return ''
+ space = ' ' * (left - 1)
+ args = (',\n%s' % space).join(args)
+ lines.append('%s%s' % (line[:left], args))
+ else:
+ lines.append(line.rstrip())
+ self.LogExit('Exit Define')
+ return '\n'.join(lines)
# Clean a string representing an object definition and return then string
# as a single space delimited set of tokens.
@@ -569,7 +499,7 @@ def TestFile(filenode):
instr.Dump()
instr = CleanString(instr.GetName())
- outstr = cgen.Define(node)
+ outstr = cgen.Define(node, releases=['M14'])
if GetOption('verbose'):
print outstr + '\n'
outstr = CleanString(outstr)
diff --git a/ppapi/generators/idl_generator.py b/ppapi/generators/idl_generator.py
index 32c943c..123d08a 100644
--- a/ppapi/generators/idl_generator.py
+++ b/ppapi/generators/idl_generator.py
@@ -20,7 +20,7 @@ Option('range', 'Which release ranges in the form of MIN,MAX.', default='')
#
# Base class for generators. This class provides a mechanism for
# adding new generator objects to the IDL driver. To use this class
-# override the GenerateVersion and GenerateRange members, and
+# override the GenerateRelease and GenerateRange members, and
# instantiate one copy of the class in the same module which defines it to
# register the generator. After the AST is generated, call the static Run
# member which will check every registered generator to see which ones have
@@ -75,13 +75,15 @@ class Generator(object):
else:
vmin = range_list[0]
vmax = range_list[1]
- ret = self.GenerateRange(ast, vmin, vmax, options)
- if not ret:
+ vmin = ast.releases.index(vmin)
+ vmax = ast.releases.index(vmax) + 1
+ ret = self.GenerateRange(ast, ast.releases[vmin:vmax], options)
+ if ret < 0:
self.Error('Failed to generate range %s : %s.' %(vmin, vmax))
# Otherwise this should be a single release generation
else:
if releasestr:
- ret = self.GenerateVersion(ast, releasestr, options)
+ ret = self.GenerateRelease(ast, releasestr, options)
if ret < 0:
self.Error('Failed to generate release %s.' % releasestr)
else:
@@ -91,7 +93,7 @@ class Generator(object):
self.Error('No range or release specified for %s.' % releasestr)
return self.errors
- def GenerateVersion(self, ast, release, options):
+ def GenerateRelease(self, ast, release, options):
__pychecker__ = 'unusednames=ast,release,options'
self.Error("Undefined release generator.")
return 0
@@ -114,11 +116,65 @@ class Generator(object):
return fail_count
+#
+# GeneratorByFile
+#
+# A subclass of Generator for use of generators which have a one to one
+# mapping between IDL sources and output files. To use, derive a new class
+# which defines:
+#
+# GetOutFile - Returns an IDLOutFile based on filenode (name) and options
+# GenerateHead - Writes the first part of the file (includes, etc...)
+# GenerateBody - Writes the body of the file (definitions)
+# GenerateTail - Writes the end of the file (closing include guard, etc...)
+#
+class GeneratorByFile(Generator):
+ def GenerateRelease(self, ast, release, options):
+ return self.GenerateRange(ast, [release], options)
+
+ def GenerateRange(self, ast, releases, options):
+ # Get list of out files
+ outlist = GetOption('out')
+ if outlist: outlist = outlist.split(',')
+
+ skipList = []
+ cnt = 0
+ for filenode in ast.GetListOf('File'):
+ # Skip this file if not required
+ if outlist and name not in outlist:
+ continue
+
+ # If this file has errors, skip it
+ if filenode.GetProperty('ERRORS') > 0:
+ skipList.append(filenode)
+ continue
+
+ # Create output file
+ out = self.GetOutFile(filenode, options)
+ self.GenerateHead(out, filenode, releases, options)
+ self.GenerateBody(out, filenode, releases, options)
+ self.GenerateTail(out, filenode, releases, options)
+
+ if out.Close(): cnt = cnt + 1
+
+ for filenode in skipList:
+ errcnt = filenode.GetProperty('ERRORS')
+ ErrOut.Log('%s : Skipped because of %d errors.' % (
+ filenode.GetName(), errcnt))
+
+ if skipList:
+ return -len(skipList)
+
+ if GetOption('diff'):
+ return -cnt
+ return cnt
+
+
check_release = 0
check_range = 0
-class GeneratorVersionTest(Generator):
- def GenerateVersion(self, ast, release, options = {}):
+class GeneratorReleaseTest(Generator):
+ def GenerateRelease(self, ast, release, options = {}):
__pychecker__ = 'unusednames=ast,release,options'
global check_release
check_map = {
@@ -182,6 +238,6 @@ def Main(args):
if __name__ == '__main__':
- GeneratorVersionTest('Test Gen', 'testgen', 'Generator Class Test.')
+ GeneratorReleaseTest('Test Gen', 'testgen', 'Generator Class Test.')
sys.exit(Main(sys.argv[1:]))
diff --git a/ppapi/generators/idl_namespace.py b/ppapi/generators/idl_namespace.py
index 2451168..98e86258 100644
--- a/ppapi/generators/idl_namespace.py
+++ b/ppapi/generators/idl_namespace.py
@@ -105,11 +105,13 @@ class IDLVersionMap(object):
self.version_to_release = {}
self.release_to_version = {}
self.versions = []
+ self.releases = []
def AddReleaseVersionMapping(self, release, version):
self.version_to_release[version] = release
self.release_to_version[release] = version
self.versions = sorted(self.version_to_release.keys())
+ self.releases = sorted(self.release_to_version.keys())
def GetRelease(self, version):
# Check for exact match
diff --git a/ppapi/generators/idl_node.py b/ppapi/generators/idl_node.py
index 0c8c180..b8f71eb 100644
--- a/ppapi/generators/idl_node.py
+++ b/ppapi/generators/idl_node.py
@@ -214,6 +214,11 @@ class IDLNode(IDLVersion):
out = self.IsVersion(version)
return out
+ def InReleases(self, releases):
+ for rel in releases:
+ if self.IsRelease(rel): return True
+ return False
+
def GetLabel(self):
label = self.GetProperty('LABEL')
if not label:
diff --git a/ppapi/generators/idl_outfile.py b/ppapi/generators/idl_outfile.py
index d643b2f..ae8da4e 100644
--- a/ppapi/generators/idl_outfile.py
+++ b/ppapi/generators/idl_outfile.py
@@ -83,7 +83,7 @@ class IDLOutFile(object):
if os.path.isfile(filename):
intext = open(filename, 'r').read()
else:
- intext = None
+ intext = ''
if IsEquivelent(intext, outtext):
if GetOption('verbose'):
diff --git a/ppapi/generators/test_cgen/enum_typedef.idl b/ppapi/generators/test_cgen/enum_typedef.idl
index 45f1472..b5d0feb 100644
--- a/ppapi/generators/test_cgen/enum_typedef.idl
+++ b/ppapi/generators/test_cgen/enum_typedef.idl
@@ -4,7 +4,9 @@
* found in the LICENSE file.
*/
-/* This file will test that the IDL snippet matches the comment */
+/**
+ * This file will test that the IDL snippet matches the comment.
+ */
/* typedef enum { A = 1, B = 2, C = 3 } et1; */
enum et1 { A=1, B=2, C=3 };
diff --git a/ppapi/generators/test_cgen/interface.idl b/ppapi/generators/test_cgen/interface.idl
index 0992614..e017daf 100644
--- a/ppapi/generators/test_cgen/interface.idl
+++ b/ppapi/generators/test_cgen/interface.idl
@@ -4,7 +4,9 @@
* found in the LICENSE file.
*/
-/* This file will test that the IDL snippet matches the comment */
+/**
+ * This file will test that the IDL snippet matches the comment.
+ */
/* struct ist { void* X; }; */
struct ist {
diff --git a/ppapi/generators/test_cgen/structs.idl b/ppapi/generators/test_cgen/structs.idl
index e942f05..ecf7163 100644
--- a/ppapi/generators/test_cgen/structs.idl
+++ b/ppapi/generators/test_cgen/structs.idl
@@ -4,7 +4,9 @@
* found in the LICENSE file.
*/
-/* This file will test that the IDL snippet matches the comment */
+/**
+ * This file will test that the IDL snippet matches the comment.
+ */
/* typedef uint8_t s_array[3]; */
typedef uint8_t[3] s_array;
diff --git a/ppapi/generators/test_cgen_range/versions.h b/ppapi/generators/test_cgen_range/versions.h
new file mode 100644
index 0000000..819ec0c
--- /dev/null
+++ b/ppapi/generators/test_cgen_range/versions.h
@@ -0,0 +1,42 @@
+/* Copyright (c) 2011 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.
+ */
+
+/* From test_cgen_range/versions.idl modified Wed Aug 24 10:35:01 2011. */
+
+#ifndef PPAPI_C_TEST_CGEN_RANGE_VERSIONS_H_
+#define PPAPI_C_TEST_CGEN_RANGE_VERSIONS_H_
+
+#include "ppapi/c/pp_macros.h"
+
+/**
+ * @file
+ * File Comment. */
+
+
+/**
+ * @addtogroup Structs
+ * @{
+ */
+/* Bogus Struct */
+struct PP_Size {
+ /**
+ * Comment for function
+ */
+ int32_t (*Foo)(int32_t x);
+ /**
+ * Comment for function
+ */
+ int32_t (*Foo)(int32_t x, int32_t y);
+ /**
+ * Comment for function
+ */
+ int32_t (*Foo)(int32_t x, int32_t y, int32_t z);
+};
+/**
+ * @}
+ */
+
+#endif /* PPAPI_C_TEST_CGEN_RANGE_VERSIONS_H_ */
+
diff --git a/ppapi/generators/test_cgen_range/versions.idl b/ppapi/generators/test_cgen_range/versions.idl
new file mode 100644
index 0000000..f4fe232
--- /dev/null
+++ b/ppapi/generators/test_cgen_range/versions.idl
@@ -0,0 +1,36 @@
+/* Copyright (c) 2011 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.
+ */
+
+/* File Comment. */
+
+label Chrome {
+ M13 = 0.0,
+ M14 = 1.0,
+ M15 = 2.0
+};
+
+[version=0.0]
+describe {
+ /** Standard Ints. */
+ int32_t;
+};
+
+
+/* Bogus Struct */
+[version=0.0]
+struct PP_Size {
+ /**
+ * Comment for function
+ */
+ [version=0.0] int32_t Foo(int32_t x);
+ /**
+ * Comment for function
+ */
+ [version=1.0] int32_t Foo(int32_t x, int32_t y);
+ /**
+ * Comment for function
+ */
+ [version=2.0] int32_t Foo(int32_t x, int32_t y, int32_t z);
+};