]> git.cworth.org Git - apitrace/blob - base.py
Dump wchar_t strings correctly.
[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             assert self.type is not Void
293             print '            return %s;' % self.fail
294         else:
295             print '            ExitProcess(0);'
296
297     def wrap_impl(self):
298         pvalue = self.pointer_value()
299         print self.prototype() + ' {'
300         if self.type is Void:
301             result = ''
302         else:
303             print '    %s result;' % self.type
304             result = 'result = '
305         self.get_true_pointer()
306         print '    Log::BeginCall("%s");' % (self.name)
307         for type, name in self.args:
308             if not type.isoutput():
309                 type.unwrap_instance(name)
310                 print '    Log::BeginArg("%s", "%s");' % (type, name)
311                 type.dump(name)
312                 print '    Log::EndArg();'
313         print '    %s%s(%s);' % (result, pvalue, ', '.join([str(name) for type, name in self.args]))
314         for type, name in self.args:
315             if type.isoutput():
316                 print '    Log::BeginArg("%s", "%s");' % (type, name)
317                 type.dump(name)
318                 print '    Log::EndArg();'
319                 type.wrap_instance(name)
320         if self.type is not Void:
321             print '    Log::BeginReturn("%s");' % self.type
322             self.type.dump("result")
323             print '    Log::EndReturn();'
324             self.type.wrap_instance('result')
325         print '    Log::EndCall();'
326         self.post_call_impl()
327         if self.type is not Void:
328             print '    return result;'
329         print '}'
330         print
331
332     def post_call_impl(self):
333         pass
334
335
336 class Interface(Type):
337
338     def __init__(self, name, base=None):
339         Type.__init__(self, name)
340         self.base = base
341         self.methods = []
342
343     def itermethods(self):
344         if self.base is not None:
345             for method in self.base.itermethods():
346                 yield method
347         for method in self.methods:
348             yield method
349         raise StopIteration
350
351     def wrap_name(self):
352         return "Wrap" + self.name
353
354     def wrap_pre_decl(self):
355         print "class %s;" % self.wrap_name()
356
357     def wrap_decl(self):
358         print "class %s : public %s " % (self.wrap_name(), self.name)
359         print "{"
360         print "public:"
361         print "    %s(%s * pInstance);" % (self.wrap_name(), self.name)
362         print "    virtual ~%s();" % self.wrap_name()
363         print
364         for method in self.itermethods():
365             print "    " + method.prototype() + ";"
366         print
367         #print "private:"
368         print "    %s * m_pInstance;" % (self.name,)
369         print "};"
370         print
371
372     def wrap_impl(self):
373         print '%s::%s(%s * pInstance) {' % (self.wrap_name(), self.wrap_name(), self.name)
374         print '    m_pInstance = pInstance;'
375         print '}'
376         print
377         print '%s::~%s() {' % (self.wrap_name(), self.wrap_name())
378         print '}'
379         print
380         for method in self.itermethods():
381             print method.prototype(self.wrap_name() + '::' + method.name) + ' {'
382             if method.type is Void:
383                 result = ''
384             else:
385                 print '    %s result;' % method.type
386                 result = 'result = '
387             print '    Log::BeginCall("%s");' % (self.name + '::' + method.name)
388             print '    Log::BeginArg("%s *", "this");' % self.name
389             print '    Log::BeginReference("%s", m_pInstance);' % self.name
390             print '    Log::EndReference();'
391             print '    Log::EndArg();'
392             for type, name in method.args:
393                 if not type.isoutput():
394                     type.unwrap_instance(name)
395                     print '    Log::BeginArg("%s", "%s");' % (type, name)
396                     type.dump(name)
397                     print '    Log::EndArg();'
398             print '    %sm_pInstance->%s(%s);' % (result, method.name, ', '.join([str(name) for type, name in method.args]))
399             for type, name in method.args:
400                 if type.isoutput():
401                     print '    Log::BeginArg("%s", "%s");' % (type, name)
402                     type.dump(name)
403                     print '    Log::EndArg();'
404                     type.wrap_instance(name)
405             if method.type is not Void:
406                 print '    Log::BeginReturn("%s");' % method.type
407                 method.type.dump("result")
408                 print '    Log::EndReturn();'
409                 method.type.wrap_instance('result')
410             print '    Log::EndCall();'
411             if method.name == 'QueryInterface':
412                 print '    if(*ppvObj == m_pInstance)'
413                 print '        *ppvObj = this;'
414             if method.name == 'Release':
415                 assert method.type is not Void
416                 print '    if(!result)'
417                 print '        delete this;'
418             if method.type is not Void:
419                 print '    return result;'
420             print '}'
421             print
422         print
423
424
425 class Method(Function):
426
427     def __init__(self, type, name, args):
428         Function.__init__(self, type, name, args)
429
430
431 towrap = []
432
433 class WrapPointer(Pointer):
434
435     def __init__(self, type):
436         Pointer.__init__(self, type)
437         if type not in towrap:
438             towrap.append(type)
439
440     def wrap_instance(self, instance):
441         print "    if(%s)" % instance
442         print "        %s = new %s(%s);" % (instance, self.type.wrap_name(), instance)
443
444     def unwrap_instance(self, instance):
445         print "    if(%s)" % instance
446         print "        %s = static_cast<%s *>(%s)->m_pInstance;" % (instance, self.type.wrap_name(), instance)
447
448
449 class _String(Type):
450
451     def __init__(self):
452         Type.__init__(self, "String")
453
454     def __str__(self):
455         return "const char *"
456
457     def dump(self, instance):
458         print '    Log::DumpString((const char *)%s);' % instance
459
460 String = _String()
461
462 class _WString(Type):
463
464     def __init__(self):
465         Type.__init__(self, "WString")
466
467     def __str__(self):
468         return "const wchar_t *"
469
470     def dump(self, instance):
471         print '    Log::DumpWString(%s);' % instance
472
473 WString = _WString()
474
475
476 SChar = Intrinsic("signed char", "%i")
477 UChar = Intrinsic("unsigned char", "%u")
478 Short = Intrinsic("short", "%i")
479 Int = Intrinsic("int", "%i")
480 Long = Intrinsic("long", "%li")
481 UShort = Intrinsic("unsigned short", "%u")
482 UInt = Intrinsic("unsigned int", "%u")
483 ULong = Intrinsic("unsigned long", "%lu")
484 Float = Intrinsic("float", "%f")
485 Double = Intrinsic("double", "%f")
486
487
488 def wrap():
489     for type in all_types.itervalues():
490         type.decl()
491     print
492     for type in all_types.itervalues():
493         type.impl()
494     print
495     for type in towrap:
496         type.wrap_pre_decl()
497     print
498     for type in towrap:
499         type.wrap_decl()
500     print
501     for type in towrap:
502         type.wrap_impl()
503     print