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