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