+
+
+u4 get_parametercount(methodinfo *m)
+{
+ utf *descr = m->descriptor; /* method-descriptor */
+ char *utf_ptr = descr->text; /* current position in utf-text */
+ char *desc_end = utf_end(descr); /* points behind utf string */
+ u4 parametercount = 0;
+
+ /* skip '(' */
+ utf_nextu2(&utf_ptr);
+
+ /* determine number of parameters */
+ while (*utf_ptr != ')') {
+ get_type(&utf_ptr, desc_end, true);
+ parametercount++;
+ }
+
+ return parametercount;
+}
+
+
+
+void fill_callblock(void *obj, utf *descr, jni_callblock blk[], va_list data, char ret)
+{
+ char *utf__ptr = descr->text; /* current position in utf-text */
+ char **utf_ptr = &utf__ptr;
+ char *desc_end = utf_end(descr); /* points behind utf string */
+ int cnt;
+ u4 dummy;
+ char c;
+
+ /*
+ log_text("fill_callblock");
+ utf_display(descr);
+ log_text("====");
+ */
+ /* skip '(' */
+ utf_nextu2(utf_ptr);
+
+ /* determine number of parameters */
+ if (obj) {
+ blk[0].itemtype = TYPE_ADR;
+ blk[0].item = PTR_TO_ITEM(obj);
+ cnt = 1;
+ } else cnt = 0;
+
+ while (**utf_ptr != ')') {
+ if (*utf_ptr >= desc_end)
+ panic("illegal method descriptor");
+
+ switch (utf_nextu2(utf_ptr)) {
+ /* primitive types */
+ case 'B':
+ case 'C':
+ case 'S':
+ case 'Z':
+ blk[cnt].itemtype = TYPE_INT;
+ blk[cnt].item = (u8) va_arg(data, int);
+ break;
+
+ case 'I':
+ blk[cnt].itemtype = TYPE_INT;
+ dummy = va_arg(data, u4);
+ /*printf("fill_callblock: pos:%d, value:%d\n",cnt,dummy);*/
+ blk[cnt].item = (u8) dummy;
+ break;
+
+ case 'J':
+ blk[cnt].itemtype = TYPE_LNG;
+ blk[cnt].item = (u8) va_arg(data, jlong);
+ break;
+
+ case 'F':
+ blk[cnt].itemtype = TYPE_FLT;
+ *((jfloat *) (&blk[cnt].item)) = (jfloat) va_arg(data, jdouble);
+ break;
+
+ case 'D':
+ blk[cnt].itemtype = TYPE_DBL;
+ *((jdouble *) (&blk[cnt].item)) = (jdouble) va_arg(data, jdouble);
+ break;
+
+ case 'V':
+ panic ("V not allowed as function parameter");
+ break;
+
+ case 'L':
+ while (utf_nextu2(utf_ptr) != ';')
+ blk[cnt].itemtype = TYPE_ADR;
+ blk[cnt].item = PTR_TO_ITEM(va_arg(data, void*));
+ break;
+
+ case '[':
+ {
+ /* XXX */
+ /* arrayclass */
+/* char *start = *utf_ptr; */
+ char ch;
+ while ((ch = utf_nextu2(utf_ptr)) == '[')
+ if (ch == 'L') {
+ while (utf_nextu2(utf_ptr) != ';') {}
+ }
+
+ ch = utf_nextu2(utf_ptr);
+ blk[cnt].itemtype = TYPE_ADR;
+ blk[cnt].item = PTR_TO_ITEM(va_arg(data, void*));
+ break;
+ }
+ }
+ cnt++;
+ }
+
+ /*the standard doesn't say anything about return value checking, but it appears to be usefull*/
+ c = utf_nextu2(utf_ptr);
+ c = utf_nextu2(utf_ptr);
+ /*printf("%c %c\n",ret,c);*/
+ if (ret == 'O') {
+ if (!((c == 'L') || (c == '[')))
+ log_text("\n====\nWarning call*Method called for function with wrong return type\n====");
+ } else if (ret != c)
+ log_text("\n====\nWarning call*Method called for function with wrong return type\n====");
+}
+
+
+/* XXX it could be considered if we should do typechecking here in the future */
+char fill_callblock_objA(void *obj, utf *descr, jni_callblock blk[], java_objectarray* params)
+{
+ char *utf__ptr = descr->text; /* current position in utf-text */
+ char **utf_ptr = &utf__ptr;
+ char *desc_end = utf_end(descr); /* points behind utf string */
+
+ jobject param;
+ int cnt;
+ int cnts;
+ char c;
+
+#if defined(USE_THREADS) && !defined(NATIVE_THREADS)
+ intsDisable();
+#endif
+ if (utf_char==0) {
+ utf_char=utf_new_char("java/lang/Character");
+ utf_bool=utf_new_char("java/lang/Boolean");
+ utf_byte=utf_new_char("java/lang/Byte");
+ utf_short=utf_new_char("java/lang/Short");
+ utf_int=utf_new_char("java/lang/Integer");
+ utf_long=utf_new_char("java/lang/Long");
+ utf_float=utf_new_char("java/lang/Float");
+ utf_double=utf_new_char("java/lang/Double");
+ }
+#if defined(USE_THREADS) && !defined(NATIVE_THREADS)
+ intsRestore();
+#endif
+
+ /*
+ log_text("fill_callblock");
+ utf_display(descr);
+ log_text("====");
+ */
+ /* skip '(' */
+ utf_nextu2(utf_ptr);
+
+ /* determine number of parameters */
+ if (obj) {
+ blk[0].itemtype = TYPE_ADR;
+ blk[0].item = PTR_TO_ITEM(obj);
+ cnt=1;
+
+ } else {
+ cnt = 0;
+ }
+
+ cnts = 0;
+ while (**utf_ptr != ')') {
+ if (*utf_ptr >= desc_end)
+ panic("illegal method descriptor");
+
+ /* primitive types */
+ switch (utf_nextu2(utf_ptr)) {
+ case 'B':
+ param = params->data[cnts];
+ if (param == 0) {
+ *exceptionptr = new_exception("java/lang/IllegalArgumentException");
+ return 0;
+ }
+ if (param->vftbl->class->name == utf_byte) {
+ blk[cnt].itemtype = TYPE_INT;
+ blk[cnt].item = (u8) ((java_lang_Byte *) param)->value;
+
+ } else {
+ *exceptionptr = new_exception("java/lang/IllegalArgumentException");
+ return 0;
+ }
+ break;
+
+ case 'C':
+ param = params->data[cnts];
+ if (param == 0) {
+ *exceptionptr = new_exception("java/lang/IllegalArgumentException");
+ return 0;
+ }
+ if (param->vftbl->class->name == utf_char) {
+ blk[cnt].itemtype = TYPE_INT;
+ blk[cnt].item = (u8) ((java_lang_Character *) param)->value;
+
+ } else {
+ *exceptionptr = new_exception("java/lang/IllegalArgumentException");
+ return 0;
+ }
+ break;
+
+ case 'S':
+ param = params->data[cnts];
+ if (param == 0) {
+ *exceptionptr = new_exception("java/lang/IllegalArgumentException");
+ return 0;
+ }
+ if (param->vftbl->class->name == utf_short) {
+ blk[cnt].itemtype = TYPE_INT;
+ blk[cnt].item = (u8) ((java_lang_Short *) param)->value;
+
+ } else {
+ if (param->vftbl->class->name == utf_byte) {
+ blk[cnt].itemtype = TYPE_INT;
+ blk[cnt].item = (u8) ((java_lang_Byte *) param)->value;
+
+ } else {
+ *exceptionptr = new_exception("java/lang/IllegalArgumentException");
+ return 0;
+ }
+ }
+ break;
+
+ case 'Z':
+ param = params->data[cnts];
+ if (param == 0) {
+ *exceptionptr = new_exception("java/lang/IllegalArgumentException");
+ return 0;
+ }
+ if (param->vftbl->class->name == utf_bool) {
+ blk[cnt].itemtype = TYPE_INT;
+ blk[cnt].item = (u8) ((java_lang_Boolean *) param)->value;
+
+ } else {
+ *exceptionptr = new_exception("java/lang/IllegalArgumentException");
+ return 0;
+ }
+ break;
+
+ case 'I':
+ /*log_text("fill_callblock_objA: param 'I'");*/
+ param = params->data[cnts];
+ if (param == 0) {
+ *exceptionptr = new_exception("java/lang/IllegalArgumentException");
+ return 0;
+ }
+ if (param->vftbl->class->name == utf_int) {
+ blk[cnt].itemtype = TYPE_INT;
+ blk[cnt].item = (u8) ((java_lang_Integer *) param)->value;
+ /*printf("INT VALUE :%d\n",((struct java_lang_Integer * )param)->value);*/
+ } else {
+ if (param->vftbl->class->name == utf_short) {
+ blk[cnt].itemtype = TYPE_INT;
+ blk[cnt].item = (u8) ((java_lang_Short *) param)->value;
+
+ } else {
+ if (param->vftbl->class->name == utf_byte) {
+ blk[cnt].itemtype = TYPE_INT;
+ blk[cnt].item = (u8) ((java_lang_Byte *) param)->value;
+
+ } else {
+ *exceptionptr = new_exception("java/lang/IllegalArgumentException");
+ return 0;
+ }
+ }
+ }
+ break;
+
+ case 'J':
+ param = params->data[cnts];
+ if (param == 0) {
+ *exceptionptr = new_exception("java/lang/IllegalArgumentException");
+ return 0;
+ }
+ if (param->vftbl->class->name == utf_long) {
+ blk[cnt].itemtype = TYPE_LNG;
+ blk[cnt].item = (u8) ((java_lang_Long *) param)->value;
+
+ } else {
+ if (param->vftbl->class->name == utf_int) {
+ blk[cnt].itemtype = TYPE_LNG;
+ blk[cnt].item = (u8) ((java_lang_Integer *) param)->value;
+
+ } else {
+ if (param->vftbl->class->name == utf_short) {
+ blk[cnt].itemtype = TYPE_LNG;
+ blk[cnt].item = (u8) ((java_lang_Short *) param)->value;
+
+ } else {
+ if (param->vftbl->class->name == utf_byte) {
+ blk[cnt].itemtype = TYPE_LNG;
+ blk[cnt].item = (u8) ((java_lang_Byte *) param)->value;
+ } else {
+ *exceptionptr = new_exception("java/lang/IllegalArgumentException");
+ return 0;
+ }
+ }
+ }
+
+ }
+ break;
+
+ case 'F':
+ param = params->data[cnts];
+ if (param == 0) {
+ *exceptionptr = new_exception("java/lang/IllegalArgumentException");
+ return 0;
+ }
+
+ if (param->vftbl->class->name == utf_float) {
+ blk[cnt].itemtype = TYPE_FLT;
+ *((jfloat *) (&blk[cnt].item)) = (jfloat) ((java_lang_Float *) param)->value;
+
+ } else {
+ *exceptionptr = new_exception("java/lang/IllegalArgumentException");
+ return 0;
+ }
+ break;
+
+ case 'D':
+ param = params->data[cnts];
+ if (param == 0) {
+ *exceptionptr = new_exception("java/lang/IllegalArgumentException");
+ return 0;
+ }
+
+ if (param->vftbl->class->name == utf_double) {
+ blk[cnt].itemtype = TYPE_DBL;
+ *((jdouble *) (&blk[cnt].item)) = (jdouble) ((java_lang_Float *) param)->value;
+
+ } else {
+ if (param->vftbl->class->name == utf_float) {
+ blk[cnt].itemtype = TYPE_DBL;
+ *((jdouble *) (&blk[cnt].item)) = (jdouble) ((java_lang_Float *) param)->value;
+
+ } else {
+ *exceptionptr = new_exception("java/lang/IllegalArgumentException");
+ return 0;
+ }
+ }
+ break;
+
+ case 'V':
+ panic("V not allowed as function parameter");
+ break;
+
+ case 'L':
+ {
+ char *start = (*utf_ptr) - 1;
+ char *end = NULL;
+
+ while (utf_nextu2(utf_ptr) != ';')
+ end = (*utf_ptr) + 1;
+
+ if (!builtin_instanceof(params->data[cnts], class_from_descriptor(start, end, 0, CLASSLOAD_LOAD))) {
+ if (params->data[cnts] != 0) {
+ *exceptionptr = new_exception("java/lang/IllegalArgumentException");
+ return 0;
+ }
+ }
+
+ blk[cnt].itemtype = TYPE_ADR;
+ blk[cnt].item = PTR_TO_ITEM(params->data[cnts]);
+ break;
+ }
+
+ case '[':
+ {
+ char *start = (*utf_ptr) - 1;
+ char *end;
+
+ char ch;
+ while ((ch = utf_nextu2(utf_ptr)) == '[')
+ if (ch == 'L') {
+ while (utf_nextu2(utf_ptr) != ';') {}
+ }
+
+ end = (*utf_ptr) - 1;
+ ch = utf_nextu2(utf_ptr);
+
+ if (!builtin_arrayinstanceof(params->data[cnts], class_from_descriptor(start, end, 0, CLASSLOAD_LOAD)->vftbl)) {
+ *exceptionptr = new_exception("java/lang/IllegalArgumentException");
+ return 0;
+ }
+
+ blk[cnt].itemtype = TYPE_ADR;
+ blk[cnt].item = PTR_TO_ITEM(params->data[cnts]);
+ break;
+ }
+ }
+ cnt++;
+ cnts++;
+ }
+
+ c = utf_nextu2(utf_ptr);
+ c = utf_nextu2(utf_ptr);
+ return c; /*return type needed usage of the right lowlevel methods*/
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+jmethodID get_virtual(jobject obj,jmethodID methodID) {
+ if (obj->vftbl->class==methodID->class) return methodID;
+ return class_resolvemethod (obj->vftbl->class, methodID->name, methodID->descriptor);
+}
+
+jmethodID get_nonvirtual(jclass clazz,jmethodID methodID) {
+ if (clazz==methodID->class) return methodID;
+/*class_resolvemethod -> classfindmethod? (JOWENN)*/
+ return class_resolvemethod (clazz, methodID->name, methodID->descriptor);
+}
+
+
+
+jobject callObjectMethod (jobject obj, jmethodID methodID, va_list args)
+{
+ int argcount;
+ jni_callblock *blk;
+ jobject ret;
+
+ /*
+ log_text("JNI-Call: CallObjectMethodV");
+ utf_display(methodID->name);
+ utf_display(methodID->descriptor);
+ printf("\nParmaeter count: %d\n",argcount);
+ utf_display(obj->vftbl->class->name);
+ printf("\n");
+ */
+
+ if (methodID == 0) {
+ *exceptionptr = new_exception(string_java_lang_NoSuchMethodError);
+ return 0;
+ }
+
+ argcount = get_parametercount(methodID);
+
+ if (!( ((methodID->flags & ACC_STATIC) && (obj == 0)) ||
+ ((!(methodID->flags & ACC_STATIC)) && (obj != 0)) )) {
+ *exceptionptr = new_exception(string_java_lang_NoSuchMethodError);
+ return 0;
+ }
+
+ if (obj && !builtin_instanceof(obj, methodID->class)) {
+ *exceptionptr = new_exception(string_java_lang_NoSuchMethodError);
+ return 0;
+ }
+
+ if (argcount > 3) {
+ *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
+ log_text("Too many arguments. CallObjectMethod does not support that");
+ return 0;
+ }
+
+ blk = MNEW(jni_callblock, 4 /*argcount+2*/);
+
+ fill_callblock(obj, methodID->descriptor, blk, args, 'O');
+
+ /* printf("parameter: obj: %p",blk[0].item); */
+ ret = asm_calljavafunction2(methodID,
+ argcount + 1,
+ (argcount + 1) * sizeof(jni_callblock),
+ blk);
+
+ MFREE(blk, jni_callblock, argcount + 1);
+ /* printf("(CallObjectMethodV)-->%p\n",ret); */
+ return ret;
+}
+
+
+/*
+ core function for integer class methods (bool, byte, short, integer)
+ This is basically needed for i386
+*/
+jint callIntegerMethod(jobject obj, jmethodID methodID, char retType, va_list args)
+{
+ int argcount;
+ jni_callblock *blk;
+ jint ret;
+
+/* printf("%p, %c\n",retType,methodID,retType);*/
+
+ /*
+ log_text("JNI-Call: CallObjectMethodV");
+ utf_display(methodID->name);
+ utf_display(methodID->descriptor);
+ printf("\nParmaeter count: %d\n",argcount);
+ utf_display(obj->vftbl->class->name);
+ printf("\n");
+ */
+ if (methodID == 0) {
+ *exceptionptr = new_exception(string_java_lang_NoSuchMethodError);
+ return 0;
+ }
+
+ argcount = get_parametercount(methodID);
+
+ if (!( ((methodID->flags & ACC_STATIC) && (obj == 0)) ||
+ ((!(methodID->flags & ACC_STATIC)) && (obj != 0)) )) {
+ *exceptionptr = new_exception(string_java_lang_NoSuchMethodError);
+ return 0;
+ }
+
+ if (obj && !builtin_instanceof(obj, methodID->class)) {
+ *exceptionptr = new_exception(string_java_lang_NoSuchMethodError);
+ return 0;
+ }
+
+
+ if (argcount > 3) {
+ *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
+ log_text("Too many arguments. CallIntegerMethod does not support that");
+ return 0;
+ }
+
+ blk = MNEW(jni_callblock, 4 /*argcount+2*/);
+
+ fill_callblock(obj, methodID->descriptor, blk, args, retType);
+
+ /* printf("parameter: obj: %p",blk[0].item); */
+ ret = (jint) asm_calljavafunction2(methodID,
+ argcount + 1,
+ (argcount + 1) * sizeof(jni_callblock),
+ blk);
+
+ MFREE(blk, jni_callblock, argcount + 1);
+ /* printf("(CallObjectMethodV)-->%p\n",ret); */
+
+ return ret;
+}
+
+
+/*core function for long class functions*/
+jlong callLongMethod(jobject obj, jmethodID methodID, va_list args)
+{
+ int argcount;
+ jni_callblock *blk;
+ jlong ret;
+
+/*
+ log_text("JNI-Call: CallObjectMethodV");
+ utf_display(methodID->name);
+ utf_display(methodID->descriptor);
+ printf("\nParmaeter count: %d\n",argcount);
+ utf_display(obj->vftbl->class->name);
+ printf("\n");
+*/
+ if (methodID == 0) {
+ *exceptionptr = new_exception(string_java_lang_NoSuchMethodError);
+ return 0;
+ }
+
+ argcount = get_parametercount(methodID);
+
+ if (!( ((methodID->flags & ACC_STATIC) && (obj == 0)) ||
+ ((!(methodID->flags & ACC_STATIC)) && (obj!=0)) )) {
+ *exceptionptr = new_exception(string_java_lang_NoSuchMethodError);
+ return 0;
+ }
+
+ if (obj && !builtin_instanceof(obj,methodID->class)) {
+ *exceptionptr = new_exception(string_java_lang_NoSuchMethodError);
+ return 0;
+ }
+
+
+ if (argcount > 3) {
+ *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
+ log_text("Too many arguments. CallObjectMethod does not support that");
+ return 0;
+ }
+
+ blk = MNEW(jni_callblock, 4 /*argcount+2*/);
+
+ fill_callblock(obj, methodID->descriptor, blk, args, 'J');
+
+ /* printf("parameter: obj: %p",blk[0].item); */
+ ret = asm_calljavafunction2long(methodID,
+ argcount + 1,
+ (argcount + 1) * sizeof(jni_callblock),
+ blk);
+
+ MFREE(blk, jni_callblock, argcount + 1);
+ /* printf("(CallObjectMethodV)-->%p\n",ret); */
+
+ return ret;
+}
+
+
+/*core function for float class methods (float,double)*/
+jdouble callFloatMethod(jobject obj, jmethodID methodID, va_list args,char retType)
+{
+ int argcount = get_parametercount(methodID);
+ jni_callblock *blk;
+ jdouble ret;
+
+ /*
+ log_text("JNI-Call: CallObjectMethodV");
+ utf_display(methodID->name);
+ utf_display(methodID->descriptor);
+ printf("\nParmaeter count: %d\n",argcount);
+ utf_display(obj->vftbl->class->name);
+ printf("\n");
+ */
+
+ if (argcount > 3) {
+ *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
+ log_text("Too many arguments. CallObjectMethod does not support that");
+ return 0;
+ }
+
+ blk = MNEW(jni_callblock, 4 /*argcount+2*/);
+
+ fill_callblock(obj, methodID->descriptor, blk, args, retType);
+
+ /* printf("parameter: obj: %p",blk[0].item); */
+ ret = asm_calljavafunction2double(methodID,
+ argcount + 1,
+ (argcount + 1) * sizeof(jni_callblock),
+ blk);
+
+ MFREE(blk, jni_callblock, argcount + 1);
+ /* printf("(CallObjectMethodV)-->%p\n",ret); */
+
+ return ret;
+}
+
+