2010-12-06 03:21:09 +00:00
|
|
|
/* Copyright (c) 2008-2010, 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. */
|
|
|
|
|
2007-10-25 15:04:13 +00:00
|
|
|
#include "stdlib.h"
|
2007-10-25 22:06:05 +00:00
|
|
|
#include "stdio.h"
|
2007-10-25 15:04:13 +00:00
|
|
|
#include "string.h"
|
2011-05-26 17:57:30 +00:00
|
|
|
#ifdef __APPLE__
|
|
|
|
# include <JavaVM/jni.h>
|
|
|
|
#else
|
|
|
|
# include "jni.h"
|
|
|
|
#endif
|
2007-06-20 19:20:25 +00:00
|
|
|
|
2010-11-27 21:46:07 +00:00
|
|
|
#include "system.h"
|
|
|
|
#include "finder.h"
|
|
|
|
|
2009-08-27 00:26:44 +00:00
|
|
|
#if (defined __MINGW32__) || (defined _MSC_VER)
|
2008-01-19 00:54:36 +00:00
|
|
|
# define PATH_SEPARATOR ';'
|
|
|
|
#else
|
|
|
|
# define PATH_SEPARATOR ':'
|
|
|
|
#endif
|
|
|
|
|
2009-08-27 00:26:44 +00:00
|
|
|
#ifdef _MSC_VER
|
|
|
|
|
|
|
|
# define not !
|
|
|
|
# define or ||
|
|
|
|
# define and &&
|
|
|
|
# define xor ^
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
class RuntimeArray {
|
|
|
|
public:
|
|
|
|
RuntimeArray(unsigned size):
|
|
|
|
body(static_cast<T*>(malloc(size * sizeof(T))))
|
|
|
|
{ }
|
|
|
|
|
|
|
|
~RuntimeArray() {
|
|
|
|
free(body);
|
|
|
|
}
|
|
|
|
|
|
|
|
T* body;
|
|
|
|
};
|
|
|
|
|
|
|
|
# define RUNTIME_ARRAY(type, name, size) RuntimeArray<type> name(size);
|
|
|
|
# define RUNTIME_ARRAY_BODY(name) name.body
|
|
|
|
|
|
|
|
#else // not _MSC_VER
|
|
|
|
|
|
|
|
# define RUNTIME_ARRAY(type, name, size) type name[size];
|
|
|
|
# define RUNTIME_ARRAY_BODY(name) name
|
|
|
|
|
|
|
|
#endif // not _MSC_VER
|
|
|
|
|
2010-11-27 21:46:07 +00:00
|
|
|
#ifdef BOOT_LIBRARY
|
|
|
|
|
|
|
|
// since we aren't linking against libstdc++, we must implement this
|
|
|
|
// ourselves:
|
|
|
|
extern "C" void __cxa_pure_virtual(void) { abort(); }
|
|
|
|
|
2010-11-30 00:39:41 +00:00
|
|
|
// we link against a System implmentation, which requires this at link
|
|
|
|
// time, but it should not be used at runtime:
|
|
|
|
extern "C" uint64_t
|
2011-01-21 23:14:21 +00:00
|
|
|
vmNativeCall(void*, void*, unsigned, unsigned)
|
|
|
|
{
|
|
|
|
abort();
|
|
|
|
// abort is not declared __declspec(noreturn) on MSVC, so we have to
|
|
|
|
// pretend it might return to make the compiler happy:
|
|
|
|
return 0;
|
|
|
|
}
|
2010-11-30 00:39:41 +00:00
|
|
|
|
2010-11-27 21:46:07 +00:00
|
|
|
#endif // BOOT_LIBRARY
|
|
|
|
|
2007-10-25 15:04:13 +00:00
|
|
|
namespace {
|
2007-06-20 19:20:25 +00:00
|
|
|
|
2010-11-27 21:46:07 +00:00
|
|
|
const char*
|
|
|
|
mainClass(const char* jar)
|
|
|
|
{
|
|
|
|
using namespace vm;
|
|
|
|
|
|
|
|
System* system = makeSystem(0);
|
|
|
|
|
|
|
|
class MyAllocator: public Allocator {
|
|
|
|
public:
|
|
|
|
MyAllocator(System* s): s(s) { }
|
|
|
|
|
|
|
|
virtual void* tryAllocate(unsigned size) {
|
|
|
|
return s->tryAllocate(size);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void* allocate(unsigned size) {
|
|
|
|
void* p = tryAllocate(size);
|
|
|
|
if (p == 0) {
|
|
|
|
abort(s);
|
|
|
|
}
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void free(const void* p, unsigned) {
|
|
|
|
s->free(p);
|
|
|
|
}
|
|
|
|
|
|
|
|
System* s;
|
|
|
|
} allocator(system);
|
|
|
|
|
|
|
|
Finder* finder = makeFinder(system, &allocator, jar, 0);
|
|
|
|
|
2010-11-30 00:39:41 +00:00
|
|
|
char* result = 0;
|
2010-11-27 21:46:07 +00:00
|
|
|
|
|
|
|
System::Region* region = finder->find("META-INF/MANIFEST.MF");
|
|
|
|
if (region) {
|
|
|
|
unsigned start = 0;
|
|
|
|
unsigned length;
|
|
|
|
while (readLine(region->start(), region->length(), &start, &length)) {
|
2010-11-30 00:39:41 +00:00
|
|
|
const unsigned PrefixLength = 12;
|
2010-11-27 21:46:07 +00:00
|
|
|
if (strncmp("Main-Class: ", reinterpret_cast<const char*>
|
2010-11-30 00:39:41 +00:00
|
|
|
(region->start() + start), PrefixLength) == 0)
|
2010-11-27 21:46:07 +00:00
|
|
|
{
|
2010-11-30 00:39:41 +00:00
|
|
|
result = static_cast<char*>(malloc(length + 1 - PrefixLength));
|
|
|
|
memcpy(result, region->start() + start + PrefixLength,
|
|
|
|
length - PrefixLength);
|
|
|
|
result[length - PrefixLength] = 0;
|
2010-11-27 21:46:07 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
start += length;
|
|
|
|
}
|
|
|
|
|
|
|
|
region->dispose();
|
|
|
|
}
|
|
|
|
|
|
|
|
finder->dispose();
|
|
|
|
|
|
|
|
system->dispose();
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2007-06-20 19:20:25 +00:00
|
|
|
void
|
|
|
|
usageAndExit(const char* name)
|
|
|
|
{
|
2008-07-14 17:21:59 +00:00
|
|
|
fprintf
|
|
|
|
(stderr, "usage: %s\n"
|
|
|
|
"\t[{-cp|-classpath} <classpath>]\n"
|
|
|
|
"\t[-Xmx<maximum heap size>]\n"
|
|
|
|
"\t[-Xbootclasspath/p:<classpath to prepend to bootstrap classpath>]\n"
|
2008-07-14 17:51:20 +00:00
|
|
|
"\t[-Xbootclasspath:<bootstrap classpath>]\n"
|
|
|
|
"\t[-Xbootclasspath/a:<classpath to append to bootstrap classpath>]\n"
|
2008-07-14 17:23:33 +00:00
|
|
|
"\t[-D<property name>=<property value> ...]\n"
|
2010-11-27 21:46:07 +00:00
|
|
|
"\t{<class name>|-jar <app jar>} [<argument> ...]\n", name);
|
2007-06-20 19:20:25 +00:00
|
|
|
exit(-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
int
|
|
|
|
main(int ac, const char** av)
|
|
|
|
{
|
2008-07-14 17:02:43 +00:00
|
|
|
JavaVMInitArgs vmArgs;
|
|
|
|
vmArgs.version = JNI_VERSION_1_2;
|
|
|
|
vmArgs.nOptions = 1;
|
|
|
|
vmArgs.ignoreUnrecognized = JNI_TRUE;
|
2007-10-25 15:04:13 +00:00
|
|
|
|
2007-06-20 19:20:25 +00:00
|
|
|
const char* class_ = 0;
|
2010-11-27 21:46:07 +00:00
|
|
|
const char* jar = 0;
|
2007-06-20 19:20:25 +00:00
|
|
|
int argc = 0;
|
|
|
|
const char** argv = 0;
|
2008-07-14 17:02:43 +00:00
|
|
|
const char* classpath = ".";
|
2007-06-20 19:20:25 +00:00
|
|
|
|
|
|
|
for (int i = 1; i < ac; ++i) {
|
2008-07-14 17:02:43 +00:00
|
|
|
if (strcmp(av[i], "-cp") == 0
|
|
|
|
or strcmp(av[i], "-classpath") == 0)
|
|
|
|
{
|
|
|
|
classpath = av[++i];
|
2010-11-27 21:46:07 +00:00
|
|
|
} else if (strcmp(av[i], "-jar") == 0)
|
|
|
|
{
|
|
|
|
jar = av[++i];
|
2008-07-14 17:02:43 +00:00
|
|
|
} else if (strncmp(av[i], "-X", 2) == 0
|
|
|
|
or strncmp(av[i], "-D", 2) == 0)
|
|
|
|
{
|
|
|
|
++ vmArgs.nOptions;
|
2007-06-20 19:20:25 +00:00
|
|
|
} else {
|
2010-11-27 21:46:07 +00:00
|
|
|
if (jar == 0) {
|
|
|
|
class_ = av[i++];
|
|
|
|
}
|
2007-06-20 19:20:25 +00:00
|
|
|
if (i < ac) {
|
|
|
|
argc = ac - i;
|
|
|
|
argv = av + i;
|
|
|
|
i = ac;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-11-27 21:46:07 +00:00
|
|
|
if (jar) {
|
|
|
|
classpath = jar;
|
|
|
|
|
|
|
|
class_ = mainClass(jar);
|
|
|
|
|
|
|
|
if (class_ == 0) {
|
|
|
|
fprintf(stderr, "Main-Class manifest header not found in %s\n", jar);
|
|
|
|
exit(-1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-07-14 17:02:43 +00:00
|
|
|
#ifdef BOOT_LIBRARY
|
|
|
|
++ vmArgs.nOptions;
|
|
|
|
#endif
|
|
|
|
|
2008-11-29 23:08:14 +00:00
|
|
|
#ifdef BOOT_IMAGE
|
|
|
|
++ vmArgs.nOptions;
|
|
|
|
#endif
|
|
|
|
|
2009-06-06 20:18:33 +00:00
|
|
|
#ifdef BOOT_BUILTINS
|
|
|
|
++ vmArgs.nOptions;
|
|
|
|
#endif
|
|
|
|
|
2009-08-27 00:26:44 +00:00
|
|
|
RUNTIME_ARRAY(JavaVMOption, options, vmArgs.nOptions);
|
|
|
|
vmArgs.options = RUNTIME_ARRAY_BODY(options);
|
2008-07-14 17:02:43 +00:00
|
|
|
|
2008-07-14 17:51:20 +00:00
|
|
|
unsigned optionIndex = 0;
|
2008-07-14 17:02:43 +00:00
|
|
|
|
2008-11-29 23:08:14 +00:00
|
|
|
#ifdef BOOT_IMAGE
|
2009-08-27 00:26:44 +00:00
|
|
|
vmArgs.options[optionIndex++].optionString
|
2008-11-29 23:08:14 +00:00
|
|
|
= const_cast<char*>("-Davian.bootimage=" BOOT_IMAGE);
|
|
|
|
#endif
|
|
|
|
|
2008-03-31 03:43:43 +00:00
|
|
|
#ifdef BOOT_LIBRARY
|
2009-08-27 00:26:44 +00:00
|
|
|
vmArgs.options[optionIndex++].optionString
|
2008-07-14 17:02:43 +00:00
|
|
|
= const_cast<char*>("-Davian.bootstrap=" BOOT_LIBRARY);
|
2008-03-31 03:43:43 +00:00
|
|
|
#endif
|
|
|
|
|
2009-06-06 20:18:33 +00:00
|
|
|
#ifdef BOOT_BUILTINS
|
2009-08-27 00:26:44 +00:00
|
|
|
vmArgs.options[optionIndex++].optionString
|
2009-06-06 20:18:33 +00:00
|
|
|
= const_cast<char*>("-Davian.builtins=" BOOT_BUILTINS);
|
|
|
|
#endif
|
|
|
|
|
2008-07-14 17:02:43 +00:00
|
|
|
#define CLASSPATH_PROPERTY "-Djava.class.path="
|
|
|
|
|
|
|
|
unsigned classpathSize = strlen(classpath);
|
|
|
|
unsigned classpathPropertyBufferSize
|
|
|
|
= sizeof(CLASSPATH_PROPERTY) + classpathSize;
|
|
|
|
|
2009-08-27 00:26:44 +00:00
|
|
|
RUNTIME_ARRAY(char, classpathPropertyBuffer, classpathPropertyBufferSize);
|
|
|
|
memcpy(RUNTIME_ARRAY_BODY(classpathPropertyBuffer),
|
2008-07-14 17:02:43 +00:00
|
|
|
CLASSPATH_PROPERTY,
|
|
|
|
sizeof(CLASSPATH_PROPERTY) - 1);
|
2009-08-27 00:26:44 +00:00
|
|
|
memcpy(RUNTIME_ARRAY_BODY(classpathPropertyBuffer)
|
|
|
|
+ sizeof(CLASSPATH_PROPERTY) - 1,
|
2008-07-14 17:02:43 +00:00
|
|
|
classpath,
|
|
|
|
classpathSize + 1);
|
|
|
|
|
2009-08-27 00:26:44 +00:00
|
|
|
vmArgs.options[optionIndex++].optionString
|
|
|
|
= RUNTIME_ARRAY_BODY(classpathPropertyBuffer);
|
2008-07-14 17:02:43 +00:00
|
|
|
|
2007-10-25 18:33:43 +00:00
|
|
|
for (int i = 1; i < ac; ++i) {
|
2008-07-14 17:02:43 +00:00
|
|
|
if (strncmp(av[i], "-X", 2) == 0
|
|
|
|
or strncmp(av[i], "-D", 2) == 0)
|
|
|
|
{
|
2009-08-27 00:26:44 +00:00
|
|
|
vmArgs.options[optionIndex++].optionString = const_cast<char*>(av[i]);
|
2007-10-25 18:33:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-06-20 19:20:25 +00:00
|
|
|
if (class_ == 0) {
|
|
|
|
usageAndExit(av[0]);
|
|
|
|
}
|
|
|
|
|
2007-10-25 15:04:13 +00:00
|
|
|
JavaVM* vm;
|
2007-10-25 22:34:40 +00:00
|
|
|
void* env;
|
|
|
|
JNI_CreateJavaVM(&vm, &env, &vmArgs);
|
|
|
|
JNIEnv* e = static_cast<JNIEnv*>(env);
|
2007-10-25 15:04:13 +00:00
|
|
|
|
|
|
|
jclass c = e->FindClass(class_);
|
2010-11-27 21:46:07 +00:00
|
|
|
|
|
|
|
if (jar) {
|
|
|
|
free(const_cast<char*>(class_));
|
|
|
|
}
|
|
|
|
|
2009-12-17 02:25:03 +00:00
|
|
|
if (not e->ExceptionCheck()) {
|
2007-10-25 15:04:13 +00:00
|
|
|
jmethodID m = e->GetStaticMethodID(c, "main", "([Ljava/lang/String;)V");
|
2009-12-17 02:25:03 +00:00
|
|
|
if (not e->ExceptionCheck()) {
|
2007-10-25 15:04:13 +00:00
|
|
|
jclass stringClass = e->FindClass("java/lang/String");
|
2009-12-17 02:25:03 +00:00
|
|
|
if (not e->ExceptionCheck()) {
|
2007-10-25 15:04:13 +00:00
|
|
|
jobjectArray a = e->NewObjectArray(argc, stringClass, 0);
|
2009-12-17 02:25:03 +00:00
|
|
|
if (not e->ExceptionCheck()) {
|
2007-10-25 15:04:13 +00:00
|
|
|
for (int i = 0; i < argc; ++i) {
|
|
|
|
e->SetObjectArrayElement(a, i, e->NewStringUTF(argv[i]));
|
|
|
|
}
|
|
|
|
|
|
|
|
e->CallStaticVoidMethod(c, m, a);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int exitCode = 0;
|
2009-12-17 02:25:03 +00:00
|
|
|
if (e->ExceptionCheck()) {
|
2007-10-25 15:04:13 +00:00
|
|
|
exitCode = -1;
|
|
|
|
e->ExceptionDescribe();
|
|
|
|
}
|
|
|
|
|
|
|
|
vm->DestroyJavaVM();
|
|
|
|
|
|
|
|
return exitCode;
|
2007-06-20 19:20:25 +00:00
|
|
|
}
|