Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4e70a9e4 authored by Jack Palevich's avatar Jack Palevich
Browse files

Improve glgen

+ gen script is really a bash script rather than a sh script,
  so declare that to be true. (For example, it uses pushd,
  which is a part of bash, but not a part of sh. Not sure
  how this worked until now. Possibly gen was only run in
  environments where /bin/sh was really bash.

+ Check the results of the java compile of the code generator,
  and abort the script if the compile fails.

+ Turn on the bash shell option that guards against using
  uninitialized variables in the script.

+ Remove the generated class files.

Refactor JniCodeEmitter into two classes: a general-purpose
JniCodeEmitter and a specific Jsr239CodeEmitter. The hope is
to use JniCodeEmitter as a base for emitting static OpenGL ES
bindings.
parent fb9edfd1
Loading
Loading
Loading
Loading
+9 −2
Original line number Original line Diff line number Diff line
#!/bin/sh
#!/bin/bash
set -u
rm -rf out generated
rm -rf out generated


mkdir out
mkdir out
@@ -12,12 +13,18 @@ echo "public interface Canvas {}" >> out/android/graphics/Canvas.java
GLFILE=out/javax/microedition/khronos/opengles/GL.java
GLFILE=out/javax/microedition/khronos/opengles/GL.java
cp stubs/GLHeader.java-if $GLFILE
cp stubs/GLHeader.java-if $GLFILE


GLGEN_FILES="CFunc.java CType.java CodeEmitter.java GenerateGL.java JFunc.java JType.java JniCodeEmitter.java ParameterChecker.java"
GLGEN_FILES="CFunc.java CType.java CodeEmitter.java GenerateGL.java JFunc.java JniCodeEmitter.java JType.java Jsr239CodeEmitter.java ParameterChecker.java"


pushd src > /dev/null
pushd src > /dev/null
javac ${GLGEN_FILES}
javac ${GLGEN_FILES}
JAVAC_RESULT=$?
if [ $JAVAC_RESULT -ne 0 ]; then
    echo "Could not compile glgen."
    exit $JAVAC_RESULT
fi
popd > /dev/null
popd > /dev/null
java -classpath src GenerateGL -c glspec-1.0 glspec-1.0ext glspec-1.1 glspec-1.1ext glspec-1.1extpack glspec-checks
java -classpath src GenerateGL -c glspec-1.0 glspec-1.0ext glspec-1.1 glspec-1.1ext glspec-1.1extpack glspec-checks
rm src/*.class


pushd out > /dev/null
pushd out > /dev/null
mkdir classes
mkdir classes
+1 −2
Original line number Original line Diff line number Diff line
@@ -23,7 +23,6 @@ public class GenerateGL {
                             PrintStream glImplStream,
                             PrintStream glImplStream,
                             PrintStream cStream) throws Exception {
                             PrintStream cStream) throws Exception {
        String s = null;
        String s = null;
        int counter = 0;
        while ((s = specReader.readLine()) != null) {
        while ((s = specReader.readLine()) != null) {
            if (s.trim().startsWith("//")) {
            if (s.trim().startsWith("//")) {
                continue;
                continue;
@@ -120,7 +119,7 @@ public class GenerateGL {
        ParameterChecker checker = new ParameterChecker(checksReader);
        ParameterChecker checker = new ParameterChecker(checksReader);


        CodeEmitter emitter =
        CodeEmitter emitter =
            new JniCodeEmitter(classPathName,
            new Jsr239CodeEmitter(classPathName,
                               checker,
                               checker,
                               gl10Stream, gl10ExtStream,
                               gl10Stream, gl10ExtStream,
                               gl11Stream, gl11ExtStream, gl11ExtPackStream,
                               gl11Stream, gl11ExtStream, gl11ExtPackStream,
+200 −279
Original line number Original line Diff line number Diff line
@@ -4,90 +4,47 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.Iterator;
import java.util.List;
import java.util.List;


/**
public class JniCodeEmitter {
 * Emits a Java interface and Java & C implementation for a C function.
 *
 * <p> The Java interface will have Buffer and array variants for functions that
 * have a typed pointer argument.  The array variant will convert a single "<type> *data"
 * argument to a pair of arguments "<type>[] data, int offset".
 */
public class JniCodeEmitter implements CodeEmitter {


    // If true, use C++ style for calling through a JNIEnv *:
    // env->Func(...)
    // If false, use C style:
    // (*env)->Func(env, ...)
    static final boolean mUseCPlusPlus = true;
    static final boolean mUseCPlusPlus = true;

    protected boolean mUseContextPointer = true;
    boolean mUseContextPointer = true;
    protected String mClassPathName;

    protected ParameterChecker mChecker;
    String mClassPathName;
    protected List<String> nativeRegistrations = new ArrayList<String>();

    ParameterChecker mChecker;
    PrintStream mJava10InterfaceStream;
    PrintStream mJava10ExtInterfaceStream;
    PrintStream mJava11InterfaceStream;
    PrintStream mJava11ExtInterfaceStream;
    PrintStream mJava11ExtPackInterfaceStream;
    PrintStream mJavaImplStream;
    PrintStream mCStream;

    PrintStream mJavaInterfaceStream;

    List<String> nativeRegistrations = new ArrayList<String>();

    boolean needsExit;
    boolean needsExit;

    protected static String indent = "    ";
    static String indent = "    ";

    HashSet<String> mFunctionsEmitted = new HashSet<String>();
    HashSet<String> mFunctionsEmitted = new HashSet<String>();


    /**
    public static String getJniName(JType jType) {
     * @param java10InterfaceStream the PrintStream to which to emit the Java interface for GL 1.0 functions
        String jniName = "";
     * @param java10ExtInterfaceStream the PrintStream to which to emit the Java interface for GL 1.0 extension functions
        if (jType.isClass()) {
     * @param java11InterfaceStream the PrintStream to which to emit the Java interface for GL 1.1 functions
            return "L" + jType.getBaseType() + ";";
     * @param java11ExtInterfaceStream the PrintStream to which to emit the Java interface for GL 1.1 Extension functions
        } else if (jType.isArray()) {
     * @param java11ExtPackInterfaceStream the PrintStream to which to emit the Java interface for GL 1.1 Extension Pack functions
            jniName = "[";
     * @param javaImplStream the PrintStream to which to emit the Java implementation
        }
     * @param cStream the PrintStream to which to emit the C implementation

     */
        String baseType = jType.getBaseType();
    public JniCodeEmitter(String classPathName,
        if (baseType.equals("int")) {
                          ParameterChecker checker,
            jniName += "I";
                          PrintStream java10InterfaceStream,
        } else if (baseType.equals("float")) {
                          PrintStream java10ExtInterfaceStream,
            jniName += "F";
                          PrintStream java11InterfaceStream,
        } else if (baseType.equals("boolean")) {
                          PrintStream java11ExtInterfaceStream,
            jniName += "Z";
                          PrintStream java11ExtPackInterfaceStream,
        } else if (baseType.equals("short")) {
                          PrintStream javaImplStream,
            jniName += "S";
                          PrintStream cStream,
        } else if (baseType.equals("long")) {
                          boolean useContextPointer) {
            jniName += "L";
        mClassPathName = classPathName;
        } else if (baseType.equals("byte")) {
        mChecker = checker;
            jniName += "B";
        mJava10InterfaceStream = java10InterfaceStream;
        mJava10ExtInterfaceStream = java10ExtInterfaceStream;
        mJava11InterfaceStream = java11InterfaceStream;
        mJava11ExtInterfaceStream = java11ExtInterfaceStream;
        mJava11ExtPackInterfaceStream = java11ExtPackInterfaceStream;
        mJavaImplStream = javaImplStream;
        mCStream = cStream;
        mUseContextPointer = useContextPointer;
    }

    public void setVersion(int version, boolean ext, boolean pack) {
        if (version == 0) {
            mJavaInterfaceStream = ext ? mJava10ExtInterfaceStream :
                mJava10InterfaceStream;
        } else if (version == 1) {
            mJavaInterfaceStream = ext ?
                (pack ? mJava11ExtPackInterfaceStream :
                 mJava11ExtInterfaceStream) :
                mJava11InterfaceStream;
        } else {
            throw new RuntimeException("Bad version: " + version);
        }
        }
        return jniName;
    }
    }


    public void emitCode(CFunc cfunc, String original) {

    public void emitCode(CFunc cfunc, String original,
            PrintStream javaInterfaceStream,
            PrintStream javaImplStream,
            PrintStream cStream) {
        JFunc jfunc;
        JFunc jfunc;
        String signature;
        String signature;
        boolean duplicate;
        boolean duplicate;
@@ -107,12 +64,12 @@ public class JniCodeEmitter implements CodeEmitter {
            }
            }


            if (!duplicate) {
            if (!duplicate) {
                emitNativeDeclaration(jfunc, mJavaImplStream);
                emitNativeDeclaration(jfunc, javaImplStream);
                emitJavaCode(jfunc, mJavaImplStream);
                emitJavaCode(jfunc, javaImplStream);
            }
            }
            emitJavaInterfaceCode(jfunc, mJavaInterfaceStream);
            emitJavaInterfaceCode(jfunc, javaInterfaceStream);
            if (!duplicate) {
            if (!duplicate) {
                emitJniCode(jfunc, mCStream);
                emitJniCode(jfunc, cStream);
            }
            }
        }
        }


