Add Python parser language-independent parts.
[free-sw/xcb/proto] / xcbgen / types.py
1 '''
2 This module contains the classes which represent XCB data types.
3 '''
4 from expr import Field, Expression
5 import __main__
6
7 class Type(object):
8     '''
9     Abstract base class for all XCB data types.
10     Contains default fields, and some abstract methods.
11     '''
12     def __init__(self, name):
13         '''
14         Default structure initializer.  Sets up default fields.
15
16         Public fields:
17         name is a tuple of strings specifying the full type name.
18         size is the size of the datatype in bytes, or None if variable-sized.
19         nmemb is 1 for non-list types, None for variable-sized lists, otherwise number of elts.
20         booleans for identifying subclasses, because I can't figure out isinstance().
21         '''
22         self.name = name
23         self.size = None
24         self.nmemb = None
25         self.resolved = False
26
27         # Screw isinstance().
28         self.is_list = False
29         self.is_expr = False
30         self.is_container = False
31         self.is_reply = False
32         self.is_union = False
33         self.is_pad = False
34
35     def resolve(self, module):
36         '''
37         Abstract method for resolving a type.
38         This should make sure any referenced types are already declared.
39         '''
40         raise Exception('abstract resolve method not overridden!')
41
42     def out(self, name):
43         '''
44         Abstract method for outputting code.
45         These are declared in the language-specific modules, and
46         there must be a dictionary containing them declared when this module is imported!
47         '''
48         raise Exception('abstract out method not overridden!')
49
50     def fixed_size(self):
51         '''
52         Abstract method for determining if the data type is fixed-size.
53         '''
54         raise Exception('abstract fixed_size method not overridden!')
55
56     def make_member_of(self, module, complex_type, field_type, field_name, visible, wire, auto):
57         '''
58         Default method for making a data type a member of a structure.
59         Extend this if the data type needs to add an additional length field or something.
60
61         module is the global module object.
62         complex_type is the structure object.
63         see Field for the meaning of the other parameters.
64         '''
65         new_field = Field(self, field_type, field_name, visible, wire, auto)
66
67         # We dump the _placeholder_byte if any fields are added.
68         for (idx, field) in enumerate(complex_type.fields):
69             if field == _placeholder_byte:
70                 complex_type.fields[idx] = new_field
71                 return
72
73         complex_type.fields.append(new_field)
74
75 class SimpleType(Type):
76     '''
77     Derived class which represents a cardinal type like CARD32 or char.
78     Any type which is typedef'ed to cardinal will be one of these.
79
80     Public fields added:
81     none
82     '''
83     def __init__(self, name, size):
84         Type.__init__(self, name)
85         self.size = size
86         self.nmemb = 1
87
88     def resolve(self, module):
89         self.resolved = True
90
91     def fixed_size(self):
92         return True
93
94     out = __main__.output['simple']
95
96
97 # Cardinal datatype globals.  See module __init__ method.
98 tcard8 = SimpleType(('uint8_t',), 1)
99 tcard16 = SimpleType(('uint16_t',), 2)
100 tcard32 = SimpleType(('uint32_t',), 4)
101 tint8 =  SimpleType(('int8_t',), 1)
102 tint16 = SimpleType(('int16_t',), 2)
103 tint32 = SimpleType(('int32_t',), 4)
104 tchar =  SimpleType(('char',), 1)
105 tfloat = SimpleType(('float',), 4)
106 tdouble = SimpleType(('double',), 8)
107
108
109 class Enum(SimpleType):
110     '''
111     Derived class which represents an enum.  Fixed-size.
112
113     Public fields added:
114     values contains a list of (name, value) tuples.  value is empty, or a number.
115     '''
116     def __init__(self, name, elt):
117         SimpleType.__init__(self, name, 4)
118         self.values = []
119         for item in list(elt):
120             # First check if we're using a default value
121             if len(list(item)) == 0:
122                 self.values.append((item.get('name'), ''))
123                 continue
124
125             # An explicit value or bit was specified.
126             value = list(item)[0]
127             if value.tag == 'value':
128                 self.values.append((item.get('name'), value.text))
129             elif value.tag == 'bit':
130                 # XXX replace this with a simple number, please.
131                 self.values.append((item.get('name'), '(1 << %s)' % value.text))
132
133     def resolve(self, module):
134         self.resolved = True
135
136     def fixed_size(self):
137         return True
138
139     out = __main__.output['enum']
140
141
142 class ListType(Type):
143     '''
144     Derived class which represents a list of some other datatype.  Fixed- or variable-sized.
145
146     Public fields added:
147     member is the datatype of the list elements.
148     parent is the structure type containing the list.
149     expr is an Expression object containing the length information, for variable-sized lists.
150     '''
151     def __init__(self, elt, member, parent):
152         Type.__init__(self, member.name)
153         self.is_list = True
154         self.member = member
155         self.parent = parent
156
157         if elt.tag == 'list':
158             elts = list(elt)
159             self.expr = Expression(elts[0] if len(elts) else elt, self)
160         elif elt.tag == 'valueparam':
161             self.expr = Expression(elt, self)
162
163         self.size = member.size if member.fixed_size() else None
164         self.nmemb = self.expr.nmemb if self.expr.fixed_size() else None
165
166     def make_member_of(self, module, complex_type, field_type, field_name, visible, wire, auto):
167         if not self.fixed_size():
168             # We need a length field.
169             # Ask our Expression object for it's name, type, and whether it's on the wire.
170             lenfid = self.expr.lenfield_type
171             lenfield_name = self.expr.lenfield_name
172             lenwire = self.expr.lenwire
173             needlen = True
174
175             # See if the length field is already in the structure.
176             for field in self.parent.fields:
177                 if field.field_name == lenfield_name:
178                     needlen = False
179
180             # It isn't, so we need to add it to the structure ourself.
181             if needlen:
182                 type = module.get_type(lenfid)
183                 lenfield_type = module.get_type_name(lenfid)
184                 type.make_member_of(module, complex_type, lenfield_type, lenfield_name, True, lenwire, False)
185
186         # Add ourself to the structure by calling our original method.
187         Type.make_member_of(self, module, complex_type, field_type, field_name, visible, wire, auto)
188
189     def resolve(self, module):
190         if self.resolved:
191             return
192         self.member.resolve(module)
193
194         # Find my length field again.  We need the actual Field object in the expr.
195         # This is needed because we might have added it ourself above.
196         if not self.fixed_size():
197             for field in self.parent.fields:
198                 if field.field_name == self.expr.lenfield_name and field.wire:
199                     self.expr.lenfield = field
200                     break
201             
202         self.resolved = True
203
204     def fixed_size(self):
205         return self.member.fixed_size() and self.expr.fixed_size()
206
207 class ExprType(Type):
208     '''
209     Derived class which represents an exprfield.  Fixed size.
210
211     Public fields added:
212     expr is an Expression object containing the value of the field.
213     '''
214     def __init__(self, elt, member, parent):
215         Type.__init__(self, member.name)
216         self.is_expr = True
217         self.member = member
218         self.parent = parent
219
220         self.expr = Expression(list(elt)[0], self)
221
222         self.size = member.size
223         self.nmemb = 1
224
225     def resolve(self, module):
226         if self.resolved:
227             return
228         self.member.resolve(module)
229         self.resolved = True
230
231     def fixed_size(self):
232         return True
233
234 class PadType(Type):
235     '''
236     Derived class which represents a padding field.
237     '''
238     def __init__(self, elt):
239         Type.__init__(self, tcard8.name)
240         self.is_pad = True
241         self.size = 1
242         self.nmemb = 1 if (elt == None) else int(elt.get('bytes'))
243
244     def resolve(self, module):
245         self.resolved = True
246
247     def fixed_size(self):
248         return True
249
250     
251 class ComplexType(Type):
252     '''
253     Derived class which represents a structure.  Base type for all structure types.
254
255     Public fields added:
256     fields is an array of Field objects describing the structure fields.
257     '''
258     def __init__(self, name, elt):
259         Type.__init__(self, name)
260         self.is_container = True
261         self.elt = elt
262         self.fields = []
263         self.nmemb = 1
264         self.size = 0
265
266     def resolve(self, module):
267         if self.resolved:
268             return
269         pads = 0
270
271         # Resolve all of our field datatypes.
272         for child in list(self.elt):
273             if child.tag == 'pad':
274                 field_name = 'pad' + str(pads)
275                 fkey = 'CARD8'
276                 type = PadType(child)
277                 pads = pads + 1
278                 visible = False
279             elif child.tag == 'field':
280                 field_name = child.get('name')
281                 fkey = child.get('type')
282                 type = module.get_type(fkey)
283                 visible = True
284             elif child.tag == 'exprfield':
285                 field_name = child.get('name')
286                 fkey = child.get('type')
287                 type = ExprType(child, module.get_type(fkey), self)
288                 visible = False
289             elif child.tag == 'list':
290                 field_name = child.get('name')
291                 fkey = child.get('type')
292                 type = ListType(child, module.get_type(fkey), self)
293                 visible = True
294             elif child.tag == 'valueparam':
295                 field_name = child.get('value-list-name')
296                 fkey = 'CARD32'
297                 type = ListType(child, module.get_type(fkey), self)
298                 visible = True
299             else:
300                 # Hit this on Reply
301                 continue 
302
303             # Get the full type name for the field
304             field_type = module.get_type_name(fkey)
305             # Add the field to ourself
306             type.make_member_of(module, self, field_type, field_name, visible, True, False)
307             # Recursively resolve the type (could be another structure, list)
308             type.resolve(module)
309
310         self.calc_size() # Figure out how big we are
311         self.resolved = True
312
313     def calc_size(self):
314         self.size = 0
315         for m in self.fields:
316             if not m.wire:
317                 continue
318             if m.type.fixed_size():
319                 self.size = self.size + m.type.size
320             else:
321                 self.size = None
322                 break
323
324     def fixed_size(self):
325         for m in self.fields:
326             if not m.type.fixed_size():
327                 return False
328         return True
329
330
331 class Struct(ComplexType):
332     '''
333     Derived class representing a struct data type.
334     '''
335     out = __main__.output['struct']
336
337
338 class Union(ComplexType):
339     '''
340     Derived class representing a union data type.
341     '''
342     def __init__(self, name, elt):
343         ComplexType.__init__(self, name, elt)
344         self.is_union = True
345
346     out = __main__.output['union']
347
348
349 class Reply(ComplexType):
350     '''
351     Derived class representing a reply.  Only found as a field of Request.
352     '''
353     def __init__(self, name, elt):
354         ComplexType.__init__(self, name, elt)
355         self.is_reply = True
356
357     def resolve(self, module):
358         if self.resolved:
359             return
360         # Add the automatic protocol fields
361         self.fields.append(Field(tcard8, tcard8.name, 'response_type', False, True, True))
362         self.fields.append(_placeholder_byte)
363         self.fields.append(Field(tcard16, tcard16.name, 'sequence', False, True, True))
364         self.fields.append(Field(tcard32, tcard32.name, 'length', False, True, True))
365         ComplexType.resolve(self, module)
366         
367
368 class Request(ComplexType):
369     '''
370     Derived class representing a request.
371
372     Public fields added:
373     reply contains the reply datatype or None for void requests.
374     opcode contains the request number.
375     '''
376     def __init__(self, name, elt):
377         ComplexType.__init__(self, name, elt)
378         self.reply = None
379         self.opcode = elt.get('opcode')
380
381         for child in list(elt):
382             if child.tag == 'reply':
383                 self.reply = Reply(name, child)
384
385     def resolve(self, module):
386         if self.resolved:
387             return
388         # Add the automatic protocol fields
389         if module.namespace.is_ext:
390             self.fields.append(Field(tcard8, tcard8.name, 'major_opcode', False, True, True))
391             self.fields.append(Field(tcard8, tcard8.name, 'minor_opcode', False, True, True))
392             self.fields.append(Field(tcard16, tcard16.name, 'length', False, True, True))
393             ComplexType.resolve(self, module)
394         else:
395             self.fields.append(Field(tcard8, tcard8.name, 'major_opcode', False, True, True))
396             self.fields.append(_placeholder_byte)
397             self.fields.append(Field(tcard16, tcard16.name, 'length', False, True, True))
398             ComplexType.resolve(self, module)
399
400         if self.reply:
401             self.reply.resolve(module)
402
403     out = __main__.output['request']
404
405
406 class Event(ComplexType):
407     '''
408     Derived class representing an event data type.
409
410     Public fields added:
411     opcodes is a dictionary of name -> opcode number, for eventcopies.
412     '''
413     def __init__(self, name, elt):
414         ComplexType.__init__(self, name, elt)
415         self.opcodes = {}
416
417         tmp = elt.get('no-sequence-number')
418         self.has_seq = (tmp == None or tmp.lower() == 'false' or tmp == '0')
419             
420     def add_opcode(self, opcode, name, main):
421         self.opcodes[name] = opcode
422         if main:
423             self.name = name
424
425     def resolve(self, module):
426         if self.resolved:
427             return
428
429         # Add the automatic protocol fields
430         self.fields.append(Field(tcard8, tcard8.name, 'response_type', False, True, True))
431         if self.has_seq:
432             self.fields.append(_placeholder_byte)
433             self.fields.append(Field(tcard16, tcard16.name, 'sequence', False, True, True))
434         ComplexType.resolve(self, module)
435
436     out = __main__.output['event']
437
438
439 class Error(ComplexType):
440     '''
441     Derived class representing an error data type.
442
443     Public fields added:
444     opcodes is a dictionary of name -> opcode number, for errorcopies.
445     '''
446     def __init__(self, name, elt):
447         ComplexType.__init__(self, name, elt)
448         self.opcodes = {}
449
450     def add_opcode(self, opcode, name, main):
451         self.opcodes[name] = opcode
452         if main:
453             self.name = name
454
455     def resolve(self, module):
456         if self.resolved:
457             return
458
459         # Add the automatic protocol fields
460         self.fields.append(Field(tcard8, tcard8.name, 'response_type', False, True, True))
461         self.fields.append(Field(tcard8, tcard8.name, 'error_code', False, True, True))
462         self.fields.append(Field(tcard16, tcard16.name, 'sequence', False, True, True))
463         ComplexType.resolve(self, module)
464
465     out = __main__.output['error']
466
467 _placeholder_byte = Field(PadType(None), tcard8.name, 'pad0', False, True, False)