This commit was manufactured by cvs2svn to create tag
[cacao.git] / headers.c
1 /* headers.c - main for header generation (cacaoh)
2
3    Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
4    R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser,
5    M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck,
6    P. Tomsich, J. Wenninger
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
23    02111-1307, USA.
24
25    Contact: cacao@complang.tuwien.ac.at
26
27    Authors: Reinhard Grafl
28
29    Changes: Mark Probst
30             Philipp Tomsich
31
32    $Id: headers.c 583 2003-11-09 19:14:31Z twisti $
33
34 */
35
36
37 #include <stdlib.h>
38 #include <string.h>
39 #include "config.h"
40 #include "global.h"
41 #include "tables.h"
42 #include "loader.h"
43 #include "toolbox/chain.h"
44 #include "toolbox/memory.h"
45 #include "toolbox/loging.h"
46
47
48 /******* replace some external functions  *********/
49  
50 functionptr native_findfunction (utf *cname, utf *mname, utf *desc, bool isstatic)
51 { return NULL; }
52
53 java_objectheader *javastring_new (utf *text)         /* schani */
54 { return NULL; }
55
56 void throw_classnotfoundexception() 
57
58         panic("class not found"); 
59 }
60
61 java_objectheader *literalstring_new (utf *u)
62 { return NULL; }  
63
64 void literalstring_free(java_objectheader *o) { }
65 void stringtable_update() { }
66 void synchronize_caches() { }
67 void asm_call_jit_compiler() { }
68 void asm_calljavamethod() { }
69 void asm_dumpregistersandcall() { }
70 s4 asm_builtin_checkcast(java_objectheader *obj, classinfo *class) { return 0; }
71
72 s4 asm_builtin_idiv(s4 a, s4 b) {return 0;}
73 s4 asm_builtin_irem(s4 a, s4 b) {return 0;}
74 s8 asm_builtin_ldiv(s8 a, s8 b) {return 0;}
75 s8 asm_builtin_lrem(s8 a, s8 b) {return 0;}
76
77 s4 asm_builtin_f2i(float a) { return 0; }
78 s8 asm_builtin_f2l(float a) { return 0; }
79 s4 asm_builtin_d2i(double a) { return 0; }
80 s8 asm_builtin_d2l(double a) { return 0; }
81
82 void asm_builtin_monitorenter(java_objectheader *o) {}
83 void asm_builtin_monitorexit(java_objectheader *o) {}
84
85 s4 asm_builtin_checkarraycast(java_objectheader *o, constant_arraydescriptor *d) {return 0;}
86
87 #if defined(__I386__)
88 s4 asm_builtin_arrayinstanceof(java_objectheader *obj, classinfo *class) { return 0; }
89 void asm_builtin_anewarray(s4 size, classinfo *elementtype) {}
90 void asm_builtin_newarray_array(s4 size, constant_arraydescriptor *elementdesc) {}
91 #endif
92 void asm_builtin_aastore(java_objectarray *a, s4 index, java_objectheader *o) {}
93
94 u1 *createcompilerstub(methodinfo *m) {return NULL;}
95 u1 *createnativestub(functionptr f, methodinfo *m) {return NULL;}
96 u1 *oldcreatenativestub(functionptr f, methodinfo *m) {return NULL;}
97
98 void removecompilerstub(u1 *stub) {}
99 void removenativestub(u1 *stub) {}
100
101 void asm_perform_threadswitch(u1 **from, u1 **to) {}
102 u1* asm_initialize_thread_stack(void *func, u1 *stack) { return NULL; }
103 void asm_switchstackandcall() {}
104 void asm_handle_builtin_exception(classinfo *c) {}
105
106 java_objectheader *native_new_and_init(void *p) { return NULL; }
107
108 /************************ global variables **********************/
109
110 java_objectheader *exceptionptr;                       /* schani */
111
112 bool verbose =  false;
113 bool runverbose = false;
114 bool collectverbose = false;
115
116 static chain *nativemethod_chain;                              /* chain with native methods     */
117 static chain *nativeclass_chain;                               /* chain with processed classes  */      
118 static chain *ident_chain;        /* chain with method and field names in current class */
119 static FILE *file = NULL;
120 static u4 outputsize;
121 static bool dopadding;
122
123
124 static void printIDpart(int c) 
125 {
126         if ((c >= 'a' && c <= 'z')
127                 || (c >= 'A' && c <= 'Z')
128                 || (c >= '0' && c <= '9')
129                 || (c == '_'))
130                 putc(c, file);
131         else
132                 putc('_', file);
133 }
134
135
136 static void printID(utf *u)
137 {
138         char *utf_ptr = u->text;
139         int i;
140
141         for (i = 0; i < utf_strlen(u); i++) 
142                 printIDpart(utf_nextu2(&utf_ptr));
143 }
144
145
146 static void addoutputsize (int len)
147 {
148         u4 newsize,i;
149         if (!dopadding) return;
150
151         newsize = ALIGN(outputsize, len);
152         
153         for (i = outputsize; i < newsize; i++) fprintf(file, "   u1 pad%d\n", (int) i);
154         outputsize = newsize;
155 }
156
157
158 static char *printtype (char *utf_ptr)
159 {
160         u2 c;
161
162         switch (utf_nextu2(&utf_ptr)) {
163         case 'V': fprintf (file, "void");
164                 break;
165         case 'I':
166         case 'S':
167         case 'B':
168         case 'C':
169         case 'Z': addoutputsize (4);
170                 fprintf (file, "s4");
171                 break;
172         case 'J': addoutputsize (8);
173                 fprintf (file, "s8");
174                 break;
175         case 'F': addoutputsize (4);
176                 fprintf (file, "float");
177                 break;
178         case 'D': addoutputsize (8);
179                 fprintf (file, "double");
180                 break;
181         case '[':
182                 addoutputsize ( sizeof(java_arrayheader*) ); 
183                 switch (utf_nextu2(&utf_ptr)) {
184                 case 'I':  fprintf (file, "java_intarray*"); break;
185                 case 'J':  fprintf (file, "java_longarray*"); break;
186                 case 'Z':  fprintf (file, "java_booleanarray*"); break;
187                 case 'B':  fprintf (file, "java_bytearray*"); break;
188                 case 'S':  fprintf (file, "java_shortarray*"); break;
189                 case 'C':  fprintf (file, "java_chararray*"); break;
190                 case 'F':  fprintf (file, "java_floatarray*"); break;
191                 case 'D':  fprintf (file, "java_doublearray*"); break;
192                                 
193                 case '[':  fprintf (file, "java_arrayarray*");                                         
194                         while ((c = utf_nextu2(&utf_ptr)) == '[') ;
195                         if (c=='L') 
196                                 while (utf_nextu2(&utf_ptr) != ';');
197                         break;
198                            
199                 case 'L':  fprintf (file, "java_objectarray*");
200                         while ( utf_nextu2(&utf_ptr) != ';');
201                         break;
202                 default: panic ("invalid type descriptor");
203                 }
204                 break;
205                 
206         case 'L': 
207                 addoutputsize ( sizeof(java_objectheader*));
208                 fprintf (file, "struct ");
209                 while ( (c = utf_nextu2(&utf_ptr)) != ';' ) printIDpart (c);     
210                 fprintf (file, "*");
211                 break;
212                                         
213         default:  panic ("Unknown type in field descriptor");
214         }
215         
216         return utf_ptr;
217 }
218
219 /******* determine the number of entries of a utf string in the ident chain *****/
220
221 static int searchidentchain_utf(utf *ident) 
222 {
223         utf *u = chain_first(ident_chain);     /* first element of list */
224         int count = 0;
225
226         while (u) {
227                 if (u==ident) count++;         /* string found */
228                 u = chain_next(ident_chain);   /* next element in list */ 
229         }
230
231         return count;
232 }
233
234 /**************** print structure for direct access to objects ******************/      
235
236 static void printfields (classinfo *c)
237 {
238         u4 i;
239         fieldinfo *f;
240         int ident_count;
241         
242         if (!c) {
243                 addoutputsize ( sizeof(java_objectheader) );
244                 fprintf (file, "   java_objectheader header;\n");
245                 return;
246         }
247                 
248         printfields (c->super);
249         
250         for (i=0; i<c->fieldscount; i++) {
251                 f = &(c->fields[i]);
252                 
253                 if (! (f->flags & ACC_STATIC) ) {
254                         fprintf (file,"   ");
255                         printtype (f->descriptor->text);
256                         fprintf (file, " ");
257                         utf_fprint (file, f->name);
258
259                         /* rename multiple fieldnames */
260                         if ((ident_count = searchidentchain_utf(f->name)))
261                                 fprintf(file,"%d",ident_count - 1);             
262                         chain_addlast(ident_chain,f->name);     
263
264                         fprintf (file, ";\n");
265                 }
266         }
267 }
268
269 /***************** store prototype for native method in file ******************/
270
271 static void printmethod (methodinfo *m)
272 {
273         char *utf_ptr;
274         u2 paramnum=1;
275         u2 ident_count;
276
277         /* search for return-type in descriptor */      
278         utf_ptr = m->descriptor->text;
279         while (utf_nextu2(&utf_ptr) != ')');
280
281         /* create remarks */
282         fprintf (file,"/*\n * Class:     ");
283         utf_fprint (file, m->class->name);
284         fprintf (file,"\n * Method:    ");
285         utf_fprint (file, m->name);
286         fprintf (file,"\n * Signature: ");
287         utf_fprint (file, m->descriptor);
288         fprintf (file,"\n */\n");       
289
290         /* create prototype */                  
291         fprintf (file,"JNIEXPORT ");                            
292         printtype (utf_ptr);
293         fprintf (file," JNICALL Java_");
294         printID (m->class->name);           
295
296         /* rename overloaded method */
297         if ((ident_count = searchidentchain_utf(m->name)))
298                 fprintf(file,"%d",ident_count - 1);             
299         chain_addlast(ident_chain,m->name);     
300
301         fprintf (file,"_");
302         printID (m->name);
303         fprintf (file," (JNIEnv *env ");
304         
305         utf_ptr = m->descriptor->text+1;
306                         
307         if (! (m->flags & ACC_STATIC) ) {
308         
309                 fprintf (file, ",  struct ");
310                 printID (m->class->name);
311                 fprintf (file, "* this ");
312
313         };
314
315         if ((*utf_ptr)!=')') fprintf (file, ", "); 
316                         
317         while ((*utf_ptr)!=')') {
318                 utf_ptr = printtype (utf_ptr);
319                 fprintf (file, " par%d", paramnum++);
320                 if ((*utf_ptr)!=')') fprintf (file, ", ");
321         }
322                         
323         fprintf (file, ");\n");
324 }
325
326
327 /****************** remove package-name in fully-qualified classname *********************/
328
329 static void simple_classname(char *buffer, utf *u)
330 {
331         int i, simplename_start;
332
333         for (i=utf_strlen(u)-1; i>=0; i--) { 
334
335                 if (u->text[i] == '$') u->text[i] = '_'; else /* convert '$' to '_' */
336                         if (u->text[i] == '/') {
337                                 /* beginning of simple name */
338                                 simplename_start = i+1;
339                                 break;
340                         }
341         }
342
343         for (i=simplename_start; i < utf_strlen(u); i++) 
344                 buffer[i-simplename_start] = u->text[i];
345
346         buffer[i-simplename_start] = '\0';                
347 }
348
349 /*********** create headerfile for classes and store native methods in chain ************/
350
351 static void headerfile_generate (classinfo *c)
352 {
353         char header_filename[1024] = "";
354         char classname[1024]; 
355         u2 i;
356         methodinfo *m;                  
357                       
358         /* store class in chain */                    
359         chain_addlast (nativeclass_chain, c);                                                           
360                                 
361         /* open headerfile for class */
362         simple_classname(classname,c->name);                                                                                                                                            
363
364         /* create chain for renaming fields */
365         ident_chain = chain_new ();
366         
367         sprintf(header_filename, "nat/%s.h", classname);
368         file = fopen (header_filename, "w");
369         if (!file) panic ("Can not open file to store header information");                                                                                     
370         fprintf (file, "/* This file is machine generated, don't edit it !*/\n\n"); 
371
372         /* create structure for direct access to objects */     
373         fprintf (file, "/* Structure information for class: ");
374         utf_fprint (file, c->name);
375         fprintf (file, " */\n\n");
376         fprintf (file, "typedef struct ");
377         printID (c->name);                                                      
378         fprintf (file, " {\n");
379         outputsize=0;
380         dopadding=true;
381         printfields (c);                                                        
382         fprintf (file, "} ");
383         printID (c->name);
384         fprintf (file, ";\n\n");                            
385
386         /* create chain for renaming overloaded methods */
387         chain_free(ident_chain);                                        
388         ident_chain = chain_new ();
389
390         /* create method-prototypes */
391                                 
392         for (i=0; i<c->methodscount; i++) {
393
394                 m = &(c->methods[i]);
395
396                 if (m->flags & ACC_NATIVE) {
397                         chain_addlast (nativemethod_chain, m);     
398                         printmethod(m);                                             
399                 }                                                       
400         }
401                                 
402
403         chain_free(ident_chain);                                 
404         fclose(file);
405 }
406
407 /******** print classname, '$' used to seperate inner-class name ***********/
408
409 void print_classname (classinfo *clazz)
410 {
411         utf *u = clazz->name;
412     char *endpos  = u->text + u->blength;
413     char *utf_ptr = u->text; 
414         u2 c;
415
416     while (utf_ptr<endpos) {
417                 if ((c=utf_nextu2(&utf_ptr)) == '_')
418                         putc ('$',file);
419                 else
420                         putc (c,file);
421         }
422
423
424
425 /*************** create table for locating native functions ****************/
426
427 static void printnativetableentry (methodinfo *m)
428 {
429         fprintf (file, "   { \"");
430         print_classname(m->class);
431         fprintf (file, "\",\n     \"");
432         utf_fprint (file, m->name);
433         fprintf (file, "\",\n     \"");
434         utf_fprint (file, m->descriptor);
435         fprintf (file, "\",\n     ");
436         if ( (m->flags & ACC_STATIC) !=0)  fprintf (file, "true");
437         else fprintf (file, "false");
438         fprintf (file, ",\n     ");
439         fprintf (file, "(functionptr) Java_");
440         printID (m->class->name);
441         fprintf (file,"_");
442         printID (m->name);
443         fprintf (file,"\n   },\n");
444 }
445
446
447 /***************************************************************************
448
449         create the nativetypes-headerfile which includes 
450         the headerfiles of the classes stored in the classes-chain 
451
452 ****************************************************************************/
453
454 static void headers_finish ()
455 {
456         methodinfo *m;
457         classinfo *c;
458         char classname[1024];
459         
460         file = fopen ("nativetypes.hh", "w");
461         if (!file) panic ("Can not open file 'native.h' to store header information");
462         
463         fprintf (file, "/* Headerfile for native methods: nativetypes.hh */\n");
464         fprintf (file, "/* This file is machine generated, don't edit it !*/\n\n");     
465         fprintf (file, "\n/* include native-Headerfiles */\n\n");
466                         
467         c = chain_first (nativeclass_chain);
468         while (c) {
469         
470                 dopadding=false;
471                 simple_classname(classname,c->name);                                                                                                                                                                                    
472                 fprintf(file,"#include \"nat/%s.h\"\n",classname);              
473                 c = chain_next (nativeclass_chain);             
474         }
475
476     fclose(file);
477         chain_free (nativeclass_chain);
478         
479         /* create table of native-methods */
480
481         file = fopen ("nativetable.hh", "w");
482         if (!file) panic ("Can not open file 'nativetable' to store native-link-table");
483
484         fprintf (file, "/* Table of native methods: nativetables.hh */\n");
485         fprintf (file, "/* This file is machine generated, don't edit it !*/\n\n"); 
486
487         while ( (m = chain_first (nativemethod_chain)) != NULL) {
488                 chain_remove (nativemethod_chain);              
489                 printnativetableentry (m);
490         }
491                 
492         chain_free (nativemethod_chain);
493         fclose (file);
494
495 }
496
497
498 /******************** internal function: print_usage ************************
499
500 Prints usage information for the JAVA header generator to stdout.
501
502 ***************************************************************************/
503
504 static void print_usage()
505 {
506         printf("Usage: cacaoh class [class..]\n");
507 }   
508
509
510
511 /************************** Function: main *******************************
512
513    Main program.
514    
515 **************************************************************************/
516
517 int main(int argc, char **argv)
518 {
519         s4 i,a;
520         char *cp;
521         classinfo *topclass;
522         void *dummy;
523                 
524
525         /********** internal (only used by main) *****************************/
526    
527         char classpath[500] = "";
528         char offsets_filename[1024] = ""; /* phil */
529         u4 heapsize = 100000;
530
531         /*********** options so only headers are generated *******************/
532    
533         makeinitializations=false;
534    
535
536         /************ Collect some info from the environment *****************/
537
538         cp = getenv("CLASSPATH");
539         if (cp) {
540                 strcpy(classpath + strlen(classpath), ":");
541                 strcpy(classpath + strlen(classpath), cp);
542         }
543
544         if (argc < 2) {
545                 print_usage();
546                 exit(10);
547         }
548
549
550         /**************************** Program start **************************/
551
552         log_init(NULL);
553         log_text("Java - header-generator started"); 
554         
555         sprintf(offsets_filename, "jit/%s/offsets.h", ARCH_DIR); /* phil */
556         file = fopen(offsets_filename, "w");
557         if (file == NULL) {
558                 fprintf(stderr, "Can not open file '%s' for write", offsets_filename);
559                 exit(-1);
560         }
561         
562         fprintf(file, "/* This file is machine generated, don't edit it !*/\n\n"); 
563
564         fprintf(file, "#define offobjvftbl    %3d\n", (int) OFFSET(java_objectheader, vftbl));
565         fprintf(file, "#define offarraysize   %3d\n", (int) OFFSET(java_arrayheader, size));
566         fprintf(file, "#define offobjarrdata  %3d\n\n", (int) OFFSET(java_objectarray, data[0]));
567         fprintf(file, "#define offbaseval     %3d\n", (int) OFFSET(vftbl, baseval));
568         fprintf(file, "#define offdiffval     %3d\n", (int) OFFSET(vftbl, diffval));
569
570         fclose(file);
571
572         suck_init(classpath);
573    
574         tables_init();
575         heap_init(heapsize, heapsize, &dummy);
576         loader_init();
577
578
579         /*********************** Load JAVA classes  **************************/
580         
581         nativemethod_chain = chain_new();
582         nativeclass_chain = chain_new();
583         
584         for (a = 1; a < argc; a++) {
585                 cp = argv[a];
586
587                 /* convert classname */
588                 for (i = strlen(cp) - 1; i >= 0; i--)    
589                         switch (cp[i]) {
590                         case '.': cp[i]='/';
591                                 break;
592                         case '_': cp[i]='$';    
593                         }
594         
595                 topclass = loader_load(utf_new_char(cp));
596                 
597         headerfile_generate(topclass);
598         }
599
600         headers_finish();
601
602         /************************ Release all resources **********************/
603
604         loader_close();
605         heap_close();
606         tables_close(literalstring_free);
607         
608
609         /* Print "finished" message */
610
611         log_text("Java - header-generator stopped");
612         log_cputime();
613         mem_usagelog(1);
614         
615         return 0;
616 }
617
618
619 /*
620  * These are local overrides for various environment variables in Emacs.
621  * Please do not remove this and leave it at the end of the file, where
622  * Emacs will automagically detect them.
623  * ---------------------------------------------------------------------
624  * Local variables:
625  * mode: c
626  * indent-tabs-mode: t
627  * c-basic-offset: 4
628  * tab-width: 4
629  * End:
630  */