All Downloads are FREE. Search and download functionalities are using the official Maven repository.

oms3.nap.JNAFortran Maven / Gradle / Ivy

/*
 * $Id: JNAFortran.java efd1c3f7fd91 2018-12-10 [email protected] $
 * 
 * This file is part of the Object Modeling System (OMS),
 * 2007-2012, Olaf David and others, Colorado State University.
 *
 * OMS is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, version 2.1.
 *
 * OMS is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with OMS.  If not, see .
 */
package oms3.nap;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import org.apache.tools.ant.Task;

/**
 *
 * @author od
 */
public abstract class JNAFortran implements AnnotationHandler {

    String libname;
    String modName;
    String javaExecFunction;
    File srcFile;
    File genFile;
    String packageName;
    Map> compAnn;
    /**
     * All the declarations
     */
    List decl = new ArrayList();

    private static class Decl {

        Map> ann;
        String type;
        String name;
        String decl;

        Decl(Map> ann, String type, String name, String decl) {
            this.ann = ann;
            this.type = type;
            this.name = name;
            this.decl = decl.toLowerCase();
        }

        boolean isOut() {
            return ann.containsKey("Out");
        }

        boolean isIn() {
            return ann.containsKey("In");
        }

        boolean isScalar() {
            return type.equals("float") || type.equals("double") || type.equals("boolean")
                    || type.equals("int");
        }

        boolean isArray() {
            return type.endsWith("[]");
        }

        String getBaseType() {
            if (isArray()) {
                return type.substring(0, type.indexOf('['));
            }
            throw new RuntimeException("Not an array declaration: " + toString());
        }

        String getReferenceType() {
            if (type.equals("float")) {
                return "FloatByReference";
            } else if (type.equals("double")) {
                return "DoubleByReference";
            } else if (type.equals("int")) {
                return "IntByReference";
            }
            throw new IllegalArgumentException(type);
        }

        String getDimension() {
            if (isArray()) {
                String dim = decl.substring(decl.indexOf("dimension"));
                dim = dim.substring(dim.indexOf('(') + 1, dim.indexOf(')'));
                return dim.trim();
            }
            throw new RuntimeException("Illegal Dimension :" + decl);
        }

        //   fDecl  INTEGER(C_INT), VALUE :: erosion_inp_len
        static String getJavaType(String fDecl) {
            String d = fDecl.toLowerCase().trim();

            if (d.contains("c_float") && isArray(fDecl)) {
                return "float[]";
            } else if (d.contains("c_int") && isArray(fDecl)) {
                return "int[]";
            } else if (d.contains("c_double") && isArray(fDecl)) {
                return "double[]";
            } else if (d.contains("c_float")) {
                return "float";
            } else if (d.contains("c_int")) {
                return "int";
            } else if (d.contains("c_double")) {
                return "double";
            } else if (d.startsWith("char")) {
                return "String";
            }
            throw new IllegalArgumentException(fDecl);
        }

        static String[] getDeclNames(String fDecl) {
            String d = fDecl.toLowerCase().trim();
            String s[] = d.split("::");
            if (s.length != 2) {
                throw new IllegalArgumentException(fDecl);
            }
            return s[1].trim().split("\\s*,\\s*");
        }

        /**
         * Parse a single src line
         *
         * @param decl
         * @param ann
         * @return
         */
        static List parse(String decl, Map> ann) {
            List l = new ArrayList();
            String jType = getJavaType(decl);
            String[] names = getDeclNames(decl);
            for (String name : names) {
                l.add(new Decl(ann, jType, name, decl));
            }
            return l;
        }

        static boolean isArray(String fDecl) {
            String d = fDecl.toLowerCase().trim();
            return d.indexOf("dimension") > -1;
        }
    }
    JNAComponentTask task;
    private boolean rebuild;

    public JNAFortran(JNAComponentTask task) {
        this.task = task;
        this.rebuild = true;
    }

