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