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