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