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