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