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