History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/tools/javal/LimboGen.java (1 of 18352 files). Show all

Unified · Split

java/tools/javal/LimboGen.java+677−0
@@ -0,0 +1,677 @@
1package javal;
2
3import java.io.File;
4import java.io.DataOutputStream;
5import java.io.FileOutputStream;
6import java.io.IOException;
7
8import java.lang.reflect.*;
9
10
11public
12class LimboGen
13{
14 public LimboGen( Class cl, Field[] fields, Method[] methods, boolean verbose )
15 {
16 theClass = cl;
17 this.fields = fields;
18 this.methods = methods;
19 opt_verbose = verbose;
20
21 // create names
22 String full_name = cl.getName();
23 base_name = ClassBaseName( full_name );
24 mod_name = base_name +"_L";
25 limbo_dotm = mod_name +".m";
26 limbo_dotb = mod_name +".b";
27
28 // some class are "special" to javal
29 // if it is a special class we don't
30 // want to generate adt's for it and
31 // will use a special ADT name
32 special = true; //assume special
33 obj_adt = SpecialClass( full_name );
34
35 if ( obj_adt == null )
36 {
37 special = false;
38 obj_adt = base_name +"_obj";
39 }
40
41 // will only generate skeleton for native methods
42 natives = GetNatives( methods );
43 has_natives = natives.length > 0;
44
45 // need to distinguish between instance and static fields
46 iFields = GetInstanceFields( fields );
47 sFields = GetStaticFields( fields );
48 }
49
50
51 /**
52 * Generate a Limbo Module Declaration
53 * file (.m) for a java class containing
54 * native methods.
55 */
56 public void DotM() throws IOException
57 {
58 // open a file
59 out = MkFile( limbo_dotm );
60
61 // emit the Limbo Module File
62
63 Emit( "# generated file edit with care\n\n" );
64 Emit( mod_name +" : module\n" );
65 Emit( "{\n" );
66
67 GenADT();
68
69 Emit( "\n" );
70
71 GenFct(false);
72
73 Emit( "\n};\n" );
74
75 out.close();
76
77 if ( merge )
78 {
79 // save off existing .m and rename
80 // tmp to .m
81 File f = new File( limbo_dotm );
82 File o = new File("old_"+limbo_dotm);
83 File t = new File( tmpname );
84
85 if ( o.exists() ) o.delete();
86 f.renameTo( o );
87 t.renameTo( f );
88
89 }
90
91 }
92
93
94 /**
95 * Generate a Limbo Module Implementation
96 * Skeleton containing native methods for
97 * a java class.
98 */
99 public void DotB() throws IOException
100 {
101 // don't generate a .b if no natives
102 if ( ! has_natives ) return;
103
104 // open a file
105 out = MkFile( limbo_dotb );
106
107 // generate file prolog
108 Emit("implement "+ mod_name +";\n\n" );
109 Emit("include \"jni.m\";\n" );
110 Emit(T1+"jni : JNI;\n" );
111 Emit(T2+"ClassModule,\n");
112 Emit(T2+ T_JString +",\n");
113 Emit(T2+ T_JArray +",\n");
114 Emit(T2+ T_JArrayI +",\n");
115 Emit(T2+ T_JArrayC +",\n");
116 Emit(T2+ T_JArrayB +",\n");
117 Emit(T2+ T_JArrayS +",\n");
118 Emit(T2+ T_JArrayJ +",\n");
119 Emit(T2+ T_JArrayF +",\n");
120 Emit(T2+ T_JArrayD +",\n");
121 Emit(T2+ T_JArrayZ +",\n");
122 Emit(T2+ T_JArrayJObject +",\n");
123 Emit(T2+ T_JArrayJClass +",\n");
124 Emit(T2+ T_JArrayJString +",\n");
125 Emit(T2+ T_JClass +",\n");
126 Emit(T2+T_JObject +" : import jni;\n\n");
127
128 Emit("#>> extra pre includes here\n\n#<<\n\n");
129
130 Emit("include \""+ limbo_dotm +"\";\n\n" );
131
132 Emit("#>> extra post includes here\n\n#<<\n\n");
133
134 // generate a skeleton for init() and each native method
135 GenFct( true );
136
137 out.close();
138
139 if ( merge )
140 FileMerge.Merge( limbo_dotb, tmpname );
141 }
142
143
144 /**
145 * Generate an ADT declaration for the class
146 * instance fields.
147 */
148 private void GenADT() throws IOException
149 {
150 // don't generate an ADT decl for "special" clases
151 if ( special ) return;
152
153 Emit( T1+ obj_adt +" : adt\n"+ T1+ "{\n" );
154
155 // emit the std object header
156 Emit( T2+ "cl_mod : ClassModule;\n" );
157
158 // walk through instance data emitting Limbo decl
159 for( int x=0; x<iFields.length; x++ )
160 {
161 Emit( T2+ GenFieldDecl( iFields[x] ) +";\n" );
162 }
163
164 Emit( T1+ "};\n" );
165 }
166
167 private void GenFct( boolean skel ) throws IOException
168 {
169 // generate init fct
170 GenInit( skel );
171
172 // walk native methods and generate
173 // a limbo fct
174 for( int x=0; x<natives.length; x++ )
175 {
176 String fct_name = MkFctName( natives[x] );
177 String this_param = "";
178
179 // if fct is virtual generate implicit this param
180 if ( ! Modifier.isStatic( natives[x].getModifiers() ) )
181 {
182 // if this is a special class then don't use ref
183 // because the generated special name is already a ref
184 this_param = ( special ? "this : " : "this : ref " );
185 this_param += obj_adt;
186 }
187
188 // determine fct parameters
189 String params = GenFctParams( natives[x].getParameterTypes() );
190
191 StringBuffer fct_params = new StringBuffer(80);
192 if ( this_param != "" )
193 {
194 fct_params.append( this_param );
195 if ( params != "" )
196 fct_params.append( ", " );
197 }
198
199 fct_params.append( params );
200
201 // determine fct return type...if any
202 String fct_t = LimboType( natives[x].getReturnType() );
203 if ( ! fct_t.equals("") )
204 fct_t = " : "+ fct_t;
205
206 if ( skel )
207 {
208 Emit( fct_name +"( "+
209 fct_params.toString() +")"+
210 fct_t +"\n{#>>\n}#<<\n\n" );
211
212 }
213 else
214 {
215 Emit( T1+ fct_name +" : fn( "+
216 fct_params.toString() +")"+
217 fct_t +";\n" );
218 }
219 }
220 }
221
222
223 /**
224 * every Limbo Native module has a init()
225 * function which the loader will call
226 * when the native mod is loaded. This
227 * method generates that fct.
228 *
229 * @param skel If true gen a fct skel; else fct decl
230 *
231 */
232 private void GenInit( boolean skel ) throws IOException
233 {
234 if ( skel )
235 {
236 Emit( "init( jni_p : JNI )\n{\n" );
237 Emit( T1+"# save java native inteface mod instance\n" );
238 Emit( T1+"jni = jni_p;\n" );
239 Emit( T1+"#>>extra initialization here\n"+T1+"#<<\n" );
240 Emit( "}\n\n" );
241 }
242 else
243 {
244 Emit( T1+"init : fn( jni_p : JNI );\n" );
245 }
246 }
247
248 /**
249 * Given an array of types return a string with
250 * a comma seperated sequence of java method
251 * parameter declarations
252 *
253 * @param ptypes An array of types
254 *
255 * @return A string representing method param decls
256 */
257 private String GenFctParams( Class[] ptypes )
258 {
259 String fct_params = "";
260 for( int x=0; x<ptypes.length; x++ )
261 {
262 fct_params = fct_params +"p"+ x +" : "+ LimboType( ptypes[x] );
263 if ( x <ptypes.length-1 )
264 fct_params = fct_params +",";
265 }
266
267 return( fct_params );
268 }
269
270
271 /**
272 * Take a Java class data-field and
273 * return a string with a coresponding
274 * Limbo adt field declaration.
275 *
276 * @param fi The Java field descriptor
277 *
278 * @return Limbo Declaration
279 */
280 private String GenFieldDecl( Field fi )
281 {
282 String fi_name = fi.getName();
283 Class java_type = fi.getType();
284
285 String limbo_type = LimboType( java_type );
286
287 return( fi_name +" : "+ limbo_type );
288 }
289
290
291 /**
292 * Accept a java Type descriptor and
293 * return a corresponding limbo type
294 * as a string. Return a empty string
295 * if the type is void or an unknown.
296 *
297 * @param java_t Java type
298 *
299 * @return Limbo type
300 */
301 private String LimboType( Class java_t )
302 {
303 String limbo_t;
304
305 if ( java_t.isPrimitive() )
306 {
307 // a java primitive type convert to appropriate limbo type
308 String t_name = java_t.getName();
309 if ( t_name.equals( "short" ) ||
310 t_name.equals( "char" ) ||
311 t_name.equals( "int" ) )
312 limbo_t = "int";
313 else if ( t_name.equals( "long" ) )
314 limbo_t = "big";
315 else if ( t_name.equals( "float" ) ||
316 t_name.equals( "double" ) )
317 limbo_t = "real";
318 else if ( t_name.equals( "byte" ) ||
319 t_name.equals( "boolean" ) )
320 limbo_t = "byte";
321 else
322 limbo_t = ""; // void
323
324 }
325 else
326 {
327 // a java reference (i.e. object or array)
328 String t_name = java_t.getName();
329
330 if ( t_name.startsWith( "[" ) )
331 limbo_t = ArrayType( t_name );
332 else
333 limbo_t = ClassName( t_name );
334 }
335
336 return( limbo_t );
337 }
338
339 private String ArrayType( String name )
340 {
341 StringBuffer aryname = new StringBuffer(20);
342 aryname.append( T_JArray );
343
344 char let = name.charAt(1);
345
346 if ( let == 'L' )
347 {
348 // array of some class, determine Limo name
349 aryname.append( ClassName( name.substring(2, name.length()-1) ) );
350 }
351 else if ( let == '[' )
352 {
353 // array of array...
354 // we only care about first level
355 ;
356 }
357 else
358 aryname.append( name.substring(1) ); //append type
359
360 return( aryname.toString() );
361 }
362
363
364 private String ClassName( String clname )
365 {
366 // we treat some classes special and
367 // use specific Limbo adt's otherwise
368 // use the generic JObject
369 String sp_class = SpecialClass( clname );
370 if ( sp_class != null )
371 return( sp_class );
372 else if ( "java.io.FileDescriptor".equals(clname) )
373 return( T_JFd );
374 else if ( "inferno.vm.FD".equals(clname) )
375 return( T_JInfernoFD );
376 else if ( clname.endsWith( base_name ) )
377 return( "ref "+ obj_adt );
378 return( T_JObject );
379 }
380
381
382 private String SpecialClass( String clname )
383 {
384 if ( "java.lang.String".equals(clname) )
385 return( T_JString );
386 else if ( "java.lang.Class".equals(clname) )
387 return( T_JClass );
388 else if ( "java.lang.Object".equals(clname) )
389 return( T_JObject );
390 else
391 return( null );
392 }
393
394 /**
395 * Scan methods list and return list of
396 * native methods.
397 *
398 * @return Array of native methods, else array of length 0.
399 */
400 private Method[] GetNatives( Method[] methods )
401 {
402 // walk the methods array and count natives
403 int native_count = 0;
404 for( int x=0; x<methods.length; x++ )
405 if ( Modifier.isNative( methods[x].getModifiers() ) )
406 native_count++;
407
408 if ( native_count == 0 ) return( new Method[0] );
409
410 if ( opt_verbose )
411 System.out.println( "Native Methods:" );
412
413 // now create an array to hold natives and fill it
414 Method[] natives = new Method[native_count];
415 native_count = 0;
416 for( int x=0; x<methods.length; x++ )
417 if ( Modifier.isNative( methods[x].getModifiers() ) )
418 {
419 natives[native_count++] = methods[x];
420 if ( opt_verbose )
421 System.out.println( "\t"+ methods[x] );
422 }
423
424 return( natives );
425 }
426
427
428 /**
429 * Scan fields list and return list of
430 * instance fields.
431 *
432 * @return Array of instnace fields, else array oflen 0
433 */
434 private Field[] GetInstanceFields( Field[] fields )
435 {
436 // walk the fields array and count non-statics
437 int count = 0;
438 for( int x=0; x<fields.length; x++ )
439 if ( ! Modifier.isStatic( fields[x].getModifiers() ) )
440 count++;
441
442 if ( count == 0 ) return( new Field[0] );
443
444 if ( opt_verbose )
445 System.out.println( "Instance Fields:" );
446
447 // now create an array to hold instance-fields and fill it
448 Field[] iFields = new Field[count];
449 count = 0;
450 for( int x=0; x<fields.length; x++ )
451 if ( ! Modifier.isStatic( fields[x].getModifiers() ) )
452 {
453 iFields[count++] = fields[x];
454 if ( opt_verbose )
455 System.out.println( "\t"+ fields[x] );
456 }
457
458 return( iFields );
459 }
460
461
462 /**
463 * Scan fields list and return list of
464 * static fields.
465 *
466 * @return Array of static fields, else array oflen 0
467 */
468 private Field[] GetStaticFields( Field[] fields )
469 {
470 // walk the fields array and count non-statics
471 int count = 0;
472 for( int x=0; x<fields.length; x++ )
473 if ( Modifier.isStatic( fields[x].getModifiers() ) )
474 count++;
475
476 if ( count == 0 ) return( new Field[0] );
477
478 if ( opt_verbose )
479 System.out.println( "Instance Fields:" );
480
481 // now create an array to hold instance-fields and fill it
482 Field[] sFields = new Field[count];
483 count = 0;
484 for( int x=0; x<fields.length; x++ )
485 if ( Modifier.isStatic( fields[x].getModifiers() ) )
486 {
487 sFields[count++] = fields[x];
488 if ( opt_verbose )
489 System.out.println( "\t"+ fields[x] );
490 }
491
492 return( sFields );
493 }
494
495
496 private String ClassBaseName( String name )
497 {
498 // for java.lang.Object return Object
499 // if last char is ';' strip it off (arrays)
500
501 int start = name.lastIndexOf( '.' );
502 int end = name.lastIndexOf( ';' );
503
504 // if neither found return name
505 if ( (start == -1) && (end==-1) ) return( name );
506
507 // adjust if ';' not found
508 end = ( (end==-1)? name.length() : end );
509
510 return( name.substring( start+1, end ) );
511 }
512
513
514 private String MkFctName( Method meth )
515 {
516 // build name from java method name
517 // java method param types, and the
518 // java method return type
519
520 StringBuffer encode = new StringBuffer(50);
521 encode.append(meth.getName());
522
523 // append parmeter encoding
524 Class[] jparam = meth.getParameterTypes();
525 for( int x=0; x<jparam.length; x++ )
526 {
527 encode.append( "_" );
528 encode.append( JTypeEncode( jparam[x] ) );
529 }
530
531 // append the method return type encoding
532 encode.append("_");
533 encode.append( JTypeEncode( meth.getReturnType() ) );
534
535 if ( opt_verbose )
536 System.out.println( "--mangled fct name:"+ encode );
537
538 return( encode.toString() );
539 }
540
541
542 private String JTypeEncode( Class jtype )
543 {
544 String t_name; //types name
545 String encode = ""; //limbo encoding
546
547 if ( jtype.isPrimitive() )
548 {
549 // a java primitive type convert to appropriate limbo type
550 t_name = jtype.getName();
551
552 // determine
553 if ( t_name.equals( "int" ) )
554 encode = "I";
555 else if ( t_name.equals( "char" ) )
556 encode = "C";
557 else if ( t_name.equals( "short" ) )
558 encode = "S";
559 else if ( t_name.equals( "long" ) )
560 encode = "J";
561 else if ( t_name.equals( "boolean" ) )
562 encode = "Z";
563 else if ( t_name.equals( "byte" ) )
564 encode = "B";
565 else if ( t_name.equals( "float" ) )
566 encode = "F";
567 else if ( t_name.equals( "double" ) )
568 encode = "D";
569 else
570 encode = "V";
571 }
572 else
573 {
574 // a java reference (i.e. object or array)
575 t_name = jtype.getName();
576
577 if ( t_name.indexOf( '[' ) == -1 )
578 {
579 // just an object reference
580 encode = "r"+ ClassBaseName( t_name );
581 }
582 else
583 {
584 // array
585 int x=0;
586 StringBuffer buf = new StringBuffer(40);
587 while( t_name.charAt(x)== '[' )
588 {
589 buf.append('a');
590 x++;
591 }
592 if ( t_name.charAt(x) == 'L' )
593 buf.append( ClassBaseName(t_name.substring(x+1)) );
594 else
595 buf.append( t_name.substring(x) );
596 encode = buf.toString();
597 }
598 }
599
600 return( encode );
601 }
602
603
604 private DataOutputStream MkFile( String name ) throws IOException
605 {
606 File f = new File( name );
607 FileOutputStream fout;
608
609 tmpname = "tmp_"+ name;
610
611 if ( f.exists() )
612 {
613 fout = new FileOutputStream( tmpname );
614 merge = true;
615 }
616 else
617 fout = new FileOutputStream( name );
618
619 return( new DataOutputStream( fout ) );
620 }
621
622 private void Emit( String info ) throws IOException
623 {
624 out.writeBytes( info );
625 }
626
627
628 // data fields
629 private String base_name; // name of class
630 private String mod_name; // module name of native "peer" module
631 private String limbo_dotm; // name of limbo module decl .m file
632 private String limbo_dotb; // name of limbo module impl .b file
633 private String obj_adt; // adt describing objects instance fields
634 private boolean special; // set true if a special class; a special
635 // class is one known to this tool.
636
637 Class theClass; // class descriptor object
638
639 DataOutputStream out; // current gen output file
640 boolean merge = false; // merge old and new gen'ed files
641 String tmpname;
642
643 Method[] methods; // all methods
644 Method[] natives; // native methods
645
646 Field[] fields; // all fields
647 Field[] iFields; // instance fields
648 Field[] sFields; // static fields
649
650 boolean opt_verbose; // print stuff if true
651 boolean has_natives; // set true if class has native methods
652
653 // consts
654 private static final String T1 = " ";
655 private static final String T2 = " ";
656 private static final String T3 = " ";
657
658 // generated Limbo/Java type names
659 private static final String T_JObject = "JObject";
660 private static final String T_JString = "JString";
661 private static final String T_JClass = "JClass";
662 private static final String T_JArrayI = "JArrayI";
663 private static final String T_JArrayC = "JArrayC";
664 private static final String T_JArrayS = "JArrayS";
665 private static final String T_JArrayB = "JArrayB";
666 private static final String T_JArrayJ = "JArrayJ";
667 private static final String T_JArrayF = "JArrayF";
668 private static final String T_JArrayD = "JArrayD";
669 private static final String T_JArrayZ = "JArrayZ";
670 private static final String T_JArrayJObject = "JArrayJObject";
671 private static final String T_JArrayJClass = "JArrayJClass";
672 private static final String T_JArrayJString = "JArrayJString";
673 private static final String T_JArray = "JArray";
674 private static final String T_JFd = "ref FileDescriptor_obj";
675 private static final String T_JInfernoFD = "ref Sys->FD";
676
677}