/* -*- Mode: C; c-file-style: "gnu" -*-
   runtime.c -- native methods for java/lang/Runtime.
   Created: Chris Toshok <toshok@hungry.com>, 24-Oct-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 "arch.h"
#include "jniint.h"
#include "compat.h"
#include <assert.h>
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#include <string.h>
#include <stdlib.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif

#define MYLOG "Native"

JNIEXPORT void JNICALL
Java_java_lang_Runtime_exitInternal(JNIEnv *env,
				    jobject obj,
				    jint exit_status)
{
  HungryEnv *henv = HVM_ThreadGetEnv();

  if (henv->vm->exit)
    (*henv->vm->exit)(exit_status);
  else
    exit(exit_status);
}

JNIEXPORT void JNICALL
Java_java_lang_Runtime_runFinalizersOnExit0(JNIEnv *env,
					    jclass cls,
					    jboolean flag)
{
  HungryEnv *henv = HVM_ThreadGetEnv();

  henv->vm->_finalizers_on_exit = flag;
}

/*
 * For Classpath, not JDK
 */
JNIEXPORT void JNICALL
Java_java_lang_Runtime_runFinalizersOnExitInternal(JNIEnv *env,
                                                   jclass cls,
                                                   jboolean value)
{
  Java_java_lang_Runtime_runFinalizersOnExit0(env, cls, value);
}

JNIEXPORT jobject JNICALL
Java_java_lang_Runtime_execInternal(JNIEnv *env,
				    jobject obj,
				    jobjectArray cmdarray,
				    jobjectArray envp)
{
  jclass unixproc = (*env)->FindClass(env, "java/lang/UNIXProcess");
  jmethodID ctor = (*env)->GetMethodID(env, unixproc, "<init>", "([Ljava/lang/String;[Ljava/lang/String;)V");
  jobject new_proc;

  new_proc = (*env)->NewObject(env, unixproc, ctor, cmdarray, envp);

  return new_proc;
}

JNIEXPORT jlong JNICALL
Java_java_lang_Runtime_freeMemory(JNIEnv *env,
				  jobject obj)
{
  HungryEnv* henv = HVM_ThreadGetEnv();

  return HVM_GCGetFreeMemory(henv->vm);
}

JNIEXPORT jlong JNICALL
Java_java_lang_Runtime_totalMemory(JNIEnv *env,
				   jobject obj)
{
  HungryEnv* henv = HVM_ThreadGetEnv();

  return HVM_GCGetTotalMemory(henv->vm);
}

JNIEXPORT void JNICALL
Java_java_lang_Runtime_gc(JNIEnv *env,
			  jobject obj)
{
  HungryEnv* henv = HVM_ThreadGetEnv();

  HVM_GCCollect(henv->vm);
}

/* JDK1.1 */
JNIEXPORT void JNICALL
Java_java_lang_Runtime_runFinalization(JNIEnv *env,
				       jclass cls)
{
  HungryEnv* henv = HVM_ThreadGetEnv();

  HVM_GCRunFinalizers(henv->vm);
}

/*JDK 1.2 */
JNIEXPORT void JNICALL
Java_java_lang_Runtime_runFinalization0(JNIEnv *env,
					jclass cls)
{
  HungryEnv* henv = HVM_ThreadGetEnv();

  HVM_GCRunFinalizers(henv->vm);
}

JNIEXPORT void JNICALL
Java_java_lang_Runtime_traceInstructions(JNIEnv *env,
					 jobject obj,
					 jboolean on)
{
  (*env)->FatalError(env, "Java_java_lang_Runtime_traceInstructions not implemented");
}

JNIEXPORT void JNICALL
Java_java_lang_Runtime_traceMethodCalls(JNIEnv *env,
					jobject obj,
					jboolean on)
{
  (*env)->FatalError(env, "Java_java_lang_Runtime_traceMethodCalls not implemented");
}

