677 lines · 16.1 KB · Java
RawDownload
package javal; import java.io.File;import java.io.DataOutputStream;import java.io.FileOutputStream;import java.io.IOException; import java.lang.reflect.*;  publicclass LimboGen{	public LimboGen( Class cl, Field[] fields, Method[] methods, boolean verbose )	{		theClass     = cl;		this.fields  = fields;		this.methods = methods;		opt_verbose  = verbose; 		// create names		String full_name = cl.getName();		base_name  = ClassBaseName( full_name );		mod_name   = base_name +"_L";		limbo_dotm = mod_name +".m";		limbo_dotb = mod_name +".b"; 		// some class are "special" to javal		// if it is a special class we don't		// want to generate adt's for it and		// will use a special ADT name		special = true;  //assume special		obj_adt = SpecialClass( full_name ); 		if ( obj_adt == null )		{			special = false;			obj_adt = base_name +"_obj";		} 		// will only generate skeleton for native methods		natives     = GetNatives( methods );		has_natives = natives.length > 0; 		// need to distinguish between instance and static fields		iFields     = GetInstanceFields( fields );		sFields     = GetStaticFields( fields );	} 		/**	 * Generate a Limbo Module Declaration	 * file (.m) for a java class containing	 * native methods.	 */	public void DotM() throws IOException	{		// open a file 		out = MkFile( limbo_dotm ); 		// emit the Limbo Module File 		Emit( "# generated file edit with care\n\n" );		Emit( mod_name +" : module\n" );		Emit( "{\n" ); 		GenADT(); 		Emit( "\n" ); 		GenFct(false); 		Emit( "\n};\n" ); 		out.close(); 		if ( merge )		{			// save off existing .m and rename			// tmp to .m			File f = new File( limbo_dotm );			File o = new File("old_"+limbo_dotm);			File t = new File( tmpname ); 			if ( o.exists() ) o.delete();			f.renameTo( o );			t.renameTo( f ); 		} 	}  	/**	 * Generate a Limbo Module Implementation	 * Skeleton containing native methods for	 * a java class.	 */	public void DotB() throws IOException	{		// don't generate a .b if no natives		if ( ! has_natives ) return;  		// open a file 		out = MkFile( limbo_dotb ); 		// generate file prolog		Emit("implement "+ mod_name +";\n\n" );		Emit("include \"jni.m\";\n" );		Emit(T1+"jni : JNI;\n" );		Emit(T2+"ClassModule,\n");		Emit(T2+ T_JString +",\n");		Emit(T2+ T_JArray  +",\n");		Emit(T2+ T_JArrayI  +",\n");		Emit(T2+ T_JArrayC  +",\n");		Emit(T2+ T_JArrayB  +",\n");		Emit(T2+ T_JArrayS  +",\n");		Emit(T2+ T_JArrayJ  +",\n");		Emit(T2+ T_JArrayF  +",\n");		Emit(T2+ T_JArrayD  +",\n");		Emit(T2+ T_JArrayZ  +",\n");		Emit(T2+ T_JArrayJObject +",\n");		Emit(T2+ T_JArrayJClass +",\n");		Emit(T2+ T_JArrayJString +",\n");		Emit(T2+ T_JClass  +",\n");		Emit(T2+T_JObject +" : import jni;\n\n"); 		Emit("#>> extra pre includes here\n\n#<<\n\n"); 		Emit("include \""+ limbo_dotm +"\";\n\n" ); 		Emit("#>> extra post includes here\n\n#<<\n\n"); 		// generate a skeleton for init() and each native method		GenFct( true ); 		out.close(); 		if ( merge )			FileMerge.Merge( limbo_dotb, tmpname );	}  	/**	 * Generate an ADT declaration for the class	 * instance fields.	 */	private void GenADT() throws IOException	{		// don't generate an ADT decl for "special" clases		if ( special ) return; 		Emit( T1+ obj_adt +" : adt\n"+ T1+ "{\n" ); 		// emit the std object header		Emit( T2+ "cl_mod : ClassModule;\n" ); 		// walk through instance data emitting Limbo decl		for( int x=0; x<iFields.length; x++ )		{			Emit( T2+ GenFieldDecl( iFields[x] ) +";\n" );		} 		Emit( T1+ "};\n" );	} 	private void GenFct( boolean skel ) throws IOException	{		// generate init fct		GenInit( skel ); 		// walk native methods and generate		// a limbo fct		for( int x=0; x<natives.length; x++ )		{			String fct_name = MkFctName( natives[x] );			String this_param = ""; 			// if fct is virtual generate implicit this param			if ( ! Modifier.isStatic( natives[x].getModifiers() ) )			{				// if this is a special class then don't use ref				// because the generated special name is already a ref				this_param  = ( special ? "this : " : "this : ref " );				this_param += obj_adt;			} 			// determine fct parameters			String params = GenFctParams( natives[x].getParameterTypes() ); 			StringBuffer fct_params = new StringBuffer(80);			if ( this_param != "" )			{				fct_params.append( this_param );				if ( params != "" )					fct_params.append( ", " );			} 			fct_params.append( params ); 			// determine fct return type...if any			String fct_t    = LimboType( natives[x].getReturnType() );			if ( ! fct_t.equals("") )				fct_t = " : "+ fct_t; 			if ( skel )			{				Emit( fct_name +"( "+ 					  fct_params.toString() +")"+					  fct_t +"\n{#>>\n}#<<\n\n" ); 			}			else			{				Emit( T1+ fct_name +" : fn( "+ 			          fct_params.toString() +")"+ 					  fct_t +";\n" );			}		}	}  	/**	 * every Limbo Native module has a init()	 * function which the loader will call	 * when the native mod is loaded. This	 * method generates that fct.	 *	 * @param skel If true gen a fct skel; else fct decl	 *	 */	private void GenInit( boolean skel ) throws IOException	{		if ( skel )		{			Emit( "init( jni_p : JNI )\n{\n" );			Emit( T1+"# save java native inteface mod instance\n" );			Emit( T1+"jni = jni_p;\n" );			Emit( T1+"#>>extra initialization here\n"+T1+"#<<\n" );			Emit( "}\n\n" );		}		else		{			Emit( T1+"init : fn( jni_p : JNI );\n" );		}	}		/**	 * Given an array of types return a string with	 * a comma seperated sequence of java method	 * parameter declarations	 *	 * @param ptypes An array of types	 *	 * @return A string representing method param decls	 */			private String GenFctParams( Class[] ptypes )	{		String fct_params = "";		for( int x=0; x<ptypes.length; x++ )		{			fct_params = fct_params +"p"+ x +" : "+ LimboType( ptypes[x] );			if ( x <ptypes.length-1 )				fct_params = fct_params +",";		} 		return( fct_params );	} 		/**	 * Take a Java class data-field and	 * return a string with a coresponding	 * Limbo adt field declaration.	 *	 * @param fi The Java field descriptor	 *	 * @return Limbo Declaration	 */	private String GenFieldDecl( Field fi )	{		String fi_name   = fi.getName();		Class  java_type = fi.getType(); 		String limbo_type = LimboType( java_type ); 		return( fi_name +" : "+ limbo_type );	}  	/**	 * Accept a java Type descriptor and	 * return a corresponding limbo type	 * as a string. Return a empty string	 * if the type is void or an unknown.	 *	 * @param java_t Java type	 * 	 * @return Limbo type	 */	private String LimboType( Class java_t )	{		String limbo_t; 		if ( java_t.isPrimitive() )		{			// a java primitive type convert to appropriate limbo type			String t_name = java_t.getName();			if ( t_name.equals( "short"   ) ||				 t_name.equals( "char"    ) ||				 t_name.equals( "int"     )    )				limbo_t = "int";			else if ( t_name.equals( "long" ) )				limbo_t = "big";			else if ( t_name.equals( "float" ) ||					  t_name.equals( "double" )   )				limbo_t = "real";			else if ( t_name.equals( "byte"    ) ||					  t_name.equals( "boolean" ) )				limbo_t = "int"; // FIXME: should be byte here, but runtime seems to assume int			else 				limbo_t = ""; // void 		}		else		{			// a java reference (i.e. object or array) 			String t_name = java_t.getName(); 			if ( t_name.startsWith( "[" ) )				limbo_t = ArrayType( t_name );			else 				limbo_t = ClassName( t_name );		} 		return( limbo_t );	}			private String ArrayType( String name )	{		StringBuffer aryname = new StringBuffer(20);		aryname.append( T_JArray ); 		char let = name.charAt(1); 		if ( let == 'L' )		{			// array of some class, determine Limo name			aryname.append( ClassName( name.substring(2, name.length()-1) ) );		}		else if ( let == '[' )		{			// array of array...			// we only care about first level			;		}		else			aryname.append( name.substring(1) ); //append type					return( aryname.toString() );	}  	private String ClassName( String clname )	{		// we treat some classes special and 		// use specific Limbo adt's otherwise		// use the generic JObject		String sp_class = SpecialClass( clname );		if ( sp_class != null )			return( sp_class );		else if ( "java.io.FileDescriptor".equals(clname) )			return( T_JFd );		else if ( "inferno.vm.FD".equals(clname) )			return( T_JInfernoFD );		else if ( clname.endsWith( base_name ) )			return( "ref "+ obj_adt );		return( T_JObject );	}  	private String SpecialClass( String clname )	{		if ( "java.lang.String".equals(clname) )			return( T_JString );		else if ( "java.lang.Class".equals(clname) )			return( T_JClass );		else if ( "java.lang.Object".equals(clname) )			return( T_JObject );		else 			return( null );	} 	/** 	 * Scan methods list and return list of	 * native methods.	 *	 * @return Array of native methods, else array of length 0.	 */	private Method[] GetNatives( Method[] methods )	{		// walk the methods array and count natives		int native_count = 0;		for( int x=0; x<methods.length; x++ )			if ( Modifier.isNative( methods[x].getModifiers() ) )				native_count++;				if ( native_count == 0 ) return( new Method[0] ); 		if ( opt_verbose )			System.out.println( "Native Methods:" ); 		// now create an array to hold natives and fill it		Method[] natives = new Method[native_count];		native_count = 0;		for( int x=0; x<methods.length; x++ )			if ( Modifier.isNative( methods[x].getModifiers() ) )			{				natives[native_count++] = methods[x];				if ( opt_verbose )					System.out.println( "\t"+ methods[x] );			} 		return( natives );	}  	/**	 * Scan fields list and return list of	 * instance fields.	 *	 * @return Array of instnace fields, else array oflen 0	 */	private Field[] GetInstanceFields( Field[] fields )	{		// walk the fields array and count non-statics		int count = 0;		for( int x=0; x<fields.length; x++ )			if ( ! Modifier.isStatic( fields[x].getModifiers() ) )				count++;				if ( count == 0 ) return( new Field[0] ); 		if ( opt_verbose )			System.out.println( "Instance Fields:" ); 		// now create an array to hold instance-fields and fill it		Field[] iFields = new Field[count];		count = 0;		for( int x=0; x<fields.length; x++ )			if ( ! Modifier.isStatic( fields[x].getModifiers() ) )			{				iFields[count++] = fields[x];				if ( opt_verbose )					System.out.println( "\t"+ fields[x] );			} 		return( iFields );	}  	/**	 * Scan fields list and return list of	 * static fields.	 *	 * @return Array of static fields, else array oflen 0	 */	private Field[] GetStaticFields( Field[] fields )	{		// walk the fields array and count non-statics		int count = 0;		for( int x=0; x<fields.length; x++ )			if ( Modifier.isStatic( fields[x].getModifiers() ) )				count++;				if ( count == 0 ) return( new Field[0] ); 		if ( opt_verbose )			System.out.println( "Instance Fields:" ); 		// now create an array to hold instance-fields and fill it		Field[] sFields = new Field[count];		count = 0;		for( int x=0; x<fields.length; x++ )			if ( Modifier.isStatic( fields[x].getModifiers() ) )			{				sFields[count++] = fields[x];				if ( opt_verbose )					System.out.println( "\t"+ fields[x] );			} 		return( sFields );	}  	private String ClassBaseName( String name )	{		// for java.lang.Object return Object		// if last char is ';' strip it off (arrays) 

Lines 1–500 of 677.