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