/* JDK1.1 */
JNIEXPORT jstring JNICALL
Java_java_lang_Runtime_initializeLinkerInternal(JNIEnv *env,
						jobject obj)
{
  jstring ld_library_path;
  char *ld_env = getenv("LD_LIBRARY_PATH");
  char *ld_env_with_internal = NULL;

  /* LIBDIR is always in DLL path */
  if (ld_env == NULL)
    ld_env = LIBDIR;
  else
    {
      ld_env_with_internal = malloc(strlen(ld_env) + strlen(":" LIBDIR) + 1);
      strcpy(ld_env_with_internal, ld_env);
      strcat(ld_env_with_internal, ":" LIBDIR);
      ld_env = ld_env_with_internal;
    }

  ld_library_path = (*env)->NewStringUTF(env, ld_env);

  if (NULL != ld_env_with_internal)
    free(ld_env_with_internal);

  return ld_library_path;
}

/**
  * For Classpath, not JDK
  */
JNIEXPORT jstring JNICALL
Java_java_lang_Runtime_getLibraryPath(JNIEnv *env,
                                      jclass this_class)
{
  return(Java_java_lang_Runtime_initializeLinkerInternal(env, this_class));
}

JNIEXPORT jstring JNICALL
Java_java_lang_Runtime_buildLibName(JNIEnv *env,
				    jobject obj,
				    jobject pathname,
				    jobject filename)
{
  jstring lib_name;
  const jbyte* filename_bytes;
  jint filename_length;
  int libname_len;
  const jbyte* pathname_bytes;
  jint pathname_length;
  char *filename_str;
  char *pathname_str;
  char *libname_str;

  filename_bytes = (*env)->GetStringUTFChars(env, filename, NULL);
  filename_length = (*env)->GetStringUTFLength(env, filename) + 1;
  filename_str = (char*)malloc(filename_length * sizeof(char));

  strncpy(filename_str, (char*)filename_bytes, filename_length);

  (*env)->ReleaseStringUTFChars(env, filename, filename_bytes);

  pathname_bytes = (*env)->GetStringUTFChars(env, pathname, NULL);
  pathname_length = (*env)->GetStringUTFLength(env, pathname) + 1;
  pathname_str = (char*)malloc(pathname_length * sizeof(char));

  strncpy(pathname_str, (char*)pathname_bytes, pathname_length);

  (*env)->ReleaseStringUTFChars(env, pathname, pathname_bytes);
  libname_len = strlen(pathname_str) + strlen(filename_str) + strlen("/libjaphar_") + 1;
  libname_str = (char*)malloc(libname_len);

  PR_snprintf(libname_str, libname_len, "%s/libjaphar_%s",
	      pathname_str, filename_str);

  free(pathname_str);
  free(filename_str);

  lib_name = (*env)->NewStringUTF(env, libname_str);

  free(libname_str);

  return lib_name;
}

/*
 * For Classpath, not JDK
 */
JNIEXPORT jstring JNICALL
Java_java_lang_Runtime_nativeGetLibname(JNIEnv *env,
				        jobject obj,
				        jobject pathname,
				        jobject filename)
{
  return(Java_java_lang_Runtime_buildLibName(env, obj, pathname, filename));
}


/* JDK1.1 */
JNIEXPORT jint JNICALL
Java_java_lang_Runtime_loadFileInternal(JNIEnv *env,
					jobject obj,
					jobject filename)
{
  HVMDllLibHandle handle;
  int filename_length;
  const jbyte *filename_bytes;
  char *filename_str;
  HungryEnv *henv = HVM_ThreadGetEnv();

  filename_bytes = (*env)->GetStringUTFChars(env, filename, NULL);

  filename_length = (*env)->GetStringUTFLength(env, filename) + 1;
  filename_str = (char*)malloc(filename_length * sizeof(char));

  strncpy(filename_str, (char*)filename_bytes, filename_length);

  (*env)->ReleaseStringUTFChars(env, filename, filename_bytes);
  
  if (henv->vm->_verbose_flags & VERBOSE_DLL)
    printf("[DLL %s loading...", filename_str);

  handle = HVM_DllLoad(filename_str);

  free(filename_str);

  if (handle)
    {
      if (henv->vm->_verbose_flags & VERBOSE_DLL)
	printf(" succeeded.]\n");
      return 1;
    }
  else
    {
      if (henv->vm->_verbose_flags & VERBOSE_DLL)
	printf(" failed.]\n");
      return 0;
    }
}

/*
 * For Classpath, not JDk
 */
JNIEXPORT jint JNICALL
Java_java_lang_Runtime_nativeLoad(JNIEnv *env,
				  jobject obj,
				  jobject filename)
{
  return(Java_java_lang_Runtime_loadFileInternal(env, obj, filename));
}

