1 /* native.c - table of native functions
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
8 This file is part of CACAO.
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.
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.
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
25 Contact: cacao@complang.tuwien.ac.at
27 Authors: Reinhard Grafl
31 The .hh files created with the header file generator are all
32 included here as are the C functions implementing these methods.
34 $Id: native.c 755 2003-12-13 22:25:24Z twisti $
52 #include "nativetypes.hh"
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"
63 /* Include files for IO functions */
67 #include <sys/types.h>
73 #include "threads/threadio.h"
75 /* searchpath for classfiles */
78 /* for java-string to char conversion */
79 #define MAXSTRINGSIZE 1000
81 /******************** systemclasses required for native methods ***************/
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;
118 /* the system classloader object */
119 struct java_lang_ClassLoader *SystemClassLoader = NULL;
121 /* for raising exceptions from native methods */
122 java_objectheader* exceptionptr = NULL;
124 /************* use classinfo structure as java.lang.Class object **************/
126 void use_class_as_object(classinfo *c)
131 if (!class_java_lang_Class)
132 class_java_lang_Class = class_new(utf_new_char ("java/lang/Class"));
134 vt = class_java_lang_Class->vftbl;
137 if (!c->classvftbl) {
138 c->classvftbl = true;
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;*/
146 c->header.vftbl = class_java_lang_Class->vftbl;
148 if (!class_java_lang_VMClass) {
149 loader_load_sysclass(&class_java_lang_VMClass,
150 utf_new_char("java/lang/VMClass"));
152 method_vmclass_init =
153 class_findmethod(class_java_lang_VMClass,
154 utf_new_char("<init>"),
155 utf_new_char("(Lgnu/classpath/RawData;)V"));
157 if (method_vmclass_init == 0) {
158 class_showmethods(class_java_lang_VMClass);
159 panic("Needed class initializer for VMClass could not be found");
163 java_objectheader *vmo = builtin_new(class_java_lang_VMClass);
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");*/
174 /*************************** include native methods ***************************/
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"
186 /************************** tables for methods ********************************/
191 /* table for locating native methods */
192 static struct nativeref {
200 #include "nativetable.hh"
205 #define NATIVETABLESIZE (sizeof(nativetable)/sizeof(struct nativeref))
207 /* table for fast string comparison */
208 static struct nativecompref {
214 } nativecomptable [NATIVETABLESIZE];
216 /* string comparsion table initialized */
217 static bool nativecompdone = false;
220 /******************************************************************************/
221 /******************************************************************************/
222 #include "natcalls.h"
224 /* string call comparison table initialized */
226 /******************************************************************************/
227 /******************************************************************************/
229 /*--------------- native method calls & classes used -------------------------*/
233 /* throw some loader exceptions */
235 void throw_noclassdeffounderror_message(utf* classname)
237 if (!class_java_lang_NoClassDefFoundError) {
238 panic("java.lang.NoClassDefFoundError not found. Maybe wrong classpath?");
241 /* throws a NoClassDefFoundError with message */
242 exceptionptr = native_new_and_init_string(class_java_lang_NoClassDefFoundError,
243 javastring_new(classname));
247 void throw_linkageerror_message(utf* classname)
249 if (!class_java_lang_LinkageError) {
250 panic("java.lang.LinkageError not found. Maybe wrong classpath?");
253 /* throws a LinkageError with message */
254 exceptionptr = native_new_and_init_string(class_java_lang_LinkageError,
255 javastring_new(classname));
259 /*********************** function: native_loadclasses **************************
261 load classes required for native methods
263 *******************************************************************************/
265 void native_loadclasses()
267 static int classesLoaded=0; /*temporary hack JoWenn*/
268 if (classesLoaded) return;
270 /* log_text("loadclasses entered");*/
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*/
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"));
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"));
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"));
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"));
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);
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"));
352 log_text("native_loadclasses finished");
356 /*************** adds a class to the vector of loaded classes ****************/
358 void systemclassloader_addclass(classinfo *c)
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;)")
369 if (!m) panic("warning: cannot initialize classloader");
371 /* prepare class to be passed as argument */
372 use_class_as_object (c);
374 /* call 'addClass' */
375 asm_calljavamethod(m,
376 (java_objectheader*) SystemClassLoader,
377 (java_objectheader*) c,
383 /*************** adds a library to the vector of loaded libraries *************/
385 void systemclassloader_addlibrary(java_objectheader *o)
387 log_text("systemclassloader_addlibrary");
390 /*****************************************************************************
392 create systemclassloader object and initialize instance fields
394 ******************************************************************************/
396 void init_systemclassloader()
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); */
405 /* systemclassloader has no parent */
406 SystemClassLoader->parent = NULL;
407 SystemClassLoader->initialized = true;
409 log_text("leaving system class loader");
413 /********************* add loaded library name *******************************/
415 void systemclassloader_addlibname(java_objectheader *o)
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")
425 if (!m) panic("cannot initialize classloader");
427 id = envTable.GetStaticFieldID(&env,class_java_lang_ClassLoader,"loadedLibraryNames","Ljava/util/Vector;");
428 if (!id) panic("can not access ClassLoader");
430 asm_calljavamethod(m,
431 GetStaticObjectField(&env,class_java_lang_ClassLoader,id),
439 /********************* function: native_setclasspath **************************/
441 void native_setclasspath (char *path)
443 /* set searchpath for classfiles */
448 /*********************** Function: native_findfunction *************************
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)
454 Remark: For faster operation, the names/descriptors are converted from C
455 strings to Unicode the first time this function is called.
457 *******************************************************************************/
459 functionptr native_findfunction(utf *cname, utf *mname,
460 utf *desc, bool isstatic)
463 /* entry of table for fast string comparison */
464 struct nativecompref *n;
465 /* for warning message if no function is found */
469 isstatic = isstatic ? true : false;
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 =
484 nativecompdone = true;
489 utf_strlen(cname) + utf_strlen(mname) + utf_strlen(desc) + 64;
491 buffer = MNEW(char, buffer_len);
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);
502 MFREE(buffer, char, buffer_len);
505 for (i = 0; i < NATIVETABLESIZE; i++) {
506 n = &(nativecomptable[i]);
508 if (cname == n->classname && mname == n->methodname &&
509 desc == n->descriptor && isstatic == n->isstatic)
513 if (cname == n->classname && mname == n->methodname ) log_text("static and descriptor mismatch");
517 utf_strlen(n->classname) + utf_strlen(n->methodname) + utf_strlen(n->descriptor) + 64;
519 buffer = MNEW(char, buffer_len);
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);
530 MFREE(buffer, char, buffer_len);
538 /* no function was found, display warning */
541 utf_strlen(cname) + utf_strlen(mname) + utf_strlen(desc) + 64;
543 buffer = MNEW(char, buffer_len);
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);
554 MFREE(buffer, char, buffer_len);
564 /********************** function: javastring_new *******************************
566 creates a new object of type java/lang/String with the text of
567 the specified utf8-string
569 return: pointer to the string or NULL if memory is exhausted.
571 *******************************************************************************/
573 /* java_objectheader *javastring_new(utf *u) */
574 java_lang_String *javastring_new(utf *u)
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 */
582 /* log_text("javastring_new");*/
584 s = (java_lang_String*) builtin_new(class_java_lang_String);
585 a = builtin_newarray_char(utflength);
587 /* javastring or character-array could not be created */
591 /* decompress utf-string */
592 for (i = 0; i < utflength; i++)
593 a->data[i] = utf_nextu2(&utf_ptr);
595 /* set fields of the javastring-object */
598 s->count = utflength;
600 /* return (java_objectheader*) s; */
605 /********************** function: javastring_new_char **************************
607 creates a new java/lang/String object which contains the convertet
608 C-string passed via text.
610 return: the object pointer or NULL if memory is exhausted.
612 *******************************************************************************/
614 /* java_objectheader *javastring_new_char (char *text) */
615 java_lang_String *javastring_new_char (char *text)
618 s4 len = strlen(text); /* length of the string */
619 java_lang_String *s; /* result-string */
622 /*log_text("javastring_new_char");*/
623 s = (java_lang_String*) builtin_new(class_java_lang_String);
624 a = builtin_newarray_char(len);
626 /* javastring or character-array could not be created */
631 for (i = 0; i < len; i++)
632 a->data[i] = text[i];
634 /* set fields of the javastring-object */
639 /* return (java_objectheader*) s; */
644 /************************* function javastring_tochar **************************
646 converts a Java string into a C string.
648 return: pointer to C string
650 Caution: every call of this function overwrites the previous string !!!
652 *******************************************************************************/
654 static char stringbuffer[MAXSTRINGSIZE];
656 char *javastring_tochar (java_objectheader *so)
658 java_lang_String *s = (java_lang_String*) so;
662 log_text("javastring_tochar");
669 if (s->count > MAXSTRINGSIZE)
671 for (i = 0; i < s->count; i++)
672 stringbuffer[i] = a->data[s->offset+i];
673 stringbuffer[i] = '\0';
678 /****************** function class_findfield_approx ****************************
680 searches in 'classinfo'-structure for a field with the
683 *******************************************************************************/
685 fieldinfo *class_findfield_approx(classinfo *c, utf *name)
688 for (i = 0; i < c->fieldscount; i++) {
689 /* compare field names */
690 if ((c->fields[i].name == name))
691 return &(c->fields[i]);
694 /* field was not found, raise exception */
695 exceptionptr = native_new_and_init(class_java_lang_NoSuchFieldException);
700 s4 class_findfield_index_approx (classinfo *c, utf *name)
703 for (i = 0; i < c->fieldscount; i++) {
704 /* compare field names */
705 if ((c->fields[i].name == name))
709 /* field was not found, raise exception */
710 exceptionptr = native_new_and_init(class_java_lang_NoSuchFieldException);
715 /********************** function: native_new_and_init *************************
717 Creates a new object on the heap and calls the initializer.
718 Returns the object pointer or NULL if memory is exhausted.
720 *******************************************************************************/
722 java_objectheader *native_new_and_init(classinfo *c)
725 java_objectheader *o;
727 /* if c==NULL it is probebly because loader_load failed */
728 if (!c) return exceptionptr;
730 o = builtin_new(c); /* create object */
733 printf("native_new_and_init ");
734 utf_display(c->name);
738 /* printf("o!=NULL\n"); */
739 /* find initializer */
741 m = class_findmethod(c, utf_new_char("<init>"), utf_new_char("()V"));
743 if (!m) { /* initializer not found */
745 char logtext[MAXLOGTEXT];
746 sprintf(logtext, "Warning: class has no instance-initializer: ");
747 utf_sprint(logtext + strlen(logtext), c->name);
753 /* call initializer */
755 asm_calljavamethod(m, o, NULL, NULL, NULL);
761 java_objectheader *native_new_and_init_string(classinfo *c, java_lang_String *s)
764 java_objectheader *o;
766 /* if c==NULL it is probebly because loader_load failed */
767 if (!c) return exceptionptr;
769 o = builtin_new(c); /* create object */
773 /* find initializer */
775 m = class_findmethod(c,
776 utf_new_char("<init>"),
777 utf_new_char("(Ljava/lang/String;)V"));
779 if (!m) { /* initializer not found */
781 char logtext[MAXLOGTEXT];
782 sprintf(logtext, "Warning: class has no instance-initializer: ");
783 utf_sprint(logtext + strlen(logtext), c->name);
789 /* call initializer */
791 asm_calljavamethod(m, o, s, NULL, NULL);
797 /******************** function: stringtable_update ****************************
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
803 *******************************************************************************/
805 void stringtable_update ()
807 java_lang_String *js;
809 literalstring *s; /* hashtable entry */
812 for (i = 0; i < string_hash.size; i++) {
813 s = string_hash.ptr[i];
817 js = (java_lang_String *) s->string;
819 if (!js || !(a = js->value))
820 /* error in hashtable found */
821 panic("invalid literalstring in hashtable");
823 if (!js->header.vftbl)
824 /* vftbl of javastring is NULL */
825 js->header.vftbl = class_java_lang_String -> vftbl;
827 if (!a->header.objheader.vftbl)
828 /* vftbl of character-array is NULL */
829 a->header.objheader.vftbl = primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl;
831 /* follow link in external hash chain */
839 /************************* function: u2_utflength ***************************
841 returns the utf length in bytes of a u2 array
843 *****************************************************************************/
845 u4 u2_utflength(u2 *text, u4 u2_length)
847 u4 result_len = 0; /* utf length in bytes */
848 u2 ch; /* current unicode character */
851 for (len = 0; len < u2_length; len++) {
852 /* next unicode character */
855 /* determine bytes required to store unicode character as utf */
856 if (ch && (ch < 0x80))
868 /********************* function: utf_new_u2 ***********************************
870 make utf symbol from u2 array,
871 if isclassname is true '.' is replaced by '/'
873 *******************************************************************************/
875 utf *utf_new_u2(u2 *unicode_pos, u4 unicode_length, bool isclassname)
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 */
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);
889 /* memory allocation failed */
891 printf("length: %d\n",buflength);
892 log_text("utf_new_u2:buffer==NULL");
898 for (i = 0; i++ < unicode_length; unicode_pos++) {
899 /* next unicode character */
902 if ((c != 0) && (c < 0x80)) {
905 if ((int) left < 0) break;
906 /* convert classname */
907 if (isclassname && c == '.')
912 } else if (c < 0x800) {
914 unsigned char high = c >> 6;
915 unsigned char low = c & 0x3F;
917 if ((int) left < 0) break;
918 *pos++ = high | 0xC0;
924 char mid = (c >> 6) & 0x3F;
927 if ((int) left < 0) break;
928 *pos++ = high | 0xE0;
934 /* insert utf-string into symbol-table */
935 result = utf_new(buffer,buflength);
937 MFREE(buffer, char, buflength);
943 /********************* function: javastring_toutf *****************************
945 make utf symbol from javastring
947 *******************************************************************************/
949 utf *javastring_toutf(java_lang_String *string, bool isclassname)
951 java_lang_String *str = (java_lang_String *) string;
952 /* printf("javastring_toutf offset: %d, len %d\n",str->offset, str->count);
954 return utf_new_u2(str->value->data + str->offset, str->count, isclassname);
958 /********************* function: literalstring_u2 *****************************
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
964 if copymode is true a copy of the u2-array is made
966 *******************************************************************************/
968 java_objectheader *literalstring_u2 (java_chararray *a, u4 length, bool copymode )
970 literalstring *s; /* hashtable element */
971 java_lang_String *js; /* u2-array wrapped in javastring */
972 java_chararray *stringdata; /* copy of u2-array */
978 printf("literalstring_u2: length: %d\n",length);
979 log_text("literalstring_u2");
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];
989 js = (java_lang_String *) s->string;
991 if (js->count == length) {
993 for (i=0; i<length; i++)
994 if (js->value->data[i] != a->data[i]) goto nomatch;
996 /* string already in hashtable, free memory */
998 lit_mem_free(a, sizeof(java_chararray) + sizeof(u2) * (length - 1) + 10);
1000 #ifdef JOWENN_DEBUG1
1001 log_text("literalstring_u2: foundentry");
1002 utf_display(javastring_toutf(js,0));
1004 return (java_objectheader *) js;
1008 /* follow link in external hash chain */
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 );
1021 /* location in hashtable found, complete arrayheader */
1022 stringdata -> header.objheader.vftbl = primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl;
1023 stringdata -> header.size = length;
1025 /* create new javastring */
1026 js = LNEW (java_lang_String);
1027 js -> header.vftbl = class_java_lang_String -> vftbl;
1028 js -> value = stringdata;
1030 js -> count = length;
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;
1038 /* update numbe of hashtable entries */
1039 string_hash.entries++;
1041 /* reorganization of hashtable */
1042 if ( string_hash.entries > (string_hash.size*2)) {
1044 /* reorganization of hashtable, average length of
1045 the external chains is approx. 2 */
1049 hashtable newhash; /* the new hashtable */
1051 /* create new hashtable, double the size */
1052 init_hashtable(&newhash, string_hash.size*2);
1053 newhash.entries=string_hash.entries;
1055 /* transfer elements to new hashtable */
1056 for (i=0; i<string_hash.size; i++) {
1057 s = string_hash.ptr[i];
1059 literalstring *nexts = s -> hashlink;
1060 js = (java_lang_String*) s->string;
1061 slot = (unicode_hashkey(js->value->data,js->count)) & (newhash.size-1);
1063 s->hashlink = newhash.ptr[slot];
1064 newhash.ptr[slot] = s;
1066 /* follow link in external hash chain */
1071 /* dispose old table */
1072 MFREE (string_hash.ptr, void*, string_hash.size);
1073 string_hash = newhash;
1075 #ifdef JOWENN_DEBUG1
1076 log_text("literalstring_u2: newly created");
1077 /* utf_display(javastring_toutf(js,0));*/
1080 return (java_objectheader *) js;
1083 /******************** Function: literalstring_new *****************************
1085 creates a new javastring with the text of the utf-symbol
1086 and inserts it into the string hashtable
1088 *******************************************************************************/
1090 java_objectheader *literalstring_new (utf *u)
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 */
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);
1105 return literalstring_u2(a, utflength, false);
1109 /********************** function: literalstring_free **************************
1111 removes a javastring from memory
1113 ******************************************************************************/
1115 void literalstring_free (java_objectheader* sobj)
1117 java_lang_String *s = (java_lang_String*) sobj;
1118 java_chararray *a = s->value;
1120 log_text("literalstring_free called");
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 ?? */
1131 void copy_vftbl(vftbl **dest, vftbl *src)
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
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));
1146 /******************************************************************************************
1148 creates method signature (excluding return type) from array of
1149 class-objects representing the parameters of the method
1151 *******************************************************************************************/
1154 utf *create_methodsig(java_objectarray* types, char *retType)
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 */
1162 if (!types) return NULL;
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;
1170 if (retType) buffer_size+=strlen(retType);
1172 /* allocate buffer */
1173 buffer = MNEW(u1, buffer_size);
1176 /* method-desciptor starts with parenthesis */
1179 for (i=0;i<types->header.size;i++) {
1182 /* current argument */
1183 classinfo *c = (classinfo *) types->data[i];
1184 /* current position in utf-text */
1185 char *utf_ptr = c->name->text;
1187 /* determine type of argument */
1188 if ( (ch = utf_nextu2(&utf_ptr)) == '[' ) {
1191 for ( utf_ptr--; utf_ptr<utf_end(c->name); utf_ptr++)
1192 *pos++ = *utf_ptr; /* copy text */
1196 /* check for primitive types */
1197 for (j=0; j<PRIMITIVETYPE_COUNT; j++) {
1199 char *utf_pos = utf_ptr-1;
1200 char *primitive = primitivetype_table[j].wrapname;
1203 while (utf_pos<utf_end(c->name))
1204 if (*utf_pos++ != *primitive++) goto nomatch;
1206 /* primitive type found */
1207 *pos++ = primitivetype_table[j].typesig;
1213 /* no primitive type and no arrayclass, so must be object */
1216 for ( utf_ptr--; utf_ptr<utf_end(c->name); utf_ptr++)
1227 for (i=0;i<strlen(retType);i++) {
1231 /* create utf-string */
1232 result = utf_new(buffer,(pos-buffer));
1233 MFREE(buffer, u1, buffer_size);
1239 /******************************************************************************************
1241 retrieve the next argument or returntype from a descriptor
1242 and return the corresponding class
1244 *******************************************************************************************/
1246 classinfo *get_type(char **utf_ptr,char *desc_end, bool skip)
1248 classinfo *c = class_from_descriptor(*utf_ptr,desc_end,utf_ptr,
1249 (skip) ? CLASSLOAD_SKIP : CLASSLOAD_LOAD);
1252 panic("illegal descriptor");
1254 if (skip) return NULL;
1256 use_class_as_object(c);
1261 /******************************************************************************************
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
1266 *******************************************************************************************/
1268 java_objectarray* get_parametertypes(methodinfo *m)
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;
1278 utf_nextu2(&utf_ptr);
1280 /* determine number of parameters */
1281 while ( *utf_ptr != ')' ) {
1282 get_type(&utf_ptr,desc_end,true);
1286 /* create class-array */
1287 result = builtin_anewarray(parametercount, class_java_lang_Class);
1289 utf_ptr = descr->text;
1290 utf_nextu2(&utf_ptr);
1292 /* get returntype classes */
1293 for (i = 0; i < parametercount; i++)
1294 result->data[i] = (java_objectheader *) get_type(&utf_ptr,desc_end, false);
1300 /******************************************************************************************
1302 get the returntype class of a method
1304 *******************************************************************************************/
1306 classinfo *get_returntype(methodinfo *m)
1308 char *utf_ptr; /* current position in utf-text */
1309 char *desc_end; /* points behind utf string */
1310 utf *desc = m->descriptor; /* method-descriptor */
1312 utf_ptr = desc->text;
1313 desc_end = utf_end(desc);
1315 /* ignore parametertypes */
1316 while ((utf_ptr<desc_end) && utf_nextu2(&utf_ptr)!=')')
1319 return get_type(&utf_ptr,desc_end, false);
1323 /*****************************************************************************/
1324 /*****************************************************************************/
1327 /*--------------------------------------------------------*/
1328 void printNativeCall(nativeCall nc) {
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);
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);
1342 printf("-+++++--------------------\n");fflush(stdout);
1345 /*--------------------------------------------------------*/
1346 void printCompNativeCall(nativeCompCall nc) {
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);
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);
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);
1366 printf("---------------------\n");fflush(stdout);
1370 /*--------------------------------------------------------*/
1371 classMeth findNativeMethodCalls(utf *c, utf *m, utf *d )
1384 /*--------------------------------------------------------*/
1385 nativeCall* findNativeClassCalls(char *aclassname ) {
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];
1396 /*--------------------------------------------------------*/
1397 /*--------------------------------------------------------*/
1398 void utfNativeCall(nativeCall nc, nativeCompCall *ncc) {
1402 ncc->classname = utf_new_char(nc.classname);
1403 ncc->methCnt = nc.methCnt;
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];
1410 for (j=0; j<nc.callCnt[i]; j++) {
1412 ncc->methods[i].methodCalls[j].classname = utf_new_char(nc.methods[i].methodCalls[j].classname);
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);
1419 ncc->methods[i].methodCalls[j].methodname = NULL;
1420 ncc->methods[i].methodCalls[j].descriptor = NULL;
1428 /*--------------------------------------------------------*/
1430 bool natcall2utf(bool natcallcompdone) {
1433 if (natcallcompdone)
1436 for (i=0;i<NATIVECALLSSIZE; i++) {
1437 utfNativeCall (nativeCalls[i], &nativeCompCalls[i]);
1442 /*--------------------------------------------------------*/
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 * ---------------------------------------------------------------------
1452 * indent-tabs-mode: t