@@ -127,12 +84,12 @@ public class JniCodeEmitter implements CodeEmitter {
        }
        }


        if (!duplicate) {
        if (!duplicate) {
            emitNativeDeclaration(jfunc, mJavaImplStream);
            emitNativeDeclaration(jfunc, javaImplStream);
        }
        }
        emitJavaInterfaceCode(jfunc, mJavaInterfaceStream);
        emitJavaInterfaceCode(jfunc, javaInterfaceStream);
        if (!duplicate) {
        if (!duplicate) {
            emitJavaCode(jfunc, mJavaImplStream);
            emitJavaCode(jfunc, javaImplStream);
            emitJniCode(jfunc, mCStream);
            emitJniCode(jfunc, cStream);
        }
        }
    }
    }


@@ -194,14 +151,13 @@ public class JniCodeEmitter implements CodeEmitter {
        out.println(iii + ");");
        out.println(iii + ");");
    }
    }


    void printIfcheckPostamble(PrintStream out, boolean isBuffer,
    void printIfcheckPostamble(PrintStream out, boolean isBuffer, boolean emitExceptionCheck,
                               boolean emitExceptionCheck, String iii) {
            String iii) {
                printIfcheckPostamble(out, isBuffer, emitExceptionCheck,
                printIfcheckPostamble(out, isBuffer, emitExceptionCheck,
                                      "offset", "_remaining", iii);
                                      "offset", "_remaining", iii);
            }
            }


    void printIfcheckPostamble(PrintStream out, boolean isBuffer,
    void printIfcheckPostamble(PrintStream out, boolean isBuffer, boolean emitExceptionCheck,
                               boolean emitExceptionCheck,
            String offset, String remaining, String iii) {
            String offset, String remaining, String iii) {
                out.println(iii + "    default:");
                out.println(iii + "    default:");
                out.println(iii + "        _needed = 0;");
                out.println(iii + "        _needed = 0;");
@@ -310,22 +266,14 @@ public class JniCodeEmitter implements CodeEmitter {
    }
    }


    void emitNativeBoundsChecks(CFunc cfunc, String cname, PrintStream out,
    void emitNativeBoundsChecks(CFunc cfunc, String cname, PrintStream out,
                                boolean isBuffer, boolean emitExceptionCheck,
            boolean isBuffer, boolean emitExceptionCheck, String offset, String remaining, String iii) {
                                String offset, String remaining, String iii) {
        CType returnType = cfunc.getType();
        boolean isVoid = returnType.isVoid();


                String[] checks = mChecker.getChecks(cfunc.getName());
                String[] checks = mChecker.getChecks(cfunc.getName());
        String checkVar;
        String retval = getErrorReturnValue(cfunc);


                boolean lastWasIfcheck = false;
                boolean lastWasIfcheck = false;


                int index = 1;
                int index = 1;
                if (checks != null) {
                if (checks != null) {
            boolean remainingDeclared = false;
            boolean nullCheckDeclared = false;
            boolean offsetChecked = false;
                    while (index < checks.length) {
                    while (index < checks.length) {
                        if (checks[index].startsWith("check")) {
                        if (checks[index].startsWith("check")) {
                            if (lastWasIfcheck) {
                            if (lastWasIfcheck) {
@@ -417,8 +365,7 @@ public class JniCodeEmitter implements CodeEmitter {
                }
                }
            }
            }


    boolean hasNonConstArg(JFunc jfunc, CFunc cfunc,
    boolean hasNonConstArg(JFunc jfunc, CFunc cfunc, List<Integer> nonPrimitiveArgs) {
        List<Integer> nonPrimitiveArgs) {
        if (nonPrimitiveArgs.size() > 0) {
        if (nonPrimitiveArgs.size() > 0) {
            for (int i = nonPrimitiveArgs.size() - 1; i >= 0; i--) {
            for (int i = nonPrimitiveArgs.size() - 1; i >= 0; i--) {
                int idx = nonPrimitiveArgs.get(i).intValue();
                int idx = nonPrimitiveArgs.get(i).intValue();
@@ -447,9 +394,7 @@ public class JniCodeEmitter implements CodeEmitter {
     *   if interfaceDecl:  public <returntype> func(args);
     *   if interfaceDecl:  public <returntype> func(args);
     *   if !interfaceDecl: public <returntype> func(args) { body }
     *   if !interfaceDecl: public <returntype> func(args) { body }
     */
     */
    void emitFunction(JFunc jfunc,
    void emitFunction(JFunc jfunc, PrintStream out, boolean nativeDecl, boolean interfaceDecl) {
                      PrintStream out,
                      boolean nativeDecl, boolean interfaceDecl) {
        boolean isPointerFunc =
        boolean isPointerFunc =
            jfunc.getName().endsWith("Pointer") &&
            jfunc.getName().endsWith("Pointer") &&
            jfunc.getCFunc().hasPointerArg();
            jfunc.getCFunc().hasPointerArg();
@@ -559,29 +504,43 @@ public class JniCodeEmitter implements CodeEmitter {
        out.println();
        out.println();
    }
    }


    public static String getJniName(JType jType) {
    public void addNativeRegistration(String s) {
        String jniName = "";
        nativeRegistrations.add(s);
        if (jType.isClass()) {
            return "L" + jType.getBaseType() + ";";
        } else if (jType.isArray()) {
            jniName = "[";
    }
    }


        String baseType = jType.getBaseType();
    public void emitNativeRegistration(PrintStream cStream) {
        if (baseType.equals("int")) {
        cStream.println("static const char *classPathName = \"" +
            jniName += "I";
                        mClassPathName +
        } else if (baseType.equals("float")) {
                        "\";");
            jniName += "F";
        cStream.println();
        } else if (baseType.equals("boolean")) {

            jniName += "Z";
        cStream.println("static JNINativeMethod methods[] = {");
        } else if (baseType.equals("short")) {

            jniName += "S";
        cStream.println("{\"_nativeClassInit\", \"()V\", (void*)nativeClassInit },");
        } else if (baseType.equals("long")) {

            jniName += "L";
        Iterator<String> i = nativeRegistrations.iterator();
        } else if (baseType.equals("byte")) {
        while (i.hasNext()) {
            jniName += "B";
            cStream.println(i.next());
        }
        }
        return jniName;

        cStream.println("};");
        cStream.println();


        cStream.println("int register_com_google_android_gles_jni_GLImpl(JNIEnv *_env)");
        cStream.println("{");
        cStream.println(indent +
                        "int err;");

        cStream.println(indent +
                        "err = android::AndroidRuntime::registerNativeMethods(_env, classPathName, methods, NELEM(methods));");

        cStream.println(indent + "return err;");
        cStream.println("}");
    }

    public JniCodeEmitter() {
        super();
    }
    }


    String getJniType(JType jType) {
    String getJniType(JType jType) {
@@ -721,8 +680,6 @@ public class JniCodeEmitter implements CodeEmitter {
        int numBuffers = 0;
        int numBuffers = 0;
        for (int i = 0; i < nonPrimitiveArgs.size(); i++) {
        for (int i = 0; i < nonPrimitiveArgs.size(); i++) {
            int idx = nonPrimitiveArgs.get(i).intValue();
            int idx = nonPrimitiveArgs.get(i).intValue();
            int cIndex = jfunc.getArgCIndex(idx);
            String cname = cfunc.getArgName(cIndex);
            if (jfunc.getArgType(idx).isArray()) {
            if (jfunc.getArgType(idx).isArray()) {
                ++numArrays;
                ++numArrays;
            }
            }
@@ -832,8 +789,6 @@ public class JniCodeEmitter implements CodeEmitter {
            out.println();
            out.println();
        }
        }


        String retval = isVoid ? "" : " _returnValue";

        // Emit 'GetPrimitiveArrayCritical' for arrays
        // Emit 'GetPrimitiveArrayCritical' for arrays
        // Emit 'GetPointer' calls for Buffer pointers
        // Emit 'GetPointer' calls for Buffer pointers
        int bufArgIdx = 0;
        int bufArgIdx = 0;
@@ -1047,38 +1002,4 @@ public class JniCodeEmitter implements CodeEmitter {
        out.println();
        out.println();
    }
    }


    public void addNativeRegistration(String s) {
        nativeRegistrations.add(s);
    }

    public void emitNativeRegistration() {
        mCStream.println("static const char *classPathName = \"" +
                        mClassPathName +
                        "\";");
        mCStream.println();

        mCStream.println("static JNINativeMethod methods[] = {");

        mCStream.println("{\"_nativeClassInit\", \"()V\", (void*)nativeClassInit },");

        Iterator<String> i = nativeRegistrations.iterator();
        while (i.hasNext()) {
            mCStream.println(i.next());
        }

        mCStream.println("};");
        mCStream.println();


        mCStream.println("int register_com_google_android_gles_jni_GLImpl(JNIEnv *_env)");
        mCStream.println("{");
        mCStream.println(indent +
                        "int err;");

        mCStream.println(indent +
                        "err = android::AndroidRuntime::registerNativeMethods(_env, classPathName, methods, NELEM(methods));");

        mCStream.println(indent + "return err;");
        mCStream.println("}");
    }
}
}
+74 −0
Original line number Original line Diff line number Diff line
import java.io.PrintStream;

/**
 * Emits a Java interface and Java & C implementation for a C function.
 *
 * <p> The Java interface will have Buffer and array variants for functions that
 * have a typed pointer argument.  The array variant will convert a single "<type> *data"
 * argument to a pair of arguments "<type>[] data, int offset".
 */
public class Jsr239CodeEmitter extends JniCodeEmitter implements CodeEmitter {

    PrintStream mJava10InterfaceStream;
    PrintStream mJava10ExtInterfaceStream;
    PrintStream mJava11InterfaceStream;
    PrintStream mJava11ExtInterfaceStream;
    PrintStream mJava11ExtPackInterfaceStream;
    PrintStream mJavaImplStream;
    PrintStream mCStream;

    PrintStream mJavaInterfaceStream;

    /**
     * @param java10InterfaceStream the PrintStream to which to emit the Java interface for GL 1.0 functions
     * @param java10ExtInterfaceStream the PrintStream to which to emit the Java interface for GL 1.0 extension functions
     * @param java11InterfaceStream the PrintStream to which to emit the Java interface for GL 1.1 functions
     * @param java11ExtInterfaceStream the PrintStream to which to emit the Java interface for GL 1.1 Extension functions
     * @param java11ExtPackInterfaceStream the PrintStream to which to emit the Java interface for GL 1.1 Extension Pack functions
     * @param javaImplStream the PrintStream to which to emit the Java implementation
     * @param cStream the PrintStream to which to emit the C implementation
     */
    public Jsr239CodeEmitter(String classPathName,
                          ParameterChecker checker,
                          PrintStream java10InterfaceStream,
                          PrintStream java10ExtInterfaceStream,
                          PrintStream java11InterfaceStream,
                          PrintStream java11ExtInterfaceStream,
                          PrintStream java11ExtPackInterfaceStream,
                          PrintStream javaImplStream,
                          PrintStream cStream,
                          boolean useContextPointer) {
        mClassPathName = classPathName;
        mChecker = checker;
        mJava10InterfaceStream = java10InterfaceStream;
        mJava10ExtInterfaceStream = java10ExtInterfaceStream;
        mJava11InterfaceStream = java11InterfaceStream;
        mJava11ExtInterfaceStream = java11ExtInterfaceStream;
        mJava11ExtPackInterfaceStream = java11ExtPackInterfaceStream;
        mJavaImplStream = javaImplStream;
        mCStream = cStream;
        mUseContextPointer = useContextPointer;
    }

    public void setVersion(int version, boolean ext, boolean pack) {
        if (version == 0) {
            mJavaInterfaceStream = ext ? mJava10ExtInterfaceStream :
                mJava10InterfaceStream;
        } else if (version == 1) {
            mJavaInterfaceStream = ext ?
                (pack ? mJava11ExtPackInterfaceStream :
                 mJava11ExtInterfaceStream) :
                mJava11InterfaceStream;
        } else {
            throw new RuntimeException("Bad version: " + version);
        }
    }

    public void emitCode(CFunc cfunc, String original) {
        emitCode(cfunc, original, mJavaInterfaceStream, mJavaImplStream, mCStream);
    }

    public void emitNativeRegistration() {
        emitNativeRegistration(mCStream);
    }
}