summaryrefslogtreecommitdiff
path: root/parsers/rulesng.py
blob: 13ceea992ca92421b3aa8ada145c441800553fd9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
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)