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