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