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