	public JNAFortran(JNAComponentTask task, boolean rebuild) {
        this.task = task;
        this.rebuild = rebuild;
    }

    public void setGenFile(File genFile) {
        this.genFile = genFile;
    }

    public void setSrcFile(File srcFile) {
        this.srcFile = srcFile;
    }

    void setRelativeFile(String incFile) {
        this.packageName = new File(incFile).getParent().toString();
    }

    public void setLibname(String libname) {
        this.libname = libname;
    }

    List getOutArrays(List l) {
        List o = new ArrayList();
        for (Decl decl : l) {
            if (decl.isArray() && decl.isOut() && !decl.isIn()) {
                o.add(decl);
            }
        }
        return o;
    }

    @Override
    public void handle(Map> ann, String line) {
        if (ann.containsKey("Execute")) {
            javaExecFunction = ann.get("Execute").get("value");
            if (javaExecFunction == null) {
                line = line.trim();
                javaExecFunction = line.substring(line.indexOf(' '), line.indexOf('('));
            } else {
                javaExecFunction = AnnotationParser.trimQuotes(javaExecFunction);
            }
            javaExecFunction = javaExecFunction.trim().toLowerCase();
            compAnn = ann;
        } else if (ann.containsKey("In") || ann.containsKey("Out")) {
            decl.addAll(Decl.parse(line.trim(), ann));
        }
    }

    @Override
    public void start(String src) {
        src = src.toLowerCase();
//        if (src.contains("module")) {
//            String line = src.substring(src.indexOf("module"));
//            line = src.substring(0, src.indexOf("\n"));
//            String[] mdecl = line.trim().split("\\s+");
//            if (mdecl.length > 0) {
//                modName = mdecl[1];
//            }
//        }
    }

    static File generateLib(JNAComponentTask task, File dir, List cl) throws FileNotFoundException {
        String libclassname = "Lib" + task.dllName;
        
        File o = new File(dir, "nap" + File.separatorChar + libclassname + ".java");
        o.getParentFile().mkdirs();
        PrintStream w = new PrintStream(o);

        w.println("// Generated at " + new Date());
        w.println("package nap;");
        w.println();
        w.println("import com.sun.jna.ptr.*;");
        w.println("import java.util.logging.Level;");
        w.println("import java.util.logging.Logger;");
        w.println("import oms3.annotations.*;");
        w.println();
        w.println(" @DLL(\"" + task.dllName + "\")");
        w.println(" public interface " + libclassname + " extends com.sun.jna.Library {");
        w.println("   // library mapping reference");
        w.println("   " + libclassname + " lib = oms3.util.NativeLibraries.bind(" + libclassname + ".class);");
        w.println("   " + libclassname + " synclib = (" + libclassname + ") com.sun.jna.Native.synchronizedLibrary(lib);");
        w.println();

        for (JNAFortran jNAFortran : cl) {
            w.println("   // DLL function");
              w.print("   void " + jNAFortran.getNativeName() + "(");

            for (int i = 0; i < jNAFortran.decl.size(); i++) {
                Decl d = jNAFortran.decl.get(i);
                if (d.isScalar()) {
                    w.print("\n     ByReference " + d.name);
                } else {
                    w.print("\n     " + d.type + " " + d.name);
                    if (d.type.equals("String")) {
                        w.print(", int " + d.name + "_len");
                    }
                }
                if (i < jNAFortran.decl.size() - 1) {
                    w.print(",");
                }
            }
            w.println(");");
            w.println();
        }
        w.println(" }");
        w.close();
        return o;
    }
    
    boolean valid = true;

