]> git.cworth.org Git - apitrace/blob - base.py
Rudimentary support for D3D10.
[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 'static void Dump%s(const %s &value);' % (self.id, self.expr)
83     
84     def impl(self):
85         print 'static 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 Array(Type):
210
211     def __init__(self, type, length):
212         Type.__init__(self, type.expr + " *", 'P' + type.id)
213         self.type = type
214         self.length = length
215
216     def dump(self, instance):
217         index = '__i' + self.type.id
218         print '    for (int %s = 0; %s < %s; ++%s) {' % (index, index, self.length, index)
219         print '        Log::BeginElement("%s");' % (self.type,)
220         self.type.dump('(%s)[%s]' % (instance, index))
221         print '        Log::EndElement();'
222         print '    }'
223
224     def wrap_instance(self, instance):
225         self.type.wrap_instance("*" + instance)
226
227     def unwrap_instance(self, instance):
228         self.type.wrap_instance("*" + instance)
229
230
231 class Struct(Concrete):
232
233     def __init__(self, name, members):
234         Concrete.__init__(self, name)
235         self.members = members
236
237     def _dump(self, instance):
238         for type, name in self.members:
239             print '    Log::BeginElement("%s", "%s");' % (type, name)
240             type.dump('(%s).%s' % (instance, name))
241             print '    Log::EndElement();'
242
243
244 class Alias(Type):
245
246     def __init__(self, name, type):
247         Type.__init__(self, name)
248         self.type = type
249
250     def dump(self, instance):
251         self.type.dump(instance)
252
253
254 class Function:
255
256     def __init__(self, type, name, args, call = '__stdcall', fail = None):
257         self.type = type
258         self.name = name
259         self.args = args
260         self.call = call
261         self.fail = fail
262
263     def prototype(self, name=None):
264         if name is not None:
265             name = name.strip()
266         else:
267             name = self.name
268         s = name
269         if self.call:
270             s = self.call + ' ' + s
271         if name.startswith('*'):
272             s = '(' + s + ')'
273         s = self.type.expr + ' ' + s
274         s += "("
275         if self.args:
276             s += ", ".join(["%s %s" % (type, name) for type, name in self.args])
277         else:
278             s += "void"
279         s += ")"
280         return s
281
282     def pointer_type(self):
283         return 'P' + self.name
284
285     def pointer_value(self):
286         return 'p' + self.name
287
288     def wrap_decl(self):
289         ptype = self.pointer_type()
290         pvalue = self.pointer_value()
291         print 'typedef ' + self.prototype('* %s' % ptype) + ';'
292         print 'static %s %s = NULL;' % (ptype, pvalue)
293         print
294
295     def get_true_pointer(self):
296         raise NotImplementedError
297
298     def fail_impl(self):
299         if self.fail is not None:
300             if self.type is Void:
301                 assert self.fail == ''
302                 print '            return;' 
303             else:
304                 assert self.fail != ''
305                 print '            return %s;' % self.fail
306         else:
307             print '            ExitProcess(0);'
308
309     def wrap_impl(self):
310         pvalue = self.pointer_value()
311         print self.prototype() + ' {'
312         if self.type is Void:
313             result = ''
314         else:
315             print '    %s result;' % self.type
316             result = 'result = '
317         self.get_true_pointer()
318         print '    Log::BeginCall("%s");' % (self.name)
319         for type, name in self.args:
320             if not type.isoutput():
321                 type.unwrap_instance(name)
322                 print '    Log::BeginArg("%s", "%s");' % (type, name)
323                 type.dump(name)
324                 print '    Log::EndArg();'
325         print '    %s%s(%s);' % (result, pvalue, ', '.join([str(name) for type, name in self.args]))
326         for type, name in self.args:
327             if type.isoutput():
328                 print '    Log::BeginArg("%s", "%s");' % (type, name)
329                 type.dump(name)
330                 print '    Log::EndArg();'
331                 type.wrap_instance(name)
332         if self.type is not Void:
333             print '    Log::BeginReturn("%s");' % self.type
334             self.type.dump("result")
335             print '    Log::EndReturn();'
336             self.type.wrap_instance('result')
337         print '    Log::EndCall();'
338         self.post_call_impl()
339         if self.type is not Void:
340             print '    return result;'
341         print '}'
342         print
343
344     def post_call_impl(self):
345         pass
346
347
348 class Interface(Type):
349
350     def __init__(self, name, base=None):
351         Type.__init__(self, name)
352         self.name = name
353         self.base = base
354         self.methods = []
355
356     def itermethods(self):
357         if self.base is not None:
358             for method in self.base.itermethods():
359                 yield method
360         for method in self.methods:
361             yield method
362         raise StopIteration
363
364     def wrap_name(self):
365         return "Wrap" + self.expr
366
367     def wrap_pre_decl(self):
368         print "class %s;" % self.wrap_name()
369
370     def wrap_decl(self):
371         print "class %s : public %s " % (self.wrap_name(), self.name)
372         print "{"
373         print "public:"
374         print "    %s(%s * pInstance);" % (self.wrap_name(), self.name)
375         print "    virtual ~%s();" % self.wrap_name()
376         print
377         for method in self.itermethods():
378             print "    " + method.prototype() + ";"
379         print
380         #print "private:"
381         print "    %s * m_pInstance;" % (self.name,)
382         print "};"
383         print
384
385     def wrap_impl(self):
386         print '%s::%s(%s * pInstance) {' % (self.wrap_name(), self.wrap_name(), self.name)
387         print '    m_pInstance = pInstance;'
388         print '}'
389         print
390         print '%s::~%s() {' % (self.wrap_name(), self.wrap_name())
391         print '}'
392         print
393         for method in self.itermethods():
394             print method.prototype(self.wrap_name() + '::' + method.name) + ' {'
395             if method.type is Void:
396                 result = ''
397             else:
398                 print '    %s result;' % method.type
399                 result = 'result = '
400             print '    Log::BeginCall("%s");' % (self.name + '::' + method.name)
401             print '    Log::BeginArg("%s *", "this");' % self.name
402             print '    Log::BeginReference("%s", m_pInstance);' % self.name
403             print '    Log::EndReference();'
404             print '    Log::EndArg();'
405             for type, name in method.args:
406                 if not type.isoutput():
407                     type.unwrap_instance(name)
408                     print '    Log::BeginArg("%s", "%s");' % (type, name)
409                     type.dump(name)
410                     print '    Log::EndArg();'
411             print '    %sm_pInstance->%s(%s);' % (result, method.name, ', '.join([str(name) for type, name in method.args]))
412             for type, name in method.args:
413                 if type.isoutput():
414                     print '    Log::BeginArg("%s", "%s");' % (type, name)
415                     type.dump(name)
416                     print '    Log::EndArg();'
417                     type.wrap_instance(name)
418             if method.type is not Void:
419                 print '    Log::BeginReturn("%s");' % method.type
420                 method.type.dump("result")
421                 print '    Log::EndReturn();'
422                 method.type.wrap_instance('result')
423             print '    Log::EndCall();'
424             if method.name == 'QueryInterface':
425                 print '    if(*ppvObj == m_pInstance)'
426                 print '        *ppvObj = this;'
427             if method.name == 'Release':
428                 assert method.type is not Void
429                 print '    if(!result)'
430                 print '        delete this;'
431             if method.type is not Void:
432                 print '    return result;'
433             print '}'
434             print
435         print
436
437
438 class Method(Function):
439
440     def __init__(self, type, name, args):
441         Function.__init__(self, type, name, args)
442
443
444 towrap = []
445
446 class WrapPointer(Pointer):
447
448     def __init__(self, type):
449         Pointer.__init__(self, type)
450         if type not in towrap:
451             towrap.append(type)
452
453     def wrap_instance(self, instance):
454         print "    if(%s)" % instance
455         print "        %s = new %s(%s);" % (instance, self.type.wrap_name(), instance)
456
457     def unwrap_instance(self, instance):
458         print "    if(%s)" % instance
459         print "        %s = static_cast<%s *>(%s)->m_pInstance;" % (instance, self.type.wrap_name(), instance)
460
461
462 class _String(Type):
463
464     def __init__(self):
465         Type.__init__(self, "char *")
466
467     def dump(self, instance):
468         print '    Log::DumpString((const char *)%s);' % instance
469
470 String = _String()
471
472 class _WString(Type):
473
474     def __init__(self):
475         Type.__init__(self, "wchar_t *")
476
477     def dump(self, instance):
478         print '    Log::DumpWString(%s);' % instance
479
480 WString = _WString()
481
482
483 SChar = Intrinsic("signed char", "%i")
484 UChar = Intrinsic("unsigned char", "%u")
485 Short = Intrinsic("short", "%i")
486 Int = Intrinsic("int", "%i")
487 Long = Intrinsic("long", "%li")
488 UShort = Intrinsic("unsigned short", "%u")
489 UInt = Intrinsic("unsigned int", "%u")
490 ULong = Intrinsic("unsigned long", "%lu")
491 Float = Intrinsic("float", "%f")
492 Double = Intrinsic("double", "%f")
493 SizeT = Intrinsic("size_t", "%lu")
494
495
496 def wrap():
497     for type in all_types.itervalues():
498         type.decl()
499     print
500     for type in all_types.itervalues():
501         type.impl()
502     print
503     for type in towrap:
504         type.wrap_pre_decl()
505     print
506     for type in towrap:
507         type.wrap_decl()
508     print
509     for type in towrap:
510         type.wrap_impl()
511     print