]> git.notmuchmail.org Git - apitrace/blob - base.py
24641bc16aefb4648ed90d3832bbe9190c9f89a3
[apitrace] / base.py
1 #############################################################################
2 #
3 # Copyright 2008 Tungsten Graphics, Inc.
4 #
5 # This program is free software: you can redistribute it and/or modify it
6 # under the terms of the GNU Lesser General Public License as published
7 # by the Free Software Foundation, either version 3 of the License, or
8 # (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU Lesser General Public License for more details.
14 #
15 # You should have received a copy of the GNU Lesser General Public License
16 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 #
18 #############################################################################
19
20 """C basic types"""
21
22
23 import debug
24
25
26 all_types = {}
27
28 class Type:
29
30     def __init__(self, name):
31         self.name = name
32
33     def __str__(self):
34         return self.name
35
36     def identifier(self):
37         return self.name.replace(' ', '_')
38
39     def isoutput(self):
40         return False
41
42     def decl(self):
43         pass
44
45     def impl(self):
46         pass
47
48     def dump(self, instance):
49         raise NotImplementedError
50     
51     def wrap_instance(self, instance):
52         pass 
53
54     def unwrap_instance(self, instance):
55         pass
56
57
58 class _Void(Type):
59
60     def __init__(self):
61         Type.__init__(self, "void")
62
63 Void = _Void()
64
65
66 class Concrete(Type):
67
68     def __init__(self, name):
69         for char in name:
70             assert char.isalnum() or char in '_ '
71
72         Type.__init__(self, name)
73         
74         assert self.name not in all_types
75         if self.name not in all_types:
76             all_types[self.name] = self
77
78     def decl(self):
79         print 'void Dump%s(const %s &value);' % (self.identifier(), str(self))
80     
81     def impl(self):
82         print 'void Dump%s(const %s &value) {' % (self.identifier(), str(self))
83         self._dump("value");
84         print '}'
85         print
86     
87     def _dump(self, instance):
88         raise NotImplementedError
89     
90     def dump(self, instance):
91         print '    Dump%s(%s);' % (self.identifier(), instance)
92     
93
94 class Intrinsic(Concrete):
95
96     def __init__(self, expr, format, name = None):
97         if name is None:
98             name = expr
99         Concrete.__init__(self, name)
100         self.expr = expr
101         self.format = format
102
103     def _dump(self, instance):
104         print '    Log::TextF("%s", %s);' % (self.format, instance)
105         
106     def __str__(self):
107         return self.expr
108
109
110 class Const(Type):
111
112     def __init__(self, type):
113         Type.__init__(self, 'C' + type.name)
114         self.type = type
115
116     def dump(self, instance):
117         self.type.dump(instance)
118
119     def __str__(self):
120         return "const " + str(self.type)
121
122
123 class Pointer(Type):
124
125     def __init__(self, type):
126         Type.__init__(self, 'P' + type.name)
127         self.type = type
128
129     def __str__(self):
130         return str(self.type) + " *"
131     
132     def dump(self, instance):
133         print '    if(%s) {' % instance
134         print '        Log::BeginReference("%s", %s);' % (self.type, instance)
135         try:
136             self.type.dump("*" + instance)
137         except NotImplementedError:
138             pass
139         print '        Log::EndReference();'
140         print '    }'
141         print '    else'
142         print '        Log::Text("NULL");'
143
144     def wrap_instance(self, instance):
145         self.type.wrap_instance("*" + instance)
146
147     def unwrap_instance(self, instance):
148         self.type.wrap_instance("*" + instance)
149
150
151 def ConstPointer(type):
152     return Pointer(Const(type))
153
154
155 class OutPointer(Pointer):
156
157     def isoutput(self):
158         return True
159
160
161 class Enum(Concrete):
162
163     def __init__(self, name, values):
164         Concrete.__init__(self, name)
165         self.values = values
166     
167     def _dump(self, instance):
168         print '    switch(%s) {' % instance
169         for value in self.values:
170             print '    case %s:' % value
171             print '        Log::Text("%s");' % value
172             print '        break;'
173         print '    default:'
174         print '        Log::TextF("%%i", %s);' % instance
175         print '        break;'
176         print '    }'
177
178
179 class FakeEnum(Enum):
180
181     __seq = 0
182     
183     def __init__(self, type, values):
184         FakeEnum.__seq += 1
185         Enum.__init__(self, type.name + str(FakeEnum.__seq), values)
186         self.type = type
187     
188     def __str__(self):
189         return str(self.type)
190
191
192 class Flags(Concrete):
193
194     __seq = 0
195     
196     def __init__(self, type, values):
197         Flags.__seq += 1
198         Concrete.__init__(self, type.name + str(Flags.__seq))
199         self.type = type
200         self.values = values
201
202     def __str__(self):
203         return str(self.type)
204     
205     def _dump(self, instance):
206         print '    bool l_First = TRUE;'
207         print '    %s l_Value = %s;' % (self.type, instance)
208         for value in self.values:
209             print '    if((l_Value & %s) == %s) {' % (value, value)
210             print '        if(!l_First)'
211             print '            Log::Text(" | ");'
212             print '        Log::Text("%s");' % value
213             print '        l_Value &= ~%s;' % value
214             print '        l_First = FALSE;'
215             print '    }'
216         print '    if(l_Value || l_First) {'
217         print '        if(!l_First)'
218         print '            Log::Text(" | ");'
219         self.type.dump("l_Value");
220         print '    }'
221
222
223 class Struct(Concrete):
224
225     def __init__(self, name, members):
226         Concrete.__init__(self, name)
227         self.members = members
228
229     def _dump(self, instance):
230         for type, name in self.members:
231             print '    Log::BeginElement("%s", "%s");' % (type, name)
232             type.dump('(%s).%s' % (instance, name))
233             print '    Log::EndElement();'
234
235
236 class Alias(Type):
237
238     def __init__(self, name, type):
239         Type.__init__(self, name)
240         self.type = type
241
242     def dump(self, instance):
243         self.type.dump(instance)
244
245
246 class Function:
247
248     def __init__(self, type, name, args, call = '__stdcall', fail = None):
249         self.type = type
250         self.name = name
251         self.args = args
252         self.call = call
253         self.fail = fail
254
255     def prototype(self, name=None):
256         if name is not None:
257             name = name.strip()
258         else:
259             name = self.name
260         s = name
261         if self.call:
262             s = self.call + ' ' + s
263         if name.startswith('*'):
264             s = '(' + s + ')'
265         s = str(self.type) + ' ' + s
266         s += "("
267         if self.args:
268             s += ", ".join(["%s %s" % (type, name) for type, name in self.args])
269         else:
270             s += "void"
271         s += ")"
272         return s
273
274     def pointer_type(self):
275         return 'P' + self.name
276
277     def pointer_value(self):
278         return 'p' + self.name
279
280     def wrap_decl(self):
281         ptype = self.pointer_type()
282         pvalue = self.pointer_value()
283         print 'typedef ' + self.prototype('* %s' % ptype) + ';'
284         print 'static %s %s = NULL;' % (ptype, pvalue)
285         print
286
287     def get_true_pointer(self):
288         raise NotImplementedError
289
290     def fail_impl(self):
291         if self.fail is not None:
292             if self.type is Void:
293                 assert self.fail == ''
294                 print '            return;' 
295             else:
296                 assert self.fail != ''
297                 print '            return %s;' % self.fail
298         else:
299             print '            ExitProcess(0);'
300
301     def wrap_impl(self):
302         pvalue = self.pointer_value()
303         print self.prototype() + ' {'
304         if self.type is Void:
305             result = ''
306         else:
307             print '    %s result;' % self.type
308             result = 'result = '
309         self.get_true_pointer()
310         print '    Log::BeginCall("%s");' % (self.name)
311         for type, name in self.args:
312             if not type.isoutput():
313                 type.unwrap_instance(name)
314                 print '    Log::BeginArg("%s", "%s");' % (type, name)
315                 type.dump(name)
316                 print '    Log::EndArg();'
317         print '    %s%s(%s);' % (result, pvalue, ', '.join([str(name) for type, name in self.args]))
318         for type, name in self.args:
319             if type.isoutput():
320                 print '    Log::BeginArg("%s", "%s");' % (type, name)
321                 type.dump(name)
322                 print '    Log::EndArg();'
323                 type.wrap_instance(name)
324         if self.type is not Void:
325             print '    Log::BeginReturn("%s");' % self.type
326             self.type.dump("result")
327             print '    Log::EndReturn();'
328             self.type.wrap_instance('result')
329         print '    Log::EndCall();'
330         self.post_call_impl()
331         if self.type is not Void:
332             print '    return result;'
333         print '}'
334         print
335
336     def post_call_impl(self):
337         pass
338
339
340 class Interface(Type):
341
342     def __init__(self, name, base=None):
343         Type.__init__(self, name)
344         self.base = base
345         self.methods = []
346
347     def itermethods(self):
348         if self.base is not None:
349             for method in self.base.itermethods():
350                 yield method
351         for method in self.methods:
352             yield method
353         raise StopIteration
354
355     def wrap_name(self):
356         return "Wrap" + self.name
357
358     def wrap_pre_decl(self):
359         print "class %s;" % self.wrap_name()
360
361     def wrap_decl(self):
362         print "class %s : public %s " % (self.wrap_name(), self.name)
363         print "{"
364         print "public:"
365         print "    %s(%s * pInstance);" % (self.wrap_name(), self.name)
366         print "    virtual ~%s();" % self.wrap_name()
367         print
368         for method in self.itermethods():
369             print "    " + method.prototype() + ";"
370         print
371         #print "private:"
372         print "    %s * m_pInstance;" % (self.name,)
373         print "};"
374         print
375
376     def wrap_impl(self):
377         print '%s::%s(%s * pInstance) {' % (self.wrap_name(), self.wrap_name(), self.name)
378         print '    m_pInstance = pInstance;'
379         print '}'
380         print
381         print '%s::~%s() {' % (self.wrap_name(), self.wrap_name())
382         print '}'
383         print
384         for method in self.itermethods():
385             print method.prototype(self.wrap_name() + '::' + method.name) + ' {'
386             if method.type is Void:
387                 result = ''
388             else:
389                 print '    %s result;' % method.type
390                 result = 'result = '
391             print '    Log::BeginCall("%s");' % (self.name + '::' + method.name)
392             print '    Log::BeginArg("%s *", "this");' % self.name
393             print '    Log::BeginReference("%s", m_pInstance);' % self.name
394             print '    Log::EndReference();'
395             print '    Log::EndArg();'
396             for type, name in method.args:
397                 if not type.isoutput():
398                     type.unwrap_instance(name)
399                     print '    Log::BeginArg("%s", "%s");' % (type, name)
400                     type.dump(name)
401                     print '    Log::EndArg();'
402             print '    %sm_pInstance->%s(%s);' % (result, method.name, ', '.join([str(name) for type, name in method.args]))
403             for type, name in method.args:
404                 if type.isoutput():
405                     print '    Log::BeginArg("%s", "%s");' % (type, name)
406                     type.dump(name)
407                     print '    Log::EndArg();'
408                     type.wrap_instance(name)
409             if method.type is not Void:
410                 print '    Log::BeginReturn("%s");' % method.type
411                 method.type.dump("result")
412                 print '    Log::EndReturn();'
413                 method.type.wrap_instance('result')
414             print '    Log::EndCall();'
415             if method.name == 'QueryInterface':
416                 print '    if(*ppvObj == m_pInstance)'
417                 print '        *ppvObj = this;'
418             if method.name == 'Release':
419                 assert method.type is not Void
420                 print '    if(!result)'
421                 print '        delete this;'
422             if method.type is not Void:
423                 print '    return result;'
424             print '}'
425             print
426         print
427
428
429 class Method(Function):
430
431     def __init__(self, type, name, args):
432         Function.__init__(self, type, name, args)
433
434
435 towrap = []
436
437 class WrapPointer(Pointer):
438
439     def __init__(self, type):
440         Pointer.__init__(self, type)
441         if type not in towrap:
442             towrap.append(type)
443
444     def wrap_instance(self, instance):
445         print "    if(%s)" % instance
446         print "        %s = new %s(%s);" % (instance, self.type.wrap_name(), instance)
447
448     def unwrap_instance(self, instance):
449         print "    if(%s)" % instance
450         print "        %s = static_cast<%s *>(%s)->m_pInstance;" % (instance, self.type.wrap_name(), instance)
451
452
453 class _String(Type):
454
455     def __init__(self):
456         Type.__init__(self, "String")
457
458     def __str__(self):
459         return "const char *"
460
461     def dump(self, instance):
462         print '    Log::DumpString((const char *)%s);' % instance
463
464 String = _String()
465
466 class _WString(Type):
467
468     def __init__(self):
469         Type.__init__(self, "WString")
470
471     def __str__(self):
472         return "const wchar_t *"
473
474     def dump(self, instance):
475         print '    Log::DumpWString(%s);' % instance
476
477 WString = _WString()
478
479
480 SChar = Intrinsic("signed char", "%i")
481 UChar = Intrinsic("unsigned char", "%u")
482 Short = Intrinsic("short", "%i")
483 Int = Intrinsic("int", "%i")
484 Long = Intrinsic("long", "%li")
485 UShort = Intrinsic("unsigned short", "%u")
486 UInt = Intrinsic("unsigned int", "%u")
487 ULong = Intrinsic("unsigned long", "%lu")
488 Float = Intrinsic("float", "%f")
489 Double = Intrinsic("double", "%f")
490
491
492 def wrap():
493     for type in all_types.itervalues():
494         type.decl()
495     print
496     for type in all_types.itervalues():
497         type.impl()
498     print
499     for type in towrap:
500         type.wrap_pre_decl()
501     print
502     for type in towrap:
503         type.wrap_decl()
504     print
505     for type in towrap:
506         type.wrap_impl()
507     print