    @Override
    public void done() throws Exception {
        if (javaExecFunction == null) {
            valid = false;
            return;
        }
        if(!rebuild) {
            return;
        }
        genFile.getParentFile().mkdirs();

        String className = genFile.getName().substring(0, genFile.getName().indexOf('.'));
        PrintStream w = new PrintStream(genFile);

        List outArr = getOutArrays(decl);

        w.println("// OMS3 Native proxy from '" + srcFile.getPath().replace('\\', '/') + "'");
        w.println("// Generated at " + new Date());
        w.println("package " + packageName.replace('/', '.') + ";");
        w.println();
        w.println("import com.sun.jna.ptr.*;");
        w.println("import java.util.logging.Level;");
        w.println("import java.util.logging.Logger;");
        w.println("import oms3.annotations.*;");
        w.println();

        compAnn.remove("Execute");
        
        String libclassname = "Lib" + task.dllName;
        String lib  = "lib";
        if (compAnn.containsKey("Synchronized")) {
            lib = "synclib";
            compAnn.remove("Synchronized");
        }
        
        w.print(AnnotationParser.toString(compAnn));
        w.println("public class " + className + " {");
        w.println();
        if (task.genlogging) {
            w.println("  static final Logger log = Logger.getLogger(\"oms3.model.\" +");
            w.println("           " + className + ".class.getName());");
        }

        if (task.gensingleton) {
            w.println("  private static " + className + " instance;");
            w.println("  public static synchronized " + className + " instance() {");
            w.println("    if (instance == null) {");
            w.println("      instance = new " + className + "();");
            w.println("    }");
            w.println("    return instance;");
            w.println("  }");
        }

        w.println();

        if (!outArr.isEmpty()) {
            w.println(" private boolean __shouldInit__ = true;");
        }
        w.println();

        for (Decl d : decl) {
            w.print(AnnotationParser.toString(d.ann));
            w.println(" public " + d.type + " " + d.name + ";");
            w.println();
        }

        w.println(" @Execute");
        w.println(" public void exec() throws Exception {");

        if (!outArr.isEmpty()) {
            w.println("  if(__shouldInit__) {");
            for (Decl decl : outArr) {
                w.println("      " + decl.name + " = new " + decl.getBaseType() + "[" + decl.getDimension() + "];");
            }
            w.println("      __shouldInit__ = false;");
            w.println("  }");
        }
        for (Decl d : decl) {
            if (d.isScalar()) {
                w.println("  " + d.getReferenceType() + " " + d.name + "__ = new " + d.getReferenceType() + "(" + d.name + ");");
            }
        }
        w.print("  nap." + libclassname + "." + lib + "." + getNativeName() + "(");
        for (int i = 0; i < decl.size(); i++) {
            Decl d = decl.get(i);
            w.print("\n     " + d.name);
            if (d.isScalar()) {
                w.print("__");
            }
            if (d.type.equals("String")) {
                w.print(", " + d.name + ".length()");
            }
            if (i < decl.size() - 1) {
                w.print(",");
            }
        }

        w.println(");");

        for (Decl d : decl) {
            if (d.isScalar() && d.isOut()) {
                w.println("  " + d.name + " = " + d.name + "__.getValue();");
            }
        }

        if (task.genlogging) {
            w.println("  if(log.isLoggable(Level.INFO)) {");
            w.println("   log.info(oms3.ComponentAccess.dump(this));");
            w.println("  }");
        }

        w.println(" }");
        w.println("}");
        w.close();

        // tag the timestamp.
        genFile.setLastModified(srcFile.lastModified());
    }

    String getNativeName() {
        return modName != null ? ("__" + modName + "_MOD_" + javaExecFunction)
                : javaExecFunction + "_";
    }

    public static void main(String[] args) throws Exception {
//        if (args.length != 1) {
//            return;
//        }
//
//        File natSrc = new File(args[0]);
//        File natSrc = new File(System.getProperty("user.dir") + "/test/oms3/ap/Arr.f90");
//        AnnotationHandler ah = new JNA();
//        AnnotationParser.handle(natSrc, ah);

        System.out.println(Arrays.toString(Decl.getDeclNames("CHARACTER(C_CHAR, len=hyd2er_len)  :: a")));
//        System.out.println(getDeclModifier("CHARACTER(C_CHAR, len=hyd2er_len)"));
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy