diff options
-rw-r--r-- | ppapi/generators/idl_ast.py | 25 | ||||
-rw-r--r-- | ppapi/generators/idl_c_header.py | 300 | ||||
-rw-r--r-- | ppapi/generators/idl_c_proto.py | 314 | ||||
-rw-r--r-- | ppapi/generators/idl_generator.py | 72 | ||||
-rw-r--r-- | ppapi/generators/idl_namespace.py | 2 | ||||
-rw-r--r-- | ppapi/generators/idl_node.py | 5 | ||||
-rw-r--r-- | ppapi/generators/idl_outfile.py | 2 | ||||
-rw-r--r-- | ppapi/generators/test_cgen/enum_typedef.idl | 4 | ||||
-rw-r--r-- | ppapi/generators/test_cgen/interface.idl | 4 | ||||
-rw-r--r-- | ppapi/generators/test_cgen/structs.idl | 4 | ||||
-rw-r--r-- | ppapi/generators/test_cgen_range/versions.h | 42 | ||||
-rw-r--r-- | ppapi/generators/test_cgen_range/versions.idl | 36 |
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); +}; |