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 930 2004-03-02 21:18:23Z jowenn $
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_gnu_java_lang_SystemClassLoader;
92 classinfo *class_java_lang_NoClassDefFoundError;
93 classinfo *class_java_lang_ClassNotFoundException;
94 classinfo *class_java_lang_LinkageError;
95 classinfo *class_java_lang_InstantiationException;
96 classinfo *class_java_lang_NoSuchMethodError;
97 classinfo *class_java_lang_NoSuchFieldError;
98 classinfo *class_java_lang_ClassFormatError;
99 classinfo *class_java_lang_IllegalArgumentException;
100 classinfo *class_java_lang_ArrayIndexOutOfBoundsException;
101 classinfo *class_java_lang_NoSuchFieldException;
102 classinfo *class_java_io_SyncFailedException;
103 classinfo *class_java_io_IOException;
104 classinfo *class_java_io_FileNotFoundException;
105 classinfo *class_java_io_UnixFileSystem;
106 classinfo *class_java_security_PrivilegedActionException;
107 classinfo *class_java_net_UnknownHostException;
108 classinfo *class_java_net_SocketException;
109 classinfo *class_java_lang_NoSuchMethodException;
110 classinfo *class_java_lang_Double;
111 classinfo *class_java_lang_Float;
112 classinfo *class_java_lang_Long;
113 classinfo *class_java_lang_Byte;
114 classinfo *class_java_lang_Short;
115 classinfo *class_java_lang_Boolean;
116 classinfo *class_java_lang_Void;
117 classinfo *class_java_lang_Character;
118 classinfo *class_java_lang_Integer;
120 /* the system classloader object */
121 struct java_lang_ClassLoader *SystemClassLoader = NULL;
123 /* for raising exceptions from native methods */
124 THREADSPECIFIC java_objectheader* _exceptionptr = NULL;
126 /************* use classinfo structure as java.lang.Class object **************/
128 void use_class_as_object(classinfo *c)
133 if (!class_java_lang_Class)
134 class_java_lang_Class = class_new(utf_new_char ("java/lang/Class"));
136 vt = class_java_lang_Class->vftbl;
139 if (!c->classvftbl) {
140 c->classvftbl = true;
142 /* copy_vftbl(&newtbl, vt);
143 newtbl->class = c->header.vftbl->class;
144 newtbl->baseval = c->header.vftbl->baseval;
145 newtbl->diffval = c->header.vftbl->diffval;
146 c->header.vftbl = newtbl;*/
148 c->header.vftbl = class_java_lang_Class->vftbl;
150 if (!class_java_lang_VMClass) {
151 loader_load_sysclass(&class_java_lang_VMClass,
152 utf_new_char("java/lang/VMClass"));
154 method_vmclass_init =
155 class_findmethod(class_java_lang_VMClass,
156 utf_new_char("<init>"),
157 utf_new_char("(Lgnu/classpath/RawData;)V"));
159 if (method_vmclass_init == 0) {
160 class_showmethods(class_java_lang_VMClass);
161 panic("Needed class initializer for VMClass could not be found");
165 java_objectheader *vmo = builtin_new(class_java_lang_VMClass);
167 if (!vmo) panic("Error while creating instance of java/lang/VMClass");
168 asm_calljavafunction(method_vmclass_init, vmo, c, NULL, NULL);
169 c->vmClass = (java_lang_VMClass *) vmo;
170 /*log_text("VMCLASS has been attached");*/
176 /*************************** include native methods ***************************/
179 #include "nat/GdkGraphics.c"
180 #include "nat/GtkComponentPeer.c"
181 #include "nat/GdkPixbufDecoder.c"
182 #include "nat/GtkScrollPanePeer.c"
183 #include "nat/GtkFileDialogPeer.c"
184 #include "nat/GtkLabelPeer.c"
188 /************************** tables for methods ********************************/
193 /* table for locating native methods */
194 static struct nativeref {
202 #include "nativetable.hh"
207 #define NATIVETABLESIZE (sizeof(nativetable)/sizeof(struct nativeref))
209 /* table for fast string comparison */
210 static struct nativecompref {
216 } nativecomptable [NATIVETABLESIZE];
218 /* string comparsion table initialized */
219 static bool nativecompdone = false;
222 /******************************************************************************/
223 /******************************************************************************/
224 #include "natcalls.h"
226 /* string call comparison table initialized */
228 /******************************************************************************/
229 /******************************************************************************/
231 /*--------------- native method calls & classes used -------------------------*/
235 /* throw some loader exceptions */
237 void throw_noclassdeffounderror_message(utf* classname)
239 if (!class_java_lang_NoClassDefFoundError) {
240 panic("java.lang.NoClassDefFoundError not found. Maybe wrong classpath?");
243 /* throws a NoClassDefFoundError with message */
244 *exceptionptr = native_new_and_init_string(class_java_lang_NoClassDefFoundError,
245 javastring_new(classname));
249 void throw_linkageerror_message(utf* classname)
251 if (!class_java_lang_LinkageError) {
252 panic("java.lang.LinkageError not found. Maybe wrong classpath?");
255 /* throws a LinkageError with message */
256 *exceptionptr = native_new_and_init_string(class_java_lang_LinkageError,
257 javastring_new(classname));
261 void throw_exception_message(char *classname, char *message)
263 classinfo *c = class_new(utf_new_char(classname));
268 *exceptionptr = native_new_and_init_string(c,
269 javastring_new_char(message));
273 /*********************** function: native_loadclasses **************************
275 load classes required for native methods
277 *******************************************************************************/
279 void native_loadclasses()
281 static int classesLoaded=0; /*temporary hack JoWenn*/
282 if (classesLoaded) return;
284 /* log_text("loadclasses entered");*/
287 /*class_java_lang_System =*/
288 (void) class_new(utf_new_char("java/lang/VMClass"));/*JoWenn*/
289 (void) class_new(utf_new_char("java/lang/Class"));/*JoWenn*/
291 /* class_new adds the class to the list of classes to be loaded */
292 if (!class_java_lang_Cloneable)
293 class_java_lang_Cloneable =
294 class_new(utf_new_char("java/lang/Cloneable"));
295 /* log_text("loadclasses: class_java_lang_Cloneable has been initialized");*/
296 class_java_lang_CloneNotSupportedException =
297 class_new(utf_new_char("java/lang/CloneNotSupportedException"));
298 if (!class_java_lang_Class)
299 class_java_lang_Class =
300 class_new(utf_new_char("java/lang/Class"));
301 class_java_io_IOException =
302 class_new(utf_new_char("java/io/IOException"));
303 class_java_io_FileNotFoundException =
304 class_new(utf_new_char("java/io/FileNotFoundException"));
305 class_java_lang_NoClassDefFoundError =
306 class_new(utf_new_char("java/lang/NoClassDefFoundError"));
307 class_java_lang_ClassNotFoundException =
308 class_new(utf_new_char("java/lang/ClassNotFoundException"));
309 class_java_lang_LinkageError =
310 class_new(utf_new_char("java/lang/LinkageError"));
311 class_java_lang_InstantiationException =
312 class_new(utf_new_char("java/lang/InstantiationException"));
313 class_java_lang_NoSuchMethodError =
314 class_new(utf_new_char("java/lang/NoSuchMethodError"));
315 class_java_lang_NoSuchFieldError =
316 class_new(utf_new_char("java/lang/NoSuchFieldError"));
317 class_java_lang_ClassFormatError =
318 class_new(utf_new_char("java/lang/ClassFormatError"));
319 class_java_io_SyncFailedException =
320 class_new(utf_new_char("java/io/SyncFailedException"));
322 /* log_text("native_loadclasses: class_new(\"java/lang/ClassLoader\")"); */
323 class_java_lang_ClassLoader =
324 class_new(utf_new_char("java/lang/ClassLoader"));
325 class_gnu_java_lang_SystemClassLoader =
326 class_new(utf_new_char("gnu/java/lang/SystemClassLoader"));
328 /* log_text("native_loadclasses: class_new(\"java/security/PrivilegedActionException\")"); */
329 class_java_security_PrivilegedActionException =
330 class_new(utf_new_char("java/security/PrivilegedActionException"));
332 loader_load_sysclass(&class_java_net_UnknownHostException,
333 utf_new_char("java/net/UnknownHostException"));
334 loader_load_sysclass(&class_java_net_SocketException,
335 utf_new_char("java/net/SocketException"));
337 class_java_lang_IllegalArgumentException =
338 class_new(utf_new_char("java/lang/IllegalArgumentException"));
339 class_java_lang_ArrayIndexOutOfBoundsException =
340 class_new(utf_new_char("java/lang/ArrayIndexOutOfBoundsException"));
341 class_java_lang_NoSuchFieldException =
342 class_new(utf_new_char("java/lang/NoSuchFieldException"));
343 class_java_lang_NoSuchMethodException =
344 class_new(utf_new_char("java/lang/NoSuchMethodException"));
346 /* load classes for wrapping primitive types */
347 class_java_lang_Double = class_new(utf_new_char("java/lang/Double"));
348 class_init(class_java_lang_Double);
350 class_java_lang_Float = class_new(utf_new_char("java/lang/Float"));
351 class_java_lang_Character = class_new(utf_new_char("java/lang/Character"));
352 class_java_lang_Integer = class_new(utf_new_char("java/lang/Integer"));
353 class_java_lang_Long = class_new(utf_new_char("java/lang/Long"));
354 class_java_lang_Byte = class_new(utf_new_char("java/lang/Byte"));
355 class_java_lang_Short = class_new(utf_new_char("java/lang/Short"));
356 class_java_lang_Boolean = class_new(utf_new_char("java/lang/Boolean"));
357 class_java_lang_Void = class_new(utf_new_char("java/lang/Void"));
363 /*************** adds a class to the vector of loaded classes ****************/
365 void systemclassloader_addclass(classinfo *c)
369 /* find method addClass of java.lang.ClassLoader */
370 m = class_resolvemethod(class_java_lang_ClassLoader,
371 utf_new_char("addClass"),
372 utf_new_char("(Ljava/lang/Class;)")
376 panic("warning: cannot initialize classloader");
378 /* prepare class to be passed as argument */
379 use_class_as_object (c);
381 /* call 'addClass' */
382 asm_calljavafunction(m,
383 (java_objectheader*) SystemClassLoader,
384 (java_objectheader*) c,
391 /*************** adds a library to the vector of loaded libraries *************/
393 void systemclassloader_addlibrary(java_objectheader *o)
395 log_text("systemclassloader_addlibrary");
399 /*****************************************************************************
401 create systemclassloader object and initialize instance fields
403 ******************************************************************************/
405 void init_systemclassloader()
407 if (!SystemClassLoader) {
408 native_loadclasses();
409 log_text("Initializing new system class loader");
410 /* create object and call initializer */
411 SystemClassLoader = (java_lang_ClassLoader*) native_new_and_init(class_gnu_java_lang_SystemClassLoader);/*class_java_lang_ClassLoader);*/
413 /* systemclassloader has no parent */
414 SystemClassLoader->parent = NULL;
415 SystemClassLoader->initialized = true;
417 log_text("leaving system class loader");
421 /********************* add loaded library name *******************************/
423 void systemclassloader_addlibname(java_objectheader *o)
428 m = class_resolvemethod(loader_load_sysclass(NULL, utf_new_char ("java/util/Vector")),
429 utf_new_char("addElement"),
430 utf_new_char("(Ljava/lang/Object;)V"));
432 if (!m) panic("cannot initialize classloader");
434 id = envTable.GetStaticFieldID(&env,
435 class_java_lang_ClassLoader,
436 "loadedLibraryNames",
437 "Ljava/util/Vector;");
439 if (!id) panic("can not access ClassLoader");
441 asm_calljavafunction(m,
442 envTable.GetStaticObjectField(&env, class_java_lang_ClassLoader, id),
449 /********************* function: native_setclasspath **************************/
451 void native_setclasspath(char *path)
453 /* set searchpath for classfiles */
458 /*********************** Function: native_findfunction *************************
460 Looks up a method (must have the same class name, method name, descriptor
461 and 'static'ness) and returns a function pointer to it.
462 Returns: function pointer or NULL (if there is no such method)
464 Remark: For faster operation, the names/descriptors are converted from C
465 strings to Unicode the first time this function is called.
467 *******************************************************************************/
469 functionptr native_findfunction(utf *cname, utf *mname,
470 utf *desc, bool isstatic)
473 /* entry of table for fast string comparison */
474 struct nativecompref *n;
475 /* for warning message if no function is found */
479 isstatic = isstatic ? true : false;
481 if (!nativecompdone) {
482 for (i = 0; i < NATIVETABLESIZE; i++) {
483 nativecomptable[i].classname =
484 utf_new_char(nativetable[i].classname);
485 nativecomptable[i].methodname =
486 utf_new_char(nativetable[i].methodname);
487 nativecomptable[i].descriptor =
488 utf_new_char(nativetable[i].descriptor);
489 nativecomptable[i].isstatic =
490 nativetable[i].isstatic;
491 nativecomptable[i].func =
494 nativecompdone = true;
499 utf_strlen(cname) + utf_strlen(mname) + utf_strlen(desc) + 64;
501 buffer = MNEW(char, buffer_len);
503 strcpy(buffer, "searching matching function in native table:");
504 utf_sprint(buffer+strlen(buffer), mname);
505 strcpy(buffer+strlen(buffer), ": ");
506 utf_sprint(buffer+strlen(buffer), desc);
507 strcpy(buffer+strlen(buffer), " for class ");
508 utf_sprint(buffer+strlen(buffer), cname);
512 MFREE(buffer, char, buffer_len);
515 for (i = 0; i < NATIVETABLESIZE; i++) {
516 n = &(nativecomptable[i]);
518 if (cname == n->classname && mname == n->methodname &&
519 desc == n->descriptor && isstatic == n->isstatic)
523 if (cname == n->classname && mname == n->methodname ) log_text("static and descriptor mismatch");
527 utf_strlen(n->classname) + utf_strlen(n->methodname) + utf_strlen(n->descriptor) + 64;
529 buffer = MNEW(char, buffer_len);
531 strcpy(buffer, "comparing with:");
532 utf_sprint(buffer+strlen(buffer), n->methodname);
533 strcpy (buffer+strlen(buffer), ": ");
534 utf_sprint(buffer+strlen(buffer), n->descriptor);
535 strcpy(buffer+strlen(buffer), " for class ");
536 utf_sprint(buffer+strlen(buffer), n->classname);
540 MFREE(buffer, char, buffer_len);
547 /* no function was found, display warning */
550 utf_strlen(cname) + utf_strlen(mname) + utf_strlen(desc) + 64;
552 buffer = MNEW(char, buffer_len);
554 strcpy(buffer, "warning: native function ");
555 utf_sprint(buffer + strlen(buffer), mname);
556 strcpy(buffer + strlen(buffer), ": ");
557 utf_sprint(buffer + strlen(buffer), desc);
558 strcpy(buffer + strlen(buffer), " not found in class ");
559 utf_sprint(buffer + strlen(buffer), cname);
563 MFREE(buffer, char, buffer_len);
567 /* keep compiler happy */
572 /********************** function: javastring_new *******************************
574 creates a new object of type java/lang/String with the text of
575 the specified utf8-string
577 return: pointer to the string or NULL if memory is exhausted.
579 *******************************************************************************/
581 /* java_objectheader *javastring_new(utf *u) */
582 java_lang_String *javastring_new(utf *u)
584 char *utf_ptr = u->text; /* current utf character in utf string */
585 int utflength = utf_strlen(u); /* length of utf-string if uncompressed */
586 java_lang_String *s; /* result-string */
590 /* log_text("javastring_new");*/
592 s = (java_lang_String*) builtin_new(class_java_lang_String);
593 a = builtin_newarray_char(utflength);
595 /* javastring or character-array could not be created */
599 /* decompress utf-string */
600 for (i = 0; i < utflength; i++)
601 a->data[i] = utf_nextu2(&utf_ptr);
603 /* set fields of the javastring-object */
606 s->count = utflength;
608 /* return (java_objectheader*) s; */
613 /********************** function: javastring_new_char **************************
615 creates a new java/lang/String object which contains the convertet
616 C-string passed via text.
618 return: the object pointer or NULL if memory is exhausted.
620 *******************************************************************************/
622 /* java_objectheader *javastring_new_char (char *text) */
623 java_lang_String *javastring_new_char (char *text)
626 s4 len = strlen(text); /* length of the string */
627 java_lang_String *s; /* result-string */
630 /*log_text("javastring_new_char");*/
631 s = (java_lang_String*) builtin_new(class_java_lang_String);
632 a = builtin_newarray_char(len);
634 /* javastring or character-array could not be created */
639 for (i = 0; i < len; i++)
640 a->data[i] = text[i];
642 /* set fields of the javastring-object */
647 /* return (java_objectheader*) s; */
652 /************************* function javastring_tochar **************************
654 converts a Java string into a C string.
656 return: pointer to C string
658 Caution: every call of this function overwrites the previous string !!!
660 *******************************************************************************/
662 static char stringbuffer[MAXSTRINGSIZE];
664 char *javastring_tochar(java_objectheader *so)
666 java_lang_String *s = (java_lang_String *) so;
678 if (s->count > MAXSTRINGSIZE)
681 for (i = 0; i < s->count; i++)
682 stringbuffer[i] = a->data[s->offset + i];
684 stringbuffer[i] = '\0';
690 /****************** function class_findfield_approx ****************************
692 searches in 'classinfo'-structure for a field with the
695 *******************************************************************************/
697 fieldinfo *class_findfield_approx(classinfo *c, utf *name)
700 for (i = 0; i < c->fieldscount; i++) {
701 /* compare field names */
702 if ((c->fields[i].name == name))
703 return &(c->fields[i]);
706 /* field was not found, raise exception */
707 *exceptionptr = native_new_and_init(class_java_lang_NoSuchFieldException);
712 s4 class_findfield_index_approx (classinfo *c, utf *name)
715 for (i = 0; i < c->fieldscount; i++) {
716 /* compare field names */
717 if ((c->fields[i].name == name))
721 /* field was not found, raise exception */
722 *exceptionptr = native_new_and_init(class_java_lang_NoSuchFieldException);
727 /********************** function: native_new_and_init *************************
729 Creates a new object on the heap and calls the initializer.
730 Returns the object pointer or NULL if memory is exhausted.
732 *******************************************************************************/
734 java_objectheader *native_new_and_init(classinfo *c)
737 java_objectheader *o;
739 /* if c==NULL it is probebly because loader_load failed */
740 if (!c) return *exceptionptr;
742 o = builtin_new(c); /* create object */
745 printf("native_new_and_init ");
746 utf_display(c->name);
750 /* printf("o!=NULL\n"); */
751 /* find initializer */
753 m = class_findmethod(c, utf_new_char("<init>"), utf_new_char("()V"));
755 if (!m) { /* initializer not found */
757 char logtext[MAXLOGTEXT];
758 sprintf(logtext, "Warning: class has no instance-initializer: ");
759 utf_sprint(logtext + strlen(logtext), c->name);
765 /* call initializer */
767 asm_calljavafunction(m, o, NULL, NULL, NULL);
773 java_objectheader *native_new_and_init_string(classinfo *c, java_lang_String *s)
776 java_objectheader *o;
778 /* if c==NULL it is probebly because loader_load failed */
779 if (!c) return *exceptionptr;
781 o = builtin_new(c); /* create object */
785 /* find initializer */
787 m = class_findmethod(c,
788 utf_new_char("<init>"),
789 utf_new_char("(Ljava/lang/String;)V"));
791 if (!m) { /* initializer not found */
793 char logtext[MAXLOGTEXT];
794 sprintf(logtext, "Warning: class has no instance-initializer: ");
795 utf_sprint(logtext + strlen(logtext), c->name);
801 /* call initializer */
803 asm_calljavafunction(m, o, s, NULL, NULL);
809 /******************** function: stringtable_update ****************************
811 traverses the javastring hashtable and sets the vftbl-entries of
812 javastrings which were temporarily set to NULL, because
813 java.lang.Object was not yet loaded
815 *******************************************************************************/
817 void stringtable_update ()
819 java_lang_String *js;
821 literalstring *s; /* hashtable entry */
824 for (i = 0; i < string_hash.size; i++) {
825 s = string_hash.ptr[i];
829 js = (java_lang_String *) s->string;
831 if (!js || !js->value)
832 /* error in hashtable found */
833 panic("invalid literalstring in hashtable");
837 if (!js->header.vftbl)
838 /* vftbl of javastring is NULL */
839 js->header.vftbl = class_java_lang_String -> vftbl;
841 if (!a->header.objheader.vftbl)
842 /* vftbl of character-array is NULL */
843 a->header.objheader.vftbl = primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl;
845 /* follow link in external hash chain */
853 /************************* function: u2_utflength ***************************
855 returns the utf length in bytes of a u2 array
857 *****************************************************************************/
859 u4 u2_utflength(u2 *text, u4 u2_length)
861 u4 result_len = 0; /* utf length in bytes */
862 u2 ch; /* current unicode character */
865 for (len = 0; len < u2_length; len++) {
866 /* next unicode character */
869 /* determine bytes required to store unicode character as utf */
870 if (ch && (ch < 0x80))
882 /********************* function: utf_new_u2 ***********************************
884 make utf symbol from u2 array,
885 if isclassname is true '.' is replaced by '/'
887 *******************************************************************************/
889 utf *utf_new_u2(u2 *unicode_pos, u4 unicode_length, bool isclassname)
891 char *buffer; /* memory buffer for unicode characters */
892 char *pos; /* pointer to current position in buffer */
893 u4 left; /* unicode characters left */
894 u4 buflength; /* utf length in bytes of the u2 array */
895 utf *result; /* resulting utf-string */
898 /* determine utf length in bytes and allocate memory */
899 /* printf("utf_new_u2: unicode_length=%d\n",unicode_length); */
900 buflength = u2_utflength(unicode_pos, unicode_length);
901 buffer = MNEW(char, buflength);
903 /* memory allocation failed */
905 printf("length: %d\n",buflength);
906 log_text("utf_new_u2:buffer==NULL");
912 for (i = 0; i++ < unicode_length; unicode_pos++) {
913 /* next unicode character */
916 if ((c != 0) && (c < 0x80)) {
919 if ((int) left < 0) break;
920 /* convert classname */
921 if (isclassname && c == '.')
926 } else if (c < 0x800) {
928 unsigned char high = c >> 6;
929 unsigned char low = c & 0x3F;
931 if ((int) left < 0) break;
932 *pos++ = high | 0xC0;
938 char mid = (c >> 6) & 0x3F;
941 if ((int) left < 0) break;
942 *pos++ = high | 0xE0;
948 /* insert utf-string into symbol-table */
949 result = utf_new(buffer,buflength);
951 MFREE(buffer, char, buflength);
957 /********************* function: javastring_toutf *****************************
959 make utf symbol from javastring
961 *******************************************************************************/
963 utf *javastring_toutf(java_lang_String *string, bool isclassname)
965 java_lang_String *str = (java_lang_String *) string;
967 /* printf("javastring_toutf offset: %d, len %d\n",str->offset, str->count); */
968 /* fflush(stdout); */
970 return utf_new_u2(str->value->data + str->offset, str->count, isclassname);
974 /********************* function: literalstring_u2 *****************************
976 searches for the javastring with the specified u2-array in
977 the string hashtable, if there is no such string a new one is
980 if copymode is true a copy of the u2-array is made
982 *******************************************************************************/
984 java_objectheader *literalstring_u2(java_chararray *a, u4 length, u4 offset,
987 literalstring *s; /* hashtable element */
988 java_lang_String *js; /* u2-array wrapped in javastring */
989 java_chararray *stringdata; /* copy of u2-array */
994 //#define DEBUG_LITERALSTRING_U2
995 #ifdef DEBUG_LITERALSTRING_U2
996 printf("literalstring_u2: length=%d, offset=%d\n", length, offset);
1000 /* find location in hashtable */
1001 key = unicode_hashkey(a->data + offset, length);
1002 slot = key & (string_hash.size - 1);
1003 s = string_hash.ptr[slot];
1006 js = (java_lang_String *) s->string;
1008 if (length == js->count) {
1010 for (i = 0; i < length; i++) {
1011 if (a->data[offset + i] != js->value->data[i])
1015 /* string already in hashtable, free memory */
1017 lit_mem_free(a, sizeof(java_chararray) + sizeof(u2) * (length - 1) + 10);
1019 #ifdef DEBUG_LITERALSTRING_U2
1020 printf("literalstring_u2: foundentry at %p\n", js);
1021 utf_display(javastring_toutf(js, 0));
1025 return (java_objectheader *) js;
1029 /* follow link in external hash chain */
1034 /* create copy of u2-array for new javastring */
1035 u4 arraysize = sizeof(java_chararray) + sizeof(u2) * (length - 1) + 10;
1036 stringdata = lit_mem_alloc(arraysize);
1037 /* memcpy(stringdata, a, arraysize); */
1038 memcpy(&(stringdata->header), &(a->header), sizeof(java_arrayheader));
1039 memcpy(&(stringdata->data), &(a->data) + offset, sizeof(u2) * (length - 1) + 10);
1045 /* location in hashtable found, complete arrayheader */
1046 stringdata->header.objheader.vftbl = primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl;
1047 stringdata->header.size = length;
1049 /* create new javastring */
1050 js = LNEW(java_lang_String);
1051 js->header.vftbl = class_java_lang_String->vftbl;
1052 js->value = stringdata;
1056 /* create new literalstring */
1057 s = NEW(literalstring);
1058 s->hashlink = string_hash.ptr[slot];
1059 s->string = (java_objectheader *) js;
1060 string_hash.ptr[slot] = s;
1062 /* update numbe of hashtable entries */
1063 string_hash.entries++;
1065 /* reorganization of hashtable */
1066 if (string_hash.entries > (string_hash.size * 2)) {
1067 /* reorganization of hashtable, average length of
1068 the external chains is approx. 2 */
1072 hashtable newhash; /* the new hashtable */
1074 /* create new hashtable, double the size */
1075 init_hashtable(&newhash, string_hash.size * 2);
1076 newhash.entries = string_hash.entries;
1078 /* transfer elements to new hashtable */
1079 for (i = 0; i < string_hash.size; i++) {
1080 s = string_hash.ptr[i];
1082 literalstring *nexts = s->hashlink;
1083 js = (java_lang_String *) s->string;
1084 slot = unicode_hashkey(js->value->data, js->count) & (newhash.size - 1);
1086 s->hashlink = newhash.ptr[slot];
1087 newhash.ptr[slot] = s;
1089 /* follow link in external hash chain */
1094 /* dispose old table */
1095 MFREE(string_hash.ptr, void*, string_hash.size);
1096 string_hash = newhash;
1099 #ifdef DEBUG_LITERALSTRING_U2
1100 printf("literalstring_u2: newly created at %p\n", js);
1101 utf_display(javastring_toutf(js, 0));
1106 return (java_objectheader *) js;
1110 /******************** Function: literalstring_new *****************************
1112 creates a new javastring with the text of the utf-symbol
1113 and inserts it into the string hashtable
1115 *******************************************************************************/
1117 java_objectheader *literalstring_new(utf *u)
1119 char *utf_ptr = u->text; /* pointer to current unicode character in utf string */
1120 u4 utflength = utf_strlen(u); /* length of utf-string if uncompressed */
1121 java_chararray *a; /* u2-array constructed from utf string */
1123 /* log_text("literalstring_new"); */
1124 /* utf_display(u);*/
1125 /*if (utflength==0) while (1) sleep(60);*/
1126 /* log_text("------------------"); */
1127 /* allocate memory */
1128 a = lit_mem_alloc(sizeof(java_chararray) + sizeof(u2) * (utflength - 1) + 10);
1130 /* convert utf-string to u2-array */
1131 for (i = 0; i < utflength; i++)
1132 a->data[i] = utf_nextu2(&utf_ptr);
1134 return literalstring_u2(a, utflength, 0, false);
1138 /********************** function: literalstring_free **************************
1140 removes a javastring from memory
1142 ******************************************************************************/
1144 void literalstring_free(java_objectheader* sobj)
1146 java_lang_String *s = (java_lang_String *) sobj;
1147 java_chararray *a = s->value;
1149 log_text("literalstring_free called");
1151 /* dispose memory of java.lang.String object */
1152 LFREE(s, java_lang_String);
1154 /* dispose memory of java-characterarray */
1155 LFREE(a, sizeof(java_chararray) + sizeof(u2) * (a->header.size - 1)); /* +10 ?? */
1159 void copy_vftbl(vftbl **dest, vftbl *src)
1163 /* XXX this kind of copying does not work (in the general
1164 * case). The interface tables would have to be copied, too. I
1165 * don't see why we should make a copy anyway. -Edwin
1167 *dest = mem_alloc(sizeof(vftbl) + sizeof(methodptr)*(src->vftbllength-1));
1168 memcpy(*dest, src, sizeof(vftbl) - sizeof(methodptr));
1169 memcpy(&(*dest)->table, &src->table, src->vftbllength * sizeof(methodptr));
1174 /******************************************************************************************
1176 creates method signature (excluding return type) from array of
1177 class-objects representing the parameters of the method
1179 *******************************************************************************************/
1182 utf *create_methodsig(java_objectarray* types, char *retType)
1184 char *buffer; /* buffer for building the desciptor */
1185 char *pos; /* current position in buffer */
1186 utf *result; /* the method signature */
1187 u4 buffer_size = 3; /* minimal size=3: room for parenthesis and returntype */
1190 if (!types) return NULL;
1192 /* determine required buffer-size */
1193 for (i = 0; i < types->header.size; i++) {
1194 classinfo *c = (classinfo *) types->data[i];
1195 buffer_size = buffer_size + c->name->blength + 2;
1198 if (retType) buffer_size += strlen(retType);
1200 /* allocate buffer */
1201 buffer = MNEW(u1, buffer_size);
1204 /* method-desciptor starts with parenthesis */
1207 for (i = 0; i < types->header.size; i++) {
1210 /* current argument */
1211 classinfo *c = (classinfo *) types->data[i];
1213 /* current position in utf-text */
1214 char *utf_ptr = c->name->text;
1216 /* determine type of argument */
1217 if ((ch = utf_nextu2(&utf_ptr)) == '[') {
1219 for (utf_ptr--; utf_ptr < utf_end(c->name); utf_ptr++) {
1220 *pos++ = *utf_ptr; /* copy text */
1224 /* check for primitive types */
1225 for (j = 0; j < PRIMITIVETYPE_COUNT; j++) {
1226 char *utf_pos = utf_ptr - 1;
1227 char *primitive = primitivetype_table[j].wrapname;
1230 while (utf_pos < utf_end(c->name)) {
1231 if (*utf_pos++ != *primitive++) goto nomatch;
1234 /* primitive type found */
1235 *pos++ = primitivetype_table[j].typesig;
1241 /* no primitive type and no arrayclass, so must be object */
1245 for (utf_ptr--; utf_ptr < utf_end(c->name); utf_ptr++) {
1258 for (i = 0; i < strlen(retType); i++) {
1259 *pos++ = retType[i];
1263 /* create utf-string */
1264 result = utf_new(buffer, (pos - buffer));
1265 MFREE(buffer, u1, buffer_size);
1271 /******************************************************************************************
1273 retrieve the next argument or returntype from a descriptor
1274 and return the corresponding class
1276 *******************************************************************************************/
1278 classinfo *get_type(char **utf_ptr,char *desc_end, bool skip)
1280 classinfo *c = class_from_descriptor(*utf_ptr,desc_end,utf_ptr,
1281 (skip) ? CLASSLOAD_SKIP : CLASSLOAD_LOAD);
1284 panic("illegal descriptor");
1286 if (skip) return NULL;
1288 use_class_as_object(c);
1293 /******************************************************************************************
1295 use the descriptor of a method to generate a java/lang/Class array
1296 which contains the classes of the parametertypes of the method
1298 *******************************************************************************************/
1300 java_objectarray* get_parametertypes(methodinfo *m)
1302 utf *descr = m->descriptor; /* method-descriptor */
1303 char *utf_ptr = descr->text; /* current position in utf-text */
1304 char *desc_end = utf_end(descr); /* points behind utf string */
1305 java_objectarray* result;
1306 int parametercount = 0;
1310 utf_nextu2(&utf_ptr);
1312 /* determine number of parameters */
1313 while ( *utf_ptr != ')' ) {
1314 get_type(&utf_ptr,desc_end,true);
1318 /* create class-array */
1319 result = builtin_anewarray(parametercount, class_java_lang_Class);
1321 utf_ptr = descr->text;
1322 utf_nextu2(&utf_ptr);
1324 /* get returntype classes */
1325 for (i = 0; i < parametercount; i++)
1326 result->data[i] = (java_objectheader *) get_type(&utf_ptr,desc_end, false);
1335 /******************************************************************************************
1337 get the exceptions which can be thrown by a method
1339 *******************************************************************************************/
1341 java_objectarray* get_exceptiontypes(methodinfo *m)
1349 /******************************************************************************************
1351 get the returntype class of a method
1353 *******************************************************************************************/
1355 classinfo *get_returntype(methodinfo *m)
1357 char *utf_ptr; /* current position in utf-text */
1358 char *desc_end; /* points behind utf string */
1359 utf *desc = m->descriptor; /* method-descriptor */
1361 utf_ptr = desc->text;
1362 desc_end = utf_end(desc);
1364 /* ignore parametertypes */
1365 while ((utf_ptr<desc_end) && utf_nextu2(&utf_ptr)!=')')
1368 return get_type(&utf_ptr,desc_end, false);
1372 /*****************************************************************************/
1373 /*****************************************************************************/
1376 /*--------------------------------------------------------*/
1377 void printNativeCall(nativeCall nc) {
1380 printf("\n%s's Native Methods call:\n",nc.classname); fflush(stdout);
1381 for (i=0; i<nc.methCnt; i++) {
1382 printf("\tMethod=%s %s\n",nc.methods[i].methodname, nc.methods[i].descriptor);fflush(stdout);
1384 for (j=0; j<nc.callCnt[i]; j++) {
1385 printf("\t\t<%i,%i>aCalled = %s %s %s\n",i,j,
1386 nc.methods[i].methodCalls[j].classname,
1387 nc.methods[i].methodCalls[j].methodname,
1388 nc.methods[i].methodCalls[j].descriptor);fflush(stdout);
1391 printf("-+++++--------------------\n");fflush(stdout);
1394 /*--------------------------------------------------------*/
1395 void printCompNativeCall(nativeCompCall nc) {
1397 printf("printCompNativeCall BEGIN\n");fflush(stdout);
1398 printf("\n%s's Native Comp Methods call:\n",nc.classname->text);fflush(stdout);
1399 utf_display(nc.classname); fflush(stdout);
1401 for (i=0; i<nc.methCnt; i++) {
1402 printf("\tMethod=%s %s\n",nc.methods[i].methodname->text,nc.methods[i].descriptor->text);fflush(stdout);
1403 utf_display(nc.methods[i].methodname); fflush(stdout);
1404 utf_display(nc.methods[i].descriptor);fflush(stdout);
1405 printf("\n");fflush(stdout);
1407 for (j=0; j<nc.callCnt[i]; j++) {
1408 printf("\t\t<%i,%i>bCalled = ",i,j);fflush(stdout);
1409 utf_display(nc.methods[i].methodCalls[j].classname);fflush(stdout);
1410 utf_display(nc.methods[i].methodCalls[j].methodname); fflush(stdout);
1411 utf_display(nc.methods[i].methodCalls[j].descriptor);fflush(stdout);
1412 printf("\n");fflush(stdout);
1415 printf("---------------------\n");fflush(stdout);
1419 /*--------------------------------------------------------*/
1420 classMeth findNativeMethodCalls(utf *c, utf *m, utf *d )
1433 /*--------------------------------------------------------*/
1434 nativeCall* findNativeClassCalls(char *aclassname ) {
1437 for (i=0;i<NATIVECALLSSIZE; i++) {
1438 /* convert table to utf later to speed up search */
1439 if (strcmp(nativeCalls[i].classname, aclassname) == 0)
1440 return &nativeCalls[i];
1445 /*--------------------------------------------------------*/
1446 /*--------------------------------------------------------*/
1447 void utfNativeCall(nativeCall nc, nativeCompCall *ncc) {
1451 ncc->classname = utf_new_char(nc.classname);
1452 ncc->methCnt = nc.methCnt;
1454 for (i=0; i<nc.methCnt; i++) {
1455 ncc->methods[i].methodname = utf_new_char(nc.methods[i].methodname);
1456 ncc->methods[i].descriptor = utf_new_char(nc.methods[i].descriptor);
1457 ncc->callCnt[i] = nc.callCnt[i];
1459 for (j=0; j<nc.callCnt[i]; j++) {
1461 ncc->methods[i].methodCalls[j].classname = utf_new_char(nc.methods[i].methodCalls[j].classname);
1463 if (strcmp("", nc.methods[i].methodCalls[j].methodname) != 0) {
1464 ncc->methods[i].methodCalls[j].methodname = utf_new_char(nc.methods[i].methodCalls[j].methodname);
1465 ncc->methods[i].methodCalls[j].descriptor = utf_new_char(nc.methods[i].methodCalls[j].descriptor);
1468 ncc->methods[i].methodCalls[j].methodname = NULL;
1469 ncc->methods[i].methodCalls[j].descriptor = NULL;
1477 /*--------------------------------------------------------*/
1479 bool natcall2utf(bool natcallcompdone) {
1482 if (natcallcompdone)
1485 for (i=0;i<NATIVECALLSSIZE; i++) {
1486 utfNativeCall (nativeCalls[i], &nativeCompCalls[i]);
1492 /*--------------------------------------------------------*/
1495 java_objectarray *builtin_asm_createclasscontextarray(classinfo **end,classinfo **start) {
1496 #warning platform dependend
1497 java_objectarray *tmpArray;
1499 classinfo **current;
1501 size_t size=(((size_t)start)-((size_t)end)) / sizeof (classinfo*);
1502 printf("end %p, start %p, size %ld\n",end,start,size);
1503 if (!class_java_lang_Class)
1504 class_java_lang_Class = class_new(utf_new_char ("java/lang/Class"));
1505 tmpArray=builtin_newarray(size, class_array_of(class_java_lang_Class)->vftbl);
1507 for(i=0,current=start;i<size;i++,current--) {
1510 utf_display(c->name);
1511 use_class_as_object(c);
1512 tmpArray->data[i]=c;
1518 java_lang_ClassLoader *builtin_asm_getclassloader(classinfo **end,classinfo **start) {
1519 #warning platform dependend
1521 classinfo **current;
1523 classinfo *privilegedAction;
1524 size_t size=(((size_t)start)-((size_t)end)) / sizeof (classinfo*);
1525 log_text("builtin_asm_getclassloader");
1526 printf("end %p, start %p, size %ld\n",end,start,size);
1528 privilegedAction=class_new(utf_new_char("java/security/PrivilegedAction"));
1530 for(i=0,current=start;i<size;i++,current--) {
1532 if (c==privilegedAction) return NULL;
1533 if (c->classloader) return c->classloader;
1541 log_text("Java_java_lang_VMSecurityManager_currentClassLoader");
1542 init_systemclassloader();
1544 return SystemClassLoader;*/
1548 * These are local overrides for various environment variables in Emacs.
1549 * Please do not remove this and leave it at the end of the file, where
1550 * Emacs will automagically detect them.
1551 * ---------------------------------------------------------------------
1554 * indent-tabs-mode: t