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