reflection, loader fix (before it did offer an unloaded (not found) class as loaded...
[cacao.git] / src / native / native.c
1 /* native.c - table of native functions
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             Roman Obermaisser
29             Andreas Krall
30
31    The .hh files created with the header file generator are all
32    included here as are the C functions implementing these methods.
33
34    $Id: native.c 682 2003-12-01 15:33:30Z jowenn $
35
36 */
37
38 #include <stdlib.h>
39 #include <unistd.h>
40 #include <time.h>
41 #include <math.h>
42 #include <string.h>
43 #include <assert.h>
44 #include <sys/time.h>
45 #include <utime.h>
46
47 #include "config.h"
48 #include "global.h"
49 #include "jni.h"
50 #include "native.h"
51 #include "nativetypes.hh"
52 #include "builtin.h"
53 #include "asmpart.h"
54 #include "tables.h"
55 #include "loader.h"
56 #include "toolbox/loging.h"
57 #include "threads/thread.h"
58 #include "threads/threadio.h"
59 #include "threads/locks.h"
60
61 /* Include files for IO functions */
62
63 #include <fcntl.h>
64 #include <dirent.h>
65 #include <sys/types.h>
66 #ifdef _OSF_SOURCE 
67 #include <sys/mode.h>
68 #endif
69 #include <sys/stat.h>
70
71 #include "threads/threadio.h"
72
73 /* searchpath for classfiles */
74 char *classpath;
75
76 /* for java-string to char conversion */
77 #define MAXSTRINGSIZE 1000                          
78
79 /******************** systemclasses required for native methods ***************/
80
81 classinfo *class_java_lang_Class;
82 classinfo *class_java_lang_VMClass;
83 methodinfo *method_vmclass_init;
84 /* static classinfo *class_java_lang_Cloneable=0; */ /* now in global.h */
85 classinfo *class_java_lang_CloneNotSupportedException;
86 classinfo *class_java_lang_System;
87 classinfo *class_java_lang_ClassLoader;
88 classinfo *class_java_lang_ClassNotFoundException;
89 classinfo *class_java_lang_LinkageError;
90 classinfo *class_java_lang_InstantiationException;
91 classinfo *class_java_lang_NoSuchMethodError;   
92 classinfo *class_java_lang_NoSuchFieldError;
93 classinfo *class_java_lang_ClassFormatError;
94 classinfo *class_java_lang_IllegalArgumentException;
95 classinfo *class_java_lang_ArrayIndexOutOfBoundsException;
96 classinfo *class_java_lang_NoSuchFieldException;
97 classinfo *class_java_io_SyncFailedException;
98 classinfo *class_java_io_IOException;
99 classinfo *class_java_io_FileNotFoundException;
100 classinfo *class_java_io_UnixFileSystem;
101 classinfo *class_java_security_PrivilegedActionException;
102 classinfo *class_java_net_UnknownHostException;
103 classinfo *class_java_net_SocketException;
104 classinfo *class_java_lang_NoSuchMethodException;
105 classinfo *class_java_lang_Double;
106 classinfo *class_java_lang_Float;
107 classinfo *class_java_lang_Long;
108 classinfo *class_java_lang_Byte;
109 classinfo *class_java_lang_Short;
110 classinfo *class_java_lang_Boolean;
111 classinfo *class_java_lang_Void;
112 classinfo *class_java_lang_Character;
113 classinfo *class_java_lang_Integer;
114
115 /* the system classloader object */
116 struct java_lang_ClassLoader *SystemClassLoader = NULL;
117
118 /* for raising exceptions from native methods */
119 java_objectheader* exceptionptr = NULL;
120
121 /************* use classinfo structure as java.lang.Class object **************/
122
123 void use_class_as_object(classinfo *c) 
124 {
125         /*log_text("use_class_as_object");*/
126         if (!class_java_lang_Class)
127                 class_java_lang_Class =
128                         class_new ( utf_new_char ("java/lang/Class") );
129         vftbl *vt = class_java_lang_Class->vftbl;
130         vftbl *newtbl;
131         if (!c->classvftbl) {
132                 c->classvftbl = true;
133
134 /*                copy_vftbl(&newtbl, vt);
135                 newtbl->class = c->header.vftbl->class;
136                 newtbl->baseval = c->header.vftbl->baseval;
137                 newtbl->diffval = c->header.vftbl->diffval;
138                 c->header.vftbl = newtbl;*/
139                 
140                 c->header.vftbl=class_java_lang_Class->vftbl;
141         
142                 if (!class_java_lang_VMClass) {
143                         class_java_lang_VMClass =
144                                         loader_load ( utf_new_char("java/lang/VMClass"));
145                         method_vmclass_init = 
146                                         class_findmethod(class_java_lang_VMClass,utf_new_char("<init>"),
147                                                 utf_new_char("(Lgnu/classpath/RawData;)V"));
148                         if (method_vmclass_init==0) {
149                                 class_showmethods(class_java_lang_VMClass);
150                                 panic("Needed class initializer for VMClass could not be found");
151                         }
152                 }
153                 {     
154                         java_objectheader *vmo = builtin_new (class_java_lang_VMClass);
155
156                         if (!vmo) panic("Error while creating instance of java/lang/VMClass");
157                         asm_calljavamethod (method_vmclass_init, vmo, c, NULL, NULL);
158                         c->vmClass=(java_lang_VMClass*)vmo;
159                         /*log_text("VMCLASS has been attached");*/
160                 }
161         }
162         
163 }
164
165
166 /*************************** include native methods ***************************/ 
167
168 #ifdef USE_GTK 
169 #include "nat/GdkGraphics.c"
170 #include "nat/GtkComponentPeer.c"
171 #include "nat/GdkPixbufDecoder.c"
172 #include "nat/GtkScrollPanePeer.c"
173 #include "nat/GtkFileDialogPeer.c"
174 #include "nat/GtkLabelPeer.c"
175 #endif
176
177
178 /************************** tables for methods ********************************/
179
180 #undef JOWENN_DEBUG
181 #undef JOWENN_DEBUG1
182
183 /* table for locating native methods */
184 static struct nativeref {
185         char *classname;
186         char *methodname;
187         char *descriptor;
188         bool isstatic;
189         functionptr func;
190 } nativetable [] = {
191
192 #include "nativetable.hh"
193
194 };
195
196
197 #define NATIVETABLESIZE  (sizeof(nativetable)/sizeof(struct nativeref))
198
199 /* table for fast string comparison */
200 static struct nativecompref {
201         utf *classname;
202         utf *methodname;
203         utf *descriptor;
204         bool isstatic;
205         functionptr func;
206 } nativecomptable [NATIVETABLESIZE];
207
208 /* string comparsion table initialized */
209 static bool nativecompdone = false;
210
211
212 /******************************************************************************/
213 /******************************************************************************/
214 #include "natcalls.h"
215
216 /* string call comparison table initialized */
217
218 /******************************************************************************/
219 /******************************************************************************/
220
221 /*--------------- native method calls & classes used -------------------------*/
222
223
224
225
226 /*********************** function: native_loadclasses **************************
227
228         load classes required for native methods        
229
230 *******************************************************************************/
231
232 void native_loadclasses()
233 {
234         static int classesLoaded=0; /*temporary hack JoWenn*/
235         if (classesLoaded) return;
236         classesLoaded=1;
237 /*      log_text("loadclasses entered");*/
238
239
240         /*class_java_lang_System =*/
241                 (void)class_new ( utf_new_char ("java/lang/VMClass") );/*JoWenn*/
242                 (void)class_new ( utf_new_char ("java/lang/Class") );/*JoWenn*/
243         /* class_new adds the class to the list of classes to be loaded */
244         if (!class_java_lang_Cloneable)
245                 class_java_lang_Cloneable = 
246                         class_new ( utf_new_char ("java/lang/Cloneable") );
247 /*      log_text("loadclasses: class_java_lang_Cloneable has been initialized");*/
248         class_java_lang_CloneNotSupportedException = 
249                 class_new ( utf_new_char ("java/lang/CloneNotSupportedException") );
250         if (!class_java_lang_Class)
251                 class_java_lang_Class =
252                         class_new ( utf_new_char ("java/lang/Class") );
253         class_java_io_IOException = 
254                 class_new(utf_new_char("java/io/IOException"));
255         class_java_io_FileNotFoundException = 
256                 class_new(utf_new_char("java/io/FileNotFoundException"));
257         class_java_lang_ClassNotFoundException =
258                 class_new(utf_new_char("java/lang/ClassNotFoundException"));
259         class_java_lang_LinkageError =
260                 class_new(utf_new_char("java/lang/LinkageError"));
261         class_java_lang_InstantiationException =
262                 class_new(utf_new_char("java/lang/InstantiationException"));
263         class_java_lang_NoSuchMethodError =
264                 class_new(utf_new_char("java/lang/NoSuchMethodError"));
265         class_java_lang_NoSuchFieldError =
266                 class_new(utf_new_char("java/lang/NoSuchFieldError"));  
267         class_java_lang_ClassFormatError =
268                 class_new(utf_new_char("java/lang/ClassFormatError"));  
269         class_java_io_SyncFailedException =
270                 class_new ( utf_new_char ("java/io/SyncFailedException") );
271                 
272 /*      log_text("native_loadclasses: class_new(\"java/lang/ClassLoader\")");           */
273         class_java_lang_ClassLoader =
274                 class_new ( utf_new_char ("java/lang/ClassLoader") );   
275 /*      log_text("native_loadclasses: class_new(\"java/security/PrivilegedActionException\")");         */
276         class_java_security_PrivilegedActionException =
277                 class_new(utf_new_char("java/security/PrivilegedActionException"));
278
279         class_java_net_UnknownHostException = 
280                 loader_load(utf_new_char("java/net/UnknownHostException"));
281         class_java_net_SocketException = 
282                 loader_load(utf_new_char("java/net/SocketException"));
283
284         class_java_lang_IllegalArgumentException =
285                 class_new(utf_new_char("java/lang/IllegalArgumentException"));
286         class_java_lang_ArrayIndexOutOfBoundsException =
287                 class_new(utf_new_char("java/lang/ArrayIndexOutOfBoundsException"));
288         class_java_lang_NoSuchFieldException =
289                 class_new(utf_new_char("java/lang/NoSuchFieldException"));
290         class_java_lang_NoSuchMethodException = 
291                 class_new(utf_new_char("java/lang/NoSuchMethodException"));
292
293         /* load classes for wrapping primitive types */
294         class_java_lang_Double =
295                 class_new( utf_new_char ("java/lang/Double") );
296         class_init(class_java_lang_Double);
297
298         class_java_lang_Float =
299                 class_new(utf_new_char("java/lang/Float"));
300         class_java_lang_Character =
301                 class_new(utf_new_char("java/lang/Character"));
302         class_java_lang_Integer =
303                 class_new(utf_new_char("java/lang/Integer"));
304         class_java_lang_Long =
305                 class_new(utf_new_char("java/lang/Long"));
306         class_java_lang_Byte =
307                 class_new(utf_new_char("java/lang/Byte"));
308         class_java_lang_Short =
309                 class_new(utf_new_char("java/lang/Short"));
310         class_java_lang_Boolean =
311                 class_new(utf_new_char("java/lang/Boolean"));
312         class_java_lang_Void =
313                 class_new(utf_new_char("java/lang/Void"));
314
315         classesLoaded=1;
316         log_text("native_loadclasses finished");
317 }
318
319
320 /*************** adds a class to the vector of loaded classes ****************/
321
322 void systemclassloader_addclass(classinfo *c)
323 {
324         methodinfo *m;
325
326         /* find method addClass of java.lang.ClassLoader */
327         m = class_resolvemethod(
328                                                         class_java_lang_ClassLoader, 
329                                                         utf_new_char("addClass"),
330                                                         utf_new_char("(Ljava/lang/Class;)")
331                                                         );
332         
333         if (!m) panic("warning: cannot initialize classloader");
334
335         /* prepare class to be passed as argument */
336         use_class_as_object (c);
337
338         /* call 'addClass' */
339         asm_calljavamethod(m,
340                                            (java_objectheader*) SystemClassLoader, 
341                                            (java_objectheader*) c,
342                                            NULL,  
343                                            NULL
344                                            );
345 }
346
347 /*************** adds a library to the vector of loaded libraries *************/
348
349 void systemclassloader_addlibrary(java_objectheader *o)
350 {
351         log_text("systemclassloader_addlibrary");
352 }
353
354 /*****************************************************************************
355
356         create systemclassloader object and initialize instance fields  
357
358 ******************************************************************************/
359
360 void init_systemclassloader() 
361 {
362   if (!SystemClassLoader) {
363         native_loadclasses();
364         log_text("Initializing new system class loader");
365         /* create object and call initializer */
366         SystemClassLoader = (java_lang_ClassLoader*) native_new_and_init(class_java_lang_ClassLoader);  
367         heap_addreference((void**) &SystemClassLoader);
368
369         /* systemclassloader has no parent */
370         SystemClassLoader->parent      = NULL;
371         SystemClassLoader->initialized = true;
372   }
373   log_text("leaving system class loader");
374 }
375
376
377 /********************* add loaded library name  *******************************/
378
379 void systemclassloader_addlibname(java_objectheader *o)
380 {
381         methodinfo *m;
382         jfieldID id;
383
384         m = class_resolvemethod(loader_load(utf_new_char ("java/util/Vector")),
385                                                         utf_new_char("addElement"),
386                                                         utf_new_char("(Ljava/lang/Object;)V")
387                                                         );
388
389         if (!m) panic("cannot initialize classloader");
390
391         id = envTable.GetStaticFieldID(&env,class_java_lang_ClassLoader,"loadedLibraryNames","Ljava/util/Vector;");
392         if (!id) panic("can not access ClassLoader");
393
394         asm_calljavamethod(m,
395                                            GetStaticObjectField(&env,class_java_lang_ClassLoader,id),
396                                            o,
397                                            NULL,  
398                                            NULL
399                                            );       
400 }
401
402
403 /********************* function: native_setclasspath **************************/
404  
405 void native_setclasspath (char *path)
406 {
407         /* set searchpath for classfiles */
408         classpath = path;
409 }
410
411
412 /***************** function: throw_classnotfoundexception *********************/
413
414 void throw_classnotfoundexception()
415 {
416     if (!class_java_lang_ClassNotFoundException) {
417         panic("java.lang.ClassNotFoundException not found. Maybe wrong classpath?");
418     }
419
420         /* throws a ClassNotFoundException */
421         exceptionptr = native_new_and_init(class_java_lang_ClassNotFoundException);
422 }
423
424
425 void throw_classnotfoundexception2(utf* classname)
426 {
427         if (!class_java_lang_ClassNotFoundException) {
428                 panic("java.lang.ClassNotFoundException not found. Maybe wrong classpath?");
429         }
430
431         /* throws a ClassNotFoundException with message */
432         exceptionptr = native_new_and_init_string(class_java_lang_ClassNotFoundException,
433                                                                                           javastring_new(classname));
434 }
435
436 void throw_linkageerror2(utf* classname)
437 {
438         if (!class_java_lang_LinkageError) {
439                 panic("java.lang.LinkageError not found. Maybe wrong classpath?");
440         }
441
442         /* throws a ClassNotFoundException with message */
443         exceptionptr = native_new_and_init_string(class_java_lang_LinkageError,
444                                                                                           javastring_new(classname));
445 }
446
447
448 /*********************** Function: native_findfunction *************************
449
450         Looks up a method (must have the same class name, method name, descriptor
451         and 'static'ness) and returns a function pointer to it.
452         Returns: function pointer or NULL (if there is no such method)
453
454         Remark: For faster operation, the names/descriptors are converted from C
455                 strings to Unicode the first time this function is called.
456
457 *******************************************************************************/
458
459 functionptr native_findfunction(utf *cname, utf *mname, 
460                                                                 utf *desc, bool isstatic)
461 {
462         int i;
463         /* entry of table for fast string comparison */
464         struct nativecompref *n;
465         /* for warning message if no function is found */
466         char *buffer;                   
467         int buffer_len;
468
469         isstatic = isstatic ? true : false;
470         
471         if (!nativecompdone) {
472                 for (i = 0; i < NATIVETABLESIZE; i++) {
473                         nativecomptable[i].classname  = 
474                                 utf_new_char(nativetable[i].classname);
475                         nativecomptable[i].methodname = 
476                                 utf_new_char(nativetable[i].methodname);
477                         nativecomptable[i].descriptor = 
478                                 utf_new_char(nativetable[i].descriptor);
479                         nativecomptable[i].isstatic   = 
480                                 nativetable[i].isstatic;
481                         nativecomptable[i].func       = 
482                                 nativetable[i].func;
483                 }
484                 nativecompdone = true;
485         }
486
487 #ifdef JOWENN_DEBUG
488         buffer_len = 
489           utf_strlen(cname) + utf_strlen(mname) + utf_strlen(desc) + 64;
490         
491         buffer = MNEW(char, buffer_len);
492
493         strcpy(buffer, "searching matching function in native table:");
494         utf_sprint(buffer+strlen(buffer), mname);
495         strcpy(buffer+strlen(buffer), ": ");
496         utf_sprint(buffer+strlen(buffer), desc);
497         strcpy(buffer+strlen(buffer), " for class ");
498         utf_sprint(buffer+strlen(buffer), cname);
499
500         log_text(buffer);       
501
502         MFREE(buffer, char, buffer_len);
503 #endif
504                 
505         for (i = 0; i < NATIVETABLESIZE; i++) {
506                 n = &(nativecomptable[i]);
507
508                 if (cname == n->classname && mname == n->methodname &&
509                     desc == n->descriptor && isstatic == n->isstatic)
510                         return n->func;
511 #ifdef JOWENN_DEBUG
512                         else {
513                                 if (cname == n->classname && mname == n->methodname )  log_text("static and descriptor mismatch");
514                         
515                                 else {
516                                         buffer_len = 
517                                           utf_strlen(n->classname) + utf_strlen(n->methodname) + utf_strlen(n->descriptor) + 64;
518         
519                                         buffer = MNEW(char, buffer_len);
520
521                                         strcpy(buffer, "comparing with:");
522                                         utf_sprint(buffer+strlen(buffer), n->methodname);
523                                         strcpy (buffer+strlen(buffer), ": ");
524                                         utf_sprint(buffer+strlen(buffer), n->descriptor);
525                                         strcpy(buffer+strlen(buffer), " for class ");
526                                         utf_sprint(buffer+strlen(buffer), n->classname);
527
528                                         log_text(buffer);       
529
530                                         MFREE(buffer, char, buffer_len);
531                         
532                                 }
533                         } 
534 #endif
535         }
536
537                 
538         /* no function was found, display warning */
539
540         buffer_len = 
541                 utf_strlen(cname) + utf_strlen(mname) + utf_strlen(desc) + 64;
542
543         buffer = MNEW(char, buffer_len);
544
545         strcpy(buffer, "warning: native function ");
546         utf_sprint(buffer + strlen(buffer), mname);
547         strcpy(buffer + strlen(buffer), ": ");
548         utf_sprint(buffer + strlen(buffer), desc);
549         strcpy(buffer + strlen(buffer), " not found in class ");
550         utf_sprint(buffer + strlen(buffer), cname);
551
552         log_text(buffer);       
553
554         MFREE(buffer, char, buffer_len);
555
556
557         exit(1);
558
559         
560         return NULL;
561 }
562
563
564 /********************** function: javastring_new *******************************
565
566         creates a new object of type java/lang/String with the text of 
567         the specified utf8-string
568
569         return: pointer to the string or NULL if memory is exhausted.   
570
571 *******************************************************************************/
572
573 java_objectheader *javastring_new (utf *u)
574 {
575         char *utf_ptr = u->text;        /* current utf character in utf string    */
576         int utflength = utf_strlen(u);  /* length of utf-string if uncompressed   */
577         java_lang_String *s;                /* result-string                          */
578         java_chararray *a;
579         s4 i;
580         
581 /*      log_text("javastring_new");*/
582         
583         s = (java_lang_String*) builtin_new (class_java_lang_String);
584         a = builtin_newarray_char (utflength);
585
586         /* javastring or character-array could not be created */
587         if ((!a) || (!s))
588                 return NULL;
589
590         /* decompress utf-string */
591         for (i = 0; i < utflength; i++)
592                 a->data[i] = utf_nextu2(&utf_ptr);
593         
594         /* set fields of the javastring-object */
595         s->value  = a;
596         s->offset = 0;
597         s->count  = utflength;
598
599         return (java_objectheader*) s;
600 }
601
602 /********************** function: javastring_new_char **************************
603
604         creates a new java/lang/String object which contains the convertet
605         C-string passed via text.
606
607         return: the object pointer or NULL if memory is exhausted.
608
609 *******************************************************************************/
610
611 java_objectheader *javastring_new_char (char *text)
612 {
613         s4 i;
614         s4 len = strlen(text); /* length of the string */
615         java_lang_String *s;   /* result-string */
616         java_chararray *a;
617         
618         /*log_text("javastring_new_char");*/
619         s = (java_lang_String*) builtin_new (class_java_lang_String);
620         a = builtin_newarray_char (len);
621
622         /* javastring or character-array could not be created */
623         if ((!a) || (!s)) return NULL;
624
625         /* copy text */
626         for (i = 0; i < len; i++)
627                 a->data[i] = text[i];
628         
629         /* set fields of the javastring-object */
630         s->value = a;
631         s->offset = 0;
632         s->count = len;
633
634         return (java_objectheader*) s;
635 }
636
637
638 /************************* function javastring_tochar **************************
639
640         converts a Java string into a C string.
641         
642         return: pointer to C string
643         
644         Caution: every call of this function overwrites the previous string !!!
645         
646 *******************************************************************************/
647
648 static char stringbuffer[MAXSTRINGSIZE];
649
650 char *javastring_tochar (java_objectheader *so) 
651 {
652         java_lang_String *s = (java_lang_String*) so;
653         java_chararray *a;
654         s4 i;
655         
656         log_text("javastring_tochar");
657         
658         if (!s)
659                 return "";
660         a = s->value;
661         if (!a)
662                 return "";
663         if (s->count > MAXSTRINGSIZE)
664                 return "";
665         for (i = 0; i < s->count; i++)
666                 stringbuffer[i] = a->data[s->offset+i];
667         stringbuffer[i] = '\0';
668         return stringbuffer;
669 }
670
671
672 /****************** function class_findfield_approx ****************************
673         
674         searches in 'classinfo'-structure for a field with the
675         specified name
676
677 *******************************************************************************/
678  
679 fieldinfo *class_findfield_approx(classinfo *c, utf *name)
680 {
681         s4 i;
682         for (i = 0; i < c->fieldscount; i++) {
683                 /* compare field names */
684                 if ((c->fields[i].name == name))
685                         return &(c->fields[i]);
686         }
687
688         /* field was not found, raise exception */      
689         exceptionptr = native_new_and_init(class_java_lang_NoSuchFieldException);
690
691         return NULL;
692 }
693
694 s4 class_findfield_index_approx (classinfo *c, utf *name)
695 {
696         s4 i;
697         for (i = 0; i < c->fieldscount; i++) {
698                 /* compare field names */
699                 if ((c->fields[i].name == name))
700                         return i;
701                 }
702
703         /* field was not found, raise exception */      
704         exceptionptr = native_new_and_init(class_java_lang_NoSuchFieldException);
705         return -1;
706 }
707
708
709 /********************** function: native_new_and_init *************************
710
711         Creates a new object on the heap and calls the initializer.
712         Returns the object pointer or NULL if memory is exhausted.
713                         
714 *******************************************************************************/
715
716 java_objectheader *native_new_and_init(classinfo *c)
717 {
718         methodinfo *m;
719         java_objectheader *o = builtin_new(c);          /* create object          */
720
721         /*
722         printf("native_new_and_init ");
723         utf_display(c->name);
724         printf("\n");
725         */
726         if (!o) return NULL;
727         /* printf("o!=NULL\n"); */
728         /* find initializer */
729
730         m = class_findmethod(c, utf_new_char("<init>"), utf_new_char("()V"));
731                                                       
732         if (!m) {                                       /* initializer not found  */
733                 if (verbose) {
734                         sprintf(logtext, "Warning: class has no instance-initializer: ");
735                         utf_sprint(logtext + strlen(logtext), c->name);
736                         dolog();
737                 }
738                 return o;
739         }
740
741         /* call initializer */
742
743         asm_calljavamethod(m, o, NULL, NULL, NULL);
744
745         return o;
746 }
747
748
749 java_objectheader *native_new_and_init_string(classinfo *c, java_lang_String *s)
750 {
751         methodinfo *m;
752         java_objectheader *o = builtin_new(c);          /* create object          */
753
754         if (!o) return NULL;
755
756         /* find initializer */
757
758         m = class_findmethod(c,
759                                                  utf_new_char("<init>"),
760                                                  utf_new_char("(Ljava/lang/String;)V"));
761                                                       
762         if (!m) {                                       /* initializer not found  */
763                 if (verbose) {
764                         sprintf(logtext, "Warning: class has no instance-initializer: ");
765                         utf_sprint(logtext + strlen(logtext), c->name);
766                         dolog();
767                 }
768                 return o;
769         }
770
771         /* call initializer */
772
773         asm_calljavamethod(m, o, s, NULL, NULL);
774
775         return o;
776 }
777
778
779 /******************** function: stringtable_update ****************************
780
781         traverses the javastring hashtable and sets the vftbl-entries of
782         javastrings which were temporarily set to NULL, because 
783         java.lang.Object was not yet loaded
784
785 *******************************************************************************/
786  
787 void stringtable_update ()
788 {
789         java_lang_String *js;   
790         java_chararray *a;
791         literalstring *s;       /* hashtable entry */
792         int i;
793
794         for (i = 0; i < string_hash.size; i++) {
795                 s = string_hash.ptr[i];
796                 if (s) {
797                         while (s) {
798                                                                 
799                                 js = (java_lang_String *) s->string;
800                                 
801                                 if (!js || !(a = js->value)) 
802                                         /* error in hashtable found */
803                                         panic("invalid literalstring in hashtable");
804
805                                 if (!js->header.vftbl) 
806                                         /* vftbl of javastring is NULL */ 
807                                         js->header.vftbl = class_java_lang_String -> vftbl;
808
809                                 if (!a->header.objheader.vftbl) 
810                                         /* vftbl of character-array is NULL */ 
811                                         a->header.objheader.vftbl = primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl;
812
813                                 /* follow link in external hash chain */
814                                 s = s->hashlink;
815                         }       
816                 }               
817         }
818 }
819
820
821 /************************* function: u2_utflength ***************************
822
823         returns the utf length in bytes of a u2 array 
824
825 *****************************************************************************/
826
827
828 u4 u2_utflength(u2 *text, u4 u2_length)
829 {
830         u4 result_len =  0;  /* utf length in bytes  */
831         u2 ch;               /* current unicode character */
832         u4 len;
833         
834         for (len = 0; len < u2_length; len++) {
835           
836           /* next unicode character */
837           ch = *text++;
838           
839           /* determine bytes required to store unicode character as utf */
840           if (ch && (ch < 0x80)) 
841             result_len++;
842           else if (ch < 0x800)
843             result_len += 2;    
844           else 
845             result_len += 3;    
846         }
847
848     return result_len;
849 }
850
851 /********************* function: utf_new_u2 ***********************************
852
853         make utf symbol from u2 array, 
854         if isclassname is true '.' is replaced by '/'
855
856 *******************************************************************************/
857
858 utf *utf_new_u2(u2 *unicode_pos, u4 unicode_length, bool isclassname)
859 {
860         char *buffer; /* memory buffer for  unicode characters */
861         char *pos;    /* pointer to current position in buffer */
862         u4 left;      /* unicode characters left */
863         u4 buflength; /* utf length in bytes of the u2 array  */
864         utf *result;  /* resulting utf-string */
865         int i;          
866
867         /* determine utf length in bytes and allocate memory */
868         /* printf("utf_new_u2: unicode_length=%d\n",unicode_length);            */
869         buflength = u2_utflength(unicode_pos, unicode_length); 
870         buffer    = MNEW(char,buflength);
871  
872         /* memory allocation failed */
873         if (!buffer) {
874                 printf("length: %d\n",buflength);
875                 log_text("utf_new_u2:buffer==NULL");
876         }
877
878         left = buflength;
879         pos  = buffer;
880
881         for (i = 0; i++ < unicode_length; unicode_pos++) {
882                 /* next unicode character */
883                 u2 c = *unicode_pos;
884                 
885                 if ((c != 0) && (c < 0x80)) {
886                 /* 1 character */       
887                 left--;
888                 if ((int) left < 0) break;
889                 /* convert classname */
890                 if (isclassname && c=='.') 
891                   *pos++ = '/';
892                 else
893                   *pos++ = (char) c;
894                 } else if (c < 0x800) {             
895                 /* 2 characters */                              
896                 unsigned char high = c >> 6;
897                 unsigned char low  = c & 0x3F;
898                 left = left - 2;
899                 if ((int) left < 0) break;
900                 *pos++ = high | 0xC0; 
901                 *pos++ = low  | 0x80;     
902                 } else {         
903                 /* 3 characters */                              
904                 char low  = c & 0x3f;
905                 char mid  = (c >> 6) & 0x3F;
906                 char high = c >> 12;
907                 left = left - 3;
908                 if ((int) left < 0) break;
909                 *pos++ = high | 0xE0; 
910                 *pos++ = mid  | 0x80;  
911                 *pos++ = low  | 0x80;   
912                 }
913         }
914         
915         /* insert utf-string into symbol-table */
916         result = utf_new(buffer,buflength);
917
918         MFREE(buffer, char, buflength);
919         return result;
920 }
921
922 /********************* function: javastring_toutf *****************************
923
924         make utf symbol from javastring
925
926 *******************************************************************************/
927
928 utf *javastring_toutf(java_lang_String *string, bool isclassname)
929 {
930         java_lang_String *str = (java_lang_String *) string;
931 /*      printf("javastring_toutf offset: %d, len %d\n",str->offset, str->count);
932         fflush(stdout);*/
933         return utf_new_u2(str->value->data+str->offset,str->count, isclassname);
934 }
935
936 /********************* function: literalstring_u2 *****************************
937
938     searches for the javastring with the specified u2-array in 
939     the string hashtable, if there is no such string a new one is 
940     created 
941
942     if copymode is true a copy of the u2-array is made
943
944 *******************************************************************************/
945
946 java_objectheader *literalstring_u2 (java_chararray *a, u4 length, bool copymode )
947 {
948     literalstring *s;                /* hashtable element */
949     java_lang_String *js;            /* u2-array wrapped in javastring */
950     java_chararray *stringdata;      /* copy of u2-array */      
951     u4 key;   
952     u4 slot;  
953     u2 i;
954
955 #if JOWENN_DEBUG1
956     printf("literalstring_u2: length: %d\n",length);    
957     log_text("literalstring_u2");
958 #endif
959     
960     /* find location in hashtable */
961     key  = unicode_hashkey (a->data, length);
962     slot = key & (string_hash.size-1);
963     s    = string_hash.ptr[slot];
964
965     while (s) {
966         
967       js = (java_lang_String *) s->string;
968         
969       if (js->count == length) {
970         /* compare text */
971         for (i=0; i<length; i++) 
972           if (js->value->data[i] != a->data[i]) goto nomatch;
973                                         
974         /* string already in hashtable, free memory */
975         if (!copymode)
976           lit_mem_free(a, sizeof(java_chararray) + sizeof(u2)*(length-1)+10);
977
978 #ifdef JOWENN_DEBUG1
979         log_text("literalstring_u2: foundentry");
980         utf_display(javastring_toutf(js,0));
981 #endif
982         return (java_objectheader *) js;
983       }
984
985       nomatch:
986       /* follow link in external hash chain */
987       s = s->hashlink;
988     }
989
990     if (copymode) {
991       /* create copy of u2-array for new javastring */
992       u4 arraysize = sizeof(java_chararray) + sizeof(u2)*(length-1)+10;
993       stringdata = lit_mem_alloc ( arraysize ); 
994       memcpy(stringdata, a, arraysize );        
995     }  
996     else
997       stringdata = a;
998
999     /* location in hashtable found, complete arrayheader */
1000     stringdata -> header.objheader.vftbl = primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl;
1001     stringdata -> header.size = length; 
1002
1003     /* create new javastring */
1004     js = LNEW (java_lang_String);
1005     js -> header.vftbl = class_java_lang_String -> vftbl;
1006     js -> value  = stringdata;
1007     js -> offset = 0;
1008     js -> count  = length;
1009
1010     /* create new literalstring */
1011     s = NEW (literalstring);
1012     s->hashlink = string_hash.ptr[slot];
1013     s->string   = (java_objectheader *) js;
1014     string_hash.ptr[slot] = s;
1015
1016     /* update numbe of hashtable entries */
1017     string_hash.entries++;
1018
1019     /* reorganization of hashtable */       
1020     if ( string_hash.entries > (string_hash.size*2)) {
1021
1022       /* reorganization of hashtable, average length of 
1023          the external chains is approx. 2                */  
1024
1025       u4 i;
1026       literalstring *s;     
1027       hashtable newhash; /* the new hashtable */
1028       
1029       /* create new hashtable, double the size */
1030       init_hashtable(&newhash, string_hash.size*2);
1031       newhash.entries=string_hash.entries;
1032       
1033       /* transfer elements to new hashtable */
1034       for (i=0; i<string_hash.size; i++) {
1035         s = string_hash.ptr[i];
1036         while (s) {
1037           literalstring *nexts = s -> hashlink;  
1038           js   = (java_lang_String*) s->string;
1039           slot = (unicode_hashkey(js->value->data,js->count)) & (newhash.size-1);
1040           
1041           s->hashlink = newhash.ptr[slot];
1042           newhash.ptr[slot] = s;
1043         
1044           /* follow link in external hash chain */  
1045           s = nexts;
1046         }
1047       }
1048         
1049       /* dispose old table */   
1050       MFREE (string_hash.ptr, void*, string_hash.size);
1051       string_hash = newhash;
1052     }
1053 #ifdef JOWENN_DEBUG1
1054         log_text("literalstring_u2: newly created");
1055 /*      utf_display(javastring_toutf(js,0));*/
1056 #endif
1057                         
1058     return (java_objectheader *) js;
1059 }
1060
1061 /******************** Function: literalstring_new *****************************
1062
1063     creates a new javastring with the text of the utf-symbol
1064     and inserts it into the string hashtable
1065
1066 *******************************************************************************/
1067
1068 java_objectheader *literalstring_new (utf *u)
1069 {
1070     char *utf_ptr = u->text;         /* pointer to current unicode character in utf string */
1071     u4 utflength  = utf_strlen(u);   /* length of utf-string if uncompressed */
1072     java_chararray *a;               /* u2-array constructed from utf string */
1073     u4 i;
1074 /*    log_text("literalstring_new"); */
1075 /*    utf_display(u);*/
1076     /*if (utflength==0) while (1) sleep(60);*/
1077 /*    log_text("------------------");    */
1078     /* allocate memory */ 
1079     a = lit_mem_alloc (sizeof(java_chararray) + sizeof(u2)*(utflength-1)+10 );  
1080     /* convert utf-string to u2-array */
1081     for (i=0; i<utflength; i++) a->data[i] = utf_nextu2(&utf_ptr);      
1082
1083     return literalstring_u2(a, utflength, false);
1084 }
1085
1086
1087 /********************** function: literalstring_free **************************
1088
1089         removes a javastring from memory                       
1090
1091 ******************************************************************************/
1092
1093 void literalstring_free (java_objectheader* sobj)
1094 {
1095         java_lang_String *s = (java_lang_String*) sobj;
1096         java_chararray *a = s->value;
1097
1098         log_text("literalstring_free called");
1099         
1100         /* dispose memory of java.lang.String object */
1101         LFREE (s, java_lang_String);
1102         /* dispose memory of java-characterarray */
1103         LFREE (a, sizeof(java_chararray) + sizeof(u2)*(a->header.size-1)); /* +10 ?? */
1104 }
1105
1106
1107
1108
1109 void copy_vftbl(vftbl **dest, vftbl *src)
1110 {
1111     *dest = src;
1112 #if 0
1113     /* XXX this kind of copying does not work (in the general
1114      * case). The interface tables would have to be copied, too. I
1115      * don't see why we should make a copy anyway. -Edwin
1116      */
1117         *dest = mem_alloc(sizeof(vftbl) + sizeof(methodptr)*(src->vftbllength-1));
1118         memcpy(*dest, src, sizeof(vftbl) - sizeof(methodptr));
1119         memcpy(&(*dest)->table, &src->table, src->vftbllength * sizeof(methodptr));
1120 #endif
1121 }
1122
1123
1124 /******************************************************************************************                                                                                                             
1125
1126         creates method signature (excluding return type) from array of 
1127         class-objects representing the parameters of the method 
1128
1129 *******************************************************************************************/
1130
1131
1132 utf *create_methodsig(java_objectarray* types, char *retType)
1133 {
1134     char *buffer;       /* buffer for building the desciptor */
1135     char *pos;          /* current position in buffer */
1136     utf *result;        /* the method signature */
1137     u4 buffer_size = 3; /* minimal size=3: room for parenthesis and returntype */
1138     u4 i, j;
1139  
1140     if (!types) return NULL;
1141
1142     /* determine required buffer-size */    
1143     for (i=0;i<types->header.size;i++) {
1144       classinfo *c = (classinfo *) types->data[i];
1145       buffer_size  = buffer_size + c->name->blength+2;
1146     }
1147
1148     if (retType) buffer_size+=strlen(retType);
1149
1150     /* allocate buffer */
1151     buffer = MNEW(u1, buffer_size);
1152     pos    = buffer;
1153     
1154     /* method-desciptor starts with parenthesis */
1155     *pos++ = '(';
1156
1157     for (i=0;i<types->header.size;i++) {
1158
1159             char ch;       
1160             /* current argument */
1161             classinfo *c = (classinfo *) types->data[i];
1162             /* current position in utf-text */
1163             char *utf_ptr = c->name->text; 
1164             
1165             /* determine type of argument */
1166             if ( (ch = utf_nextu2(&utf_ptr)) == '[' ) {
1167         
1168                 /* arrayclass */
1169                 for ( utf_ptr--; utf_ptr<utf_end(c->name); utf_ptr++)
1170                    *pos++ = *utf_ptr; /* copy text */
1171
1172             } else
1173             {           
1174                 /* check for primitive types */
1175                 for (j=0; j<PRIMITIVETYPE_COUNT; j++) {
1176
1177                         char *utf_pos   = utf_ptr-1;
1178                         char *primitive = primitivetype_table[j].wrapname;
1179
1180                         /* compare text */
1181                         while (utf_pos<utf_end(c->name))
1182                                 if (*utf_pos++ != *primitive++) goto nomatch;
1183
1184                         /* primitive type found */
1185                         *pos++ = primitivetype_table[j].typesig;
1186                         goto next_type;
1187
1188                 nomatch:
1189                 }
1190
1191                 /* no primitive type and no arrayclass, so must be object */
1192                 *pos++ = 'L';
1193                 /* copy text */
1194                 for ( utf_ptr--; utf_ptr<utf_end(c->name); utf_ptr++)
1195                         *pos++ = *utf_ptr;
1196                 *pos++ = ';';
1197
1198                 next_type:
1199             }  
1200     }       
1201
1202     *pos++ = ')';
1203
1204     if (retType) {
1205         for (i=0;i<strlen(retType);i++) {
1206                 *pos++=retType[i];
1207         }
1208     }
1209     /* create utf-string */
1210     result = utf_new(buffer,(pos-buffer));
1211     MFREE(buffer, u1, buffer_size);
1212
1213     return result;
1214 }
1215
1216
1217 /******************************************************************************************
1218
1219         retrieve the next argument or returntype from a descriptor
1220         and return the corresponding class 
1221
1222 *******************************************************************************************/
1223
1224 classinfo *get_type(char **utf_ptr,char *desc_end, bool skip)
1225 {
1226     classinfo *c = class_from_descriptor(*utf_ptr,desc_end,utf_ptr,
1227                                          (skip) ? CLASSLOAD_SKIP : CLASSLOAD_LOAD);
1228     if (!c)
1229         /* unknown type */
1230         panic("illegal descriptor");
1231
1232     if (skip) return NULL;
1233
1234     use_class_as_object(c);
1235     return c;
1236 }
1237
1238
1239 /******************************************************************************************
1240
1241         use the descriptor of a method to generate a java/lang/Class array
1242         which contains the classes of the parametertypes of the method
1243
1244 *******************************************************************************************/
1245
1246 java_objectarray* get_parametertypes(methodinfo *m) 
1247 {
1248     utf  *descr    =  m->descriptor;    /* method-descriptor */ 
1249     char *utf_ptr  =  descr->text;      /* current position in utf-text */
1250     char *desc_end =  utf_end(descr);   /* points behind utf string     */
1251     java_objectarray* result;
1252     int parametercount = 0;
1253     int i;
1254
1255     /* skip '(' */
1256     utf_nextu2(&utf_ptr);
1257   
1258     /* determine number of parameters */
1259     while ( *utf_ptr != ')' ) {
1260         get_type(&utf_ptr,desc_end,true);
1261         parametercount++;
1262     }
1263
1264     /* create class-array */
1265     result = builtin_anewarray(parametercount, class_java_lang_Class);
1266
1267     utf_ptr  =  descr->text;
1268     utf_nextu2(&utf_ptr);
1269
1270     /* get returntype classes */
1271     for (i = 0; i < parametercount; i++)
1272             result->data[i] = (java_objectheader *) get_type(&utf_ptr,desc_end, false);
1273
1274     return result;
1275 }
1276
1277
1278 /******************************************************************************************
1279
1280         get the returntype class of a method
1281
1282 *******************************************************************************************/
1283
1284 classinfo *get_returntype(methodinfo *m) 
1285 {
1286         char *utf_ptr;   /* current position in utf-text */
1287         char *desc_end;  /* points behind utf string     */
1288         utf *desc = m->descriptor; /* method-descriptor  */
1289
1290         utf_ptr  = desc->text;
1291         desc_end = utf_end(desc);
1292
1293         /* ignore parametertypes */
1294         while ((utf_ptr<desc_end) && utf_nextu2(&utf_ptr)!=')')
1295                 /* skip */ ;
1296
1297         return get_type(&utf_ptr,desc_end, false);
1298 }
1299
1300
1301 /*****************************************************************************/
1302 /*****************************************************************************/
1303
1304
1305 /*--------------------------------------------------------*/
1306 void printNativeCall(nativeCall nc) {
1307   int i,j;
1308
1309   printf("\n%s's Native Methods call:\n",nc.classname); fflush(stdout);
1310   for (i=0; i<nc.methCnt; i++) {  
1311       printf("\tMethod=%s %s\n",nc.methods[i].methodname, nc.methods[i].descriptor);fflush(stdout);
1312
1313     for (j=0; j<nc.callCnt[i]; j++) {  
1314         printf("\t\t<%i,%i>aCalled = %s %s %s\n",i,j,
1315         nc.methods[i].methodCalls[j].classname, 
1316         nc.methods[i].methodCalls[j].methodname, 
1317         nc.methods[i].methodCalls[j].descriptor);fflush(stdout);
1318       }
1319     }
1320   printf("-+++++--------------------\n");fflush(stdout);
1321 }
1322
1323 /*--------------------------------------------------------*/
1324 void printCompNativeCall(nativeCompCall nc) {
1325   int i,j;
1326   printf("printCompNativeCall BEGIN\n");fflush(stdout); 
1327   printf("\n%s's Native Comp Methods call:\n",nc.classname->text);fflush(stdout);
1328   utf_display(nc.classname); fflush(stdout);
1329   
1330   for (i=0; i<nc.methCnt; i++) {  
1331     printf("\tMethod=%s %s\n",nc.methods[i].methodname->text,nc.methods[i].descriptor->text);fflush(stdout);
1332     utf_display(nc.methods[i].methodname); fflush(stdout);
1333     utf_display(nc.methods[i].descriptor);fflush(stdout);
1334     printf("\n");fflush(stdout);
1335
1336     for (j=0; j<nc.callCnt[i]; j++) {  
1337       printf("\t\t<%i,%i>bCalled = ",i,j);fflush(stdout);
1338         utf_display(nc.methods[i].methodCalls[j].classname);fflush(stdout);
1339         utf_display(nc.methods[i].methodCalls[j].methodname); fflush(stdout);
1340         utf_display(nc.methods[i].methodCalls[j].descriptor);fflush(stdout);
1341         printf("\n");fflush(stdout);
1342       }
1343     }
1344 printf("---------------------\n");fflush(stdout);
1345 }
1346
1347
1348 /*--------------------------------------------------------*/
1349 classMeth findNativeMethodCalls(utf *c, utf *m, utf *d ) 
1350 {
1351     int i = 0;
1352     int j = 0;
1353     int cnt = 0;
1354     classMeth mc;
1355     mc.i_class = i;
1356     mc.j_method = j;
1357     mc.methCnt = cnt;
1358
1359     return mc;
1360 }
1361
1362 /*--------------------------------------------------------*/
1363 nativeCall* findNativeClassCalls(char *aclassname ) {
1364 int i;
1365
1366 for (i=0;i<NATIVECALLSSIZE; i++) {
1367    /* convert table to utf later to speed up search */ 
1368    if (strcmp(nativeCalls[i].classname, aclassname) == 0) 
1369         return &nativeCalls[i];
1370    }
1371
1372 return NULL;
1373 }
1374 /*--------------------------------------------------------*/
1375 /*--------------------------------------------------------*/
1376 void utfNativeCall(nativeCall nc, nativeCompCall *ncc) {
1377   int i,j;
1378
1379
1380   ncc->classname = utf_new_char(nc.classname); 
1381   ncc->methCnt = nc.methCnt;
1382   
1383   for (i=0; i<nc.methCnt; i++) {  
1384     ncc->methods[i].methodname = utf_new_char(nc.methods[i].methodname);
1385     ncc->methods[i].descriptor = utf_new_char(nc.methods[i].descriptor);
1386     ncc->callCnt[i] = nc.callCnt[i];
1387
1388     for (j=0; j<nc.callCnt[i]; j++) {  
1389
1390         ncc->methods[i].methodCalls[j].classname  = utf_new_char(nc.methods[i].methodCalls[j].classname);
1391
1392         if (strcmp("", nc.methods[i].methodCalls[j].methodname) != 0) {
1393           ncc->methods[i].methodCalls[j].methodname = utf_new_char(nc.methods[i].methodCalls[j].methodname);
1394           ncc->methods[i].methodCalls[j].descriptor = utf_new_char(nc.methods[i].methodCalls[j].descriptor);
1395           }
1396         else {
1397           ncc->methods[i].methodCalls[j].methodname = NULL;
1398           ncc->methods[i].methodCalls[j].descriptor = NULL;
1399           }
1400       }
1401     }
1402 }
1403
1404
1405
1406 /*--------------------------------------------------------*/
1407
1408 bool natcall2utf(bool natcallcompdone) {
1409 int i;
1410
1411 if (natcallcompdone) 
1412         return true;
1413
1414 for (i=0;i<NATIVECALLSSIZE; i++) {
1415    utfNativeCall  (nativeCalls[i], &nativeCompCalls[i]);  
1416    }
1417
1418 return true;
1419 }
1420 /*--------------------------------------------------------*/
1421
1422
1423 /*
1424  * These are local overrides for various environment variables in Emacs.
1425  * Please do not remove this and leave it at the end of the file, where
1426  * Emacs will automagically detect them.
1427  * ---------------------------------------------------------------------
1428  * Local variables:
1429  * mode: c
1430  * indent-tabs-mode: t
1431  * c-basic-offset: 4
1432  * tab-width: 4
1433  * End:
1434  */