X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=base.py;h=8213403aafccc37043aedac98f4e9410cd0df9eb;hb=dce84c4cbc8176d627c5e7801c2acbd0e2027b86;hp=40f98998ebc95b44a597a0378da6df52a737cbdf;hpb=954424450b9a4dd44c9ebf3f4f8c35eb41d50fd5;p=apitrace diff --git a/base.py b/base.py index 40f9899..8213403 100644 --- a/base.py +++ b/base.py @@ -1,168 +1,363 @@ -############################################################################# +########################################################################## # -# Copyright 2008 Jose Fonseca +# Copyright 2008-2009 VMware, Inc. +# All Rights Reserved. # -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published -# by the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: # -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. # -# You should have received a copy of the GNU Lesser General Public License -# along with this program. If not, see . +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. # -############################################################################# +##########################################################################/ """C basic types""" + +import debug + + +all_types = {} + + +class Visitor: + + def visit(self, type, *args, **kwargs): + return type.visit(self, *args, **kwargs) + + def visit_void(self, void, *args, **kwargs): + raise NotImplementedError + + def visit_literal(self, literal, *args, **kwargs): + raise NotImplementedError + + def visit_string(self, string, *args, **kwargs): + raise NotImplementedError + + def visit_const(self, const, *args, **kwargs): + raise NotImplementedError + + def visit_struct(self, struct, *args, **kwargs): + raise NotImplementedError + + def visit_array(self, array, *args, **kwargs): + raise NotImplementedError + + def visit_blob(self, blob, *args, **kwargs): + raise NotImplementedError + + def visit_enum(self, enum, *args, **kwargs): + raise NotImplementedError + + def visit_bitmask(self, bitmask, *args, **kwargs): + raise NotImplementedError + + def visit_pointer(self, pointer, *args, **kwargs): + raise NotImplementedError + + def visit_handle(self, handle, *args, **kwargs): + raise NotImplementedError + + def visit_alias(self, alias, *args, **kwargs): + raise NotImplementedError + + def visit_opaque(self, opaque, *args, **kwargs): + raise NotImplementedError + + def visit_interface(self, interface, *args, **kwargs): + raise NotImplementedError + + +class OnceVisitor(Visitor): + + def __init__(self): + self.__visited = set() + + def visit(self, type, *args, **kwargs): + if type not in self.__visited: + self.__visited.add(type) + return type.visit(self, *args, **kwargs) + return None + + +class Rebuilder(Visitor): + + def visit_void(self, void): + return void + + def visit_literal(self, literal): + return literal + + def visit_string(self, string): + return string + + def visit_const(self, const): + return Const(const.type) + + def visit_struct(self, struct): + members = [self.visit(member) for member in struct.members] + return Struct(struct.name, members) + + def visit_array(self, array): + type = self.visit(array.type) + return Array(type, array.length) + + def visit_blob(self, blob): + type = self.visit(blob.type) + return Blob(type, blob.size) + + def visit_enum(self, enum): + return enum + + def visit_bitmask(self, bitmask): + type = self.visit(bitmask.type) + return Bitmask(type, bitmask.values) + + def visit_pointer(self, pointer): + type = self.visit(pointer.type) + return Pointer(type) + + def visit_handle(self, handle): + type = self.visit(handle.type) + return Handle(handle.name, type) + + def visit_alias(self, alias): + type = self.visit(alias.type) + return Alias(alias.expr, type) + + def visit_opaque(self, opaque): + return opaque + + class Type: - def __init__(self, name): - self.name = name + __seq = 0 - def __str__(self): - return self.name + def __init__(self, expr, id = ''): + self.expr = expr + + for char in id: + assert char.isalnum() or char in '_ ' - def isoutput(self): - return False + id = id.replace(' ', '_') + + if id in all_types: + Type.__seq += 1 + id += str(Type.__seq) + + assert id not in all_types + all_types[id] = self - def dump(self, instance): + self.id = id + + def __str__(self): + return self.expr + + def visit(self, visitor, *args, **kwargs): raise NotImplementedError - - def wrap_instance(self, instance): - pass - def unwrap_instance(self, instance): - pass -class Void(Type): +class _Void(Type): def __init__(self): Type.__init__(self, "void") -Void = Void() + def visit(self, visitor, *args, **kwargs): + return visitor.visit_void(self, *args, **kwargs) +Void = _Void() -class Intrinsic(Type): - def __init__(self, name, format): - Type.__init__(self, name) - self.format = format +class Concrete(Type): + def decl(self): + print 'static void Dump%s(const %s &value);' % (self.id, self.expr) + + def impl(self): + print 'static void Dump%s(const %s &value) {' % (self.id, self.expr) + self._dump("value"); + print '}' + print + + def _dump(self, instance): + raise NotImplementedError + def dump(self, instance): - print ' g_pLog->TextF("%s", %s);' % (self.format, instance) + print ' Dump%s(%s);' % (self.id, instance) + + +class Literal(Type): + + def __init__(self, expr, format, base=10): + Type.__init__(self, expr) + self.format = format + + def visit(self, visitor, *args, **kwargs): + return visitor.visit_literal(self, *args, **kwargs) class Const(Type): def __init__(self, type): - Type.__init__(self, 'C' + type.name) - self.type = type - def dump(self, instance): - self.type.dump(instance) + if type.expr.startswith("const "): + expr = type.expr + " const" + else: + expr = "const " + type.expr - def __str__(self): - return "const " + str(self.type) + Type.__init__(self, expr, 'C' + type.id) + + self.type = type + + def visit(self, visitor, *args, **kwargs): + return visitor.visit_const(self, *args, **kwargs) class Pointer(Type): def __init__(self, type): - Type.__init__(self, 'P' + type.name) + Type.__init__(self, type.expr + " *", 'P' + type.id) self.type = type - def __str__(self): - return str(self.type) + " *" - - def dump(self, instance): - print ' if(%s) {' % instance - try: - self.type.dump("*" + instance) - except NotImplementedError: - print ' g_pLog->TextF("%%p", %s);' % instance - print ' }' - print ' else' - print ' g_pLog->Text("NULL");' + def visit(self, visitor, *args, **kwargs): + return visitor.visit_pointer(self, *args, **kwargs) + - def wrap_instance(self, instance): - self.type.wrap_instance("*" + instance) +class Handle(Type): - def unwrap_instance(self, instance): - self.type.wrap_instance("*" + instance) + def __init__(self, name, type): + Type.__init__(self, type.expr, 'P' + type.id) + self.name = name + self.type = type + def visit(self, visitor, *args, **kwargs): + return visitor.visit_handle(self, *args, **kwargs) -class OutPointer(Pointer): - def isoutput(self): - return True +def ConstPointer(type): + return Pointer(Const(type)) -class Enum(Type): +class Enum(Concrete): def __init__(self, name, values): - Type.__init__(self, name) + Concrete.__init__(self, name) self.values = values - def dump(self, instance): - print ' switch(%s) {' % instance - for value in self.values: - print ' case %s:' % value - print ' g_pLog->Text("%s");' % value - print ' break;' - print ' default:' - print ' g_pLog->TextF("%%i", %s);' % instance - print ' break;' - print ' }' + def visit(self, visitor, *args, **kwargs): + return visitor.visit_enum(self, *args, **kwargs) + +def FakeEnum(type, values): + return Enum(type.expr, values) -class Flags(Type): + +class Bitmask(Concrete): def __init__(self, type, values): - Type.__init__(self, type.name) + Concrete.__init__(self, type.expr) + self.type = type self.values = values + def visit(self, visitor, *args, **kwargs): + return visitor.visit_bitmask(self, *args, **kwargs) + +Flags = Bitmask + + +class Array(Type): + + def __init__(self, type, length): + Type.__init__(self, type.expr + " *") + self.type = type + self.length = length + + def visit(self, visitor, *args, **kwargs): + return visitor.visit_array(self, *args, **kwargs) + -class Struct(Type): +class Blob(Type): + + def __init__(self, type, size): + Type.__init__(self, type.expr + ' *') + self.type = type + self.size = size + + def visit(self, visitor, *args, **kwargs): + return visitor.visit_blob(self, *args, **kwargs) + + +class Struct(Concrete): def __init__(self, name, members): - Type.__init__(self, name) + Concrete.__init__(self, name) + self.name = name self.members = members - def dump(self, instance): - print ' g_pLog->Text("{");' - first = True - for type, name in self.members: - if first: - first = False - else: - print ' g_pLog->Text(", ");' - type.dump('(%s).%s' % (instance, name)) - print ' g_pLog->Text("}");' + def visit(self, visitor, *args, **kwargs): + return visitor.visit_struct(self, *args, **kwargs) class Alias(Type): - def __init__(self, name, type): - Type.__init__(self, name) + def __init__(self, expr, type): + Type.__init__(self, expr) self.type = type - def dump(self, instance): - self.type.dump(instance) + def visit(self, visitor, *args, **kwargs): + return visitor.visit_alias(self, *args, **kwargs) + + +def Out(type, name): + arg = Arg(type, name, output=True) + return arg + + +class Arg: + + def __init__(self, type, name, output=False): + self.type = type + self.name = name + self.output = output + self.index = None + + def __str__(self): + return '%s %s' % (self.type, self.name) class Function: - def __init__(self, type, name, args, call = '__stdcall'): + def __init__(self, type, name, args, call = '', fail = None, sideeffects=True, hidden=False): self.type = type self.name = name - self.args = args + + self.args = [] + index = 0 + for arg in args: + if isinstance(arg, tuple): + arg_type, arg_name = arg + arg = Arg(arg_type, arg_name) + arg.index = index + index += 1 + self.args.append(arg) + self.call = call + self.fail = fail + self.sideeffects = sideeffects + self.hidden = False def prototype(self, name=None): if name is not None: @@ -174,20 +369,31 @@ class Function: s = self.call + ' ' + s if name.startswith('*'): s = '(' + s + ')' - s = str(self.type) + ' ' + s + s = self.type.expr + ' ' + s s += "(" if self.args: - s += ", ".join(["%s %s" % (type, name) for type, name in self.args]) + s += ", ".join(["%s %s" % (arg.type, arg.name) for arg in self.args]) else: s += "void" s += ")" return s +def StdFunction(*args, **kwargs): + kwargs.setdefault('call', 'GLAPIENTRY') + return Function(*args, **kwargs) + + +def FunctionPointer(type, name, args, **kwargs): + # XXX + return Opaque(name) + + class Interface(Type): def __init__(self, name, base=None): Type.__init__(self, name) + self.name = name self.base = base self.methods = [] @@ -199,115 +405,153 @@ class Interface(Type): yield method raise StopIteration - def wrap_name(self): - return "Wrap" + self.name - def wrap_pre_decl(self): - print "class %s;" % self.wrap_name() +class Method(Function): - def wrap_decl(self): - print "class %s : public %s " % (self.wrap_name(), self.name) - print "{" - print "public:" - print " %s(%s * pInstance);" % (self.wrap_name(), self.name) - print " virtual ~%s();" % self.wrap_name() - print - for method in self.itermethods(): - print " " + method.prototype() + ";" - print - #print "private:" - print " %s * m_pInstance;" % (self.name,) - print "};" - print + def __init__(self, type, name, args): + Function.__init__(self, type, name, args, call = '__stdcall') - def wrap_impl(self): - print '%s::%s(%s * pInstance) {' % (self.wrap_name(), self.wrap_name(), self.name) - print ' m_pInstance = pInstance;' - print '}' - print - print '%s::~%s() {' % (self.wrap_name(), self.wrap_name()) - print '}' - print - for method in self.itermethods(): - print method.prototype(self.wrap_name() + '::' + method.name) + ' {' - if method.type is Void: - result = '' - else: - print ' %s result;' % method.type - result = 'result = ' - print ' g_pLog->BeginCall("%s");' % (self.name + '::' + method.name) - print ' g_pLog->BeginParam("this", "%s *");' % self.name - print ' g_pLog->TextF("%p", m_pInstance);' - print ' g_pLog->EndParam();' - for type, name in method.args: - if not type.isoutput(): - type.unwrap_instance(name) - print ' g_pLog->BeginParam("%s", "%s");' % (name, type) - type.dump(name) - print ' g_pLog->EndParam();' - print ' %sm_pInstance->%s(%s);' % (result, method.name, ', '.join([str(name) for type, name in method.args])) - for type, name in method.args: - if type.isoutput(): - print ' g_pLog->BeginParam("%s", "%s");' % (name, type) - type.dump(name) - print ' g_pLog->EndParam();' - type.wrap_instance(name) - if method.type is not Void: - print ' g_pLog->BeginReturn("%s");' % method.type - method.type.dump("result") - print ' g_pLog->EndReturn();' - method.type.wrap_instance('result') - print ' g_pLog->EndCall();' - if method.name == 'QueryInterface': - print ' if(*ppvObj == m_pInstance)' - print ' *ppvObj = this;' - if method.name == 'Release': - assert method.type is not Void - print ' if(!result)' - print ' delete this;' - if method.type is not Void: - print ' return result;' - print '}' - print - print +towrap = [] -class Method(Function): - def __init__(self, type, name, args): - Function.__init__(self, type, name, args) +def WrapPointer(type): + return Pointer(type) -towrap = [] +class String(Type): -class WrapPointer(Pointer): + def __init__(self, expr = "char *", length = None): + Type.__init__(self, expr) + self.length = length + + def visit(self, visitor, *args, **kwargs): + return visitor.visit_string(self, *args, **kwargs) + +CString = String() + + +class Opaque(Type): + '''Opaque pointer.''' + + def __init__(self, expr): + Type.__init__(self, expr) + + def visit(self, visitor, *args, **kwargs): + return visitor.visit_opaque(self, *args, **kwargs) + + +def OpaquePointer(type): + return Opaque(type.expr + ' *') + + +class Collector(Visitor): + '''Collect.''' + + def __init__(self): + self.__visited = set() + self.types = [] + + def visit(self, type): + if type in self.__visited: + return + self.__visited.add(type) + Visitor.visit(self, type) + self.types.append(type) + + def visit_void(self, literal): + pass + + def visit_literal(self, literal): + pass + + def visit_string(self, string): + pass + + def visit_const(self, const): + self.visit(const.type) + + def visit_struct(self, struct): + for type, name in struct.members: + self.visit(type) + + def visit_array(self, array): + self.visit(array.type) + + def visit_blob(self, array): + pass + + def visit_enum(self, enum): + pass + + def visit_bitmask(self, bitmask): + self.visit(bitmask.type) + + def visit_pointer(self, pointer): + self.visit(pointer.type) + + def visit_handle(self, handle): + self.visit(handle.type) + + def visit_alias(self, alias): + self.visit(alias.type) + + def visit_opaque(self, opaque): + pass + + def visit_interface(self, interface): + pass + + +class API: + + def __init__(self, name): + self.name = name + self.headers = [] + self.functions = [] + self.interfaces = [] + + def all_types(self): + collector = Collector() + for function in self.functions: + for arg in function.args: + collector.visit(arg.type) + collector.visit(function.type) + for interface in self.interfaces: + collector.visit(interface) + for method in interface.methods: + for arg in method.args: + collector.visit(arg.type) + collector.visit(method.type) + return collector.types + + def add_function(self, function): + self.functions.append(function) + + def add_functions(self, functions): + for function in functions: + self.add_function(function) + + def add_interface(self, interface): + self.interfaces.append(interface) + + def add_interfaces(self, interfaces): + self.interfaces.extend(interfaces) + + +Bool = Literal("bool", "Bool") +SChar = Literal("signed char", "SInt") +UChar = Literal("unsigned char", "UInt") +Short = Literal("short", "SInt") +Int = Literal("int", "SInt") +Long = Literal("long", "SInt") +LongLong = Literal("long long", "SInt") +UShort = Literal("unsigned short", "UInt") +UInt = Literal("unsigned int", "UInt") +ULong = Literal("unsigned long", "UInt") +ULongLong = Literal("unsigned long long", "UInt") +Float = Literal("float", "Float") +Double = Literal("double", "Float") +SizeT = Literal("size_t", "UInt") +WString = Literal("wchar_t *", "WString") - def __init__(self, type): - Pointer.__init__(self, type) - if type not in towrap: - towrap.append(type) - - def wrap_instance(self, instance): - print " if(%s)" % instance - print " %s = new %s(%s);" % (instance, self.type.wrap_name(), instance) - - def unwrap_instance(self, instance): - print " if(%s)" % instance - print " %s = static_cast<%s *>(%s)->m_pInstance;" % (instance, self.type.wrap_name(), instance) - -String = Intrinsic("char *", "%s") -Int = Intrinsic("int", "%i") -Long = Intrinsic("long", "%li") -Float = Intrinsic("float", "%f") - - -def wrap(): - for type in towrap: - type.wrap_pre_decl() - print - for type in towrap: - type.wrap_decl() - print - for type in towrap: - type.wrap_impl() - print