/* -*- Mode: C; c-file-style: "gnu" -*-
   jvmdi.h -- Java Virtual Machine Debugger Interface (JDK 1.2)
   Created: Chris Toshok <toshok@hungry.com>, 9-Feb-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
*/
#ifndef _jvmdi_h
#define _jvmdi_h

#include "jni.h"

#ifdef __cplusplus
extern "C" {
#endif

  /* version number = 1.0 */
#define JVMDI_VERSION_NUMBER 0x00010000

  typedef jobject jthread;
  typedef jobject jthreadGroup;

  struct _jframeID;
  typedef struct _jframeID *jframeID;

  typedef jlong jlocation;

  /* error codes */
  typedef enum {
    JVMDI_ERROR_NONE,
    JVMDI_ERROR_INVALID_THREAD,
    JVMDI_ERROR_INVALID_THREAD_GROUP,
    JVMDI_ERROR_INVALID_FIELDID,
    JVMDI_ERROR_INVALID_METHODID,
    JVMDI_ERROR_INVALID_LOCATION,
    JVMDI_ERROR_INVALID_FRAMEID,
    JVMDI_ERROR_NO_MORE_FRAMES,
    JVMDI_ERROR_OPAQUE_FRAME,
    JVMDI_ERROR_NOT_CURRENT_FRAME,
    JVMDI_ERROR_TYPE_MISMATCH,
    JVMDI_ERROR_INVALID_SLOT,
    JVMDI_ERROR_DUPLICATE_BREAKPOINT,
    JVMDI_ERROR_NO_SUCH_BREAKPOINT,
    JVMDI_ERROR_THREAD_NOT_SUSPENDED,
    JVMDI_ERROR_THREAD_SUSPENDED,
    JVMDI_ERROR_INVALID_OBJECT,
    JVMDI_ERROR_INVALID_CLASS,
    JVMDI_ERROR_NULL_POINTER,
    JVMDI_ERROR_ABSENT_INFORMATION,
    JVMDI_ERROR_OUT_OF_MEMORY,
    JVMDI_ERROR_VM_DEAD,
    JVMDI_ERROR_INTERNAL,
    JVMDI_ERROR_NOT_IMPLEMENTED
  } jvmdiError;

  /* thread statuses */
  enum {
    JVMDI_THREAD_STATUS_UNKNOWN,
    JVMDI_THREAD_STATUS_ZOMBIE,
    JVMDI_THREAD_STATUS_RUNNING,
    JVMDI_THREAD_STATUS_SLEEPING,
    JVMDI_THREAD_STATUS_MONITOR,
    JVMDI_THREAD_STATUS_WAIT,
    JVMDI_THREAD_STATUS_SUSPENDED,
    JVMDI_THREAD_STATUS_BREAK
  };

  /* for the "kind" field in JVMDI_Event */
  enum {
    JVMDI_EVENT_SINGLE_STEP,
    JVMDI_EVENT_BREAKPOINT,
    JVMDI_EVENT_FRAME_POP,
    JVMDI_EVENT_EXCEPTION,
    JVMDI_EVENT_USER_DEFINED,
    JVMDI_EVENT_THREAD_START,
    JVMDI_EVENT_THREAD_END,
    JVMDI_EVENT_CLASS_LINK,
    JVMDI_EVENT_CLASS_UNLINK,
    JVMDI_EVENT_VM_DEATH
  };

  /* kind = JVMDI_EVENT_SINGLE_STEP */
  typedef struct { 
    jthread thread;
    jclass clazz;
    jmethodID method;
    jlocation location;
  } JVMDI_single_step_event_data;
		
  /* kind = JVMDI_EVENT_BREAKPOINT */
  typedef struct { 
    jthread thread;
    jclass clazz;
    jmethodID method;
    jlocation location;
  } JVMDI_breakpoint_event_data;

  /* kind = JVMDI_EVENT_FRAME_POP */
  typedef struct { 
    jthread thread;
    jframeID frame;
  } JVMDI_frame_pop_event_data;

  /* kind = JVMDI_EVENT_EXCEPTION */
  typedef struct { 
    jthread thread;
    jclass clazz;
    jmethodID method;
    jlocation location;
    jobject exception;
    jclass catch_clazz;
    jmethodID catch_method;
    jlocation catch_location;
  } JVMDI_exception_event_data;

  /* kind = JVMDI_EVENT_USER_DEFINED */
  typedef struct { 
    jobject object;
    jint key;
  } JVMDI_user_event_data;

  /* kind = JVMDI_EVENT_THREAD_END or */
  /* JVMDI_EVENT_THREAD_START */
  typedef struct { 
    jthread thread;
  } JVMDI_thread_change_event_data;

  /* kind = JVMDI_EVENT_CLASS_LINK or */
  /* JVMDI_EVENT_CLASS_UNLINK */
  typedef struct { 
    jthread thread;
    jclass clazz;
  } JVMDI_link_event_data;
    

  /* This stucture passes information about the event.
   * location is the index of the last instruction executed. 
   */
  typedef struct {
    jint kind;		/* the discriminant */

    union {
      /* kind = JVMDI_EVENT_SINGLE_STEP */
      JVMDI_single_step_event_data single_step;
			
      /* kind = JVMDI_EVENT_BREAKPOINT */
      JVMDI_breakpoint_event_data breakpoint;

      /* kind = JVMDI_EVENT_FRAME_POP */
      JVMDI_frame_pop_event_data frame_pop;

      /* kind = JVMDI_EVENT_EXCEPTION */
      JVMDI_exception_event_data exception;

      /* kind = JVMDI_EVENT_USER_DEFINED */
      JVMDI_user_event_data user;
			
      /* kind = JVMDI_EVENT_THREAD_END or */
      /* JVMDI_EVENT_THREAD_START */
      JVMDI_thread_change_event_data thread_change;
			
      /* kind = JVMDI_EVENT_CLASS_LINK or */
      /* JVMDI_EVENT_CLASS_UNLINK */
      JVMDI_link_event_data link;
			
      /* kind = JVMDI_EVENT_VM_DEATH */
      /* no additional fields */		
    } u;
  } JVMDI_Event;

  typedef struct {
    char *name;
    jint  priority;
    jboolean isDaemon;
    jthreadGroup threadGroup;
    jobject contextClassLoader;
  } JVMDI_thread_info;

  typedef struct {
    jthreadGroup parent;
    char *name;
    jint  maxPriority;
    jboolean isDaemon;
  } JVMDI_thread_group_info;

  typedef struct {
    jlocation start_location;
    jint line_number;
  } JVMDI_line_number_entry;

  typedef struct {
    jlocation start_location;   /* variable valid start_location */
    jint length;                /* upto start_location+length */ 
    char *name;                 /* name in UTF8 */
    char *signature;            /* type signature in UTF8 */
    jint slot;                  /* variable slot, see JVMDI_GetLocal*()  */
  } JVMDI_local_variable_entry;

  typedef struct {
    jlocation start_location;
    jlocation end_location;
    jlocation handler_location;
    jclass exception;           /* if null, all exceptions */
  } JVMDI_exception_handler_entry;

  /* Allocator hook type */
  typedef jvmdiError 
  (*JVMDI_AllocHook)(JNIEnv *env, jlong size, jbyte** memPtr);

  /* Deallocator hook type */
  typedef jvmdiError 
  (*JVMDI_DeallocHook)(JNIEnv *env, jbyte* mem);

  /* Event hook type */
  typedef void
  (*JVMDI_EventHook)(JNIEnv *env, JVMDI_Event *event);


  /* Memory Management */

  JNIEXPORT jvmdiError JNICALL
  JVMDI_SetAllocationHooks(JNIEnv *env, JVMDI_AllocHook ahook,
			   JVMDI_DeallocHook dhook);

  JNIEXPORT jvmdiError JNICALL
  JVMDI_Allocate(JNIEnv *env, jlong size, jbyte** memPtr);

  JNIEXPORT jvmdiError JNICALL
  JVMDI_Deallocate(JNIEnv *env, jbyte* mem);


  /* Thread Execution Functions */

  JNIEXPORT jvmdiError JNICALL
  JVMDI_GetThreadStatus(JNIEnv *env, jthread thread, jint *statusPtr);

  JNIEXPORT jvmdiError JNICALL
  JVMDI_GetAllThreads(JNIEnv *env, jint *threadsCountPtr,
		      jthread **threadsPtr);

  JNIEXPORT jvmdiError JNICALL
  JVMDI_SuspendThread(JNIEnv *env, jthread thread); 

  JNIEXPORT jvmdiError JNICALL
  JVMDI_ResumeThread(JNIEnv *env, jthread thread);

  JNIEXPORT jvmdiError JNICALL
  JVMDI_StopThread(JNIEnv *env, jthread thread, jobject exception);

  JNIEXPORT jvmdiError JNICALL
  JVMDI_InterruptThread(JNIEnv *env, jthread thread);

  JNIEXPORT jvmdiError JNICALL
  JVMDI_SetSingleStep(JNIEnv *env, jthread thread, jboolean shouldStep);

  /* Thread Group Functions */

  JNIEXPORT jvmdiError JNICALL
  JVMDI_GetTopThreadGroups(JNIEnv *env, jint *groupCountPtr, 
			   jthreadGroup **groupsPtr);

  JNIEXPORT jvmdiError JNICALL
  JVMDI_GetThreadGroupInfo(JNIEnv *env, jthreadGroup group, 
			   JVMDI_thread_group_info *infoPtr);

  JNIEXPORT jvmdiError JNICALL
  JVMDI_GetThreadGroupChildren(JNIEnv *env, jthreadGroup group, 
			       jint *threadCountPtr, jthread **threadsPtr,
			       jint *groupCountPtr, jthreadGroup **groupsPtr);

  /* Stack Frame Access */

  JNIEXPORT jvmdiError JNICALL
  JVMDI_GetCurrentFrame(JNIEnv *env, jthread thread, jframeID *framePtr);

  JNIEXPORT jvmdiError JNICALL
  JVMDI_GetCallerFrame(JNIEnv *env, jframeID called, jframeID *framePtr);

  JNIEXPORT jvmdiError JNICALL
  JVMDI_GetFrameLocation(JNIEnv *env, jframeID frame, 
			 jclass *classPtr, jmethodID *methodPtr,
			 jlocation *locationPtr);

  JNIEXPORT jvmdiError JNICALL
  JVMDI_GetFrameMethod(JNIEnv *env,
		       jframeID frame, 
		       jclass *classPtr,
		       jmethodID *methodPtr);

  JNIEXPORT jvmdiError JNICALL
  JVMDI_NotifyFramePop(JNIEnv *env, jframeID frame); 


  /* Local Variable Access */

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

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

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

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

  JNIEXPORT jvmdiError JNICALL
  JVMDI_GetLocalDouble(JNIEnv *env, jframeID frame, jint slot, 
		       jdouble *valuePtr);

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

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

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

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

  JNIEXPORT jvmdiError JNICALL
  JVMDI_SetLocalDouble(JNIEnv *env, jframeID frame, jint slot, jdouble value);


  /* Breakpoints */

  JNIEXPORT jvmdiError JNICALL
  JVMDI_SetBreakpoint(JNIEnv *env, jclass clazz, 
		      jmethodID method, jlocation location);

  JNIEXPORT jvmdiError JNICALL
  JVMDI_ClearBreakpoint(JNIEnv *env, jclass clazz, 
			jmethodID method, jlocation location);

  JNIEXPORT jvmdiError JNICALL
  JVMDI_ClearAllBreakpoints(JNIEnv *env);


  /* Class Information */

  JNIEXPORT jvmdiError JNICALL
  JVMDI_GetClassName(JNIEnv *env, jclass clazz, char **namePtr);

  JNIEXPORT jvmdiError JNICALL
  JVMDI_GetSourcePath(JNIEnv *env, jclass clazz, char **sourcePathPtr);

  JNIEXPORT jvmdiError JNICALL
  JVMDI_GetClassModifiers(JNIEnv *env, jclass clazz, jint *modifiersPtr);

  JNIEXPORT jvmdiError JNICALL
  JVMDI_GetClassMethods(JNIEnv *env, jclass clazz, 
			jint *methodCountPtr, jmethodID **methodsPtr);

  JNIEXPORT jvmdiError JNICALL
  JVMDI_GetClassFields(JNIEnv *env, jclass clazz, 
		       jint *fieldCountPtr, jfieldID **fieldsPtr);

  JNIEXPORT jvmdiError JNICALL
  JVMDI_GetImplementedInterfaces(JNIEnv *env, jclass clazz,
				 jint *interfaceCountPtr, 
				 jclass **interfacesPtr);

  JNIEXPORT jvmdiError JNICALL
  JVMDI_IsInterface(JNIEnv *env, jclass clazz, jboolean *isInterfacePtr);

  JNIEXPORT jvmdiError JNICALL
  JVMDI_IsArray(JNIEnv *env, jclass clazz, jboolean *isArrayPtr);

  JNIEXPORT jvmdiError JNICALL
  JVMDI_ClassLoader(JNIEnv *env, jclass clazz, jobject *classloaderPtr);


  /* Field Information */

  JNIEXPORT jvmdiError JNICALL
  JVMDI_GetFieldName(JNIEnv *env, jclass clazz, jfieldID field, 
		     char **namePtr, char **signaturePtr);

  JNIEXPORT jvmdiError JNICALL
  JVMDI_GetFieldDeclaringClass(JNIEnv *env, jclass clazz, jfieldID field,
			       jclass *declaringClassPtr);

  JNIEXPORT jvmdiError JNICALL
  JVMDI_GetFieldModifiers(JNIEnv *env, jclass clazz, jfieldID field,
			  jint *modifiersPtr);


  /* Method Information */

  JNIEXPORT jvmdiError JNICALL
  JVMDI_GetMethodName(JNIEnv *env, jclass clazz, jmethodID method, 
		      jstring *namePtr, jstring *signaturePtr);

  JNIEXPORT jvmdiError JNICALL
  JVMDI_GetMethodDeclaringClass(JNIEnv *env, jclass clazz, jmethodID method,
				jclass *declaringClassPtr);

  JNIEXPORT jvmdiError JNICALL
  JVMDI_GetMethodModifiers(JNIEnv *env, jclass clazz, jmethodID method,
			   jint *modifiersPtr);

  JNIEXPORT jvmdiError JNICALL
  JVMDI_GetMaxStack(JNIEnv *env, jclass clazz, jmethodID method,
		    jint *maxPtr);

  JNIEXPORT jvmdiError JNICALL
  JVMDI_GetMaxLocals(JNIEnv *env, jclass clazz, jmethodID method,
		     jint *maxPtr);

  JNIEXPORT jvmdiError JNICALL
  JVMDI_GetArgumentsSize(JNIEnv *env, jclass clazz, jmethodID method,
			 jint *sizePtr);

  JNIEXPORT jvmdiError JNICALL
  JVMDI_GetLineNumberTable(JNIEnv *env, jclass clazz, jmethodID method,
			   jint *entryCountPtr, 
			   JVMDI_line_number_entry **tablePtr);

  JNIEXPORT jvmdiError JNICALL
  JVMDI_GetMethodLocation(JNIEnv *env, jclass clazz, jmethodID method,
			  jlocation *startLocationPtr, 
			  jlocation *endLocationPtr);

  JNIEXPORT jvmdiError JNICALL
  JVMDI_GetLocalVariableTable(JNIEnv *env, jclass clazz, jmethodID method,
			      jint *entryCountPtr, 
			      JVMDI_local_variable_entry **tablePtr);

  JNIEXPORT jvmdiError JNICALL
  JVMDI_GetExceptionHandlerTable(JNIEnv *env, jclass clazz, jmethodID method,
				 jint *entryCountPtr, 
				 JVMDI_exception_handler_entry **tablePtr);

  JNIEXPORT jvmdiError JNICALL
  JVMDI_GetThrownExceptions(JNIEnv *env, jclass clazz, jmethodID method,
			    jint *exceptionCountPtr, jclass **exceptionsPtr);

  JNIEXPORT jvmdiError JNICALL
  JVMDI_GetBytecodes(JNIEnv *env, jclass clazz, jmethodID method,
		     jint *bytecodeCountPtr,
		     jbyte **bytecodesPtr);

  JNIEXPORT jvmdiError JNICALL
  JVMDI_IsMethodNative(JNIEnv *env, jclass clazz, jmethodID method, 
		       jboolean *isNativePtr);


  /* Events */

  JNIEXPORT jvmdiError JNICALL
  JVMDI_SetEventHook(JNIEnv *env, JVMDI_EventHook hook);


  /* Miscellaneous Functions */

  JNIEXPORT jvmdiError JNICALL
  JVMDI_GetLinkedClasses(JNIEnv *env, 
			 jint *classCountPtr, jclass **classesPtr);

  JNIEXPORT jvmdiError JNICALL
  JVMDI_GetVersionNumber(JNIEnv *env, jint *versionPtr);

#ifdef __cplusplus
}
#endif

#endif /* _jvmdi_h */
