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