X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=specs%2Fstdapi.py;h=c652736a8383e9156e5bd7e88af34dde79760382;hb=999284fd424cbf7dde024f949cdece0f308d41db;hp=60e287dadc1cfa816f1c49504be43769f4a95980;hpb=143e92584550e5c61f61c8e6d2a2d2070e5a98c8;p=apitrace diff --git a/specs/stdapi.py b/specs/stdapi.py index 60e287d..c652736 100644 --- a/specs/stdapi.py +++ b/specs/stdapi.py @@ -102,17 +102,43 @@ class Literal(Type): return visitor.visitLiteral(self, *args, **kwargs) +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", "Double") +SizeT = Literal("size_t", "UInt") + +Char = Literal("char", "SInt") +WChar = Literal("wchar_t", "SInt") + +Int8 = Literal("int8_t", "SInt") +UInt8 = Literal("uint8_t", "UInt") +Int16 = Literal("int16_t", "SInt") +UInt16 = Literal("uint16_t", "UInt") +Int32 = Literal("int32_t", "SInt") +UInt32 = Literal("uint32_t", "UInt") +Int64 = Literal("int64_t", "SInt") +UInt64 = Literal("uint64_t", "UInt") + +IntPtr = Literal("intptr_t", "SInt") +UIntPtr = Literal("uintptr_t", "UInt") + class Const(Type): def __init__(self, type): # While "const foo" and "foo const" are synonymous, "const foo *" and # "foo * const" are not quite the same, and some compilers do enforce # strict const correctness. - if isinstance(type, String) or type is WString: - # For strings we never intend to say a const pointer to chars, but - # rather a point to const chars. - expr = "const " + type.expr - elif type.expr.startswith("const ") or '*' in type.expr: + if type.expr.startswith("const ") or '*' in type.expr: expr = type.expr + " const" else: # The most legible @@ -266,33 +292,18 @@ class Struct(Type): Struct.__id += 1 self.name = name - self.members = [] - - # Eliminate anonymous unions - for type, name in members: - if name is not None: - self.members.append((type, name)) - else: - assert isinstance(type, Union) - assert type.name is None - self.members.extend(type.members) + self.members = members def visit(self, visitor, *args, **kwargs): return visitor.visitStruct(self, *args, **kwargs) -class Union(Type): - - __id = 0 - - def __init__(self, name, members): - Type.__init__(self, name) - - self.id = Union.__id - Union.__id += 1 - - self.name = name - self.members = members +def Union(kindExpr, kindTypes, contextLess=True): + switchTypes = [] + for kindCase, kindType, kindMemberName in kindTypes: + switchType = Struct(None, [(kindType, kindMemberName)]) + switchTypes.append((kindCase, switchType)) + return Polymorphic(kindExpr, switchTypes, contextLess=contextLess) class Alias(Type): @@ -329,13 +340,7 @@ def InOut(type, name): class Function: - # 0-3 are reserved to memcpy, malloc, free, and realloc - __id = 4 - - def __init__(self, type, name, args, call = '', fail = None, sideeffects=True): - self.id = Function.__id - Function.__id += 1 - + def __init__(self, type, name, args, call = '', fail = None, sideeffects=True, internal=False): self.type = type self.name = name @@ -356,6 +361,7 @@ class Function: self.call = call self.fail = fail self.sideeffects = sideeffects + self.internal = internal def prototype(self, name=None): if name is not None: @@ -379,6 +385,12 @@ class Function: def argNames(self): return [arg.name for arg in self.args] + def getArgByName(self, name): + for arg in self.args: + if arg.name == name: + return arg + return None + def StdFunction(*args, **kwargs): kwargs.setdefault('call', '__stdcall') @@ -401,6 +413,12 @@ class Interface(Type): def visit(self, visitor, *args, **kwargs): return visitor.visitInterface(self, *args, **kwargs) + def getMethodByName(self, name): + for method in self.iterMethods(): + if method.name == name: + return method + return None + def iterMethods(self): if self.base is not None: for method in self.base.iterMethods(): @@ -427,7 +445,8 @@ class Interface(Type): class Method(Function): - def __init__(self, type, name, args, call = '__stdcall', const=False, sideeffects=True): + def __init__(self, type, name, args, call = '', const=False, sideeffects=True): + assert call == '__stdcall' Function.__init__(self, type, name, args, call = call, sideeffects=sideeffects) for index in range(len(self.args)): self.args[index].index = index + 1 @@ -446,11 +465,14 @@ def StdMethod(*args, **kwargs): class String(Type): + '''Human-legible character string.''' - def __init__(self, expr = "char *", length = None, kind = 'String'): - Type.__init__(self, expr) + def __init__(self, type = Char, length = None, wide = False): + assert isinstance(type, Type) + Type.__init__(self, type.expr + ' *') + self.type = type self.length = length - self.kind = kind + self.wide = wide def visit(self, visitor, *args, **kwargs): return visitor.visitString(self, *args, **kwargs) @@ -478,18 +500,27 @@ def OpaqueBlob(type, size): class Polymorphic(Type): - def __init__(self, defaultType, switchExpr, switchTypes): - Type.__init__(self, defaultType.expr) - self.defaultType = defaultType + def __init__(self, switchExpr, switchTypes, defaultType=None, contextLess=True): + if defaultType is None: + Type.__init__(self, None) + contextLess = False + else: + Type.__init__(self, defaultType.expr) self.switchExpr = switchExpr self.switchTypes = switchTypes + self.defaultType = defaultType + self.contextLess = contextLess def visit(self, visitor, *args, **kwargs): return visitor.visitPolymorphic(self, *args, **kwargs) def iterSwitch(self): - cases = [['default']] - types = [self.defaultType] + cases = [] + types = [] + + if self.defaultType is not None: + cases.append(['default']) + types.append(self.defaultType) for expr, type in self.switchTypes: case = 'case %s' % expr @@ -504,6 +535,13 @@ class Polymorphic(Type): return zip(cases, types) +def EnumPolymorphic(enumName, switchExpr, switchTypes, defaultType, contextLess=True): + enumValues = [expr for expr, type in switchTypes] + enum = Enum(enumName, enumValues) + polymorphic = Polymorphic(switchExpr, switchTypes, defaultType, contextLess) + return enum, polymorphic + + class Visitor: '''Abstract visitor for the type hierarchy.''' @@ -595,7 +633,11 @@ class Rebuilder(Visitor): return literal def visitString(self, string): - return string + string_type = self.visit(string.type) + if string_type is string.type: + return string + else: + return String(string_type, string.length, string.wide) def visitConst(self, const): const_type = self.visit(const.type) @@ -675,15 +717,21 @@ class Rebuilder(Visitor): return interface def visitPolymorphic(self, polymorphic): - defaultType = self.visit(polymorphic.defaultType) switchExpr = polymorphic.switchExpr switchTypes = [(expr, self.visit(type)) for expr, type in polymorphic.switchTypes] - return Polymorphic(defaultType, switchExpr, switchTypes) + if polymorphic.defaultType is None: + defaultType = None + else: + defaultType = self.visit(polymorphic.defaultType) + return Polymorphic(switchExpr, switchTypes, defaultType, polymorphic.contextLess) class MutableRebuilder(Rebuilder): '''Type visitor which derives a mutable type.''' + def visitString(self, string): + return string + def visitConst(self, const): # Strip out const qualifier return const.type @@ -764,9 +812,10 @@ class Traverser(Visitor): self.visit(method.type, *args, **kwargs) def visitPolymorphic(self, polymorphic, *args, **kwargs): - self.visit(polymorphic.defaultType, *args, **kwargs) for expr, type in polymorphic.switchTypes: self.visit(type, *args, **kwargs) + if polymorphic.defaultType is not None: + self.visit(polymorphic.defaultType, *args, **kwargs) class Collector(Traverser): @@ -784,12 +833,52 @@ class Collector(Traverser): self.types.append(type) +class ExpanderMixin: + '''Mixin class that provides a bunch of methods to expand C expressions + from the specifications.''' -class API: - '''API abstraction. + __structs = None + __indices = None - Essentially, a collection of types, functions, and interfaces. - ''' + def expand(self, expr): + # Expand a C expression, replacing certain variables + if not isinstance(expr, basestring): + return expr + variables = {} + + if self.__structs is not None: + variables['self'] = '(%s)' % self.__structs[0] + if self.__indices is not None: + variables['i'] = self.__indices[0] + + expandedExpr = expr.format(**variables) + if expandedExpr != expr and 0: + sys.stderr.write(" %r -> %r\n" % (expr, expandedExpr)) + return expandedExpr + + def visitMember(self, member, structInstance, *args, **kwargs): + memberType, memberName = member + if memberName is None: + # Anonymous structure/union member + memberInstance = structInstance + else: + memberInstance = '(%s).%s' % (structInstance, memberName) + self.__structs = (structInstance, self.__structs) + try: + return self.visit(memberType, memberInstance, *args, **kwargs) + finally: + _, self.__structs = self.__structs + + def visitElement(self, elementIndex, elementType, *args, **kwargs): + self.__indices = (elementIndex, self.__indices) + try: + return self.visit(elementType, *args, **kwargs) + finally: + _, self.__indices = self.__indices + + +class Module: + '''A collection of functions.''' def __init__(self, name = None): self.name = name @@ -797,77 +886,78 @@ class API: self.functions = [] self.interfaces = [] + def addFunctions(self, functions): + self.functions.extend(functions) + + def addInterfaces(self, interfaces): + self.interfaces.extend(interfaces) + + def mergeModule(self, module): + self.headers.extend(module.headers) + self.functions.extend(module.functions) + self.interfaces.extend(module.interfaces) + + def getFunctionByName(self, name): + for function in self.functions: + if function.name == name: + return function + return None + + +class API: + '''API abstraction. + + Essentially, a collection of types, functions, and interfaces. + ''' + + def __init__(self, modules = None): + self.modules = [] + if modules is not None: + self.modules.extend(modules) + def getAllTypes(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.iterMethods(): - for arg in method.args: + for module in self.modules: + for function in module.functions: + for arg in function.args: collector.visit(arg.type) - collector.visit(method.type) + collector.visit(function.type) + for interface in module.interfaces: + collector.visit(interface) + for method in interface.iterMethods(): + for arg in method.args: + collector.visit(arg.type) + collector.visit(method.type) return collector.types + def getAllFunctions(self): + functions = [] + for module in self.modules: + functions.extend(module.functions) + return functions + def getAllInterfaces(self): types = self.getAllTypes() interfaces = [type for type in types if isinstance(type, Interface)] - for interface in self.interfaces: - if interface not in interfaces: - interfaces.append(interface) + for module in self.modules: + for interface in module.interfaces: + if interface not in interfaces: + interfaces.append(interface) return interfaces - def addFunction(self, function): - self.functions.append(function) - - def addFunctions(self, functions): - for function in functions: - self.addFunction(function) - - def addInterface(self, interface): - self.interfaces.append(interface) + def addModule(self, module): + self.modules.append(module) - def addInterfaces(self, interfaces): - self.interfaces.extend(interfaces) - - def addApi(self, api): - self.headers.extend(api.headers) - self.addFunctions(api.functions) - self.addInterfaces(api.interfaces) - - def get_function_by_name(self, name): - for function in self.functions: - if function.name == name: - return function + def getFunctionByName(self, name): + for module in self.modules: + for function in module.functions: + if function.name == name: + return function return None -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", "Double") -SizeT = Literal("size_t", "UInt") - # C string (i.e., zero terminated) -CString = String() -WString = String("wchar_t *", kind="WString") - -Int8 = Literal("int8_t", "SInt") -UInt8 = Literal("uint8_t", "UInt") -Int16 = Literal("int16_t", "SInt") -UInt16 = Literal("uint16_t", "UInt") -Int32 = Literal("int32_t", "SInt") -UInt32 = Literal("uint32_t", "UInt") -Int64 = Literal("int64_t", "SInt") -UInt64 = Literal("uint64_t", "UInt") +CString = String(Char) +WString = String(WChar, wide=True) +ConstCString = String(Const(Char)) +ConstWString = String(Const(WChar), wide=True)