/* -*- Mode: C; c-file-style: "gnu" -*-
   jvmdiloc.c -- JVMDI Local Variable Access Functions
   Created: Hernan Otero <hernan_otero@bigfoot.com>, 18-Jul-1998.
 */
/*
  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) 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 "jvmdiint.h"
#include "interp.h"
#include "objects.h"
#include "log.h"

#include <assert.h>

#define MYLOG "JVMDI"


JNIEXPORT jvmdiError JNICALL
JVMDI_GetLocalObject(JNIEnv *env,
		     jframeID frame,
		     jint slot,
		     jobject *valuePtr)
{
  StackFrame *sframe = (StackFrame*)frame;

  /* usual NULL checks. */
  if (env == NULL
      || sframe == NULL
      || valuePtr == NULL)
    return JVMDI_ERROR_NULL_POINTER;

  /* make sure the slot number is possible in this sframe. */
  if (slot < 0 || slot > sframe->method->max_locals)
    return JVMDI_ERROR_INVALID_SLOT;

  /* check the type of the slot */
  if (sframe->vars[slot].tag != SIG_JOBJECT)
    return JVMDI_ERROR_TYPE_MISMATCH;

  *valuePtr = sframe->vars[slot].value.l;
  return JVMDI_ERROR_NONE;
}

JNIEXPORT jvmdiError JNICALL
JVMDI_GetLocalInt(JNIEnv *env,
		  jframeID frame,
		  jint slot,
		  jint *valuePtr)
{
  StackFrame *sframe = (StackFrame*)frame;

  /* usual NULL checks. */
  if (env == NULL
      || sframe == NULL
      || valuePtr == NULL)
    return JVMDI_ERROR_NULL_POINTER;

  /* make sure the slot number is possible in this sframe. */
  if (slot < 0 || slot > sframe->method->max_locals)
    return JVMDI_ERROR_INVALID_SLOT;

  /* check the type of the slot */
  if (sframe->vars[slot].tag != SIG_JINT)
    return JVMDI_ERROR_TYPE_MISMATCH;

  *valuePtr = sframe->vars[slot].value.i;
  return JVMDI_ERROR_NONE;
}

JNIEXPORT jvmdiError JNICALL
JVMDI_GetLocalLong(JNIEnv *env,
		   jframeID frame,
		   jint slot,
		   jlong *valuePtr)
{
  StackFrame *sframe = (StackFrame*)frame;

  /* usual NULL checks. */
  if (env == NULL
      || sframe == NULL
      || valuePtr == NULL)
    return JVMDI_ERROR_NULL_POINTER;

  /* make sure the slot number is possible in this sframe. */
  if (slot < 0 || slot > sframe->method->max_locals - 1)
    return JVMDI_ERROR_INVALID_SLOT;

  /* check the type of the slot */
  if (sframe->vars[slot].tag != SIG_JLONG1
      || sframe->vars[slot + 1].tag != SIG_JLONG2)
    return JVMDI_ERROR_TYPE_MISMATCH;

  *valuePtr = (jlong)sframe->vars[slot].value.i << 32;
  *valuePtr |= sframe->vars[slot + 1].value.j & 0xffffffff;
  return JVMDI_ERROR_NONE;
}

JNIEXPORT jvmdiError JNICALL
JVMDI_GetLocalFloat(JNIEnv *env,
		    jframeID frame,
		    jint slot,
		    jfloat *valuePtr)
{
  StackFrame *sframe = (StackFrame*)frame;

  /* usual NULL checks. */
  if (env == NULL
      || sframe == NULL
      || valuePtr == NULL)
    return JVMDI_ERROR_NULL_POINTER;

  /* make sure the slot number is possible in this sframe. */
  if (slot < 0 || slot > sframe->method->max_locals)
    return JVMDI_ERROR_INVALID_SLOT;

  /* check the type of the slot */
  if (sframe->vars[slot].tag != SIG_JFLOAT)
    return JVMDI_ERROR_TYPE_MISMATCH;

  *valuePtr = sframe->vars[slot].value.f;
  return JVMDI_ERROR_NONE;
}

JNIEXPORT jvmdiError JNICALL
JVMDI_GetLocalDouble(JNIEnv *env,
		     jframeID frame,
		     jint slot,
		     jdouble *valuePtr)
{
  StackFrame *sframe = (StackFrame*)frame;
  jvalue value;

  /* usual NULL checks. */
  if (env == NULL
      || sframe == NULL
      || valuePtr == NULL)
    return JVMDI_ERROR_NULL_POINTER;

  /* make sure the slot number is possible in this sframe. */
  if (slot < 0 || slot > sframe->method->max_locals - 1)
    return JVMDI_ERROR_INVALID_SLOT;

  /* check the type of the slot */
  if (sframe->vars[slot].tag != SIG_JDOUBLE1
      || sframe->vars[slot + 1].tag != SIG_JDOUBLE2)
    return JVMDI_ERROR_TYPE_MISMATCH;

  value.j = (jlong)sframe->vars[slot].value.i << 32;
  value.j |= sframe->vars[slot + 1].value.j & 0xffffffff;

  *valuePtr = value.d;
  return JVMDI_ERROR_NONE;
}

