5378f1d7e10c4ecde1f3fa6a25c91251860db75c
[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     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 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         jfieldID id;
368
369         m = class_resolvemethod (
370                 loader_load ( utf_new_char ("java/util/Vector") ),
371                 utf_new_char("addElement"),
372                 utf_new_char("(Ljava/lang/Object;)V")
373             );
374
375         if (!m) panic("cannot initialize classloader");
376
377         id = env.GetStaticFieldID(&env,class_java_lang_ClassLoader,"loadedLibraryNames","Ljava/util/Vector;");
378         if (!id) panic("can not access ClassLoader");
379
380         asm_calljavamethod(m,
381                            GetStaticObjectField(&env,class_java_lang_ClassLoader,id),
382                            o,
383                            NULL,  
384                            NULL
385                           );       
386 }
387
388
389 /********************* function: native_setclasspath **************************/
390  
391 void native_setclasspath (char *path)
392 {
393         /* set searchpath for classfiles */
394         classpath = path;
395 }
396
397 /***************** function: throw_classnotfoundexception *********************/
398
399 void throw_classnotfoundexception()
400 {
401     if (!class_java_lang_ClassNotFoundException) {
402         panic("java.lang.ClassNotFoundException not found. Maybe wrong classpath?");
403     }
404
405         /* throws a ClassNotFoundException */
406         exceptionptr = native_new_and_init (class_java_lang_ClassNotFoundException);
407 }
408
409
410 /*********************** Function: native_findfunction *************************
411
412         Looks up a method (must have the same class name, method name, descriptor
413         and 'static'ness) and returns a function pointer to it.
414         Returns: function pointer or NULL (if there is no such method)
415
416         Remark: For faster operation, the names/descriptors are converted from C
417                 strings to Unicode the first time this function is called.
418
419 *******************************************************************************/
420
421 functionptr native_findfunction (utf *cname, utf *mname, 
422                                  utf *desc, bool isstatic)
423 {
424         int i;
425         /* entry of table for fast string comparison */
426         struct nativecompref *n;
427         /* for warning message if no function is found */
428         char *buffer;                   
429         int buffer_len;
430
431         isstatic = isstatic ? true : false;
432
433         if (!nativecompdone) {
434                 for (i = 0; i < NATIVETABLESIZE; i++) {
435                         nativecomptable[i].classname  = 
436                                         utf_new_char(nativetable[i].classname);
437                         nativecomptable[i].methodname = 
438                                         utf_new_char(nativetable[i].methodname);
439                         nativecomptable[i].descriptor = 
440                                         utf_new_char(nativetable[i].descriptor);
441                         nativecomptable[i].isstatic   = 
442                                         nativetable[i].isstatic;
443                         nativecomptable[i].func       = 
444                                         nativetable[i].func;
445                         }
446                 nativecompdone = true;
447                 }
448
449         for (i = 0; i < NATIVETABLESIZE; i++) {
450                 n = &(nativecomptable[i]);
451
452                 if (cname == n->classname && mname == n->methodname &&
453                     desc == n->descriptor && isstatic == n->isstatic)
454                         return n->func;
455                 }
456
457         /* no function was found, display warning */
458
459         buffer_len = 
460           utf_strlen(cname) + utf_strlen(mname) + utf_strlen(desc) + 64;
461
462         buffer = MNEW(char, buffer_len);
463
464         strcpy(buffer, "warning: native function ");
465         utf_sprint(buffer+strlen(buffer), mname);
466         strcpy(buffer+strlen(buffer), ": ");
467         utf_sprint(buffer+strlen(buffer), desc);
468         strcpy(buffer+strlen(buffer), " not found in class ");
469         utf_sprint(buffer+strlen(buffer), cname);
470
471         log_text(buffer);       
472
473         MFREE(buffer, char, buffer_len);
474
475         return NULL;
476 }
477
478
479 /********************** function: javastring_new *******************************
480
481         creates a new object of type java/lang/String with the text of 
482         the specified utf8-string
483
484         return: pointer to the string or NULL if memory is exhausted.   
485
486 *******************************************************************************/
487
488 java_objectheader *javastring_new (utf *u)
489 {
490         char *utf_ptr = u->text;        /* current utf character in utf string    */
491         int utflength = utf_strlen(u);  /* length of utf-string if uncompressed   */
492         java_lang_String *s;                /* result-string                          */
493         java_chararray *a;
494         s4 i;
495         
496         s = (java_lang_String*) builtin_new (class_java_lang_String);
497         a = builtin_newarray_char (utflength);
498
499         /* javastring or character-array could not be created */
500         if ((!a) || (!s))
501                 return NULL;
502
503         /* decompress utf-string */
504         for (i = 0; i < utflength; i++)
505                 a->data[i] = utf_nextu2(&utf_ptr);
506         
507         /* set fields of the javastring-object */
508         s -> value  = a;
509         s -> offset = 0;
510         s -> count  = utflength;
511
512         return (java_objectheader*) s;
513 }
514
515 /********************** function: javastring_new_char **************************
516
517         creates a new java/lang/String object which contains the convertet
518         C-string passed via text.
519
520         return: the object pointer or NULL if memory is exhausted.
521
522 *******************************************************************************/
523
524 java_objectheader *javastring_new_char (char *text)
525 {
526         s4 i;
527         s4 len = strlen(text); /* length of the string */
528         java_lang_String *s;   /* result-string */
529         java_chararray *a;
530         
531         s = (java_lang_String*) builtin_new (class_java_lang_String);
532         a = builtin_newarray_char (len);
533
534         /* javastring or character-array could not be created */
535         if ((!a) || (!s)) return NULL;
536
537         /* copy text */
538         for (i = 0; i < len; i++)
539                 a->data[i] = text[i];
540         
541         /* set fields of the javastring-object */
542         s -> value = a;
543         s -> offset = 0;
544         s -> count = len;
545
546         return (java_objectheader*) s;
547 }
548
549
550 /************************* function javastring_tochar **************************
551
552         converts a Java string into a C string.
553         
554         return: pointer to C string
555         
556         Caution: every call of this function overwrites the previous string !!!
557         
558 *******************************************************************************/
559
560 static char stringbuffer[MAXSTRINGSIZE];
561
562 char *javastring_tochar (java_objectheader *so) 
563 {
564         java_lang_String *s = (java_lang_String*) so;
565         java_chararray *a;
566         s4 i;
567         
568         if (!s)
569                 return "";
570         a = s->value;
571         if (!a)
572                 return "";
573         if (s->count > MAXSTRINGSIZE)
574                 return "";
575         for (i = 0; i < s->count; i++)
576                 stringbuffer[i] = a->data[s->offset+i];
577         stringbuffer[i] = '\0';
578         return stringbuffer;
579 }
580
581
582 /****************** function class_findfield_approx ****************************
583         
584         searches in 'classinfo'-structure for a field with the
585         specified name
586
587 *******************************************************************************/
588  
589 fieldinfo *class_findfield_approx (classinfo *c, utf *name)
590 {
591         s4 i;
592         for (i = 0; i < c->fieldscount; i++) {
593                 /* compare field names */
594                 if ((c->fields[i].name == name))
595                         return &(c->fields[i]);
596                 }
597
598         /* field was not found, raise exception */      
599         exceptionptr = native_new_and_init(class_java_lang_NoSuchFieldException);
600         return NULL;
601 }
602
603
604 /********************** function: native_new_and_init *************************
605
606         Creates a new object on the heap and calls the initializer.
607         Returns the object pointer or NULL if memory is exhausted.
608                         
609 *******************************************************************************/
610
611 java_objectheader *native_new_and_init (classinfo *c)
612 {
613         methodinfo *m;
614         java_objectheader *o = builtin_new (c);         /*          create object */
615
616         if (!o) return NULL;
617         
618         /* find initializer */
619
620         m = class_findmethod(c, utf_new_char("<init>"), utf_new_char("()V"));
621                                                       
622         if (!m) {                                       /* initializer not found  */
623                 if (verbose) {
624                         sprintf(logtext, "Warning: class has no instance-initializer: ");
625                         utf_sprint(logtext + strlen(logtext), c->name);
626                         dolog();
627                         }
628                 return o;
629                 }
630
631         /* call initializer */
632
633         asm_calljavamethod (m, o, NULL, NULL, NULL);
634         return o;
635 }
636
637 /******************** function: stringtable_update ****************************
638
639         traverses the javastring hashtable and sets the vftbl-entries of
640         javastrings which were temporarily set to NULL, because 
641         java.lang.Object was not yet loaded
642
643 *******************************************************************************/
644  
645 void stringtable_update ()
646 {
647         java_lang_String *js;   
648         java_chararray *a;
649         literalstring *s;       /* hashtable entry */
650         int i;
651
652         for (i = 0; i < string_hash.size; i++) {
653                 s = string_hash.ptr[i];
654                 if (s) {
655                         while (s) {
656                                                                 
657                                 js = (java_lang_String *) s->string;
658                                 
659                                 if (!js || !(a = js->value)) 
660                                         /* error in hashtable found */
661                                         panic("invalid literalstring in hashtable");
662
663                                 if (!js->header.vftbl) 
664                                         /* vftbl of javastring is NULL */ 
665                                         js->header.vftbl = class_java_lang_String -> vftbl;
666
667                                 if (!a->header.objheader.vftbl) 
668                                         /* vftbl of character-array is NULL */ 
669                                         a->header.objheader.vftbl = class_array -> vftbl;
670
671                                 /* follow link in external hash chain */
672                                 s = s->hashlink;
673                         }       
674                 }               
675         }
676 }
677
678
679 /************************* function: u2_utflength ***************************
680
681         returns the utf length in bytes of a u2 array 
682
683 *****************************************************************************/
684
685
686 u4 u2_utflength(u2 *text, u4 u2_length)
687 {
688         u4 result_len =  0;  /* utf length in bytes  */
689         u2 ch;               /* current unicode character */
690         u4 len;
691         
692         for (len = 0; len < u2_length; len++) {
693           
694           /* next unicode character */
695           ch = *text++;
696           
697           /* determine bytes required to store unicode character as utf */
698           if (ch && (ch < 0x80)) 
699             result_len++;
700           else if (ch < 0x800)
701             result_len += 2;    
702           else 
703             result_len += 3;    
704         }
705
706     return result_len;
707 }
708
709 /********************* function: utf_new_u2 ***********************************
710
711         make utf symbol from u2 array, 
712         if isclassname is true '.' is replaced by '/'
713
714 *******************************************************************************/
715
716 utf *utf_new_u2(u2 *unicode_pos, u4 unicode_length, bool isclassname)
717 {
718         char *buffer; /* memory buffer for  unicode characters */
719         char *pos;    /* pointer to current position in buffer */
720         u4 left;      /* unicode characters left */
721         u4 buflength; /* utf length in bytes of the u2 array  */
722         utf *result;  /* resulting utf-string */
723         int i;          
724
725         /* determine utf length in bytes and allocate memory */         
726         buflength = u2_utflength(unicode_pos, unicode_length); 
727         buffer    = MNEW(char,buflength);
728  
729         /* memory allocation failed */
730         if (!buffer) return NULL;
731
732         left = buflength;
733         pos  = buffer;
734
735         for (i = 0; i++ < unicode_length; unicode_pos++) {
736                 /* next unicode character */
737                 u2 c = *unicode_pos;
738                 
739                 if ((c != 0) && (c < 0x80)) {
740                 /* 1 character */       
741                 left--;
742                 if ((int) left < 0) break;
743                 /* convert classname */
744                 if (isclassname && c=='.') 
745                   *pos++ = '/';
746                 else
747                   *pos++ = (char) c;
748                 } else if (c < 0x800) {             
749                 /* 2 characters */                              
750                 unsigned char high = c >> 6;
751                 unsigned char low  = c & 0x3F;
752                 left = left - 2;
753                 if ((int) left < 0) break;
754                 *pos++ = high | 0xC0; 
755                 *pos++ = low  | 0x80;     
756                 } else {         
757                 /* 3 characters */                              
758                 char low  = c & 0x3f;
759                 char mid  = (c >> 6) & 0x3F;
760                 char high = c >> 12;
761                 left = left - 3;
762                 if ((int) left < 0) break;
763                 *pos++ = high | 0xE0; 
764                 *pos++ = mid  | 0x80;  
765                 *pos++ = low  | 0x80;   
766                 }
767         }
768         
769         /* insert utf-string into symbol-table */
770         result = utf_new(buffer,buflength);
771         MFREE(buffer, char, buflength);
772         return result;
773 }
774
775 /********************* function: javastring_toutf *****************************
776
777         make utf symbol from javastring
778
779 *******************************************************************************/
780
781 utf *javastring_toutf(java_lang_String *string, bool isclassname)
782 {
783         java_lang_String *str = (java_lang_String *) string;
784         return utf_new_u2(str->value->data,str->count, isclassname);
785 }
786
787 /********************* function: literalstring_u2 *****************************
788
789     searches for the javastring with the specified u2-array in 
790     the string hashtable, if there is no such string a new one is 
791     created 
792
793     if copymode is true a copy of the u2-array is made
794
795 *******************************************************************************/
796
797 java_objectheader *literalstring_u2 (java_chararray *a, u4 length, bool copymode )
798 {
799     literalstring *s;                /* hashtable element */
800     java_lang_String *js;            /* u2-array wrapped in javastring */
801     java_chararray *stringdata;      /* copy of u2-array */      
802     u4 key;   
803     u4 slot;  
804     u2 i;
805
806     /* find location in hashtable */
807     key  = unicode_hashkey (a->data, length);
808     slot = key & (string_hash.size-1);
809     s    = string_hash.ptr[slot];
810
811     while (s) {
812         
813       js = (java_lang_String *) s->string;
814         
815       if (js->count == length) {
816         /* compare text */
817         for (i=0; i<length; i++) 
818           if (js->value->data[i] != a->data[i]) goto nomatch;
819                                         
820         /* string already in hashtable, free memory */
821         if (!copymode)
822           lit_mem_free(a, sizeof(java_chararray) + sizeof(u2)*(length-1)+10);
823
824         return (java_objectheader *) js;
825       }
826
827       nomatch:
828       /* follow link in external hash chain */
829       s = s->hashlink;
830     }
831
832     if (copymode) {
833       /* create copy of u2-array for new javastring */
834       u4 arraysize = sizeof(java_chararray) + sizeof(u2)*(length-1)+10;
835       stringdata = lit_mem_alloc ( arraysize ); 
836       memcpy(stringdata, a, arraysize );        
837     }  
838     else
839       stringdata = a;
840
841     /* location in hashtable found, complete arrayheader */
842     if (class_array==NULL) panic("class_array not initialized");
843     stringdata -> header.objheader.vftbl = class_array -> vftbl;
844     stringdata -> header.size = length; 
845     stringdata -> header.arraytype = ARRAYTYPE_CHAR;    
846
847     /* create new javastring */
848     js = LNEW (java_lang_String);
849     js -> header.vftbl = class_java_lang_String -> vftbl;
850     js -> value  = stringdata;
851     js -> offset = 0;
852     js -> count  = length;
853
854     /* create new literalstring */
855     s = NEW (literalstring);
856     s->hashlink = string_hash.ptr[slot];
857     s->string   = (java_objectheader *) js;
858     string_hash.ptr[slot] = s;
859
860     /* update numbe of hashtable entries */
861     string_hash.entries++;
862
863     /* reorganization of hashtable */       
864     if ( string_hash.entries > (string_hash.size*2)) {
865
866       /* reorganization of hashtable, average length of 
867          the external chains is approx. 2                */  
868
869       u4 i;
870       literalstring *s;     
871       hashtable newhash; /* the new hashtable */
872       
873       /* create new hashtable, double the size */
874       init_hashtable(&newhash, string_hash.size*2);
875       newhash.entries=string_hash.entries;
876       
877       /* transfer elements to new hashtable */
878       for (i=0; i<string_hash.size; i++) {
879         s = string_hash.ptr[i];
880         while (s) {
881           literalstring *nexts = s -> hashlink;  
882           js   = (java_lang_String*) s->string;
883           slot = (unicode_hashkey(js->value->data,js->count)) & (newhash.size-1);
884           
885           s->hashlink = newhash.ptr[slot];
886           newhash.ptr[slot] = s;
887         
888           /* follow link in external hash chain */  
889           s = nexts;
890         }
891       }
892         
893       /* dispose old table */   
894       MFREE (string_hash.ptr, void*, string_hash.size);
895       string_hash = newhash;
896     }
897                         
898     return (java_objectheader *) js;
899 }
900
901 /******************** Function: literalstring_new *****************************
902
903     creates a new javastring with the text of the utf-symbol
904     and inserts it into the string hashtable
905
906 *******************************************************************************/
907
908 java_objectheader *literalstring_new (utf *u)
909 {
910     char *utf_ptr = u->text;         /* pointer to current unicode character in utf string */
911     u4 utflength  = utf_strlen(u);   /* length of utf-string if uncompressed */
912     java_chararray *a;               /* u2-array constructed from utf string */
913     u4 i;
914     
915     /* allocate memory */ 
916     a = lit_mem_alloc (sizeof(java_chararray) + sizeof(u2)*(utflength-1)+10 );  
917     /* convert utf-string to u2-array */
918     for (i=0; i<utflength; i++) a->data[i] = utf_nextu2(&utf_ptr);      
919
920     return literalstring_u2(a, utflength, false);
921 }
922
923
924 /********************** function: literalstring_free **************************
925
926         removes a javastring from memory                       
927
928 ******************************************************************************/
929
930 void literalstring_free (java_objectheader* sobj)
931 {
932         java_lang_String *s = (java_lang_String*) sobj;
933         java_chararray *a = s->value;
934
935         log_text("literalstring_free called");
936         
937         /* dispose memory of java.lang.String object */
938         LFREE (s, java_lang_String);
939         /* dispose memory of java-characterarray */
940         LFREE (a, sizeof(java_chararray) + sizeof(u2)*(a->header.size-1)); /* +10 ?? */
941 }
942
943
944
945
946 void copy_vftbl(vftbl **dest, vftbl *src)
947 {
948         *dest = mem_alloc(sizeof(vftbl) + sizeof(methodptr)*(src->vftbllength-1));
949         memcpy(*dest, src, sizeof(vftbl) - sizeof(methodptr));
950         memcpy(&(*dest)->table, &src->table, src->vftbllength * sizeof(methodptr));
951 }
952
953 /*****************************************************************************/
954 /*****************************************************************************/
955
956
957 /*--------------------------------------------------------*/
958 void printNativeCall(nativeCall nc) {
959   int i,j;
960
961   printf("\n%s's Native Methods call:\n",nc.classname); fflush(stdout);
962   for (i=0; i<nc.methCnt; i++) {  
963     printf("\tMethod=%s %s\n",nc.methods[i].methodname, nc.methods[i].descriptor);fflush(stdout);
964
965     for (j=0; j<nc.callCnt[i]; j++) {  
966       printf("\t\t<%i,%i>aCalled = %s %s %s\n",i,j,
967         nc.methods[i].methodCalls[j].classname, 
968         nc.methods[i].methodCalls[j].methodname, 
969         nc.methods[i].methodCalls[j].descriptor);fflush(stdout);
970       }
971     }
972 printf("-+++++--------------------\n");fflush(stdout);
973 }
974
975 /*--------------------------------------------------------*/
976 void printCompNativeCall(nativeCompCall nc) {
977   int i,j;
978 printf("printCompNativeCall BEGIN\n");fflush(stdout);
979   printf("\n%s's Native Comp Methods call:\n",nc.classname->text);fflush(stdout);
980   utf_display(nc.classname); fflush(stdout);
981   
982   for (i=0; i<nc.methCnt; i++) {  
983     printf("\tMethod=%s %s\n",nc.methods[i].methodname->text,nc.methods[i].descriptor->text);fflush(stdout);
984     utf_display(nc.methods[i].methodname); fflush(stdout);
985     utf_display(nc.methods[i].descriptor);fflush(stdout);
986     printf("\n");fflush(stdout);
987
988     for (j=0; j<nc.callCnt[i]; j++) {  
989       printf("\t\t<%i,%i>bCalled = ",i,j);fflush(stdout);
990         utf_display(nc.methods[i].methodCalls[j].classname);fflush(stdout);
991         utf_display(nc.methods[i].methodCalls[j].methodname); fflush(stdout);
992         utf_display(nc.methods[i].methodCalls[j].descriptor);fflush(stdout);
993         printf("\n");fflush(stdout);
994       }
995     }
996 printf("---------------------\n");fflush(stdout);
997 }
998
999
1000 /*--------------------------------------------------------*/
1001 classMeth findNativeMethodCalls(utf *c, utf *m, utf *d ) 
1002 {
1003     int i = 0;
1004     int j = 0;
1005     int cnt = 0;
1006     classMeth mc;
1007     mc.i_class = i;
1008     mc.j_method = j;
1009     mc.methCnt = cnt;
1010
1011     return mc;
1012 }
1013
1014 /*--------------------------------------------------------*/
1015 nativeCall* findNativeClassCalls(char *aclassname ) {
1016 int i;
1017
1018 for (i=0;i<NATIVECALLSSIZE; i++) {
1019    /* convert table to utf later to speed up search */ 
1020    if (strcmp(nativeCalls[i].classname, aclassname) == 0) 
1021         return &nativeCalls[i];
1022    }
1023
1024 return NULL;
1025 }
1026 /*--------------------------------------------------------*/
1027 /*--------------------------------------------------------*/
1028 void utfNativeCall(nativeCall nc, nativeCompCall *ncc) {
1029   int i,j;
1030
1031
1032   ncc->classname = utf_new_char(nc.classname); 
1033   ncc->methCnt = nc.methCnt;
1034   
1035   for (i=0; i<nc.methCnt; i++) {  
1036     ncc->methods[i].methodname = utf_new_char(nc.methods[i].methodname);
1037     ncc->methods[i].descriptor = utf_new_char(nc.methods[i].descriptor);
1038     ncc->callCnt[i] = nc.callCnt[i];
1039
1040     for (j=0; j<nc.callCnt[i]; j++) {  
1041
1042         ncc->methods[i].methodCalls[j].classname  = utf_new_char(nc.methods[i].methodCalls[j].classname);
1043
1044         if (strcmp("", nc.methods[i].methodCalls[j].methodname) != 0) {
1045           ncc->methods[i].methodCalls[j].methodname = utf_new_char(nc.methods[i].methodCalls[j].methodname);
1046           ncc->methods[i].methodCalls[j].descriptor = utf_new_char(nc.methods[i].methodCalls[j].descriptor);
1047           }
1048         else {
1049           ncc->methods[i].methodCalls[j].methodname = NULL;
1050           ncc->methods[i].methodCalls[j].descriptor = NULL;
1051           }
1052       }
1053     }
1054 }
1055
1056
1057
1058 /*--------------------------------------------------------*/
1059
1060 bool natcall2utf(bool natcallcompdone) {
1061 int i;
1062
1063 if (natcallcompdone) 
1064         return true;
1065
1066 for (i=0;i<NATIVECALLSSIZE; i++) {
1067    utfNativeCall  (nativeCalls[i], &nativeCompCalls[i]);  
1068    }
1069
1070 return true;
1071 }
1072 /*--------------------------------------------------------*/