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