046513ef069037fbf4dc38e3dd52612f00d18c82
[free-sw/xcb/proto] / xcbgen / xtypes.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_simple = False
29         self.is_list = False
30         self.is_expr = False
31         self.is_container = False
32         self.is_reply = False
33         self.is_union = False
34         self.is_pad = False
35         self.is_switch = False
36
37     def resolve(self, module):
38         '''
39         Abstract method for resolving a type.
40         This should make sure any referenced types are already declared.
41         '''
42         raise Exception('abstract resolve method not overridden!')
43
44     def out(self, name):
45         '''
46         Abstract method for outputting code.
47         These are declared in the language-specific modules, and
48         there must be a dictionary containing them declared when this module is imported!
49         '''
50         raise Exception('abstract out method not overridden!')
51
52     def fixed_size(self):
53         '''
54         Abstract method for determining if the data type is fixed-size.
55         '''
56         raise Exception('abstract fixed_size method not overridden!')
57
58     def make_member_of(self, module, complex_type, field_type, field_name, visible, wire, auto):
59         '''
60         Default method for making a data type a member of a structure.
61         Extend this if the data type needs to add an additional length field or something.
62
63         module is the global module object.
64         complex_type is the structure object.
65         see Field for the meaning of the other parameters.
66         '''
67         new_field = Field(self, field_type, field_name, visible, wire, auto)
68
69         # We dump the _placeholder_byte if any fields are added.
70         for (idx, field) in enumerate(complex_type.fields):
71             if field == _placeholder_byte:
72                 complex_type.fields[idx] = new_field
73                 return
74
75         complex_type.fields.append(new_field)
76
77
78 class SimpleType(Type):
79     '''
80     Derived class which represents a cardinal type like CARD32 or char.
81     Any type which is typedef'ed to cardinal will be one of these.
82
83     Public fields added:
84     none
85     '''
86     def __init__(self, name, size):
87         Type.__init__(self, name)
88         self.is_simple = True
89         self.size = size
90         self.nmemb = 1
91
92     def resolve(self, module):
93         self.resolved = True
94
95     def fixed_size(self):
96         return True
97
98     out = __main__.output['simple']
99
100
101 # Cardinal datatype globals.  See module __init__ method.
102 tcard8 = SimpleType(('uint8_t',), 1)
103 tcard16 = SimpleType(('uint16_t',), 2)
104 tcard32 = SimpleType(('uint32_t',), 4)
105 tint8 =  SimpleType(('int8_t',), 1)
106 tint16 = SimpleType(('int16_t',), 2)
107 tint32 = SimpleType(('int32_t',), 4)
108 tchar =  SimpleType(('char',), 1)
109 tfloat = SimpleType(('float',), 4)
110 tdouble = SimpleType(('double',), 8)
111
112
113 class Enum(SimpleType):
114     '''
115     Derived class which represents an enum.  Fixed-size.
116
117     Public fields added:
118     values contains a list of (name, value) tuples.  value is empty, or a number.
119     bits contains a list of (name, bitnum) tuples.  items only appear if specified as a bit. bitnum is a number.
120     '''
121     def __init__(self, name, elt):
122         SimpleType.__init__(self, name, 4)
123         self.values = []
124         self.bits = []
125         for item in list(elt):
126             # First check if we're using a default value
127             if len(list(item)) == 0:
128                 self.values.append((item.get('name'), ''))
129                 continue
130
131             # An explicit value or bit was specified.
132             value = list(item)[0]
133             if value.tag == 'value':
134                 self.values.append((item.get('name'), value.text))
135             elif value.tag == 'bit':
136                 self.values.append((item.get('name'), '%u' % (1 << int(value.text, 0))))
137                 self.bits.append((item.get('name'), value.text))
138
139     def resolve(self, module):
140         self.resolved = True
141
142     def fixed_size(self):
143         return True
144
145     out = __main__.output['enum']
146
147
148 class ListType(Type):
149     '''
150     Derived class which represents a list of some other datatype.  Fixed- or variable-sized.
151
152     Public fields added:
153     member is the datatype of the list elements.
154     parent is the structure type containing the list.
155     expr is an Expression object containing the length information, for variable-sized lists.
156     '''
157     def __init__(self, elt, member, *parent):
158         Type.__init__(self, member.name)
159         self.is_list = True
160         self.member = member
161         self.parent = list(parent)
162
163         if elt.tag == 'list':
164             elts = list(elt)
165             self.expr = Expression(elts[0] if len(elts) else elt, self)
166         elif elt.tag == 'valueparam':
167             self.expr = Expression(elt, self)
168
169         self.size = member.size if member.fixed_size() else None
170         self.nmemb = self.expr.nmemb if self.expr.fixed_size() else None
171
172     def make_member_of(self, module, complex_type, field_type, field_name, visible, wire, auto):
173         if not self.fixed_size():
174             # We need a length field.
175             # Ask our Expression object for it's name, type, and whether it's on the wire.
176             lenfid = self.expr.lenfield_type
177             lenfield_name = self.expr.lenfield_name
178             lenwire = self.expr.lenwire
179             needlen = True
180
181             # See if the length field is already in the structure.
182             for parent in self.parent:
183                 for field in parent.fields:
184                     if field.field_name == lenfield_name:
185                         needlen = False
186
187             # It isn't, so we need to add it to the structure ourself.
188             if needlen:
189                 type = module.get_type(lenfid)
190                 lenfield_type = module.get_type_name(lenfid)
191                 type.make_member_of(module, complex_type, lenfield_type, lenfield_name, True, lenwire, False)
192
193         # Add ourself to the structure by calling our original method.
194         Type.make_member_of(self, module, complex_type, field_type, field_name, visible, wire, auto)
195
196     def resolve(self, module):
197         if self.resolved:
198             return
199         self.member.resolve(module)
200         self.expr.resolve(module, self.parent)
201
202         # Find my length field again.  We need the actual Field object in the expr.
203         # This is needed because we might have added it ourself above.
204         if not self.fixed_size():
205             for parent in self.parent:
206                 for field in parent.fields:
207                     if field.field_name == self.expr.lenfield_name and field.wire:
208                         self.expr.lenfield = field
209                         break
210
211         self.resolved = True
212
213     def fixed_size(self):
214         return self.member.fixed_size() and self.expr.fixed_size()
215
216 class ExprType(Type):
217     '''
218     Derived class which represents an exprfield.  Fixed size.
219
220     Public fields added:
221     expr is an Expression object containing the value of the field.
222     '''
223     def __init__(self, elt, member, *parent):
224         Type.__init__(self, member.name)
225         self.is_expr = True
226         self.member = member
227         self.parent = parent
228
229         self.expr = Expression(list(elt)[0], self)
230
231         self.size = member.size
232         self.nmemb = 1
233
234     def resolve(self, module):
235         if self.resolved:
236             return
237         self.member.resolve(module)
238         self.resolved = True
239
240     def fixed_size(self):
241         return True
242
243 class PadType(Type):
244     '''
245     Derived class which represents a padding field.
246     '''
247     def __init__(self, elt):
248         Type.__init__(self, tcard8.name)
249         self.is_pad = True
250         self.size = 1
251         self.nmemb = 1 if (elt == None) else int(elt.get('bytes'), 0)
252
253     def resolve(self, module):
254         self.resolved = True
255
256     def fixed_size(self):
257         return True
258
259     
260 class ComplexType(Type):
261     '''
262     Derived class which represents a structure.  Base type for all structure types.
263
264     Public fields added:
265     fields is an array of Field objects describing the structure fields.
266     '''
267     def __init__(self, name, elt):
268         Type.__init__(self, name)
269         self.is_container = True
270         self.elt = elt
271         self.fields = []
272         self.nmemb = 1
273         self.size = 0
274         self.lenfield_parent = [self]
275
276     def resolve(self, module):
277         if self.resolved:
278             return
279         pads = 0
280
281         # Resolve all of our field datatypes.
282         for child in list(self.elt):
283             if child.tag == 'pad':
284                 field_name = 'pad' + str(pads)
285                 fkey = 'CARD8'
286                 type = PadType(child)
287                 pads = pads + 1
288                 visible = False
289             elif child.tag == 'field':
290                 field_name = child.get('name')
291                 fkey = child.get('type')
292                 type = module.get_type(fkey)
293                 visible = True
294             elif child.tag == 'exprfield':
295                 field_name = child.get('name')
296                 fkey = child.get('type')
297                 type = ExprType(child, module.get_type(fkey), *self.lenfield_parent)
298                 visible = False
299             elif child.tag == 'list':
300                 field_name = child.get('name')
301                 fkey = child.get('type')
302                 type = ListType(child, module.get_type(fkey), *self.lenfield_parent)
303                 visible = True
304             elif child.tag == 'valueparam':
305                 field_name = child.get('value-list-name')
306                 fkey = 'CARD32'
307                 type = ListType(child, module.get_type(fkey), *self.lenfield_parent)
308                 visible = True
309             elif child.tag == 'switch':
310                 field_name = child.get('name')
311                 # construct the switch type name from the parent type and the field name
312                 field_type = self.name + (field_name,)
313                 type = SwitchType(field_type, child, *self.lenfield_parent)
314                 visible = True
315                 type.make_member_of(module, self, field_type, field_name, visible, True, False)
316                 type.resolve(module)
317                 continue
318             else:
319                 # Hit this on Reply
320                 continue 
321
322             # Get the full type name for the field
323             field_type = module.get_type_name(fkey)
324             # Add the field to ourself
325             type.make_member_of(module, self, field_type, field_name, visible, True, False)
326             # Recursively resolve the type (could be another structure, list)
327             type.resolve(module)
328
329         self.calc_size() # Figure out how big we are
330         self.resolved = True
331
332     def calc_size(self):
333         self.size = 0
334         for m in self.fields:
335             if not m.wire:
336                 continue
337             if m.type.fixed_size():
338                 self.size = self.size + (m.type.size * m.type.nmemb)
339             else:
340                 self.size = None
341                 break
342
343     def fixed_size(self):
344         for m in self.fields:
345             if not m.type.fixed_size():
346                 return False
347         return True
348
349 class SwitchType(ComplexType):
350     '''
351     Derived class which represents a List of Items.  
352
353     Public fields added:
354     bitcases is an array of Bitcase objects describing the list items
355     '''
356
357     def __init__(self, name, elt, *parents):
358         ComplexType.__init__(self, name, elt)
359         self.parent = parents
360         # FIXME: switch cannot store lenfields, so it should just delegate the parents
361         self.lenfield_parent = list(parents) + [self]
362         # self.fields contains all possible fields collected from the Bitcase objects, 
363         # whereas self.items contains the Bitcase objects themselves
364         self.bitcases = []
365
366         self.is_switch = True
367         elts = list(elt)
368         self.expr = Expression(elts[0] if len(elts) else elt, self)
369
370     def resolve(self, module):
371         if self.resolved:
372             return
373 #        pads = 0
374
375         # Resolve all of our field datatypes.
376         for index, child in enumerate(list(self.elt)):
377             if child.tag == 'bitcase':
378                 # use self.parent to indicate anchestor, 
379                 # as switch does not contain named fields itself
380                 type = BitcaseType(index, child, *self.parent)
381                 visible = True
382
383                 # Get the full type name for the field
384                 field_type = type.name               
385
386                 # add the field to ourself
387                 type.make_member_of(module, self, field_type, index, visible, True, False)
388
389                 # recursively resolve the type (could be another structure, list)
390                 type.resolve(module)
391                 inserted = False
392                 for new_field in type.fields:
393                     # We dump the _placeholder_byte if any fields are added.
394                     for (idx, field) in enumerate(self.fields):
395                         if field == _placeholder_byte:
396                             self.fields[idx] = new_field
397                             inserted = True
398                             break
399                     if False == inserted:
400                         self.fields.append(new_field)
401
402         self.calc_size() # Figure out how big we are
403         self.resolved = True
404
405     # FIXME: really necessary for Switch??
406     def make_member_of(self, module, complex_type, field_type, field_name, visible, wire, auto):
407         if not self.fixed_size():
408             # We need a length field.
409             # Ask our Expression object for it's name, type, and whether it's on the wire.
410             lenfid = self.expr.lenfield_type
411             lenfield_name = self.expr.lenfield_name
412             lenwire = self.expr.lenwire
413             needlen = True
414
415             # See if the length field is already in the structure.
416             for parent in self.parent:
417                 for field in parent.fields:
418                     if field.field_name == lenfield_name:
419                         needlen = False
420
421             # It isn't, so we need to add it to the structure ourself.
422             if needlen:
423                 type = module.get_type(lenfid)
424                 lenfield_type = module.get_type_name(lenfid)
425                 type.make_member_of(module, complex_type, lenfield_type, lenfield_name, True, lenwire, False)
426
427         # Add ourself to the structure by calling our original method.
428         Type.make_member_of(self, module, complex_type, field_type, field_name, visible, wire, auto)
429
430     # size for switch can only be calculated at runtime
431     def calc_size(self):
432         pass
433
434     # note: switch is _always_ of variable size, but we indicate here wether 
435     # it contains elements that are variable-sized themselves
436     def fixed_size(self):
437         return False
438 #        for m in self.fields:
439 #            if not m.type.fixed_size():
440 #                return False
441 #        return True
442
443
444 class Struct(ComplexType):
445     '''
446     Derived class representing a struct data type.
447     '''
448     out = __main__.output['struct']
449
450
451 class Union(ComplexType):
452     '''
453     Derived class representing a union data type.
454     '''
455     def __init__(self, name, elt):
456         ComplexType.__init__(self, name, elt)
457         self.is_union = True
458
459     out = __main__.output['union']
460
461
462 class BitcaseType(ComplexType):
463     '''
464     Derived class representing a struct data type.
465     '''
466     def __init__(self, index, elt, *parent):
467         elts = list(elt)
468         self.expr = Expression(elts[0] if len(elts) else elt, self)
469         ComplexType.__init__(self, ('bitcase%d' % index,), elts[1:])        
470         self.lenfield_parent = list(parent) + [self]
471         self.parents = list(parent)
472
473     def make_member_of(self, module, switch_type, field_type, field_name, visible, wire, auto):
474         '''
475         register BitcaseType with the corresponding SwitchType
476
477         module is the global module object.
478         complex_type is the structure object.
479         see Field for the meaning of the other parameters.
480         '''
481         new_field = Field(self, field_type, field_name, visible, wire, auto)
482
483         # We dump the _placeholder_byte if any bitcases are added.
484         for (idx, field) in enumerate(switch_type.bitcases):
485             if field == _placeholder_byte:
486                 switch_type.bitcases[idx] = new_field
487                 return
488
489         switch_type.bitcases.append(new_field)
490
491     def resolve(self, module):
492         if self.resolved:
493             return
494         
495         self.expr.resolve(module, self.parents+[self])
496
497         # Resolve the bitcase expression
498         ComplexType.resolve(self, module)
499
500
501 class Reply(ComplexType):
502     '''
503     Derived class representing a reply.  Only found as a field of Request.
504     '''
505     def __init__(self, name, elt):
506         ComplexType.__init__(self, name, elt)
507         self.is_reply = True
508
509     def resolve(self, module):
510         if self.resolved:
511             return
512         # Add the automatic protocol fields
513         self.fields.append(Field(tcard8, tcard8.name, 'response_type', False, True, True))
514         self.fields.append(_placeholder_byte)
515         self.fields.append(Field(tcard16, tcard16.name, 'sequence', False, True, True))
516         self.fields.append(Field(tcard32, tcard32.name, 'length', False, True, True))
517         ComplexType.resolve(self, module)
518         
519
520 class Request(ComplexType):
521     '''
522     Derived class representing a request.
523
524     Public fields added:
525     reply contains the reply datatype or None for void requests.
526     opcode contains the request number.
527     '''
528     def __init__(self, name, elt):
529         ComplexType.__init__(self, name, elt)
530         self.reply = None
531         self.opcode = elt.get('opcode')
532
533         for child in list(elt):
534             if child.tag == 'reply':
535                 self.reply = Reply(name, child)
536
537     def resolve(self, module):
538         if self.resolved:
539             return
540         # Add the automatic protocol fields
541         if module.namespace.is_ext:
542             self.fields.append(Field(tcard8, tcard8.name, 'major_opcode', False, True, True))
543             self.fields.append(Field(tcard8, tcard8.name, 'minor_opcode', False, True, True))
544             self.fields.append(Field(tcard16, tcard16.name, 'length', False, True, True))
545             ComplexType.resolve(self, module)
546         else:
547             self.fields.append(Field(tcard8, tcard8.name, 'major_opcode', False, True, True))
548             self.fields.append(_placeholder_byte)
549             self.fields.append(Field(tcard16, tcard16.name, 'length', False, True, True))
550             ComplexType.resolve(self, module)
551
552         if self.reply:
553             self.reply.resolve(module)
554
555     out = __main__.output['request']
556
557
558 class Event(ComplexType):
559     '''
560     Derived class representing an event data type.
561
562     Public fields added:
563     opcodes is a dictionary of name -> opcode number, for eventcopies.
564     '''
565     def __init__(self, name, elt):
566         ComplexType.__init__(self, name, elt)
567         self.opcodes = {}
568
569         tmp = elt.get('no-sequence-number')
570         self.has_seq = (tmp == None or tmp.lower() == 'false' or tmp == '0')
571             
572     def add_opcode(self, opcode, name, main):
573         self.opcodes[name] = opcode
574         if main:
575             self.name = name
576
577     def resolve(self, module):
578         if self.resolved:
579             return
580
581         # Add the automatic protocol fields
582         self.fields.append(Field(tcard8, tcard8.name, 'response_type', False, True, True))
583         if self.has_seq:
584             self.fields.append(_placeholder_byte)
585             self.fields.append(Field(tcard16, tcard16.name, 'sequence', False, True, True))
586         ComplexType.resolve(self, module)
587
588     out = __main__.output['event']
589
590
591 class Error(ComplexType):
592     '''
593     Derived class representing an error data type.
594
595     Public fields added:
596     opcodes is a dictionary of name -> opcode number, for errorcopies.
597     '''
598     def __init__(self, name, elt):
599         ComplexType.__init__(self, name, elt)
600         self.opcodes = {}
601
602     def add_opcode(self, opcode, name, main):
603         self.opcodes[name] = opcode
604         if main:
605             self.name = name
606
607     def resolve(self, module):
608         if self.resolved:
609             return
610
611         # Add the automatic protocol fields
612         self.fields.append(Field(tcard8, tcard8.name, 'response_type', False, True, True))
613         self.fields.append(Field(tcard8, tcard8.name, 'error_code', False, True, True))
614         self.fields.append(Field(tcard16, tcard16.name, 'sequence', False, True, True))
615         ComplexType.resolve(self, module)
616
617     out = __main__.output['error']
618
619 _placeholder_byte = Field(PadType(None), tcard8.name, 'pad0', False, True, False)