Add support for X Generic Extension events
[free-sw/xcb/proto] / xcbgen / xtypes.py
1 '''
2 This module contains the classes which represent XCB data types.
3 '''
4 from xcbgen.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, enum=None):
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, enum)
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         self.doc = None
127         for item in list(elt):
128             if item.tag == 'doc':
129                 self.doc = Doc(name, item)
130
131             # First check if we're using a default value
132             if len(list(item)) == 0:
133                 self.values.append((item.get('name'), ''))
134                 continue
135
136             # An explicit value or bit was specified.
137             value = list(item)[0]
138             if value.tag == 'value':
139                 self.values.append((item.get('name'), value.text))
140             elif value.tag == 'bit':
141                 self.values.append((item.get('name'), '%u' % (1 << int(value.text, 0))))
142                 self.bits.append((item.get('name'), value.text))
143
144     def resolve(self, module):
145         self.resolved = True
146
147     def fixed_size(self):
148         return True
149
150     out = __main__.output['enum']
151
152
153 class ListType(Type):
154     '''
155     Derived class which represents a list of some other datatype.  Fixed- or variable-sized.
156
157     Public fields added:
158     member is the datatype of the list elements.
159     parent is the structure type containing the list.
160     expr is an Expression object containing the length information, for variable-sized lists.
161     '''
162     def __init__(self, elt, member, *parent):
163         Type.__init__(self, member.name)
164         self.is_list = True
165         self.member = member
166         self.parents = list(parent)
167
168         if elt.tag == 'list':
169             elts = list(elt)
170             self.expr = Expression(elts[0] if len(elts) else elt, self)
171         elif elt.tag == 'valueparam':
172             self.expr = Expression(elt, self)
173
174         self.size = member.size if member.fixed_size() else None
175         self.nmemb = self.expr.nmemb if self.expr.fixed_size() else None
176
177     def make_member_of(self, module, complex_type, field_type, field_name, visible, wire, auto, enum=None):
178         if not self.fixed_size():
179             # We need a length field.
180             # Ask our Expression object for it's name, type, and whether it's on the wire.
181             lenfid = self.expr.lenfield_type
182             lenfield_name = self.expr.lenfield_name
183             lenwire = self.expr.lenwire
184             needlen = True
185
186             # See if the length field is already in the structure.
187             for parent in self.parents:
188                 for field in parent.fields:
189                     if field.field_name == lenfield_name:
190                         needlen = False
191
192             # It isn't, so we need to add it to the structure ourself.
193             if needlen:
194                 type = module.get_type(lenfid)
195                 lenfield_type = module.get_type_name(lenfid)
196                 type.make_member_of(module, complex_type, lenfield_type, lenfield_name, True, lenwire, False, enum)
197
198         # Add ourself to the structure by calling our original method.
199         Type.make_member_of(self, module, complex_type, field_type, field_name, visible, wire, auto, enum)
200
201     def resolve(self, module):
202         if self.resolved:
203             return
204         self.member.resolve(module)
205         self.expr.resolve(module, self.parents)
206
207         # Find my length field again.  We need the actual Field object in the expr.
208         # This is needed because we might have added it ourself above.
209         if not self.fixed_size():
210             for parent in self.parents:
211                 for field in parent.fields:
212                     if field.field_name == self.expr.lenfield_name and field.wire:
213                         self.expr.lenfield = field
214                         break
215
216         self.resolved = True
217
218     def fixed_size(self):
219         return self.member.fixed_size() and self.expr.fixed_size()
220
221 class ExprType(Type):
222     '''
223     Derived class which represents an exprfield.  Fixed size.
224
225     Public fields added:
226     expr is an Expression object containing the value of the field.
227     '''
228     def __init__(self, elt, member, *parents):
229         Type.__init__(self, member.name)
230         self.is_expr = True
231         self.member = member
232         self.parents = parents
233
234         self.expr = Expression(list(elt)[0], self)
235
236         self.size = member.size
237         self.nmemb = 1
238
239     def resolve(self, module):
240         if self.resolved:
241             return
242         self.member.resolve(module)
243         self.resolved = True
244
245     def fixed_size(self):
246         return True
247
248 class PadType(Type):
249     '''
250     Derived class which represents a padding field.
251     '''
252     def __init__(self, elt):
253         Type.__init__(self, tcard8.name)
254         self.is_pad = True
255         self.size = 1
256         self.nmemb = 1 if (elt == None) else int(elt.get('bytes'), 0)
257
258     def resolve(self, module):
259         self.resolved = True
260
261     def fixed_size(self):
262         return True
263
264     
265 class ComplexType(Type):
266     '''
267     Derived class which represents a structure.  Base type for all structure types.
268
269     Public fields added:
270     fields is an array of Field objects describing the structure fields.
271     '''
272     def __init__(self, name, elt):
273         Type.__init__(self, name)
274         self.is_container = True
275         self.elt = elt
276         self.fields = []
277         self.nmemb = 1
278         self.size = 0
279         self.lenfield_parent = [self]
280
281     def resolve(self, module):
282         if self.resolved:
283             return
284         pads = 0
285         enum = None
286
287         # Resolve all of our field datatypes.
288         for child in list(self.elt):
289             if child.tag == 'pad':
290                 field_name = 'pad' + str(pads)
291                 fkey = 'CARD8'
292                 type = PadType(child)
293                 pads = pads + 1
294                 visible = False
295             elif child.tag == 'field':
296                 field_name = child.get('name')
297                 enum = child.get('enum')
298                 fkey = child.get('type')
299                 type = module.get_type(fkey)
300                 visible = True
301             elif child.tag == 'exprfield':
302                 field_name = child.get('name')
303                 fkey = child.get('type')
304                 type = ExprType(child, module.get_type(fkey), *self.lenfield_parent)
305                 visible = False
306             elif child.tag == 'list':
307                 field_name = child.get('name')
308                 fkey = child.get('type')
309                 type = ListType(child, module.get_type(fkey), *self.lenfield_parent)
310                 visible = True
311             elif child.tag == 'valueparam':
312                 field_name = child.get('value-list-name')
313                 fkey = 'CARD32'
314                 type = ListType(child, module.get_type(fkey), *self.lenfield_parent)
315                 visible = True
316             elif child.tag == 'switch':
317                 field_name = child.get('name')
318                 # construct the switch type name from the parent type and the field name
319                 field_type = self.name + (field_name,)
320                 type = SwitchType(field_type, child, *self.lenfield_parent)
321                 visible = True
322                 type.make_member_of(module, self, field_type, field_name, visible, True, False)
323                 type.resolve(module)
324                 continue
325             else:
326                 # Hit this on Reply
327                 continue 
328
329             # Get the full type name for the field
330             field_type = module.get_type_name(fkey)
331             # Add the field to ourself
332             type.make_member_of(module, self, field_type, field_name, visible, True, False, enum)
333             # Recursively resolve the type (could be another structure, list)
334             type.resolve(module)
335
336         self.calc_size() # Figure out how big we are
337         self.resolved = True
338
339     def calc_size(self):
340         self.size = 0
341         for m in self.fields:
342             if not m.wire:
343                 continue
344             if m.type.fixed_size():
345                 self.size = self.size + (m.type.size * m.type.nmemb)
346             else:
347                 self.size = None
348                 break
349
350     def fixed_size(self):
351         for m in self.fields:
352             if not m.type.fixed_size():
353                 return False
354         return True
355
356 class SwitchType(ComplexType):
357     '''
358     Derived class which represents a List of Items.  
359
360     Public fields added:
361     bitcases is an array of Bitcase objects describing the list items
362     '''
363
364     def __init__(self, name, elt, *parents):
365         ComplexType.__init__(self, name, elt)
366         self.parents = parents
367         # FIXME: switch cannot store lenfields, so it should just delegate the parents
368         self.lenfield_parent = list(parents) + [self]
369         # self.fields contains all possible fields collected from the Bitcase objects, 
370         # whereas self.items contains the Bitcase objects themselves
371         self.bitcases = []
372
373         self.is_switch = True
374         elts = list(elt)
375         self.expr = Expression(elts[0] if len(elts) else elt, self)
376
377     def resolve(self, module):
378         if self.resolved:
379             return
380 #        pads = 0
381
382         parents = list(self.parents) + [self]
383
384         # Resolve all of our field datatypes.
385         for index, child in enumerate(list(self.elt)):
386             if child.tag == 'bitcase':
387                 field_name = child.get('name')
388                 if field_name is None:
389                     field_type = self.name + ('bitcase%d' % index,)
390                 else:
391                     field_type = self.name + (field_name,)
392
393                 # use self.parent to indicate anchestor, 
394                 # as switch does not contain named fields itself
395                 type = BitcaseType(index, field_type, child, *parents)
396                 # construct the switch type name from the parent type and the field name
397                 if field_name is None:
398                     type.has_name = False
399                     # Get the full type name for the field
400                     field_type = type.name               
401                 visible = True
402
403                 # add the field to ourself
404                 type.make_member_of(module, self, field_type, field_name, visible, True, False)
405
406                 # recursively resolve the type (could be another structure, list)
407                 type.resolve(module)
408                 inserted = False
409                 for new_field in type.fields:
410                     # We dump the _placeholder_byte if any fields are added.
411                     for (idx, field) in enumerate(self.fields):
412                         if field == _placeholder_byte:
413                             self.fields[idx] = new_field
414                             inserted = True
415                             break
416                     if False == inserted:
417                         self.fields.append(new_field)
418
419         self.calc_size() # Figure out how big we are
420         self.resolved = True
421
422     def make_member_of(self, module, complex_type, field_type, field_name, visible, wire, auto, enum=None):
423         if not self.fixed_size():
424             # We need a length field.
425             # Ask our Expression object for it's name, type, and whether it's on the wire.
426             lenfid = self.expr.lenfield_type
427             lenfield_name = self.expr.lenfield_name
428             lenwire = self.expr.lenwire
429             needlen = True
430
431             # See if the length field is already in the structure.
432             for parent in self.parents:
433                 for field in parent.fields:
434                     if field.field_name == lenfield_name:
435                         needlen = False
436
437             # It isn't, so we need to add it to the structure ourself.
438             if needlen:
439                 type = module.get_type(lenfid)
440                 lenfield_type = module.get_type_name(lenfid)
441                 type.make_member_of(module, complex_type, lenfield_type, lenfield_name, True, lenwire, False, enum)
442
443         # Add ourself to the structure by calling our original method.
444         Type.make_member_of(self, module, complex_type, field_type, field_name, visible, wire, auto, enum)
445
446     # size for switch can only be calculated at runtime
447     def calc_size(self):
448         pass
449
450     # note: switch is _always_ of variable size, but we indicate here wether 
451     # it contains elements that are variable-sized themselves
452     def fixed_size(self):
453         return False
454 #        for m in self.fields:
455 #            if not m.type.fixed_size():
456 #                return False
457 #        return True
458
459
460 class Struct(ComplexType):
461     '''
462     Derived class representing a struct data type.
463     '''
464     out = __main__.output['struct']
465
466
467 class Union(ComplexType):
468     '''
469     Derived class representing a union data type.
470     '''
471     def __init__(self, name, elt):
472         ComplexType.__init__(self, name, elt)
473         self.is_union = True
474
475     out = __main__.output['union']
476
477
478 class BitcaseType(ComplexType):
479     '''
480     Derived class representing a struct data type.
481     '''
482     def __init__(self, index, name, elt, *parent):
483         elts = list(elt)
484         self.expr = []
485         fields = []
486         for elt in elts:
487             if elt.tag == 'enumref':
488                 self.expr.append(Expression(elt, self))
489             else:
490                 fields.append(elt)
491         ComplexType.__init__(self, name, fields)
492         self.has_name = True
493         self.index = 1
494         self.lenfield_parent = list(parent) + [self]
495         self.parents = list(parent)
496         self.is_bitcase = True
497
498     def make_member_of(self, module, switch_type, field_type, field_name, visible, wire, auto, enum=None):
499         '''
500         register BitcaseType with the corresponding SwitchType
501
502         module is the global module object.
503         complex_type is the structure object.
504         see Field for the meaning of the other parameters.
505         '''
506         new_field = Field(self, field_type, field_name, visible, wire, auto, enum)
507
508         # We dump the _placeholder_byte if any bitcases are added.
509         for (idx, field) in enumerate(switch_type.bitcases):
510             if field == _placeholder_byte:
511                 switch_type.bitcases[idx] = new_field
512                 return
513
514         switch_type.bitcases.append(new_field)
515
516     def resolve(self, module):
517         if self.resolved:
518             return
519
520         for e in self.expr:
521             e.resolve(module, self.parents+[self])
522
523         # Resolve the bitcase expression
524         ComplexType.resolve(self, module)
525
526
527 class Reply(ComplexType):
528     '''
529     Derived class representing a reply.  Only found as a field of Request.
530     '''
531     def __init__(self, name, elt):
532         ComplexType.__init__(self, name, elt)
533         self.is_reply = True
534         self.doc = None
535
536         for child in list(elt):
537             if child.tag == 'doc':
538                 self.doc = Doc(name, child)
539
540     def resolve(self, module):
541         if self.resolved:
542             return
543         # Add the automatic protocol fields
544         self.fields.append(Field(tcard8, tcard8.name, 'response_type', False, True, True))
545         self.fields.append(_placeholder_byte)
546         self.fields.append(Field(tcard16, tcard16.name, 'sequence', False, True, True))
547         self.fields.append(Field(tcard32, tcard32.name, 'length', False, True, True))
548         ComplexType.resolve(self, module)
549         
550
551 class Request(ComplexType):
552     '''
553     Derived class representing a request.
554
555     Public fields added:
556     reply contains the reply datatype or None for void requests.
557     opcode contains the request number.
558     '''
559     def __init__(self, name, elt):
560         ComplexType.__init__(self, name, elt)
561         self.reply = None
562         self.doc = None
563         self.opcode = elt.get('opcode')
564
565         for child in list(elt):
566             if child.tag == 'reply':
567                 self.reply = Reply(name, child)
568             if child.tag == 'doc':
569                 self.doc = Doc(name, child)
570
571     def resolve(self, module):
572         if self.resolved:
573             return
574         # Add the automatic protocol fields
575         if module.namespace.is_ext:
576             self.fields.append(Field(tcard8, tcard8.name, 'major_opcode', False, True, True))
577             self.fields.append(Field(tcard8, tcard8.name, 'minor_opcode', False, True, True))
578             self.fields.append(Field(tcard16, tcard16.name, 'length', False, True, True))
579             ComplexType.resolve(self, module)
580         else:
581             self.fields.append(Field(tcard8, tcard8.name, 'major_opcode', False, True, True))
582             self.fields.append(_placeholder_byte)
583             self.fields.append(Field(tcard16, tcard16.name, 'length', False, True, True))
584             ComplexType.resolve(self, module)
585
586         if self.reply:
587             self.reply.resolve(module)
588
589     out = __main__.output['request']
590
591
592 class Event(ComplexType):
593     '''
594     Derived class representing an event data type.
595
596     Public fields added:
597     opcodes is a dictionary of name -> opcode number, for eventcopies.
598     '''
599     def __init__(self, name, elt):
600         ComplexType.__init__(self, name, elt)
601         self.opcodes = {}
602
603         self.has_seq = not bool(elt.get('no-sequence-number'))
604
605         self.is_ge_event = bool(elt.get('xge'))
606
607         self.doc = None
608         for item in list(elt):
609             if item.tag == 'doc':
610                 self.doc = Doc(name, item)
611
612     def add_opcode(self, opcode, name, main):
613         self.opcodes[name] = opcode
614         if main:
615             self.name = name
616
617     def resolve(self, module):
618         def add_event_header():
619             self.fields.append(Field(tcard8, tcard8.name, 'response_type', False, True, True))
620             if self.has_seq:
621                 self.fields.append(_placeholder_byte)
622                 self.fields.append(Field(tcard16, tcard16.name, 'sequence', False, True, True))
623
624         def add_ge_event_header():
625             self.fields.append(Field(tcard8,  tcard8.name,  'response_type', False, True, True))
626             self.fields.append(Field(tcard8,  tcard8.name,  'extension', False, True, True))
627             self.fields.append(Field(tcard16, tcard16.name, 'sequence', False, True, True))
628             self.fields.append(Field(tcard32, tcard32.name, 'length', False, True, True))
629             self.fields.append(Field(tcard16, tcard16.name, 'event_type', False, True, True))
630
631         if self.resolved:
632             return
633
634         # Add the automatic protocol fields
635         if self.is_ge_event:
636             add_ge_event_header()
637         else:
638             add_event_header()
639
640         ComplexType.resolve(self, module)
641
642     out = __main__.output['event']
643
644
645 class Error(ComplexType):
646     '''
647     Derived class representing an error data type.
648
649     Public fields added:
650     opcodes is a dictionary of name -> opcode number, for errorcopies.
651     '''
652     def __init__(self, name, elt):
653         ComplexType.__init__(self, name, elt)
654         self.opcodes = {}
655
656     def add_opcode(self, opcode, name, main):
657         self.opcodes[name] = opcode
658         if main:
659             self.name = name
660
661     def resolve(self, module):
662         if self.resolved:
663             return
664
665         # Add the automatic protocol fields
666         self.fields.append(Field(tcard8, tcard8.name, 'response_type', False, True, True))
667         self.fields.append(Field(tcard8, tcard8.name, 'error_code', False, True, True))
668         self.fields.append(Field(tcard16, tcard16.name, 'sequence', False, True, True))
669         ComplexType.resolve(self, module)
670
671     out = __main__.output['error']
672
673
674 class Doc(object):
675     '''
676     Class representing a <doc> tag.
677     '''
678     def __init__(self, name, elt):
679         self.name = name
680         self.description = None
681         self.brief = 'BRIEF DESCRIPTION MISSING'
682         self.fields = {}
683         self.errors = {}
684         self.see = {}
685         self.example = None
686
687         for child in list(elt):
688             text = child.text if child.text else ''
689             if child.tag == 'description':
690                 self.description = text.strip()
691             if child.tag == 'brief':
692                 self.brief = text.strip()
693             if child.tag == 'field':
694                 self.fields[child.get('name')] = text.strip()
695             if child.tag == 'error':
696                 self.errors[child.get('type')] = text.strip()
697             if child.tag == 'see':
698                 self.see[child.get('name')] = child.get('type')
699             if child.tag == 'example':
700                 self.example = text.strip()
701
702
703
704 _placeholder_byte = Field(PadType(None), tcard8.name, 'pad0', False, True, False)