Mercurial > projects > dwt-mac
diff dwt/internal/cocoa/MacGenerator.d @ 0:380af2bdd8e5
Upload of whole dwt tree
author | Jacob Carlborg <doob@me.com> <jacob.carlborg@gmail.com> |
---|---|
date | Sat, 09 Aug 2008 17:00:02 +0200 |
parents | |
children | e831403a80a9 f565d3a95c0a |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwt/internal/cocoa/MacGenerator.d Sat Aug 09 17:00:02 2008 +0200 @@ -0,0 +1,839 @@ +/******************************************************************************* + * Copyright (c) 2007 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * + * Port to the D Programming language: + * Jacob Carlborg <jacob.carlborg@gmail.com> + *******************************************************************************/ +module dwt.internal.cocoa.MacGenerator; + +import tango.text.xml.Document; + +import dwt.dwthelper.BufferedOutputStream; +import dwt.dwthelper.FileOutputStream; +/*import dwt.dwthelper.PrintStream; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; + +import com.sun.org.apache.xerces.internal.parsers.DOMParser; +import org.w3c.dom.*;*/ + +import dwt.dwthelper.utils; + +public class MacGenerator { + String[] classes; + String xml[]; + String outputDir; + + //PrintStream output; + +public this(String[] xml) +{ + this.xml = xml; +} + +public void print (String str) { + /*PrintStream output = this.output; + if (output is null) output = System.out; + output.print(str);*/ +} + +public void println() { + /*PrintStream output = this.output; + if (output is null) output = System.out; + output.println();*/ +} + +public void generateConstants() +{ + foreach (str ; xml) + { + Document document = new Document!(char); + document.parse(str); + + foreach (node ; document.root.children) + { + if ("constant" == node.name) + { + Node attribute; + + print("public static final native int "); + + foreach (a ; node.attributes) + if (a.name == "name") + { + attribute = a; + break; + } + + print(attribute.value); + print("();"); + println; + } + } + } +} + +public void generateConstantsMetaData() +{ + foreach (str ; xml) + { + Document document = new Document!(char); + document.parse(str); + + foreach (node ; document.root.children) + { + if ("constant" == node.name) + { + Node attribute; + + print("OS_"); + + foreach (a ; node.attributes) + if (a.name == "name") + { + attribute = a; + break; + } + + print(attribute.value); + print("=flags=const"); + println; + } + } + } +} + +public void generateEnums() +{ + foreach (str ; xml) + { + Document document = new Document!(char); + document.parse(str); + + foreach (node ; document.root.children) + { + if ("enum" == node.name) + { + Node attributeName = null; + Node attributeValue = null; + + print("OS_"); + + foreach (a ; node.attributes) + if (a.name == "value") + { + attributeValue = a; + break; + } + + if (attributeValue !is null) + { + print("public static final "); + + if (attributeValue.value.indexOf('.') !is -1) + print("double "); + + else + print("int "); + } + + foreach (a ; node.attributes) + if (a.name == "name") + { + attributeName = a; + break; + } + + print(attributeName.value); + print(" = "); + print(attributeValue.value); + print(";"); + println; + } + } + } +} + +bool isStruct(Node node) +{ + String code; + + foreach (a ; node.attributes) + if(a.name == "type") + { + code = a.value; + break; + } + + return code.startsWith("{"); +} + +bool isFloatingPoint(Node node) { + NamedNodeMap attributes = node.getAttributes(); + String code = attributes.getNamedItem("type").getNodeValue(); + return code.opEquals("f") || code.opEquals("d"); +} + +bool isObject(Node node) { + NamedNodeMap attributes = node.getAttributes(); + String code = attributes.getNamedItem("type").getNodeValue(); + return code.opEquals("@"); +} + +bool isBoolean(Node node) { + NamedNodeMap attributes = node.getAttributes(); + String code = attributes.getNamedItem("type").getNodeValue(); + return code.opEquals("B"); +} + +bool getGenerateClass(String className) { + if (classes !is null) { + for (int i = 0; i < classes.length; i++) { + if (className.opEquals(classes[i])) return true; + } + return false; + } + return true; +} + +public bool isUnique(Node method, NodeList methods) { + String methodName = method.getAttributes().getNamedItem("selector").getNodeValue(); + int index = methodName.indexOf(":"); + if (index !is -1) methodName = methodName.substring(0, index); + for (int j = 0; j < methods.getLength(); j++) { + Node other = methods.item(j); + NamedNodeMap attributes = other.getAttributes(); + Node otherSel = null; + if (attributes !is null) otherSel = attributes.getNamedItem("selector"); + if (other !is method && otherSel !is null) { + String otherName = otherSel.getNodeValue(); + index = otherName.indexOf(":"); + if (index !is -1) otherName = otherName.substring(0, index); + if (methodName.opEquals(otherName)) { + return false; + } + } + } + return true; +} + +public void generateClasses() { + for (int x = 0; x < xml.length; x++) { + DOMParser parser = new DOMParser(); + parser.parse(xml[x]); + Document document = parser.getDocument(); + NodeList list = document.getDocumentElement().getChildNodes(); + for (int i = 0; i < list.getLength(); i++) { + Node node = list.item(i); + if ("class".opEquals(node.getLocalName())) { + NamedNodeMap attributes = node.getAttributes(); + String name = attributes.getNamedItem("name").getNodeValue(); + if (getGenerateClass(name)) { + if (outputDir !is null) { + FileOutputStream is = new FileOutputStream(outputDir + "/" + name + ".java"); + out = new PrintStream(new BufferedOutputStream(is)); + } + out("module dwt.internal.cocoa;"); + outln(); + outln(); + out("public class "); + out(name); + if (name.opEquals("NSObject")) { + out(" : id {"); + } else { + out(" : NSObject {"); + } + outln(); + outln(); + out("public "); + out(name); + out("() {"); + outln(); + out("\tsuper();"); + outln(); + out("}"); + outln(); + outln(); + out("public "); + out(name); + out("(int id) {"); + outln(); + out("\tsuper(id);"); + outln(); + out("}"); + outln(); + outln(); + NodeList methods = node.getChildNodes(); + for (int j = 0; j < methods.getLength(); j++) { + Node method = methods.item(j); + if ("method".opEquals(method.getLocalName())) { + String sel = method.getAttributes().getNamedItem("selector").getNodeValue(); + out("public "); + bool isStatic = method.getAttributes().getNamedItem("class_method") !is null; + if (isStatic) out("static "); + Node returnNode = getReturnNode(method.getChildNodes()); + if (getType(returnNode).opEquals("void")) returnNode = null; + if (returnNode !is null) { + out(getJavaType(returnNode)); + out(" "); + } else { + out("void "); + } + String methodName = sel; + if (isUnique(method, methods)) { + int index = methodName.indexOf(":"); + if (index !is -1) methodName = methodName.substring(0, index); + } else { + methodName = methodName.replaceAll(":", "_"); + if (isStatic) methodName = "static_" + methodName; + } + out(methodName); + out("("); + NodeList params = method.getChildNodes(); + bool first = true; + for (int k = 0; k < params.getLength(); k++) { + Node param = params.item(k); + if ("arg".opEquals(param.getLocalName())) { + NamedNodeMap paramAttributes = param.getAttributes(); + if (!first) out(", "); + out(getJavaType(param)); + first = false; + out(" "); + String paramName = paramAttributes.getNamedItem("name").getNodeValue(); + if (paramName.opEquals("bool")) paramName = "b"; + out(paramName); + } + } + out(") {"); + outln(); + if (returnNode !is null && isStruct(returnNode)) { + String type = getJavaType(returnNode); + out("\t"); + out(type); + out(" result = new "); + out(type); + out("();"); + outln(); + out("\tOS.objc_msgSend_stret(result, "); + } else if (returnNode !is null && isFloatingPoint(returnNode)) { + String type = getJavaType(returnNode); + out("\treturn "); + if (type.opEquals("float")) out("(float)"); + out("OS.objc_msgSend_fpret("); + } else if (returnNode !is null && isObject(returnNode)) { + out("\tint result = OS.objc_msgSend("); + } else { + if (returnNode !is null) { + out("\treturn "); + String type = getJavaType(returnNode); + if (!(type.opEquals("int") || type.opEquals("bool"))) { + out("("); + out(type); + out(")"); + } + } else { + out("\t"); + } + out("OS.objc_msgSend("); + } + if (isStatic) { + out("OS.class_"); + out(name); + } else { + out("this.id"); + } + out(", OS."); + out(getSelConst(sel)); + first = false; + for (int k = 0; k < params.getLength(); k++) { + Node param = params.item(k); + if ("arg".opEquals(param.getLocalName())) { + NamedNodeMap paramAttributes = param.getAttributes(); + if (!first) out(", "); + first = false; + String paramName = paramAttributes.getNamedItem("name").getNodeValue(); + if (paramName.opEquals("bool")) paramName = "b"; + if (isObject(param)) { + out(paramName); + out(" !is null ? "); + out(paramName); + out(".id : 0"); + } else { + out(paramName); + } + } + } + out(")"); + if (returnNode !is null && isBoolean(returnNode)) { + out(" !is 0"); + } + out(";"); + outln(); + if (returnNode !is null && isObject(returnNode)) { + if (!isStatic && getJavaType(returnNode).opEquals(name)) { + out("\treturn result is this.id ? this : (result !is 0 ? new "); + out(getJavaType(returnNode)); + out("(result) : null);"); + } else { + out("\treturn result !is 0 ? new "); + out(getJavaType(returnNode)); + out("(result) : null;"); + } + outln(); + } else if (returnNode !is null && isStruct(returnNode)) { + out("\treturn result;"); + outln(); + } + out("}"); + outln(); + outln(); + } + } + out("}"); + outln(); + if (outputDir !is null) { + out.close(); + out = null; + } + } + } + } + } +} + +public void generateSelectorsConst() { + HashSet set = new HashSet(); + for (int x = 0; x < xml.length; x++) { + DOMParser parser = new DOMParser(); + parser.parse(xml[x]); + Document document = parser.getDocument(); + NodeList list = document.getDocumentElement().getChildNodes(); + for (int i = 0; i < list.getLength(); i++) { + Node node = list.item(i); + if ("class".opEquals(node.getLocalName())) { + NamedNodeMap attributes = node.getAttributes(); + String name = attributes.getNamedItem("name").getNodeValue(); + if (getGenerateClass(name)) { + NodeList methods = node.getChildNodes(); + for (int j = 0; j < methods.getLength(); j++) { + Node method = methods.item(j); + if ("method".opEquals(method.getLocalName())) { + String sel = method.getAttributes().getNamedItem("selector").getNodeValue(); + set.add(sel); + } + } + } + } + } + } + for (Iterator iterator = set.iterator(); iterator.hasNext();) { + String sel = (String) iterator.next(); + String selConst = getSelConst(sel); + out("public static final int "); + out(selConst); + out(" = "); + out("sel_registerName(\""); + out(sel); + out("\");"); + outln(); + } +} + +public void generateSends() { + HashSet set = new HashSet(); + for (int x = 0; x < xml.length; x++) { + DOMParser parser = new DOMParser(); + parser.parse(xml[x]); + Document document = parser.getDocument(); + NodeList list = document.getDocumentElement().getChildNodes(); + for (int i = 0; i < list.getLength(); i++) { + Node node = list.item(i); + if ("class".opEquals(node.getLocalName())) { + NamedNodeMap attributes = node.getAttributes(); + String name = attributes.getNamedItem("name").getNodeValue(); + if (getGenerateClass(name)) { + NodeList methods = node.getChildNodes(); + for (int j = 0; j < methods.getLength(); j++) { + Node method = methods.item(j); + if ("method".opEquals(method.getLocalName())) { + Node returnNode = getReturnNode(method.getChildNodes()); + StringBuffer buffer = new StringBuffer(); + buffer.append("public static final native "); + if (returnNode !is null && isStruct(returnNode)) { + buffer.append("void objc_msgSend_stret("); + buffer.append(getJavaType(returnNode)); + buffer.append(" result, "); + } else if (returnNode !is null && isFloatingPoint(returnNode)) { + buffer.append("double objc_msgSend_fpret("); + } else { + buffer.append("int objc_msgSend("); + } + buffer.append("int id, int sel"); + NodeList params = method.getChildNodes(); + bool first = false; + int count = 0; + for (int k = 0; k < params.getLength(); k++) { + Node param = params.item(k); + if ("arg".opEquals(param.getLocalName())) { + if (!first) buffer.append(", "); + if (isStruct(param)) { + buffer.append(getJavaType(param)); + } else { + buffer.append(getType(param)); + } + first = false; + buffer.append(" arg"); + buffer.append(String.valueOf(count++)); + } + } + buffer.append(");"); + set.add(buffer.toString()); + } + } + } + } + } + } + for (Iterator iterator = set.iterator(); iterator.hasNext();) { + out(iterator.next().toString()); + outln(); + } +} + +public void generateSendsMetaData() { + HashMap set = new HashMap(); + for (int x = 0; x < xml.length; x++) { + DOMParser parser = new DOMParser(); + parser.parse(xml[x]); + Document document = parser.getDocument(); + NodeList list = document.getDocumentElement().getChildNodes(); + for (int i = 0; i < list.getLength(); i++) { + Node node = list.item(i); + if ("class".opEquals(node.getLocalName())) { + NamedNodeMap attributes = node.getAttributes(); + String name = attributes.getNamedItem("name").getNodeValue(); + if (getGenerateClass(name)) { + NodeList methods = node.getChildNodes(); + for (int j = 0; j < methods.getLength(); j++) { + Node method = methods.item(j); + if ("method".opEquals(method.getLocalName())) { + Node returnNode = getReturnNode(method.getChildNodes()); + StringBuffer buffer = new StringBuffer(); + if (returnNode !is null && isStruct(returnNode)) { + buffer.append("OS_objc_1msgSend_1stret__"); + buffer.append("Lorg_eclipse_swt_internal_cocoa_"); + buffer.append(getJavaType(returnNode)); + buffer.append("_2"); + } else if (returnNode !is null && isFloatingPoint(returnNode)) { + buffer.append("OS_objc_1msgSend_1fpret__"); + } else { + buffer.append("OS_objc_1msgSend__"); + } + buffer.append("II"); + NodeList params = method.getChildNodes(); + for (int k = 0; k < params.getLength(); k++) { + Node param = params.item(k); + if ("arg".opEquals(param.getLocalName())) { + if (isStruct(param)) { + buffer.append("Lorg_eclipse_swt_internal_cocoa_"); + buffer.append(getJavaType(param)); + buffer.append("_2"); + } else { + buffer.append(getJNIType(param)); + } + } + } + String key = buffer.toString(); + if (set.get(key) is null) set.put(key, method); + } + } + } + } + } + } + for (Iterator iterator = set.keySet().iterator(); iterator.hasNext();) { + String key = iterator.next().toString(); + out(key); + out("=flags=cast"); + outln(); + int count = 2; + if (key.indexOf("stret") !is -1) { + count = 3; + out(key); + out("_0="); + outln(); + out(key); + out("_1=cast=(id)"); + outln(); + out(key); + out("_2=cast=(SEL)"); + outln(); + } else { + out(key); + out("_0=cast=(id)"); + outln(); + out(key); + out("_1=cast=(SEL)"); + outln(); + } + Node method = (Node)set.get(key); + NodeList params = method.getChildNodes(); + for (int k = 0; k < params.getLength(); k++) { + Node param = params.item(k); + if ("arg".opEquals(param.getLocalName())) { + out(key); + out("_"); + out(String.valueOf(count)); + out("="); + if (isStruct(param)) { + out("flags=struct"); + } + outln(); + count++; + } + } + outln(); + } +} + + +String getSelConst(String sel) { + return "sel_" + sel.replaceAll(":", "_1"); +} + +public void generateClassesConst() { + HashSet set = new HashSet(); + for (int x = 0; x < xml.length; x++) { + DOMParser parser = new DOMParser(); + parser.parse(xml[x]); + Document document = parser.getDocument(); + NodeList list = document.getDocumentElement().getChildNodes(); + for (int i = 0; i < list.getLength(); i++) { + Node node = list.item(i); + if ("class".opEquals(node.getLocalName())) { + NamedNodeMap attributes = node.getAttributes(); + String name = attributes.getNamedItem("name").getNodeValue(); + if (getGenerateClass(name)) { + set.add(name); + } + } + } + } + for (Iterator iterator = set.iterator(); iterator.hasNext();) { + String cls = (String) iterator.next(); + String clsConst = "class_" + cls; + out("public static final int "); + out(clsConst); + out(" = "); + out("objc_getClass(\""); + out(cls); + out("\");"); + outln(); + } +} + +Node getReturnNode(NodeList list) { + for (int j = 0; j < list.getLength(); j++) { + Node node = list.item(j); + if ("retval".opEquals(node.getLocalName())) { + return node; + } + } + return null; +} + +String getType(Node node) { + NamedNodeMap attributes = node.getAttributes(); + String code = attributes.getNamedItem("type").getNodeValue(); + if (code.opEquals("c")) return "byte"; + if (code.opEquals("i")) return "int"; + if (code.opEquals("s")) return "short"; + if (code.opEquals("l")) return "int"; + if (code.opEquals("q")) return "long"; + if (code.opEquals("C")) return "byte"; + if (code.opEquals("I")) return "int"; + if (code.opEquals("S")) return "short"; + if (code.opEquals("L")) return "int"; + if (code.opEquals("Q")) return "long"; + if (code.opEquals("f")) return "float"; + if (code.opEquals("d")) return "double"; + if (code.opEquals("B")) return "bool"; + if (code.opEquals("v")) return "void"; + if (code.opEquals("*")) return "int"; + if (code.opEquals("@")) return "int"; + if (code.opEquals("#")) return "int"; + if (code.opEquals(":")) return "int"; + if (code.startsWith("^")) return "int"; + if (code.startsWith("[")) return "BAD " + code; + if (code.startsWith("{")) { + return attributes.getNamedItem("declared_type").getNodeValue(); + } + if (code.startsWith("(")) return "BAD " + code; + return "BAD " + code; +} +String getJNIType(Node node) { + NamedNodeMap attributes = node.getAttributes(); + String code = attributes.getNamedItem("type").getNodeValue(); + if (code.opEquals("c")) return "B"; + if (code.opEquals("i")) return "I"; + if (code.opEquals("s")) return "S"; + if (code.opEquals("l")) return "I"; + if (code.opEquals("q")) return "J"; + if (code.opEquals("C")) return "B"; + if (code.opEquals("I")) return "I"; + if (code.opEquals("S")) return "S"; + if (code.opEquals("L")) return "I"; + if (code.opEquals("Q")) return "J"; + if (code.opEquals("f")) return "F"; + if (code.opEquals("d")) return "D"; + if (code.opEquals("B")) return "Z"; + if (code.opEquals("v")) return "V"; + if (code.opEquals("*")) return "I"; + if (code.opEquals("@")) return "I"; + if (code.opEquals("#")) return "I"; + if (code.opEquals(":")) return "I"; + if (code.startsWith("^")) return "I"; + if (code.startsWith("[")) return "BAD " + code; + if (code.startsWith("{")) { + return "BAD " + code; + } + if (code.startsWith("(")) return "BAD " + code; + return "BAD " + code; +} + +String getJavaType(Node node) { + NamedNodeMap attributes = node.getAttributes(); + String code = attributes.getNamedItem("type").getNodeValue(); + if (code.opEquals("c")) return "byte"; + if (code.opEquals("i")) return "int"; + if (code.opEquals("s")) return "short"; + if (code.opEquals("l")) return "int"; + if (code.opEquals("q")) return "long"; + if (code.opEquals("C")) return "byte"; + if (code.opEquals("I")) return "int"; + if (code.opEquals("S")) return "short"; + if (code.opEquals("L")) return "int"; + if (code.opEquals("Q")) return "long"; + if (code.opEquals("f")) return "float"; + if (code.opEquals("d")) return "double"; + if (code.opEquals("B")) return "bool"; + if (code.opEquals("v")) return "void"; + if (code.opEquals("*")) return "int"; + if (code.opEquals("@")) { + String type = attributes.getNamedItem("declared_type").getNodeValue(); + int index = type.indexOf('*'); + if (index !is -1) type = type.substring(0, index); + index = type.indexOf('<'); + if (index !is -1) type = type.substring(0, index); + return type; + } + if (code.opEquals("#")) return "int"; + if (code.opEquals(":")) return "int"; + if (code.startsWith("^")) return "int"; + if (code.startsWith("[")) return "BAD " + code; + if (code.startsWith("{")) { + return attributes.getNamedItem("declared_type").getNodeValue(); + } + if (code.startsWith("(")) return "BAD " + code; + return "BAD " + code; +} + +public void generateFunctions() { + for (int x = 0; x < xml.length; x++) { + DOMParser parser = new DOMParser(); + parser.parse(xml[x]); + Document document = parser.getDocument(); + NodeList list = document.getDocumentElement().getChildNodes(); + for (int i = 0; i < list.getLength(); i++) { + Node node = list.item(i); + if ("function".opEquals(node.getLocalName())) { + NamedNodeMap attributes = node.getAttributes(); + String name = attributes.getNamedItem("name").getNodeValue(); + out("public static final native "); + Node returnNode = getReturnNode(node.getChildNodes()); + if (returnNode !is null) { + out(getType(returnNode)); + out(" "); + } else { + out("void "); + } + out(name); + out("("); + NodeList params = node.getChildNodes(); + bool first = true; + for (int j = 0; j < params.getLength(); j++) { + Node param = params.item(j); + if ("arg".opEquals(param.getLocalName())) { + NamedNodeMap paramAttributes = param.getAttributes(); + if (!first) out(", "); + out(getType(param)); + first = false; + out(" "); + out(paramAttributes.getNamedItem("name").getNodeValue()); + } + } + out(");"); + outln(); + } + } + } +} + +public void generateOS() { + out("/** Classes */"); + outln(); + generateClassesConst(); + outln(); + out("/** Selectors */"); + outln(); + generateSelectorsConst(); + outln(); + out("/** Constants */"); + outln(); + generateEnums(); + outln(); + out("/** Globals */"); + outln(); + generateConstants(); + outln(); + out("/** Functions */"); + outln(); + generateFunctions(); + outln(); + out("/** Sends */"); + outln(); + generateSends(); +} + +public void generateMetadata() { + generateConstantsMetaData(); + generateSendsMetaData(); +} + +public void setClasses(String[] classes) { + this.classes = classes; +} + +public void setOutputDir(String dir) { + this.outputDir = dir; +} + +public static void main(String[] args) { + MacGenerator gen = new MacGenerator(args); +// gen.setClasses(new String[]{ +// "NSURL", +// }); + gen.setOutputDir("/Users/adclabs/Desktop/workspace/dwt/Eclipse DWT PI/cocoa/org/eclipse/swt/internal/cocoa"); +// gen.generateOS(); +// gen.generateMetadata(); + gen.generateClasses(); +} +}