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