diff options
Diffstat (limited to 'contrib/xclasses/xclasses.py')
-rw-r--r-- | contrib/xclasses/xclasses.py | 870 |
1 files changed, 870 insertions, 0 deletions
diff --git a/contrib/xclasses/xclasses.py b/contrib/xclasses/xclasses.py new file mode 100644 index 000000000000..eaf449b19a27 --- /dev/null +++ b/contrib/xclasses/xclasses.py @@ -0,0 +1,870 @@ +import copy +import string +import sys +import time +import types + + +def capitalize(s): + return string.upper(s[0]) + s[1:] + +def fprint(f, s): + print >> f, s + + +def fprintHeader(f, comment = "//"): + fprint(f, comment) + fprint(f, comment + " Generated by xclasses.py at " + time.strftime("%Y/%m/%d %H:%M:%S")) + fprint(f, comment) + fprint(f, comment) + fprint(f, "") + +def fprintFooter(f, comment = "//"): + fprint(f, "") + fprint(f, "") + fprint(f, comment + " end of file") + fprint(f, "") + +multicallCallTypeFunction = 0 +multicallCallTypeMethod = 1 +multicallCallTypeVirtualMethod = 2 + +multicallReturnTypeVoid = 0 +multicallReturnTypeInteger = 16 +multicallReturnTypeCstring = 32 +multicallReturnTypeFloat = 48 + +multicallExplicitVtable = 512 + + +ficlVmName = "ficlVm" + +h_headers = [] +def xAddHHeader(line): + h_headers.append(line) + +h_footers = [] +def xAddHFooter(line): + h_footers.append(line) + +ficl_headers = [] +def xAddFiclHeader(line): + ficl_headers.append(line) + +ficl_footers = [] +def xAddFiclFooter(line): + ficl_footers.append(line) + +c_headers = [] +def xAddCHeader(line): + c_headers.append(line) + +c_footers = [] +def xAddCFooter(line): + c_footers.append(line) + + +classes = [] + +class xVariable: + def __init__(self, name, typeCPP = None, cells = None, count = None, defaultValue = None, cstring = None): + self.comments = [] + self.setName(name) + self.setCells(cells) + self.setCount(count) + self.setDefaultValue(defaultValue) + self.setCString(cstring) + self.setTypeCPP(typeCPP) + + def setName(self, name): + self.name = name + return self + + def setTypeCPP(self, typeCPP): + self.typeCPP = typeCPP + if (typeCPP == "char *"): + self.setCString(1) + return self + + def setCells(self, cells): + if cells == None: + self.cells = 1 + else: + self.cells = cells + return self + + def setCString(self, cstring): + self.cstring = cstring + return self + + def isCString(self): + return self.cstring + + def getTotalSize(self): + return self.cells * self.count + + def setCount(self, count): + if type(count) != types.IntType: + count = 1 + self.count = count + return self + + def setDefaultValue(self, defaultValue): + if (defaultValue != None) and (type(defaultValue) != types.StringType): + defaultValue = str(defaultValue) + self.defaultValue = defaultValue + return self + + def addComment(self, c): + self.comments.append(c) + return self + + def isFloat(self): + return self.typeCPP == "float" + + def stringCPP(self, wantDefaultValues=1): + if (type(self.typeCPP) != types.StringType): + sys.exit("didn't set a CPP type on variable " + self.name + "!") + output = self.typeCPP + if (self.typeCPP[-1] != "*") and (self.typeCPP[-1] != "&"): + output += " " + output += self.name + if self.count > 1: + output += "[" + str(self.count) + "]" + if self.count == 0: + output += "[]" + if wantDefaultValues and (self.defaultValue != None): + output += " = " + self.defaultValue + return output + + def printH(self, f): + if len(self.comments): + for comment in self.comments: + fprint(f, "\t" + "// " + comment) + fprint(f, "\t" + self.stringCPP() + ";") + + def printF(self, f): + totalCells = self.count * self.cells + if (totalCells <= 1): + typeF = "cell:" + else: + typeF = str(totalCells) + " cells:" + if len(self.comments): + for comment in self.comments: + fprint(f, "\t" + "// " + comment) + fprint(f, "\t" + "S\" " + typeF + " ." + self.name + " \" evaluate") + + +class xMethod: + def __init__(self, name, returnType = None, virtual = None, static = None, body = None): + self.arguments = [] + self.comments = [] + + self.setName(name) + self.setReturnType(returnType) + self.setVirtual(virtual) + self.setStatic(static) + self.setBody(body) + self.setThunkVariable(None) + self.vtableOffset = 0 + + def copy(): + clone = xMethod(self.name, self.returnType, self.virtual, self.static) + clone.arguments = self.arguments + clone.comments = self.comments + + def setName(self, name): + self.name = name + return self + + def setReturnType(self, returnType): + if returnType.__class__ == xVariable: + self.returnType = returnType + elif type(returnType) == types.StringType: + self.returnType = xVariable("ignored", returnType) + else: + self.returnType = None + return self + + def returnTypeIsVoid(self): + return(self.returnType == None) or (self.returnType.typeCPP == None) or (self.returnType.typeCPP == "") or (self.returnType.typeCPP == "void") + + def setVirtual(self, virtual): + self.virtual = virtual + return self + + def isVirtual(self): + return self.virtual > 0 + + def isPureVirtual(self): + return self.virtual > 1 + + def setStatic(self, static): + self.static = static + return self + + def setThunkVariable(self, thunkVariable): + self.thunkVariable = thunkVariable + return self + + def isStatic(self): + return self.static + + # a constructor or a destructor + def isClassSpecial(self): + return (self.returnType == None) or (self.returnType.typeCPP == None) or (self.returnType.typeCPP == "") + + def setBody(self, body): + self.body = body + return self + + def addArgument(self, argument): + self.arguments.append(argument) + return self + + def addComment(self, c): + self.comments.append(c) + return self + + def prototype(self, isDefinition=None): + arguments = "" + for a in self.arguments: + if len(arguments): + arguments += ", " + arguments += a.stringCPP(not isDefinition) + + if len(arguments) == 0: + arguments = "void" + className = "" + if (isDefinition): + className = self.memberOf.name + "::" + modifiers = "" + if self.virtual and (not isDefinition): + modifiers += "virtual " + if self.static and (not isDefinition): + modifiers += "static " + returnType = "" + name = self.name + if (name == "") or (name == "~"): + name += self.memberOf.name + if (self.returnType != None) and (len(self.returnType.typeCPP) > 0): + returnType = self.returnType.typeCPP + " " + return modifiers + returnType + className + name + "(" + arguments + ")" + + def printH(self, f): + pureVirtual = "" + if (self.virtual > 1): + pureVirtual = " = 0" + suffix = ";" + modifiers = "" + if self.body != None: + modifiers = "inline " + suffix = " " + self.body + fprint(f, "\t" + modifiers + self.prototype() + pureVirtual + suffix) + + def printF(self, f): + if not self.isVirtual(): + return + + if len(self.comments): + for comment in self.comments: + fprint(f, "\t" + "// " + comment) + + flags = multicallReturnTypeInteger + if self.returnTypeIsVoid(): + flags = multicallReturnTypeVoid + elif (self.returnType.isCString()): + flags = multicallReturnTypeCString + elif (self.returnType.typeCPP == "float"): + flags = multicallReturnTypeFloat + flags |= multicallCallTypeVirtualMethod + # move floating-point arguments from float stack + floatArgumentsBitfield = 0 + cstringArgumentsBitfield = 0 + argumentNumber = 0 + cstrings = 0 + name = self.name + if (self.memberOf.pureVirtual): + vtable = "" + else: + vtable = " drop [ " + self.memberOf.name + "-vtable literal ] " + flags |= multicallExplicitVtable + if (name == "") or (name == "~"): + name += self.memberOf.name + for a in self.arguments: + if a.isFloat(): + floatArgumentsBitfield |= (1 << argumentNumber) + elif a.isCString(): + cstringArgumentsBitfield |= (1 << argumentNumber) + cstrings += 1 + argumentNumber += 1 + fprint(f, "\tS\" : " + name + vtable + str(len(self.arguments) + cstrings) + " " + str(floatArgumentsBitfield) + " " + str(cstringArgumentsBitfield) + " " + str(self.vtableOffset) + " " + str(flags) + " multicall ; \" evaluate ") + + def printCPP(self, f): + if (self.thunkVariable != None): + if (self.returnType != None) and (self.returnType.isCString()): + sys.exit("Can't thunk char * return values, sorry.") + fprint(f, "") + fprint(f, self.prototype(1)) + fprint(f, "\t{") + fprint(f, "\tif (" + self.thunkVariable.name + " == NULL)") + if self.isClassSpecial() or self.returnTypeIsVoid(): + fprint(f, "\t\treturn;") + elif (self.returnType.isFloat()): + fprint(f, "\t\treturn 0.0f;") + else: + fprint(f, "\t\treturn (" + self.returnType.typeCPP + ")0;") + fprint(f, "") + + ficlVmName = self.memberOf.getFiclVmName() + + ## output stack-checking code! how cool is that? --lch + dataStackPush = 2 # why 2? we always push this and ficlClass. + dataStackPop = 0 + floatStackPush = 0 + floatStackPop = 0 + + for a in self.arguments: + if (a.isCString()): + dataStackPush = dataStackPush + 2 + elif (a.isFloat()): + floatStackPush = floatStackPush + 1 + else: + dataStackPush = dataStackPush + 1 + + if (not self.returnTypeIsVoid()): + if (self.returnType.isFloat()): + floatStackPop = 1 + else: + dataStackPop = 1 + + if (dataStackPush or dataStackPop or floatStackPush or floatStackPop): + fprint(f, "#ifdef _DEBUG") + if (dataStackPush or dataStackPop): + fprint(f, "\tficlStackCheck(" + ficlVmName + "->dataStack, " + str(dataStackPush) + ", " + str(dataStackPop) + ");") + if (floatStackPush or floatStackPop): + fprint(f, "\tficlStackCheck(" + ficlVmName + "->floatStack, " + str(floatStackPush) + ", " + str(floatStackPop) + ");") + fprint(f, "#endif // _DEBUG") + + reversedArguments = copy.copy(self.arguments) + reversedArguments.reverse() + + for a in reversedArguments: + if (a.isCString()): + fprint(f, "\tficlStackPushPointer(" + ficlVmName + "->dataStack, " + a.name + ");") + fprint(f, "\tficlStackPushInteger(" + ficlVmName + "->dataStack, strlen(" + a.name + "));") + elif (a.isFloat()): + fprint(f, "\tficlStackPushFloat(" + ficlVmName + "->floatStack, " + a.name + ");") + else: + fprint(f, "\tficlStackPushInteger(" + ficlVmName + "->dataStack, (int)" + a.name + ");") + fprint(f, "\tficlStackPushPointer(" + ficlVmName + "->dataStack, this);") + fprint(f, "\tficlStackPushPointer(" + ficlVmName + "->dataStack, ficlClass);") + fprint(f, "\tficlVmExecuteXT(" + ficlVmName + ", " + self.thunkVariable.name + ");") + if (not self.returnTypeIsVoid()): + if (self.returnType.isFloat()): + fprint(f, "\treturn ficlStackPopFloat(" + ficlVmName + "->floatStack);") + else: + fprint(f, "\treturn (" + self.returnType.typeCPP + ")ficlStackPopInteger(" + ficlVmName + "->dataStack);") + fprint(f, "\t}") + fprint(f, "") + + # don't do virtual functions + if self.isVirtual() or self.isClassSpecial(): + return + + name = self.name + if (name == "") or (name == "~"): + name += self.memberOf.name + + fprint(f, "// " + self.memberOf.name + "::" + name) + if len(self.comments): + fprint(f, "\t" + "//") + for comment in self.comments: + fprint(f, "\t" + "// " + comment) + + arguments = "" + for a in self.arguments: + if len(arguments): + arguments += ", " + arguments += a.stringCPP() + + if len(arguments) == 0: + arguments = "void" + classModifier = self.memberOf.name + "::" + calltype = "FICL_MULTICALL_CALLTYPE_METHOD" + if self.isStatic(): + classModifier = "" + calltype = "FICL_MULTICALL_CALLTYPE_FUNCTION" + returnString = "FICL_MULTICALL_RETURNTYPE_INTEGER" + if self.returnTypeIsVoid(): + returnString = "FICL_MULTICALL_RETURNTYPE_VOID" + elif (self.returnType.typeCPP == "float"): + returnString = "FICL_MULTICALL_RETURNTYPE_FLOAT" + elif (self.returnType.isCString()): + returnString = "FICL_MULTICALL_RETURNTYPE_CSTRING" + + # set bits in argumentFlags + floatArgumentsBitfield = 0 + cstringArgumentsBitfield = 0 + argumentNumber = 0 + cstrings = 0 + for a in self.arguments: + if a.isFloat(): + floatArgumentsBitfield |= (1 << argumentNumber) + elif a.isCString(): + cstringArgumentsBitfield |= (1 << argumentNumber) + cstrings += 1 + argumentNumber += 1 + + uniqueSuffix = "_" + self.memberOf.name + "_" + name + # constructor is blank! + if (self.name == ""): + uniqueSuffix = "_" + self.memberOf.name + "_constructor" + # destructor is just a squiggle! + elif (self.name == "~"): + uniqueSuffix = "_" + self.memberOf.name + "_destructor" + printingHash = {} + printingHash["classname"] = "xMethod" + uniqueSuffix + printingHash["variablename"] = "instance" + uniqueSuffix + printingHash["address"] = self.returnType.typeCPP + " (" + classModifier + "*address)(" + arguments + ")" + printingHash["function"] = self.memberOf.name + "::" + name + printingHash["methodname"] = name + printingHash["argumentCount"] = str(len(self.arguments) + cstrings) + printingHash["floatArgumentsBitfield"] = str(floatArgumentsBitfield) + printingHash["cstringArgumentsBitfield"] = str(cstringArgumentsBitfield) + printingHash["flags"] = calltype + " | " + returnString + fprint(f, """ +struct %(classname)s + { + char *name; + int argumentCount; + int floatArgumentBitfield; + int cstringArgumentBitfield; + int flags; + %(address)s; + int zero; + }; + +static %(classname)s %(variablename)s = { "%(methodname)s", %(argumentCount)s, %(floatArgumentsBitfield)s, %(cstringArgumentsBitfield)s, %(flags)s, %(function)s, 0 }; +""" % printingHash) + + + + + +class xClass: + def __init__(self, name): + self.members = [] + self.methods = [] + self.verbatim = [] + self.name = name + self.superclass = None + self.superclassName = None + self.containsVtable = 0 + self.vtableEntries = 0 + self.firstMember = None + self.memberCellsTotal = 0 + self.thunkedSubclass = None + self.pureVirtual = 0 + self.setFiclVmName(None) + classes.append(self) + + + def subclassOf(self, superclass): + if type(superclass) == types.StringType: + self.superclassName = superclass + else: + self.superclass = superclass + self.superclassName = superclass.name + if superclass.containsVtable: + self.containsVtable = 2 + self.pureVirtual = superclass.pureVirtual + self.vtableEntries = superclass.vtableEntries + else: + self.containsVtable = 0 + return self + + def thunkedSubclassOf(self, superclass): + self.subclassOf(superclass) + self.addMember(xVariable("ficlClass", "void *")) + for method in superclass.methods: + if not method.isClassSpecial() or method.isPureVirtual(): + method = copy.deepcopy(method) + if method.isPureVirtual(): + method.setVirtual(1) + self.addThunkedMethod(method) + self.constructor = xMethod("") + self.addMethod(self.constructor) + self.thunkedSubclass = 1 + return self + + def forwardDeclare(self): + xAddHHeader("class " + self.name + ";") + + + def addVerbatim(self, v): + self.verbatim.append(v) + return self + + def addMember(self, variable): + self.members.append(variable) + self.memberCellsTotal += variable.getTotalSize() + if (self.firstMember == None): + self.firstMember = variable + return self + + def removeMember(self, variable): + self.members.remove(variable) + self.memberCellsTotal -= variable.getTotalSize() + if (self.firstMember == variable): + self.firstMember = self.members[0] + return self + + def addMemberArray(self, array): + map(self.addMember, copy.deepcopy(array)) + + + def findPreviousInstanceOfVirtualMethod(self, name): + for method in self.methods: + if method.name == name: + return method + if (self.superclass != None) and (type(self.superclass) != types.StringType): + return self.superclass.findPreviousInstanceOfVirtualMethod(name) + return None + + def setFiclVmName(self, name): + self.ficlVmName = name + return self + + def getFiclVmName(self): + if self.ficlVmName != None: + return self.ficlVmName + + global ficlVmName + return ficlVmName + + def addMethod(self, method): + method.memberOf = self + if method.virtual: + previousInstance = self.findPreviousInstanceOfVirtualMethod(method.name) + if (previousInstance != None): + method.vtableOffset = previousInstance.vtableOffset + if previousInstance.isPureVirtual() and (not method.isPureVirtual()): + self.pureVirtual -= 1 + else: + method.vtableOffset = self.vtableEntries + self.vtableEntries = self.vtableEntries + 1 + if (not self.containsVtable): + self.containsVtable = 1 + if method.isPureVirtual(): + self.pureVirtual += 1 + self.methods.append(method) + return self + + def lookupMethod(self, methodName): + for m in self.methods: + if (m.name == methodName): + return m + return None + + def removeMethod(self, method): + if (type(method) == types.StringType): + method = self.lookupMethod(method) + if method == None: + return None + method.memberOf = None + self.methods.remove(method) + if method.virtual: + previousInstance = self.findPreviousInstanceOfVirtualMethod(method.name) + if (previousInstance == None): + for m in self.methods: + if (m.vtableOffset >= method.vtableOffset): + m.vtableOffset = m.vtableOffset - 1 + self.vtableEntries = self.vtableEntries - 1 + if (self.vtableEntries == 0): + self.containsVtable = 0 + if previousInstance.isPureVirtual() and (not method.isPureVirtual()): + self.pureVirtual += 1 + else: + if method.isPureVirtual(): + self.pureVirtual -= 1 + + if method.thunkVariable != None: + self.removeMember(method.thunkVariable) + + return self + + def addThunkedMethod(self, method): + method = copy.deepcopy(method) + self.addMethod(method) + name = capitalize(method.name) + if (method.isClassSpecial()): + if (name == ""): + name = "Constructor" + else: + name = "Destructor" + thunkVariable = xVariable("xt" + name, "ficlWord *") + self.addMember(thunkVariable) + method.setThunkVariable(thunkVariable) + return self + + def addNoopConstructor(self): + self.addVerbatim(self.name + "() { }") + return self + + def addConstructor(self, virtual = 0): + method = xMethod("") + method.setVirtual(virtual) + self.addMethod(method) + return method + + def addDestructor(self, virtual = 0): + method = xMethod("~") + method.setVirtual(virtual) + self.addMethod(method) + return method + + def addMemberWithAccessors(self, variable, writeBodiesToo = 1): + self.addMember(variable) + capitalizedName = capitalize(variable.name) + + m = xMethod("set" + capitalizedName, "void").addArgument(variable) + if writeBodiesToo: + m.setBody("\t{ this->" + variable.name + " = " + variable.name + "; }") + self.addMethod(m) + + m = xMethod("get" + capitalizedName, variable.typeCPP) + if writeBodiesToo: + m.setBody("\t{ return this->" + variable.name + "; }") + self.addMethod(m) + + def addMethodArray(self, array): + map(self.addMethod, copy.deepcopy(array)) + + def addThunkedMethodArray(self, array): + map(self.addThunkedMethod, copy.deepcopy(array)) + + def printHforward(self, f): + fprint(f, "class " + self.name + ";") + + def printH(self, f): + if (self.thunkedSubclass): + body = "\n\t\t{\n" + for m in self.methods: + if m.thunkVariable != None: + body += "\t\t" + m.thunkVariable.name + " = NULL;\n" + body += "\t\t}\n" + self.constructor.setBody(body) + s = "" + if self.superclassName != None: + s = " : public " + self.superclassName + fprint(f, "class " + self.name + s) + fprint(f, "\t" + "{") + fprint(f, "\t" + "public:") + fprint(f, "") + for member in self.members: + member.printH(f) + fprint(f, "") + for method in self.methods: + method.printH(f) + for v in self.verbatim: + fprint(f, "\t" + v + "\n") + fprint(f, "\t" + "};\n\n") + + def printF(self, f): + s = self.superclassName + if s == None: + s = "object" + + fprint(f, "") + fprint(f, "//") + fprint(f, "// " + self.name) + fprint(f, "//") + fprint(f, ": declare-" + self.name) + fprint(f, "\t" + "S\" " + s + " subclass " + self.name + " \" evaluate") + fprint(f, "") + if self.containsVtable == 1: + fprint(f, "\t" + "S\" cell: .vtable\" evaluate") + for member in self.members: + member.printF(f) + fprint(f, "") + if (self.firstMember == None): + fprint(f, "\t" + "S\" : default-init 2drop ; \" evaluate // no members!") + else: + storeFiclClass = "" + if (self.thunkedSubclass != None): + storeFiclClass = "this this my=> .ficlClass ! drop " + setVtable = "" + if self.containsVtable and (not self.pureVirtual): + setVtable = self.name + "-vtable this my=> .vtable ! " + fprint(f, "\t" + "S\" : default-init { 2:this -- } this my=> super my=> init this my=> ." + self.firstMember.name + " " + str(self.memberCellsTotal) + " cells 0 fill " + setVtable + storeFiclClass + "; \" evaluate") + fprint(f, "\t// " + self.name + " methods:") + fprint(f, "\t" + self.name + "-declare-methods") + for method in self.methods: + method.printF(f) + fprint(f, "\t;") + fprint(f, "") + fprint(f, ": end-" + self.name) + fprint(f, "\t" + "S\" end-class \" evaluate") + fprint(f, "\t" + "S\" " + self.name + " 2constant " + self.name + ".constant \" evaluate") + fprint(f, "\t;") + fprint(f, "") + + def printCPP(self, f): + fprint(f, "//") + fprint(f, "// " + self.name) + fprint(f, "//") + for method in self.methods: + method.printCPP(f) + fprint(f, "") + fprint(f, "// " + self.name + " final structure") + fprint(f, "static xMethod *" + self.name + "_methods[] =") + fprint(f, "\t" + "{") + for method in self.methods: + if (method.isVirtual() or method.isClassSpecial()): + continue + fprint(f, "\t" + "(xMethod *)(&instance_" + self.name + "_" + method.name + "),") + fprint(f, "\t" + "NULL") + fprint(f, "\t" + "};") + if self.containsVtable and (not self.pureVirtual): + fprint(f, "") + fprint(f, "// " + self.name + " instance, so we can get the vtable") + fprint(f, "static " + self.name + " " + self.name + "_instance;" ) + fprint(f, "") + + + +def xclassesFooter(): + f = open("xclasses.h", "wt") + + fprintHeader(f) + fprint(f, "#ifndef __XCLASSES_H") + fprint(f, "#define __XCLASSES_H") + fprint(f, "") + fprint(f, "extern void xclassesDefineMethods(ficlVm *vm);") + fprint(f, "") + fprint(f, "enum xtype"); + fprint(f, "\t{"); + fprint(f, "\txtypeInvalid = 0,"); + for c in classes: + fprint(f, "\txtype_" + c.name + ","); + fprint(f, "\txtypeLast,"); + fprint(f, "\t};"); + fprint(f, ""); + for line in h_headers: + fprint(f, line) + fprint(f, "") + fprint(f, "") + for c in classes: + c.printH(f) + for line in h_footers: + fprint(f, line) + fprint(f, "") + fprint(f, "#endif // __XCLASSES_H") + fprintFooter(f) + f.close() + + + f = open("xclasses.f", "wt") + fprintHeader(f) + fprint(f, ": use-default-init S\" : init { 2:this } this my=> super my=> init this my=> default-init ; \" evaluate ;"); + for line in ficl_headers: + fprint(f, line) + fprint(f, "") + for c in classes: + c.printF(f) + for line in ficl_footers: + fprint(f, line) + fprint(f, "") + fprintFooter(f) + f.close() + + + f = open("xclasses.cpp", "wt") + fprintHeader(f) + + for line in c_headers: + fprint(f, line) + fprint(f, "") + + fprint(f, "#include \"xclasses.h\"") + fprint(f, """ + +struct xMethod + { + char *name; + int argumentCount; + int floatArgumentBitfield; + int cstringArgumentBitfield; + int flags; + void *address; + int zero; + }; + +struct xClass + { + char *name; + xMethod **methods; + void **instance; + }; + +""") + + for c in classes: + c.printCPP(f) + fprint(f, """ +static xClass classes[] = + { +""") + for c in classes: + vtableVariable = "NULL" + if c.containsVtable and (not c.pureVirtual): + vtableVariable = "(void **)&" + c.name + "_instance" + fprint(f, "\t" + "{ \"" + c.name + "\", " + c.name + "_methods, " + vtableVariable + " },") + fprint(f, """ + { NULL, NULL } + }; + +void xclassesDefineMethods(ficlVm *vm) + { + char buffer[1024]; + xClass *c; + xMethod **m; + + for (c = classes; c->name != NULL; c++) + { + sprintf(buffer, " : %s-declare-methods ", c->name); + ficlVmEvaluate(vm, buffer); + for (m = c->methods; *m != NULL; m++) + { + xMethod *method = *m; + /* why is this here? I dunno, but MSVC seems to be packing my struct. So if address is zero, the next dword has the address. --lch */ + if (method->address == NULL) + method->address = (void *)method->zero; + sprintf(buffer, " S\\" : %s drop %d %d %d %d %d multicall ; \\" evaluate ", + method->name, + method->argumentCount, + method->floatArgumentBitfield, + method->cstringArgumentBitfield, + method->address, + method->flags + ); + ficlVmEvaluate(vm, buffer); + } + ficlVmEvaluate(vm, " ; "); + if (c->instance != NULL) + { + sprintf(buffer, "%s-vtable", c->name); + ficlDictionarySetConstantPointer(ficlVmGetDictionary(vm), buffer, *(c->instance)); + } + } + } +""") + for line in c_footers: + fprint(f, line) + fprint(f, "") + fprintFooter(f) + f.close() + + + |