e5cf06ed070f6d1a221d891189542ce67cb131e4
[cacao.git] / src / native / 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 676 2003-11-24 20:50:23Z twisti $
35
36 */
37
38 #include <stdlib.h>
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
47 #include "config.h"
48 #include "global.h"
49 #include "jni.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 #include "threads/threadio.h"
72
73 /* searchpath for classfiles */
74 char *classpath;
75
76 /* for java-string to char conversion */
77 #define MAXSTRINGSIZE 1000                          
78
79 /******************** systemclasses required for native methods ***************/
80
81 classinfo *class_java_lang_Class;
82 classinfo *class_java_lang_VMClass;
83 methodinfo *method_vmclass_init;
84 /* static classinfo *class_java_lang_Cloneable=0; */ /* now in global.h */
85 classinfo *class_java_lang_CloneNotSupportedException;
86 classinfo *class_java_lang_System;
87 classinfo *class_java_lang_ClassLoader;
88 classinfo *class_java_lang_ClassNotFoundException;
89 classinfo *class_java_lang_InstantiationException;
90 classinfo *class_java_lang_NoSuchMethodError;   
91 classinfo *class_java_lang_NoSuchFieldError;
92 classinfo *class_java_lang_ClassFormatError;
93 classinfo *class_java_lang_IllegalArgumentException;
94 classinfo *class_java_lang_ArrayIndexOutOfBoundsException;
95 classinfo *class_java_lang_NoSuchFieldException;
96 classinfo *class_java_io_SyncFailedException;
97 classinfo *class_java_io_IOException;
98 classinfo *class_java_io_FileNotFoundException;
99 classinfo *class_java_io_UnixFileSystem;
100 classinfo *class_java_security_PrivilegedActionException;
101 classinfo *class_java_net_UnknownHostException;
102 classinfo *class_java_net_SocketException;
103 classinfo *class_java_lang_NoSuchMethodException;
104 classinfo *class_java_lang_Double;
105 classinfo *class_java_lang_Float;
106 classinfo *class_java_lang_Long;
107 classinfo *class_java_lang_Byte;
108 classinfo *class_java_lang_Short;
109 classinfo *class_java_lang_Boolean;
110 classinfo *class_java_lang_Void;
111 classinfo *class_java_lang_Character;
112 classinfo *class_java_lang_Integer;
113
114 /* the system classloader object */
115 struct java_lang_ClassLoader *SystemClassLoader = NULL;
116
117 /* for raising exceptions from native methods */
118 java_objectheader* exceptionptr = NULL;
119
120 /************* use classinfo structure as java.lang.Class object **************/
121
122 void use_class_as_object(classinfo *c) 
123 {
124         /*log_text("use_class_as_object");*/
125         if (!class_java_lang_Class)
126                 class_java_lang_Class =
127                         class_new ( utf_new_char ("java/lang/Class") );
128         vftbl *vt = class_java_lang_Class->vftbl;
129         vftbl *newtbl;
130         if (!c->classvftbl) {
131                 c->classvftbl = true;
132                 copy_vftbl(&newtbl, vt);
133                 newtbl->class = c->header.vftbl->class;
134                 newtbl->baseval = c->header.vftbl->baseval;
135                 newtbl->diffval = c->header.vftbl->diffval;
136                 c->header.vftbl = newtbl;
137         }
138         
139         if (!class_java_lang_VMClass) {
140                 class_java_lang_VMClass =
141                                 class_new ( utf_new_char("java/lang/VMClass"));
142                 method_vmclass_init = 
143                                 class_findmethod(class_java_lang_VMClass,utf_new_char("<init>"),
144                                         utf_new_char("(Lgnu/classpath/RawData;)V"));
145                 if (method_vmclass_init==0) {
146                         class_showmethods(class_java_lang_VMClass);
147                         panic("Needed class initializer for VMClass could not be found");
148                 }
149         }
150         {
151                 java_objectheader *vmo = builtin_new (class_java_lang_VMClass);
152                 asm_calljavamethod (method_vmclass_init, vmo, c, NULL, NULL);
153                 c->vmClass=(java_lang_VMClass*)vmo;
154         }
155 }
156
157
158 /*************************** include native methods ***************************/ 
159
160 #ifdef USE_GTK 
161 #include "nat/GdkGraphics.c"
162 #include "nat/GtkComponentPeer.c"
163 #include "nat/GdkPixbufDecoder.c"
164 #include "nat/GtkScrollPanePeer.c"
165 #include "nat/GtkFileDialogPeer.c"
166 #include "nat/GtkLabelPeer.c"
167 #endif
168
169
170 /************************** tables for methods ********************************/
171
172 #undef JOWENN_DEBUG
173 #undef JOWENN_DEBUG1
174
175 /* table for locating native methods */
176 static struct nativeref {
177         char *classname;
178         char *methodname;
179         char *descriptor;
180         bool isstatic;
181         functionptr func;
182 } nativetable [] = {
183
184 #include "nativetable.hh"
185
186 };
187
188
189 #define NATIVETABLESIZE  (sizeof(nativetable)/sizeof(struct nativeref))
190
191 /* table for fast string comparison */
192 static struct nativecompref {
193         utf *classname;
194         utf *methodname;
195         utf *descriptor;
196         bool isstatic;
197         functionptr func;
198 } nativecomptable [NATIVETABLESIZE];
199
200 /* string comparsion table initialized */
201 static bool nativecompdone = false;
202
203
204 /******************************************************************************/
205 /******************************************************************************/
206 #include "natcalls.h"
207
208 /* string call comparison table initialized */
209
210 /******************************************************************************/
211 /******************************************************************************/
212
213 /*--------------- native method calls & classes used -------------------------*/
214
215
216
217
218 /*********************** function: native_loadclasses **************************
219
220         load classes required for native methods        
221
222 *******************************************************************************/
223
224 void native_loadclasses()
225 {
226         static int classesLoaded=0; /*temporary hack JoWenn*/
227         if (classesLoaded) return;
228         classesLoaded=1;
229 /*      log_text("loadclasses entered");*/
230
231
232         /*class_java_lang_System =*/
233                 (void)class_new ( utf_new_char ("java/lang/VMClass") );/*JoWenn*/
234                 (void)class_new ( utf_new_char ("java/lang/Class") );/*JoWenn*/
235         /* class_new adds the class to the list of classes to be loaded */
236         if (!class_java_lang_Cloneable)
237                 class_java_lang_Cloneable = 
238                         class_new ( utf_new_char ("java/lang/Cloneable") );
239 /*      log_text("loadclasses: class_java_lang_Cloneable has been initialized");*/
240         class_java_lang_CloneNotSupportedException = 
241                 class_new ( utf_new_char ("java/lang/CloneNotSupportedException") );
242         if (!class_java_lang_Class)
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                 
262 /*      log_text("native_loadclasses: class_new(\"java/lang/ClassLoader\")");           */
263         class_java_lang_ClassLoader =
264                 class_new ( utf_new_char ("java/lang/ClassLoader") );   
265 /*      log_text("native_loadclasses: class_new(\"java/security/PrivilegedActionException\")");         */
266         class_java_security_PrivilegedActionException =
267                 class_new(utf_new_char("java/security/PrivilegedActionException"));
268
269         class_java_net_UnknownHostException = 
270                 loader_load(utf_new_char("java/net/UnknownHostException"));
271         class_java_net_SocketException = 
272                 loader_load(utf_new_char("java/net/SocketException"));
273
274         class_java_lang_IllegalArgumentException =
275                 class_new(utf_new_char("java/lang/IllegalArgumentException"));
276         class_java_lang_ArrayIndexOutOfBoundsException =
277                 class_new(utf_new_char("java/lang/ArrayIndexOutOfBoundsException"));
278         class_java_lang_NoSuchFieldException =
279                 class_new(utf_new_char("java/lang/NoSuchFieldException"));
280         class_java_lang_NoSuchMethodException = 
281                 class_new(utf_new_char("java/lang/NoSuchMethodException"));
282
283         /* load classes for wrapping primitive types */
284         class_java_lang_Double =
285                 class_new( utf_new_char ("java/lang/Double") );
286         class_init(class_java_lang_Double);
287
288         class_java_lang_Float =
289                 class_new(utf_new_char("java/lang/Float"));
290         class_java_lang_Character =
291                 class_new(utf_new_char("java/lang/Character"));
292         class_java_lang_Integer =
293                 class_new(utf_new_char("java/lang/Integer"));
294         class_java_lang_Long =
295                 class_new(utf_new_char("java/lang/Long"));
296         class_java_lang_Byte =
297                 class_new(utf_new_char("java/lang/Byte"));
298         class_java_lang_Short =
299                 class_new(utf_new_char("java/lang/Short"));
300         class_java_lang_Boolean =
301                 class_new(utf_new_char("java/lang/Boolean"));
302         class_java_lang_Void =
303                 class_new(utf_new_char("java/lang/Void"));
304
305         /* load to avoid dynamic classloading */
306 /*JoWenn        class_new(utf_new_char("sun/net/www/protocol/file/Handler"));
307         class_new(utf_new_char("sun/net/www/protocol/jar/Handler"));    
308         class_new(utf_new_char("sun/io/CharToByteISO8859_1"));*/
309         
310         /* start classloader */
311 /*JoWenn        loader_load(utf_new_char("sun/io/ByteToCharISO8859_1")); */
312
313         classesLoaded=1;
314         log_text("native_loadclasses finished");
315 }
316
317
318 /*************** adds a class to the vector of loaded classes ****************/
319
320 void systemclassloader_addclass(classinfo *c)
321 {
322         methodinfo *m;
323
324         /* find method addClass of java.lang.ClassLoader */
325         m = class_resolvemethod(
326                                                         class_java_lang_ClassLoader, 
327                                                         utf_new_char("addClass"),
328                                                         utf_new_char("(Ljava/lang/Class;)")
329                                                         );
330         
331         if (!m) panic("warning: cannot initialize classloader");
332
333         /* prepare class to be passed as argument */
334         use_class_as_object (c);
335
336         /* call 'addClass' */
337         asm_calljavamethod(m,
338                                            (java_objectheader*) SystemClassLoader, 
339                                            (java_objectheader*) c,
340                                            NULL,  
341                                            NULL
342                                            );
343 }
344
345 /*************** adds a library to the vector of loaded libraries *************/
346
347 void systemclassloader_addlibrary(java_objectheader *o)
348 {
349         log_text("systemclassloader_addlibrary");
350 }
351
352 /*****************************************************************************
353
354         create systemclassloader object and initialize instance fields  
355
356 ******************************************************************************/
357
358 void init_systemclassloader() 
359 {
360   if (!SystemClassLoader) {
361         native_loadclasses();
362         log_text("Initializing new system class loader");
363         /* create object and call initializer */
364         SystemClassLoader = (java_lang_ClassLoader*) native_new_and_init(class_java_lang_ClassLoader);  
365         heap_addreference((void**) &SystemClassLoader);
366
367         /* systemclassloader has no parent */
368         SystemClassLoader->parent      = NULL;
369         SystemClassLoader->initialized = true;
370   }
371   log_text("leaving system class loader");
372 }
373
374
375 /********************* add loaded library name  *******************************/
376
377 void systemclassloader_addlibname(java_objectheader *o)
378 {
379         methodinfo *m;
380         jfieldID id;
381
382         m = class_resolvemethod(loader_load(utf_new_char ("java/util/Vector")),
383                                                         utf_new_char("addElement"),
384                                                         utf_new_char("(Ljava/lang/Object;)V")
385                                                         );
386
387         if (!m) panic("cannot initialize classloader");
388
389         id = envTable.GetStaticFieldID(&env,class_java_lang_ClassLoader,"loadedLibraryNames","Ljava/util/Vector;");
390         if (!id) panic("can not access ClassLoader");
391
392         asm_calljavamethod(m,
393                                            GetStaticObjectField(&env,class_java_lang_ClassLoader,id),
394                                            o,
395                                            NULL,  
396                                            NULL
397                                            );       
398 }
399
400
401 /********************* function: native_setclasspath **************************/
402  
403 void native_setclasspath (char *path)
404 {
405         /* set searchpath for classfiles */
406         classpath = path;
407 }
408
409
410 /***************** function: throw_classnotfoundexception *********************/
411
412 void throw_classnotfoundexception()
413 {
414     if (!class_java_lang_ClassNotFoundException) {
415         panic("java.lang.ClassNotFoundException not found. Maybe wrong classpath?");
416     }
417
418         /* throws a ClassNotFoundException */
419         exceptionptr = native_new_and_init(class_java_lang_ClassNotFoundException);
420 }
421
422
423 void throw_classnotfoundexception2(utf* classname)
424 {
425         if (!class_java_lang_ClassNotFoundException) {
426                 panic("java.lang.ClassNotFoundException not found. Maybe wrong classpath?");
427         }
428
429         /* throws a ClassNotFoundException with message */
430         exceptionptr = native_new_and_init_string(class_java_lang_ClassNotFoundException,
431                                                                                           javastring_new(classname));
432 }
433
434
435 /*********************** Function: native_findfunction *************************
436
437         Looks up a method (must have the same class name, method name, descriptor
438         and 'static'ness) and returns a function pointer to it.
439         Returns: function pointer or NULL (if there is no such method)
440
441         Remark: For faster operation, the names/descriptors are converted from C
442                 strings to Unicode the first time this function is called.
443
444 *******************************************************************************/
445
446 functionptr native_findfunction(utf *cname, utf *mname, 
447                                                                 utf *desc, bool isstatic)
448 {
449         int i;
450         /* entry of table for fast string comparison */
451         struct nativecompref *n;
452         /* for warning message if no function is found */
453         char *buffer;                   
454         int buffer_len;
455
456         isstatic = isstatic ? true : false;
457         
458         if (!nativecompdone) {
459                 for (i = 0; i < NATIVETABLESIZE; i++) {
460                         nativecomptable[i].classname  = 
461                                 utf_new_char(nativetable[i].classname);
462                         nativecomptable[i].methodname = 
463                                 utf_new_char(nativetable[i].methodname);
464                         nativecomptable[i].descriptor = 
465                                 utf_new_char(nativetable[i].descriptor);
466                         nativecomptable[i].isstatic   = 
467                                 nativetable[i].isstatic;
468                         nativecomptable[i].func       = 
469                                 nativetable[i].func;
470                 }
471                 nativecompdone = true;
472         }
473
474 #ifdef JOWENN_DEBUG
475         buffer_len = 
476           utf_strlen(cname) + utf_strlen(mname) + utf_strlen(desc) + 64;
477         
478         buffer = MNEW(char, buffer_len);
479
480         strcpy(buffer, "searching matching function in native table:");
481         utf_sprint(buffer+strlen(buffer), mname);
482         strcpy(buffer+strlen(buffer), ": ");
483         utf_sprint(buffer+strlen(buffer), desc);
484         strcpy(buffer+strlen(buffer), " for class ");
485         utf_sprint(buffer+strlen(buffer), cname);
486
487         log_text(buffer);       
488
489         MFREE(buffer, char, buffer_len);
490 #endif
491                 
492         for (i = 0; i < NATIVETABLESIZE; i++) {
493                 n = &(nativecomptable[i]);
494
495                 if (cname == n->classname && mname == n->methodname &&
496                     desc == n->descriptor && isstatic == n->isstatic)
497                         return n->func;
498 #ifdef JOWENN_DEBUG
499                         else {
500                                 if (cname == n->classname && mname == n->methodname )  log_text("static and descriptor mismatch");
501                         
502                                 else {
503                                         buffer_len = 
504                                           utf_strlen(n->classname) + utf_strlen(n->methodname) + utf_strlen(n->descriptor) + 64;
505         
506                                         buffer = MNEW(char, buffer_len);
507
508                                         strcpy(buffer, "comparing with:");
509                                         utf_sprint(buffer+strlen(buffer), n->methodname);
510                                         strcpy (buffer+strlen(buffer), ": ");
511                                         utf_sprint(buffer+strlen(buffer), n->descriptor);
512                                         strcpy(buffer+strlen(buffer), " for class ");
513                                         utf_sprint(buffer+strlen(buffer), n->classname);
514
515                                         log_text(buffer);       
516
517                                         MFREE(buffer, char, buffer_len);
518                         
519                                 }
520                         } 
521 #endif
522         }
523
524                 
525         /* no function was found, display warning */
526
527         buffer_len = 
528                 utf_strlen(cname) + utf_strlen(mname) + utf_strlen(desc) + 64;
529
530         buffer = MNEW(char, buffer_len);
531
532         strcpy(buffer, "warning: native function ");
533         utf_sprint(buffer + strlen(buffer), mname);
534         strcpy(buffer + strlen(buffer), ": ");
535         utf_sprint(buffer + strlen(buffer), desc);
536         strcpy(buffer + strlen(buffer), " not found in class ");
537         utf_sprint(buffer + strlen(buffer), cname);
538
539         log_text(buffer);       
540
541         MFREE(buffer, char, buffer_len);
542
543
544         exit(1);
545
546         
547         return NULL;
548 }
549
550
551 /********************** function: javastring_new *******************************
552
553         creates a new object of type java/lang/String with the text of 
554         the specified utf8-string
555
556         return: pointer to the string or NULL if memory is exhausted.   
557
558 *******************************************************************************/
559
560 java_objectheader *javastring_new (utf *u)
561 {
562         char *utf_ptr = u->text;        /* current utf character in utf string    */
563         int utflength = utf_strlen(u);  /* length of utf-string if uncompressed   */
564         java_lang_String *s;                /* result-string                          */
565         java_chararray *a;
566         s4 i;
567         
568 /*      log_text("javastring_new");*/
569         
570         s = (java_lang_String*) builtin_new (class_java_lang_String);
571         a = builtin_newarray_char (utflength);
572
573         /* javastring or character-array could not be created */
574         if ((!a) || (!s))
575                 return NULL;
576
577         /* decompress utf-string */
578         for (i = 0; i < utflength; i++)
579                 a->data[i] = utf_nextu2(&utf_ptr);
580         
581         /* set fields of the javastring-object */
582         s->value  = a;
583         s->offset = 0;
584         s->count  = utflength;
585
586         return (java_objectheader*) s;
587 }
588
589 /********************** function: javastring_new_char **************************
590
591         creates a new java/lang/String object which contains the convertet
592         C-string passed via text.
593
594         return: the object pointer or NULL if memory is exhausted.
595
596 *******************************************************************************/
597
598 java_objectheader *javastring_new_char (char *text)
599 {
600         s4 i;
601         s4 len = strlen(text); /* length of the string */
602         java_lang_String *s;   /* result-string */
603         java_chararray *a;
604         
605         /*log_text("javastring_new_char");*/
606         s = (java_lang_String*) builtin_new (class_java_lang_String);
607         a = builtin_newarray_char (len);
608
609         /* javastring or character-array could not be created */
610         if ((!a) || (!s)) return NULL;
611
612         /* copy text */
613         for (i = 0; i < len; i++)
614                 a->data[i] = text[i];
615         
616         /* set fields of the javastring-object */
617         s->value = a;
618         s->offset = 0;
619         s->count = len;
620
621         return (java_objectheader*) s;
622 }
623
624
625 /************************* function javastring_tochar **************************
626
627         converts a Java string into a C string.
628         
629         return: pointer to C string
630         
631         Caution: every call of this function overwrites the previous string !!!
632         
633 *******************************************************************************/
634
635 static char stringbuffer[MAXSTRINGSIZE];
636
637 char *javastring_tochar (java_objectheader *so) 
638 {
639         java_lang_String *s = (java_lang_String*) so;
640         java_chararray *a;
641         s4 i;
642         
643         log_text("javastring_tochar");
644         
645         if (!s)
646                 return "";
647         a = s->value;
648         if (!a)
649                 return "";
650         if (s->count > MAXSTRINGSIZE)
651                 return "";
652         for (i = 0; i < s->count; i++)
653                 stringbuffer[i] = a->data[s->offset+i];
654         stringbuffer[i] = '\0';
655         return stringbuffer;
656 }
657
658
659 /****************** function class_findfield_approx ****************************
660         
661         searches in 'classinfo'-structure for a field with the
662         specified name
663
664 *******************************************************************************/
665  
666 fieldinfo *class_findfield_approx(classinfo *c, utf *name)
667 {
668         s4 i;
669         for (i = 0; i < c->fieldscount; i++) {
670                 /* compare field names */
671                 if ((c->fields[i].name == name))
672                         return &(c->fields[i]);
673         }
674
675         /* field was not found, raise exception */      
676         exceptionptr = native_new_and_init(class_java_lang_NoSuchFieldException);
677
678         return NULL;
679 }
680
681 s4 class_findfield_index_approx (classinfo *c, utf *name)
682 {
683         s4 i;
684         for (i = 0; i < c->fieldscount; i++) {
685                 /* compare field names */
686                 if ((c->fields[i].name == name))
687                         return i;
688                 }
689
690         /* field was not found, raise exception */      
691         exceptionptr = native_new_and_init(class_java_lang_NoSuchFieldException);
692         return -1;
693 }
694
695
696 /********************** function: native_new_and_init *************************
697
698         Creates a new object on the heap and calls the initializer.
699         Returns the object pointer or NULL if memory is exhausted.
700                         
701 *******************************************************************************/
702
703 java_objectheader *native_new_and_init(classinfo *c)
704 {
705         methodinfo *m;
706         java_objectheader *o = builtin_new(c);          /* create object          */
707
708         /*
709         printf("native_new_and_init ");
710         utf_display(c->name);
711         printf("\n");
712         */
713         if (!o) return NULL;
714         /* printf("o!=NULL\n"); */
715         /* find initializer */
716
717         m = class_findmethod(c, utf_new_char("<init>"), utf_new_char("()V"));
718                                                       
719         if (!m) {                                       /* initializer not found  */
720                 if (verbose) {
721                         sprintf(logtext, "Warning: class has no instance-initializer: ");
722                         utf_sprint(logtext + strlen(logtext), c->name);
723                         dolog();
724                 }
725                 return o;
726         }
727
728         /* call initializer */
729
730         asm_calljavamethod(m, o, NULL, NULL, NULL);
731
732         return o;
733 }
734
735
736 java_objectheader *native_new_and_init_string(classinfo *c, java_lang_String *s)
737 {
738         methodinfo *m;
739         java_objectheader *o = builtin_new(c);          /* create object          */
740
741         if (!o) return NULL;
742
743         /* find initializer */
744
745         m = class_findmethod(c,
746                                                  utf_new_char("<init>"),
747                                                  utf_new_char("(Ljava/lang/String;)V"));
748                                                       
749         if (!m) {                                       /* initializer not found  */
750                 if (verbose) {
751                         sprintf(logtext, "Warning: class has no instance-initializer: ");
752                         utf_sprint(logtext + strlen(logtext), c->name);
753                         dolog();
754                 }
755                 return o;
756         }
757
758         /* call initializer */
759
760         asm_calljavamethod(m, o, s, NULL, NULL);
761
762         return o;
763 }
764
765
766 /******************** function: stringtable_update ****************************
767
768         traverses the javastring hashtable and sets the vftbl-entries of
769         javastrings which were temporarily set to NULL, because 
770         java.lang.Object was not yet loaded
771
772 *******************************************************************************/
773  
774 void stringtable_update ()
775 {
776         java_lang_String *js;   
777         java_chararray *a;
778         literalstring *s;       /* hashtable entry */
779         int i;
780
781         for (i = 0; i < string_hash.size; i++) {
782                 s = string_hash.ptr[i];
783                 if (s) {
784                         while (s) {
785                                                                 
786                                 js = (java_lang_String *) s->string;
787                                 
788                                 if (!js || !(a = js->value)) 
789                                         /* error in hashtable found */
790                                         panic("invalid literalstring in hashtable");
791
792                                 if (!js->header.vftbl) 
793                                         /* vftbl of javastring is NULL */ 
794                                         js->header.vftbl = class_java_lang_String -> vftbl;
795
796                                 if (!a->header.objheader.vftbl) 
797                                         /* vftbl of character-array is NULL */ 
798                                         a->header.objheader.vftbl = primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl;
799
800                                 /* follow link in external hash chain */
801                                 s = s->hashlink;
802                         }       
803                 }               
804         }
805 }
806
807
808 /************************* function: u2_utflength ***************************
809
810         returns the utf length in bytes of a u2 array 
811
812 *****************************************************************************/
813
814
815 u4 u2_utflength(u2 *text, u4 u2_length)
816 {
817         u4 result_len =  0;  /* utf length in bytes  */
818         u2 ch;               /* current unicode character */
819         u4 len;
820         
821         for (len = 0; len < u2_length; len++) {
822           
823           /* next unicode character */
824           ch = *text++;
825           
826           /* determine bytes required to store unicode character as utf */
827           if (ch && (ch < 0x80)) 
828             result_len++;
829           else if (ch < 0x800)
830             result_len += 2;    
831           else 
832             result_len += 3;    
833         }
834
835     return result_len;
836 }
837
838 /********************* function: utf_new_u2 ***********************************
839
840         make utf symbol from u2 array, 
841         if isclassname is true '.' is replaced by '/'
842
843 *******************************************************************************/
844
845 utf *utf_new_u2(u2 *unicode_pos, u4 unicode_length, bool isclassname)
846 {
847         char *buffer; /* memory buffer for  unicode characters */
848         char *pos;    /* pointer to current position in buffer */
849         u4 left;      /* unicode characters left */
850         u4 buflength; /* utf length in bytes of the u2 array  */
851         utf *result;  /* resulting utf-string */
852         int i;          
853
854         /* determine utf length in bytes and allocate memory */
855         /* printf("utf_new_u2: unicode_length=%d\n",unicode_length);            */
856         buflength = u2_utflength(unicode_pos, unicode_length); 
857         buffer    = MNEW(char,buflength);
858  
859         /* memory allocation failed */
860         if (!buffer) {
861                 printf("length: %d\n",buflength);
862                 log_text("utf_new_u2:buffer==NULL");
863         }
864
865         left = buflength;
866         pos  = buffer;
867
868         for (i = 0; i++ < unicode_length; unicode_pos++) {
869                 /* next unicode character */
870                 u2 c = *unicode_pos;
871                 
872                 if ((c != 0) && (c < 0x80)) {
873                 /* 1 character */       
874                 left--;
875                 if ((int) left < 0) break;
876                 /* convert classname */
877                 if (isclassname && c=='.') 
878                   *pos++ = '/';
879                 else
880                   *pos++ = (char) c;
881                 } else if (c < 0x800) {             
882                 /* 2 characters */                              
883                 unsigned char high = c >> 6;
884                 unsigned char low  = c & 0x3F;
885                 left = left - 2;
886                 if ((int) left < 0) break;
887                 *pos++ = high | 0xC0; 
888                 *pos++ = low  | 0x80;     
889                 } else {         
890                 /* 3 characters */                              
891                 char low  = c & 0x3f;
892                 char mid  = (c >> 6) & 0x3F;
893                 char high = c >> 12;
894                 left = left - 3;
895                 if ((int) left < 0) break;
896                 *pos++ = high | 0xE0; 
897                 *pos++ = mid  | 0x80;  
898                 *pos++ = low  | 0x80;   
899                 }
900         }
901         
902         /* insert utf-string into symbol-table */
903         result = utf_new(buffer,buflength);
904
905         MFREE(buffer, char, buflength);
906         return result;
907 }
908
909 /********************* function: javastring_toutf *****************************
910
911         make utf symbol from javastring
912
913 *******************************************************************************/
914
915 utf *javastring_toutf(java_lang_String *string, bool isclassname)
916 {
917         java_lang_String *str = (java_lang_String *) string;
918 /*      printf("javastring_toutf offset: %d, len %d\n",str->offset, str->count);
919         fflush(stdout);*/
920         return utf_new_u2(str->value->data+str->offset,str->count, isclassname);
921 }
922
923 /********************* function: literalstring_u2 *****************************
924
925     searches for the javastring with the specified u2-array in 
926     the string hashtable, if there is no such string a new one is 
927     created 
928
929     if copymode is true a copy of the u2-array is made
930
931 *******************************************************************************/
932
933 java_objectheader *literalstring_u2 (java_chararray *a, u4 length, bool copymode )
934 {
935     literalstring *s;                /* hashtable element */
936     java_lang_String *js;            /* u2-array wrapped in javastring */
937     java_chararray *stringdata;      /* copy of u2-array */      
938     u4 key;   
939     u4 slot;  
940     u2 i;
941
942 #if JOWENN_DEBUG1
943     printf("literalstring_u2: length: %d\n",length);    
944     log_text("literalstring_u2");
945 #endif
946     
947     /* find location in hashtable */
948     key  = unicode_hashkey (a->data, length);
949     slot = key & (string_hash.size-1);
950     s    = string_hash.ptr[slot];
951
952     while (s) {
953         
954       js = (java_lang_String *) s->string;
955         
956       if (js->count == length) {
957         /* compare text */
958         for (i=0; i<length; i++) 
959           if (js->value->data[i] != a->data[i]) goto nomatch;
960                                         
961         /* string already in hashtable, free memory */
962         if (!copymode)
963           lit_mem_free(a, sizeof(java_chararray) + sizeof(u2)*(length-1)+10);
964
965 #ifdef JOWENN_DEBUG1
966         log_text("literalstring_u2: foundentry");
967         utf_display(javastring_toutf(js,0));
968 #endif
969         return (java_objectheader *) js;
970       }
971
972       nomatch:
973       /* follow link in external hash chain */
974       s = s->hashlink;
975     }
976
977     if (copymode) {
978       /* create copy of u2-array for new javastring */
979       u4 arraysize = sizeof(java_chararray) + sizeof(u2)*(length-1)+10;
980       stringdata = lit_mem_alloc ( arraysize ); 
981       memcpy(stringdata, a, arraysize );        
982     }  
983     else
984       stringdata = a;
985
986     /* location in hashtable found, complete arrayheader */
987     stringdata -> header.objheader.vftbl = primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl;
988     stringdata -> header.size = length; 
989
990     /* create new javastring */
991     js = LNEW (java_lang_String);
992     js -> header.vftbl = class_java_lang_String -> vftbl;
993     js -> value  = stringdata;
994     js -> offset = 0;
995     js -> count  = length;
996
997     /* create new literalstring */
998     s = NEW (literalstring);
999     s->hashlink = string_hash.ptr[slot];
1000     s->string   = (java_objectheader *) js;
1001     string_hash.ptr[slot] = s;
1002
1003     /* update numbe of hashtable entries */
1004     string_hash.entries++;
1005
1006     /* reorganization of hashtable */       
1007     if ( string_hash.entries > (string_hash.size*2)) {
1008
1009       /* reorganization of hashtable, average length of 
1010          the external chains is approx. 2                */  
1011
1012       u4 i;
1013       literalstring *s;     
1014       hashtable newhash; /* the new hashtable */
1015       
1016       /* create new hashtable, double the size */
1017       init_hashtable(&newhash, string_hash.size*2);
1018       newhash.entries=string_hash.entries;
1019       
1020       /* transfer elements to new hashtable */
1021       for (i=0; i<string_hash.size; i++) {
1022         s = string_hash.ptr[i];
1023         while (s) {
1024           literalstring *nexts = s -> hashlink;  
1025           js   = (java_lang_String*) s->string;
1026           slot = (unicode_hashkey(js->value->data,js->count)) & (newhash.size-1);
1027           
1028           s->hashlink = newhash.ptr[slot];
1029           newhash.ptr[slot] = s;
1030         
1031           /* follow link in external hash chain */  
1032           s = nexts;
1033         }
1034       }
1035         
1036       /* dispose old table */   
1037       MFREE (string_hash.ptr, void*, string_hash.size);
1038       string_hash = newhash;
1039     }
1040 #ifdef JOWENN_DEBUG1
1041         log_text("literalstring_u2: newly created");
1042 /*      utf_display(javastring_toutf(js,0));*/
1043 #endif
1044                         
1045     return (java_objectheader *) js;
1046 }
1047
1048 /******************** Function: literalstring_new *****************************
1049
1050     creates a new javastring with the text of the utf-symbol
1051     and inserts it into the string hashtable
1052
1053 *******************************************************************************/
1054
1055 java_objectheader *literalstring_new (utf *u)
1056 {
1057     char *utf_ptr = u->text;         /* pointer to current unicode character in utf string */
1058     u4 utflength  = utf_strlen(u);   /* length of utf-string if uncompressed */
1059     java_chararray *a;               /* u2-array constructed from utf string */
1060     u4 i;
1061 /*    log_text("literalstring_new"); */
1062 /*    utf_display(u);*/
1063     /*if (utflength==0) while (1) sleep(60);*/
1064 /*    log_text("------------------");    */
1065     /* allocate memory */ 
1066     a = lit_mem_alloc (sizeof(java_chararray) + sizeof(u2)*(utflength-1)+10 );  
1067     /* convert utf-string to u2-array */
1068     for (i=0; i<utflength; i++) a->data[i] = utf_nextu2(&utf_ptr);      
1069
1070     return literalstring_u2(a, utflength, false);
1071 }
1072
1073
1074 /********************** function: literalstring_free **************************
1075
1076         removes a javastring from memory                       
1077
1078 ******************************************************************************/
1079
1080 void literalstring_free (java_objectheader* sobj)
1081 {
1082         java_lang_String *s = (java_lang_String*) sobj;
1083         java_chararray *a = s->value;
1084
1085         log_text("literalstring_free called");
1086         
1087         /* dispose memory of java.lang.String object */
1088         LFREE (s, java_lang_String);
1089         /* dispose memory of java-characterarray */
1090         LFREE (a, sizeof(java_chararray) + sizeof(u2)*(a->header.size-1)); /* +10 ?? */
1091 }
1092
1093
1094
1095
1096 void copy_vftbl(vftbl **dest, vftbl *src)
1097 {
1098     *dest = src;
1099 #if 0
1100     /* XXX this kind of copying does not work (in the general
1101      * case). The interface tables would have to be copied, too. I
1102      * don't see why we should make a copy anyway. -Edwin
1103      */
1104         *dest = mem_alloc(sizeof(vftbl) + sizeof(methodptr)*(src->vftbllength-1));
1105         memcpy(*dest, src, sizeof(vftbl) - sizeof(methodptr));
1106         memcpy(&(*dest)->table, &src->table, src->vftbllength * sizeof(methodptr));
1107 #endif
1108 }
1109
1110
1111 /******************************************************************************************                                                                                                             
1112
1113         creates method signature (excluding return type) from array of 
1114         class-objects representing the parameters of the method 
1115
1116 *******************************************************************************************/
1117
1118
1119 utf *create_methodsig(java_objectarray* types, char *retType)
1120 {
1121     char *buffer;       /* buffer for building the desciptor */
1122     char *pos;          /* current position in buffer */
1123     utf *result;        /* the method signature */
1124     u4 buffer_size = 3; /* minimal size=3: room for parenthesis and returntype */
1125     u4 i, j;
1126  
1127     if (!types) return NULL;
1128
1129     /* determine required buffer-size */    
1130     for (i=0;i<types->header.size;i++) {
1131       classinfo *c = (classinfo *) types->data[i];
1132       buffer_size  = buffer_size + c->name->blength+2;
1133     }
1134
1135     if (retType) buffer_size+=strlen(retType);
1136
1137     /* allocate buffer */
1138     buffer = MNEW(u1, buffer_size);
1139     pos    = buffer;
1140     
1141     /* method-desciptor starts with parenthesis */
1142     *pos++ = '(';
1143
1144     for (i=0;i<types->header.size;i++) {
1145
1146             char ch;       
1147             /* current argument */
1148             classinfo *c = (classinfo *) types->data[i];
1149             /* current position in utf-text */
1150             char *utf_ptr = c->name->text; 
1151             
1152             /* determine type of argument */
1153             if ( (ch = utf_nextu2(&utf_ptr)) == '[' ) {
1154         
1155                 /* arrayclass */
1156                 for ( utf_ptr--; utf_ptr<utf_end(c->name); utf_ptr++)
1157                    *pos++ = *utf_ptr; /* copy text */
1158
1159             } else
1160             {           
1161                 /* check for primitive types */
1162                 for (j=0; j<PRIMITIVETYPE_COUNT; j++) {
1163
1164                         char *utf_pos   = utf_ptr-1;
1165                         char *primitive = primitivetype_table[j].wrapname;
1166
1167                         /* compare text */
1168                         while (utf_pos<utf_end(c->name))
1169                                 if (*utf_pos++ != *primitive++) goto nomatch;
1170
1171                         /* primitive type found */
1172                         *pos++ = primitivetype_table[j].typesig;
1173                         goto next_type;
1174
1175                 nomatch:
1176                 }
1177
1178                 /* no primitive type and no arrayclass, so must be object */
1179                 *pos++ = 'L';
1180                 /* copy text */
1181                 for ( utf_ptr--; utf_ptr<utf_end(c->name); utf_ptr++)
1182                         *pos++ = *utf_ptr;
1183                 *pos++ = ';';
1184
1185                 next_type:
1186             }  
1187     }       
1188
1189     *pos++ = ')';
1190
1191     if (retType) {
1192         for (i=0;i<strlen(retType);i++) {
1193                 *pos++=retType[i];
1194         }
1195     }
1196     /* create utf-string */
1197     result = utf_new(buffer,(pos-buffer));
1198     MFREE(buffer, u1, buffer_size);
1199
1200     return result;
1201 }
1202
1203
1204 /******************************************************************************************
1205
1206         retrieve the next argument or returntype from a descriptor
1207         and return the corresponding class 
1208
1209 *******************************************************************************************/
1210
1211 classinfo *get_type(char **utf_ptr,char *desc_end, bool skip)
1212 {
1213     classinfo *c = class_from_descriptor(*utf_ptr,desc_end,utf_ptr,
1214                                          (skip) ? CLASSLOAD_SKIP : CLASSLOAD_LOAD);
1215     if (!c)
1216         /* unknown type */
1217         panic("illegal descriptor");
1218
1219     if (skip) return NULL;
1220
1221     use_class_as_object(c);
1222     return c;
1223 }
1224
1225
1226 /******************************************************************************************
1227
1228         use the descriptor of a method to generate a java/lang/Class array
1229         which contains the classes of the parametertypes of the method
1230
1231 *******************************************************************************************/
1232
1233 java_objectarray* get_parametertypes(methodinfo *m) 
1234 {
1235     utf  *descr    =  m->descriptor;    /* method-descriptor */ 
1236     char *utf_ptr  =  descr->text;      /* current position in utf-text */
1237     char *desc_end =  utf_end(descr);   /* points behind utf string     */
1238     java_objectarray* result;
1239     int parametercount = 0;
1240     int i;
1241
1242     /* skip '(' */
1243     utf_nextu2(&utf_ptr);
1244   
1245     /* determine number of parameters */
1246     while ( *utf_ptr != ')' ) {
1247         get_type(&utf_ptr,desc_end,true);
1248         parametercount++;
1249     }
1250
1251     /* create class-array */
1252     result = builtin_anewarray(parametercount, class_java_lang_Class);
1253
1254     utf_ptr  =  descr->text;
1255     utf_nextu2(&utf_ptr);
1256
1257     /* get returntype classes */
1258     for (i = 0; i < parametercount; i++)
1259             result->data[i] = (java_objectheader *) get_type(&utf_ptr,desc_end, false);
1260
1261     return result;
1262 }
1263
1264
1265 /******************************************************************************************
1266
1267         get the returntype class of a method
1268
1269 *******************************************************************************************/
1270
1271 classinfo *get_returntype(methodinfo *m) 
1272 {
1273         char *utf_ptr;   /* current position in utf-text */
1274         char *desc_end;  /* points behind utf string     */
1275         utf *desc = m->descriptor; /* method-descriptor  */
1276
1277         utf_ptr  = desc->text;
1278         desc_end = utf_end(desc);
1279
1280         /* ignore parametertypes */
1281         while ((utf_ptr<desc_end) && utf_nextu2(&utf_ptr)!=')')
1282                 /* skip */ ;
1283
1284         return get_type(&utf_ptr,desc_end, false);
1285 }
1286
1287
1288 /*****************************************************************************/
1289 /*****************************************************************************/
1290
1291
1292 /*--------------------------------------------------------*/
1293 void printNativeCall(nativeCall nc) {
1294   int i,j;
1295
1296   printf("\n%s's Native Methods call:\n",nc.classname); fflush(stdout);
1297   for (i=0; i<nc.methCnt; i++) {  
1298       printf("\tMethod=%s %s\n",nc.methods[i].methodname, nc.methods[i].descriptor);fflush(stdout);
1299
1300     for (j=0; j<nc.callCnt[i]; j++) {  
1301         printf("\t\t<%i,%i>aCalled = %s %s %s\n",i,j,
1302         nc.methods[i].methodCalls[j].classname, 
1303         nc.methods[i].methodCalls[j].methodname, 
1304         nc.methods[i].methodCalls[j].descriptor);fflush(stdout);
1305       }
1306     }
1307   printf("-+++++--------------------\n");fflush(stdout);
1308 }
1309
1310 /*--------------------------------------------------------*/
1311 void printCompNativeCall(nativeCompCall nc) {
1312   int i,j;
1313   printf("printCompNativeCall BEGIN\n");fflush(stdout); 
1314   printf("\n%s's Native Comp Methods call:\n",nc.classname->text);fflush(stdout);
1315   utf_display(nc.classname); fflush(stdout);
1316   
1317   for (i=0; i<nc.methCnt; i++) {  
1318     printf("\tMethod=%s %s\n",nc.methods[i].methodname->text,nc.methods[i].descriptor->text);fflush(stdout);
1319     utf_display(nc.methods[i].methodname); fflush(stdout);
1320     utf_display(nc.methods[i].descriptor);fflush(stdout);
1321     printf("\n");fflush(stdout);
1322
1323     for (j=0; j<nc.callCnt[i]; j++) {  
1324       printf("\t\t<%i,%i>bCalled = ",i,j);fflush(stdout);
1325         utf_display(nc.methods[i].methodCalls[j].classname);fflush(stdout);
1326         utf_display(nc.methods[i].methodCalls[j].methodname); fflush(stdout);
1327         utf_display(nc.methods[i].methodCalls[j].descriptor);fflush(stdout);
1328         printf("\n");fflush(stdout);
1329       }
1330     }
1331 printf("---------------------\n");fflush(stdout);
1332 }
1333
1334
1335 /*--------------------------------------------------------*/
1336 classMeth findNativeMethodCalls(utf *c, utf *m, utf *d ) 
1337 {
1338     int i = 0;
1339     int j = 0;
1340     int cnt = 0;
1341     classMeth mc;
1342     mc.i_class = i;
1343     mc.j_method = j;
1344     mc.methCnt = cnt;
1345
1346     return mc;
1347 }
1348
1349 /*--------------------------------------------------------*/
1350 nativeCall* findNativeClassCalls(char *aclassname ) {
1351 int i;
1352
1353 for (i=0;i<NATIVECALLSSIZE; i++) {
1354    /* convert table to utf later to speed up search */ 
1355    if (strcmp(nativeCalls[i].classname, aclassname) == 0) 
1356         return &nativeCalls[i];
1357    }
1358
1359 return NULL;
1360 }
1361 /*--------------------------------------------------------*/
1362 /*--------------------------------------------------------*/
1363 void utfNativeCall(nativeCall nc, nativeCompCall *ncc) {
1364   int i,j;
1365
1366
1367   ncc->classname = utf_new_char(nc.classname); 
1368   ncc->methCnt = nc.methCnt;
1369   
1370   for (i=0; i<nc.methCnt; i++) {  
1371     ncc->methods[i].methodname = utf_new_char(nc.methods[i].methodname);
1372     ncc->methods[i].descriptor = utf_new_char(nc.methods[i].descriptor);
1373     ncc->callCnt[i] = nc.callCnt[i];
1374
1375     for (j=0; j<nc.callCnt[i]; j++) {  
1376
1377         ncc->methods[i].methodCalls[j].classname  = utf_new_char(nc.methods[i].methodCalls[j].classname);
1378
1379         if (strcmp("", nc.methods[i].methodCalls[j].methodname) != 0) {
1380           ncc->methods[i].methodCalls[j].methodname = utf_new_char(nc.methods[i].methodCalls[j].methodname);
1381           ncc->methods[i].methodCalls[j].descriptor = utf_new_char(nc.methods[i].methodCalls[j].descriptor);
1382           }
1383         else {
1384           ncc->methods[i].methodCalls[j].methodname = NULL;
1385           ncc->methods[i].methodCalls[j].descriptor = NULL;
1386           }
1387       }
1388     }
1389 }
1390
1391
1392
1393 /*--------------------------------------------------------*/
1394
1395 bool natcall2utf(bool natcallcompdone) {
1396 int i;
1397
1398 if (natcallcompdone) 
1399         return true;
1400
1401 for (i=0;i<NATIVECALLSSIZE; i++) {
1402    utfNativeCall  (nativeCalls[i], &nativeCompCalls[i]);  
1403    }
1404
1405 return true;
1406 }
1407 /*--------------------------------------------------------*/
1408
1409
1410 /*
1411  * These are local overrides for various environment variables in Emacs.
1412  * Please do not remove this and leave it at the end of the file, where
1413  * Emacs will automagically detect them.
1414  * ---------------------------------------------------------------------
1415  * Local variables:
1416  * mode: c
1417  * indent-tabs-mode: t
1418  * c-basic-offset: 4
1419  * tab-width: 4
1420  * End:
1421  */