JNIEXPORT jvmdiError JNICALL
JVMDI_SetLocalObject(JNIEnv *env,
		     jframeID frame,
		     jint slot,
		     jobject value)
{
  StackFrame *sframe = (StackFrame*)frame;

  /* usual NULL checks. */
  if (env == NULL
      || sframe == NULL)
    return JVMDI_ERROR_NULL_POINTER;

  /* make sure the slot number is possible in this sframe. */
  if (slot < 0 || slot > sframe->method->max_locals)
    return JVMDI_ERROR_INVALID_SLOT;

  /* check the type of the slot */
  if (sframe->vars[slot].tag != SIG_JOBJECT)
    return JVMDI_ERROR_TYPE_MISMATCH;

  sframe->vars[slot].value.l = value;
  return JVMDI_ERROR_NONE;
}

JNIEXPORT jvmdiError JNICALL
JVMDI_SetLocalInt(JNIEnv *env,
		  jframeID frame,
		  jint slot,
		  jint value)
{
  StackFrame *sframe = (StackFrame*)frame;

  /* usual NULL checks. */
  if (env == NULL
      || sframe == NULL)
    return JVMDI_ERROR_NULL_POINTER;

  /* make sure the slot number is possible in this sframe. */
  if (slot < 0 || slot > sframe->method->max_locals)
    return JVMDI_ERROR_INVALID_SLOT;

  /* check the type of the slot */
  if (sframe->vars[slot].tag != SIG_JINT)
    return JVMDI_ERROR_TYPE_MISMATCH;

  sframe->vars[slot].value.i = value;
  return JVMDI_ERROR_NONE;
}

JNIEXPORT jvmdiError JNICALL
JVMDI_SetLocalFloat(JNIEnv *env,
		    jframeID frame,
		    jint slot,
		    jfloat value)
{
  StackFrame *sframe = (StackFrame*)frame;

  /* usual NULL checks. */
  if (env == NULL
      || sframe == NULL)
    return JVMDI_ERROR_NULL_POINTER;

  /* make sure the slot number is possible in this sframe. */
  if (slot < 0 || slot > sframe->method->max_locals)
    return JVMDI_ERROR_INVALID_SLOT;

  /* check the type of the slot */
  if (sframe->vars[slot].tag != SIG_JFLOAT)
    return JVMDI_ERROR_TYPE_MISMATCH;

  sframe->vars[slot].value.f = value;
  return JVMDI_ERROR_NONE;
}

JNIEXPORT jvmdiError JNICALL
JVMDI_SetLocalLong(JNIEnv *env,
		   jframeID frame,
		   jint slot,
		   jlong value)
{
  StackFrame *sframe = (StackFrame*)frame;

  /* usual NULL checks. */
  if (env == NULL
      || sframe == NULL)
    return JVMDI_ERROR_NULL_POINTER;

  /* make sure the slot number is possible in this sframe. */
  if (slot < 0 || slot > sframe->method->max_locals - 1)
    return JVMDI_ERROR_INVALID_SLOT;

  /* check the type of the slot */
  if (sframe->vars[slot].tag != SIG_JLONG1
      || sframe->vars[slot + 1].tag != SIG_JLONG2)
    return JVMDI_ERROR_TYPE_MISMATCH;

  sframe->vars[slot].value.i = (value >> 32) & 0xffffffff;
  sframe->vars[slot + 1].value.i = value & 0xffffffff;
  return JVMDI_ERROR_NONE;
}

JNIEXPORT jvmdiError JNICALL
JVMDI_SetLocalDouble(JNIEnv *env,
		     jframeID frame,
		     jint slot,
		     jdouble value)
{
  StackFrame *sframe = (StackFrame*)frame;
  jvalue tmp_value;

  /* usual NULL checks. */
  if (env == NULL
      || sframe == NULL)
    return JVMDI_ERROR_NULL_POINTER;

  /* make sure the slot number is possible in this sframe. */
  if (slot < 0 || slot > sframe->method->max_locals - 1)
    return JVMDI_ERROR_INVALID_SLOT;

  /* check the type of the slot */
  if (sframe->vars[slot].tag != SIG_JLONG1
      || sframe->vars[slot + 1].tag != SIG_JLONG2)
    return JVMDI_ERROR_TYPE_MISMATCH;

  tmp_value.d = value;

  sframe->vars[slot].value.i = (tmp_value.j >> 32) & 0xffffffff;
  sframe->vars[slot + 1].value.i = tmp_value.j & 0xffffffff;
  return JVMDI_ERROR_NONE;
}
