summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoakim Sindholt <opensource@zhasha.com>2009-10-15 03:55:38 +0200
committerJoakim Sindholt <opensource@zhasha.com>2009-10-15 03:55:38 +0200
commit5ddb8d65093f5d7974da646c6055211cb61169e1 (patch)
tree0319fea06366645a14a4f08fec381eefa148bd71
parentbcdc0c6501d22d5041d57cc47d289e7943bf4639 (diff)
Add parsers directory for future parsers
-rw-r--r--parsers/rules-ng.xsd413
-rwxr-xr-xparsers/rulesng.py158
-rwxr-xr-xparsers/rulesngCollectors.py281
3 files changed, 852 insertions, 0 deletions
diff --git a/parsers/rules-ng.xsd b/parsers/rules-ng.xsd
new file mode 100644
index 0000000..c387afd
--- /dev/null
+++ b/parsers/rules-ng.xsd
@@ -0,0 +1,413 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema"
+ targetNamespace="http://nouveau.freedesktop.org/"
+ xmlns:rng="http://nouveau.freedesktop.org/"
+ elementFormDefault="qualified">
+
+ <annotation>
+ <documentation>
+ An updated version of the old rules.xml file from the
+ RivaTV project. Specifications by Pekka Paalanen,
+ preliminary attempt by KoalaBR,
+ first working version by Jakob Bornecrantz.
+ For specifications, see the file rules-ng-format.txt
+ in Nouveau CVS module 'rules-ng'.
+ </documentation>
+ <documentation>Version 0.1</documentation>
+ </annotation>
+
+
+ <!-- Elements -->
+
+ <element name="value" type="rng:valueType" />
+ <element name="bitfield" type="rng:bitfieldType" />
+ <element name="bitset" type="rng:bitsetType" />
+ <element name="reg32" type="rng:registerType" />
+ <element name="reg8" type="rng:registerType" />
+ <element name="array" type="rng:arrayType" />
+ <element name="stripe" type="rng:stripeType" />
+ <element name="enum" type="rng:enumType" />
+ <element name="database" type="rng:databaseType" />
+ <element name="group" type="rng:groupType" />
+ <element name="variant" type="rng:variantType" />
+ <element name="domain" type="rng:domainType" />
+ <element name="translation" type="rng:translationType" />
+ <element name="use-bitset" type="rng:refType" />
+ <element name="use-group" type="rng:refType" />
+ <element name="use-enum" type="rng:refType" />
+
+ <!-- Documentation elements -->
+
+ <!-- FIXME: allowed only one per parent element -->
+ <element name="brief" type="rng:briefType" />
+
+ <element name="doc" type="rng:docType" />
+ <element name="b" type="rng:textformatType" />
+ <element name="i" type="rng:textformatType" />
+ <element name="u" type="rng:textformatType" />
+ <element name="code" type="rng:textcodeType" />
+ <element name="ul" type="rng:listType" />
+ <element name="ol" type="rng:listType" />
+ <element name="li" type="rng:listitemType" />
+
+
+
+ <!-- Database element types -->
+
+ <complexType name="databaseType">
+ <annotation>
+ <documentation>databaseType</documentation>
+ </annotation>
+ <sequence>
+ <element ref="rng:domain" />
+ <choice minOccurs="0" maxOccurs="unbounded">
+ <group ref="rng:regarrayGroup" />
+ <group ref="rng:docGroup" />
+ <element ref="rng:variant" />
+ <element ref="rng:enum" />
+ <element ref="rng:group" />
+ <element ref="rng:bitset" />
+ </choice>
+ </sequence>
+ </complexType>
+
+ <complexType name="variantType">
+ <annotation>
+ <documentation>variantType</documentation>
+ </annotation>
+ <choice minOccurs="0" maxOccurs="unbounded">
+ <group ref="rng:regarrayGroup" />
+ <group ref="rng:docGroup" />
+ <element ref="rng:variant" />
+ <element ref="rng:use-group" />
+ </choice>
+ <attribute name="id" type="NMTOKENS" use="required" />
+ </complexType>
+
+ <complexType name="enumType">
+ <annotation>
+ <documentation>enumType</documentation>
+ </annotation>
+ <choice maxOccurs="unbounded">
+ <element ref="rng:value" />
+ <group ref="rng:docGroup" />
+ </choice>
+ <attribute name="name" type="rng:Cname" use="required" />
+ </complexType>
+
+ <complexType name="valueType">
+ <annotation>
+ <documentation>valueType</documentation>
+ </annotation>
+ <choice minOccurs="0" maxOccurs="unbounded">
+ <group ref="rng:docGroup" />
+ </choice>
+ <attribute name="name" type="rng:objName" use="required" />
+ <attribute name="value" type="string" use="required" />
+ </complexType>
+
+ <complexType name="arrayType">
+ <annotation>
+ <documentation>arrayType</documentation>
+ </annotation>
+ <choice minOccurs="0" maxOccurs="unbounded">
+ <group ref="rng:regarrayGroup" minOccurs="0" />
+ <group ref="rng:docGroup" />
+ <element ref="rng:use-group" />
+ </choice>
+ <attribute name="name" type="rng:objName" use="required" />
+ <attributeGroup ref="rng:basicArrayAttributes" />
+ <attribute name="type" type="rng:Type" default="hex" />
+ </complexType>
+
+ <complexType name="stripeType">
+ <annotation>
+ <documentation>stripeType</documentation>
+ </annotation>
+ <choice minOccurs="0" maxOccurs="unbounded">
+ <group ref="rng:regarrayGroup" minOccurs="0" />
+ <group ref="rng:docGroup" />
+ <element ref="rng:use-group" />
+ </choice>
+ <attribute name="name" type="rng:objName" use="optional" />
+ <attributeGroup ref="rng:basicArrayAttributes" />
+ </complexType>
+
+ <complexType name="bitfieldType">
+ <annotation>
+ <documentation>bitfieldType</documentation>
+ </annotation>
+ <choice minOccurs="0" maxOccurs="unbounded">
+ <group ref="rng:docGroup" />
+ <element ref="rng:use-enum" />
+ <element ref="rng:value" maxOccurs="unbounded" />
+ </choice>
+ <attribute name="name" type="rng:objName" use="required" />
+ <attribute name="high" type="nonNegativeInteger"
+ use="required" />
+ <attribute name="low" type="nonNegativeInteger"
+ use="required" />
+ <attribute name="type" type="rng:Type" default="hex" />
+ </complexType>
+
+ <complexType name="bitsetType">
+ <annotation>
+ <documentation>bitsetType</documentation>
+ </annotation>
+ <choice maxOccurs="unbounded">
+ <element ref="rng:bitfield" />
+ <group ref="rng:docGroup" />
+ </choice>
+ <attribute name="name" type="rng:Cname" use="required" />
+ </complexType>
+
+ <complexType name="groupType">
+ <annotation>
+ <documentation>groupType</documentation>
+ </annotation>
+ <choice maxOccurs="unbounded">
+ <group ref="rng:regarrayGroup" />
+ <group ref="rng:docGroup" />
+ <element ref="rng:use-group" />
+ </choice>
+ <attribute name="name" type="rng:Cname" use="required" />
+ <attribute name="prepend" type="rng:objName" />
+ </complexType>
+
+ <complexType name="refType">
+ <annotation>
+ <documentation>refType</documentation>
+ </annotation>
+ <attribute name="ref" type="rng:Cname" use="required" />
+ </complexType>
+
+ <complexType name="domainType">
+ <annotation>
+ <documentation>domainType</documentation>
+ </annotation>
+ <attribute name="name" type="rng:Cname" use="required" />
+ </complexType>
+
+ <complexType name="registerType">
+ <annotation>
+ <documentation>
+ registerType used by both reg8 and reg32
+ </documentation>
+ </annotation>
+ <choice minOccurs="0" maxOccurs="1">
+ <choice minOccurs="0" maxOccurs="unbounded">
+ <element ref="rng:value" />
+ <element ref="rng:use-enum" />
+ <group ref="rng:docGroup" />
+ </choice>
+ <choice minOccurs="0" maxOccurs="unbounded">
+ <element ref="rng:bitfield" />
+ <element ref="rng:use-bitset" />
+ <group ref="rng:docGroup" />
+ </choice>
+ </choice>
+ <attribute name="name" type="rng:objName" use="required" />
+ <attribute name="offset" type="rng:Hexadecimal"
+ use="required" />
+ <attribute name="access" type="rng:Access" default="rw" />
+ <attribute name="type" type="rng:Type" default="hex" />
+ </complexType>
+
+ <complexType name="translationType">
+ <annotation>
+ <documentation>translationType</documentation>
+ </annotation>
+ <choice maxOccurs="unbounded">
+ <element ref="rng:reg8" />
+ <element ref="rng:reg32" />
+ <group ref="rng:docGroup" />
+ </choice>
+ <attribute name="domain" type="rng:Cname" use="required" />
+ <attribute name="variant" type="NMTOKEN" />
+ </complexType>
+
+
+
+ <!-- Documentation element types -->
+
+ <complexType name="briefType">
+ <annotation>
+ <documentation>
+ brief documentation, no markup
+ </documentation>
+ </annotation>
+ <simpleContent>
+ <extension base="string" />
+ </simpleContent>
+ </complexType>
+
+ <complexType name="docType" mixed="true">
+ <annotation>
+ <documentation>
+ root element of documentation sub-tree
+ </documentation>
+ </annotation>
+ <choice minOccurs="0" maxOccurs="unbounded">
+ <group ref="rng:textformatGroup" />
+ <group ref="rng:listGroup" />
+ <element ref="rng:code" />
+ </choice>
+ </complexType>
+
+ <complexType name="textformatType" mixed="true">
+ <annotation>
+ <documentation>
+ for bold, underline, italics
+ </documentation>
+ </annotation>
+ <choice minOccurs="0" maxOccurs="unbounded">
+ <group ref="rng:textformatGroup" />
+ </choice>
+ </complexType>
+
+ <complexType name="textcodeType">
+ <simpleContent>
+ <extension base="string">
+ <attribute name="title" type="string" />
+ </extension>
+ </simpleContent>
+ </complexType>
+
+ <complexType name="listType">
+ <annotation>
+ <documentation>
+ definition of a list, ordered or unordered
+ </documentation>
+ </annotation>
+ <choice minOccurs="0" maxOccurs="unbounded">
+ <element ref="rng:li" />
+ </choice>
+ </complexType>
+
+ <complexType name="listitemType" mixed="true">
+ <annotation>
+ <documentation>
+ items of a list
+ </documentation>
+ </annotation>
+ <choice minOccurs="0" maxOccurs="unbounded">
+ <group ref="rng:textformatGroup" />
+ <group ref="rng:listGroup" />
+ <element ref="rng:code" />
+ </choice>
+ </complexType>
+
+
+
+ <!-- Attribute value types -->
+
+ <simpleType name="Cname">
+ <annotation>
+ <documentation>
+ C language identifier or macro name.
+ The C99 standard seems to allow non-ASCII-7
+ letters in names, but we do not. Or do we?
+ </documentation>
+ </annotation>
+ <restriction base="token">
+ <pattern value="[a-zA-Z_][0-9a-zA-Z_]*" />
+ </restriction>
+ </simpleType>
+
+ <simpleType name="objName">
+ <annotation>
+ <documentation>
+ This is either a (normal) prefixed name,
+ or an absolute name with a leading slash.
+ The absolute name is the same as slash and
+ Cname concatenated.
+ </documentation>
+ </annotation>
+ <restriction base="token">
+ <pattern value="/[a-zA-Z_][0-9a-zA-Z_]*" />
+ <pattern value="[0-9a-zA-Z_]+" />
+ </restriction>
+ </simpleType>
+
+ <simpleType name="Hexadecimal">
+ <restriction base="string">
+ <pattern value="0x[0-9a-f]+" />
+ <pattern value="0x[0-9A-F]+" />
+ </restriction>
+ </simpleType>
+
+ <simpleType name="HexOrNumber">
+ <annotation>
+ <documentation>HexOrNumber</documentation>
+ </annotation>
+ <union memberTypes="rng:Hexadecimal nonNegativeInteger" />
+ </simpleType>
+
+ <simpleType name="Type">
+ <annotation>
+ <documentation>Type</documentation>
+ </annotation>
+ <restriction base="NMTOKENS" />
+ </simpleType>
+
+ <simpleType name="Access">
+ <annotation>
+ <documentation>Access</documentation>
+ </annotation>
+ <restriction base="string">
+ <enumeration value="r" />
+ <enumeration value="w" />
+ <enumeration value="rw" />
+ </restriction>
+ </simpleType>
+
+
+
+ <!-- Attribute groups -->
+
+ <attributeGroup name="basicArrayAttributes">
+ <attribute name="offset" type="rng:Hexadecimal"
+ use="required" />
+ <attribute name="stride" type="rng:HexOrNumber"
+ use="required" />
+ <attribute name="length" type="rng:HexOrNumber"
+ use="required" />
+ </attributeGroup>
+
+
+ <!-- Element groups -->
+
+ <group name="regarrayGroup">
+ <choice>
+ <element ref="rng:reg32" />
+ <element ref="rng:reg8" />
+ <element ref="rng:array" />
+ <element ref="rng:stripe" />
+ <element ref="rng:translation" />
+ </choice>
+ </group>
+
+ <group name="docGroup">
+ <choice>
+ <element ref="rng:brief" />
+ <element ref="rng:doc" />
+ </choice>
+ </group>
+
+ <group name="textformatGroup">
+ <choice>
+ <element ref="rng:b" />
+ <element ref="rng:i" />
+ <element ref="rng:u" />
+ </choice>
+ </group>
+
+ <group name="listGroup">
+ <choice>
+ <element ref="rng:ul" />
+ <element ref="rng:ol" />
+ </choice>
+ </group>
+
+</schema>
+
diff --git a/parsers/rulesng.py b/parsers/rulesng.py
new file mode 100755
index 0000000..13ceea9
--- /dev/null
+++ b/parsers/rulesng.py
@@ -0,0 +1,158 @@
+import sys
+try:
+ from lxml import etree
+except ImportError:
+ sys.stderr.write("You need the lxml python module installed. "
+ "Preferably version 1.2.1 or later.\n"
+ "See http://codespeak.net/lxml/\n\n")
+ raise
+
+
+rules_ns_ = '{http://nouveau.freedesktop.org/}'
+
+# This really should not be here, but libxml2 does not load
+# attribute defaults from the Schema.
+rules_defaults_ = {
+ 'reg8:type':'hex',
+ 'reg8:access':'rw',
+ 'reg32:type':'hex',
+ 'reg32:access':'rw',
+ 'array:type':'hex',
+ 'bitfield:type':'hex',
+ 'translation:variant':None
+ }
+
+def load_xmlfile(fname):
+ src = open(fname, "r")
+ doc = etree.parse(src)
+ src.close()
+ return doc
+
+def load_schema(fname):
+ return etree.XMLSchema(load_xmlfile(fname))
+
+def getatt(elem, attrib):
+ val = elem.get(attrib)
+ if val is not None:
+ return val
+ name = "%s:%s" % ( elem.tag.replace(rules_ns_, ''), attrib )
+ try:
+ val = rules_defaults_[name]
+ except KeyError:
+ sys.stderr.write("Default value not found for %s.\n" % name)
+ val = None
+ return val
+
+
+class RulesngHandler:
+ def __init__(self):
+ self._domain = ""
+ self._idcnt = 0
+
+ def process_children(self, root):
+ """For the given element 'root', call dispatch_elem() for its
+ every child element and collect the return values into a
+ list, filtering out Nones."""
+ outs = map(self.dispatch_elem, root.getchildren())
+ return filter(lambda x: x is not None, outs)
+
+ def dispatch_elem(self, elem):
+ """Determine the element type and call the proper function,
+ returning the functions return value."""
+ if type(elem) == etree._Comment:
+ return
+ elname = elem.tag.replace(rules_ns_, "elem_").replace('-', '_')
+ if hasattr(self, elname):
+ return getattr(self, elname)(elem)
+
+ def temp_array_name(self, oname):
+ """Create a unique name for a temporary array.
+ The returned name can be different on each call."""
+ self._idcnt += 1
+ name = oname.replace('/', 's')
+ return "__%s_%03d" % (name, self._idcnt)
+
+ def def_name(self, oname):
+ """Mangle object name to create a known private name in C."""
+ name = oname.replace('/', 's')
+ return "__%s_def" % name
+
+
+class RulesngElement:
+ """Object to store the complete identity of a register, array
+ or stripe from Rules-ng. Complete identity includes absolute
+ address and full name, with applicable variants.
+
+ Attributes:
+ variants a set of variant id strings
+ base the absolute base address, integer
+ arrinfo list of (stride, len) tuples from arrays/stripes
+ prefix name prefix string
+ elem reference to the lxml element object
+ parent reference to the parent RulesngElement object
+ children list of references to child Rulesnglement objects
+ containers list of container names; groups, bitsets, enums
+ translation reference to the translation RulesngElement, or None
+ idnum an arbitrary id number
+ """
+
+ _id_base = 1000
+
+ def __init__(self, elem):
+ self.variants = set()
+ self.base = 0
+ self.arrinfo = []
+ self.prefix = ""
+ self.elem = elem
+ self.parent = None
+ self.children = []
+ self.containers = []
+ self.translation = None
+ self.idnum = RulesngElement._id_base
+ RulesngElement._id_base += 1
+
+ def copy(self):
+ """Create a proper semideep copy; do a deep copy, except for
+ references to other RulesngElements."""
+ re = RulesngElement(self.elem)
+ re.variants = set(self.variants)
+ re.base = self.base
+ re.arrinfo = list(self.arrinfo)
+ re.prefix = self.prefix
+ re.parent = self.parent
+ re.children = list(self.children)
+ re.containers = list(self.containers)
+ re.translation = self.translation
+ return re
+
+ def getType(self):
+ """Returns the name of the XML element as string."""
+ return self.elem.tag.replace(rules_ns_, '')
+
+ def getAddress(self):
+ """Returns the absolute address (related to offset
+ attribute).
+ """
+ return self.base + int(self.elem.get("offset"), 0)
+
+ def getStride(self):
+ return int(self.elem.get("stride"), 0)
+
+ def getLength(self):
+ return int(self.elem.get("length"), 0)
+
+ def getName(self):
+ """Returns the complete name with prefixes."""
+ myname = self.elem.get("name")
+ if myname is not None:
+ if myname[0] == '/':
+ return myname[1:]
+ return self.prefix + myname
+ else:
+ return self.prefix
+ def getAtt(self, attribute):
+ """Returns the value of the requested attribute, using
+ Rules-ng specified defaults if the attribute is not
+ defined in the lxml object."""
+
+ return getatt(self.elem, attribute)
diff --git a/parsers/rulesngCollectors.py b/parsers/rulesngCollectors.py
new file mode 100755
index 0000000..017946d
--- /dev/null
+++ b/parsers/rulesngCollectors.py
@@ -0,0 +1,281 @@
+from rulesng import *
+import sys
+
+class GroupCollector(RulesngHandler):
+ """Collector object only goes through the <database> element
+ and collects references to all <enum>, <bitset> and <group>
+ elements into a dictionary.
+ Traverses the lxml object tree according to Rules-ng specs."""
+
+ def __init__(self):
+ RulesngHandler.__init__(self)
+ self.enumTable = {}
+ self.groupTable = {}
+ self.bitsetTable = {}
+
+ def elem_enum(self, elem):
+ self.enumTable[elem.get("name")] = elem
+
+ def elem_group(self, elem):
+ self.groupTable[elem.get("name")] = elem
+
+ def elem_bitset(self, elem):
+ self.bitsetTable[elem.get("name")] = elem
+
+ def elem_database(self, elem):
+ self.process_children(elem)
+
+
+class NameCollector(RulesngHandler):
+ """Collect all names into a dictionary."""
+
+ def __init__(self, options={}):
+ """As parameter, provide a reference to executed
+ GroupCollector object, so that <use-foo> elements can work."""
+
+ RulesngHandler.__init__(self)
+ self.groups = None
+
+ # process optional features
+ self.options = {
+ # no optional features
+ }
+ self.options.update(options)
+
+ # Context stacks for different aspects
+ self.variants = [] # set
+ self.base = [0] # integer
+ self.arrinfo = [] # (stride, len) tuples
+ self.prefix = [""] # string
+ self.parents = [] # RulesngElement
+ self.containers = [] # string (group etc. name)
+
+ # Current translation in effect
+ self.translation = None
+
+ # dictionary for all register-like symbols,
+ # keys are full names, values are lists of RulesngElement refs.
+ self.symbols = {};
+
+ def processXMLTree(self, rootnode):
+ self.groups = GroupCollector()
+ self.groups.dispatch_elem(rootnode)
+ self.dispatch_elem(rootnode)
+ self.combineElements()
+
+ def addToSymbolList(self, re):
+ name = re.getName()
+ if len(name) == 0:
+ eprint("Warning: nameless symbol found.")
+ try:
+ lst = self.symbols[name]
+ # Check for duplicate names, accounting for variants
+ for item in lst:
+ ids = item.variants.intersection(re.variants)
+ if len(ids) > 0:
+ eprint("Warning: name %s multiply "
+ "defined for variants %s"
+ % (name, ", ".join(ids)) )
+ if len(item.variants) == 0 and \
+ len(re.variants) == 0:
+ eprint("Warning: name %s multiply "
+ "defined" % name)
+ lst.append(re)
+ except KeyError:
+ self.symbols[name] = [re]
+
+ def newRElem(self, elem):
+ re = RulesngElement(elem)
+ if len(self.variants) > 0:
+ re.variants = self.variants[-1]
+ re.base = self.base[-1]
+ re.arrinfo = list(self.arrinfo)
+ re.prefix = self.prefix[-1]
+ if len(self.parents) > 0:
+ re.parent = self.parents[-1]
+ re.containers = list(self.containers)
+ re.translation = self.translation
+ return re
+
+ def combineElements(self):
+ """Call combineRulesngElements for each object list in
+ NameCollector.symbols."""
+
+ for k in self.symbols.keys():
+ combineRulesngElements(self.symbols[k])
+
+
+ def elem_database(self, elem):
+ self.process_children(elem)
+
+ def elem_domain(self, elem):
+ self._domain = elem.get("name")
+
+ def elem_variant(self, elem):
+ ids = set(elem.get("id").split(' '))
+ if len(self.variants) > 0:
+ valids = ids.intersection(self.variants[-1])
+ if valids != ids:
+ eprint("variant error: " + str(ids) +
+ " != " + str(valids) )
+ self.variants.append(ids)
+ self.process_children(elem)
+ self.variants.pop()
+
+ def elem_reg32(self, elem):
+ re = self.newRElem(elem)
+ self.addToSymbolList(re)
+ self.prefix.append(re.getName() + "_")
+ self.base.append(re.getAddress())
+ self.parents.append(re)
+ re.children = flatten( self.process_children(elem) )
+ self.parents.pop()
+ self.base.pop()
+ self.prefix.pop()
+ return re
+
+ def elem_reg8(self, elem):
+ return self.elem_reg32(elem)
+
+ def elem_array(self, elem):
+ re = self.newRElem(elem)
+ self.addToSymbolList(re)
+ nameless = elem.get("name") is None
+ if not nameless:
+ self.prefix.append(re.getName() + "_")
+ self.base.append(re.getAddress())
+ self.arrinfo.append( (re.getStride(), re.getLength()) )
+ self.parents.append(re)
+ re.children = flatten(self.process_children(elem))
+ self.parents.pop()
+ self.arrinfo.pop()
+ self.base.pop()
+ if not nameless:
+ self.prefix.pop()
+ return re
+
+ def elem_stripe(self, elem):
+ re = self.newRElem(elem)
+ nameless = elem.get("name") is None
+ if not nameless:
+ self.prefix.append(re.getName() + "_")
+ self.base.append(re.getAddress())
+ self.arrinfo.append( (re.getStride(), re.getLength()) )
+ ret = self.process_children(elem)
+ self.arrinfo.pop()
+ self.base.pop()
+ if not nameless:
+ self.prefix.pop()
+ return flatten(ret)
+
+ def elem_bitfield(self, elem):
+ re = self.newRElem(elem)
+ self.prefix.append(re.getName() + "_")
+ self.parents.append(re)
+ re.children = flatten( self.process_children(elem) )
+ self.parents.pop()
+ self.prefix.pop()
+ return re
+
+ def elem_value(self, elem):
+ re = self.newRElem(elem)
+ return re
+
+ def elem_translation(self, elem):
+ re = self.newRElem(elem)
+ self.translation = re
+ re.children = flatten(self.process_children(elem))
+ self.translation = None
+ return re
+
+ def elem_use_bitset(self, elem):
+ ref = elem.get("ref")
+ bitset = self.groups.bitsetTable[ref]
+ self.containers.append(ref)
+ ret = self.process_children(bitset)
+ self.containers.pop()
+ return ret
+
+ def elem_use_enum(self, elem):
+ ref = elem.get("ref")
+ enum = self.groups.enumTable[ref]
+ self.containers.append(ref)
+ ret = self.process_children(enum)
+ self.containers.pop()
+ return ret
+
+ def elem_use_group(self, elem):
+ ref = elem.get("ref")
+ group = self.groups.groupTable[ref]
+ self.containers.append(ref)
+ ret = self.process_children(group)
+ self.containers.pop()
+ return ret
+
+def eprint(msg):
+ sys.stderr.write(msg + "\n")
+
+def flatten(lst):
+ ret = []
+ for i in lst:
+ if type(i) == list:
+ ret.extend(i)
+ else:
+ ret.append(i)
+ return ret
+
+def countTailMatch(lst1, lst2):
+ """Return the number of equivalent elements between two lists,
+ counting fron the end."""
+ m = min(len(lst1), len(lst2))
+ for i in range(1, m+1):
+ if lst1[-i] != lst2[-i]:
+ return i-1
+ return m
+
+def combineRulesngElements(elemlist):
+ """Many time the same registers are included from the same groups
+ under many different variants. This function combines all those
+ different instances into single RulesngElement objects.
+
+ After successful processing, elemlist is modified IN PLACE."""
+
+ addr_cmp = lambda a, b: a.getAddress() != b.getAddress()
+ value_cmp = lambda a, b: False
+ cmp_switch = {
+ 'reg8' : addr_cmp,
+ 'reg32' : addr_cmp,
+ 'array' : addr_cmp,
+ 'stripe' : addr_cmp,
+ 'value' : value_cmp,
+ 'bitfield' : value_cmp
+ }
+
+ newlist = []
+ for re in elemlist:
+ for nre in newlist:
+ ctm = countTailMatch(re.containers, nre.containers)
+ # Can re be combined into nre?
+ if ctm == 0:
+ continue
+ if re.getType() != nre.getType():
+ continue
+ if cmp_switch[re.getType()](re, nre):
+ continue
+
+ # update variant set
+ nre.variants.update(re.variants)
+ # cut containers list to only the common part
+ l = len(nre.containers)
+ del nre.containers[1:(l-ctm+1)]
+ # fix all references to the old object
+ for child in re.children:
+ child.parent = nre
+ if re.parent:
+ re.parent.child = nre
+ break
+ else:
+ newlist.append(re)
+ # modify elemlist in place
+ del elemlist[:]
+ elemlist.extend(newlist)