diff options
author | noelallen@chromium.org <noelallen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-23 18:10:02 +0000 |
---|---|---|
committer | noelallen@chromium.org <noelallen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-23 18:10:02 +0000 |
commit | 98cfdfce60a0a155ada3b5c952ec0358e5933484 (patch) | |
tree | efd6f8b65498a5bfc5335d1c54d40fd56ee2a2af /ppapi | |
parent | ccec4adb0558007d00b89da348ff49a10d113e9c (diff) | |
download | chromium_src-98cfdfce60a0a155ada3b5c952ec0358e5933484.zip chromium_src-98cfdfce60a0a155ada3b5c952ec0358e5933484.tar.gz chromium_src-98cfdfce60a0a155ada3b5c952ec0358e5933484.tar.bz2 |
Change the way we generate versions.
Changes (sehr)
Remove hashes used to determine 'unique' versions.
Build release lists for versionable nodes
Build mapping for any release to first release
Added support to treat interface as type
Cleanup (sehr)
Removed verbose output from pnacl wrapper.
Cleanup use of "private" members
Add better error recovery on parsing to prevent deadlock.
Fix parser tests.
To prevent growing this CL, additional cleanup in BUG=157025
PPAPI (brettw)
api/private/*.idl + c/private/*.h
Fix IDL use of net_address_private prior to definition
Date change on ppapi headers to pass presubmit
BUG=156719
TEST=idl_parser.py --test
Review URL: https://chromiumcodereview.appspot.com/11235016
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@163603 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ppapi')
-rw-r--r-- | ppapi/api/private/ppb_net_address_private.idl | 3 | ||||
-rw-r--r-- | ppapi/c/private/ppb_net_address_private.h | 2 | ||||
-rwxr-xr-x | ppapi/generators/generator.py | 4 | ||||
-rw-r--r-- | ppapi/generators/idl_ast.py | 146 | ||||
-rwxr-xr-x | ppapi/generators/idl_c_header.py | 4 | ||||
-rwxr-xr-x | ppapi/generators/idl_c_proto.py | 37 | ||||
-rw-r--r-- | ppapi/generators/idl_gen_wrapper.py | 12 | ||||
-rwxr-xr-x | ppapi/generators/idl_namespace.py | 32 | ||||
-rwxr-xr-x | ppapi/generators/idl_node.py | 160 | ||||
-rwxr-xr-x | ppapi/generators/idl_parser.py | 96 | ||||
-rwxr-xr-x | ppapi/generators/idl_propertynode.py | 1 | ||||
-rwxr-xr-x | ppapi/generators/idl_release.py | 38 | ||||
-rw-r--r-- | ppapi/generators/test_cgen/interface.idl | 17 | ||||
-rw-r--r-- | ppapi/generators/test_namespace/bar.idl | 4 | ||||
-rw-r--r-- | ppapi/generators/test_namespace/foo.idl | 2 | ||||
-rw-r--r-- | ppapi/generators/test_parser/enum.idl | 4 | ||||
-rw-r--r-- | ppapi/native_client/src/untrusted/pnacl_irt_shim/pnacl_shim.c | 2 |
17 files changed, 428 insertions, 136 deletions
diff --git a/ppapi/api/private/ppb_net_address_private.idl b/ppapi/api/private/ppb_net_address_private.idl index 222097f..cf6804c 100644 --- a/ppapi/api/private/ppb_net_address_private.idl +++ b/ppapi/api/private/ppb_net_address_private.idl @@ -8,6 +8,7 @@ */ label Chrome { + M13 = 0.0, M17 = 0.1, M19_0 = 1.0, M19_1 = 1.1 @@ -43,7 +44,7 @@ struct PP_NetAddress_Private { * The <code>PPB_NetAddress_Private</code> interface provides operations on * network addresses. */ -interface PPB_NetAddress_Private { +[version=0.1] interface PPB_NetAddress_Private { /** * Returns PP_TRUE if the two addresses are equal (host and port). */ diff --git a/ppapi/c/private/ppb_net_address_private.h b/ppapi/c/private/ppb_net_address_private.h index d5a5350..2ae1366 100644 --- a/ppapi/c/private/ppb_net_address_private.h +++ b/ppapi/c/private/ppb_net_address_private.h @@ -4,7 +4,7 @@ */ /* From private/ppb_net_address_private.idl, - * modified Wed Mar 21 11:10:47 2012. + * modified Sat Oct 20 12:39:54 2012. */ #ifndef PPAPI_C_PRIVATE_PPB_NET_ADDRESS_PRIVATE_H_ diff --git a/ppapi/generators/generator.py b/ppapi/generators/generator.py index ffa24d3..b1ab0ee 100755 --- a/ppapi/generators/generator.py +++ b/ppapi/generators/generator.py @@ -36,8 +36,12 @@ def Main(): filenames = ParseOptions(args) ast = ParseFiles(filenames) + if ast.errors: + print 'Found %d errors. Aborting build.\n' % ast.errors + return 1 return Generator.Run(ast) if __name__ == '__main__': sys.exit(Main()) + diff --git a/ppapi/generators/idl_ast.py b/ppapi/generators/idl_ast.py index b7ad6f0..2765892 100644 --- a/ppapi/generators/idl_ast.py +++ b/ppapi/generators/idl_ast.py @@ -19,28 +19,76 @@ BuiltIn = set(['int8_t', 'int16_t', 'int32_t', 'int64_t', 'uint8_t', # -# IDLNamespaceLabelResolver +# IDLLabelResolver # -# Once the AST is build, we need to resolve the namespace and version -# information. +# A specialized visitor which traverses the AST, building a mapping of +# Release names to Versions numbers and calculating a min version. +# The mapping is applied to the File nodes within the AST. # -class IDLNamespaceLabelResolver(IDLVisitor): +class IDLLabelResolver(IDLVisitor): + def Arrive(self, node, ignore): + # If we are entering a File, clear the visitor local mapping + if node.IsA('File'): + self.release_map = None + self.filenode = node + # For any non AST node, the filenode is the last known file + if not node.IsA('AST'): + node.filenode = self.filenode + return ignore + + def Depart(self, node, ignore, childdata): + # Build list of Release=Version + if node.IsA('LabelItem'): + return (node.GetName(), node.GetProperty('VALUE')) + + # On completion of the Label, apply to the parent File if the + # name of the label matches the generation label. + if node.IsA('Label') and node.GetName() == GetOption('label'): + try: + self.release_map = IDLReleaseMap(childdata) + node.parent.release_map = self.release_map + except Exception as err: + node.Error('Unable to build release map: %s' % str(err)) + + # For File objects, set the minimum version + if node.IsA('File'): + file_min, file_max = node.release_map.GetReleaseRange() + node.SetMin(file_min) + + return None + + +# +# IDLNamespaceVersionResolver +# +# A specialized visitor which traverses the AST, building a namespace tree +# as it goes. The namespace tree is mapping from a name to a version list. +# Labels must already be resolved to use. +# +class IDLNamespaceVersionResolver(IDLVisitor): NamespaceSet = set(['AST', 'Callspec', 'Interface', 'Member', 'Struct']) # # When we arrive at a node we must assign it a namespace and if the # node is named, then place it in the appropriate namespace. # def Arrive(self, node, parent_namespace): - # If we are entering a parent, clear the local Label\ - if node.IsA('File'): self.release_map = None + # If we are a File, grab the Min version and replease mapping + if node.IsA('File'): + self.rmin = node.GetMinMax()[0] + self.release_map = node.release_map + + # Set the min version on any non Label within the File + if not node.IsA('AST', 'File', 'Label', 'LabelItem'): + my_min, my_max = node.GetMinMax() + if not my_min: + node.SetMin(self.rmin) # If this object is not a namespace aware object, use the parent's one if node.cls not in self.NamespaceSet: node.namespace = parent_namespace else: # otherwise create one. - node.namespace = IDLNamespace(parent_namespace) - node.namespace.name = node.GetName() + node.namespace = IDLNamespace(parent_namespace, node.GetName()) # If this node is named, place it in its parent's namespace if parent_namespace and node.cls in IDLNode.NamedSet: @@ -48,7 +96,11 @@ class IDLNamespaceLabelResolver(IDLVisitor): if self.release_map: vmin = node.GetProperty('version') vmax = node.GetProperty('deprecate') - rmin = self.release_map.GetRelease(vmin) + # If no min is available, the use the parent File's min + if vmin == None: + rmin = self.rmin + else: + rmin = self.release_map.GetRelease(vmin) rmax = self.release_map.GetRelease(vmax) node.SetReleaseRange(rmin, rmax) parent_namespace.AddNode(node) @@ -56,24 +108,15 @@ class IDLNamespaceLabelResolver(IDLVisitor): # Pass this namespace to each child in case they inherit it return node.namespace - # - # As we return from a node, if the node is a LabelItem we pass back - # the key=value pair representing the mapping of release to version. - # If the node is a Label take the lists of mapping and generate a - # version map which is assigned to the Labels parent as a property. - # - def Depart(self, node, data, childdata): - if node.IsA('LabelItem'): - return (node.GetName(), node.GetProperty('VALUE')) - if node.IsA('Label') and node.GetName() == GetOption('label'): - try: - self.release_map = IDLReleaseMap(childdata) - node.parent.release_map = self.release_map - except Exception as err: - node.Error('Unable to build release map: %s' % str(err)) - return None - +# +# IDLFileTypeRessolver +# +# A specialized visitor which traverses the AST and sets a FILE property +# on all file nodes. In addition, searches the namespace resolving all +# type references. The namespace tree must already have been populated +# before this visitor is used. +# class IDLFileTypeResolver(IDLVisitor): def VisitFilter(self, node, data): return not node.IsA('Comment', 'Copyright') @@ -82,6 +125,13 @@ class IDLFileTypeResolver(IDLVisitor): # Track the file node to update errors if node.IsA('File'): node.SetProperty('FILE', node) + filenode = node + + if not node.IsA('AST'): + file_min, file_max = filenode.release_map.GetReleaseRange() + if not file_min: + print 'Resetting min on %s to %s' % (node, file_min) + node.SetMinRange(file_min) # If this node has a TYPEREF, resolve it to a version list typeref = node.property_node.GetPropertyLocal('TYPEREF') @@ -93,13 +143,26 @@ class IDLFileTypeResolver(IDLVisitor): node.typelist = None return filenode +# +# IDLReleaseResolver +# +# A specialized visitor which will traverse the AST, and generate a mapping +# from any release to the first release in which that version of the object +# was generated. Types must already be resolved to use. +# +class IDLReleaseResolver(IDLVisitor): + def Arrive(self, node, releases): + node.BuildReleaseMap(releases) + return releases + # # IDLAst # # A specialized version of the IDLNode for containing the whole of the -# AST. The specialized BuildTree function pulls the per file namespaces -# into the global AST namespace and checks for collisions. +# AST. Construction of the AST object will cause resolution of the +# tree including versions, types, etc... Errors counts will be collected +# both per file, and on the AST itself. # class IDLAst(IDLNode): def __init__(self, children): @@ -107,18 +170,25 @@ class IDLAst(IDLNode): self.Resolve() def Resolve(self): - self.namespace = IDLNamespace(None) - self.namespace.name = 'AST' - IDLNamespaceLabelResolver().Visit(self, self.namespace) + # Set the appropriate Release=Version mapping for each File + IDLLabelResolver().Visit(self, None) + + # Generate the Namesapce Tree + self.namespace = IDLNamespace(None, 'AST') + IDLNamespaceVersionResolver().Visit(self, self.namespace) + + # Using the namespace, resolve type references IDLFileTypeResolver().Visit(self, None) # Build an ordered list of all releases - self.releases = set() + releases = set() for filenode in self.GetListOf('File'): - self.releases |= set(filenode.release_map.GetReleases()) - self.releases = sorted(self.releases) + releases |= set(filenode.release_map.GetReleases()) + + # Generate a per node list of releases and release mapping + IDLReleaseResolver().Visit(self, sorted(releases)) + + for filenode in self.GetListOf('File'): + self.errors += int(filenode.GetProperty('ERRORS', 0)) + - def SetTypeInfo(self, name, properties): - node = self.namespace[name] - for prop in properties: - node.properties[prop] = properties[prop] diff --git a/ppapi/generators/idl_c_header.py b/ppapi/generators/idl_c_header.py index d6d897e..3344a4d 100755 --- a/ppapi/generators/idl_c_header.py +++ b/ppapi/generators/idl_c_header.py @@ -110,8 +110,8 @@ class HGen(GeneratorByFile): def GenerateFile(self, filenode, releases, options): savename = GetOutFileName(filenode, GetOption('dstroot')) - unique_releases = filenode.GetUniqueReleases(releases) - if not unique_releases: + my_min, my_max = filenode.GetMinMax(releases) + if my_min > releases[-1] or my_max < releases[0]: if os.path.isfile(savename): print "Removing stale %s for this range." % filenode.GetName() os.remove(os.path.realpath(savename)) diff --git a/ppapi/generators/idl_c_proto.py b/ppapi/generators/idl_c_proto.py index dffd375..c522bab 100755 --- a/ppapi/generators/idl_c_proto.py +++ b/ppapi/generators/idl_c_proto.py @@ -95,6 +95,13 @@ class CGen(object): 'store': '%s', 'return': '%s' }, + 'Interface': { + 'in': 'const %s*', + 'inout': '%s*', + 'out': '%s**', + 'return': '%s*', + 'store': '%s*' + }, 'Struct': { 'in': 'const %s*', 'inout': '%s*', @@ -243,6 +250,7 @@ class CGen(object): 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 @@ -252,8 +260,13 @@ class CGen(object): 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('Interface', 'Struct'): + elif typeref.IsA('Struct'): if typeref.GetProperty('union'): name = 'union %s%s' % (prefix, typeref.GetName()) else: @@ -427,8 +440,14 @@ class CGen(object): # Define a Typedef. def DefineTypedef(self, node, releases, prefix='', comment=False): __pychecker__ = 'unusednames=comment' - release = releases[0] - out = 'typedef %s;\n' % self.GetSignature(node, release, 'return', + 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.') + 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 @@ -440,6 +459,7 @@ class CGen(object): name = '%s%s' % (prefix, node.GetName()) notypedef = node.GetProperty('notypedef') unnamed = node.GetProperty('unnamed') + if unnamed: out = 'enum {' elif notypedef: @@ -505,6 +525,13 @@ class CGen(object): 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], @@ -654,13 +681,13 @@ def Main(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 - print DefineDepends(node) for node in f.GetChildren()[2:]: - print Define(node, comment=True, prefix='tst_') + print cgen.Define(node, comment=True, prefix='tst_') if __name__ == '__main__': diff --git a/ppapi/generators/idl_gen_wrapper.py b/ppapi/generators/idl_gen_wrapper.py index ee1fe68..ca5587d 100644 --- a/ppapi/generators/idl_gen_wrapper.py +++ b/ppapi/generators/idl_gen_wrapper.py @@ -12,6 +12,7 @@ import sys from idl_c_proto import CGen from idl_generator import Generator from idl_log import ErrOut, InfoOut, WarnOut +from idl_option import GetOption from idl_outfile import IDLOutFile @@ -219,8 +220,9 @@ const void *__%(wrapper_prefix)s_PPPGetInterface(const char *name) { for filenode in ast.GetListOf('File'): # If this file has errors, skip it if filenode in self.skip_list: - InfoOut.Log('WrapperGen: Skipping %s due to errors\n' % - filenode.GetName()) + if GetOption('verbose'): + InfoOut.Log('WrapperGen: Skipping %s due to errors\n' % + filenode.GetName()) continue file_name = self.GetHeaderName(filenode.GetName()) @@ -233,8 +235,9 @@ const void *__%(wrapper_prefix)s_PPPGetInterface(const char *name) { include_version=True) needs_wrap = self.InterfaceVersionNeedsWrapping(iface, version) if not needs_wrap: - InfoOut.Log('Interface %s ver %s does not need wrapping' % - (struct_name, version)) + if GetOption('verbose'): + InfoOut.Log('Interface %s ver %s does not need wrapping' % + (struct_name, version)) iface_releases.append( Interface(iface, release, version, struct_name, needs_wrap, file_name)) @@ -456,3 +459,4 @@ const void *__%(wrapper_prefix)s_PPPGetInterface(const char *name) { out.Write(self.GetGuardEnd()) out.Close() return 0 + diff --git a/ppapi/generators/idl_namespace.py b/ppapi/generators/idl_namespace.py index f7429c1..0d74b547 100755 --- a/ppapi/generators/idl_namespace.py +++ b/ppapi/generators/idl_namespace.py @@ -28,45 +28,46 @@ Option('namespace_debug', 'Use the specified release') # one or more IDLNodes based on a release or range of releases. # class IDLNamespace(object): - def __init__(self, parent): - self.namespace = {} - self.parent = parent + def __init__(self, parent, name): + self._name_to_releases = {} + self._parent = parent + self._name = name def Dump(self): - for name in self.namespace: + for name in self._name_to_releases: InfoOut.Log('NAME=%s' % name) - for cver in self.namespace[name].nodes: + for cver in self._name_to_releases[name].GetReleases(): InfoOut.Log(' %s' % cver) InfoOut.Log('') def FindRelease(self, name, release): - verlist = self.namespace.get(name, None) + verlist = self._name_to_releases.get(name, None) if verlist == None: - if self.parent: - return self.parent.FindRelease(name, release) + if self._parent: + return self._parent.FindRelease(name, release) else: return None return verlist.FindRelease(release) def FindRange(self, name, rmin, rmax): - verlist = self.namespace.get(name, None) + verlist = self._name_to_releases.get(name, None) if verlist == None: - if self.parent: - return self.parent.FindRange(name, rmin, rmax) + if self._parent: + return self._parent.FindRange(name, rmin, rmax) else: return [] return verlist.FindRange(rmin, rmax) def FindList(self, name): - verlist = self.namespace.get(name, None) + verlist = self._name_to_releases.get(name, None) if verlist == None: - if self.parent: - return self.parent.FindList(name) + if self._parent: + return self._parent.FindList(name) return verlist def AddNode(self, node): name = node.GetName() - verlist = self.namespace.setdefault(name,IDLReleaseList()) + verlist = self._name_to_releases.setdefault(name,IDLReleaseList()) if GetOption('namespace_debug'): print "Adding to namespace: %s" % node return verlist.AddNode(node) @@ -247,3 +248,4 @@ def Main(args): if __name__ == '__main__': sys.exit(Main(sys.argv[1:])) + diff --git a/ppapi/generators/idl_node.py b/ppapi/generators/idl_node.py index 275562c..34c4d22 100755 --- a/ppapi/generators/idl_node.py +++ b/ppapi/generators/idl_node.py @@ -63,6 +63,7 @@ class IDLNode(IDLRelease): self.lineno = lineno self.pos = pos self.filename = filename + self.filenode = None self.hashes = {} self.deps = {} self.errors = 0 @@ -70,6 +71,13 @@ class IDLNode(IDLRelease): self.typelist = None self.parent = None self.property_node = IDLPropertyNode() + + # A list of unique releases for this node + self.releases = None + + # A map from any release, to the first unique release + self.first_release = None + # self.children is a list of children ordered as defined self.children = [] # Process the passed in list of children, placing ExtAttributes into the @@ -104,7 +112,9 @@ class IDLNode(IDLRelease): self.errors += 1 ErrOut.LogLine(self.filename, self.lineno, 0, ' %s %s' % (str(self), msg)) - if self.lineno == 46: raise Exception("huh?") + if self.filenode: + errcnt = self.filenode.GetProperty('ERRORS', 0) + self.filenode.SetProperty('ERRORS', errcnt + 1) # Log a warning for this object def Warning(self, msg): @@ -130,13 +140,19 @@ class IDLNode(IDLRelease): if not comments and is_comment: return tab = ''.rjust(depth * 2) - if is_comment: out.write('%sComment\n' % tab) for line in self.GetName().split('\n'): out.write('%s "%s"\n' % (tab, line)) else: - out.write('%s%s\n' % (tab, self)) + ver = IDLRelease.__str__(self) + if self.releases: + release_list = ': ' + ' '.join(self.releases) + else: + release_list = ': undefined' + out.write('%s%s%s%s\n' % (tab, self, ver, release_list)) + if self.typelist: + out.write('%s Typelist: %s\n' % (tab, self.typelist.GetReleases()[0])) properties = self.property_node.GetPropertyList() if properties: out.write('%s Properties\n' % tab) @@ -151,7 +167,6 @@ class IDLNode(IDLRelease): # # Search related functions # - # Check if node is of a given type def IsA(self, *typelist): if self.cls in typelist: return True @@ -247,58 +262,102 @@ class IDLNode(IDLRelease): return None return filenode.release_map.GetVersion(release) + def GetUniqueReleases(self, releases): + my_min, my_max = self.GetMinMax(releases) + if my_min > releases[-1] or my_max < releases[0]: + return [] + + out = set() + for rel in releases: + remapped = self.first_release[rel] + if not remapped: continue + if remapped < releases[0]: + remapped = releases[0] + out |= set([remapped]) + out = sorted(out) + return out + + def GetRelease(self, version): filenode = self.GetProperty('FILE') if not filenode: return None return filenode.release_map.GetRelease(version) - def GetUniqueReleases(self, releases): - # Given a list of global release, return a subset of releases - # for this object that change. - last_hash = None - builds = [] - filenode = self.GetProperty('FILE') - file_releases = filenode.release_map.GetReleases() - - # Generate a set of unique releases for this object based on versions - # available in this file's release labels. - for rel in file_releases: - # Check if this object is valid for the release in question. - if not self.IsRelease(rel): continue - # Only add it if the hash is different. - cur_hash = self.GetHash(rel) - if last_hash != cur_hash: - builds.append(rel) - last_hash = cur_hash - - # Remap the requested releases to releases in the unique build set to - # use first available release names and remove duplicates. - # UNIQUE VERSION: 'M13', 'M14', 'M17' - # REQUESTED RANGE: 'M15', 'M16', 'M17', 'M18' - # REMAP RESULT: 'M14', 'M17' - out_list = [] - build_len = len(builds) - build_index = 0 - rel_len = len(releases) - rel_index = 0 - - while build_index < build_len and rel_index < rel_len: - while rel_index < rel_len and releases[rel_index] < builds[build_index]: - rel_index = rel_index + 1 - - # If we've reached the end of the request list, we must be done - if rel_index == rel_len: - break - - # Check this current request - cur = releases[rel_index] - while build_index < build_len and cur >= builds[build_index]: - build_index = build_index + 1 - - out_list.append(builds[build_index - 1]) - rel_index = rel_index + 1 - return out_list + def _GetReleases(self, releases): + if not self.releases: + my_min, my_max = self.GetMinMax(releases) + my_releases = [my_min] + if my_max != releases[-1]: + my_releases.append(my_max) + my_releases = set(my_releases) + for child in self.GetChildren(): + if child.IsA('Copyright', 'Comment', 'Label'): + continue + my_releases |= child.GetReleases(releases) + self.releases = my_releases + return self.releases + + + def _GetReleaseList(self, releases): + if not self.releases: + # If we are unversionable, then return first available release + if self.IsA('Comment', 'Copyright', 'Label'): + self.releases = [] + return self.releases + + # Generate the first and if deprecated within this subset, the + # last release for this node + my_min, my_max = self.GetMinMax(releases) + + if my_max != releases[-1]: + my_releases = set([my_min, my_max]) + else: + my_releases = set([my_min]) + + # Files inherit all there releases from items in the file + if self.IsA('AST', 'File'): + my_releases = set() + + child_releases = set() + for child in self.children: + child_releases |= set(child._GetReleaseList(releases)) + + type_releases = set() + if self.typelist: + type_list = self.typelist.GetReleases() + for typenode in type_list: + type_releases |= set(typenode._GetReleaseList(releases)) + + type_release_list = sorted(type_releases) + if my_min < type_release_list[0]: + type_node = type_list[0] + self.Error('requires %s in %s which is undefined at %s.' % ( + type_node, type_node.filename, my_min)) + + for rel in child_releases: + if rel >= my_min and rel <= my_max: + my_releases |= set([rel]) + + self.releases = sorted(my_releases) + + return self.releases + + def GetReleaseList(self): + return self.releases + + def BuildReleaseMap(self, releases): + unique_list = self._GetReleaseList(releases) + my_min, my_max = self.GetMinMax(releases) + + self.first_release = {} + last_rel = None + for rel in releases: + if rel in unique_list: + last_rel = rel + self.first_release[rel] = last_rel + if rel == my_max: + last_rel = None def SetProperty(self, name, val): self.property_node.SetProperty(name, val) @@ -393,3 +452,4 @@ def Main(): if __name__ == '__main__': sys.exit(Main()) + diff --git a/ppapi/generators/idl_parser.py b/ppapi/generators/idl_parser.py index 22517d0..161845d 100755 --- a/ppapi/generators/idl_parser.py +++ b/ppapi/generators/idl_parser.py @@ -35,6 +35,7 @@ from idl_lexer import IDLLexer from idl_node import IDLAttribute, IDLFile, IDLNode from idl_option import GetOption, Option, ParseOptions from idl_lint import Lint +from idl_visitor import IDLVisitor from ply import lex from ply import yacc @@ -242,6 +243,7 @@ class IDLParser(IDLLexer): | namespace top_list | struct_block top_list | typedef_decl top_list + | bad_decl top_list | """ if len(p) > 2: p[0] = ListFromConcat(p[1], p[2]) @@ -252,6 +254,11 @@ class IDLParser(IDLLexer): """top_list : error top_list""" p[0] = p[2] + # Recover from error and continue parsing at the next top match. + def p_bad_decl(self, p): + """bad_decl : modifiers SYMBOL error '}' ';'""" + p[0] = [] + # # Modifier List # @@ -443,6 +450,11 @@ class IDLParser(IDLLexer): p[0] = self.BuildProduction('Describe', p, 2, children) if self.parse_debug: DumpReduction('describe_block', p) + # Recover from describe error and continue parsing at the next top match. + def p_describe_error(self, p): + """describe_list : error describe_list""" + p[0] = [] + def p_describe_list(self, p): """describe_list : modifiers SYMBOL ';' describe_list | modifiers ENUM ';' describe_list @@ -453,10 +465,6 @@ class IDLParser(IDLLexer): Type = self.BuildNamed('Type', p, 2, p[1]) p[0] = ListFromConcat(Type, p[4]) - def p_describe_error(self, p): - """describe_list : error describe_list""" - p[0] = p[2] - # # Constant Values (integer, value) # @@ -648,6 +656,15 @@ class IDLParser(IDLLexer): p[0] = self.BuildNamed('Enum', p, 3, ListFromConcat(p[1], p[5])) if self.parse_debug: DumpReduction('enum_block', p) + # Recover from enum error and continue parsing at the next top match. + def p_enum_errorA(self, p): + """enum_block : modifiers ENUM error '{' enum_list '}' ';'""" + p[0] = [] + + def p_enum_errorB(self, p): + """enum_block : modifiers ENUM error ';'""" + p[0] = [] + def p_enum_list(self, p): """enum_list : modifiers SYMBOL '=' expression enum_cont | modifiers SYMBOL enum_cont""" @@ -743,6 +760,10 @@ class IDLParser(IDLLexer): p[0] = self.BuildNamed('Interface', p, 3, ListFromConcat(p[1], p[5])) if self.parse_debug: DumpReduction('interface_block', p) + def p_interface_error(self, p): + """interface_block : modifiers INTERFACE error '{' interface_list '}' ';'""" + p[0] = [] + def p_interface_list(self, p): """interface_list : member_function ';' interface_list | """ @@ -750,9 +771,6 @@ class IDLParser(IDLLexer): p[0] = ListFromConcat(p[1], p[3]) if self.parse_debug: DumpReduction('interface_list', p) - def p_interface_error(self, p): - """interface_list : error interface_list""" - p[0] = p[2] # # Struct @@ -766,15 +784,17 @@ class IDLParser(IDLLexer): p[0] = self.BuildNamed('Struct', p, 3, children) if self.parse_debug: DumpReduction('struct_block', p) + # Recover from struct error and continue parsing at the next top match. + def p_struct_error(self, p): + """enum_block : modifiers STRUCT error '{' struct_list '}' ';'""" + p[0] = [] + def p_struct_list(self, p): """struct_list : member_attribute ';' struct_list | member_function ';' struct_list |""" if len(p) > 1: p[0] = ListFromConcat(p[1], p[3]) - def p_struct_error(self, p): - """struct_list : error struct_list""" - p[0] = p[2] # # Parser Errors @@ -1103,6 +1123,60 @@ def TestNamespaceFiles(filter): InfoOut.Log("Passed namespace test.") return errs + + +def FindVersionError(releases, node): + err_cnt = 0 + if node.IsA('Interface', 'Struct'): + comment_list = [] + comment = node.GetOneOf('Comment') + if comment: + print comment.GetName() + if comment and comment.GetName()[:4] == 'REL:': + comment_list = comment.GetName()[5:].strip().split(' ') + print comment_list + + if len(comment_list) != len(releases): + node.Error("Mismatch size of releases: %s vs %s." % ( + comment_list, releases)) + err_cnt += 1 + else: + first_list = [node.first_release[rel] for rel in releases] + if first_list != comment_list: + node.Error("Mismatch in releases: %s vs %s." % ( + comment_list, first_list)) + err_cnt += 1 + + for child in node.GetChildren(): + err_cnt += FindVersionError(releases, child) + return err_cnt + + +def TestVersionFiles(filter): + idldir = os.path.split(sys.argv[0])[0] + idldir = os.path.join(idldir, 'test_version', '*.idl') + filenames = glob.glob(idldir) + testnames = [] + + for filename in filenames: + if filter and filename not in filter: continue + testnames.append(filename) + + # If we have no files to test, then skip this test + if not testnames: + InfoOut.Log('No files to test for version.') + return 0 + + ast = ParseFiles(testnames) + errs = FindVersionError(ast.releases, ast) + + if errs: + ErrOut.Log("Failed version test.") + else: + InfoOut.Log("Passed version test.") + return errs + + default_dirs = ['.', 'trusted', 'dev', 'private'] def ParseFiles(filenames): parser = IDLParser() @@ -1140,6 +1214,7 @@ def Main(args): if GetOption('test'): errs = TestErrorFiles(filenames) errs = TestNamespaceFiles(filenames) + errs = TestVersionFiles(filenames) if errs: ErrOut.Log("Parser failed with %d errors." % errs) return -1 @@ -1156,3 +1231,4 @@ def Main(args): if __name__ == '__main__': sys.exit(Main(sys.argv[1:])) + diff --git a/ppapi/generators/idl_propertynode.py b/ppapi/generators/idl_propertynode.py index 24e10d9..33837a3 100755 --- a/ppapi/generators/idl_propertynode.py +++ b/ppapi/generators/idl_propertynode.py @@ -194,3 +194,4 @@ def Main(): if __name__ == '__main__': sys.exit(Main()) + diff --git a/ppapi/generators/idl_release.py b/ppapi/generators/idl_release.py index ca350e1..eafc95f 100755 --- a/ppapi/generators/idl_release.py +++ b/ppapi/generators/idl_release.py @@ -107,6 +107,24 @@ class IDLRelease(object): InfoOut.Log('%f to %f is in %s' % (rmin, rmax, self)) return True + def GetMinMax(self, releases = None): + if not releases: + return self.rmin, self.rmax + + if not self.rmin: + rmin = releases[0] + else: + rmin = str(self.rmin) + if not self.rmax: + rmax = releases[-1] + else: + rmax = str(self.rmax) + return (rmin, rmax) + + def SetMin(self, release): + assert not self.rmin + self.rmin = release + def Error(self, msg): ReportReleaseError(msg) @@ -123,10 +141,13 @@ class IDLRelease(object): # class IDLReleaseList(object): def __init__(self): - self.nodes = [] + self._nodes = [] + + def GetReleases(self): + return self._nodes def FindRelease(self, release): - for node in self.nodes: + for node in self._nodes: if node.IsRelease(release): return node return None @@ -135,7 +156,7 @@ class IDLReleaseList(object): assert (rmin == None) or rmin != rmax out = [] - for node in self.nodes: + for node in self._nodes: if node.InRange(rmin, rmax): out.append(node) return out @@ -146,7 +167,7 @@ class IDLReleaseList(object): last = None # Check current releases in that namespace - for cver in self.nodes: + for cver in self._nodes: if GetOption('release_debug'): InfoOut.Log(' Checking %s' % cver) # We should only be missing a 'release' tag for the first item. @@ -180,7 +201,7 @@ class IDLReleaseList(object): # and does not overlap with anything previously added, so # we can add it to the end of the list. if GetOption('release_debug'): InfoOut.Log('Done %s' % node) - self.nodes.append(node) + self._nodes.append(node) return True # @@ -211,6 +232,12 @@ class IDLReleaseMap(object): def GetReleases(self): return self.releases + def GetReleaseRange(self): + return (self.releases[0], self.releases[-1]) + + def GetVersionRange(self): + return (self.versions[0], self.version[-1]) + # # Test Code # @@ -321,3 +348,4 @@ def Main(args): if __name__ == '__main__': sys.exit(Main(sys.argv[1:])) + diff --git a/ppapi/generators/test_cgen/interface.idl b/ppapi/generators/test_cgen/interface.idl index 2072532..22a4a03 100644 --- a/ppapi/generators/test_cgen/interface.idl +++ b/ppapi/generators/test_cgen/interface.idl @@ -8,6 +8,10 @@ * This file will test that the IDL snippet matches the comment. */ +label Chrome { + M14 = 1.0, + M15 = 2.0 +}; /* struct ist { void* X; }; */ struct ist { mem_t X; @@ -23,12 +27,21 @@ struct ist { * int32_t (*mem6)(void** ptr); * }; */ -interface iface1 { +interface ifaceFoo { int8_t mem1([in] int16_t x, [in] int32_t y); int32_t mem2([in] ist a); int32_t mem3([out] ist b); int32_t mem4([in] blob_t ptr); int32_t mem5([out] blob_t ptr); - int32_t mem6([inout] blob_t ptr); + [version=2.0] int32_t mem6([inout] blob_t ptr); +}; + +interface ifaceBar { + int8_t testIface([in] ifaceFoo foo, [in] int32_t y); + ifaceFoo createIface([in] str_t name); +}; + +struct struct2 { + ifaceBar bar; }; diff --git a/ppapi/generators/test_namespace/bar.idl b/ppapi/generators/test_namespace/bar.idl index ea73402..0e1d76b 100644 --- a/ppapi/generators/test_namespace/bar.idl +++ b/ppapi/generators/test_namespace/bar.idl @@ -5,6 +5,10 @@ /* This file tests the namespace functions in the parser. */ +label Chrome { + M14 = 1.0 +}; + /* PPAPI ID */ typedef int32_t PP_Instance; diff --git a/ppapi/generators/test_namespace/foo.idl b/ppapi/generators/test_namespace/foo.idl index 6bbff31..3b04c79 100644 --- a/ppapi/generators/test_namespace/foo.idl +++ b/ppapi/generators/test_namespace/foo.idl @@ -15,6 +15,8 @@ struct PP_Size { /* PPAPI Enum */ enum PP_Bool { + /* Decalare False */ PP_FALSE = 0, + /* Decalare True */ PP_TRUE = 1 }; diff --git a/ppapi/generators/test_parser/enum.idl b/ppapi/generators/test_parser/enum.idl index 0924728..7048d4f 100644 --- a/ppapi/generators/test_parser/enum.idl +++ b/ppapi/generators/test_parser/enum.idl @@ -43,9 +43,8 @@ enum Es6 { E6 = 12 } -/* OK Enum(Es7) */ +/* Bad comment because of Es6 */ enum Es7 { - /* OK EnumItem(E11) */ E11 = 11 }; @@ -55,6 +54,7 @@ enum Es8 { /* OK EnumItem(E12) */ E12 = 12, /* OK EnumItem(E13) */ + /* FAIL Unexpected value 13.0 after "=". */ E13 = 13.0, /* FAIL Unexpected string "hello" after "=". */ /* OK EnumItem(E14) */ diff --git a/ppapi/native_client/src/untrusted/pnacl_irt_shim/pnacl_shim.c b/ppapi/native_client/src/untrusted/pnacl_irt_shim/pnacl_shim.c index 2f3bb66..3b106ad 100644 --- a/ppapi/native_client/src/untrusted/pnacl_irt_shim/pnacl_shim.c +++ b/ppapi/native_client/src/untrusted/pnacl_irt_shim/pnacl_shim.c @@ -3,7 +3,7 @@ * found in the LICENSE file. */ -/* Last generated from IDL: Fri Oct 19 10:45:30 2012. */ +/* Last generated from IDL: Mon Oct 22 13:38:21 2012. */ #include "ppapi/generators/pnacl_shim.h" #include "ppapi/c/ppb.h" |