Milán Major

netscape-revival

1 branch
Code

sun-java/classsrc/netscape/tools/jric/HeaderGenerator.java

// Copyright (c) 1995 Netscape Communications Corporation. All rights reserved. 

package netscape.tools.jric;

import netscape.tools.ClassFileParser.*;
import java.io.*;

public 
class HeaderGenerator extends NativesGenerator {

    public HeaderGenerator(Main global, ClassDef clazz) {
	super(global, clazz);
    }

    protected String getFileName() {
	return clazzCName + ".h";
    }

    protected String getHeaderString() {
	return clazz.name + " header file\n * Generated by jric";
    }

    protected void generateOutput() throws IOException {
	int i;

	String prefix = clazz.getPrefix();

	out.println("#ifndef _" + clazzCName + "_H_");
	out.println("#define _" + clazzCName + "_H_\n");

	out.println("#include \"jri.h\"\n");

	out.println("#ifdef __cplusplus");
	out.println("extern \"C\" {");
	out.println("#endif /* __cplusplus */\n");

	for (i = 0; i < clazz.fields.length; i++) {
	    FieldDef field = clazz.fields[i];
	    forwardDeclare(field);
	}
	for (i = 0; i < clazz.methods.length; i++) {
	    MethodDef method = clazz.methods[i];
	    forwardDeclare(method);
	}
	out.println("struct java_lang_Class;\n");

	printBlockComment("Class " + clazz.name);

	out.println("typedef struct " + clazzCName + " "
		    + clazzCName + ";\n");
	out.println("#define classname_" + clazzCName + "\t\""
		    + clazz.name + "\"\n");
	out.println("#define class_" + clazzCName + "(env)\t\\");
	out.println("\t((struct java_lang_Class*)JRI_FindClass(env, classname_"
		    + clazzCName + "))\n");

	printBlockComment("Public Methods");
	out.println("#ifdef DEBUG\n");
	// Public Method Functions
	for (i = 0; i < clazz.methods.length; i++) {
	    MethodDef method = clazz.methods[i];
	    if (method.hasAccess(ClassFileParser.ACC_PUBLIC)) {
		method.describe(out);
		printMethodFunctionDecl(prefix, method, i, false);
	    }
	}
	out.println("#else /* !DEBUG */\n");
	// Public Method Macros
	for (i = 0; i < clazz.methods.length; i++) {
	    MethodDef method = clazz.methods[i];
	    if (method.hasAccess(ClassFileParser.ACC_PUBLIC)) {
		method.describe(out);
		printMethodMacroDecl(prefix, method, i);
	    }
	}
	out.println("#endif /* !DEBUG */\n");
	// Public Method Info
	for (i = 0; i < clazz.methods.length; i++) {
	    MethodDef method = clazz.methods[i];
	    if (method.hasAccess(ClassFileParser.ACC_PUBLIC)) {
		method.describe(out);
		printMethodInfo(prefix, method, i);
	    }
	}

	printBlockComment("Public Fields");
	out.println("#ifdef DEBUG\n");
	// Public Field Functions
	for (i = 0; i < clazz.fields.length; i++) {
	    FieldDef field = clazz.fields[i];
	    if (field.hasAccess(ClassFileParser.ACC_PUBLIC)) {
		field.describe(out);
		printFieldFunctionDecl(field);
	    }
	}
	out.println("#else /* !DEBUG */\n");
	// Public Field Macros
	for (i = 0; i < clazz.fields.length; i++) {
	    FieldDef field = clazz.fields[i];
	    if (field.hasAccess(ClassFileParser.ACC_PUBLIC)) {
		field.describe(out);
		printFieldMacroDecl(field);
	    }
	}
	out.println("#endif /* !DEBUG */\n");
	// Public Field Info
	for (i = 0; i < clazz.fields.length; i++) {
	    FieldDef field = clazz.fields[i];
	    if (field.hasAccess(ClassFileParser.ACC_PUBLIC)) {
		field.describe(out);
		printFieldInfo(field);
	    }
	}

	printBlockComment("IMPLEMENTATION SECTION: \n" +
			  " * Define the IMPLEMENT_" + clazzCName + " symbol \n" +
			  " * if you intend to implement the native methods of this class. This \n" +
			  " * symbol makes the private and protected methods available. You should \n" +
			  " * also call the register_" + clazzCName + " routine \n" +
			  " * to make your native methods available.");

	out.println("extern JRI_PUBLIC_API(struct java_lang_Class*)");
	out.println("use_" + clazzCName + "(JRIEnv* env);\n");

	out.println("extern JRI_PUBLIC_API(void)");
	out.println("unuse_" + clazzCName + "(JRIEnv* env);\n");

	out.println("extern JRI_PUBLIC_API(struct java_lang_Class*)");
	out.println("register_" + clazzCName + "(JRIEnv* env);\n");

	out.println("extern JRI_PUBLIC_API(void)");
	out.println("unregister_" + clazzCName + "(JRIEnv* env);\n");

	out.println("#ifdef IMPLEMENT_" + clazzCName + "\n");

	printBlockComment("Native Methods:\n" + 
			  " * These are the signatures of the native methods which you must implement.");
	for (i = 0; i < clazz.methods.length; i++) {
	    MethodDef method = clazz.methods[i];
	    if (method.hasAccess(ClassFileParser.ACC_NATIVE)) {
		method.describe(out);
		printMethodFunctionDecl(prefix, method, i, true);
	    }
	}

	printBlockComment("Implementation Methods:\n" + 
			  " * You should only use these from within the native method definitions.");
	out.println("#ifdef DEBUG\n");
	// Implementation Method Functions
	for (i = 0; i < clazz.methods.length; i++) {
	    MethodDef method = clazz.methods[i];
	    if (!method.hasAccess(ClassFileParser.ACC_PUBLIC)) {
		method.describe(out);
		printMethodFunctionDecl(prefix, method, i, false);
	    }
	}
	out.println("#else /* !DEBUG */\n");
	// Implementation Method Macros
	for (i = 0; i < clazz.methods.length; i++) {
	    MethodDef method = clazz.methods[i];
	    if (!method.hasAccess(ClassFileParser.ACC_PUBLIC)) {
		method.describe(out);
		printMethodMacroDecl(prefix, method, i);
	    }
	}
	out.println("#endif /* !DEBUG */\n");
	// Implementation Method Info
	for (i = 0; i < clazz.methods.length; i++) {
	    MethodDef method = clazz.methods[i];
	    if (!method.hasAccess(ClassFileParser.ACC_PUBLIC)) {
		method.describe(out);
		printMethodInfo(prefix, method, i);
	    }
	}

	printBlockComment("Implementation Fields:\n" + 
			  " * You should only use these from within the native method definitions.");
	out.println("#ifdef DEBUG\n");
	// Implementation Field Functions
	for (i = 0; i < clazz.fields.length; i++) {
	    FieldDef field = clazz.fields[i];
	    if (!field.hasAccess(ClassFileParser.ACC_PUBLIC)) {
		field.describe(out);
		printFieldFunctionDecl(field);
	    }
	}
	out.println("#else /* !DEBUG */\n");
	// Implementation Field Macros
	for (i = 0; i < clazz.fields.length; i++) {
	    FieldDef field = clazz.fields[i];
	    if (!field.hasAccess(ClassFileParser.ACC_PUBLIC)) {
		field.describe(out);
		printFieldMacroDecl(field);
	    }
	}
	out.println("#endif /* !DEBUG */\n");
	// Implementation Field Info
	for (i = 0; i < clazz.fields.length; i++) {
	    FieldDef field = clazz.fields[i];
	    if (!field.hasAccess(ClassFileParser.ACC_PUBLIC)) {
		field.describe(out);
		printFieldInfo(field);
	    }
	}

	out.println("#endif /* IMPLEMENT_" + clazzCName + " */\n");

	out.println("#ifdef __cplusplus");
	out.println("} /* extern \"C\" */\n");

	//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
	printBlockComment("C++ Definitions");

	for (i = 0; i < clazz.interfaces.length; i++) {
	    ClassDef intf = clazz.interfaces[i];
	    out.println("#include \"" + intf.getCName()
			+ ".h\"");
	}
	if (clazz.superclass != null) {
	    out.println("#include \"" + 
			clazz.superclass.getCName()
			+ ".h\"\n");
	}
	out.print("struct " + clazzCName);
	boolean needsColon = true;
	for (i = 0; i < clazz.interfaces.length; i++) {
	    ClassDef intf = clazz.interfaces[i];
	    out.print((needsColon ? " :" : ",") + " public "
		      + intf.getCName());
	    needsColon = false;
	}
	if (clazz.superclass != null) {
	    out.print((needsColon ? " :" : ",") + " public "
		      + clazz.superclass.getCName());
	    needsColon = false;
	}
	out.println(" {\n");

	out.println("\tstatic struct java_lang_Class* _use(JRIEnv* env) {");
	out.println("\t\treturn use_" + clazzCName + "(env);\n\t}\n");

	out.println("\tstatic void _unuse(JRIEnv* env) {");
	out.println("\t\tunuse_" + clazzCName + "(env);\n\t}\n");

	out.println("\tstatic struct java_lang_Class* _register(JRIEnv* env) {");
	out.println("\t\treturn register_" + clazzCName + "(env);\n\t}\n");

	out.println("\tstatic void _unregister(JRIEnv* env) {");
	out.println("\t\tunregister_" + clazzCName + "(env);\n\t}\n");

	out.println("\tstatic struct java_lang_Class* _class(JRIEnv* env) {");
	out.println("\t\treturn class_" + clazzCName + "(env);\n\t}\n");

	out.println("\t/* Public Fields */");
	for (i = 0; i < clazz.fields.length; i++) {
	    FieldDef field = clazz.fields[i];
	    if (field.hasAccess(ClassFileParser.ACC_PUBLIC)
		&& !field.hasAccess(ClassFileParser.ACC_STATIC)) {
		out.print("\t");
		field.describe(out);
		printFieldCppDecl(field);
	    }
	}

	out.println("\t/* Public Methods */");
	for (i = 0; i < clazz.methods.length; i++) {
	    MethodDef method = clazz.methods[i];
	    if (method.hasAccess(ClassFileParser.ACC_PUBLIC)) {
		out.print("\t");
		method.describe(out);
		printMethodCppDecl(prefix, method, i);
	    }
	}

	out.println("#ifdef IMPLEMENT_" + clazzCName + "\n");

	out.println("\t/* Implementation Fields */");
	for (i = 0; i < clazz.fields.length; i++) {
	    FieldDef field = clazz.fields[i];
	    if (!field.hasAccess(ClassFileParser.ACC_PUBLIC)
		&& !field.hasAccess(ClassFileParser.ACC_STATIC)) {
		out.print("\t");
		field.describe(out);
		printFieldCppDecl(field);
	    }
	}

	out.println("\t/* Implementation Methods */");
	for (i = 0; i < clazz.methods.length; i++) {
	    MethodDef method = clazz.methods[i];
	    if (!method.hasAccess(ClassFileParser.ACC_PUBLIC)) {
		out.print("\t");
		method.describe(out);
		printMethodCppDecl(prefix, method, i);
	    }
	}

	out.println("#endif /* IMPLEMENT_" + clazzCName + " */\n");
	out.println("};\n");

	//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
	out.println("#endif /* __cplusplus */\n");

	out.println("#endif /* _" + clazzCName + "_H_ */");
    }

