2011-07-13 14:25:21 +00:00
|
|
|
/* Copyright (c) 2008-2011, Avian Contributors
|
2008-02-19 18:06:52 +00:00
|
|
|
|
|
|
|
Permission to use, copy, modify, and/or distribute this software
|
|
|
|
for any purpose with or without fee is hereby granted, provided
|
|
|
|
that the above copyright notice and this permission notice appear
|
|
|
|
in all copies.
|
|
|
|
|
|
|
|
There is NO WARRANTY for this software. See license.txt for
|
|
|
|
details. */
|
2009-07-01 15:13:01 +00:00
|
|
|
|
2007-10-11 21:39:21 +00:00
|
|
|
#include "math.h"
|
|
|
|
#include "stdlib.h"
|
2007-07-28 16:10:13 +00:00
|
|
|
#include "time.h"
|
2007-07-07 23:47:35 +00:00
|
|
|
#include "string.h"
|
2007-09-12 01:13:05 +00:00
|
|
|
#include "stdio.h"
|
2011-06-01 19:56:03 +00:00
|
|
|
#include "jni.h"
|
2007-08-27 13:46:17 +00:00
|
|
|
#include "jni-util.h"
|
2007-11-30 23:39:51 +00:00
|
|
|
#include "errno.h"
|
|
|
|
#include "fcntl.h"
|
2010-10-07 22:32:59 +00:00
|
|
|
#include "ctype.h"
|
2007-06-25 01:34:07 +00:00
|
|
|
|
2009-08-27 00:26:44 +00:00
|
|
|
#ifdef PLATFORM_WINDOWS
|
|
|
|
|
2007-10-23 17:22:48 +00:00
|
|
|
# include "windows.h"
|
2007-11-30 01:01:07 +00:00
|
|
|
# include "winbase.h"
|
2007-11-29 00:52:08 +00:00
|
|
|
# include "io.h"
|
|
|
|
# include "tchar.h"
|
2009-08-27 00:26:44 +00:00
|
|
|
# include "float.h"
|
2008-06-17 15:05:57 +00:00
|
|
|
# include "sys/types.h"
|
|
|
|
# include "sys/timeb.h"
|
2007-10-24 16:24:02 +00:00
|
|
|
# define SO_PREFIX ""
|
2009-08-27 00:26:44 +00:00
|
|
|
# define SO_SUFFIX ".dll"
|
|
|
|
|
|
|
|
# ifdef _MSC_VER
|
|
|
|
# define snprintf sprintf_s
|
|
|
|
# define isnan _isnan
|
|
|
|
# define isfinite _finite
|
|
|
|
# define strtof strtod
|
|
|
|
# endif
|
|
|
|
|
|
|
|
#else // not PLATFORM_WINDOWS
|
|
|
|
|
2007-10-24 16:24:02 +00:00
|
|
|
# define SO_PREFIX "lib"
|
2009-08-27 00:26:44 +00:00
|
|
|
# ifdef __APPLE__
|
|
|
|
# define SO_SUFFIX ".jnilib"
|
2011-08-11 01:21:48 +00:00
|
|
|
# ifndef ARCH_arm
|
|
|
|
# include <CoreServices/CoreServices.h>
|
|
|
|
# endif
|
2009-08-27 00:26:44 +00:00
|
|
|
# else
|
|
|
|
# define SO_SUFFIX ".so"
|
|
|
|
# endif
|
|
|
|
# include "unistd.h"
|
2011-07-11 16:44:06 +00:00
|
|
|
# include "limits.h"
|
2011-11-04 15:37:24 +00:00
|
|
|
# include "signal.h"
|
2009-08-27 00:26:44 +00:00
|
|
|
# include "sys/time.h"
|
2011-11-04 15:37:24 +00:00
|
|
|
# include "sys/types.h"
|
2009-08-27 00:26:44 +00:00
|
|
|
# include "sys/sysctl.h"
|
|
|
|
# include "sys/utsname.h"
|
|
|
|
# include "sys/wait.h"
|
2007-10-24 16:24:02 +00:00
|
|
|
|
2009-08-27 00:26:44 +00:00
|
|
|
#endif // not PLATFORM_WINDOWS
|
2007-09-20 16:13:41 +00:00
|
|
|
|
2007-11-29 00:52:08 +00:00
|
|
|
namespace {
|
2009-08-27 00:26:44 +00:00
|
|
|
#ifdef PLATFORM_WINDOWS
|
2007-11-30 01:01:07 +00:00
|
|
|
char* getErrorStr(DWORD err){
|
|
|
|
// The poor man's error string, just print the error code
|
|
|
|
char * errStr = (char*) malloc(9 * sizeof(char));
|
|
|
|
snprintf(errStr, 9, "%d", (int) err);
|
|
|
|
return errStr;
|
|
|
|
|
|
|
|
// The better way to do this, if I could figure out how to convert LPTSTR to char*
|
|
|
|
//char* errStr;
|
|
|
|
//LPTSTR s;
|
|
|
|
//if(FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
|
|
|
|
// FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, 0, &s, 0, NULL) == 0)
|
|
|
|
//{
|
|
|
|
// errStr.Format("Unknown error occurred (%08x)", err);
|
|
|
|
//} else {
|
|
|
|
// errStr = s;
|
|
|
|
//}
|
|
|
|
//return errStr;
|
|
|
|
}
|
|
|
|
|
2007-11-29 00:52:08 +00:00
|
|
|
void makePipe(JNIEnv* e, HANDLE p[2])
|
|
|
|
{
|
|
|
|
SECURITY_ATTRIBUTES sa;
|
|
|
|
sa.nLength = sizeof(sa);
|
|
|
|
sa.bInheritHandle = 1;
|
|
|
|
sa.lpSecurityDescriptor = 0;
|
|
|
|
|
|
|
|
BOOL success = CreatePipe(p, p + 1, &sa, 0);
|
|
|
|
if (not success) {
|
2007-11-30 01:01:07 +00:00
|
|
|
throwNew(e, "java/io/IOException", getErrorStr(GetLastError()));
|
2007-11-29 00:52:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int descriptor(JNIEnv* e, HANDLE h)
|
|
|
|
{
|
2009-06-05 20:32:36 +00:00
|
|
|
int fd = _open_osfhandle(reinterpret_cast<intptr_t>(h), 0);
|
2007-11-29 00:52:08 +00:00
|
|
|
if (fd == -1) {
|
2009-08-27 00:26:44 +00:00
|
|
|
throwNewErrno(e, "java/io/IOException");
|
2007-11-29 00:52:08 +00:00
|
|
|
}
|
|
|
|
return fd;
|
|
|
|
}
|
2007-11-30 23:39:51 +00:00
|
|
|
#else
|
|
|
|
void makePipe(JNIEnv* e, int p[2])
|
|
|
|
{
|
|
|
|
if(pipe(p) != 0) {
|
2009-08-27 00:26:44 +00:00
|
|
|
throwNewErrno(e, "java/io/IOException");
|
2007-11-30 23:39:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void safeClose(int &fd)
|
|
|
|
{
|
|
|
|
if(fd != -1) close(fd);
|
|
|
|
fd = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void close(int p[2])
|
|
|
|
{
|
|
|
|
::close(p[0]);
|
|
|
|
::close(p[1]);
|
|
|
|
}
|
|
|
|
|
|
|
|
void clean(JNIEnv* e, jobjectArray command, char** p)
|
|
|
|
{
|
|
|
|
int i = 0;
|
|
|
|
for(char** x = p; *x; ++x, ++i){
|
|
|
|
jstring element = (jstring) e->GetObjectArrayElement(command, i);
|
|
|
|
e->ReleaseStringUTFChars(element, *x);
|
|
|
|
}
|
|
|
|
free(p);
|
|
|
|
}
|
2007-11-29 00:52:08 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2010-10-14 22:20:41 +00:00
|
|
|
class Locale { // represents an ISO two-char language/country pair
|
|
|
|
static const unsigned FIELDLEN = 2;
|
|
|
|
static const unsigned FIELDSIZE = FIELDLEN + 1;
|
2010-10-07 22:32:59 +00:00
|
|
|
|
|
|
|
static const char* DEFAULT_LANGUAGE;
|
|
|
|
static const char* DEFAULT_REGION;
|
|
|
|
|
|
|
|
char language[FIELDSIZE];
|
|
|
|
char region[FIELDSIZE];
|
|
|
|
|
|
|
|
bool isLanguage(const char* language) {
|
|
|
|
if (!language) return false;
|
|
|
|
unsigned len = strlen(language);
|
2010-10-14 22:20:41 +00:00
|
|
|
if (len != FIELDLEN) return false;
|
2010-10-07 22:32:59 +00:00
|
|
|
const char* p = language - 1;
|
2010-11-08 16:47:46 +00:00
|
|
|
while (islower(*++p)) ;
|
2010-10-07 22:32:59 +00:00
|
|
|
if (*p != '\0') return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool isRegion(const char* region) {
|
|
|
|
if (!region) return false;
|
|
|
|
unsigned len = strlen(region);
|
2010-10-14 22:20:41 +00:00
|
|
|
if (len != FIELDLEN) return false;
|
2010-10-07 22:32:59 +00:00
|
|
|
const char* p = region - 1;
|
2010-11-08 16:47:46 +00:00
|
|
|
while (isupper(*++p)) ;
|
2010-10-07 22:32:59 +00:00
|
|
|
if (*p != '\0') return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
2010-10-14 22:20:41 +00:00
|
|
|
Locale(const char* language = "") {
|
|
|
|
Locale l(language, "");
|
|
|
|
*this = l;
|
|
|
|
}
|
|
|
|
|
|
|
|
Locale(const char* language, const char* region) {
|
|
|
|
language = isLanguage(language) ? language : DEFAULT_LANGUAGE;
|
|
|
|
region = isRegion(region) ? region : DEFAULT_REGION;
|
|
|
|
memcpy(this->language, language, FIELDSIZE);
|
|
|
|
memcpy(this->region, region, FIELDSIZE);
|
2010-10-07 22:32:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Locale& operator=(const Locale& l) {
|
|
|
|
memcpy(language, l.language, FIELDSIZE);
|
|
|
|
memcpy(region, l.region, FIELDSIZE);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char* getLanguage() { return reinterpret_cast<const char*>(language); }
|
|
|
|
const char* getRegion() { return reinterpret_cast<const char*>(region); }
|
|
|
|
};
|
|
|
|
const char* Locale::DEFAULT_LANGUAGE = "en";
|
|
|
|
const char* Locale::DEFAULT_REGION = "";
|
|
|
|
|
2009-08-27 00:26:44 +00:00
|
|
|
#ifdef PLATFORM_WINDOWS
|
2007-11-30 01:01:07 +00:00
|
|
|
extern "C" JNIEXPORT void JNICALL
|
|
|
|
Java_java_lang_Runtime_exec(JNIEnv* e, jclass,
|
|
|
|
jobjectArray command, jlongArray process)
|
2007-11-29 00:52:08 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
int size = 0;
|
|
|
|
for (int i = 0; i < e->GetArrayLength(command); ++i){
|
|
|
|
jstring element = (jstring) e->GetObjectArrayElement(command, i);
|
|
|
|
size += e->GetStringUTFLength(element) + 1;
|
|
|
|
}
|
|
|
|
|
2009-08-27 00:26:44 +00:00
|
|
|
RUNTIME_ARRAY(char, line, size);
|
|
|
|
char* linep = RUNTIME_ARRAY_BODY(line);
|
2007-11-29 00:52:08 +00:00
|
|
|
for (int i = 0; i < e->GetArrayLength(command); ++i) {
|
|
|
|
if (i) *(linep++) = _T(' ');
|
|
|
|
jstring element = (jstring) e->GetObjectArrayElement(command, i);
|
|
|
|
const char* s = e->GetStringUTFChars(element, 0);
|
2009-08-27 00:26:44 +00:00
|
|
|
#ifdef _MSC_VER
|
|
|
|
_tcscpy_s(linep, size - (linep - RUNTIME_ARRAY_BODY(line)), s);
|
|
|
|
#else
|
2007-11-29 00:52:08 +00:00
|
|
|
_tcscpy(linep, s);
|
2009-08-27 00:26:44 +00:00
|
|
|
#endif
|
2007-11-30 01:01:07 +00:00
|
|
|
e->ReleaseStringUTFChars(element, s);
|
2007-11-29 00:52:08 +00:00
|
|
|
linep += e->GetStringUTFLength(element);
|
|
|
|
}
|
|
|
|
*(linep++) = _T('\0');
|
|
|
|
|
|
|
|
HANDLE in[] = { 0, 0 };
|
|
|
|
HANDLE out[] = { 0, 0 };
|
|
|
|
HANDLE err[] = { 0, 0 };
|
|
|
|
|
|
|
|
makePipe(e, in);
|
|
|
|
SetHandleInformation(in[0], HANDLE_FLAG_INHERIT, 0);
|
2007-11-30 01:01:07 +00:00
|
|
|
jlong inDescriptor = static_cast<jlong>(descriptor(e, in[0]));
|
2009-12-17 02:25:03 +00:00
|
|
|
if(e->ExceptionCheck()) return;
|
2010-11-09 21:56:26 +00:00
|
|
|
e->SetLongArrayRegion(process, 2, 1, &inDescriptor);
|
2007-11-29 00:52:08 +00:00
|
|
|
makePipe(e, out);
|
|
|
|
SetHandleInformation(out[1], HANDLE_FLAG_INHERIT, 0);
|
2007-11-30 01:01:07 +00:00
|
|
|
jlong outDescriptor = static_cast<jlong>(descriptor(e, out[1]));
|
2009-12-17 02:25:03 +00:00
|
|
|
if(e->ExceptionCheck()) return;
|
2010-11-09 21:56:26 +00:00
|
|
|
e->SetLongArrayRegion(process, 3, 1, &outDescriptor);
|
2007-11-29 00:52:08 +00:00
|
|
|
makePipe(e, err);
|
|
|
|
SetHandleInformation(err[0], HANDLE_FLAG_INHERIT, 0);
|
2007-11-30 01:01:07 +00:00
|
|
|
jlong errDescriptor = static_cast<jlong>(descriptor(e, err[0]));
|
2009-12-17 02:25:03 +00:00
|
|
|
if(e->ExceptionCheck()) return;
|
2010-11-09 21:56:26 +00:00
|
|
|
e->SetLongArrayRegion(process, 4, 1, &errDescriptor);
|
2007-11-29 00:52:08 +00:00
|
|
|
|
|
|
|
PROCESS_INFORMATION pi;
|
|
|
|
ZeroMemory(&pi, sizeof(pi));
|
|
|
|
|
|
|
|
STARTUPINFO si;
|
|
|
|
ZeroMemory(&si, sizeof(si));
|
|
|
|
si.cb = sizeof(si);
|
|
|
|
si.dwFlags = STARTF_USESTDHANDLES;
|
|
|
|
si.hStdOutput = in[1];
|
|
|
|
si.hStdInput = out[0];
|
|
|
|
si.hStdError = err[1];
|
|
|
|
|
2009-08-27 00:26:44 +00:00
|
|
|
BOOL success = CreateProcess(0, (LPSTR) RUNTIME_ARRAY_BODY(line), 0, 0, 1,
|
2007-11-29 00:52:08 +00:00
|
|
|
CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT,
|
|
|
|
0, 0, &si, &pi);
|
2010-11-09 17:22:23 +00:00
|
|
|
|
|
|
|
CloseHandle(in[1]);
|
|
|
|
CloseHandle(out[0]);
|
|
|
|
CloseHandle(err[1]);
|
2007-11-29 00:52:08 +00:00
|
|
|
|
|
|
|
if (not success) {
|
2007-11-30 01:01:07 +00:00
|
|
|
throwNew(e, "java/io/IOException", getErrorStr(GetLastError()));
|
2007-11-29 00:52:08 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2007-11-30 01:01:07 +00:00
|
|
|
jlong pid = reinterpret_cast<jlong>(pi.hProcess);
|
|
|
|
e->SetLongArrayRegion(process, 0, 1, &pid);
|
2010-11-09 21:56:26 +00:00
|
|
|
jlong tid = reinterpret_cast<jlong>(pi.hThread);
|
|
|
|
e->SetLongArrayRegion(process, 1, 1, &tid);
|
2007-11-29 00:52:08 +00:00
|
|
|
}
|
2007-11-30 01:01:07 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
2010-11-09 21:56:26 +00:00
|
|
|
Java_java_lang_Runtime_waitFor(JNIEnv* e, jclass, jlong pid, jlong tid)
|
2007-11-30 01:01:07 +00:00
|
|
|
{
|
|
|
|
DWORD exitCode;
|
|
|
|
WaitForSingleObject(reinterpret_cast<HANDLE>(pid), INFINITE);
|
|
|
|
BOOL success = GetExitCodeProcess(reinterpret_cast<HANDLE>(pid), &exitCode);
|
|
|
|
if(not success){
|
|
|
|
throwNew(e, "java/lang/Exception", getErrorStr(GetLastError()));
|
|
|
|
}
|
2010-11-09 21:56:26 +00:00
|
|
|
|
|
|
|
CloseHandle(reinterpret_cast<HANDLE>(pid));
|
|
|
|
CloseHandle(reinterpret_cast<HANDLE>(tid));
|
|
|
|
|
2007-11-30 01:01:07 +00:00
|
|
|
return exitCode;
|
|
|
|
}
|
2010-10-05 23:24:44 +00:00
|
|
|
|
2011-11-03 18:30:51 +00:00
|
|
|
extern "C" JNIEXPORT void JNICALL
|
|
|
|
Java_java_lang_Runtime_kill(JNIEnv*, jclass, jlong pid) {
|
|
|
|
TerminateProcess(reinterpret_cast<HANDLE>(pid), 1);
|
|
|
|
}
|
|
|
|
|
2010-10-07 22:32:59 +00:00
|
|
|
Locale getLocale() {
|
|
|
|
const char* lang = "";
|
|
|
|
const char* reg = "";
|
|
|
|
unsigned langid = GetUserDefaultUILanguage();
|
|
|
|
unsigned prilang = langid & 0x3ff;
|
|
|
|
unsigned sublang = langid >> 10;
|
2010-10-05 23:24:44 +00:00
|
|
|
|
|
|
|
switch (prilang) {
|
|
|
|
case 0x004: {
|
|
|
|
lang = "zh";
|
|
|
|
switch (sublang) {
|
2010-10-14 22:20:41 +00:00
|
|
|
case 0x01: reg = "CN"; break;
|
|
|
|
case 0x02: reg = "TW"; break;
|
2010-10-05 23:24:44 +00:00
|
|
|
case 0x03: reg = "HK"; break;
|
|
|
|
case 0x04: reg = "SG"; break;
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
case 0x006: lang = "da"; reg = "DK"; break;
|
|
|
|
case 0x007: lang = "de"; reg = "DE"; break;
|
|
|
|
case 0x009: {
|
|
|
|
lang = "en";
|
|
|
|
switch (sublang) {
|
|
|
|
case 0x01: reg = "US"; break;
|
|
|
|
case 0x02: reg = "GB"; break;
|
|
|
|
case 0x03: reg = "AU"; break;
|
|
|
|
case 0x04: reg = "CA"; break;
|
|
|
|
case 0x05: reg = "NZ"; break;
|
|
|
|
case 0x06: reg = "IE"; break;
|
|
|
|
case 0x07: reg = "ZA"; break;
|
|
|
|
case 0x10: reg = "IN"; break;
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
case 0x00a: {
|
|
|
|
lang = "es";
|
|
|
|
switch (sublang) {
|
2010-10-05 23:53:17 +00:00
|
|
|
case 0x01: case 0x03: reg = "ES"; break;
|
2010-10-05 23:24:44 +00:00
|
|
|
case 0x02: reg = "MX"; break;
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
case 0x00c: {
|
|
|
|
lang = "fr";
|
|
|
|
switch (sublang) {
|
|
|
|
case 0x01: reg = "FR"; break;
|
|
|
|
case 0x02: reg = "BE"; break;
|
|
|
|
case 0x03: reg = "CA"; break;
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
case 0x010: lang = "it"; reg = "IT"; break;
|
|
|
|
case 0x011: lang = "ja"; reg = "JP"; break;
|
|
|
|
case 0x012: lang = "ko"; reg = "KR"; break;
|
|
|
|
case 0x013: {
|
|
|
|
lang = "nl";
|
|
|
|
switch (sublang) {
|
|
|
|
case 0x01: reg = "NL"; break;
|
|
|
|
case 0x02: reg = "BE"; break;
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
case 0x014: lang = "no"; reg = "NO"; break;
|
|
|
|
case 0x015: lang = "pl"; reg = "PL"; break;
|
|
|
|
case 0x016: {
|
|
|
|
lang = "pt";
|
|
|
|
switch (sublang) {
|
|
|
|
case 0x01: reg = "BR"; break;
|
|
|
|
case 0x02: reg = "PT"; break;
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
case 0x018: lang = "ro"; reg = "RO"; break;
|
|
|
|
case 0x019: lang = "ru"; reg = "RU"; break;
|
|
|
|
case 0x01d: lang = "sv"; reg = "SE"; break;
|
2010-10-07 22:32:59 +00:00
|
|
|
default: lang = "en";
|
2010-10-05 23:24:44 +00:00
|
|
|
}
|
|
|
|
|
2010-10-07 22:32:59 +00:00
|
|
|
Locale locale(lang, reg);
|
|
|
|
return locale;
|
2010-10-05 23:24:44 +00:00
|
|
|
}
|
2007-11-30 23:39:51 +00:00
|
|
|
#else
|
|
|
|
extern "C" JNIEXPORT void JNICALL
|
|
|
|
Java_java_lang_Runtime_exec(JNIEnv* e, jclass,
|
|
|
|
jobjectArray command, jlongArray process)
|
|
|
|
{
|
2010-10-22 20:39:38 +00:00
|
|
|
char** argv = static_cast<char**>
|
|
|
|
(malloc((e->GetArrayLength(command) + 1) * sizeof(char*)));
|
2007-11-30 23:39:51 +00:00
|
|
|
int i;
|
|
|
|
for(i = 0; i < e->GetArrayLength(command); i++){
|
|
|
|
jstring element = (jstring) e->GetObjectArrayElement(command, i);
|
|
|
|
char* s = const_cast<char*>(e->GetStringUTFChars(element, 0));
|
|
|
|
argv[i] = s;
|
|
|
|
}
|
|
|
|
argv[i] = 0;
|
|
|
|
|
|
|
|
int in[] = { -1, -1 };
|
|
|
|
int out[] = { -1, -1 };
|
|
|
|
int err[] = { -1, -1 };
|
|
|
|
int msg[] = { -1, -1 };
|
|
|
|
|
|
|
|
makePipe(e, in);
|
2009-12-17 02:25:03 +00:00
|
|
|
if(e->ExceptionCheck()) return;
|
2007-11-30 23:39:51 +00:00
|
|
|
jlong inDescriptor = static_cast<jlong>(in[0]);
|
2010-11-09 21:56:26 +00:00
|
|
|
e->SetLongArrayRegion(process, 2, 1, &inDescriptor);
|
2007-11-30 23:39:51 +00:00
|
|
|
makePipe(e, out);
|
2009-12-17 02:25:03 +00:00
|
|
|
if(e->ExceptionCheck()) return;
|
2007-11-30 23:39:51 +00:00
|
|
|
jlong outDescriptor = static_cast<jlong>(out[1]);
|
2010-11-09 21:56:26 +00:00
|
|
|
e->SetLongArrayRegion(process, 3, 1, &outDescriptor);
|
2007-11-30 23:39:51 +00:00
|
|
|
makePipe(e, err);
|
2009-12-17 02:25:03 +00:00
|
|
|
if(e->ExceptionCheck()) return;
|
2007-11-30 23:39:51 +00:00
|
|
|
jlong errDescriptor = static_cast<jlong>(err[0]);
|
2010-11-09 21:56:26 +00:00
|
|
|
e->SetLongArrayRegion(process, 4, 1, &errDescriptor);
|
2007-11-30 23:39:51 +00:00
|
|
|
makePipe(e, msg);
|
2009-12-17 02:25:03 +00:00
|
|
|
if(e->ExceptionCheck()) return;
|
2007-11-30 23:39:51 +00:00
|
|
|
if(fcntl(msg[1], F_SETFD, FD_CLOEXEC) != 0) {
|
2009-08-27 00:26:44 +00:00
|
|
|
throwNewErrno(e, "java/io/IOException");
|
2007-11-30 23:39:51 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
pid_t pid = fork();
|
|
|
|
switch(pid){
|
|
|
|
case -1: // error
|
2009-08-27 00:26:44 +00:00
|
|
|
throwNewErrno(e, "java/io/IOException");
|
2007-11-30 23:39:51 +00:00
|
|
|
return;
|
|
|
|
case 0: { // child
|
|
|
|
// Setup stdin, stdout and stderr
|
|
|
|
dup2(in[1], 1);
|
|
|
|
close(in);
|
|
|
|
dup2(out[0], 0);
|
|
|
|
close(out);
|
|
|
|
dup2(err[1], 2);
|
|
|
|
close(err);
|
|
|
|
close(msg[0]);
|
|
|
|
|
|
|
|
execvp(argv[0], argv);
|
|
|
|
|
|
|
|
// Error if here
|
2011-08-15 13:12:52 +00:00
|
|
|
int val = errno;
|
|
|
|
ssize_t rv UNUSED = write(msg[1], &val, sizeof(val));
|
2007-11-30 23:39:51 +00:00
|
|
|
exit(127);
|
|
|
|
} break;
|
|
|
|
|
|
|
|
default: { //parent
|
|
|
|
jlong JNIPid = static_cast<jlong>(pid);
|
|
|
|
e->SetLongArrayRegion(process, 0, 1, &JNIPid);
|
|
|
|
|
|
|
|
safeClose(in[1]);
|
|
|
|
safeClose(out[0]);
|
|
|
|
safeClose(err[1]);
|
|
|
|
safeClose(msg[1]);
|
|
|
|
|
2011-08-15 13:12:52 +00:00
|
|
|
int val;
|
|
|
|
int r = read(msg[0], &val, sizeof(val));
|
2007-11-30 23:39:51 +00:00
|
|
|
if(r == -1) {
|
2009-08-27 00:26:44 +00:00
|
|
|
throwNewErrno(e, "java/io/IOException");
|
2007-11-30 23:39:51 +00:00
|
|
|
return;
|
|
|
|
} else if(r) {
|
2011-08-15 13:12:52 +00:00
|
|
|
errno = val;
|
2009-08-27 00:26:44 +00:00
|
|
|
throwNewErrno(e, "java/io/IOException");
|
2007-11-30 23:39:51 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
}
|
|
|
|
|
|
|
|
safeClose(msg[0]);
|
|
|
|
clean(e, command, argv);
|
|
|
|
|
|
|
|
fcntl(in[0], F_SETFD, FD_CLOEXEC);
|
|
|
|
fcntl(out[1], F_SETFD, FD_CLOEXEC);
|
|
|
|
fcntl(err[0], F_SETFD, FD_CLOEXEC);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
2010-11-09 21:56:26 +00:00
|
|
|
Java_java_lang_Runtime_waitFor(JNIEnv*, jclass, jlong pid, jlong)
|
2007-11-30 23:39:51 +00:00
|
|
|
{
|
|
|
|
bool finished = false;
|
|
|
|
int status;
|
|
|
|
int exitCode;
|
|
|
|
while(!finished){
|
|
|
|
waitpid(pid, &status, 0);
|
|
|
|
if(WIFEXITED(status)){
|
|
|
|
finished = true;
|
|
|
|
exitCode = WEXITSTATUS(status);
|
|
|
|
} else if(WIFSIGNALED(status)){
|
|
|
|
finished = true;
|
|
|
|
exitCode = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return exitCode;
|
|
|
|
}
|
2010-10-05 23:24:44 +00:00
|
|
|
|
2011-11-03 18:30:51 +00:00
|
|
|
extern "C" JNIEXPORT void JNICALL
|
|
|
|
Java_java_lang_Runtime_kill(JNIEnv*, jclass, jlong pid) {
|
|
|
|
kill((pid_t)pid, SIGTERM);
|
|
|
|
}
|
|
|
|
|
2010-10-07 22:32:59 +00:00
|
|
|
Locale getLocale() {
|
|
|
|
Locale fallback;
|
|
|
|
|
2010-10-05 23:24:44 +00:00
|
|
|
const char* LANG = getenv("LANG");
|
2010-10-07 22:32:59 +00:00
|
|
|
if (!LANG || strcmp(LANG, "C") == 0) return fallback;
|
2010-10-05 23:24:44 +00:00
|
|
|
|
2010-10-07 22:32:59 +00:00
|
|
|
int len = strlen(LANG);
|
2011-04-05 21:13:29 +00:00
|
|
|
char buf[len + 1]; // + 1 for the '\0' char
|
|
|
|
memcpy(buf, LANG, len + 1);
|
2010-10-05 23:24:44 +00:00
|
|
|
|
2010-10-07 22:32:59 +00:00
|
|
|
char* tracer = buf;
|
|
|
|
const char* reg;
|
|
|
|
|
|
|
|
while (*tracer && *tracer != '_') ++tracer;
|
|
|
|
if (!*tracer) return fallback;
|
|
|
|
*tracer = '\0';
|
2011-04-05 21:13:29 +00:00
|
|
|
reg = ++tracer;
|
2010-10-07 22:32:59 +00:00
|
|
|
|
|
|
|
while (*tracer && *tracer != '.') ++tracer;
|
|
|
|
if (tracer == reg) return fallback;
|
|
|
|
*tracer = '\0';
|
|
|
|
|
|
|
|
Locale locale(buf, reg);
|
|
|
|
return locale;
|
2010-10-05 23:24:44 +00:00
|
|
|
}
|
2007-11-29 00:52:08 +00:00
|
|
|
#endif
|
|
|
|
|
2007-07-07 23:47:35 +00:00
|
|
|
extern "C" JNIEXPORT jstring JNICALL
|
2007-10-26 18:13:21 +00:00
|
|
|
Java_java_lang_System_getProperty(JNIEnv* e, jclass, jstring name,
|
|
|
|
jbooleanArray found)
|
2007-07-07 23:47:35 +00:00
|
|
|
{
|
2007-10-26 18:13:21 +00:00
|
|
|
jstring r = 0;
|
|
|
|
const char* chars = e->GetStringUTFChars(name, 0);
|
|
|
|
if (chars) {
|
2009-08-27 00:26:44 +00:00
|
|
|
#ifdef PLATFORM_WINDOWS
|
2007-10-26 18:13:21 +00:00
|
|
|
if (strcmp(chars, "line.separator") == 0) {
|
|
|
|
r = e->NewStringUTF("\r\n");
|
|
|
|
} else if (strcmp(chars, "file.separator") == 0) {
|
|
|
|
r = e->NewStringUTF("\\");
|
|
|
|
} else if (strcmp(chars, "os.name") == 0) {
|
2008-01-18 15:35:20 +00:00
|
|
|
r = e->NewStringUTF("Windows");
|
2009-07-01 15:13:01 +00:00
|
|
|
} else if (strcmp(chars, "os.version") == 0) {
|
|
|
|
unsigned size = 32;
|
2009-08-27 00:26:44 +00:00
|
|
|
RUNTIME_ARRAY(char, buffer, size);
|
2009-07-01 15:13:01 +00:00
|
|
|
OSVERSIONINFO OSversion;
|
|
|
|
OSversion.dwOSVersionInfoSize=sizeof(OSVERSIONINFO);
|
|
|
|
::GetVersionEx(&OSversion);
|
2009-08-27 00:26:44 +00:00
|
|
|
snprintf(RUNTIME_ARRAY_BODY(buffer), size, "%i.%i", (int)OSversion.dwMajorVersion, (int)OSversion.dwMinorVersion);
|
|
|
|
r = e->NewStringUTF(RUNTIME_ARRAY_BODY(buffer));
|
2009-07-28 16:16:27 +00:00
|
|
|
} else if (strcmp(chars, "os.arch") == 0) {
|
2009-08-27 00:26:44 +00:00
|
|
|
#ifdef ARCH_x86_32
|
2009-07-28 16:16:27 +00:00
|
|
|
r = e->NewStringUTF("x86");
|
2009-08-27 00:26:44 +00:00
|
|
|
#elif defined ARCH_x86_64
|
|
|
|
r = e->NewStringUTF("x86_64");
|
|
|
|
#elif defined ARCH_powerpc
|
|
|
|
r = e->NewStringUTF("ppc");
|
|
|
|
#elif defined ARCH_arm
|
|
|
|
r = e->NewStringUTF("arm");
|
|
|
|
#endif
|
2007-10-26 18:13:21 +00:00
|
|
|
} else if (strcmp(chars, "java.io.tmpdir") == 0) {
|
|
|
|
TCHAR buffer[MAX_PATH];
|
|
|
|
GetTempPath(MAX_PATH, buffer);
|
|
|
|
r = e->NewStringUTF(buffer);
|
2010-09-20 23:28:42 +00:00
|
|
|
} else if (strcmp(chars, "user.dir") == 0) {
|
|
|
|
TCHAR buffer[MAX_PATH];
|
|
|
|
GetCurrentDirectory(MAX_PATH, buffer);
|
|
|
|
r = e->NewStringUTF(buffer);
|
2007-10-26 18:13:21 +00:00
|
|
|
} else if (strcmp(chars, "user.home") == 0) {
|
2009-08-27 00:26:44 +00:00
|
|
|
# ifdef _MSC_VER
|
|
|
|
WCHAR buffer[MAX_PATH];
|
2009-12-13 00:55:00 +00:00
|
|
|
size_t needed;
|
|
|
|
if (_wgetenv_s(&needed, buffer, MAX_PATH, L"USERPROFILE") == 0) {
|
2009-08-27 00:26:44 +00:00
|
|
|
r = e->NewString(reinterpret_cast<jchar*>(buffer), lstrlenW(buffer));
|
|
|
|
} else {
|
|
|
|
r = 0;
|
|
|
|
}
|
|
|
|
# else
|
2007-10-26 18:13:21 +00:00
|
|
|
LPWSTR home = _wgetenv(L"USERPROFILE");
|
|
|
|
r = e->NewString(reinterpret_cast<jchar*>(home), lstrlenW(home));
|
2009-08-27 00:26:44 +00:00
|
|
|
# endif
|
2007-10-26 18:13:21 +00:00
|
|
|
}
|
|
|
|
#else
|
|
|
|
if (strcmp(chars, "line.separator") == 0) {
|
|
|
|
r = e->NewStringUTF("\n");
|
|
|
|
} else if (strcmp(chars, "file.separator") == 0) {
|
|
|
|
r = e->NewStringUTF("/");
|
|
|
|
} else if (strcmp(chars, "os.name") == 0) {
|
2008-01-18 15:35:20 +00:00
|
|
|
#ifdef __APPLE__
|
|
|
|
r = e->NewStringUTF("Mac OS X");
|
|
|
|
#else
|
|
|
|
r = e->NewStringUTF("Linux");
|
2009-07-01 15:13:01 +00:00
|
|
|
#endif
|
|
|
|
} else if (strcmp(chars, "os.version") == 0) {
|
2011-09-22 22:55:45 +00:00
|
|
|
#if (defined __APPLE__) && (! defined AVIAN_IOS)
|
2009-07-02 09:13:39 +00:00
|
|
|
unsigned size = 32;
|
2009-07-01 15:13:01 +00:00
|
|
|
char buffer[size];
|
2009-10-19 16:31:34 +00:00
|
|
|
#ifdef ARCH_x86_64
|
2009-10-14 16:01:37 +00:00
|
|
|
int32_t minorVersion, majorVersion;
|
2009-10-19 16:31:34 +00:00
|
|
|
#else
|
|
|
|
long minorVersion, majorVersion;
|
|
|
|
#endif
|
2009-07-01 15:13:01 +00:00
|
|
|
|
|
|
|
Gestalt(gestaltSystemVersionMajor, &majorVersion);
|
|
|
|
Gestalt(gestaltSystemVersionMinor, &minorVersion);
|
|
|
|
|
2009-10-19 16:31:34 +00:00
|
|
|
snprintf(buffer, size, "%d.%d", static_cast<int32_t>(majorVersion),
|
|
|
|
static_cast<int32_t>(minorVersion));
|
2009-07-02 09:13:39 +00:00
|
|
|
r = e->NewStringUTF(buffer);
|
2009-07-01 15:13:01 +00:00
|
|
|
#else
|
|
|
|
struct utsname system_id;
|
|
|
|
uname(&system_id);
|
|
|
|
r = e->NewStringUTF(system_id.release);
|
2008-01-18 15:35:20 +00:00
|
|
|
#endif
|
2009-07-28 16:16:27 +00:00
|
|
|
} else if (strcmp(chars, "os.arch") == 0) {
|
2009-08-27 00:26:44 +00:00
|
|
|
#ifdef ARCH_x86_32
|
2009-07-28 16:16:27 +00:00
|
|
|
r = e->NewStringUTF("x86");
|
2009-08-27 00:26:44 +00:00
|
|
|
#elif defined ARCH_x86_64
|
|
|
|
r = e->NewStringUTF("x86_64");
|
|
|
|
#elif defined ARCH_powerpc
|
|
|
|
r = e->NewStringUTF("ppc");
|
|
|
|
#elif defined ARCH_arm
|
|
|
|
r = e->NewStringUTF("arm");
|
|
|
|
#endif
|
2007-10-26 18:13:21 +00:00
|
|
|
} else if (strcmp(chars, "java.io.tmpdir") == 0) {
|
|
|
|
r = e->NewStringUTF("/tmp");
|
2010-09-20 23:28:42 +00:00
|
|
|
} else if (strcmp(chars, "user.dir") == 0) {
|
2011-07-11 16:44:06 +00:00
|
|
|
char buffer[PATH_MAX];
|
|
|
|
r = e->NewStringUTF(getcwd(buffer, PATH_MAX));
|
2007-10-26 18:13:21 +00:00
|
|
|
} else if (strcmp(chars, "user.home") == 0) {
|
2009-07-01 15:13:01 +00:00
|
|
|
r = e->NewStringUTF(getenv("HOME"));
|
2007-10-26 18:13:21 +00:00
|
|
|
}
|
|
|
|
#endif
|
2010-10-05 23:24:44 +00:00
|
|
|
else if (strcmp(chars, "user.language") == 0) {
|
2010-10-07 22:32:59 +00:00
|
|
|
Locale locale = getLocale();
|
|
|
|
if (strlen(locale.getLanguage())) r = e->NewStringUTF(locale.getLanguage());
|
2010-10-05 23:24:44 +00:00
|
|
|
} else if (strcmp(chars, "user.region") == 0) {
|
2010-10-07 22:32:59 +00:00
|
|
|
Locale locale = getLocale();
|
|
|
|
if (strlen(locale.getRegion())) r = e->NewStringUTF(locale.getRegion());
|
2010-10-05 23:24:44 +00:00
|
|
|
}
|
2007-07-07 23:47:35 +00:00
|
|
|
|
2007-10-26 18:13:21 +00:00
|
|
|
e->ReleaseStringUTFChars(name, chars);
|
2007-10-24 15:44:51 +00:00
|
|
|
}
|
2007-09-13 00:21:37 +00:00
|
|
|
|
2007-10-26 18:13:21 +00:00
|
|
|
if (r) {
|
|
|
|
jboolean v = true;
|
|
|
|
e->SetBooleanArrayRegion(found, 0, 1, &v);
|
2007-10-24 15:44:51 +00:00
|
|
|
}
|
2007-10-24 16:24:02 +00:00
|
|
|
|
2007-10-26 18:13:21 +00:00
|
|
|
return r;
|
2007-07-07 23:47:35 +00:00
|
|
|
}
|
2007-07-28 16:10:13 +00:00
|
|
|
|
2012-04-03 04:15:02 +00:00
|
|
|
// System.getEnvironment() implementation
|
|
|
|
// TODO: For Win32, replace usage of deprecated _wenviron
|
|
|
|
#ifndef PLATFORM_WINDOWS
|
|
|
|
extern char** environ;
|
|
|
|
# else
|
|
|
|
extern wchar_t** _wenviron;
|
|
|
|
const wchar_t** environ = _wenviron;
|
|
|
|
#endif
|
|
|
|
extern "C" JNIEXPORT jobjectArray JNICALL
|
|
|
|
Java_java_lang_System_getEnvironment(JNIEnv* env, jclass) {
|
|
|
|
int length;
|
|
|
|
for (length = 0; environ[length] != 0; ++length);
|
|
|
|
|
|
|
|
jobjectArray stringArray =
|
|
|
|
env->NewObjectArray(length, env->FindClass("java/lang/String"),
|
|
|
|
env->NewStringUTF(""));
|
|
|
|
|
|
|
|
for (int i = 0; i < length; i++) {
|
|
|
|
#ifndef PLATFORM_WINDOWS
|
|
|
|
jobject varString = env->NewStringUTF(environ[i]); // UTF-8
|
|
|
|
#else
|
|
|
|
jobject varString = env->NewString(environ[i]); // UTF-16
|
|
|
|
#endif
|
|
|
|
env->SetObjectArrayElement(stringArray, i, varString);
|
|
|
|
}
|
|
|
|
|
|
|
|
return stringArray;
|
|
|
|
}
|
|
|
|
|
2007-07-28 16:10:13 +00:00
|
|
|
extern "C" JNIEXPORT jlong JNICALL
|
|
|
|
Java_java_lang_System_currentTimeMillis(JNIEnv*, jclass)
|
|
|
|
{
|
2009-08-27 00:26:44 +00:00
|
|
|
#ifdef PLATFORM_WINDOWS
|
2010-10-29 02:30:49 +00:00
|
|
|
// We used to use _ftime here, but that only gives us 1-second
|
|
|
|
// resolution on Windows 7. _ftime_s might work better, but MinGW
|
|
|
|
// doesn't have it as of this writing. So we use this mess instead:
|
|
|
|
FILETIME time;
|
|
|
|
GetSystemTimeAsFileTime(&time);
|
|
|
|
return (((static_cast<jlong>(time.dwHighDateTime) << 32)
|
|
|
|
| time.dwLowDateTime) / 10000) - 11644473600000LL;
|
2007-10-23 17:22:48 +00:00
|
|
|
#else
|
2007-07-28 16:10:13 +00:00
|
|
|
timeval tv = { 0, 0 };
|
|
|
|
gettimeofday(&tv, 0);
|
|
|
|
return (static_cast<jlong>(tv.tv_sec) * 1000) +
|
|
|
|
(static_cast<jlong>(tv.tv_usec) / 1000);
|
2007-10-23 17:22:48 +00:00
|
|
|
#endif
|
2007-07-28 16:10:13 +00:00
|
|
|
}
|
2007-09-12 01:13:05 +00:00
|
|
|
|
|
|
|
extern "C" JNIEXPORT jstring JNICALL
|
|
|
|
Java_java_lang_System_doMapLibraryName(JNIEnv* e, jclass, jstring name)
|
|
|
|
{
|
|
|
|
jstring r = 0;
|
|
|
|
const char* chars = e->GetStringUTFChars(name, 0);
|
|
|
|
if (chars) {
|
|
|
|
unsigned nameLength = strlen(chars);
|
2007-10-24 16:24:02 +00:00
|
|
|
unsigned size = sizeof(SO_PREFIX) + nameLength + sizeof(SO_SUFFIX);
|
2009-08-27 00:26:44 +00:00
|
|
|
RUNTIME_ARRAY(char, buffer, size);
|
|
|
|
snprintf
|
|
|
|
(RUNTIME_ARRAY_BODY(buffer), size, SO_PREFIX "%s" SO_SUFFIX, chars);
|
|
|
|
r = e->NewStringUTF(RUNTIME_ARRAY_BODY(buffer));
|
2007-09-12 01:13:05 +00:00
|
|
|
|
|
|
|
e->ReleaseStringUTFChars(name, chars);
|
|
|
|
}
|
|
|
|
return r;
|
|
|
|
}
|
2007-10-02 14:58:35 +00:00
|
|
|
|
2008-02-28 15:35:16 +00:00
|
|
|
extern "C" JNIEXPORT jboolean JNICALL
|
|
|
|
Java_java_lang_Double_isInfinite(JNIEnv*, jclass, jdouble val)
|
|
|
|
{
|
|
|
|
return !isfinite(val);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jboolean JNICALL
|
|
|
|
Java_java_lang_Double_isNaN(JNIEnv*, jclass, jdouble val)
|
|
|
|
{
|
|
|
|
return isnan(val);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jdouble JNICALL
|
|
|
|
Java_java_lang_Double_doubleFromString(JNIEnv*e, jclass, jstring s,
|
|
|
|
jintArray numDoublesRead)
|
|
|
|
{
|
|
|
|
const char* chars = e->GetStringUTFChars(s, 0);
|
|
|
|
double d = 0.0;
|
2008-02-28 17:03:24 +00:00
|
|
|
jint numRead = 0;
|
2008-02-28 15:35:16 +00:00
|
|
|
|
|
|
|
if (chars) {
|
|
|
|
char* lastRead;
|
|
|
|
d = strtod(chars, &lastRead);
|
|
|
|
if ((lastRead != chars) && ((chars + strlen(chars)) == lastRead)) {
|
|
|
|
numRead = 1;
|
|
|
|
}
|
|
|
|
e->ReleaseStringUTFChars(s, chars);
|
|
|
|
}
|
|
|
|
e->SetIntArrayRegion(numDoublesRead, 0, 1, &numRead);
|
|
|
|
return d;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jboolean JNICALL
|
|
|
|
Java_java_lang_Float_isInfinite(JNIEnv*, jclass, jfloat val)
|
|
|
|
{
|
|
|
|
return !isfinite(val);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jboolean JNICALL
|
|
|
|
Java_java_lang_Float_isNaN(JNIEnv*, jclass, jfloat val)
|
|
|
|
{
|
|
|
|
return isnan(val);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jfloat JNICALL
|
|
|
|
Java_java_lang_Float_floatFromString(JNIEnv*e, jclass, jstring s,
|
|
|
|
jintArray numFloatsRead)
|
|
|
|
{
|
|
|
|
const char* chars = e->GetStringUTFChars(s, 0);
|
|
|
|
float f = 0.0;
|
2008-02-28 17:03:24 +00:00
|
|
|
jint numRead = 0;
|
2008-02-28 15:35:16 +00:00
|
|
|
|
|
|
|
if (chars) {
|
|
|
|
char* lastRead;
|
|
|
|
f = strtof(chars, &lastRead);
|
|
|
|
if ((lastRead != chars) && ((chars + strlen(chars)) == lastRead)) {
|
|
|
|
numRead = 1;
|
|
|
|
}
|
|
|
|
e->ReleaseStringUTFChars(s, chars);
|
|
|
|
}
|
|
|
|
e->SetIntArrayRegion(numFloatsRead, 0, 1, &numRead);
|
|
|
|
return f;
|
|
|
|
}
|
|
|
|
|
2007-10-12 18:53:56 +00:00
|
|
|
extern "C" JNIEXPORT jdouble JNICALL
|
|
|
|
Java_java_lang_Math_sin(JNIEnv*, jclass, jdouble val)
|
|
|
|
{
|
|
|
|
return sin(val);
|
|
|
|
}
|
|
|
|
|
2007-12-21 21:10:40 +00:00
|
|
|
extern "C" JNIEXPORT jdouble JNICALL
|
|
|
|
Java_java_lang_Math_cos(JNIEnv*, jclass, jdouble val)
|
|
|
|
{
|
|
|
|
return cos(val);
|
|
|
|
}
|
|
|
|
|
2007-10-11 22:41:52 +00:00
|
|
|
extern "C" JNIEXPORT jdouble JNICALL
|
|
|
|
Java_java_lang_Math_sqrt(JNIEnv*, jclass, jdouble val)
|
|
|
|
{
|
|
|
|
return sqrt(val);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" JNIEXPORT jdouble JNICALL
|
|
|
|
Java_java_lang_Math_pow(JNIEnv*, jclass, jdouble val, jdouble exp)
|
|
|
|
{
|
|
|
|
return pow(val, exp);
|
|
|
|
}
|
|
|
|
|
2007-10-11 15:59:22 +00:00
|
|
|
extern "C" JNIEXPORT jdouble JNICALL
|
|
|
|
Java_java_lang_Math_floor(JNIEnv*, jclass, jdouble val)
|
|
|
|
{
|
|
|
|
return floor(val);
|
|
|
|
}
|
|
|
|
|
2007-10-12 18:53:56 +00:00
|
|
|
extern "C" JNIEXPORT jdouble JNICALL
|
|
|
|
Java_java_lang_Math_ceil(JNIEnv*, jclass, jdouble val)
|
|
|
|
{
|
|
|
|
return ceil(val);
|
|
|
|
}
|
|
|
|
|
2007-10-02 14:58:35 +00:00
|
|
|
extern "C" JNIEXPORT jint JNICALL
|
2007-10-11 15:59:22 +00:00
|
|
|
Java_java_lang_Double_fillBufferWithDouble(JNIEnv* e, jclass, jdouble val,
|
2007-10-02 14:58:35 +00:00
|
|
|
jbyteArray buffer, jint bufferSize) {
|
2007-10-02 15:23:49 +00:00
|
|
|
jboolean isCopy;
|
|
|
|
jbyte* buf = e->GetByteArrayElements(buffer, &isCopy);
|
|
|
|
jint count = snprintf(reinterpret_cast<char*>(buf), bufferSize, "%g", val);
|
|
|
|
e->ReleaseByteArrayElements(buffer, buf, 0);
|
|
|
|
return count;
|
2007-10-02 14:58:35 +00:00
|
|
|
}
|