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 862 2004-01-06 23:42:01Z stefan $
52 #include "nativetypes.hh"
58 #include "toolbox/loging.h"
59 #include "toolbox/memory.h"
60 #include "threads/thread.h"
61 #include "threads/threadio.h"
62 #include "threads/locks.h"
64 /* Include files for IO functions */
68 #include <sys/types.h>
74 #include "threads/threadio.h"
76 /* searchpath for classfiles */
79 /* for java-string to char conversion */
80 #define MAXSTRINGSIZE 1000
82 /******************** systemclasses required for native methods ***************/
84 classinfo *class_java_lang_Class;
85 classinfo *class_java_lang_VMClass;
86 methodinfo *method_vmclass_init;
87 /* static classinfo *class_java_lang_Cloneable=0; */ /* now in global.h */
88 classinfo *class_java_lang_CloneNotSupportedException;
89 classinfo *class_java_lang_System;
90 classinfo *class_java_lang_ClassLoader;
91 classinfo *class_java_lang_NoClassDefFoundError;
92 classinfo *class_java_lang_ClassNotFoundException;
93 classinfo *class_java_lang_LinkageError;
94 classinfo *class_java_lang_InstantiationException;
95 classinfo *class_java_lang_NoSuchMethodError;
96 classinfo *class_java_lang_NoSuchFieldError;
97 classinfo *class_java_lang_ClassFormatError;
98 classinfo *class_java_lang_IllegalArgumentException;
99 classinfo *class_java_lang_ArrayIndexOutOfBoundsException;
100 classinfo *class_java_lang_NoSuchFieldException;
101 classinfo *class_java_io_SyncFailedException;
102 classinfo *class_java_io_IOException;
103 classinfo *class_java_io_FileNotFoundException;
104 classinfo *class_java_io_UnixFileSystem;
105 classinfo *class_java_security_PrivilegedActionException;
106 classinfo *class_java_net_UnknownHostException;
107 classinfo *class_java_net_SocketException;
108 classinfo *class_java_lang_NoSuchMethodException;
109 classinfo *class_java_lang_Double;
110 classinfo *class_java_lang_Float;
111 classinfo *class_java_lang_Long;
112 classinfo *class_java_lang_Byte;
113 classinfo *class_java_lang_Short;
114 classinfo *class_java_lang_Boolean;
115 classinfo *class_java_lang_Void;
116 classinfo *class_java_lang_Character;
117 classinfo *class_java_lang_Integer;
119 /* the system classloader object */
120 struct java_lang_ClassLoader *SystemClassLoader = NULL;
122 /* for raising exceptions from native methods */
123 THREADSPECIFIC java_objectheader* _exceptionptr = NULL;
125 /************* use classinfo structure as java.lang.Class object **************/
127 void use_class_as_object(classinfo *c)
132 if (!class_java_lang_Class)
133 class_java_lang_Class = class_new(utf_new_char ("java/lang/Class"));
135 vt = class_java_lang_Class->vftbl;
138 if (!c->classvftbl) {
139 c->classvftbl = true;
141 /* copy_vftbl(&newtbl, vt);
142 newtbl->class = c->header.vftbl->class;
143 newtbl->baseval = c->header.vftbl->baseval;
144 newtbl->diffval = c->header.vftbl->diffval;
145 c->header.vftbl = newtbl;*/
147 c->header.vftbl = class_java_lang_Class->vftbl;
149 if (!class_java_lang_VMClass) {
150 loader_load_sysclass(&class_java_lang_VMClass,
151 utf_new_char("java/lang/VMClass"));
153 method_vmclass_init =
154 class_findmethod(class_java_lang_VMClass,
155 utf_new_char("<init>"),
156 utf_new_char("(Lgnu/classpath/RawData;)V"));
158 if (method_vmclass_init == 0) {
159 class_showmethods(class_java_lang_VMClass);
160 panic("Needed class initializer for VMClass could not be found");
164 java_objectheader *vmo = builtin_new(class_java_lang_VMClass);
166 if (!vmo) panic("Error while creating instance of java/lang/VMClass");
167 asm_calljavafunction(method_vmclass_init, vmo, c, NULL, NULL);
168 c->vmClass = (java_lang_VMClass *) vmo;
169 /*log_text("VMCLASS has been attached");*/
175 /*************************** include native methods ***************************/
178 #include "nat/GdkGraphics.c"
179 #include "nat/GtkComponentPeer.c"
180 #include "nat/GdkPixbufDecoder.c"
181 #include "nat/GtkScrollPanePeer.c"
182 #include "nat/GtkFileDialogPeer.c"
183 #include "nat/GtkLabelPeer.c"
187 /************************** tables for methods ********************************/
192 /* table for locating native methods */
193 static struct nativeref {
201 #include "nativetable.hh"
206 #define NATIVETABLESIZE (sizeof(nativetable)/sizeof(struct nativeref))
208 /* table for fast string comparison */
209 static struct nativecompref {
215 } nativecomptable [NATIVETABLESIZE];
217 /* string comparsion table initialized */
218 static bool nativecompdone = false;
221 /******************************************************************************/
222 /******************************************************************************/
223 #include "natcalls.h"
225 /* string call comparison table initialized */
227 /******************************************************************************/
228 /******************************************************************************/
230 /*--------------- native method calls & classes used -------------------------*/
234 /* throw some loader exceptions */
236 void throw_noclassdeffounderror_message(utf* classname)
238 if (!class_java_lang_NoClassDefFoundError) {
239 panic("java.lang.NoClassDefFoundError not found. Maybe wrong classpath?");
242 /* throws a NoClassDefFoundError with message */
243 *exceptionptr = native_new_and_init_string(class_java_lang_NoClassDefFoundError,
244 javastring_new(classname));
248 void throw_linkageerror_message(utf* classname)
250 if (!class_java_lang_LinkageError) {
251 panic("java.lang.LinkageError not found. Maybe wrong classpath?");
254 /* throws a LinkageError with message */
255 *exceptionptr = native_new_and_init_string(class_java_lang_LinkageError,
256 javastring_new(classname));
260 /*********************** function: native_loadclasses **************************
262 load classes required for native methods
264 *******************************************************************************/
266 void native_loadclasses()
268 static int classesLoaded=0; /*temporary hack JoWenn*/
269 if (classesLoaded) return;
271 /* log_text("loadclasses entered");*/
274 /*class_java_lang_System =*/
275 (void) class_new(utf_new_char("java/lang/VMClass"));/*JoWenn*/
276 (void) class_new(utf_new_char("java/lang/Class"));/*JoWenn*/
278 /* class_new adds the class to the list of classes to be loaded */
279 if (!class_java_lang_Cloneable)
280 class_java_lang_Cloneable =
281 class_new(utf_new_char("java/lang/Cloneable"));
282 /* log_text("loadclasses: class_java_lang_Cloneable has been initialized");*/
283 class_java_lang_CloneNotSupportedException =
284 class_new(utf_new_char("java/lang/CloneNotSupportedException"));
285 if (!class_java_lang_Class)
286 class_java_lang_Class =
287 class_new(utf_new_char("java/lang/Class"));
288 class_java_io_IOException =
289 class_new(utf_new_char("java/io/IOException"));
290 class_java_io_FileNotFoundException =
291 class_new(utf_new_char("java/io/FileNotFoundException"));
292 class_java_lang_NoClassDefFoundError =
293 class_new(utf_new_char("java/lang/NoClassDefFoundError"));
294 class_java_lang_ClassNotFoundException =
295 class_new(utf_new_char("java/lang/ClassNotFoundException"));
296 class_java_lang_LinkageError =
297 class_new(utf_new_char("java/lang/LinkageError"));
298 class_java_lang_InstantiationException =
299 class_new(utf_new_char("java/lang/InstantiationException"));
300 class_java_lang_NoSuchMethodError =
301 class_new(utf_new_char("java/lang/NoSuchMethodError"));
302 class_java_lang_NoSuchFieldError =
303 class_new(utf_new_char("java/lang/NoSuchFieldError"));
304 class_java_lang_ClassFormatError =
305 class_new(utf_new_char("java/lang/ClassFormatError"));
306 class_java_io_SyncFailedException =
307 class_new(utf_new_char("java/io/SyncFailedException"));
309 /* log_text("native_loadclasses: class_new(\"java/lang/ClassLoader\")"); */
310 class_java_lang_ClassLoader =
311 class_new(utf_new_char("java/lang/ClassLoader"));
312 /* log_text("native_loadclasses: class_new(\"java/security/PrivilegedActionException\")"); */
313 class_java_security_PrivilegedActionException =
314 class_new(utf_new_char("java/security/PrivilegedActionException"));
316 loader_load_sysclass(&class_java_net_UnknownHostException,
317 utf_new_char("java/net/UnknownHostException"));
318 loader_load_sysclass(&class_java_net_SocketException,
319 utf_new_char("java/net/SocketException"));
321 class_java_lang_IllegalArgumentException =
322 class_new(utf_new_char("java/lang/IllegalArgumentException"));
323 class_java_lang_ArrayIndexOutOfBoundsException =
324 class_new(utf_new_char("java/lang/ArrayIndexOutOfBoundsException"));
325 class_java_lang_NoSuchFieldException =
326 class_new(utf_new_char("java/lang/NoSuchFieldException"));
327 class_java_lang_NoSuchMethodException =
328 class_new(utf_new_char("java/lang/NoSuchMethodException"));
330 /* load classes for wrapping primitive types */
331 class_java_lang_Double = class_new(utf_new_char("java/lang/Double"));
332 class_init(class_java_lang_Double);
334 class_java_lang_Float = class_new(utf_new_char("java/lang/Float"));
335 class_java_lang_Character = class_new(utf_new_char("java/lang/Character"));
336 class_java_lang_Integer = class_new(utf_new_char("java/lang/Integer"));
337 class_java_lang_Long = class_new(utf_new_char("java/lang/Long"));
338 class_java_lang_Byte = class_new(utf_new_char("java/lang/Byte"));
339 class_java_lang_Short = class_new(utf_new_char("java/lang/Short"));
340 class_java_lang_Boolean = class_new(utf_new_char("java/lang/Boolean"));
341 class_java_lang_Void = class_new(utf_new_char("java/lang/Void"));
347 /*************** adds a class to the vector of loaded classes ****************/
349 void systemclassloader_addclass(classinfo *c)
353 /* find method addClass of java.lang.ClassLoader */
354 m = class_resolvemethod(class_java_lang_ClassLoader,
355 utf_new_char("addClass"),
356 utf_new_char("(Ljava/lang/Class;)")
360 panic("warning: cannot initialize classloader");
362 /* prepare class to be passed as argument */
363 use_class_as_object (c);
365 /* call 'addClass' */
366 asm_calljavafunction(m,
367 (java_objectheader*) SystemClassLoader,
368 (java_objectheader*) c,
375 /*************** adds a library to the vector of loaded libraries *************/
377 void systemclassloader_addlibrary(java_objectheader *o)
379 log_text("systemclassloader_addlibrary");
383 /*****************************************************************************
385 create systemclassloader object and initialize instance fields
387 ******************************************************************************/
389 void init_systemclassloader()
391 if (!SystemClassLoader) {
392 native_loadclasses();
393 log_text("Initializing new system class loader");
394 /* create object and call initializer */
395 SystemClassLoader = (java_lang_ClassLoader*) native_new_and_init(class_java_lang_ClassLoader);
397 /* systemclassloader has no parent */
398 SystemClassLoader->parent = NULL;
399 SystemClassLoader->initialized = true;
401 log_text("leaving system class loader");
405 /********************* add loaded library name *******************************/
407 void systemclassloader_addlibname(java_objectheader *o)
412 m = class_resolvemethod(loader_load_sysclass(NULL, utf_new_char ("java/util/Vector")),
413 utf_new_char("addElement"),
414 utf_new_char("(Ljava/lang/Object;)V"));
416 if (!m) panic("cannot initialize classloader");
418 id = envTable.GetStaticFieldID(&env,
419 class_java_lang_ClassLoader,
420 "loadedLibraryNames",
421 "Ljava/util/Vector;");
423 if (!id) panic("can not access ClassLoader");
425 asm_calljavafunction(m,
426 envTable.GetStaticObjectField(&env, class_java_lang_ClassLoader, id),
433 /********************* function: native_setclasspath **************************/
435 void native_setclasspath(char *path)
437 /* set searchpath for classfiles */
442 /*********************** Function: native_findfunction *************************
444 Looks up a method (must have the same class name, method name, descriptor
445 and 'static'ness) and returns a function pointer to it.
446 Returns: function pointer or NULL (if there is no such method)
448 Remark: For faster operation, the names/descriptors are converted from C
449 strings to Unicode the first time this function is called.
451 *******************************************************************************/
453 functionptr native_findfunction(utf *cname, utf *mname,
454 utf *desc, bool isstatic)
457 /* entry of table for fast string comparison */
458 struct nativecompref *n;
459 /* for warning message if no function is found */
463 isstatic = isstatic ? true : false;
465 if (!nativecompdone) {
466 for (i = 0; i < NATIVETABLESIZE; i++) {
467 nativecomptable[i].classname =
468 utf_new_char(nativetable[i].classname);
469 nativecomptable[i].methodname =
470 utf_new_char(nativetable[i].methodname);
471 nativecomptable[i].descriptor =
472 utf_new_char(nativetable[i].descriptor);
473 nativecomptable[i].isstatic =
474 nativetable[i].isstatic;
475 nativecomptable[i].func =
478 nativecompdone = true;
483 utf_strlen(cname) + utf_strlen(mname) + utf_strlen(desc) + 64;
485 buffer = MNEW(char, buffer_len);
487 strcpy(buffer, "searching matching function in native table:");
488 utf_sprint(buffer+strlen(buffer), mname);
489 strcpy(buffer+strlen(buffer), ": ");
490 utf_sprint(buffer+strlen(buffer), desc);
491 strcpy(buffer+strlen(buffer), " for class ");
492 utf_sprint(buffer+strlen(buffer), cname);
496 MFREE(buffer, char, buffer_len);
499 for (i = 0; i < NATIVETABLESIZE; i++) {
500 n = &(nativecomptable[i]);
502 if (cname == n->classname && mname == n->methodname &&
503 desc == n->descriptor && isstatic == n->isstatic)
507 if (cname == n->classname && mname == n->methodname ) log_text("static and descriptor mismatch");
511 utf_strlen(n->classname) + utf_strlen(n->methodname) + utf_strlen(n->descriptor) + 64;
513 buffer = MNEW(char, buffer_len);
515 strcpy(buffer, "comparing with:");
516 utf_sprint(buffer+strlen(buffer), n->methodname);
517 strcpy (buffer+strlen(buffer), ": ");
518 utf_sprint(buffer+strlen(buffer), n->descriptor);
519 strcpy(buffer+strlen(buffer), " for class ");
520 utf_sprint(buffer+strlen(buffer), n->classname);
524 MFREE(buffer, char, buffer_len);
531 /* no function was found, display warning */
534 utf_strlen(cname) + utf_strlen(mname) + utf_strlen(desc) + 64;
536 buffer = MNEW(char, buffer_len);
538 strcpy(buffer, "warning: native function ");
539 utf_sprint(buffer + strlen(buffer), mname);
540 strcpy(buffer + strlen(buffer), ": ");
541 utf_sprint(buffer + strlen(buffer), desc);
542 strcpy(buffer + strlen(buffer), " not found in class ");
543 utf_sprint(buffer + strlen(buffer), cname);
547 MFREE(buffer, char, buffer_len);
551 /* keep compiler happy */
556 /********************** function: javastring_new *******************************
558 creates a new object of type java/lang/String with the text of
559 the specified utf8-string
561 return: pointer to the string or NULL if memory is exhausted.
563 *******************************************************************************/
565 /* java_objectheader *javastring_new(utf *u) */
566 java_lang_String *javastring_new(utf *u)
568 char *utf_ptr = u->text; /* current utf character in utf string */
569 int utflength = utf_strlen(u); /* length of utf-string if uncompressed */
570 java_lang_String *s; /* result-string */
574 /* log_text("javastring_new");*/
576 s = (java_lang_String*) builtin_new(class_java_lang_String);
577 a = builtin_newarray_char(utflength);
579 /* javastring or character-array could not be created */
583 /* decompress utf-string */
584 for (i = 0; i < utflength; i++)
585 a->data[i] = utf_nextu2(&utf_ptr);
587 /* set fields of the javastring-object */
590 s->count = utflength;
592 /* return (java_objectheader*) s; */
597 /********************** function: javastring_new_char **************************
599 creates a new java/lang/String object which contains the convertet
600 C-string passed via text.
602 return: the object pointer or NULL if memory is exhausted.
604 *******************************************************************************/
606 /* java_objectheader *javastring_new_char (char *text) */
607 java_lang_String *javastring_new_char (char *text)
610 s4 len = strlen(text); /* length of the string */
611 java_lang_String *s; /* result-string */
614 /*log_text("javastring_new_char");*/
615 s = (java_lang_String*) builtin_new(class_java_lang_String);
616 a = builtin_newarray_char(len);
618 /* javastring or character-array could not be created */
623 for (i = 0; i < len; i++)
624 a->data[i] = text[i];
626 /* set fields of the javastring-object */
631 /* return (java_objectheader*) s; */
636 /************************* function javastring_tochar **************************
638 converts a Java string into a C string.
640 return: pointer to C string
642 Caution: every call of this function overwrites the previous string !!!
644 *******************************************************************************/
646 static char stringbuffer[MAXSTRINGSIZE];
648 char *javastring_tochar (java_objectheader *so)
650 java_lang_String *s = (java_lang_String*) so;
654 log_text("javastring_tochar");
661 if (s->count > MAXSTRINGSIZE)
663 for (i = 0; i < s->count; i++)
664 stringbuffer[i] = a->data[s->offset+i];
665 stringbuffer[i] = '\0';
670 /****************** function class_findfield_approx ****************************
672 searches in 'classinfo'-structure for a field with the
675 *******************************************************************************/
677 fieldinfo *class_findfield_approx(classinfo *c, utf *name)
680 for (i = 0; i < c->fieldscount; i++) {
681 /* compare field names */
682 if ((c->fields[i].name == name))
683 return &(c->fields[i]);
686 /* field was not found, raise exception */
687 *exceptionptr = native_new_and_init(class_java_lang_NoSuchFieldException);
692 s4 class_findfield_index_approx (classinfo *c, utf *name)
695 for (i = 0; i < c->fieldscount; i++) {
696 /* compare field names */
697 if ((c->fields[i].name == name))
701 /* field was not found, raise exception */
702 *exceptionptr = native_new_and_init(class_java_lang_NoSuchFieldException);
707 /********************** function: native_new_and_init *************************
709 Creates a new object on the heap and calls the initializer.
710 Returns the object pointer or NULL if memory is exhausted.
712 *******************************************************************************/
714 java_objectheader *native_new_and_init(classinfo *c)
717 java_objectheader *o;
719 /* if c==NULL it is probebly because loader_load failed */
720 if (!c) return *exceptionptr;
722 o = builtin_new(c); /* create object */
725 printf("native_new_and_init ");
726 utf_display(c->name);
730 /* printf("o!=NULL\n"); */
731 /* find initializer */
733 m = class_findmethod(c, utf_new_char("<init>"), utf_new_char("()V"));
735 if (!m) { /* initializer not found */
737 char logtext[MAXLOGTEXT];
738 sprintf(logtext, "Warning: class has no instance-initializer: ");
739 utf_sprint(logtext + strlen(logtext), c->name);
745 /* call initializer */
747 asm_calljavafunction(m, o, NULL, NULL, NULL);
753 java_objectheader *native_new_and_init_string(classinfo *c, java_lang_String *s)
756 java_objectheader *o;
758 /* if c==NULL it is probebly because loader_load failed */
759 if (!c) return *exceptionptr;
761 o = builtin_new(c); /* create object */
765 /* find initializer */
767 m = class_findmethod(c,
768 utf_new_char("<init>"),
769 utf_new_char("(Ljava/lang/String;)V"));
771 if (!m) { /* initializer not found */
773 char logtext[MAXLOGTEXT];
774 sprintf(logtext, "Warning: class has no instance-initializer: ");
775 utf_sprint(logtext + strlen(logtext), c->name);
781 /* call initializer */
783 asm_calljavafunction(m, o, s, NULL, NULL);
789 /******************** function: stringtable_update ****************************
791 traverses the javastring hashtable and sets the vftbl-entries of
792 javastrings which were temporarily set to NULL, because
793 java.lang.Object was not yet loaded
795 *******************************************************************************/
797 void stringtable_update ()
799 java_lang_String *js;
801 literalstring *s; /* hashtable entry */
804 for (i = 0; i < string_hash.size; i++) {
805 s = string_hash.ptr[i];
809 js = (java_lang_String *) s->string;
811 if (!js || !js->value)
812 /* error in hashtable found */
813 panic("invalid literalstring in hashtable");
817 if (!js->header.vftbl)
818 /* vftbl of javastring is NULL */
819 js->header.vftbl = class_java_lang_String -> vftbl;
821 if (!a->header.objheader.vftbl)
822 /* vftbl of character-array is NULL */
823 a->header.objheader.vftbl = primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl;
825 /* follow link in external hash chain */
833 /************************* function: u2_utflength ***************************
835 returns the utf length in bytes of a u2 array
837 *****************************************************************************/
839 u4 u2_utflength(u2 *text, u4 u2_length)
841 u4 result_len = 0; /* utf length in bytes */
842 u2 ch; /* current unicode character */
845 for (len = 0; len < u2_length; len++) {
846 /* next unicode character */
849 /* determine bytes required to store unicode character as utf */
850 if (ch && (ch < 0x80))
862 /********************* function: utf_new_u2 ***********************************
864 make utf symbol from u2 array,
865 if isclassname is true '.' is replaced by '/'
867 *******************************************************************************/
869 utf *utf_new_u2(u2 *unicode_pos, u4 unicode_length, bool isclassname)
871 char *buffer; /* memory buffer for unicode characters */
872 char *pos; /* pointer to current position in buffer */
873 u4 left; /* unicode characters left */
874 u4 buflength; /* utf length in bytes of the u2 array */
875 utf *result; /* resulting utf-string */
878 /* determine utf length in bytes and allocate memory */
879 /* printf("utf_new_u2: unicode_length=%d\n",unicode_length); */
880 buflength = u2_utflength(unicode_pos, unicode_length);
881 buffer = MNEW(char, buflength);
883 /* memory allocation failed */
885 printf("length: %d\n",buflength);
886 log_text("utf_new_u2:buffer==NULL");
892 for (i = 0; i++ < unicode_length; unicode_pos++) {
893 /* next unicode character */
896 if ((c != 0) && (c < 0x80)) {
899 if ((int) left < 0) break;
900 /* convert classname */
901 if (isclassname && c == '.')
906 } else if (c < 0x800) {
908 unsigned char high = c >> 6;
909 unsigned char low = c & 0x3F;
911 if ((int) left < 0) break;
912 *pos++ = high | 0xC0;
918 char mid = (c >> 6) & 0x3F;
921 if ((int) left < 0) break;
922 *pos++ = high | 0xE0;
928 /* insert utf-string into symbol-table */
929 result = utf_new(buffer,buflength);
931 MFREE(buffer, char, buflength);
937 /********************* function: javastring_toutf *****************************
939 make utf symbol from javastring
941 *******************************************************************************/
943 utf *javastring_toutf(java_lang_String *string, bool isclassname)
945 java_lang_String *str = (java_lang_String *) string;
946 /* printf("javastring_toutf offset: %d, len %d\n",str->offset, str->count);
948 return utf_new_u2(str->value->data + str->offset, str->count, isclassname);
952 /********************* function: literalstring_u2 *****************************
954 searches for the javastring with the specified u2-array in
955 the string hashtable, if there is no such string a new one is
958 if copymode is true a copy of the u2-array is made
960 *******************************************************************************/
962 java_objectheader *literalstring_u2 (java_chararray *a, u4 length, bool copymode )
964 literalstring *s; /* hashtable element */
965 java_lang_String *js; /* u2-array wrapped in javastring */
966 java_chararray *stringdata; /* copy of u2-array */
972 printf("literalstring_u2: length: %d\n",length);
973 log_text("literalstring_u2");
976 /* find location in hashtable */
977 key = unicode_hashkey (a->data, length);
978 slot = key & (string_hash.size-1);
979 s = string_hash.ptr[slot];
983 js = (java_lang_String *) s->string;
985 if (js->count == length) {
987 for (i=0; i<length; i++)
988 if (js->value->data[i] != a->data[i]) goto nomatch;
990 /* string already in hashtable, free memory */
992 lit_mem_free(a, sizeof(java_chararray) + sizeof(u2) * (length - 1) + 10);
995 log_text("literalstring_u2: foundentry");
996 utf_display(javastring_toutf(js,0));
998 return (java_objectheader *) js;
1002 /* follow link in external hash chain */
1007 /* create copy of u2-array for new javastring */
1008 u4 arraysize = sizeof(java_chararray) + sizeof(u2)*(length-1)+10;
1009 stringdata = lit_mem_alloc ( arraysize );
1010 memcpy(stringdata, a, arraysize );
1015 /* location in hashtable found, complete arrayheader */
1016 stringdata -> header.objheader.vftbl = primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl;
1017 stringdata -> header.size = length;
1019 /* create new javastring */
1020 js = LNEW (java_lang_String);
1021 js -> header.vftbl = class_java_lang_String -> vftbl;
1022 js -> value = stringdata;
1024 js -> count = length;
1026 /* create new literalstring */
1027 s = NEW (literalstring);
1028 s->hashlink = string_hash.ptr[slot];
1029 s->string = (java_objectheader *) js;
1030 string_hash.ptr[slot] = s;
1032 /* update numbe of hashtable entries */
1033 string_hash.entries++;
1035 /* reorganization of hashtable */
1036 if ( string_hash.entries > (string_hash.size*2)) {
1038 /* reorganization of hashtable, average length of
1039 the external chains is approx. 2 */
1043 hashtable newhash; /* the new hashtable */
1045 /* create new hashtable, double the size */
1046 init_hashtable(&newhash, string_hash.size*2);
1047 newhash.entries=string_hash.entries;
1049 /* transfer elements to new hashtable */
1050 for (i=0; i<string_hash.size; i++) {
1051 s = string_hash.ptr[i];
1053 literalstring *nexts = s -> hashlink;
1054 js = (java_lang_String*) s->string;
1055 slot = (unicode_hashkey(js->value->data,js->count)) & (newhash.size-1);
1057 s->hashlink = newhash.ptr[slot];
1058 newhash.ptr[slot] = s;
1060 /* follow link in external hash chain */
1065 /* dispose old table */
1066 MFREE (string_hash.ptr, void*, string_hash.size);
1067 string_hash = newhash;
1069 #ifdef JOWENN_DEBUG1
1070 log_text("literalstring_u2: newly created");
1071 /* utf_display(javastring_toutf(js,0));*/
1074 return (java_objectheader *) js;
1077 /******************** Function: literalstring_new *****************************
1079 creates a new javastring with the text of the utf-symbol
1080 and inserts it into the string hashtable
1082 *******************************************************************************/
1084 java_objectheader *literalstring_new (utf *u)
1086 char *utf_ptr = u->text; /* pointer to current unicode character in utf string */
1087 u4 utflength = utf_strlen(u); /* length of utf-string if uncompressed */
1088 java_chararray *a; /* u2-array constructed from utf string */
1090 /* log_text("literalstring_new"); */
1091 /* utf_display(u);*/
1092 /*if (utflength==0) while (1) sleep(60);*/
1093 /* log_text("------------------"); */
1094 /* allocate memory */
1095 a = lit_mem_alloc (sizeof(java_chararray) + sizeof(u2)*(utflength-1)+10 );
1096 /* convert utf-string to u2-array */
1097 for (i=0; i<utflength; i++) a->data[i] = utf_nextu2(&utf_ptr);
1099 return literalstring_u2(a, utflength, false);
1103 /********************** function: literalstring_free **************************
1105 removes a javastring from memory
1107 ******************************************************************************/
1109 void literalstring_free (java_objectheader* sobj)
1111 java_lang_String *s = (java_lang_String*) sobj;
1112 java_chararray *a = s->value;
1114 log_text("literalstring_free called");
1116 /* dispose memory of java.lang.String object */
1117 LFREE (s, java_lang_String);
1118 /* dispose memory of java-characterarray */
1119 LFREE (a, sizeof(java_chararray) + sizeof(u2)*(a->header.size-1)); /* +10 ?? */
1125 void copy_vftbl(vftbl **dest, vftbl *src)
1129 /* XXX this kind of copying does not work (in the general
1130 * case). The interface tables would have to be copied, too. I
1131 * don't see why we should make a copy anyway. -Edwin
1133 *dest = mem_alloc(sizeof(vftbl) + sizeof(methodptr)*(src->vftbllength-1));
1134 memcpy(*dest, src, sizeof(vftbl) - sizeof(methodptr));
1135 memcpy(&(*dest)->table, &src->table, src->vftbllength * sizeof(methodptr));
1140 /******************************************************************************************
1142 creates method signature (excluding return type) from array of
1143 class-objects representing the parameters of the method
1145 *******************************************************************************************/
1148 utf *create_methodsig(java_objectarray* types, char *retType)
1150 char *buffer; /* buffer for building the desciptor */
1151 char *pos; /* current position in buffer */
1152 utf *result; /* the method signature */
1153 u4 buffer_size = 3; /* minimal size=3: room for parenthesis and returntype */
1156 if (!types) return NULL;
1158 /* determine required buffer-size */
1159 for (i = 0; i < types->header.size; i++) {
1160 classinfo *c = (classinfo *) types->data[i];
1161 buffer_size = buffer_size + c->name->blength + 2;
1164 if (retType) buffer_size += strlen(retType);
1166 /* allocate buffer */
1167 buffer = MNEW(u1, buffer_size);
1170 /* method-desciptor starts with parenthesis */
1173 for (i = 0; i < types->header.size; i++) {
1176 /* current argument */
1177 classinfo *c = (classinfo *) types->data[i];
1179 /* current position in utf-text */
1180 char *utf_ptr = c->name->text;
1182 /* determine type of argument */
1183 if ((ch = utf_nextu2(&utf_ptr)) == '[') {
1185 for (utf_ptr--; utf_ptr < utf_end(c->name); utf_ptr++) {
1186 *pos++ = *utf_ptr; /* copy text */
1190 /* check for primitive types */
1191 for (j = 0; j < PRIMITIVETYPE_COUNT; j++) {
1192 char *utf_pos = utf_ptr - 1;
1193 char *primitive = primitivetype_table[j].wrapname;
1196 while (utf_pos < utf_end(c->name)) {
1197 if (*utf_pos++ != *primitive++) goto nomatch;
1200 /* primitive type found */
1201 *pos++ = primitivetype_table[j].typesig;
1207 /* no primitive type and no arrayclass, so must be object */
1211 for (utf_ptr--; utf_ptr < utf_end(c->name); utf_ptr++) {
1224 for (i = 0; i < strlen(retType); i++) {
1225 *pos++ = retType[i];
1229 /* create utf-string */
1230 result = utf_new(buffer, (pos - buffer));
1231 MFREE(buffer, u1, buffer_size);
1237 /******************************************************************************************
1239 retrieve the next argument or returntype from a descriptor
1240 and return the corresponding class
1242 *******************************************************************************************/
1244 classinfo *get_type(char **utf_ptr,char *desc_end, bool skip)
1246 classinfo *c = class_from_descriptor(*utf_ptr,desc_end,utf_ptr,
1247 (skip) ? CLASSLOAD_SKIP : CLASSLOAD_LOAD);
1250 panic("illegal descriptor");
1252 if (skip) return NULL;
1254 use_class_as_object(c);
1259 /******************************************************************************************
1261 use the descriptor of a method to generate a java/lang/Class array
1262 which contains the classes of the parametertypes of the method
1264 *******************************************************************************************/
1266 java_objectarray* get_parametertypes(methodinfo *m)
1268 utf *descr = m->descriptor; /* method-descriptor */
1269 char *utf_ptr = descr->text; /* current position in utf-text */
1270 char *desc_end = utf_end(descr); /* points behind utf string */
1271 java_objectarray* result;
1272 int parametercount = 0;
1276 utf_nextu2(&utf_ptr);
1278 /* determine number of parameters */
1279 while ( *utf_ptr != ')' ) {
1280 get_type(&utf_ptr,desc_end,true);
1284 /* create class-array */
1285 result = builtin_anewarray(parametercount, class_java_lang_Class);
1287 utf_ptr = descr->text;
1288 utf_nextu2(&utf_ptr);
1290 /* get returntype classes */
1291 for (i = 0; i < parametercount; i++)
1292 result->data[i] = (java_objectheader *) get_type(&utf_ptr,desc_end, false);
1301 /******************************************************************************************
1303 get the exceptions which can be thrown by a method
1305 *******************************************************************************************/
1307 java_objectarray* get_exceptiontypes(methodinfo *m)
1315 /******************************************************************************************
1317 get the returntype class of a method
1319 *******************************************************************************************/
1321 classinfo *get_returntype(methodinfo *m)
1323 char *utf_ptr; /* current position in utf-text */
1324 char *desc_end; /* points behind utf string */
1325 utf *desc = m->descriptor; /* method-descriptor */
1327 utf_ptr = desc->text;
1328 desc_end = utf_end(desc);
1330 /* ignore parametertypes */
1331 while ((utf_ptr<desc_end) && utf_nextu2(&utf_ptr)!=')')
1334 return get_type(&utf_ptr,desc_end, false);
1338 /*****************************************************************************/
1339 /*****************************************************************************/
1342 /*--------------------------------------------------------*/
1343 void printNativeCall(nativeCall nc) {
1346 printf("\n%s's Native Methods call:\n",nc.classname); fflush(stdout);
1347 for (i=0; i<nc.methCnt; i++) {
1348 printf("\tMethod=%s %s\n",nc.methods[i].methodname, nc.methods[i].descriptor);fflush(stdout);
1350 for (j=0; j<nc.callCnt[i]; j++) {
1351 printf("\t\t<%i,%i>aCalled = %s %s %s\n",i,j,
1352 nc.methods[i].methodCalls[j].classname,
1353 nc.methods[i].methodCalls[j].methodname,
1354 nc.methods[i].methodCalls[j].descriptor);fflush(stdout);
1357 printf("-+++++--------------------\n");fflush(stdout);
1360 /*--------------------------------------------------------*/
1361 void printCompNativeCall(nativeCompCall nc) {
1363 printf("printCompNativeCall BEGIN\n");fflush(stdout);
1364 printf("\n%s's Native Comp Methods call:\n",nc.classname->text);fflush(stdout);
1365 utf_display(nc.classname); fflush(stdout);
1367 for (i=0; i<nc.methCnt; i++) {
1368 printf("\tMethod=%s %s\n",nc.methods[i].methodname->text,nc.methods[i].descriptor->text);fflush(stdout);
1369 utf_display(nc.methods[i].methodname); fflush(stdout);
1370 utf_display(nc.methods[i].descriptor);fflush(stdout);
1371 printf("\n");fflush(stdout);
1373 for (j=0; j<nc.callCnt[i]; j++) {
1374 printf("\t\t<%i,%i>bCalled = ",i,j);fflush(stdout);
1375 utf_display(nc.methods[i].methodCalls[j].classname);fflush(stdout);
1376 utf_display(nc.methods[i].methodCalls[j].methodname); fflush(stdout);
1377 utf_display(nc.methods[i].methodCalls[j].descriptor);fflush(stdout);
1378 printf("\n");fflush(stdout);
1381 printf("---------------------\n");fflush(stdout);
1385 /*--------------------------------------------------------*/
1386 classMeth findNativeMethodCalls(utf *c, utf *m, utf *d )
1399 /*--------------------------------------------------------*/
1400 nativeCall* findNativeClassCalls(char *aclassname ) {
1403 for (i=0;i<NATIVECALLSSIZE; i++) {
1404 /* convert table to utf later to speed up search */
1405 if (strcmp(nativeCalls[i].classname, aclassname) == 0)
1406 return &nativeCalls[i];
1411 /*--------------------------------------------------------*/
1412 /*--------------------------------------------------------*/
1413 void utfNativeCall(nativeCall nc, nativeCompCall *ncc) {
1417 ncc->classname = utf_new_char(nc.classname);
1418 ncc->methCnt = nc.methCnt;
1420 for (i=0; i<nc.methCnt; i++) {
1421 ncc->methods[i].methodname = utf_new_char(nc.methods[i].methodname);
1422 ncc->methods[i].descriptor = utf_new_char(nc.methods[i].descriptor);
1423 ncc->callCnt[i] = nc.callCnt[i];
1425 for (j=0; j<nc.callCnt[i]; j++) {
1427 ncc->methods[i].methodCalls[j].classname = utf_new_char(nc.methods[i].methodCalls[j].classname);
1429 if (strcmp("", nc.methods[i].methodCalls[j].methodname) != 0) {
1430 ncc->methods[i].methodCalls[j].methodname = utf_new_char(nc.methods[i].methodCalls[j].methodname);
1431 ncc->methods[i].methodCalls[j].descriptor = utf_new_char(nc.methods[i].methodCalls[j].descriptor);
1434 ncc->methods[i].methodCalls[j].methodname = NULL;
1435 ncc->methods[i].methodCalls[j].descriptor = NULL;
1443 /*--------------------------------------------------------*/
1445 bool natcall2utf(bool natcallcompdone) {
1448 if (natcallcompdone)
1451 for (i=0;i<NATIVECALLSSIZE; i++) {
1452 utfNativeCall (nativeCalls[i], &nativeCompCalls[i]);
1457 /*--------------------------------------------------------*/
1461 * These are local overrides for various environment variables in Emacs.
1462 * Please do not remove this and leave it at the end of the file, where
1463 * Emacs will automagically detect them.
1464 * ---------------------------------------------------------------------
1467 * indent-tabs-mode: t