| OLD | NEW |
| 1 #!/usr/bin/python | 1 #!/usr/bin/python |
| 2 # | 2 # |
| 3 # Copyright (c) 2011 The Chromium Authors. All rights reserved. | 3 # Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 4 # Use of this source code is governed by a BSD-style license that can be | 4 # Use of this source code is governed by a BSD-style license that can be |
| 5 # found in the LICENSE file. | 5 # found in the LICENSE file. |
| 6 | 6 |
| 7 """Nodes for PPAPI IDL AST""" | 7 """Nodes for PPAPI IDL AST""" |
| 8 | 8 |
| 9 # | 9 # |
| 10 # IDL Node | 10 # IDL Node |
| 11 # | 11 # |
| 12 # IDL Node defines the IDLAttribute and IDLNode objects which are constructed | 12 # IDL Node defines the IDLAttribute and IDLNode objects which are constructed |
| 13 # by the parser as it processes the various 'productions'. The IDLAttribute | 13 # by the parser as it processes the various 'productions'. The IDLAttribute |
| 14 # objects are assigned to the IDLNode's property dictionary instead of being | 14 # objects are assigned to the IDLNode's property dictionary instead of being |
| 15 # applied as children of The IDLNodes, so they do not exist in the final tree. | 15 # applied as children of The IDLNodes, so they do not exist in the final tree. |
| 16 # The AST of IDLNodes is the output from the parsing state and will be used | 16 # The AST of IDLNodes is the output from the parsing state and will be used |
| 17 # as the source data by the various generators. | 17 # as the source data by the various generators. |
| 18 # | 18 # |
| 19 | 19 |
| 20 import hashlib | 20 import hashlib |
| 21 import sys | 21 import sys |
| 22 | 22 |
| 23 from idl_log import ErrOut, InfoOut, WarnOut | 23 from idl_log import ErrOut, InfoOut, WarnOut |
| 24 from idl_propertynode import IDLPropertyNode | 24 from idl_propertynode import IDLPropertyNode |
| 25 from idl_namespace import IDLNamespace | 25 from idl_namespace import IDLNamespace |
| 26 from idl_version import IDLVersion | 26 from idl_release import IDLRelease, IDLReleaseMap |
| 27 | 27 |
| 28 | 28 |
| 29 # IDLAttribute | 29 # IDLAttribute |
| 30 # | 30 # |
| 31 # A temporary object used by the parsing process to hold an Extended Attribute | 31 # A temporary object used by the parsing process to hold an Extended Attribute |
| 32 # which will be passed as a child to a standard IDLNode. | 32 # which will be passed as a child to a standard IDLNode. |
| 33 # | 33 # |
| 34 class IDLAttribute(object): | 34 class IDLAttribute(object): |
| 35 def __init__(self, name, value): | 35 def __init__(self, name, value): |
| 36 self.cls = 'ExtAttribute' | 36 self.cls = 'ExtAttribute' |
| 37 self.name = name | 37 self.name = name |
| 38 self.value = value | 38 self.value = value |
| 39 | 39 |
| 40 def __str__(self): | 40 def __str__(self): |
| 41 return '%s=%s' % (self.name, self.value) | 41 return '%s=%s' % (self.name, self.value) |
| 42 | 42 |
| 43 | 43 |
| 44 # | 44 # |
| 45 # IDLNode | 45 # IDLNode |
| 46 # | 46 # |
| 47 # This class implements the AST tree, providing the associations between | 47 # This class implements the AST tree, providing the associations between |
| 48 # parents and children. It also contains a namepsace and propertynode to | 48 # parents and children. It also contains a namepsace and propertynode to |
| 49 # allow for look-ups. IDLNode is derived from IDLVersion, so it is | 49 # allow for look-ups. IDLNode is derived from IDLRelease, so it is |
| 50 # version aware. | 50 # version aware. |
| 51 # | 51 # |
| 52 class IDLNode(IDLVersion): | 52 class IDLNode(IDLRelease): |
| 53 | 53 |
| 54 # Set of object IDLNode types which have a name and belong in the namespace. | 54 # Set of object IDLNode types which have a name and belong in the namespace. |
| 55 NamedSet = set(['Enum', 'EnumItem', 'File', 'Function', 'Interface', | 55 NamedSet = set(['Enum', 'EnumItem', 'File', 'Function', 'Interface', |
| 56 'Member', 'Param', 'Struct', 'Type', 'Typedef']) | 56 'Member', 'Param', 'Struct', 'Type', 'Typedef']) |
| 57 | 57 |
| 58 show_versions = False | 58 show_versions = False |
| 59 def __init__(self, cls, filename, lineno, pos, children=None): | 59 def __init__(self, cls, filename, lineno, pos, children=None): |
| 60 # Initialize with no starting or ending Version | 60 # Initialize with no starting or ending Version |
| 61 IDLVersion.__init__(self, None, None) | 61 IDLRelease.__init__(self, None, None) |
| 62 | 62 |
| 63 self.cls = cls | 63 self.cls = cls |
| 64 self.lineno = lineno | 64 self.lineno = lineno |
| 65 self.pos = pos | 65 self.pos = pos |
| 66 self.filename = filename | 66 self.filename = filename |
| 67 self.hashes = {} | 67 self.hashes = {} |
| 68 self.deps = {} | 68 self.deps = {} |
| 69 self.errors = 0 | 69 self.errors = 0 |
| 70 self.namespace = None | 70 self.namespace = None |
| 71 self.typelist = None | 71 self.typelist = None |
| (...skipping 12 matching lines...) Expand all Loading... |
| 84 self.AddChild(child) | 84 self.AddChild(child) |
| 85 | 85 |
| 86 # | 86 # |
| 87 # String related functions | 87 # String related functions |
| 88 # | 88 # |
| 89 # | 89 # |
| 90 | 90 |
| 91 # Return a string representation of this node | 91 # Return a string representation of this node |
| 92 def __str__(self): | 92 def __str__(self): |
| 93 name = self.GetName() | 93 name = self.GetName() |
| 94 ver = IDLVersion.__str__(self) | 94 ver = IDLRelease.__str__(self) |
| 95 if name is None: name = '' | 95 if name is None: name = '' |
| 96 if not IDLNode.show_versions: ver = '' | 96 if not IDLNode.show_versions: ver = '' |
| 97 return '%s(%s%s)' % (self.cls, name, ver) | 97 return '%s(%s%s)' % (self.cls, name, ver) |
| 98 | 98 |
| 99 # Return file and line number for where node was defined | 99 # Return file and line number for where node was defined |
| 100 def Location(self): | 100 def Location(self): |
| 101 return '%s(%d)' % (self.filename, self.lineno) | 101 return '%s(%d)' % (self.filename, self.lineno) |
| 102 | 102 |
| 103 # Log an error for this object | 103 # Log an error for this object |
| 104 def Error(self, msg): | 104 def Error(self, msg): |
| 105 self.errors += 1 | 105 self.errors += 1 |
| 106 ErrOut.LogLine(self.filename, self.lineno, 0, ' %s %s' % | 106 ErrOut.LogLine(self.filename, self.lineno, 0, ' %s %s' % |
| 107 (str(self), msg)) | 107 (str(self), msg)) |
| 108 if self.lineno == 46: raise Exception("huh?") | 108 if self.lineno == 46: raise Exception("huh?") |
| 109 | 109 |
| 110 # Log a warning for this object | 110 # Log a warning for this object |
| 111 def Warning(self, msg): | 111 def Warning(self, msg): |
| 112 WarnOut.LogLine(self.filename, self.lineno, 0, ' %s %s' % | 112 WarnOut.LogLine(self.filename, self.lineno, 0, ' %s %s' % |
| 113 (str(self), msg)) | 113 (str(self), msg)) |
| 114 | 114 |
| 115 def GetName(self): | 115 def GetName(self): |
| 116 return self.GetProperty('NAME') | 116 return self.GetProperty('NAME') |
| 117 | 117 |
| 118 def GetNameVersion(self): | 118 def GetNameVersion(self): |
| 119 name = self.GetProperty('NAME', default='') | 119 name = self.GetProperty('NAME', default='') |
| 120 ver = IDLVersion.__str__(self) | 120 ver = IDLRelease.__str__(self) |
| 121 return '%s%s' % (name, ver) | 121 return '%s%s' % (name, ver) |
| 122 | 122 |
| 123 # Dump this object and its children | 123 # Dump this object and its children |
| 124 def Dump(self, depth=0, comments=False, out=sys.stdout): | 124 def Dump(self, depth=0, comments=False, out=sys.stdout): |
| 125 if self.cls in ['Comment', 'Copyright']: | 125 if self.cls in ['Comment', 'Copyright']: |
| 126 is_comment = True | 126 is_comment = True |
| 127 else: | 127 else: |
| 128 is_comment = False | 128 is_comment = False |
| 129 | 129 |
| 130 # Skip this node if it's a comment, and we are not printing comments | 130 # Skip this node if it's a comment, and we are not printing comments |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 197 if not node and self.parent: | 197 if not node and self.parent: |
| 198 node = self.parent.FindVersion(name, version) | 198 node = self.parent.FindVersion(name, version) |
| 199 return node | 199 return node |
| 200 | 200 |
| 201 def FindRange(self, name, vmin, vmax): | 201 def FindRange(self, name, vmin, vmax): |
| 202 nodes = self.namespace.FindNodes(name, vmin, vmax) | 202 nodes = self.namespace.FindNodes(name, vmin, vmax) |
| 203 if not nodes and self.parent: | 203 if not nodes and self.parent: |
| 204 nodes = self.parent.FindVersion(name, vmin, vmax) | 204 nodes = self.parent.FindVersion(name, vmin, vmax) |
| 205 return nodes | 205 return nodes |
| 206 | 206 |
| 207 def IsRelease(self, release): | |
| 208 label = self.GetLabel() | |
| 209 # Assume object is always available if there is no Label | |
| 210 if not label: | |
| 211 return True | |
| 212 | |
| 213 version = label.GetVersion(release) | |
| 214 out = self.IsVersion(version) | |
| 215 return out | |
| 216 | |
| 217 def InReleases(self, releases): | |
| 218 for rel in releases: | |
| 219 if self.IsRelease(rel): return True | |
| 220 return False | |
| 221 | |
| 222 def GetLabel(self): | |
| 223 label = self.GetProperty('LABEL') | |
| 224 if not label: | |
| 225 self.Error('No label availible.') | |
| 226 return None | |
| 227 return label | |
| 228 | |
| 229 def GetType(self, release): | 207 def GetType(self, release): |
| 230 label = self.GetLabel() | |
| 231 if not label: return None | |
| 232 if not self.typelist: return None | 208 if not self.typelist: return None |
| 233 version = label.GetVersion(release) | 209 return self.typelist.FindRelease(release) |
| 234 return self.typelist.FindVersion(version) | |
| 235 | 210 |
| 236 def GetHash(self, release): | 211 def GetHash(self, release): |
| 237 hashval = self.hashes.get(release, None) | 212 hashval = self.hashes.get(release, None) |
| 238 if hashval is None: | 213 if hashval is None: |
| 239 hashval = hashlib.sha1() | 214 hashval = hashlib.sha1() |
| 240 hashval.update(self.cls) | 215 hashval.update(self.cls) |
| 241 for key in self.property_node.GetPropertyList(): | 216 for key in self.property_node.GetPropertyList(): |
| 242 val = self.GetProperty(key) | 217 val = self.GetProperty(key) |
| 243 hashval.update('%s=%s' % (key, str(val))) | 218 hashval.update('%s=%s' % (key, str(val))) |
| 244 typeref = self.GetType(release) | 219 typeref = self.GetType(release) |
| (...skipping 11 matching lines...) Expand all Loading... |
| 256 deps = self.deps.get(release, None) | 231 deps = self.deps.get(release, None) |
| 257 if deps is None: | 232 if deps is None: |
| 258 deps = set([self]) | 233 deps = set([self]) |
| 259 for child in self.GetChildren(): | 234 for child in self.GetChildren(): |
| 260 deps |= child.GetDeps(release) | 235 deps |= child.GetDeps(release) |
| 261 typeref = self.GetType(release) | 236 typeref = self.GetType(release) |
| 262 if typeref: deps |= typeref.GetDeps(release) | 237 if typeref: deps |= typeref.GetDeps(release) |
| 263 self.deps[release] = deps | 238 self.deps[release] = deps |
| 264 return deps | 239 return deps |
| 265 | 240 |
| 266 def GetRelease(self, version): | |
| 267 label = self.GetLabel() | |
| 268 if not label: return None | |
| 269 return label.GetRelease(version) | |
| 270 | |
| 271 def GetVersion(self, release): | 241 def GetVersion(self, release): |
| 272 label = self.GetLabel() | 242 filenode = self.GetProperty('FILE') |
| 273 if not label: return None | 243 if not filenode: |
| 274 return label.GetVersion(release) | 244 return None |
| 245 return filenode.release_map.GetVersion(release) |
| 275 | 246 |
| 276 def GetUniqueReleases(self, releases): | 247 def GetUniqueReleases(self, releases): |
| 277 # Given a list of release, return a subset of releases that change. | 248 # Given a list of global release, return a subset of releases |
| 249 # for this object that change. |
| 278 last_hash = None | 250 last_hash = None |
| 279 build_list = [] | 251 build_list = [] |
| 252 filenode = self.GetProperty('FILE') |
| 253 my_releases = filenode.release_map.GetReleases() |
| 280 for rel in releases: | 254 for rel in releases: |
| 255 if not self.IsRelease(rel): continue |
| 256 # Only check releases used by this source file |
| 257 if rel not in my_releases: continue |
| 281 cur_hash = self.GetHash(rel) | 258 cur_hash = self.GetHash(rel) |
| 282 if last_hash != cur_hash: | 259 if last_hash != cur_hash: |
| 283 build_list.append(rel) | 260 build_list.append(rel) |
| 284 last_hash = cur_hash | 261 last_hash = cur_hash |
| 285 return build_list | 262 return build_list |
| 286 | 263 |
| 287 def SetProperty(self, name, val): | 264 def SetProperty(self, name, val): |
| 288 self.property_node.SetProperty(name, val) | 265 self.property_node.SetProperty(name, val) |
| 289 | 266 |
| 290 def GetProperty(self, name, default=None): | 267 def GetProperty(self, name, default=None): |
| 291 return self.property_node.GetProperty(name, default) | 268 return self.property_node.GetProperty(name, default) |
| 292 | 269 |
| 293 def Traverse(self, data, func): | 270 def Traverse(self, data, func): |
| 294 func(self, data) | 271 func(self, data) |
| 295 for child in self.children: | 272 for child in self.children: |
| 296 child.Traverse(data, func) | 273 child.Traverse(data, func) |
| 297 | 274 |
| 298 | 275 |
| 299 # | 276 # |
| 300 # IDLFile | 277 # IDLFile |
| 301 # | 278 # |
| 302 # A specialized version of IDLNode which tracks errors and warnings. | 279 # A specialized version of IDLNode which tracks errors and warnings. |
| 303 # | 280 # |
| 304 class IDLFile(IDLNode): | 281 class IDLFile(IDLNode): |
| 305 def __init__(self, name, children, errors=0): | 282 def __init__(self, name, children, errors=0): |
| 306 attrs = [IDLAttribute('NAME', name), | 283 attrs = [IDLAttribute('NAME', name), |
| 307 IDLAttribute('ERRORS', errors)] | 284 IDLAttribute('ERRORS', errors)] |
| 308 if not children: children = [] | 285 if not children: children = [] |
| 309 IDLNode.__init__(self, 'File', name, 1, 0, attrs + children) | 286 IDLNode.__init__(self, 'File', name, 1, 0, attrs + children) |
| 287 self.release_map = IDLReleaseMap([('M13', 1.0)]) |
| 310 | 288 |
| 311 | 289 |
| 312 # | 290 # |
| 313 # Tests | 291 # Tests |
| 314 # | 292 # |
| 315 def StringTest(): | 293 def StringTest(): |
| 316 errors = 0 | 294 errors = 0 |
| 317 name_str = 'MyName' | 295 name_str = 'MyName' |
| 318 text_str = 'MyNode(%s)' % name_str | 296 text_str = 'MyNode(%s)' % name_str |
| 319 name_node = IDLAttribute('NAME', name_str) | 297 name_node = IDLAttribute('NAME', name_str) |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 370 errors += ChildTest() | 348 errors += ChildTest() |
| 371 | 349 |
| 372 if errors: | 350 if errors: |
| 373 ErrOut.Log('IDLNode failed with %d errors.' % errors) | 351 ErrOut.Log('IDLNode failed with %d errors.' % errors) |
| 374 return -1 | 352 return -1 |
| 375 return 0 | 353 return 0 |
| 376 | 354 |
| 377 if __name__ == '__main__': | 355 if __name__ == '__main__': |
| 378 sys.exit(Main()) | 356 sys.exit(Main()) |
| 379 | 357 |
| OLD | NEW |