    //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
    // C Utilities
    protected void printMethodFunctionDecl(String prefix, MethodDef method, 
					   int methodIndex, boolean printAsNative) {
/*
	int i;
	boolean comment = true;
	for (i = 0; i < method.attributes.length; i++) {
	    if (comment) {
		out.println("/"+"*");
		comment = false;
	    }
	    method.attributes[i].describe(out);
	}
	System.out.println("method args = "+method.getParamNames());
	if (!comment) {
	    out.println("\n*"+"/");
	}
*/
	out.print("extern ");
	printMethodFunctionSig(prefix, method, methodIndex, printAsNative);
	out.println(";\n");
    }

    protected void printMethodMacroDecl(String prefix, MethodDef method, int methodIndex) {
	out.print("#define ");
	String fname = method.getCName(methodIndex);
	out.print(prefix + "_" + fname);
	printMethodArgUse(prefix, method, methodIndex, false, false);
	out.print("\t\\\n\t(");
	printInvocation(prefix, method, methodIndex);
	out.print(")\n\n");
    }

    protected void printInvocation(String prefix, MethodDef method, int methodIndex) {
	String opName;
	if (method.hasAccess(ClassFileParser.ACC_STATIC))
	    opName = "JRI_CallStaticMethod";
	else if (method.isConstructor())
	    opName = "JRI_NewObject";
	else
	    opName = "JRI_CallMethod";
	out.print("(" + getResultTypeName(method) + ")"
		  + opName + getResultSuffix(method) + "(env)");
	printMethodArgUse(prefix, method, methodIndex, true, false);
    }

