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