]> git.cworth.org Git - apitrace/blob - base.py
Make better use of C++ implicit casts. Support arrays.
[apitrace] / base.py
1 ##########################################################################
2 #
3 # Copyright 2008-2009 VMware, Inc.
4 # All Rights Reserved.
5 #
6 # Permission is hereby granted, free of charge, to any person obtaining a copy
7 # of this software and associated documentation files (the "Software"), to deal
8 # in the Software without restriction, including without limitation the rights
9 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 # copies of the Software, and to permit persons to whom the Software is
11 # furnished to do so, subject to the following conditions:
12 #
13 # The above copyright notice and this permission notice shall be included in
14 # all copies or substantial portions of the Software.
15 #
16 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 # THE SOFTWARE.
23 #
24 ##########################################################################/
25
26 """C basic types"""
27
28
29 import debug
30
31
32 all_types = {}
33
34
35 class Visitor:
36
37     def visit(self, type, *args, **kwargs):
38         return type.visit(self, *args, **kwargs)
39
40     __call__ = visit
41
42     def visit_void(self, type, *args, **kwargs):
43         raise NotImplementedError
44
45     def visit_literal(self, type, *args, **kwargs):
46         raise NotImplementedError
47
48     def visit_const(self, type, *args, **kwargs):
49         raise NotImplementedError
50
51     def visit_struct(self, type, *args, **kwargs):
52         raise NotImplementedError
53
54     def visit_array(self, type, *args, **kwargs):
55         raise NotImplementedError
56
57     def visit_enum(self, type, *args, **kwargs):
58         raise NotImplementedError
59
60     def visit_bitmask(self, type, *args, **kwargs):
61         raise NotImplementedError
62
63     def visit_pointer(self, type, *args, **kwargs):
64         raise NotImplementedError
65
66     def visit_alias(self, type, *args, **kwargs):
67         raise NotImplementedError
68
69     def visit_opaque(self, type, *args, **kwargs):
70         raise NotImplementedError
71
72
73 class Rebuilder(Visitor):
74
75     def visit_void(self, void):
76         return void
77
78     def visit_literal(self, literal):
79         return literal
80
81     def visit_const(self, const):
82         return Const(const.type)
83
84     def visit_struct(self, struct):
85         members = [self.visit(member) for member in struct.members]
86         return Struct(struct.name, members)
87
88     def visit_array(self, array):
89         type = self.visit(array.type)
90         return Array(type, array.length)
91
92     def visit_enum(self, enum):
93         return enum
94
95     def visit_bitmask(self, bitmask):
96         type = self.visit(bitmask.type)
97         return Bitmask(type, bitmask.values)
98
99     def visit_pointer(self, pointer):
100         type = self.visit(pointer.type)
101         return Pointer(type)
102
103     def visit_alias(self, alias):
104         type = self.visit(alias.type)
105         return Alias(alias.expr, type)
106
107     def visit_opaque(self, opaque):
108         return opaque
109
110
111 class Type:
112
113     __seq = 0
114
115     def __init__(self, expr, id = ''):
116         self.expr = expr
117         
118         for char in id:
119             assert char.isalnum() or char in '_ '
120
121         id = id.replace(' ', '_')
122         
123         if id in all_types:
124             Type.__seq += 1
125             id += str(Type.__seq)
126         
127         assert id not in all_types
128         all_types[id] = self
129
130         self.id = id
131
132     def __str__(self):
133         return self.expr
134
135     def visit(self, visitor, *args, **kwargs):
136         raise NotImplementedError
137
138     def isoutput(self):
139         return False
140
141     def decl(self):
142         pass
143
144     def impl(self):
145         pass
146
147     def dump(self, instance):
148         raise NotImplementedError
149     
150     def wrap_instance(self, instance):
151         pass 
152
153     def unwrap_instance(self, instance):
154         pass
155
156
157 class _Void(Type):
158
159     def __init__(self):
160         Type.__init__(self, "void")
161
162     def visit(self, visitor, *args, **kwargs):
163         return visitor.visit_void(self, *args, **kwargs)
164
165 Void = _Void()
166
167
168 class Concrete(Type):
169
170     def decl(self):
171         print 'static void Dump%s(const %s &value);' % (self.id, self.expr)
172     
173     def impl(self):
174         print 'static void Dump%s(const %s &value) {' % (self.id, self.expr)
175         self._dump("value");
176         print '}'
177         print
178     
179     def _dump(self, instance):
180         raise NotImplementedError
181     
182     def dump(self, instance):
183         print '    Dump%s(%s);' % (self.id, instance)
184     
185
186 class Literal(Concrete):
187
188     def __init__(self, expr, format, base=10):
189         Concrete.__init__(self, expr)
190         self.format = format
191
192     def visit(self, visitor, *args, **kwargs):
193         return visitor.visit_literal(self, *args, **kwargs)
194
195     def _dump(self, instance):
196         print '    Log::Literal%s(%s);' % (self.format, instance)
197
198
199 class Const(Type):
200
201     def __init__(self, type):
202
203         if isinstance(type, Pointer):
204             expr = type.expr + " const"
205         else:
206             expr = "const " + type.expr
207
208         Type.__init__(self, expr, 'C' + type.id)
209
210         self.type = type
211
212     def visit(self, visitor, *args, **kwargs):
213         return visitor.visit_const(self, *args, **kwargs)
214
215     def dump(self, instance):
216         self.type.dump(instance)
217
218
219 class Pointer(Type):
220
221     def __init__(self, type):
222         Type.__init__(self, type.expr + " *", 'P' + type.id)
223         self.type = type
224
225     def visit(self, visitor, *args, **kwargs):
226         return visitor.visit_pointer(self, *args, **kwargs)
227
228     def dump(self, instance):
229         print '    if(%s) {' % instance
230         print '        Log::BeginPointer("%s", (const void *)%s);' % (self.type, instance)
231         try:
232             self.type.dump("*" + instance)
233         except NotImplementedError:
234             pass
235         print '        Log::EndPointer();'
236         print '    }'
237         print '    else'
238         print '        Log::LiteralNull();'
239
240     def wrap_instance(self, instance):
241         self.type.wrap_instance("*" + instance)
242
243     def unwrap_instance(self, instance):
244         self.type.wrap_instance("*" + instance)
245
246
247 def ConstPointer(type):
248     return Pointer(Const(type))
249
250
251 class OutPointer(Pointer):
252
253     def isoutput(self):
254         return True
255
256
257 class Enum(Concrete):
258
259     def __init__(self, name, values):
260         Concrete.__init__(self, name)
261         self.values = values
262     
263     def visit(self, visitor, *args, **kwargs):
264         return visitor.visit_enum(self, *args, **kwargs)
265
266     def _dump(self, instance):
267         print '    switch(%s) {' % instance
268         for value in self.values:
269             print '    case %s:' % value
270             print '        Log::LiteralNamedConstant("%s", %s);' % (value, value)
271             print '        break;'
272         print '    default:'
273         print '        Log::LiteralSInt(%s);' % instance
274         print '        break;'
275         print '    }'
276
277
278 def FakeEnum(type, values):
279     return Enum(type.expr, values)
280
281
282 class Bitmask(Concrete):
283
284     def __init__(self, type, values):
285         Concrete.__init__(self, type.expr)
286         self.type = type
287         self.values = values
288
289     def visit(self, visitor, *args, **kwargs):
290         return visitor.visit_bitmask(self, *args, **kwargs)
291
292     def _dump(self, instance):
293         print '    %s l_Value = %s;' % (self.type, instance)
294         print '    Log::BeginBitmask("%s");' % (self.type,)
295         for value in self.values:
296             print '    if((l_Value & %s) == %s) {' % (value, value)
297             print '        Log::LiteralNamedConstant("%s", %s);' % (value, value)
298             print '        l_Value &= ~%s;' % value
299             print '    }'
300         print '    if(l_Value) {'
301         self.type.dump("l_Value");
302         print '    }'
303         print '    Log::EndBitmask();'
304
305 Flags = Bitmask
306
307
308 class Array(Type):
309
310     def __init__(self, type, length):
311         Type.__init__(self, type.expr + " *", 'P' + type.id)
312         self.type = type
313         self.length = length
314
315     def visit(self, visitor, *args, **kwargs):
316         return visitor.visit_array(self, *args, **kwargs)
317
318     def dump(self, instance):
319         index = '__i' + self.type.id
320         print '    Log::BeginArray("%s", %s);' % (self.type, self.length)
321         print '    for (int %s = 0; %s < %s; ++%s) {' % (index, index, self.length, index)
322         print '        Log::BeginElement("%s");' % (self.type,)
323         self.type.dump('(%s)[%s]' % (instance, index))
324         print '        Log::EndElement();'
325         print '    }'
326         print '    Log::EndArray();'
327
328     def wrap_instance(self, instance):
329         self.type.wrap_instance("*" + instance)
330
331     def unwrap_instance(self, instance):
332         self.type.wrap_instance("*" + instance)
333
334
335 class OutArray(Array):
336
337     def isoutput(self):
338         return True
339
340
341 class Struct(Concrete):
342
343     def __init__(self, name, members):
344         Concrete.__init__(self, name)
345         self.name = name
346         self.members = members
347
348     def visit(self, visitor, *args, **kwargs):
349         return visitor.visit_struct(self, *args, **kwargs)
350
351     def _dump(self, instance):
352         print '    Log::BeginStruct("%s");' % (self.name,)
353         for type, name in self.members:
354             print '    Log::BeginMember("%s", "%s");' % (type, name)
355             type.dump('(%s).%s' % (instance, name))
356             print '    Log::EndMember();'
357         print '    Log::EndStruct();'
358
359
360 class Alias(Type):
361
362     def __init__(self, expr, type):
363         Type.__init__(self, expr)
364         self.type = type
365
366     def visit(self, visitor, *args, **kwargs):
367         return visitor.visit_alias(self, *args, **kwargs)
368
369     def dump(self, instance):
370         self.type.dump(instance)
371
372
373 class Out(Type):
374
375     def __init__(self, type):
376         Type.__init__(self, type.expr)
377         self.type = type
378
379     def isoutput(self):
380         return True
381
382     def decl(self):
383         self.type.decl()
384
385     def impl(self):
386         self.type.impl()
387
388     def dump(self, instance):
389         self.type.dump(instance)
390     
391     def wrap_instance(self, instance):
392         self.type.wrap_instance(instance)
393
394     def unwrap_instance(self, instance):
395         self.type.unwrap_instance(instance)
396
397
398 class Function:
399
400     def __init__(self, type, name, args, call = '__stdcall', fail = None):
401         self.type = type
402         self.name = name
403         self.args = args
404         self.call = call
405         self.fail = fail
406
407     def prototype(self, name=None):
408         if name is not None:
409             name = name.strip()
410         else:
411             name = self.name
412         s = name
413         if self.call:
414             s = self.call + ' ' + s
415         if name.startswith('*'):
416             s = '(' + s + ')'
417         s = self.type.expr + ' ' + s
418         s += "("
419         if self.args:
420             s += ", ".join(["%s %s" % (type, name) for type, name in self.args])
421         else:
422             s += "void"
423         s += ")"
424         return s
425
426     def pointer_type(self):
427         return 'P' + self.name
428
429     def pointer_value(self):
430         return 'p' + self.name
431
432     def wrap_decl(self):
433         ptype = self.pointer_type()
434         pvalue = self.pointer_value()
435         print 'typedef ' + self.prototype('* %s' % ptype) + ';'
436         print 'static %s %s = NULL;' % (ptype, pvalue)
437         print
438
439     def get_true_pointer(self):
440         raise NotImplementedError
441
442     def exit_impl(self):
443         print '            ExitProcess(0);'
444
445     def fail_impl(self):
446         if self.fail is not None:
447             if self.type is Void:
448                 assert self.fail == ''
449                 print '            return;' 
450             else:
451                 assert self.fail != ''
452                 print '            return %s;' % self.fail
453         else:
454             self.exit_impl()
455
456     def wrap_impl(self):
457         pvalue = self.pointer_value()
458         print self.prototype() + ' {'
459         if self.type is Void:
460             result = ''
461         else:
462             print '    %s result;' % self.type
463             result = 'result = '
464         self.get_true_pointer()
465         print '    Log::BeginCall("%s");' % (self.name)
466         for type, name in self.args:
467             if not type.isoutput():
468                 type.unwrap_instance(name)
469                 print '    Log::BeginArg("%s", "%s");' % (type, name)
470                 type.dump(name)
471                 print '    Log::EndArg();'
472         print '    %s%s(%s);' % (result, pvalue, ', '.join([str(name) for type, name in self.args]))
473         for type, name in self.args:
474             if type.isoutput():
475                 print '    Log::BeginArg("%s", "%s");' % (type, name)
476                 type.dump(name)
477                 print '    Log::EndArg();'
478                 type.wrap_instance(name)
479         if self.type is not Void:
480             print '    Log::BeginReturn("%s");' % self.type
481             self.type.dump("result")
482             print '    Log::EndReturn();'
483             self.type.wrap_instance('result')
484         print '    Log::EndCall();'
485         self.post_call_impl()
486         if self.type is not Void:
487             print '    return result;'
488         print '}'
489         print
490
491     def post_call_impl(self):
492         pass
493
494
495 class Interface(Type):
496
497     def __init__(self, name, base=None):
498         Type.__init__(self, name)
499         self.name = name
500         self.base = base
501         self.methods = []
502
503     def itermethods(self):
504         if self.base is not None:
505             for method in self.base.itermethods():
506                 yield method
507         for method in self.methods:
508             yield method
509         raise StopIteration
510
511     def wrap_name(self):
512         return "Wrap" + self.expr
513
514     def wrap_pre_decl(self):
515         print "class %s;" % self.wrap_name()
516
517     def wrap_decl(self):
518         print "class %s : public %s " % (self.wrap_name(), self.name)
519         print "{"
520         print "public:"
521         print "    %s(%s * pInstance);" % (self.wrap_name(), self.name)
522         print "    virtual ~%s();" % self.wrap_name()
523         print
524         for method in self.itermethods():
525             print "    " + method.prototype() + ";"
526         print
527         #print "private:"
528         print "    %s * m_pInstance;" % (self.name,)
529         print "};"
530         print
531
532     def wrap_impl(self):
533         print '%s::%s(%s * pInstance) {' % (self.wrap_name(), self.wrap_name(), self.name)
534         print '    m_pInstance = pInstance;'
535         print '}'
536         print
537         print '%s::~%s() {' % (self.wrap_name(), self.wrap_name())
538         print '}'
539         print
540         for method in self.itermethods():
541             print method.prototype(self.wrap_name() + '::' + method.name) + ' {'
542             if method.type is Void:
543                 result = ''
544             else:
545                 print '    %s result;' % method.type
546                 result = 'result = '
547             print '    Log::BeginCall("%s");' % (self.name + '::' + method.name)
548             print '    Log::BeginArg("%s *", "this");' % self.name
549             print '    Log::BeginPointer("%s", (const void *)m_pInstance);' % self.name
550             print '    Log::EndPointer();'
551             print '    Log::EndArg();'
552             for type, name in method.args:
553                 if not type.isoutput():
554                     type.unwrap_instance(name)
555                     print '    Log::BeginArg("%s", "%s");' % (type, name)
556                     type.dump(name)
557                     print '    Log::EndArg();'
558             print '    %sm_pInstance->%s(%s);' % (result, method.name, ', '.join([str(name) for type, name in method.args]))
559             for type, name in method.args:
560                 if type.isoutput():
561                     print '    Log::BeginArg("%s", "%s");' % (type, name)
562                     type.dump(name)
563                     print '    Log::EndArg();'
564                     type.wrap_instance(name)
565             if method.type is not Void:
566                 print '    Log::BeginReturn("%s");' % method.type
567                 method.type.dump("result")
568                 print '    Log::EndReturn();'
569                 method.type.wrap_instance('result')
570             print '    Log::EndCall();'
571             if method.name == 'QueryInterface':
572                 print '    if(*ppvObj == m_pInstance)'
573                 print '        *ppvObj = this;'
574             if method.name == 'Release':
575                 assert method.type is not Void
576                 print '    if(!result)'
577                 print '        delete this;'
578             if method.type is not Void:
579                 print '    return result;'
580             print '}'
581             print
582         print
583
584
585 class Method(Function):
586
587     def __init__(self, type, name, args):
588         Function.__init__(self, type, name, args, call = '__stdcall')
589
590
591 towrap = []
592
593 class WrapPointer(Pointer):
594
595     def __init__(self, type):
596         Pointer.__init__(self, type)
597         if type not in towrap:
598             towrap.append(type)
599
600     def wrap_instance(self, instance):
601         print "    if(%s)" % instance
602         print "        %s = new %s(%s);" % (instance, self.type.wrap_name(), instance)
603
604     def unwrap_instance(self, instance):
605         print "    if(%s)" % instance
606         print "        %s = static_cast<%s *>(%s)->m_pInstance;" % (instance, self.type.wrap_name(), instance)
607
608
609 class _String(Type):
610
611     def __init__(self):
612         Type.__init__(self, "char *")
613
614     def visit(self, visitor, *args, **kwargs):
615         return visitor.visit_literal(self, *args, **kwargs)
616
617     def dump(self, instance):
618         print '    Log::LiteralString((const char *)%s);' % instance
619
620 String = _String()
621
622
623 class _Opaque(Type):
624
625     def __init__(self):
626         Type.__init__(self, "void")
627
628     def visit(self, visitor, *args, **kwargs):
629         return visitor.visit_opaque(self, *args, **kwargs)
630
631     def dump(self, instance):
632         print '    Log::LiteralOpaque();'
633
634 Opaque = Pointer(_Opaque())
635
636
637 Bool = Literal("bool", "Bool")
638 SChar = Literal("signed char", "SInt")
639 UChar = Literal("unsigned char", "UInt")
640 Short = Literal("short", "SInt")
641 Int = Literal("int", "SInt")
642 Long = Literal("long", "SInt")
643 LongLong = Literal("long long", "SInt")
644 UShort = Literal("unsigned short", "UInt")
645 UInt = Literal("unsigned int", "UInt")
646 ULong = Literal("unsigned long", "UInt")
647 Float = Literal("float", "Float")
648 Double = Literal("double", "Float")
649 SizeT = Literal("size_t", "UInt")
650 WString = Literal("wchar_t *", "WString")
651
652
653 def wrap():
654     for type in all_types.itervalues():
655         type.decl()
656     print
657     for type in all_types.itervalues():
658         type.impl()
659     print
660     for type in towrap:
661         type.wrap_pre_decl()
662     print
663     for type in towrap:
664         type.wrap_decl()
665     print
666     for type in towrap:
667         type.wrap_impl()
668     print