Fixed some exceptions in native functions
[cacao.git] / native.c
1 /****************************** native.c ***************************************
2
3         Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
4
5         See file COPYRIGHT for information on usage and disclaimer of warranties
6
7     Contains the tables for native methods.
8         The .hh files created with the header file generator are all included here
9         as are the C functions implementing these methods.
10         
11         Authors: Reinhard Grafl      EMAIL: cacao@complang.tuwien.ac.at 
12                  Roman Obermaisser   EMAIL: cacao@complang.tuwien.ac.at 
13                  Andreas Krall       EMAIL: cacao@complang.tuwien.ac.at 
14
15         Last Change: 2003/02/26
16
17 *******************************************************************************/
18
19 #include <unistd.h>
20 #include <time.h>
21 #include "global.h"
22 #include "native.h"
23 #include "nativetypes.hh"
24 #include "builtin.h"
25 #include "asmpart.h"
26 #include "tables.h"
27 #include "loader.h"
28 #include <math.h>
29 #include <string.h>
30 #include <assert.h>
31 #include <sys/time.h>
32 #include <utime.h>
33 #include <sys/utsname.h>
34
35 #include "threads/thread.h"                       /* schani */
36 #include "threads/locks.h"
37
38 /* Include files for IO functions */
39
40 #include <fcntl.h>
41 #include <dirent.h>
42 #include <sys/types.h>
43 #ifdef _OSF_SOURCE 
44 #include <sys/mode.h>
45 #endif
46 #include <sys/stat.h>
47
48 #include "../threads/threadio.h"                    
49
50 /* searchpath for classfiles */
51 static char *classpath;
52
53 /* for java-string to char conversion */
54 #define MAXSTRINGSIZE 1000                          
55
56 /******************** systemclasses required for native methods ***************/
57
58 static classinfo *class_java_lang_Class;
59 static classinfo *class_java_lang_Cloneable;
60 static classinfo *class_java_lang_CloneNotSupportedException;
61 static classinfo *class_java_lang_System;
62 static classinfo *class_java_lang_ClassLoader;
63 static classinfo *class_java_lang_ClassNotFoundException;
64 static classinfo *class_java_lang_InstantiationException;
65 static classinfo *class_java_lang_NoSuchMethodError;   
66 static classinfo *class_java_lang_NoSuchFieldError;
67 static classinfo *class_java_lang_ClassFormatError;
68 static classinfo *class_java_lang_IllegalArgumentException;
69 static classinfo *class_java_lang_ArrayIndexOutOfBoundsException;
70 static classinfo *class_java_lang_NoSuchFieldException;
71 static classinfo *class_java_io_SyncFailedException;
72 static classinfo *class_java_io_IOException;
73 static classinfo *class_java_io_FileNotFoundException;
74 static classinfo *class_java_io_UnixFileSystem;
75 static classinfo *class_java_security_PrivilegedActionException;
76 static classinfo *class_java_net_UnknownHostException;
77 static classinfo *class_java_net_SocketException;
78 static classinfo *class_java_lang_NoSuchMethodException;
79 static classinfo *class_java_lang_Double;
80 static classinfo *class_java_lang_Float;
81 static classinfo *class_java_lang_Long;
82 static classinfo *class_java_lang_Byte;
83 static classinfo *class_java_lang_Short;
84 static classinfo *class_java_lang_Boolean;
85 static classinfo *class_java_lang_Void;
86 static classinfo *class_java_lang_Character;
87 static classinfo *class_java_lang_Integer;
88
89 /* the system classloader object */
90 struct java_lang_ClassLoader *SystemClassLoader = NULL;
91
92 /* for raising exceptions from native methods */
93 java_objectheader* exceptionptr = NULL;
94
95 /************* use classinfo structure as java.lang.Class object **************/
96
97 static void use_class_as_object (classinfo *c) 
98 {
99         vftbl *vt = class_java_lang_Class -> vftbl;
100         vftbl *newtbl;
101         if (!c->classvftbl) {
102                 c->classvftbl = true;
103                 copy_vftbl(&newtbl, vt);
104                 newtbl->class = c->header.vftbl->class;
105                 newtbl->baseval = c->header.vftbl->baseval;
106                 newtbl->diffval = c->header.vftbl->diffval;
107                 c->header.vftbl = newtbl;
108         }
109 }
110
111 /*********************** include Java Native Interface ************************/ 
112
113 #include "jni.c"
114
115 /*************************** include native methods ***************************/ 
116
117 #include "nat/Object.c"
118 #include "nat/String.c"
119 #include "nat/ClassLoader.c"
120 #include "nat/Class.c"
121 #include "nat/Compiler.c"
122 #include "nat/Double.c"
123 #include "nat/Float.c"
124 #include "nat/Math.c"
125 #include "nat/Package.c"
126 #include "nat/Runtime.c"
127 #include "nat/SecurityManager.c"
128 #include "nat/System.c"
129 #include "nat/Thread.c"
130 #include "nat/Throwable.c"
131 #include "nat/Finalizer.c"
132 #include "nat/Array.c"
133 #include "nat/Constructor.c"
134 #include "nat/Field.c"
135 #include "nat/Method.c"
136 #include "nat/FileDescriptor.c"
137 #include "nat/FileInputStream.c"
138 #include "nat/FileOutputStream.c"
139 #include "nat/FileSystem.c"
140 #include "nat/ObjectInputStream.c"
141 #include "nat/ObjectStreamClass.c"
142 #include "nat/RandomAccessFile.c"
143 #include "nat/ResourceBundle.c"
144 #include "nat/JarFile.c"
145 #include "nat/Adler32.c"
146 #include "nat/CRC32.c"
147 #include "nat/Deflater.c"
148 #include "nat/Inflater.c"
149 #include "nat/ZipEntry.c"
150 #include "nat/ZipFile.c"
151 #include "nat/BigInteger.c"
152 #include "nat/InetAddress.c"
153 #include "nat/InetAddressImpl.c"
154 #include "nat/DatagramPacket.c"
155 #include "nat/PlainDatagramSocketImpl.c"
156 #include "nat/PlainSocketImpl.c"
157 #include "nat/SocketInputStream.c"
158 #include "nat/SocketOutputStream.c"
159 #include "nat/AccessController.c"
160 #include "nat/ClassLoader_NativeLibrary.c"
161 #include "nat/UnixFileSystem.c"
162
163 /************************** tables for methods ********************************/
164
165 /* table for locating native methods */
166 static struct nativeref {
167         char *classname;
168         char *methodname;
169         char *descriptor;
170         bool isstatic;
171         functionptr func;
172 } nativetable [] = {
173
174 #include "nativetable.hh"
175
176 };
177
178
179 #define NATIVETABLESIZE  (sizeof(nativetable)/sizeof(struct nativeref))
180
181 /* table for fast string comparison */
182 static struct nativecompref {
183         utf *classname;
184         utf *methodname;
185         utf *descriptor;
186         bool isstatic;
187         functionptr func;
188         } nativecomptable [NATIVETABLESIZE];
189
190 /* string comparsion table initialized */
191 static bool nativecompdone = false;
192
193
194 /*********************** function: native_loadclasses **************************
195
196         load classes required for native methods        
197
198 *******************************************************************************/
199
200 void native_loadclasses()
201 {
202         /* class_new adds the class to the list of classes to be loaded */
203         class_java_lang_Cloneable = 
204                 class_new ( utf_new_char ("java/lang/Cloneable") );
205         class_java_lang_CloneNotSupportedException = 
206                 class_new ( utf_new_char ("java/lang/CloneNotSupportedException") );
207         class_java_lang_Class =
208                 class_new ( utf_new_char ("java/lang/Class") );
209         class_java_io_IOException = 
210                 class_new ( utf_new_char ("java/io/IOException") );
211         class_java_io_FileNotFoundException = 
212                 class_new ( utf_new_char ("java/io/FileNotFoundException") );
213         class_java_lang_ClassNotFoundException =
214                 class_new ( utf_new_char ("java/lang/ClassNotFoundException") );
215         class_java_lang_InstantiationException =
216                 class_new ( utf_new_char ("java/lang/InstantiationException") );
217         class_java_lang_NoSuchMethodError =
218                 class_new ( utf_new_char ("java/lang/NoSuchMethodError") );
219         class_java_lang_NoSuchFieldError =
220                 class_new ( utf_new_char ("java/lang/NoSuchFieldError") );      
221         class_java_lang_ClassFormatError =
222                 class_new ( utf_new_char ("java/lang/ClassFormatError") );      
223         class_java_io_SyncFailedException =
224                 class_new ( utf_new_char ("java/io/SyncFailedException") );
225         class_java_io_UnixFileSystem =
226                 class_new ( utf_new_char ("java/io/UnixFileSystem") );
227         class_java_lang_System =
228                 class_new ( utf_new_char ("java/lang/System") );
229         class_java_lang_ClassLoader =
230                 class_new ( utf_new_char ("java/lang/ClassLoader") );   
231         class_java_security_PrivilegedActionException =
232                 class_new( utf_new_char("java/security/PrivilegedActionException"));
233         class_java_net_UnknownHostException = 
234                 loader_load( utf_new_char ("java/net/UnknownHostException") );
235         class_java_net_SocketException = 
236                 loader_load( utf_new_char ("java/net/SocketException") );
237         class_java_lang_IllegalArgumentException =
238                 class_new( utf_new_char("java/lang/IllegalArgumentException"));
239         class_java_lang_ArrayIndexOutOfBoundsException =
240                 class_new( utf_new_char ("java/lang/ArrayIndexOutOfBoundsException") );
241         class_java_lang_NoSuchFieldException =
242                 class_new( utf_new_char ("java/lang/NoSuchFieldException") );       
243         class_java_lang_NoSuchMethodException = 
244                 class_new( utf_new_char ("java/lang/NoSuchMethodException") );      
245
246         /* load classes for wrapping primitive types */
247         class_java_lang_Double =
248                 class_new( utf_new_char ("java/lang/Double") );
249         class_java_lang_Float =
250                 class_new( utf_new_char ("java/lang/Float") );
251         class_java_lang_Character =
252                 class_new( utf_new_char ("java/lang/Character") );
253         class_java_lang_Integer =
254                 class_new( utf_new_char ("java/lang/Integer") );
255         class_java_lang_Long =
256                 class_new( utf_new_char ("java/lang/Long") );
257         class_java_lang_Byte =
258                 class_new( utf_new_char ("java/lang/Byte") );
259         class_java_lang_Short =
260                 class_new( utf_new_char ("java/lang/Short") );
261         class_java_lang_Boolean =
262                 class_new( utf_new_char ("java/lang/Boolean") );
263         class_java_lang_Void =
264                 class_new( utf_new_char ("java/lang/Void") );
265
266         /* load to avoid dynamic classloading */
267         class_new(utf_new_char("sun/net/www/protocol/file/Handler"));
268         class_new(utf_new_char("sun/net/www/protocol/jar/Handler"));    
269         class_new(utf_new_char("sun/io/CharToByteISO8859_1"));
270         
271         /* start classloader */
272         loader_load(utf_new_char("sun/io/ByteToCharISO8859_1")); 
273 }
274
275
276 /*************** adds a class to the vector of loaded classes ****************/
277
278 void systemclassloader_addclass(classinfo *c)
279 {
280         methodinfo *m;
281
282         /* find method addClass of java.lang.ClassLoader */
283         m = class_resolvemethod (
284                 class_java_lang_ClassLoader, 
285                 utf_new_char("addClass"),
286                 utf_new_char("(Ljava/lang/Class;)")
287             );
288
289         if (!m) panic("warning: cannot initialize classloader");
290
291         /* prepare class to be passed as argument */
292         use_class_as_object (c);
293
294         /* call 'addClass' */
295         asm_calljavamethod(m,
296                            (java_objectheader*) SystemClassLoader, 
297                            (java_objectheader*) c,
298                            NULL,  
299                            NULL
300                           );       
301 }
302
303 /*************** adds a library to the vector of loaded libraries *************/
304
305 void systemclassloader_addlibrary(java_objectheader *o)
306 {
307         methodinfo *m;
308
309         /* find method addElement of java.util.Vector */
310         m = class_resolvemethod (
311                 loader_load ( utf_new_char ("java/util/Vector") ),
312                 utf_new_char("addElement"),
313                 utf_new_char("(Ljava/lang/Object;)V")
314             );
315
316         if (!m) panic("cannot initialize classloader");
317
318         /* call 'addElement' */
319         asm_calljavamethod(m,
320                            SystemClassLoader->nativeLibraries,
321                            o,
322                            NULL,  
323                            NULL
324                           );       
325 }
326
327 /*****************************************************************************
328
329         create systemclassloader object and initialize instance fields  
330
331 ******************************************************************************/
332
333 void init_systemclassloader() 
334 {
335   if (!SystemClassLoader) {
336
337         /* create object and call initializer */
338         SystemClassLoader = (java_lang_ClassLoader*) native_new_and_init(class_java_lang_ClassLoader);  
339         heap_addreference((void**) &SystemClassLoader);
340
341         /* systemclassloader has no parent */
342         SystemClassLoader->parent      = NULL;
343         SystemClassLoader->initialized = true;
344   }
345 }
346
347
348 /********************* add loaded library name  *******************************/
349
350 void systemclassloader_addlibname(java_objectheader *o)
351 {
352         methodinfo *m;
353         java_objectheader *LibraryNameVector;
354         jfieldID id;
355
356         m = class_resolvemethod (
357                 loader_load ( utf_new_char ("java/util/Vector") ),
358                 utf_new_char("addElement"),
359                 utf_new_char("(Ljava/lang/Object;)V")
360             );
361
362         if (!m) panic("cannot initialize classloader");
363
364         id = env.GetStaticFieldID(&env,class_java_lang_ClassLoader,"loadedLibraryNames","Ljava/util/Vector;");
365         if (!id) panic("can not access ClassLoader");
366
367         asm_calljavamethod(m,
368                            GetStaticObjectField(&env,class_java_lang_ClassLoader,id),
369                            o,
370                            NULL,  
371                            NULL
372                           );       
373 }
374
375
376 /********************* function: native_setclasspath **************************/
377  
378 void native_setclasspath (char *path)
379 {
380         /* set searchpath for classfiles */
381         classpath = path;
382 }
383
384 /***************** function: throw_classnotfoundexception *********************/
385
386 void throw_classnotfoundexception()
387 {
388         /* throws a ClassNotFoundException */
389         exceptionptr = native_new_and_init (class_java_lang_ClassNotFoundException);
390 }
391
392
393 /*********************** Function: native_findfunction *************************
394
395         Looks up a method (must have the same class name, method name, descriptor
396         and 'static'ness) and returns a function pointer to it.
397         Returns: function pointer or NULL (if there is no such method)
398
399         Remark: For faster operation, the names/descriptors are converted from C
400                 strings to Unicode the first time this function is called.
401
402 *******************************************************************************/
403
404 functionptr native_findfunction (utf *cname, utf *mname, 
405                                  utf *desc, bool isstatic)
406 {
407         int i;
408         /* entry of table for fast string comparison */
409         struct nativecompref *n;
410         /* for warning message if no function is found */
411         char *buffer;                   
412         int buffer_len, pos;
413
414         isstatic = isstatic ? true : false;
415
416         if (!nativecompdone) {
417                 for (i = 0; i < NATIVETABLESIZE; i++) {
418                         nativecomptable[i].classname  = 
419                                         utf_new_char(nativetable[i].classname);
420                         nativecomptable[i].methodname = 
421                                         utf_new_char(nativetable[i].methodname);
422                         nativecomptable[i].descriptor = 
423                                         utf_new_char(nativetable[i].descriptor);
424                         nativecomptable[i].isstatic   = 
425                                         nativetable[i].isstatic;
426                         nativecomptable[i].func       = 
427                                         nativetable[i].func;
428                         }
429                 nativecompdone = true;
430                 }
431
432         for (i = 0; i < NATIVETABLESIZE; i++) {
433                 n = &(nativecomptable[i]);
434
435                 if (cname == n->classname && mname == n->methodname &&
436                     desc == n->descriptor && isstatic == n->isstatic)
437                         return n->func;
438                 }
439
440         /* no function was found, display warning */
441
442         buffer_len = 
443           utf_strlen(cname) + utf_strlen(mname) + utf_strlen(desc) + 64;
444
445         buffer = MNEW(char, buffer_len);
446
447         strcpy(buffer, "warning: native function ");
448         utf_sprint(buffer+strlen(buffer), mname);
449         strcpy(buffer+strlen(buffer), ": ");
450         utf_sprint(buffer+strlen(buffer), desc);
451         strcpy(buffer+strlen(buffer), " not found in class ");
452         utf_sprint(buffer+strlen(buffer), cname);
453
454         log_text(buffer);       
455
456         MFREE(buffer, char, buffer_len);
457
458         return NULL;
459 }
460
461
462 /********************** function: javastring_new *******************************
463
464         creates a new object of type java/lang/String with the text of 
465         the specified utf8-string
466
467         return: pointer to the string or NULL if memory is exhausted.   
468
469 *******************************************************************************/
470
471 java_objectheader *javastring_new (utf *u)
472 {
473         char *utf_ptr = u->text;        /* current utf character in utf string    */
474         int utflength = utf_strlen(u);  /* length of utf-string if uncompressed   */
475         java_lang_String *s;                /* result-string                          */
476         java_chararray *a;
477         s4 i;
478         
479         s = (java_lang_String*) builtin_new (class_java_lang_String);
480         a = builtin_newarray_char (utflength);
481
482         /* javastring or character-array could not be created */
483         if ((!a) || (!s))
484                 return NULL;
485
486         /* decompress utf-string */
487         for (i = 0; i < utflength; i++)
488                 a->data[i] = utf_nextu2(&utf_ptr);
489         
490         /* set fields of the javastring-object */
491         s -> value  = a;
492         s -> offset = 0;
493         s -> count  = utflength;
494
495         return (java_objectheader*) s;
496 }
497
498 /********************** function: javastring_new_char **************************
499
500         creates a new java/lang/String object which contains the convertet
501         C-string passed via text.
502
503         return: the object pointer or NULL if memory is exhausted.
504
505 *******************************************************************************/
506
507 java_objectheader *javastring_new_char (char *text)
508 {
509         s4 i;
510         s4 len = strlen(text); /* length of the string */
511         java_lang_String *s;   /* result-string */
512         java_chararray *a;
513         
514         s = (java_lang_String*) builtin_new (class_java_lang_String);
515         a = builtin_newarray_char (len);
516
517         /* javastring or character-array could not be created */
518         if ((!a) || (!s)) return NULL;
519
520         /* copy text */
521         for (i = 0; i < len; i++)
522                 a->data[i] = text[i];
523         
524         /* set fields of the javastring-object */
525         s -> value = a;
526         s -> offset = 0;
527         s -> count = len;
528
529         return (java_objectheader*) s;
530 }
531
532
533 /************************* function javastring_tochar **************************
534
535         converts a Java string into a C string.
536         
537         return: pointer to C string
538         
539         Caution: every call of this function overwrites the previous string !!!
540         
541 *******************************************************************************/
542
543 static char stringbuffer[MAXSTRINGSIZE];
544
545 char *javastring_tochar (java_objectheader *so) 
546 {
547         java_lang_String *s = (java_lang_String*) so;
548         java_chararray *a;
549         s4 i;
550         
551         if (!s)
552                 return "";
553         a = s->value;
554         if (!a)
555                 return "";
556         if (s->count > MAXSTRINGSIZE)
557                 return "";
558         for (i = 0; i < s->count; i++)
559                 stringbuffer[i] = a->data[s->offset+i];
560         stringbuffer[i] = '\0';
561         return stringbuffer;
562 }
563
564
565 /****************** function class_findfield_approx ****************************
566         
567         searches in 'classinfo'-structure for a field with the
568         specified name
569
570 *******************************************************************************/
571  
572 fieldinfo *class_findfield_approx (classinfo *c, utf *name)
573 {
574         s4 i;
575         for (i = 0; i < c->fieldscount; i++) {
576                 /* compare field names */
577                 if ((c->fields[i].name == name))
578                         return &(c->fields[i]);
579                 }
580
581         /* field was not found, raise exception */      
582         exceptionptr = native_new_and_init(class_java_lang_NoSuchFieldException);
583         return NULL;
584 }
585
586
587 /********************** function: native_new_and_init *************************
588
589         Creates a new object on the heap and calls the initializer.
590         Returns the object pointer or NULL if memory is exhausted.
591                         
592 *******************************************************************************/
593
594 java_objectheader *native_new_and_init (classinfo *c)
595 {
596         methodinfo *m;
597         java_objectheader *o = builtin_new (c);         /*          create object */
598
599         if (!o) return NULL;
600         
601         /* find initializer */
602
603         m = class_findmethod(c, utf_new_char("<init>"), utf_new_char("()V"));
604                                                       
605         if (!m) {                                       /* initializer not found  */
606                 if (verbose) {
607                         sprintf(logtext, "Warning: class has no instance-initializer: ");
608                         utf_sprint(logtext + strlen(logtext), c->name);
609                         dolog();
610                         }
611                 return o;
612                 }
613
614         /* call initializer */
615
616         asm_calljavamethod (m, o, NULL, NULL, NULL);
617         return o;
618 }
619
620 /******************** function: stringtable_update ****************************
621
622         traverses the javastring hashtable and sets the vftbl-entries of
623         javastrings which were temporarily set to NULL, because 
624         java.lang.Object was not yet loaded
625
626 *******************************************************************************/
627  
628 void stringtable_update ()
629 {
630         java_lang_String *js;   
631         java_chararray *a;
632         literalstring *s;       /* hashtable entry */
633         int i;
634
635         for (i = 0; i < string_hash.size; i++) {
636                 s = string_hash.ptr[i];
637                 if (s) {
638                         while (s) {
639                                                                 
640                                 js = (java_lang_String *) s->string;
641                                 
642                                 if (!js || !(a = js->value)) 
643                                         /* error in hashtable found */
644                                         panic("invalid literalstring in hashtable");
645
646                                 if (!js->header.vftbl) 
647                                         /* vftbl of javastring is NULL */ 
648                                         js->header.vftbl = class_java_lang_String -> vftbl;
649
650                                 if (!a->header.objheader.vftbl) 
651                                         /* vftbl of character-array is NULL */ 
652                                         a->header.objheader.vftbl = class_array -> vftbl;
653
654                                 /* follow link in external hash chain */
655                                 s = s->hashlink;
656                         }       
657                 }               
658         }
659 }
660
661
662 /************************* function: u2_utflength ***************************
663
664         returns the utf length in bytes of a u2 array 
665
666 *****************************************************************************/
667
668
669 u4 u2_utflength(u2 *text, u4 u2_length)
670 {
671         u4 result_len =  0;  /* utf length in bytes  */
672         u2 ch;               /* current unicode character */
673         u4 len;
674         
675         for (len = 0; len < u2_length; len++) {
676           
677           /* next unicode character */
678           ch = *text++;
679           
680           /* determine bytes required to store unicode character as utf */
681           if (ch && (ch < 0x80)) 
682             result_len++;
683           else if (ch < 0x800)
684             result_len += 2;    
685           else 
686             result_len += 3;    
687         }
688
689     return result_len;
690 }
691
692 /********************* function: utf_new_u2 ***********************************
693
694         make utf symbol from u2 array, 
695         if isclassname is true '.' is replaced by '/'
696
697 *******************************************************************************/
698
699 utf *utf_new_u2(u2 *unicode_pos, u4 unicode_length, bool isclassname)
700 {
701         char *buffer; /* memory buffer for  unicode characters */
702         char *pos;    /* pointer to current position in buffer */
703         u4 left;      /* unicode characters left */
704         u4 buflength; /* utf length in bytes of the u2 array  */
705         utf *result;  /* resulting utf-string */
706         int i;          
707
708         /* determine utf length in bytes and allocate memory */         
709         buflength = u2_utflength(unicode_pos, unicode_length); 
710         buffer    = MNEW(char,buflength);
711  
712         /* memory allocation failed */
713         if (!buffer) return NULL;
714
715         left = buflength;
716         pos  = buffer;
717
718         for (i = 0; i++ < unicode_length; unicode_pos++) {
719                 /* next unicode character */
720                 u2 c = *unicode_pos;
721                 
722                 if ((c != 0) && (c < 0x80)) {
723                 /* 1 character */       
724                 left--;
725                 if ((int) left < 0) break;
726                 /* convert classname */
727                 if (isclassname && c=='.') 
728                   *pos++ = '/';
729                 else
730                   *pos++ = (char) c;
731                 } else if (c < 0x800) {             
732                 /* 2 characters */                              
733                 unsigned char high = c >> 6;
734                 unsigned char low  = c & 0x3F;
735                 left = left - 2;
736                 if ((int) left < 0) break;
737                 *pos++ = high | 0xC0; 
738                 *pos++ = low  | 0x80;     
739                 } else {         
740                 /* 3 characters */                              
741                 char low  = c & 0x3f;
742                 char mid  = (c >> 6) & 0x3F;
743                 char high = c >> 12;
744                 left = left - 3;
745                 if ((int) left < 0) break;
746                 *pos++ = high | 0xE0; 
747                 *pos++ = mid  | 0x80;  
748                 *pos++ = low  | 0x80;   
749                 }
750         }
751         
752         /* insert utf-string into symbol-table */
753         result = utf_new(buffer,buflength);
754         MFREE(buffer, char, buflength);
755         return result;
756 }
757
758 /********************* function: javastring_toutf *****************************
759
760         make utf symbol from javastring
761
762 *******************************************************************************/
763
764 utf *javastring_toutf(java_lang_String *string, bool isclassname)
765 {
766         java_lang_String *str = (java_lang_String *) string;
767         return utf_new_u2(str->value->data,str->count, isclassname);
768 }
769
770 /********************* function: literalstring_u2 *****************************
771
772     searches for the javastring with the specified u2-array in 
773     the string hashtable, if there is no such string a new one is 
774     created 
775
776     if copymode is true a copy of the u2-array is made
777
778 *******************************************************************************/
779
780 java_objectheader *literalstring_u2 (java_chararray *a, u4 length, bool copymode )
781 {
782     literalstring *s;                /* hashtable element */
783     java_lang_String *js;            /* u2-array wrapped in javastring */
784     java_chararray *stringdata;      /* copy of u2-array */      
785     u4 key;   
786     u4 slot;  
787     u2 i;
788
789     /* find location in hashtable */
790     key  = unicode_hashkey (a->data, length);
791     slot = key & (string_hash.size-1);
792     s    = string_hash.ptr[slot];
793
794     while (s) {
795         
796       js = (java_lang_String *) s->string;
797         
798       if (js->count == length) {
799         /* compare text */
800         for (i=0; i<length; i++) 
801           if (js->value->data[i] != a->data[i]) goto nomatch;
802                                         
803         /* string already in hashtable, free memory */
804         if (!copymode)
805           lit_mem_free(a, sizeof(java_chararray) + sizeof(u2)*(length-1)+10);
806
807         return (java_objectheader *) js;
808       }
809
810       nomatch:
811       /* follow link in external hash chain */
812       s = s->hashlink;
813     }
814
815     if (copymode) {
816       /* create copy of u2-array for new javastring */
817       u4 arraysize = sizeof(java_chararray) + sizeof(u2)*(length-1)+10;
818       stringdata = lit_mem_alloc ( arraysize ); 
819       memcpy(stringdata, a, arraysize );        
820     }  
821     else
822       stringdata = a;
823
824     /* location in hashtable found, complete arrayheader */
825     if (class_array==NULL) panic("class_array not initialized");
826     stringdata -> header.objheader.vftbl = class_array -> vftbl;
827     stringdata -> header.size = length; 
828     stringdata -> header.arraytype = ARRAYTYPE_CHAR;    
829
830     /* create new javastring */
831     js = LNEW (java_lang_String);
832     js -> header.vftbl = class_java_lang_String -> vftbl;
833     js -> value  = stringdata;
834     js -> offset = 0;
835     js -> count  = length;
836
837     /* create new literalstring */
838     s = NEW (literalstring);
839     s->hashlink = string_hash.ptr[slot];
840     s->string   = (java_objectheader *) js;
841     string_hash.ptr[slot] = s;
842
843     /* update numbe of hashtable entries */
844     string_hash.entries++;
845
846     /* reorganization of hashtable */       
847     if ( string_hash.entries > (string_hash.size*2)) {
848
849       /* reorganization of hashtable, average length of 
850          the external chains is approx. 2                */  
851
852       u4 i;
853       literalstring *s;     
854       hashtable newhash; /* the new hashtable */
855       
856       /* create new hashtable, double the size */
857       init_hashtable(&newhash, string_hash.size*2);
858       newhash.entries=string_hash.entries;
859       
860       /* transfer elements to new hashtable */
861       for (i=0; i<string_hash.size; i++) {
862         s = string_hash.ptr[i];
863         while (s) {
864           literalstring *nexts = s -> hashlink;  
865           js   = (java_lang_String*) s->string;
866           slot = (unicode_hashkey(js->value->data,js->count)) & (newhash.size-1);
867           
868           s->hashlink = newhash.ptr[slot];
869           newhash.ptr[slot] = s;
870         
871           /* follow link in external hash chain */  
872           s = nexts;
873         }
874       }
875         
876       /* dispose old table */   
877       MFREE (string_hash.ptr, void*, string_hash.size);
878       string_hash = newhash;
879     }
880                         
881     return (java_objectheader *) js;
882 }
883
884 /******************** Function: literalstring_new *****************************
885
886     creates a new javastring with the text of the utf-symbol
887     and inserts it into the string hashtable
888
889 *******************************************************************************/
890
891 java_objectheader *literalstring_new (utf *u)
892 {
893     char *utf_ptr = u->text;         /* pointer to current unicode character in utf string */
894     u4 utflength  = utf_strlen(u);   /* length of utf-string if uncompressed */
895     java_chararray *a;               /* u2-array constructed from utf string */
896     java_objectheader *js;
897     u4 i;
898     
899     /* allocate memory */ 
900     a = lit_mem_alloc (sizeof(java_chararray) + sizeof(u2)*(utflength-1)+10 );  
901     /* convert utf-string to u2-array */
902     for (i=0; i<utflength; i++) a->data[i] = utf_nextu2(&utf_ptr);      
903
904     return literalstring_u2(a, utflength, false);
905 }
906
907
908 /********************** function: literalstring_free **************************
909
910         removes a javastring from memory                       
911
912 ******************************************************************************/
913
914 void literalstring_free (java_objectheader* sobj)
915 {
916         java_lang_String *s = (java_lang_String*) sobj;
917         java_chararray *a = s->value;
918
919         log_text("literalstring_free called");
920         
921         /* dispose memory of java.lang.String object */
922         LFREE (s, java_lang_String);
923         /* dispose memory of java-characterarray */
924         LFREE (a, sizeof(java_chararray) + sizeof(u2)*(a->header.size-1)); /* +10 ?? */
925 }
926
927
928
929
930 void copy_vftbl(vftbl **dest, vftbl *src)
931 {
932         *dest = mem_alloc(sizeof(vftbl) + sizeof(methodptr)*(src->vftbllength-1));
933         memcpy(*dest, src, sizeof(vftbl) - sizeof(methodptr));
934         memcpy(&(*dest)->table, &src->table, src->vftbllength * sizeof(methodptr));
935 }