view dwt/internal/cocoa/MacGenerator.d @ 7:e831403a80a9

Add 'cast' to casts
author Frank Benoit <benoit@tionex.de>
date Wed, 27 Aug 2008 14:30:35 +0200
parents 380af2bdd8e5
children 30a762abda2a
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!cast(wchar);
        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!cast(wchar);
        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!cast(wchar);
        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("cast(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 = cast(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=cast(SEL)");
            outln();
        } else {
            out(key);
            out("_0=cast=(id)");
            outln();
            out(key);
            out("_1=cast=cast(SEL)");
            outln();
        }
        Node method = cast(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 = cast(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();
}
}