    protected void printMethodInfo(String prefix, MethodDef method, int methodIndex) {
	String cName = prefix + "_" + method.getCName(methodIndex);
	out.println("extern JRIMethodID FAR methodID_" + cName + ";");
	out.println("#define name_" + cName + "\t\"" + method.name + "\"");
	out.println("#define sig_" + cName + "\t\"" + method.signature + "\"");

	out.println("#define use_" + cName + "(env, clazz)\t\\");
	out.println("\t(methodID_" + cName + " =\t\\");
	out.println("\t\tJRI_GetMethodID(env, clazz,\t\\");
	out.println("\t\t\tname_" + cName + ",\t\\");
	out.println("\t\t\tsig_" + cName + "))");

	out.println("#define unuse_" + cName + "(env, clazz)\t\\");
	out.println("\t(methodID_" + cName + " = JRIUninitialized)\n");
    }

    protected void printFieldFunctionDecl(FieldDef field) {
	out.print("extern ");
	printGetterFunctionSig(field);
	out.println(";");
	out.print("extern ");
	printSetterFunctionSig(field);
	out.println(";\n");
    }

    protected void printFieldMacroDecl(FieldDef field) {
	out.print("#define get_" + field.getCName());
	printGetterArgUse(field, false);
	out.print("\t\\\n\t(");
	printGetter(field);
	out.print(")\n");
	out.print("#define set_" + field.getCName());
	printSetterArgUse(field, false);
	out.print("\t\\\n\t(");
	printSetter(field);
	out.print(")\n\n");
    }

