Mercurial > projects > dwt-mac
view dwt/internal/cocoa/MacGenerator.d @ 13:f565d3a95c0a
Ported dwt.internal
author | Jacob Carlborg <doob@me.com> <jacob.carlborg@gmail.com> |
---|---|
date | Fri, 22 Aug 2008 16:46:34 +0200 |
parents | 380af2bdd8e5 |
children | 5b53d338c709 |
line wrap: on
line source
/******************************************************************************* * 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(); } }