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