    protected void printGetter(FieldDef field) {
	String opName;
	if (field.hasAccess(ClassFileParser.ACC_STATIC))
	    opName = "JRI_GetStaticField";
	else
	    opName = "JRI_GetField";
	out.print("(" + getTypeName(field.signature, 0) + ")" + opName
		  + getSuffix(field.signature, 0));
	printGetterArgUse(field, true);
    }

    protected void printSetter(FieldDef field) {
	String opName;
	if (field.hasAccess(ClassFileParser.ACC_STATIC))
	    opName = "JRI_SetStaticField";
	else
	    opName = "JRI_SetField";
	out.print(opName
		  + getSuffix(field.signature, 0));
	printSetterArgUse(field, true);
    }

    protected void printGetterFunctionSig(FieldDef field) {
	String fname = field.getCName();
	String resultType = getTypeName(field.signature, 0);
	out.println("JRI_PUBLIC_API(" + resultType + ")");
	out.print("get_" + fname);
	printGetterArgDecl(field);
    }

    protected void printSetterFunctionSig(FieldDef field) {
	String fname = field.getCName();
	out.println("JRI_PUBLIC_API(void)");
	out.print("set_" + fname);
	printSetterArgDecl(field);
    }

    protected void printFieldInfo(FieldDef field) {
	String cName = field.getCName();
	out.println("extern JRIFieldID FAR fieldID_" + cName + ";");
	out.println("#define name_" + cName + "\t\"" + field.name + "\"");
	out.println("#define sig_" + cName + "\t\"" + field.signature
		    + "\"");

	out.println("#define use_" + cName + "(env, clazz)\t\\");
	out.println("\t(fieldID_" + cName + " =\t\\");
	out.println("\t\tJRI_GetFieldID(env, clazz,\t\\");
	out.println("\t\t\tname_" + cName + ",\t\\");
	out.println("\t\t\tsig_" + cName + "))");

	out.println("#define unuse_" + cName + "(env, clazz)\t\\");
	out.println("\t(fieldID_" + cName + " = JRIUninitialized)\n");
    }

    //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
    // C++ Utilities

    protected void printFieldCppDecl(FieldDef field) {
	out.println("\t" + getTypeName(field.signature, 0) + " "
		    + field.name + "(JRIEnv* env) {");
	out.println("\t\treturn get_" + field.getCName()
		    + "(env, this);\n\t}");
	out.println("\tvoid " + field.name
		    + "(JRIEnv* env, " +  getTypeName(field.signature, 0)
		    + " v) {");
	out.println("\t\tset_" + field.getCName()
		    + "(env, this, v);\n\t}\n");
    }

    protected void printMethodCppDecl(String prefix, MethodDef method, int methodIndex) {
	String resultType = getResultTypeName(method);
	out.print("\t"
		  + (method.hasAccess(ClassFileParser.ACC_STATIC)
		     || method.isConstructor() ? "static " : "")
		  + resultType + " " + method.getCppName(methodIndex));
	printMethodArgDecl(method, true);
	out.print(" {\n\t\t");
	if (!resultType.equals("void"))
	    out.print("return ");
	out.print(prefix + "_" + method.getCName(methodIndex));
	printMethodArgUse(prefix, method, methodIndex, false, true);
	out.println(";\n\t}\n");
    }

}