summaryrefslogtreecommitdiff
path: root/contrib/xclasses/xclasses.py
diff options
context:
space:
mode:
authorPedro F. Giffuni <pfg@FreeBSD.org>2015-05-12 03:27:06 +0000
committerPedro F. Giffuni <pfg@FreeBSD.org>2015-05-12 03:27:06 +0000
commitf4e75c6395310fa4b119d3eaa9a4a9f8913df200 (patch)
tree2b015c205d81fa2431f0c36d7d9e903088a56d1c /contrib/xclasses/xclasses.py
parentbe98e1ae3decabdd852fbe6496166aaa9acfbf9e (diff)
Notes
Diffstat (limited to 'contrib/xclasses/xclasses.py')
-rw-r--r--contrib/xclasses/xclasses.py870
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()
+
+
+