/* -*- Mode: C; c-file-style: "gnu"; indent-tabs-mode:nil -*-
   jnismeth.c -- Java Native Interface methods relating to static methods.
   Created: Chris Toshok <toshok@hungry.com>, 26-Jul-1997
 */
/*
  This file is part of Japhar, the GNU Virtual Machine for Java Bytecodes.
  Japhar is a project of The Hungry Programmers, GNU, and OryxSoft.

  Copyright (C) 1997, 1998, 1999 The Hungry Programmers

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Library General Public
  License as published by the Free Software Foundation; either
  version 2 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Library General Public License for more details.

  You should have received a copy of the GNU Library General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "jniint.h"

jmethodID
JNIFUNC(GetStaticMethodID)(JNIEnv *env,
                           jclass clazz,
                           const char *name,
                           const char *sig)
{
  HungryEnv *henv = JNIEnvToHEnv(env);
  ClazzFile *cf = jclass_to_clazzfile(henv, clazz);
  MethodStruct* method;

  method = HVM_MethodFindStatic(henv, cf, name, sig);

  if (method == NULL)
    {
      jclass no_such_method = (*env)->FindClass(env,
                                                java_lang_NoSuchMethodError);
      if (no_such_method)
        (*env)->ThrowNew(env, no_such_method, name);
      else
        (*env)->FatalError(env, "Could not load java/lang/NoSuchMethodError");
    }

  return method;
}

#define STATIC_METHOD_FOO(jtype, JType, unionselector) \
 \
jtype \
JNIFUNC(CallStatic##JType##Method)(JNIEnv *env, \
                                   jclass clazz, \
                                   jmethodID methodID, \
                                   ...) \
{ \
  va_list varargs; \
  jtype result; \
 \
  va_start(varargs, methodID); \
  result = JNIFUNC(CallStatic##JType##MethodV)(env, clazz, methodID, varargs); \
  va_end(varargs); \
 \
  return result; \
} \
 \
jtype \
JNIFUNC(CallStatic##JType##MethodA)(JNIEnv *env, \
                                    jclass clazz, \
                                    jmethodID methodID, \
                                    jvalue *args) \
{ \
  HungryEnv *henv = JNIEnvToHEnv(env); \
  InterpValue value; \
 \
  value = HVM_MethodCallStaticA(henv,\
                                (MethodStruct*)methodID, \
                                (InterpValue*)args); \
 \
  return value.unionselector; \
} \
 \
jtype \
JNIFUNC(CallStatic##JType##MethodV)(JNIEnv *env, \
                                    jclass clazz, \
                                    jmethodID methodID, \
                                    va_list args) \
{ \
  HungryEnv *henv = JNIEnvToHEnv(env); \
  jvalue *params; \
  int i; \
  MethodStruct *method = (MethodStruct*)methodID; \
  HVMSignature *sig = HVM_SigParseFromJavaSig(henv, method->sig_str); \
  int num_params = HVM_SigNumParams(henv, sig); \
  jtype result; \
   \
  params = (jvalue*)PR_Calloc(num_params, sizeof(jvalue*)); \
 \
  for (i = 0; i < num_params; i ++) \
    { \
      switch (HVM_SigSizeofStrInWords(henv, sig->method.params[i])) \
        { \
        case 1: \
          params[i].i = va_arg(args, jint); \
          break; \
        case 2: \
          params[i].j = va_arg(args, jlong); \
          break; \
        } \
    } \
 \
  HVM_SigFree(henv, sig); \
\
  result = JNIFUNC(CallStatic##JType##MethodA)(env, clazz, methodID, params); \
   \
  PR_DELETE(params); \
 \
  return result; \
}

STATIC_METHOD_FOO(jboolean, Boolean, z)
     STATIC_METHOD_FOO(jbyte, Byte, b)
     STATIC_METHOD_FOO(jchar, Char, c)
     STATIC_METHOD_FOO(jshort, Short, s)
     STATIC_METHOD_FOO(jint, Int, i)
     STATIC_METHOD_FOO(jlong, Long, j)
     STATIC_METHOD_FOO(jobject, Object, l)
     STATIC_METHOD_FOO(jfloat, Float, f)
     STATIC_METHOD_FOO(jdouble, Double, d)

     void
JNIFUNC(CallStaticVoidMethod)(JNIEnv *env,
                              jclass clazz,
                              jmethodID methodID, 
                              ...)
{
  va_list varargs;

  va_start(varargs, methodID);
  JNIFUNC(CallStaticVoidMethodV)(env, clazz, methodID, varargs);
  va_end(varargs);
}

void
JNIFUNC(CallStaticVoidMethodA)(JNIEnv *env, 
                               jclass clazz,
                               jmethodID methodID, 
                               jvalue *args)
{
  HungryEnv *henv = JNIEnvToHEnv(env);
  HVM_MethodCallStaticA(henv,
                        (MethodStruct*)methodID,
                        (InterpValue*)args);
}

void
JNIFUNC(CallStaticVoidMethodV)(JNIEnv *env, 
                               jclass clazz,
                               jmethodID methodID, 
                               va_list args)
{
  HungryEnv *henv = JNIEnvToHEnv(env);
  jvalue *params = NULL;
  MethodStruct *method = (MethodStruct*)methodID;
  HVMSignature *sig = HVM_SigParseFromJavaSig(henv, method->sig_str);
  int num_params = HVM_SigNumParams(henv, sig);
  int i;

  if (0 < num_params)
    params = (jvalue*)PR_Calloc(num_params, sizeof(jvalue*));

  for (i = 0; i < num_params; i ++)
    {
      switch (HVM_SigSizeofStrInWords(henv, sig->method.params[i]))
        {
        case 1:
          params[i].i = va_arg(args, jint);
          break;
        case 2:
          params[i].j = va_arg(args, jlong);
          break;
        }
    }

  HVM_SigFree(henv, sig);

  JNIFUNC(CallStaticVoidMethodA)(env, clazz, methodID, params);

  if (NULL != params)
    PR_DELETE(params);
}
