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