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